Merge release branch 21.x in to main
diff --git a/.bazelignore b/.bazelignore
index 5c3a81c..dc5c301 100644
--- a/.bazelignore
+++ b/.bazelignore
@@ -1,4 +1,4 @@
 # These are fetched as external repositories.
-third_party/benchmark
+third_party/abseil-cpp
 third_party/googletest
 _build/
diff --git a/.bazelrc b/.bazelrc
new file mode 100644
index 0000000..de30d6b
--- /dev/null
+++ b/.bazelrc
@@ -0,0 +1,35 @@
+build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14
+
+build:dbg --compilation_mode=dbg
+
+build:opt --compilation_mode=opt
+
+build:san-common --config=dbg --strip=never --copt=-O0 --copt=-fno-omit-frame-pointer
+
+build:asan --config=san-common --copt=-fsanitize=address --linkopt=-fsanitize=address
+build:asan --copt=-DADDRESS_SANITIZER=1
+# ASAN hits ODR violations with shared linkage due to rules_proto.
+build:asan --dynamic_mode=off
+
+build:msan --config=san-common --copt=-fsanitize=memory --linkopt=-fsanitize=memory
+build:msan --copt=-fsanitize-memory-track-origins
+build:msan --copt=-fsanitize-memory-use-after-dtor
+build:msan --action_env=MSAN_OPTIONS=poison_in_dtor=1
+build:msan --copt=-DMEMORY_SANITIZER=1
+
+# Use our instrumented LLVM libc++ in Kokoro.
+build:kokoro-msan --config=msan
+build:kokoro-msan --linkopt=-L/opt/libcxx_msan/lib
+build:kokoro-msan --linkopt=-Wl,-rpath,/opt/libcxx_msan/lib
+build:kokoro-msan --cxxopt=-stdlib=libc++ --linkopt=-stdlib=libc++
+
+
+build:tsan --config=san-common --copt=-fsanitize=thread --linkopt=-fsanitize=thread
+build:tsan --copt=-DTHREAD_SANITIZER=1
+
+build:ubsan --config=san-common --copt=-fsanitize=undefined --linkopt=-fsanitize=undefined
+build:ubsan --action_env=UBSAN_OPTIONS=halt_on_error=1:print_stacktrace=1
+build:ubsan --copt=-DUNDEFINED_SANITIZER=1
+# Workaround for the fact that Bazel links with $CC, not $CXX
+# https://github.com/bazelbuild/bazel/issues/11122#issuecomment-613746748
+build:ubsan --copt=-fno-sanitize=function --copt=-fno-sanitize=vptr
diff --git a/.github/CODEOWNERSHIP b/.github/CODEOWNERSHIP
new file mode 100644
index 0000000..03c0412
--- /dev/null
+++ b/.github/CODEOWNERSHIP
@@ -0,0 +1,36 @@
+/src/ @protocolbuffers/protobuf-compiler
+
+/src/google/protobuf/compiler/cpp @protocolbuffers/protobuf-cpp
+
+/csharp/ @protocolbuffers/protobuf-csharp
+/src/google/protobuf/compiler/csharp/ @protocolbuffers/protobuf-csharp
+
+/docs/ @protocolbuffers/protobuf-docs
+/examples/ @protocolbuffers/protobuf-docs
+
+/java/ @protocolbuffers/protobuf-java
+/src/google/protobuf/compiler/java/ @protocolbuffers/protobuf-java
+
+/java/kotlin-lite/ @protocolbuffers/protobuf-kotlin
+/java/kotlin/ @protocolbuffers/protobuf-kotlin
+
+/objectivec/ @protocolbuffers/protobuf-objc
+/src/google/protobuf/compiler/objectivec/ @protocolbuffers/protobuf-objc
+
+/php/ @protocolbuffers/protobuf-php
+/src/google/protobuf/compiler/php/ @protocolbuffers/protobuf-php
+
+/python/ @protocolbuffers/protobuf-python
+/src/google/protobuf/compiler/python/ @protocolbuffers/protobuf-python
+
+/ruby/ @protocolbuffers/protobuf-ruby
+/src/google/protobuf/compiler/ruby/ @protocolbuffers/protobuf-ruby
+
+/build_defs/ @protocolbuffers/protobuf-btr
+/cmake/ @protocolbuffers/protobuf-btr
+/pkg/ @protocolbuffers/protobuf-btr
+/toolchain/ @protocolbuffers/protobuf-btr
+/conformance/ @protocolbuffers/protobuf-btr
+/kokoro/ @protocolbuffers/protobuf-btr
+/third_party/ @protocolbuffers/protobuf-btr
+*.bazel @protocolbuffers/protobuf-btr
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE/bug_report.md
index f9411a6..88bc074 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE/bug_report.md
@@ -2,7 +2,7 @@
 name: Bug report
 about: Create a report to help us improve
 title: ''
-labels: ''
+labels: 'untriaged'
 assignees: ''
 
 ---
@@ -16,7 +16,7 @@
 -->
 
 **What version of protobuf and what language are you using?**
-Version: main/v3.6.0/v3.5.0 etc.
+Version: main/v3.6.0/v3.5.0 etc. (NOTE: please try updating to the latest version of protoc/runtime possible beforehand to attempt to resolve your problem)
 Language: C++/Java/Python/C#/Ruby/PHP/Objective-C/Javascript
 
 **What operating system (Linux, Windows, ...) and version?**
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
index 28b9bc9..ada9ed7 100644
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ b/.github/ISSUE_TEMPLATE/feature_request.md
@@ -2,7 +2,7 @@
 name: Feature request
 about: Suggest an idea for this project
 title: ''
-labels: ''
+labels: 'untriaged'
 assignees: ''
 
 ---
diff --git a/.github/mergeable.yml b/.github/mergeable.yml
index 1768852..fdb06d9 100644
--- a/.github/mergeable.yml
+++ b/.github/mergeable.yml
@@ -5,14 +5,11 @@
         - must_exclude:
             regex: '^disposition/DO NOT MERGE'
             message: 'Pull request marked not mergeable'
-        - or:
-          - and:
-            - must_include:
-                regex: 'release notes: yes'
-                message: 'Include release notes: yes'
-            - must_include:
-                regex: '^(autotools|bazel|c#|c\+\+|cleanup|cmake|conformance tests|integration|go|java|javascript|objective-c|php|protoc|python|ruby|kotlin)'
-                message: '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: 'Include release notes: no'
+        - must_include:
+            regex: 'mergeable:force-allow'
+            message: 'Pull requests should not be merged directly and should instead
+              be handled by Copybara.
+
+              To enable Github merges, add the `mergeable:force-allow` label.
+              This should almost never be used except for releases or as a break glass measure
+              after discussing with the team.'
diff --git a/.github/workflows/codespell.yml b/.github/workflows/codespell.yml
index 887c8a2..b32c0a2 100644
--- a/.github/workflows/codespell.yml
+++ b/.github/workflows/codespell.yml
@@ -13,4 +13,4 @@
         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,falsy,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',ro,te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,streem,sur"
+          ignore_words_list: "alow,alse,ba,chec,cleare,copyable,cloneable,dedup,dur,errorprone,falsy,files',fo,fundementals,hel,importd,inout,leapyear,nd,nin,ois,ons,parseable,process',ro,te,testof,ue,unparseable,wasn,wee,gae,keyserver,objext,od,optin,streem,sur,falsy"
diff --git a/.github/workflows/generate_files.yml b/.github/workflows/generate_files.yml
new file mode 100644
index 0000000..c1562b3
--- /dev/null
+++ b/.github/workflows/generate_files.yml
@@ -0,0 +1,29 @@
+name: Auto-generate checked-in files
+
+on:
+  push:
+    branches:
+      - main
+      - '[0-9]+.x'
+      # The 21.x branch predates support for auto-generation, so we make sure
+      # to exclude it.
+      - '!21.x'
+
+jobs:
+  cmake:
+    if: github.repository == 'protocolbuffers/protobuf'
+    runs-on: ubuntu-latest
+
+    strategy:
+      fail-fast: false   # Don't cancel all jobs if one fails.
+
+    steps:
+      - uses: actions/checkout@v3
+        with:
+          # Note: this token has an expiration date, so if the workflow starts
+          # failing then you may need to generate a fresh token.
+          token: ${{ secrets.BOT_ACCESS_TOKEN }}
+      - name: Configure name and email address in Git
+        run: cd ${{ github.workspace }} && git config user.name "Protobuf Team Bot" && git config user.email "protobuf-team-bot@google.com"
+      - name: Commit and push update
+        run: cd ${{ github.workspace }} && ./push_auto_update.sh
diff --git a/.github/workflows/php-ext.yml b/.github/workflows/php-ext.yml
index 4d3af3e..17b6adf 100644
--- a/.github/workflows/php-ext.yml
+++ b/.github/workflows/php-ext.yml
@@ -27,7 +27,6 @@
           chmod a+x $HOME/bin/bazel
       - name: Install git
         run: |
-          apt-get update -q
           apt-get install -qy --no-install-recommends git
       - name: Checkout
         uses: actions/checkout@v3
diff --git a/.github/workflows/update_php_repo.yml b/.github/workflows/update_php_repo.yml
new file mode 100644
index 0000000..2224cd2
--- /dev/null
+++ b/.github/workflows/update_php_repo.yml
@@ -0,0 +1,45 @@
+name: Update protobuf-php Repo
+
+on:
+  push:
+    tags:
+      - v[0-9]+.[0-9]+
+      - v[0-9]+.[0-9]+-rc[0-9]+
+
+jobs:
+  update-repo:
+    name: Update PHP Repo
+    runs-on: ubuntu-latest
+    steps:
+      - name: Checkout protobuf-php
+        uses: actions/checkout@v3
+        with:
+          repository: protocolbuffers/protobuf-php
+          token: ${{ secrets.BOT_ACCESS_TOKEN }}
+      - name: Clone protobuf
+        uses: actions/checkout@v3
+        with:
+          path: protobuf
+      - name: Configure Git Bot
+        run: |
+          git config user.name "Protobuf Team Bot"
+          git config user.email "protobuf-team-bot@google.com"
+      - name: Get PHP Version
+        run: |
+          unformatted_version=$( cat protobuf/version.json | jq -r '.main.languages.php' )
+          version=${unformatted_version/-rc/RC}
+          version_tag=v$version
+          echo "VERSION=$version" >> $GITHUB_ENV
+          echo "VERSION_TAG=$version_tag" >> $GITHUB_ENV
+      - name: Copy files
+        run: |
+          rm -rf src
+          cp -r protobuf/php/src .
+          cp protobuf/php/composer.json.dist composer.json
+          rm -rf protobuf
+      - name: Push Changes
+        run: |
+          git commit -a -m "$VERSION sync"
+          git push --force origin master
+          git tag -a $VERSION_TAG -m "Tag release $VERSION_TAG"
+          git push origin $VERSION_TAG
diff --git a/.gitignore b/.gitignore
index 62de6f1..ea95cc9 100644
--- a/.gitignore
+++ b/.gitignore
@@ -1,29 +1,24 @@
-# autogen.sh-generated files
-Makefile.in
-src/Makefile.in
-config.guess
-config.h.in
-config.sub
-configure
-depcomp
-install-sh
-ltmain.sh
-missing
+# CMake-generated files
+.ninja_deps
+.ninja_logs
+cmake/protobuf/*.cmake
+cmake_install.cmake
+CMakeCache.txt
+CTestTestfile.cmake
+CMakeFiles/*
+Testing/Temporary/*
 
-aclocal.m4
-m4/libtool.m4
-m4/ltoptions.m4
-m4/ltsugar.m4
-m4/ltversion.m4
-m4/lt~obsolete.m4
-autom4te.cache
+/core
+/protoc
+/test_plugin
+/tests
+/lite-test
+/protoc-*.*
 
 # downloaded files
 /gmock
 
 # in-tree configure-generated files
-Makefile
-src/Makefile
 /config.h
 config.log
 config.status
@@ -38,8 +33,8 @@
 *.o
 *.lo
 *.la
-src/.libs
 *.so
+*.a
 
 .dirstamp
 
@@ -60,8 +55,6 @@
 python/docs/_build/
 
 src/js_embed
-src/protoc
-src/unittest_proto_middleman
 
 # vim generated
 *.swp
diff --git a/.gitmodules b/.gitmodules
index bcd125a..db938cf 100644
--- a/.gitmodules
+++ b/.gitmodules
@@ -1,7 +1,14 @@
-[submodule "third_party/benchmark"]
-	path = third_party/benchmark
-	url = https://github.com/google/benchmark.git
 [submodule "third_party/googletest"]
 	path = third_party/googletest
 	url = https://github.com/google/googletest.git
 	ignore = dirty
+[submodule "third_party/abseil-cpp"]
+	path = third_party/abseil-cpp
+	url = https://github.com/abseil/abseil-cpp.git
+	branch = lts_2022_06_23
+[submodule "third_party/jsoncpp"]
+	path = third_party/jsoncpp
+	url = https://github.com/open-source-parsers/jsoncpp.git
+[submodule "third_party/utf8_range"]
+	path = third_party/utf8_range
+	url = https://github.com/protocolbuffers/utf8_range.git
diff --git a/BUILD.bazel b/BUILD.bazel
index 0f6e41e..c9b2472 100644
--- a/BUILD.bazel
+++ b/BUILD.bazel
@@ -1,252 +1,17 @@
 # Bazel (https://bazel.build/) BUILD file for Protobuf.
 
-load("@bazel_skylib//rules:common_settings.bzl", "string_flag")
-load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_proto_library")
 load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
 load("@rules_proto//proto:defs.bzl", "proto_lang_toolchain", "proto_library")
-load("@rules_python//python:defs.bzl", "py_library")
-load("@rules_java//java:defs.bzl", "java_binary", "java_lite_proto_library", "java_proto_library")
+load("@rules_java//java:defs.bzl", "java_lite_proto_library", "java_proto_library")
 load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS", "PROTOC_LINK_OPTS")
-load(
-    ":protobuf.bzl",
-    "adapt_proto_library",
-    "cc_proto_library",
-    "internal_copied_filegroup",
-    "internal_protobuf_py_tests",
-    "py_proto_library",
-)
+load(":protobuf.bzl", "internal_objc_proto_library", "internal_php_proto_library", "internal_py_proto_library", "internal_ruby_proto_library")
 
 licenses(["notice"])
 
 exports_files(["LICENSE"])
 
 ################################################################################
-# Protobuf Runtime Library
-################################################################################
-
-cc_library(
-    name = "protobuf_lite",
-    srcs = [
-        # AUTOGEN(protobuf_lite_srcs)
-        "src/google/protobuf/any_lite.cc",
-        "src/google/protobuf/arena.cc",
-        "src/google/protobuf/arenastring.cc",
-        "src/google/protobuf/arenaz_sampler.cc",
-        "src/google/protobuf/extension_set.cc",
-        "src/google/protobuf/generated_enum_util.cc",
-        "src/google/protobuf/generated_message_tctable_lite.cc",
-        "src/google/protobuf/generated_message_util.cc",
-        "src/google/protobuf/implicit_weak_message.cc",
-        "src/google/protobuf/inlined_string_field.cc",
-        "src/google/protobuf/io/coded_stream.cc",
-        "src/google/protobuf/io/io_win32.cc",
-        "src/google/protobuf/io/strtod.cc",
-        "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",
-        "src/google/protobuf/repeated_ptr_field.cc",
-        "src/google/protobuf/stubs/bytestream.cc",
-        "src/google/protobuf/stubs/common.cc",
-        "src/google/protobuf/stubs/int128.cc",
-        "src/google/protobuf/stubs/status.cc",
-        "src/google/protobuf/stubs/statusor.cc",
-        "src/google/protobuf/stubs/stringpiece.cc",
-        "src/google/protobuf/stubs/stringprintf.cc",
-        "src/google/protobuf/stubs/structurally_valid.cc",
-        "src/google/protobuf/stubs/strutil.cc",
-        "src/google/protobuf/stubs/time.cc",
-        "src/google/protobuf/wire_format_lite.cc",
-    ],
-    hdrs = glob([
-        "src/google/protobuf/**/*.h",
-        "src/google/protobuf/**/*.inc",
-    ]),
-    copts = COPTS,
-    includes = ["src/"],
-    linkopts = LINK_OPTS,
-    visibility = ["//visibility:public"],
-)
-
-cc_library(
-    name = "protobuf",
-    srcs = [
-        # AUTOGEN(protobuf_srcs)
-        "src/google/protobuf/any.cc",
-        "src/google/protobuf/any.pb.cc",
-        "src/google/protobuf/api.pb.cc",
-        "src/google/protobuf/compiler/importer.cc",
-        "src/google/protobuf/compiler/parser.cc",
-        "src/google/protobuf/descriptor.cc",
-        "src/google/protobuf/descriptor.pb.cc",
-        "src/google/protobuf/descriptor_database.cc",
-        "src/google/protobuf/duration.pb.cc",
-        "src/google/protobuf/dynamic_message.cc",
-        "src/google/protobuf/empty.pb.cc",
-        "src/google/protobuf/extension_set_heavy.cc",
-        "src/google/protobuf/field_mask.pb.cc",
-        "src/google/protobuf/generated_message_bases.cc",
-        "src/google/protobuf/generated_message_reflection.cc",
-        "src/google/protobuf/generated_message_tctable_full.cc",
-        "src/google/protobuf/io/gzip_stream.cc",
-        "src/google/protobuf/io/printer.cc",
-        "src/google/protobuf/io/tokenizer.cc",
-        "src/google/protobuf/map_field.cc",
-        "src/google/protobuf/message.cc",
-        "src/google/protobuf/reflection_ops.cc",
-        "src/google/protobuf/service.cc",
-        "src/google/protobuf/source_context.pb.cc",
-        "src/google/protobuf/struct.pb.cc",
-        "src/google/protobuf/stubs/substitute.cc",
-        "src/google/protobuf/text_format.cc",
-        "src/google/protobuf/timestamp.pb.cc",
-        "src/google/protobuf/type.pb.cc",
-        "src/google/protobuf/unknown_field_set.cc",
-        "src/google/protobuf/util/delimited_message_util.cc",
-        "src/google/protobuf/util/field_comparator.cc",
-        "src/google/protobuf/util/field_mask_util.cc",
-        "src/google/protobuf/util/internal/datapiece.cc",
-        "src/google/protobuf/util/internal/default_value_objectwriter.cc",
-        "src/google/protobuf/util/internal/error_listener.cc",
-        "src/google/protobuf/util/internal/field_mask_utility.cc",
-        "src/google/protobuf/util/internal/json_escaping.cc",
-        "src/google/protobuf/util/internal/json_objectwriter.cc",
-        "src/google/protobuf/util/internal/json_stream_parser.cc",
-        "src/google/protobuf/util/internal/object_writer.cc",
-        "src/google/protobuf/util/internal/proto_writer.cc",
-        "src/google/protobuf/util/internal/protostream_objectsource.cc",
-        "src/google/protobuf/util/internal/protostream_objectwriter.cc",
-        "src/google/protobuf/util/internal/type_info.cc",
-        "src/google/protobuf/util/internal/utility.cc",
-        "src/google/protobuf/util/json_util.cc",
-        "src/google/protobuf/util/message_differencer.cc",
-        "src/google/protobuf/util/time_util.cc",
-        "src/google/protobuf/util/type_resolver_util.cc",
-        "src/google/protobuf/wire_format.cc",
-        "src/google/protobuf/wrappers.pb.cc",
-    ],
-    hdrs = glob([
-        "src/**/*.h",
-        "src/**/*.inc",
-    ]),
-    copts = COPTS,
-    includes = ["src/"],
-    linkopts = LINK_OPTS,
-    visibility = ["//visibility:public"],
-    deps = [":protobuf_lite"] + select({
-        "//build_defs:config_msvc": [],
-        "//conditions:default": ["@zlib//:zlib"],
-    }),
-)
-
-# This provides just the header files for use in projects that need to build
-# shared libraries for dynamic loading. This target is available until Bazel
-# adds native support for such use cases.
-# TODO(keveman): Remove this target once the support gets added to Bazel.
-cc_library(
-    name = "protobuf_headers",
-    hdrs = glob([
-        "src/**/*.h",
-        "src/**/*.inc",
-    ]),
-    includes = ["src/"],
-    visibility = ["//visibility:public"],
-)
-
-# DEPRECATED: Prefer :well_known_type_protos for the Well-Known Types
-# (https://developers.google.com/protocol-buffers/docs/reference/google.protobuf)
-# or :descriptor_proto(_srcs) for descriptor.proto (source), or
-# :compiler_plugin_proto for compiler/plugin.proto.
-filegroup(
-    name = "well_known_protos",
-    srcs = [
-        "src/google/protobuf/compiler/plugin.proto",
-        "src/google/protobuf/descriptor.proto",
-        ":well_known_type_protos",
-    ],
-    deprecation = "Prefer :well_known_type_protos instead.",
-    visibility = ["//visibility:public"],
-)
-
-filegroup(
-    name = "well_known_type_protos",
-    srcs = [
-        "src/google/protobuf/any.proto",
-        "src/google/protobuf/api.proto",
-        "src/google/protobuf/duration.proto",
-        "src/google/protobuf/empty.proto",
-        "src/google/protobuf/field_mask.proto",
-        "src/google/protobuf/source_context.proto",
-        "src/google/protobuf/struct.proto",
-        "src/google/protobuf/timestamp.proto",
-        "src/google/protobuf/type.proto",
-        "src/google/protobuf/wrappers.proto",
-    ],
-    visibility = ["//visibility:public"],
-)
-
-filegroup(
-    name = "built_in_runtime_protos",
-    srcs = [
-        "src/google/protobuf/compiler/plugin.proto",
-        "src/google/protobuf/descriptor.proto",
-    ],
-    visibility = ["//:__subpackages__"],
-)
-
-exports_files(
-    srcs = [
-        "src/google/protobuf/any.proto",
-        "src/google/protobuf/api.proto",
-        "src/google/protobuf/compiler/plugin.proto",
-        "src/google/protobuf/descriptor.proto",
-        "src/google/protobuf/duration.proto",
-        "src/google/protobuf/empty.proto",
-        "src/google/protobuf/field_mask.proto",
-        "src/google/protobuf/source_context.proto",
-        "src/google/protobuf/struct.proto",
-        "src/google/protobuf/timestamp.proto",
-        "src/google/protobuf/type.proto",
-        "src/google/protobuf/wrappers.proto",
-    ],
-    visibility = ["//pkg:__pkg__"],
-)
-
-alias(
-    name = "lite_well_known_protos",
-    actual = ":well_known_type_protos",
-    visibility = ["//visibility:public"],
-)
-
-adapt_proto_library(
-    name = "cc_wkt_protos_genproto",
-    visibility = ["//visibility:public"],
-    deps = [
-        "//:any_proto",
-        "//:api_proto",
-        "//:compiler_plugin_proto",
-        "//:descriptor_proto",
-        "//:duration_proto",
-        "//:empty_proto",
-        "//:field_mask_proto",
-        "//:source_context_proto",
-        "//:struct_proto",
-        "//:timestamp_proto",
-        "//:type_proto",
-        "//:wrappers_proto",
-    ],
-)
-
-cc_library(
-    name = "cc_wkt_protos",
-    deprecation = "Only for backward compatibility. Do not use.",
-    visibility = ["//visibility:public"],
-)
-
-################################################################################
 # Well Known Types Proto Library Rules
 #
 # https://developers.google.com/protocol-buffers/docs/reference/google.protobuf
@@ -256,507 +21,206 @@
 #
 # java_proto_library(
 #   name = "any_java_proto",
-#   deps = ["@com_google_protobuf//:any_proto],
+#   deps = ["@com_google_protobuf//:any_proto"],
 # )
 ################################################################################
 
-proto_library(
+alias(
     name = "any_proto",
-    srcs = ["src/google/protobuf/any.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:any_proto",
     visibility = ["//visibility:public"],
 )
 
-proto_library(
+alias(
     name = "api_proto",
-    srcs = ["src/google/protobuf/api.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:api_proto",
     visibility = ["//visibility:public"],
-    deps = [
-        "//:source_context_proto",
-        "//:type_proto",
-    ],
 )
 
-proto_library(
+alias(
     name = "duration_proto",
-    srcs = ["//:src/google/protobuf/duration.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:duration_proto",
     visibility = ["//visibility:public"],
 )
 
-proto_library(
+alias(
     name = "empty_proto",
-    srcs = ["src/google/protobuf/empty.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:empty_proto",
     visibility = ["//visibility:public"],
 )
 
-proto_library(
+alias(
     name = "field_mask_proto",
-    srcs = ["src/google/protobuf/field_mask.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:field_mask_proto",
     visibility = ["//visibility:public"],
 )
 
-proto_library(
+alias(
     name = "source_context_proto",
-    srcs = ["src/google/protobuf/source_context.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:source_context_proto",
     visibility = ["//visibility:public"],
 )
 
-proto_library(
+alias(
     name = "struct_proto",
-    srcs = ["src/google/protobuf/struct.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:struct_proto",
     visibility = ["//visibility:public"],
 )
 
-proto_library(
+alias(
     name = "timestamp_proto",
-    srcs = ["src/google/protobuf/timestamp.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:timestamp_proto",
     visibility = ["//visibility:public"],
 )
 
-proto_library(
+alias(
     name = "type_proto",
-    srcs = ["src/google/protobuf/type.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:type_proto",
     visibility = ["//visibility:public"],
-    deps = [
-        "//:any_proto",
-        "//:source_context_proto",
-    ],
 )
 
-proto_library(
+alias(
     name = "wrappers_proto",
-    srcs = ["src/google/protobuf/wrappers.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:wrappers_proto",
     visibility = ["//visibility:public"],
 )
 
-# Built-in runtime types
-
-proto_library(
-    name = "compiler_plugin_proto",
-    srcs = ["src/google/protobuf/compiler/plugin.proto"],
-    strip_import_prefix = "src",
+# Source files: these are aliases to a filegroup, not a `proto_library`.
+#
+# (This is _probably_ not what you want.)
+alias(
+    name = "lite_well_known_protos",
+    actual = "//src/google/protobuf:well_known_type_protos",  # filegroup
     visibility = ["//visibility:public"],
-    deps = ["//:descriptor_proto"],
 )
 
-proto_library(
+alias(
+    name = "well_known_type_protos",
+    actual = "//src/google/protobuf:well_known_type_protos",  # filegroup
+    visibility = ["//visibility:public"],
+)
+
+# Built-in runtime protos: these are part of protobuf's internal
+# implementation, but are not Well-Known Types.
+
+alias(
     name = "descriptor_proto",
-    srcs = ["src/google/protobuf/descriptor.proto"],
-    strip_import_prefix = "src",
+    actual = "//src/google/protobuf:descriptor_proto",  # proto_library
     visibility = ["//visibility:public"],
 )
 
+alias(
+    name = "descriptor_proto_srcs",
+    actual = "//src/google/protobuf:descriptor_proto_srcs",  # filegroup
+    visibility = ["//visibility:public"],
+)
+
+alias(
+    name = "compiler_plugin_proto",
+    actual = "//src/google/protobuf/compiler:plugin_proto",  # proto_library
+    visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "cc_wkt_protos",
+    deprecation = "Only for backward compatibility. Do not use.",
+    visibility = ["//visibility:public"],
+)
+
+# Source protos that are typically part of the protobuf runtime.
+#
+# DEPRECATED: Prefer :well_known_type_protos for the Well-Known Types
+# (https://developers.google.com/protocol-buffers/docs/reference/google.protobuf)
+# or :descriptor_proto(_srcs) for descriptor.proto (source), or
+# :compiler_plugin_proto for compiler/plugin.proto.
+filegroup(
+    name = "well_known_protos",
+    srcs = [
+        ":descriptor_proto_srcs",
+        ":well_known_type_protos",
+        "//src/google/protobuf/compiler:plugin.proto",
+    ],
+    deprecation = "Prefer :well_known_type_protos instead.",
+    visibility = ["//visibility:public"],
+)
+
+internal_ruby_proto_library(
+    name = "well_known_ruby_protos",
+    srcs = [":well_known_protos"],
+    includes = ["src"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//ruby:__subpackages__",
+    ],
+)
+
 ################################################################################
 # Protocol Buffers Compiler
 ################################################################################
 
-cc_library(
-    name = "protoc_lib",
-    srcs = [
-        # AUTOGEN(protoc_lib_srcs)
-        "src/google/protobuf/compiler/code_generator.cc",
-        "src/google/protobuf/compiler/command_line_interface.cc",
-        "src/google/protobuf/compiler/cpp/enum.cc",
-        "src/google/protobuf/compiler/cpp/enum_field.cc",
-        "src/google/protobuf/compiler/cpp/extension.cc",
-        "src/google/protobuf/compiler/cpp/field.cc",
-        "src/google/protobuf/compiler/cpp/file.cc",
-        "src/google/protobuf/compiler/cpp/generator.cc",
-        "src/google/protobuf/compiler/cpp/helpers.cc",
-        "src/google/protobuf/compiler/cpp/map_field.cc",
-        "src/google/protobuf/compiler/cpp/message.cc",
-        "src/google/protobuf/compiler/cpp/message_field.cc",
-        "src/google/protobuf/compiler/cpp/padding_optimizer.cc",
-        "src/google/protobuf/compiler/cpp/parse_function_generator.cc",
-        "src/google/protobuf/compiler/cpp/primitive_field.cc",
-        "src/google/protobuf/compiler/cpp/service.cc",
-        "src/google/protobuf/compiler/cpp/string_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_doc_comment.cc",
-        "src/google/protobuf/compiler/csharp/csharp_enum.cc",
-        "src/google/protobuf/compiler/csharp/csharp_enum_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_field_base.cc",
-        "src/google/protobuf/compiler/csharp/csharp_generator.cc",
-        "src/google/protobuf/compiler/csharp/csharp_helpers.cc",
-        "src/google/protobuf/compiler/csharp/csharp_map_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_message.cc",
-        "src/google/protobuf/compiler/csharp/csharp_message_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_primitive_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_reflection_class.cc",
-        "src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc",
-        "src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc",
-        "src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc",
-        "src/google/protobuf/compiler/java/context.cc",
-        "src/google/protobuf/compiler/java/doc_comment.cc",
-        "src/google/protobuf/compiler/java/enum.cc",
-        "src/google/protobuf/compiler/java/enum_field.cc",
-        "src/google/protobuf/compiler/java/enum_field_lite.cc",
-        "src/google/protobuf/compiler/java/enum_lite.cc",
-        "src/google/protobuf/compiler/java/extension.cc",
-        "src/google/protobuf/compiler/java/extension_lite.cc",
-        "src/google/protobuf/compiler/java/field.cc",
-        "src/google/protobuf/compiler/java/file.cc",
-        "src/google/protobuf/compiler/java/generator.cc",
-        "src/google/protobuf/compiler/java/generator_factory.cc",
-        "src/google/protobuf/compiler/java/helpers.cc",
-        "src/google/protobuf/compiler/java/kotlin_generator.cc",
-        "src/google/protobuf/compiler/java/map_field.cc",
-        "src/google/protobuf/compiler/java/map_field_lite.cc",
-        "src/google/protobuf/compiler/java/message.cc",
-        "src/google/protobuf/compiler/java/message_builder.cc",
-        "src/google/protobuf/compiler/java/message_builder_lite.cc",
-        "src/google/protobuf/compiler/java/message_field.cc",
-        "src/google/protobuf/compiler/java/message_field_lite.cc",
-        "src/google/protobuf/compiler/java/message_lite.cc",
-        "src/google/protobuf/compiler/java/name_resolver.cc",
-        "src/google/protobuf/compiler/java/primitive_field.cc",
-        "src/google/protobuf/compiler/java/primitive_field_lite.cc",
-        "src/google/protobuf/compiler/java/service.cc",
-        "src/google/protobuf/compiler/java/shared_code_generator.cc",
-        "src/google/protobuf/compiler/java/string_field.cc",
-        "src/google/protobuf/compiler/java/string_field_lite.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_enum.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_extension.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_field.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_file.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_generator.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_helpers.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_map_field.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_message.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_message_field.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_oneof.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc",
-        "src/google/protobuf/compiler/php/php_generator.cc",
-        "src/google/protobuf/compiler/plugin.cc",
-        "src/google/protobuf/compiler/plugin.pb.cc",
-        "src/google/protobuf/compiler/python/generator.cc",
-        "src/google/protobuf/compiler/python/helpers.cc",
-        "src/google/protobuf/compiler/python/pyi_generator.cc",
-        "src/google/protobuf/compiler/ruby/ruby_generator.cc",
-        "src/google/protobuf/compiler/subprocess.cc",
-        "src/google/protobuf/compiler/zip_writer.cc",
-    ],
-    copts = COPTS,
-    includes = ["src/"],
-    linkopts = LINK_OPTS,
-    visibility = ["//visibility:public"],
-    deps = [":protobuf"],
-)
-
 cc_binary(
     name = "protoc",
-    srcs = ["src/google/protobuf/compiler/main.cc"],
+    copts = COPTS,
     linkopts = LINK_OPTS + PROTOC_LINK_OPTS,
     visibility = ["//visibility:public"],
-    deps = [":protoc_lib"],
+    deps = ["//src/google/protobuf/compiler:protoc_lib"],
 )
 
 ################################################################################
-# Tests
+# C++ runtime
 ################################################################################
 
-filegroup(
-    name = "testdata",
-    srcs = glob(["src/google/protobuf/testdata/**/*"]),
-    visibility = [
-        "//:__subpackages__",
-        "@upb//:__subpackages__",
-    ],
+# The "lite" runtime works for .proto files that specify the option:
+#     optimize_for = LITE_RUNTIME;
+#
+# The lite runtime does not include the `Reflection` APIs (including
+# `Descriptor` and related types) or Well-Known Types.
+#
+# See also:
+#     https://developers.google.com/protocol-buffers/docs/reference/cpp-generated#message
+#     https://developers.google.com/protocol-buffers/docs/reference/google.protobuf
+alias(
+    name = "protobuf_lite",
+    actual = "//src/google/protobuf:protobuf_lite",
+    visibility = ["//visibility:public"],
 )
 
-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",
-]
-
-LITE_TEST_PROTOS = ["src/" + s for s in RELATIVE_LITE_TEST_PROTOS]
-
-RELATIVE_TEST_PROTOS = [
-    # AUTOGEN(test_protos)
-    "google/protobuf/any_test.proto",
-    "google/protobuf/compiler/cpp/test_bad_identifiers.proto",
-    "google/protobuf/compiler/cpp/test_large_enum_value.proto",
-    "google/protobuf/map_proto2_unittest.proto",
-    "google/protobuf/map_unittest.proto",
-    "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",
-    "google/protobuf/util/internal/testdata/anys.proto",
-    "google/protobuf/util/internal/testdata/books.proto",
-    "google/protobuf/util/internal/testdata/default_value.proto",
-    "google/protobuf/util/internal/testdata/default_value_test.proto",
-    "google/protobuf/util/internal/testdata/field_mask.proto",
-    "google/protobuf/util/internal/testdata/maps.proto",
-    "google/protobuf/util/internal/testdata/oneofs.proto",
-    "google/protobuf/util/internal/testdata/proto3.proto",
-    "google/protobuf/util/internal/testdata/struct.proto",
-    "google/protobuf/util/internal/testdata/timestamp_duration.proto",
-    "google/protobuf/util/internal/testdata/wrappers.proto",
-    "google/protobuf/util/json_format.proto",
-    "google/protobuf/util/json_format_proto3.proto",
-    "google/protobuf/util/message_differencer_unittest.proto",
-]
-
-TEST_PROTOS = ["src/" + s for s in RELATIVE_TEST_PROTOS]
-
-GENERIC_RELATIVE_TEST_PROTOS = [
-    "google/protobuf/map_proto2_unittest.proto",
-    "google/protobuf/map_unittest.proto",
-    "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",
-    srcs = LITE_TEST_PROTOS + GENERIC_TEST_PROTOS,
-    strip_import_prefix = "src",
-    visibility = ["//:__subpackages__"],
-    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,
-    include = "src",
-    default_runtime = ":protobuf",
-    protoc = ":protoc",
-    deps = [":cc_wkt_protos"],
-)
-
-COMMON_TEST_SRCS = [
-    # AUTOGEN(common_test_srcs)
-    "src/google/protobuf/arena_test_util.cc",
-    "src/google/protobuf/map_lite_test_util.cc",
-    "src/google/protobuf/test_util_lite.cc",
-    "src/google/protobuf/map_test_util.inc",
-    "src/google/protobuf/reflection_tester.cc",
-    "src/google/protobuf/test_util.cc",
-    "src/google/protobuf/test_util.inc",
-    "src/google/protobuf/testing/file.cc",
-    "src/google/protobuf/testing/googletest.cc",
-]
-
-cc_binary(
-    name = "test_plugin",
-    testonly = True,
-    srcs = [
-        # AUTOGEN(test_plugin_srcs)
-        "src/google/protobuf/compiler/mock_code_generator.cc",
-        "src/google/protobuf/compiler/test_plugin.cc",
-        "src/google/protobuf/testing/file.cc",
-    ],
-    deps = [
-        ":protobuf",
-        ":protoc_lib",
-        "@com_google_googletest//:gtest",
-    ],
-)
-
-cc_test(
-    name = "win32_test",
-    srcs = ["src/google/protobuf/io/io_win32_unittest.cc"],
-    tags = [
-        "manual",
-        "windows",
-    ],
-    deps = [
-        ":protobuf_lite",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ],
-)
-
-cc_test(
-    name = "protobuf_test",
-    srcs = COMMON_TEST_SRCS + [
-        # AUTOGEN(test_srcs)
-        "src/google/protobuf/any_test.cc",
-        "src/google/protobuf/arena_unittest.cc",
-        "src/google/protobuf/arenastring_unittest.cc",
-        "src/google/protobuf/arenaz_sampler_test.cc",
-        "src/google/protobuf/compiler/annotation_test_util.cc",
-        "src/google/protobuf/compiler/command_line_interface_unittest.cc",
-        "src/google/protobuf/compiler/cpp/bootstrap_unittest.cc",
-        "src/google/protobuf/compiler/cpp/metadata_test.cc",
-        "src/google/protobuf/compiler/cpp/move_unittest.cc",
-        "src/google/protobuf/compiler/cpp/plugin_unittest.cc",
-        "src/google/protobuf/compiler/cpp/unittest.cc",
-        "src/google/protobuf/compiler/cpp/unittest.inc",
-        "src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc",
-        "src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc",
-        "src/google/protobuf/compiler/importer_unittest.cc",
-        "src/google/protobuf/compiler/java/doc_comment_unittest.cc",
-        "src/google/protobuf/compiler/java/plugin_unittest.cc",
-        "src/google/protobuf/compiler/mock_code_generator.cc",
-        "src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc",
-        "src/google/protobuf/compiler/parser_unittest.cc",
-        "src/google/protobuf/compiler/python/plugin_unittest.cc",
-        "src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc",
-        "src/google/protobuf/descriptor_database_unittest.cc",
-        "src/google/protobuf/descriptor_unittest.cc",
-        "src/google/protobuf/drop_unknown_fields_test.cc",
-        "src/google/protobuf/dynamic_message_unittest.cc",
-        "src/google/protobuf/extension_set_unittest.cc",
-        "src/google/protobuf/generated_message_reflection_unittest.cc",
-        "src/google/protobuf/generated_message_tctable_lite_test.cc",
-        "src/google/protobuf/inlined_string_field_unittest.cc",
-        "src/google/protobuf/io/coded_stream_unittest.cc",
-        "src/google/protobuf/io/io_win32_unittest.cc",
-        "src/google/protobuf/io/printer_unittest.cc",
-        "src/google/protobuf/io/tokenizer_unittest.cc",
-        "src/google/protobuf/io/zero_copy_stream_unittest.cc",
-        "src/google/protobuf/map_field_test.cc",
-        "src/google/protobuf/map_test.cc",
-        "src/google/protobuf/map_test.inc",
-        "src/google/protobuf/message_unittest.cc",
-        "src/google/protobuf/message_unittest.inc",
-        "src/google/protobuf/no_field_presence_test.cc",
-        "src/google/protobuf/preserve_unknown_enum_test.cc",
-        "src/google/protobuf/proto3_arena_lite_unittest.cc",
-        "src/google/protobuf/proto3_arena_unittest.cc",
-        "src/google/protobuf/proto3_lite_unittest.cc",
-        "src/google/protobuf/proto3_lite_unittest.inc",
-        "src/google/protobuf/reflection_ops_unittest.cc",
-        "src/google/protobuf/repeated_field_reflection_unittest.cc",
-        "src/google/protobuf/repeated_field_unittest.cc",
-        "src/google/protobuf/stubs/bytestream_unittest.cc",
-        "src/google/protobuf/stubs/common_unittest.cc",
-        "src/google/protobuf/stubs/int128_unittest.cc",
-        "src/google/protobuf/stubs/status_test.cc",
-        "src/google/protobuf/stubs/statusor_test.cc",
-        "src/google/protobuf/stubs/stringpiece_unittest.cc",
-        "src/google/protobuf/stubs/stringprintf_unittest.cc",
-        "src/google/protobuf/stubs/structurally_valid_unittest.cc",
-        "src/google/protobuf/stubs/strutil_unittest.cc",
-        "src/google/protobuf/stubs/template_util_unittest.cc",
-        "src/google/protobuf/stubs/time_test.cc",
-        "src/google/protobuf/text_format_unittest.cc",
-        "src/google/protobuf/unknown_field_set_unittest.cc",
-        "src/google/protobuf/util/delimited_message_util_test.cc",
-        "src/google/protobuf/util/field_comparator_test.cc",
-        "src/google/protobuf/util/field_mask_util_test.cc",
-        "src/google/protobuf/util/internal/default_value_objectwriter_test.cc",
-        "src/google/protobuf/util/internal/json_objectwriter_test.cc",
-        "src/google/protobuf/util/internal/json_stream_parser_test.cc",
-        "src/google/protobuf/util/internal/protostream_objectsource_test.cc",
-        "src/google/protobuf/util/internal/protostream_objectwriter_test.cc",
-        "src/google/protobuf/util/internal/type_info_test_helper.cc",
-        "src/google/protobuf/util/json_util_test.cc",
-        "src/google/protobuf/util/message_differencer_unittest.cc",
-        "src/google/protobuf/util/time_util_test.cc",
-        "src/google/protobuf/util/type_resolver_util_test.cc",
-        "src/google/protobuf/well_known_types_unittest.cc",
-        "src/google/protobuf/wire_format_unittest.cc",
-        "src/google/protobuf/wire_format_unittest.inc",
-    ],
-    copts = COPTS + select({
-        "//build_defs:config_msvc": [],
-        "//conditions:default": [
-            "-Wno-deprecated-declarations",
-        ],
-    }),
-    data = [
-        # Files for csharp_bootstrap_unittest.cc.
-        "//conformance:all_files",
-        ":test_plugin",
-    ] + glob([
-        "src/google/protobuf/**/*",
-    ]) + glob(
-        [
-            # Files for csharp_bootstrap_unittest.cc.
-            "csharp/src/**/*",
-        ],
-        allow_empty = True,
-    ),
-    includes = [
-        "src/",
-    ],
+cc_library(
+    name = "protobuf",
+    hdrs = glob([
+        "src/**/*.h",
+        "src/**/*.inc",
+    ]),
+    copts = COPTS,
+    include_prefix = "google/protobuf/io",
     linkopts = LINK_OPTS,
+    visibility = ["//visibility:public"],
     deps = [
-        ":cc_test_protos",
-        ":protobuf",
-        ":protoc_lib",
-        "@com_google_googletest//:gtest",
-        "@com_google_googletest//:gtest_main",
-    ] + select({
-        "//build_defs:config_msvc": [],
-        "//conditions:default": ["@zlib//:zlib"],
-    }),
+        "//src/google/protobuf",
+        "//src/google/protobuf/compiler:importer",
+        "//src/google/protobuf/util:delimited_message_util",
+        "//src/google/protobuf/util:differencer",
+        "//src/google/protobuf/util:field_mask_util",
+        "//src/google/protobuf/util:json_util",
+        "//src/google/protobuf/util:time_util",
+        "//src/google/protobuf/util:type_resolver_util",
+    ],
+)
+
+# This provides just the header files for use in projects that need to build
+# shared libraries for dynamic loading. This target is available until Bazel
+# adds native support for such use cases.
+# TODO(keveman): Remove this target once the support gets added to Bazel.
+alias(
+    name = "protobuf_headers",
+    actual = "//src/google/protobuf:protobuf_headers",
+    visibility = ["//visibility:public"],
+)
+
+alias(
+    name = "json",
+    actual = "//src/google/protobuf/json",
+    visibility = ["//visibility:public"],
 )
 
 ################################################################################
@@ -797,288 +261,57 @@
 # Python support
 ################################################################################
 
-py_library(
-    name = "python_srcs",
-    srcs = glob(
-        [
-            "python/google/protobuf/**/*.py",
-        ],
-    ),
-    imports = ["python"],
-    srcs_version = "PY2AND3",
-    visibility = ["@upb//:__subpackages__"],
-)
-
-py_library(
-    name = "python_test_srcs",
-    srcs = glob(
-        [
-            "python/google/protobuf/internal/*_test.py",
-            "python/google/protobuf/internal/test_util.py",
-        ],
-    ),
-    imports = ["python"],
-    srcs_version = "PY3",
-    visibility = ["@upb//:__subpackages__"],
-)
-
-cc_binary(
-    name = "python/google/protobuf/internal/_api_implementation.so",
-    srcs = ["python/google/protobuf/internal/api_implementation.cc"],
-    copts = COPTS + [
-        "-DPYTHON_PROTO2_CPP_IMPL_V2",
-    ],
-    linkshared = 1,
-    linkstatic = 1,
-    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",
-    ],
-    deps = select({
-        "//conditions:default": [],
-        ":use_fast_cpp_protos": ["//external:python_headers"],
-    }),
-)
-
-cc_binary(
-    name = "python/google/protobuf/pyext/_message.so",
-    srcs = glob([
-        "python/google/protobuf/pyext/*.cc",
-        "python/google/protobuf/pyext/*.h",
-    ]),
-    copts = COPTS + [
-        "-DGOOGLE_PROTOBUF_HAS_ONEOF=1",
-    ] + select({
-        "//conditions:default": [],
-        ":allow_oversize_protos": ["-DPROTOBUF_PYTHON_ALLOW_OVERSIZE_PROTOS=1"],
-    }),
-    includes = [
-        "python/",
-        "src/",
-    ],
-    linkshared = 1,
-    linkstatic = 1,
-    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",
-    ],
-    deps = [
-        ":protobuf",
-        ":proto_api",
-    ] + select({
-        "//conditions:default": [],
-        ":use_fast_cpp_protos": ["//external:python_headers"],
-    }),
-)
-
-config_setting(
-    name = "use_fast_cpp_protos",
-    values = {
-        "define": "use_fast_cpp_protos=true",
-    },
-    visibility = [
-        # Public, but Protobuf only visibility.
-        "//:__subpackages__",
-    ],
-)
-
-config_setting(
-    name = "allow_oversize_protos",
-    values = {
-        "define": "allow_oversize_protos=true",
-    },
-    visibility = [
-        # Public, but Protobuf only visibility.
-        "//:__subpackages__",
-    ],
-)
-
-# Copy the builtin proto files from src/google/protobuf to
-# python/google/protobuf. This way, the generated Python sources will be in the
-# same directory as the Python runtime sources. This is necessary for the
-# modules to be imported correctly since they are all part of the same Python
-# package.
-internal_copied_filegroup(
-    name = "protos_python",
-    srcs = [
-        "src/google/protobuf/any.proto",
-        "src/google/protobuf/api.proto",
-        "src/google/protobuf/compiler/plugin.proto",
-        "src/google/protobuf/descriptor.proto",
-        "src/google/protobuf/duration.proto",
-        "src/google/protobuf/empty.proto",
-        "src/google/protobuf/field_mask.proto",
-        "src/google/protobuf/source_context.proto",
-        "src/google/protobuf/struct.proto",
-        "src/google/protobuf/timestamp.proto",
-        "src/google/protobuf/type.proto",
-        "src/google/protobuf/wrappers.proto",
-    ],
-    dest = "python",
-    strip_prefix = "src",
-)
-
-py_proto_library(
-    name = "well_known_types_py_pb2",
-    srcs = [
-        "python/google/protobuf/any.proto",
-        "python/google/protobuf/api.proto",
-        "python/google/protobuf/compiler/plugin.proto",
-        "python/google/protobuf/descriptor.proto",
-        "python/google/protobuf/duration.proto",
-        "python/google/protobuf/empty.proto",
-        "python/google/protobuf/field_mask.proto",
-        "python/google/protobuf/source_context.proto",
-        "python/google/protobuf/struct.proto",
-        "python/google/protobuf/timestamp.proto",
-        "python/google/protobuf/type.proto",
-        "python/google/protobuf/wrappers.proto",
-    ],
-    include = "python",
-    default_runtime = "",
-    protoc = ":protoc",
-    srcs_version = "PY2AND3",
-    visibility = ["//visibility:public"],
-)
-
-py_library(
+alias(
     name = "protobuf_python",
-    data = select({
-        "//conditions:default": [],
-        ":use_fast_cpp_protos": [
-            ":python/google/protobuf/internal/_api_implementation.so",
-            ":python/google/protobuf/pyext/_message.so",
-        ],
-    }),
+    actual = "//python:protobuf_python",
     visibility = ["//visibility:public"],
-    deps = [
-        ":python_srcs",
-        ":well_known_types_py_pb2",
-    ],
 )
 
-# Copy the test proto files from src/google/protobuf to
-# python/google/protobuf. This way, the generated Python sources will be in the
-# same directory as the Python runtime sources. This is necessary for the
-# modules to be imported correctly by the tests since they are all part of the
-# same Python package.
-internal_copied_filegroup(
-    name = "protos_python_test",
-    srcs = LITE_TEST_PROTOS + TEST_PROTOS,
-    dest = "python",
-    strip_prefix = "src",
+alias(
+    name = "python_srcs",
+    actual = "//python:python_srcs",
+    visibility = ["@upb//:__subpackages__"],
 )
 
-# TODO(dzc): Remove this once py_proto_library can have labels in srcs, in
-# which case we can simply add :protos_python_test in srcs.
-COPIED_LITE_TEST_PROTOS = ["python/" + s for s in RELATIVE_LITE_TEST_PROTOS]
+alias(
+    name = "python_test_srcs",
+    actual = "//python:python_test_srcs",
+    visibility = ["@upb//:__subpackages__"],
+)
 
-COPIED_TEST_PROTOS = ["python/" + s for s in RELATIVE_TEST_PROTOS]
+alias(
+    name = "well_known_types_py_pb2",
+    actual = "//python:well_known_types_py_pb2",
+    visibility = ["//visibility:public"],
+)
 
-py_proto_library(
+alias(
     name = "python_common_test_protos",
-    srcs = COPIED_LITE_TEST_PROTOS + COPIED_TEST_PROTOS,
-    include = "python",
-    default_runtime = "",
-    protoc = ":protoc",
-    srcs_version = "PY2AND3",
+    actual = "//python:python_common_test_protos",
     visibility = ["//visibility:public"],
-    deps = [":well_known_types_py_pb2"],
 )
 
-py_proto_library(
+alias(
     name = "python_specific_test_protos",
-    srcs = glob([
-        "python/google/protobuf/internal/*.proto",
-        "python/google/protobuf/internal/import_test_package/*.proto",
-    ]),
-    include = "python",
-    default_runtime = ":protobuf_python",
-    protoc = ":protoc",
-    srcs_version = "PY2AND3",
+    actual = "//python:python_specific_test_protos",
     visibility = ["//visibility:public"],
-    deps = [":python_common_test_protos"],
-)
-
-py_library(
-    name = "python_tests",
-    srcs = glob(
-        [
-            "python/google/protobuf/internal/*_test.py",
-            "python/google/protobuf/internal/test_util.py",
-            "python/google/protobuf/internal/import_test_package/__init__.py",
-        ],
-    ),
-    imports = ["python"],
-    srcs_version = "PY2AND3",
-    deps = [
-        ":protobuf_python",
-        ":python_common_test_protos",
-        ":python_specific_test_protos",
-    ],
-)
-
-internal_protobuf_py_tests(
-    name = "python_tests_batch",
-    data = glob([
-        "src/google/protobuf/**/*",
-    ]),
-    modules = [
-        "descriptor_database_test",
-        "descriptor_pool_test",
-        "descriptor_test",
-        "generator_test",
-        "json_format_test",
-        "message_factory_test",
-        "message_test",
-        "proto_builder_test",
-        "reflection_test",
-        "service_reflection_test",
-        "symbol_database_test",
-        "text_encoding_test",
-        "text_format_test",
-        "unknown_fields_test",
-        "wire_format_test",
-    ],
-    deps = [":python_tests"],
-)
-
-cc_library(
-    name = "proto_api",
-    hdrs = ["python/google/protobuf/proto_api.h"],
-    visibility = ["//visibility:public"],
-    deps = [
-        "//external:python_headers",
-    ],
 )
 
 proto_lang_toolchain(
     name = "cc_toolchain",
     blacklisted_protos = [
-        "@com_google_protobuf//:any_proto",
-        "@com_google_protobuf//:api_proto",
         "@com_google_protobuf//:compiler_plugin_proto",
         "@com_google_protobuf//:descriptor_proto",
-        "@com_google_protobuf//:duration_proto",
-        "@com_google_protobuf//:empty_proto",
-        "@com_google_protobuf//:field_mask_proto",
-        "@com_google_protobuf//:source_context_proto",
-        "@com_google_protobuf//:struct_proto",
-        "@com_google_protobuf//:timestamp_proto",
-        "@com_google_protobuf//:type_proto",
-        "@com_google_protobuf//:wrappers_proto",
     ],
     command_line = "--cpp_out=$(OUT)",
     runtime = ":protobuf",
     visibility = ["//visibility:public"],
 )
 
+################################################################################
+# Objective-C support
+################################################################################
+
 alias(
     name = "objectivec",
     actual = "//objectivec",
@@ -1094,84 +327,80 @@
 )
 
 ################################################################################
-# Test generated proto support
+# Test protos
 ################################################################################
 
+alias(
+    name = "lite_test_proto_srcs",
+    actual = "//src/google/protobuf:lite_test_proto_srcs",  # proto_library
+    visibility = ["//:__subpackages__"],
+)
+
+alias(
+    name = "lite_test_protos",
+    actual = "//src/google/protobuf:lite_test_protos",  # proto_library
+    visibility = ["//:__subpackages__"],
+)
+
+alias(
+    name = "test_proto_srcs",
+    actual = "//src/google/protobuf:test_proto_srcs",  # filegroup
+    visibility = ["//:__subpackages__"],
+)
+
+alias(
+    name = "test_protos",
+    actual = "//src/google/protobuf:test_protos",  # proto_library
+    visibility = ["//:__subpackages__"],
+)
+
+# Validate generated proto source inputs:
+
 genrule(
     name = "generated_protos",
-    srcs = ["src/google/protobuf/unittest_import.proto"],
+    testonly = 1,
+    srcs = ["//src/google/protobuf:test_proto_srcs"],
     outs = ["unittest_gen_import.proto"],
-    cmd = "cat $(SRCS) | sed 's|google/|src/google/|' >  $(OUTS)",
+    cmd = "cat src/google/protobuf/unittest_import.proto > $@",
 )
 
 proto_library(
     name = "generated_protos_proto",
-    srcs = [
-        "src/google/protobuf/unittest_import_public.proto",
-        "unittest_gen_import.proto",
-    ],
+    testonly = 1,
+    srcs = [":generated_protos"],
+    deps = ["//src/google/protobuf:generic_test_protos"],
 )
 
-py_proto_library(
+internal_py_proto_library(
     name = "generated_protos_py",
-    srcs = [
-        "src/google/protobuf/unittest_import_public.proto",
-        "unittest_gen_import.proto",
-    ],
+    testonly = 1,
+    srcs = [":generated_protos"],
     default_runtime = "",
     protoc = ":protoc",
+    deps = ["//python:python_common_test_protos"],
 )
 
 ################################################################################
 # Conformance tests
 ################################################################################
 
-alias(
-    name = "conformance_test_runner",
-    actual = "//conformance:conformance_test_runner",
-    visibility = ["//visibility:public"],
-)
-
-proto_library(
-    name = "test_messages_proto2_proto",
-    strip_import_prefix = "src",
-    srcs = ["src/google/protobuf/test_messages_proto2.proto"],
-    visibility = ["//visibility:public"],
-)
-
-proto_library(
-    name = "test_messages_proto3_proto",
-    strip_import_prefix = "src",
-    srcs = ["src/google/protobuf/test_messages_proto3.proto"],
-    visibility = ["//visibility:public"],
-    deps = [
-        ":any_proto",
-        ":duration_proto",
-        ":field_mask_proto",
-        ":struct_proto",
-        ":timestamp_proto",
-        ":wrappers_proto",
+cc_proto_library(
+    name = "test_messages_proto2_cc_proto",
+    visibility = [
+        "//conformance:__pkg__",
+        "//src:__subpackages__",
     ],
+    deps = ["//src/google/protobuf:test_messages_proto2_proto"],
 )
 
-# TODO: re-enable this test if appropriate, or replace with something that
-# uses the new setup.
-# sh_test(
-#     name = "build_files_updated_unittest",
-#     srcs = [
-#         "build_files_updated_unittest.sh",
-#     ],
-#     data = [
-#         "BUILD",
-#         "cmake/extract_includes.bat.in",
-#         "cmake/libprotobuf.cmake",
-#         "cmake/libprotobuf-lite.cmake",
-#         "cmake/libprotoc.cmake",
-#         "cmake/tests.cmake",
-#         "src/Makefile.am",
-#         "update_file_lists.sh",
-#     ],
-# )
+cc_proto_library(
+    name = "test_messages_proto3_cc_proto",
+    visibility = [
+        "//conformance:__pkg__",
+        "//src:__subpackages__",
+    ],
+    deps = ["//src/google/protobuf:test_messages_proto3_proto"],
+)
 
 java_proto_library(
     name = "test_messages_proto2_java_proto",
@@ -1179,7 +408,7 @@
         "//conformance:__pkg__",
         "//java:__subpackages__",
     ],
-    deps = [":test_messages_proto2_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto2_proto"],
 )
 
 java_proto_library(
@@ -1188,7 +417,7 @@
         "//conformance:__pkg__",
         "//java:__subpackages__",
     ],
-    deps = [":test_messages_proto3_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto3_proto"],
 )
 
 java_lite_proto_library(
@@ -1197,7 +426,7 @@
         "//conformance:__pkg__",
         "//java:__subpackages__",
     ],
-    deps = [":test_messages_proto2_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto2_proto"],
 )
 
 java_lite_proto_library(
@@ -1206,7 +435,89 @@
         "//conformance:__pkg__",
         "//java:__subpackages__",
     ],
-    deps = [":test_messages_proto3_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto3_proto"],
+)
+
+internal_objc_proto_library(
+    name = "test_messages_proto2_objc_proto",
+    testonly = 1,
+    srcs = ["//src/google/protobuf:test_messages_proto2.proto"],
+    includes = ["src/google/protobuf"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//objectivec:__subpackages__",
+    ],
+)
+
+internal_objc_proto_library(
+    name = "test_messages_proto3_objc_proto",
+    testonly = 1,
+    srcs = ["//src/google/protobuf:test_messages_proto3.proto"],
+    includes = [
+        "src/google/protobuf",
+        # The above must come first.
+        "src",
+    ],
+    proto_deps = [":well_known_protos"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//objectivec:__subpackages__",
+    ],
+)
+
+internal_php_proto_library(
+    name = "test_messages_proto3_php_proto",
+    testonly = 1,
+    srcs = ["//src/google/protobuf:test_messages_proto3.proto"],
+    outs = [
+        "GPBMetadata/TestMessagesProto3.php",
+        "Protobuf_test_messages/Proto3/EnumOnlyProto3.php",
+        "Protobuf_test_messages/Proto3/EnumOnlyProto3/PBBool.php",
+        "Protobuf_test_messages/Proto3/ForeignEnum.php",
+        "Protobuf_test_messages/Proto3/ForeignMessage.php",
+        "Protobuf_test_messages/Proto3/NullHypothesisProto3.php",
+        "Protobuf_test_messages/Proto3/TestAllTypesProto3.php",
+        "Protobuf_test_messages/Proto3/TestAllTypesProto3/AliasedEnum.php",
+        "Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedEnum.php",
+        "Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedMessage.php",
+    ],
+    includes = [
+        "src/google/protobuf",
+        # The above must come first.
+        "src",
+    ],
+    proto_deps = [":well_known_protos"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//php:__subpackages__",
+    ],
+)
+
+internal_ruby_proto_library(
+    name = "test_messages_proto2_ruby_proto",
+    testonly = 1,
+    srcs = ["//src/google/protobuf:test_messages_proto2.proto"],
+    includes = ["src/google/protobuf"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//ruby:__subpackages__",
+    ],
+)
+
+internal_ruby_proto_library(
+    name = "test_messages_proto3_ruby_proto",
+    testonly = 1,
+    srcs = ["//src/google/protobuf:test_messages_proto3.proto"],
+    includes = [
+        "src/google/protobuf",
+        # The above must come first.
+        "src",
+    ],
+    proto_deps = [":well_known_protos"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//ruby:__subpackages__",
+    ],
 )
 
 filegroup(
@@ -1215,46 +526,6 @@
     visibility = ["//visibility:public"],
 )
 
-# Kotlin proto rules
-
-proto_library(
-    name = "kt_unittest_lite",
-    srcs = [
-        "src/google/protobuf/map_lite_unittest.proto",
-        "src/google/protobuf/unittest_import_lite.proto",
-        "src/google/protobuf/unittest_import_public_lite.proto",
-        "src/google/protobuf/unittest_lite.proto",
-    ],
-    visibility = ["//java/kotlin-lite:__subpackages__"],
-    strip_import_prefix = "src",
-)
-
-proto_library(
-    name = "kt_unittest",
-    srcs = [
-        "src/google/protobuf/map_proto2_unittest.proto",
-        "src/google/protobuf/unittest.proto",
-        "src/google/protobuf/unittest_import.proto",
-        "src/google/protobuf/unittest_import_public.proto",
-    ],
-    visibility = ["//java/kotlin:__subpackages__"],
-    strip_import_prefix = "src",
-)
-
-proto_library(
-    name = "kt_proto3_unittest",
-    srcs = [
-        "src/google/protobuf/unittest_import.proto",
-        "src/google/protobuf/unittest_import_public.proto",
-        "src/google/protobuf/unittest_proto3.proto",
-    ],
-    visibility = [
-        "//java/kotlin:__subpackages__",
-        "//java/kotlin-lite:__subpackages__",
-    ],
-    strip_import_prefix = "src",
-)
-
 ################################################################################
 # Packaging rules
 ################################################################################
@@ -1268,22 +539,6 @@
             "cmake/*.cmake",
             "cmake/*.in",
             "editors/*",
-
-            # Several of these files are generated by autogen.sh, so using
-            # glob() lets us ignore them if they are missing. (This is not good
-            # practice, though.)
-            "Makefile.in",
-            "aclocal.m4",
-            "ar-lib",
-            "compile",
-            "config*",
-            "depcomp",
-            "install-sh",
-            "ltmain.sh",
-            "m4/*.m4",
-            "missing",
-            "protobuf*.pc.in",
-            "test-driver",
         ],
         allow_empty = True,
     ) + [
@@ -1292,37 +547,19 @@
         "CMakeLists.txt",
         "CONTRIBUTORS.txt",
         "LICENSE",
-        "Makefile.am",
         "README.md",
         "WORKSPACE",
-        "autogen.sh",
-        "build_files_updated_unittest.sh",
         "cmake/CMakeLists.txt",
         "cmake/README.md",
         "generate_descriptor_proto.sh",
         "maven_install.json",
-        "update_file_lists.sh",
         "//third_party:BUILD.bazel",
         "//third_party:zlib.BUILD",
-        "//util/python:BUILD.bazel",
     ],
     strip_prefix = strip_prefix.from_root(""),
     visibility = ["//pkg:__pkg__"],
 )
 
-# C++ runtime
-pkg_files(
-    name = "cpp_dist_files",
-    srcs = glob(
-        ["src/**/*"],
-        exclude = [
-            "src/google/protobuf/compiler/objectivec/method_dump.sh",  # not in autotools dist
-        ],
-    ),
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//pkg:__pkg__"],
-)
-
 # Additional files for C#
 pkg_files(
     name = "csharp_dist_files",
@@ -1340,29 +577,3 @@
     ],
     visibility = ["//pkg:__pkg__"],
 )
-
-# Python runtime
-pkg_files(
-    name = "python_dist_files",
-    srcs = glob([
-        "python/google/**/*.proto",
-        "python/google/**/*.py",
-        "python/google/protobuf/internal/*.cc",
-        "python/google/protobuf/pyext/*.cc",
-        "python/google/protobuf/pyext/*.h",
-    ]) + [
-        "python/MANIFEST.in",
-        "python/README.md",
-        "python/google/protobuf/proto_api.h",
-        "python/google/protobuf/pyext/README",
-        "python/google/protobuf/python_protobuf.h",
-        "python/mox.py",
-        "python/release.sh",
-        "python/setup.cfg",
-        "python/setup.py",
-        "python/stubout.py",
-        "python/tox.ini",
-    ],
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//pkg:__pkg__"],
-)
diff --git a/CHANGES.txt b/CHANGES.txt
index 98cdf20..88d1df9 100644
--- a/CHANGES.txt
+++ b/CHANGES.txt
@@ -1,3 +1,86 @@
+2022-07-01 Unreleased version
+  C++
+  * cpp_generated_lib_linked support is removed in protoc
+  * Reduced .pb.o object file size slightly by explicitly instantiating
+    InternalMetadata templates in the runtime.
+  * Add C++20 keywords guarded by PROTOBUF_FUTURE_CPP20_KEYWORDS
+  * Fixed crash in ThreadLocalStorage for pre-C++17 compilers on 32-bit ARM.
+  * Clarified that JSON API non-OK statuses are not a stable API.
+  * Added a default implementation of MessageDifferencer::Reporter methods.
+  * proto2::MapPair is now an alias to std::pair.
+  * Hide C++ RepeatedField::UnsafeArenaSwap
+  * Use table-driven parser for reflection based objects.
+  * Update Map's InternalSwap() to take a pointer to the other Map.
+  * Add ARM-optimized Varint decoding functions.
+  * Minor optimization for parsing groups
+  * Declare ReflectiveProtoHook class
+  * Reduce size of VarintParse code in protocol buffers, by calling the shared
+    routine after handling just one-byte varint encoding inline, rather than
+    handling one-byte and two-byte varints inline.
+  * Avoid inlining some large heavily duplicated routines in repeated_ptr_field.h
+  * Add ReflectiveProtoHook to Reflection.
+  * Turns on table-driven parser for reflection based objects.
+  * Save code space by avoiding inlining of large-in-aggregate code-space MessageLite::~MessageLite destructor.
+  * Undefine the macro `linux` when compiling protobuf
+  * Reduce memory consumption of MessageSet parsing.
+  * Save code space by avoiding inlining of large-in-aggregate code-space MessageLite::~MessageLite destructor.
+  * Breaking change: delete Arena::Init
+  * Make a PROTOBUF_POISON/UNPOISON to reduce noise in the source
+  * Put alignment functions in "arena_align.h"
+  * Split off `cleanup` arena functions into "arena_cleanup.h"
+  * Fix signed / unsigned match in CHECK_EQ
+  * Kill Atomic<>. it's not pulling it's weight
+  * Move AllocationPolicy out of arena_impl, and unify arena_config for bazel
+  * Fix failure case in table-driven parser.
+  * Add a new JSON parser.
+  * Removed old JSON parsing code.
+  * Introduce the Printer::{SetRedactDebugString,SetRandomizeDebugString} private flags.
+  * Introduce global flags to control Printer::{SetRedactDebugString, SetRandomizeDebugString}.
+  * proto3 string fields no longer trigger clang-tidy warning bugprone-branch-clone.
+  * Fix the API of DescriptorUpgrader::set_allow_unknown_dependencies to set to True always, and to populate into the DescriptorPool as well.
+  * Report line numbers consistently in text-format deprecated-field warnings.
+  * Reserve C++20 keywords
+  * Fixed C++ code generation for protos that use int32_t, uint32_t, int64_t, uint64_t, size_t as field names.
+  * Annotate generated C++ public aliases for enum types.
+  * Change default arena max block size from 8K to 32K.
+
+
+  Kotlin
+  * Suppress deprecation warnings in Kotlin generated code.
+  * Kotlin generated code comments now use kdoc format instead of javadoc.
+  * Escape keywords in package names in proto generated code
+  * Add Kotlin enum int value getters and setters
+
+  Java
+  * Performance improvement for repeated use of FieldMaskUtil#merge by caching
+    constructed FieldMaskTrees.
+  * Optimized Java proto serialization gencode for protos having many extension ranges with few fields in between.
+  * More thoroughly annotate public generated code in Java lite protocol buffers.
+  * Fixed Bug in proto3 java lite repeated enum fields. Failed to call copyOnWrite before modifying previously built message. Causes modification to already "built" messages that should be immutable.
+  * Fix Java reflection serialization of empty packed fields.
+  * Refactoring java full runtime to reuse sub-message builders and prepare to migrate parsing logic from parse constructor to builder.
+  * Fix TextFormat parser to build up recurring (but supposedly not repeated) sub-messages directly from text rather than building a new sub-message and merging the fully formed message into the existing field.
+  * Make message-type extensions merge from wire-format instead of building up instances and merging afterwards. This has much better performance.
+  * Change the Lite runtime to prefer merging from the wireformat into mutable messages rather than building up a new immutable object before merging. This way results in fewer allocations and copy operations.
+  * Move proto wireformat parsing functionality from the private "parsing constructor" to the Builder class.
+  * Refactoring java full runtime to reuse sub-message builders and prepare to migrate parsing logic from parse constructor to builder.
+  * Move proto wireformat parsing functionality from the private "parsing constructor" to the Builder class.
+  * Change the Lite runtime to prefer merging from the wireformat into mutable messages rather than building up a new immutable object before merging. This way results in fewer allocations and copy operations.
+  * Make message-type extensions merge from wire-format instead of building up instances and merging afterwards. This has much better performance.
+  * Fix TextFormat parser to build up recurring (but supposedly not repeated) sub-messages directly from text rather than building a new sub-message and merging the fully formed message into the existing field.
+  * Fix bug in nested builder caching logic where cleared sub-field builders would remain dirty after a clear and build in a parent layer. https://github.com/protocolbuffers/protobuf/issues/10624
+  * Performance test for TextFormat to verify fix for https://github.com/protocolbuffers/protobuf/security/advisories/GHSA-h4h5-3hr4-j3g2
+
+  Python
+  * Changes ordering of printed fields in .pyi files from lexicographic to the same ordering found in the proto descriptor.
+  * Adds GeneratedCodeInfo annotations to python proto .pyi outputs as a base64 encoded docstring in the last line of the .pyi file for code analysis tools.
+  * Fix message factory's behavior in python cpp extension to return same message classes for same descriptor, even if the factories are different.
+  * Add type annotation for enum value fields in enum classes.
+
+  Compiler
+  * Print full path name of source .proto file on error
+  * Include proto message type in the annotation comments.
+
 2022-11-29 version 21.10 (C++/Java/Python/PHP/Objective-C/C#/Ruby)
 
   Java
@@ -33,7 +116,6 @@
   Ruby
   * Auto capitalize enums name in Ruby (#10454) (#10763)
 
-
 2022-09-29 version 21.7 (C++/Java/Python/PHP/Objective-C/C#/Ruby)
   Java
   * Refactoring java full runtime to reuse sub-message builders and prepare to
@@ -63,7 +145,6 @@
   Python
   * Fixed comparison of maps in Python.
 
-
 2022-07-25 version 21.4 (C++/Java/Python/PHP/Objective-C/C#/Ruby)
 
   C++
@@ -200,6 +281,7 @@
   Java
   * Update protobuf_version.bzl to separate protoc and per-language java … (#9900)
   * 6x speedup in ArrayEncoder.writeUInt32NotTag
+  * Java generated code is no longer compatible with runtimes 2.6.1 and earlier
 
   Python
   * Increment python major version to 4 in version.json for python upb (#9926)
@@ -211,6 +293,7 @@
   * Due to the breaking changes for Python, the major version number for Python
     has been incremented.
   * The binary wheel for macOS now supports Apple silicon.
+  * In TextFormat, transform UnicodeDecodeError into ParseError.
 
 
   PHP
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 04cb330..f60142b 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -19,6 +19,14 @@
 if(POLICY CMP0091)
   cmake_policy(SET CMP0091 NEW)
 endif()
+# Honor visibility properties for all target types.
+if(POLICY CMP0063)
+  cmake_policy(SET CMP0063 NEW)
+endif()
+# option() honor variables
+if (POLICY CMP0077)
+  cmake_policy(SET CMP0077 NEW)
+endif (POLICY CMP0077)
 
 # Project
 project(protobuf C CXX)
@@ -32,11 +40,23 @@
   get_filename_component(protobuf_SOURCE_DIR ${protobuf_SOURCE_DIR} DIRECTORY)
 endif()
 
-# Add c++11 flags
-if (CYGWIN)
-  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++11")
+# Add C++14 flags
+if(NOT CMAKE_CXX_STANDARD)
+  set(CMAKE_CXX_STANDARD 14)
+endif()
+if(CYGWIN)
+  string(REGEX_MATCH "-std=gnu\\+\\+([0-9]+)" _protobuf_CXX_STD "${CMAKE_CXX_FLAGS}")
+endif()
+if(NOT _protobuf_CXX_STD)
+  set(_protobuf_CXX_STD "${CMAKE_CXX_STANDARD}")
+endif()
+if(_protobuf_CXX_STD LESS "14")
+  message(FATAL_ERROR "Protocol Buffers requires at least C++14, but is configured for C++${_protobuf_CXX_STD}")
+endif()
+if(CYGWIN)
+  set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -std=gnu++${_protobuf_CXX_STD}")
 else()
-  set(CMAKE_CXX_STANDARD 11)
+  set(CMAKE_CXX_STANDARD ${_protobuf_CXX_STD})
   set(CMAKE_CXX_STANDARD_REQUIRED ON)
   set(CMAKE_CXX_EXTENSIONS OFF)
 endif()
@@ -57,9 +77,11 @@
 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_PROTOBUF_BINARIES "Build protobuf libraries and protoc compiler" ON)
 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)
+option(protobuf_TEST_XML_OUTDIR "Output directory for XML logs from tests." "")
 if (BUILD_SHARED_LIBS)
   set(protobuf_BUILD_SHARED_LIBS_DEFAULT ON)
 else (BUILD_SHARED_LIBS)
@@ -77,27 +99,37 @@
 # User options
 include(${protobuf_SOURCE_DIR}/cmake/protobuf-options.cmake)
 
+if (protobuf_BUILD_SHARED_LIBS)
+  # This is necessary for linking in Abseil.
+  set(CMAKE_POSITION_INDEPENDENT_CODE ON)
+
+  # Build Abseil as shared libraries to avoid ODR violations.
+  set(BUILD_SHARED_LIBS ON)
+
+  # Output directory is correct by default for most build setups. However, when
+  # building Protobuf as a DLL, it is important to have the DLL in the same
+  # directory as the executable using it. Thus, we put all binaries in a single
+  # /bin directory.
+  if (MSVC)
+    set(CMAKE_RUNTIME_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+    set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+    set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+    set(CMAKE_PDB_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/bin)
+  endif ()
+endif ()
+
+# Version metadata
+set(protobuf_VERSION_STRING "3.21.4")
+set(protobuf_DESCRIPTION "Protocol Buffers")
+set(protobuf_CONTACT "protobuf@googlegroups.com")
+
 # 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 "${protobuf_SOURCE_DIR}/configure.ac")
-
-# Parse configure script
-set(protobuf_AC_INIT_REGEX
-  "^AC_INIT\\(\\[([^]]+)\\],\\[([^]]+)\\],\\[([^]]+)\\],\\[([^]]+)\\]\\)$")
-file(STRINGS "${protobuf_CONFIGURE_SCRIPT}" protobuf_AC_INIT_LINE
-  LIMIT_COUNT 1 REGEX "^AC_INIT")
-# Description
-string(REGEX REPLACE        "${protobuf_AC_INIT_REGEX}" "\\1"
-    protobuf_DESCRIPTION    "${protobuf_AC_INIT_LINE}")
-# Version
-string(REGEX REPLACE        "${protobuf_AC_INIT_REGEX}" "\\2"
-    protobuf_VERSION_STRING "${protobuf_AC_INIT_LINE}")
-# Contact
-string(REGEX REPLACE        "${protobuf_AC_INIT_REGEX}" "\\3"
-    protobuf_CONTACT        "${protobuf_AC_INIT_LINE}")
+if (NOT protobuf_BUILD_PROTOBUF_BINARIES)
+  set(protobuf_INSTALL OFF)
+endif()
 # Parse version tweaks
 set(protobuf_VERSION_REGEX "^([0-9]+)\\.([0-9]+)\\.([0-9]+)([-]rc[-]|\\.)?([0-9]*)$")
 string(REGEX REPLACE     "${protobuf_VERSION_REGEX}" "\\1"
@@ -162,6 +194,14 @@
 
 find_package(Threads REQUIRED)
 
+# We can install dependencies from submodules if we're running
+# CMake v3.13 or newer.
+if(CMAKE_VERSION VERSION_LESS 3.13)
+  set(_protobuf_INSTALL_SUPPORTED_FROM_MODULE OFF)
+else()
+  set(_protobuf_INSTALL_SUPPORTED_FROM_MODULE ON)
+endif()
+
 set(_protobuf_FIND_ZLIB)
 if (protobuf_WITH_ZLIB)
   find_package(ZLIB)
@@ -194,11 +234,11 @@
 if (NOT MSVC)
   include(CheckCXXSourceCompiles)
   set(OLD_CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS})
-  set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} -std=c++11)
+  set(CMAKE_REQUIRED_FLAGS ${CMAKE_REQUIRED_FLAGS} -std=c++14)
   check_cxx_source_compiles("
     #include <atomic>
     int main() {
-      return std::atomic<int64_t>{};
+      return static_cast<int>(std::atomic<int64_t>{});
     }
   " protobuf_HAVE_BUILTIN_ATOMICS)
   if (NOT protobuf_HAVE_BUILTIN_ATOMICS)
@@ -242,12 +282,12 @@
 if (MSVC)
   if (CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
     # Build with multiple processes
-    add_definitions(/MP)
+    add_compile_options(/MP)
   endif()
   # Set source file and execution character sets to UTF-8
-  add_definitions(/utf-8)
+  add_compile_options(/utf-8)
   # MSVC warning suppressions
-  add_definitions(
+  add_compile_options(
     /wd4065 # switch statement contains 'default' but no 'case' labels
     /wd4244 # 'conversion' conversion from 'type1' to 'type2', possible loss of data
     /wd4251 # 'identifier' : class 'type' needs to have dll-interface to be used by clients of class 'type2'
@@ -262,23 +302,16 @@
     /wd4996 # The compiler encountered a deprecated declaration.
   )
   # Allow big object
-  add_definitions(/bigobj)
+  add_compile_options(/bigobj)
   string(REPLACE "/" "\\" PROTOBUF_SOURCE_WIN32_PATH ${protobuf_SOURCE_DIR})
   string(REPLACE "/" "\\" PROTOBUF_BINARY_WIN32_PATH ${protobuf_BINARY_DIR})
   string(REPLACE "." ","  protobuf_RC_FILEVERSION "${protobuf_VERSION}")
-  configure_file(${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in extract_includes.bat)
 
   # Suppress linker warnings about files with no symbols defined.
-  set(CMAKE_STATIC_LINKER_FLAGS "${CMAKE_STATIC_LINKER_FLAGS} /ignore:4221")
+  string(APPEND CMAKE_STATIC_LINKER_FLAGS " /ignore:4221")
 
-  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()
+  # use English language (0x409) in resource compiler
+  string(APPEND CMAKE_RC_FLAGS " -l0x409")
 
   # Generate the version.rc file used elsewhere.
   configure_file(${protobuf_SOURCE_DIR}/cmake/version.rc.in ${CMAKE_CURRENT_BINARY_DIR}/version.rc @ONLY)
@@ -304,28 +337,55 @@
   add_definitions(-DUNICODE -D_UNICODE)
 endif (protobuf_UNICODE)
 
-include(${protobuf_SOURCE_DIR}/cmake/libprotobuf-lite.cmake)
-include(${protobuf_SOURCE_DIR}/cmake/libprotobuf.cmake)
-if (protobuf_BUILD_LIBPROTOC)
-  include(${protobuf_SOURCE_DIR}/cmake/libprotoc.cmake)
-endif (protobuf_BUILD_LIBPROTOC)
-if (protobuf_BUILD_PROTOC_BINARIES)
-  include(${protobuf_SOURCE_DIR}/cmake/protoc.cmake)
-  if (NOT DEFINED protobuf_PROTOC_EXE)
-    set(protobuf_PROTOC_EXE protoc)
-  endif (NOT DEFINED protobuf_PROTOC_EXE)
-endif (protobuf_BUILD_PROTOC_BINARIES)
+set(protobuf_ABSL_PROVIDER "module" CACHE STRING "Provider of absl library")
+set_property(CACHE protobuf_ABSL_PROVIDER PROPERTY STRINGS "module" "package")
 
-# Ensure we have a protoc executable if we need one
+include(${protobuf_SOURCE_DIR}/cmake/abseil-cpp.cmake)
+
+if (protobuf_BUILD_PROTOBUF_BINARIES)
+  include(${protobuf_SOURCE_DIR}/cmake/utf8_range.cmake)
+  include(${protobuf_SOURCE_DIR}/cmake/libprotobuf-lite.cmake)
+  if (NOT DEFINED protobuf_LIB_PROTOBUF_LITE)
+    set(protobuf_LIB_PROTOBUF_LITE libprotobuf-lite)
+  endif ()
+  include(${protobuf_SOURCE_DIR}/cmake/libprotobuf.cmake)
+  if (NOT DEFINED protobuf_LIB_PROTOBUF)
+    set(protobuf_LIB_PROTOBUF libprotobuf)
+  endif ()
+  if (protobuf_BUILD_LIBPROTOC)
+    include(${protobuf_SOURCE_DIR}/cmake/libprotoc.cmake)
+    if (NOT DEFINED protobuf_LIB_PROTOC)
+      set(protobuf_LIB_PROTOC libprotoc)
+    endif ()
+  endif ()
+  if (protobuf_BUILD_PROTOC_BINARIES)
+    include(${protobuf_SOURCE_DIR}/cmake/protoc.cmake)
+    if (NOT DEFINED protobuf_PROTOC_EXE)
+      set(protobuf_PROTOC_EXE protoc)
+    endif ()
+  endif ()
+else ()
+  find_package(Protobuf NO_MODULE)
+  if (Protobuf_FOUND)
+    set(protobuf_PROTOC_EXE protobuf::protoc)
+    set(protobuf_LIB_PROTOC protobuf::libprotoc)
+    set(protobuf_LIB_PROTOBUF protobuf::libprotobuf)
+    set(protobuf_LIB_PROTOBUF_LITE protobuf::libprotobuf-lite)
+    message(STATUS "CMake installation of Protobuf found.")
+  endif ()
+endif ()
+
+# Ensure we have a protoc executable and protobuf libraries 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 ()
+    find_program(protobuf_PROTOC_EXE protoc REQUIRED)
+    message(STATUS "Found system ${protobuf_PROTOC_EXE}.")
   endif ()
   if(protobuf_VERBOSE)
     message(STATUS "Using protoc : ${protobuf_PROTOC_EXE}")
+    message(STATUS "Using libprotobuf : ${protobuf_LIB_PROTOBUF}")
+    message(STATUS "Using libprotobuf-lite : ${protobuf_LIB_PROTOBUF_LITE}")
+    message(STATUS "Using libprotoc : ${protobuf_LIB_PROTOC}")
   endif(protobuf_VERBOSE)
 endif ()
 
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
new file mode 100644
index 0000000..ba19063
--- /dev/null
+++ b/CODE_OF_CONDUCT.md
@@ -0,0 +1,3 @@
+This project is governed by
+[Protobuf's Code of Conduct](https://github.com/protocolbuffers/.github/blob/main/profile/CODE_OF_CONDUCT.md).
+
diff --git a/Makefile.am b/Makefile.am
deleted file mode 100644
index 681cd8c..0000000
--- a/Makefile.am
+++ /dev/null
@@ -1,1292 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-ACLOCAL_AMFLAGS = -I m4
-
-AUTOMAKE_OPTIONS = foreign
-
-# Build . before src so that our all-local and clean-local hooks kicks in at
-# the right time.
-SUBDIRS = . src
-
-# Always include third_party directories in distributions.
-#
-# Note that distribution artifacts will be produced by Bazel in the future.
-# See pkg/BUILD.bazel for overall definitions.
-DIST_SUBDIRS = src conformance benchmarks third_party/googletest
-
-# Build gmock before we build protobuf tests.  We don't add gmock to SUBDIRS
-# because then "make check" would also build and run all of gmock's own tests,
-# which takes a lot of time and is generally not useful to us.  Also, we don't
-# want "make install" to recurse into gmock since we don't want to overwrite
-# the installed version of gmock if there is one.
-check-local:
-	@echo "Making lib/libgmock.a lib/libgmock_main.a in gmock"
-	@cd third_party/googletest/googletest && $(MAKE) $(AM_MAKEFLAGS) lib/libgtest.la lib/libgtest_main.la
-	@cd third_party/googletest/googlemock && $(MAKE) $(AM_MAKEFLAGS) lib/libgmock.la lib/libgmock_main.la
-
-# We would like to clean gmock when "make clean" is invoked.  But we have to
-# be careful because clean-local is also invoked during "make distclean", but
-# "make distclean" already recurses into gmock because it's listed among the
-# DIST_SUBDIRS.  distclean will delete gmock/Makefile, so if we then try to
-# cd to the directory again and "make clean" it will fail.  So, check that the
-# Makefile exists before recursing.
-clean-local:
-	@if test -e third_party/googletest/Makefile; then \
-	  echo "Making clean in googletest"; \
-	  cd third_party/googletest && $(MAKE) $(AM_MAKEFLAGS) clean; \
-	fi; \
-	if test -e conformance/Makefile; then \
-	  echo "Making clean in conformance"; \
-	  cd conformance && $(MAKE) $(AM_MAKEFLAGS) clean; \
-	fi; \
-	if test -e benchmarks/Makefile; then \
-	  echo "Making clean in benchmarks"; \
-	  cd benchmarks && $(MAKE) $(AM_MAKEFLAGS) clean; \
-	fi; \
-	if test -e objectivec/DevTools; then \
-	  echo "Cleaning any ObjC pyc files"; \
-	  rm -f objectivec/DevTools/*.pyc; \
-	fi
-
-pkgconfigdir = $(libdir)/pkgconfig
-pkgconfig_DATA = protobuf.pc protobuf-lite.pc
-
-# Note: please keep this in sync with the dist_files rule in csharp/BUILD.bazel.
-csharp_EXTRA_DIST=                                                           \
-  global.json                                                                \
-  csharp/.editorconfig                                                       \
-  csharp/.gitignore                                                          \
-  csharp/CHANGES.txt                                                         \
-  csharp/Google.Protobuf.Tools.targets                                       \
-  csharp/Google.Protobuf.Tools.nuspec                                        \
-  csharp/NuGet.Config                                                        \
-  csharp/README.md                                                           \
-  csharp/build_packages.bat                                                  \
-  csharp/build_tools.sh                                                      \
-  csharp/buildall.bat                                                        \
-  csharp/buildall.sh                                                         \
-  csharp/generate_protos.sh                                                  \
-  csharp/install_dotnet_sdk.ps1                                              \
-  csharp/keys/Google.Protobuf.public.snk                                     \
-  csharp/keys/Google.Protobuf.snk                                            \
-  csharp/keys/README.md                                                      \
-  csharp/protos/README.md                                                    \
-  csharp/protos/map_unittest_proto3.proto                                    \
-  csharp/protos/old_extensions1.proto                                        \
-  csharp/protos/old_extensions2.proto                                        \
-  csharp/protos/unittest_issue6936_a.proto                                   \
-  csharp/protos/unittest_issue6936_b.proto                                   \
-  csharp/protos/unittest_issue6936_c.proto                                   \
-  csharp/protos/unittest_custom_options_proto3.proto                         \
-  csharp/protos/unittest_import_public_proto3.proto                          \
-  csharp/protos/unittest_import_public.proto                                 \
-  csharp/protos/unittest_import_proto3.proto                                 \
-  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                                      \
-  csharp/src/AddressBook/AddressBook.csproj                                  \
-  csharp/src/AddressBook/ListPeople.cs                                       \
-  csharp/src/AddressBook/Program.cs                                          \
-  csharp/src/AddressBook/SampleUsage.cs                                      \
-  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/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                    \
-  csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs                   \
-  csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs                \
-  csharp/src/Google.Protobuf.Test/Collections/ProtobufEqualityComparersTest.cs \
-  csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs           \
-  csharp/src/Google.Protobuf.Test/Compatibility/PropertyInfoExtensionsTest.cs \
-  csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs      \
-  csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs        \
-  csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs                    \
-  csharp/src/Google.Protobuf.Test/EqualityTester.cs                          \
-  csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs                        \
-  csharp/src/Google.Protobuf.Test/FieldCodecTest.cs                          \
-  csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs                       \
-  csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs                    \
-  csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs             \
-  csharp/src/Google.Protobuf.Test/Google.Protobuf.Test.csproj                \
-  csharp/src/Google.Protobuf.Test/IssuesTest.cs                              \
-  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              \
-  csharp/src/Google.Protobuf.Test/Reflection/FieldAccessTest.cs              \
-  csharp/src/Google.Protobuf.Test/Reflection/TypeRegistryTest.cs             \
-  csharp/src/Google.Protobuf.Test/SampleEnum.cs                              \
-  csharp/src/Google.Protobuf.Test/SampleMessages.cs                          \
-  csharp/src/Google.Protobuf.Test/SampleNaNs.cs                              \
-  csharp/src/Google.Protobuf.Test/TestCornerCases.cs                         \
-  csharp/src/Google.Protobuf.Test.TestProtos/Google.Protobuf.Test.TestProtos.csproj \
-  csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.cs              \
-  csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs              \
-  csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs              \
-  csharp/src/Google.Protobuf.Test.TestProtos/ForeignMessagePartial.cs           \
-  csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs               \
-  csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions1.cs                  \
-  csharp/src/Google.Protobuf.Test.TestProtos/OldExtensions2.cs                  \
-  csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs              \
-  csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs              \
-  csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs     \
-  csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs            \
-  csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs      \
-  csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs            \
-  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                  \
-  csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs             \
-  csharp/src/Google.Protobuf.Test/WellKnownTypes/FieldMaskTest.cs            \
-  csharp/src/Google.Protobuf.Test/WellKnownTypes/TimestampTest.cs            \
-  csharp/src/Google.Protobuf.Test/WellKnownTypes/WrappersTest.cs             \
-  csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs                     \
-  csharp/src/Google.Protobuf.Test/testprotos.pb                              \
-  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                            \
-  csharp/src/Google.Protobuf/Collections/Lists.cs                            \
-  csharp/src/Google.Protobuf/Collections/MapField.cs                         \
-  csharp/src/Google.Protobuf/Collections/ProtobufEqualityComparers.cs        \
-  csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs               \
-  csharp/src/Google.Protobuf/Collections/RepeatedField.cs                    \
-  csharp/src/Google.Protobuf/Compatibility/DynamicallyAccessedMembersAttribute.cs \
-  csharp/src/Google.Protobuf/Compatibility/DynamicallyAccessedMemberTypes.cs \
-  csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs           \
-  csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs         \
-  csharp/src/Google.Protobuf/Compatibility/RequiresUnreferencedCodeAttribute.cs \
-  csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs               \
-  csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs                 \
-  csharp/src/Google.Protobuf/Compatibility/UnconditionalSuppressMessageAttribute.cs \
-  csharp/src/Google.Protobuf/Extension.cs                                    \
-  csharp/src/Google.Protobuf/ExtensionRegistry.cs                            \
-  csharp/src/Google.Protobuf/ExtensionSet.cs                                 \
-  csharp/src/Google.Protobuf/ExtensionValue.cs                               \
-  csharp/src/Google.Protobuf/FieldCodec.cs                                   \
-  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                           \
-  csharp/src/Google.Protobuf/IMessage.cs                                     \
-  csharp/src/Google.Protobuf/InvalidJsonException.cs                         \
-  csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs               \
-  csharp/src/Google.Protobuf/JsonFormatter.cs                                \
-  csharp/src/Google.Protobuf/JsonParser.cs                                   \
-  csharp/src/Google.Protobuf/JsonToken.cs                                    \
-  csharp/src/Google.Protobuf/JsonTokenizer.cs                                \
-  csharp/src/Google.Protobuf/LimitedInputStream.cs                           \
-  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                        \
-  csharp/src/Google.Protobuf/Reflection/DescriptorBase.cs                    \
-  csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs             \
-  csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs                    \
-  csharp/src/Google.Protobuf/Reflection/DescriptorUtil.cs                    \
-  csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs     \
-  csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs                    \
-  csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs               \
-  csharp/src/Google.Protobuf/Reflection/ExtensionAccessor.cs                 \
-  csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs               \
-  csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs                 \
-  csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs                   \
-  csharp/src/Google.Protobuf/Reflection/FieldType.cs                         \
-  csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs                    \
-  csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs              \
-  csharp/src/Google.Protobuf/Reflection/IDescriptor.cs                       \
-  csharp/src/Google.Protobuf/Reflection/IFieldAccessor.cs                    \
-  csharp/src/Google.Protobuf/Reflection/MapFieldAccessor.cs                  \
-  csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs                 \
-  csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs                  \
-  csharp/src/Google.Protobuf/Reflection/OneofAccessor.cs                     \
-  csharp/src/Google.Protobuf/Reflection/OneofDescriptor.cs                   \
-  csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs             \
-  csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs                 \
-  csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs                    \
-  csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs             \
-  csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs                 \
-  csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs               \
-  csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs                      \
-  csharp/src/Google.Protobuf/WellKnownTypes/Any.cs                           \
-  csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs                    \
-  csharp/src/Google.Protobuf/WellKnownTypes/Api.cs                           \
-  csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs                      \
-  csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs               \
-  csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs                         \
-  csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs                     \
-  csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs              \
-  csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs                 \
-  csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs                        \
-  csharp/src/Google.Protobuf/WellKnownTypes/TimeExtensions.cs                \
-  csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs                     \
-  csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs              \
-  csharp/src/Google.Protobuf/WellKnownTypes/Type.cs                          \
-  csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs                  \
-  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/UnsafeByteOperations.cs
-
-# Note: please keep this in sync with the dist_files rules under java/.../BUILD.bazel.
-java_EXTRA_DIST=                                                                   \
-  java/README.md                                                                   \
-  java/bom/pom.xml                                                                 \
-  java/core/BUILD.bazel                                                            \
-  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                  \
-  java/core/src/main/java/com/google/protobuf/AbstractProtobufList.java            \
-  java/core/src/main/java/com/google/protobuf/AllocatedBuffer.java                 \
-  java/core/src/main/java/com/google/protobuf/Android.java                         \
-  java/core/src/main/java/com/google/protobuf/ArrayDecoders.java                   \
-  java/core/src/main/java/com/google/protobuf/BinaryReader.java                    \
-  java/core/src/main/java/com/google/protobuf/BinaryWriter.java                    \
-  java/core/src/main/java/com/google/protobuf/BlockingRpcChannel.java              \
-  java/core/src/main/java/com/google/protobuf/BlockingService.java                 \
-  java/core/src/main/java/com/google/protobuf/BooleanArrayList.java                \
-  java/core/src/main/java/com/google/protobuf/BufferAllocator.java                 \
-  java/core/src/main/java/com/google/protobuf/ByteBufferWriter.java                \
-  java/core/src/main/java/com/google/protobuf/ByteOutput.java                      \
-  java/core/src/main/java/com/google/protobuf/ByteString.java                      \
-  java/core/src/main/java/com/google/protobuf/CanIgnoreReturnValue.java            \
-  java/core/src/main/java/com/google/protobuf/CheckReturnValue.java                \
-  java/core/src/main/java/com/google/protobuf/CodedInputStream.java                \
-  java/core/src/main/java/com/google/protobuf/CodedInputStreamReader.java          \
-  java/core/src/main/java/com/google/protobuf/CodedOutputStream.java               \
-  java/core/src/main/java/com/google/protobuf/CodedOutputStreamWriter.java         \
-  java/core/src/main/java/com/google/protobuf/CompileTimeConstant.java             \
-  java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java    \
-  java/core/src/main/java/com/google/protobuf/Descriptors.java                     \
-  java/core/src/main/java/com/google/protobuf/DiscardUnknownFieldsParser.java      \
-  java/core/src/main/java/com/google/protobuf/DoubleArrayList.java                 \
-  java/core/src/main/java/com/google/protobuf/DynamicMessage.java                  \
-  java/core/src/main/java/com/google/protobuf/ExperimentalApi.java                 \
-  java/core/src/main/java/com/google/protobuf/Extension.java                       \
-  java/core/src/main/java/com/google/protobuf/ExtensionLite.java                   \
-  java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java               \
-  java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java        \
-  java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java           \
-  java/core/src/main/java/com/google/protobuf/ExtensionSchema.java                 \
-  java/core/src/main/java/com/google/protobuf/ExtensionSchemaFull.java             \
-  java/core/src/main/java/com/google/protobuf/ExtensionSchemaLite.java             \
-  java/core/src/main/java/com/google/protobuf/ExtensionSchemas.java                \
-  java/core/src/main/java/com/google/protobuf/FieldInfo.java                       \
-  java/core/src/main/java/com/google/protobuf/FieldSet.java                        \
-  java/core/src/main/java/com/google/protobuf/FieldType.java                       \
-  java/core/src/main/java/com/google/protobuf/FloatArrayList.java                  \
-  java/core/src/main/java/com/google/protobuf/GeneratedMessage.java                \
-  java/core/src/main/java/com/google/protobuf/GeneratedMessageInfoFactory.java     \
-  java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java            \
-  java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java              \
-  java/core/src/main/java/com/google/protobuf/InlineMe.java                        \
-  java/core/src/main/java/com/google/protobuf/IntArrayList.java                    \
-  java/core/src/main/java/com/google/protobuf/Internal.java                        \
-  java/core/src/main/java/com/google/protobuf/InvalidProtocolBufferException.java  \
-  java/core/src/main/java/com/google/protobuf/IterableByteBufferInputStream.java   \
-  java/core/src/main/java/com/google/protobuf/JavaType.java                        \
-  java/core/src/main/java/com/google/protobuf/LazyField.java                       \
-  java/core/src/main/java/com/google/protobuf/LazyFieldLite.java                   \
-  java/core/src/main/java/com/google/protobuf/LazyStringArrayList.java             \
-  java/core/src/main/java/com/google/protobuf/LazyStringList.java                  \
-  java/core/src/main/java/com/google/protobuf/ListFieldSchema.java                 \
-  java/core/src/main/java/com/google/protobuf/LongArrayList.java                   \
-  java/core/src/main/java/com/google/protobuf/ManifestSchemaFactory.java           \
-  java/core/src/main/java/com/google/protobuf/MapEntry.java                        \
-  java/core/src/main/java/com/google/protobuf/MapEntryLite.java                    \
-  java/core/src/main/java/com/google/protobuf/MapField.java                        \
-  java/core/src/main/java/com/google/protobuf/MapFieldLite.java                    \
-  java/core/src/main/java/com/google/protobuf/MapFieldSchema.java                  \
-  java/core/src/main/java/com/google/protobuf/MapFieldSchemaFull.java              \
-  java/core/src/main/java/com/google/protobuf/MapFieldSchemaLite.java              \
-  java/core/src/main/java/com/google/protobuf/MapFieldSchemas.java                 \
-  java/core/src/main/java/com/google/protobuf/Message.java                         \
-  java/core/src/main/java/com/google/protobuf/MessageInfo.java                     \
-  java/core/src/main/java/com/google/protobuf/MessageInfoFactory.java              \
-  java/core/src/main/java/com/google/protobuf/MessageLite.java                     \
-  java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java            \
-  java/core/src/main/java/com/google/protobuf/MessageLiteToString.java             \
-  java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java                \
-  java/core/src/main/java/com/google/protobuf/MessageReflection.java               \
-  java/core/src/main/java/com/google/protobuf/MessageSchema.java                   \
-  java/core/src/main/java/com/google/protobuf/MessageSetSchema.java                \
-  java/core/src/main/java/com/google/protobuf/MutabilityOracle.java                \
-  java/core/src/main/java/com/google/protobuf/NewInstanceSchema.java               \
-  java/core/src/main/java/com/google/protobuf/NewInstanceSchemaFull.java           \
-  java/core/src/main/java/com/google/protobuf/NewInstanceSchemaLite.java           \
-  java/core/src/main/java/com/google/protobuf/NewInstanceSchemas.java              \
-  java/core/src/main/java/com/google/protobuf/NioByteString.java                   \
-  java/core/src/main/java/com/google/protobuf/OneofInfo.java                       \
-  java/core/src/main/java/com/google/protobuf/Parser.java                          \
-  java/core/src/main/java/com/google/protobuf/PrimitiveNonBoxingCollection.java    \
-  java/core/src/main/java/com/google/protobuf/ProtoSyntax.java                     \
-  java/core/src/main/java/com/google/protobuf/Protobuf.java                        \
-  java/core/src/main/java/com/google/protobuf/ProtobufArrayList.java               \
-  java/core/src/main/java/com/google/protobuf/ProtobufLists.java                   \
-  java/core/src/main/java/com/google/protobuf/ProtocolMessageEnum.java             \
-  java/core/src/main/java/com/google/protobuf/ProtocolStringList.java              \
-  java/core/src/main/java/com/google/protobuf/RawMessageInfo.java                  \
-  java/core/src/main/java/com/google/protobuf/Reader.java                          \
-  java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java            \
-  java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java          \
-  java/core/src/main/java/com/google/protobuf/RopeByteString.java                  \
-  java/core/src/main/java/com/google/protobuf/RpcCallback.java                     \
-  java/core/src/main/java/com/google/protobuf/RpcChannel.java                      \
-  java/core/src/main/java/com/google/protobuf/RpcController.java                   \
-  java/core/src/main/java/com/google/protobuf/RpcUtil.java                         \
-  java/core/src/main/java/com/google/protobuf/Schema.java                          \
-  java/core/src/main/java/com/google/protobuf/SchemaFactory.java                   \
-  java/core/src/main/java/com/google/protobuf/SchemaUtil.java                      \
-  java/core/src/main/java/com/google/protobuf/Service.java                         \
-  java/core/src/main/java/com/google/protobuf/ServiceException.java                \
-  java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java              \
-  java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java            \
-  java/core/src/main/java/com/google/protobuf/SmallSortedMap.java                  \
-  java/core/src/main/java/com/google/protobuf/StructuralMessageInfo.java           \
-  java/core/src/main/java/com/google/protobuf/TextFormat.java                      \
-  java/core/src/main/java/com/google/protobuf/TextFormatEscaper.java               \
-  java/core/src/main/java/com/google/protobuf/TextFormatParseInfoTree.java         \
-  java/core/src/main/java/com/google/protobuf/TextFormatParseLocation.java         \
-  java/core/src/main/java/com/google/protobuf/TypeRegistry.java                    \
-  java/core/src/main/java/com/google/protobuf/UninitializedMessageException.java   \
-  java/core/src/main/java/com/google/protobuf/UnknownFieldSchema.java              \
-  java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java                 \
-  java/core/src/main/java/com/google/protobuf/UnknownFieldSetLite.java             \
-  java/core/src/main/java/com/google/protobuf/UnknownFieldSetLiteSchema.java       \
-  java/core/src/main/java/com/google/protobuf/UnknownFieldSetSchema.java           \
-  java/core/src/main/java/com/google/protobuf/UnmodifiableLazyStringList.java      \
-  java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java            \
-  java/core/src/main/java/com/google/protobuf/UnsafeUtil.java                      \
-  java/core/src/main/java/com/google/protobuf/Utf8.java                            \
-  java/core/src/main/java/com/google/protobuf/WireFormat.java                      \
-  java/core/src/main/java/com/google/protobuf/Writer.java                          \
-  java/core/src/test/java/com/google/protobuf/AbstractMessageTest.java             \
-  java/core/src/test/java/com/google/protobuf/AbstractProto2LiteSchemaTest.java    \
-  java/core/src/test/java/com/google/protobuf/AbstractProto2SchemaTest.java        \
-  java/core/src/test/java/com/google/protobuf/AbstractProto3LiteSchemaTest.java    \
-  java/core/src/test/java/com/google/protobuf/AbstractProto3SchemaTest.java        \
-  java/core/src/test/java/com/google/protobuf/AbstractSchemaTest.java              \
-  java/core/src/test/java/com/google/protobuf/AnyTest.java                         \
-  java/core/src/test/java/com/google/protobuf/ArrayDecodersTest.java               \
-  java/core/src/test/java/com/google/protobuf/BinaryProtocolTest.java              \
-  java/core/src/test/java/com/google/protobuf/BooleanArrayListTest.java            \
-  java/core/src/test/java/com/google/protobuf/BoundedByteStringTest.java           \
-  java/core/src/test/java/com/google/protobuf/ByteBufferWriterTest.java            \
-  java/core/src/test/java/com/google/protobuf/ByteStringTest.java                  \
-  java/core/src/test/java/com/google/protobuf/CachedFieldSizeTest.java             \
-  java/core/src/test/java/com/google/protobuf/CheckUtf8Test.java                   \
-  java/core/src/test/java/com/google/protobuf/CodedAdapterTest.java                \
-  java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java            \
-  java/core/src/test/java/com/google/protobuf/CodedOutputStreamTest.java           \
-  java/core/src/test/java/com/google/protobuf/DecodeUtf8Test.java                  \
-  java/core/src/test/java/com/google/protobuf/DeprecatedFieldTest.java             \
-  java/core/src/test/java/com/google/protobuf/DescriptorsTest.java                 \
-  java/core/src/test/java/com/google/protobuf/DiscardUnknownFieldsTest.java        \
-  java/core/src/test/java/com/google/protobuf/DoubleArrayListTest.java             \
-  java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java              \
-  java/core/src/test/java/com/google/protobuf/EnumTest.java                        \
-  java/core/src/test/java/com/google/protobuf/ExperimentalMessageFactory.java      \
-  java/core/src/test/java/com/google/protobuf/ExperimentalSerializationUtil.java   \
-  java/core/src/test/java/com/google/protobuf/ExperimentalTestDataProvider.java    \
-  java/core/src/test/java/com/google/protobuf/ExtensionRegistryFactoryTest.java    \
-  java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java               \
-  java/core/src/test/java/com/google/protobuf/FloatArrayListTest.java              \
-  java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java            \
-  java/core/src/test/java/com/google/protobuf/IntArrayListTest.java                \
-  java/core/src/test/java/com/google/protobuf/InvalidProtocolBufferExceptionTest.java \
-  java/core/src/test/java/com/google/protobuf/IsValidUtf8Test.java                 \
-  java/core/src/test/java/com/google/protobuf/IsValidUtf8TestUtil.java             \
-  java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java               \
-  java/core/src/test/java/com/google/protobuf/LazyFieldTest.java                   \
-  java/core/src/test/java/com/google/protobuf/LazyMessageLiteTest.java             \
-  java/core/src/test/java/com/google/protobuf/LazyStringArrayListTest.java         \
-  java/core/src/test/java/com/google/protobuf/LazyStringEndToEndTest.java          \
-  java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java           \
-  java/core/src/test/java/com/google/protobuf/LiteralByteStringTest.java           \
-  java/core/src/test/java/com/google/protobuf/LongArrayListTest.java               \
-  java/core/src/test/java/com/google/protobuf/MapForProto2LiteTest.java            \
-  java/core/src/test/java/com/google/protobuf/MapForProto2Test.java                \
-  java/core/src/test/java/com/google/protobuf/MapLiteTest.java                     \
-  java/core/src/test/java/com/google/protobuf/MapTest.java                         \
-  java/core/src/test/java/com/google/protobuf/MessageTest.java                     \
-  java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java              \
-  java/core/src/test/java/com/google/protobuf/NioByteStringTest.java               \
-  java/core/src/test/java/com/google/protobuf/PackedFieldTest.java                 \
-  java/core/src/test/java/com/google/protobuf/ParseExceptionsTest.java             \
-  java/core/src/test/java/com/google/protobuf/ParserLiteTest.java                  \
-  java/core/src/test/java/com/google/protobuf/ParserTest.java                      \
-  java/core/src/test/java/com/google/protobuf/Proto2ExtensionLookupSchemaTest.java \
-  java/core/src/test/java/com/google/protobuf/Proto2LiteSchemaTest.java            \
-  java/core/src/test/java/com/google/protobuf/Proto2MessageFactory.java            \
-  java/core/src/test/java/com/google/protobuf/Proto2MessageLiteFactory.java        \
-  java/core/src/test/java/com/google/protobuf/Proto2SchemaTest.java                \
-  java/core/src/test/java/com/google/protobuf/Proto2UnknownEnumValueTest.java      \
-  java/core/src/test/java/com/google/protobuf/Proto3LiteSchemaTest.java            \
-  java/core/src/test/java/com/google/protobuf/Proto3MessageFactory.java            \
-  java/core/src/test/java/com/google/protobuf/Proto3MessageLiteFactory.java        \
-  java/core/src/test/java/com/google/protobuf/Proto3SchemaTest.java                \
-  java/core/src/test/java/com/google/protobuf/ProtobufArrayListTest.java           \
-  java/core/src/test/java/com/google/protobuf/RepeatedFieldBuilderV3Test.java      \
-  java/core/src/test/java/com/google/protobuf/RopeByteStringSubstringTest.java     \
-  java/core/src/test/java/com/google/protobuf/RopeByteStringTest.java              \
-  java/core/src/test/java/com/google/protobuf/ServiceTest.java                     \
-  java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java        \
-  java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java              \
-  java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java              \
-  java/core/src/test/java/com/google/protobuf/TestBadIdentifiersLite.java          \
-  java/core/src/test/java/com/google/protobuf/TestSchemas.java                     \
-  java/core/src/test/java/com/google/protobuf/TestSchemasLite.java                 \
-  java/core/src/test/java/com/google/protobuf/TestUtil.java                        \
-  java/core/src/test/java/com/google/protobuf/TestUtilLite.java                    \
-  java/core/src/test/java/com/google/protobuf/TextFormatParseInfoTreeTest.java     \
-  java/core/src/test/java/com/google/protobuf/TextFormatParseLocationTest.java     \
-  java/core/src/test/java/com/google/protobuf/TextFormatTest.java                  \
-  java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java                \
-  java/core/src/test/java/com/google/protobuf/UnknownEnumValueTest.java            \
-  java/core/src/test/java/com/google/protobuf/UnknownFieldSetTest.java             \
-  java/core/src/test/java/com/google/protobuf/UnknownFieldSetPerformanceTest.java             \
-  java/core/src/test/java/com/google/protobuf/UnmodifiableLazyStringListTest.java  \
-  java/core/src/test/java/com/google/protobuf/Utf8Test.java                        \
-  java/core/src/test/java/com/google/protobuf/WellKnownTypesTest.java              \
-  java/core/src/test/java/com/google/protobuf/WireFormatLiteTest.java              \
-  java/core/src/test/java/com/google/protobuf/WireFormatTest.java                  \
-  java/core/src/test/java/com/google/protobuf/WrappersLiteOfMethodTest.java        \
-  java/core/src/test/java/com/google/protobuf/WrappersOfMethodTest.java            \
-  java/core/src/test/proto/com/google/protobuf/any_test.proto                      \
-  java/core/src/test/proto/com/google/protobuf/cached_field_size_test.proto        \
-  java/core/src/test/proto/com/google/protobuf/deprecated_file.proto               \
-  java/core/src/test/proto/com/google/protobuf/dynamic_message_test.proto          \
-  java/core/src/test/proto/com/google/protobuf/field_presence_test.proto           \
-  java/core/src/test/proto/com/google/protobuf/lazy_fields_lite.proto              \
-  java/core/src/test/proto/com/google/protobuf/lite_equals_and_hash.proto          \
-  java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto      \
-  java/core/src/test/proto/com/google/protobuf/map_for_proto2_test.proto           \
-  java/core/src/test/proto/com/google/protobuf/map_initialization_order_test.proto \
-  java/core/src/test/proto/com/google/protobuf/map_lite_test.proto                 \
-  java/core/src/test/proto/com/google/protobuf/map_test.proto                      \
-  java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto           \
-  java/core/src/test/proto/com/google/protobuf/nested_builders_test.proto          \
-  java/core/src/test/proto/com/google/protobuf/nested_extension.proto              \
-  java/core/src/test/proto/com/google/protobuf/nested_extension_lite.proto         \
-  java/core/src/test/proto/com/google/protobuf/non_nested_extension.proto          \
-  java/core/src/test/proto/com/google/protobuf/non_nested_extension_lite.proto     \
-  java/core/src/test/proto/com/google/protobuf/outer_class_name_test.proto         \
-  java/core/src/test/proto/com/google/protobuf/outer_class_name_test2.proto        \
-  java/core/src/test/proto/com/google/protobuf/outer_class_name_test3.proto        \
-  java/core/src/test/proto/com/google/protobuf/packed_field_test.proto             \
-  java/core/src/test/proto/com/google/protobuf/proto2_message.proto                \
-  java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto           \
-  java/core/src/test/proto/com/google/protobuf/proto2_unknown_enum_values.proto    \
-  java/core/src/test/proto/com/google/protobuf/proto3_message.proto                \
-  java/core/src/test/proto/com/google/protobuf/proto3_message_lite.proto           \
-  java/core/src/test/proto/com/google/protobuf/test_bad_identifiers.proto          \
-  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/wrappers_test.proto                 \
-  java/internal/BUILD.bazel                                                        \
-  java/internal/testing.bzl                                                        \
-  java/kotlin/BUILD.bazel                                                          \
-  java/kotlin/generate-sources-build.xml                                           \
-  java/kotlin/generate-test-sources-build.xml                                      \
-  java/kotlin/pom.xml                                                              \
-  java/kotlin/pom_template.xml                                                     \
-  java/kotlin/src/main/kotlin/com/google/protobuf/Anies.kt                         \
-  java/kotlin/src/main/kotlin/com/google/protobuf/ByteStrings.kt                   \
-  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/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/AniesTest.kt                     \
-  java/kotlin/src/test/kotlin/com/google/protobuf/ByteStringsTest.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/BUILD.bazel                                                     \
-  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/pom_template.xml                                                \
-  java/kotlin-lite/process-lite-sources-build.xml                                  \
-  java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt\
-  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.bazel                                                            \
-  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/BUILD.bazel                                                                 \
-  java/pom.xml                                                                     \
-  java/util/BUILD.bazel                                                            \
-  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/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/DurationsTest.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/TimestampsTest.java             \
-  java/util/src/test/java/com/google/protobuf/util/ValuesTest.java                 \
-  java/util/src/test/proto/com/google/protobuf/util/json_test.proto
-
-# Note: please keep this in sync with the dist_files rule in objectivec/BUILD.bazel.
-objectivec_EXTRA_DIST=                                                       \
-  objectivec/.clang-format                                                   \
-  objectivec/BUILD.bazel                                                     \
-  objectivec/DevTools/check_version_stamps.sh                                \
-  objectivec/DevTools/compile_testing_protos.sh                              \
-  objectivec/DevTools/full_mac_build.sh                                      \
-  objectivec/DevTools/pddm.py                                                \
-  objectivec/DevTools/pddm_tests.py                                          \
-  objectivec/generate_well_known_types.sh                                    \
-  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                               \
-  objectivec/GPBAny.pbobjc.h                                                 \
-  objectivec/GPBAny.pbobjc.m                                                 \
-  objectivec/GPBApi.pbobjc.h                                                 \
-  objectivec/GPBApi.pbobjc.m                                                 \
-  objectivec/GPBArray.h                                                      \
-  objectivec/GPBArray.m                                                      \
-  objectivec/GPBArray_PackagePrivate.h                                       \
-  objectivec/GPBBootstrap.h                                                  \
-  objectivec/GPBCodedInputStream.h                                           \
-  objectivec/GPBCodedInputStream.m                                           \
-  objectivec/GPBCodedInputStream_PackagePrivate.h                            \
-  objectivec/GPBCodedOutputStream.h                                          \
-  objectivec/GPBCodedOutputStream.m                                          \
-  objectivec/GPBCodedOutputStream_PackagePrivate.h                           \
-  objectivec/GPBDescriptor.h                                                 \
-  objectivec/GPBDescriptor.m                                                 \
-  objectivec/GPBDescriptor_PackagePrivate.h                                  \
-  objectivec/GPBDictionary.h                                                 \
-  objectivec/GPBDictionary.m                                                 \
-  objectivec/GPBDictionary_PackagePrivate.h                                  \
-  objectivec/GPBDuration.pbobjc.h                                            \
-  objectivec/GPBDuration.pbobjc.m                                            \
-  objectivec/GPBEmpty.pbobjc.h                                               \
-  objectivec/GPBEmpty.pbobjc.m                                               \
-  objectivec/GPBExtensionInternals.h                                         \
-  objectivec/GPBExtensionInternals.m                                         \
-  objectivec/GPBExtensionRegistry.h                                          \
-  objectivec/GPBExtensionRegistry.m                                          \
-  objectivec/GPBFieldMask.pbobjc.h                                           \
-  objectivec/GPBFieldMask.pbobjc.m                                           \
-  objectivec/GPBMessage.h                                                    \
-  objectivec/GPBMessage.m                                                    \
-  objectivec/GPBMessage_PackagePrivate.h                                     \
-  objectivec/GPBProtocolBuffers.h                                            \
-  objectivec/GPBProtocolBuffers.m                                            \
-  objectivec/GPBProtocolBuffers_RuntimeSupport.h                             \
-  objectivec/GPBRootObject.h                                                 \
-  objectivec/GPBRootObject.m                                                 \
-  objectivec/GPBRootObject_PackagePrivate.h                                  \
-  objectivec/GPBRuntimeTypes.h                                               \
-  objectivec/GPBSourceContext.pbobjc.h                                       \
-  objectivec/GPBSourceContext.pbobjc.m                                       \
-  objectivec/GPBStruct.pbobjc.h                                              \
-  objectivec/GPBStruct.pbobjc.m                                              \
-  objectivec/GPBTimestamp.pbobjc.h                                           \
-  objectivec/GPBTimestamp.pbobjc.m                                           \
-  objectivec/GPBType.pbobjc.h                                                \
-  objectivec/GPBType.pbobjc.m                                                \
-  objectivec/GPBUnknownField.h                                               \
-  objectivec/GPBUnknownField.m                                               \
-  objectivec/GPBUnknownField_PackagePrivate.h                                \
-  objectivec/GPBUnknownFieldSet.h                                            \
-  objectivec/GPBUnknownFieldSet.m                                            \
-  objectivec/GPBUnknownFieldSet_PackagePrivate.h                             \
-  objectivec/GPBUtilities.h                                                  \
-  objectivec/GPBUtilities.m                                                  \
-  objectivec/GPBUtilities_PackagePrivate.h                                   \
-  objectivec/GPBWellKnownTypes.h                                             \
-  objectivec/GPBWellKnownTypes.m                                             \
-  objectivec/GPBWireFormat.h                                                 \
-  objectivec/GPBWireFormat.m                                                 \
-  objectivec/GPBWrappers.pbobjc.h                                            \
-  objectivec/GPBWrappers.pbobjc.m                                            \
-  objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj                   \
-  objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
-  objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist \
-  objectivec/ProtocolBuffers_iOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
-  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
-  objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
-  objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj                   \
-  objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
-  objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist \
-  objectivec/ProtocolBuffers_OSX.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
-  objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
-  objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
-  objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj                  \
-  objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/contents.xcworkspacedata \
-  objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/IDEWorkspaceChecks.plist \
-  objectivec/ProtocolBuffers_tvOS.xcodeproj/project.xcworkspace/xcshareddata/WorkspaceSettings.xcsettings \
-  objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme \
-  objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme \
-  objectivec/README.md                                                       \
-  objectivec/Tests/golden_message                                            \
-  objectivec/Tests/golden_packed_fields_message                              \
-  objectivec/Tests/GPBARCUnittestProtos.m                                    \
-  objectivec/Tests/GPBArrayTests.m                                           \
-  objectivec/Tests/GPBCodedInputStreamTests.m                                \
-  objectivec/Tests/GPBCodedOuputStreamTests.m                                \
-  objectivec/Tests/GPBCompileTest01.m                                        \
-  objectivec/Tests/GPBCompileTest02.m                                        \
-  objectivec/Tests/GPBCompileTest03.m                                        \
-  objectivec/Tests/GPBCompileTest04.m                                        \
-  objectivec/Tests/GPBCompileTest05.m                                        \
-  objectivec/Tests/GPBCompileTest06.m                                        \
-  objectivec/Tests/GPBCompileTest07.m                                        \
-  objectivec/Tests/GPBCompileTest08.m                                        \
-  objectivec/Tests/GPBCompileTest09.m                                        \
-  objectivec/Tests/GPBCompileTest10.m                                        \
-  objectivec/Tests/GPBCompileTest11.m                                        \
-  objectivec/Tests/GPBCompileTest12.m                                        \
-  objectivec/Tests/GPBCompileTest13.m                                        \
-  objectivec/Tests/GPBCompileTest14.m                                        \
-  objectivec/Tests/GPBCompileTest15.m                                        \
-  objectivec/Tests/GPBCompileTest16.m                                        \
-  objectivec/Tests/GPBCompileTest17.m                                        \
-  objectivec/Tests/GPBCompileTest18.m                                        \
-  objectivec/Tests/GPBCompileTest19.m                                        \
-  objectivec/Tests/GPBCompileTest20.m                                        \
-  objectivec/Tests/GPBCompileTest21.m                                        \
-  objectivec/Tests/GPBCompileTest22.m                                        \
-  objectivec/Tests/GPBCompileTest23.m                                        \
-  objectivec/Tests/GPBCompileTest24.m                                        \
-  objectivec/Tests/GPBCompileTest25.m                                        \
-  objectivec/Tests/GPBConcurrencyTests.m                                     \
-  objectivec/Tests/GPBDescriptorTests.m                                      \
-  objectivec/Tests/GPBDictionaryTests+Bool.m                                 \
-  objectivec/Tests/GPBDictionaryTests+Int32.m                                \
-  objectivec/Tests/GPBDictionaryTests+Int64.m                                \
-  objectivec/Tests/GPBDictionaryTests+String.m                               \
-  objectivec/Tests/GPBDictionaryTests+UInt32.m                               \
-  objectivec/Tests/GPBDictionaryTests+UInt64.m                               \
-  objectivec/Tests/GPBDictionaryTests.m                                      \
-  objectivec/Tests/GPBDictionaryTests.pddm                                   \
-  objectivec/Tests/GPBExtensionRegistryTest.m                                \
-  objectivec/Tests/GPBMessageTests+ClassNames.m                              \
-  objectivec/Tests/GPBMessageTests+Merge.m                                   \
-  objectivec/Tests/GPBMessageTests+Runtime.m                                 \
-  objectivec/Tests/GPBMessageTests+Serialization.m                           \
-  objectivec/Tests/GPBMessageTests.m                                         \
-  objectivec/Tests/GPBObjectiveCPlusPlusTest.mm                              \
-  objectivec/Tests/GPBPerfTests.m                                            \
-  objectivec/Tests/GPBSwiftTests.swift                                       \
-  objectivec/Tests/GPBTestUtilities.h                                        \
-  objectivec/Tests/GPBTestUtilities.m                                        \
-  objectivec/Tests/GPBUnittestProtos.m                                       \
-  objectivec/Tests/GPBUnittestProtos2.m                                      \
-  objectivec/Tests/GPBUnknownFieldSetTest.m                                  \
-  objectivec/Tests/GPBUtilitiesTests.m                                       \
-  objectivec/Tests/GPBWellKnownTypesTest.m                                   \
-  objectivec/Tests/GPBWireFormatTests.m                                      \
-  objectivec/Tests/text_format_extensions_unittest_data.txt                   \
-  objectivec/Tests/text_format_map_unittest_data.txt                          \
-  objectivec/Tests/text_format_unittest_data.txt                              \
-  objectivec/Tests/unittest_cycle.proto                                       \
-  objectivec/Tests/unittest_deprecated.proto                                  \
-  objectivec/Tests/unittest_deprecated_file.proto                             \
-  objectivec/Tests/unittest_extension_chain_a.proto                           \
-  objectivec/Tests/unittest_extension_chain_b.proto                           \
-  objectivec/Tests/unittest_extension_chain_c.proto                           \
-  objectivec/Tests/unittest_extension_chain_d.proto                           \
-  objectivec/Tests/unittest_extension_chain_e.proto                           \
-  objectivec/Tests/unittest_extension_chain_f.proto                           \
-  objectivec/Tests/unittest_extension_chain_g.proto                           \
-  objectivec/Tests/unittest_objc.proto                                        \
-  objectivec/Tests/unittest_objc_options.proto                                \
-  objectivec/Tests/unittest_objc_startup.proto                                \
-  objectivec/Tests/unittest_runtime_proto2.proto                              \
-  objectivec/Tests/unittest_runtime_proto3.proto                              \
-  objectivec/Tests/UnitTests-Bridging-Header.h                                \
-  objectivec/Tests/UnitTests-Info.plist                                       \
-  Protobuf.podspec
-
-# Note: please keep this in sync with the dist_files rule in php/BUILD.bazel.
-php_EXTRA_DIST=                                                       \
-  php/README.md                                                       \
-  php/REFCOUNTING.md                                                  \
-  php/composer.json                                                   \
-  php/composer.json.dist                                              \
-  php/ext/google/protobuf/arena.c                                     \
-  php/ext/google/protobuf/arena.h                                     \
-  php/ext/google/protobuf/array.c                                     \
-  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/def.h                                       \
-  php/ext/google/protobuf/generate_package_xml.sh                     \
-  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/php-upb.c                                   \
-  php/ext/google/protobuf/php-upb.h                                   \
-  php/ext/google/protobuf/php_protobuf.h                              \
-  php/ext/google/protobuf/protobuf.c                                  \
-  php/ext/google/protobuf/protobuf.h                                  \
-  php/ext/google/protobuf/template_package.xml                        \
-  php/ext/google/protobuf/wkt.inc                                     \
-  php/ext/google/protobuf/tests/unnecessary_zval.phpt                 \
-  php/generate_descriptor_protos.sh                                   \
-  php/generate_test_protos.sh                                         \
-  php/release.sh                                                      \
-  php/src/GPBMetadata/Google/Protobuf/Any.php                         \
-  php/src/GPBMetadata/Google/Protobuf/Api.php                         \
-  php/src/GPBMetadata/Google/Protobuf/Duration.php                    \
-  php/src/GPBMetadata/Google/Protobuf/FieldMask.php                   \
-  php/src/GPBMetadata/Google/Protobuf/GPBEmpty.php                    \
-  php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php         \
-  php/src/GPBMetadata/Google/Protobuf/SourceContext.php               \
-  php/src/GPBMetadata/Google/Protobuf/Struct.php                      \
-  php/src/GPBMetadata/Google/Protobuf/Timestamp.php                   \
-  php/src/GPBMetadata/Google/Protobuf/Type.php                        \
-  php/src/GPBMetadata/Google/Protobuf/Wrappers.php                    \
-  php/src/Google/Protobuf/Any.php                                     \
-  php/src/Google/Protobuf/Api.php                                     \
-  php/src/Google/Protobuf/BoolValue.php                               \
-  php/src/Google/Protobuf/BytesValue.php                              \
-  php/src/Google/Protobuf/Descriptor.php                              \
-  php/src/Google/Protobuf/DescriptorPool.php                          \
-  php/src/Google/Protobuf/DoubleValue.php                             \
-  php/src/Google/Protobuf/Duration.php                                \
-  php/src/Google/Protobuf/Enum.php                                    \
-  php/src/Google/Protobuf/EnumDescriptor.php                          \
-  php/src/Google/Protobuf/EnumValue.php                               \
-  php/src/Google/Protobuf/EnumValueDescriptor.php                     \
-  php/src/Google/Protobuf/Field.php                                   \
-  php/src/Google/Protobuf/FieldDescriptor.php                         \
-  php/src/Google/Protobuf/FieldMask.php                               \
-  php/src/Google/Protobuf/Field/Cardinality.php                       \
-  php/src/Google/Protobuf/Field_Cardinality.php                       \
-  php/src/Google/Protobuf/Field/Kind.php                              \
-  php/src/Google/Protobuf/Field_Kind.php                              \
-  php/src/Google/Protobuf/FloatValue.php                              \
-  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                     \
-  php/src/Google/Protobuf/Internal/DescriptorPool.php                 \
-  php/src/Google/Protobuf/Internal/DescriptorProto.php                \
-  php/src/Google/Protobuf/Internal/DescriptorProto/ExtensionRange.php \
-  php/src/Google/Protobuf/Internal/DescriptorProto/ReservedRange.php  \
-  php/src/Google/Protobuf/Internal/EnumBuilderContext.php             \
-  php/src/Google/Protobuf/Internal/EnumDescriptor.php                 \
-  php/src/Google/Protobuf/Internal/EnumDescriptorProto.php            \
-  php/src/Google/Protobuf/Internal/EnumDescriptorProto/EnumReservedRange.php \
-  php/src/Google/Protobuf/Internal/EnumOptions.php                    \
-  php/src/Google/Protobuf/Internal/EnumValueDescriptorProto.php       \
-  php/src/Google/Protobuf/Internal/EnumValueOptions.php               \
-  php/src/Google/Protobuf/Internal/ExtensionRangeOptions.php          \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto.php           \
-  php/src/Google/Protobuf/Internal/FieldDescriptor.php                \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto.php           \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto/Label.php     \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto/Type.php      \
-  php/src/Google/Protobuf/Internal/FieldOptions.php                   \
-  php/src/Google/Protobuf/Internal/FieldOptions/CType.php             \
-  php/src/Google/Protobuf/Internal/FieldOptions/JSType.php            \
-  php/src/Google/Protobuf/Internal/FileDescriptor.php                 \
-  php/src/Google/Protobuf/Internal/FileDescriptorProto.php            \
-  php/src/Google/Protobuf/Internal/FileDescriptorSet.php              \
-  php/src/Google/Protobuf/Internal/FileOptions.php                    \
-  php/src/Google/Protobuf/Internal/FileOptions/OptimizeMode.php       \
-  php/src/Google/Protobuf/Internal/GPBDecodeException.php             \
-  php/src/Google/Protobuf/Internal/GPBJsonWire.php                    \
-  php/src/Google/Protobuf/Internal/GPBLabel.php                       \
-  php/src/Google/Protobuf/Internal/GPBType.php                        \
-  php/src/Google/Protobuf/Internal/GPBUtil.php                        \
-  php/src/Google/Protobuf/Internal/GPBWire.php                        \
-  php/src/Google/Protobuf/Internal/GPBWireType.php                    \
-  php/src/Google/Protobuf/Internal/GeneratedCodeInfo.php              \
-  php/src/Google/Protobuf/Internal/GeneratedCodeInfo/Annotation.php   \
-  php/src/Google/Protobuf/Internal/GetPublicDescriptorTrait.php       \
-  php/src/Google/Protobuf/Internal/HasPublicDescriptorTrait.php       \
-  php/src/Google/Protobuf/Internal/MapEntry.php                       \
-  php/src/Google/Protobuf/Internal/MapField.php                       \
-  php/src/Google/Protobuf/Internal/MapFieldIter.php                   \
-  php/src/Google/Protobuf/Internal/Message.php                        \
-  php/src/Google/Protobuf/Internal/MessageBuilderContext.php          \
-  php/src/Google/Protobuf/Internal/MessageOptions.php                 \
-  php/src/Google/Protobuf/Internal/MethodDescriptorProto.php          \
-  php/src/Google/Protobuf/Internal/MethodOptions.php                  \
-  php/src/Google/Protobuf/Internal/MethodOptions/IdempotencyLevel.php \
-  php/src/Google/Protobuf/Internal/OneofDescriptor.php                \
-  php/src/Google/Protobuf/Internal/OneofDescriptorProto.php           \
-  php/src/Google/Protobuf/Internal/OneofField.php                     \
-  php/src/Google/Protobuf/Internal/OneofOptions.php                   \
-  php/src/Google/Protobuf/Internal/RawInputStream.php                 \
-  php/src/Google/Protobuf/Internal/RepeatedField.php                  \
-  php/src/Google/Protobuf/Internal/RepeatedFieldIter.php              \
-  php/src/Google/Protobuf/Internal/ServiceDescriptorProto.php         \
-  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 \
-  php/src/Google/Protobuf/Internal/DescriptorProto_ReservedRange.php  \
-  php/src/Google/Protobuf/Internal/EnumDescriptorProto_EnumReservedRange.php \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto_Label.php     \
-  php/src/Google/Protobuf/Internal/FieldDescriptorProto_Type.php      \
-  php/src/Google/Protobuf/Internal/FieldOptions_CType.php             \
-  php/src/Google/Protobuf/Internal/FieldOptions_JSType.php            \
-  php/src/Google/Protobuf/Internal/FileOptions_OptimizeMode.php       \
-  php/src/Google/Protobuf/Internal/GeneratedCodeInfo_Annotation.php   \
-  php/src/Google/Protobuf/Internal/MethodOptions_IdempotencyLevel.php \
-  php/src/Google/Protobuf/Internal/SourceCodeInfo_Location.php        \
-  php/src/Google/Protobuf/Internal/UninterpretedOption_NamePart.php   \
-  php/src/Google/Protobuf/ListValue.php                               \
-  php/src/Google/Protobuf/Method.php                                  \
-  php/src/Google/Protobuf/Mixin.php                                   \
-  php/src/Google/Protobuf/NullValue.php                               \
-  php/src/Google/Protobuf/OneofDescriptor.php                         \
-  php/src/Google/Protobuf/Option.php                                  \
-  php/src/Google/Protobuf/SourceContext.php                           \
-  php/src/Google/Protobuf/StringValue.php                             \
-  php/src/Google/Protobuf/Struct.php                                  \
-  php/src/Google/Protobuf/Syntax.php                                  \
-  php/src/Google/Protobuf/Timestamp.php                               \
-  php/src/Google/Protobuf/Type.php                                    \
-  php/src/Google/Protobuf/UInt32Value.php                             \
-  php/src/Google/Protobuf/UInt64Value.php                             \
-  php/src/Google/Protobuf/Value.php                                   \
-  php/src/phpdoc.dist.xml                                             \
-  php/tests/ArrayTest.php                                             \
-  php/tests/compatibility_test.sh                                     \
-  php/tests/compile_extension.sh                                      \
-  php/tests/DescriptorsTest.php                                       \
-  php/tests/EncodeDecodeTest.php                                      \
-  php/tests/force_c_ext.php                                           \
-  php/tests/gdb_test.sh                                               \
-  php/tests/generated_previous/GPBMetadata/ProtoPrevious/TestPreviouslyUnreservedMessage.php \
-  php/tests/generated_previous/Previous/readonly.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/memory_leak_test.sh                                       \
-  php/tests/multirequest.php                                          \
-  php/tests/multirequest.sh                                           \
-  php/tests/PhpImplementationTest.php                                 \
-  php/tests/PreviouslyGeneratedClassTest.php                          \
-  php/tests/proto/empty/echo.proto                                    \
-  php/tests/proto/test.proto                                          \
-  php/tests/proto/test_descriptors.proto                              \
-  php/tests/proto/test_empty_php_namespace.proto                      \
-  php/tests/proto/test_import_descriptor_proto.proto                  \
-  php/tests/proto/test_include.proto                                  \
-  php/tests/proto/test_no_namespace.proto                             \
-  php/tests/proto/test_php_namespace.proto                            \
-  php/tests/proto/test_prefix.proto                                   \
-  php/tests/proto/test_reserved_enum_lower.proto                      \
-  php/tests/proto/test_reserved_enum_upper.proto                      \
-  php/tests/proto/test_reserved_enum_value_lower.proto                \
-  php/tests/proto/test_reserved_enum_value_upper.proto                \
-  php/tests/proto/test_reserved_message_lower.proto                   \
-  php/tests/proto/test_reserved_message_upper.proto                   \
-  php/tests/proto/test_service.proto                                  \
-  php/tests/proto/test_service_namespace.proto                        \
-  php/tests/proto/test_wrapper_type_setters.proto                     \
-  php/tests/proto_previous/test_previously_unreserved_message.proto   \
-  php/tests/test_base.php                                             \
-  php/tests/test_util.php                                             \
-  php/tests/valgrind.supp                                             \
-  php/tests/WellKnownTest.php                                         \
-  php/tests/WrapperTypeSettersTest.php
-
-# Note: please keep this in sync with the python_dist_files rule in BUILD.bazel.
-python_EXTRA_DIST=                                                           \
-  python/MANIFEST.in                                                         \
-  python/google/__init__.py                                                  \
-  python/google/protobuf/__init__.py                                         \
-  python/google/protobuf/compiler/__init__.py                                \
-  python/google/protobuf/descriptor.py                                       \
-  python/google/protobuf/descriptor_database.py                              \
-  python/google/protobuf/descriptor_pool.py                                  \
-  python/google/protobuf/internal/__init__.py                                \
-  python/google/protobuf/internal/_parameterized.py                          \
-  python/google/protobuf/internal/any_test.proto                             \
-  python/google/protobuf/internal/any_test.proto                             \
-  python/google/protobuf/internal/api_implementation.cc                      \
-  python/google/protobuf/internal/api_implementation.py                      \
-  python/google/protobuf/internal/builder.py                                 \
-  python/google/protobuf/internal/containers.py                              \
-  python/google/protobuf/internal/decoder.py                                 \
-  python/google/protobuf/internal/descriptor_database_test.py                \
-  python/google/protobuf/internal/descriptor_pool_test.py                    \
-  python/google/protobuf/internal/descriptor_pool_test1.proto                \
-  python/google/protobuf/internal/descriptor_pool_test2.proto                \
-  python/google/protobuf/internal/descriptor_test.py                         \
-  python/google/protobuf/internal/encoder.py                                 \
-  python/google/protobuf/internal/enum_type_wrapper.py                       \
-  python/google/protobuf/internal/extension_dict.py                          \
-  python/google/protobuf/internal/factory_test1.proto                        \
-  python/google/protobuf/internal/factory_test2.proto                        \
-  python/google/protobuf/internal/file_options_test.proto                    \
-  python/google/protobuf/internal/generator_test.py                          \
-  python/google/protobuf/internal/import_test.py                             \
-  python/google/protobuf/internal/import_test_package/__init__.py            \
-  python/google/protobuf/internal/import_test_package/import_public.proto    \
-  python/google/protobuf/internal/import_test_package/import_public_nested.proto \
-  python/google/protobuf/internal/import_test_package/inner.proto            \
-  python/google/protobuf/internal/import_test_package/outer.proto            \
-  python/google/protobuf/internal/json_format_test.py                        \
-  python/google/protobuf/internal/keywords_test.py                           \
-  python/google/protobuf/internal/message_factory_test.py                    \
-  python/google/protobuf/internal/message_listener.py                        \
-  python/google/protobuf/internal/message_set_extensions.proto               \
-  python/google/protobuf/internal/message_test.py                            \
-  python/google/protobuf/internal/missing_enum_values.proto                  \
-  python/google/protobuf/internal/more_extensions.proto                      \
-  python/google/protobuf/internal/more_extensions_dynamic.proto              \
-  python/google/protobuf/internal/more_messages.proto                        \
-  python/google/protobuf/internal/no_package.proto                           \
-  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                    \
-  python/google/protobuf/internal/test_bad_identifiers.proto                 \
-  python/google/protobuf/internal/test_proto3_optional.proto                 \
-  python/google/protobuf/internal/test_util.py                               \
-  python/google/protobuf/internal/testing_refleaks.py                        \
-  python/google/protobuf/internal/text_encoding_test.py                      \
-  python/google/protobuf/internal/text_format_test.py                        \
-  python/google/protobuf/internal/type_checkers.py                           \
-  python/google/protobuf/internal/unknown_fields_test.py                     \
-  python/google/protobuf/internal/well_known_types.py                        \
-  python/google/protobuf/internal/well_known_types.py                        \
-  python/google/protobuf/internal/well_known_types_test.py                   \
-  python/google/protobuf/internal/well_known_types_test.py                   \
-  python/google/protobuf/internal/wire_format.py                             \
-  python/google/protobuf/internal/wire_format_test.py                        \
-  python/google/protobuf/json_format.py                                      \
-  python/google/protobuf/message.py                                          \
-  python/google/protobuf/message_factory.py                                  \
-  python/google/protobuf/proto_api.h                                         \
-  python/google/protobuf/proto_builder.py                                    \
-  python/google/protobuf/pyext/README                                        \
-  python/google/protobuf/pyext/__init__.py                                   \
-  python/google/protobuf/pyext/cpp_message.py                                \
-  python/google/protobuf/pyext/descriptor.cc                                 \
-  python/google/protobuf/pyext/descriptor.h                                  \
-  python/google/protobuf/pyext/descriptor_containers.cc                      \
-  python/google/protobuf/pyext/descriptor_containers.h                       \
-  python/google/protobuf/pyext/descriptor_database.cc                        \
-  python/google/protobuf/pyext/descriptor_database.h                         \
-  python/google/protobuf/pyext/descriptor_pool.cc                            \
-  python/google/protobuf/pyext/descriptor_pool.h                             \
-  python/google/protobuf/pyext/extension_dict.cc                             \
-  python/google/protobuf/pyext/extension_dict.h                              \
-  python/google/protobuf/pyext/map_container.cc                              \
-  python/google/protobuf/pyext/map_container.h                               \
-  python/google/protobuf/pyext/message.cc                                    \
-  python/google/protobuf/pyext/message.h                                     \
-  python/google/protobuf/pyext/field.cc                                      \
-  python/google/protobuf/pyext/field.h                                       \
-  python/google/protobuf/pyext/unknown_fields.cc                             \
-  python/google/protobuf/pyext/unknown_fields.h                              \
-  python/google/protobuf/pyext/message_factory.cc                            \
-  python/google/protobuf/pyext/message_factory.h                             \
-  python/google/protobuf/pyext/message_module.cc                             \
-  python/google/protobuf/pyext/proto2_api_test.proto                         \
-  python/google/protobuf/pyext/python.proto                                  \
-  python/google/protobuf/pyext/repeated_composite_container.cc               \
-  python/google/protobuf/pyext/repeated_composite_container.h                \
-  python/google/protobuf/pyext/repeated_scalar_container.cc                  \
-  python/google/protobuf/pyext/repeated_scalar_container.h                   \
-  python/google/protobuf/pyext/safe_numerics.h                               \
-  python/google/protobuf/pyext/scoped_pyobject_ptr.h                         \
-  python/google/protobuf/pyext/unknown_field_set.cc                          \
-  python/google/protobuf/pyext/unknown_field_set.h                           \
-  python/google/protobuf/python_protobuf.h                                   \
-  python/google/protobuf/reflection.py                                       \
-  python/google/protobuf/service.py                                          \
-  python/google/protobuf/service_reflection.py                               \
-  python/google/protobuf/symbol_database.py                                  \
-  python/google/protobuf/text_encoding.py                                    \
-  python/google/protobuf/text_format.py                                      \
-  python/google/protobuf/unknown_fields.py                                   \
-  python/google/protobuf/util/__init__.py                                    \
-  python/release.sh                                                          \
-  python/mox.py                                                              \
-  python/setup.cfg                                                           \
-  python/setup.py                                                            \
-  python/stubout.py                                                          \
-  python/tox.ini                                                             \
-  python/README.md
-
-# Note: please keep this in sync with the dist_files rule in ruby/BUILD.bazel.
-ruby_EXTRA_DIST=                                                             \
-  ruby/Gemfile                                                               \
-  ruby/.gitignore                                                            \
-  ruby/README.md                                                             \
-  ruby/Rakefile                                                              \
-  ruby/compatibility_tests/v3.0.0/tests/test_import.proto                    \
-  ruby/compatibility_tests/v3.0.0/tests/stress.rb                            \
-  ruby/compatibility_tests/v3.0.0/tests/repeated_field_test.rb               \
-  ruby/compatibility_tests/v3.0.0/tests/generated_code_test.rb               \
-  ruby/compatibility_tests/v3.0.0/tests/generated_code.proto                 \
-  ruby/compatibility_tests/v3.0.0/tests/basic.rb                             \
-  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/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/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/descriptor_dsl.rb                                 \
-  ruby/lib/google/protobuf/message_exts.rb                                   \
-  ruby/lib/google/protobuf/repeated_field.rb                                 \
-  ruby/lib/google/protobuf/well_known_types.rb                               \
-  ruby/lib/google/protobuf.rb                                                \
-  ruby/pom.xml                                                               \
-  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/RubyEnumDescriptor.java       \
-  ruby/src/main/java/com/google/protobuf/jruby/RubyFieldDescriptor.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/RubyMessage.java              \
-  ruby/src/main/java/com/google/protobuf/jruby/RubyOneofDescriptor.java      \
-  ruby/src/main/java/com/google/protobuf/jruby/RubyProtobuf.java             \
-  ruby/src/main/java/com/google/protobuf/jruby/RubyRepeatedField.java        \
-  ruby/src/main/java/com/google/protobuf/jruby/SentinelOuterClass.java       \
-  ruby/src/main/java/com/google/protobuf/jruby/Utils.java                    \
-  ruby/src/main/java/google/ProtobufJavaService.java                         \
-  ruby/src/main/sentinel.proto                                               \
-  ruby/tests/basic_proto2.rb                                                 \
-  ruby/tests/basic_test_proto2.proto                                         \
-  ruby/tests/basic_test.proto                                                \
-  ruby/tests/basic.rb                                                        \
-  ruby/tests/common_tests.rb                                                 \
-  ruby/tests/encode_decode_test.rb                                           \
-  ruby/tests/gc_test.rb                                                      \
-  ruby/tests/repeated_field_test.rb                                          \
-  ruby/tests/stress.rb                                                       \
-  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                                  \
-  ruby/tests/test_ruby_package.proto                                         \
-  ruby/tests/generated_code_test.rb                                          \
-  ruby/tests/well_known_types_test.rb                                        \
-  ruby/tests/type_errors.rb                                                  \
-  ruby/travis-test.sh
-
-all_EXTRA_DIST=$(csharp_EXTRA_DIST) $(java_EXTRA_DIST) $(objectivec_EXTRA_DIST) $(php_EXTRA_DIST) $(python_EXTRA_DIST) $(ruby_EXTRA_DIST)
-
-# Note: please keep this in sync with the common_dist_files rule in BUILD.bazel.
-EXTRA_DIST = $(@DIST_LANG@_EXTRA_DIST)              \
-  autogen.sh                                        \
-  generate_descriptor_proto.sh                      \
-  README.md                                         \
-  LICENSE                                           \
-  CONTRIBUTORS.txt                                  \
-  CHANGES.txt                                       \
-  update_file_lists.sh                              \
-  BUILD.bazel                                       \
-  WORKSPACE                                         \
-  CMakeLists.txt                                    \
-  build_defs/BUILD.bazel                            \
-  build_defs/cc_proto_blacklist_test.bzl            \
-  build_defs/compiler_config_setting.bzl            \
-  build_defs/cpp_opts.bzl                           \
-  build_files_updated_unittest.sh                   \
-  cmake/CMakeLists.txt                              \
-  cmake/README.md                                   \
-  cmake/conformance.cmake                           \
-  cmake/examples.cmake                              \
-  cmake/extract_includes.bat.in                     \
-  cmake/install.cmake                               \
-  cmake/libprotobuf-lite.cmake                      \
-  cmake/libprotobuf.cmake                           \
-  cmake/libprotoc.cmake                             \
-  cmake/protobuf-config-version.cmake.in            \
-  cmake/protobuf-config.cmake.in                    \
-  cmake/protobuf-lite.pc.cmake                      \
-  cmake/protobuf-module.cmake.in                    \
-  cmake/protobuf-options.cmake                      \
-  cmake/protobuf.pc.cmake                           \
-  cmake/protoc.cmake                                \
-  cmake/tests.cmake                                 \
-  cmake/version.rc.in                               \
-  csharp/BUILD.bazel                                \
-  editors/README.txt                                \
-  editors/proto.vim                                 \
-  editors/protobuf-mode.el                          \
-  examples/AddPerson.java                           \
-  examples/BUILD.bazel                              \
-  examples/CMakeLists.txt                           \
-  examples/ListPeople.java                          \
-  examples/Makefile                                 \
-  examples/README.md                                \
-  examples/WORKSPACE                                \
-  examples/add_person.cc                            \
-  examples/add_person.dart                          \
-  examples/add_person.py                            \
-  examples/addressbook.proto                        \
-  examples/go/cmd/add_person/add_person.go          \
-  examples/go/cmd/add_person/add_person_test.go     \
-  examples/go/cmd/list_people/list_people.go        \
-  examples/go/cmd/list_people/list_people_test.go   \
-  examples/go/go.sum                                \
-  examples/go/go.mod                                \
-  examples/list_people.cc                           \
-  examples/list_people.dart                         \
-  examples/list_people.py                           \
-  examples/pubspec.yaml                             \
-  conformance/BUILD.bazel                           \
-  conformance/defs.bzl                              \
-  maven_install.json                                \
-  php/BUILD.bazel                                   \
-  protobuf.bzl                                      \
-  protobuf_deps.bzl                                 \
-  protobuf_release.bzl                              \
-  protobuf_version.bzl                              \
-  ruby/BUILD.bazel                                  \
-  third_party/zlib.BUILD                            \
-  util/python/BUILD.bazel
-
-# Deletes all the files generated by autogen.sh.
-MAINTAINERCLEANFILES =   \
-  aclocal.m4             \
-  ar-lib                 \
-  config.guess           \
-  config.sub             \
-  configure              \
-  depcomp                \
-  install-sh             \
-  ltmain.sh              \
-  Makefile.in            \
-  missing                \
-  mkinstalldirs          \
-  config.h.in            \
-  stamp.h.in             \
-  m4/ltsugar.m4          \
-  m4/libtool.m4          \
-  m4/ltversion.m4        \
-  m4/lt~obsolete.m4      \
-  m4/ltoptions.m4
diff --git a/Protobuf-C++.podspec b/Protobuf-C++.podspec
index 41fab1b..9fad46b 100644
--- a/Protobuf-C++.podspec
+++ b/Protobuf-C++.podspec
@@ -13,8 +13,7 @@
   s.source_files = 'src/google/protobuf/*.{h,cc,inc}',
                    'src/google/protobuf/stubs/*.{h,cc}',
                    'src/google/protobuf/io/*.{h,cc}',
-                   'src/google/protobuf/util/*.{h,cc}',
-                   'src/google/protobuf/util/internal/*.{h,cc}'
+                   'src/google/protobuf/util/*.{h,cc}'
 
   # Excluding all the tests in the directories above
   s.exclude_files = 'src/google/**/*_test.{h,cc,inc}',
diff --git a/Protobuf.podspec b/Protobuf.podspec
index b5fe42e..3188764 100644
--- a/Protobuf.podspec
+++ b/Protobuf.podspec
@@ -34,10 +34,10 @@
   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 = '9.0'
-  s.osx.deployment_target = '10.9'
-  s.tvos.deployment_target = '9.0'
-  s.watchos.deployment_target = '2.0'
+  s.ios.deployment_target = '10.0'
+  s.osx.deployment_target = '10.12'
+  s.tvos.deployment_target = '12.0'
+  s.watchos.deployment_target = '6.0'
   s.requires_arc = false
 
   # The unittest need the generate sources from the testing related .proto
diff --git a/README.md b/README.md
index c2e6575..3bfeb0f 100644
--- a/README.md
+++ b/README.md
@@ -3,7 +3,7 @@
 
 Copyright 2008 Google Inc.
 
-https://developers.google.com/protocol-buffers/
+[Protocol Buffers documentation](https://developers.google.com/protocol-buffers/)
 
 Overview
 --------
@@ -24,26 +24,21 @@
 with the C++ runtime.
 
 For non-C++ users, the simplest way to install the protocol compiler is to
-download a pre-built binary from our release page:
-
-  [https://github.com/protocolbuffers/protobuf/releases](https://github.com/protocolbuffers/protobuf/releases)
+download a pre-built binary from our [GitHub release page](https://github.com/protocolbuffers/protobuf/releases).
 
 In the downloads section of each release, you can find pre-built binaries in
-zip packages: protoc-$VERSION-$PLATFORM.zip. It contains the protoc binary
-as well as a set of standard .proto files distributed along with protobuf.
+zip packages: `protoc-$VERSION-$PLATFORM.zip`. It contains the protoc binary
+as well as a set of standard `.proto` files distributed along with protobuf.
 
 If you are looking for an old version that is not available in the release
-page, check out the maven repo here:
-
-  [https://repo1.maven.org/maven2/com/google/protobuf/protoc/](https://repo1.maven.org/maven2/com/google/protobuf/protoc/)
+page, check out the [Maven repository](https://repo1.maven.org/maven2/com/google/protobuf/protoc/).
 
 These pre-built binaries are only provided for released versions. If you want
 to use the github main version at HEAD, or you need to modify protobuf code,
 or you are using C++, it's recommended to build your own protoc binary from
 source.
 
-If you would like to build protoc binary from source, see the [C++ Installation
-Instructions](src/README.md).
+If you would like to build protoc binary from source, see the [C++ Installation Instructions](src/README.md).
 
 Protobuf Runtime Installation
 -----------------------------
@@ -63,14 +58,13 @@
 | Go                                   | [protocolbuffers/protobuf-go](https://github.com/protocolbuffers/protobuf-go)|
 | PHP                                  | [php](php)                                                  |
 | Dart                                 | [dart-lang/protobuf](https://github.com/dart-lang/protobuf) |
+| Javascript                           | [protocolbuffers/protobuf-javascript](https://github.com/protocolbuffers/protobuf-javascript)|
 
 Quick Start
 -----------
 
-The best way to learn how to use protobuf is to follow the tutorials in our
-developer guide:
-
-https://developers.google.com/protocol-buffers/docs/tutorials
+The best way to learn how to use protobuf is to follow the [tutorials in our
+developer guide](https://developers.google.com/protocol-buffers/docs/tutorials).
 
 If you want to learn from code examples, take a look at the examples in the
 [examples](examples) directory.
@@ -78,7 +72,11 @@
 Documentation
 -------------
 
-The complete documentation for Protocol Buffers is available via the
-web at:
+The complete documentation is available via the [Protocol Buffers documentation](https://developers.google.com/protocol-buffers/).
 
-https://developers.google.com/protocol-buffers/
+Developer Community
+-------------------
+
+To be alerted to upcoming changes in Protocol Buffers and connect with protobuf developers and users,
+[join the Google Group](https://groups.google.com/g/protobuf).
+
diff --git a/WORKSPACE b/WORKSPACE
index d01122a..b10e0d0 100644
--- a/WORKSPACE
+++ b/WORKSPACE
@@ -9,32 +9,32 @@
 
 http_archive(
     name = "com_google_googletest",
-    sha256 = "9dc9157a9a1551ec7a7e43daea9a694a0bb5fb8bec81235d8a1e6ef64c716dcb",
-    strip_prefix = "googletest-release-1.10.0",
+    sha256 = "ea54c9845568cb31c03f2eddc7a40f7f83912d04ab977ff50ec33278119548dd",
+    strip_prefix = "googletest-4c9a3bb62bf3ba1f1010bf96f9c8ed767b363774",
     urls = [
-        "https://mirror.bazel.build/github.com/google/googletest/archive/release-1.10.0.tar.gz",
-        "https://github.com/google/googletest/archive/release-1.10.0.tar.gz",
+        "https://github.com/google/googletest/archive/4c9a3bb62bf3ba1f1010bf96f9c8ed767b363774.tar.gz",
     ],
 )
 
 http_archive(
-    name = "com_github_google_benchmark",
-    sha256 = "2a778d821997df7d8646c9c59b8edb9a573a6e04c534c01892a40aa524a7b68c",
-    strip_prefix = "benchmark-bf585a2789e30585b4e3ce6baf11ef2750b54677",
-    urls = [
-        "https://github.com/google/benchmark/archive/bf585a2789e30585b4e3ce6baf11ef2750b54677.zip",
-    ],
+    name = "com_googlesource_code_re2",
+    sha256 = "906d0df8ff48f8d3a00a808827f009a840190f404559f649cb8e4d7143255ef9",
+    strip_prefix = "re2-a276a8c738735a0fe45a6ee590fe2df69bcf4502",
+    urls = ["https://github.com/google/re2/archive/a276a8c738735a0fe45a6ee590fe2df69bcf4502.zip"],  # 2022-04-08
+)
+
+# Bazel platform rules.
+http_archive(
+    name = "platforms",
+    sha256 = "a879ea428c6d56ab0ec18224f976515948822451473a80d06c2e50af0bbe5121",
+    strip_prefix = "platforms-da5541f26b7de1dc8e04c075c99df5351742a4a2",
+    urls = ["https://github.com/bazelbuild/platforms/archive/da5541f26b7de1dc8e04c075c99df5351742a4a2.zip"],  # 2022-05-27
 )
 
 # Load common dependencies.
 load("//:protobuf_deps.bzl", "PROTOBUF_MAVEN_ARTIFACTS", "protobuf_deps")
 protobuf_deps()
 
-bind(
-    name = "python_headers",
-    actual = "//util/python:python_headers",
-)
-
 load("@rules_jvm_external//:defs.bzl", "maven_install")
 
 maven_install(
@@ -69,3 +69,29 @@
 
 load("@upb//bazel:workspace_deps.bzl", "upb_deps")
 upb_deps()
+
+load("@upb//bazel:system_python.bzl", "system_python")
+system_python(
+    name = "system_python",
+    minimum_python_version = "3.7",
+)
+
+load("@system_python//:pip.bzl", "pip_parse")
+pip_parse(
+    name="pip_deps",
+    requirements = "@upb//python:requirements.txt",
+    requirements_overrides = {
+        "3.11": "@upb//python:requirements_311.txt",
+    },
+)
+
+load("@pip_deps//:requirements.bzl", "install_deps")
+install_deps()
+
+load("@utf8_range//:workspace_deps.bzl", "utf8_range_deps")
+utf8_range_deps()
+
+bind(
+    name = "python_headers",
+    actual = "@system_python//:python_headers",
+)
diff --git a/appveyor.yml b/appveyor.yml
index 91f737a..1e2834b 100644
--- a/appveyor.yml
+++ b/appveyor.yml
@@ -3,16 +3,16 @@
 
 environment:
   matrix:
-    # Only test few combinations: "Visual Studio 2015 (14) + Win64/MinGW + Debug + DLL". We can
+    # Only test few combinations: "Visual Studio 2017 (15) + Win64/MinGW + Debug + DLL". We can
     # test more combinations but AppVeyor just takes too long to finish (each
     # combination takes ~15mins).
     - platform: MinGW
       language: cpp
-      image: Visual Studio 2015
+      image: Visual Studio 2017
 
     - platform: Win64
       language: cpp
-      image: Visual Studio 2015
+      image: Visual Studio 2017
       BUILD_DLL: ON
       UNICODE: ON
 
@@ -35,8 +35,8 @@
 
 before_build:
   - if %platform%==MinGW set generator=MinGW Makefiles
-  - if %platform%==Win32 set generator=Visual Studio 14
-  - if %platform%==Win64 set generator=Visual Studio 14 Win64
+  - if %platform%==Win32 set generator=Visual Studio 15
+  - if %platform%==Win64 set generator=Visual Studio 15 Win64
   - if %platform%==Win32 set vcplatform=Win32
   - if %platform%==Win64 set vcplatform=x64
 
diff --git a/autogen.sh b/autogen.sh
deleted file mode 100755
index 105bf09..0000000
--- a/autogen.sh
+++ /dev/null
@@ -1,44 +0,0 @@
-#!/bin/sh
-
-# Run this script to generate the configure script and other files that will
-# be included in the distribution.  These files are not checked in because they
-# are automatically generated.
-
-set -e
-
-if [ ! -z "$@" ]; then
-  for argument in "$@"; do
-    case $argument in
-	  # make curl silent
-      "-s")
-        curlopts="-s"
-        ;;
-    esac
-  done
-fi
-
-# Check that we're being run from the right directory.
-if test ! -f src/google/protobuf/stubs/common.h; then
-  cat >&2 << __EOF__
-Could not find source code.  Make sure you are running this script from the
-root of the distribution tree.
-__EOF__
-  exit 1
-fi
-
-set -ex
-
-# 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. (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
-
-rm -rf autom4te.cache config.h.in~
-exit 0
diff --git a/benchmarks/BUILD.bazel b/benchmarks/BUILD.bazel
deleted file mode 100644
index 36f6283..0000000
--- a/benchmarks/BUILD.bazel
+++ /dev/null
@@ -1,98 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_proto_library")
-load("@rules_java//java:defs.bzl", "java_proto_library")
-load("@rules_pkg//:mappings.bzl", "pkg_filegroup", "pkg_files", "strip_prefix")
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = glob(
-        [
-            "*",
-            "python/*.cc",
-            "util/*.cc",
-        ],
-        exclude = [
-            "__init__.py",  # not in autotools dist
-            "go/*",
-        ],
-    ),
-    strip_prefix = strip_prefix.from_root(""),
-)
-
-# Convenience filegroup for all files that should be packaged.
-pkg_filegroup(
-    name = "all_dist_files",
-    srcs = [
-        ":dist_files",
-        "//benchmarks/cpp:dist_files",
-        # "//benchmarks/datasets:dist_files",  # not in autotools dist
-        "//benchmarks/datasets/google_message1/proto2:dist_files",
-        "//benchmarks/datasets/google_message1/proto3:dist_files",
-        "//benchmarks/datasets/google_message2:dist_files",
-        "//benchmarks/datasets/google_message3:dist_files",
-        "//benchmarks/datasets/google_message4:dist_files",
-    ],
-    visibility = ["//pkg:__pkg__"],
-)
diff --git a/benchmarks/Makefile.am b/benchmarks/Makefile.am
deleted file mode 100644
index ed57978..0000000
--- a/benchmarks/Makefile.am
+++ /dev/null
@@ -1,664 +0,0 @@
-benchmarks_protoc_inputs_benchmark_wrapper =                               \
-	benchmarks.proto
-
-benchmarks_protoc_inputs =                                                 \
-	datasets/google_message1/proto3/benchmark_message1_proto3.proto
-
-benchmarks_protoc_inputs_proto2 =                                          \
-	datasets/google_message1/proto2/benchmark_message1_proto2.proto          \
-	datasets/google_message2/benchmark_message2.proto                        \
-	datasets/google_message3/benchmark_message3.proto                        \
-	datasets/google_message3/benchmark_message3_1.proto                      \
-	datasets/google_message3/benchmark_message3_2.proto                      \
-	datasets/google_message3/benchmark_message3_3.proto                      \
-	datasets/google_message3/benchmark_message3_4.proto                      \
-	datasets/google_message3/benchmark_message3_5.proto                      \
-	datasets/google_message3/benchmark_message3_6.proto                      \
-	datasets/google_message3/benchmark_message3_7.proto                      \
-	datasets/google_message3/benchmark_message3_8.proto                      \
-	datasets/google_message4/benchmark_message4.proto                        \
-	datasets/google_message4/benchmark_message4_1.proto                      \
-	datasets/google_message4/benchmark_message4_2.proto                      \
-	datasets/google_message4/benchmark_message4_3.proto
-
-make_tmp_dir:
-	mkdir -p 'tmp/java/src/main/java'
-	touch make_tmp_dir
-
-
-# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
-# relative to srcdir, which may not be the same as the current directory when
-# building out-of-tree.
-protoc_middleman: make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper)
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd/cpp --java_out=$$oldpwd/tmp/java/src/main/java --python_out=$$oldpwd/tmp $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) )
-	touch protoc_middleman
-
-protoc_middleman2:  make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs_proto2) $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --cpp_out=$$oldpwd/cpp --java_out=$$oldpwd/tmp/java/src/main/java --python_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2) )
-	touch protoc_middleman2
-
-all_data = $$(find $$(cd $(srcdir) && pwd) -type f -name "dataset.*.pb" -not -path "$$(cd $(srcdir) && pwd)/tmp/*")
-
-############# CPP RULES ##############
-
-benchmarks_protoc_outputs =                                                \
-	cpp/benchmarks.pb.cc                                                     \
-	cpp/datasets/google_message1/proto3/benchmark_message1_proto3.pb.cc
-
-benchmarks_protoc_outputs_header =                                         \
-	cpp/benchmarks.pb.h                                                      \
-	cpp/datasets/google_message1/proto3/benchmark_message1_proto3.pb.h
-
-benchmarks_protoc_outputs_proto2_header =                                  \
-	cpp/datasets/google_message1/proto2/benchmark_message1_proto2.pb.h       \
-	cpp/datasets/google_message2/benchmark_message2.pb.h                     \
-	cpp/datasets/google_message3/benchmark_message3.pb.h                     \
-	cpp/datasets/google_message3/benchmark_message3_1.pb.h                   \
-	cpp/datasets/google_message3/benchmark_message3_2.pb.h                   \
-	cpp/datasets/google_message3/benchmark_message3_3.pb.h                   \
-	cpp/datasets/google_message3/benchmark_message3_4.pb.h                   \
-	cpp/datasets/google_message3/benchmark_message3_5.pb.h                   \
-	cpp/datasets/google_message3/benchmark_message3_6.pb.h                   \
-	cpp/datasets/google_message3/benchmark_message3_7.pb.h                   \
-	cpp/datasets/google_message3/benchmark_message3_8.pb.h                   \
-	cpp/datasets/google_message4/benchmark_message4.pb.h                     \
-	cpp/datasets/google_message4/benchmark_message4_1.pb.h                   \
-	cpp/datasets/google_message4/benchmark_message4_2.pb.h                   \
-	cpp/datasets/google_message4/benchmark_message4_3.pb.h
-
-benchmarks_protoc_outputs_proto2 =                                         \
-	cpp/datasets/google_message1/proto2/benchmark_message1_proto2.pb.cc      \
-	cpp/datasets/google_message2/benchmark_message2.pb.cc                    \
-	cpp/datasets/google_message3/benchmark_message3.pb.cc                    \
-	cpp/datasets/google_message3/benchmark_message3_1.pb.cc                  \
-	cpp/datasets/google_message3/benchmark_message3_2.pb.cc                  \
-	cpp/datasets/google_message3/benchmark_message3_3.pb.cc                  \
-	cpp/datasets/google_message3/benchmark_message3_4.pb.cc                  \
-	cpp/datasets/google_message3/benchmark_message3_5.pb.cc                  \
-	cpp/datasets/google_message3/benchmark_message3_6.pb.cc                  \
-	cpp/datasets/google_message3/benchmark_message3_7.pb.cc                  \
-	cpp/datasets/google_message3/benchmark_message3_8.pb.cc                  \
-	cpp/datasets/google_message4/benchmark_message4.pb.cc                    \
-	cpp/datasets/google_message4/benchmark_message4_1.pb.cc                  \
-	cpp/datasets/google_message4/benchmark_message4_2.pb.cc                  \
-	cpp/datasets/google_message4/benchmark_message4_3.pb.cc
-
-
-$(benchmarks_protoc_outputs): protoc_middleman
-$(benchmarks_protoc_outputs_header): protoc_middleman
-$(benchmarks_protoc_outputs_proto2): protoc_middleman2
-$(benchmarks_protoc_outputs_proto2_header): protoc_middleman2
-
-initialize_submodule:
-	oldpwd=`pwd`
-	cd $(top_srcdir) && git submodule update --init -r third_party/benchmark && cd third_party/benchmark \
-	 && cmake -DCMAKE_BUILD_TYPE=Release && make
-	cd $$oldpwd
-	touch initialize_submodule
-
-$(top_srcdir)/third_party/benchmark/src/libbenchmark.a: initialize_submodule
-
-AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG) -Wall -Wwrite-strings -Woverloaded-virtual -Wno-sign-compare
-
-bin_PROGRAMS = cpp-benchmark
-
-cpp_benchmark_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
-cpp_benchmark_SOURCES = cpp/cpp_benchmark.cc
-cpp_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(top_srcdir)/third_party/benchmark/include
-# Explicit deps because BUILT_SOURCES are only done before a "make all/check"
-# so a direct "make test_cpp" could fail if parallel enough.
-# See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
-cpp/cpp_benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
-cpp/benchmark-cpp_benchmark.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
-nodist_cpp_benchmark_SOURCES =                                             \
-	$(benchmarks_protoc_outputs)                                             \
-	$(benchmarks_protoc_outputs_proto2)                                      \
-	$(benchmarks_protoc_outputs_proto2_header)                               \
-	$(benchmarks_protoc_outputs_header)
-
-cpp: protoc_middleman protoc_middleman2 cpp-benchmark initialize_submodule
-	./cpp-benchmark $(all_data)
-
-############ CPP RULES END ############
-
-############# JAVA RULES ##############
-
-java_benchmark_testing_files =                                      \
-	java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java
-
-javac_middleman: $(java_benchmark_testing_files) protoc_middleman protoc_middleman2
-	cp -r $(srcdir)/java tmp
-	mkdir -p tmp/java/lib
-	cp $(top_srcdir)/java/core/target/*.jar tmp/java/lib/protobuf-java.jar
-	cd tmp/java && mvn clean compile assembly:single -Dprotobuf.version=$(PACKAGE_VERSION) && cd ../..
-	@touch javac_middleman
-
-java-benchmark: javac_middleman
-	@echo "Writing shortcut script java-benchmark..."
-	@echo '#! /bin/bash' > java-benchmark
-	@echo 'all_data=""' >> java-benchmark
-	@echo 'conf=()' >> java-benchmark
-	@echo 'data_files=""' >> java-benchmark
-	@echo 'for arg in $$@; do if [[ $${arg:0:1} == "-" ]]; then conf+=($$arg); else data_files+="$$arg,"; fi; done' >> java-benchmark
-	@echo 'java -cp '\"tmp/java/target/*:$(top_srcdir)/java/core/target/*:$(top_srcdir)/java/util/target/*\"" \\" >>java-benchmark
-	@echo '   com.google.caliper.runner.CaliperMain com.google.protobuf.ProtoCaliperBenchmark -i runtime '"\\"  >> java-benchmark
-	@echo '   -b serializeToByteArray,serializeToMemoryStream,deserializeFromByteArray,deserializeFromMemoryStream '"\\" >> java-benchmark
-	@echo '   -DdataFile=$${data_files:0:-1} $${conf[*]}' >> java-benchmark
-	@chmod +x java-benchmark
-
-java: protoc_middleman protoc_middleman2 java-benchmark
-	./java-benchmark $(all_data)
-
-############# JAVA RULES END ##############
-
-
-############# PYTHON RULES ##############
-
-python_add_init: protoc_middleman protoc_middleman2
-	all_file=`find tmp -type f -regex '.*\.py'` &&                   \
-	for file in $${all_file[@]}; do                                  \
-		path="$${file%/*}";                                            \
-		while true; do                                                 \
-			touch "$$path/__init__.py" && chmod +x "$$path/__init__.py"; \
-			if [[ $$path != *"/"* ]]; then break; fi;                    \
-			path=$${path%/*};                                            \
-		done                                                           \
-	done
-
-python_cpp_pkg_flags = `pkg-config --cflags --libs python3`
-
-lib_LTLIBRARIES = libbenchmark_messages.la
-libbenchmark_messages_la_SOURCES = python/python_benchmark_messages.cc
-libbenchmark_messages_la_LIBADD = $(top_srcdir)/src/.libs/libprotobuf.la
-libbenchmark_messages_la_LDFLAGS = -version-info 1:0:0 -export-dynamic
-libbenchmark_messages_la_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp $(python_cpp_pkg_flags)
-libbenchmark_messages_la-python_benchmark_messages.$(OBJEXT): $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header) $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2)
-nodist_libbenchmark_messages_la_SOURCES =                         \
-	$(benchmarks_protoc_outputs)                                    \
-	$(benchmarks_protoc_outputs_proto2)                             \
-	$(benchmarks_protoc_outputs_proto2_header)                      \
-	$(benchmarks_protoc_outputs_header)
-
-python-pure-python-benchmark: python_add_init
-	@echo "Writing shortcut script python-pure-python-benchmark..."
-	@echo '#! /bin/bash' > python-pure-python-benchmark
-	@echo export LD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-pure-python-benchmark
-	@echo export DYLD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-pure-python-benchmark
-	@echo export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=\'python\' >> python-pure-python-benchmark
-	@echo cp $(srcdir)/python/py_benchmark.py tmp >> python-pure-python-benchmark
-	@echo python3 tmp/py_benchmark.py '$$@' >> python-pure-python-benchmark
-	@chmod +x python-pure-python-benchmark
-
-python-cpp-reflection-benchmark: python_add_init
-	@echo "Writing shortcut script python-cpp-reflection-benchmark..."
-	@echo '#! /bin/bash' > python-cpp-reflection-benchmark
-	@echo export LD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-reflection-benchmark
-	@echo export DYLD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-reflection-benchmark
-	@echo export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=\'cpp\' >> python-cpp-reflection-benchmark
-	@echo cp $(srcdir)/python/py_benchmark.py tmp >> python-cpp-reflection-benchmark
-	@echo python3 tmp/py_benchmark.py '$$@' >> python-cpp-reflection-benchmark
-	@chmod +x python-cpp-reflection-benchmark
-
-python-cpp-generated-code-benchmark: python_add_init libbenchmark_messages.la
-	@echo "Writing shortcut script python-cpp-generated-code-benchmark..."
-	@echo '#! /bin/bash' > python-cpp-generated-code-benchmark
-	@echo export LD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-generated-code-benchmark
-	@echo export DYLD_LIBRARY_PATH=$(top_srcdir)/src/.libs >> python-cpp-generated-code-benchmark
-	@echo export PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=\'cpp\' >> python-cpp-generated-code-benchmark
-	@echo cp $(srcdir)/python/py_benchmark.py tmp >> python-cpp-generated-code-benchmark
-	@echo python3 tmp/py_benchmark.py --cpp_generated '$$@' >> python-cpp-generated-code-benchmark
-	@chmod +x python-cpp-generated-code-benchmark
-
-python-pure-python: python-pure-python-benchmark
-	./python-pure-python-benchmark $(all_data)
-
-python-cpp-reflection: python-cpp-reflection-benchmark
-	./python-cpp-reflection-benchmark $(all_data)
-
-python-cpp-generated-code: python-cpp-generated-code-benchmark
-	./python-cpp-generated-code-benchmark $(all_data)
-
-############# PYTHON RULES END ##############
-
-############# GO RULES BEGIN ##############
-
-benchmarks_protoc_inputs_proto2_message1 =                                 \
-	datasets/google_message1/proto2/benchmark_message1_proto2.proto
-
-benchmarks_protoc_inputs_proto2_message2 =                                 \
-	datasets/google_message2/benchmark_message2.proto
-
-benchmarks_protoc_inputs_proto2_message3 =                                 \
-	datasets/google_message3/benchmark_message3.proto                        \
-	datasets/google_message3/benchmark_message3_1.proto                      \
-	datasets/google_message3/benchmark_message3_2.proto                      \
-	datasets/google_message3/benchmark_message3_3.proto                      \
-	datasets/google_message3/benchmark_message3_4.proto                      \
-	datasets/google_message3/benchmark_message3_5.proto                      \
-	datasets/google_message3/benchmark_message3_6.proto                      \
-	datasets/google_message3/benchmark_message3_7.proto                      \
-	datasets/google_message3/benchmark_message3_8.proto
-
-benchmarks_protoc_inputs_proto2_message4 =                                 \
-	datasets/google_message4/benchmark_message4.proto                        \
-	datasets/google_message4/benchmark_message4_1.proto                      \
-	datasets/google_message4/benchmark_message4_2.proto                      \
-	datasets/google_message4/benchmark_message4_3.proto
-
-go_protoc_middleman: make_tmp_dir $(top_srcdir)/src/protoc$(EXEEXT) $(benchmarks_protoc_inputs) $(well_known_type_protoc_inputs) $(benchmarks_protoc_inputs_proto2_message1) $(benchmarks_protoc_inputs_proto2_message2) $(benchmarks_protoc_inputs_proto2_message3) $(benchmarks_protoc_inputs_proto2_message4) $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs) )
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_benchmark_wrapper) )
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message1) )
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message2) )
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message3) )
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --go_out=$$oldpwd/tmp $(benchmarks_protoc_inputs_proto2_message4) )
-	touch go_protoc_middleman
-
-go-benchmark: go_protoc_middleman
-	@echo "Writing shortcut script go-benchmark..."
-	@echo '#! /bin/bash' > go-benchmark
-	@echo 'cd $(srcdir)/go' >> go-benchmark
-	@echo 'all_data=""' >> go-benchmark
-	@echo 'conf=()' >> go-benchmark
-	@echo 'data_files=()' >> go-benchmark
-	@echo 'for arg in $$@; do if [[ $${arg:0:1} == "-" ]]; then conf+=($$arg); else data_files+=("$$arg"); fi; done' >> go-benchmark
-	@echo 'go test -bench=. $${conf[*]} -- $${data_files[*]}' >> go-benchmark
-	@echo 'cd ..' >> go-benchmark
-	@chmod +x go-benchmark
-
-go: go_protoc_middleman go-benchmark
-	./go-benchmark $(all_data)
-
-############# GO RULES END ##############
-
-############# GOGO RULES BEGIN ############
-
-cpp_no_group_benchmarks_protoc_outputs_header =                             \
-	gogo/cpp_no_group/benchmarks.pb.h                                         \
-	gogo/cpp_no_group/datasets/google_message1/proto3/benchmark_message1_proto3.pb.h
-
-cpp_no_group_benchmarks_protoc_outputs =                                    \
-	gogo/cpp_no_group/benchmarks.pb.cc                                        \
-	gogo/cpp_no_group/datasets/google_message1/proto3/benchmark_message1_proto3.pb.cc
-
-cpp_no_group_benchmarks_protoc_outputs_proto2_header =                      \
-	gogo/cpp_no_group/datasets/google_message1/proto2/benchmark_message1_proto2.pb.h \
-	gogo/cpp_no_group/datasets/google_message2/benchmark_message2.pb.h        \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3.pb.h        \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_1.pb.h      \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_2.pb.h      \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_3.pb.h      \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_4.pb.h      \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_5.pb.h      \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_6.pb.h      \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_7.pb.h      \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_8.pb.h      \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4.pb.h        \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4_1.pb.h      \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4_2.pb.h      \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4_3.pb.h
-
-cpp_no_group_benchmarks_protoc_outputs_proto2 =                             \
-	gogo/cpp_no_group/datasets/google_message1/proto2/benchmark_message1_proto2.pb.cc \
-	gogo/cpp_no_group/datasets/google_message2/benchmark_message2.pb.cc       \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3.pb.cc       \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_1.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_2.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_3.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_4.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_5.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_6.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_7.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message3/benchmark_message3_8.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4.pb.cc       \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4_1.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4_2.pb.cc     \
-	gogo/cpp_no_group/datasets/google_message4/benchmark_message4_3.pb.cc
-
-$(cpp_no_group_benchmarks_protoc_outputs): cpp_no_group_protoc_middleman
-$(cpp_no_group_benchmarks_protoc_outputs_header): cpp_no_group_protoc_middleman
-$(cpp_no_group_benchmarks_protoc_outputs_proto2): cpp_no_group_protoc_middleman
-$(cpp_no_group_benchmarks_protoc_outputs_proto2_header): cpp_no_group_protoc_middleman
-
-generate_cpp_no_group_benchmark_code:
-	cp $(srcdir)/cpp/cpp_benchmark.cc gogo/cpp_no_group/cpp_benchmark.cc
-	sed -i -e "s/\#include \"datasets/\#include \"gogo\/cpp_no_group\/datasets/g" gogo/cpp_no_group/cpp_benchmark.cc
-	sed -i -e "s/\#include \"benchmarks.pb.h/\#include \"gogo\/cpp_no_group\/benchmarks.pb.h/g" gogo/cpp_no_group/cpp_benchmark.cc
-	touch generate_cpp_no_group_benchmark_code
-
-bin_PROGRAMS += cpp-no-group-benchmark
-cpp_no_group_benchmark_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/third_party/benchmark/src/libbenchmark.a
-cpp_no_group_benchmark_SOURCES = gogo/cpp_no_group/cpp_benchmark.cc
-cpp_no_group_benchmark_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/gogo/cpp_no_group -I$(top_srcdir)/third_party/benchmark/include
-# Explicit deps because BUILT_SOURCES are only done before a "make all/check"
-# so a direct "make test_cpp" could fail if parallel enough.
-# See: https://www.gnu.org/software/automake/manual/html_node/Built-Sources-Example.html#Recording-Dependencies-manually
-gogo/cpp_no_group/cpp_no_group_benchmark-cpp_benchmark.$(OBJEXT): $(cpp_no_group_benchmarks_protoc_outputs) $(cpp_no_group_benchmarks_protoc_outputs_proto2) $(cpp_no_group_benchmarks_protoc_outputs_header) \
-	$(cpp_no_group_benchmarks_protoc_outputs_proto2_header) $(top_srcdir)/third_party/benchmark/src/libbenchmark.a generate_cpp_no_group_benchmark_code
-gogo/cpp_no_group/cpp_benchmark.cc: generate_cpp_no_group_benchmark_code
-nodist_cpp_no_group_benchmark_SOURCES =                                    \
-	$(cpp_no_group_benchmarks_protoc_outputs_proto2)                         \
-	$(cpp_no_group_benchmarks_protoc_outputs)                                \
-	$(cpp_no_group_benchmarks_protoc_outputs_header)                         \
-	$(cpp_no_group_benchmarks_protoc_outputs_proto2_header)
-
-cpp_no_group: cpp_no_group_protoc_middleman generate_gogo_data cpp-no-group-benchmark
-	./cpp-no-group-benchmark $(gogo_data)
-
-gogo_proto_middleman: protoc-gen-gogoproto
-	mkdir -p "tmp/gogo_proto"
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I$(srcdir) -I$(top_srcdir) --plugin=protoc-gen-gogoproto --gogoproto_out=$$oldpwd/tmp/gogo_proto $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2) )
-	touch gogo_proto_middleman
-
-gogo_data = $$(for data in $(all_data); do echo "tmp/gogo_data$${data\#$(srcdir)}"; done | xargs)
-
-generate_gogo_data: protoc_middleman protoc_middleman2 gogo-data-scrubber
-	mkdir -p `dirname $(gogo_data)`
-	./gogo-data-scrubber $(all_data) $(gogo_data)
-	touch generate_gogo_data
-
-make_tmp_dir_gogo:
-	mkdir -p tmp/go_no_group/benchmark_code
-	mkdir -p tmp/gogofast/benchmark_code
-	mkdir -p tmp/gogofaster/benchmark_code
-	mkdir -p tmp/gogoslick/benchmark_code
-	touch make_tmp_dir_gogo
-
-go_no_group_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_benchmark_wrapper) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message1) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message2) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message3) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --go_out=$$oldpwd/tmp/go_no_group $(benchmarks_protoc_inputs_proto2_message4) )
-	touch go_no_group_protoc_middleman
-
-cpp_no_group_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_benchmark_wrapper) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message1) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message2) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message3) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --cpp_out=$$oldpwd/gogo/cpp_no_group $(benchmarks_protoc_inputs_proto2_message4) )
-	touch cpp_no_group_protoc_middleman
-
-gogofast_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_benchmark_wrapper) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message1) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message2) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message3) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofast_out=$$oldpwd/tmp/gogofast $(benchmarks_protoc_inputs_proto2_message4) )
-	touch gogofast_protoc_middleman
-
-gogofaster_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_benchmark_wrapper) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message1) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message2) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message3) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogofaster_out=$$oldpwd/tmp/gogofaster $(benchmarks_protoc_inputs_proto2_message4) )
-	touch gogofaster_protoc_middleman
-
-gogoslick_protoc_middleman: make_tmp_dir_gogo $(top_srcdir)/src/protoc$(EXEEXT) gogo_proto_middleman $(well_known_type_protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_benchmark_wrapper) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message1) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message2) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message3) )
-	oldpwd=`pwd` && ( cd $(srcdir)/tmp/gogo_proto && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$$oldpwd/$(top_srcdir)/src --gogoslick_out=$$oldpwd/tmp/gogoslick $(benchmarks_protoc_inputs_proto2_message4) )
-	touch gogoslick_protoc_middleman
-
-generate-gogo-benchmark-code:
-	@echo '#! /bin/bash' > generate-gogo-benchmark-code
-	@echo 'cp $(srcdir)/go/go_benchmark_test.go tmp/$$1/benchmark_code/$$1_benchmark1_test.go' >> generate-gogo-benchmark-code
-	@echo 'sed -i -e "s/\.\.\/tmp/../g" tmp/$$1/benchmark_code/$$1_benchmark1_test.go' >> generate-gogo-benchmark-code
-	@echo 'sed -i -e "s/b\.Run(\"\(.*\)\"/b.Run(\"\1\_$$1\"/g" tmp/$$1/benchmark_code/$$1_benchmark1_test.go' >> generate-gogo-benchmark-code
-	@echo 'if [[ $$2 == 1 ]]; then sed -i -e "s/github\.com\/golang/github.com\/gogo/g" tmp/$$1/benchmark_code/$$1_benchmark1_test.go; fi ' >> generate-gogo-benchmark-code
-	@chmod +x generate-gogo-benchmark-code
-
-generate_all_gogo_benchmark_code: generate-gogo-benchmark-code make_tmp_dir_gogo
-	./generate-gogo-benchmark-code go_no_group 0
-	./generate-gogo-benchmark-code gogofast 1
-	./generate-gogo-benchmark-code gogofaster 1
-	./generate-gogo-benchmark-code gogoslick 1
-
-gogo-benchmark:
-	@echo "Writing shortcut script gogo-benchmark..."
-	@echo '#! /bin/bash' > gogo-benchmark
-	@echo 'cd tmp/$$1/benchmark_code' >> gogo-benchmark
-	@echo 'shift' >> gogo-benchmark
-	@echo 'all_data=""' >> gogo-benchmark
-	@echo 'for data_file in $$@; do all_data="$$all_data ../../../$$data_file"; done' >> gogo-benchmark
-	@echo 'go test -bench=. -- $$all_data' >> gogo-benchmark
-	@echo 'cd ../..' >> gogo-benchmark
-	@chmod +x gogo-benchmark
-
-go_no_group: go_no_group_protoc_middleman generate_gogo_data generate_all_gogo_benchmark_code gogo-benchmark
-	./gogo-benchmark go_no_group $(gogo_data)
-
-gogofast: gogofast_protoc_middleman generate_gogo_data gogo-benchmark generate_all_gogo_benchmark_code
-	./gogo-benchmark gogofast $(gogo_data)
-
-gogofaster: gogofaster_protoc_middleman  generate_gogo_data gogo-benchmark generate_all_gogo_benchmark_code
-	./gogo-benchmark gogofaster $(gogo_data)
-
-gogoslick: gogoslick_protoc_middleman  generate_gogo_data gogo-benchmark generate_all_gogo_benchmark_code
-	./gogo-benchmark gogoslick $(gogo_data)
-
-
-############# GOGO RULES END ############
-
-
-############ UTIL RULES BEGIN ############
-
-bin_PROGRAMS += protoc-gen-gogoproto gogo-data-scrubber protoc-gen-proto2_to_proto3 proto3-data-stripper
-
-protoc_gen_gogoproto_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/src/libprotoc.la
-protoc_gen_gogoproto_SOURCES = util/protoc-gen-gogoproto.cc
-protoc_gen_gogoproto_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util
-
-gogo_data_scrubber_LDADD = $(top_srcdir)/src/libprotobuf.la
-gogo_data_scrubber_SOURCES = util/gogo_data_scrubber.cc
-gogo_data_scrubber_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util
-util/gogo_data_scrubber-gogo_data_scrubber.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header)
-nodist_gogo_data_scrubber_SOURCES =                                        \
-	$(benchmarks_protoc_outputs)                                             \
-	$(benchmarks_protoc_outputs_proto2)                                      \
-	$(benchmarks_protoc_outputs_proto2_header)                               \
-	$(benchmarks_protoc_outputs_header)
-
-protoc_gen_proto2_to_proto3_LDADD = $(top_srcdir)/src/libprotobuf.la $(top_srcdir)/src/libprotoc.la
-protoc_gen_proto2_to_proto3_SOURCES = util/protoc-gen-proto2_to_proto3.cc
-protoc_gen_proto2_to_proto3_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util
-
-proto3_data_stripper_LDADD = $(top_srcdir)/src/libprotobuf.la
-proto3_data_stripper_SOURCES = util/proto3_data_stripper.cc
-proto3_data_stripper_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)/cpp -I$(srcdir)/util
-util/proto3_data_stripper-proto3_data_stripper.$(OBJEXT): $(benchmarks_protoc_outputs) $(benchmarks_protoc_outputs_proto2) $(benchmarks_protoc_outputs_header) $(benchmarks_protoc_outputs_proto2_header)
-nodist_proto3_data_stripper_SOURCES =                                      \
-	$(benchmarks_protoc_outputs)                                             \
-	$(benchmarks_protoc_outputs_proto2)                                      \
-	$(benchmarks_protoc_outputs_proto2_header)                               \
-	$(benchmarks_protoc_outputs_header)
-
-
-############ UTIL RULES END ############
-
-############ PROTO3 PREPARATION BEGIN #############
-
-proto3_proto_middleman: protoc-gen-proto2_to_proto3
-	mkdir -p "tmp/proto3_proto"
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I$(srcdir) -I$(top_srcdir) --plugin=protoc-gen-proto2_to_proto3 --proto2_to_proto3_out=$$oldpwd/tmp/proto3_proto $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2) )
-	touch proto3_proto_middleman
-
-full_srcdir = $$(cd $(srcdir) && pwd)
-proto3_data = $$(for data in $(all_data); do echo $(full_srcdir)"/tmp/proto3_data$${data\#$(full_srcdir)}"; done | xargs)
-
-generate_proto3_data: protoc_middleman protoc_middleman2 proto3-data-stripper
-	mkdir -p `dirname $(proto3_data)`
-	./proto3-data-stripper $(all_data) $(proto3_data)
-	touch generate_proto3_data
-
-############ PROTO3 PREPARATION END #############
-
-############ PHP RULES BEGIN #################
-
-proto3_middleman_php: proto3_proto_middleman
-	mkdir -p "tmp/php"
-	oldpwd=`pwd` && ( cd tmp/proto3_proto && $$oldpwd/../src/protoc$(EXEEXT) -I$(srcdir) -I$(top_srcdir) --php_out=$$oldpwd/tmp/php $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2) )
-	touch proto3_middleman_php
-
-php-benchmark: proto3_middleman_php generate_proto3_data
-	mkdir -p "tmp/php/Google/Protobuf/Benchmark" && cp php/PhpBenchmark.php "tmp/php/Google/Protobuf/Benchmark"
-	cp php/autoload.php "tmp/php"
-	@echo "Writing shortcut script php-benchmark..."
-	@echo '#! /bin/bash' > php-benchmark
-	@echo 'export PROTOBUF_PHP_SRCDIR="$$(cd $(top_srcdir) && pwd)/php/src"' >> php-benchmark
-	@echo 'cd tmp/php' >> php-benchmark
-	@echo 'export CURRENT_DIR=$$(pwd)' >> php-benchmark
-	@echo 'php -d auto_prepend_file="autoload.php" -d include_path="$$(pwd)" Google/Protobuf/Benchmark/PhpBenchmark.php $$@' >> php-benchmark
-	@echo 'cd ../..' >> php-benchmark
-	@chmod +x php-benchmark
-
-php: php-benchmark proto3_middleman_php
-	./php-benchmark --behavior_prefix="php" $(proto3_data)
-
-php_c_extension:
-	cd $(top_srcdir)/php/ext/google/protobuf && phpize && ./configure CFLAGS='-O3' && make -j8
-
-php-c-benchmark: proto3_middleman_php generate_proto3_data php_c_extension php_c_extension
-	mkdir -p "tmp/php/Google/Protobuf/Benchmark" && cp php/PhpBenchmark.php "tmp/php/Google/Protobuf/Benchmark"
-	cp php/autoload.php "tmp/php"
-	@echo "Writing shortcut script php-c-benchmark..."
-	@echo '#! /bin/bash' > php-c-benchmark
-	@echo 'export PROTOBUF_PHP_SRCDIR="$$(cd $(top_srcdir) && pwd)/php/src"' >> php-c-benchmark
-	@echo 'export PROTOBUF_PHP_EXTDIR="$$PROTOBUF_PHP_SRCDIR/../ext/google/protobuf/modules"' >> php-c-benchmark
-	@echo 'cd tmp/php' >> php-c-benchmark
-	@echo 'export CURRENT_DIR=$$(pwd)' >> php-c-benchmark
-	@echo 'php -d auto_prepend_file="autoload.php" -d include_path="$$(pwd)" -d extension="$$PROTOBUF_PHP_EXTDIR/protobuf.so" Google/Protobuf/Benchmark/PhpBenchmark.php $$@' >> php-c-benchmark
-	@echo 'cd ../..' >> php-c-benchmark
-	@chmod +x php-c-benchmark
-
-php_c: php-c-benchmark proto3_middleman_php
-	./php-c-benchmark --behavior_prefix="php_c" $(proto3_data)
-
-
-############ PHP RULES END #################
-
-############ protobuf.js RULE BEGIN #############
-
-pbjs_preparation:
-	mkdir -p tmp/protobuf.js
-	cd tmp/protobuf.js && git clone https://github.com/dcodeIO/protobuf.js.git && \
-			cd protobuf.js && npm install && npm run build
-	cd tmp/protobuf.js && npm install benchmark
-	cp protobuf.js/* tmp/protobuf.js
-	cp js/benchmark_suite.js tmp/protobuf.js
-	touch pbjs_preparation
-
-pbjs_middleman: pbjs_preparation
-	export OLDDIR=$$(pwd) && cd tmp/protobuf.js && node generate_pbjs_files.js --target static-module --include_path=$$OLDDIR -o generated_bundle_code.js $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2)
-	touch pbjs_middleman
-
-pbjs-benchmark: pbjs_middleman
-	@echo '#! /bin/bash' > pbjs-benchmark
-	@echo 'cd tmp/protobuf.js' >> pbjs-benchmark
-	@echo 'sed -i "s/protobufjs/.\/protobuf.js/g" generated_bundle_code.js' >> pbjs-benchmark
-	@echo 'env NODE_PATH=".:./node_modules:$$NODE_PATH" node protobufjs_benchmark.js $$@' >> pbjs-benchmark
-	@chmod +x pbjs-benchmark
-
-pbjs: pbjs-benchmark
-	./pbjs-benchmark $(all_data)
-
-############ protobuf.js RULE END #############
-
-############ JS RULE BEGIN #############
-
-js_preparation:
-	mkdir -p tmp/js
-	oldpwd=$$(pwd) && cd $(top_srcdir)/js && npm install && npm test
-	cd tmp/js && npm install benchmark
-	cp js/* tmp/js
-	touch js_preparation
-
-js_middleman: js_preparation
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/../src/protoc$(EXEEXT) -I. -I$(top_srcdir)/src --js_out=import_style=commonjs,binary:$$oldpwd/tmp/js $(benchmarks_protoc_inputs) $(benchmarks_protoc_inputs_benchmark_wrapper) $(benchmarks_protoc_inputs_proto2))
-	touch js_middleman
-
-js-benchmark: js_middleman
-	@echo '#! /bin/bash' > js-benchmark
-	@echo 'export TOP_JS_SRCDIR=$$(cd $(top_srcdir)/js && pwd)' >> js-benchmark
-	@echo 'cd tmp/js' >> js-benchmark
-	@echo 'env NODE_PATH="$$TOP_JS_SRCDIR:.:./node_modules:$$NODE_PATH" node --max-old-space-size=4096 js_benchmark.js $$@' >> js-benchmark
-	@chmod +x js-benchmark
-
-js: js-benchmark
-	./js-benchmark $(all_data)
-
-############ JS RULE END #############
-
-EXTRA_DIST =									\
-	$(benchmarks_protoc_inputs_benchmark_wrapper)				\
-	$(benchmarks_protoc_inputs)						\
-	$(benchmarks_protoc_inputs_proto2)					\
-	google_size.proto
-
-MAINTAINERCLEANFILES =                                                     \
-	Makefile.in
-
-CLEANFILES =                                                               \
-	$(benchmarks_protoc_outputs)                                             \
-	$(benchmarks_protoc_outputs_header)                                      \
-	$(benchmarks_protoc_outputs_proto2)                                      \
-	$(benchmarks_protoc_outputs_proto2_header)                               \
-	initialize_submodule                                                     \
-	make_tmp_dir                                                             \
-	protoc_middleman                                                         \
-	protoc_middleman2                                                        \
-	javac_middleman                                                          \
-	java-benchmark                                                           \
-	python_cpp_proto_library                                                 \
-	python-pure-python-benchmark                                             \
-	python-cpp-reflection-benchmark                                          \
-	python-cpp-generated-code-benchmark                                      \
-	go-benchmark                                                             \
-	go_protoc_middleman                                                      \
-	make_tmp_dir_gogo                                                        \
-	gogo_proto_middleman                                                     \
-	generate_gogo_data                                                       \
-	go_no_group_protoc_middleman                                             \
-	go_no_group                                                              \
-	go-no-group-benchmark                                                    \
-	$(cpp_no_group_benchmarks_protoc_outputs_header)                         \
-	$(cpp_no_group_benchmarks_protoc_outputs)                                \
-	$(cpp_no_group_benchmarks_protoc_outputs_proto2_header)                  \
-	$(cpp_no_group_benchmarks_protoc_outputs_proto2)                         \
-	generate_all_gogo_benchmark_code                                         \
-	generate-gogo-benchmark-code                                             \
-	cpp_no_group_protoc_middleman                                            \
-	generate_cpp_no_group_benchmark_code                                     \
-	generate_gogo_benchmark_code                                             \
-	gogofast_protoc_middleman                                                \
-	gogofast                                                                 \
-	gogofaster_protoc_middleman                                              \
-	gogofaster                                                               \
-	gogoslick_protoc_middleman                                               \
-	gogoslick                                                                \
-	gogo-benchmark                                                           \
-	gogo/cpp_no_group/cpp_benchmark.*                                        \
-	proto3_proto_middleman                                                   \
-	generate_proto3_data                                                     \
-	php-benchmark                                                            \
-	php-c-benchmark                                                          \
-	proto3_middleman_php                                                     \
-	pbjs_preparation                                                         \
-	pbjs_middleman                                                           \
-	pbjs-benchmark                                                           \
-	js_preparation                                                           \
-	js_middleman                                                             \
-	js-benchmark
-
-clean-local:
-	-rm -rf tmp/*
-
diff --git a/benchmarks/README.md b/benchmarks/README.md
deleted file mode 100644
index 70c3596..0000000
--- a/benchmarks/README.md
+++ /dev/null
@@ -1,239 +0,0 @@
-
-# Protocol Buffers Benchmarks
-
-This directory contains benchmarking schemas and data sets that you
-can use to test a variety of performance scenarios against your
-protobuf language runtime. If you are looking for performance
-numbers of officially supported languages, see [Protobuf Performance](
-https://github.com/protocolbuffers/protobuf/blob/main/docs/performance.md).
-
-## Prerequisite
-
-First, you need to follow the instruction in the root directory's README to
-build your language's protobuf, then:
-
-### CPP
-You need to install [cmake](https://cmake.org/) before building the benchmark.
-
-We are using [google/benchmark](https://github.com/google/benchmark) as the
-benchmark tool for testing cpp. This will be automatically made during build the
-cpp benchmark.
-
-The cpp protobuf performance can be improved by linking with
-[TCMalloc](https://google.github.io/tcmalloc).
-
-### Java
-We're using maven to build the java benchmarks, which is the same as to build
-the Java protobuf. There're no other tools need to install. We're using
-[google/caliper](https://github.com/google/caliper) as benchmark tool, which
-can be automatically included by maven.
-
-### Python
-We're using python C++ API for testing the generated
-CPP proto version of python protobuf, which is also a prerequisite for Python
-protobuf cpp implementation. You need to install the correct version of Python
-C++ extension package before run generated CPP proto version of Python
-protobuf's benchmark. e.g. under Ubuntu, you need to
-
-```
-$ sudo apt-get install python-dev
-$ sudo apt-get install python3-dev
-```
-And you also need to make sure `pkg-config` is installed.
-
-### Go
-Go protobufs are maintained at [github.com/golang/protobuf](
-http://github.com/golang/protobuf). If not done already, you need to install the
-toolchain and the Go protoc-gen-go plugin for protoc.
-
-To install protoc-gen-go, run:
-
-```
-$ go get -u github.com/golang/protobuf/protoc-gen-go
-$ export PATH=$PATH:$(go env GOPATH)/bin
-```
-
-The first command installs `protoc-gen-go` into the `bin` directory in your local `GOPATH`.
-The second command adds the `bin` directory to your `PATH` so that `protoc` can locate the plugin later.
-
-### PHP
-PHP benchmark's requirement is the same as PHP protobuf's requirements. The benchmark will automatically
-include PHP protobuf's src and build the c extension if required.
-
-### Node.js
-Node.js benchmark need [node](https://nodejs.org/en/)(higher than V6) and [npm](https://www.npmjs.com/) package manager installed. This benchmark is using the [benchmark](https://www.npmjs.com/package/benchmark) framework to test, which needn't to manually install. And another prerequisite is [protobuf js](https://github.com/protocolbuffers/protobuf/tree/main/js), which needn't to manually install either
-
-### C#
-The C# benchmark code is built as part of the main Google.Protobuf
-solution. It requires the .NET Core SDK, and depends on
-[BenchmarkDotNet](https://github.com/dotnet/BenchmarkDotNet), which
-will be downloaded automatically.
-
-## Run instructions
-
-To run all the benchmark dataset:
-
-### Java:
-
-First build the Java binary in the usual way with Maven:
-
-```
-$ cd java
-$ mvn install
-```
-
-Assuming that completes successfully,
-
-```
-$ cd ../benchmarks
-$ make java
-```
-
-### CPP:
-
-```
-$ make cpp
-```
-
-For linking with tcmalloc:
-
-```
-$ env LD_PRELOAD={directory to libtcmalloc.so} make cpp
-```
-
-### Python:
-
-We have three versions of python protobuf implementation: pure python, cpp
-reflection and cpp generated code. To run these version benchmark, you need to:
-
-#### Pure Python:
-
-```
-$ make python-pure-python
-```
-
-#### CPP reflection:
-
-```
-$ make python-cpp-reflection
-```
-
-#### CPP generated code:
-
-```
-$ make python-cpp-generated-code
-```
-
-### Go
-```
-$ make go
-```
-
-
-### PHP
-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
-```
-#### PHP with c extension
-```
-$ make php_c
-```
-
-### Node.js
-```
-$ make js
-```
-
-To run a specific dataset or run with specific options:
-
-### Java:
-
-```
-$ make java-benchmark
-$ ./java-benchmark $(specific generated dataset file name) [$(caliper options)]
-```
-
-### CPP:
-
-```
-$ make cpp-benchmark
-$ ./cpp-benchmark $(specific generated dataset file name) [$(benchmark options)]
-```
-
-### Python:
-
-For Python benchmark we have `--json` for outputting the json result
-
-#### Pure Python:
-
-```
-$ make python-pure-python-benchmark
-$ ./python-pure-python-benchmark [--json] $(specific generated dataset file name)
-```
-
-#### CPP reflection:
-
-```
-$ make python-cpp-reflection-benchmark
-$ ./python-cpp-reflection-benchmark [--json] $(specific generated dataset file name)
-```
-
-#### CPP generated code:
-
-```
-$ make python-cpp-generated-code-benchmark
-$ ./python-cpp-generated-code-benchmark [--json] $(specific generated dataset file name)
-```
-
-### Go:
-```
-$ make go-benchmark
-$ ./go-benchmark $(specific generated dataset file name) [go testing options]
-```
-
-### PHP
-#### Pure PHP
-```
-$ make php-benchmark
-$ ./php-benchmark $(specific generated dataset file name)
-```
-#### PHP with c extension
-```
-$ make php-c-benchmark
-$ ./php-c-benchmark $(specific generated dataset file name)
-```
-
-### Node.js
-```
-$ make js-benchmark
-$ ./js-benchmark $(specific generated dataset file name)
-```
-
-### C#
-From `csharp/src/Google.Protobuf.Benchmarks`, run:
-
-```
-$ dotnet run -c Release
-```
-
-We intend to add support for this within the makefile in due course.
-
-## Benchmark datasets
-
-Each data set is in the format of benchmarks.proto:
-
-1. name is the benchmark dataset's name.
-2. message_name is the benchmark's message type full name (including package and message name)
-3. payload is the list of raw data.
-
-The schema for the datasets is described in `benchmarks.proto`.
-
-Benchmark likely want to run several benchmarks against each data set (parse,
-serialize, possibly JSON, possibly using different APIs, etc).
-
-We would like to add more data sets.  In general we will favor data sets
-that make the overall suite diverse without being too large or having
-too many similar tests.  Ideally everyone can run through the entire
-suite without the test run getting too long.
diff --git a/benchmarks/__init__.py b/benchmarks/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/benchmarks/__init__.py
+++ /dev/null
diff --git a/benchmarks/benchmarks.proto b/benchmarks/benchmarks.proto
deleted file mode 100644
index 51c0b54..0000000
--- a/benchmarks/benchmarks.proto
+++ /dev/null
@@ -1,63 +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 = "proto3";
-package benchmarks;
-option java_package = "com.google.protobuf.benchmarks";
-
-message BenchmarkDataset {
-  // Name of the benchmark dataset.  This should be unique across all datasets.
-  // Should only contain word characters: [a-zA-Z0-9_]
-  string name = 1;
-
-  // Fully-qualified name of the protobuf message for this dataset.
-  // It will be one of the messages defined benchmark_messages_proto2.proto
-  // or benchmark_messages_proto3.proto.
-  //
-  // Implementations that do not support reflection can implement this with
-  // an explicit "if/else" chain that lists every known message defined
-  // in those files.
-  string message_name = 2;
-
-  // The payload(s) for this dataset.  They should be parsed or serialized
-  // in sequence, in a loop, ie.
-  //
-  //  while (!benchmarkDone) {  // Benchmark runner decides when to exit.
-  //    for (i = 0; i < benchmark.payload.length; i++) {
-  //      parse(benchmark.payload[i])
-  //    }
-  //  }
-  //
-  // This is intended to let datasets include a variety of data to provide
-  // potentially more realistic results than just parsing the same message
-  // over and over.  A single message parsed repeatedly could yield unusually
-  // good branch prediction performance.
-  repeated bytes payload = 3;
-}
diff --git a/benchmarks/cpp/BUILD.bazel b/benchmarks/cpp/BUILD.bazel
deleted file mode 100644
index 7a3d3ba..0000000
--- a/benchmarks/cpp/BUILD.bazel
+++ /dev/null
@@ -1,26 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_binary")
-load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
-
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = [
-        "BUILD.bazel",
-        "cpp_benchmark.cc",
-    ],
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//benchmarks:__pkg__"],
-)
diff --git a/benchmarks/cpp/cpp_benchmark.cc b/benchmarks/cpp/cpp_benchmark.cc
deleted file mode 100644
index 036d234..0000000
--- a/benchmarks/cpp/cpp_benchmark.cc
+++ /dev/null
@@ -1,254 +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 <fstream>
-#include <iostream>
-#include "benchmark/benchmark.h"
-#include "benchmarks.pb.h"
-#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h"
-#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h"
-#include "datasets/google_message2/benchmark_message2.pb.h"
-#include "datasets/google_message3/benchmark_message3.pb.h"
-#include "datasets/google_message4/benchmark_message4.pb.h"
-
-
-#define PREFIX "dataset."
-#define SUFFIX ".pb"
-
-using benchmarks::BenchmarkDataset;
-using google::protobuf::Arena;
-using google::protobuf::Descriptor;
-using google::protobuf::DescriptorPool;
-using google::protobuf::Message;
-using google::protobuf::MessageFactory;
-
-class Fixture : public benchmark::Fixture {
- public:
-  Fixture(const BenchmarkDataset& dataset, const std::string& suffix) {
-    for (int i = 0; i < dataset.payload_size(); i++) {
-      payloads_.push_back(dataset.payload(i));
-    }
-
-    const Descriptor* d =
-        DescriptorPool::generated_pool()->FindMessageTypeByName(
-            dataset.message_name());
-
-    if (!d) {
-      std::cerr << "Couldn't find message named '" << dataset.message_name()
-                << "\n";
-    }
-
-    prototype_ = MessageFactory::generated_factory()->GetPrototype(d);
-    SetName((dataset.name() + suffix).c_str());
-  }
-
- protected:
-  std::vector<std::string> payloads_;
-  const Message* prototype_;
-};
-
-class WrappingCounter {
- public:
-  WrappingCounter(size_t limit) : value_(0), limit_(limit) {}
-
-  size_t Next() {
-    size_t ret = value_;
-    if (++value_ == limit_) {
-      value_ = 0;
-    }
-    return ret;
-  }
-
- private:
-  size_t value_;
-  size_t limit_;
-};
-
-template <class T>
-class ParseNewFixture : public Fixture {
- public:
-  ParseNewFixture(const BenchmarkDataset& dataset)
-      : Fixture(dataset, "_parse_new") {}
-
-  virtual void BenchmarkCase(benchmark::State& state) {
-    WrappingCounter i(payloads_.size());
-    size_t total = 0;
-
-    while (state.KeepRunning()) {
-      T m;
-      const std::string& payload = payloads_[i.Next()];
-      total += payload.size();
-      m.ParseFromString(payload);
-    }
-
-    state.SetBytesProcessed(total);
-  }
-};
-
-template <class T>
-class ParseNewArenaFixture : public Fixture {
- public:
-  ParseNewArenaFixture(const BenchmarkDataset& dataset)
-      : Fixture(dataset, "_parse_newarena") {}
-
-  virtual void BenchmarkCase(benchmark::State& state) {
-    WrappingCounter i(payloads_.size());
-    size_t total = 0;
-    Arena arena;
-
-    while (state.KeepRunning()) {
-      arena.Reset();
-      Message* m = Arena::CreateMessage<T>(&arena);
-      const std::string& payload = payloads_[i.Next()];
-      total += payload.size();
-      m->ParseFromString(payload);
-    }
-
-    state.SetBytesProcessed(total);
-  }
-};
-
-template <class T>
-class ParseReuseFixture : public Fixture {
- public:
-  ParseReuseFixture(const BenchmarkDataset& dataset)
-      : Fixture(dataset, "_parse_reuse") {}
-
-  virtual void BenchmarkCase(benchmark::State& state) {
-    T m;
-    WrappingCounter i(payloads_.size());
-    size_t total = 0;
-
-    while (state.KeepRunning()) {
-      const std::string& payload = payloads_[i.Next()];
-      total += payload.size();
-      m.ParseFromString(payload);
-    }
-
-    state.SetBytesProcessed(total);
-  }
-};
-
-template <class T>
-class SerializeFixture : public Fixture {
- public:
-  SerializeFixture(const BenchmarkDataset& dataset)
-      : Fixture(dataset, "_serialize") {
-    for (size_t i = 0; i < payloads_.size(); i++) {
-      message_.push_back(new T);
-      message_.back()->ParseFromString(payloads_[i]);
-    }
-  }
-
-  ~SerializeFixture() {
-    for (size_t i = 0; i < message_.size(); i++) {
-      delete message_[i];
-    }
-  }
-
-  virtual void BenchmarkCase(benchmark::State& state) {
-    size_t total = 0;
-    std::string str;
-    WrappingCounter i(payloads_.size());
-
-    while (state.KeepRunning()) {
-      str.clear();
-      message_[i.Next()]->SerializeToString(&str);
-      total += str.size();
-    }
-
-    state.SetBytesProcessed(total);
-  }
-
- private:
-  std::vector<T*> message_;
-};
-
-std::string ReadFile(const std::string& name) {
-  std::ifstream file(name.c_str());
-  GOOGLE_CHECK(file.is_open()) << "Couldn't find file '" << name <<
-                                  "', please make sure you are running "
-                                  "this command from the benchmarks/ "
-                                  "directory.\n";
-  return std::string((std::istreambuf_iterator<char>(file)),
-                     std::istreambuf_iterator<char>());
-}
-
-template <class T>
-void RegisterBenchmarksForType(const BenchmarkDataset& dataset) {
-  ::benchmark::internal::RegisterBenchmarkInternal(
-      new ParseNewFixture<T>(dataset));
-  ::benchmark::internal::RegisterBenchmarkInternal(
-      new ParseReuseFixture<T>(dataset));
-  ::benchmark::internal::RegisterBenchmarkInternal(
-      new ParseNewArenaFixture<T>(dataset));
-  ::benchmark::internal::RegisterBenchmarkInternal(
-      new SerializeFixture<T>(dataset));
-}
-
-void RegisterBenchmarks(const std::string& dataset_bytes) {
-  BenchmarkDataset dataset;
-  GOOGLE_CHECK(dataset.ParseFromString(dataset_bytes));
-
-  if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") {
-    RegisterBenchmarksForType<benchmarks::proto3::GoogleMessage1>(dataset);
-  } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") {
-    RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage1>(dataset);
-  } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") {
-    RegisterBenchmarksForType<benchmarks::proto2::GoogleMessage2>(dataset);
-  } else if (dataset.message_name() ==
-      "benchmarks.google_message3.GoogleMessage3") {
-    RegisterBenchmarksForType
-    <benchmarks::google_message3::GoogleMessage3>(dataset);
-  } else if (dataset.message_name() ==
-      "benchmarks.google_message4.GoogleMessage4") {
-    RegisterBenchmarksForType
-    <benchmarks::google_message4::GoogleMessage4>(dataset);
-  } else {
-    std::cerr << "Unknown message type: " << dataset.message_name();
-    exit(1);
-  }
-}
-
-int main(int argc, char *argv[]) {
-  ::benchmark::Initialize(&argc, argv);
-  if (argc == 1) {
-    std::cerr << "Usage: ./cpp-benchmark <input data>" << std::endl;
-    std::cerr << "input data is in the format of \"benchmarks.proto\""
-        << std::endl;
-    return 1;
-  } else {
-    for (int i = 1; i < argc; i++) {
-      RegisterBenchmarks(ReadFile(argv[i]));
-    }
-  }
-
-  ::benchmark::RunSpecifiedBenchmarks();
-}
diff --git a/benchmarks/datasets/BUILD.bazel b/benchmarks/datasets/BUILD.bazel
deleted file mode 100644
index 2a8b402..0000000
--- a/benchmarks/datasets/BUILD.bazel
+++ /dev/null
@@ -1,67 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_library")
-load("@rules_java//java:defs.bzl", "java_library")
-load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = ["BUILD.bazel"],
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//benchmarks:__pkg__"],
-)
diff --git a/benchmarks/datasets/google_message1/proto2/BUILD.bazel b/benchmarks/datasets/google_message1/proto2/BUILD.bazel
deleted file mode 100644
index 30caed5..0000000
--- a/benchmarks/datasets/google_message1/proto2/BUILD.bazel
+++ /dev/null
@@ -1,52 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_proto_library")
-load("@rules_java//java:defs.bzl", "java_proto_library")
-load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = glob(["*"]),
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//benchmarks:__pkg__"],
-)
diff --git a/benchmarks/datasets/google_message1/proto2/benchmark_message1_proto2.proto b/benchmarks/datasets/google_message1/proto2/benchmark_message1_proto2.proto
deleted file mode 100644
index e404b9f..0000000
--- a/benchmarks/datasets/google_message1/proto2/benchmark_message1_proto2.proto
+++ /dev/null
@@ -1,108 +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.
-
-// Benchmark messages for proto2.
-
-syntax = "proto2";
-
-package benchmarks.proto2;
-option java_package = "com.google.protobuf.benchmarks";
-
-// This is the default, but we specify it here explicitly.
-option optimize_for = SPEED;
-
-option cc_enable_arenas = true;
-
-message GoogleMessage1 {
-  required string field1 = 1;
-  optional string field9 = 9;
-  optional string field18 = 18;
-  optional bool field80 = 80 [default = false];
-  optional bool field81 = 81 [default = true];
-  required int32 field2 = 2;
-  required int32 field3 = 3;
-  optional int32 field280 = 280;
-  optional int32 field6 = 6 [default = 0];
-  optional int64 field22 = 22;
-  optional string field4 = 4;
-  repeated fixed64 field5 = 5;
-  optional bool field59 = 59 [default = false];
-  optional string field7 = 7;
-  optional int32 field16 = 16;
-  optional int32 field130 = 130 [default = 0];
-  optional bool field12 = 12 [default = true];
-  optional bool field17 = 17 [default = true];
-  optional bool field13 = 13 [default = true];
-  optional bool field14 = 14 [default = true];
-  optional int32 field104 = 104 [default = 0];
-  optional int32 field100 = 100 [default = 0];
-  optional int32 field101 = 101 [default = 0];
-  optional string field102 = 102;
-  optional string field103 = 103;
-  optional int32 field29 = 29 [default = 0];
-  optional bool field30 = 30 [default = false];
-  optional int32 field60 = 60 [default = -1];
-  optional int32 field271 = 271 [default = -1];
-  optional int32 field272 = 272 [default = -1];
-  optional int32 field150 = 150;
-  optional int32 field23 = 23 [default = 0];
-  optional bool field24 = 24 [default = false];
-  optional int32 field25 = 25 [default = 0];
-  optional GoogleMessage1SubMessage field15 = 15;
-  optional bool field78 = 78;
-  optional int32 field67 = 67 [default = 0];
-  optional int32 field68 = 68;
-  optional int32 field128 = 128 [default = 0];
-  optional string field129 = 129 [default = "xxxxxxxxxxxxxxxxxxxxx"];
-  optional int32 field131 = 131 [default = 0];
-}
-
-message GoogleMessage1SubMessage {
-  optional int32 field1 = 1 [default = 0];
-  optional int32 field2 = 2 [default = 0];
-  optional int32 field3 = 3 [default = 0];
-  optional string field15 = 15;
-  optional bool field12 = 12 [default = true];
-  optional int64 field13 = 13;
-  optional int64 field14 = 14;
-  optional int32 field16 = 16;
-  optional int32 field19 = 19 [default = 2];
-  optional bool field20 = 20 [default = true];
-  optional bool field28 = 28 [default = true];
-  optional fixed64 field21 = 21;
-  optional int32 field22 = 22;
-  optional bool field23 = 23 [default = false];
-  optional bool field206 = 206 [default = false];
-  optional fixed32 field203 = 203;
-  optional int32 field204 = 204;
-  optional string field205 = 205;
-  optional uint64 field207 = 207;
-  optional uint64 field300 = 300;
-}
diff --git a/benchmarks/datasets/google_message1/proto2/dataset.google_message1_proto2.pb b/benchmarks/datasets/google_message1/proto2/dataset.google_message1_proto2.pb
deleted file mode 100644
index f6fe784..0000000
--- a/benchmarks/datasets/google_message1/proto2/dataset.google_message1_proto2.pb
+++ /dev/null
Binary files differ
diff --git a/benchmarks/datasets/google_message1/proto3/BUILD.bazel b/benchmarks/datasets/google_message1/proto3/BUILD.bazel
deleted file mode 100644
index 0dc59d1..0000000
--- a/benchmarks/datasets/google_message1/proto3/BUILD.bazel
+++ /dev/null
@@ -1,52 +0,0 @@
-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")
-load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
-
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = glob(["*"]),
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//benchmarks:__pkg__"],
-)
diff --git a/benchmarks/datasets/google_message1/proto3/benchmark_message1_proto3.proto b/benchmarks/datasets/google_message1/proto3/benchmark_message1_proto3.proto
deleted file mode 100644
index 8aee2f6..0000000
--- a/benchmarks/datasets/google_message1/proto3/benchmark_message1_proto3.proto
+++ /dev/null
@@ -1,108 +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.
-
-// Benchmark messages for proto3.
-
-syntax = "proto3";
-
-package benchmarks.proto3;
-option java_package = "com.google.protobuf.benchmarks";
-
-// This is the default, but we specify it here explicitly.
-option optimize_for = SPEED;
-
-option cc_enable_arenas = true;
-
-message GoogleMessage1 {
-  string field1 = 1;
-  string field9 = 9;
-  string field18 = 18;
-  bool field80 = 80;
-  bool field81 = 81;
-  int32 field2 = 2;
-  int32 field3 = 3;
-  int32 field280 = 280;
-  int32 field6 = 6;
-  int64 field22 = 22;
-  string field4 = 4;
-  repeated fixed64 field5 = 5;
-  bool field59 = 59;
-  string field7 = 7;
-  int32 field16 = 16;
-  int32 field130 = 130;
-  bool field12 = 12;
-  bool field17 = 17;
-  bool field13 = 13;
-  bool field14 = 14;
-  int32 field104 = 104;
-  int32 field100 = 100;
-  int32 field101 = 101;
-  string field102 = 102;
-  string field103 = 103;
-  int32 field29 = 29;
-  bool field30 = 30;
-  int32 field60 = 60;
-  int32 field271 = 271;
-  int32 field272 = 272;
-  int32 field150 = 150;
-  int32 field23 = 23;
-  bool field24 = 24;
-  int32 field25 = 25;
-  GoogleMessage1SubMessage field15 = 15;
-  bool field78 = 78;
-  int32 field67 = 67;
-  int32 field68 = 68;
-  int32 field128 = 128;
-  string field129 = 129;
-  int32 field131 = 131;
-}
-
-message GoogleMessage1SubMessage {
-  int32 field1 = 1;
-  int32 field2 = 2;
-  int32 field3 = 3;
-  string field15 = 15;
-  bool field12 = 12;
-  int64 field13 = 13;
-  int64 field14 = 14;
-  int32 field16 = 16;
-  int32 field19 = 19;
-  bool field20  = 20;
-  bool field28 = 28;
-  fixed64 field21 = 21;
-  int32 field22 = 22;
-  bool field23 = 23;
-  bool field206 = 206;
-  fixed32 field203 = 203;
-  int32 field204 = 204;
-  string field205 = 205;
-  uint64 field207 = 207;
-  uint64 field300 = 300;
-}
diff --git a/benchmarks/datasets/google_message1/proto3/dataset.google_message1_proto3.pb b/benchmarks/datasets/google_message1/proto3/dataset.google_message1_proto3.pb
deleted file mode 100644
index 4955bed..0000000
--- a/benchmarks/datasets/google_message1/proto3/dataset.google_message1_proto3.pb
+++ /dev/null
Binary files differ
diff --git a/benchmarks/datasets/google_message2/BUILD.bazel b/benchmarks/datasets/google_message2/BUILD.bazel
deleted file mode 100644
index f3d66a2..0000000
--- a/benchmarks/datasets/google_message2/BUILD.bazel
+++ /dev/null
@@ -1,52 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_proto_library")
-load("@rules_java//java:defs.bzl", "java_proto_library")
-load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = glob(["*"]),
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//benchmarks:__pkg__"],
-)
diff --git a/benchmarks/datasets/google_message2/benchmark_message2.proto b/benchmarks/datasets/google_message2/benchmark_message2.proto
deleted file mode 100644
index 500c5d6..0000000
--- a/benchmarks/datasets/google_message2/benchmark_message2.proto
+++ /dev/null
@@ -1,108 +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.
-
-// LINT: ALLOW_GROUPS
-
-// Benchmark messages for proto2.
-
-syntax = "proto2";
-
-package benchmarks.proto2;
-option java_package = "com.google.protobuf.benchmarks";
-
-// This is the default, but we specify it here explicitly.
-option optimize_for = SPEED;
-
-option cc_enable_arenas = true;
-
-message GoogleMessage2 {
-  optional string field1 = 1;
-  optional int64 field3 = 3;
-  optional int64 field4 = 4;
-  optional int64 field30 = 30;
-  optional bool field75 = 75 [default = false];
-  optional string field6 = 6;
-  optional bytes field2 = 2;
-  optional int32 field21 = 21 [default = 0];
-  optional int32 field71 = 71;
-  optional float field25 = 25;
-  optional int32 field109 = 109 [default = 0];
-  optional int32 field210 = 210 [default = 0];
-  optional int32 field211 = 211 [default = 0];
-  optional int32 field212 = 212 [default = 0];
-  optional int32 field213 = 213 [default = 0];
-  optional int32 field216 = 216 [default = 0];
-  optional int32 field217 = 217 [default = 0];
-  optional int32 field218 = 218 [default = 0];
-  optional int32 field220 = 220 [default = 0];
-  optional int32 field221 = 221 [default = 0];
-  optional float field222 = 222 [default = 0.0];
-  optional int32 field63 = 63;
-
-  repeated group Group1 = 10 {
-    required float field11 = 11;
-    optional float field26 = 26;
-    optional string field12 = 12;
-    optional string field13 = 13;
-    repeated string field14 = 14;
-    required uint64 field15 = 15;
-    optional int32 field5 = 5;
-    optional string field27 = 27;
-    optional int32 field28 = 28;
-    optional string field29 = 29;
-    optional string field16 = 16;
-    repeated string field22 = 22;
-    repeated int32 field73 = 73;
-    optional int32 field20 = 20 [default = 0];
-    optional string field24 = 24;
-    optional GoogleMessage2GroupedMessage field31 = 31;
-  }
-  repeated string field128 = 128;
-  optional int64 field131 = 131;
-  repeated string field127 = 127;
-  optional int32 field129 = 129;
-  repeated int64 field130 = 130;
-  optional bool field205 = 205 [default = false];
-  optional bool field206 = 206 [default = false];
-}
-
-message GoogleMessage2GroupedMessage {
-  optional float field1 = 1;
-  optional float field2 = 2;
-  optional float field3 = 3 [default = 0.0];
-  optional bool field4 = 4;
-  optional bool field5 = 5;
-  optional bool field6 = 6 [default = true];
-  optional bool field7 = 7 [default = false];
-  optional float field8 = 8;
-  optional bool field9 = 9;
-  optional float field10 = 10;
-  optional int64 field11 = 11;
-}
diff --git a/benchmarks/datasets/google_message2/dataset.google_message2.pb b/benchmarks/datasets/google_message2/dataset.google_message2.pb
deleted file mode 100644
index 3fa0e49..0000000
--- a/benchmarks/datasets/google_message2/dataset.google_message2.pb
+++ /dev/null
Binary files differ
diff --git a/benchmarks/datasets/google_message3/BUILD.bazel b/benchmarks/datasets/google_message3/BUILD.bazel
deleted file mode 100644
index a729e50..0000000
--- a/benchmarks/datasets/google_message3/BUILD.bazel
+++ /dev/null
@@ -1,58 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_proto_library")
-load("@rules_java//java:defs.bzl", "java_proto_library")
-load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = glob(["*"]),
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//benchmarks:__pkg__"],
-)
diff --git a/benchmarks/datasets/google_message3/benchmark_message3.proto b/benchmarks/datasets/google_message3/benchmark_message3.proto
deleted file mode 100644
index 82422f9..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3.proto
+++ /dev/null
@@ -1,566 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message3;
-
-import "datasets/google_message3/benchmark_message3_1.proto";
-import "datasets/google_message3/benchmark_message3_2.proto";
-import "datasets/google_message3/benchmark_message3_3.proto";
-import "datasets/google_message3/benchmark_message3_4.proto";
-import "datasets/google_message3/benchmark_message3_5.proto";
-import "datasets/google_message3/benchmark_message3_7.proto";
-import "datasets/google_message3/benchmark_message3_8.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message GoogleMessage3 {
-  optional .benchmarks.google_message3.Message37487 field37519 = 2;
-  optional .benchmarks.google_message3.Message36876 field37520 = 3;
-  optional .benchmarks.google_message3.Message13062 field37521 = 4;
-  optional .benchmarks.google_message3.Message952 field37522 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37523 = 6;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37524 = 7;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37525 = 8;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37526 = 9;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37527 = 10;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37528 = 11;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37529 = 12;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37530 = 13;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37531 = 14;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37532 = 15;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37533 = 16;
-}
-
-message Message1327 {
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field1369 = 1;
-  repeated .benchmarks.google_message3.Message1328 field1370 = 3;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field1371 = 5;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field1372 = 6;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message1327 field1373 = 23104162;
-  }
-}
-
-message Message3672 {
-  optional .benchmarks.google_message3.Enum3476 field3727 = 1;
-  optional int32 field3728 = 11;
-  optional int32 field3729 = 2;
-  repeated group Message3673 = 3 {
-    required .benchmarks.google_message3.Enum3476 field3738 = 4;
-    required int32 field3739 = 5;
-  }
-  repeated group Message3674 = 6 {
-    required .benchmarks.google_message3.Enum3476 field3740 = 7;
-    required int32 field3741 = 8;
-  }
-  optional bool field3732 = 9;
-  optional int32 field3733 = 10;
-  optional .benchmarks.google_message3.Enum3476 field3734 = 20;
-  optional int32 field3735 = 21;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field3736 = 50;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message3672 field3737 = 3144435;
-  }
-}
-
-message Message3804 {
-  required int64 field3818 = 1;
-  required bool field3819 = 2;
-  repeated .benchmarks.google_message3.Enum3805 field3820 = 4;
-  optional int32 field3821 = 5;
-  optional bool field3822 = 6;
-  optional int64 field3823 = 7;
-  optional .benchmarks.google_message3.Enum3783 field3824 = 8;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message3804 field3825 = 59241828;
-  }
-}
-
-message Message6849 {
-  repeated .benchmarks.google_message3.Message6850 field6910 = 1;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message6849 field6911 = 107558455;
-  }
-}
-
-message Message6866 {
-  repeated .benchmarks.google_message3.Message6863 field6973 = 1;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message6866 field6974 = 22259060;
-  }
-}
-
-message Message6870 {
-  repeated .benchmarks.google_message3.Message6871 field6991 = 1;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message6870 field6992 = 90034652;
-  }
-}
-
-message Message7651 {
-  optional string field7685 = 1;
-  optional int64 field7686 = 2;
-  optional int64 field7687 = 3;
-  optional int64 field7688 = 4;
-  optional int32 field7689 = 5;
-  optional int32 field7690 = 6;
-  optional int32 field7691 = 7;
-  optional int32 field7692 = 8;
-  optional int32 field7693 = 9;
-  optional int32 field7694 = 10;
-  optional int32 field7695 = 11;
-  optional int32 field7696 = 12;
-  optional int32 field7697 = 13;
-  optional int32 field7698 = 14;
-  optional int32 field7699 = 15;
-  optional int32 field7700 = 16;
-  optional int32 field7701 = 17;
-  optional int32 field7702 = 18;
-  optional bool field7703 = 19;
-  repeated int32 field7704 = 20;
-  repeated int32 field7705 = 21;
-  repeated string field7706 = 22;
-  repeated string field7707 = 23;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field7708 = 24;
-  optional int32 field7709 = 25;
-  optional int32 field7710 = 26;
-  optional int32 field7711 = 27;
-  optional int32 field7712 = 43;
-  optional int32 field7713 = 28;
-  optional int32 field7714 = 29;
-  repeated .benchmarks.google_message3.Message7547 field7715 = 30;
-  repeated .benchmarks.google_message3.Message7547 field7716 = 31;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field7717 = 32;
-  repeated string field7718 = 33;
-  repeated string field7719 = 34;
-  repeated .benchmarks.google_message3.Message7648 field7720 = 35;
-  optional bool field7721 = 36;
-  optional bool field7722 = 37;
-  optional bool field7723 = 38;
-  optional bool field7724 = 39;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field7725 = 40;
-  optional .benchmarks.google_message3.UnusedEnum field7726 = 41;
-  optional .benchmarks.google_message3.Enum7654 field7727 = 42;
-  optional string field7728 = 44;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field7729 = 45;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message7651 field7730 = 55876009;
-  }
-}
-
-message Message7864 {
-  optional string field7866 = 1;
-  optional string field7867 = 2;
-  repeated .benchmarks.google_message3.Message7865 field7868 = 5;
-  repeated .benchmarks.google_message3.Message7865 field7869 = 6;
-  repeated .benchmarks.google_message3.Message7865 field7870 = 7;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field7871 = 8;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message7864 field7872 = 44542730;
-  }
-}
-
-message Message7929 {
-  optional int64 field7942 = 1;
-  optional int64 field7943 = 4;
-  optional int64 field7944 = 5;
-  optional int64 field7945 = 12;
-  optional int64 field7946 = 13;
-  optional int64 field7947 = 18;
-  optional int64 field7948 = 6;
-  optional int64 field7949 = 7;
-  repeated .benchmarks.google_message3.Message7919 field7950 = 8;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field7951 = 20;
-  repeated .benchmarks.google_message3.Message7920 field7952 = 14;
-  repeated .benchmarks.google_message3.Message7921 field7953 = 15;
-  repeated .benchmarks.google_message3.Message7928 field7954 = 17;
-  optional int64 field7955 = 19;
-  optional bool field7956 = 2;
-  optional int64 field7957 = 3;
-  optional int64 field7958 = 9;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field7959 = 10;
-  repeated bytes field7960 = 11;
-  optional int64 field7961 = 16;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message7929 field7962 = 53392238;
-  }
-}
-
-message Message8508 {
-  repeated .benchmarks.google_message3.Message8511 field8517 = 8;
-  repeated .benchmarks.google_message3.Message8512 field8518 = 9;
-  repeated .benchmarks.google_message3.Message8513 field8519 = 11;
-  optional bool field8520 = 13;
-  optional .benchmarks.google_message3.Message8514 field8521 = 14;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8522 = 15;
-  repeated .benchmarks.google_message3.Message8515 field8523 = 16;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8524 = 17;
-  optional int64 field8525 = 1;
-  optional float field8526 = 2;
-  optional int64 field8527 = 3;
-  optional int64 field8528 = 4;
-  optional int32 field8529 = 5;
-  optional bytes field8530 = 6;
-  repeated bytes field8531 = 7;
-  optional bool field8532 = 10;
-  optional bytes field8533 = 12;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message8508 field8534 = 3811804;
-  }
-}
-
-message Message9122 {
-  optional float field9132 = 1;
-  optional float field9133 = 2;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message9122 field9134 = 120398939;
-  }
-}
-
-message Message10177 {
-  repeated .benchmarks.google_message3.Message10155 field10270 = 1;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message10177 field10271 = 26801105;
-  }
-}
-
-message Message10278 {
-  repeated int32 field10286 = 1 [packed = true];
-  repeated int32 field10287 = 2 [packed = true];
-  optional int32 field10288 = 3;
-  extend .benchmarks.google_message3.Message10155 {
-    optional .benchmarks.google_message3.Message10278 field10289 = 29374161;
-  }
-}
-
-message Message10323 {
-  repeated .benchmarks.google_message3.Message10320 field10360 = 1;
-  extend .benchmarks.google_message3.Message10155 {
-    optional .benchmarks.google_message3.Message10323 field10361 = 27922524;
-  }
-}
-
-message Message10324 {
-  repeated .benchmarks.google_message3.Message10322 field10362 = 1;
-  optional .benchmarks.google_message3.Message10321 field10363 = 2;
-  extend .benchmarks.google_message3.Message10155 {
-    optional .benchmarks.google_message3.Message10324 field10364 = 27832297;
-  }
-}
-
-message Message11990 {
-  repeated .benchmarks.google_message3.Message11988 field12030 = 1;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message11990 field12031 = 21265426;
-  }
-}
-
-message Message12691 {
-  optional string field12713 = 1;
-  optional int32 field12714 = 2;
-  optional .benchmarks.google_message3.Message12668 field12715 = 3;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message12691 field12716 = 28426536;
-  }
-}
-
-message Message12870 {
-  required int32 field12879 = 1;
-  optional int32 field12880 = 7;
-  required int32 field12881 = 2;
-  optional uint64 field12882 = 3;
-  optional string field12883 = 2001;
-  optional fixed64 field12884 = 4;
-  repeated fixed64 field12885 = 14;
-  optional int32 field12886 = 9;
-  optional int64 field12887 = 18;
-  repeated .benchmarks.google_message3.Message12870 field12888 = 8;
-  optional int32 field12889 = 5;
-  optional uint64 field12890 = 6;
-  optional int32 field12891 = 10;
-  optional int32 field12892 = 11;
-  optional double field12893 = 12;
-  optional .benchmarks.google_message3.Message12825 field12894 = 13;
-  optional double field12895 = 15;
-  optional string field12896 = 16;
-  optional .benchmarks.google_message3.Enum12871 field12897 = 17;
-  optional int32 field12898 = 19;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message12870 field12899 = 5447656;
-  }
-}
-
-message Message13154 {
-  required float field13164 = 1;
-  required float field13165 = 2;
-  extend .benchmarks.google_message3.Message13145 {
-    optional .benchmarks.google_message3.Message13154 field13166 = 47301086;
-  }
-}
-
-message Message16507 {
-  optional bool field16510 = 3;
-  optional bool field16511 = 4;
-  optional bool field16512 = 14;
-  repeated string field16513 = 5;
-  repeated string field16514 = 6;
-  optional string field16515 = 8;
-  repeated int32 field16516 = 9;
-  repeated int32 field16517 = 10;
-  optional int32 field16518 = 7;
-  optional string field16519 = 15;
-  repeated string field16520 = 11;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16521 = 27;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16522 = 22;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16523 = 28;
-  optional string field16524 = 18;
-  optional int32 field16525 = 19;
-  optional int32 field16526 = 20;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field16527 = 23;
-  optional bool field16528 = 24;
-  repeated string field16529 = 25;
-  optional double field16530 = 26;
-  optional .benchmarks.google_message3.Message16478 field16531 = 30;
-  optional bool field16532 = 31;
-  optional string field16533 = 32;
-  optional bool field16534 = 33;
-  optional bool field16535 = 35;
-  optional bool field16536 = 36;
-  optional bool field16537 = 37;
-  optional bool field16538 = 38;
-  optional bool field16539 = 39;
-  optional bool field16540 = 40;
-  repeated string field16541 = 41;
-  extensions 21 to 21;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message16507 field16542 = 5569941;
-  }
-}
-
-message Message16564 {
-  repeated .benchmarks.google_message3.Message16552 field16568 = 1;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message16564 field16569 = 25830030;
-  }
-}
-
-message Message16661 {
-  repeated .benchmarks.google_message3.Message16660 field16671 = 1;
-  repeated uint64 field16672 = 2;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message16661 field16673 = 31274398;
-  }
-}
-
-message Message16746 {
-  repeated .benchmarks.google_message3.Message16727 field16806 = 1;
-  optional bool field16807 = 2;
-  optional bool field16808 = 3;
-  repeated .benchmarks.google_message3.Message16725 field16809 = 4;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message16746 field16810 = 28406765;
-  }
-}
-
-message Message17786 {
-  repeated group Message17787 = 1 {
-    required int32 field18177 = 2;
-    required int32 field18178 = 3;
-    optional .benchmarks.google_message3.Message17783 field18179 = 4;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18180 = 5;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18181 = 6;
-    repeated .benchmarks.google_message3.UnusedEmptyMessage field18182 = 8;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18183 = 9;
-    optional .benchmarks.google_message3.Message17726 field18184 = 10;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18185 = 11;
-    optional .benchmarks.google_message3.Message16945 field18186 = 102;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18187 = 12;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18188 = 13;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18189 = 7;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18190 = 100;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18191 = 101;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18192 = 14;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18193 = 19;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18194 = 22;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18195 = 24;
-    optional .benchmarks.google_message3.Enum16925 field18196 = 21;
-    optional bool field18197 = 18;
-    repeated .benchmarks.google_message3.UnusedEnum field18198 = 23;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18199 = 15;
-    optional string field18200 = 16;
-    optional string field18201 = 17;
-    optional bool field18202 = 99;
-  }
-  repeated .benchmarks.google_message3.Message17782 field18175 = 20;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message17786 field18176 = 11823055;
-  }
-}
-
-message Message22857 {
-  repeated .benchmarks.google_message3.Message22853 field22874 = 1;
-  extend .benchmarks.google_message3.Message10155 {
-    optional .benchmarks.google_message3.Message22857 field22875 = 67799715;
-  }
-}
-
-message Message24404 {
-  repeated group Message24405 = 1 {
-    required int32 field24686 = 2;
-    required int32 field24687 = 3;
-    optional .benchmarks.google_message3.Message24317 field24688 = 4;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24689 = 5;
-    optional .benchmarks.google_message3.Message24376 field24690 = 6;
-    optional .benchmarks.google_message3.Message24345 field24691 = 7;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24692 = 8;
-    optional .benchmarks.google_message3.Message24379 field24693 = 9;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24694 = 10;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24695 = 11;
-    optional .benchmarks.google_message3.Message24391 field24696 = 12;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24697 = 13;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24698 = 14;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24699 = 22;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24700 = 23;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24701 = 25;
-    optional .benchmarks.google_message3.Enum16925 field24702 = 18;
-    optional float field24703 = 20;
-    optional bool field24704 = 19;
-    repeated .benchmarks.google_message3.Enum16891 field24705 = 24;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field24706 = 15;
-    optional string field24707 = 16;
-    optional string field24708 = 17;
-    optional float field24709 = 21;
-    optional bool field24710 = 26;
-    optional .benchmarks.google_message3.UnusedEnum field24711 = 27;
-    optional bool field24712 = 28;
-    optional .benchmarks.google_message3.UnusedEnum field24713 = 29;
-    optional bool field24714 = 31;
-    optional bool field24715 = 99;
-    optional int64 field24716 = 32;
-  }
-  optional .benchmarks.google_message3.Message24403 field24684 = 30;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message24404 field24685 = 9129287;
-  }
-}
-
-message Message27300 {
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field27302 = 1;
-  optional string field27303 = 2;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message27300 field27304 = 24956467;
-  }
-}
-
-message Message27453 {
-  optional string field27459 = 15;
-  repeated string field27460 = 1;
-  repeated float field27461 = 6;
-  repeated int32 field27462 = 27;
-  repeated int32 field27463 = 28;
-  repeated .benchmarks.google_message3.Message27454 field27464 = 24;
-  repeated string field27465 = 2;
-  repeated float field27466 = 7;
-  repeated string field27467 = 22;
-  repeated string field27468 = 23;
-  optional string field27469 = 26;
-  repeated .benchmarks.google_message3.Message27357 field27470 = 8;
-  optional .benchmarks.google_message3.Message27360 field27471 = 16;
-  optional string field27472 = 25;
-  optional string field27473 = 11;
-  optional bool field27474 = 13;
-  optional bool field27475 = 14;
-  optional bool field27476 = 17;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field27477 = 12;
-  optional bool field27478 = 34268945;
-  optional bool field27479 = 20;
-  optional string field27480 = 21;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field27481 = 10;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message27453 field27482 = 8086204;
-  }
-}
-
-extend .benchmarks.google_message3.Message16945 {
-  optional string field17026 = 472;
-  repeated string field17027 = 818;
-  optional .benchmarks.google_message3.Message0 field17031 = 215;
-  repeated .benchmarks.google_message3.Message0 field17032 = 292;
-  repeated .benchmarks.google_message3.Message0 field17038 = 234;
-  repeated .benchmarks.google_message3.Message0 field17039 = 235;
-  optional .benchmarks.google_message3.Message0 field17042 = 246;
-  optional string field17043 = 224;
-  optional string field17044 = 225;
-  repeated string field17048 = 63;
-  repeated string field17049 = 64;
-  repeated .benchmarks.google_message3.Message0 field17052 = 233;
-  repeated .benchmarks.google_message3.Message0 field17053 = 66;
-  repeated string field17056 = 275;
-  optional string field17057 = 226;
-  repeated .benchmarks.google_message3.Message0 field17060 = 27;
-  repeated string field17073 = 75;
-  repeated .benchmarks.google_message3.Message0 field17076 = 77;
-  repeated string field17078 = 296;
-  repeated .benchmarks.google_message3.Message0 field17082 = 160;
-  repeated .benchmarks.google_message3.Message0 field17091 = 585;
-  repeated .benchmarks.google_message3.Message0 field17098 = 987;
-  repeated .benchmarks.google_message3.Message0 field17101 = 157;
-  repeated string field17102 = 158;
-  repeated string field17107 = 166;
-  repeated string field17133 = 567;
-  repeated string field17134 = 572;
-  repeated string field17160 = 49;
-  repeated string field17168 = 32;
-  repeated string field17170 = 34;
-  repeated .benchmarks.google_message3.Message0 field17172 = 509;
-  repeated string field17174 = 39;
-  repeated .benchmarks.google_message3.Message0 field17175 = 40;
-  repeated .benchmarks.google_message3.Message0 field17178 = 511;
-  repeated .benchmarks.google_message3.Message0 field17185 = 50;
-  repeated int32 field17207 = 1081;
-  repeated .benchmarks.google_message3.Message0 field17238 = 184;
-  repeated .benchmarks.google_message3.Message0 field17289 = 177;
-  repeated .benchmarks.google_message3.Message0 field17290 = 178;
-  repeated .benchmarks.google_message3.Message0 field17296 = 474;
-  repeated string field17298 = 44;
-  repeated .benchmarks.google_message3.Message0 field17301 = 47;
-  optional .benchmarks.google_message3.Message0 field17412 = 21;
-  repeated .benchmarks.google_message3.Message0 field17438 = 132;
-  repeated .benchmarks.google_message3.Message0 field17458 = 512;
-  repeated string field17460 = 560;
-  repeated string field17466 = 552;
-  repeated .benchmarks.google_message3.Message0 field17617 = 1080;
-  repeated int32 field17618 = 1084;
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_1.proto b/benchmarks/datasets/google_message3/benchmark_message3_1.proto
deleted file mode 100644
index 1ee5c9e..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_1.proto
+++ /dev/null
@@ -1,1298 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message3;
-
-import "datasets/google_message3/benchmark_message3_2.proto";
-import "datasets/google_message3/benchmark_message3_3.proto";
-import "datasets/google_message3/benchmark_message3_5.proto";
-import "datasets/google_message3/benchmark_message3_7.proto";
-import "datasets/google_message3/benchmark_message3_8.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message34390 {
-  repeated .benchmarks.google_message3.Message34387 field34452 = 1;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message34390 field34453 = 92144610;
-  }
-}
-
-message Message34624 {
-  optional .benchmarks.google_message3.Message34621 field34683 = 1;
-  optional .benchmarks.google_message3.Message34621 field34684 = 2;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message34624 field34685 = 18178548;
-  }
-}
-
-message Message34791 {
-  optional fixed64 field34793 = 1;
-  repeated group Message34792 = 2 {
-    required string field34808 = 3;
-    optional string field34809 = 4;
-  }
-  optional int32 field34795 = 5;
-  optional int32 field34796 = 6;
-  optional int32 field34797 = 7;
-  optional int32 field34798 = 8;
-  optional int32 field34799 = 9;
-  optional int32 field34800 = 10;
-  optional bool field34801 = 11;
-  optional float field34802 = 12;
-  optional int32 field34803 = 13;
-  optional string field34804 = 14;
-  optional int64 field34805 = 15;
-  repeated fixed64 field34806 = 17 [packed = true];
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message34791 field34807 = 6330340;
-  }
-}
-
-message Message35483 {
-  optional int32 field35499 = 1;
-  optional string field35500 = 2;
-  optional string field35501 = 3;
-  optional string field35502 = 4;
-  repeated .benchmarks.google_message3.Message35476 field35503 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field35504 = 6;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message35483 field35505 = 7913554;
-  }
-}
-
-message Message35807 {
-  optional int32 field35810 = 1;
-  optional int32 field35811 = 2;
-  optional int32 field35812 = 3;
-  optional int32 field35813 = 4;
-  optional int32 field35814 = 5;
-  optional int32 field35815 = 6;
-  optional int32 field35816 = 7;
-  optional int32 field35817 = 8;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message35807 field35818 = 3803299;
-  }
-}
-
-message Message37487 {
-  optional bytes field37501 = 2;
-  optional bool field37502 = 3;
-}
-
-message Message13062 {
-  optional int64 field13075 = 1;
-  optional string field13076 = 2;
-  optional int32 field13077 = 3;
-  optional string field13078 = 4;
-  optional int32 field13079 = 5;
-}
-
-message Message952 {
-  repeated .benchmarks.google_message3.Message949 field963 = 1;
-}
-
-message Message36876 {
-  optional .benchmarks.google_message3.Message2356 field36980 = 1;
-  repeated group Message36877 = 111 {
-    required string field37044 = 112;
-    optional int32 field37045 = 113;
-    optional bytes field37046 = 114;
-    optional int32 field37047 = 115;
-    optional int32 field37048 = 157;
-  }
-  repeated group Message36878 = 168 {}
-  repeated group Message36879 = 55 {
-    required string field37050 = 56;
-    optional int32 field37051 = 69;
-  }
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field36984 = 78;
-  optional group Message36880 = 137 {}
-  optional uint64 field36986 = 59;
-  optional bytes field36987 = 121;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field36988 = 2;
-  optional .benchmarks.google_message3.Message7029 field36989 = 118;
-  optional .benchmarks.google_message3.Message35573 field36990 = 11;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field36991 = 21;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field36992 = 22;
-  optional float field36993 = 13;
-  optional int32 field36994 = 20;
-  optional bool field36995 = 51;
-  optional bool field36996 = 57;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field36997 = 100;
-  optional int32 field36998 = 47;
-  optional int32 field36999 = 48;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37000 = 68;
-  repeated group Message36881 = 23 {}
-  optional .benchmarks.google_message3.Message4144 field37002 = 125;
-  repeated group Message36882 = 35 {}
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37004 = 49;
-  optional .benchmarks.google_message3.Message18921 field37005 = 52;
-  optional .benchmarks.google_message3.Message36858 field37006 = 46;
-  optional .benchmarks.google_message3.Message18831 field37007 = 54;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37008 = 58;
-  optional .benchmarks.google_message3.Message18283 field37009 = 10;
-  optional string field37010 = 44;
-  optional string field37011 = 103;
-  optional .benchmarks.google_message3.Message0 field37012 = 43;
-  optional .benchmarks.google_message3.Message0 field37013 = 143;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37014 = 53;
-  optional .benchmarks.google_message3.Message36869 field37015 = 15;
-  optional group Message36883 = 3 {}
-  repeated group Message36884 = 16 {}
-  repeated group Message36885 = 27 {}
-  optional group Message36886 = 32 {}
-  repeated .benchmarks.google_message3.UnusedEnum field37020 = 71;
-  repeated int32 field37021 = 70;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37022 = 66;
-  optional .benchmarks.google_message3.Message13090 field37023 = 67;
-  optional group Message36887 = 62 {}
-  repeated .benchmarks.google_message3.Message10155 field37025 = 50;
-  repeated .benchmarks.google_message3.Message11874 field37026 = 151;
-  optional string field37027 = 12;
-  optional int64 field37028 = 72;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37029 = 73;
-  optional .benchmarks.google_message3.Message35546 field37030 = 108;
-  optional group Message36888 = 74 {
-    optional uint64 field37089 = 75;
-    optional bool field37090 = 76;
-    optional uint64 field37091 = 165;
-    optional double field37092 = 166;
-    optional uint64 field37093 = 109;
-    optional bytes field37094 = 122;
-  }
-  repeated .benchmarks.google_message3.Message19255 field37032 = 104;
-  optional .benchmarks.google_message3.Message33968 field37033 = 105;
-  optional bool field37034 = 106;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field37035 = 107;
-  optional .benchmarks.google_message3.Message6644 field37036 = 110;
-  optional bytes field37037 = 133;
-  optional group Message36889 = 116 {
-    optional int64 field37095 = 117;
-    optional string field37096 = 145;
-    optional int32 field37097 = 123;
-    optional bool field37098 = 163;
-    optional int32 field37099 = 164;
-    optional int32 field37100 = 149;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field37101 = 129;
-    optional .benchmarks.google_message3.Message13174 field37102 = 124;
-    optional .benchmarks.google_message3.Message13169 field37103 = 128;
-    optional uint64 field37104 = 132;
-    repeated .benchmarks.google_message3.Enum36890 field37105 = 131;
-    optional bool field37106 = 134;
-    optional bool field37107 = 140;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field37108 = 135;
-    optional float field37109 = 136;
-    optional float field37110 = 156;
-    optional bool field37111 = 142;
-    optional int64 field37112 = 167;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field37113 = 146;
-    optional bool field37114 = 148;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field37115 = 154;
-    optional .benchmarks.google_message3.UnusedEnum field37116 = 158;
-    repeated .benchmarks.google_message3.UnusedEnum field37117 = 159;
-    optional int32 field37118 = 160;
-    repeated string field37119 = 161;
-  }
-  repeated group Message36910 = 119 {}
-  optional group Message36911 = 126 {
-    optional .benchmarks.google_message3.UnusedEmptyMessage field37121 = 127;
-    optional .benchmarks.google_message3.Message35538 field37122 = 130;
-    optional .benchmarks.google_message3.Message35540 field37123 = 144;
-    optional .benchmarks.google_message3.Message35542 field37124 = 150;
-  }
-  optional group Message36912 = 152 {
-    optional .benchmarks.google_message3.Message3901 field37125 = 153;
-    optional .benchmarks.google_message3.Message3901 field37126 = 162;
-  }
-  optional .benchmarks.google_message3.UnusedEmptyMessage field37042 = 155;
-}
-
-message Message1328 {}
-
-message Message6850 {}
-
-message Message6863 {
-  optional .benchmarks.google_message3.Enum6858 field6931 = 1;
-  optional .benchmarks.google_message3.Enum6858 field6932 = 2;
-  optional .benchmarks.google_message3.UnusedEnum field6933 = 36;
-  optional bool field6934 = 27;
-  optional .benchmarks.google_message3.Message6773 field6935 = 26;
-  optional int32 field6936 = 30;
-  optional int32 field6937 = 37;
-  optional .benchmarks.google_message3.Enum6815 field6938 = 31;
-  optional string field6939 = 3;
-  optional int32 field6940 = 4;
-  optional .benchmarks.google_message3.Enum6822 field6941 = 15;
-  optional bool field6942 = 10;
-  optional bool field6943 = 17;
-  optional float field6944 = 18;
-  optional float field6945 = 19;
-  optional int32 field6946 = 5;
-  optional int32 field6947 = 6;
-  optional bool field6948 = 7;
-  optional int32 field6949 = 12;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6950 = 8;
-  optional uint64 field6951 = 9;
-  optional string field6952 = 11;
-  optional bytes field6953 = 13;
-  optional int32 field6954 = 14;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6955 = 16;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6956 = 22;
-  optional .benchmarks.google_message3.Message3886 field6957 = 38;
-  optional string field6958 = 20;
-  optional uint32 field6959 = 21;
-  optional .benchmarks.google_message3.Message6743 field6960 = 23;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6961 = 29;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6962 = 33;
-  optional bool field6963 = 34;
-}
-
-message Message6871 {}
-
-message Message7547 {
-  required bytes field7549 = 1;
-  required int32 field7550 = 2;
-}
-
-message Message7648 {
-  optional string field7669 = 1;
-  optional int32 field7670 = 2;
-  optional int32 field7671 = 3;
-  optional int32 field7672 = 4;
-  optional int32 field7673 = 5;
-  optional int32 field7674 = 6;
-  optional float field7675 = 7;
-  optional bool field7676 = 8;
-  optional bool field7677 = 9;
-  optional bool field7678 = 10;
-  optional bool field7679 = 11;
-  optional bool field7680 = 12;
-}
-
-message Message7865 {}
-
-message Message7928 {
-  optional string field7940 = 1;
-  optional int64 field7941 = 2;
-}
-
-message Message7919 {
-  optional fixed64 field7931 = 1;
-  optional int64 field7932 = 2;
-  optional bytes field7933 = 3;
-}
-
-message Message7920 {
-  optional int64 field7934 = 1;
-  optional int64 field7935 = 2;
-}
-
-message Message7921 {
-  optional int32 field7936 = 1;
-  optional int64 field7937 = 2;
-  optional float field7938 = 3;
-  optional .benchmarks.google_message3.UnusedEnum field7939 = 4;
-}
-
-message Message8511 {
-  optional .benchmarks.google_message3.Message8224 field8539 = 1;
-  optional string field8540 = 2;
-  optional bool field8541 = 3;
-  optional int64 field8542 = 4;
-  optional string field8543 = 5;
-}
-
-message Message8512 {
-  optional .benchmarks.google_message3.Message8301 field8544 = 1;
-  optional .benchmarks.google_message3.Message8302 field8545 = 2;
-  optional string field8546 = 3;
-  optional bool field8547 = 4;
-  optional int64 field8548 = 5;
-  optional string field8549 = 6;
-}
-
-message Message8513 {
-  repeated .benchmarks.google_message3.Message8392 field8550 = 1;
-  optional string field8551 = 2;
-  optional bool field8552 = 3;
-  optional string field8553 = 4;
-}
-
-message Message8514 {
-  optional string field8554 = 1;
-  optional int64 field8555 = 2;
-  optional bool field8556 = 3;
-  repeated .benchmarks.google_message3.Message8130 field8557 = 4;
-  optional string field8558 = 5;
-}
-
-message Message8515 {
-  optional .benchmarks.google_message3.Message8479 field8559 = 1;
-  optional .benchmarks.google_message3.Message8478 field8560 = 2;
-  optional string field8561 = 3;
-}
-
-message Message10320 {
-  optional .benchmarks.google_message3.Enum10335 field10347 = 1;
-  repeated .benchmarks.google_message3.Message10319 field10348 = 2;
-  optional int32 field10349 = 3;
-  optional int32 field10350 = 4;
-  optional int32 field10351 = 5;
-  optional int32 field10352 = 6;
-  optional .benchmarks.google_message3.Enum10337 field10353 = 7;
-}
-
-message Message10321 {
-  optional int32 field10354 = 1;
-  optional int32 field10355 = 2;
-  optional uint64 field10356 = 3;
-}
-
-message Message10322 {
-  optional .benchmarks.google_message3.Message4016 field10357 = 1;
-  optional bool field10358 = 2;
-  optional bool field10359 = 3;
-}
-
-message Message11988 {
-  optional string field12021 = 1;
-  optional string field12022 = 2;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field12023 = 3;
-  optional .benchmarks.google_message3.Message10155 field12024 = 4;
-}
-
-message Message12668 {
-  repeated .benchmarks.google_message3.Message12669 field12677 = 1;
-  optional int32 field12678 = 2;
-  optional int32 field12679 = 3;
-  optional int32 field12680 = 4;
-}
-
-message Message12825 {
-  repeated .benchmarks.google_message3.Message12818 field12862 = 1;
-  optional int32 field12863 = 2;
-  optional .benchmarks.google_message3.Message12819 field12864 = 3;
-  optional .benchmarks.google_message3.Message12820 field12865 = 4;
-  optional int32 field12866 = 5;
-  repeated .benchmarks.google_message3.Message12821 field12867 = 6;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field12868 = 7;
-}
-
-message Message16478 {
-  repeated .benchmarks.google_message3.Message16479 field16481 = 1;
-  optional bool field16482 = 3;
-  optional int32 field16483 = 2;
-}
-
-message Message16552 {
-  optional fixed64 field16565 = 1;
-  optional int32 field16566 = 2;
-  optional .benchmarks.google_message3.Enum16553 field16567 = 3;
-}
-
-message Message16660 {
-  optional string field16668 = 1;
-  optional string field16669 = 2;
-  optional int32 field16670 = 3;
-}
-
-message Message16727 {
-  required .benchmarks.google_message3.Enum16728 field16782 = 1;
-  required string field16783 = 2;
-  optional string field16784 = 3;
-  optional int32 field16785 = 23;
-  required string field16786 = 4;
-  optional string field16787 = 5;
-  optional string field16788 = 6;
-  required .benchmarks.google_message3.Enum16732 field16789 = 7;
-  optional string field16790 = 8;
-  optional string field16791 = 9;
-  optional string field16792 = 10;
-  optional .benchmarks.google_message3.Enum16738 field16793 = 11;
-  optional int32 field16794 = 12;
-  repeated .benchmarks.google_message3.Message16722 field16795 = 13;
-  optional bool field16796 = 19;
-  optional bool field16797 = 24;
-  optional string field16798 = 14;
-  optional int64 field16799 = 15;
-  optional bool field16800 = 16;
-  optional string field16801 = 17;
-  optional .benchmarks.google_message3.Enum16698 field16802 = 18;
-  optional .benchmarks.google_message3.Message16724 field16803 = 20;
-  optional bool field16804 = 22;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field16805 = 25;
-  extensions 1000 to 536870911;
-}
-
-message Message16725 {
-  optional .benchmarks.google_message3.Enum16728 field16774 = 1;
-  repeated string field16775 = 2;
-}
-
-message Message17726 {
-  optional string field17801 = 1;
-  repeated string field17802 = 2;
-  optional string field17803 = 3;
-  repeated string field17804 = 4;
-  optional string field17805 = 5;
-  repeated string field17806 = 6;
-  optional string field17807 = 7;
-  optional string field17808 = 8;
-  repeated string field17809 = 15;
-  repeated string field17810 = 16;
-  repeated string field17811 = 17;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17812 = 18;
-  optional string field17813 = 9;
-  optional string field17814 = 10;
-  optional string field17815 = 11;
-  optional string field17816 = 12;
-  optional string field17817 = 13;
-  optional string field17818 = 14;
-  optional string field17819 = 19;
-  repeated .benchmarks.google_message3.Message17728 field17820 = 20;
-  repeated .benchmarks.google_message3.Message17728 field17821 = 21;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17822 = 30;
-}
-
-message Message17782 {
-  optional string field18153 = 1;
-  optional string field18154 = 2;
-}
-
-message Message17783 {
-  optional string field18155 = 1;
-  optional string field18156 = 2;
-  optional string field18157 = 3;
-  repeated group Message17784 = 4 {
-    optional string field18162 = 5;
-    optional string field18163 = 6;
-    optional string field18164 = 7;
-    repeated string field18165 = 8;
-    optional string field18166 = 17;
-    optional string field18167 = 18;
-  }
-  repeated group Message17785 = 9 {
-    optional string field18168 = 10;
-    optional string field18169 = 11;
-    optional .benchmarks.google_message3.Message17783 field18170 = 12;
-    optional string field18171 = 13;
-    optional string field18172 = 14;
-    repeated string field18173 = 15;
-  }
-  repeated string field18160 = 16;
-}
-
-message Message16945 {
-  optional string field16946 = 1;
-  optional string field16947 = 2;
-  optional string field16948 = 3;
-  optional string field16949 = 4;
-  optional string field16950 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field16951 = 872;
-  repeated .benchmarks.google_message3.Message0 field16952 = 16;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16953 = 54;
-  repeated .benchmarks.google_message3.Message0 field16954 = 55;
-  repeated string field16955 = 58;
-  repeated string field16956 = 59;
-  repeated string field16957 = 62;
-  repeated string field16958 = 37;
-  repeated string field16959 = 18;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16960 = 38;
-  repeated .benchmarks.google_message3.Message0 field16961 = 67;
-  repeated .benchmarks.google_message3.Message0 field16962 = 130;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16963 = 136;
-  repeated string field16964 = 138;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16965 = 156;
-  repeated string field16966 = 139;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16967 = 126;
-  repeated string field16968 = 152;
-  repeated .benchmarks.google_message3.Message0 field16969 = 183;
-  repeated string field16970 = 168;
-  repeated string field16971 = 212;
-  repeated string field16972 = 213;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16973 = 189;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16974 = 190;
-  repeated string field16975 = 191;
-  repeated string field16976 = 192;
-  repeated .benchmarks.google_message3.Message0 field16977 = 193;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16978 = 194;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16979 = 195;
-  repeated int32 field16980 = 196;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16981 = 95;
-  repeated string field16982 = 96;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16983 = 97;
-  repeated string field16984 = 1086;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16985 = 98;
-  repeated string field16986 = 99;
-  repeated string field16987 = 100;
-  repeated string field16988 = 48;
-  optional string field16989 = 22;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field16990 = 51;
-  repeated string field16991 = 81;
-  repeated string field16992 = 85;
-  repeated string field16993 = 169;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field16994 = 260;
-  optional int32 field16995 = 198;
-  optional int32 field16996 = 204;
-  optional string field16997 = 1087;
-  repeated string field16998 = 197;
-  repeated string field16999 = 206;
-  optional string field17000 = 211;
-  repeated string field17001 = 205;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17002 = 68;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17003 = 69;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17004 = 70;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17005 = 71;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17006 = 72;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17007 = 19;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17008 = 24;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field17009 = 23;
-  repeated .benchmarks.google_message3.Message0 field17010 = 131;
-  repeated string field17011 = 133;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17012 = 142;
-  repeated string field17013 = 143;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field17014 = 153;
-  repeated .benchmarks.google_message3.Message0 field17015 = 170;
-  repeated string field17016 = 171;
-  repeated string field17017 = 172;
-  repeated string field17018 = 173;
-  repeated string field17019 = 174;
-  repeated string field17020 = 175;
-  repeated string field17021 = 186;
-  repeated string field17022 = 101;
-  repeated .benchmarks.google_message3.Message0 field17023 = 102;
-  repeated string field17024 = 274;
-  extensions 17 to 17;
-  extensions 21 to 21;
-  extensions 25 to 25;
-  extensions 27 to 27;
-  extensions 29 to 29;
-  extensions 30 to 30;
-  extensions 31 to 31;
-  extensions 32 to 32;
-  extensions 33 to 33;
-  extensions 34 to 34;
-  extensions 35 to 35;
-  extensions 36 to 36;
-  extensions 39 to 39;
-  extensions 40 to 40;
-  extensions 41 to 41;
-  extensions 42 to 42;
-  extensions 43 to 43;
-  extensions 44 to 44;
-  extensions 45 to 45;
-  extensions 46 to 46;
-  extensions 47 to 47;
-  extensions 49 to 49;
-  extensions 50 to 50;
-  extensions 52 to 52;
-  extensions 53 to 53;
-  extensions 56 to 56;
-  extensions 57 to 57;
-  extensions 60 to 60;
-  extensions 61 to 61;
-  extensions 63 to 63;
-  extensions 64 to 64;
-  extensions 65 to 65;
-  extensions 66 to 66;
-  extensions 73 to 73;
-  extensions 74 to 74;
-  extensions 75 to 75;
-  extensions 76 to 76;
-  extensions 77 to 77;
-  extensions 78 to 78;
-  extensions 79 to 79;
-  extensions 80 to 80;
-  extensions 82 to 82;
-  extensions 83 to 83;
-  extensions 84 to 84;
-  extensions 86 to 86;
-  extensions 87 to 87;
-  extensions 88 to 88;
-  extensions 89 to 89;
-  extensions 90 to 90;
-  extensions 91 to 91;
-  extensions 92 to 92;
-  extensions 93 to 93;
-  extensions 94 to 94;
-  extensions 103 to 103;
-  extensions 104 to 104;
-  extensions 105 to 105;
-  extensions 106 to 106;
-  extensions 107 to 107;
-  extensions 108 to 108;
-  extensions 109 to 109;
-  extensions 110 to 110;
-  extensions 111 to 111;
-  extensions 112 to 112;
-  extensions 113 to 113;
-  extensions 114 to 114;
-  extensions 115 to 115;
-  extensions 116 to 116;
-  extensions 117 to 117;
-  extensions 118 to 118;
-  extensions 119 to 119;
-  extensions 120 to 120;
-  extensions 121 to 121;
-  extensions 122 to 122;
-  extensions 123 to 123;
-  extensions 124 to 124;
-  extensions 125 to 125;
-  extensions 127 to 127;
-  extensions 128 to 128;
-  extensions 129 to 129;
-  extensions 132 to 132;
-  extensions 134 to 134;
-  extensions 135 to 135;
-  extensions 137 to 137;
-  extensions 140 to 140;
-  extensions 141 to 141;
-  extensions 144 to 144;
-  extensions 145 to 145;
-  extensions 146 to 146;
-  extensions 147 to 147;
-  extensions 148 to 148;
-  extensions 149 to 149;
-  extensions 150 to 150;
-  extensions 151 to 151;
-  extensions 154 to 154;
-  extensions 155 to 155;
-  extensions 157 to 157;
-  extensions 158 to 158;
-  extensions 159 to 159;
-  extensions 160 to 160;
-  extensions 161 to 161;
-  extensions 162 to 162;
-  extensions 163 to 163;
-  extensions 164 to 164;
-  extensions 165 to 165;
-  extensions 166 to 166;
-  extensions 167 to 167;
-  extensions 176 to 176;
-  extensions 177 to 177;
-  extensions 178 to 178;
-  extensions 179 to 179;
-  extensions 180 to 180;
-  extensions 181 to 181;
-  extensions 182 to 182;
-  extensions 184 to 184;
-  extensions 185 to 185;
-  extensions 187 to 187;
-  extensions 188 to 188;
-  extensions 199 to 199;
-  extensions 200 to 200;
-  extensions 201 to 201;
-  extensions 202 to 202;
-  extensions 203 to 203;
-  extensions 207 to 207;
-  extensions 208 to 208;
-  extensions 209 to 209;
-  extensions 210 to 210;
-  extensions 214 to 214;
-  extensions 215 to 215;
-  extensions 216 to 216;
-  extensions 217 to 217;
-  extensions 218 to 218;
-  extensions 219 to 219;
-  extensions 220 to 220;
-  extensions 221 to 221;
-  extensions 222 to 222;
-  extensions 223 to 223;
-  extensions 224 to 224;
-  extensions 225 to 225;
-  extensions 226 to 226;
-  extensions 227 to 227;
-  extensions 228 to 228;
-  extensions 229 to 229;
-  extensions 230 to 230;
-  extensions 231 to 231;
-  extensions 232 to 232;
-  extensions 233 to 233;
-  extensions 234 to 234;
-  extensions 235 to 235;
-  extensions 236 to 236;
-  extensions 237 to 237;
-  extensions 238 to 238;
-  extensions 239 to 239;
-  extensions 240 to 240;
-  extensions 241 to 241;
-  extensions 242 to 242;
-  extensions 243 to 243;
-  extensions 244 to 244;
-  extensions 245 to 245;
-  extensions 246 to 246;
-  extensions 247 to 247;
-  extensions 248 to 248;
-  extensions 249 to 249;
-  extensions 250 to 250;
-  extensions 251 to 251;
-  extensions 252 to 252;
-  extensions 253 to 253;
-  extensions 254 to 254;
-  extensions 255 to 255;
-  extensions 256 to 256;
-  extensions 257 to 257;
-  extensions 258 to 258;
-  extensions 259 to 259;
-  extensions 261 to 261;
-  extensions 262 to 262;
-  extensions 263 to 263;
-  extensions 264 to 264;
-  extensions 265 to 265;
-  extensions 266 to 266;
-  extensions 267 to 267;
-  extensions 268 to 268;
-  extensions 269 to 269;
-  extensions 270 to 270;
-  extensions 271 to 271;
-  extensions 272 to 272;
-  extensions 273 to 273;
-  extensions 275 to 275;
-  extensions 276 to 276;
-  extensions 277 to 277;
-  extensions 278 to 278;
-  extensions 279 to 279;
-  extensions 280 to 280;
-  extensions 281 to 281;
-  extensions 282 to 282;
-  extensions 283 to 283;
-  extensions 284 to 284;
-  extensions 285 to 285;
-  extensions 286 to 286;
-  extensions 290 to 290;
-  extensions 291 to 291;
-  extensions 292 to 292;
-  extensions 293 to 293;
-  extensions 294 to 294;
-  extensions 295 to 295;
-  extensions 296 to 296;
-  extensions 297 to 297;
-  extensions 298 to 298;
-  extensions 299 to 299;
-  extensions 300 to 300;
-  extensions 301 to 301;
-  extensions 302 to 302;
-  extensions 303 to 303;
-  extensions 304 to 304;
-  extensions 305 to 305;
-  extensions 306 to 306;
-  extensions 307 to 307;
-  extensions 308 to 308;
-  extensions 309 to 309;
-  extensions 310 to 310;
-  extensions 311 to 311;
-  extensions 312 to 312;
-  extensions 313 to 313;
-  extensions 314 to 314;
-  extensions 315 to 315;
-  extensions 316 to 316;
-  extensions 317 to 317;
-  extensions 318 to 318;
-  extensions 319 to 319;
-  extensions 320 to 320;
-  extensions 321 to 321;
-  extensions 322 to 322;
-  extensions 323 to 323;
-  extensions 324 to 324;
-  extensions 325 to 325;
-  extensions 326 to 326;
-  extensions 327 to 327;
-  extensions 328 to 328;
-  extensions 329 to 329;
-  extensions 330 to 330;
-  extensions 331 to 331;
-  extensions 332 to 332;
-  extensions 333 to 333;
-  extensions 334 to 334;
-  extensions 335 to 335;
-  extensions 336 to 336;
-  extensions 337 to 337;
-  extensions 338 to 338;
-  extensions 339 to 339;
-  extensions 340 to 340;
-  extensions 341 to 341;
-  extensions 342 to 342;
-  extensions 343 to 343;
-  extensions 344 to 344;
-  extensions 345 to 345;
-  extensions 346 to 346;
-  extensions 347 to 347;
-  extensions 348 to 348;
-  extensions 349 to 349;
-  extensions 350 to 350;
-  extensions 351 to 351;
-  extensions 352 to 352;
-  extensions 353 to 353;
-  extensions 354 to 354;
-  extensions 355 to 355;
-  extensions 356 to 356;
-  extensions 357 to 357;
-  extensions 358 to 358;
-  extensions 359 to 359;
-  extensions 360 to 360;
-  extensions 361 to 361;
-  extensions 362 to 362;
-  extensions 363 to 363;
-  extensions 364 to 364;
-  extensions 365 to 365;
-  extensions 366 to 366;
-  extensions 367 to 367;
-  extensions 368 to 368;
-  extensions 369 to 369;
-  extensions 370 to 370;
-  extensions 371 to 371;
-  extensions 372 to 372;
-  extensions 373 to 373;
-  extensions 374 to 374;
-  extensions 375 to 375;
-  extensions 376 to 376;
-  extensions 377 to 377;
-  extensions 378 to 378;
-  extensions 379 to 379;
-  extensions 380 to 380;
-  extensions 381 to 381;
-  extensions 382 to 382;
-  extensions 383 to 383;
-  extensions 384 to 384;
-  extensions 385 to 385;
-  extensions 386 to 386;
-  extensions 387 to 387;
-  extensions 388 to 388;
-  extensions 389 to 389;
-  extensions 390 to 390;
-  extensions 391 to 391;
-  extensions 392 to 392;
-  extensions 393 to 393;
-  extensions 394 to 394;
-  extensions 395 to 395;
-  extensions 396 to 396;
-  extensions 397 to 397;
-  extensions 398 to 398;
-  extensions 399 to 399;
-  extensions 400 to 400;
-  extensions 401 to 401;
-  extensions 402 to 402;
-  extensions 403 to 403;
-  extensions 404 to 404;
-  extensions 405 to 405;
-  extensions 406 to 406;
-  extensions 407 to 407;
-  extensions 408 to 408;
-  extensions 409 to 409;
-  extensions 410 to 410;
-  extensions 411 to 411;
-  extensions 412 to 412;
-  extensions 413 to 413;
-  extensions 414 to 414;
-  extensions 415 to 415;
-  extensions 416 to 416;
-  extensions 417 to 417;
-  extensions 418 to 418;
-  extensions 419 to 419;
-  extensions 420 to 420;
-  extensions 421 to 421;
-  extensions 422 to 422;
-  extensions 423 to 423;
-  extensions 424 to 424;
-  extensions 425 to 425;
-  extensions 426 to 426;
-  extensions 427 to 427;
-  extensions 428 to 428;
-  extensions 429 to 429;
-  extensions 430 to 430;
-  extensions 431 to 431;
-  extensions 432 to 432;
-  extensions 433 to 433;
-  extensions 434 to 434;
-  extensions 435 to 435;
-  extensions 436 to 436;
-  extensions 437 to 437;
-  extensions 438 to 438;
-  extensions 439 to 439;
-  extensions 440 to 440;
-  extensions 441 to 441;
-  extensions 442 to 442;
-  extensions 443 to 443;
-  extensions 444 to 444;
-  extensions 445 to 445;
-  extensions 446 to 446;
-  extensions 447 to 447;
-  extensions 448 to 448;
-  extensions 449 to 449;
-  extensions 450 to 450;
-  extensions 451 to 451;
-  extensions 452 to 452;
-  extensions 453 to 453;
-  extensions 454 to 454;
-  extensions 455 to 455;
-  extensions 456 to 456;
-  extensions 457 to 457;
-  extensions 458 to 458;
-  extensions 459 to 459;
-  extensions 460 to 460;
-  extensions 461 to 461;
-  extensions 462 to 462;
-  extensions 463 to 463;
-  extensions 464 to 464;
-  extensions 465 to 465;
-  extensions 466 to 466;
-  extensions 467 to 467;
-  extensions 468 to 468;
-  extensions 469 to 469;
-  extensions 470 to 470;
-  extensions 471 to 471;
-  extensions 472 to 472;
-  extensions 473 to 473;
-  extensions 474 to 474;
-  extensions 509 to 509;
-  extensions 511 to 511;
-  extensions 512 to 512;
-  extensions 513 to 513;
-  extensions 514 to 514;
-  extensions 515 to 515;
-  extensions 516 to 516;
-  extensions 517 to 517;
-  extensions 518 to 518;
-  extensions 519 to 519;
-  extensions 520 to 520;
-  extensions 521 to 521;
-  extensions 522 to 522;
-  extensions 523 to 523;
-  extensions 524 to 524;
-  extensions 525 to 525;
-  extensions 526 to 526;
-  extensions 527 to 527;
-  extensions 528 to 528;
-  extensions 529 to 529;
-  extensions 530 to 530;
-  extensions 531 to 531;
-  extensions 532 to 532;
-  extensions 533 to 533;
-  extensions 534 to 534;
-  extensions 535 to 535;
-  extensions 536 to 536;
-  extensions 537 to 537;
-  extensions 538 to 538;
-  extensions 539 to 539;
-  extensions 540 to 540;
-  extensions 541 to 541;
-  extensions 542 to 542;
-  extensions 543 to 543;
-  extensions 544 to 544;
-  extensions 545 to 545;
-  extensions 546 to 546;
-  extensions 547 to 547;
-  extensions 548 to 548;
-  extensions 549 to 549;
-  extensions 550 to 550;
-  extensions 551 to 551;
-  extensions 552 to 552;
-  extensions 553 to 553;
-  extensions 554 to 554;
-  extensions 555 to 555;
-  extensions 556 to 556;
-  extensions 557 to 557;
-  extensions 558 to 558;
-  extensions 559 to 559;
-  extensions 560 to 560;
-  extensions 561 to 561;
-  extensions 562 to 562;
-  extensions 563 to 563;
-  extensions 564 to 564;
-  extensions 565 to 565;
-  extensions 566 to 566;
-  extensions 567 to 567;
-  extensions 568 to 568;
-  extensions 569 to 569;
-  extensions 570 to 570;
-  extensions 571 to 571;
-  extensions 572 to 572;
-  extensions 573 to 573;
-  extensions 574 to 574;
-  extensions 575 to 575;
-  extensions 576 to 576;
-  extensions 577 to 577;
-  extensions 578 to 578;
-  extensions 579 to 579;
-  extensions 580 to 580;
-  extensions 581 to 581;
-  extensions 582 to 582;
-  extensions 583 to 583;
-  extensions 584 to 584;
-  extensions 585 to 585;
-  extensions 586 to 586;
-  extensions 587 to 587;
-  extensions 588 to 588;
-  extensions 589 to 589;
-  extensions 590 to 590;
-  extensions 604 to 604;
-  extensions 605 to 605;
-  extensions 606 to 606;
-  extensions 607 to 607;
-  extensions 608 to 608;
-  extensions 609 to 609;
-  extensions 610 to 610;
-  extensions 611 to 611;
-  extensions 612 to 612;
-  extensions 613 to 613;
-  extensions 614 to 614;
-  extensions 615 to 615;
-  extensions 616 to 616;
-  extensions 617 to 617;
-  extensions 618 to 618;
-  extensions 619 to 619;
-  extensions 620 to 620;
-  extensions 621 to 621;
-  extensions 622 to 622;
-  extensions 623 to 623;
-  extensions 624 to 624;
-  extensions 625 to 625;
-  extensions 626 to 626;
-  extensions 627 to 627;
-  extensions 628 to 628;
-  extensions 629 to 629;
-  extensions 813 to 813;
-  extensions 814 to 814;
-  extensions 815 to 815;
-  extensions 816 to 816;
-  extensions 817 to 817;
-  extensions 818 to 818;
-  extensions 819 to 819;
-  extensions 820 to 820;
-  extensions 821 to 821;
-  extensions 822 to 822;
-  extensions 823 to 823;
-  extensions 824 to 824;
-  extensions 827 to 827;
-  extensions 828 to 828;
-  extensions 829 to 829;
-  extensions 830 to 830;
-  extensions 831 to 831;
-  extensions 832 to 832;
-  extensions 833 to 833;
-  extensions 834 to 834;
-  extensions 835 to 835;
-  extensions 836 to 836;
-  extensions 837 to 837;
-  extensions 838 to 838;
-  extensions 839 to 839;
-  extensions 840 to 840;
-  extensions 841 to 841;
-  extensions 842 to 842;
-  extensions 843 to 843;
-  extensions 844 to 844;
-  extensions 845 to 845;
-  extensions 846 to 846;
-  extensions 847 to 847;
-  extensions 848 to 848;
-  extensions 849 to 849;
-  extensions 850 to 850;
-  extensions 851 to 851;
-  extensions 852 to 852;
-  extensions 853 to 853;
-  extensions 854 to 854;
-  extensions 855 to 855;
-  extensions 856 to 856;
-  extensions 857 to 857;
-  extensions 858 to 858;
-  extensions 859 to 859;
-  extensions 860 to 860;
-  extensions 861 to 861;
-  extensions 862 to 862;
-  extensions 863 to 863;
-  extensions 864 to 864;
-  extensions 865 to 865;
-  extensions 866 to 866;
-  extensions 867 to 867;
-  extensions 868 to 868;
-  extensions 869 to 869;
-  extensions 870 to 870;
-  extensions 871 to 871;
-  extensions 880 to 880;
-  extensions 881 to 881;
-  extensions 882 to 882;
-  extensions 883 to 883;
-  extensions 884 to 884;
-  extensions 885 to 885;
-  extensions 886 to 886;
-  extensions 887 to 887;
-  extensions 888 to 888;
-  extensions 890 to 890;
-  extensions 891 to 891;
-  extensions 892 to 892;
-  extensions 912 to 912;
-  extensions 914 to 914;
-  extensions 915 to 915;
-  extensions 916 to 916;
-  extensions 917 to 917;
-  extensions 918 to 918;
-  extensions 919 to 919;
-  extensions 920 to 920;
-  extensions 921 to 921;
-  extensions 922 to 922;
-  extensions 923 to 923;
-  extensions 924 to 924;
-  extensions 925 to 925;
-  extensions 926 to 926;
-  extensions 927 to 927;
-  extensions 928 to 928;
-  extensions 929 to 929;
-  extensions 930 to 930;
-  extensions 931 to 931;
-  extensions 932 to 932;
-  extensions 933 to 933;
-  extensions 934 to 934;
-  extensions 935 to 935;
-  extensions 936 to 936;
-  extensions 937 to 937;
-  extensions 938 to 938;
-  extensions 939 to 939;
-  extensions 940 to 940;
-  extensions 941 to 941;
-  extensions 942 to 942;
-  extensions 943 to 943;
-  extensions 944 to 944;
-  extensions 945 to 945;
-  extensions 946 to 946;
-  extensions 947 to 947;
-  extensions 949 to 949;
-  extensions 950 to 950;
-  extensions 951 to 951;
-  extensions 952 to 952;
-  extensions 954 to 954;
-  extensions 955 to 955;
-  extensions 956 to 956;
-  extensions 957 to 957;
-  extensions 958 to 958;
-  extensions 959 to 959;
-  extensions 960 to 960;
-  extensions 961 to 961;
-  extensions 962 to 962;
-  extensions 963 to 963;
-  extensions 964 to 964;
-  extensions 965 to 965;
-  extensions 966 to 966;
-  extensions 967 to 967;
-  extensions 968 to 968;
-  extensions 969 to 969;
-  extensions 970 to 970;
-  extensions 971 to 971;
-  extensions 972 to 972;
-  extensions 973 to 973;
-  extensions 974 to 974;
-  extensions 975 to 975;
-  extensions 976 to 976;
-  extensions 977 to 977;
-  extensions 978 to 978;
-  extensions 979 to 979;
-  extensions 980 to 980;
-  extensions 981 to 981;
-  extensions 982 to 982;
-  extensions 983 to 983;
-  extensions 984 to 984;
-  extensions 985 to 985;
-  extensions 987 to 987;
-  extensions 988 to 988;
-  extensions 1000 to 1000;
-  extensions 1001 to 1001;
-  extensions 1002 to 1002;
-  extensions 1003 to 1003;
-  extensions 1004 to 1004;
-  extensions 1005 to 1005;
-  extensions 1006 to 1006;
-  extensions 1007 to 1007;
-  extensions 1008 to 1008;
-  extensions 1009 to 1009;
-  extensions 1010 to 1010;
-  extensions 1011 to 1011;
-  extensions 1012 to 1012;
-  extensions 1013 to 1013;
-  extensions 1014 to 1014;
-  extensions 1015 to 1015;
-  extensions 1016 to 1016;
-  extensions 1017 to 1017;
-  extensions 1018 to 1018;
-  extensions 1019 to 1019;
-  extensions 1020 to 1020;
-  extensions 1021 to 1021;
-  extensions 1022 to 1022;
-  extensions 1023 to 1023;
-  extensions 1024 to 1024;
-  extensions 1025 to 1025;
-  extensions 1026 to 1026;
-  extensions 1027 to 1027;
-  extensions 1028 to 1028;
-  extensions 1029 to 1029;
-  extensions 1030 to 1030;
-  extensions 1031 to 1031;
-  extensions 1032 to 1032;
-  extensions 1033 to 1033;
-  extensions 1034 to 1034;
-  extensions 1035 to 1035;
-  extensions 1036 to 1036;
-  extensions 1037 to 1037;
-  extensions 1038 to 1038;
-  extensions 1039 to 1039;
-  extensions 1040 to 1040;
-  extensions 1041 to 1041;
-  extensions 1042 to 1042;
-  extensions 1043 to 1043;
-  extensions 1044 to 1044;
-  extensions 1045 to 1045;
-  extensions 1046 to 1046;
-  extensions 1047 to 1047;
-  extensions 1048 to 1048;
-  extensions 1049 to 1049;
-  extensions 1050 to 1050;
-  extensions 1051 to 1051;
-  extensions 1052 to 1052;
-  extensions 1053 to 1053;
-  extensions 1054 to 1054;
-  extensions 1055 to 1055;
-  extensions 1056 to 1056;
-  extensions 1057 to 1057;
-  extensions 1058 to 1058;
-  extensions 1079 to 1079;
-  extensions 1080 to 1080;
-  extensions 1081 to 1081;
-  extensions 1082 to 1082;
-  extensions 1083 to 1083;
-  extensions 1084 to 1084;
-  extensions 1085 to 1085;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message16945 field17025 = 22068132;
-  }
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_2.proto b/benchmarks/datasets/google_message3/benchmark_message3_2.proto
deleted file mode 100644
index d123a72..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_2.proto
+++ /dev/null
@@ -1,528 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message3;
-
-import "datasets/google_message3/benchmark_message3_3.proto";
-import "datasets/google_message3/benchmark_message3_4.proto";
-import "datasets/google_message3/benchmark_message3_5.proto";
-import "datasets/google_message3/benchmark_message3_7.proto";
-import "datasets/google_message3/benchmark_message3_8.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message22853 {
-  optional .benchmarks.google_message3.Enum22854 field22869 = 1;
-  repeated uint32 field22870 = 2 [packed = true];
-  repeated float field22871 = 3 [packed = true];
-  repeated float field22872 = 5 [packed = true];
-  optional .benchmarks.google_message3.UnusedEmptyMessage field22873 = 4;
-}
-
-message Message24345 {
-  optional string field24533 = 1;
-  optional .benchmarks.google_message3.UnusedEnum field24534 = 22;
-  optional .benchmarks.google_message3.Message24346 field24535 = 2;
-  optional string field24536 = 3;
-  optional string field24537 = 4;
-  optional .benchmarks.google_message3.UnusedEnum field24538 = 23;
-  optional string field24539 = 5;
-  required string field24540 = 6;
-  optional string field24541 = 7;
-  optional string field24542 = 8;
-  optional .benchmarks.google_message3.Message24316 field24543 = 9;
-  optional .benchmarks.google_message3.Message24376 field24544 = 10;
-  optional string field24545 = 11;
-  optional string field24546 = 19;
-  optional string field24547 = 20;
-  optional string field24548 = 21;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24549 = 12;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24550 = 13;
-  repeated string field24551 = 14;
-  optional string field24552 = 15;
-  optional int32 field24553 = 18;
-  optional .benchmarks.google_message3.Message24379 field24554 = 16;
-  optional string field24555 = 17;
-  repeated .benchmarks.google_message3.Message24356 field24556 = 24;
-  repeated .benchmarks.google_message3.Message24366 field24557 = 25;
-}
-
-message Message24403 {
-  optional .benchmarks.google_message3.Message24401 field24681 = 1;
-  optional .benchmarks.google_message3.Message24402 field24682 = 2;
-}
-
-message Message24391 {
-  optional string field24631 = 1;
-  optional string field24632 = 2;
-  repeated string field24633 = 3;
-  optional string field24634 = 4;
-  repeated string field24635 = 5;
-  repeated string field24636 = 16;
-  optional string field24637 = 17;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24638 = 25;
-  optional string field24639 = 7;
-  optional string field24640 = 18;
-  optional string field24641 = 19;
-  optional string field24642 = 20;
-  optional int32 field24643 = 24;
-  optional .benchmarks.google_message3.Message24379 field24644 = 8;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24645 = 9;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24646 = 10;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24647 = 11;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24648 = 12;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24649 = 13;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24650 = 14;
-  optional string field24651 = 21;
-  optional int32 field24652 = 22;
-  optional int32 field24653 = 23;
-  repeated string field24654 = 15;
-  repeated string field24655 = 6;
-}
-
-message Message27454 {}
-
-message Message27357 {
-  optional string field27410 = 1;
-  optional float field27411 = 2;
-  optional string field27412 = 3;
-  optional bool field27413 = 4;
-  optional bool field27414 = 5;
-}
-
-message Message27360 {
-  optional .benchmarks.google_message3.Message27358 field27426 = 1;
-  optional .benchmarks.google_message3.Enum27361 field27427 = 2;
-  optional .benchmarks.google_message3.Message27358 field27428 = 3;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field27429 = 4;
-}
-
-message Message34387 {
-  optional string field34446 = 1;
-  repeated .benchmarks.google_message3.Message34381 field34447 = 2;
-  optional .benchmarks.google_message3.UnusedEnum field34448 = 3;
-  optional .benchmarks.google_message3.Enum34388 field34449 = 4;
-  optional int64 field34450 = 5;
-}
-
-message Message34621 {
-  optional double field34651 = 1;
-  optional double field34652 = 2;
-  optional double field34653 = 3;
-  optional double field34654 = 4;
-  optional double field34655 = 11;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34656 = 13;
-  optional .benchmarks.google_message3.Message34619 field34657 = 14;
-  optional string field34658 = 5;
-  optional string field34659 = 9;
-  optional double field34660 = 12;
-  optional bytes field34661 = 19;
-  optional string field34662 = 15;
-  optional string field34663 = 16;
-  optional string field34664 = 17;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34665 = 18;
-  optional .benchmarks.google_message3.Message34621 field34666 = 20;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field34667 = 100;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34668 = 101;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message34621 field34669 = 17562023;
-  }
-}
-
-message Message35476 {
-  optional string field35484 = 1;
-  optional string field35485 = 2;
-  optional string field35486 = 3;
-  optional .benchmarks.google_message3.Enum35477 field35487 = 4;
-  optional float field35488 = 5;
-  optional float field35489 = 6;
-  optional float field35490 = 7;
-  optional float field35491 = 8;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field35492 = 9;
-  optional int32 field35493 = 10;
-  optional int32 field35494 = 11;
-  optional int32 field35495 = 12;
-  optional string field35496 = 13;
-  optional string field35497 = 14;
-}
-
-message Message949 {
-  optional string field955 = 1;
-  optional int64 field956 = 2;
-  optional int64 field957 = 3;
-  optional .benchmarks.google_message3.Message730 field958 = 4;
-  repeated string field959 = 5;
-  optional string field960 = 6;
-  optional bool field961 = 7;
-}
-
-message Message36869 {
-  optional int32 field36970 = 1;
-  optional int32 field36971 = 2;
-}
-
-message Message33968 {
-  repeated group Message33969 = 1 {}
-  repeated .benchmarks.google_message3.Message33958 field33989 = 3;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field33990 = 106;
-  optional bool field33991 = 108;
-  optional .benchmarks.google_message3.UnusedEnum field33992 = 107;
-}
-
-message Message6644 {
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6701 = 8;
-  optional string field6702 = 1;
-  optional double field6703 = 2;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6704 = 9;
-  optional bytes field6705 = 3;
-  optional bytes field6706 = 19;
-  optional .benchmarks.google_message3.Message6637 field6707 = 4;
-  repeated .benchmarks.google_message3.Message6126 field6708 = 18;
-  optional bool field6709 = 6;
-  optional .benchmarks.google_message3.Message6643 field6710 = 10;
-  optional string field6711 = 12;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6712 = 14;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6713 = 15;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6714 = 16;
-  optional int32 field6715 = 17;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6716 = 20;
-}
-
-message Message18831 {
-  repeated group Message18832 = 1 {
-    optional int32 field18836 = 2;
-    optional string field18837 = 5;
-    optional float field18838 = 3;
-    optional float field18839 = 9;
-    optional int32 field18840 = 11;
-    repeated uint64 field18841 = 4;
-    repeated group Message18833 = 6 {
-      required uint64 field18843 = 7;
-      optional string field18844 = 8;
-      optional float field18845 = 10;
-      optional int32 field18846 = 12;
-      optional bool field18847 = 13;
-    }
-  }
-}
-
-message Message13090 {
-  optional .benchmarks.google_message3.Message13083 field13141 = 1;
-  optional .benchmarks.google_message3.Message13088 field13142 = 2;
-}
-
-message Message11874 {
-  optional .benchmarks.google_message3.Message10391 field11888 = 3;
-  optional string field11889 = 4;
-  optional .benchmarks.google_message3.Message11873 field11890 = 6;
-  optional bool field11891 = 7;
-  extensions 1 to 1;
-  extensions 2 to 2;
-  extensions 5 to 5;
-}
-
-message Message4144 {
-  repeated group Message4145 = 1 {
-    required .benchmarks.google_message3.Enum4146 field4165 = 2;
-    required int32 field4166 = 3;
-    optional .benchmarks.google_message3.Enum4160 field4167 = 9;
-    optional bytes field4168 = 4;
-    optional .benchmarks.google_message3.Enum4152 field4169 = 5;
-    optional string field4170 = 6;
-  }
-}
-
-message Message35573 {
-  optional fixed64 field35695 = 16;
-  optional string field35696 = 1000;
-  optional string field35697 = 1004;
-  optional int32 field35698 = 1003;
-  repeated group Message35574 = 1012 {}
-  optional int64 field35700 = 1011;
-  optional int64 field35701 = 1005;
-  optional int64 field35702 = 1006;
-  optional int64 field35703 = 1007;
-  optional int64 field35704 = 1008;
-  repeated group Message35575 = 1 {
-    optional int64 field35709 = 2;
-    optional string field35710 = 3;
-    optional string field35711 = 19;
-    optional int32 field35712 = 20;
-    optional int32 field35713 = 21;
-    optional int32 field35714 = 22;
-    optional bool field35715 = 23;
-    optional int32 field35716 = 47;
-    optional int32 field35717 = 48;
-    optional bool field35718 = 24;
-    optional fixed64 field35719 = 25;
-    optional bytes field35720 = 52;
-    optional int32 field35721 = 18;
-    optional fixed32 field35722 = 43;
-    optional bool field35723 = 26;
-    optional int32 field35724 = 27;
-    optional int32 field35725 = 17;
-    optional bool field35726 = 45;
-    repeated int32 field35727 = 33;
-    repeated int32 field35728 = 58;
-    optional float field35729 = 34;
-    optional float field35730 = 1009;
-    optional int32 field35731 = 28;
-    repeated fixed64 field35732 = 1001;
-    repeated fixed64 field35733 = 1002;
-    optional int32 field35734 = 44;
-    optional int32 field35735 = 50;
-    optional int32 field35736 = 36;
-    optional int32 field35737 = 40;
-    optional bool field35738 = 1016;
-    optional bool field35739 = 1010;
-    optional int32 field35740 = 37;
-    optional int32 field35741 = 38;
-    optional string field35742 = 46;
-    optional uint32 field35743 = 60;
-    repeated bytes field35744 = 56;
-    optional .benchmarks.google_message3.Message0 field35745 = 57;
-    required group Message35576 = 4 {
-      optional fixed64 field35747 = 5;
-      optional int32 field35748 = 6;
-      optional int32 field35749 = 49;
-      optional int32 field35750 = 7;
-      optional uint32 field35751 = 59;
-      optional int32 field35752 = 14;
-      optional int32 field35753 = 15;
-      optional int32 field35754 = 35;
-      optional bytes field35755 = 53;
-      optional int32 field35756 = 8;
-      optional string field35757 = 9;
-      optional fixed64 field35758 = 10;
-      optional int32 field35759 = 11;
-      optional int32 field35760 = 12;
-      optional int32 field35761 = 41;
-      optional int32 field35762 = 30;
-      optional int32 field35763 = 31;
-      optional int32 field35764 = 13;
-      optional bytes field35765 = 39;
-      optional string field35766 = 29;
-      optional int32 field35767 = 42;
-      repeated int32 field35768 = 32;
-      repeated int32 field35769 = 51;
-      optional int64 field35770 = 54;
-      optional .benchmarks.google_message3.Message0 field35771 = 55;
-    }
-  }
-}
-
-message Message36858 {
-  repeated int32 field36956 = 1;
-  repeated string field36957 = 2;
-  repeated string field36958 = 12;
-  optional int32 field36959 = 3;
-  optional int32 field36960 = 4;
-  optional int32 field36961 = 14;
-  optional string field36962 = 11;
-  optional bool field36963 = 5;
-  optional bool field36964 = 13;
-  optional int64 field36965 = 6;
-  optional .benchmarks.google_message3.Message35506 field36966 = 7;
-  repeated group Message36859 = 8 {
-    required .benchmarks.google_message3.Enum36860 field36968 = 9;
-    optional float field36969 = 10;
-  }
-}
-
-message Message13174 {
-  required int32 field13237 = 6;
-  optional int32 field13238 = 3;
-  required int32 field13239 = 4;
-  optional int32 field13240 = 8;
-  optional double field13241 = 5;
-  optional double field13242 = 7;
-  optional int32 field13243 = 17;
-  optional int32 field13244 = 19;
-  optional double field13245 = 20;
-  optional int32 field13246 = 9;
-  optional double field13247 = 10;
-  optional int32 field13248 = 11;
-  optional .benchmarks.google_message3.Message13151 field13249 = 21;
-  optional int32 field13250 = 1;
-  optional double field13251 = 2;
-  optional double field13252 = 15;
-  optional double field13253 = 16;
-  optional double field13254 = 12;
-  optional double field13255 = 13;
-  optional double field13256 = 14;
-  optional int32 field13257 = 18;
-}
-
-message Message18283 {
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18478 = 1;
-  optional int32 field18479 = 4;
-  optional int32 field18480 = 106;
-  optional int32 field18481 = 107;
-  optional int32 field18482 = 108;
-  optional int32 field18483 = 109;
-  optional int32 field18484 = 105;
-  optional int32 field18485 = 113;
-  optional int32 field18486 = 114;
-  optional int32 field18487 = 124;
-  optional int32 field18488 = 125;
-  optional int32 field18489 = 128;
-  optional int32 field18490 = 135;
-  optional bool field18491 = 166;
-  optional bool field18492 = 136;
-  optional int32 field18493 = 140;
-  optional int32 field18494 = 171;
-  optional int32 field18495 = 148;
-  optional int32 field18496 = 145;
-  optional float field18497 = 117;
-  optional int32 field18498 = 146;
-  optional string field18499 = 3;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18500 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18501 = 6;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18502 = 9;
-  optional .benchmarks.google_message3.Message18253 field18503 = 155;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18504 = 184;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18505 = 163;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18506 = 16;
-  repeated int32 field18507 = 20;
-  repeated int32 field18508 = 7;
-  repeated string field18509 = 194;
-  optional bytes field18510 = 30;
-  optional int32 field18511 = 31;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18512 = 178;
-  optional string field18513 = 8;
-  optional float field18514 = 2;
-  optional float field18515 = 100;
-  optional float field18516 = 101;
-  optional float field18517 = 102;
-  optional int32 field18518 = 103;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field18519 = 104;
-  optional int32 field18520 = 110;
-  optional int32 field18521 = 112;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18522 = 111;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18523 = 115;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18524 = 119;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18525 = 127;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18526 = 185;
-  optional int32 field18527 = 120;
-  optional int32 field18528 = 132;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18529 = 126;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18530 = 129;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18531 = 131;
-  optional fixed64 field18532 = 150;
-  optional int32 field18533 = 133;
-  optional int32 field18534 = 134;
-  optional int32 field18535 = 139;
-  optional fixed64 field18536 = 137;
-  optional fixed64 field18537 = 138;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18538 = 141;
-  optional int32 field18539 = 142;
-  optional int32 field18540 = 181;
-  optional .benchmarks.google_message3.Message16816 field18541 = 143;
-  optional .benchmarks.google_message3.Message16685 field18542 = 154;
-  optional int32 field18543 = 144;
-  optional int64 field18544 = 147;
-  optional int64 field18545 = 149;
-  optional int32 field18546 = 151;
-  optional int32 field18547 = 152;
-  optional int32 field18548 = 153;
-  optional float field18549 = 161;
-  optional .benchmarks.google_message3.Message0 field18550 = 123;
-  repeated int64 field18551 = 156;
-  optional int32 field18552 = 157;
-  repeated fixed64 field18553 = 188;
-  optional int32 field18554 = 158;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18555 = 159;
-  optional bool field18556 = 160;
-  optional uint64 field18557 = 162;
-  optional int32 field18558 = 164;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18559 = 10;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18560 = 167;
-  optional int32 field18561 = 168;
-  repeated fixed64 field18562 = 169;
-  repeated string field18563 = 170;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18564 = 172;
-  optional int64 field18565 = 173;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18566 = 174;
-  optional int64 field18567 = 175;
-  optional uint32 field18568 = 189;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18569 = 176;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18570 = 177;
-  optional uint32 field18571 = 179;
-  optional uint32 field18572 = 180;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18573 = 182;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18574 = 183;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18575 = 121;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18576 = 186;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18577 = 187;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18578 = 190;
-  optional int32 field18579 = 191;
-  optional float field18580 = 192;
-  optional bool field18581 = 193;
-  extensions 116 to 116;
-  extensions 118 to 118;
-  extensions 130 to 130;
-  extensions 165 to 165;
-}
-
-message Message13169 {
-  repeated .benchmarks.google_message3.Message13168 field13223 = 1;
-  required .benchmarks.google_message3.Message13167 field13224 = 2;
-  optional string field13225 = 3;
-}
-
-message Message19255 {
-  optional string field19257 = 1;
-}
-
-message Message35542 {
-  optional bool field35543 = 1;
-  optional bool field35544 = 2;
-  optional bool field35545 = 3;
-}
-
-message Message3901 {
-  optional int32 field3990 = 1;
-  optional int32 field3991 = 2;
-  optional int32 field3992 = 3;
-  optional int32 field3993 = 4;
-  optional int32 field3994 = 7;
-  optional int32 field3995 = 8;
-  optional int32 field3996 = 9;
-  optional int32 field3997 = 10;
-  optional int32 field3998 = 11;
-  optional int32 field3999 = 12;
-  optional .benchmarks.google_message3.UnusedEnum field4000 = 6;
-  optional int32 field4001 = 5;
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_3.proto b/benchmarks/datasets/google_message3/benchmark_message3_3.proto
deleted file mode 100644
index 2e534a6..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_3.proto
+++ /dev/null
@@ -1,496 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message3;
-
-import "datasets/google_message3/benchmark_message3_4.proto";
-import "datasets/google_message3/benchmark_message3_5.proto";
-import "datasets/google_message3/benchmark_message3_7.proto";
-import "datasets/google_message3/benchmark_message3_8.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message35546 {
-  optional int64 field35556 = 1;
-  optional int32 field35557 = 2;
-  optional bool field35558 = 3;
-  optional int64 field35559 = 13;
-  optional group Message35547 = 4 {
-    required int32 field35569 = 5;
-    required int32 field35570 = 6;
-  }
-  optional group Message35548 = 10 {
-    required int64 field35571 = 11;
-    required int64 field35572 = 12;
-  }
-  optional bool field35562 = 14;
-  optional bool field35563 = 15;
-  optional int32 field35564 = 16;
-  optional bool field35565 = 17;
-  optional bool field35566 = 18;
-  optional string field35567 = 100;
-}
-
-message Message2356 {
-  optional .benchmarks.google_message3.Message1374 field2368 = 121;
-  optional uint64 field2369 = 1;
-  optional int32 field2370 = 2;
-  optional int32 field2371 = 17;
-  required string field2372 = 3;
-  optional int32 field2373 = 7;
-  optional bytes field2374 = 8;
-  optional string field2375 = 4;
-  optional string field2376 = 101;
-  optional int32 field2377 = 102;
-  optional int32 field2378 = 103;
-  optional int32 field2379 = 104;
-  optional int32 field2380 = 113;
-  optional int32 field2381 = 114;
-  optional int32 field2382 = 115;
-  optional int32 field2383 = 117;
-  optional int32 field2384 = 118;
-  optional int32 field2385 = 119;
-  optional int32 field2386 = 105;
-  optional bytes field2387 = 5;
-  optional group Message2357 = 6 {
-    optional int64 field2399 = 9;
-    optional int32 field2400 = 10;
-    optional int32 field2401 = 11;
-    optional int32 field2402 = 12;
-    optional int32 field2403 = 13;
-    optional int32 field2404 = 116;
-    optional int32 field2405 = 106;
-    required bytes field2406 = 14;
-    optional int32 field2407 = 45;
-    optional int32 field2408 = 112;
-    optional bool field2409 = 122;
-    optional bytes field2410 = 124;
-  }
-  optional string field2389 = 120;
-  optional group Message2358 = 107 {}
-  repeated group Message2359 = 40 {
-    optional string field2413 = 41;
-    optional string field2414 = 42;
-    optional string field2415 = 43;
-    optional string field2416 = 44;
-    optional int32 field2417 = 46;
-    optional string field2418 = 47;
-    optional float field2419 = 110;
-    optional float field2420 = 111;
-  }
-  optional int32 field2392 = 50;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field2393 = 60;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field2394 = 70;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field2395 = 80;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field2396 = 90;
-  optional string field2397 = 100;
-  optional string field2398 = 123;
-}
-
-message Message7029 {
-  required int32 field7183 = 1;
-  optional int32 field7184 = 2;
-  optional int32 field7185 = 3;
-  optional int32 field7186 = 4;
-  optional int32 field7187 = 5;
-  optional int32 field7188 = 6;
-  optional int32 field7189 = 17;
-  optional int32 field7190 = 18;
-  optional int32 field7191 = 49;
-  optional int32 field7192 = 28;
-  optional int32 field7193 = 33;
-  optional int32 field7194 = 25;
-  optional int32 field7195 = 26;
-  optional int32 field7196 = 40;
-  optional int32 field7197 = 41;
-  optional int32 field7198 = 42;
-  optional int32 field7199 = 43;
-  optional int32 field7200 = 19;
-  optional int32 field7201 = 7;
-  optional int32 field7202 = 8;
-  optional int32 field7203 = 9;
-  optional int32 field7204 = 10;
-  optional int32 field7205 = 11;
-  optional int32 field7206 = 12;
-  repeated group Message7030 = 13 {
-    optional string field7226 = 14;
-    optional string field7227 = 15;
-    optional int64 field7228 = 16;
-  }
-  repeated group Message7031 = 21 {
-    optional string field7229 = 22;
-    optional int32 field7230 = 23;
-    optional int32 field7231 = 24;
-    optional int32 field7232 = 30;
-    optional int32 field7233 = 31;
-    optional int32 field7234 = 35;
-  }
-  optional int32 field7209 = 20;
-  optional float field7210 = 27;
-  optional int32 field7211 = 29;
-  optional int32 field7212 = 32;
-  optional string field7213 = 48;
-  optional bool field7214 = 34;
-  optional int32 field7215 = 36;
-  optional float field7216 = 37;
-  optional bool field7217 = 38;
-  optional bool field7218 = 39;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field7219 = 44;
-  optional int32 field7220 = 45;
-  optional int32 field7221 = 46;
-  optional int32 field7222 = 47;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field7223 = 50;
-  optional int32 field7224 = 51;
-}
-
-message Message35538 {
-  required int64 field35539 = 1;
-}
-
-message Message18921 {
-  optional string field18946 = 1;
-  optional fixed64 field18947 = 2;
-  optional int32 field18948 = 3;
-  optional double field18949 = 4;
-  optional bool field18950 = 17;
-  optional bool field18951 = 23;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field18952 = 24;
-  repeated group Message18922 = 5 {
-    optional uint64 field18959 = 6;
-    optional string field18960 = 13;
-    optional bool field18961 = 21;
-    optional bool field18962 = 33;
-    optional int32 field18963 = 7;
-    optional int32 field18964 = 8;
-    optional string field18965 = 9;
-    optional .benchmarks.google_message3.Message18856 field18966 = 10;
-    optional uint64 field18967 = 34;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18968 = 11;
-    optional uint64 field18969 = 35;
-    optional float field18970 = 12;
-    repeated string field18971 = 14;
-    optional bool field18972 = 15;
-    optional bool field18973 = 16;
-    optional float field18974 = 22;
-    optional int32 field18975 = 18;
-    optional int32 field18976 = 19;
-    optional int32 field18977 = 20;
-    optional .benchmarks.google_message3.UnusedEmptyMessage field18978 = 25;
-    optional .benchmarks.google_message3.UnusedEnum field18979 = 26;
-    repeated string field18980 = 27;
-    optional float field18981 = 28;
-  }
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field18954 = 29;
-  repeated .benchmarks.google_message3.Message18943 field18955 = 30;
-  repeated .benchmarks.google_message3.Message18944 field18956 = 31;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field18957 = 32;
-}
-
-message Message35540 {
-  optional bool field35541 = 1;
-}
-
-message Message3886 {
-  repeated group Message3887 = 1 {
-    required string field3932 = 2;
-    optional string field3933 = 9;
-    optional .benchmarks.google_message3.Message3850 field3934 = 3;
-    optional bytes field3935 = 8;
-  }
-}
-
-message Message6743 {
-  optional .benchmarks.google_message3.Message6721 field6759 = 1;
-  optional .benchmarks.google_message3.Message6723 field6760 = 2;
-  optional .benchmarks.google_message3.Message6723 field6761 = 8;
-  optional .benchmarks.google_message3.Message6725 field6762 = 3;
-  optional .benchmarks.google_message3.Message6726 field6763 = 4;
-  optional .benchmarks.google_message3.Message6733 field6764 = 5;
-  optional .benchmarks.google_message3.Message6734 field6765 = 6;
-  optional .benchmarks.google_message3.Message6742 field6766 = 7;
-}
-
-message Message6773 {
-  optional .benchmarks.google_message3.Enum6769 field6794 = 1;
-  optional int32 field6795 = 9;
-  optional .benchmarks.google_message3.UnusedEnum field6796 = 10;
-  optional int32 field6797 = 11;
-  optional int32 field6798 = 2;
-  optional .benchmarks.google_message3.Enum6774 field6799 = 3;
-  optional double field6800 = 5;
-  optional double field6801 = 7;
-  optional double field6802 = 8;
-  optional .benchmarks.google_message3.Enum6782 field6803 = 6;
-}
-
-message Message8224 {
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8255 = 1;
-  optional .benchmarks.google_message3.Message8184 field8256 = 2;
-  optional .benchmarks.google_message3.Message7966 field8257 = 3;
-  optional string field8258 = 4;
-  optional string field8259 = 5;
-  optional bool field8260 = 6;
-  optional int64 field8261 = 7;
-  optional string field8262 = 8;
-  optional int64 field8263 = 9;
-  optional double field8264 = 10;
-  optional int64 field8265 = 11;
-  repeated string field8266 = 12;
-  optional int64 field8267 = 13;
-  optional int32 field8268 = 14;
-  optional int32 field8269 = 15;
-  optional int64 field8270 = 16;
-  optional double field8271 = 17;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8272 = 18;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8273 = 19;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8274 = 20;
-  optional bool field8275 = 21;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8276 = 22;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8277 = 23;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8278 = 24;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8279 = 25;
-  optional bool field8280 = 26;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8281 = 27;
-}
-
-message Message8392 {
-  optional string field8395 = 1;
-  optional string field8396 = 2;
-  optional .benchmarks.google_message3.Message7966 field8397 = 3;
-  optional string field8398 = 4;
-  optional string field8399 = 5;
-  optional string field8400 = 6;
-  optional string field8401 = 7;
-  optional string field8402 = 8;
-  optional string field8403 = 9;
-}
-
-message Message8130 {
-  optional string field8156 = 1;
-  optional string field8157 = 2;
-  optional string field8158 = 4;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8159 = 6;
-  repeated string field8160 = 7;
-  optional int64 field8161 = 8;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8162 = 9;
-  optional string field8163 = 10;
-  optional string field8164 = 11;
-  optional string field8165 = 12;
-  optional string field8166 = 13;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8167 = 14;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8168 = 15;
-  optional string field8169 = 16;
-  optional .benchmarks.google_message3.UnusedEnum field8170 = 17;
-  optional .benchmarks.google_message3.UnusedEnum field8171 = 18;
-  optional bool field8172 = 19;
-  optional bool field8173 = 20;
-  optional double field8174 = 21;
-  optional int32 field8175 = 22;
-  optional int32 field8176 = 23;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8177 = 24;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8178 = 25;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8179 = 26;
-}
-
-message Message8478 {
-  optional string field8489 = 7;
-  optional .benchmarks.google_message3.Message7966 field8490 = 1;
-  optional .benchmarks.google_message3.Message8476 field8491 = 2;
-  optional int64 field8492 = 3;
-  optional .benchmarks.google_message3.Message8476 field8493 = 4;
-  repeated .benchmarks.google_message3.Message8477 field8494 = 5;
-  optional .benchmarks.google_message3.Message8454 field8495 = 6;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8496 = 8;
-}
-
-message Message8479 {
-  optional .benchmarks.google_message3.Message8475 field8497 = 1;
-  optional .benchmarks.google_message3.Message7966 field8498 = 2;
-  optional .benchmarks.google_message3.Message8476 field8499 = 3;
-  optional .benchmarks.google_message3.Message8476 field8500 = 4;
-  optional string field8501 = 6;
-  optional string field8502 = 7;
-  optional .benchmarks.google_message3.Message7966 field8503 = 8;
-  optional .benchmarks.google_message3.Message8455 field8504 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8505 = 9;
-}
-
-message Message10319 {
-  optional .benchmarks.google_message3.Enum10325 field10340 = 1;
-  optional int32 field10341 = 4;
-  optional int32 field10342 = 5;
-  optional bytes field10343 = 3;
-  optional string field10344 = 2;
-  optional string field10345 = 6;
-  optional string field10346 = 7;
-}
-
-message Message4016 {
-  required int32 field4017 = 1;
-  required int32 field4018 = 2;
-  required int32 field4019 = 3;
-  required int32 field4020 = 4;
-}
-
-message Message12669 {
-  optional .benchmarks.google_message3.Message12559 field12681 = 1;
-  optional float field12682 = 2;
-  optional bool field12683 = 3;
-  optional .benchmarks.google_message3.Enum12670 field12684 = 4;
-}
-
-message Message12819 {
-  optional double field12834 = 1;
-  optional double field12835 = 2;
-  optional double field12836 = 3;
-  optional double field12837 = 4;
-  optional double field12838 = 5;
-  optional double field12839 = 6;
-}
-
-message Message12820 {
-  optional int32 field12840 = 1;
-  optional int32 field12841 = 2;
-  optional int32 field12842 = 3;
-  optional int32 field12843 = 8;
-  optional int32 field12844 = 4;
-  optional int32 field12845 = 5;
-  optional int32 field12846 = 6;
-  optional int32 field12847 = 7;
-}
-
-message Message12821 {
-  optional int32 field12848 = 1;
-  optional int32 field12849 = 2;
-  optional int32 field12850 = 3;
-  optional int32 field12851 = 4;
-  optional int32 field12852 = 5;
-}
-
-message Message12818 {
-  optional uint64 field12829 = 1;
-  optional int32 field12830 = 2;
-  optional int32 field12831 = 3;
-  optional int32 field12832 = 5;
-  repeated .benchmarks.google_message3.Message12817 field12833 = 4;
-}
-
-message Message16479 {
-  optional .benchmarks.google_message3.Message16480 field16484 = 1;
-  optional int32 field16485 = 5;
-  optional float field16486 = 2;
-  optional uint32 field16487 = 4;
-  optional bool field16488 = 3;
-  optional uint32 field16489 = 6;
-}
-
-message Message16722 {
-  optional string field16752 = 1;
-  optional string field16753 = 2;
-  optional string field16754 = 3;
-  optional int32 field16755 = 5;
-  optional string field16756 = 4;
-}
-
-message Message16724 {
-  optional int64 field16761 = 1;
-  optional float field16762 = 2;
-  optional int64 field16763 = 3;
-  optional int64 field16764 = 4;
-  optional bool field16765 = 5;
-  repeated string field16766 = 6;
-  repeated string field16767 = 7;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field16768 = 8;
-  optional bool field16769 = 9;
-  optional uint32 field16770 = 10;
-  optional .benchmarks.google_message3.Enum16728 field16771 = 11;
-  repeated int32 field16772 = 12;
-  optional bool field16773 = 13;
-}
-
-message Message17728 {}
-
-message Message24356 {
-  optional string field24559 = 1;
-  optional string field24560 = 2;
-  optional int32 field24561 = 14;
-  optional string field24562 = 3;
-  optional string field24563 = 4;
-  optional string field24564 = 5;
-  optional .benchmarks.google_message3.UnusedEnum field24565 = 13;
-  optional string field24566 = 6;
-  optional .benchmarks.google_message3.Enum24361 field24567 = 12;
-  optional string field24568 = 7;
-  optional string field24569 = 8;
-  optional string field24570 = 9;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24571 = 10;
-  repeated string field24572 = 11;
-  repeated string field24573 = 15;
-}
-
-message Message24376 {
-  optional string field24589 = 1;
-  optional string field24590 = 2;
-  optional string field24591 = 3;
-  required .benchmarks.google_message3.Message24377 field24592 = 4;
-  optional .benchmarks.google_message3.Message24317 field24593 = 5;
-  optional string field24594 = 6;
-  optional .benchmarks.google_message3.Message24378 field24595 = 7;
-  repeated string field24596 = 8;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24597 = 14;
-  repeated string field24598 = 9;
-  repeated string field24599 = 10;
-  repeated string field24600 = 11;
-  optional string field24601 = 12;
-  repeated string field24602 = 13;
-}
-
-message Message24366 {
-  optional string field24574 = 1;
-  optional string field24575 = 2;
-  optional string field24576 = 3;
-  optional int32 field24577 = 10;
-  optional string field24578 = 13;
-  optional string field24579 = 4;
-  optional string field24580 = 5;
-  optional .benchmarks.google_message3.UnusedEnum field24581 = 9;
-  optional string field24582 = 14;
-  optional .benchmarks.google_message3.UnusedEnum field24583 = 15;
-  optional string field24584 = 6;
-  optional string field24585 = 12;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24586 = 7;
-  repeated string field24587 = 8;
-  repeated string field24588 = 11;
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_4.proto b/benchmarks/datasets/google_message3/benchmark_message3_4.proto
deleted file mode 100644
index b304148..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_4.proto
+++ /dev/null
@@ -1,514 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message3;
-
-import "datasets/google_message3/benchmark_message3_5.proto";
-import "datasets/google_message3/benchmark_message3_6.proto";
-import "datasets/google_message3/benchmark_message3_7.proto";
-import "datasets/google_message3/benchmark_message3_8.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message24346 {}
-
-message Message24401 {
-  optional .benchmarks.google_message3.Message24400 field24679 = 1;
-}
-
-message Message24402 {
-  optional .benchmarks.google_message3.Message24400 field24680 = 1;
-}
-
-message Message24379 {
-  optional string field24603 = 1;
-  optional string field24604 = 2;
-  optional string field24605 = 3;
-  required .benchmarks.google_message3.Message24380 field24606 = 4;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24607 = 5;
-  optional string field24608 = 6;
-  optional .benchmarks.google_message3.Message24381 field24609 = 7;
-  repeated string field24610 = 8;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24611 = 17;
-  repeated string field24612 = 9;
-  repeated string field24613 = 10;
-  repeated string field24614 = 11;
-  optional string field24615 = 14;
-  optional string field24616 = 12;
-  optional string field24617 = 16;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24618 = 13;
-  repeated string field24619 = 15;
-  repeated string field24620 = 18;
-}
-
-message Message27358 {
-  optional int32 field27415 = 1;
-  optional int32 field27416 = 2;
-}
-
-message Message34381 {
-  optional string field34398 = 1;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34399 = 2;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34400 = 3;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34401 = 4;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34402 = 5;
-  optional bool field34403 = 6;
-  optional bool field34404 = 7;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34405 = 8;
-  optional bool field34406 = 9;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34407 = 10;
-}
-
-message Message34619 {
-  optional double field34641 = 1;
-  optional double field34642 = 2;
-  optional double field34643 = 3;
-  optional double field34644 = 4;
-  optional double field34645 = 11;
-  optional double field34646 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field34647 = 100;
-}
-
-message Message730 {
-  optional string field897 = 19;
-  repeated string field898 = 27;
-  repeated string field899 = 28;
-  repeated string field900 = 21;
-  optional string field901 = 30;
-  repeated uint32 field902 = 20;
-  repeated uint32 field903 = 32;
-  repeated string field904 = 16;
-  repeated .benchmarks.google_message3.Message697 field905 = 6;
-  repeated .benchmarks.google_message3.Message704 field906 = 7;
-  repeated string field907 = 18;
-  repeated .benchmarks.google_message3.Message703 field908 = 8;
-  repeated string field909 = 9;
-  optional .benchmarks.google_message3.Message716 field910 = 10;
-  optional .benchmarks.google_message3.Message718 field911 = 11;
-  optional bool field912 = 14;
-  repeated .benchmarks.google_message3.Message715 field913 = 4;
-  repeated string field914 = 17;
-  repeated string field915 = 23;
-  repeated .benchmarks.google_message3.Message719 field916 = 24;
-  repeated .benchmarks.google_message3.Message728 field917 = 26;
-  repeated .benchmarks.google_message3.Message702 field918 = 35;
-  optional string field919 = 36;
-  repeated string field920 = 37;
-  optional int64 field921 = 38;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field922 = 39;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field923 = 1;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field924 = 2;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field925 = 3;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field926 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field927 = 13;
-  repeated string field928 = 22;
-  optional bytes field929 = 31;
-  extensions 25 to 25;
-  extensions 29 to 29;
-  extensions 34 to 34;
-  extensions 15 to 15;
-}
-
-message Message33958 {
-  optional string field33977 = 1;
-  optional string field33978 = 9;
-  repeated group Message33959 = 2 {
-    required string field33982 = 3;
-    optional string field33983 = 4;
-    optional string field33984 = 5;
-    optional fixed64 field33985 = 8;
-    optional bool field33986 = 10;
-    optional .benchmarks.google_message3.Message0 field33987 = 6;
-  }
-  optional .benchmarks.google_message3.Enum33960 field33980 = 7;
-  extend .benchmarks.google_message3.Message0 {
-    optional .benchmarks.google_message3.Message33958 field33981 = 10747482;
-  }
-}
-
-message Message6637 {
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6670 = 2;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field6671 = 1;
-  optional int32 field6672 = 3;
-  repeated string field6673 = 4;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6674 = 5;
-}
-
-message Message6643 {
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6683 = 3;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6684 = 4;
-  optional double field6685 = 5;
-  optional double field6686 = 6;
-  optional int32 field6687 = 1;
-  optional int32 field6688 = 2;
-  optional double field6689 = 9;
-  optional bytes field6690 = 10;
-  optional int32 field6691 = 11;
-  optional bool field6692 = 12;
-  optional bool field6693 = 13;
-  optional .benchmarks.google_message3.Message6578 field6694 = 15;
-  optional .benchmarks.google_message3.UnusedEnum field6695 = 16;
-  optional int64 field6696 = 17;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field6697 = 22;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6698 = 19;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6699 = 20;
-  optional int32 field6700 = 21;
-}
-
-message Message6126 {
-  required string field6152 = 1;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field6153 = 9;
-  optional int32 field6154 = 14;
-  optional bytes field6155 = 10;
-  optional .benchmarks.google_message3.Message6024 field6156 = 12;
-  optional int32 field6157 = 4;
-  optional string field6158 = 5;
-  optional int32 field6159 = 6;
-  repeated int32 field6160 = 2;
-  repeated int32 field6161 = 3;
-  repeated .benchmarks.google_message3.Message6052 field6162 = 7;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field6163 = 11;
-  optional .benchmarks.google_message3.Enum6065 field6164 = 15;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field6165 = 8;
-  optional bool field6166 = 13;
-  optional bool field6167 = 16;
-  optional bool field6168 = 18;
-  repeated .benchmarks.google_message3.Message6054 field6169 = 17;
-  optional int32 field6170 = 19;
-}
-
-message Message13083 {
-  optional float field13096 = 1;
-  repeated group Message13084 = 2 {
-    required float field13107 = 3;
-    required int32 field13108 = 4;
-    optional float field13109 = 5;
-    repeated .benchmarks.google_message3.Enum13092 field13110 = 6;
-  }
-  optional float field13098 = 44;
-  optional float field13099 = 45;
-  optional uint64 field13100 = 46;
-  optional float field13101 = 47;
-  optional group Message13085 = 16 {}
-  repeated group Message13086 = 23 {}
-  repeated group Message13087 = 29 {}
-  optional .benchmarks.google_message3.UnusedEmptyMessage field13105 = 43;
-}
-
-message Message13088 {
-  repeated group Message13089 = 1 {
-    required string field13139 = 2;
-    optional float field13140 = 3;
-  }
-  optional int64 field13136 = 4;
-  optional bool field13137 = 5;
-}
-
-message Message10391 {
-  optional .benchmarks.google_message3.Enum10392 field10411 = 1;
-  optional .benchmarks.google_message3.UnusedEnum field10412 = 2;
-  optional int64 field10413 = 3;
-  optional string field10414 = 4;
-  optional string field10415 = 5;
-  optional bytes field10416 = 6;
-  optional bool field10417 = 8;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field10418 = 9;
-  optional bool field10419 = 10;
-}
-
-message Message11873 {
-  optional string field11876 = 1;
-  optional string field11877 = 4;
-  optional .benchmarks.google_message3.Message10573 field11878 = 5;
-  optional .benchmarks.google_message3.Message10582 field11879 = 6;
-  optional .benchmarks.google_message3.Message10824 field11880 = 7;
-  optional .benchmarks.google_message3.Message10773 field11881 = 12;
-  optional .benchmarks.google_message3.Message11866 field11882 = 8;
-  optional .benchmarks.google_message3.Message10818 field11883 = 13;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field11884 = 16;
-  optional .benchmarks.google_message3.Message10155 field11885 = 11;
-  optional .benchmarks.google_message3.Message10469 field11886 = 14;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field11887 = 15;
-  extensions 9 to 9;
-  extensions 10 to 10;
-}
-
-message Message35506 {
-  optional int32 field35524 = 1;
-  optional string field35525 = 2;
-  optional .benchmarks.google_message3.Enum35507 field35526 = 3;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field35527 = 4;
-}
-
-message Message13151 {
-  repeated .benchmarks.google_message3.Message13145 field13158 = 1;
-}
-
-message Message18253 {
-  repeated group Message18254 = 1 {
-    required fixed64 field18362 = 2;
-    required double field18363 = 3;
-  }
-}
-
-message Message16685 {
-  repeated .benchmarks.google_message3.Message16686 field16694 = 2;
-}
-
-message Message16816 {
-  optional float field16826 = 1;
-  optional .benchmarks.google_message3.Enum16819 field16827 = 2;
-  optional float field16828 = 3;
-  repeated group Message16817 = 4 {}
-  optional bool field16830 = 7;
-  optional bool field16831 = 8;
-  repeated group Message16818 = 12 {}
-  optional string field16833 = 10;
-  optional bool field16834 = 13;
-  optional bool field16835 = 14;
-}
-
-message Message13168 {
-  required int32 field13212 = 1;
-  optional fixed64 field13213 = 7;
-  optional bool field13214 = 8;
-  optional fixed64 field13215 = 10;
-  optional bool field13216 = 11;
-  optional .benchmarks.google_message3.Message12796 field13217 = 9;
-  required double field13218 = 2;
-  required bool field13219 = 3;
-  optional int32 field13220 = 4;
-  required bool field13221 = 5;
-  optional int32 field13222 = 6;
-}
-
-message Message13167 {
-  required int32 field13199 = 1;
-  optional int32 field13200 = 2;
-  optional int32 field13201 = 3;
-  optional bool field13202 = 8;
-  optional fixed64 field13203 = 12;
-  optional bool field13204 = 13;
-  optional .benchmarks.google_message3.Message12796 field13205 = 11;
-  optional fixed64 field13206 = 9;
-  optional bool field13207 = 10;
-  repeated int32 field13208 = 4;
-  optional int32 field13209 = 5;
-  optional int32 field13210 = 6;
-  optional int32 field13211 = 7;
-}
-
-message Message1374 {
-  required string field1375 = 1;
-  optional string field1376 = 2;
-}
-
-message Message18943 {}
-
-message Message18944 {}
-
-message Message18856 {
-  optional string field18857 = 1;
-  optional string field18858 = 2;
-  optional bool field18859 = 31;
-  optional string field18860 = 26;
-  optional string field18861 = 3;
-  optional string field18862 = 4;
-  optional string field18863 = 5;
-  optional string field18864 = 17;
-  optional string field18865 = 6;
-  optional string field18866 = 7;
-  optional string field18867 = 8;
-  optional string field18868 = 9;
-  optional string field18869 = 10;
-  optional string field18870 = 11;
-  optional string field18871 = 21;
-  optional string field18872 = 18;
-  optional string field18873 = 19;
-  optional string field18874 = 20;
-  optional string field18875 = 22;
-  optional string field18876 = 23;
-  optional string field18877 = 24;
-  optional string field18878 = 25;
-  optional string field18879 = 12;
-  optional string field18880 = 13;
-  optional string field18881 = 29;
-  optional string field18882 = 30;
-  optional string field18883 = 15;
-  optional string field18884 = 16;
-  repeated string field18885 = 14;
-  optional string field18886 = 27;
-  optional string field18887 = 28;
-}
-
-message Message3850 {
-  optional .benchmarks.google_message3.Enum3851 field3924 = 2;
-  optional bool field3925 = 12;
-  optional int32 field3926 = 4;
-  optional bool field3927 = 10;
-  optional bool field3928 = 13;
-  optional bool field3929 = 14;
-}
-
-message Message6721 {
-  optional .benchmarks.google_message3.Message6722 field6744 = 1;
-  optional bool field6745 = 2;
-  optional bool field6746 = 3;
-  optional bool field6747 = 4;
-}
-
-message Message6742 {
-  optional bool field6758 = 1;
-}
-
-message Message6726 {
-  optional int64 field6752 = 1;
-  repeated .benchmarks.google_message3.Message6727 field6753 = 2;
-}
-
-message Message6733 {
-  optional int64 field6754 = 1;
-  optional int64 field6755 = 2;
-  optional bool field6756 = 3;
-}
-
-message Message6723 {
-  optional int64 field6748 = 1;
-  repeated .benchmarks.google_message3.Message6724 field6749 = 2;
-}
-
-message Message6725 {
-  optional int32 field6750 = 1;
-  optional int32 field6751 = 2;
-}
-
-message Message6734 {
-  repeated .benchmarks.google_message3.Message6735 field6757 = 1;
-}
-
-message Message8184 {
-  optional .benchmarks.google_message3.Message7966 field8228 = 1;
-  optional bool field8229 = 2;
-  repeated .benchmarks.google_message3.Message8183 field8230 = 3;
-}
-
-message Message8477 {
-  optional .benchmarks.google_message3.Message7966 field8486 = 1;
-  optional int64 field8487 = 2;
-  optional string field8488 = 3;
-}
-
-message Message8454 {
-  optional .benchmarks.google_message3.Message8449 field8465 = 1;
-  optional int64 field8466 = 3;
-  optional int32 field8467 = 4;
-  optional bool field8468 = 5;
-  extend .benchmarks.google_message3.Message8301 {
-    optional .benchmarks.google_message3.Message8454 field8469 = 66;
-  }
-}
-
-message Message8476 {
-  optional string field8483 = 1;
-  optional string field8484 = 2;
-  optional string field8485 = 3;
-}
-
-message Message8455 {
-  optional .benchmarks.google_message3.Message8449 field8470 = 1;
-  repeated .benchmarks.google_message3.Message8456 field8471 = 2;
-  optional .benchmarks.google_message3.Message8457 field8472 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8473 = 6;
-  extend .benchmarks.google_message3.Message8302 {
-    optional .benchmarks.google_message3.Message8455 field8474 = 66;
-  }
-}
-
-message Message8475 {
-  optional string field8481 = 1;
-  optional int64 field8482 = 2;
-}
-
-message Message12559 {}
-
-message Message12817 {
-  optional int32 field12826 = 1;
-  optional int32 field12827 = 2;
-  optional int32 field12828 = 3;
-}
-
-message Message16480 {
-  optional .benchmarks.google_message3.Message13358 field16490 = 1;
-  optional .benchmarks.google_message3.Enum16042 field16491 = 2;
-  optional .benchmarks.google_message3.Message13912 field16492 = 3;
-  optional string field16493 = 4;
-  optional string field16494 = 5;
-  optional string field16495 = 6;
-  optional string field16496 = 7;
-  optional .benchmarks.google_message3.Message13358 field16497 = 8;
-  optional fixed32 field16498 = 9;
-}
-
-message Message24317 {
-  optional string field24446 = 1;
-  optional .benchmarks.google_message3.Message24312 field24447 = 2;
-  repeated .benchmarks.google_message3.Message24315 field24448 = 3;
-  repeated .benchmarks.google_message3.Message24313 field24449 = 4;
-  repeated .benchmarks.google_message3.Message24316 field24450 = 5;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field24451 = 6;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field24452 = 7;
-  repeated string field24453 = 8;
-  repeated string field24454 = 9;
-  repeated string field24455 = 10;
-  repeated string field24456 = 28;
-  optional string field24457 = 11;
-  optional string field24458 = 12;
-  optional string field24459 = 13;
-  optional string field24460 = 14;
-  repeated string field24461 = 15;
-  optional string field24462 = 16;
-  repeated string field24463 = 17;
-  repeated string field24464 = 18;
-  repeated string field24465 = 19;
-  repeated string field24466 = 20;
-  repeated string field24467 = 21;
-  repeated string field24468 = 22;
-  repeated string field24469 = 23;
-  repeated string field24470 = 24;
-  optional string field24471 = 25;
-  optional string field24472 = 26;
-  repeated string field24473 = 27;
-  optional bool field24474 = 40;
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_5.proto b/benchmarks/datasets/google_message3/benchmark_message3_5.proto
deleted file mode 100644
index e72d7ee..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_5.proto
+++ /dev/null
@@ -1,496 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message3;
-
-import "datasets/google_message3/benchmark_message3_6.proto";
-import "datasets/google_message3/benchmark_message3_7.proto";
-import "datasets/google_message3/benchmark_message3_8.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message24377 {}
-
-message Message24378 {}
-
-message Message24400 {
-  optional int32 field24674 = 1;
-  optional int32 field24675 = 2;
-  optional int32 field24676 = 3;
-  optional int32 field24677 = 4;
-  optional int32 field24678 = 5;
-}
-
-message Message24380 {}
-
-message Message24381 {}
-
-message Message719 {
-  repeated string field881 = 1;
-  repeated string field882 = 2;
-  repeated string field883 = 3;
-  optional .benchmarks.google_message3.Enum720 field884 = 4;
-}
-
-message Message728 {
-  required string field887 = 1;
-  repeated string field888 = 2;
-  repeated .benchmarks.google_message3.Message703 field889 = 3;
-  repeated .benchmarks.google_message3.Message715 field890 = 4;
-  repeated string field891 = 5;
-  repeated string field892 = 6;
-  optional .benchmarks.google_message3.Message718 field893 = 7;
-  optional .benchmarks.google_message3.Message716 field894 = 8;
-  repeated string field895 = 9;
-  extensions 10 to 10;
-  extensions 11 to 11;
-  extensions 12 to 12;
-}
-
-message Message704 {
-  optional string field800 = 1;
-  optional string field801 = 7;
-  optional string field802 = 2;
-  optional string field803 = 3;
-  optional string field804 = 4;
-  optional string field805 = 5;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field806 = 6;
-}
-
-message Message697 {
-  optional string field743 = 7;
-  repeated string field744 = 1;
-  repeated string field745 = 2;
-  repeated string field746 = 33;
-  repeated string field747 = 29;
-  repeated string field748 = 30;
-  repeated string field749 = 31;
-  repeated string field750 = 32;
-  repeated string field751 = 13;
-  repeated string field752 = 6;
-  repeated string field753 = 3;
-  repeated string field754 = 14;
-  repeated string field755 = 15;
-  repeated string field756 = 16;
-  repeated string field757 = 4;
-  repeated string field758 = 34;
-  repeated string field759 = 35;
-  repeated string field760 = 5;
-  repeated string field761 = 17;
-  repeated string field762 = 18;
-  repeated string field763 = 19;
-  optional bool field764 = 36;
-  repeated string field765 = 8;
-  repeated string field766 = 9;
-  optional string field767 = 27;
-  optional bool field768 = 25;
-  optional .benchmarks.google_message3.Message700 field769 = 10;
-  optional bool field770 = 11;
-  optional bool field771 = 24;
-  repeated string field772 = 12;
-  repeated string field773 = 20;
-  repeated string field774 = 21;
-  repeated string field775 = 22;
-  repeated .benchmarks.google_message3.Message699 field776 = 23;
-  repeated .benchmarks.google_message3.Message698 field777 = 37;
-  optional int64 field778 = 38;
-  extensions 28 to 28;
-  extensions 26 to 26;
-}
-
-message Message0 {
-  option message_set_wire_format = true;
-
-  extensions 4 to 2147483646;
-}
-
-message Message6578 {
-  optional .benchmarks.google_message3.Enum6579 field6632 = 1;
-  optional .benchmarks.google_message3.Enum6588 field6633 = 2;
-}
-
-message Message6024 {
-  optional .benchmarks.google_message3.Enum6025 field6048 = 1;
-  optional string field6049 = 2;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field6050 = 3;
-}
-
-message Message6052 {
-  required string field6084 = 1;
-  required bytes field6085 = 2;
-}
-
-message Message6054 {
-  required string field6089 = 1;
-  optional string field6090 = 2;
-}
-
-message Message10573 {
-  repeated .benchmarks.google_message3.Message10576 field10580 = 1;
-  optional string field10581 = 2;
-  extensions 10000 to 536870911;
-}
-
-message Message10824 {
-  required string field10825 = 1;
-  optional int32 field10826 = 2;
-}
-
-message Message10582 {
-  required bool field10583 = 1;
-  required double field10584 = 2;
-  optional bool field10585 = 3;
-  optional double field10586 = 4;
-  optional double field10587 = 5;
-  optional bool field10588 = 6;
-}
-
-message Message10155 {
-  required int32 field10195 = 1;
-  required int32 field10196 = 2;
-  optional .benchmarks.google_message3.Enum10157 field10197 = 59;
-  optional int32 field10198 = 18;
-  optional int32 field10199 = 19;
-  optional int32 field10200 = 21;
-  repeated group Message10156 = 50 {
-    optional .benchmarks.google_message3.Enum8862 field10266 = 51;
-    optional int32 field10267 = 52;
-    optional int32 field10268 = 53;
-    optional int32 field10269 = 54;
-  }
-  optional int32 field10202 = 3;
-  optional int32 field10203 = 4;
-  optional int32 field10204 = 5;
-  optional bool field10205 = 84;
-  optional bool field10206 = 33;
-  optional int32 field10207 = 75;
-  optional float field10208 = 26;
-  optional int32 field10209 = 27;
-  optional int32 field10210 = 49;
-  optional int32 field10211 = 10;
-  optional float field10212 = 78;
-  optional .benchmarks.google_message3.Message9151 field10213 = 91;
-  optional int32 field10214 = 11;
-  optional int32 field10215 = 12;
-  optional float field10216 = 41;
-  optional .benchmarks.google_message3.Message10154 field10217 = 61;
-  optional int32 field10218 = 23;
-  optional bytes field10219 = 24;
-  optional int32 field10220 = 65;
-  repeated bytes field10221 = 66;
-  optional int32 field10222 = 70;
-  optional bytes field10223 = 71;
-  repeated fixed64 field10224 = 73;
-  optional float field10225 = 29;
-  optional int32 field10226 = 30;
-  optional float field10227 = 31;
-  optional int32 field10228 = 32;
-  optional float field10229 = 34;
-  optional int32 field10230 = 35;
-  optional string field10231 = 22;
-  optional fixed64 field10232 = 13;
-  optional fixed64 field10233 = 20;
-  optional bool field10234 = 79;
-  repeated .benchmarks.google_message3.Enum10167 field10235 = 80
-      [packed = true];
-  optional int32 field10236 = 14;
-  optional int32 field10237 = 15;
-  optional int32 field10238 = 28;
-  repeated string field10239 = 16;
-  optional .benchmarks.google_message3.Message9182 field10240 = 17;
-  optional int32 field10241 = 63;
-  optional float field10242 = 64;
-  optional float field10243 = 37;
-  repeated float field10244 = 43;
-  optional int32 field10245 = 44;
-  optional .benchmarks.google_message3.Message9242 field10246 = 45;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field10247 = 46;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field10248 = 62;
-  optional .benchmarks.google_message3.Message8944 field10249 = 48;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field10250 = 87;
-  optional int32 field10251 = 58;
-  optional int32 field10252 = 92;
-  optional .benchmarks.google_message3.Message9123 field10253 = 93;
-  optional .benchmarks.google_message3.Message9160 field10254 = 60;
-  optional .benchmarks.google_message3.Message8890 field10255 = 67;
-  optional string field10256 = 69;
-  optional int64 field10257 = 74;
-  optional float field10258 = 82;
-  optional float field10259 = 85;
-  optional float field10260 = 86;
-  optional int64 field10261 = 83;
-  optional string field10262 = 77;
-  optional bool field10263 = 88;
-  repeated .benchmarks.google_message3.Message9628 field10264 = 94;
-  extensions 57 to 57;
-  extensions 1000 to 536870911;
-}
-
-message Message11866 {
-  required .benchmarks.google_message3.Message11014 field11868 = 1;
-  optional bool field11869 = 2;
-  optional double field11870 = 3;
-  optional double field11871 = 4;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field11872 = 5;
-}
-
-message Message10469 {
-  optional string field10473 = 1;
-  optional float field10474 = 2;
-  optional int32 field10475 = 3;
-  optional int32 field10476 = 4;
-  optional int32 field10477 = 5;
-  optional bool field10478 = 6;
-  optional bool field10479 = 7;
-  optional int32 field10480 = 8;
-  optional float field10481 = 9;
-}
-
-message Message10818 {
-  optional .benchmarks.google_message3.Message10800 field10819 = 1;
-  optional .benchmarks.google_message3.Message10801 field10820 = 2;
-}
-
-message Message10773 {
-  optional bool field10774 = 9;
-  optional bool field10775 = 1;
-  optional bool field10776 = 23;
-  optional bool field10777 = 2;
-  optional bool field10778 = 3;
-  optional int32 field10779 = 4;
-  optional int32 field10780 = 5;
-  optional int32 field10781 = 6;
-  optional int32 field10782 = 7;
-  optional int32 field10783 = 8;
-  optional int32 field10784 = 10;
-  optional .benchmarks.google_message3.Message10749 field10785 = 11;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field10786 = 12;
-  optional bool field10787 = 13;
-  optional bool field10788 = 15;
-  optional bool field10789 = 16;
-  optional int32 field10790 = 17;
-  optional int32 field10791 = 18;
-  optional bool field10792 = 19;
-  optional bool field10793 = 20;
-  optional bool field10794 = 21;
-  optional .benchmarks.google_message3.UnusedEnum field10795 = 14;
-  optional .benchmarks.google_message3.UnusedEnum field10796 = 22;
-}
-
-message Message13145 {
-  required .benchmarks.google_message3.Enum13146 field13155 = 1;
-  optional float field13156 = 2;
-  optional float field13157 = 3;
-  extensions 1000 to 536870911;
-}
-
-message Message16686 {}
-
-message Message12796 {
-  repeated fixed64 field12800 = 1;
-  optional uint64 field12801 = 2;
-}
-
-message Message6722 {}
-
-message Message6727 {}
-
-message Message6724 {}
-
-message Message6735 {}
-
-message Message8183 {
-  optional string field8226 = 1;
-  optional string field8227 = 2;
-}
-
-message Message8301 {
-  optional string field8328 = 1;
-  optional .benchmarks.google_message3.Message7966 field8329 = 2;
-  optional string field8330 = 3;
-  optional string field8331 = 4;
-  repeated .benchmarks.google_message3.Message8290 field8332 = 5;
-  optional .benchmarks.google_message3.Message7966 field8333 = 6;
-  repeated .benchmarks.google_message3.Message8298 field8334 = 7;
-  optional .benchmarks.google_message3.Message8300 field8335 = 8;
-  optional int64 field8336 = 9;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8337 = 10;
-  optional .benchmarks.google_message3.Message7965 field8338 = 11;
-  extensions 64 to 536870911;
-}
-
-message Message8456 {}
-
-message Message8302 {
-  optional string field8339 = 1;
-  optional .benchmarks.google_message3.Message7966 field8340 = 2;
-  optional string field8341 = 3;
-  optional string field8342 = 4;
-  optional string field8343 = 5;
-  optional string field8344 = 6;
-  optional string field8345 = 7;
-  optional int64 field8346 = 8;
-  optional int64 field8347 = 9;
-  repeated .benchmarks.google_message3.Message8290 field8348 = 10;
-  optional string field8349 = 11;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8350 = 12;
-  optional .benchmarks.google_message3.Message8291 field8351 = 13;
-  optional int64 field8352 = 14;
-  optional .benchmarks.google_message3.Message8296 field8353 = 15;
-  optional string field8354 = 16;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field8355 = 17;
-  repeated int32 field8356 = 18;
-  repeated int32 field8357 = 19;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field8358 = 20;
-  optional .benchmarks.google_message3.Message7965 field8359 = 21;
-  extensions 64 to 536870911;
-}
-
-message Message8457 {}
-
-message Message8449 {
-  optional string field8458 = 1;
-  optional bool field8459 = 2;
-  optional .benchmarks.google_message3.Enum8450 field8460 = 3;
-  repeated string field8461 = 4;
-  optional string field8462 = 5;
-  optional string field8463 = 6;
-  optional .benchmarks.google_message3.Message7966 field8464 = 7;
-}
-
-message Message13358 {
-  required fixed64 field13359 = 1;
-  required fixed64 field13360 = 2;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field13361 = 3;
-}
-
-message Message13912 {
-  required fixed32 field13913 = 1;
-  required fixed32 field13914 = 2;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field13915 = 500;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field13916 = 15;
-}
-
-message Message24316 {
-  repeated string field24443 = 1;
-  repeated string field24444 = 2;
-  repeated string field24445 = 3;
-}
-
-message Message24312 {
-  optional string field24421 = 1;
-  optional string field24422 = 2;
-  repeated string field24423 = 3;
-  repeated string field24424 = 4;
-  repeated string field24425 = 5;
-  repeated string field24426 = 6;
-}
-
-message Message24313 {
-  optional string field24427 = 1;
-  optional string field24428 = 2;
-  repeated string field24429 = 3;
-  optional string field24430 = 4;
-  optional string field24431 = 5;
-  optional string field24432 = 6;
-  optional string field24433 = 7;
-  repeated string field24434 = 8;
-  optional string field24435 = 9;
-  repeated string field24436 = 10;
-}
-
-message Message24315 {
-  required string field24440 = 1;
-  repeated string field24441 = 2;
-  repeated string field24442 = 3;
-}
-
-message Message716 {
-  required string field872 = 1;
-  required int32 field873 = 2;
-  optional bool field874 = 3;
-  optional .benchmarks.google_message3.Message717 field875 = 4;
-}
-
-message Message718 {
-  repeated string field878 = 1;
-  repeated string field879 = 2;
-  optional string field880 = 3;
-}
-
-message Message703 {
-  required string field795 = 1;
-  repeated string field796 = 2;
-  repeated string field797 = 3;
-  optional string field798 = 4;
-  repeated string field799 = 5;
-}
-
-message Message715 {
-  required string field859 = 1;
-  optional string field860 = 7;
-  repeated .benchmarks.google_message3.Message707 field861 = 2;
-  repeated .benchmarks.google_message3.Message708 field862 = 3;
-  repeated .benchmarks.google_message3.Message711 field863 = 4;
-  repeated .benchmarks.google_message3.Message712 field864 = 5;
-  repeated .benchmarks.google_message3.Message713 field865 = 6;
-  repeated .benchmarks.google_message3.Message714 field866 = 8;
-  repeated .benchmarks.google_message3.Message710 field867 = 9;
-  repeated .benchmarks.google_message3.Message709 field868 = 10;
-  repeated .benchmarks.google_message3.Message705 field869 = 11;
-  repeated .benchmarks.google_message3.Message702 field870 = 12;
-  repeated .benchmarks.google_message3.Message706 field871 = 13;
-}
-
-message Message700 {
-  repeated string field789 = 1;
-  repeated string field790 = 2;
-}
-
-message Message699 {
-  required string field787 = 1;
-  repeated string field788 = 2;
-}
-
-message Message698 {
-  optional string field779 = 1;
-  optional string field780 = 2;
-  optional string field781 = 3;
-  optional string field782 = 4;
-  optional uint64 field783 = 5;
-  optional uint32 field784 = 6;
-  optional int64 field785 = 7;
-  repeated string field786 = 8;
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_6.proto b/benchmarks/datasets/google_message3/benchmark_message3_6.proto
deleted file mode 100644
index c766f7c..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_6.proto
+++ /dev/null
@@ -1,483 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message3;
-
-import "datasets/google_message3/benchmark_message3_7.proto";
-import "datasets/google_message3/benchmark_message3_8.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message10576 {}
-
-message Message10154 {
-  optional bytes field10192 = 1;
-  optional int32 field10193 = 2;
-}
-
-message Message8944 {
-  optional string field9045 = 2;
-  optional string field9046 = 3;
-  optional string field9047 = 23;
-  optional string field9048 = 52;
-  optional int32 field9049 = 53;
-  optional int32 field9050 = 54;
-  optional float field9051 = 55;
-  optional float field9052 = 56;
-  optional string field9053 = 57;
-  optional int64 field9054 = 1;
-  optional bool field9055 = 4;
-  optional int32 field9056 = 5;
-  optional int32 field9057 = 6;
-  optional int32 field9058 = 7;
-  optional float field9059 = 8;
-  optional float field9060 = 11;
-  optional float field9061 = 9;
-  optional float field9062 = 10;
-  optional float field9063 = 13;
-  optional bool field9064 = 14;
-  optional float field9065 = 70;
-  optional int32 field9066 = 71;
-  optional .benchmarks.google_message3.Enum8945 field9067 = 15;
-  optional int32 field9068 = 16;
-  optional int32 field9069 = 17;
-  optional float field9070 = 18;
-  optional float field9071 = 19;
-  optional int32 field9072 = 28;
-  optional int32 field9073 = 29;
-  optional float field9074 = 60;
-  optional float field9075 = 61;
-  optional int32 field9076 = 72;
-  optional int32 field9077 = 73;
-  optional .benchmarks.google_message3.Enum8951 field9078 = 62;
-  optional string field9079 = 20;
-  optional string field9080 = 21;
-  optional string field9081 = 22;
-  optional double field9082 = 31;
-  optional double field9083 = 32;
-  optional double field9084 = 33;
-  optional double field9085 = 36;
-  optional .benchmarks.google_message3.UnusedEnum field9086 = 37;
-  optional double field9087 = 38;
-  optional double field9088 = 39;
-  optional double field9089 = 63;
-  optional double field9090 = 64;
-  optional double field9091 = 65;
-  optional double field9092 = 34;
-  optional .benchmarks.google_message3.UnusedEnum field9093 = 35;
-  optional .benchmarks.google_message3.UnusedEnum field9094 = 66;
-  optional string field9095 = 40;
-  optional string field9096 = 41;
-  optional string field9097 = 42;
-  optional string field9098 = 43;
-  optional string field9099 = 44;
-  optional string field9100 = 45;
-  optional string field9101 = 46;
-  optional string field9102 = 47;
-  optional string field9103 = 48;
-  optional string field9104 = 49;
-  optional .benchmarks.google_message3.Message8939 field9105 = 100;
-  optional int64 field9106 = 101;
-}
-
-message Message9182 {
-  optional string field9205 = 1;
-  optional string field9206 = 2;
-  optional float field9207 = 16;
-  optional int32 field9208 = 17;
-  optional int32 field9209 = 27;
-  optional int32 field9210 = 7;
-  optional int32 field9211 = 8;
-  optional float field9212 = 26;
-  optional float field9213 = 22;
-  optional bool field9214 = 28;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field9215 = 21;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field9216 = 25;
-  repeated .benchmarks.google_message3.Message9181 field9217 = 29;
-  optional bool field9218 = 18;
-  optional bool field9219 = 19;
-  optional bool field9220 = 20;
-  optional .benchmarks.google_message3.Message9164 field9221 = 30;
-  optional .benchmarks.google_message3.Message9165 field9222 = 31;
-  optional .benchmarks.google_message3.Message9166 field9223 = 32;
-  optional float field9224 = 33;
-  optional .benchmarks.google_message3.Message9151 field9225 = 34;
-  optional float field9226 = 35;
-  optional float field9227 = 36;
-  optional float field9228 = 37;
-  optional float field9229 = 38;
-  optional float field9230 = 39;
-  extensions 3 to 6;
-  extensions 9 to 15;
-  extensions 23 to 23;
-  extensions 24 to 24;
-  extensions 1000 to 536870911;
-}
-
-message Message9160 {
-  optional int32 field9161 = 1;
-  optional bytes field9162 = 2;
-}
-
-message Message9242 {
-  repeated .benchmarks.google_message3.Enum9243 field9327 = 1;
-}
-
-message Message8890 {
-  repeated .benchmarks.google_message3.Message8888 field8916 = 1;
-}
-
-message Message9123 {
-  optional float field9135 = 1;
-}
-
-message Message9628 {
-  optional .benchmarks.google_message3.Message9627 field9673 = 1;
-  optional string field9674 = 2;
-  repeated int32 field9675 = 3;
-  optional int32 field9676 = 4;
-}
-
-message Message11014 {
-  optional int32 field11780 = 40;
-  optional string field11781 = 46;
-  optional bool field11782 = 47;
-  optional .benchmarks.google_message3.Enum11107 field11783 = 1;
-  optional int32 field11784 = 2;
-  optional double field11785 = 4;
-  optional int32 field11786 = 5;
-  optional int32 field11787 = 6;
-  optional double field11788 = 7;
-  optional double field11789 = 8;
-  optional int64 field11790 = 9;
-  optional bool field11791 = 10;
-  optional int64 field11792 = 28;
-  optional bool field11793 = 37;
-  optional .benchmarks.google_message3.Enum11541 field11794 = 44;
-  optional double field11795 = 49;
-  optional double field11796 = 51;
-  optional int64 field11797 = 54;
-  optional int64 field11798 = 55;
-  optional .benchmarks.google_message3.UnusedEnum field11799 = 57;
-  optional .benchmarks.google_message3.Enum11468 field11800 = 58;
-  optional int32 field11801 = 59;
-  optional .benchmarks.google_message3.UnusedEnum field11802 = 60;
-  optional int32 field11803 = 61;
-  optional int32 field11804 = 62;
-  optional int32 field11805 = 69;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field11806 = 68;
-  repeated .benchmarks.google_message3.Message11018 field11807 = 71;
-  optional bool field11808 = 50;
-  optional bool field11809 = 56;
-  optional bool field11810 = 66;
-  optional bool field11811 = 63;
-  optional bool field11812 = 64;
-  optional bool field11813 = 65;
-  optional bool field11814 = 67;
-  optional .benchmarks.google_message3.Enum11107 field11815 = 15;
-  optional int64 field11816 = 16;
-  optional double field11817 = 17;
-  optional int64 field11818 = 18;
-  optional int32 field11819 = 19;
-  optional int64 field11820 = 20;
-  optional int32 field11821 = 42;
-  optional int64 field11822 = 52;
-  optional int64 field11823 = 53;
-  optional int64 field11824 = 41;
-  optional double field11825 = 48;
-  repeated .benchmarks.google_message3.Message11020 field11826 = 70;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field11827 = 72;
-  optional double field11828 = 25;
-  optional string field11829 = 26;
-  optional int64 field11830 = 27;
-  optional int64 field11831 = 32;
-  optional uint64 field11832 = 33;
-  optional bool field11833 = 29;
-  optional bool field11834 = 34;
-  optional string field11835 = 30;
-  optional int32 field11836 = 3;
-  optional int32 field11837 = 31;
-  optional int32 field11838 = 73;
-  optional int32 field11839 = 35;
-  optional .benchmarks.google_message3.Enum11022 field11840 = 36;
-  optional .benchmarks.google_message3.Message11013 field11841 = 38;
-  optional double field11842 = 39;
-  optional int32 field11843 = 45;
-  optional bool field11844 = 74;
-}
-
-message Message10801 {
-  optional .benchmarks.google_message3.Message10800 field10812 = 1;
-  repeated .benchmarks.google_message3.Message10802 field10813 = 2;
-  optional int32 field10814 = 3;
-}
-
-message Message10749 {
-  repeated .benchmarks.google_message3.Message10748 field10754 = 1;
-}
-
-message Message8298 {
-  optional .benchmarks.google_message3.Message7966 field8321 = 1;
-  optional int64 field8322 = 2;
-  optional string field8323 = 3;
-}
-
-message Message8300 {
-  optional string field8326 = 1;
-  optional .benchmarks.google_message3.Message7966 field8327 = 2;
-}
-
-message Message8291 {
-  optional string field8306 = 1;
-  optional int32 field8307 = 2;
-  optional string field8308 = 3;
-  optional string field8309 = 4;
-  optional .benchmarks.google_message3.Enum8292 field8310 = 5;
-}
-
-message Message8296 {
-  optional .benchmarks.google_message3.Message7966 field8311 = 1;
-  optional string field8312 = 2;
-  optional .benchmarks.google_message3.Message7966 field8313 = 3;
-  optional int32 field8314 = 4;
-  optional int32 field8315 = 5;
-  optional string field8316 = 6;
-}
-
-message Message7965 {
-  optional int32 field7967 = 1;
-  optional int32 field7968 = 2;
-}
-
-message Message8290 {
-  optional string field8304 = 1;
-  optional string field8305 = 2;
-}
-
-message Message717 {
-  repeated string field876 = 1;
-  optional double field877 = 2;
-}
-
-message Message713 {
-  required .benchmarks.google_message3.Message708 field852 = 1;
-  repeated string field853 = 2;
-}
-
-message Message705 {
-  required string field807 = 1;
-  optional string field808 = 2;
-  optional string field809 = 3;
-  optional bool field810 = 4;
-  optional string field811 = 5;
-  optional string field812 = 6;
-  repeated string field813 = 7;
-}
-
-message Message709 {
-  repeated string field829 = 1;
-  repeated string field830 = 2;
-  repeated string field831 = 3;
-  repeated string field832 = 4;
-  repeated string field833 = 5;
-}
-
-message Message702 {
-  optional string field793 = 1;
-  optional string field794 = 2;
-}
-
-message Message714 {
-  optional string field854 = 1;
-  optional string field855 = 2;
-  optional string field856 = 3;
-  optional string field857 = 4;
-  optional uint32 field858 = 5;
-}
-
-message Message710 {
-  repeated string field834 = 1;
-  optional string field835 = 2;
-  optional string field836 = 3;
-  repeated string field837 = 4;
-  repeated string field838 = 5;
-}
-
-message Message706 {
-  repeated string field814 = 1;
-  optional string field815 = 2;
-  repeated string field816 = 3;
-  repeated string field817 = 4;
-}
-
-message Message707 {
-  required string field818 = 1;
-  required string field819 = 2;
-  required string field820 = 3;
-  optional bool field821 = 4;
-  repeated string field822 = 5;
-}
-
-message Message711 {
-  optional .benchmarks.google_message3.UnusedEmptyMessage field839 = 1;
-  repeated string field840 = 4;
-  repeated string field841 = 2;
-  repeated string field842 = 3;
-}
-
-message Message712 {
-  repeated string field843 = 1;
-  required string field844 = 2;
-  optional string field845 = 3;
-  repeated string field846 = 4;
-  repeated string field847 = 5;
-  optional string field848 = 6;
-  repeated string field849 = 7;
-  optional string field850 = 8;
-  optional string field851 = 9;
-}
-
-message Message8939 {
-  optional string field9010 = 1;
-  optional string field9011 = 2;
-  optional string field9012 = 3;
-  repeated string field9013 = 4;
-  optional string field9014 = 5;
-  repeated group Message8940 = 11 {}
-  optional int64 field9016 = 21;
-  optional int64 field9017 = 22;
-  optional int64 field9018 = 23;
-  optional group Message8941 = 31 {
-    optional string field9033 = 32;
-    optional string field9034 = 33;
-    optional string field9035 = 34;
-    optional string field9036 = 35;
-    optional string field9037 = 36;
-    optional string field9038 = 37;
-  }
-  optional .benchmarks.google_message3.Message8942 field9020 = 38;
-  repeated .benchmarks.google_message3.UnusedEmptyMessage field9021 = 39;
-  repeated string field9022 = 41;
-  optional string field9023 = 42;
-  optional string field9024 = 43;
-  optional string field9025 = 44;
-  optional string field9026 = 45;
-  optional string field9027 = 46;
-  optional string field9028 = 47;
-  optional .benchmarks.google_message3.UnusedEnum field9029 = 48;
-  optional .benchmarks.google_message3.UnusedEnum field9030 = 49;
-  optional group Message8943 = 51 {
-    optional string field9039 = 1;
-    optional string field9040 = 2;
-    optional string field9041 = 3;
-    optional string field9042 = 4;
-    optional string field9043 = 5;
-    optional string field9044 = 6;
-  }
-}
-
-message Message9181 {
-  optional string field9204 = 1;
-}
-
-message Message9164 {
-  optional int32 field9168 = 1;
-  optional int32 field9169 = 2;
-  optional int32 field9170 = 3;
-}
-
-message Message9165 {
-  optional float field9171 = 1;
-  optional float field9172 = 2;
-}
-
-message Message9166 {
-  optional float field9173 = 1;
-  optional int32 field9174 = 2;
-}
-
-message Message9151 {
-  optional double field9152 = 1;
-  optional double field9153 = 2;
-  optional float field9154 = 3;
-  optional float field9155 = 4;
-  optional float field9156 = 5;
-  optional float field9157 = 6;
-  optional float field9158 = 7;
-  optional float field9159 = 8;
-}
-
-message Message8888 {
-  optional int32 field8908 = 1;
-  optional .benchmarks.google_message3.Enum8900 field8909 = 4;
-  repeated int32 field8910 = 2 [packed = true];
-  optional bytes field8911 = 3;
-}
-
-message Message9627 {
-  required int32 field9668 = 1;
-  required int32 field9669 = 2;
-  required int32 field9670 = 3;
-  required int32 field9671 = 4;
-  optional float field9672 = 5;
-}
-
-message Message11020 {}
-
-message Message11013 {
-  optional bytes field11757 = 19;
-  optional bytes field11758 = 1;
-  optional bytes field11759 = 2;
-  optional bytes field11760 = 3;
-  optional bytes field11761 = 4;
-  optional bytes field11762 = 5;
-  optional bytes field11763 = 6;
-  optional bytes field11764 = 7;
-  optional bytes field11765 = 8;
-  optional bytes field11766 = 9;
-  optional bytes field11767 = 10;
-  optional bytes field11768 = 11;
-  optional bytes field11769 = 12;
-  optional bytes field11770 = 13;
-  optional bytes field11771 = 14;
-  optional bytes field11772 = 15;
-  optional bytes field11773 = 16;
-  optional bytes field11774 = 17;
-  optional bytes field11775 = 18;
-  optional bytes field11776 = 20;
-  optional bytes field11777 = 21;
-  optional .benchmarks.google_message3.UnusedEmptyMessage field11778 = 23;
-  repeated .benchmarks.google_message3.Message11011 field11779 = 22;
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_7.proto b/benchmarks/datasets/google_message3/benchmark_message3_7.proto
deleted file mode 100644
index 0f8f10c..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_7.proto
+++ /dev/null
@@ -1,81 +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";
-
-package benchmarks.google_message3;
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message11018 {}
-
-message Message10800 {
-  optional string field10808 = 1;
-  optional int64 field10809 = 2;
-  optional bool field10810 = 3;
-  optional float field10811 = 4;
-}
-
-message Message10802 {}
-
-message Message10748 {
-  optional string field10750 = 1;
-  optional int32 field10751 = 2;
-  optional int32 field10752 = 3;
-  optional int32 field10753 = 4;
-}
-
-message Message7966 {
-  optional string field7969 = 1;
-  optional bool field7970 = 2;
-}
-
-message Message708 {
-  optional .benchmarks.google_message3.Message741 field823 = 1;
-  repeated string field824 = 6;
-  optional string field825 = 2;
-  optional string field826 = 3;
-  repeated string field827 = 4;
-  repeated string field828 = 5;
-}
-
-message Message8942 {}
-
-message Message11011 {
-  required bytes field11752 = 1;
-  required bytes field11753 = 2;
-}
-
-message UnusedEmptyMessage {}
-
-message Message741 {
-  repeated string field936 = 1;
-}
diff --git a/benchmarks/datasets/google_message3/benchmark_message3_8.proto b/benchmarks/datasets/google_message3/benchmark_message3_8.proto
deleted file mode 100644
index 68fe8e9..0000000
--- a/benchmarks/datasets/google_message3/benchmark_message3_8.proto
+++ /dev/null
@@ -1,1925 +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";
-
-package benchmarks.google_message3;
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-enum Enum720 {
-  ENUM_VALUE721 = 1;
-  ENUM_VALUE722 = 2;
-}
-
-enum Enum3476 {
-  ENUM_VALUE3477 = 0;
-  ENUM_VALUE3478 = 1;
-  ENUM_VALUE3479 = 2;
-  ENUM_VALUE3480 = 3;
-  ENUM_VALUE3481 = 4;
-  ENUM_VALUE3482 = 5;
-  ENUM_VALUE3483 = 6;
-  ENUM_VALUE3484 = 7;
-  ENUM_VALUE3485 = 8;
-  ENUM_VALUE3486 = 9;
-  ENUM_VALUE3487 = 10;
-  ENUM_VALUE3488 = 11;
-  ENUM_VALUE3489 = 12;
-  ENUM_VALUE3490 = 13;
-  ENUM_VALUE3491 = 14;
-  ENUM_VALUE3492 = 15;
-  ENUM_VALUE3493 = 16;
-  ENUM_VALUE3494 = 17;
-  ENUM_VALUE3495 = 18;
-  ENUM_VALUE3496 = 19;
-  ENUM_VALUE3497 = 20;
-  ENUM_VALUE3498 = 21;
-  ENUM_VALUE3499 = 22;
-  ENUM_VALUE3500 = 23;
-  ENUM_VALUE3501 = 24;
-  ENUM_VALUE3502 = 25;
-  ENUM_VALUE3503 = 26;
-  ENUM_VALUE3504 = 27;
-  ENUM_VALUE3505 = 28;
-  ENUM_VALUE3506 = 29;
-  ENUM_VALUE3507 = 30;
-  ENUM_VALUE3508 = 31;
-  ENUM_VALUE3509 = 32;
-  ENUM_VALUE3510 = 33;
-  ENUM_VALUE3511 = 34;
-  ENUM_VALUE3512 = 35;
-  ENUM_VALUE3513 = 36;
-  ENUM_VALUE3514 = 37;
-  ENUM_VALUE3515 = 38;
-  ENUM_VALUE3516 = 39;
-  ENUM_VALUE3517 = 40;
-  ENUM_VALUE3518 = 41;
-  ENUM_VALUE3519 = 42;
-  ENUM_VALUE3520 = 43;
-  ENUM_VALUE3521 = 44;
-  ENUM_VALUE3522 = 45;
-  ENUM_VALUE3523 = 46;
-  ENUM_VALUE3524 = 47;
-  ENUM_VALUE3525 = 48;
-  ENUM_VALUE3526 = 49;
-  ENUM_VALUE3527 = 50;
-  ENUM_VALUE3528 = 51;
-  ENUM_VALUE3529 = 52;
-  ENUM_VALUE3530 = 53;
-  ENUM_VALUE3531 = 54;
-  ENUM_VALUE3532 = 55;
-  ENUM_VALUE3533 = 56;
-  ENUM_VALUE3534 = 57;
-  ENUM_VALUE3535 = 58;
-  ENUM_VALUE3536 = 59;
-  ENUM_VALUE3537 = 60;
-  ENUM_VALUE3538 = 61;
-  ENUM_VALUE3539 = 62;
-  ENUM_VALUE3540 = 63;
-  ENUM_VALUE3541 = 64;
-  ENUM_VALUE3542 = 65;
-  ENUM_VALUE3543 = 66;
-  ENUM_VALUE3544 = 67;
-  ENUM_VALUE3545 = 68;
-  ENUM_VALUE3546 = 69;
-  ENUM_VALUE3547 = 70;
-  ENUM_VALUE3548 = 71;
-  ENUM_VALUE3549 = 72;
-  ENUM_VALUE3550 = 73;
-  ENUM_VALUE3551 = 74;
-  ENUM_VALUE3552 = 75;
-  ENUM_VALUE3553 = 76;
-  ENUM_VALUE3554 = 77;
-  ENUM_VALUE3555 = 78;
-  ENUM_VALUE3556 = 79;
-  ENUM_VALUE3557 = 80;
-  ENUM_VALUE3558 = 81;
-  ENUM_VALUE3559 = 82;
-  ENUM_VALUE3560 = 83;
-  ENUM_VALUE3561 = 84;
-  ENUM_VALUE3562 = 85;
-  ENUM_VALUE3563 = 86;
-  ENUM_VALUE3564 = 87;
-  ENUM_VALUE3565 = 88;
-  ENUM_VALUE3566 = 89;
-  ENUM_VALUE3567 = 90;
-  ENUM_VALUE3568 = 91;
-  ENUM_VALUE3569 = 92;
-  ENUM_VALUE3570 = 93;
-  ENUM_VALUE3571 = 94;
-  ENUM_VALUE3572 = 95;
-  ENUM_VALUE3573 = 96;
-  ENUM_VALUE3574 = 97;
-  ENUM_VALUE3575 = 98;
-  ENUM_VALUE3576 = 99;
-  ENUM_VALUE3577 = 100;
-  ENUM_VALUE3578 = 101;
-  ENUM_VALUE3579 = 102;
-  ENUM_VALUE3580 = 103;
-  ENUM_VALUE3581 = 104;
-  ENUM_VALUE3582 = 105;
-  ENUM_VALUE3583 = 106;
-  ENUM_VALUE3584 = 107;
-  ENUM_VALUE3585 = 108;
-  ENUM_VALUE3586 = 109;
-  ENUM_VALUE3587 = 110;
-  ENUM_VALUE3588 = 111;
-  ENUM_VALUE3589 = 112;
-  ENUM_VALUE3590 = 113;
-  ENUM_VALUE3591 = 114;
-  ENUM_VALUE3592 = 115;
-  ENUM_VALUE3593 = 116;
-  ENUM_VALUE3594 = 117;
-  ENUM_VALUE3595 = 118;
-  ENUM_VALUE3596 = 119;
-  ENUM_VALUE3597 = 120;
-  ENUM_VALUE3598 = 121;
-  ENUM_VALUE3599 = 122;
-  ENUM_VALUE3600 = 123;
-  ENUM_VALUE3601 = 124;
-  ENUM_VALUE3602 = 125;
-  ENUM_VALUE3603 = 126;
-  ENUM_VALUE3604 = 127;
-  ENUM_VALUE3605 = 128;
-  ENUM_VALUE3606 = 129;
-  ENUM_VALUE3607 = 130;
-  ENUM_VALUE3608 = 131;
-  ENUM_VALUE3609 = 132;
-  ENUM_VALUE3610 = 133;
-  ENUM_VALUE3611 = 134;
-  ENUM_VALUE3612 = 135;
-  ENUM_VALUE3613 = 136;
-  ENUM_VALUE3614 = 137;
-  ENUM_VALUE3615 = 138;
-  ENUM_VALUE3616 = 139;
-  ENUM_VALUE3617 = 140;
-  ENUM_VALUE3618 = 141;
-  ENUM_VALUE3619 = 142;
-  ENUM_VALUE3620 = 143;
-  ENUM_VALUE3621 = 144;
-  ENUM_VALUE3622 = 145;
-  ENUM_VALUE3623 = 146;
-  ENUM_VALUE3624 = 147;
-  ENUM_VALUE3625 = 148;
-  ENUM_VALUE3626 = 149;
-  ENUM_VALUE3627 = 150;
-  ENUM_VALUE3628 = 151;
-  ENUM_VALUE3629 = 152;
-  ENUM_VALUE3630 = 153;
-  ENUM_VALUE3631 = 154;
-  ENUM_VALUE3632 = 155;
-  ENUM_VALUE3633 = 156;
-  ENUM_VALUE3634 = 157;
-  ENUM_VALUE3635 = 158;
-  ENUM_VALUE3636 = 159;
-  ENUM_VALUE3637 = 160;
-  ENUM_VALUE3638 = 161;
-  ENUM_VALUE3639 = 162;
-  ENUM_VALUE3640 = 163;
-  ENUM_VALUE3641 = 164;
-  ENUM_VALUE3642 = 165;
-  ENUM_VALUE3643 = 166;
-  ENUM_VALUE3644 = 167;
-  ENUM_VALUE3645 = 168;
-  ENUM_VALUE3646 = 169;
-  ENUM_VALUE3647 = 170;
-  ENUM_VALUE3648 = 171;
-  ENUM_VALUE3649 = 172;
-  ENUM_VALUE3650 = 173;
-  ENUM_VALUE3651 = 174;
-  ENUM_VALUE3652 = 175;
-  ENUM_VALUE3653 = 176;
-  ENUM_VALUE3654 = 177;
-  ENUM_VALUE3655 = 178;
-  ENUM_VALUE3656 = 179;
-  ENUM_VALUE3657 = 180;
-  ENUM_VALUE3658 = 181;
-  ENUM_VALUE3659 = 182;
-  ENUM_VALUE3660 = 183;
-}
-
-enum Enum3805 {
-  ENUM_VALUE3806 = 0;
-  ENUM_VALUE3807 = 1;
-  ENUM_VALUE3808 = 2;
-  ENUM_VALUE3809 = 3;
-  ENUM_VALUE3810 = 4;
-  ENUM_VALUE3811 = 5;
-  ENUM_VALUE3812 = 6;
-  ENUM_VALUE3813 = 7;
-  ENUM_VALUE3814 = 8;
-  ENUM_VALUE3815 = 9;
-  ENUM_VALUE3816 = 11;
-  ENUM_VALUE3817 = 10;
-}
-
-enum Enum3783 {
-  ENUM_VALUE3784 = 0;
-  ENUM_VALUE3785 = 1;
-  ENUM_VALUE3786 = 2;
-  ENUM_VALUE3787 = 3;
-  ENUM_VALUE3788 = 4;
-  ENUM_VALUE3789 = 5;
-  ENUM_VALUE3790 = 6;
-  ENUM_VALUE3791 = 7;
-  ENUM_VALUE3792 = 8;
-  ENUM_VALUE3793 = 9;
-  ENUM_VALUE3794 = 10;
-  ENUM_VALUE3795 = 11;
-  ENUM_VALUE3796 = 12;
-  ENUM_VALUE3797 = 13;
-  ENUM_VALUE3798 = 14;
-  ENUM_VALUE3799 = 15;
-  ENUM_VALUE3800 = 16;
-  ENUM_VALUE3801 = 20;
-  ENUM_VALUE3802 = 21;
-  ENUM_VALUE3803 = 50;
-}
-
-enum Enum3851 {
-  ENUM_VALUE3852 = 0;
-  ENUM_VALUE3853 = 1;
-  ENUM_VALUE3854 = 2;
-  ENUM_VALUE3855 = 3;
-  ENUM_VALUE3856 = 4;
-  ENUM_VALUE3857 = 5;
-  ENUM_VALUE3858 = 6;
-  ENUM_VALUE3859 = 7;
-  ENUM_VALUE3860 = 8;
-  ENUM_VALUE3861 = 9;
-  ENUM_VALUE3862 = 10;
-  ENUM_VALUE3863 = 11;
-  ENUM_VALUE3864 = 12;
-  ENUM_VALUE3865 = 13;
-  ENUM_VALUE3866 = 14;
-  ENUM_VALUE3867 = 15;
-  ENUM_VALUE3868 = 16;
-  ENUM_VALUE3869 = 17;
-}
-
-enum UnusedEnum {
-  UNUSED_ENUM_VALUE1 = 0;
-  UNUSED_ENUM_VALUE2 = 1;
-}
-
-enum Enum4146 {
-  ENUM_VALUE4147 = 0;
-  ENUM_VALUE4148 = 1;
-  ENUM_VALUE4149 = 2;
-  ENUM_VALUE4150 = 3;
-  ENUM_VALUE4151 = 4;
-}
-
-enum Enum4160 {
-  ENUM_VALUE4161 = 0;
-  ENUM_VALUE4162 = 1;
-}
-
-enum Enum4152 {
-  ENUM_VALUE4153 = 0;
-  ENUM_VALUE4154 = 1;
-  ENUM_VALUE4155 = 2;
-  ENUM_VALUE4156 = 3;
-  ENUM_VALUE4157 = 4;
-  ENUM_VALUE4158 = 5;
-  ENUM_VALUE4159 = 6;
-}
-
-enum Enum6025 {
-  ENUM_VALUE6026 = 0;
-  ENUM_VALUE6027 = 1;
-  ENUM_VALUE6028 = 2;
-  ENUM_VALUE6029 = 3;
-  ENUM_VALUE6030 = 4;
-  ENUM_VALUE6031 = 5;
-  ENUM_VALUE6032 = 6;
-  ENUM_VALUE6033 = 7;
-  ENUM_VALUE6034 = 8;
-  ENUM_VALUE6035 = 9;
-  ENUM_VALUE6036 = 10;
-  ENUM_VALUE6037 = 11;
-  ENUM_VALUE6038 = 12;
-  ENUM_VALUE6039 = 13;
-  ENUM_VALUE6040 = 14;
-  ENUM_VALUE6041 = 15;
-  ENUM_VALUE6042 = 16;
-  ENUM_VALUE6043 = 17;
-  ENUM_VALUE6044 = 18;
-  ENUM_VALUE6045 = 19;
-  ENUM_VALUE6046 = 20;
-  ENUM_VALUE6047 = 21;
-}
-
-enum Enum6065 {
-  ENUM_VALUE6066 = 0;
-  ENUM_VALUE6067 = 1;
-  ENUM_VALUE6068 = 2;
-  ENUM_VALUE6069 = 3;
-  ENUM_VALUE6070 = 4;
-  ENUM_VALUE6071 = 5;
-  ENUM_VALUE6072 = 6;
-  ENUM_VALUE6073 = 7;
-  ENUM_VALUE6074 = 8;
-  ENUM_VALUE6075 = 9;
-  ENUM_VALUE6076 = 10;
-  ENUM_VALUE6077 = 11;
-  ENUM_VALUE6078 = 12;
-  ENUM_VALUE6079 = 13;
-  ENUM_VALUE6080 = 14;
-}
-
-enum Enum6579 {
-  ENUM_VALUE6580 = 0;
-  ENUM_VALUE6581 = 2;
-  ENUM_VALUE6582 = 3;
-  ENUM_VALUE6583 = 5;
-  ENUM_VALUE6584 = 10;
-  ENUM_VALUE6585 = 15;
-  ENUM_VALUE6586 = 25;
-  ENUM_VALUE6587 = 30;
-}
-
-enum Enum6588 {
-  ENUM_VALUE6589 = 0;
-  ENUM_VALUE6590 = 1;
-  ENUM_VALUE6591 = 2;
-  ENUM_VALUE6592 = 3;
-  ENUM_VALUE6593 = 4;
-  ENUM_VALUE6594 = 5;
-  ENUM_VALUE6595 = 6;
-  ENUM_VALUE6596 = 7;
-  ENUM_VALUE6597 = 8;
-  ENUM_VALUE6598 = 9;
-  ENUM_VALUE6599 = 10;
-  ENUM_VALUE6600 = 11;
-  ENUM_VALUE6601 = 12;
-  ENUM_VALUE6602 = 13;
-  ENUM_VALUE6603 = 14;
-  ENUM_VALUE6604 = 15;
-  ENUM_VALUE6605 = 16;
-  ENUM_VALUE6606 = 17;
-  ENUM_VALUE6607 = 19;
-  ENUM_VALUE6608 = 20;
-  ENUM_VALUE6609 = 21;
-  ENUM_VALUE6610 = 22;
-  ENUM_VALUE6611 = 23;
-  ENUM_VALUE6612 = 24;
-  ENUM_VALUE6613 = 25;
-  ENUM_VALUE6614 = 26;
-  ENUM_VALUE6615 = 27;
-  ENUM_VALUE6616 = 28;
-  ENUM_VALUE6617 = 29;
-  ENUM_VALUE6618 = 30;
-  ENUM_VALUE6619 = 31;
-  ENUM_VALUE6620 = 32;
-  ENUM_VALUE6621 = 33;
-  ENUM_VALUE6622 = 34;
-}
-
-enum Enum6769 {
-  ENUM_VALUE6770 = 0;
-  ENUM_VALUE6771 = 1;
-  ENUM_VALUE6772 = 2;
-}
-
-enum Enum6774 {
-  ENUM_VALUE6775 = 0;
-  ENUM_VALUE6776 = 1;
-  ENUM_VALUE6777 = 2;
-  ENUM_VALUE6778 = 3;
-  ENUM_VALUE6779 = 4;
-  ENUM_VALUE6780 = 5;
-  ENUM_VALUE6781 = 6;
-}
-
-enum Enum6782 {
-  ENUM_VALUE6783 = 0;
-  ENUM_VALUE6784 = 1;
-  ENUM_VALUE6785 = 2;
-  ENUM_VALUE6786 = 3;
-  ENUM_VALUE6787 = 4;
-  ENUM_VALUE6788 = 5;
-}
-
-enum Enum6858 {
-  ENUM_VALUE6859 = 1;
-  ENUM_VALUE6860 = 2;
-  ENUM_VALUE6861 = 3;
-  ENUM_VALUE6862 = 4;
-}
-
-enum Enum6815 {
-  ENUM_VALUE6816 = 0;
-  ENUM_VALUE6817 = 1;
-  ENUM_VALUE6818 = 2;
-  ENUM_VALUE6819 = 3;
-  ENUM_VALUE6820 = 4;
-  ENUM_VALUE6821 = 5;
-}
-
-enum Enum6822 {
-  ENUM_VALUE6823 = 0;
-  ENUM_VALUE6824 = 1;
-  ENUM_VALUE6825 = 2;
-  ENUM_VALUE6826 = 3;
-}
-
-enum Enum7654 {
-  ENUM_VALUE7655 = 1;
-  ENUM_VALUE7656 = 2;
-  ENUM_VALUE7657 = 3;
-}
-
-enum Enum8292 {
-  ENUM_VALUE8293 = 0;
-  ENUM_VALUE8294 = 1;
-  ENUM_VALUE8295 = 2;
-}
-
-enum Enum8450 {
-  ENUM_VALUE8451 = 0;
-  ENUM_VALUE8452 = 1;
-  ENUM_VALUE8453 = 2;
-}
-
-enum Enum8900 {
-  ENUM_VALUE8901 = 0;
-  ENUM_VALUE8902 = 1;
-  ENUM_VALUE8903 = 2;
-  ENUM_VALUE8904 = 3;
-  ENUM_VALUE8905 = 4;
-}
-
-enum Enum8945 {
-  ENUM_VALUE8946 = 0;
-  ENUM_VALUE8947 = 1;
-  ENUM_VALUE8948 = 2;
-  ENUM_VALUE8949 = 3;
-  ENUM_VALUE8950 = 4;
-}
-
-enum Enum8951 {
-  ENUM_VALUE8952 = 1;
-  ENUM_VALUE8953 = 2;
-  ENUM_VALUE8954 = 3;
-  ENUM_VALUE8955 = 4;
-  ENUM_VALUE8956 = 5;
-  ENUM_VALUE8957 = 6;
-  ENUM_VALUE8958 = 7;
-  ENUM_VALUE8959 = 8;
-}
-
-enum Enum9243 {
-  ENUM_VALUE9244 = -1;
-  ENUM_VALUE9245 = 0;
-  ENUM_VALUE9246 = 1;
-  ENUM_VALUE9247 = 2;
-  ENUM_VALUE9248 = 3;
-  ENUM_VALUE9249 = 4;
-  ENUM_VALUE9250 = 5;
-  ENUM_VALUE9251 = 6;
-  ENUM_VALUE9252 = 7;
-  ENUM_VALUE9253 = 8;
-  ENUM_VALUE9254 = 9;
-  ENUM_VALUE9255 = 10;
-  ENUM_VALUE9256 = 11;
-  ENUM_VALUE9257 = 12;
-  ENUM_VALUE9258 = 13;
-  ENUM_VALUE9259 = 14;
-  ENUM_VALUE9260 = 15;
-  ENUM_VALUE9261 = 16;
-  ENUM_VALUE9262 = 17;
-  ENUM_VALUE9263 = 71;
-  ENUM_VALUE9264 = 72;
-  ENUM_VALUE9265 = 73;
-  ENUM_VALUE9266 = 74;
-  ENUM_VALUE9267 = 18;
-  ENUM_VALUE9268 = 20;
-  ENUM_VALUE9269 = 21;
-  ENUM_VALUE9270 = 22;
-  ENUM_VALUE9271 = 23;
-  ENUM_VALUE9272 = 61;
-  ENUM_VALUE9273 = 62;
-  ENUM_VALUE9274 = 63;
-  ENUM_VALUE9275 = 64;
-  ENUM_VALUE9276 = 66;
-  ENUM_VALUE9277 = 67;
-  ENUM_VALUE9278 = 24;
-  ENUM_VALUE9279 = 25;
-  ENUM_VALUE9280 = 26;
-  ENUM_VALUE9281 = 27;
-  ENUM_VALUE9282 = 28;
-  ENUM_VALUE9283 = 29;
-  ENUM_VALUE9284 = 30;
-  ENUM_VALUE9285 = 31;
-  ENUM_VALUE9286 = 32;
-  ENUM_VALUE9287 = 33;
-  ENUM_VALUE9288 = 34;
-  ENUM_VALUE9289 = 35;
-  ENUM_VALUE9290 = 36;
-  ENUM_VALUE9291 = 37;
-  ENUM_VALUE9292 = 38;
-  ENUM_VALUE9293 = 39;
-  ENUM_VALUE9294 = 40;
-  ENUM_VALUE9295 = 41;
-  ENUM_VALUE9296 = 42;
-  ENUM_VALUE9297 = 43;
-  ENUM_VALUE9298 = 44;
-  ENUM_VALUE9299 = 45;
-  ENUM_VALUE9300 = 46;
-  ENUM_VALUE9301 = 47;
-  ENUM_VALUE9302 = 48;
-  ENUM_VALUE9303 = 49;
-  ENUM_VALUE9304 = 50;
-  ENUM_VALUE9305 = 51;
-  ENUM_VALUE9306 = 52;
-  ENUM_VALUE9307 = 53;
-  ENUM_VALUE9308 = 54;
-  ENUM_VALUE9309 = 55;
-  ENUM_VALUE9310 = 56;
-  ENUM_VALUE9311 = 57;
-  ENUM_VALUE9312 = 58;
-  ENUM_VALUE9313 = 59;
-  ENUM_VALUE9314 = 60;
-  ENUM_VALUE9315 = 68;
-  ENUM_VALUE9316 = 69;
-  ENUM_VALUE9317 = 70;
-  ENUM_VALUE9318 = 1000;
-  ENUM_VALUE9319 = 1001;
-  ENUM_VALUE9320 = 1002;
-  ENUM_VALUE9321 = 1003;
-  ENUM_VALUE9322 = 1004;
-  ENUM_VALUE9323 = 1005;
-  ENUM_VALUE9324 = 1006;
-  ENUM_VALUE9325 = 1007;
-  ENUM_VALUE9326 = 65;
-}
-
-enum Enum10157 {
-  ENUM_VALUE10158 = 0;
-  ENUM_VALUE10159 = 1;
-  ENUM_VALUE10160 = 2;
-  ENUM_VALUE10161 = 3;
-  ENUM_VALUE10162 = 4;
-  ENUM_VALUE10163 = 5;
-  ENUM_VALUE10164 = 6;
-  ENUM_VALUE10165 = 7;
-  ENUM_VALUE10166 = 8;
-}
-
-enum Enum10167 {
-  ENUM_VALUE10168 = 0;
-  ENUM_VALUE10169 = 1;
-  ENUM_VALUE10170 = 2;
-  ENUM_VALUE10171 = 3;
-  ENUM_VALUE10172 = 4;
-  ENUM_VALUE10173 = 5;
-  ENUM_VALUE10174 = 6;
-  ENUM_VALUE10175 = 7;
-  ENUM_VALUE10176 = 8;
-}
-
-enum Enum8862 {
-  ENUM_VALUE8863 = 0;
-  ENUM_VALUE8864 = 1;
-  ENUM_VALUE8865 = 2;
-  ENUM_VALUE8866 = 3;
-  ENUM_VALUE8867 = 4;
-  ENUM_VALUE8868 = 5;
-  ENUM_VALUE8869 = 6;
-  ENUM_VALUE8870 = 7;
-  ENUM_VALUE8871 = 13;
-  ENUM_VALUE8872 = 14;
-  ENUM_VALUE8873 = 8;
-  ENUM_VALUE8874 = 9;
-  ENUM_VALUE8875 = 10;
-  ENUM_VALUE8876 = 11;
-  ENUM_VALUE8877 = 12;
-  ENUM_VALUE8878 = 15;
-}
-
-enum Enum10325 {
-  ENUM_VALUE10326 = 0;
-  ENUM_VALUE10327 = 1;
-  ENUM_VALUE10328 = 2;
-  ENUM_VALUE10329 = 3;
-  ENUM_VALUE10330 = 4;
-  ENUM_VALUE10331 = 5;
-  ENUM_VALUE10332 = 6;
-  ENUM_VALUE10333 = 7;
-  ENUM_VALUE10334 = 8;
-}
-
-enum Enum10335 { ENUM_VALUE10336 = 0; }
-
-enum Enum10337 {
-  ENUM_VALUE10338 = 0;
-  ENUM_VALUE10339 = 1;
-}
-
-enum Enum10392 {
-  ENUM_VALUE10393 = 0;
-  ENUM_VALUE10394 = 1;
-  ENUM_VALUE10395 = 2;
-  ENUM_VALUE10396 = 3;
-  ENUM_VALUE10397 = 4;
-  ENUM_VALUE10398 = 5;
-  ENUM_VALUE10399 = 6;
-  ENUM_VALUE10400 = 7;
-  ENUM_VALUE10401 = 8;
-  ENUM_VALUE10402 = 15;
-  ENUM_VALUE10403 = 9;
-  ENUM_VALUE10404 = 10;
-  ENUM_VALUE10405 = 11;
-  ENUM_VALUE10406 = 12;
-  ENUM_VALUE10407 = 13;
-  ENUM_VALUE10408 = 14;
-  ENUM_VALUE10409 = 101;
-  ENUM_VALUE10410 = 102;
-}
-
-enum Enum11107 {
-  ENUM_VALUE11108 = 0;
-  ENUM_VALUE11109 = 1;
-  ENUM_VALUE11110 = 2;
-  ENUM_VALUE11111 = 3;
-  ENUM_VALUE11112 = 4;
-  ENUM_VALUE11113 = 5;
-  ENUM_VALUE11114 = 6;
-  ENUM_VALUE11115 = 7;
-  ENUM_VALUE11116 = 8;
-  ENUM_VALUE11117 = 9;
-  ENUM_VALUE11118 = 10;
-  ENUM_VALUE11119 = 11;
-  ENUM_VALUE11120 = 12;
-  ENUM_VALUE11121 = 13;
-  ENUM_VALUE11122 = 14;
-  ENUM_VALUE11123 = 15;
-  ENUM_VALUE11124 = 16;
-  ENUM_VALUE11125 = 17;
-  ENUM_VALUE11126 = 18;
-  ENUM_VALUE11127 = 19;
-  ENUM_VALUE11128 = 20;
-  ENUM_VALUE11129 = 21;
-  ENUM_VALUE11130 = 22;
-  ENUM_VALUE11131 = 23;
-  ENUM_VALUE11132 = 24;
-  ENUM_VALUE11133 = 25;
-  ENUM_VALUE11134 = 26;
-  ENUM_VALUE11135 = 27;
-  ENUM_VALUE11136 = 28;
-  ENUM_VALUE11137 = 29;
-  ENUM_VALUE11138 = 30;
-  ENUM_VALUE11139 = 31;
-  ENUM_VALUE11140 = 32;
-  ENUM_VALUE11141 = 33;
-  ENUM_VALUE11142 = 34;
-  ENUM_VALUE11143 = 35;
-  ENUM_VALUE11144 = 36;
-  ENUM_VALUE11145 = 37;
-  ENUM_VALUE11146 = 38;
-  ENUM_VALUE11147 = 39;
-  ENUM_VALUE11148 = 40;
-  ENUM_VALUE11149 = 41;
-  ENUM_VALUE11150 = 42;
-  ENUM_VALUE11151 = 43;
-  ENUM_VALUE11152 = 44;
-  ENUM_VALUE11153 = 45;
-  ENUM_VALUE11154 = 46;
-  ENUM_VALUE11155 = 47;
-  ENUM_VALUE11156 = 48;
-  ENUM_VALUE11157 = 49;
-  ENUM_VALUE11158 = 50;
-  ENUM_VALUE11159 = 51;
-  ENUM_VALUE11160 = 52;
-  ENUM_VALUE11161 = 53;
-  ENUM_VALUE11162 = 54;
-  ENUM_VALUE11163 = 55;
-  ENUM_VALUE11164 = 56;
-  ENUM_VALUE11165 = 57;
-  ENUM_VALUE11166 = 58;
-  ENUM_VALUE11167 = 59;
-  ENUM_VALUE11168 = 60;
-  ENUM_VALUE11169 = 61;
-  ENUM_VALUE11170 = 62;
-  ENUM_VALUE11171 = 63;
-  ENUM_VALUE11172 = 64;
-  ENUM_VALUE11173 = 65;
-  ENUM_VALUE11174 = 66;
-  ENUM_VALUE11175 = 67;
-  ENUM_VALUE11176 = 68;
-  ENUM_VALUE11177 = 69;
-  ENUM_VALUE11178 = 70;
-  ENUM_VALUE11179 = 71;
-  ENUM_VALUE11180 = 72;
-  ENUM_VALUE11181 = 73;
-  ENUM_VALUE11182 = 74;
-  ENUM_VALUE11183 = 75;
-  ENUM_VALUE11184 = 76;
-  ENUM_VALUE11185 = 77;
-  ENUM_VALUE11186 = 78;
-  ENUM_VALUE11187 = 79;
-  ENUM_VALUE11188 = 80;
-  ENUM_VALUE11189 = 81;
-  ENUM_VALUE11190 = 82;
-  ENUM_VALUE11191 = 83;
-  ENUM_VALUE11192 = 84;
-  ENUM_VALUE11193 = 85;
-  ENUM_VALUE11194 = 86;
-  ENUM_VALUE11195 = 87;
-  ENUM_VALUE11196 = 88;
-  ENUM_VALUE11197 = 89;
-  ENUM_VALUE11198 = 90;
-  ENUM_VALUE11199 = 91;
-  ENUM_VALUE11200 = 92;
-  ENUM_VALUE11201 = 93;
-  ENUM_VALUE11202 = 94;
-  ENUM_VALUE11203 = 95;
-  ENUM_VALUE11204 = 96;
-  ENUM_VALUE11205 = 97;
-  ENUM_VALUE11206 = 98;
-  ENUM_VALUE11207 = 99;
-  ENUM_VALUE11208 = 100;
-  ENUM_VALUE11209 = 101;
-  ENUM_VALUE11210 = 102;
-  ENUM_VALUE11211 = 103;
-  ENUM_VALUE11212 = 104;
-  ENUM_VALUE11213 = 105;
-  ENUM_VALUE11214 = 106;
-  ENUM_VALUE11215 = 107;
-  ENUM_VALUE11216 = 108;
-  ENUM_VALUE11217 = 109;
-  ENUM_VALUE11218 = 110;
-  ENUM_VALUE11219 = 111;
-  ENUM_VALUE11220 = 112;
-  ENUM_VALUE11221 = 113;
-  ENUM_VALUE11222 = 114;
-  ENUM_VALUE11223 = 115;
-  ENUM_VALUE11224 = 116;
-  ENUM_VALUE11225 = 117;
-  ENUM_VALUE11226 = 118;
-  ENUM_VALUE11227 = 119;
-  ENUM_VALUE11228 = 120;
-  ENUM_VALUE11229 = 121;
-  ENUM_VALUE11230 = 122;
-  ENUM_VALUE11231 = 123;
-  ENUM_VALUE11232 = 124;
-  ENUM_VALUE11233 = 125;
-  ENUM_VALUE11234 = 126;
-  ENUM_VALUE11235 = 127;
-  ENUM_VALUE11236 = 128;
-  ENUM_VALUE11237 = 129;
-  ENUM_VALUE11238 = 130;
-  ENUM_VALUE11239 = 131;
-  ENUM_VALUE11240 = 132;
-  ENUM_VALUE11241 = 133;
-  ENUM_VALUE11242 = 134;
-  ENUM_VALUE11243 = 135;
-  ENUM_VALUE11244 = 136;
-  ENUM_VALUE11245 = 137;
-  ENUM_VALUE11246 = 138;
-  ENUM_VALUE11247 = 139;
-  ENUM_VALUE11248 = 140;
-  ENUM_VALUE11249 = 141;
-  ENUM_VALUE11250 = 142;
-  ENUM_VALUE11251 = 143;
-  ENUM_VALUE11252 = 144;
-  ENUM_VALUE11253 = 145;
-  ENUM_VALUE11254 = 146;
-  ENUM_VALUE11255 = 147;
-  ENUM_VALUE11256 = 148;
-  ENUM_VALUE11257 = 149;
-  ENUM_VALUE11258 = 150;
-  ENUM_VALUE11259 = 151;
-  ENUM_VALUE11260 = 152;
-  ENUM_VALUE11261 = 153;
-  ENUM_VALUE11262 = 154;
-  ENUM_VALUE11263 = 155;
-  ENUM_VALUE11264 = 156;
-  ENUM_VALUE11265 = 157;
-  ENUM_VALUE11266 = 158;
-  ENUM_VALUE11267 = 159;
-  ENUM_VALUE11268 = 160;
-  ENUM_VALUE11269 = 161;
-  ENUM_VALUE11270 = 163;
-  ENUM_VALUE11271 = 164;
-  ENUM_VALUE11272 = 165;
-  ENUM_VALUE11273 = 166;
-  ENUM_VALUE11274 = 167;
-  ENUM_VALUE11275 = 168;
-  ENUM_VALUE11276 = 169;
-  ENUM_VALUE11277 = 170;
-  ENUM_VALUE11278 = 171;
-  ENUM_VALUE11279 = 172;
-  ENUM_VALUE11280 = 173;
-  ENUM_VALUE11281 = 174;
-  ENUM_VALUE11282 = 175;
-  ENUM_VALUE11283 = 176;
-  ENUM_VALUE11284 = 177;
-  ENUM_VALUE11285 = 178;
-  ENUM_VALUE11286 = 179;
-  ENUM_VALUE11287 = 180;
-  ENUM_VALUE11288 = 181;
-  ENUM_VALUE11289 = 182;
-  ENUM_VALUE11290 = 183;
-  ENUM_VALUE11291 = 184;
-  ENUM_VALUE11292 = 185;
-  ENUM_VALUE11293 = 187;
-  ENUM_VALUE11294 = 188;
-  ENUM_VALUE11295 = 189;
-  ENUM_VALUE11296 = 190;
-  ENUM_VALUE11297 = 191;
-  ENUM_VALUE11298 = 192;
-  ENUM_VALUE11299 = 193;
-  ENUM_VALUE11300 = 194;
-  ENUM_VALUE11301 = 195;
-  ENUM_VALUE11302 = 196;
-  ENUM_VALUE11303 = 197;
-  ENUM_VALUE11304 = 198;
-  ENUM_VALUE11305 = 65535;
-  ENUM_VALUE11306 = 65536;
-  ENUM_VALUE11307 = 65537;
-  ENUM_VALUE11308 = 65538;
-  ENUM_VALUE11309 = 65539;
-  ENUM_VALUE11310 = 65540;
-  ENUM_VALUE11311 = 65541;
-  ENUM_VALUE11312 = 65542;
-  ENUM_VALUE11313 = 65543;
-  ENUM_VALUE11314 = 65544;
-  ENUM_VALUE11315 = 65545;
-  ENUM_VALUE11316 = 65546;
-  ENUM_VALUE11317 = 65547;
-  ENUM_VALUE11318 = 65548;
-  ENUM_VALUE11319 = 65549;
-  ENUM_VALUE11320 = 65550;
-  ENUM_VALUE11321 = 65551;
-  ENUM_VALUE11322 = 65552;
-  ENUM_VALUE11323 = 65553;
-  ENUM_VALUE11324 = 65554;
-  ENUM_VALUE11325 = 65555;
-  ENUM_VALUE11326 = 65556;
-  ENUM_VALUE11327 = 65557;
-  ENUM_VALUE11328 = 65558;
-  ENUM_VALUE11329 = 65559;
-  ENUM_VALUE11330 = 65560;
-  ENUM_VALUE11331 = 65561;
-  ENUM_VALUE11332 = 65562;
-  ENUM_VALUE11333 = 65563;
-  ENUM_VALUE11334 = 69632;
-  ENUM_VALUE11335 = 69633;
-  ENUM_VALUE11336 = 69634;
-  ENUM_VALUE11337 = 69635;
-  ENUM_VALUE11338 = 69636;
-  ENUM_VALUE11339 = 69637;
-  ENUM_VALUE11340 = 69638;
-  ENUM_VALUE11341 = 69639;
-  ENUM_VALUE11342 = 69640;
-  ENUM_VALUE11343 = 69641;
-  ENUM_VALUE11344 = 69642;
-  ENUM_VALUE11345 = 69643;
-  ENUM_VALUE11346 = 69644;
-  ENUM_VALUE11347 = 69645;
-  ENUM_VALUE11348 = 69646;
-  ENUM_VALUE11349 = 69647;
-  ENUM_VALUE11350 = 69648;
-  ENUM_VALUE11351 = 69649;
-  ENUM_VALUE11352 = 69650;
-  ENUM_VALUE11353 = 69651;
-  ENUM_VALUE11354 = 69652;
-  ENUM_VALUE11355 = 69653;
-  ENUM_VALUE11356 = 69654;
-  ENUM_VALUE11357 = 69655;
-  ENUM_VALUE11358 = 69656;
-  ENUM_VALUE11359 = 69657;
-  ENUM_VALUE11360 = 69658;
-  ENUM_VALUE11361 = 69659;
-  ENUM_VALUE11362 = 69660;
-  ENUM_VALUE11363 = 69661;
-  ENUM_VALUE11364 = 69662;
-  ENUM_VALUE11365 = 73728;
-  ENUM_VALUE11366 = 73729;
-  ENUM_VALUE11367 = 77824;
-  ENUM_VALUE11368 = 77825;
-  ENUM_VALUE11369 = 81920;
-  ENUM_VALUE11370 = 81921;
-  ENUM_VALUE11371 = 81922;
-  ENUM_VALUE11372 = 81923;
-  ENUM_VALUE11373 = 86016;
-  ENUM_VALUE11374 = 86017;
-  ENUM_VALUE11375 = 86018;
-  ENUM_VALUE11376 = 86019;
-  ENUM_VALUE11377 = 86020;
-  ENUM_VALUE11378 = 86021;
-  ENUM_VALUE11379 = 86022;
-  ENUM_VALUE11380 = 86023;
-  ENUM_VALUE11381 = 86024;
-  ENUM_VALUE11382 = 86025;
-  ENUM_VALUE11383 = 86026;
-  ENUM_VALUE11384 = 86027;
-  ENUM_VALUE11385 = 86028;
-  ENUM_VALUE11386 = 86029;
-  ENUM_VALUE11387 = 86030;
-  ENUM_VALUE11388 = 86031;
-  ENUM_VALUE11389 = 86032;
-  ENUM_VALUE11390 = 86033;
-  ENUM_VALUE11391 = 86034;
-  ENUM_VALUE11392 = 86035;
-  ENUM_VALUE11393 = 86036;
-  ENUM_VALUE11394 = 86037;
-  ENUM_VALUE11395 = 86038;
-  ENUM_VALUE11396 = 86039;
-  ENUM_VALUE11397 = 86040;
-  ENUM_VALUE11398 = 86041;
-  ENUM_VALUE11399 = 86042;
-  ENUM_VALUE11400 = 86043;
-  ENUM_VALUE11401 = 86044;
-  ENUM_VALUE11402 = 86045;
-  ENUM_VALUE11403 = 86046;
-  ENUM_VALUE11404 = 86047;
-  ENUM_VALUE11405 = 86048;
-  ENUM_VALUE11406 = 86049;
-  ENUM_VALUE11407 = 86050;
-  ENUM_VALUE11408 = 86051;
-  ENUM_VALUE11409 = 86052;
-  ENUM_VALUE11410 = 86053;
-  ENUM_VALUE11411 = 86054;
-  ENUM_VALUE11412 = 86055;
-  ENUM_VALUE11413 = 86056;
-  ENUM_VALUE11414 = 86057;
-  ENUM_VALUE11415 = 86058;
-  ENUM_VALUE11416 = 86059;
-  ENUM_VALUE11417 = 86060;
-  ENUM_VALUE11418 = 86061;
-  ENUM_VALUE11419 = 86062;
-  ENUM_VALUE11420 = 86063;
-  ENUM_VALUE11421 = 86064;
-  ENUM_VALUE11422 = 86065;
-  ENUM_VALUE11423 = 86066;
-  ENUM_VALUE11424 = 86067;
-  ENUM_VALUE11425 = 86068;
-  ENUM_VALUE11426 = 86069;
-  ENUM_VALUE11427 = 86070;
-  ENUM_VALUE11428 = 86071;
-  ENUM_VALUE11429 = 86072;
-  ENUM_VALUE11430 = 86073;
-  ENUM_VALUE11431 = 86074;
-  ENUM_VALUE11432 = 86077;
-  ENUM_VALUE11433 = 86078;
-  ENUM_VALUE11434 = 86079;
-  ENUM_VALUE11435 = 86080;
-  ENUM_VALUE11436 = 86081;
-  ENUM_VALUE11437 = 86082;
-  ENUM_VALUE11438 = 86083;
-  ENUM_VALUE11439 = 86084;
-  ENUM_VALUE11440 = 90112;
-  ENUM_VALUE11441 = 94208;
-  ENUM_VALUE11442 = 94209;
-  ENUM_VALUE11443 = 94210;
-  ENUM_VALUE11444 = 94211;
-  ENUM_VALUE11445 = 94212;
-  ENUM_VALUE11446 = 94213;
-  ENUM_VALUE11447 = 94214;
-  ENUM_VALUE11448 = 94215;
-  ENUM_VALUE11449 = 94216;
-  ENUM_VALUE11450 = 94217;
-  ENUM_VALUE11451 = 94218;
-  ENUM_VALUE11452 = 94219;
-  ENUM_VALUE11453 = 94220;
-  ENUM_VALUE11454 = 94221;
-  ENUM_VALUE11455 = 94222;
-  ENUM_VALUE11456 = 94223;
-  ENUM_VALUE11457 = 94224;
-  ENUM_VALUE11458 = 98304;
-  ENUM_VALUE11459 = 98305;
-  ENUM_VALUE11460 = 98306;
-  ENUM_VALUE11461 = 98307;
-  ENUM_VALUE11462 = 98308;
-  ENUM_VALUE11463 = 102400;
-  ENUM_VALUE11464 = 131072;
-  ENUM_VALUE11465 = 131073;
-  ENUM_VALUE11466 = 135168;
-  ENUM_VALUE11467 = 9439507;
-}
-
-enum Enum11541 {
-  ENUM_VALUE11542 = -1;
-  ENUM_VALUE11543 = 0;
-  ENUM_VALUE11544 = 1;
-  ENUM_VALUE11545 = 2;
-  ENUM_VALUE11546 = 3;
-  ENUM_VALUE11547 = 4;
-  ENUM_VALUE11548 = 5;
-  ENUM_VALUE11549 = 6;
-  ENUM_VALUE11550 = 7;
-  ENUM_VALUE11551 = 8;
-  ENUM_VALUE11552 = 9;
-  ENUM_VALUE11553 = 10;
-  ENUM_VALUE11554 = 11;
-  ENUM_VALUE11555 = 12;
-  ENUM_VALUE11556 = 13;
-  ENUM_VALUE11557 = 14;
-  ENUM_VALUE11558 = 15;
-  ENUM_VALUE11559 = 16;
-  ENUM_VALUE11560 = 17;
-  ENUM_VALUE11561 = 18;
-  ENUM_VALUE11562 = 19;
-  ENUM_VALUE11563 = 20;
-  ENUM_VALUE11564 = 21;
-  ENUM_VALUE11565 = 22;
-  ENUM_VALUE11566 = 23;
-  ENUM_VALUE11567 = 24;
-  ENUM_VALUE11568 = 25;
-  ENUM_VALUE11569 = 26;
-  ENUM_VALUE11570 = 27;
-  ENUM_VALUE11571 = 28;
-  ENUM_VALUE11572 = 29;
-  ENUM_VALUE11573 = 30;
-  ENUM_VALUE11574 = 31;
-  ENUM_VALUE11575 = 32;
-  ENUM_VALUE11576 = 33;
-  ENUM_VALUE11577 = 34;
-  ENUM_VALUE11578 = 35;
-  ENUM_VALUE11579 = 36;
-  ENUM_VALUE11580 = 37;
-  ENUM_VALUE11581 = 38;
-  ENUM_VALUE11582 = 39;
-  ENUM_VALUE11583 = 40;
-  ENUM_VALUE11584 = 41;
-  ENUM_VALUE11585 = 42;
-  ENUM_VALUE11586 = 43;
-  ENUM_VALUE11587 = 44;
-  ENUM_VALUE11588 = 45;
-  ENUM_VALUE11589 = 46;
-  ENUM_VALUE11590 = 47;
-  ENUM_VALUE11591 = 48;
-  ENUM_VALUE11592 = 49;
-  ENUM_VALUE11593 = 50;
-  ENUM_VALUE11594 = 51;
-  ENUM_VALUE11595 = 52;
-  ENUM_VALUE11596 = 53;
-  ENUM_VALUE11597 = 54;
-  ENUM_VALUE11598 = 55;
-  ENUM_VALUE11599 = 56;
-  ENUM_VALUE11600 = 57;
-  ENUM_VALUE11601 = 58;
-  ENUM_VALUE11602 = 59;
-  ENUM_VALUE11603 = 60;
-  ENUM_VALUE11604 = 61;
-  ENUM_VALUE11605 = 62;
-  ENUM_VALUE11606 = 63;
-  ENUM_VALUE11607 = 64;
-  ENUM_VALUE11608 = 65;
-  ENUM_VALUE11609 = 66;
-  ENUM_VALUE11610 = 67;
-  ENUM_VALUE11611 = 68;
-  ENUM_VALUE11612 = 69;
-  ENUM_VALUE11613 = 70;
-  ENUM_VALUE11614 = 71;
-  ENUM_VALUE11615 = 72;
-  ENUM_VALUE11616 = 73;
-  ENUM_VALUE11617 = 74;
-  ENUM_VALUE11618 = 75;
-  ENUM_VALUE11619 = 76;
-  ENUM_VALUE11620 = 77;
-  ENUM_VALUE11621 = 78;
-  ENUM_VALUE11622 = 79;
-  ENUM_VALUE11623 = 80;
-  ENUM_VALUE11624 = 81;
-  ENUM_VALUE11625 = 82;
-  ENUM_VALUE11626 = 83;
-  ENUM_VALUE11627 = 84;
-  ENUM_VALUE11628 = 85;
-  ENUM_VALUE11629 = 86;
-  ENUM_VALUE11630 = 87;
-  ENUM_VALUE11631 = 88;
-  ENUM_VALUE11632 = 89;
-  ENUM_VALUE11633 = 90;
-  ENUM_VALUE11634 = 91;
-  ENUM_VALUE11635 = 92;
-  ENUM_VALUE11636 = 93;
-  ENUM_VALUE11637 = 94;
-  ENUM_VALUE11638 = 95;
-  ENUM_VALUE11639 = 96;
-  ENUM_VALUE11640 = 97;
-  ENUM_VALUE11641 = 98;
-  ENUM_VALUE11642 = 99;
-  ENUM_VALUE11643 = 100;
-  ENUM_VALUE11644 = 101;
-  ENUM_VALUE11645 = 102;
-  ENUM_VALUE11646 = 103;
-  ENUM_VALUE11647 = 104;
-  ENUM_VALUE11648 = 105;
-  ENUM_VALUE11649 = 106;
-  ENUM_VALUE11650 = 107;
-  ENUM_VALUE11651 = 108;
-  ENUM_VALUE11652 = 109;
-  ENUM_VALUE11653 = 110;
-  ENUM_VALUE11654 = 111;
-  ENUM_VALUE11655 = 112;
-  ENUM_VALUE11656 = 113;
-  ENUM_VALUE11657 = 114;
-  ENUM_VALUE11658 = 115;
-  ENUM_VALUE11659 = 116;
-  ENUM_VALUE11660 = 117;
-  ENUM_VALUE11661 = 118;
-  ENUM_VALUE11662 = 119;
-  ENUM_VALUE11663 = 120;
-  ENUM_VALUE11664 = 121;
-  ENUM_VALUE11665 = 122;
-  ENUM_VALUE11666 = 123;
-  ENUM_VALUE11667 = 124;
-  ENUM_VALUE11668 = 125;
-  ENUM_VALUE11669 = 126;
-  ENUM_VALUE11670 = 127;
-  ENUM_VALUE11671 = 128;
-  ENUM_VALUE11672 = 129;
-  ENUM_VALUE11673 = 130;
-  ENUM_VALUE11674 = 131;
-  ENUM_VALUE11675 = 132;
-  ENUM_VALUE11676 = 133;
-  ENUM_VALUE11677 = 134;
-  ENUM_VALUE11678 = 135;
-  ENUM_VALUE11679 = 136;
-  ENUM_VALUE11680 = 137;
-  ENUM_VALUE11681 = 138;
-  ENUM_VALUE11682 = 139;
-  ENUM_VALUE11683 = 140;
-  ENUM_VALUE11684 = 141;
-  ENUM_VALUE11685 = 142;
-  ENUM_VALUE11686 = 143;
-  ENUM_VALUE11687 = 144;
-  ENUM_VALUE11688 = 145;
-  ENUM_VALUE11689 = 146;
-  ENUM_VALUE11690 = 147;
-  ENUM_VALUE11691 = 148;
-  ENUM_VALUE11692 = 149;
-  ENUM_VALUE11693 = 150;
-  ENUM_VALUE11694 = 151;
-  ENUM_VALUE11695 = 152;
-  ENUM_VALUE11696 = 153;
-  ENUM_VALUE11697 = 154;
-  ENUM_VALUE11698 = 155;
-  ENUM_VALUE11699 = 156;
-  ENUM_VALUE11700 = 157;
-  ENUM_VALUE11701 = 158;
-  ENUM_VALUE11702 = 159;
-  ENUM_VALUE11703 = 160;
-  ENUM_VALUE11704 = 161;
-  ENUM_VALUE11705 = 162;
-  ENUM_VALUE11706 = 163;
-  ENUM_VALUE11707 = 164;
-  ENUM_VALUE11708 = 165;
-  ENUM_VALUE11709 = 166;
-  ENUM_VALUE11710 = 167;
-  ENUM_VALUE11711 = 168;
-  ENUM_VALUE11712 = 169;
-  ENUM_VALUE11713 = 170;
-  ENUM_VALUE11714 = 171;
-  ENUM_VALUE11715 = 172;
-  ENUM_VALUE11716 = 173;
-  ENUM_VALUE11717 = 174;
-  ENUM_VALUE11718 = 175;
-  ENUM_VALUE11719 = 176;
-  ENUM_VALUE11720 = 177;
-  ENUM_VALUE11721 = 178;
-  ENUM_VALUE11722 = 179;
-  ENUM_VALUE11723 = 180;
-  ENUM_VALUE11724 = 181;
-  ENUM_VALUE11725 = 182;
-  ENUM_VALUE11726 = 183;
-  ENUM_VALUE11727 = 184;
-  ENUM_VALUE11728 = 185;
-  ENUM_VALUE11729 = 186;
-  ENUM_VALUE11730 = 187;
-  ENUM_VALUE11731 = 188;
-  ENUM_VALUE11732 = 16777215;
-}
-
-enum Enum11468 {
-  ENUM_VALUE11469 = -99;
-  ENUM_VALUE11470 = 0;
-  ENUM_VALUE11471 = 1;
-  ENUM_VALUE11472 = 2;
-  ENUM_VALUE11473 = 3;
-  ENUM_VALUE11474 = 4;
-  ENUM_VALUE11475 = 28;
-  ENUM_VALUE11476 = 22;
-  ENUM_VALUE11477 = 38;
-  ENUM_VALUE11478 = 512;
-  ENUM_VALUE11479 = 2048;
-  ENUM_VALUE11480 = 66;
-  ENUM_VALUE11481 = 578;
-  ENUM_VALUE11482 = 77;
-  ENUM_VALUE11483 = 88;
-  ENUM_VALUE11484 = 100;
-  ENUM_VALUE11485 = 110;
-  ENUM_VALUE11486 = 2158;
-  ENUM_VALUE11487 = 122;
-  ENUM_VALUE11488 = 2170;
-  ENUM_VALUE11489 = 144;
-  ENUM_VALUE11490 = 244;
-  ENUM_VALUE11491 = 2292;
-  ENUM_VALUE11492 = 44;
-}
-
-enum Enum11022 {
-  ENUM_VALUE11023 = 0;
-  ENUM_VALUE11024 = 1;
-  ENUM_VALUE11025 = 2;
-  ENUM_VALUE11026 = 3;
-  ENUM_VALUE11027 = 4;
-  ENUM_VALUE11028 = 5;
-  ENUM_VALUE11029 = 6;
-  ENUM_VALUE11030 = 7;
-  ENUM_VALUE11031 = 8;
-  ENUM_VALUE11032 = 9;
-  ENUM_VALUE11033 = 10;
-  ENUM_VALUE11034 = 11;
-  ENUM_VALUE11035 = 12;
-  ENUM_VALUE11036 = 13;
-  ENUM_VALUE11037 = 14;
-  ENUM_VALUE11038 = 15;
-  ENUM_VALUE11039 = 16;
-  ENUM_VALUE11040 = 17;
-  ENUM_VALUE11041 = 18;
-  ENUM_VALUE11042 = 19;
-  ENUM_VALUE11043 = 20;
-  ENUM_VALUE11044 = 21;
-  ENUM_VALUE11045 = 22;
-  ENUM_VALUE11046 = 23;
-  ENUM_VALUE11047 = 24;
-  ENUM_VALUE11048 = 25;
-  ENUM_VALUE11049 = 26;
-  ENUM_VALUE11050 = 27;
-  ENUM_VALUE11051 = 28;
-  ENUM_VALUE11052 = 29;
-  ENUM_VALUE11053 = 30;
-  ENUM_VALUE11054 = 31;
-  ENUM_VALUE11055 = 32;
-  ENUM_VALUE11056 = 33;
-  ENUM_VALUE11057 = 34;
-  ENUM_VALUE11058 = 35;
-  ENUM_VALUE11059 = 36;
-  ENUM_VALUE11060 = 37;
-  ENUM_VALUE11061 = 38;
-  ENUM_VALUE11062 = 39;
-  ENUM_VALUE11063 = 40;
-  ENUM_VALUE11064 = 41;
-  ENUM_VALUE11065 = 42;
-  ENUM_VALUE11066 = 43;
-  ENUM_VALUE11067 = 44;
-  ENUM_VALUE11068 = 45;
-  ENUM_VALUE11069 = 46;
-  ENUM_VALUE11070 = 47;
-  ENUM_VALUE11071 = 48;
-  ENUM_VALUE11072 = 49;
-  ENUM_VALUE11073 = 50;
-  ENUM_VALUE11074 = 51;
-  ENUM_VALUE11075 = 52;
-  ENUM_VALUE11076 = 53;
-  ENUM_VALUE11077 = 54;
-  ENUM_VALUE11078 = 55;
-  ENUM_VALUE11079 = 56;
-  ENUM_VALUE11080 = 57;
-  ENUM_VALUE11081 = 58;
-  ENUM_VALUE11082 = 59;
-  ENUM_VALUE11083 = 60;
-  ENUM_VALUE11084 = 61;
-  ENUM_VALUE11085 = 62;
-  ENUM_VALUE11086 = 63;
-  ENUM_VALUE11087 = 64;
-  ENUM_VALUE11088 = 65;
-  ENUM_VALUE11089 = 66;
-  ENUM_VALUE11090 = 67;
-  ENUM_VALUE11091 = 68;
-  ENUM_VALUE11092 = 69;
-  ENUM_VALUE11093 = 70;
-  ENUM_VALUE11094 = 71;
-  ENUM_VALUE11095 = 72;
-  ENUM_VALUE11096 = 73;
-  ENUM_VALUE11097 = 74;
-  ENUM_VALUE11098 = 75;
-  ENUM_VALUE11099 = 76;
-  ENUM_VALUE11100 = 77;
-  ENUM_VALUE11101 = 78;
-  ENUM_VALUE11102 = 79;
-  ENUM_VALUE11103 = 80;
-  ENUM_VALUE11104 = 81;
-  ENUM_VALUE11105 = 82;
-  ENUM_VALUE11106 = 83;
-}
-
-enum Enum12670 {
-  ENUM_VALUE12671 = 0;
-  ENUM_VALUE12672 = 1;
-  ENUM_VALUE12673 = 2;
-}
-
-enum Enum12871 {
-  ENUM_VALUE12872 = 1;
-  ENUM_VALUE12873 = 2;
-  ENUM_VALUE12874 = 3;
-  ENUM_VALUE12875 = 4;
-  ENUM_VALUE12876 = 5;
-  ENUM_VALUE12877 = 6;
-}
-
-enum Enum13092 {
-  ENUM_VALUE13093 = 1;
-  ENUM_VALUE13094 = 2;
-  ENUM_VALUE13095 = 3;
-}
-
-enum Enum13146 {
-  ENUM_VALUE13147 = 0;
-  ENUM_VALUE13148 = 1;
-  ENUM_VALUE13149 = 2;
-  ENUM_VALUE13150 = 3;
-}
-
-enum Enum16042 {
-  ENUM_VALUE16043 = 0;
-  ENUM_VALUE16044 = 1;
-  ENUM_VALUE16045 = 17;
-  ENUM_VALUE16046 = 273;
-  ENUM_VALUE16047 = 274;
-  ENUM_VALUE16048 = 4385;
-  ENUM_VALUE16049 = 4386;
-  ENUM_VALUE16050 = 4387;
-  ENUM_VALUE16051 = 4388;
-  ENUM_VALUE16052 = 4389;
-  ENUM_VALUE16053 = 4390;
-  ENUM_VALUE16054 = 4391;
-  ENUM_VALUE16055 = 4392;
-  ENUM_VALUE16056 = 4393;
-  ENUM_VALUE16057 = 276;
-  ENUM_VALUE16058 = 277;
-  ENUM_VALUE16059 = 18;
-  ENUM_VALUE16060 = 289;
-  ENUM_VALUE16061 = 291;
-  ENUM_VALUE16062 = 4657;
-  ENUM_VALUE16063 = 74513;
-  ENUM_VALUE16064 = 4658;
-  ENUM_VALUE16065 = 4659;
-  ENUM_VALUE16066 = 4660;
-  ENUM_VALUE16067 = 4661;
-  ENUM_VALUE16068 = 4662;
-  ENUM_VALUE16069 = 4663;
-  ENUM_VALUE16070 = 4664;
-  ENUM_VALUE16071 = 292;
-  ENUM_VALUE16072 = 4673;
-  ENUM_VALUE16073 = 4674;
-  ENUM_VALUE16074 = 293;
-  ENUM_VALUE16075 = 19;
-  ENUM_VALUE16076 = 20;
-  ENUM_VALUE16077 = 321;
-  ENUM_VALUE16078 = 5137;
-  ENUM_VALUE16079 = 5138;
-  ENUM_VALUE16080 = 5139;
-  ENUM_VALUE16081 = 5140;
-  ENUM_VALUE16082 = 5141;
-  ENUM_VALUE16083 = 5142;
-  ENUM_VALUE16084 = 82273;
-  ENUM_VALUE16085 = 82274;
-  ENUM_VALUE16086 = 82275;
-  ENUM_VALUE16087 = 82276;
-  ENUM_VALUE16088 = 82277;
-  ENUM_VALUE16089 = 82278;
-  ENUM_VALUE16090 = 5143;
-  ENUM_VALUE16091 = 5144;
-  ENUM_VALUE16092 = 5145;
-  ENUM_VALUE16093 = 5146;
-  ENUM_VALUE16094 = 82337;
-  ENUM_VALUE16095 = 5147;
-  ENUM_VALUE16096 = 5148;
-  ENUM_VALUE16097 = 322;
-  ENUM_VALUE16098 = 323;
-  ENUM_VALUE16099 = 324;
-  ENUM_VALUE16100 = 325;
-  ENUM_VALUE16101 = 326;
-  ENUM_VALUE16102 = 327;
-  ENUM_VALUE16103 = 328;
-  ENUM_VALUE16104 = 21;
-  ENUM_VALUE16105 = 337;
-  ENUM_VALUE16106 = 22;
-  ENUM_VALUE16107 = 23;
-  ENUM_VALUE16108 = 24;
-  ENUM_VALUE16109 = 2;
-  ENUM_VALUE16110 = 33;
-  ENUM_VALUE16111 = 34;
-  ENUM_VALUE16112 = 545;
-  ENUM_VALUE16113 = 8721;
-  ENUM_VALUE16114 = 8723;
-  ENUM_VALUE16115 = 8724;
-  ENUM_VALUE16116 = 546;
-  ENUM_VALUE16117 = 8739;
-  ENUM_VALUE16118 = 8740;
-  ENUM_VALUE16119 = 547;
-  ENUM_VALUE16120 = 548;
-  ENUM_VALUE16121 = 549;
-  ENUM_VALUE16122 = 550;
-  ENUM_VALUE16123 = 551;
-  ENUM_VALUE16124 = 552;
-  ENUM_VALUE16125 = 553;
-  ENUM_VALUE16126 = 35;
-  ENUM_VALUE16127 = 36;
-  ENUM_VALUE16128 = 37;
-  ENUM_VALUE16129 = 593;
-  ENUM_VALUE16130 = 594;
-  ENUM_VALUE16131 = 595;
-  ENUM_VALUE16132 = 596;
-  ENUM_VALUE16133 = 597;
-  ENUM_VALUE16134 = 38;
-  ENUM_VALUE16135 = 609;
-  ENUM_VALUE16136 = 610;
-  ENUM_VALUE16137 = 617;
-  ENUM_VALUE16138 = 614;
-  ENUM_VALUE16139 = 615;
-  ENUM_VALUE16140 = 616;
-  ENUM_VALUE16141 = 618;
-  ENUM_VALUE16142 = 620;
-  ENUM_VALUE16143 = 9937;
-  ENUM_VALUE16144 = 9938;
-  ENUM_VALUE16145 = 9939;
-  ENUM_VALUE16146 = 9940;
-  ENUM_VALUE16147 = 9941;
-  ENUM_VALUE16148 = 39;
-  ENUM_VALUE16149 = 40;
-  ENUM_VALUE16150 = 41;
-  ENUM_VALUE16151 = 42;
-  ENUM_VALUE16152 = 43;
-  ENUM_VALUE16153 = 44;
-  ENUM_VALUE16154 = 45;
-  ENUM_VALUE16155 = 11793;
-  ENUM_VALUE16156 = 3;
-  ENUM_VALUE16157 = 49;
-  ENUM_VALUE16158 = 50;
-  ENUM_VALUE16159 = 51;
-  ENUM_VALUE16160 = 817;
-  ENUM_VALUE16161 = 818;
-  ENUM_VALUE16162 = 819;
-  ENUM_VALUE16163 = 52;
-  ENUM_VALUE16164 = 833;
-  ENUM_VALUE16165 = 53;
-  ENUM_VALUE16166 = 54;
-  ENUM_VALUE16167 = 4;
-  ENUM_VALUE16168 = 1041;
-  ENUM_VALUE16169 = 16657;
-  ENUM_VALUE16170 = 16658;
-  ENUM_VALUE16171 = 16659;
-  ENUM_VALUE16172 = 16660;
-  ENUM_VALUE16173 = 16661;
-  ENUM_VALUE16174 = 1042;
-  ENUM_VALUE16175 = 16673;
-  ENUM_VALUE16176 = 1043;
-  ENUM_VALUE16177 = 16689;
-  ENUM_VALUE16178 = 16690;
-  ENUM_VALUE16179 = 16691;
-  ENUM_VALUE16180 = 16692;
-  ENUM_VALUE16181 = 16693;
-  ENUM_VALUE16182 = 16694;
-  ENUM_VALUE16183 = 16695;
-  ENUM_VALUE16184 = 1044;
-  ENUM_VALUE16185 = 16705;
-  ENUM_VALUE16186 = 16706;
-  ENUM_VALUE16187 = 16707;
-  ENUM_VALUE16188 = 16708;
-  ENUM_VALUE16189 = 16709;
-  ENUM_VALUE16190 = 16710;
-  ENUM_VALUE16191 = 16711;
-  ENUM_VALUE16192 = 16712;
-  ENUM_VALUE16193 = 16713;
-  ENUM_VALUE16194 = 1046;
-  ENUM_VALUE16195 = 16737;
-  ENUM_VALUE16196 = 1047;
-  ENUM_VALUE16197 = 16753;
-  ENUM_VALUE16198 = 268049;
-  ENUM_VALUE16199 = 268050;
-  ENUM_VALUE16200 = 268051;
-  ENUM_VALUE16201 = 268052;
-  ENUM_VALUE16202 = 1048;
-  ENUM_VALUE16203 = 16769;
-  ENUM_VALUE16204 = 16770;
-  ENUM_VALUE16205 = 16771;
-  ENUM_VALUE16206 = 16772;
-  ENUM_VALUE16207 = 16773;
-  ENUM_VALUE16208 = 1049;
-  ENUM_VALUE16209 = 1056;
-  ENUM_VALUE16210 = 1058;
-  ENUM_VALUE16211 = 1059;
-  ENUM_VALUE16212 = 1060;
-  ENUM_VALUE16213 = 1061;
-  ENUM_VALUE16214 = 5;
-  ENUM_VALUE16215 = 6;
-  ENUM_VALUE16216 = 97;
-  ENUM_VALUE16217 = 98;
-  ENUM_VALUE16218 = 99;
-  ENUM_VALUE16219 = 100;
-  ENUM_VALUE16220 = 101;
-  ENUM_VALUE16221 = 102;
-  ENUM_VALUE16222 = 103;
-  ENUM_VALUE16223 = 104;
-  ENUM_VALUE16224 = 105;
-  ENUM_VALUE16225 = 106;
-  ENUM_VALUE16226 = 108;
-  ENUM_VALUE16227 = 1729;
-  ENUM_VALUE16228 = 1730;
-  ENUM_VALUE16229 = 1731;
-  ENUM_VALUE16230 = 7;
-  ENUM_VALUE16231 = 8;
-  ENUM_VALUE16232 = 9;
-  ENUM_VALUE16233 = 10;
-  ENUM_VALUE16234 = 161;
-  ENUM_VALUE16235 = 2577;
-  ENUM_VALUE16236 = 41233;
-  ENUM_VALUE16237 = 41234;
-  ENUM_VALUE16238 = 2578;
-  ENUM_VALUE16239 = 2579;
-  ENUM_VALUE16240 = 41265;
-  ENUM_VALUE16241 = 2580;
-  ENUM_VALUE16242 = 2581;
-  ENUM_VALUE16243 = 41297;
-  ENUM_VALUE16244 = 41298;
-  ENUM_VALUE16245 = 41299;
-  ENUM_VALUE16246 = 41300;
-  ENUM_VALUE16247 = 2582;
-  ENUM_VALUE16248 = 2583;
-  ENUM_VALUE16249 = 2584;
-  ENUM_VALUE16250 = 162;
-  ENUM_VALUE16251 = 2593;
-  ENUM_VALUE16252 = 41489;
-  ENUM_VALUE16253 = 663825;
-  ENUM_VALUE16254 = 663826;
-  ENUM_VALUE16255 = 41490;
-  ENUM_VALUE16256 = 41491;
-  ENUM_VALUE16257 = 41492;
-  ENUM_VALUE16258 = 663873;
-  ENUM_VALUE16259 = 2594;
-  ENUM_VALUE16260 = 41505;
-  ENUM_VALUE16261 = 41506;
-  ENUM_VALUE16262 = 41507;
-  ENUM_VALUE16263 = 2595;
-  ENUM_VALUE16264 = 41521;
-  ENUM_VALUE16265 = 41522;
-  ENUM_VALUE16266 = 41523;
-  ENUM_VALUE16267 = 41524;
-  ENUM_VALUE16268 = 41525;
-  ENUM_VALUE16269 = 664401;
-  ENUM_VALUE16270 = 664402;
-  ENUM_VALUE16271 = 41526;
-  ENUM_VALUE16272 = 41527;
-  ENUM_VALUE16273 = 2596;
-  ENUM_VALUE16274 = 2597;
-  ENUM_VALUE16275 = 2598;
-  ENUM_VALUE16276 = 41569;
-  ENUM_VALUE16277 = 41570;
-  ENUM_VALUE16278 = 41571;
-  ENUM_VALUE16279 = 41572;
-  ENUM_VALUE16280 = 41573;
-  ENUM_VALUE16281 = 665169;
-  ENUM_VALUE16282 = 665170;
-  ENUM_VALUE16283 = 665171;
-  ENUM_VALUE16284 = 665172;
-  ENUM_VALUE16285 = 2599;
-  ENUM_VALUE16286 = 2600;
-  ENUM_VALUE16287 = 2601;
-  ENUM_VALUE16288 = 2603;
-  ENUM_VALUE16289 = 2604;
-  ENUM_VALUE16290 = 163;
-  ENUM_VALUE16291 = 2608;
-  ENUM_VALUE16292 = 2609;
-  ENUM_VALUE16293 = 2610;
-  ENUM_VALUE16294 = 2611;
-  ENUM_VALUE16295 = 2612;
-  ENUM_VALUE16296 = 164;
-  ENUM_VALUE16297 = 2625;
-  ENUM_VALUE16298 = 2626;
-  ENUM_VALUE16299 = 42017;
-  ENUM_VALUE16300 = 42018;
-  ENUM_VALUE16301 = 42019;
-  ENUM_VALUE16302 = 2627;
-  ENUM_VALUE16303 = 2628;
-  ENUM_VALUE16304 = 165;
-  ENUM_VALUE16305 = 2641;
-  ENUM_VALUE16306 = 42257;
-  ENUM_VALUE16307 = 42258;
-  ENUM_VALUE16308 = 2642;
-  ENUM_VALUE16309 = 2643;
-  ENUM_VALUE16310 = 2644;
-  ENUM_VALUE16311 = 2646;
-  ENUM_VALUE16312 = 2647;
-  ENUM_VALUE16313 = 42353;
-  ENUM_VALUE16314 = 2648;
-  ENUM_VALUE16315 = 2649;
-  ENUM_VALUE16316 = 2650;
-  ENUM_VALUE16317 = 2651;
-  ENUM_VALUE16318 = 2652;
-  ENUM_VALUE16319 = 2653;
-  ENUM_VALUE16320 = 2654;
-  ENUM_VALUE16321 = 42481;
-  ENUM_VALUE16322 = 42482;
-  ENUM_VALUE16323 = 42483;
-  ENUM_VALUE16324 = 166;
-  ENUM_VALUE16325 = 2657;
-  ENUM_VALUE16326 = 2658;
-  ENUM_VALUE16327 = 42529;
-  ENUM_VALUE16328 = 2659;
-  ENUM_VALUE16329 = 2660;
-  ENUM_VALUE16330 = 2661;
-  ENUM_VALUE16331 = 2662;
-  ENUM_VALUE16332 = 2663;
-  ENUM_VALUE16333 = 42609;
-  ENUM_VALUE16334 = 2664;
-  ENUM_VALUE16335 = 2665;
-  ENUM_VALUE16336 = 42753;
-  ENUM_VALUE16337 = 42754;
-  ENUM_VALUE16338 = 42755;
-  ENUM_VALUE16339 = 11;
-  ENUM_VALUE16340 = 177;
-  ENUM_VALUE16341 = 2833;
-  ENUM_VALUE16342 = 179;
-  ENUM_VALUE16343 = 180;
-  ENUM_VALUE16344 = 2881;
-  ENUM_VALUE16345 = 182;
-  ENUM_VALUE16346 = 183;
-  ENUM_VALUE16347 = 12;
-  ENUM_VALUE16348 = 3089;
-  ENUM_VALUE16349 = 194;
-  ENUM_VALUE16350 = 195;
-  ENUM_VALUE16351 = 196;
-  ENUM_VALUE16352 = 198;
-  ENUM_VALUE16353 = 3169;
-  ENUM_VALUE16354 = 199;
-  ENUM_VALUE16355 = 200;
-  ENUM_VALUE16356 = 208;
-  ENUM_VALUE16357 = 3329;
-  ENUM_VALUE16358 = 3330;
-  ENUM_VALUE16359 = 3331;
-  ENUM_VALUE16360 = 209;
-  ENUM_VALUE16361 = 210;
-  ENUM_VALUE16362 = 211;
-  ENUM_VALUE16363 = 3377;
-  ENUM_VALUE16364 = 3378;
-  ENUM_VALUE16365 = 3379;
-  ENUM_VALUE16366 = 3380;
-  ENUM_VALUE16367 = 3381;
-  ENUM_VALUE16368 = 865809;
-  ENUM_VALUE16369 = 865810;
-  ENUM_VALUE16370 = 865811;
-  ENUM_VALUE16371 = 865812;
-  ENUM_VALUE16372 = 865813;
-  ENUM_VALUE16373 = 865814;
-  ENUM_VALUE16374 = 865815;
-  ENUM_VALUE16375 = 865816;
-  ENUM_VALUE16376 = 865817;
-  ENUM_VALUE16377 = 865818;
-  ENUM_VALUE16378 = 865819;
-  ENUM_VALUE16379 = 865820;
-  ENUM_VALUE16380 = 865821;
-  ENUM_VALUE16381 = 865822;
-  ENUM_VALUE16382 = 865823;
-  ENUM_VALUE16383 = 865824;
-  ENUM_VALUE16384 = 865825;
-  ENUM_VALUE16385 = 865826;
-  ENUM_VALUE16386 = 865827;
-  ENUM_VALUE16387 = 865828;
-  ENUM_VALUE16388 = 865829;
-  ENUM_VALUE16389 = 212;
-  ENUM_VALUE16390 = 3393;
-  ENUM_VALUE16391 = 3394;
-  ENUM_VALUE16392 = 3395;
-  ENUM_VALUE16393 = 213;
-  ENUM_VALUE16394 = 214;
-  ENUM_VALUE16395 = 215;
-  ENUM_VALUE16396 = 3441;
-  ENUM_VALUE16397 = 3442;
-  ENUM_VALUE16398 = 216;
-  ENUM_VALUE16399 = 217;
-  ENUM_VALUE16400 = 3473;
-  ENUM_VALUE16401 = 3474;
-  ENUM_VALUE16402 = 3475;
-  ENUM_VALUE16403 = 254;
-  ENUM_VALUE16404 = 255;
-}
-
-enum Enum16553 {
-  ENUM_VALUE16554 = 0;
-  ENUM_VALUE16555 = 1;
-  ENUM_VALUE16556 = 2;
-  ENUM_VALUE16557 = 3;
-  ENUM_VALUE16558 = 4;
-  ENUM_VALUE16559 = 5;
-  ENUM_VALUE16560 = 6;
-  ENUM_VALUE16561 = 7;
-  ENUM_VALUE16562 = 8;
-  ENUM_VALUE16563 = 9;
-}
-
-enum Enum16728 {
-  ENUM_VALUE16729 = 1;
-  ENUM_VALUE16730 = 2;
-  ENUM_VALUE16731 = 3;
-}
-
-enum Enum16732 {
-  ENUM_VALUE16733 = 1;
-  ENUM_VALUE16734 = 2;
-  ENUM_VALUE16735 = 3;
-  ENUM_VALUE16736 = 4;
-  ENUM_VALUE16737 = 5;
-}
-
-enum Enum16738 {
-  ENUM_VALUE16739 = 1;
-  ENUM_VALUE16740 = 2;
-  ENUM_VALUE16741 = 3;
-  ENUM_VALUE16742 = 4;
-  ENUM_VALUE16743 = 5;
-  ENUM_VALUE16744 = 6;
-  ENUM_VALUE16745 = 7;
-}
-
-enum Enum16698 {
-  ENUM_VALUE16699 = -1;
-  ENUM_VALUE16700 = 100;
-  ENUM_VALUE16701 = 2;
-  ENUM_VALUE16702 = 0;
-  ENUM_VALUE16703 = 1;
-  ENUM_VALUE16704 = 4;
-  ENUM_VALUE16705 = 11;
-  ENUM_VALUE16706 = 12;
-  ENUM_VALUE16707 = 3;
-  ENUM_VALUE16708 = 5;
-  ENUM_VALUE16709 = 6;
-  ENUM_VALUE16710 = 7;
-  ENUM_VALUE16711 = 8;
-  ENUM_VALUE16712 = 9;
-  ENUM_VALUE16713 = 10;
-  ENUM_VALUE16714 = 13;
-  ENUM_VALUE16715 = 14;
-  ENUM_VALUE16716 = 15;
-  ENUM_VALUE16717 = 16;
-  ENUM_VALUE16718 = 18;
-  ENUM_VALUE16719 = 17;
-  ENUM_VALUE16720 = 19;
-  ENUM_VALUE16721 = 20;
-}
-
-enum Enum16819 {
-  ENUM_VALUE16820 = 0;
-  ENUM_VALUE16821 = 1;
-  ENUM_VALUE16822 = 2;
-  ENUM_VALUE16823 = 3;
-  ENUM_VALUE16824 = 4;
-  ENUM_VALUE16825 = 5;
-}
-
-enum Enum16925 {
-  ENUM_VALUE16926 = 0;
-  ENUM_VALUE16927 = 1;
-  ENUM_VALUE16928 = 2;
-  ENUM_VALUE16929 = 3;
-  ENUM_VALUE16930 = 4;
-  ENUM_VALUE16931 = 5;
-  ENUM_VALUE16932 = 6;
-  ENUM_VALUE16933 = 7;
-  ENUM_VALUE16934 = 8;
-  ENUM_VALUE16935 = 9;
-  ENUM_VALUE16936 = 10;
-  ENUM_VALUE16937 = 11;
-  ENUM_VALUE16938 = 12;
-  ENUM_VALUE16939 = 13;
-}
-
-enum Enum22854 {
-  ENUM_VALUE22855 = 0;
-  ENUM_VALUE22856 = 1;
-}
-
-enum Enum24361 {
-  ENUM_VALUE24362 = 0;
-  ENUM_VALUE24363 = 1;
-  ENUM_VALUE24364 = 2;
-  ENUM_VALUE24365 = 3;
-}
-
-enum Enum16891 {
-  ENUM_VALUE16892 = 0;
-  ENUM_VALUE16893 = 1;
-  ENUM_VALUE16894 = 2;
-  ENUM_VALUE16895 = 3;
-  ENUM_VALUE16896 = 4;
-  ENUM_VALUE16897 = 5;
-  ENUM_VALUE16898 = 6;
-  ENUM_VALUE16899 = 7;
-  ENUM_VALUE16900 = 8;
-  ENUM_VALUE16901 = 9;
-  ENUM_VALUE16902 = 10;
-  ENUM_VALUE16903 = 11;
-  ENUM_VALUE16904 = 12;
-  ENUM_VALUE16905 = 13;
-  ENUM_VALUE16906 = 14;
-  ENUM_VALUE16907 = 15;
-  ENUM_VALUE16908 = 16;
-  ENUM_VALUE16909 = 17;
-  ENUM_VALUE16910 = 18;
-  ENUM_VALUE16911 = 19;
-  ENUM_VALUE16912 = 20;
-  ENUM_VALUE16913 = 21;
-  ENUM_VALUE16914 = 22;
-  ENUM_VALUE16915 = 23;
-  ENUM_VALUE16916 = 24;
-  ENUM_VALUE16917 = 25;
-  ENUM_VALUE16918 = 26;
-  ENUM_VALUE16919 = 27;
-  ENUM_VALUE16920 = 28;
-  ENUM_VALUE16921 = 29;
-  ENUM_VALUE16922 = 30;
-  ENUM_VALUE16923 = 31;
-}
-
-enum Enum27361 {
-  ENUM_VALUE27362 = 0;
-  ENUM_VALUE27363 = 1;
-  ENUM_VALUE27364 = 2;
-  ENUM_VALUE27365 = 3;
-  ENUM_VALUE27366 = 4;
-}
-
-enum Enum33960 {
-  ENUM_VALUE33961 = 0;
-  ENUM_VALUE33962 = 1;
-  ENUM_VALUE33963 = 2;
-  ENUM_VALUE33964 = 3;
-  ENUM_VALUE33965 = 4;
-  ENUM_VALUE33966 = 5;
-  ENUM_VALUE33967 = 6;
-}
-
-enum Enum34388 { ENUM_VALUE34389 = 1; }
-
-enum Enum35477 {
-  ENUM_VALUE35478 = 4;
-  ENUM_VALUE35479 = 3;
-  ENUM_VALUE35480 = 2;
-  ENUM_VALUE35481 = 1;
-  ENUM_VALUE35482 = 0;
-}
-
-enum Enum35507 {
-  ENUM_VALUE35508 = 0;
-  ENUM_VALUE35509 = 1;
-  ENUM_VALUE35510 = 2;
-  ENUM_VALUE35511 = 3;
-  ENUM_VALUE35512 = 4;
-  ENUM_VALUE35513 = 5;
-  ENUM_VALUE35514 = 6;
-  ENUM_VALUE35515 = 7;
-  ENUM_VALUE35516 = 8;
-  ENUM_VALUE35517 = 9;
-}
-
-enum Enum36860 {
-  ENUM_VALUE36861 = 0;
-  ENUM_VALUE36862 = 1;
-  ENUM_VALUE36863 = 2;
-  ENUM_VALUE36864 = 3;
-  ENUM_VALUE36865 = 4;
-  ENUM_VALUE36866 = 5;
-  ENUM_VALUE36867 = 6;
-  ENUM_VALUE36868 = 7;
-}
-
-enum Enum36890 {
-  ENUM_VALUE36891 = 0;
-  ENUM_VALUE36892 = 1;
-}
diff --git a/benchmarks/datasets/google_message4/BUILD.bazel b/benchmarks/datasets/google_message4/BUILD.bazel
deleted file mode 100644
index 33de093..0000000
--- a/benchmarks/datasets/google_message4/BUILD.bazel
+++ /dev/null
@@ -1,53 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_proto_library")
-load("@rules_java//java:defs.bzl", "java_proto_library")
-load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
-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",
-    ],
-)
-
-pkg_files(
-    name = "dist_files",
-    srcs = glob(["*"]),
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//benchmarks:__pkg__"],
-)
diff --git a/benchmarks/datasets/google_message4/benchmark_message4.proto b/benchmarks/datasets/google_message4/benchmark_message4.proto
deleted file mode 100644
index 424ed10..0000000
--- a/benchmarks/datasets/google_message4/benchmark_message4.proto
+++ /dev/null
@@ -1,484 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message4;
-
-import "datasets/google_message4/benchmark_message4_1.proto";
-import "datasets/google_message4/benchmark_message4_2.proto";
-import "datasets/google_message4/benchmark_message4_3.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message GoogleMessage4 {
-  optional int32 field37503 = 1;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37504 = 2;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37505 = 3;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37506 = 4;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37507 = 5;
-  optional .benchmarks.google_message4.Message37489 field37508 = 6;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37509 = 7;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37510 = 8;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37511 = 9;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37512 = 10;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37513 = 11;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37514 = 12;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37515 = 13;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37516 = 14;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37517 = 15;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37518 = 16;
-}
-
-message Message37489 {
-  optional .benchmarks.google_message4.Message2517 field37534 = 3;
-  optional .benchmarks.google_message4.Message7330 field37535 = 4;
-  optional .benchmarks.google_message4.Message8815 field37536 = 6;
-  optional .benchmarks.google_message4.Message8817 field37537 = 7;
-  optional .benchmarks.google_message4.Message8835 field37538 = 8;
-  optional .benchmarks.google_message4.Message8848 field37539 = 9;
-  optional .benchmarks.google_message4.Message8856 field37540 = 11;
-  optional .benchmarks.google_message4.Message12717 field37541 = 15;
-  optional .benchmarks.google_message4.Message12748 field37542 = 20;
-  optional .benchmarks.google_message4.Message7319 field37543 = 22;
-  optional .benchmarks.google_message4.Message12908 field37544 = 24;
-  optional .benchmarks.google_message4.Message12910 field37545 = 25;
-  optional .benchmarks.google_message4.Message12960 field37546 = 30;
-  optional .benchmarks.google_message4.Message176 field37547 = 33;
-  optional .benchmarks.google_message4.Message13000 field37548 = 34;
-  optional .benchmarks.google_message4.Message13035 field37549 = 35;
-  optional .benchmarks.google_message4.Message37331 field37550 = 36;
-  optional .benchmarks.google_message4.Message37329 field37551 = 37;
-  optional .benchmarks.google_message4.Message37327 field37552 = 38;
-  optional .benchmarks.google_message4.Message37333 field37553 = 39;
-  optional .benchmarks.google_message4.Message37335 field37554 = 40;
-}
-
-message Message7319 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7321 = 1;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7322 = 7;
-}
-
-message Message12717 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12719 = 1;
-  optional string field12720 = 2;
-  optional uint32 field12721 = 3;
-  optional .benchmarks.google_message4.Message11976 field12722 = 4;
-  repeated .benchmarks.google_message4.Message11948 field12723 = 5;
-  optional .benchmarks.google_message4.Message11947 field12724 = 6;
-  optional .benchmarks.google_message4.Message12687 field12725 = 7;
-  repeated .benchmarks.google_message4.Message11948 field12726 = 8;
-  optional int64 field12727 = 9;
-}
-
-message Message37331 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37367 = 4;
-  required .benchmarks.google_message4.Message37326 field37368 = 1;
-  required int64 field37369 = 2;
-  required bytes field37370 = 3;
-}
-
-message Message8815 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8819 = 1;
-  repeated .benchmarks.google_message4.Message8768 field8820 = 2;
-  optional bool field8821 = 3;
-}
-
-message Message7330 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7332 = 1;
-  optional .benchmarks.google_message4.Message3069 field7333 = 2;
-  optional .benchmarks.google_message4.Message7320 field7334 = 3;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7335 = 4;
-  optional bool field7336 = 5;
-  optional int64 field7337 = 6;
-}
-
-message Message12960 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12962 = 1;
-  optional .benchmarks.google_message4.Message12948 field12963 = 2;
-}
-
-message Message176 {
-  required string field408 = 1;
-  optional int32 field409 = 4;
-  optional string field410 = 50;
-  optional int32 field411 = 2;
-  optional uint64 field412 = 47;
-  optional string field413 = 56;
-  optional int32 field414 = 24;
-  optional string field415 = 21;
-  optional bytes field416 = 3;
-  optional string field417 = 57;
-  optional int32 field418 = 51;
-  optional float field419 = 7;
-  optional bool field420 = 5;
-  optional bool field421 = 28;
-  optional int32 field422 = 6;
-  repeated int32 field423 = 40;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field424 = 41;
-  optional bool field425 = 25;
-  optional uint64 field426 = 26;
-  optional int32 field427 = 38;
-  optional bytes field428 = 15;
-  optional bytes field429 = 55;
-  optional bytes field430 = 16;
-  optional bytes field431 = 23;
-  optional bool field432 = 33;
-  optional bytes field433 = 31;
-  optional bytes field434 = 32;
-  optional int32 field435 = 36;
-  optional uint64 field436 = 17;
-  optional int32 field437 = 45;
-  optional uint64 field438 = 18;
-  optional string field439 = 46;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field440 = 64;
-  optional int32 field441 = 39;
-  optional uint64 field442 = 48;
-  optional bytes field443 = 19;
-  optional bytes field444 = 42;
-  optional bytes field445 = 43;
-  optional string field446 = 44;
-  optional string field447 = 49;
-  optional int64 field448 = 20;
-  optional bool field449 = 53;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field450 = 54;
-  repeated .benchmarks.google_message4.UnusedEmptyMessage field451 = 22;
-  optional .benchmarks.google_message4.UnusedEnum field452 = 27;
-  optional int32 field453 = 29;
-  optional int32 field454 = 30;
-  optional .benchmarks.google_message4.UnusedEnum field455 = 37;
-  optional .benchmarks.google_message4.UnusedEnum field456 = 34;
-  optional int32 field457 = 35;
-  repeated group Message178 = 101 {}
-  optional bool field459 = 52;
-  optional uint64 field460 = 58;
-  optional uint64 field461 = 59;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field462 = 60;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field463 = 61;
-  optional .benchmarks.google_message4.UnusedEnum field464 = 62;
-  repeated string field465 = 63;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field466 = 65;
-}
-
-message Message8817 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8825 = 1;
-  repeated .benchmarks.google_message4.Message8768 field8826 = 2;
-  optional string field8827 = 3;
-}
-
-message Message8835 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8837 = 1;
-  repeated string field8838 = 2;
-  optional .benchmarks.google_message4.UnusedEnum field8839 = 3;
-}
-
-message Message37333 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37372 = 3;
-  required .benchmarks.google_message4.Message37326 field37373 = 1;
-  optional uint64 field37374 = 2;
-}
-
-message Message13000 {
-  optional int64 field13015 = 1;
-  repeated .benchmarks.google_message4.Message12979 field13016 = 2;
-}
-
-message Message37335 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37376 = 4;
-  required .benchmarks.google_message4.Message37326 field37377 = 1;
-  required .benchmarks.google_message4.Message37173 field37378 = 2;
-  optional uint64 field37379 = 3;
-}
-
-message Message8848 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8850 = 1;
-  optional string field8851 = 2;
-  optional bytes field8852 = 3;
-}
-
-message Message13035 {
-  optional int64 field13058 = 1;
-  repeated int64 field13059 = 2;
-}
-
-message Message8856 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8858 = 1;
-  optional string field8859 = 2;
-}
-
-message Message12908 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12912 = 1;
-  optional string field12913 = 2;
-  optional .benchmarks.google_message4.Message12799 field12914 = 3;
-  optional int64 field12915 = 4;
-  optional .benchmarks.google_message4.Message3804 field12916 = 5;
-  optional .benchmarks.google_message4.Message12870 field12917 = 6;
-}
-
-message Message12910 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12920 = 1;
-  optional .benchmarks.google_message4.Message12818 field12921 = 2;
-  repeated .benchmarks.google_message4.Message12903 field12922 = 3;
-}
-
-message Message37327 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37347 = 11;
-  required .benchmarks.google_message4.Message37326 field37348 = 1;
-  optional bool field37349 = 2;
-  optional bool field37350 = 3;
-  optional bool field37351 = 4;
-  optional bool field37352 = 5;
-  optional bool field37353 = 6;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37354 = 7;
-  optional uint64 field37355 = 8;
-  optional bool field37356 = 9;
-  optional bool field37357 = 10;
-}
-
-message Message37329 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37359 = 6;
-  required .benchmarks.google_message4.Message37326 field37360 = 1;
-  required int64 field37361 = 2;
-  required int64 field37362 = 3;
-  optional bool field37363 = 4;
-}
-
-message Message2517 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field2519 = 1;
-  optional .benchmarks.google_message4.Message2356 field2520 = 2;
-  optional .benchmarks.google_message4.Message0 field2521 = 3;
-  optional .benchmarks.google_message4.Message2463 field2522 = 4;
-  repeated .benchmarks.google_message4.Message971 field2523 = 5;
-}
-
-message Message12748 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12754 = 1;
-  optional string field12755 = 2;
-  optional string field12756 = 3;
-  optional .benchmarks.google_message4.Enum12735 field12757 = 4;
-}
-
-message Message12687 {
-  repeated .benchmarks.google_message4.Message12686 field12701 = 1;
-}
-
-message Message11948 {
-  optional string field11954 = 1;
-  repeated .benchmarks.google_message4.Message11949 field11955 = 2;
-  optional bool field11956 = 3;
-}
-
-message Message11976 {
-  repeated .benchmarks.google_message4.Message11975 field12002 = 1;
-}
-
-message Message7320 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7323 = 1;
-  optional .benchmarks.google_message4.Message7287 field7324 = 8;
-}
-
-message Message3069 {
-  optional .benchmarks.google_message4.Message3061 field3374 = 1;
-  optional bytes field3375 = 2;
-  repeated group Message3070 = 3 {
-    required .benchmarks.google_message4.Enum3071 field3378 = 4;
-    required bytes field3379 = 5;
-  }
-  extensions 10000 to 536870911;
-}
-
-message Message12948 {
-  repeated .benchmarks.google_message4.Message12949 field12958 = 1;
-}
-
-message Message8768 {
-  optional string field8782 = 1;
-  optional .benchmarks.google_message4.Message8572 field8783 = 2;
-  optional bool field8784 = 3;
-  repeated .benchmarks.google_message4.Message8774 field8785 = 4;
-  optional int64 field8786 = 5;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8787 = 6;
-  optional string field8788 = 7;
-}
-
-message Message12979 {
-  required bytes field12981 = 1;
-  repeated string field12982 = 2;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12983 = 3;
-  optional int64 field12984 = 4;
-  optional string field12985 = 5;
-  optional int32 field12986 = 6;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12987 = 7;
-}
-
-message Message37173 {
-  optional string field37252 = 1;
-  optional int64 field37253 = 2;
-  optional .benchmarks.google_message4.UnusedEnum field37254 = 4;
-  optional bool field37255 = 5;
-  optional bool field37256 = 6;
-  optional bool field37257 = 7;
-  optional string field37258 = 8;
-  optional string field37259 = 9;
-  optional uint32 field37260 = 10;
-  optional fixed32 field37261 = 11;
-  optional string field37262 = 12;
-  optional string field37263 = 13;
-  optional string field37264 = 14;
-  optional int32 field37265 = 15;
-  optional int64 field37266 = 16;
-  optional int64 field37267 = 17;
-  optional int32 field37268 = 18;
-  optional int32 field37269 = 19;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37270 = 20;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37271 = 21;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37272 = 22;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37273 = 23;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field37274 = 24;
-  optional string field37275 = 25;
-  optional bool field37276 = 26;
-}
-
-message Message12799 {
-  required string field12809 = 1;
-  repeated fixed64 field12810 = 2;
-  repeated .benchmarks.google_message4.Message12776 field12811 = 8;
-  repeated int32 field12812 = 4;
-  repeated .benchmarks.google_message4.Message12798 field12813 = 5;
-  required int32 field12814 = 3;
-  optional int32 field12815 = 6;
-  optional .benchmarks.google_message4.Message12797 field12816 = 7;
-}
-
-message Message12870 {
-  required int32 field12879 = 1;
-  optional int32 field12880 = 7;
-  required int32 field12881 = 2;
-  optional uint64 field12882 = 3;
-  optional string field12883 = 2001;
-  optional fixed64 field12884 = 4;
-  repeated fixed64 field12885 = 14;
-  optional int32 field12886 = 9;
-  optional int64 field12887 = 18;
-  repeated .benchmarks.google_message4.Message12870 field12888 = 8;
-  optional int32 field12889 = 5;
-  optional uint64 field12890 = 6;
-  optional int32 field12891 = 10;
-  optional int32 field12892 = 11;
-  optional double field12893 = 12;
-  optional .benchmarks.google_message4.Message12825 field12894 = 13;
-  optional double field12895 = 15;
-  optional string field12896 = 16;
-  optional .benchmarks.google_message4.Enum12871 field12897 = 17;
-  optional int32 field12898 = 19;
-}
-
-message Message3804 {
-  required int64 field3818 = 1;
-  required bool field3819 = 2;
-  repeated .benchmarks.google_message4.Enum3805 field3820 = 4;
-  optional int32 field3821 = 5;
-  optional bool field3822 = 6;
-  optional int64 field3823 = 7;
-  optional .benchmarks.google_message4.Enum3783 field3824 = 8;
-}
-
-message Message12903 {
-  optional string field12905 = 1;
-  optional .benchmarks.google_message4.Message8587 field12906 = 2;
-  repeated .benchmarks.google_message4.Message8590 field12907 = 3;
-}
-
-message Message37326 {
-  required string field37345 = 1;
-  optional string field37346 = 2;
-}
-
-message Message2356 {
-  optional .benchmarks.google_message4.Message1374 field2368 = 121;
-  optional uint64 field2369 = 1;
-  optional int32 field2370 = 2;
-  optional int32 field2371 = 17;
-  required string field2372 = 3;
-  optional int32 field2373 = 7;
-  optional bytes field2374 = 8;
-  optional string field2375 = 4;
-  optional string field2376 = 101;
-  optional int32 field2377 = 102;
-  optional int32 field2378 = 103;
-  optional int32 field2379 = 104;
-  optional int32 field2380 = 113;
-  optional int32 field2381 = 114;
-  optional int32 field2382 = 115;
-  optional int32 field2383 = 117;
-  optional int32 field2384 = 118;
-  optional int32 field2385 = 119;
-  optional int32 field2386 = 105;
-  optional bytes field2387 = 5;
-  optional group Message2357 = 6 {
-    optional int64 field2399 = 9;
-    optional int32 field2400 = 10;
-    optional int32 field2401 = 11;
-    optional int32 field2402 = 12;
-    optional int32 field2403 = 13;
-    optional int32 field2404 = 116;
-    optional int32 field2405 = 106;
-    required bytes field2406 = 14;
-    optional int32 field2407 = 45;
-    optional int32 field2408 = 112;
-    optional bool field2409 = 122;
-    optional bytes field2410 = 124;
-  }
-  optional string field2389 = 120;
-  optional group Message2358 = 107 {}
-  repeated group Message2359 = 40 {}
-  optional int32 field2392 = 50;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field2393 = 60;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field2394 = 70;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field2395 = 80;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field2396 = 90;
-  optional string field2397 = 100;
-  optional string field2398 = 123;
-}
-
-message Message0 {
-  option message_set_wire_format = true;
-
-  extensions 4 to 2147483646;
-}
-
-message Message971 {
-  optional string field972 = 1;
-  optional int32 field973 = 2;
-  optional bool field974 = 3;
-}
diff --git a/benchmarks/datasets/google_message4/benchmark_message4_1.proto b/benchmarks/datasets/google_message4/benchmark_message4_1.proto
deleted file mode 100644
index c5deecd..0000000
--- a/benchmarks/datasets/google_message4/benchmark_message4_1.proto
+++ /dev/null
@@ -1,500 +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.
-
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package benchmarks.google_message4;
-
-import "datasets/google_message4/benchmark_message4_2.proto";
-import "datasets/google_message4/benchmark_message4_3.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message2463 {
-  repeated .benchmarks.google_message4.Message2462 field2498 = 1;
-}
-
-message Message12686 {
-  optional string field12699 = 1;
-  optional .benchmarks.google_message4.Message12685 field12700 = 2;
-}
-
-message Message11949 {}
-
-message Message11975 {
-  optional string field11992 = 1;
-  optional int32 field11993 = 2;
-  repeated .benchmarks.google_message4.Message10320 field11994 = 3;
-  optional .benchmarks.google_message4.Message11947 field11995 = 4;
-  optional .benchmarks.google_message4.Message11920 field11996 = 5;
-  optional bool field11997 = 6;
-  repeated string field11998 = 7;
-  optional float field11999 = 8;
-  repeated .benchmarks.google_message4.UnusedEnum field12000 = 9;
-  optional int32 field12001 = 11;
-}
-
-message Message7287 {
-  optional .benchmarks.google_message4.Message6133 field7311 = 1;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7312 = 8;
-  optional string field7313 = 3;
-  optional .benchmarks.google_message4.Message6643 field7314 = 4;
-  optional .benchmarks.google_message4.Enum7288 field7315 = 5;
-  optional bytes field7316 = 6;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7317 = 7;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7318 = 9;
-}
-
-message Message3061 {
-  optional string field3286 = 2;
-  optional int32 field3287 = 77;
-  optional string field3288 = 49;
-  required .benchmarks.google_message4.Message3046 field3289 = 3;
-  optional .benchmarks.google_message4.Message3046 field3290 = 58;
-  optional group Message3062 = 4 {
-    required int32 field3335 = 5;
-    optional int32 field3336 = 6;
-    optional int32 field3337 = 7;
-  }
-  optional .benchmarks.google_message4.Message3060 field3292 = 104;
-  optional int64 field3293 = 32;
-  optional int32 field3294 = 41;
-  optional group Message3063 = 13 {
-    required int32 field3338 = 14;
-    optional .benchmarks.google_message4.Enum2851 field3339 = 18;
-    optional int64 field3340 = 15;
-    optional int64 field3341 = 23;
-  }
-  optional .benchmarks.google_message4.Enum2834 field3296 = 94;
-  optional bool field3297 = 25;
-  optional bool field3298 = 50;
-  optional string field3299 = 89;
-  optional string field3300 = 91;
-  optional string field3301 = 105;
-  optional .benchmarks.google_message4.Message3050 field3302 = 53;
-  optional fixed64 field3303 = 51;
-  optional fixed64 field3304 = 106;
-  optional int32 field3305 = 60;
-  optional string field3306 = 44;
-  optional bytes field3307 = 81;
-  optional string field3308 = 70;
-  optional bytes field3309 = 45;
-  optional .benchmarks.google_message4.Enum2806 field3310 = 71;
-  optional int32 field3311 = 72;
-  optional bytes field3312 = 78;
-  optional int32 field3313 = 20;
-  repeated group Message3064 = 8 {
-    required .benchmarks.google_message4.Enum2602 field3342 = 9;
-    optional int32 field3343 = 92;
-    optional string field3344 = 10;
-    optional bytes field3345 = 11;
-    optional int32 field3346 = 12;
-    optional .benchmarks.google_message4.Message3060 field3347 = 98;
-    optional .benchmarks.google_message4.UnusedEmptyMessage field3348 = 82;
-    optional .benchmarks.google_message4.Message3050 field3349 = 80;
-    optional fixed64 field3350 = 52;
-    optional int32 field3351 = 33;
-    optional string field3352 = 42;
-    optional string field3353 = 69;
-    optional bytes field3354 = 43;
-    optional .benchmarks.google_message4.Enum2806 field3355 = 73;
-    optional int32 field3356 = 74;
-    optional int32 field3357 = 90;
-    optional bytes field3358 = 79;
-    optional int32 field3359 = 19;
-    optional .benchmarks.google_message4.Enum2834 field3360 = 95;
-  }
-  optional .benchmarks.google_message4.UnusedEmptyMessage field3315 = 39;
-  optional int32 field3316 = 76;
-  optional group Message3065 = 63 {}
-  optional .benchmarks.google_message4.Enum2806 field3318 = 54;
-  optional int32 field3319 = 46;
-  repeated string field3320 = 24;
-  optional fixed32 field3321 = 38;
-  optional bytes field3322 = 99;
-  optional fixed64 field3323 = 1;
-  optional fixed64 field3324 = 97;
-  repeated .benchmarks.google_message4.Message3040 field3325 = 16;
-  repeated .benchmarks.google_message4.Message3041 field3326 = 61;
-  optional group Message3066 = 21 {
-    optional int32 field3366 = 22;
-    optional int32 field3367 = 55;
-    optional int32 field3368 = 88;
-    optional int32 field3369 = 56;
-    optional int32 field3370 = 75;
-    optional int32 field3371 = 57;
-    optional .benchmarks.google_message4.UnusedEmptyMessage field3372 = 85;
-    optional .benchmarks.google_message4.UnusedEmptyMessage field3373 = 96;
-  }
-  optional .benchmarks.google_message4.UnusedEmptyMessage field3328 = 47;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field3329 = 48;
-  optional fixed64 field3330 = 40;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field3331 = 86;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field3332 = 59;
-  optional int32 field3333 = 17;
-}
-
-message Message12949 {}
-
-message Message8572 {
-  optional bytes field8647 = 1;
-  optional bytes field8648 = 3;
-  optional .benchmarks.google_message4.Message3886 field8649 = 4;
-  optional .benchmarks.google_message4.Message3919 field8650 = 57;
-  optional bool field8651 = 5;
-  optional int32 field8652 = 6;
-  optional int32 field8653 = 49;
-  optional .benchmarks.google_message4.Message7905 field8654 = 7;
-  optional int32 field8655 = 10;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8656 = 11;
-  optional bool field8657 = 35;
-  optional bytes field8658 = 12;
-  optional string field8659 = 14;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8660 = 13;
-  optional bytes field8661 = 15;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8662 = 17;
-  optional int32 field8663 = 18;
-  optional int32 field8664 = 19;
-  optional bool field8665 = 20;
-  optional .benchmarks.google_message4.Enum3476 field8666 = 31;
-  optional bool field8667 = 36;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8668 = 39;
-  optional bytes field8669 = 22;
-  optional int32 field8670 = 24;
-  optional .benchmarks.google_message4.Message3052 field8671 = 25;
-  optional bytes field8672 = 26;
-  optional bytes field8673 = 28;
-  optional int32 field8674 = 29;
-  optional bytes field8675 = 30;
-  optional bytes field8676 = 32;
-  optional string field8677 = 33;
-  optional int32 field8678 = 34;
-  optional int32 field8679 = 37;
-  optional double field8680 = 38;
-  optional double field8681 = 42;
-  optional .benchmarks.google_message4.Message3922 field8682 = 40;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8683 = 43;
-  optional int64 field8684 = 44;
-  optional .benchmarks.google_message4.Message7929 field8685 = 45;
-  optional uint64 field8686 = 46;
-  optional uint32 field8687 = 48;
-  optional .benchmarks.google_message4.Message7843 field8688 = 47;
-  optional .benchmarks.google_message4.Message7864 field8689 = 50;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8690 = 52;
-  optional bool field8691 = 58;
-  optional bool field8692 = 54;
-  optional string field8693 = 55;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8694 = 41;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field8695 = 53;
-  optional .benchmarks.google_message4.Message8575 field8696 = 61;
-}
-
-message Message8774 {
-  optional string field8810 = 1;
-  optional string field8811 = 2;
-  optional string field8812 = 3;
-  optional string field8813 = 4;
-  optional string field8814 = 5;
-}
-
-message Message12776 {
-  optional string field12786 = 1;
-  optional fixed64 field12787 = 11;
-  optional int32 field12788 = 6;
-  optional int32 field12789 = 13;
-  optional int32 field12790 = 14;
-  optional int32 field12791 = 15;
-  optional int32 field12792 = 16;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12793 = 8;
-  optional .benchmarks.google_message4.Message12774 field12794 = 10;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field12795 = 12;
-  extensions 2 to 2;
-  extensions 3 to 3;
-  extensions 4 to 4;
-  extensions 5 to 5;
-  extensions 7 to 7;
-  extensions 9 to 9;
-}
-
-message Message12798 {
-  optional int32 field12805 = 1;
-  optional int32 field12806 = 2;
-  optional .benchmarks.google_message4.Message12774 field12807 = 6;
-  optional bool field12808 = 7;
-}
-
-message Message12797 {
-  optional .benchmarks.google_message4.Message12796 field12802 = 1;
-  repeated .benchmarks.google_message4.Message12796 field12803 = 2;
-  optional string field12804 = 3;
-}
-
-message Message12825 {
-  repeated .benchmarks.google_message4.Message12818 field12862 = 1;
-  optional int32 field12863 = 2;
-  optional .benchmarks.google_message4.Message12819 field12864 = 3;
-  optional .benchmarks.google_message4.Message12820 field12865 = 4;
-  optional int32 field12866 = 5;
-  repeated .benchmarks.google_message4.Message12821 field12867 = 6;
-  repeated .benchmarks.google_message4.UnusedEmptyMessage field12868 = 7;
-}
-
-message Message8590 {}
-
-message Message8587 {}
-
-message Message1374 {
-  required string field1375 = 1;
-  optional string field1376 = 2;
-}
-
-message Message2462 {
-  required bytes field2496 = 1;
-  required double field2497 = 2;
-}
-
-message Message12685 {
-  repeated string field12692 = 1;
-  repeated string field12693 = 2;
-  optional int64 field12694 = 3;
-  optional uint32 field12695 = 4;
-  repeated string field12696 = 5;
-  optional string field12697 = 6;
-  optional string field12698 = 7;
-}
-
-message Message10320 {
-  optional .benchmarks.google_message4.Enum10335 field10347 = 1;
-  repeated .benchmarks.google_message4.Message10319 field10348 = 2;
-  optional int32 field10349 = 3;
-  optional int32 field10350 = 4;
-  optional int32 field10351 = 5;
-  optional int32 field10352 = 6;
-  optional .benchmarks.google_message4.Enum10337 field10353 = 7;
-}
-
-message Message11947 {
-  optional uint32 field11951 = 1;
-  optional bool field11952 = 2;
-  optional int32 field11953 = 3;
-}
-
-message Message11920 {
-  optional .benchmarks.google_message4.Enum11901 field11945 = 1;
-  optional .benchmarks.google_message4.UnusedEnum field11946 = 2;
-}
-
-message Message6643 {
-  optional .benchmarks.google_message4.UnusedEmptyMessage field6683 = 3;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field6684 = 4;
-  optional double field6685 = 5;
-  optional double field6686 = 6;
-  optional int32 field6687 = 1;
-  optional int32 field6688 = 2;
-  optional double field6689 = 9;
-  optional bytes field6690 = 10;
-  optional int32 field6691 = 11;
-  optional bool field6692 = 12;
-  optional bool field6693 = 13;
-  optional .benchmarks.google_message4.Message6578 field6694 = 15;
-  optional .benchmarks.google_message4.UnusedEnum field6695 = 16;
-  optional int64 field6696 = 17;
-  repeated .benchmarks.google_message4.UnusedEmptyMessage field6697 = 22;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field6698 = 19;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field6699 = 20;
-  optional int32 field6700 = 21;
-}
-
-message Message6133 {
-  optional .benchmarks.google_message4.Message4016 field6173 = 12;
-  optional double field6174 = 16;
-  required string field6175 = 1;
-  required string field6176 = 2;
-  required string field6177 = 3;
-  optional string field6178 = 4;
-  optional string field6179 = 8;
-  repeated .benchmarks.google_message4.Message6109 field6180 = 5;
-  repeated .benchmarks.google_message4.Message5908 field6181 = 13;
-  repeated .benchmarks.google_message4.Message6107 field6182 = 7;
-  repeated .benchmarks.google_message4.Message6126 field6183 = 9;
-  repeated .benchmarks.google_message4.Message6129 field6184 = 15;
-  optional int32 field6185 = 10;
-  optional int32 field6186 = 11;
-  optional .benchmarks.google_message4.Message4016 field6187 = 17;
-  optional double field6188 = 14;
-  optional double field6189 = 18;
-  optional string field6190 = 19;
-  optional string field6191 = 20;
-  repeated .benchmarks.google_message4.Message5881 field6192 = 21;
-}
-
-message Message6109 {
-  optional string field6140 = 1;
-  required .benchmarks.google_message4.Enum6111 field6141 = 2;
-  optional int32 field6142 = 9;
-  optional string field6143 = 3;
-  repeated .benchmarks.google_message4.Message6110 field6144 = 4;
-  repeated int32 field6145 = 7;
-  repeated int32 field6146 = 8;
-  optional .benchmarks.google_message4.Message6133 field6147 = 10;
-  repeated int32 field6148 = 11;
-  optional string field6149 = 12;
-  optional string field6150 = 13;
-  optional bool field6151 = 14;
-  extensions 1000 to 536870911;
-}
-
-message Message3046 {
-  required .benchmarks.google_message4.Enum2593 field3222 = 1;
-  optional int32 field3223 = 4;
-}
-
-message Message3060 {
-  optional int64 field3283 = 1;
-  optional int64 field3284 = 2;
-  optional int64 field3285 = 3;
-}
-
-message Message3041 {
-  optional string field3214 = 1;
-  optional int32 field3215 = 2;
-}
-
-message Message3040 {
-  required fixed64 field3209 = 1;
-  repeated fixed64 field3210 = 4;
-  optional int32 field3211 = 5;
-  optional fixed64 field3212 = 2;
-  required string field3213 = 3;
-}
-
-message Message3050 {
-  optional bytes field3245 = 5;
-  optional int32 field3246 = 2;
-  optional bytes field3247 = 6;
-  optional int32 field3248 = 4;
-  optional fixed32 field3249 = 1;
-  optional fixed32 field3250 = 3;
-}
-
-message Message7905 {
-  optional int32 field7911 = 1;
-  optional bool field7912 = 2;
-  optional bytes field7913 = 3;
-  optional int32 field7914 = 4;
-  optional int32 field7915 = 5;
-  optional bytes field7916 = 6;
-  optional int32 field7917 = 7;
-}
-
-message Message3886 {
-  repeated group Message3887 = 1 {
-    required string field3932 = 2;
-    optional string field3933 = 9;
-    optional .benchmarks.google_message4.Message3850 field3934 = 3;
-    optional bytes field3935 = 8;
-  }
-}
-
-message Message7864 {
-  optional string field7866 = 1;
-  optional string field7867 = 2;
-  repeated .benchmarks.google_message4.Message7865 field7868 = 5;
-  repeated .benchmarks.google_message4.Message7865 field7869 = 6;
-  repeated .benchmarks.google_message4.Message7865 field7870 = 7;
-  repeated .benchmarks.google_message4.UnusedEmptyMessage field7871 = 8;
-}
-
-message Message3922 {
-  optional uint64 field4012 = 1;
-}
-
-message Message3052 {
-  repeated string field3254 = 1;
-  repeated string field3255 = 2;
-  repeated bytes field3256 = 3;
-  repeated string field3257 = 4;
-  optional bool field3258 = 5;
-  optional int32 field3259 = 6;
-  optional int32 field3260 = 7;
-  optional string field3261 = 8;
-  optional string field3262 = 9;
-}
-
-message Message8575 {}
-
-message Message7843 {
-  optional bool field7844 = 5;
-  optional int32 field7845 = 1;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7846 = 22;
-  repeated int32 field7847 = 3;
-  repeated string field7848 = 11;
-  optional .benchmarks.google_message4.UnusedEnum field7849 = 15;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7850 = 6;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7851 = 14;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7852 = 10;
-  optional .benchmarks.google_message4.Message7511 field7853 = 13;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7854 = 16;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7855 = 17;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7856 = 19;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field7857 = 18;
-  optional .benchmarks.google_message4.UnusedEnum field7858 = 20;
-  optional int32 field7859 = 2;
-}
-
-message Message3919 {
-  repeated .benchmarks.google_message4.Message3920 field4009 = 1;
-}
-
-message Message7929 {
-  optional int64 field7942 = 1;
-  optional int64 field7943 = 4;
-  optional int64 field7944 = 5;
-  optional int64 field7945 = 12;
-  optional int64 field7946 = 13;
-  optional int64 field7947 = 18;
-  optional int64 field7948 = 6;
-  optional int64 field7949 = 7;
-  repeated .benchmarks.google_message4.Message7919 field7950 = 8;
-  repeated .benchmarks.google_message4.UnusedEmptyMessage field7951 = 20;
-  repeated .benchmarks.google_message4.Message7920 field7952 = 14;
-  repeated .benchmarks.google_message4.Message7921 field7953 = 15;
-  repeated .benchmarks.google_message4.Message7928 field7954 = 17;
-  optional int64 field7955 = 19;
-  optional bool field7956 = 2;
-  optional int64 field7957 = 3;
-  optional int64 field7958 = 9;
-  repeated .benchmarks.google_message4.UnusedEmptyMessage field7959 = 10;
-  repeated bytes field7960 = 11;
-  optional int64 field7961 = 16;
-}
diff --git a/benchmarks/datasets/google_message4/benchmark_message4_2.proto b/benchmarks/datasets/google_message4/benchmark_message4_2.proto
deleted file mode 100644
index 0c4cdfd..0000000
--- a/benchmarks/datasets/google_message4/benchmark_message4_2.proto
+++ /dev/null
@@ -1,316 +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";
-
-package benchmarks.google_message4;
-
-import "datasets/google_message4/benchmark_message4_3.proto";
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-message Message12774 {
-  optional uint32 field12777 = 1;
-  optional uint32 field12778 = 2;
-  optional uint32 field12779 = 3;
-  optional uint32 field12780 = 4;
-  optional uint32 field12781 = 5;
-  optional bool field12782 = 6;
-}
-
-message Message12796 {
-  repeated fixed64 field12800 = 1;
-  optional uint64 field12801 = 2;
-}
-
-message Message12821 {
-  optional int32 field12848 = 1;
-  optional int32 field12849 = 2;
-  optional int32 field12850 = 3;
-  optional int32 field12851 = 4;
-  optional int32 field12852 = 5;
-}
-
-message Message12820 {
-  optional int32 field12840 = 1;
-  optional int32 field12841 = 2;
-  optional int32 field12842 = 3;
-  optional int32 field12843 = 8;
-  optional int32 field12844 = 4;
-  optional int32 field12845 = 5;
-  optional int32 field12846 = 6;
-  optional int32 field12847 = 7;
-}
-
-message Message12819 {
-  optional double field12834 = 1;
-  optional double field12835 = 2;
-  optional double field12836 = 3;
-  optional double field12837 = 4;
-  optional double field12838 = 5;
-  optional double field12839 = 6;
-}
-
-message Message12818 {
-  optional uint64 field12829 = 1;
-  optional int32 field12830 = 2;
-  optional int32 field12831 = 3;
-  optional int32 field12832 = 5;
-  repeated .benchmarks.google_message4.Message12817 field12833 = 4;
-}
-
-message Message10319 {
-  optional .benchmarks.google_message4.Enum10325 field10340 = 1;
-  optional int32 field10341 = 4;
-  optional int32 field10342 = 5;
-  optional bytes field10343 = 3;
-  optional string field10344 = 2;
-  optional string field10345 = 6;
-  optional string field10346 = 7;
-}
-
-message Message6578 {
-  optional .benchmarks.google_message4.Enum6579 field6632 = 1;
-  optional .benchmarks.google_message4.Enum6588 field6633 = 2;
-}
-
-message Message6126 {
-  required string field6152 = 1;
-  repeated .benchmarks.google_message4.Message6127 field6153 = 9;
-  optional int32 field6154 = 14;
-  optional bytes field6155 = 10;
-  optional .benchmarks.google_message4.Message6024 field6156 = 12;
-  optional int32 field6157 = 4;
-  optional string field6158 = 5;
-  optional int32 field6159 = 6;
-  repeated int32 field6160 = 2;
-  repeated int32 field6161 = 3;
-  repeated .benchmarks.google_message4.Message6052 field6162 = 7;
-  repeated .benchmarks.google_message4.UnusedEmptyMessage field6163 = 11;
-  optional .benchmarks.google_message4.Enum6065 field6164 = 15;
-  repeated .benchmarks.google_message4.Message6127 field6165 = 8;
-  optional bool field6166 = 13;
-  optional bool field6167 = 16;
-  optional bool field6168 = 18;
-  repeated .benchmarks.google_message4.Message6054 field6169 = 17;
-  optional int32 field6170 = 19;
-}
-
-message Message5881 {
-  required double field5897 = 1;
-  optional string field5898 = 5;
-  optional .benchmarks.google_message4.Message5861 field5899 = 2;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field5900 = 3;
-  optional .benchmarks.google_message4.Message5867 field5901 = 4;
-  optional .benchmarks.google_message4.Message5880 field5902 = 6;
-}
-
-message Message6110 {}
-
-message Message6107 {
-  optional .benchmarks.google_message4.Message4016 field6134 = 1;
-  optional int32 field6135 = 2;
-  optional string field6136 = 3;
-  repeated int32 field6137 = 4;
-  optional int32 field6138 = 5;
-  repeated .benchmarks.google_message4.Message6108 field6139 = 6;
-}
-
-message Message6129 {
-  required .benchmarks.google_message4.Enum6130 field6171 = 1;
-  required string field6172 = 2;
-}
-
-message Message5908 {
-  optional string field5971 = 1;
-  optional int32 field5972 = 2;
-  optional int32 field5973 = 3;
-  optional .benchmarks.google_message4.Enum5909 field5974 = 45;
-  optional .benchmarks.google_message4.Enum5912 field5975 = 4;
-  optional fixed32 field5976 = 50;
-  optional fixed32 field5977 = 5;
-  optional fixed32 field5978 = 6;
-  optional string field5979 = 7;
-  optional .benchmarks.google_message4.Enum5915 field5980 = 8;
-  optional .benchmarks.google_message4.Message5903 field5981 = 9;
-  optional .benchmarks.google_message4.Message5903 field5982 = 10;
-  optional .benchmarks.google_message4.Enum5920 field5983 = 11;
-  optional .benchmarks.google_message4.Enum5923 field5984 = 40;
-  optional .benchmarks.google_message4.Message5903 field5985 = 41;
-  optional .benchmarks.google_message4.Message5903 field5986 = 42;
-  optional .benchmarks.google_message4.Enum5928 field5987 = 47;
-  optional bool field5988 = 48;
-  repeated fixed32 field5989 = 49;
-  optional string field5990 = 12;
-  optional .benchmarks.google_message4.Message5903 field5991 = 13;
-  optional .benchmarks.google_message4.Message5903 field5992 = 14;
-  optional .benchmarks.google_message4.Message5903 field5993 = 15;
-  optional .benchmarks.google_message4.Message5903 field5994 = 16;
-  optional .benchmarks.google_message4.Message5903 field5995 = 32;
-  optional .benchmarks.google_message4.Message5903 field5996 = 33;
-  optional .benchmarks.google_message4.Message5903 field5997 = 34;
-  optional .benchmarks.google_message4.Message5903 field5998 = 35;
-  optional .benchmarks.google_message4.Enum5931 field5999 = 17;
-  optional .benchmarks.google_message4.Enum5935 field6000 = 18;
-  optional .benchmarks.google_message4.Enum5939 field6001 = 36;
-  optional .benchmarks.google_message4.Enum5939 field6002 = 37;
-  repeated int32 field6003 = 19;
-  optional uint32 field6004 = 20;
-  optional uint32 field6005 = 21;
-  optional uint32 field6006 = 22;
-  optional uint32 field6007 = 23;
-  optional .benchmarks.google_message4.Enum5946 field6008 = 24;
-  optional .benchmarks.google_message4.Enum5946 field6009 = 25;
-  optional .benchmarks.google_message4.Enum5946 field6010 = 26;
-  optional .benchmarks.google_message4.Enum5946 field6011 = 27;
-  optional fixed32 field6012 = 28;
-  optional fixed32 field6013 = 29;
-  optional fixed32 field6014 = 30;
-  optional fixed32 field6015 = 31;
-  optional int32 field6016 = 38;
-  optional float field6017 = 39;
-  optional .benchmarks.google_message4.Enum5957 field6018 = 43;
-  optional .benchmarks.google_message4.Message5907 field6019 = 44;
-  optional .benchmarks.google_message4.Enum5962 field6020 = 46;
-}
-
-message Message3850 {
-  optional .benchmarks.google_message4.Enum3851 field3924 = 2;
-  optional bool field3925 = 12;
-  optional int32 field3926 = 4;
-  optional bool field3927 = 10;
-  optional bool field3928 = 13;
-  optional bool field3929 = 14;
-}
-
-message Message7865 {}
-
-message Message7511 {
-  optional bool field7523 = 1;
-  optional .benchmarks.google_message4.Enum7512 field7524 = 2;
-  optional int32 field7525 = 3;
-  optional int32 field7526 = 4;
-  optional bool field7527 = 5;
-  optional int32 field7528 = 6;
-  optional int32 field7529 = 7;
-}
-
-message Message3920 {}
-
-message Message7928 {
-  optional string field7940 = 1;
-  optional int64 field7941 = 2;
-}
-
-message Message7921 {
-  optional int32 field7936 = 1;
-  optional int64 field7937 = 2;
-  optional float field7938 = 3;
-  optional .benchmarks.google_message4.Enum7922 field7939 = 4;
-}
-
-message Message7920 {
-  optional int64 field7934 = 1;
-  optional int64 field7935 = 2;
-}
-
-message Message7919 {
-  optional fixed64 field7931 = 1;
-  optional int64 field7932 = 2;
-  optional bytes field7933 = 3;
-}
-
-message Message12817 {
-  optional int32 field12826 = 1;
-  optional int32 field12827 = 2;
-  optional int32 field12828 = 3;
-}
-
-message Message6054 {
-  required string field6089 = 1;
-  optional string field6090 = 2;
-}
-
-message Message6127 {}
-
-message Message6052 {
-  required string field6084 = 1;
-  required bytes field6085 = 2;
-}
-
-message Message6024 {
-  optional .benchmarks.google_message4.Enum6025 field6048 = 1;
-  optional string field6049 = 2;
-  optional .benchmarks.google_message4.UnusedEmptyMessage field6050 = 3;
-}
-
-message Message5861 {
-  required .benchmarks.google_message4.Enum5862 field5882 = 1;
-  required string field5883 = 2;
-  optional bool field5884 = 3;
-  optional string field5885 = 4;
-}
-
-message Message5880 {
-  optional string field5896 = 1;
-}
-
-message Message5867 {
-  optional .benchmarks.google_message4.Enum5868 field5890 = 1;
-  optional string field5891 = 2;
-  optional .benchmarks.google_message4.Enum5873 field5892 = 3;
-  optional int32 field5893 = 4;
-  optional .benchmarks.google_message4.UnusedEnum field5894 = 5;
-  optional bool field5895 = 6;
-}
-
-message Message4016 {
-  required int32 field4017 = 1;
-  required int32 field4018 = 2;
-  required int32 field4019 = 3;
-  required int32 field4020 = 4;
-}
-
-message Message6108 {}
-
-message Message5907 {
-  optional .benchmarks.google_message4.Message5903 field5967 = 1;
-  optional .benchmarks.google_message4.Message5903 field5968 = 2;
-  optional .benchmarks.google_message4.Message5903 field5969 = 3;
-  optional .benchmarks.google_message4.Message5903 field5970 = 4;
-}
-
-message UnusedEmptyMessage {}
-
-message Message5903 {
-  required int32 field5965 = 1;
-  optional .benchmarks.google_message4.Enum5904 field5966 = 2;
-}
diff --git a/benchmarks/datasets/google_message4/benchmark_message4_3.proto b/benchmarks/datasets/google_message4/benchmark_message4_3.proto
deleted file mode 100644
index 42e254b..0000000
--- a/benchmarks/datasets/google_message4/benchmark_message4_3.proto
+++ /dev/null
@@ -1,779 +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";
-
-package benchmarks.google_message4;
-
-option cc_enable_arenas = true;
-option java_package = "com.google.protobuf.benchmarks";
-
-enum UnusedEnum {
-  UNUSED_ENUM_VALUE1 = 0;
-  UNUSED_ENUM_VALUE2 = 1;
-}
-
-enum Enum2593 {
-  ENUM_VALUE2594 = 0;
-  ENUM_VALUE2595 = 1;
-  ENUM_VALUE2596 = 2;
-  ENUM_VALUE2597 = 3;
-  ENUM_VALUE2598 = 4;
-  ENUM_VALUE2599 = 5;
-  ENUM_VALUE2600 = 6;
-  ENUM_VALUE2601 = 7;
-}
-
-enum Enum2834 {
-  ENUM_VALUE2835 = 0;
-  ENUM_VALUE2836 = 1;
-  ENUM_VALUE2837 = 2;
-}
-
-enum Enum2806 {
-  ENUM_VALUE2807 = 0;
-  ENUM_VALUE2808 = 1;
-  ENUM_VALUE2809 = 2;
-  ENUM_VALUE2810 = 3;
-  ENUM_VALUE2811 = 4;
-  ENUM_VALUE2812 = 5;
-  ENUM_VALUE2813 = 6;
-  ENUM_VALUE2814 = 7;
-  ENUM_VALUE2815 = 8;
-  ENUM_VALUE2816 = 9;
-  ENUM_VALUE2817 = 10;
-  ENUM_VALUE2818 = 11;
-  ENUM_VALUE2819 = 12;
-  ENUM_VALUE2820 = 13;
-  ENUM_VALUE2821 = 14;
-}
-
-enum Enum2851 {
-  option allow_alias = true;
-
-  ENUM_VALUE2852 = 0;
-  ENUM_VALUE2853 = 0;
-  ENUM_VALUE2854 = 1;
-  ENUM_VALUE2855 = 2;
-  ENUM_VALUE2856 = 3;
-  ENUM_VALUE2857 = 4;
-  ENUM_VALUE2858 = 5;
-  ENUM_VALUE2859 = 6;
-  ENUM_VALUE2860 = 7;
-  ENUM_VALUE2861 = 8;
-  ENUM_VALUE2862 = 9;
-  ENUM_VALUE2863 = 10;
-  ENUM_VALUE2864 = 11;
-  ENUM_VALUE2865 = 12;
-  ENUM_VALUE2866 = 13;
-  ENUM_VALUE2867 = 14;
-  ENUM_VALUE2868 = 15;
-  ENUM_VALUE2869 = 16;
-  ENUM_VALUE2870 = 17;
-  ENUM_VALUE2871 = 18;
-  ENUM_VALUE2872 = 19;
-  ENUM_VALUE2873 = 20;
-  ENUM_VALUE2874 = 21;
-  ENUM_VALUE2875 = 22;
-  ENUM_VALUE2876 = 23;
-  ENUM_VALUE2877 = 24;
-  ENUM_VALUE2878 = 25;
-  ENUM_VALUE2879 = 26;
-  ENUM_VALUE2880 = 27;
-  ENUM_VALUE2881 = 28;
-  ENUM_VALUE2882 = 29;
-  ENUM_VALUE2883 = 30;
-  ENUM_VALUE2884 = 31;
-  ENUM_VALUE2885 = 32;
-  ENUM_VALUE2886 = 33;
-  ENUM_VALUE2887 = 34;
-  ENUM_VALUE2888 = 35;
-  ENUM_VALUE2889 = 36;
-  ENUM_VALUE2890 = 37;
-  ENUM_VALUE2891 = 38;
-  ENUM_VALUE2892 = 39;
-  ENUM_VALUE2893 = 40;
-  ENUM_VALUE2894 = 41;
-  ENUM_VALUE2895 = 42;
-  ENUM_VALUE2896 = 43;
-  ENUM_VALUE2897 = 44;
-  ENUM_VALUE2898 = 45;
-  ENUM_VALUE2899 = 46;
-  ENUM_VALUE2900 = 47;
-  ENUM_VALUE2901 = 48;
-  ENUM_VALUE2902 = 49;
-  ENUM_VALUE2903 = 50;
-  ENUM_VALUE2904 = 51;
-  ENUM_VALUE2905 = 52;
-  ENUM_VALUE2906 = 53;
-  ENUM_VALUE2907 = 54;
-  ENUM_VALUE2908 = 55;
-  ENUM_VALUE2909 = 56;
-  ENUM_VALUE2910 = 57;
-  ENUM_VALUE2911 = 58;
-  ENUM_VALUE2912 = 59;
-  ENUM_VALUE2913 = 60;
-  ENUM_VALUE2914 = 61;
-  ENUM_VALUE2915 = 62;
-  ENUM_VALUE2916 = 63;
-  ENUM_VALUE2917 = 64;
-  ENUM_VALUE2918 = 65;
-  ENUM_VALUE2919 = 66;
-  ENUM_VALUE2920 = 67;
-  ENUM_VALUE2921 = 68;
-  ENUM_VALUE2922 = 69;
-  ENUM_VALUE2923 = 70;
-  ENUM_VALUE2924 = 71;
-  ENUM_VALUE2925 = 72;
-  ENUM_VALUE2926 = 73;
-  ENUM_VALUE2927 = 74;
-  ENUM_VALUE2928 = 75;
-  ENUM_VALUE2929 = 76;
-  ENUM_VALUE2930 = 77;
-  ENUM_VALUE2931 = 78;
-  ENUM_VALUE2932 = 79;
-  ENUM_VALUE2933 = 80;
-  ENUM_VALUE2934 = 81;
-  ENUM_VALUE2935 = 82;
-  ENUM_VALUE2936 = 83;
-  ENUM_VALUE2937 = 84;
-  ENUM_VALUE2938 = 85;
-  ENUM_VALUE2939 = 86;
-  ENUM_VALUE2940 = 87;
-  ENUM_VALUE2941 = 88;
-  ENUM_VALUE2942 = 89;
-  ENUM_VALUE2943 = 90;
-  ENUM_VALUE2944 = 91;
-  ENUM_VALUE2945 = 92;
-  ENUM_VALUE2946 = 93;
-  ENUM_VALUE2947 = 94;
-  ENUM_VALUE2948 = 95;
-  ENUM_VALUE2949 = 96;
-  ENUM_VALUE2950 = 97;
-  ENUM_VALUE2951 = 98;
-  ENUM_VALUE2952 = 99;
-  ENUM_VALUE2953 = 100;
-  ENUM_VALUE2954 = 101;
-  ENUM_VALUE2955 = 102;
-  ENUM_VALUE2956 = 103;
-  ENUM_VALUE2957 = 104;
-  ENUM_VALUE2958 = 105;
-  ENUM_VALUE2959 = 106;
-  ENUM_VALUE2960 = 107;
-  ENUM_VALUE2961 = 108;
-  ENUM_VALUE2962 = 109;
-  ENUM_VALUE2963 = 110;
-  ENUM_VALUE2964 = 111;
-  ENUM_VALUE2965 = 112;
-  ENUM_VALUE2966 = 113;
-  ENUM_VALUE2967 = 114;
-  ENUM_VALUE2968 = 115;
-  ENUM_VALUE2969 = 116;
-  ENUM_VALUE2970 = 117;
-  ENUM_VALUE2971 = 118;
-  ENUM_VALUE2972 = 119;
-}
-
-enum Enum2602 {
-  ENUM_VALUE2603 = 0;
-  ENUM_VALUE2604 = 1;
-  ENUM_VALUE2605 = 2;
-  ENUM_VALUE2606 = 3;
-  ENUM_VALUE2607 = 4;
-  ENUM_VALUE2608 = 5;
-  ENUM_VALUE2609 = 6;
-  ENUM_VALUE2610 = 7;
-  ENUM_VALUE2611 = 8;
-  ENUM_VALUE2612 = 9;
-  ENUM_VALUE2613 = 10;
-  ENUM_VALUE2614 = 11;
-}
-
-enum Enum3071 {
-  ENUM_VALUE3072 = 1;
-  ENUM_VALUE3073 = 2;
-  ENUM_VALUE3074 = 3;
-  ENUM_VALUE3075 = 4;
-  ENUM_VALUE3076 = 5;
-  ENUM_VALUE3077 = 6;
-  ENUM_VALUE3078 = 7;
-  ENUM_VALUE3079 = 8;
-  ENUM_VALUE3080 = 9;
-  ENUM_VALUE3081 = 10;
-  ENUM_VALUE3082 = 11;
-  ENUM_VALUE3083 = 12;
-  ENUM_VALUE3084 = 13;
-  ENUM_VALUE3085 = 14;
-  ENUM_VALUE3086 = 15;
-  ENUM_VALUE3087 = 16;
-  ENUM_VALUE3088 = 17;
-  ENUM_VALUE3089 = 18;
-  ENUM_VALUE3090 = 19;
-  ENUM_VALUE3091 = 20;
-  ENUM_VALUE3092 = 21;
-  ENUM_VALUE3093 = 22;
-  ENUM_VALUE3094 = 23;
-  ENUM_VALUE3095 = 24;
-  ENUM_VALUE3096 = 25;
-  ENUM_VALUE3097 = 26;
-  ENUM_VALUE3098 = 27;
-  ENUM_VALUE3099 = 28;
-}
-
-enum Enum3805 {
-  ENUM_VALUE3806 = 0;
-  ENUM_VALUE3807 = 1;
-  ENUM_VALUE3808 = 2;
-  ENUM_VALUE3809 = 3;
-  ENUM_VALUE3810 = 4;
-  ENUM_VALUE3811 = 5;
-  ENUM_VALUE3812 = 6;
-  ENUM_VALUE3813 = 7;
-  ENUM_VALUE3814 = 8;
-  ENUM_VALUE3815 = 9;
-  ENUM_VALUE3816 = 11;
-  ENUM_VALUE3817 = 10;
-}
-
-enum Enum3783 {
-  ENUM_VALUE3784 = 0;
-  ENUM_VALUE3785 = 1;
-  ENUM_VALUE3786 = 2;
-  ENUM_VALUE3787 = 3;
-  ENUM_VALUE3788 = 4;
-  ENUM_VALUE3789 = 5;
-  ENUM_VALUE3790 = 6;
-  ENUM_VALUE3791 = 7;
-  ENUM_VALUE3792 = 8;
-  ENUM_VALUE3793 = 9;
-  ENUM_VALUE3794 = 10;
-  ENUM_VALUE3795 = 11;
-  ENUM_VALUE3796 = 12;
-  ENUM_VALUE3797 = 13;
-  ENUM_VALUE3798 = 14;
-  ENUM_VALUE3799 = 15;
-  ENUM_VALUE3800 = 16;
-  ENUM_VALUE3801 = 20;
-  ENUM_VALUE3802 = 21;
-  ENUM_VALUE3803 = 50;
-}
-
-enum Enum3851 {
-  ENUM_VALUE3852 = 0;
-  ENUM_VALUE3853 = 1;
-  ENUM_VALUE3854 = 2;
-  ENUM_VALUE3855 = 3;
-  ENUM_VALUE3856 = 4;
-  ENUM_VALUE3857 = 5;
-  ENUM_VALUE3858 = 6;
-  ENUM_VALUE3859 = 7;
-  ENUM_VALUE3860 = 8;
-  ENUM_VALUE3861 = 9;
-  ENUM_VALUE3862 = 10;
-  ENUM_VALUE3863 = 11;
-  ENUM_VALUE3864 = 12;
-  ENUM_VALUE3865 = 13;
-  ENUM_VALUE3866 = 14;
-  ENUM_VALUE3867 = 15;
-  ENUM_VALUE3868 = 16;
-  ENUM_VALUE3869 = 17;
-}
-
-enum Enum5862 {
-  ENUM_VALUE5863 = 1;
-  ENUM_VALUE5864 = 2;
-  ENUM_VALUE5865 = 3;
-}
-
-enum Enum5868 {
-  ENUM_VALUE5869 = 0;
-  ENUM_VALUE5870 = 1;
-  ENUM_VALUE5871 = 2;
-  ENUM_VALUE5872 = 3;
-}
-
-enum Enum5873 {
-  ENUM_VALUE5874 = 0;
-  ENUM_VALUE5875 = 1;
-  ENUM_VALUE5876 = 2;
-}
-
-enum Enum5904 {
-  ENUM_VALUE5905 = 0;
-  ENUM_VALUE5906 = 1;
-}
-
-enum Enum5909 {
-  ENUM_VALUE5910 = 0;
-  ENUM_VALUE5911 = 1;
-}
-
-enum Enum5912 {
-  ENUM_VALUE5913 = 0;
-  ENUM_VALUE5914 = 1;
-}
-
-enum Enum5915 {
-  ENUM_VALUE5916 = 0;
-  ENUM_VALUE5917 = 1;
-  ENUM_VALUE5918 = 2;
-  ENUM_VALUE5919 = 3;
-}
-
-enum Enum5920 {
-  ENUM_VALUE5921 = 0;
-  ENUM_VALUE5922 = 1;
-}
-
-enum Enum5923 {
-  ENUM_VALUE5924 = 0;
-  ENUM_VALUE5925 = 1;
-  ENUM_VALUE5926 = 2;
-  ENUM_VALUE5927 = 3;
-}
-
-enum Enum5928 {
-  ENUM_VALUE5929 = 0;
-  ENUM_VALUE5930 = 1;
-}
-
-enum Enum5931 {
-  ENUM_VALUE5932 = 0;
-  ENUM_VALUE5933 = 1;
-  ENUM_VALUE5934 = 2;
-}
-
-enum Enum5935 {
-  ENUM_VALUE5936 = 0;
-  ENUM_VALUE5937 = 1;
-  ENUM_VALUE5938 = 2;
-}
-
-enum Enum5939 {
-  ENUM_VALUE5940 = 0;
-  ENUM_VALUE5941 = 1;
-  ENUM_VALUE5942 = 2;
-  ENUM_VALUE5943 = 3;
-  ENUM_VALUE5944 = 4;
-  ENUM_VALUE5945 = 5;
-}
-
-enum Enum5946 {
-  ENUM_VALUE5947 = 0;
-  ENUM_VALUE5948 = 1;
-  ENUM_VALUE5949 = 2;
-  ENUM_VALUE5950 = 3;
-  ENUM_VALUE5951 = 4;
-  ENUM_VALUE5952 = 5;
-  ENUM_VALUE5953 = 6;
-  ENUM_VALUE5954 = 7;
-  ENUM_VALUE5955 = 8;
-  ENUM_VALUE5956 = 9;
-}
-
-enum Enum5957 {
-  ENUM_VALUE5958 = 0;
-  ENUM_VALUE5959 = 1;
-  ENUM_VALUE5960 = 2;
-  ENUM_VALUE5961 = 3;
-}
-
-enum Enum5962 {
-  ENUM_VALUE5963 = 0;
-  ENUM_VALUE5964 = 1;
-}
-
-enum Enum6025 {
-  ENUM_VALUE6026 = 0;
-  ENUM_VALUE6027 = 1;
-  ENUM_VALUE6028 = 2;
-  ENUM_VALUE6029 = 3;
-  ENUM_VALUE6030 = 4;
-  ENUM_VALUE6031 = 5;
-  ENUM_VALUE6032 = 6;
-  ENUM_VALUE6033 = 7;
-  ENUM_VALUE6034 = 8;
-  ENUM_VALUE6035 = 9;
-  ENUM_VALUE6036 = 10;
-  ENUM_VALUE6037 = 11;
-  ENUM_VALUE6038 = 12;
-  ENUM_VALUE6039 = 13;
-  ENUM_VALUE6040 = 14;
-  ENUM_VALUE6041 = 15;
-  ENUM_VALUE6042 = 16;
-  ENUM_VALUE6043 = 17;
-  ENUM_VALUE6044 = 18;
-  ENUM_VALUE6045 = 19;
-  ENUM_VALUE6046 = 20;
-  ENUM_VALUE6047 = 21;
-}
-
-enum Enum6111 {
-  ENUM_VALUE6112 = 1;
-  ENUM_VALUE6113 = 2;
-  ENUM_VALUE6114 = 3;
-  ENUM_VALUE6115 = 4;
-  ENUM_VALUE6116 = 5;
-  ENUM_VALUE6117 = 6;
-  ENUM_VALUE6118 = 7;
-  ENUM_VALUE6119 = 8;
-  ENUM_VALUE6120 = 9;
-  ENUM_VALUE6121 = 10;
-  ENUM_VALUE6122 = 11;
-  ENUM_VALUE6123 = 12;
-  ENUM_VALUE6124 = 13;
-  ENUM_VALUE6125 = 14;
-}
-
-enum Enum6065 {
-  ENUM_VALUE6066 = 0;
-  ENUM_VALUE6067 = 1;
-  ENUM_VALUE6068 = 2;
-  ENUM_VALUE6069 = 3;
-  ENUM_VALUE6070 = 4;
-  ENUM_VALUE6071 = 5;
-  ENUM_VALUE6072 = 6;
-  ENUM_VALUE6073 = 7;
-  ENUM_VALUE6074 = 8;
-  ENUM_VALUE6075 = 9;
-  ENUM_VALUE6076 = 10;
-  ENUM_VALUE6077 = 11;
-  ENUM_VALUE6078 = 12;
-  ENUM_VALUE6079 = 13;
-  ENUM_VALUE6080 = 14;
-}
-
-enum Enum6130 {
-  ENUM_VALUE6131 = 0;
-  ENUM_VALUE6132 = 1;
-}
-
-enum Enum6579 {
-  ENUM_VALUE6580 = 0;
-  ENUM_VALUE6581 = 2;
-  ENUM_VALUE6582 = 3;
-  ENUM_VALUE6583 = 5;
-  ENUM_VALUE6584 = 10;
-  ENUM_VALUE6585 = 15;
-  ENUM_VALUE6586 = 25;
-  ENUM_VALUE6587 = 30;
-}
-
-enum Enum6588 {
-  ENUM_VALUE6589 = 0;
-  ENUM_VALUE6590 = 1;
-  ENUM_VALUE6591 = 2;
-  ENUM_VALUE6592 = 3;
-  ENUM_VALUE6593 = 4;
-  ENUM_VALUE6594 = 5;
-  ENUM_VALUE6595 = 6;
-  ENUM_VALUE6596 = 7;
-  ENUM_VALUE6597 = 8;
-  ENUM_VALUE6598 = 9;
-  ENUM_VALUE6599 = 10;
-  ENUM_VALUE6600 = 11;
-  ENUM_VALUE6601 = 12;
-  ENUM_VALUE6602 = 13;
-  ENUM_VALUE6603 = 14;
-  ENUM_VALUE6604 = 15;
-  ENUM_VALUE6605 = 16;
-  ENUM_VALUE6606 = 17;
-  ENUM_VALUE6607 = 19;
-  ENUM_VALUE6608 = 20;
-  ENUM_VALUE6609 = 21;
-  ENUM_VALUE6610 = 22;
-  ENUM_VALUE6611 = 23;
-  ENUM_VALUE6612 = 24;
-  ENUM_VALUE6613 = 25;
-  ENUM_VALUE6614 = 26;
-  ENUM_VALUE6615 = 27;
-  ENUM_VALUE6616 = 28;
-  ENUM_VALUE6617 = 29;
-  ENUM_VALUE6618 = 30;
-  ENUM_VALUE6619 = 31;
-  ENUM_VALUE6620 = 32;
-  ENUM_VALUE6621 = 33;
-  ENUM_VALUE6622 = 34;
-}
-
-enum Enum7288 {
-  ENUM_VALUE7289 = 0;
-  ENUM_VALUE7290 = 1;
-  ENUM_VALUE7291 = 2;
-  ENUM_VALUE7292 = 3;
-}
-
-enum Enum7512 {
-  ENUM_VALUE7513 = 0;
-  ENUM_VALUE7514 = 1;
-  ENUM_VALUE7515 = 2;
-  ENUM_VALUE7516 = 3;
-  ENUM_VALUE7517 = 4;
-  ENUM_VALUE7518 = 5;
-  ENUM_VALUE7519 = 6;
-  ENUM_VALUE7520 = 7;
-}
-
-enum Enum7922 {
-  ENUM_VALUE7923 = 1;
-  ENUM_VALUE7924 = 2;
-  ENUM_VALUE7925 = 3;
-  ENUM_VALUE7926 = 4;
-  ENUM_VALUE7927 = 5;
-}
-
-enum Enum3476 {
-  ENUM_VALUE3477 = 0;
-  ENUM_VALUE3478 = 1;
-  ENUM_VALUE3479 = 2;
-  ENUM_VALUE3480 = 3;
-  ENUM_VALUE3481 = 4;
-  ENUM_VALUE3482 = 5;
-  ENUM_VALUE3483 = 6;
-  ENUM_VALUE3484 = 7;
-  ENUM_VALUE3485 = 8;
-  ENUM_VALUE3486 = 9;
-  ENUM_VALUE3487 = 10;
-  ENUM_VALUE3488 = 11;
-  ENUM_VALUE3489 = 12;
-  ENUM_VALUE3490 = 13;
-  ENUM_VALUE3491 = 14;
-  ENUM_VALUE3492 = 15;
-  ENUM_VALUE3493 = 16;
-  ENUM_VALUE3494 = 17;
-  ENUM_VALUE3495 = 18;
-  ENUM_VALUE3496 = 19;
-  ENUM_VALUE3497 = 20;
-  ENUM_VALUE3498 = 21;
-  ENUM_VALUE3499 = 22;
-  ENUM_VALUE3500 = 23;
-  ENUM_VALUE3501 = 24;
-  ENUM_VALUE3502 = 25;
-  ENUM_VALUE3503 = 26;
-  ENUM_VALUE3504 = 27;
-  ENUM_VALUE3505 = 28;
-  ENUM_VALUE3506 = 29;
-  ENUM_VALUE3507 = 30;
-  ENUM_VALUE3508 = 31;
-  ENUM_VALUE3509 = 32;
-  ENUM_VALUE3510 = 33;
-  ENUM_VALUE3511 = 34;
-  ENUM_VALUE3512 = 35;
-  ENUM_VALUE3513 = 36;
-  ENUM_VALUE3514 = 37;
-  ENUM_VALUE3515 = 38;
-  ENUM_VALUE3516 = 39;
-  ENUM_VALUE3517 = 40;
-  ENUM_VALUE3518 = 41;
-  ENUM_VALUE3519 = 42;
-  ENUM_VALUE3520 = 43;
-  ENUM_VALUE3521 = 44;
-  ENUM_VALUE3522 = 45;
-  ENUM_VALUE3523 = 46;
-  ENUM_VALUE3524 = 47;
-  ENUM_VALUE3525 = 48;
-  ENUM_VALUE3526 = 49;
-  ENUM_VALUE3527 = 50;
-  ENUM_VALUE3528 = 51;
-  ENUM_VALUE3529 = 52;
-  ENUM_VALUE3530 = 53;
-  ENUM_VALUE3531 = 54;
-  ENUM_VALUE3532 = 55;
-  ENUM_VALUE3533 = 56;
-  ENUM_VALUE3534 = 57;
-  ENUM_VALUE3535 = 58;
-  ENUM_VALUE3536 = 59;
-  ENUM_VALUE3537 = 60;
-  ENUM_VALUE3538 = 61;
-  ENUM_VALUE3539 = 62;
-  ENUM_VALUE3540 = 63;
-  ENUM_VALUE3541 = 64;
-  ENUM_VALUE3542 = 65;
-  ENUM_VALUE3543 = 66;
-  ENUM_VALUE3544 = 67;
-  ENUM_VALUE3545 = 68;
-  ENUM_VALUE3546 = 69;
-  ENUM_VALUE3547 = 70;
-  ENUM_VALUE3548 = 71;
-  ENUM_VALUE3549 = 72;
-  ENUM_VALUE3550 = 73;
-  ENUM_VALUE3551 = 74;
-  ENUM_VALUE3552 = 75;
-  ENUM_VALUE3553 = 76;
-  ENUM_VALUE3554 = 77;
-  ENUM_VALUE3555 = 78;
-  ENUM_VALUE3556 = 79;
-  ENUM_VALUE3557 = 80;
-  ENUM_VALUE3558 = 81;
-  ENUM_VALUE3559 = 82;
-  ENUM_VALUE3560 = 83;
-  ENUM_VALUE3561 = 84;
-  ENUM_VALUE3562 = 85;
-  ENUM_VALUE3563 = 86;
-  ENUM_VALUE3564 = 87;
-  ENUM_VALUE3565 = 88;
-  ENUM_VALUE3566 = 89;
-  ENUM_VALUE3567 = 90;
-  ENUM_VALUE3568 = 91;
-  ENUM_VALUE3569 = 92;
-  ENUM_VALUE3570 = 93;
-  ENUM_VALUE3571 = 94;
-  ENUM_VALUE3572 = 95;
-  ENUM_VALUE3573 = 96;
-  ENUM_VALUE3574 = 97;
-  ENUM_VALUE3575 = 98;
-  ENUM_VALUE3576 = 99;
-  ENUM_VALUE3577 = 100;
-  ENUM_VALUE3578 = 101;
-  ENUM_VALUE3579 = 102;
-  ENUM_VALUE3580 = 103;
-  ENUM_VALUE3581 = 104;
-  ENUM_VALUE3582 = 105;
-  ENUM_VALUE3583 = 106;
-  ENUM_VALUE3584 = 107;
-  ENUM_VALUE3585 = 108;
-  ENUM_VALUE3586 = 109;
-  ENUM_VALUE3587 = 110;
-  ENUM_VALUE3588 = 111;
-  ENUM_VALUE3589 = 112;
-  ENUM_VALUE3590 = 113;
-  ENUM_VALUE3591 = 114;
-  ENUM_VALUE3592 = 115;
-  ENUM_VALUE3593 = 116;
-  ENUM_VALUE3594 = 117;
-  ENUM_VALUE3595 = 118;
-  ENUM_VALUE3596 = 119;
-  ENUM_VALUE3597 = 120;
-  ENUM_VALUE3598 = 121;
-  ENUM_VALUE3599 = 122;
-  ENUM_VALUE3600 = 123;
-  ENUM_VALUE3601 = 124;
-  ENUM_VALUE3602 = 125;
-  ENUM_VALUE3603 = 126;
-  ENUM_VALUE3604 = 127;
-  ENUM_VALUE3605 = 128;
-  ENUM_VALUE3606 = 129;
-  ENUM_VALUE3607 = 130;
-  ENUM_VALUE3608 = 131;
-  ENUM_VALUE3609 = 132;
-  ENUM_VALUE3610 = 133;
-  ENUM_VALUE3611 = 134;
-  ENUM_VALUE3612 = 135;
-  ENUM_VALUE3613 = 136;
-  ENUM_VALUE3614 = 137;
-  ENUM_VALUE3615 = 138;
-  ENUM_VALUE3616 = 139;
-  ENUM_VALUE3617 = 140;
-  ENUM_VALUE3618 = 141;
-  ENUM_VALUE3619 = 142;
-  ENUM_VALUE3620 = 143;
-  ENUM_VALUE3621 = 144;
-  ENUM_VALUE3622 = 145;
-  ENUM_VALUE3623 = 146;
-  ENUM_VALUE3624 = 147;
-  ENUM_VALUE3625 = 148;
-  ENUM_VALUE3626 = 149;
-  ENUM_VALUE3627 = 150;
-  ENUM_VALUE3628 = 151;
-  ENUM_VALUE3629 = 152;
-  ENUM_VALUE3630 = 153;
-  ENUM_VALUE3631 = 154;
-  ENUM_VALUE3632 = 155;
-  ENUM_VALUE3633 = 156;
-  ENUM_VALUE3634 = 157;
-  ENUM_VALUE3635 = 158;
-  ENUM_VALUE3636 = 159;
-  ENUM_VALUE3637 = 160;
-  ENUM_VALUE3638 = 161;
-  ENUM_VALUE3639 = 162;
-  ENUM_VALUE3640 = 163;
-  ENUM_VALUE3641 = 164;
-  ENUM_VALUE3642 = 165;
-  ENUM_VALUE3643 = 166;
-  ENUM_VALUE3644 = 167;
-  ENUM_VALUE3645 = 168;
-  ENUM_VALUE3646 = 169;
-  ENUM_VALUE3647 = 170;
-  ENUM_VALUE3648 = 171;
-  ENUM_VALUE3649 = 172;
-  ENUM_VALUE3650 = 173;
-  ENUM_VALUE3651 = 174;
-  ENUM_VALUE3652 = 175;
-  ENUM_VALUE3653 = 176;
-  ENUM_VALUE3654 = 177;
-  ENUM_VALUE3655 = 178;
-  ENUM_VALUE3656 = 179;
-  ENUM_VALUE3657 = 180;
-  ENUM_VALUE3658 = 181;
-  ENUM_VALUE3659 = 182;
-  ENUM_VALUE3660 = 183;
-}
-
-enum Enum10325 {
-  ENUM_VALUE10326 = 0;
-  ENUM_VALUE10327 = 1;
-  ENUM_VALUE10328 = 2;
-  ENUM_VALUE10329 = 3;
-  ENUM_VALUE10330 = 4;
-  ENUM_VALUE10331 = 5;
-  ENUM_VALUE10332 = 6;
-  ENUM_VALUE10333 = 7;
-  ENUM_VALUE10334 = 8;
-}
-
-enum Enum10335 { ENUM_VALUE10336 = 0; }
-
-enum Enum10337 {
-  ENUM_VALUE10338 = 0;
-  ENUM_VALUE10339 = 1;
-}
-
-enum Enum11901 {
-  ENUM_VALUE11902 = 0;
-  ENUM_VALUE11903 = 1;
-  ENUM_VALUE11904 = 2;
-  ENUM_VALUE11905 = 3;
-}
-
-enum Enum12735 {
-  ENUM_VALUE12736 = 0;
-  ENUM_VALUE12737 = 1;
-  ENUM_VALUE12738 = 2;
-  ENUM_VALUE12739 = 3;
-}
-
-enum Enum12871 {
-  ENUM_VALUE12872 = 1;
-  ENUM_VALUE12873 = 2;
-  ENUM_VALUE12874 = 3;
-  ENUM_VALUE12875 = 4;
-  ENUM_VALUE12876 = 5;
-  ENUM_VALUE12877 = 6;
-}
diff --git a/benchmarks/go/go_benchmark_test.go b/benchmarks/go/go_benchmark_test.go
deleted file mode 100644
index 8c741b7..0000000
--- a/benchmarks/go/go_benchmark_test.go
+++ /dev/null
@@ -1,124 +0,0 @@
-package main
-
-import (
-	benchmarkWrapper "../tmp"
-	googleMessage1Proto2 "../tmp/datasets/google_message1/proto2"
-	googleMessage1Proto3 "../tmp/datasets/google_message1/proto3"
-	googleMessage2 "../tmp/datasets/google_message2"
-	googleMessage3 "../tmp/datasets/google_message3"
-	googleMessage4 "../tmp/datasets/google_message4"
-	"flag"
-	"github.com/golang/protobuf/proto"
-	"io/ioutil"
-	"testing"
-)
-
-// Data is returned by the Load function.
-type Dataset struct {
-	name        string
-	newMessage  func() proto.Message
-	marshaled   [][]byte
-	unmarshaled []proto.Message
-}
-
-var datasets []Dataset
-
-// This is used to getDefaultInstance for a message type.
-func generateNewMessageFunction(dataset benchmarkWrapper.BenchmarkDataset) func() proto.Message {
-	switch dataset.MessageName {
-	case "benchmarks.proto3.GoogleMessage1":
-		return func() proto.Message { return new(googleMessage1Proto3.GoogleMessage1) }
-	case "benchmarks.proto2.GoogleMessage1":
-		return func() proto.Message { return new(googleMessage1Proto2.GoogleMessage1) }
-	case "benchmarks.proto2.GoogleMessage2":
-		return func() proto.Message { return new(googleMessage2.GoogleMessage2) }
-	case "benchmarks.google_message3.GoogleMessage3":
-		return func() proto.Message { return new(googleMessage3.GoogleMessage3) }
-	case "benchmarks.google_message4.GoogleMessage4":
-		return func() proto.Message { return new(googleMessage4.GoogleMessage4) }
-	default:
-		panic("Unknown message type: " + dataset.MessageName)
-	}
-}
-
-func init() {
-	flag.Parse()
-	for _, f := range flag.Args() {
-		// Load the benchmark.
-		b, err := ioutil.ReadFile(f)
-		if err != nil {
-			panic(err)
-		}
-
-		// Parse the benchmark.
-		var dm benchmarkWrapper.BenchmarkDataset
-		if err := proto.Unmarshal(b, &dm); err != nil {
-			panic(err)
-		}
-
-		// Determine the concrete protobuf message type to use.
-		var ds Dataset
-		ds.newMessage = generateNewMessageFunction(dm)
-
-		// Unmarshal each test message.
-		for _, payload := range dm.Payload {
-			ds.marshaled = append(ds.marshaled, payload)
-			m := ds.newMessage()
-			if err := proto.Unmarshal(payload, m); err != nil {
-				panic(err)
-			}
-			ds.unmarshaled = append(ds.unmarshaled, m)
-		}
-		ds.name = f
-
-		datasets = append(datasets, ds)
-	}
-}
-
-func Benchmark(b *testing.B) {
-	for _, ds := range datasets {
-		b.Run(ds.name, func(b *testing.B) {
-			b.Run("Unmarshal", func(b *testing.B) {
-				for i := 0; i < b.N; i++ {
-					for j, payload := range ds.marshaled {
-						out := ds.newMessage()
-						if err := proto.Unmarshal(payload, out); err != nil {
-							b.Fatalf("can't unmarshal message %d %v", j, err)
-						}
-					}
-				}
-			})
-			b.Run("Marshal", func(b *testing.B) {
-				for i := 0; i < b.N; i++ {
-					for j, m := range ds.unmarshaled {
-						if _, err := proto.Marshal(m); err != nil {
-							b.Fatalf("can't marshal message %d %+v: %v", j, m, err)
-						}
-					}
-				}
-			})
-			b.Run("Size", func(b *testing.B) {
-				for i := 0; i < b.N; i++ {
-					for _, m := range ds.unmarshaled {
-						proto.Size(m)
-					}
-				}
-			})
-			b.Run("Clone", func(b *testing.B) {
-				for i := 0; i < b.N; i++ {
-					for _, m := range ds.unmarshaled {
-						proto.Clone(m)
-					}
-				}
-			})
-			b.Run("Merge", func(b *testing.B) {
-				for i := 0; i < b.N; i++ {
-					for _, m := range ds.unmarshaled {
-						out := ds.newMessage()
-						proto.Merge(out, m)
-					}
-				}
-			})
-		})
-	}
-}
diff --git a/benchmarks/google_size.proto b/benchmarks/google_size.proto
deleted file mode 100644
index d2d319f..0000000
--- a/benchmarks/google_size.proto
+++ /dev/null
@@ -1,138 +0,0 @@
-syntax = "proto2";
-
-package benchmarks;
-
-option java_outer_classname = "GoogleSize";
-option optimize_for = CODE_SIZE;
-
-message SizeMessage1 {
-  required string field1 = 1;
-  optional string field9 = 9;
-  optional string field18 = 18;
-  optional bool field80 = 80 [default=false];
-  optional bool field81 = 81 [default=true];
-  required int32 field2 = 2;
-  required int32 field3 = 3;
-  optional int32 field280 = 280;
-  optional int32 field6 = 6 [default=0];
-  optional int64 field22 = 22;
-  optional string field4 = 4;
-  repeated fixed64 field5 = 5;
-  optional bool field59 = 59 [default=false];
-  optional string field7 = 7;
-  optional int32 field16 = 16;
-  optional int32 field130 = 130 [default=0];
-  optional bool field12 = 12 [default=true];
-  optional bool field17 = 17 [default=true];
-  optional bool field13 = 13 [default=true];
-  optional bool field14 = 14 [default=true];
-  optional int32 field104 = 104 [default=0];
-  optional int32 field100 = 100 [default=0];
-  optional int32 field101 = 101 [default=0];
-  optional string field102 = 102;
-  optional string field103 = 103;
-  optional int32 field29 = 29 [default=0];
-  optional bool field30 = 30 [default=false];
-  optional int32 field60 = 60 [default=-1];
-  optional int32 field271 = 271 [default=-1];
-  optional int32 field272 = 272 [default=-1];
-  optional int32 field150 = 150;
-  optional int32 field23 = 23 [default=0];
-  optional bool field24 = 24 [default=false];
-  optional int32 field25 = 25 [default=0];
-  optional SizeMessage1SubMessage field15 = 15;
-  optional bool field78 = 78;
-  optional int32 field67 = 67 [default=0];
-  optional int32 field68 = 68;
-  optional int32 field128 = 128 [default=0];
-  optional string field129 = 129 [default="xxxxxxxxxxxxxxxxxxxxx"];
-  optional int32 field131 = 131 [default=0];
-}
-
-message SizeMessage1SubMessage {
-  optional int32 field1 = 1 [default=0];
-  optional int32 field2 = 2 [default=0];
-  optional int32 field3 = 3 [default=0];
-  optional string field15 = 15;
-  optional bool field12 = 12 [default=true];
-  optional int64 field13 = 13;
-  optional int64 field14 = 14;
-  optional int32 field16 = 16;
-  optional int32 field19 = 19 [default=2];
-  optional bool field20  = 20 [default=true];
-  optional bool field28 = 28 [default=true];
-  optional fixed64 field21 = 21;
-  optional int32 field22 = 22;
-  optional bool field23 = 23 [ default=false ];
-  optional bool field206 = 206 [default=false];
-  optional fixed32 field203 = 203;
-  optional int32 field204 = 204;
-  optional string field205 = 205;
-  optional uint64 field207 = 207;
-  optional uint64 field300 = 300;
-}
-
-message SizeMessage2 {
-  optional string field1 = 1;
-  optional int64 field3 = 3;
-  optional int64 field4 = 4;
-  optional int64 field30 = 30;
-  optional bool field75  = 75 [default=false];
-  optional string field6 = 6;
-  optional bytes field2 = 2;
-  optional int32 field21 = 21 [default=0];
-  optional int32 field71 = 71;
-  optional float field25 = 25;
-  optional int32 field109 = 109 [default=0];
-  optional int32 field210 = 210 [default=0];
-  optional int32 field211 = 211 [default=0];
-  optional int32 field212 = 212 [default=0];
-  optional int32 field213 = 213 [default=0];
-  optional int32 field216 = 216 [default=0];
-  optional int32 field217 = 217 [default=0];
-  optional int32 field218 = 218 [default=0];
-  optional int32 field220 = 220 [default=0];
-  optional int32 field221 = 221 [default=0];
-  optional float field222 = 222 [default=0.0];
-  optional int32 field63 = 63;
-
-  repeated group Group1 = 10 {
-    required float field11 = 11;
-    optional float field26 = 26;
-    optional string field12 = 12;
-    optional string field13 = 13;
-    repeated string field14 = 14;
-    required uint64 field15 = 15;
-    optional int32 field5 = 5;
-    optional string field27 = 27;
-    optional int32 field28 = 28;
-    optional string field29 = 29;
-    optional string field16 = 16;
-    repeated string field22 = 22;
-    repeated int32 field73 = 73;
-    optional int32 field20 = 20 [default=0];
-    optional string field24 = 24;
-    optional SizeMessage2GroupedMessage field31 = 31;
-  }
-  repeated string field128 = 128;
-  optional int64 field131 = 131;
-  repeated string field127 = 127;
-  optional int32 field129 = 129;
-  repeated int64 field130 = 130;
-  optional bool field205 = 205 [default=false];
-  optional bool field206 = 206 [default=false];
-}
-
-message SizeMessage2GroupedMessage {
-  optional float field1 = 1;
-  optional float field2 = 2;
-  optional float field3 = 3 [default=0.0];
-  optional bool field4 = 4;
-  optional bool field5 = 5;
-  optional bool field6 = 6 [default=true];
-  optional bool field7 = 7 [default=false];
-  optional float field8 = 8;
-  optional bool field9 = 9;
-  optional float field10 = 10;
-  optional int64 field11 = 11;
-}
diff --git a/benchmarks/java/pom.xml b/benchmarks/java/pom.xml
deleted file mode 100644
index c0dc940..0000000
--- a/benchmarks/java/pom.xml
+++ /dev/null
@@ -1,98 +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>
-  <artifactId>protobuf-java-benchmark</artifactId>
-  <groupId>com.google.protobuf</groupId>
-  <version>1.0.0</version>
-  <name>Protocol Buffers [Benchmark]</name>
-  <description>The benchmark tools for Protobuf Java.</description>
-
-  <dependencies>
-    <dependency>
-      <groupId>com.google.protobuf</groupId>
-      <artifactId>protobuf-java</artifactId>
-      <version>${protobuf.version}</version>
-      <type>jar</type>
-      <scope>system</scope>
-      <systemPath>${project.basedir}/lib/protobuf-java.jar</systemPath>
-    </dependency>
-    <dependency>
-      <groupId>com.google.caliper</groupId>
-      <artifactId>caliper</artifactId>
-      <version>1.0-beta-3</version>
-    </dependency>
-  </dependencies>
-
-  <build>
-    <pluginManagement>
-      <plugins>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-assembly-plugin</artifactId>
-          <version>2.4.1</version>
-          <configuration>
-            <!-- get all project dependencies -->
-            <descriptorRefs>
-              <descriptorRef>jar-with-dependencies</descriptorRef>
-            </descriptorRefs>
-            <!-- MainClass in mainfest make a executable jar -->
-            <archive>
-              <manifest>
-                <mainClass>com.mkyong.core.utils.App</mainClass>
-              </manifest>
-            </archive>
-          </configuration>
-          <executions>
-            <execution>
-              <id>make-assembly</id>
-              <!-- bind to the packaging phase -->
-              <phase>package</phase>
-              <goals>
-                <goal>single</goal>
-              </goals>
-            </execution>
-          </executions>
-        </plugin>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-compiler-plugin</artifactId>
-          <version>3.5.1</version>
-          <configuration>
-            <source>1.8</source>
-            <target>1.8</target>
-          </configuration>
-        </plugin>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-jar-plugin</artifactId>
-          <version>2.5</version>
-          <configuration>
-            <archive>
-              <manifest>
-                <addClasspath>true</addClasspath>
-                <mainClass>com.google.protocolbuffers.ProtoBench</mainClass>
-              </manifest>
-            </archive>
-          </configuration>
-        </plugin>
-        <plugin>
-          <groupId>org.apache.maven.plugins</groupId>
-          <artifactId>maven-source-plugin</artifactId>
-          <version>2.4</version>
-          <executions>
-            <execution>
-              <id>attach-sources</id>
-              <goals>
-                <goal>jar-no-fork</goal>
-              </goals>
-            </execution>
-          </executions>
-        </plugin>
-      </plugins>
-    </pluginManagement>
-  </build>
-</project>
-
diff --git a/benchmarks/java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java b/benchmarks/java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java
deleted file mode 100644
index ef30749..0000000
--- a/benchmarks/java/src/main/java/com/google/protobuf/ProtoCaliperBenchmark.java
+++ /dev/null
@@ -1,208 +0,0 @@
-package com.google.protobuf;
-
-import com.google.caliper.BeforeExperiment;
-import com.google.caliper.Benchmark;
-import com.google.caliper.Param;
-import com.google.protobuf.benchmarks.Benchmarks.BenchmarkDataset;
-import java.io.ByteArrayInputStream;
-import java.io.ByteArrayOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * Basic benchmarks for Java protobuf parsing.
- */
-public class ProtoCaliperBenchmark {
-  public enum BenchmarkMessageType {
-    GOOGLE_MESSAGE1_PROTO3 {
-      @Override
-      ExtensionRegistry getExtensionRegistry() {
-        return ExtensionRegistry.newInstance();
-      }
-      @Override
-      Message getDefaultInstance() {
-        return com.google.protobuf.benchmarks.BenchmarkMessage1Proto3.GoogleMessage1
-            .getDefaultInstance();
-      }
-    },
-    GOOGLE_MESSAGE1_PROTO2 {
-      @Override ExtensionRegistry getExtensionRegistry() {
-        return ExtensionRegistry.newInstance();
-      }
-      @Override
-      Message getDefaultInstance() {
-        return com.google.protobuf.benchmarks.BenchmarkMessage1Proto2.GoogleMessage1
-            .getDefaultInstance();
-      }
-    },
-    GOOGLE_MESSAGE2 {
-      @Override
-      ExtensionRegistry getExtensionRegistry() {
-        return ExtensionRegistry.newInstance();
-      }
-      @Override
-      Message getDefaultInstance() {
-        return com.google.protobuf.benchmarks.BenchmarkMessage2.GoogleMessage2.getDefaultInstance();
-      }
-    },
-    GOOGLE_MESSAGE3 {
-      @Override
-      ExtensionRegistry getExtensionRegistry() {
-        ExtensionRegistry extensions = ExtensionRegistry.newInstance();
-        com.google.protobuf.benchmarks.BenchmarkMessage38.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage37.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage36.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage35.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage34.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage33.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage32.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage31.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage3.registerAllExtensions(extensions);
-        return extensions;
-      }
-      @Override
-      Message getDefaultInstance() {
-        return com.google.protobuf.benchmarks.BenchmarkMessage3.GoogleMessage3.getDefaultInstance();
-      }
-    },
-    GOOGLE_MESSAGE4 {
-      @Override
-      ExtensionRegistry getExtensionRegistry() {
-        ExtensionRegistry extensions = ExtensionRegistry.newInstance();
-        com.google.protobuf.benchmarks.BenchmarkMessage43.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage42.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage41.registerAllExtensions(extensions);
-        com.google.protobuf.benchmarks.BenchmarkMessage4.registerAllExtensions(extensions);
-        return extensions;
-      }
-      @Override
-      Message getDefaultInstance() {
-        return com.google.protobuf.benchmarks.BenchmarkMessage4.GoogleMessage4.getDefaultInstance();
-      }
-    };
-
-    abstract ExtensionRegistry getExtensionRegistry();
-    abstract Message getDefaultInstance();
-  }
-
-  private BenchmarkMessageType benchmarkMessageType;
-  @Param("")
-  private String dataFile;
-
-  private byte[] inputData;
-  private BenchmarkDataset benchmarkDataset;
-  private Message defaultMessage;
-  private ExtensionRegistry extensions;
-  private List<byte[]> inputDataList;
-  private List<ByteArrayInputStream> inputStreamList;
-  private List<ByteString> inputStringList;
-  private List<Message> sampleMessageList;
-
-  private BenchmarkMessageType getMessageType() throws IOException {
-    if (benchmarkDataset.getMessageName().equals("benchmarks.proto3.GoogleMessage1")) {
-      return BenchmarkMessageType.GOOGLE_MESSAGE1_PROTO3;
-    } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage1")) {
-      return BenchmarkMessageType.GOOGLE_MESSAGE1_PROTO2;
-    } else if (benchmarkDataset.getMessageName().equals("benchmarks.proto2.GoogleMessage2")) {
-      return BenchmarkMessageType.GOOGLE_MESSAGE2;
-    } else if (benchmarkDataset.getMessageName().
-        equals("benchmarks.google_message3.GoogleMessage3")) {
-      return BenchmarkMessageType.GOOGLE_MESSAGE3;
-    } else if (benchmarkDataset.getMessageName().
-        equals("benchmarks.google_message4.GoogleMessage4")) {
-      return BenchmarkMessageType.GOOGLE_MESSAGE4;
-    } else {
-      throw new IllegalStateException("Invalid DataFile! There's no testing message named "
-          + benchmarkDataset.getMessageName());
-    }
-  }
-
-  @BeforeExperiment
-  void setUp() throws IOException {
-    if (!dataFile.equals("")) {
-      RandomAccessFile file = new RandomAccessFile(new File(dataFile), "r");
-      inputData = new byte[(int) file.length()];
-      file.readFully(inputData);
-      benchmarkDataset = BenchmarkDataset.parseFrom(inputData);
-      benchmarkMessageType = getMessageType();
-    } else {
-      inputData = new byte[0];
-      benchmarkDataset = BenchmarkDataset.parseFrom(inputData);
-      benchmarkMessageType = BenchmarkMessageType.GOOGLE_MESSAGE2;
-    }
-    defaultMessage = benchmarkMessageType.getDefaultInstance();
-    extensions = benchmarkMessageType.getExtensionRegistry();
-    inputDataList = new ArrayList<byte[]>();
-    inputStreamList = new ArrayList<ByteArrayInputStream>();
-    inputStringList = new ArrayList<ByteString>();
-    sampleMessageList = new ArrayList<Message>();
-
-    for (int i = 0; i < benchmarkDataset.getPayloadCount(); i++) {
-      byte[] singleInputData = benchmarkDataset.getPayload(i).toByteArray();
-      inputDataList.add(benchmarkDataset.getPayload(i).toByteArray());
-      inputStreamList.add(new ByteArrayInputStream(
-          benchmarkDataset.getPayload(i).toByteArray()));
-      inputStringList.add(benchmarkDataset.getPayload(i));
-      sampleMessageList.add(
-          defaultMessage.newBuilderForType().mergeFrom(singleInputData, extensions).build());
-    }
-  }
-
-  @SuppressWarnings("IgnoredPureGetter")
-  @Benchmark
-  void serializeToByteArray(int reps) throws IOException {
-    if (sampleMessageList.size() == 0) {
-      return;
-    }
-    for (int i = 0; i < reps; i++) {
-      for (int j = 0; j < sampleMessageList.size(); j++) {
-        sampleMessageList.get(j).toByteArray();
-      }
-    }
-  }
-
-  @Benchmark
-  void serializeToMemoryStream(int reps) throws IOException {
-    if (sampleMessageList.size() == 0) {
-      return;
-    }
-    for (int i = 0; i < reps; i++) {
-      for (int j = 0; j < sampleMessageList.size(); j++) {
-        ByteArrayOutputStream output = new ByteArrayOutputStream();
-        sampleMessageList.get(j).writeTo(output);
-      }
-    }
-  }
-
-  @Benchmark
-  void deserializeFromByteArray(int reps) throws IOException {
-    if (inputDataList.size() == 0) {
-      return;
-    }
-    for (int i = 0; i < reps; i++) {
-      for (int j = 0; j < inputDataList.size(); j++) {
-        benchmarkMessageType.getDefaultInstance().getParserForType().parseFrom(
-          inputDataList.get(j), extensions);
-      }
-    }
-  }
-
-  @Benchmark
-  void deserializeFromMemoryStream(int reps) throws IOException {
-    if (inputStreamList.size() == 0) {
-      return;
-    }
-    for (int i = 0; i < reps; i++) {
-      for (int j = 0; j < inputStreamList.size(); j++) {
-        benchmarkMessageType.getDefaultInstance().getParserForType().parseFrom(
-            inputStreamList.get(j), extensions);
-        inputStreamList.get(j).reset();
-      }
-    }
-  }
-}
-
-
diff --git a/benchmarks/js/benchmark_suite.js b/benchmarks/js/benchmark_suite.js
deleted file mode 100644
index c5c3e51..0000000
--- a/benchmarks/js/benchmark_suite.js
+++ /dev/null
@@ -1,33 +0,0 @@
-var benchmark = require("benchmark");
-
-function newBenchmark(messageName, filename, language) {
-  var benches = [];
-  return {
-    suite: new benchmark.Suite(messageName + filename + language )
-      .on("add", function(event) {
-          benches.push(event.target);
-      })
-      .on("start", function() {
-          process.stdout.write(
-            "benchmarking message " + messageName
-            + " of dataset file " + filename
-            + "'s performance ..." + "\n\n");
-      })
-      .on("cycle", function(event) {
-          process.stdout.write(String(event.target) + "\n");
-      })
-      .on("complete", function() {
-          var getHz = function(bench) {
-            return 1 / (bench.stats.mean + bench.stats.moe);
-          }
-          benches.forEach(function(val, index) {
-            benches[index] = getHz(val);
-          });
-      }),
-     benches: benches
-  }
-}
-
-module.exports = {
-        newBenchmark: newBenchmark
-}
diff --git a/benchmarks/js/js_benchmark.js b/benchmarks/js/js_benchmark.js
deleted file mode 100644
index 9ba4828..0000000
--- a/benchmarks/js/js_benchmark.js
+++ /dev/null
@@ -1,82 +0,0 @@
-require('./datasets/google_message1/proto2/benchmark_message1_proto2_pb.js');
-require('./datasets/google_message1/proto3/benchmark_message1_proto3_pb.js');
-require('./datasets/google_message2/benchmark_message2_pb.js');
-require('./datasets/google_message3/benchmark_message3_pb.js');
-require('./datasets/google_message4/benchmark_message4_pb.js');
-require('./benchmarks_pb.js');
-
-var fs = require('fs');
-var benchmarkSuite = require("./benchmark_suite.js");
-
-
-function getNewPrototype(name) {
-  var message = eval("proto." + name);
-  if (typeof(message) == "undefined") {
-    throw "type " + name + " is undefined";
-  }
-  return message;
-}
-
-var results = [];
-var json_file = "";
-
-console.log("#####################################################");
-console.log("Js Benchmark: ");
-process.argv.forEach(function(filename, index) {
-  if (index < 2) {
-    return;
-  }
-  if (filename.indexOf("--json_output") != -1) {
-    json_file = filename.replace(/^--json_output=/, '');
-    return;
-  }
-
-  var benchmarkDataset =
-      proto.benchmarks.BenchmarkDataset.deserializeBinary(fs.readFileSync(filename));
-  var messageList = [];
-  var totalBytes = 0;
-  benchmarkDataset.getPayloadList().forEach(function(onePayload) {
-    var message = getNewPrototype(benchmarkDataset.getMessageName());
-    messageList.push(message.deserializeBinary(onePayload));
-    totalBytes += onePayload.length;
-  });
-
-  var scenarios = benchmarkSuite.newBenchmark(
-      benchmarkDataset.getMessageName(), filename, "js");
-  scenarios.suite
-  .add("js deserialize", function() {
-    benchmarkDataset.getPayloadList().forEach(function(onePayload) {
-      var protoType = getNewPrototype(benchmarkDataset.getMessageName());
-      protoType.deserializeBinary(onePayload);
-    });
-  })
-  .add("js serialize", function() {
-    var protoType = getNewPrototype(benchmarkDataset.getMessageName());
-    messageList.forEach(function(message) {
-      message.serializeBinary();
-    });
-  })
-  .run({"Async": false});
-
-  results.push({
-    filename: filename,
-    benchmarks: {
-      protobufjs_decoding: scenarios.benches[0] * totalBytes / 1024 / 1024,
-      protobufjs_encoding: scenarios.benches[1] * totalBytes / 1024 / 1024
-    }
-  })
-
-  console.log("Throughput for deserialize: "
-    + scenarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" );
-  console.log("Throughput for serialize: "
-    + scenarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" );
-  console.log("");
-});
-console.log("#####################################################");
-
-if (json_file != "") {
-  fs.writeFile(json_file, JSON.stringify(results), (err) => {
-    if (err) throw err;
-  });
-}
-
diff --git a/benchmarks/php/PhpBenchmark.php b/benchmarks/php/PhpBenchmark.php
deleted file mode 100644
index d3db61d..0000000
--- a/benchmarks/php/PhpBenchmark.php
+++ /dev/null
@@ -1,170 +0,0 @@
-<?php
-
-namespace Google\Protobuf\Benchmark;
-ini_set('memory_limit', '4096M');
-
-const NAME = "PhpBenchmark.php";
-
-function _require_all($dir, &$prefix) {
-    // require all php files
-    foreach (glob("$dir/*") as $path) {
-        if (preg_match('/\.php$/', $path) &&
-            substr($path, -strlen(NAME)) != NAME) {
-                require_once(substr($path, strlen($prefix) + 1));
-            } elseif (is_dir($path)) {
-                _require_all($path, $prefix);
-            }
-    }
-}
-// include all file
-foreach (explode(PATH_SEPARATOR, get_include_path()) as $one_include_path) {
-    _require_all($one_include_path, $one_include_path);
-}
-
-use Benchmarks\BenchmarkDataset;
-
-class BenchmarkMethod
-{
-    // $args[0]: dataset
-    // $args[1]: message class
-    static function parse(&$args) {
-        $payloads = $args[0]->getPayload();
-        for ($i = $payloads->count() - 1; $i >= 0; $i--) {
-            (new $args[1]())->mergeFromString($payloads->offsetGet($i));
-        }
-    }
-
-    // $args: array of message
-    static function serialize(&$args) {
-        foreach ($args as &$temp_message) {
-            $temp_message->serializeToString();
-        }
-    }
-}
-
-class Benchmark
-{
-    private $benchmark_name;
-    private $args;
-    private $benchmark_time;
-    private $total_bytes;
-    private $coefficient;
-
-    public function __construct($benchmark_name, $args, $total_bytes,
-        $benchmark_time = 5.0) {
-            $this->args = $args;
-            $this->benchmark_name = $benchmark_name;
-            $this->benchmark_time = $benchmark_time;
-            $this->total_bytes = $total_bytes;
-            $this->coefficient = pow (10, 0) / pow(2, 20);
-    }
-
-    public function runBenchmark() {
-        $t = $this->runBenchmarkWithTimes(1);
-        $times = ceil($this->benchmark_time / $t);
-        return $this->total_bytes * $times /
-        ($times == 1 ? $t : $this->runBenchmarkWithTimes($times)) *
-        $this->coefficient;
-    }
-
-    private function runBenchmarkWithTimes($times) {
-        $st = microtime(true);
-        for ($i = 0; $i < $times; $i++) {
-            call_user_func_array($this->benchmark_name, array(&$this->args));
-        }
-        $en = microtime(true);
-        return $en - $st;
-    }
-}
-
-function getMessageName(&$dataset) {
-    switch ($dataset->getMessageName()) {
-        case "benchmarks.proto3.GoogleMessage1":
-            return "\Benchmarks\Proto3\GoogleMessage1";
-        case "benchmarks.proto2.GoogleMessage1":
-            return "\Benchmarks\Proto2\GoogleMessage1";
-        case "benchmarks.proto2.GoogleMessage2":
-            return "\Benchmarks\Proto2\GoogleMessage2";
-        case "benchmarks.google_message3.GoogleMessage3":
-            return "\Benchmarks\Google_message3\GoogleMessage3";
-        case "benchmarks.google_message4.GoogleMessage4":
-            return "\Benchmarks\Google_message4\GoogleMessage4";
-        default:
-            exit("Message " . $dataset->getMessageName() . " not found !");
-    }
-}
-
-function runBenchmark($file, $behavior_prefix) {
-    $datafile = fopen($file, "r") or die("Unable to open file " . $file);
-    $bytes = fread($datafile, filesize($file));
-    $dataset = new BenchmarkDataset(NULL);
-    $dataset->mergeFromString($bytes);
-    $message_name = getMessageName($dataset);
-    $message_list = array();
-    $total_bytes = 0;
-    $payloads = $dataset->getPayload();
-    for ($i = $payloads->count() - 1; $i >= 0; $i--) {
-        $new_message = new $message_name();
-        $new_message->mergeFromString($payloads->offsetGet($i));
-        array_push($message_list, $new_message);
-        $total_bytes += strlen($payloads->offsetGet($i));
-    }
-
-    $parse_benchmark = new Benchmark(
-        "\Google\Protobuf\Benchmark\BenchmarkMethod::parse",
-        array($dataset, $message_name), $total_bytes);
-    $serialize_benchmark = new Benchmark(
-        "\Google\Protobuf\Benchmark\BenchmarkMethod::serialize",
-        $message_list, $total_bytes);
-
-    return array(
-        "filename" => $file,
-        "benchmarks" => array(
-            $behavior_prefix . "_parse" => $parse_benchmark->runBenchmark(),
-            $behavior_prefix . "_serailize" => $serialize_benchmark->runBenchmark()
-        ),
-        "message_name" => $dataset->getMessageName()
-    );
-}
-
-// main
-$json_output = false;
-$results = array();
-$behavior_prefix = "";
-
-foreach ($argv as $index => $arg) {
-    if ($index == 0) {
-        continue;
-    }
-    if ($arg == "--json") {
-        $json_output = true;
-    } else if (strpos($arg, "--behavior_prefix") == 0) {
-        $behavior_prefix = str_replace("--behavior_prefix=", "", $arg);
-    }
-}
-
-foreach ($argv as $index => $arg) {
-    if ($index == 0) {
-        continue;
-    }
-    if (substr($arg, 0, 2) == "--") {
-        continue;
-    } else {
-        array_push($results, runBenchmark($arg, $behavior_prefix));
-    }
-}
-
-if ($json_output) {
-    print json_encode($results);
-} else {
-    print "PHP protobuf benchmark result:\n\n";
-    foreach ($results as $result) {
-        printf("result for test data file: %s\n", $result["filename"]);
-        foreach ($result["benchmarks"] as $benchmark => $throughput) {
-            printf("   Throughput for benchmark %s: %.2f MB/s\n",
-                $benchmark, $throughput);
-        }
-    }
-}
-
-?>
diff --git a/benchmarks/php/autoload.php b/benchmarks/php/autoload.php
deleted file mode 100644
index 52a8741..0000000
--- a/benchmarks/php/autoload.php
+++ /dev/null
@@ -1,25 +0,0 @@
-<?php
-
-define("GOOGLE_INTERNAL_NAMESPACE", "Google\\Protobuf\\Internal\\");
-define("GOOGLE_NAMESPACE", "Google\\Protobuf\\");
-define("GOOGLE_GPBMETADATA_NAMESPACE", "GPBMetadata\\Google\\Protobuf\\");
-define("BENCHMARK_NAMESPACE", "Benchmarks");
-define("BENCHMARK_GPBMETADATA_NAMESPACE", "GPBMetadata\\Benchmarks");
-
-function protobuf_autoloader_impl($class, $prefix, $include_path) {
-    $length = strlen($prefix);
-    if ((substr($class, 0, $length) === $prefix)) {
-        $path = $include_path . '/' . implode('/', array_map('ucwords', explode('\\', $class))) . '.php';
-        include_once $path;
-    }
-}
-
-function protobuf_autoloader($class) {
-    protobuf_autoloader_impl($class, GOOGLE_INTERNAL_NAMESPACE, getenv('PROTOBUF_PHP_SRCDIR'));
-    protobuf_autoloader_impl($class, GOOGLE_NAMESPACE, getenv('PROTOBUF_PHP_SRCDIR'));
-    protobuf_autoloader_impl($class, GOOGLE_GPBMETADATA_NAMESPACE, getenv('PROTOBUF_PHP_SRCDIR'));
-    protobuf_autoloader_impl($class, BENCHMARK_NAMESPACE, getenv('CURRENT_DIR'));
-    protobuf_autoloader_impl($class, BENCHMARK_GPBMETADATA_NAMESPACE, getenv('CURRENT_DIR'));
-}
-
-spl_autoload_register('protobuf_autoloader');
diff --git a/benchmarks/protobuf.js/generate_pbjs_files.js b/benchmarks/protobuf.js/generate_pbjs_files.js
deleted file mode 100644
index 11945bf..0000000
--- a/benchmarks/protobuf.js/generate_pbjs_files.js
+++ /dev/null
@@ -1,25 +0,0 @@
-var pbjs = require("./protobuf.js/cli").pbjs
-
-var argv = [];
-var protoFiles = [];
-var prefix = "";
-process.argv.forEach(function(val, index) {
-  var arg = val;
-  if (arg.length > 6 && arg.substring(arg.length - 6) == ".proto") {
-    protoFiles.push(arg);
-  } else if (arg.length > 15 && arg.substring(0, 15) ==  "--include_path=") {
-    prefix = arg.substring(15);
-  } else if (index >= 2) {
-    argv.push(arg);
-  }
-});
-protoFiles.forEach(function(val) {
-  argv.push(prefix + "/" + val);
-});
-
-pbjs.main(argv, function(err, output){
-  if (err) {
-    console.log(err);
-  }
-});
-
diff --git a/benchmarks/protobuf.js/protobufjs_benchmark.js b/benchmarks/protobuf.js/protobufjs_benchmark.js
deleted file mode 100644
index e062d1c..0000000
--- a/benchmarks/protobuf.js/protobufjs_benchmark.js
+++ /dev/null
@@ -1,66 +0,0 @@
-var root = require("./generated_bundle_code.js");
-var fs = require('fs');
-var benchmark = require("./node_modules/benchmark");
-var benchmarkSuite = require("./benchmark_suite.js");
-
-
-function getNewPrototype(name) {
-  var message = eval("root." + name);
-  if (typeof(message) == "undefined") {
-    throw "type " + name + " is undefined";
-  }
-  return message;
-}
-
-
-var results = [];
-
-console.log("#####################################################");
-console.log("ProtobufJs Benchmark: ");
-process.argv.forEach(function(filename, index) {
-  if (index < 2) {
-    return;
-  }
-  var benchmarkDataset =
-      root.benchmarks.BenchmarkDataset.decode(fs.readFileSync(filename));
-  var messageList = [];
-  var totalBytes = 0;
-  benchmarkDataset.payload.forEach(function(onePayload) {
-    var message = getNewPrototype(benchmarkDataset.messageName);
-    messageList.push(message.decode(onePayload));
-    totalBytes += onePayload.length;
-  });
-
-  var scenarios = benchmarkSuite.newBenchmark(
-    benchmarkDataset.messageName, filename, "protobufjs");
-  scenarios.suite
-  .add("protobuf.js static decoding", function() {
-    benchmarkDataset.payload.forEach(function(onePayload) {
-      var protoType = getNewPrototype(benchmarkDataset.messageName);
-      protoType.decode(onePayload);
-    });
-  })
-  .add("protobuf.js static encoding", function() {
-    var protoType = getNewPrototype(benchmarkDataset.messageName);
-    messageList.forEach(function(message) {
-      protoType.encode(message).finish();
-    });
-  })
-  .run({"Async": false});
-
-  results.push({
-    filename: filename,
-    benchmarks: {
-      protobufjs_decoding: scenarios.benches[0] * totalBytes,
-      protobufjs_encoding: scenarios.benches[1] * totalBytes
-    }
-  })
-
-  console.log("Throughput for decoding: "
-    + scenarios.benches[0] * totalBytes / 1024 / 1024 + "MB/s" );
-  console.log("Throughput for encoding: "
-    + scenarios.benches[1] * totalBytes / 1024 / 1024 + "MB/s" );
-  console.log("");
-});
-console.log("#####################################################");
-
diff --git a/benchmarks/python/__init__.py b/benchmarks/python/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/benchmarks/python/__init__.py
+++ /dev/null
diff --git a/benchmarks/python/py_benchmark.py b/benchmarks/python/py_benchmark.py
deleted file mode 100644
index 60e377e..0000000
--- a/benchmarks/python/py_benchmark.py
+++ /dev/null
@@ -1,161 +0,0 @@
-from __future__ import print_function
-import sys
-import os
-import timeit
-import math
-import argparse
-import fnmatch
-import json
-
-parser = argparse.ArgumentParser(description="Python protobuf benchmark")
-parser.add_argument("data_files", metavar="dataFile", nargs="+",
-                    help="testing data files.")
-parser.add_argument("--json", action="store_const", dest="json",
-                    const="yes", default="no",
-                    help="Whether to output json results")
-parser.add_argument("--behavior_prefix", dest="behavior_prefix",
-                    help="The output json format's behavior's name's prefix",
-                    default="")
-# BEGIN CPP GENERATED MESSAGE
-parser.add_argument("--cpp_generated", action="store_const",
-                    dest="cpp_generated", const="yes", default="no",
-                    help="Whether to link generated code library")
-# END CPP GENERATED MESSAGE
-args = parser.parse_args()
-# BEGIN CPP GENERATED MESSAGE
-# CPP generated code must be linked before importing the generated Python code
-# for the descriptor can be found in the pool
-if args.cpp_generated != "no":
-  sys.path.append( os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ) + "/.libs" )
-  import libbenchmark_messages
-  sys.path.append( os.path.dirname( os.path.dirname( os.path.abspath(__file__) ) ) + "/tmp" )
-# END CPP GENERATED MESSAGE
-
-
-import datasets.google_message1.proto2.benchmark_message1_proto2_pb2 as benchmark_message1_proto2_pb2
-import datasets.google_message1.proto3.benchmark_message1_proto3_pb2 as benchmark_message1_proto3_pb2
-import datasets.google_message2.benchmark_message2_pb2 as benchmark_message2_pb2
-import datasets.google_message3.benchmark_message3_pb2 as benchmark_message3_pb2
-import datasets.google_message4.benchmark_message4_pb2 as benchmark_message4_pb2
-import benchmarks_pb2 as benchmarks_pb2
-
-
-def run_one_test(filename):
-  data = open(filename, "rb").read()
-  benchmark_dataset = benchmarks_pb2.BenchmarkDataset()
-  benchmark_dataset.ParseFromString(data)
-  total_bytes = 0
-  for payload in benchmark_dataset.payload:
-    total_bytes += len(payload)
-  benchmark_util = Benchmark(full_iteration=len(benchmark_dataset.payload),
-                             module="py_benchmark",
-                             setup_method="init",
-                             total_bytes=total_bytes)
-  result={}
-  result["filename"] =  filename
-  result["message_name"] =  benchmark_dataset.message_name
-  result["benchmarks"] = {}
-  benchmark_util.set_test_method("parse_from_benchmark")
-  result["benchmarks"][args.behavior_prefix + "_parse_from_benchmark"] = \
-    benchmark_util.run_benchmark(setup_method_args='"%s"' % (filename))
-  benchmark_util.set_test_method("serialize_to_benchmark")
-  result["benchmarks"][args.behavior_prefix + "_serialize_to_benchmark"] = \
-    benchmark_util.run_benchmark(setup_method_args='"%s"' % (filename))
-  return result
-
-
-def init(filename):
-  global benchmark_dataset, message_class, message_list, counter, total_bytes
-  message_list=[]
-  counter = 0
-  total_bytes = 0
-  data = open(filename, "rb").read()
-  benchmark_dataset = benchmarks_pb2.BenchmarkDataset()
-  benchmark_dataset.ParseFromString(data)
-
-  if benchmark_dataset.message_name == "benchmarks.proto3.GoogleMessage1":
-    message_class = benchmark_message1_proto3_pb2.GoogleMessage1
-  elif benchmark_dataset.message_name == "benchmarks.proto2.GoogleMessage1":
-    message_class = benchmark_message1_proto2_pb2.GoogleMessage1
-  elif benchmark_dataset.message_name == "benchmarks.proto2.GoogleMessage2":
-    message_class = benchmark_message2_pb2.GoogleMessage2
-  elif benchmark_dataset.message_name == "benchmarks.google_message3.GoogleMessage3":
-    message_class = benchmark_message3_pb2.GoogleMessage3
-  elif benchmark_dataset.message_name == "benchmarks.google_message4.GoogleMessage4":
-    message_class = benchmark_message4_pb2.GoogleMessage4
-  else:
-    raise IOError("Message %s not found!" % (benchmark_dataset.message_name))
-
-  for one_payload in benchmark_dataset.payload:
-    temp = message_class()
-    temp.ParseFromString(one_payload)
-    message_list.append(temp)
-    total_bytes += len(one_payload)
-
-
-def parse_from_benchmark():
-  global counter, message_class, benchmark_dataset
-  m = message_class().ParseFromString(benchmark_dataset.payload[counter % len(benchmark_dataset.payload)])
-  counter = counter + 1
-
-
-def serialize_to_benchmark():
-  global counter, message_list, message_class
-  s = message_list[counter % len(benchmark_dataset.payload)].SerializeToString()
-  counter = counter + 1
-
-
-class Benchmark:
-  def __init__(self, module=None, test_method=None,
-               setup_method=None, total_bytes=None, full_iteration = 1):
-    self.full_iteration = full_iteration
-    self.module = module
-    self.test_method = test_method
-    self.setup_method = setup_method
-    self.total_bytes = total_bytes
-
-  def set_test_method(self, test_method):
-    self.test_method = test_method
-
-  def full_setup_code(self, setup_method_args=''):
-    setup_code = ""
-    setup_code += "from %s import %s\n" % (self.module, self.test_method)
-    setup_code += "from %s import %s\n" % (self.module, self.setup_method)
-    setup_code += "%s(%s)\n" % (self.setup_method, setup_method_args)
-    return setup_code
-
-  def dry_run(self, test_method_args='', setup_method_args=''):
-    return timeit.timeit(stmt="%s(%s)" % (self.test_method, test_method_args),
-                         setup=self.full_setup_code(setup_method_args),
-                         number=self.full_iteration);
-
-  def run_benchmark(self, test_method_args='', setup_method_args=''):
-    reps = self.full_iteration;
-    t = self.dry_run(test_method_args, setup_method_args);
-    if t < 3 :
-      reps = int(math.ceil(3 / t)) * self.full_iteration
-    if reps != self.full_iteration:
-        t = timeit.timeit(stmt="%s(%s)" % (self.test_method, test_method_args),
-                          setup=self.full_setup_code(setup_method_args),
-                          number=reps);
-    return self.total_bytes * 1.0 / 2 ** 20 / (1.0 * t / reps * self.full_iteration)
-
-
-if __name__ == "__main__":
-  results = []
-  for file in args.data_files:
-    results.append(run_one_test(file))
-
-  if args.json != "no":
-    print(json.dumps(results))
-  else:
-    for result in results:
-      print("Message %s of dataset file %s" % \
-          (result["message_name"], result["filename"]))
-      print("Average throughput for parse_from_benchmark: %.2f MB/s" % \
-          (result["benchmarks"][ \
-                      args.behavior_prefix + "_parse_from_benchmark"]))
-      print("Average throughput for serialize_to_benchmark: %.2f MB/s" % \
-          (result["benchmarks"][ \
-                      args.behavior_prefix + "_serialize_to_benchmark"]))
-      print("")
diff --git a/benchmarks/python/python_benchmark_messages.cc b/benchmarks/python/python_benchmark_messages.cc
deleted file mode 100644
index f6ddcf3..0000000
--- a/benchmarks/python/python_benchmark_messages.cc
+++ /dev/null
@@ -1,31 +0,0 @@
-#include <Python.h>
-
-#include "benchmarks.pb.h"
-#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h"
-#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h"
-#include "datasets/google_message2/benchmark_message2.pb.h"
-#include "datasets/google_message3/benchmark_message3.pb.h"
-#include "datasets/google_message4/benchmark_message4.pb.h"
-
-static struct PyModuleDef _module = {PyModuleDef_HEAD_INIT,
-                                     "libbenchmark_messages",
-                                     "Benchmark messages Python module",
-                                     -1,
-                                     NULL,
-                                     NULL,
-                                     NULL,
-                                     NULL,
-                                     NULL};
-
-extern "C" {
-PyMODINIT_FUNC PyInit_libbenchmark_messages() {
-  benchmarks::BenchmarkDataset().descriptor();
-  benchmarks::proto3::GoogleMessage1().descriptor();
-  benchmarks::proto2::GoogleMessage1().descriptor();
-  benchmarks::proto2::GoogleMessage2().descriptor();
-  benchmarks::google_message3::GoogleMessage3().descriptor();
-  benchmarks::google_message4::GoogleMessage4().descriptor();
-
-  return PyModule_Create(&_module);
-}
-}
diff --git a/benchmarks/util/__init__.py b/benchmarks/util/__init__.py
deleted file mode 100644
index e69de29..0000000
--- a/benchmarks/util/__init__.py
+++ /dev/null
diff --git a/benchmarks/util/big_query_utils.py b/benchmarks/util/big_query_utils.py
deleted file mode 100755
index aea55bb..0000000
--- a/benchmarks/util/big_query_utils.py
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/bin/env python2.7
-
-from __future__ import print_function
-import argparse
-import json
-import uuid
-import httplib2
-
-from apiclient import discovery
-from apiclient.errors import HttpError
-from oauth2client.client import GoogleCredentials
-
-# 30 days in milliseconds
-_EXPIRATION_MS = 30 * 24 * 60 * 60 * 1000
-NUM_RETRIES = 3
-
-
-def create_big_query():
-    """Authenticates with cloud platform and gets a BiqQuery service object
-  """
-    creds = GoogleCredentials.get_application_default()
-    return discovery.build(
-        'bigquery', 'v2', credentials=creds, cache_discovery=False)
-
-
-def create_dataset(biq_query, project_id, dataset_id):
-    is_success = True
-    body = {
-        'datasetReference': {
-            'projectId': project_id,
-            'datasetId': dataset_id
-        }
-    }
-
-    try:
-        dataset_req = biq_query.datasets().insert(
-            projectId=project_id, body=body)
-        dataset_req.execute(num_retries=NUM_RETRIES)
-    except HttpError as http_error:
-        if http_error.resp.status == 409:
-            print('Warning: The dataset %s already exists' % dataset_id)
-        else:
-            # Note: For more debugging info, print "http_error.content"
-            print('Error in creating dataset: %s. Err: %s' % (dataset_id,
-                                                              http_error))
-            is_success = False
-    return is_success
-
-
-def create_table(big_query, project_id, dataset_id, table_id, table_schema,
-                 description):
-    fields = [{
-        'name': field_name,
-        'type': field_type,
-        'description': field_description
-    } for (field_name, field_type, field_description) in table_schema]
-    return create_table2(big_query, project_id, dataset_id, table_id, fields,
-                         description)
-
-
-def create_partitioned_table(big_query,
-                             project_id,
-                             dataset_id,
-                             table_id,
-                             table_schema,
-                             description,
-                             partition_type='DAY',
-                             expiration_ms=_EXPIRATION_MS):
-    """Creates a partitioned table. By default, a date-paritioned table is created with
-  each partition lasting 30 days after it was last modified.
-  """
-    fields = [{
-        'name': field_name,
-        'type': field_type,
-        'description': field_description
-    } for (field_name, field_type, field_description) in table_schema]
-    return create_table2(big_query, project_id, dataset_id, table_id, fields,
-                         description, partition_type, expiration_ms)
-
-
-def create_table2(big_query,
-                  project_id,
-                  dataset_id,
-                  table_id,
-                  fields_schema,
-                  description,
-                  partition_type=None,
-                  expiration_ms=None):
-    is_success = True
-
-    body = {
-        'description': description,
-        'schema': {
-            'fields': fields_schema
-        },
-        'tableReference': {
-            'datasetId': dataset_id,
-            'projectId': project_id,
-            'tableId': table_id
-        }
-    }
-
-    if partition_type and expiration_ms:
-        body["timePartitioning"] = {
-            "type": partition_type,
-            "expirationMs": expiration_ms
-        }
-
-    try:
-        table_req = big_query.tables().insert(
-            projectId=project_id, datasetId=dataset_id, body=body)
-        res = table_req.execute(num_retries=NUM_RETRIES)
-        print('Successfully created %s "%s"' % (res['kind'], res['id']))
-    except HttpError as http_error:
-        if http_error.resp.status == 409:
-            print('Warning: Table %s already exists' % table_id)
-        else:
-            print('Error in creating table: %s. Err: %s' % (table_id,
-                                                            http_error))
-            is_success = False
-    return is_success
-
-
-def patch_table(big_query, project_id, dataset_id, table_id, fields_schema):
-    is_success = True
-
-    body = {
-        'schema': {
-            'fields': fields_schema
-        },
-        'tableReference': {
-            'datasetId': dataset_id,
-            'projectId': project_id,
-            'tableId': table_id
-        }
-    }
-
-    try:
-        table_req = big_query.tables().patch(
-            projectId=project_id,
-            datasetId=dataset_id,
-            tableId=table_id,
-            body=body)
-        res = table_req.execute(num_retries=NUM_RETRIES)
-        print('Successfully patched %s "%s"' % (res['kind'], res['id']))
-    except HttpError as http_error:
-        print('Error in creating table: %s. Err: %s' % (table_id, http_error))
-        is_success = False
-    return is_success
-
-
-def insert_rows(big_query, project_id, dataset_id, table_id, rows_list):
-    is_success = True
-    body = {'rows': rows_list}
-    try:
-        insert_req = big_query.tabledata().insertAll(
-            projectId=project_id,
-            datasetId=dataset_id,
-            tableId=table_id,
-            body=body)
-        res = insert_req.execute(num_retries=NUM_RETRIES)
-        if res.get('insertErrors', None):
-            print('Error inserting rows! Response: %s' % res)
-            is_success = False
-    except HttpError as http_error:
-        print('Error inserting rows to the table %s' % table_id)
-        is_success = False
-
-    return is_success
-
-
-def sync_query_job(big_query, project_id, query, timeout=5000):
-    query_data = {'query': query, 'timeoutMs': timeout}
-    query_job = None
-    try:
-        query_job = big_query.jobs().query(
-            projectId=project_id,
-            body=query_data).execute(num_retries=NUM_RETRIES)
-    except HttpError as http_error:
-        print('Query execute job failed with error: %s' % http_error)
-        print(http_error.content)
-    return query_job
-
-
-    # List of (column name, column type, description) tuples
-def make_row(unique_row_id, row_values_dict):
-    """row_values_dict is a dictionary of column name and column value.
-  """
-    return {'insertId': unique_row_id, 'json': row_values_dict}
diff --git a/benchmarks/util/data_proto2_to_proto3_util.h b/benchmarks/util/data_proto2_to_proto3_util.h
deleted file mode 100644
index 5eea850..0000000
--- a/benchmarks/util/data_proto2_to_proto3_util.h
+++ /dev/null
@@ -1,64 +0,0 @@
-#ifndef PROTOBUF_BENCHMARKS_UTIL_DATA_PROTO2_TO_PROTO3_UTIL_H_
-#define PROTOBUF_BENCHMARKS_UTIL_DATA_PROTO2_TO_PROTO3_UTIL_H_
-
-#include "google/protobuf/message.h"
-#include "google/protobuf/descriptor.h"
-
-using google::protobuf::FieldDescriptor;
-using google::protobuf::Message;
-using google::protobuf::Reflection;
-
-namespace google {
-namespace protobuf {
-namespace util {
-
-class DataStripper {
- public:
-  void StripMessage(Message *message) {
-    std::vector<const FieldDescriptor*> set_fields;
-    const Reflection* reflection = message->GetReflection();
-    reflection->ListFields(*message, &set_fields);
-
-    for (size_t i = 0; i < set_fields.size(); i++) {
-      const FieldDescriptor* field = set_fields[i];
-      if (ShouldBeClear(field)) {
-        reflection->ClearField(message, field);
-        continue;
-      }
-      if (field->type() == FieldDescriptor::TYPE_MESSAGE) {
-        if (field->is_repeated()) {
-          for (int j = 0; j < reflection->FieldSize(*message, field); j++) {
-            StripMessage(reflection->MutableRepeatedMessage(message, field, j));
-          }
-        } else {
-          StripMessage(reflection->MutableMessage(message, field));
-        }
-      }
-    }
-
-    reflection->MutableUnknownFields(message)->Clear();
-  }
- private:
-  virtual bool ShouldBeClear(const FieldDescriptor *field) = 0;
-};
-
-class GogoDataStripper : public DataStripper {
- private:
-  virtual bool ShouldBeClear(const FieldDescriptor *field) {
-    return field->type() == FieldDescriptor::TYPE_GROUP;
-  }
-};
-
-class Proto3DataStripper : public DataStripper {
- private:
-  virtual bool ShouldBeClear(const FieldDescriptor *field) {
-    return field->type() == FieldDescriptor::TYPE_GROUP ||
-           field->is_extension();
-  }
-};
-
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // PROTOBUF_BENCHMARKS_UTIL_DATA_PROTO2_TO_PROTO3_UTIL_H_
diff --git a/benchmarks/util/gogo_data_scrubber.cc b/benchmarks/util/gogo_data_scrubber.cc
deleted file mode 100644
index 9ef57b0..0000000
--- a/benchmarks/util/gogo_data_scrubber.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-#include "benchmarks.pb.h"
-#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h"
-#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h"
-#include "datasets/google_message2/benchmark_message2.pb.h"
-#include "datasets/google_message3/benchmark_message3.pb.h"
-#include "datasets/google_message4/benchmark_message4.pb.h"
-#include "data_proto2_to_proto3_util.h"
-
-#include <fstream>
-
-using google::protobuf::util::GogoDataStripper;
-
-std::string ReadFile(const std::string& name) {
-  std::ifstream file(name.c_str());
-  GOOGLE_CHECK(file.is_open()) << "Couldn't find file '"
-      << name
-      << "', please make sure you are running this command from the benchmarks"
-      << " directory.\n";
-  return std::string((std::istreambuf_iterator<char>(file)),
-                     std::istreambuf_iterator<char>());
-}
-
-int main(int argc, char *argv[]) {
-  if (argc % 2 == 0 || argc == 1) {
-    std::cerr << "Usage: [input_files] [output_file_names] where " <<
-        "input_files are one to one mapping to output_file_names." <<
-        std::endl;
-    return 1;
-  }
-
-  for (int i = argc / 2; i > 0; i--) {
-    const std::string &input_file = argv[i];
-    const std::string &output_file = argv[i + argc / 2];
-
-    std::cerr << "Generating " << input_file
-        << " to " << output_file << std::endl;
-    benchmarks::BenchmarkDataset dataset;
-    Message* message;
-    std::string dataset_payload = ReadFile(input_file);
-    GOOGLE_CHECK(dataset.ParseFromString(dataset_payload))
-      << "Can' t parse data file " << input_file;
-
-    if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") {
-      message = new benchmarks::proto3::GoogleMessage1;
-    } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") {
-      message = new benchmarks::proto2::GoogleMessage1;
-    } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") {
-      message = new benchmarks::proto2::GoogleMessage2;
-    } else if (dataset.message_name() ==
-        "benchmarks.google_message3.GoogleMessage3") {
-      message = new benchmarks::google_message3::GoogleMessage3;
-    } else if (dataset.message_name() ==
-        "benchmarks.google_message4.GoogleMessage4") {
-      message = new benchmarks::google_message4::GoogleMessage4;
-    } else {
-      std::cerr << "Unknown message type: " << dataset.message_name();
-      exit(1);
-    }
-
-    for (int i = 0; i < dataset.payload_size(); i++) {
-      message->ParseFromString(dataset.payload(i));
-      GogoDataStripper stripper;
-      stripper.StripMessage(message);
-      dataset.set_payload(i, message->SerializeAsString());
-    }
-
-    std::ofstream ofs(output_file);
-    ofs << dataset.SerializeAsString();
-    ofs.close();
-  }
-
-
-  return 0;
-}
diff --git a/benchmarks/util/proto3_data_stripper.cc b/benchmarks/util/proto3_data_stripper.cc
deleted file mode 100644
index 3096c4c..0000000
--- a/benchmarks/util/proto3_data_stripper.cc
+++ /dev/null
@@ -1,74 +0,0 @@
-#include "benchmarks.pb.h"
-#include "datasets/google_message1/proto2/benchmark_message1_proto2.pb.h"
-#include "datasets/google_message1/proto3/benchmark_message1_proto3.pb.h"
-#include "datasets/google_message2/benchmark_message2.pb.h"
-#include "datasets/google_message3/benchmark_message3.pb.h"
-#include "datasets/google_message4/benchmark_message4.pb.h"
-#include "data_proto2_to_proto3_util.h"
-
-#include <fstream>
-
-using google::protobuf::util::Proto3DataStripper;
-
-std::string ReadFile(const std::string& name) {
-  std::ifstream file(name.c_str());
-  GOOGLE_CHECK(file.is_open()) << "Couldn't find file '"
-      << name
-      << "', please make sure you are running this command from the benchmarks"
-      << " directory.\n";
-  return std::string((std::istreambuf_iterator<char>(file)),
-                     std::istreambuf_iterator<char>());
-}
-
-int main(int argc, char *argv[]) {
-  if (argc % 2 == 0 || argc == 1) {
-    std::cerr << "Usage: [input_files] [output_file_names] where " <<
-        "input_files are one to one mapping to output_file_names." <<
-        std::endl;
-    return 1;
-  }
-
-  for (int i = argc / 2; i > 0; i--) {
-    const std::string &input_file = argv[i];
-    const std::string &output_file = argv[i + argc / 2];
-
-    std::cerr << "Generating " << input_file
-        << " to " << output_file << std::endl;
-    benchmarks::BenchmarkDataset dataset;
-    Message* message;
-    std::string dataset_payload = ReadFile(input_file);
-    GOOGLE_CHECK(dataset.ParseFromString(dataset_payload))
-      << "Can' t parse data file " << input_file;
-
-    if (dataset.message_name() == "benchmarks.proto3.GoogleMessage1") {
-      message = new benchmarks::proto3::GoogleMessage1;
-    } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage1") {
-      message = new benchmarks::proto2::GoogleMessage1;
-    } else if (dataset.message_name() == "benchmarks.proto2.GoogleMessage2") {
-      message = new benchmarks::proto2::GoogleMessage2;
-    } else if (dataset.message_name() ==
-        "benchmarks.google_message3.GoogleMessage3") {
-      message = new benchmarks::google_message3::GoogleMessage3;
-    } else if (dataset.message_name() ==
-        "benchmarks.google_message4.GoogleMessage4") {
-      message = new benchmarks::google_message4::GoogleMessage4;
-    } else {
-      std::cerr << "Unknown message type: " << dataset.message_name();
-      exit(1);
-    }
-
-    for (int i = 0; i < dataset.payload_size(); i++) {
-      message->ParseFromString(dataset.payload(i));
-      Proto3DataStripper stripper;
-      stripper.StripMessage(message);
-      dataset.set_payload(i, message->SerializeAsString());
-    }
-
-    std::ofstream ofs(output_file);
-    ofs << dataset.SerializeAsString();
-    ofs.close();
-  }
-
-
-  return 0;
-}
diff --git a/benchmarks/util/protoc-gen-gogoproto.cc b/benchmarks/util/protoc-gen-gogoproto.cc
deleted file mode 100644
index 9c1b3d0..0000000
--- a/benchmarks/util/protoc-gen-gogoproto.cc
+++ /dev/null
@@ -1,103 +0,0 @@
-#include "google/protobuf/compiler/code_generator.h"
-#include "google/protobuf/io/zero_copy_stream.h"
-#include "google/protobuf/io/printer.h"
-#include "google/protobuf/descriptor.h"
-#include "google/protobuf/descriptor.pb.h"
-#include "schema_proto2_to_proto3_util.h"
-
-#include "google/protobuf/compiler/plugin.h"
-
-using google::protobuf::FileDescriptorProto;
-using google::protobuf::FileDescriptor;
-using google::protobuf::DescriptorPool;
-using google::protobuf::io::Printer;
-using google::protobuf::util::SchemaGroupStripper;
-using google::protobuf::util::EnumScrubber;
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-
-namespace {
-
-string StripProto(string filename) {
-  if (filename.substr(filename.size() - 11) == ".protodevel") {
-    // .protodevel
-    return filename.substr(0, filename.size() - 11);
-  } else {
-    // .proto
-    return filename.substr(0, filename.size() - 6);
-  }
-}
-
-DescriptorPool new_pool_;
-
-}  // namespace
-
-class GoGoProtoGenerator : public CodeGenerator {
- public:
-  virtual bool GenerateAll(const std::vector<const FileDescriptor*>& files,
-                           const string& parameter,
-                           GeneratorContext* context,
-                           string* error) const {
-    for (int i = 0; i < files.size(); i++) {
-      for (auto file : files) {
-        bool can_generate =
-            (new_pool_.FindFileByName(file->name()) == nullptr);
-        for (int j = 0; j < file->dependency_count(); j++) {
-          can_generate &= (new_pool_.FindFileByName(
-              file->dependency(j)->name()) != nullptr);
-        }
-        for (int j = 0; j < file->public_dependency_count(); j++) {
-          can_generate &= (new_pool_.FindFileByName(
-              file->public_dependency(j)->name()) != nullptr);
-        }
-        for (int j = 0; j < file->weak_dependency_count(); j++) {
-          can_generate &= (new_pool_.FindFileByName(
-              file->weak_dependency(j)->name()) != nullptr);
-        }
-        if (can_generate) {
-          Generate(file, parameter, context, error);
-          break;
-        }
-      }
-    }
-
-    return true;
-  }
-
-  virtual bool Generate(const FileDescriptor* file,
-                        const string& parameter,
-                        GeneratorContext* context,
-                        string* error) const {
-    FileDescriptorProto new_file;
-    file->CopyTo(&new_file);
-    SchemaGroupStripper::StripFile(file, &new_file);
-
-    EnumScrubber enum_scrubber;
-    enum_scrubber.ScrubFile(&new_file);
-
-    string filename = file->name();
-    string basename = StripProto(filename);
-
-    std::vector<std::pair<string,string>> option_pairs;
-    ParseGeneratorParameter(parameter, &option_pairs);
-
-    std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
-        context->Open(basename + ".proto"));
-    string content = new_pool_.BuildFile(new_file)->DebugString();
-    Printer printer(output.get(), '$');
-    printer.WriteRaw(content.c_str(), content.size());
-
-    return true;
-  }
-};
-
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
-int main(int argc, char* argv[]) {
-  google::protobuf::compiler::GoGoProtoGenerator generator;
-  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
-}
diff --git a/benchmarks/util/protoc-gen-proto2_to_proto3.cc b/benchmarks/util/protoc-gen-proto2_to_proto3.cc
deleted file mode 100644
index d0a8902..0000000
--- a/benchmarks/util/protoc-gen-proto2_to_proto3.cc
+++ /dev/null
@@ -1,115 +0,0 @@
-#include "google/protobuf/compiler/code_generator.h"
-#include "google/protobuf/io/zero_copy_stream.h"
-#include "google/protobuf/io/printer.h"
-#include "google/protobuf/descriptor.h"
-#include "google/protobuf/descriptor.pb.h"
-#include "schema_proto2_to_proto3_util.h"
-
-#include "google/protobuf/compiler/plugin.h"
-
-using google::protobuf::FileDescriptorProto;
-using google::protobuf::FileDescriptor;
-using google::protobuf::DescriptorPool;
-using google::protobuf::io::Printer;
-using google::protobuf::util::SchemaGroupStripper;
-using google::protobuf::util::EnumScrubber;
-using google::protobuf::util::ExtensionStripper;
-using google::protobuf::util::FieldScrubber;
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-
-namespace {
-
-string StripProto(string filename) {
-  return filename.substr(0, filename.rfind(".proto"));
-}
-
-DescriptorPool* GetPool() {
-  static DescriptorPool *pool = new DescriptorPool();
-  return pool;
-}
-
-}  // namespace
-
-class Proto2ToProto3Generator final : public CodeGenerator {
- public:
-  bool GenerateAll(const std::vector<const FileDescriptor*>& files,
-                           const string& parameter,
-                           GeneratorContext* context,
-                           string* error) const {
-    for (int i = 0; i < files.size(); i++) {
-      for (auto file : files) {
-        if (CanGenerate(file)) {
-          Generate(file, parameter, context, error);
-          break;
-        }
-      }
-    }
-
-    return true;
-  }
-
-  bool Generate(const FileDescriptor* file,
-                        const string& parameter,
-                        GeneratorContext* context,
-                        string* error) const {
-    FileDescriptorProto new_file;
-    file->CopyTo(&new_file);
-    SchemaGroupStripper::StripFile(file, &new_file);
-
-    EnumScrubber enum_scrubber;
-    enum_scrubber.ScrubFile(&new_file);
-    ExtensionStripper::StripFile(&new_file);
-    FieldScrubber::ScrubFile(&new_file);
-    new_file.set_syntax("proto3");
-
-    string filename = file->name();
-    string basename = StripProto(filename);
-
-    std::vector<std::pair<string,string>> option_pairs;
-    ParseGeneratorParameter(parameter, &option_pairs);
-
-    std::unique_ptr<google::protobuf::io::ZeroCopyOutputStream> output(
-        context->Open(basename + ".proto"));
-    string content = GetPool()->BuildFile(new_file)->DebugString();
-    Printer printer(output.get(), '$');
-    printer.WriteRaw(content.c_str(), content.size());
-
-    return true;
-  }
- private:
-  bool CanGenerate(const FileDescriptor* file) const {
-    if (GetPool()->FindFileByName(file->name()) != nullptr) {
-      return false;
-    }
-    for (int j = 0; j < file->dependency_count(); j++) {
-      if (GetPool()->FindFileByName(file->dependency(j)->name()) == nullptr) {
-        return false;
-      }
-    }
-    for (int j = 0; j < file->public_dependency_count(); j++) {
-      if (GetPool()->FindFileByName(
-          file->public_dependency(j)->name()) == nullptr) {
-        return false;
-      }
-    }
-    for (int j = 0; j < file->weak_dependency_count(); j++) {
-      if (GetPool()->FindFileByName(
-          file->weak_dependency(j)->name()) == nullptr) {
-        return false;
-      }
-    }
-    return true;
-  }
-};
-
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
-int main(int argc, char* argv[]) {
-  google::protobuf::compiler::Proto2ToProto3Generator generator;
-  return google::protobuf::compiler::PluginMain(argc, argv, &generator);
-}
diff --git a/benchmarks/util/result_parser.py b/benchmarks/util/result_parser.py
deleted file mode 100644
index d3251a8..0000000
--- a/benchmarks/util/result_parser.py
+++ /dev/null
@@ -1,352 +0,0 @@
-# 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
-# BEGIN OPENSOURCE
-import sys
-sys.path.append(os.path.join(os.path.dirname(os.path.realpath(__file__)), os.pardir))
-# END OPENSOURCE
-import tmp.benchmarks_pb2 as benchmarks_pb2
-
-__file_size_map = {}
-
-def __get_data_size(filename):
-  if filename[0] != '/':
-    filename = os.path.dirname(os.path.abspath(__file__)) + "/../" + filename
-  if filename in __file_size_map:
-    return __file_size_map[filename]
-  benchmark_dataset = benchmarks_pb2.BenchmarkDataset()
-  benchmark_dataset.ParseFromString(
-      open(filename, "rb").read())
-  size = 0
-  count = 0
-  for payload in benchmark_dataset.payload:
-    size += len(payload)
-    count += 1
-  __file_size_map[filename] = (size, 1.0 * size / count)
-  return size, 1.0 * size / count
-
-
-def __extract_file_name(file_name):
-  name_list = re.split(r"[/\.]", file_name)
-  short_file_name = ""
-  for name in name_list:
-    if name[:14] == "google_message":
-      short_file_name = name
-  return short_file_name
-
-
-__results = []
-
-
-# CPP results example:
-# [
-#   "benchmarks": [
-#     {
-#       "bytes_per_second": int,
-#       "cpu_time_ns": double,
-#       "iterations": int,
-#       "name: string,
-#       "real_time_ns: double,
-#       ...
-#     },
-#     ...
-#   ],
-#   ...
-# ]
-def __parse_cpp_result(filename):
-  if filename == "":
-    return
-  if filename[0] != '/':
-    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
-  with open(filename, encoding="utf-8") as f:
-    results = json.loads(f.read())
-    for benchmark in results["benchmarks"]:
-      data_filename = "".join(
-          re.split("(_parse_|_serialize)", benchmark["name"])[0])
-      behavior = benchmark["name"][len(data_filename) + 1:]
-      if data_filename[:2] == "BM":
-        data_filename = data_filename[3:]
-      __results.append({
-        "language": "cpp",
-        "dataFilename": data_filename,
-        "behavior": behavior,
-        "throughput": benchmark["bytes_per_second"] / 2.0 ** 20
-      })
-
-
-# Synthetic benchmark results example:
-# [
-#   "benchmarks": [
-#     {
-#       "cpu_time_ns": double,
-#       "iterations": int,
-#       "name: string,
-#       "real_time_ns: double,
-#       ...
-#     },
-#     ...
-#   ],
-#   ...
-# ]
-def __parse_synthetic_result(filename):
-  if filename == "":
-    return
-  if filename[0] != "/":
-    filename = os.path.dirname(os.path.abspath(__file__)) + "/" + filename
-  with open(filename, encoding="utf-8") as f:
-    results = json.loads(f.read())
-    for benchmark in results["benchmarks"]:
-      __results.append({
-          "language": "cpp",
-          "dataFilename": "",
-          "behavior": "synthetic",
-          "throughput": 10.0**9 / benchmark["cpu_time_ns"]
-      })
-
-
-# Python results example:
-# [
-#   [
-#     {
-#       "filename": string,
-#       "benchmarks": {
-#         behavior: results,
-#         ...
-#       },
-#     },
-#     ...
-#   ], #pure-python
-#   ...
-# ]
-def __parse_python_result(filename):
-  if filename == "":
-    return
-  if filename[0] != '/':
-    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
-  with open(filename, encoding="utf-8") as f:
-    results_list = json.loads(f.read())
-    for results in results_list:
-      for result in results:
-        _, avg_size = __get_data_size(result["filename"])
-        for behavior in result["benchmarks"]:
-          __results.append({
-            "language": "python",
-            "dataFilename": __extract_file_name(result["filename"]),
-            "behavior": behavior,
-            "throughput": result["benchmarks"][behavior]
-          })
-
-
-# Java results example:
-# [
-#   {
-#     "id": string,
-#     "instrumentSpec": {...},
-#     "measurements": [
-#       {
-#         "weight": float,
-#         "value": {
-#           "magnitude": float,
-#           "unit": string
-#         },
-#         ...
-#       },
-#       ...
-#     ],
-#     "run": {...},
-#     "scenario": {
-#       "benchmarkSpec": {
-#         "methodName": string,
-#         "parameters": {
-#            defined parameters in the benchmark: parameters value
-#         },
-#         ...
-#       },
-#       ...
-#     }
-#
-#   },
-#   ...
-# ]
-def __parse_java_result(filename):
-  if filename == "":
-    return
-  if filename[0] != '/':
-    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
-  with open(filename, encoding="utf-8") as f:
-    results = json.loads(f.read())
-    for result in results:
-      total_weight = 0
-      total_value = 0
-      for measurement in result["measurements"]:
-        total_weight += measurement["weight"]
-        total_value += measurement["value"]["magnitude"]
-      avg_time = total_value * 1.0 / total_weight
-      total_size, _ = __get_data_size(
-          result["scenario"]["benchmarkSpec"]["parameters"]["dataFile"])
-      __results.append({
-        "language": "java",
-        "throughput": total_size / avg_time * 1e9 / 2 ** 20,
-        "behavior": result["scenario"]["benchmarkSpec"]["methodName"],
-        "dataFilename": __extract_file_name(
-            result["scenario"]["benchmarkSpec"]["parameters"]["dataFile"])
-      })
-
-
-# Go benchmark results:
-#
-# goos: linux
-# goarch: amd64
-# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Unmarshal-12               3000      705784 ns/op
-# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Marshal-12                 2000      634648 ns/op
-# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Size-12                    5000      244174 ns/op
-# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Clone-12                    300     4120954 ns/op
-# Benchmark/.././datasets/google_message2/dataset.google_message2.pb/Merge-12                    300     4108632 ns/op
-# PASS
-# ok    _/usr/local/google/home/yilunchong/mygit/protobuf/benchmarks  124.173s
-def __parse_go_result(filename):
-  if filename == "":
-    return
-  if filename[0] != '/':
-    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
-  with open(filename, encoding="utf-8") as f:
-    for line in f:
-      result_list = re.split(r"[\ \t]+", line)
-      if result_list[0][:9] != "Benchmark":
-        continue
-      first_slash_index = result_list[0].find('/')
-      last_slash_index = result_list[0].rfind('/')
-      full_filename = result_list[0][first_slash_index+1:last_slash_index]
-      total_bytes, _ = __get_data_size(full_filename)
-      behavior_with_suffix = result_list[0][last_slash_index+1:]
-      last_dash = behavior_with_suffix.rfind("-")
-      if last_dash == -1:
-        behavior = behavior_with_suffix
-      else:
-        behavior = behavior_with_suffix[:last_dash]
-      __results.append({
-        "dataFilename": __extract_file_name(full_filename),
-        "throughput": total_bytes / float(result_list[2]) * 1e9 / 2 ** 20,
-        "behavior": behavior,
-        "language": "go"
-      })
-
-
-# Self built json results example:
-#
-# [
-#   {
-#     "filename": string,
-#     "benchmarks": {
-#       behavior: results,
-#       ...
-#     },
-#   },
-#   ...
-# ]
-def __parse_custom_result(filename, language):
-  if filename == "":
-    return
-  if filename[0] != '/':
-    filename = os.path.dirname(os.path.abspath(__file__)) + '/' + filename
-  with open(filename, encoding="utf-8") as f:
-    results = json.loads(f.read())
-    for result in results:
-      _, avg_size = __get_data_size(result["filename"])
-      for behavior in result["benchmarks"]:
-        __results.append({
-          "language": language,
-          "dataFilename": __extract_file_name(result["filename"]),
-          "behavior": behavior,
-          "throughput": result["benchmarks"][behavior]
-        })
-
-
-def __parse_js_result(filename, language):
-  return __parse_custom_result(filename, language)
-
-def __parse_php_result(filename, language):
-  return __parse_custom_result(filename, language)
-
-
-def get_result_from_file(cpp_file="",
-                         java_file="",
-                         python_file="",
-                         go_file="",
-                         synthetic_file="",
-                         node_file="",
-                         php_c_file="",
-                         php_file=""):
-  results = {}
-  if cpp_file != "":
-    __parse_cpp_result(cpp_file)
-  if java_file != "":
-    __parse_java_result(java_file)
-  if python_file != "":
-    __parse_python_result(python_file)
-  if go_file != "":
-    __parse_go_result(go_file)
-  if synthetic_file != "":
-    __parse_synthetic_result(synthetic_file)
-  if node_file != "":
-    __parse_js_result(node_file, "node")
-  if php_file != "":
-    __parse_php_result(php_file, "php")
-  if php_c_file != "":
-    __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/benchmarks/util/result_uploader.py b/benchmarks/util/result_uploader.py
deleted file mode 100644
index 2a35d96..0000000
--- a/benchmarks/util/result_uploader.py
+++ /dev/null
@@ -1,107 +0,0 @@
-from __future__ import print_function
-from __future__ import absolute_import
-import argparse
-import os
-import re
-import copy
-import uuid
-import calendar
-import time
-import datetime
-
-from util import big_query_utils
-from util import result_parser
-
-_PROJECT_ID = 'grpc-testing'
-_DATASET = 'protobuf_benchmark_result'
-_TABLE = 'opensource_result_v2'
-_NOW = "%d%02d%02d" % (datetime.datetime.now().year,
-                       datetime.datetime.now().month,
-                       datetime.datetime.now().day)
-
-_INITIAL_TIME = calendar.timegm(time.gmtime())
-
-def get_metadata():
-  build_number = os.getenv('BUILD_NUMBER')
-  build_url = os.getenv('BUILD_URL')
-  job_name = os.getenv('JOB_NAME')
-  git_commit = os.getenv('GIT_COMMIT')
-  # actual commit is the actual head of PR that is getting tested
-  git_actual_commit = os.getenv('ghprbActualCommit')
-
-  utc_timestamp = str(calendar.timegm(time.gmtime()))
-  metadata = {'created': utc_timestamp}
-
-  if build_number:
-    metadata['buildNumber'] = build_number
-  if build_url:
-    metadata['buildUrl'] = build_url
-  if job_name:
-    metadata['jobName'] = job_name
-  if git_commit:
-    metadata['gitCommit'] = git_commit
-  if git_actual_commit:
-    metadata['gitActualCommit'] = git_actual_commit
-
-  return metadata
-
-
-def upload_result(result_list, metadata):
-  for result in result_list:
-    new_result = {}
-    new_result["metric"] = "throughput"
-    new_result["value"] = result["throughput"]
-    new_result["unit"] = "MB/s"
-    new_result["test"] = "protobuf_benchmark"
-    new_result["product_name"] = "protobuf"
-    labels_string = ""
-    for key in result:
-      labels_string += ",|%s:%s|" % (key, result[key])
-    new_result["labels"] = labels_string[1:]
-    new_result["timestamp"] = _INITIAL_TIME
-    print(labels_string)
-
-    bq = big_query_utils.create_big_query()
-    row = big_query_utils.make_row(str(uuid.uuid4()), new_result)
-    if not big_query_utils.insert_rows(bq, _PROJECT_ID, _DATASET,
-                                        _TABLE + "$" + _NOW,
-                                        [row]):
-      print('Error when uploading result', new_result)
-
-
-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()
-
-  metadata = get_metadata()
-  print("uploading results...")
-  upload_result(result_parser.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,
-  ), metadata)
diff --git a/benchmarks/util/schema_proto2_to_proto3_util.h b/benchmarks/util/schema_proto2_to_proto3_util.h
deleted file mode 100644
index 0079f6f..0000000
--- a/benchmarks/util/schema_proto2_to_proto3_util.h
+++ /dev/null
@@ -1,194 +0,0 @@
-#ifndef PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_
-#define PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_
-
-#include "google/protobuf/message.h"
-#include "google/protobuf/descriptor.h"
-#include "google/protobuf/descriptor.pb.h"
-
-#include <sstream>
-#include <algorithm>
-
-using google::protobuf::Descriptor;
-using google::protobuf::DescriptorProto;
-using google::protobuf::FileDescriptorProto;
-using google::protobuf::FieldDescriptorProto;
-using google::protobuf::Message;
-using google::protobuf::EnumValueDescriptorProto;
-
-namespace google {
-namespace protobuf {
-namespace util {
-
-class SchemaGroupStripper {
-
- public:
-  static void StripFile(const FileDescriptor* old_file,
-                        FileDescriptorProto *file) {
-    for (int i = file->mutable_message_type()->size() - 1; i >= 0; i--) {
-      if (IsMessageSet(old_file->message_type(i))) {
-        file->mutable_message_type()->DeleteSubrange(i, 1);
-        continue;
-      }
-      StripMessage(old_file->message_type(i), file->mutable_message_type(i));
-    }
-    for (int i = file->mutable_extension()->size() - 1; i >= 0; i--) {
-      auto field = old_file->extension(i);
-      if (field->type() == FieldDescriptor::TYPE_GROUP ||
-          IsMessageSet(field->message_type()) ||
-          IsMessageSet(field->containing_type())) {
-        file->mutable_extension()->DeleteSubrange(i, 1);
-      }
-    }
-  }
-
- private:
-  static bool IsMessageSet(const Descriptor *descriptor) {
-    if (descriptor != nullptr
-        && descriptor->options().message_set_wire_format()) {
-      return true;
-    }
-    return false;
-  }
-
-  static void StripMessage(const Descriptor *old_message,
-                           DescriptorProto *new_message) {
-    for (int i = new_message->mutable_field()->size() - 1; i >= 0; i--) {
-      if (old_message->field(i)->type() == FieldDescriptor::TYPE_GROUP ||
-          IsMessageSet(old_message->field(i)->message_type())) {
-        new_message->mutable_field()->DeleteSubrange(i, 1);
-      }
-    }
-    for (int i = new_message->mutable_extension()->size() - 1; i >= 0; i--) {
-      auto field_type_name = new_message->mutable_extension(i)->type_name();
-      if (old_message->extension(i)->type() == FieldDescriptor::TYPE_GROUP ||
-          IsMessageSet(old_message->extension(i)->containing_type()) ||
-          IsMessageSet(old_message->extension(i)->message_type())) {
-        new_message->mutable_extension()->DeleteSubrange(i, 1);
-      }
-    }
-    for (int i = 0; i < new_message->mutable_nested_type()->size(); i++) {
-      StripMessage(old_message->nested_type(i),
-                   new_message->mutable_nested_type(i));
-    }
-  }
-
-};
-
-class EnumScrubber {
-
- public:
-  EnumScrubber()
-      : total_added_(0) {
-  }
-
-  void ScrubFile(FileDescriptorProto *file) {
-    for (int i = 0; i < file->enum_type_size(); i++) {
-      ScrubEnum(file->mutable_enum_type(i));
-    }
-    for (int i = 0; i < file->mutable_message_type()->size(); i++) {
-      ScrubMessage(file->mutable_message_type(i));
-    }
-  }
-
- private:
-  void ScrubEnum(EnumDescriptorProto *enum_type) {
-    if (enum_type->value(0).number() != 0) {
-      bool has_zero = false;
-      for (int j = 0; j < enum_type->value().size(); j++) {
-        if (enum_type->value(j).number() == 0) {
-          EnumValueDescriptorProto temp_enum_value;
-          temp_enum_value.CopyFrom(enum_type->value(j));
-          enum_type->mutable_value(j)->CopyFrom(enum_type->value(0));
-          enum_type->mutable_value(0)->CopyFrom(temp_enum_value);
-          has_zero = true;
-          break;
-        }
-      }
-      if (!has_zero) {
-        enum_type->mutable_value()->Add();
-        for (int i = enum_type->mutable_value()->size() - 1; i > 0; i--) {
-          enum_type->mutable_value(i)->CopyFrom(
-              *enum_type->mutable_value(i - 1));
-        }
-        enum_type->mutable_value(0)->set_number(0);
-        enum_type->mutable_value(0)->set_name("ADDED_ZERO_VALUE_" +
-                                              std::to_string(total_added_++));
-      }
-    }
-
-  }
-
-  void ScrubMessage(DescriptorProto *message_type) {
-    for (int i = 0; i < message_type->mutable_enum_type()->size(); i++) {
-      ScrubEnum(message_type->mutable_enum_type(i));
-    }
-    for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) {
-      ScrubMessage(message_type->mutable_nested_type(i));
-    }
-  }
-
-  int total_added_;
-};
-
-class ExtensionStripper {
- public:
-  static void StripFile(FileDescriptorProto *file) {
-    for (int i = 0; i < file->mutable_message_type()->size(); i++) {
-      StripMessage(file->mutable_message_type(i));
-    }
-    file->mutable_extension()->Clear();
-  }
- private:
-  static void StripMessage(DescriptorProto *message_type) {
-    message_type->mutable_extension()->Clear();
-    message_type->clear_extension_range();
-    for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) {
-      StripMessage(message_type->mutable_nested_type(i));
-    }
-  }
-};
-
-
-class FieldScrubber {
- public:
-  static void ScrubFile(FileDescriptorProto *file) {
-    for (int i = 0; i < file->mutable_message_type()->size(); i++) {
-      ScrubMessage(file->mutable_message_type(i));
-    }
-    for (int i = 0; i < file->mutable_extension()->size(); i++) {
-      file->mutable_extension(i)->clear_default_value();
-      if (ShouldClearLabel(file->mutable_extension(i))) {
-        file->mutable_extension(i)->clear_label();
-      }
-    }
-  }
- private:
-  static bool ShouldClearLabel(const FieldDescriptorProto *field) {
-    return field->label() == FieldDescriptorProto::LABEL_REQUIRED;
-  }
-
-  static void ScrubMessage(DescriptorProto *message_type) {
-    message_type->mutable_extension()->Clear();
-    for (int i = 0; i < message_type->mutable_extension()->size(); i++) {
-      message_type->mutable_extension(i)->clear_default_value();
-      if (ShouldClearLabel(message_type->mutable_extension(i))) {
-        message_type->mutable_extension(i)->clear_label();
-      }
-    }
-    for (int i = 0; i < message_type->mutable_field()->size(); i++) {
-      message_type->mutable_field(i)->clear_default_value();
-      if (ShouldClearLabel(message_type->mutable_field(i))) {
-        message_type->mutable_field(i)->clear_label();
-      }
-    }
-    for (int i = 0; i < message_type->mutable_nested_type()->size(); i++) {
-      ScrubMessage(message_type->mutable_nested_type(i));
-    }
-  }
-};
-
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // PROTOBUF_BENCHMARKS_UTIL_SCHEMA_PROTO2_TO_PROTO3_UTIL_H_
diff --git a/build_defs/BUILD.bazel b/build_defs/BUILD.bazel
index a5d831c..4ac09c8 100644
--- a/build_defs/BUILD.bazel
+++ b/build_defs/BUILD.bazel
@@ -17,6 +17,16 @@
     value = "msvc-cl",
 )
 
+config_setting(
+    name = "aarch64",
+    values = {"cpu": "linux-aarch_64"},
+)
+
+config_setting(
+    name = "x86_64",
+    values = {"cpu": "linux-x86_64"},
+)
+
 # Android NDK builds can specify different crosstool_top flags to choose which
 # STL they use for C++. We need these multiple variants to catch all of those
 # versions of crosstool_top and reliably detect Android.
diff --git a/build_defs/arch_tests.bzl b/build_defs/arch_tests.bzl
new file mode 100644
index 0000000..61fa00c
--- /dev/null
+++ b/build_defs/arch_tests.bzl
@@ -0,0 +1,56 @@
+"""Generated unittests to verify that a binary is built for the expected architecture."""
+
+load("//build_defs:internal_shell.bzl", "inline_sh_test")
+
+def _arch_test_impl(
+        name,
+        platform,
+        file_platform,
+        bazel_binaries = [],
+        system_binaries = [],
+        **kwargs):
+    """Bazel rule to verify that a Bazel or system binary is built for the aarch64 architecture.
+
+    Args:
+      name: the name of the test.
+      platform: a diagnostic name for this architecture.
+      file_platform: the expected output of `file`.
+      bazel_binaries: a set of binary targets to inspect.
+      system_binaries: a set of paths to system executables to inspect.
+      **kwargs: other keyword arguments that are passed to the test.
+    """
+
+    inline_sh_test(
+        name = name,
+        tools = bazel_binaries,
+        cmd = """
+          for binary in "$(rootpaths %s) %s"; do
+            (file -L $$binary | grep -q "%s") \
+                || (echo "Test binary is not an %s binary: "; file -L $$binary; exit 1)
+          done
+        """ % (
+            " ".join(bazel_binaries),
+            " ".join(system_binaries),
+            file_platform,
+            platform,
+        ),
+        target_compatible_with = select({
+            "//build_defs:" + platform: [],
+            "//conditions:default": ["@platforms//:incompatible"],
+        }),
+        **kwargs
+    )
+
+def aarch64_test(**kwargs):
+    _arch_test_impl(
+        platform = "aarch64",
+        file_platform = "ELF 64-bit LSB executable, ARM aarch64",
+        **kwargs
+    )
+
+def x86_64_test(**kwargs):
+    _arch_test_impl(
+        platform = "x86_64",
+        file_platform = "ELF 64-bit LSB executable, ARM x86_64",
+        **kwargs
+    )
diff --git a/build_defs/cpp_opts.bzl b/build_defs/cpp_opts.bzl
index 1d5594d..912c19b 100644
--- a/build_defs/cpp_opts.bzl
+++ b/build_defs/cpp_opts.bzl
@@ -1,4 +1,4 @@
-# C++ compile/link options for Protobuf.
+"""C++ compile/link options for Protobuf libraries."""
 
 COPTS = select({
     "//build_defs:config_msvc": [
@@ -19,6 +19,7 @@
         "-DHAVE_ZLIB",
         "-Woverloaded-virtual",
         "-Wno-sign-compare",
+        "-Werror",
     ],
 })
 
diff --git a/build_defs/internal_shell.bzl b/build_defs/internal_shell.bzl
new file mode 100644
index 0000000..670c4d5
--- /dev/null
+++ b/build_defs/internal_shell.bzl
@@ -0,0 +1,93 @@
+"""
+Internal tools to migrate shell commands to Bazel as an intermediate step
+to wider Bazelification.
+"""
+
+def inline_sh_binary(
+        name,
+        srcs = [],
+        tools = [],
+        deps = [],
+        cmd = "",
+        testonly = None,
+        **kwargs):
+    """Bazel rule to wrap up an inline bash script in a binary.
+
+    This is most useful as a stop-gap solution for migrating off Autotools.
+    These binaries are likely to be non-hermetic, with implicit system
+    dependencies.
+
+    NOTE: the rule is only an internal workaround. The interface may change and
+    the rule may be removed when everything is properly "Bazelified".
+
+    Args:
+      name: the name of the inline_sh_binary.
+      srcs: the files used directly by the script.
+      tools: the executable tools used directly by the script.  Any target used
+        with rootpath/execpath/location must be declared here or in `srcs`.
+      deps: a list of dependency labels that are required to run this binary.
+      cmd: the inline sh command to run.
+      **kwargs: other keyword arguments that are passed to sh_binary.
+      testonly: common rule attribute (see:
+          https://bazel.build/reference/be/common-definitions#common-attributes)
+    """
+
+    native.genrule(
+        name = name + "_genrule",
+        srcs = srcs,
+        exec_tools = tools,
+        outs = [name + ".sh"],
+        cmd = "cat <<'EOF' >$(OUTS)\n#!/bin/bash -exu\n%s\nEOF\n" % cmd,
+        testonly = testonly,
+        visibility = ["//visibility:private"],
+    )
+
+    native.sh_binary(
+        name = name,
+        srcs = [name + "_genrule"],
+        data = srcs + tools + deps,
+        testonly = testonly,
+        **kwargs
+    )
+
+def inline_sh_test(
+        name,
+        srcs = [],
+        tools = [],
+        deps = [],
+        cmd = "",
+        **kwargs):
+    """Bazel rule to wrap up an inline bash script in a test.
+
+    This is most useful as a stop-gap solution for migrating off Autotools.
+    These tests are likely to be non-hermetic, with implicit system dependencies.
+
+    NOTE: the rule is only an internal workaround. The interface may change and
+    the rule may be removed when everything is properly "Bazelified".
+
+    Args:
+      name: the name of the inline_sh_binary.
+      srcs: the files used directly by the script.
+      tools: the executable tools used directly by the script.  Any target used
+        with rootpath/execpath/location must be declared here or in `srcs`.
+      deps: a list of dependency labels that are required to run this binary.
+      cmd: the inline sh command to run.
+      **kwargs: other keyword arguments that are passed to sh_binary.
+          https://bazel.build/reference/be/common-definitions#common-attributes)
+    """
+
+    native.genrule(
+        name = name + "_genrule",
+        srcs = srcs,
+        exec_tools = tools,
+        outs = [name + ".sh"],
+        cmd = "cat <<'EOF' >$(OUTS)\n#!/bin/bash -exu\n%s\nEOF\n" % cmd,
+        visibility = ["//visibility:private"],
+    )
+
+    native.sh_test(
+        name = name,
+        srcs = [name + "_genrule"],
+        data = srcs + tools + deps,
+        **kwargs
+    )
diff --git a/build_files_updated_unittest.sh b/build_files_updated_unittest.sh
deleted file mode 100755
index 87541c3..0000000
--- a/build_files_updated_unittest.sh
+++ /dev/null
@@ -1,62 +0,0 @@
-#!/bin/bash
-
-# This script verifies that BUILD files and cmake files are in sync with src/Makefile.am
-
-set -eo pipefail
-
-if [ "$(uname)" != "Linux" ]; then
-  echo "build_files_updated_unittest only supported on Linux. Skipping..."
-  exit 0
-fi
-
-# Keep in sync with files needed by update_file_lists.sh
-generated_files=(
-  "BUILD"
-  "cmake/extract_includes.bat.in"
-  "cmake/libprotobuf-lite.cmake"
-  "cmake/libprotobuf.cmake"
-  "cmake/libprotoc.cmake"
-  "cmake/tests.cmake"
-  "src/Makefile.am"
-)
-
-# If we're running in Bazel, use the Bazel-provided temp-dir.
-if [ -n "${TEST_TMPDIR}" ]; then
-  # Env-var TEST_TMPDIR is set, assume that this is Bazel.
-  # Bazel may have opinions whether we are allowed to delete TEST_TMPDIR.
-  test_root="${TEST_TMPDIR}/build_files_updated_unittest"
-  mkdir "${test_root}"
-else
-  # Seems like we're not executed by Bazel.
-  test_root=$(mktemp -d)
-fi
-
-# From now on, fail if there are any unbound variables.
-set -u
-
-# Remove artifacts after test is finished.
-function cleanup {
-  rm -rf "${test_root}"
-}
-trap cleanup EXIT
-
-# Create golden dir and add snapshot of current state.
-golden_dir="${test_root}/golden"
-mkdir -p "${golden_dir}/cmake" "${golden_dir}/src"
-for file in ${generated_files[@]}; do
-  cp "${file}" "${golden_dir}/${file}"
-done
-
-# Create test dir, copy current state into it, and execute update script.
-test_dir="${test_root}/test"
-cp -R "${golden_dir}" "${test_dir}"
-
-cp "update_file_lists.sh" "${test_dir}/update_file_lists.sh"
-chmod +x "${test_dir}/update_file_lists.sh"
-cd "${test_root}/test"
-bash "${test_dir}/update_file_lists.sh"
-
-# Test whether there are any differences
-for file in ${generated_files[@]}; do
-  diff -du "${golden_dir}/${file}" "${test_dir}/${file}"
-done
diff --git a/cmake/README.md b/cmake/README.md
index ce3e680..396d495 100644
--- a/cmake/README.md
+++ b/cmake/README.md
@@ -1,15 +1,21 @@
-This directory contains *CMake* files that can be used to build protobuf
-with *MSVC* on *Windows*. You can build the project from *Command Prompt*
-and using an *Visual Studio* IDE.
+This directory contains *CMake* files that can be used to build protobuf.
 
-You need to have [CMake](http://www.cmake.org), [Visual Studio](https://www.visualstudio.com)
-and optionally [Git](http://git-scm.com) installed on your computer before proceeding.
+You need to have [CMake](http://www.cmake.org) and
+[Git](http://git-scm.com) installed on your computer before proceeding.  We
+currently support CMake 3.5 and newer on both [Windows](#windows-builds) and
+[Linux](#linux-builds).
 
-Most of the instructions will be given to the *Сommand Prompt*, but the same
-actions can be performed using appropriate GUI tools.
+Most of the instructions will be given using CMake's command-line interface, but
+the same actions can be performed using appropriate GUI tools.
 
-Environment Setup
-=================
+# Windows Builds
+
+On Windows, you can build the project from *Command Prompt* and using an
+*Visual Studio* IDE.  You will also need to have
+[Visual Studio](https://www.visualstudio.com) installed on your computer before
+proceeding.
+
+## Environment Setup
 
 Open the appropriate *Command Prompt* from the *Start* menu.
 
@@ -42,8 +48,7 @@
 
 Good. Now you are ready to continue.
 
-Getting Sources
-===============
+## Getting Sources
 
 You can get the latest stable source packages from the release page:
 
@@ -76,8 +81,7 @@
 
 Good. Now you are ready for *CMake* configuration.
 
-CMake Configuration
-===================
+## CMake Configuration
 
 *CMake* supports a lot of different
 [generators](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html)
@@ -85,9 +89,6 @@
 
 Of most interest to Windows programmers are the following:
 
-* [Makefile](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#makefile-generators).
-  This generates NMake Makefiles for Visual Studio. These work, but they are rather slow.
-
 * [Visual Studio](http://www.cmake.org/cmake/help/latest/manual/cmake-generators.7.html#visual-studio-generators)
   This generates a Visual Studio solution for the project.
 
@@ -108,16 +109,6 @@
 The *Makefile* and *Ninja* generators can build the project in only one configuration, so you need to build
 a separate folder for each configuration.
 
-To start using a *Release* configuration via the *NMmake* generator:
-
-     C:\Path\to\build\protobuf>mkdir release & cd release
-     C:\Path\to\build\protobuf\release>cmake -G "NMake Makefiles" ^
-     -DCMAKE_BUILD_TYPE=Release ^
-     -DCMAKE_INSTALL_PREFIX=C:\Path\to\install ^
-     C:\Path\to\src\protobuf
-
-It will generate a *NMake* *Makefile* in the current directory.
-
 To use *Debug* configuration using *Ninja*:
 
      C:\Path\to\build\protobuf>mkdir debug & cd debug
@@ -137,8 +128,7 @@
 
 It will generate *Visual Studio* solution file *protobuf.sln* in current directory.
 
-Unit Tests
-----------
+### Unit Tests
 
 Unit tests are being built along with the rest of protobuf. The unit tests require Google Mock (now a part of Google Test).
 
@@ -178,8 +168,7 @@
      -Dprotobuf_BUILD_TESTS=OFF ^
      C:\Path\to\src\protobuf
 
-Compiling
-=========
+## Compiling
 
 The standard way to compile a *CMake* project is `cmake --build <directory>`.
 
@@ -190,10 +179,6 @@
 
 You can also run directly the build tool you've configured:
 
-     C:\Path\to\build\protobuf\release>nmake
-
-or
-
      C:\Path\to\build\protobuf\debug>ninja
 
 And wait for the compilation to finish.
@@ -206,8 +191,7 @@
 
 And wait for the compilation to finish.
 
-Testing
-=======
+## Testing
 
 To run unit-tests, first you must compile protobuf as described above.
 Then run:
@@ -259,8 +243,7 @@
 
 If all tests are passed, safely continue.
 
-Installing
-==========
+## Installing
 
 To install protobuf to the *install* folder you've specified in the configuration step, you need to build the `install` target:
 
@@ -268,10 +251,6 @@
 
 Or if you prefer:
 
-     C:\Path\to\build\protobuf\release>nmake install
-
-or
-
      C:\Path\to\build\protobuf\debug>ninja install
 
 You can also build project *INSTALL* from Visual Studio solution.
@@ -292,8 +271,7 @@
 debug build of libprotobufd.lib with "d" postfix.  Similarly, release builds should link against
 release libprotobuf.lib library.
 
-DLLs vs. static linking
-=======================
+## DLLs vs. static linking
 
 Static linking is now the default for the Protocol Buffer libraries.  Due to
 issues with Win32's use of a separate heap for each DLL, as well as binary
@@ -318,8 +296,7 @@
 public interface, and that you statically link protocol buffers into your
 library.
 
-ZLib support
-============
+## ZLib support
 
 If you want to include GzipInputStream and GzipOutputStream
 (google/protobuf/io/gzip_stream.h) in libprotobuf, you will need to do a few
@@ -369,8 +346,7 @@
 
 Build and testing protobuf as usual.
 
-Notes on Compiler Warnings
-==========================
+## Notes on Compiler Warnings
 
 The following warnings have been disabled while building the protobuf libraries
 and compiler.  You may have to disable some of them in your own project as
@@ -397,3 +373,23 @@
 nevertheless.  So, we disable it.  Unfortunately, this warning will also be
 produced when compiling code which merely uses protocol buffers, meaning you
 may have to disable it in your code too.
+
+# Linux Builds
+
+Building with CMake works very similarly on Linux.  Instead of Visual Studio,
+you will need to have gcc or clang installed to handle the C++ builds.  CMake
+will generate Makefiles by default, but can also be configured to use Ninja.  To
+build Protobuf, you will need to run (from the source directory):
+
+     cmake .
+     cmake --build . --parallel 10
+
+Protobuf can be tested and installed with CMake:
+
+     ctest --verbose
+     sudo cmake --install .
+
+or directly with the generated Makefiles:
+
+     make VERBOSE=1 test
+     sudo make install
diff --git a/cmake/abseil-cpp.cmake b/cmake/abseil-cpp.cmake
new file mode 100644
index 0000000..523517c
--- /dev/null
+++ b/cmake/abseil-cpp.cmake
@@ -0,0 +1,70 @@
+# Setup our dependency on Abseil.
+
+set(ABSL_PROPAGATE_CXX_STD ON)
+
+if(TARGET absl::strings)
+  # If Abseil is included already, skip including it.
+  # (https://github.com/protocolbuffers/protobuf/issues/10435)
+elseif(protobuf_ABSL_PROVIDER STREQUAL "module")
+  if(NOT ABSL_ROOT_DIR)
+    set(ABSL_ROOT_DIR ${CMAKE_CURRENT_SOURCE_DIR}/third_party/abseil-cpp)
+  endif()
+  if(EXISTS "${ABSL_ROOT_DIR}/CMakeLists.txt")
+    if(protobuf_INSTALL)
+      # When protobuf_INSTALL is enabled and Abseil will be built as a module,
+      # Abseil will be installed along with protobuf for convenience.
+      set(ABSL_ENABLE_INSTALL ON)
+    endif()
+    add_subdirectory(${ABSL_ROOT_DIR} third_party/abseil-cpp)
+  else()
+    message(WARNING "protobuf_ABSL_PROVIDER is \"module\" but ABSL_ROOT_DIR is wrong")
+  endif()
+  if(protobuf_INSTALL AND NOT _protobuf_INSTALL_SUPPORTED_FROM_MODULE)
+    message(WARNING "protobuf_INSTALL will be forced to FALSE because protobuf_ABSL_PROVIDER is \"module\" and CMake version (${CMAKE_VERSION}) is less than 3.13.")
+    set(protobuf_INSTALL FALSE)
+  endif()
+elseif(protobuf_ABSL_PROVIDER STREQUAL "package")
+  # Use "CONFIG" as there is no built-in cmake module for absl.
+  find_package(absl REQUIRED CONFIG)
+endif()
+set(_protobuf_FIND_ABSL "if(NOT TARGET absl::strings)\n  find_package(absl CONFIG)\nendif()")
+
+if (BUILD_SHARED_LIBS AND MSVC)
+  # On MSVC Abseil is bundled into a single DLL.
+  set(protobuf_ABSL_USED_TARGETS abseil_dll)
+
+  # As a workaround for https://github.com/abseil/abseil-cpp/issues/1118,
+  # make sure ABSL_CONSUME_DLL gets set for all subsequent builds.
+  add_definitions(-DABSL_CONSUME_DLL)
+else()
+  set(protobuf_ABSL_USED_TARGETS
+    absl::algorithm
+    absl::base
+    absl::bind_front
+    absl::bits
+    absl::btree
+    absl::cleanup
+    absl::cord
+    absl::core_headers
+    absl::debugging
+    absl::dynamic_annotations
+    absl::flags
+    absl::flat_hash_map
+    absl::flat_hash_set
+    absl::function_ref
+    absl::hash
+    absl::layout
+    absl::memory
+    absl::node_hash_map
+    absl::node_hash_set
+    absl::optional
+    absl::span
+    absl::status
+    absl::statusor
+    absl::strings
+    absl::synchronization
+    absl::time
+    absl::utility
+    absl::variant
+  )
+endif ()
\ No newline at end of file
diff --git a/cmake/conformance.cmake b/cmake/conformance.cmake
index d6c435a..61ac25a 100644
--- a/cmake/conformance.cmake
+++ b/cmake/conformance.cmake
@@ -1,6 +1,18 @@
 
+if (NOT EXISTS "${protobuf_SOURCE_DIR}/third_party/jsoncpp/CMakeLists.txt")
+  message(FATAL_ERROR
+          "Cannot find third_party/jsoncpp directory that's needed to "
+          "build conformance tests. If you use git, make sure you have cloned "
+          "submodules:\n"
+          "  git submodule update --init --recursive\n"
+          "If instead you want to skip them, run cmake with:\n"
+          "  cmake -Dprotobuf_BUILD_CONFORMANCE=OFF\n")
+endif()
+
 add_custom_command(
-  OUTPUT ${protobuf_SOURCE_DIR}/conformance/conformance.pb.cc
+  OUTPUT
+    ${protobuf_SOURCE_DIR}/conformance/conformance.pb.h
+    ${protobuf_SOURCE_DIR}/conformance/conformance.pb.cc
   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
@@ -8,8 +20,11 @@
 )
 
 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
+  OUTPUT
+    ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.h
+    ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
+    ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.h
+    ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
   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
@@ -21,29 +36,54 @@
 add_executable(conformance_test_runner
   ${protobuf_SOURCE_DIR}/conformance/binary_json_conformance_suite.cc
   ${protobuf_SOURCE_DIR}/conformance/binary_json_conformance_suite.h
+  ${protobuf_SOURCE_DIR}/conformance/conformance.pb.h
   ${protobuf_SOURCE_DIR}/conformance/conformance.pb.cc
   ${protobuf_SOURCE_DIR}/conformance/conformance_test.cc
   ${protobuf_SOURCE_DIR}/conformance/conformance_test_runner.cc
-  ${protobuf_SOURCE_DIR}/conformance/third_party/jsoncpp/json.h
-  ${protobuf_SOURCE_DIR}/conformance/third_party/jsoncpp/jsoncpp.cpp
+  ${protobuf_SOURCE_DIR}/conformance/conformance_test_main.cc
+  ${protobuf_SOURCE_DIR}/conformance/text_format_conformance_suite.cc
+  ${protobuf_SOURCE_DIR}/conformance/text_format_conformance_suite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.h
   ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.h
   ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
 )
 
 add_executable(conformance_cpp
+  ${protobuf_SOURCE_DIR}/conformance/conformance.pb.h
   ${protobuf_SOURCE_DIR}/conformance/conformance.pb.cc
   ${protobuf_SOURCE_DIR}/conformance/conformance_cpp.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.h
   ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto2.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.h
   ${protobuf_SOURCE_DIR}/src/google/protobuf/test_messages_proto3.pb.cc
 )
 
 target_include_directories(
   conformance_test_runner
-  PUBLIC ${protobuf_SOURCE_DIR}/conformance)
+  PUBLIC ${protobuf_SOURCE_DIR} ${protobuf_SOURCE_DIR}/conformance)
 
 target_include_directories(
   conformance_cpp
-  PUBLIC ${protobuf_SOURCE_DIR}/conformance)
+  PUBLIC ${protobuf_SOURCE_DIR})
 
-target_link_libraries(conformance_test_runner libprotobuf)
-target_link_libraries(conformance_cpp libprotobuf)
+target_include_directories(conformance_test_runner PRIVATE ${ABSL_ROOT_DIR})
+target_include_directories(conformance_cpp PRIVATE ${ABSL_ROOT_DIR})
+
+target_link_libraries(conformance_test_runner ${protobuf_LIB_PROTOBUF})
+target_link_libraries(conformance_test_runner ${protobuf_ABSL_USED_TARGETS})
+target_link_libraries(conformance_cpp ${protobuf_LIB_PROTOBUF})
+target_link_libraries(conformance_cpp ${protobuf_ABSL_USED_TARGETS})
+
+add_test(NAME conformance_cpp_test
+  COMMAND ${CMAKE_RUNTIME_OUTPUT_DIRECTORY}/conformance_test_runner
+    --failure_list ${protobuf_SOURCE_DIR}/conformance/failure_list_cpp.txt
+    --text_format_failure_list ${protobuf_SOURCE_DIR}/conformance/text_format_failure_list_cpp.txt
+    --output_dir ${protobuf_TEST_XML_OUTDIR}
+    ${CMAKE_CURRENT_BINARY_DIR}/conformance_cpp
+  DEPENDS conformance_test_runner conformance_cpp)
+
+set(JSONCPP_WITH_TESTS OFF CACHE BOOL "Disable tests")
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/jsoncpp third_party/jsoncpp)
+target_include_directories(conformance_test_runner PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/jsoncpp/include)
+target_link_libraries(conformance_test_runner jsoncpp_lib)
diff --git a/cmake/examples.cmake b/cmake/examples.cmake
index 3b83d2b..07cfad2 100644
--- a/cmake/examples.cmake
+++ b/cmake/examples.cmake
@@ -30,7 +30,7 @@
 # Add examples as an external project.
 # sub_directory cannot be used because the find_package(protobuf) call would cause failures with redefined targets.
 add_examples_build(examples "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}")
-add_dependencies(examples libprotobuf protoc)
+add_dependencies(examples ${protobuf_LIB_PROTOBUF} ${protobuf_PROTOC_EXE})
 
 option(protobuf_BUILD_EXAMPLES_MULTITEST "Build Examples in multiple configurations. Useful for testing." OFF)
 mark_as_advanced(protobuf_BUILD_EXAMPLES_MULTITEST)
@@ -42,7 +42,7 @@
     "-Dprotobuf_DIR:PATH=${CMAKE_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}"
     "-Dprotobuf_MODULE_COMPATIBLE:BOOL=TRUE"
   )
-  add_dependencies(examples-legacy libprotobuf protoc)
+  add_dependencies(examples-legacy ${protobuf_LIB_PROTOBUF} ${protobuf_PROTOC_EXE})
 
   #Build using the installed library.
   add_examples_build(examples-installed
diff --git a/cmake/extract_includes.bat.in b/cmake/extract_includes.bat.in
deleted file mode 100644
index 1292829..0000000
--- a/cmake/extract_includes.bat.in
+++ /dev/null
@@ -1,144 +0,0 @@
-mkdir include
-mkdir include\google
-mkdir include\google\protobuf
-mkdir include\google\protobuf\compiler
-mkdir include\google\protobuf\compiler\cpp
-mkdir include\google\protobuf\compiler\csharp
-mkdir include\google\protobuf\compiler\java
-mkdir include\google\protobuf\compiler\objectivec
-mkdir include\google\protobuf\compiler\php
-mkdir include\google\protobuf\compiler\python
-mkdir include\google\protobuf\compiler\ruby
-mkdir include\google\protobuf\io
-mkdir include\google\protobuf\stubs
-mkdir include\google\protobuf\util
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.h" include\google\protobuf\any.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.pb.h" include\google\protobuf\any.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.pb.h" include\google\protobuf\api.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena.h" include\google\protobuf\arena.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arena_impl.h" include\google\protobuf\arena_impl.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenastring.h" include\google\protobuf\arenastring.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\arenaz_sampler.h" include\google\protobuf\arenaz_sampler.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\code_generator.h" include\google\protobuf\compiler\code_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\command_line_interface.h" include\google\protobuf\compiler\command_line_interface.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\file.h" include\google\protobuf\compiler\cpp\file.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\cpp_generator.h" include\google\protobuf\compiler\cpp\cpp_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\generator.h" include\google\protobuf\compiler\cpp\generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\helpers.h" include\google\protobuf\compiler\cpp\helpers.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\cpp\names.h" include\google\protobuf\compiler\cpp\names.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_doc_comment.h" include\google\protobuf\compiler\csharp\csharp_doc_comment.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\csharp\csharp_generator.h" include\google\protobuf\compiler\csharp\csharp_generator.h
-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\csharp\csharp_options.h" include\google\protobuf\compiler\csharp\csharp_options.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\generator.h" include\google\protobuf\compiler\java\generator.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\kotlin_generator.h" include\google\protobuf\compiler\java\kotlin_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\java\names.h" include\google\protobuf\compiler\java\names.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_generator.h" include\google\protobuf\compiler\objectivec\objectivec_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\objectivec\objectivec_helpers.h" include\google\protobuf\compiler\objectivec\objectivec_helpers.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\parser.h" include\google\protobuf\compiler\parser.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\php\php_generator.h" include\google\protobuf\compiler\php\php_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.h" include\google\protobuf\compiler\plugin.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.pb.h" include\google\protobuf\compiler\plugin.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\generator.h" include\google\protobuf\compiler\python\generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\pyi_generator.h" include\google\protobuf\compiler\python\pyi_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\python\python_generator.h" include\google\protobuf\compiler\python\python_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\ruby\ruby_generator.h" include\google\protobuf\compiler\ruby\ruby_generator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.h" include\google\protobuf\descriptor.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.pb.h" include\google\protobuf\descriptor.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor_database.h" include\google\protobuf\descriptor_database.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.pb.h" include\google\protobuf\duration.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\dynamic_message.h" include\google\protobuf\dynamic_message.h
-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\endian.h" include\google\protobuf\endian.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\explicitly_constructed.h" include\google\protobuf\explicitly_constructed.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_bases.h" include\google\protobuf\generated_message_bases.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_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_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
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\printer.h" include\google\protobuf\io\printer.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\strtod.h" include\google\protobuf\io\strtod.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\tokenizer.h" include\google\protobuf\io\tokenizer.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream.h" include\google\protobuf\io\zero_copy_stream.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl.h" include\google\protobuf\io\zero_copy_stream_impl.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\io\zero_copy_stream_impl_lite.h" include\google\protobuf\io\zero_copy_stream_impl_lite.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map.h" include\google\protobuf\map.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry.h" include\google\protobuf\map_entry.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_entry_lite.h" include\google\protobuf\map_entry_lite.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field.h" include\google\protobuf\map_field.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_inl.h" include\google\protobuf\map_field_inl.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_field_lite.h" include\google\protobuf\map_field_lite.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\map_type_handler.h" include\google\protobuf\map_type_handler.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message.h" include\google\protobuf\message.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\message_lite.h" include\google\protobuf\message_lite.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata.h" include\google\protobuf\metadata.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\metadata_lite.h" include\google\protobuf\metadata_lite.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\parse_context.h" include\google\protobuf\parse_context.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port.h" include\google\protobuf\port.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_def.inc" include\google\protobuf\port_def.inc
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\port_undef.inc" include\google\protobuf\port_undef.inc
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection.h" include\google\protobuf\reflection.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\reflection_ops.h" include\google\protobuf\reflection_ops.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_field.h" include\google\protobuf\repeated_field.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\repeated_ptr_field.h" include\google\protobuf\repeated_ptr_field.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\service.h" include\google\protobuf\service.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.pb.h" include\google\protobuf\source_context.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.pb.h" include\google\protobuf\struct.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\bytestream.h" include\google\protobuf\stubs\bytestream.h
-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\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
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\map_util.h" include\google\protobuf\stubs\map_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\mutex.h" include\google\protobuf\stubs\mutex.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\once.h" include\google\protobuf\stubs\once.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\platform_macros.h" include\google\protobuf\stubs\platform_macros.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\port.h" include\google\protobuf\stubs\port.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\status.h" include\google\protobuf\stubs\status.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stl_util.h" include\google\protobuf\stubs\stl_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\stringpiece.h" include\google\protobuf\stubs\stringpiece.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\strutil.h" include\google\protobuf\stubs\strutil.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\stubs\template_util.h" include\google\protobuf\stubs\template_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\text_format.h" include\google\protobuf\text_format.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.pb.h" include\google\protobuf\timestamp.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.pb.h" include\google\protobuf\type.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\unknown_field_set.h" include\google\protobuf\unknown_field_set.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\delimited_message_util.h" include\google\protobuf\util\delimited_message_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_comparator.h" include\google\protobuf\util\field_comparator.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\field_mask_util.h" include\google\protobuf\util\field_mask_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\json_util.h" include\google\protobuf\util\json_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\message_differencer.h" include\google\protobuf\util\message_differencer.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\time_util.h" include\google\protobuf\util\time_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver.h" include\google\protobuf\util\type_resolver.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\util\type_resolver_util.h" include\google\protobuf\util\type_resolver_util.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format.h" include\google\protobuf\wire_format.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wire_format_lite.h" include\google\protobuf\wire_format_lite.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.pb.h" include\google\protobuf\wrappers.pb.h
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\any.proto" include\google\protobuf\any.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\api.proto" include\google\protobuf\api.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\compiler\plugin.proto" include\google\protobuf\compiler\plugin.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\descriptor.proto" include\google\protobuf\descriptor.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\duration.proto" include\google\protobuf\duration.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\empty.proto" include\google\protobuf\empty.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\field_mask.proto" include\google\protobuf\field_mask.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\source_context.proto" include\google\protobuf\source_context.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\struct.proto" include\google\protobuf\struct.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\timestamp.proto" include\google\protobuf\timestamp.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\type.proto" include\google\protobuf\type.proto
-copy "${PROTOBUF_SOURCE_WIN32_PATH}\..\src\google\protobuf\wrappers.proto" include\google\protobuf\wrappers.proto
diff --git a/cmake/install.cmake b/cmake/install.cmake
index 825cb25..90230c5 100644
--- a/cmake/install.cmake
+++ b/cmake/install.cmake
@@ -43,106 +43,65 @@
 
 install(FILES ${CMAKE_CURRENT_BINARY_DIR}/protobuf.pc ${CMAKE_CURRENT_BINARY_DIR}/protobuf-lite.pc DESTINATION "${CMAKE_INSTALL_LIBDIR}/pkgconfig")
 
-file(STRINGS ${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in _extract_strings
-  REGEX "^copy")
-foreach(_extract_string ${_extract_strings})
-  string(REGEX REPLACE "^.* .+ include\\\\(.+)$" "\\1"
-    _header ${_extract_string})
-  string(REPLACE "\\" "/" _header ${_header})
+include(${protobuf_SOURCE_DIR}/src/file_lists.cmake)
+set(protobuf_HEADERS
+  ${libprotobuf_hdrs}
+  ${libprotoc_hdrs}
+  ${wkt_protos_files}
+  ${descriptor_proto_proto_srcs}
+  ${plugin_proto_proto_srcs}
+)
+foreach(_header ${protobuf_HEADERS})
+  string(REPLACE "${protobuf_SOURCE_DIR}/src" "" _header ${_header})
   get_filename_component(_extract_from "${protobuf_SOURCE_DIR}/src/${_header}" ABSOLUTE)
   get_filename_component(_extract_name ${_header} NAME)
   get_filename_component(_extract_to "${CMAKE_INSTALL_INCLUDEDIR}/${_header}" DIRECTORY)
-  if(EXISTS "${_extract_from}")
-    install(FILES "${_extract_from}"
-      DESTINATION "${_extract_to}"
-      COMPONENT protobuf-headers
-      RENAME "${_extract_name}")
-  else()
-    message(AUTHOR_WARNING "The file \"${_extract_from}\" is listed in "
-      "\"${protobuf_SOURCE_DIR}/cmake/extract_includes.bat.in\" "
-      "but there not exists. The file will not be installed.")
-  endif()
-endforeach()
-
-# Internal function for parsing auto tools scripts
-function(_protobuf_auto_list FILE_NAME VARIABLE)
-  file(STRINGS ${FILE_NAME} _strings)
-  set(_list)
-  foreach(_string ${_strings})
-    set(_found)
-    string(REGEX MATCH "^[ \t]*${VARIABLE}[ \t]*=[ \t]*" _found "${_string}")
-    if(_found)
-      string(LENGTH "${_found}" _length)
-      string(SUBSTRING "${_string}" ${_length} -1 _draft_list)
-      foreach(_item ${_draft_list})
-        string(STRIP "${_item}" _item)
-        list(APPEND _list "${_item}")
-      endforeach()
-    endif()
-  endforeach()
-  set(${VARIABLE} ${_list} PARENT_SCOPE)
-endfunction()
-
-# Install well-known type proto files
-_protobuf_auto_list("${protobuf_SOURCE_DIR}/src/Makefile.am" nobase_dist_proto_DATA)
-foreach(_file ${nobase_dist_proto_DATA})
-  get_filename_component(_file_from "${protobuf_SOURCE_DIR}/src/${_file}" ABSOLUTE)
-  get_filename_component(_file_name ${_file} NAME)
-  get_filename_component(_dir ${_file} DIRECTORY)
-  if(EXISTS "${_file_from}")
-    install(FILES "${_file_from}"
-      DESTINATION "${CMAKE_INSTALL_INCLUDEDIR}/${_dir}"
-      COMPONENT protobuf-protos
-      RENAME "${_file_name}")
-  else()
-    message(AUTHOR_WARNING "The file \"${_file_from}\" is listed in "
-      "\"${protobuf_SOURCE_DIR}/src/Makefile.am\" as nobase_dist_proto_DATA "
-      "but there not exists. The file will not be installed.")
-  endif()
+  install(FILES "${_extract_from}"
+    DESTINATION "${_extract_to}"
+    COMPONENT protobuf-headers
+    RENAME "${_extract_name}")
 endforeach()
 
 # Install configuration
-set(_cmakedir_desc "Directory relative to CMAKE_INSTALL to install the cmake configuration files")
+set(_install_cmakedir_desc "Directory relative to CMAKE_INSTALL to install the cmake configuration files")
+set(_build_cmakedir_desc "Directory relative to CMAKE_CURRENT_BINARY_DIR for cmake configuration files")
 set(_exampledir_desc "Directory relative to CMAKE_INSTALL_DATA to install examples")
+set(_protobuf_subdir_desc "Subdirectory in which to install cmake configuration files")
 if(NOT MSVC)
-  set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/cmake/protobuf" CACHE STRING "${_cmakedir_desc}")
+  set(protobuf_CMAKE_SUBDIR "cmake/protobuf" CACHE STRING "${_protobuf_subdir_desc}")
+  set(CMAKE_INSTALL_CMAKEDIR "${CMAKE_INSTALL_LIBDIR}/${protobuf_CMAKE_SUBDIR}" CACHE STRING "${_install_cmakedir_desc}")
   set(CMAKE_INSTALL_EXAMPLEDIR "${CMAKE_INSTALL_DATADIR}/protobuf/examples" CACHE STRING "${_exampledir_desc}")
 else()
+  set(protobuf_CMAKE_SUBDIR "cmake" CACHE STRING "${_protobuf_subdir_desc}")
   set(CMAKE_INSTALL_CMAKEDIR "cmake" CACHE STRING "${_cmakedir_desc}")
   set(CMAKE_INSTALL_EXAMPLEDIR "examples" CACHE STRING "${_exampledir_desc}")
 endif()
+set(CMAKE_BUILD_CMAKEDIR "${CMAKE_CURRENT_BINARY_DIR}/${protobuf_CMAKE_SUBDIR}" CACHE STRING "${_build_cmakedir_desc}")
+mark_as_advanced(protobuf_CMAKE_SUBDIR)
+mark_as_advanced(CMAKE_BUILD_CMAKEDIR)
 mark_as_advanced(CMAKE_INSTALL_CMAKEDIR)
 mark_as_advanced(CMAKE_INSTALL_EXAMPLEDIR)
 
 configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-config.cmake.in
-  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-config.cmake @ONLY)
+  ${CMAKE_BUILD_CMAKEDIR}/protobuf-config.cmake @ONLY)
 configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-config-version.cmake.in
-  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-config-version.cmake @ONLY)
+  ${CMAKE_BUILD_CMAKEDIR}/protobuf-config-version.cmake @ONLY)
 configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-module.cmake.in
-  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-module.cmake @ONLY)
+  ${CMAKE_BUILD_CMAKEDIR}/protobuf-module.cmake @ONLY)
 configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-options.cmake
-  ${CMAKE_INSTALL_CMAKEDIR}/protobuf-options.cmake @ONLY)
+  ${CMAKE_BUILD_CMAKEDIR}/protobuf-options.cmake @ONLY)
+configure_file(${protobuf_SOURCE_DIR}/cmake/protobuf-generate.cmake
+  ${CMAKE_BUILD_CMAKEDIR}/protobuf-generate.cmake @ONLY)
 
 # Allows the build directory to be used as a find directory.
 
-if (protobuf_BUILD_PROTOC_BINARIES)
-  export(TARGETS libprotobuf-lite libprotobuf libprotoc protoc
-    NAMESPACE protobuf::
-    FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake
-  )
-else (protobuf_BUILD_PROTOC_BINARIES)
-  export(TARGETS libprotobuf-lite libprotobuf
-    NAMESPACE protobuf::
-    FILE ${CMAKE_INSTALL_CMAKEDIR}/protobuf-targets.cmake
-  )
-endif (protobuf_BUILD_PROTOC_BINARIES)
-
 install(EXPORT protobuf-targets
   DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
   NAMESPACE protobuf::
-  COMPONENT protobuf-export)
+  COMPONENT protobuf-export
+)
 
-install(DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}/${CMAKE_INSTALL_CMAKEDIR}/
+install(DIRECTORY ${CMAKE_BUILD_CMAKEDIR}/
   DESTINATION "${CMAKE_INSTALL_CMAKEDIR}"
   COMPONENT protobuf-export
   PATTERN protobuf-targets.cmake EXCLUDE
diff --git a/cmake/libprotobuf-lite.cmake b/cmake/libprotobuf-lite.cmake
index 83e9703..9a82d92 100644
--- a/cmake/libprotobuf-lite.cmake
+++ b/cmake/libprotobuf-lite.cmake
@@ -1,93 +1,11 @@
-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/arenaz_sampler.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_tctable_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/strtod.cc
-  ${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
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/bytestream.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/int128.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/statusor.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringpiece.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringprintf.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/structurally_valid.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/time.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.cc
-)
+# CMake definitions for libprotobuf_lite (the "lite" C++ protobuf runtime).
 
-set(libprotobuf_lite_includes
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_impl.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/endian.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/explicitly_constructed.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_inl.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_decl.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_impl.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/has_bits.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/strtod.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_entry_lite.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_lite.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_type_handler.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/message_lite.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/metadata_lite.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/parse_context.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/port.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/bytestream.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/callback.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/casts.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/hash.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/logging.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/macros.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/map_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/mutex.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/once.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/platform_macros.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/port.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stl_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringpiece.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/template_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.h
-)
+include(${protobuf_SOURCE_DIR}/src/file_lists.cmake)
 
 add_library(libprotobuf-lite ${protobuf_SHARED_OR_STATIC}
-  ${libprotobuf_lite_files} ${libprotobuf_lite_includes} ${protobuf_version_rc_file})
+  ${libprotobuf_lite_srcs}
+  ${libprotobuf_lite_hdrs}
+  ${protobuf_version_rc_file})
 if(protobuf_HAVE_LD_VERSION_SCRIPT)
   if(${CMAKE_VERSION} VERSION_GREATER 3.13 OR ${CMAKE_VERSION} VERSION_EQUAL 3.13)
     target_link_options(libprotobuf-lite PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotobuf-lite.map)
@@ -105,6 +23,7 @@
   target_link_libraries(libprotobuf-lite PRIVATE log)
 endif()
 target_include_directories(libprotobuf-lite PUBLIC ${protobuf_SOURCE_DIR}/src)
+target_link_libraries(libprotobuf-lite PUBLIC ${protobuf_ABSL_USED_TARGETS})
 if(protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotobuf-lite
     PUBLIC  PROTOBUF_USE_DLLS
@@ -112,7 +31,14 @@
 endif()
 set_target_properties(libprotobuf-lite PROPERTIES
     VERSION ${protobuf_VERSION}
-    SOVERSION 32
     OUTPUT_NAME ${LIB_PREFIX}protobuf-lite
-    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
+    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}"
+    # For -fvisibility=hidden and -fvisibility-inlines-hidden
+    C_VISIBILITY_PRESET hidden
+    CXX_VISIBILITY_PRESET hidden
+    VISIBILITY_INLINES_HIDDEN ON
+)
 add_library(protobuf::libprotobuf-lite ALIAS libprotobuf-lite)
+
+target_include_directories(libprotobuf-lite PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/utf8_range)
+target_link_libraries(libprotobuf-lite PRIVATE utf8_validity)
diff --git a/cmake/libprotobuf.cmake b/cmake/libprotobuf.cmake
index 07e4bcf..2352842 100644
--- a/cmake/libprotobuf.cmake
+++ b/cmake/libprotobuf.cmake
@@ -1,106 +1,11 @@
-set(libprotobuf_files
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/duration.pb.cc
-  ${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_mask.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_bases.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_full.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/gzip_stream.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/message.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/service.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/substitute.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/text_format.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/type.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/datapiece.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/default_value_objectwriter.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/error_listener.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/field_mask_utility.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_escaping.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_objectwriter.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_stream_parser.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/object_writer.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/proto_writer.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectsource.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectwriter.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/type_info.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/utility.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.cc
-)
+# CMake definitions for libprotobuf (the "full" C++ protobuf runtime).
 
-set(libprotobuf_includes
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database.h
-  ${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_enum_reflection.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_bases.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/gzip_stream.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_entry.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_inl.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/message.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/metadata.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_internal.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/service.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.pb.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/text_format.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.pb.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/type.pb.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.h
-)
+include(${protobuf_SOURCE_DIR}/src/file_lists.cmake)
 
 add_library(libprotobuf ${protobuf_SHARED_OR_STATIC}
-  ${libprotobuf_lite_files} ${libprotobuf_files} ${libprotobuf_includes} ${protobuf_version_rc_file})
+  ${libprotobuf_srcs}
+  ${libprotobuf_hdrs}
+  ${protobuf_version_rc_file})
 if(protobuf_HAVE_LD_VERSION_SCRIPT)
   if(${CMAKE_VERSION} VERSION_GREATER 3.13 OR ${CMAKE_VERSION} VERSION_EQUAL 3.13)
     target_link_options(libprotobuf PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotobuf.map)
@@ -121,6 +26,7 @@
   target_link_libraries(libprotobuf PRIVATE log)
 endif()
 target_include_directories(libprotobuf PUBLIC ${protobuf_SOURCE_DIR}/src)
+target_link_libraries(libprotobuf PUBLIC ${protobuf_ABSL_USED_TARGETS})
 if(protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotobuf
     PUBLIC  PROTOBUF_USE_DLLS
@@ -128,7 +34,14 @@
 endif()
 set_target_properties(libprotobuf PROPERTIES
     VERSION ${protobuf_VERSION}
-    SOVERSION 32
     OUTPUT_NAME ${LIB_PREFIX}protobuf
-    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
+    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}"
+    # For -fvisibility=hidden and -fvisibility-inlines-hidden
+    C_VISIBILITY_PRESET hidden
+    CXX_VISIBILITY_PRESET hidden
+    VISIBILITY_INLINES_HIDDEN ON
+)
 add_library(protobuf::libprotobuf ALIAS libprotobuf)
+
+target_include_directories(libprotobuf PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/third_party/utf8_range)
+target_link_libraries(libprotobuf PRIVATE utf8_validity)
diff --git a/cmake/libprotoc.cmake b/cmake/libprotoc.cmake
index 15a47e5..02667c5 100644
--- a/cmake/libprotoc.cmake
+++ b/cmake/libprotoc.cmake
@@ -1,117 +1,11 @@
-set(libprotoc_files
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/extension.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/map_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/padding_optimizer.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/parse_function_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/primitive_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/service.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/string_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_field_base.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_helpers.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_map_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/context.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/file.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator_factory.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/helpers.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/name_resolver.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/service.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/shared_code_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field_lite.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_file.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_message.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.pb.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/helpers.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/pyi_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/subprocess.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/zip_writer.cc
-)
+# CMake definitions for libprotoc (the protobuf compiler library).
 
-set(libprotoc_headers
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/cpp_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/names.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_names.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_options.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/java_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/names.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/pyi_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/python_generator.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.h
-)
+include(${protobuf_SOURCE_DIR}/src/file_lists.cmake)
 
 add_library(libprotoc ${protobuf_SHARED_OR_STATIC}
-  ${libprotoc_files} ${libprotoc_headers} ${protobuf_version_rc_file})
+  ${libprotoc_srcs}
+  ${libprotoc_hdrs}
+  ${protobuf_version_rc_file})
 if(protobuf_HAVE_LD_VERSION_SCRIPT)
   if(${CMAKE_VERSION} VERSION_GREATER 3.13 OR ${CMAKE_VERSION} VERSION_EQUAL 3.13)
     target_link_options(libprotoc PRIVATE -Wl,--version-script=${protobuf_SOURCE_DIR}/src/libprotoc.map)
@@ -122,6 +16,7 @@
     LINK_DEPENDS ${protobuf_SOURCE_DIR}/src/libprotoc.map)
 endif()
 target_link_libraries(libprotoc PRIVATE libprotobuf)
+target_link_libraries(libprotoc PUBLIC ${protobuf_ABSL_USED_TARGETS})
 if(protobuf_BUILD_SHARED_LIBS)
   target_compile_definitions(libprotoc
     PUBLIC  PROTOBUF_USE_DLLS
@@ -130,7 +25,11 @@
 set_target_properties(libprotoc PROPERTIES
     COMPILE_DEFINITIONS LIBPROTOC_EXPORTS
     VERSION ${protobuf_VERSION}
-    SOVERSION 32
     OUTPUT_NAME ${LIB_PREFIX}protoc
-    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}")
+    DEBUG_POSTFIX "${protobuf_DEBUG_POSTFIX}"
+    # For -fvisibility=hidden and -fvisibility-inlines-hidden
+    C_VISIBILITY_PRESET hidden
+    CXX_VISIBILITY_PRESET hidden
+    VISIBILITY_INLINES_HIDDEN ON
+)
 add_library(protobuf::libprotoc ALIAS libprotoc)
diff --git a/cmake/protobuf-config.cmake.in b/cmake/protobuf-config.cmake.in
index 6166911..44805c7 100644
--- a/cmake/protobuf-config.cmake.in
+++ b/cmake/protobuf-config.cmake.in
@@ -3,165 +3,14 @@
 
 # Depend packages
 @_protobuf_FIND_ZLIB@
+@_protobuf_FIND_ABSL@
+@_protobuf_FIND_UTF8_RANGE@
 
 # Imported targets
 include("${CMAKE_CURRENT_LIST_DIR}/protobuf-targets.cmake")
 
-function(protobuf_generate)
-  include(CMakeParseArguments)
-
-  set(_options APPEND_PATH)
-  set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS)
-  if(COMMAND target_sources)
-    list(APPEND _singleargs TARGET)
-  endif()
-  set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS)
-
-  cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
-
-  if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
-    message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
-    return()
-  endif()
-
-  if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET)
-    message(SEND_ERROR "Error: protobuf_generate called without a target or output variable")
-    return()
-  endif()
-
-  if(NOT protobuf_generate_LANGUAGE)
-    set(protobuf_generate_LANGUAGE cpp)
-  endif()
-  string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE)
-
-  if(NOT protobuf_generate_PROTOC_OUT_DIR)
-    set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
-  endif()
-
-  if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp)
-    set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}")
-  endif()
-
-  foreach(_option ${_dll_export_decl} ${protobuf_generate_PLUGIN_OPTIONS})
-    # append comma - not using CMake lists and string replacement as users
-    # might have semicolons in options
-    if(_plugin_options)
-      set( _plugin_options "${_plugin_options},")
-    endif()
-    set(_plugin_options "${_plugin_options}${_option}")
-  endforeach()
-
-  if(protobuf_generate_PLUGIN)
-      set(_plugin "--plugin=${protobuf_generate_PLUGIN}")
-  endif()
-
-  if(NOT protobuf_generate_GENERATE_EXTENSIONS)
-    if(protobuf_generate_LANGUAGE STREQUAL cpp)
-      set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc)
-    elseif(protobuf_generate_LANGUAGE STREQUAL python)
-      set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py)
-    else()
-      message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS")
-      return()
-    endif()
-  endif()
-
-  if(protobuf_generate_TARGET)
-    get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES)
-    foreach(_file ${_source_list})
-      if(_file MATCHES "proto$")
-        list(APPEND protobuf_generate_PROTOS ${_file})
-      endif()
-    endforeach()
-  endif()
-
-  if(NOT protobuf_generate_PROTOS)
-    message(SEND_ERROR "Error: protobuf_generate could not find any .proto files")
-    return()
-  endif()
-
-  if(protobuf_generate_APPEND_PATH)
-    # Create an include path for each file specified
-    foreach(_file ${protobuf_generate_PROTOS})
-      get_filename_component(_abs_file ${_file} ABSOLUTE)
-      get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
-      list(FIND _protobuf_include_path ${_abs_dir} _contains_already)
-      if(${_contains_already} EQUAL -1)
-          list(APPEND _protobuf_include_path -I ${_abs_dir})
-      endif()
-    endforeach()
-  endif()
-
-  foreach(DIR ${protobuf_generate_IMPORT_DIRS})
-    get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
-    list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
-    if(${_contains_already} EQUAL -1)
-        list(APPEND _protobuf_include_path -I ${ABS_PATH})
-    endif()
-  endforeach()
-
-  if(NOT _protobuf_include_path)
-    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
-  endif()
-
-  set(_generated_srcs_all)
-  foreach(_proto ${protobuf_generate_PROTOS})
-    get_filename_component(_abs_file ${_proto} ABSOLUTE)
-    get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
-
-    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})
-        string(FIND "${_rel_dir}" "../" _is_in_parent_folder)
-        if (NOT ${_is_in_parent_folder} EQUAL 0)
-          set(_suitable_include_found TRUE)
-          break()
-        endif()
-      endif()
-    endforeach()
-
-    if(NOT _suitable_include_found)
-      message(SEND_ERROR "Error: protobuf_generate could not find any correct proto include directory.")
-      return()
-    endif()
-
-    set(_generated_srcs)
-    foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS})
-      list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_rel_dir}/${_basename}${_ext}")
-    endforeach()
-    list(APPEND _generated_srcs_all ${_generated_srcs})
-
-    set(_comment "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}")
-    if(protobuf_generate_PROTOC_OPTIONS)
-      set(_comment "${_comment}, protoc-options: ${protobuf_generate_PROTOC_OPTIONS}")
-    endif()
-    if(_plugin_options)
-      set(_comment "${_comment}, plugin-options: ${_plugin_options}")
-    endif()
-
-    add_custom_command(
-      OUTPUT ${_generated_srcs}
-      COMMAND protobuf::protoc
-      ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_plugin_options}:${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
-      DEPENDS ${_abs_file} protobuf::protoc
-      COMMENT ${_comment}
-      VERBATIM )
-  endforeach()
-
-  set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE)
-  if(protobuf_generate_OUT_VAR)
-    set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE)
-  endif()
-  if(protobuf_generate_TARGET)
-    target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all})
-  endif()
-
-endfunction()
+# protobuf-generate function
+include("${CMAKE_CURRENT_LIST_DIR}/protobuf-generate.cmake")
 
 # CMake FindProtobuf module compatible file
 if(protobuf_MODULE_COMPATIBLE)
diff --git a/cmake/protobuf-generate.cmake b/cmake/protobuf-generate.cmake
new file mode 100644
index 0000000..10fd616
--- /dev/null
+++ b/cmake/protobuf-generate.cmake
@@ -0,0 +1,155 @@
+function(protobuf_generate)
+  include(CMakeParseArguments)
+
+  set(_options APPEND_PATH)
+  set(_singleargs LANGUAGE OUT_VAR EXPORT_MACRO PROTOC_OUT_DIR PLUGIN PLUGIN_OPTIONS DEPENDENCIES)
+  if(COMMAND target_sources)
+    list(APPEND _singleargs TARGET)
+  endif()
+  set(_multiargs PROTOS IMPORT_DIRS GENERATE_EXTENSIONS PROTOC_OPTIONS)
+
+  cmake_parse_arguments(protobuf_generate "${_options}" "${_singleargs}" "${_multiargs}" "${ARGN}")
+
+  if(NOT protobuf_generate_PROTOS AND NOT protobuf_generate_TARGET)
+    message(SEND_ERROR "Error: protobuf_generate called without any targets or source files")
+    return()
+  endif()
+
+  if(NOT protobuf_generate_OUT_VAR AND NOT protobuf_generate_TARGET)
+    message(SEND_ERROR "Error: protobuf_generate called without a target or output variable")
+    return()
+  endif()
+
+  if(NOT protobuf_generate_LANGUAGE)
+    set(protobuf_generate_LANGUAGE cpp)
+  endif()
+  string(TOLOWER ${protobuf_generate_LANGUAGE} protobuf_generate_LANGUAGE)
+
+  if(NOT protobuf_generate_PROTOC_OUT_DIR)
+    set(protobuf_generate_PROTOC_OUT_DIR ${CMAKE_CURRENT_BINARY_DIR})
+  endif()
+
+  if(protobuf_generate_EXPORT_MACRO AND protobuf_generate_LANGUAGE STREQUAL cpp)
+    set(_dll_export_decl "dllexport_decl=${protobuf_generate_EXPORT_MACRO}")
+  endif()
+
+  foreach(_option ${_dll_export_decl} ${protobuf_generate_PLUGIN_OPTIONS})
+    # append comma - not using CMake lists and string replacement as users
+    # might have semicolons in options
+    if(_plugin_options)
+      set( _plugin_options "${_plugin_options},")
+    endif()
+    set(_plugin_options "${_plugin_options}${_option}")
+  endforeach()
+
+  if(protobuf_generate_PLUGIN)
+      set(_plugin "--plugin=${protobuf_generate_PLUGIN}")
+  endif()
+
+  if(NOT protobuf_generate_GENERATE_EXTENSIONS)
+    if(protobuf_generate_LANGUAGE STREQUAL cpp)
+      set(protobuf_generate_GENERATE_EXTENSIONS .pb.h .pb.cc)
+    elseif(protobuf_generate_LANGUAGE STREQUAL python)
+      set(protobuf_generate_GENERATE_EXTENSIONS _pb2.py)
+    else()
+      message(SEND_ERROR "Error: protobuf_generate given unknown Language ${LANGUAGE}, please provide a value for GENERATE_EXTENSIONS")
+      return()
+    endif()
+  endif()
+
+  if(protobuf_generate_TARGET)
+    get_target_property(_source_list ${protobuf_generate_TARGET} SOURCES)
+    foreach(_file ${_source_list})
+      if(_file MATCHES "proto$")
+        list(APPEND protobuf_generate_PROTOS ${_file})
+      endif()
+    endforeach()
+  endif()
+
+  if(NOT protobuf_generate_PROTOS)
+    message(SEND_ERROR "Error: protobuf_generate could not find any .proto files")
+    return()
+  endif()
+
+  if(protobuf_generate_APPEND_PATH)
+    # Create an include path for each file specified
+    foreach(_file ${protobuf_generate_PROTOS})
+      get_filename_component(_abs_file ${_file} ABSOLUTE)
+      get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
+      list(FIND _protobuf_include_path ${_abs_dir} _contains_already)
+      if(${_contains_already} EQUAL -1)
+          list(APPEND _protobuf_include_path -I ${_abs_dir})
+      endif()
+    endforeach()
+  endif()
+
+  foreach(DIR ${protobuf_generate_IMPORT_DIRS})
+    get_filename_component(ABS_PATH ${DIR} ABSOLUTE)
+    list(FIND _protobuf_include_path ${ABS_PATH} _contains_already)
+    if(${_contains_already} EQUAL -1)
+        list(APPEND _protobuf_include_path -I ${ABS_PATH})
+    endif()
+  endforeach()
+
+  if(NOT _protobuf_include_path)
+    set(_protobuf_include_path -I ${CMAKE_CURRENT_SOURCE_DIR})
+  endif()
+
+  set(_generated_srcs_all)
+  foreach(_proto ${protobuf_generate_PROTOS})
+    get_filename_component(_abs_file ${_proto} ABSOLUTE)
+    get_filename_component(_abs_dir ${_abs_file} DIRECTORY)
+
+    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})
+        string(FIND "${_rel_dir}" "../" _is_in_parent_folder)
+        if (NOT ${_is_in_parent_folder} EQUAL 0)
+          set(_suitable_include_found TRUE)
+          break()
+        endif()
+      endif()
+    endforeach()
+
+    if(NOT _suitable_include_found)
+      message(SEND_ERROR "Error: protobuf_generate could not find any correct proto include directory.")
+      return()
+    endif()
+
+    set(_generated_srcs)
+    foreach(_ext ${protobuf_generate_GENERATE_EXTENSIONS})
+      list(APPEND _generated_srcs "${protobuf_generate_PROTOC_OUT_DIR}/${_rel_dir}/${_basename}${_ext}")
+    endforeach()
+    list(APPEND _generated_srcs_all ${_generated_srcs})
+
+    set(_comment "Running ${protobuf_generate_LANGUAGE} protocol buffer compiler on ${_proto}")
+    if(protobuf_generate_PROTOC_OPTIONS)
+      set(_comment "${_comment}, protoc-options: ${protobuf_generate_PROTOC_OPTIONS}")
+    endif()
+    if(_plugin_options)
+      set(_comment "${_comment}, plugin-options: ${_plugin_options}")
+    endif()
+
+    add_custom_command(
+      OUTPUT ${_generated_srcs}
+      COMMAND protobuf::protoc
+      ARGS ${protobuf_generate_PROTOC_OPTIONS} --${protobuf_generate_LANGUAGE}_out ${_plugin_options}:${protobuf_generate_PROTOC_OUT_DIR} ${_plugin} ${_protobuf_include_path} ${_abs_file}
+      DEPENDS ${_abs_file} protobuf::protoc ${protobuf_generate_DEPENDENCIES}
+      COMMENT ${_comment}
+      VERBATIM )
+  endforeach()
+
+  set_source_files_properties(${_generated_srcs_all} PROPERTIES GENERATED TRUE)
+  if(protobuf_generate_OUT_VAR)
+    set(${protobuf_generate_OUT_VAR} ${_generated_srcs_all} PARENT_SCOPE)
+  endif()
+  if(protobuf_generate_TARGET)
+    target_sources(${protobuf_generate_TARGET} PRIVATE ${_generated_srcs_all})
+  endif()
+
+endfunction()
diff --git a/cmake/protoc.cmake b/cmake/protoc.cmake
index 472b642..385a7a3 100644
--- a/cmake/protoc.cmake
+++ b/cmake/protoc.cmake
@@ -6,6 +6,7 @@
 target_link_libraries(protoc
   libprotoc
   libprotobuf
+  ${protobuf_ABSL_USED_TARGETS}
 )
 add_executable(protobuf::protoc ALIAS protoc)
 
diff --git a/cmake/tests.cmake b/cmake/tests.cmake
index 1905673..d3a0517 100644
--- a/cmake/tests.cmake
+++ b/cmake/tests.cmake
@@ -1,6 +1,7 @@
 option(protobuf_USE_EXTERNAL_GTEST "Use external Google Test (i.e. not the one in third_party/googletest)" OFF)
 
-option(protobuf_TEST_XML_OUTDIR "Output directory for XML logs from tests." "")
+option(protobuf_REMOVE_INSTALLED_HEADERS
+  "Remove local headers so that installed ones are used instead" OFF)
 
 option(protobuf_ABSOLUTE_TEST_PLUGIN_PATH
   "Using absolute test_plugin path in tests" ON)
@@ -39,65 +40,24 @@
   add_library(GTest::gmock_main ALIAS gmock_main)
 endif()
 
+include(${protobuf_SOURCE_DIR}/src/file_lists.cmake)
+
 set(lite_test_protos
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_unittest.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_lite.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public_lite.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite.proto
+  ${protobuf_lite_test_protos_files}
 )
 
 set(tests_protos
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_large_enum_value.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_proto2_unittest.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_unittest.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_arena.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_custom_options.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_drop_unknown_fields.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_embed_optimize_for.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_empty.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_enormous_descriptor.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_enum.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite_imports_nonlite.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset_wire_format.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_field_presence.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_generic_services.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_optimize_for.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum2.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena_lite.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_lite.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_optional.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_well_known_types.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/anys.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/books.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/default_value.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/default_value_test.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/field_mask.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/maps.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/oneofs.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/proto3.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/struct.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/testdata/wrappers.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_format.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_format_proto3.proto
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer_unittest.proto
+  ${protobuf_test_protos_files}
+  ${compiler_test_protos_files}
+  ${util_test_protos_files}
+  ${lite_test_protos}
 )
 
 macro(compile_proto_file filename)
-  string(REPLACE .proto .pb.cc pb_file ${filename})
+  string(REPLACE .proto .pb.h pb_hdr ${filename})
+  string(REPLACE .proto .pb.cc pb_src ${filename})
   add_custom_command(
-    OUTPUT ${pb_file}
+    OUTPUT ${pb_hdr} ${pb_src}
     DEPENDS ${protobuf_PROTOC_EXE} ${filename}
     COMMAND ${protobuf_PROTOC_EXE} ${filename}
         --proto_path=${protobuf_SOURCE_DIR}/src
@@ -109,119 +69,30 @@
 set(lite_test_proto_files)
 foreach(proto_file ${lite_test_protos})
   compile_proto_file(${proto_file})
-  set(lite_test_proto_files ${lite_test_proto_files} ${pb_file})
+  set(lite_test_proto_files ${lite_test_proto_files} ${pb_src} ${pb_hdr})
 endforeach(proto_file)
 
 set(tests_proto_files)
 foreach(proto_file ${tests_protos})
   compile_proto_file(${proto_file})
-  set(tests_proto_files ${tests_proto_files} ${pb_file})
+  set(tests_proto_files ${tests_proto_files} ${pb_src} ${pb_hdr})
 endforeach(proto_file)
 
-set(common_lite_test_files
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_test_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_test_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util_lite.cc
-)
-
-add_library(protobuf-lite-test-common STATIC
-  ${common_lite_test_files} ${lite_test_proto_files})
-target_link_libraries(protobuf-lite-test-common libprotobuf-lite GTest::gmock)
-
 set(common_test_files
-  ${common_lite_test_files}
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test_util.inc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_tester.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/googletest.cc
+  ${test_util_hdrs}
+  ${lite_test_util_srcs}
+  ${test_util_srcs}
+  ${common_test_hdrs}
+  ${common_test_srcs}
 )
 
-add_library(protobuf-test-common STATIC
-  ${common_test_files} ${tests_proto_files})
-target_link_libraries(protobuf-test-common libprotobuf GTest::gmock)
-
 set(tests_files
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.h
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_size_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/metadata_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/move_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/plugin_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/unittest.inc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/plugin_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/plugin_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/drop_unknown_fields_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/dynamic_message_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_lite_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test.inc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/message_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/message_unittest.inc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/no_field_presence_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/preserve_unknown_enum_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_arena_lite_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_arena_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_lite_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_lite_unittest.inc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_reflection_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/bytestream_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/int128_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/statusor_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringpiece_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/stringprintf_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/structurally_valid_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/strutil_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/template_util_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/time_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/text_format_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_objectwriter_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/json_stream_parser_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectsource_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/internal/type_info_test_helper.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_util_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util_test.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/well_known_types_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_unittest.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_unittest.inc
+  ${protobuf_test_files}
+  ${compiler_test_files}
+  ${annotation_test_util_srcs}
+  ${io_test_files}
+  ${util_test_files}
+  ${stubs_test_files}
 )
 
 if(protobuf_ABSOLUTE_TEST_PLUGIN_PATH)
@@ -248,47 +119,98 @@
   set(protobuf_GTEST_ARGS)
 endif()
 
-add_executable(tests ${tests_files})
+add_executable(tests
+  ${tests_files}
+  ${common_test_files}
+  ${tests_proto_files}
+)
 if (MSVC)
   target_compile_options(tests PRIVATE
     /wd4146 # unary minus operator applied to unsigned type, result still unsigned
   )
 endif()
-target_link_libraries(tests protobuf-lite-test-common protobuf-test-common libprotoc libprotobuf GTest::gmock_main)
+target_link_libraries(tests
+  ${protobuf_LIB_PROTOC}
+  ${protobuf_LIB_PROTOBUF}
+  ${protobuf_ABSL_USED_TARGETS}
+  GTest::gmock_main
+)
 
 set(test_plugin_files
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/test_plugin.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.cc
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.h
+  ${test_plugin_files}
+  ${common_test_hdrs}
+  ${common_test_srcs}
 )
 
 add_executable(test_plugin ${test_plugin_files})
-target_link_libraries(test_plugin libprotoc libprotobuf GTest::gmock)
-
-set(lite_test_files
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/lite_unittest.cc
+target_include_directories(test_plugin PRIVATE ${ABSL_ROOT_DIR})
+target_link_libraries(test_plugin
+  ${protobuf_LIB_PROTOC}
+  ${protobuf_LIB_PROTOBUF}
+  ${protobuf_ABSL_USED_TARGETS}
+  GTest::gmock
 )
-add_executable(lite-test ${lite_test_files})
-target_link_libraries(lite-test protobuf-lite-test-common libprotobuf-lite GTest::gmock_main)
+
+add_executable(lite-test
+  ${protobuf_lite_test_files}
+  ${lite_test_util_srcs}
+  ${lite_test_proto_files}
+)
+target_link_libraries(lite-test
+  ${protobuf_LIB_PROTOBUF_LITE}
+  ${protobuf_ABSL_USED_TARGETS}
+  GTest::gmock_main
+)
 
 add_test(NAME lite-test
   COMMAND lite-test ${protobuf_GTEST_ARGS})
 
-set(lite_arena_test_files
-  ${protobuf_SOURCE_DIR}/src/google/protobuf/lite_arena_unittest.cc
-)
-add_executable(lite-arena-test ${lite_arena_test_files})
-target_link_libraries(lite-arena-test protobuf-lite-test-common libprotobuf-lite GTest::gmock_main)
-
-add_test(NAME lite-arena-test
-  COMMAND lite-arena-test ${protobuf_GTEST_ARGS})
-
 add_custom_target(check
   COMMAND tests
-  DEPENDS tests test_plugin
+  DEPENDS tests lite-test test_plugin
   WORKING_DIRECTORY ${protobuf_SOURCE_DIR})
 
 add_test(NAME check
-  COMMAND tests ${protobuf_GTEST_ARGS}
-  WORKING_DIRECTORY "${protobuf_SOURCE_DIR}")
+  COMMAND tests ${protobuf_GTEST_ARGS})
+
+# For test purposes, remove headers that should already be installed.  This
+# prevents accidental conflicts and also version skew (since local headers take
+# precedence over installed headers).
+add_custom_target(save-installed-headers)
+add_custom_target(remove-installed-headers)
+add_custom_target(restore-installed-headers)
+
+file(GLOB_RECURSE _local_hdrs
+  "${PROJECT_SOURCE_DIR}/src/*.h"
+  "${PROJECT_SOURCE_DIR}/src/*.inc")
+
+# Exclude the bootstrapping that are directly used by tests.
+set(_exclude_hdrs
+  "${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.h"
+  "${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.pb.h")
+
+# Exclude test library headers.
+list(APPEND _exclude_hdrs ${test_util_hdrs} ${lite_test_util_hdrs} ${common_test_hdrs}
+  ${compiler_test_utils_hdrs})
+foreach(_hdr ${_exclude_hdrs})
+  list(REMOVE_ITEM _local_hdrs ${_hdr})
+endforeach()
+
+foreach(_hdr ${_local_hdrs})
+  string(REPLACE "${protobuf_SOURCE_DIR}/src" "" _file ${_hdr})
+  set(_tmp_file "${CMAKE_BINARY_DIR}/tmp-install-test/${_file}")
+  add_custom_command(TARGET remove-installed-headers PRE_BUILD
+                     COMMAND ${CMAKE_COMMAND} -E remove -f "${_hdr}")
+  add_custom_command(TARGET save-installed-headers PRE_BUILD
+                     COMMAND ${CMAKE_COMMAND} -E
+                        copy "${_hdr}" "${_tmp_file}" || true)
+  add_custom_command(TARGET restore-installed-headers PRE_BUILD
+                     COMMAND ${CMAKE_COMMAND} -E
+                        copy "${_tmp_file}" "${_hdr}")
+endforeach()
+
+add_dependencies(remove-installed-headers save-installed-headers)
+if(protobuf_REMOVE_INSTALLED_HEADERS)
+  # Make sure we remove all the headers *before* any codegen occurs.
+  add_dependencies(${protobuf_PROTOC_EXE} remove-installed-headers)
+endif()
diff --git a/cmake/utf8_range.cmake b/cmake/utf8_range.cmake
new file mode 100644
index 0000000..4dcfa4b
--- /dev/null
+++ b/cmake/utf8_range.cmake
@@ -0,0 +1,14 @@
+set(utf8_range_ENABLE_TESTS OFF CACHE BOOL "Disable utf8_range tests")
+
+if (NOT EXISTS "${protobuf_SOURCE_DIR}/third_party/utf8_range/CMakeLists.txt")
+  message(FATAL_ERROR
+          "Cannot find third_party/utf8_range directory that's needed to "
+          "build conformance tests. If you use git, make sure you have cloned "
+          "submodules:\n"
+          "  git submodule update --init --recursive\n")
+endif()
+
+set(utf8_range_ENABLE_INSTALL ${protobuf_INSTALL} CACHE BOOL "Set install")
+add_subdirectory(${CMAKE_CURRENT_SOURCE_DIR}/third_party/utf8_range third_party/utf8_range)
+
+set(_protobuf_FIND_UTF8_RANGE "if(NOT TARGET utf8_range)\n  find_package(utf8_range CONFIG)\nendif()")
diff --git a/configure.ac b/configure.ac
deleted file mode 100644
index ed00950..0000000
--- a/configure.ac
+++ /dev/null
@@ -1,247 +0,0 @@
-## Process this file with autoconf to produce configure.
-## In general, the safest way to proceed is to run ./autogen.sh
-
-AC_PREREQ(2.59)
-
-# Note:  If you change the version, you must also update it in:
-# * Protobuf.podspec
-# * csharp/Google.Protobuf.Tools.nuspec
-# * csharp/src/*/AssemblyInfo.cs
-# * csharp/src/Google.Protobuf/Google.Protobuf.nuspec
-# * java/*/pom.xml
-# * python/google/protobuf/__init__.py
-# * protoc-artifacts/pom.xml
-# * src/google/protobuf/stubs/common.h
-# * src/Makefile.am (Update -version-info for LDFLAGS if needed)
-#
-# 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.21.10],[protobuf@googlegroups.com],[protobuf])
-
-AM_MAINTAINER_MODE([enable])
-
-AC_CONFIG_SRCDIR(src/google/protobuf/message.cc)
-# The config file is generated but not used by the source code, since we only
-# need very few of them, e.g. HAVE_PTHREAD and HAVE_ZLIB. Those macros are
-# passed down in CXXFLAGS manually in src/Makefile.am
-AC_CONFIG_HEADERS([config.h])
-AC_CONFIG_MACRO_DIR([m4])
-
-AC_ARG_VAR(DIST_LANG, [language to include in the distribution package (i.e., make dist)])
-case "$DIST_LANG" in
-  "") DIST_LANG=all ;;
-  all | cpp | csharp | java | python | javanano | objectivec | ruby | php) ;;
-  *) AC_MSG_FAILURE([unknown language: $DIST_LANG]) ;;
-esac
-AC_SUBST(DIST_LANG)
-
-# autoconf's default CXXFLAGS are usually "-g -O2".  These aren't necessarily
-# the best choice for libprotobuf.
-AS_IF([test "x${ac_cv_env_CFLAGS_set}" = "x"],
-      [CFLAGS=""])
-AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],
-      [CXXFLAGS=""])
-
-AC_CANONICAL_TARGET
-
-AM_INIT_AUTOMAKE([1.9 tar-ustar subdir-objects])
-
-# Silent rules enabled: the output is minimal but informative.
-# In particular, the warnings from the compiler stick out very clearly.
-# To see all logs, use the --disable-silent-rules on configure or via make V=1
-AM_SILENT_RULES([yes])
-
-AC_ARG_WITH([zlib],
-  [AS_HELP_STRING([--with-zlib],
-    [include classes for streaming compressed data in and out @<:@default=check@:>@])],
-  [],[with_zlib=check])
-
-AC_ARG_WITH([zlib-include],
-  [AS_HELP_STRING([--with-zlib-include=PATH],
-    [zlib include directory])],
-  [CPPFLAGS="-I$withval $CPPFLAGS"])
-
-AC_ARG_WITH([zlib-lib],
-  [AS_HELP_STRING([--with-zlib-lib=PATH],
-    [zlib lib directory])],
-  [LDFLAGS="-L$withval $LDFLAGS"])
-
-AC_ARG_WITH([protoc],
-  [AS_HELP_STRING([--with-protoc=COMMAND],
-    [use the given protoc command instead of building a new one when building tests (useful for cross-compiling)])],
-  [],[with_protoc=no])
-
-# Checks for programs.
-AC_PROG_CC
-AC_PROG_CXX
-AC_PROG_CXX_FOR_BUILD
-AC_LANG([C++])
-ACX_USE_SYSTEM_EXTENSIONS
-m4_ifdef([AM_PROG_AR], [AM_PROG_AR])
-AM_CONDITIONAL(GCC, test "$GCC" = yes)   # let the Makefile know if we're gcc
-AS_CASE([$target_os], [darwin*], [AC_PROG_OBJC], [AM_CONDITIONAL([am__fastdepOBJC], [false])])
-
-# test_util.cc takes forever to compile with GCC and optimization turned on.
-AC_MSG_CHECKING([C++ compiler flags...])
-AS_IF([test "x${ac_cv_env_CXXFLAGS_set}" = "x"],[
-  AS_IF([test "$GCC" = "yes"],[
-    PROTOBUF_OPT_FLAG="-O2"
-    CXXFLAGS="${CXXFLAGS} -g"
-  ])
-
-  # Protocol Buffers contains several checks that are intended to be used only
-  # for debugging and which might hurt performance.  Most users are probably
-  # end users who don't want these checks, so add -DNDEBUG by default.
-  CXXFLAGS="$CXXFLAGS -std=c++11 -DNDEBUG"
-
-  AC_MSG_RESULT([use default: $PROTOBUF_OPT_FLAG $CXXFLAGS])
-],[
-  AC_MSG_RESULT([use user-supplied: $CXXFLAGS])
-])
-
-AC_SUBST(PROTOBUF_OPT_FLAG)
-
-ACX_CHECK_SUNCC
-
-# Have to do libtool after SUNCC, other wise it "helpfully" adds Crun Cstd
-# to the link
-AC_PROG_LIBTOOL
-
-# Check whether the linker supports version scripts
-AC_MSG_CHECKING([whether the linker supports version scripts])
-save_LDFLAGS=$LDFLAGS
-LDFLAGS="$LDFLAGS -Wl,--version-script=conftest.map"
-cat > conftest.map <<EOF
-{
-  global:
-    main;
-  local:
-    *;
-};
-EOF
-AC_LINK_IFELSE(
-  [AC_LANG_SOURCE([int main() { return 0; }])],
-  [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"])
-
-# Checks for header files.
-AC_HEADER_STDC
-AC_CHECK_HEADERS([fcntl.h inttypes.h limits.h stdlib.h unistd.h])
-
-# Checks for library functions.
-AC_FUNC_MEMCMP
-AC_FUNC_STRTOD
-AC_CHECK_FUNCS([ftruncate memset mkdir strchr strerror strtol])
-
-# Check for zlib.
-HAVE_ZLIB=0
-AS_IF([test "$with_zlib" != no], [
-  AC_MSG_CHECKING([zlib version])
-
-  # First check the zlib header version.
-  AC_COMPILE_IFELSE(
-    [AC_LANG_PROGRAM([[
-        #include <zlib.h>
-        #if !defined(ZLIB_VERNUM) || (ZLIB_VERNUM < 0x1204)
-        # error zlib version too old
-        #endif
-        ]], [])], [
-    AC_MSG_RESULT([ok (1.2.0.4 or later)])
-
-    # Also need to add -lz to the linker flags and make sure this succeeds.
-    AC_SEARCH_LIBS([zlibVersion], [z], [
-      AC_DEFINE([HAVE_ZLIB], [1], [Enable classes using zlib compression.])
-      HAVE_ZLIB=1
-    ], [
-      AS_IF([test "$with_zlib" != check], [
-        AC_MSG_FAILURE([--with-zlib was given, but no working zlib library was found])
-      ])
-    ])
-  ], [
-    AS_IF([test "$with_zlib" = check], [
-      AC_MSG_RESULT([headers missing or too old (requires 1.2.0.4)])
-    ], [
-      AC_MSG_FAILURE([--with-zlib was given, but zlib headers were not present or were too old (requires 1.2.0.4)])
-    ])
-  ])
-])
-AM_CONDITIONAL([HAVE_ZLIB], [test $HAVE_ZLIB = 1])
-
-# Add -std=c++11 if necesssary. It is important for us to do this before the
-# libatomic check below, since that also depends on C++11.
-AX_CXX_COMPILE_STDCXX([11], [noext], [mandatory])
-
-dnl On some platforms, std::atomic needs a helper library
-AC_MSG_CHECKING(whether -latomic is needed)
-AC_LINK_IFELSE([AC_LANG_SOURCE([[
-  #include <atomic>
-  #include <cstdint>
-  std::atomic<std::int64_t> v;
-  int main() {
-    return v;
-  }
-]])], STD_ATOMIC_NEED_LIBATOMIC=no, STD_ATOMIC_NEED_LIBATOMIC=yes)
-AC_MSG_RESULT($STD_ATOMIC_NEED_LIBATOMIC)
-if test "x$STD_ATOMIC_NEED_LIBATOMIC" = xyes; then
-  LIBATOMIC_LIBS="-latomic"
-fi
-AC_SUBST([LIBATOMIC_LIBS])
-
-AS_IF([test "$with_protoc" != "no"], [
-  PROTOC=$with_protoc
-  AS_IF([test "$with_protoc" = "yes"], [
-    # No argument given.  Use system protoc.
-    PROTOC=protoc
-  ])
-  AS_IF([echo "$PROTOC" | grep -q '^@<:@^/@:>@.*/'], [
-    # Does not start with a slash, but contains a slash.  So, it's a relative
-    # path (as opposed to an absolute path or an executable in $PATH).
-    # Since it will actually be executed from the src directory, prefix with
-    # the current directory.  We also insert $ac_top_build_prefix in case this
-    # is a nested package and --with-protoc was actually given on the outer
-    # package's configure script.
-    PROTOC=`pwd`/${ac_top_build_prefix}$PROTOC
-  ])
-  AC_SUBST([PROTOC])
-])
-AM_CONDITIONAL([USE_EXTERNAL_PROTOC], [test "$with_protoc" != "no"])
-
-AX_PTHREAD
-AM_CONDITIONAL([HAVE_PTHREAD], [test "x$ax_pthread_ok" = "xyes"])
-# We still keep this for improving pbconfig.h for unsupported platforms.
-AC_CXX_STL_HASH
-
-# Enable ObjC support for conformance directory on OS X.
-OBJC_CONFORMANCE_TEST=0
-case "$target_os" in
-  darwin*)
-    OBJC_CONFORMANCE_TEST=1
-    ;;
-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.
-export CFLAGS
-export CXXFLAGS
-AC_CONFIG_SUBDIRS([third_party/googletest])
-
-AC_CONFIG_FILES([Makefile src/Makefile benchmarks/Makefile conformance/Makefile protobuf.pc protobuf-lite.pc])
-AC_OUTPUT
diff --git a/conformance/BUILD.bazel b/conformance/BUILD.bazel
index 7de2b8e..486d652 100644
--- a/conformance/BUILD.bazel
+++ b/conformance/BUILD.bazel
@@ -1,30 +1,48 @@
 # Conformance testing for Protobuf.
 
-load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_proto_library")
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_proto_library", "objc_library")
+load("//:protobuf.bzl", "internal_csharp_proto_library", "internal_objc_proto_library", "internal_php_proto_library", "internal_py_proto_library", "internal_ruby_proto_library")
+load("//build_defs:internal_shell.bzl", "inline_sh_binary")
 load(
     "@rules_pkg//:mappings.bzl",
-    "pkg_attributes",
     "pkg_filegroup",
     "pkg_files",
     "strip_prefix",
 )
 
 exports_files([
-    "conformance_test_runner.sh",
+    "bazel_conformance_test_runner.sh",
+    "failure_list_cpp.txt",
+    "failure_list_csharp.txt",
     "failure_list_java.txt",
     "failure_list_java_lite.txt",
+    "failure_list_objc.txt",
+    "failure_list_php.txt",
+    "failure_list_php_c.txt",
+    "failure_list_python.txt",
+    "failure_list_python_cpp.txt",
+    "failure_list_ruby.txt",
+    "failure_list_jruby.txt",
+    "text_format_failure_list_cpp.txt",
+    "text_format_failure_list_csharp.txt",
     "text_format_failure_list_java.txt",
     "text_format_failure_list_java_lite.txt",
+    "text_format_failure_list_php.txt",
+    "text_format_failure_list_php_c.txt",
+    "text_format_failure_list_python.txt",
+    "text_format_failure_list_python_cpp.txt",
+    "text_format_failure_list_ruby.txt",
+    "text_format_failure_list_jruby.txt",
 ])
 
 cc_proto_library(
     name = "test_messages_proto2_proto_cc",
-    deps = ["//:test_messages_proto2_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto2_proto"],
 )
 
 cc_proto_library(
     name = "test_messages_proto3_proto_cc",
-    deps = ["//:test_messages_proto3_proto"],
+    deps = ["//src/google/protobuf:test_messages_proto3_proto"],
 )
 
 proto_library(
@@ -34,10 +52,18 @@
 )
 
 cc_proto_library(
-    name = "conformance_proto_cc",
+    name = "conformance_cc_proto",
     deps = [":conformance_proto"],
 )
 
+internal_csharp_proto_library(
+    name = "conformance_csharp_proto",
+    srcs = ["conformance.proto"],
+    visibility = [
+        "//csharp:__subpackages__",
+    ],
+)
+
 java_proto_library(
     name = "conformance_java_proto",
     visibility = [
@@ -54,11 +80,49 @@
     deps = [":conformance_proto"],
 )
 
-cc_library(
-    name = "jsoncpp",
-    srcs = ["third_party/jsoncpp/jsoncpp.cpp"],
-    hdrs = ["third_party/jsoncpp/json.h"],
-    includes = ["."],
+internal_objc_proto_library(
+    name = "conformance_objc_proto",
+    srcs = ["conformance.proto"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//objc:__pkg__",
+    ],
+)
+
+internal_py_proto_library(
+    name = "conformance_py_proto",
+    srcs = ["conformance.proto"],
+    srcs_version = "PY2AND3",
+    visibility = [
+        "//python:__subpackages__",
+    ],
+)
+
+internal_php_proto_library(
+    name = "conformance_php_proto",
+    srcs = ["conformance.proto"],
+    outs = [
+        "Conformance/ConformanceRequest.php",
+        "Conformance/ConformanceResponse.php",
+        "Conformance/FailureSet.php",
+        "Conformance/JspbEncodingConfig.php",
+        "Conformance/TestCategory.php",
+        "Conformance/WireFormat.php",
+        "GPBMetadata/Conformance.php",
+    ],
+    visibility = [
+        "//conformance:__pkg__",
+        "//php:__pkg__",
+    ],
+)
+
+internal_ruby_proto_library(
+    name = "conformance_ruby_proto",
+    srcs = ["conformance.proto"],
+    visibility = [
+        "//conformance:__pkg__",
+        "//ruby:__pkg__",
+    ],
 )
 
 cc_library(
@@ -71,7 +135,11 @@
         "conformance_test.h",
     ],
     includes = ["."],
-    deps = [":conformance_proto_cc"],
+    deps = [
+        ":conformance_cc_proto",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+    ],
 )
 
 cc_library(
@@ -80,9 +148,10 @@
     hdrs = ["binary_json_conformance_suite.h"],
     deps = [
         ":conformance_test",
-        ":jsoncpp",
         ":test_messages_proto2_proto_cc",
         ":test_messages_proto3_proto_cc",
+        "@com_google_absl//absl/status",
+        "@jsoncpp",
     ],
 )
 
@@ -105,11 +174,28 @@
         ":binary_json_conformance_suite",
         ":conformance_test",
         ":text_format_conformance_suite",
+        "@com_google_absl//absl/strings:str_format",
+    ],
+)
+
+cc_binary(
+    name = "conformance_cpp",
+    testonly = 1,
+    srcs = ["conformance_cpp.cc"],
+    visibility = ["//src:__subpackages__"],
+    deps = [
+        ":conformance_cc_proto",
+        "//:protobuf",
+        "//:test_messages_proto2_cc_proto",
+        "//:test_messages_proto3_cc_proto",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
     ],
 )
 
 java_binary(
     name = "conformance_java",
+    testonly = 1,
     srcs = ["ConformanceJava.java"],
     main_class = "ConformanceJava",
     visibility = [
@@ -126,6 +212,7 @@
 
 java_binary(
     name = "conformance_java_lite",
+    testonly = 1,
     srcs = ["ConformanceJavaLite.java"],
     main_class = "ConformanceJavaLite",
     visibility = [
@@ -140,10 +227,119 @@
     ],
 )
 
+py_binary(
+    name = "conformance_python",
+    testonly = 1,
+    srcs = ["conformance_python.py"],
+    imports = [
+        "..",
+        "../python",
+    ],
+    srcs_version = "PY2AND3",
+    visibility = ["//python:__subpackages__"],
+    deps = [
+        ":conformance_py_proto",
+        "//:protobuf_python",
+        "//python:test_messages_proto2_py_proto",
+        "//python:test_messages_proto3_py_proto",
+    ],
+)
+
+inline_sh_binary(
+    name = "conformance_php",
+    testonly = 1,
+    srcs = [
+        "autoload.php",
+        "conformance_php.php",
+    ],
+    cmd = """
+        php -d include_path=conformance:src/google/protobuf \\
+            -d auto_prepend_file=$(rootpath autoload.php) \\
+            $(rootpath conformance_php.php)
+    """,
+    visibility = ["//php:__subpackages__"],
+    deps = [
+        ":conformance_php_proto",
+        "//:test_messages_proto3_php_proto",
+        "//php:source_files",
+    ],
+)
+
+inline_sh_binary(
+    name = "conformance_php_c",
+    testonly = 1,
+    srcs = [
+        "conformance_php.php",
+        "//php:extension",
+    ],
+    cmd = """
+        php -dextension=$(rootpath //php:extension) \\
+            -d include_path=conformance:src/google/protobuf \\
+            $(rootpath conformance_php.php)
+    """,
+    visibility = ["//php:__subpackages__"],
+    deps = [
+        ":conformance_php_proto",
+        "//:test_messages_proto3_php_proto",
+    ],
+)
+
+inline_sh_binary(
+    name = "conformance_csharp",
+    testonly = 1,
+    srcs = ["//csharp/src/Google.Protobuf.Conformance:conformance_dll"],
+    cmd = "dotnet $(rootpath //csharp/src/Google.Protobuf.Conformance:conformance_dll)",
+    visibility = ["//csharp:__subpackages__"],
+    deps = [
+        "//csharp/src/Google.Protobuf.Conformance:conformance_runfiles",
+    ],
+)
+
+objc_library(
+    name = "conformance_objc_lib",
+    testonly = 1,
+    non_arc_srcs = ["conformance_objc.m"],
+    # See https://github.com/bazelbuild/bazel/issues/12897.
+    tags = ["manual"],
+    deps = [
+        ":conformance_objc_proto",
+        "//:test_messages_proto2_objc_proto",
+        "//:test_messages_proto3_objc_proto",
+    ],
+)
+
+cc_binary(
+    name = "conformance_objc",
+    testonly = 1,
+    # See https://github.com/bazelbuild/bazel/issues/12897.
+    tags = ["manual"],
+    visibility = ["//objectivec:__subpackages__"],
+    deps = [":conformance_objc_lib"],
+)
+
+inline_sh_binary(
+    name = "conformance_ruby",
+    testonly = 1,
+    srcs = ["conformance_ruby.rb"],
+    cmd = "RUBYLIB=ruby/lib:conformance:src $(rootpath conformance_ruby.rb)",
+    visibility = ["//ruby:__subpackages__"],
+    deps = [
+        ":conformance_ruby_proto",
+        "//:test_messages_proto2_ruby_proto",
+        "//:test_messages_proto3_ruby_proto",
+        "//:well_known_ruby_protos",
+        "//ruby:protobuf",
+    ],
+)
+
+################################################################################
+# Distribution files
+################################################################################
+
 filegroup(
     name = "all_files",
     srcs = glob(["**/*"]),
-    visibility = ["//:__pkg__"],
+    visibility = ["//src/google/protobuf/compiler/csharp:__pkg__"],
 )
 
 pkg_files(
@@ -152,11 +348,10 @@
         ["**/*"],
         exclude = [
             # Handled by dist_scripts:
-            "conformance_test_runner.sh",
+            "bazel_conformance_test_runner.sh",
 
             # The following are not in autotools dist:
             "autoload.php",
-            "conformance_nodejs.js",
             "failure_list_jruby.txt",
             "update_failure_list.py",
         ],
@@ -165,19 +360,10 @@
     visibility = ["//pkg:__pkg__"],
 )
 
-pkg_files(
-    name = "dist_scripts",
-    srcs = ["conformance_test_runner.sh"],
-    attributes = pkg_attributes(mode = "0555"),
-    strip_prefix = strip_prefix.from_root(""),
-    visibility = ["//pkg:__pkg__"],
-)
-
 pkg_filegroup(
     name = "all_dist_files",
     srcs = [
         ":dist_files",
-        ":dist_scripts",
     ],
     visibility = ["//pkg:__pkg__"],
 )
diff --git a/conformance/Makefile.am b/conformance/Makefile.am
deleted file mode 100644
index 415412b..0000000
--- a/conformance/Makefile.am
+++ /dev/null
@@ -1,372 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-conformance_protoc_inputs =                                    \
-  conformance.proto                                            \
-  $(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 php.
-conformance_proto2_protoc_inputs =                             \
-  $(top_srcdir)/src/google/protobuf/test_messages_proto2.proto
-
-well_known_type_protoc_inputs =                                \
-  $(top_srcdir)/src/google/protobuf/any.proto                  \
-  $(top_srcdir)/src/google/protobuf/duration.proto             \
-  $(top_srcdir)/src/google/protobuf/field_mask.proto           \
-  $(top_srcdir)/src/google/protobuf/struct.proto               \
-  $(top_srcdir)/src/google/protobuf/timestamp.proto            \
-  $(top_srcdir)/src/google/protobuf/wrappers.proto
-
-
-protoc_outputs =                                               \
-  conformance.pb.cc                                            \
-  conformance.pb.h
-
-other_language_protoc_outputs =                                \
-  conformance_pb2.py                                           \
-  Conformance.pbobjc.h                                         \
-  Conformance.pbobjc.m                                         \
-  conformance_pb.js                                            \
-  conformance_pb.rb                                            \
-  com/google/protobuf/Any.java                                 \
-  com/google/protobuf/AnyOrBuilder.java                        \
-  com/google/protobuf/AnyProto.java                            \
-  com/google/protobuf/BoolValue.java                           \
-  com/google/protobuf/BoolValueOrBuilder.java                  \
-  com/google/protobuf/BytesValue.java                          \
-  com/google/protobuf/BytesValueOrBuilder.java                 \
-  com/google/protobuf/conformance/Conformance.java             \
-  com/google/protobuf/DoubleValue.java                         \
-  com/google/protobuf/DoubleValueOrBuilder.java                \
-  com/google/protobuf/Duration.java                            \
-  com/google/protobuf/DurationOrBuilder.java                   \
-  com/google/protobuf/DurationProto.java                       \
-  com/google/protobuf/FieldMask.java                           \
-  com/google/protobuf/FieldMaskOrBuilder.java                  \
-  com/google/protobuf/FieldMaskProto.java                      \
-  com/google/protobuf/FloatValue.java                          \
-  com/google/protobuf/FloatValueOrBuilder.java                 \
-  com/google/protobuf/Int32Value.java                          \
-  com/google/protobuf/Int32ValueOrBuilder.java                 \
-  com/google/protobuf/Int64Value.java                          \
-  com/google/protobuf/Int64ValueOrBuilder.java                 \
-  com/google/protobuf/ListValue.java                           \
-  com/google/protobuf/ListValueOrBuilder.java                  \
-  com/google/protobuf/NullValue.java                           \
-  com/google/protobuf/StringValue.java                         \
-  com/google/protobuf/StringValueOrBuilder.java                \
-  com/google/protobuf/Struct.java                              \
-  com/google/protobuf/StructOrBuilder.java                     \
-  com/google/protobuf/StructProto.java                         \
-  com/google/protobuf/Timestamp.java                           \
-  com/google/protobuf/TimestampOrBuilder.java                  \
-  com/google/protobuf/TimestampProto.java                      \
-  com/google/protobuf/UInt32Value.java                         \
-  com/google/protobuf/UInt32ValueOrBuilder.java                \
-  com/google/protobuf/UInt64Value.java                         \
-  com/google/protobuf/UInt64ValueOrBuilder.java                \
-  com/google/protobuf/Value.java                               \
-  com/google/protobuf/ValueOrBuilder.java                      \
-  com/google/protobuf/WrappersProto.java                       \
-  com/google/protobuf_test_messages/proto3/TestMessagesProto3.java \
-  com/google/protobuf_test_messages/proto2/TestMessagesProto2.java \
-  google/protobuf/any.pb.cc                                    \
-  google/protobuf/any.pb.h                                     \
-  google/protobuf/any.rb                                       \
-  google/protobuf/any_pb2.py                                   \
-  google/protobuf/duration.pb.cc                               \
-  google/protobuf/duration.pb.h                                \
-  google/protobuf/duration.rb                                  \
-  google/protobuf/duration_pb2.py                              \
-  google/protobuf/field_mask.pb.cc                             \
-  google/protobuf/field_mask.pb.h                              \
-  google/protobuf/field_mask.rb                                \
-  google/protobuf/field_mask_pb2.py                            \
-  google/protobuf/struct.pb.cc                                 \
-  google/protobuf/struct.pb.h                                  \
-  google/protobuf/struct.rb                                    \
-  google/protobuf/struct_pb2.py                                \
-  google/protobuf/TestMessagesProto2.pbobjc.h                  \
-  google/protobuf/TestMessagesProto2.pbobjc.m                  \
-  google/protobuf/TestMessagesProto3.pbobjc.h                  \
-  google/protobuf/TestMessagesProto3.pbobjc.m                  \
-  google/protobuf/test_messages_proto3.pb.cc                   \
-  google/protobuf/test_messages_proto3.pb.h                    \
-  google/protobuf/test_messages_proto2.pb.cc                   \
-  google/protobuf/test_messages_proto2.pb.h                    \
-  google/protobuf/test_messages_proto3_pb.rb                   \
-  google/protobuf/test_messages_proto3_pb2.py                  \
-  google/protobuf/test_messages_proto2_pb2.py                  \
-  google/protobuf/timestamp.pb.cc                              \
-  google/protobuf/timestamp.pb.h                               \
-  google/protobuf/timestamp.rb                                 \
-  google/protobuf/timestamp_pb2.py                             \
-  google/protobuf/wrappers.pb.cc                               \
-  google/protobuf/wrappers.pb.h                                \
-  google/protobuf/wrappers.rb                                  \
-  google/protobuf/wrappers_pb2.py                              \
-  Conformance/ConformanceRequest.php                           \
-  Conformance/ConformanceResponse.php                          \
-  Conformance/FailureSet.php                                   \
-  Conformance/WireFormat.php                                   \
-  GPBMetadata/Conformance.php                                  \
-  GPBMetadata/Google/Protobuf/Any.php                          \
-  GPBMetadata/Google/Protobuf/Duration.php                     \
-  GPBMetadata/Google/Protobuf/FieldMask.php                    \
-  GPBMetadata/Google/Protobuf/Struct.php                       \
-  GPBMetadata/Google/Protobuf/TestMessagesProto3.php           \
-  GPBMetadata/Google/Protobuf/Timestamp.php                    \
-  GPBMetadata/Google/Protobuf/Wrappers.php                     \
-  Google/Protobuf/Any.php                                      \
-  Google/Protobuf/BoolValue.php                                \
-  Google/Protobuf/BytesValue.php                               \
-  Google/Protobuf/DoubleValue.php                              \
-  Google/Protobuf/Duration.php                                 \
-  Google/Protobuf/FieldMask.php                                \
-  Google/Protobuf/FloatValue.php                               \
-  Google/Protobuf/Int32Value.php                               \
-  Google/Protobuf/Int64Value.php                               \
-  Google/Protobuf/ListValue.php                                \
-  Google/Protobuf/NullValue.php                                \
-  Google/Protobuf/StringValue.php                              \
-  Google/Protobuf/Struct.php                                   \
-  Google/Protobuf/Timestamp.php                                \
-  Google/Protobuf/UInt32Value.php                              \
-  Google/Protobuf/UInt64Value.php                              \
-  Google/Protobuf/Value.php                                    \
-  Protobuf_test_messages/Proto3/ForeignEnum.php                \
-  Protobuf_test_messages/Proto3/ForeignMessage.php             \
-  Protobuf_test_messages/Proto3/TestAllTypes_NestedEnum.php    \
-  Protobuf_test_messages/Proto3/TestAllTypes_NestedMessage.php \
-  Protobuf_test_messages/Proto3/TestAllTypes.php
-  # lite/com/google/protobuf/Any.java                            \
-  # lite/com/google/protobuf/AnyOrBuilder.java                   \
-  # lite/com/google/protobuf/AnyProto.java                       \
-  # lite/com/google/protobuf/BoolValue.java                      \
-  # lite/com/google/protobuf/BoolValueOrBuilder.java             \
-  # lite/com/google/protobuf/BytesValue.java                     \
-  # lite/com/google/protobuf/BytesValueOrBuilder.java            \
-  # lite/com/google/protobuf/conformance/Conformance.java        \
-  # lite/com/google/protobuf/DoubleValue.java                    \
-  # lite/com/google/protobuf/DoubleValueOrBuilder.java           \
-  # lite/com/google/protobuf/Duration.java                       \
-  # lite/com/google/protobuf/DurationOrBuilder.java              \
-  # lite/com/google/protobuf/DurationProto.java                  \
-  # lite/com/google/protobuf/FieldMask.java                      \
-  # lite/com/google/protobuf/FieldMaskOrBuilder.java             \
-  # lite/com/google/protobuf/FieldMaskProto.java                 \
-  # lite/com/google/protobuf/FloatValue.java                     \
-  # lite/com/google/protobuf/FloatValueOrBuilder.java            \
-  # lite/com/google/protobuf/Int32Value.java                     \
-  # lite/com/google/protobuf/Int32ValueOrBuilder.java            \
-  # lite/com/google/protobuf/Int64Value.java                     \
-  # lite/com/google/protobuf/Int64ValueOrBuilder.java            \
-  # lite/com/google/protobuf/ListValue.java                      \
-  # lite/com/google/protobuf/ListValueOrBuilder.java             \
-  # lite/com/google/protobuf/NullValue.java                      \
-  # lite/com/google/protobuf/StringValue.java                    \
-  # lite/com/google/protobuf/StringValueOrBuilder.java           \
-  # lite/com/google/protobuf/Struct.java                         \
-  # lite/com/google/protobuf/StructOrBuilder.java                \
-  # lite/com/google/protobuf/StructProto.java                    \
-  # lite/com/google/protobuf/Timestamp.java                      \
-  # lite/com/google/protobuf/TimestampOrBuilder.java             \
-  # lite/com/google/protobuf/TimestampProto.java                 \
-  # lite/com/google/protobuf/UInt32Value.java                    \
-  # lite/com/google/protobuf/UInt32ValueOrBuilder.java           \
-  # lite/com/google/protobuf/UInt64Value.java                    \
-  # lite/com/google/protobuf/UInt64ValueOrBuilder.java           \
-  # lite/com/google/protobuf/Value.java                          \
-  # lite/com/google/protobuf/ValueOrBuilder.java                 \
-  # lite/com/google/protobuf/WrappersProto.java
-
-bin_PROGRAMS = conformance-test-runner conformance-cpp
-
-# All source files excepet C++/Objective-C ones should be explicitly listed
-# here because the autoconf tools don't include files of other languages
-# automatically.
-EXTRA_DIST =                  \
-  ConformanceJava.java        \
-  ConformanceJavaLite.java    \
-  README.md                   \
-  conformance.proto           \
-  conformance_python.py       \
-  conformance_ruby.rb         \
-  conformance_php.php         \
-  failure_list_cpp.txt        \
-  failure_list_csharp.txt     \
-  failure_list_java.txt       \
-  failure_list_js.txt         \
-  failure_list_objc.txt       \
-  failure_list_python.txt     \
-  failure_list_python_cpp.txt \
-  failure_list_python-post26.txt \
-  failure_list_ruby.txt       \
-  failure_list_php.txt        \
-  failure_list_php_c.txt
-
-conformance_test_runner_LDADD = $(top_srcdir)/src/libprotobuf.la
-conformance_test_runner_SOURCES = conformance_test.h conformance_test.cc \
-                                  conformance_test_main.cc               \
-                                  binary_json_conformance_suite.h        \
-                                  binary_json_conformance_suite.cc       \
-                                  text_format_conformance_suite.h        \
-                                  text_format_conformance_suite.cc       \
-                                  conformance_test_runner.cc             \
-                                  third_party/jsoncpp/json.h             \
-                                  third_party/jsoncpp/jsoncpp.cpp
-nodist_conformance_test_runner_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc
-conformance_test_runner_CPPFLAGS = -I$(top_srcdir)/src -I$(srcdir)
-conformance_test_runner_CXXFLAGS = -std=c++11
-# Explicit deps because BUILT_SOURCES are only done before a "make all/check"
-# so a direct "make test_cpp" could fail if parallel enough.
-conformance_test_runner-conformance_test.$(OBJEXT): conformance.pb.h
-conformance_test_runner-conformance_test_runner.$(OBJEXT): conformance.pb.h
-
-conformance_cpp_LDADD = $(top_srcdir)/src/libprotobuf.la
-conformance_cpp_SOURCES = conformance_cpp.cc
-nodist_conformance_cpp_SOURCES = conformance.pb.cc google/protobuf/test_messages_proto3.pb.cc google/protobuf/test_messages_proto2.pb.cc
-conformance_cpp_CPPFLAGS = -I$(top_srcdir)/src
-# Explicit dep because BUILT_SOURCES are only done before a "make all/check"
-# so a direct "make test_cpp" could fail if parallel enough.
-conformance_cpp-conformance_cpp.$(OBJEXT): conformance.pb.h
-
-if OBJC_CONFORMANCE_TEST
-
-bin_PROGRAMS += conformance-objc
-
-conformance_objc_SOURCES = conformance_objc.m ../objectivec/GPBProtocolBuffers.m
-nodist_conformance_objc_SOURCES = Conformance.pbobjc.m google/protobuf/TestMessagesProto2.pbobjc.m google/protobuf/TestMessagesProto3.pbobjc.m
-# On travis, the build fails without the isysroot because whatever system
-# headers are being found don't include generics support for
-# NSArray/NSDictionary, the only guess is their image at one time had an odd
-# setup for Xcode and old frameworks are being found.
-conformance_objc_CPPFLAGS = -I$(top_srcdir)/objectivec -isysroot `xcrun --sdk macosx --show-sdk-path`
-conformance_objc_LDFLAGS = -framework Foundation
-# Explicit dep because BUILT_SOURCES are only done before a "make all/check"
-# so a direct "make test_objc" could fail if parallel enough.
-conformance_objc-conformance_objc.$(OBJEXT): Conformance.pbobjc.h google/protobuf/TestMessagesProto2.pbobjc.h google/protobuf/TestMessagesProto3.pbobjc.h
-
-endif
-
-# JavaScript well-known types are expected to be in a directory called
-# google-protobuf, because they are usually in the google-protobuf npm
-# package.  But we want to use the sources from our tree, so we recreate
-# that directory structure here.
-google-protobuf:
-	mkdir google-protobuf
-
-if USE_EXTERNAL_PROTOC
-
-# 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=. $(conformance_protoc_inputs)
-	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --objc_out=. --python_out=. $(conformance_proto2_protoc_inputs)
-	$(PROTOC) -I$(srcdir) -I$(top_srcdir) --cpp_out=. --java_out=. --ruby_out=. --python_out=. $(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
-
-else
-
-# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
-# relative to srcdir, which may not be the same as the current directory when
-# 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 $(conformance_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 $(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 $(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) )
-	touch protoc_middleman
-
-endif
-
-$(protoc_outputs): protoc_middleman
-
-$(other_language_protoc_outputs): protoc_middleman
-
-CLEANFILES = $(protoc_outputs) protoc_middleman javac_middleman conformance-java javac_middleman_lite conformance-java-lite conformance-csharp conformance-php conformance-php-c $(other_language_protoc_outputs)
-
-MAINTAINERCLEANFILES =   \
-  Makefile.in
-
-javac_middleman: ConformanceJava.java protoc_middleman $(other_language_protoc_outputs)
-	jar=`ls ../java/util/target/*jar-with-dependencies.jar` && javac -classpath ../java/target/classes:$$jar ConformanceJava.java com/google/protobuf/conformance/Conformance.java com/google/protobuf_test_messages/proto3/TestMessagesProto3.java com/google/protobuf_test_messages/proto2/TestMessagesProto2.java
-	@touch javac_middleman
-
-conformance-java: javac_middleman
-	@echo "Writing shortcut script conformance-java..."
-	@echo '#! /bin/sh' > conformance-java
-	@jar=`ls ../java/util/target/*jar-with-dependencies.jar` && echo java -classpath .:../java/target/classes:$$jar ConformanceJava '$$@' >> conformance-java
-	@chmod +x conformance-java
-
-javac_middleman_lite: ConformanceJavaLite.java protoc_middleman $(other_language_protoc_outputs)
-	javac -classpath ../java/lite/target/classes:lite ConformanceJavaLite.java lite/com/google/protobuf/conformance/Conformance.java
-	@touch javac_middleman_lite
-
-conformance-java-lite: javac_middleman_lite
-	@echo "Writing shortcut script conformance-java-lite..."
-	@echo '#! /bin/sh' > conformance-java-lite
-	@echo java -classpath .:../java/lite/target/classes:lite ConformanceJavaLite '$$@' >> conformance-java-lite
-	@chmod +x conformance-java-lite
-
-# Currently the conformance code is alongside the rest of the C#
-# source, as it's easier to maintain there. We assume we've already
-# built that, so we just need a script to run it.
-conformance-csharp: $(other_language_protoc_outputs)
-	@echo "Writing shortcut script conformance-csharp..."
-	@echo '#! /bin/sh' > conformance-csharp
-	@echo 'dotnet ../csharp/src/Google.Protobuf.Conformance/bin/Release/netcoreapp3.1/Google.Protobuf.Conformance.dll "$$@"' >> conformance-csharp
-	@chmod +x conformance-csharp
-
-conformance-php:
-	@echo "Writing shortcut script conformance-php..."
-	@echo '#! /bin/sh' > conformance-php
-	@echo 'php -d auto_prepend_file=autoload.php ./conformance_php.php' >> conformance-php
-	@chmod +x conformance-php
-
-conformance-php-c:
-	@echo "Writing shortcut script conformance-php-c..."
-	@echo '#! /bin/sh' > conformance-php-c
-	@echo 'php -dextension=../php/ext/google/protobuf/modules/protobuf.so ./conformance_php.php' >> conformance-php-c
-	@chmod +x conformance-php-c
-
-# 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 --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
-
-test_java_lite: protoc_middleman conformance-test-runner conformance-java-lite
-	./conformance-test-runner --enforce_recommended ./conformance-java-lite
-
-test_csharp: protoc_middleman conformance-test-runner conformance-csharp
-	./conformance-test-runner --enforce_recommended --failure_list failure_list_csharp.txt --text_format_failure_list text_format_failure_list_csharp.txt ./conformance-csharp
-
-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
-
-# 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
-
-test_python_cpp: protoc_middleman conformance-test-runner
-	./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
-
-if OBJC_CONFORMANCE_TEST
-
-test_objc: protoc_middleman conformance-test-runner conformance-objc
-	./conformance-test-runner --enforce_recommended --failure_list failure_list_objc.txt ./conformance-objc
-
-endif
diff --git a/conformance/README.md b/conformance/README.md
index 901d287..8569a6a 100644
--- a/conformance/README.md
+++ b/conformance/README.md
@@ -12,44 +12,77 @@
 in whatever language you want to test communicate with the tester
 program over a pipe.
 
-Before running any of these tests, make sure you run `make` in the base
-directory to build `protoc`, since all the tests depend on it.
+If you're not using Bazel to run these tests, make sure you build the C++
+tester code beforehand, e.g. from the base directory:
 
-    $ make
+    $ cmake . -Dprotobuf_BUILD_CONFORMANCE=ON && cmake --build .
+
+This will produce a `conformance_test_runner` binary that can be used to run
+conformance tests on any executable.  Pass it `--help` for more information.
 
 Running the tests for C++
 -------------------------
 
 To run the tests against the C++ implementation, run:
 
-    $ cd conformance && make test_cpp
+    $ bazel test //src:conformance_test
 
-Running the tests for JavaScript (Node.js)
-------------------------------------------
+Or alternatively with CMake:
 
-To run the JavaScript tests against Node.js, make sure you have "node"
-on your path and then run:
-
-    $ cd conformance && make test_nodejs
-
-Running the tests for Ruby (MRI)
---------------------------------
-
-To run the Ruby tests against MRI, first build the C extension:
-
-    $ cd ruby && rake
-
-Then run the tests like so:
-
-    $ cd conformance && make test_ruby
+    $ ctest -R conformance_cpp_test
 
 Running the tests for other languages
 -------------------------------------
 
-Most of the languages in the Protobuf source tree are set up to run
-conformance tests.  However some of them are more tricky to set up
-properly.  See `tests.sh` in the base of the repository to see how
-Kokoro runs the tests.
+All of the languages in the Protobuf source tree are set up to run conformance
+tests using similar patterns.  You can either use Bazel to run the
+`conformance_test` target defined in the language's root `BUILD.bazel` file,
+or create an executable for a custom test and pass it to
+`conformance_test_runner`.
+
+Note: CMake can be used to build the conformance test runner, but not any of
+the conformance test executables outside C++.  So if you aren't using Bazel
+you'll need to create the executable you pass to `conformance_test_runner` via
+some alternate build system.
+
+While we plan to model all our supported languages more completely in Bazel,
+today some of them are a bit tricky to run.  Below is a list of the commands
+(and prerequisites) to run each language's conformance tests.
+
+Java:
+
+    $ bazel test //java/core:conformance_test //java/lite:conformance_test
+
+Python:
+
+    $ bazel test //python:conformance_test
+
+Python C++:
+
+    $ bazel test //python:conformance_test_cpp --define=use_fast_cpp_protos=true
+
+C#:
+
+    $ `which dotnet || echo "You must have dotnet installed!"
+    $ `bazel test //csharp:conformance_test \
+        --action_env=DOTNET_CLI_TELEMETRY_OPTOUT=1 --test_env=DOTNET_CLI_HOME=~ \
+        --action_env=DOTNET_SYSTEM_GLOBALIZATION_INVARIANT=1
+
+Objective-c (Mac only):
+
+    $ `bazel test //objectivec:conformance_test --macos_minimum_os=10.9
+
+Ruby:
+
+    $ [[ $(ruby --version) == "ruby"* ]] || echo "Select a C Ruby!"
+    $ bazel test //ruby:conformance_test --define=ruby_platform=c \
+        --action_env=PATH --action_env=GEM_PATH --action_env=GEM_HOME
+
+JRuby:
+
+    $ [[ $(ruby --version) == "jruby"* ]] || echo "Switch to Java Ruby!"
+    $ bazel test //ruby:conformance_test_jruby --define=ruby_platform=java \
+        --action_env=PATH --action_env=GEM_PATH --action_env=GEM_HOME
 
 Testing other Protocol Buffer implementations
 ---------------------------------------------
diff --git a/conformance/autoload.php b/conformance/autoload.php
index 0f49aec..7f04cc0 100644
--- a/conformance/autoload.php
+++ b/conformance/autoload.php
@@ -7,7 +7,7 @@
 function protobuf_autoloader_impl($class, $prefix) {
     $length = strlen($prefix);
     if ((substr($class, 0, $length) === $prefix)) {
-        $path = '../php/src/' . implode('/', array_map('ucwords', explode('\\', $class))) . '.php';
+        $path = 'php/src/' . implode('/', array_map('ucwords', explode('\\', $class))) . '.php';
         include_once $path;
     }
 }
diff --git a/conformance/conformance_test_runner.sh b/conformance/bazel_conformance_test_runner.sh
similarity index 81%
rename from conformance/conformance_test_runner.sh
rename to conformance/bazel_conformance_test_runner.sh
index 3149f82..fcf4a48 100755
--- a/conformance/conformance_test_runner.sh
+++ b/conformance/bazel_conformance_test_runner.sh
@@ -1,4 +1,7 @@
 #!/bin/bash
+# This is an internal file that should only be called from Bazel rules.  For
+# custom conformance tests outside of Bazel use CMAKE with
+# -Dprotobuf_BUILD_CONFORMANCE=ON to build the test runner.
 
 set -x
 echo $@
@@ -44,13 +47,13 @@
 conformance_testee=$(rlocation $TESTEE)
 args=(--enforce_recommended)
 
-failure_list=$(rlocation $FAILURE_LIST)
-if [ "$failure_list" != "1" ] ; then
+failure_list=$(rlocation $FAILURE_LIST) || unset
+if [ -n "$failure_list" ] ; then
   args+=(--failure_list $failure_list)
 fi
 
-text_format_failure_list=$(rlocation $TEXT_FORMAT_FAILURE_LIST)
-if [ "$text_format_failure_list" != "1" ]; then
+text_format_failure_list=$(rlocation $TEXT_FORMAT_FAILURE_LIST) || unset
+if [ -n "$text_format_failure_list" ]; then
   args+=(--text_format_failure_list $text_format_failure_list)
 fi
 
diff --git a/conformance/binary_json_conformance_suite.cc b/conformance/binary_json_conformance_suite.cc
index 9b1548d..d1dda61 100644
--- a/conformance/binary_json_conformance_suite.cc
+++ b/conformance/binary_json_conformance_suite.cc
@@ -30,15 +30,17 @@
 
 #include "binary_json_conformance_suite.h"
 
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/util/json_util.h>
-#include <google/protobuf/util/type_resolver_util.h>
-#include "third_party/jsoncpp/json.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/util/json_util.h"
+#include "google/protobuf/util/type_resolver_util.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+#include "json/json.h"
+#include "conformance/conformance.pb.h"
 #include "conformance_test.h"
-#include <google/protobuf/test_messages_proto2.pb.h>
-#include <google/protobuf/test_messages_proto3.pb.h>
-#include <google/protobuf/stubs/status.h>
+#include "google/protobuf/test_messages_proto2.pb.h"
+#include "google/protobuf/test_messages_proto3.pb.h"
+#include "google/protobuf/wire_format_lite.h"
 
 namespace proto2_messages = protobuf_test_messages::proto2;
 
@@ -59,6 +61,10 @@
 
 static const char kTypeUrlPrefix[] = "type.googleapis.com";
 
+// The number of repetitions to use for performance tests.
+// Corresponds approx to 500KB wireformat bytes.
+static const size_t kPerformanceRepeatCount = 50000;
+
 static string GetTypeUrl(const Descriptor* message) {
   return string(kTypeUrlPrefix) + "/" + message->full_name();
 }
@@ -354,7 +360,7 @@
     const ConformanceResponse& response,
     Message* test_message) {
   string binary_protobuf;
-  util::Status status =
+  absl::Status status =
       JsonToBinaryString(type_resolver_.get(), type_url_,
                          response.json_payload(), &binary_protobuf);
 
@@ -384,7 +390,7 @@
     case ConformanceResponse::kProtobufPayload: {
       if (requested_output != conformance::PROTOBUF) {
         ReportFailure(test_name, level, request, response,
-                      StrCat("Test was asked for ",
+                      absl::StrCat("Test was asked for ",
                                    WireFormatToString(requested_output),
                                    " output but provided PROTOBUF instead.")
                           .c_str());
@@ -403,7 +409,7 @@
     case ConformanceResponse::kJsonPayload: {
       if (requested_output != conformance::JSON) {
         ReportFailure(test_name, level, request, response,
-                      StrCat("Test was asked for ",
+                      absl::StrCat("Test was asked for ",
                                    WireFormatToString(requested_output),
                                    " output but provided JSON instead.")
                           .c_str());
@@ -440,7 +446,7 @@
 
   const ConformanceRequest& request = setting.GetRequest();
   ConformanceResponse response;
-  string effective_test_name = StrCat(
+  string effective_test_name = absl::StrCat(
       setting.ConformanceLevelToString(level),
       (is_proto3 ? ".Proto3" : ".Proto2"), ".ProtobufInput.", test_name);
 
@@ -476,6 +482,25 @@
     const string& test_name, ConformanceLevel level, const string& input_json,
     const string& equivalent_text_format) {
   TestAllTypesProto3 prototype;
+  RunValidJsonTestWithMessage(test_name, level, input_json,
+                              equivalent_text_format, prototype);
+}
+
+void BinaryAndJsonConformanceSuite::RunValidJsonTest(
+    const string& test_name, ConformanceLevel level, const string& input_json,
+    const string& equivalent_text_format, bool is_proto3) {
+  if (is_proto3) {
+    RunValidJsonTest(test_name, level, input_json, equivalent_text_format);
+  } else {
+    TestAllTypesProto2 prototype;
+    RunValidJsonTestWithMessage(test_name, level, input_json,
+                                equivalent_text_format, prototype);
+  }
+}
+
+void BinaryAndJsonConformanceSuite::RunValidJsonTestWithMessage(
+    const string& test_name, ConformanceLevel level, const string& input_json,
+    const string& equivalent_text_format, const Message& prototype) {
   ConformanceRequestSetting setting1(
       level, conformance::JSON, conformance::PROTOBUF,
       conformance::JSON_TEST,
@@ -549,6 +574,27 @@
   RunValidBinaryInputTest(setting, expected_protobuf, true);
 }
 
+void BinaryAndJsonConformanceSuite::RunBinaryPerformanceMergeMessageWithField(
+    const string& test_name, const string& field_proto, bool is_proto3) {
+  string message_tag = tag(27, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+  string message_proto = cat(message_tag, delim(field_proto));
+
+  string proto;
+  for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
+    proto.append(message_proto);
+  }
+
+  string multiple_repeated_field_proto;
+  for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
+    multiple_repeated_field_proto.append(field_proto);
+  }
+  string expected_proto =
+      cat(message_tag, delim(multiple_repeated_field_proto));
+
+  RunValidBinaryProtobufTest(test_name, RECOMMENDED, proto, expected_proto,
+                             is_proto3);
+}
+
 void BinaryAndJsonConformanceSuite::RunValidProtobufTestWithMessage(
     const string& test_name, ConformanceLevel level, const Message *input,
     const string& equivalent_text_format, bool is_proto3) {
@@ -571,7 +617,7 @@
   const ConformanceRequest& request = setting.GetRequest();
   ConformanceResponse response;
   string effective_test_name =
-      StrCat(setting.ConformanceLevelToString(level),
+      absl::StrCat(setting.ConformanceLevelToString(level),
                    is_proto3 ? ".Proto3.JsonInput." : ".Proto2.JsonInput.",
                    test_name, ".Validator");
 
@@ -584,16 +630,16 @@
 
   if (response.result_case() != ConformanceResponse::kJsonPayload) {
     ReportFailure(effective_test_name, level, request, response,
-                  "Expected JSON payload but got type %d.",
-                  response.result_case());
+                  absl::StrCat("Expected JSON payload but got type ",
+                               response.result_case()));
     return;
   }
   Json::Reader reader;
   Json::Value value;
   if (!reader.parse(response.json_payload(), value)) {
     ReportFailure(effective_test_name, level, request, response,
-                  "JSON payload cannot be parsed as valid JSON: %s",
-                  reader.getFormattedErrorMessages().c_str());
+                  absl::StrCat("JSON payload cannot be parsed as valid JSON: ",
+                               reader.getFormattedErrorMessages()));
     return;
   }
   if (!validator(value)) {
@@ -615,7 +661,7 @@
       prototype, test_name, input_json);
   const ConformanceRequest& request = setting.GetRequest();
   ConformanceResponse response;
-  string effective_test_name = StrCat(
+  string effective_test_name = absl::StrCat(
       setting.ConformanceLevelToString(level), ".Proto3.JsonInput.", test_name);
 
   RunTest(effective_test_name, request, &response);
@@ -642,7 +688,7 @@
       prototype, test_name, payload_message.SerializeAsString());
   const ConformanceRequest& request = setting.GetRequest();
   ConformanceResponse response;
-  string effective_test_name = StrCat(
+  string effective_test_name = absl::StrCat(
       setting.ConformanceLevelToString(level), ".", test_name, ".JsonOutput");
 
   RunTest(effective_test_name, request, &response);
@@ -765,13 +811,14 @@
               : cat(tag(field->number(), wire_type), values[i].second);
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(expected_proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
       RunValidProtobufTest(
-          StrCat("ValidDataScalar", type_name, "[", i, "]"), REQUIRED,
+          absl::StrCat("ValidDataScalar", type_name, "[", i, "]"), REQUIRED,
           proto, text, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataScalarBinary", type_name, "[", i, "]"),
+          absl::StrCat("ValidDataScalarBinary", type_name, "[", i, "]"),
           RECOMMENDED, proto, expected_proto, is_proto3);
     }
 
@@ -787,7 +834,8 @@
           cat(tag(field->number(), wire_type), values.back().second);
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(expected_proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
       RunValidProtobufTest("RepeatedScalarSelectsLast" + type_name, REQUIRED,
                            proto, text, is_proto3);
@@ -848,14 +896,15 @@
 
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(default_proto_packed_expected);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
       // Ensures both packed and unpacked data can be parsed.
       RunValidProtobufTest(
-          StrCat("ValidDataRepeated", type_name, ".UnpackedInput"),
+          absl::StrCat("ValidDataRepeated", type_name, ".UnpackedInput"),
           REQUIRED, default_proto_unpacked, text, is_proto3);
       RunValidProtobufTest(
-          StrCat("ValidDataRepeated", type_name, ".PackedInput"),
+          absl::StrCat("ValidDataRepeated", type_name, ".PackedInput"),
           REQUIRED, default_proto_packed, text, is_proto3);
 
       // proto2 should encode as unpacked by default and proto3 should encode as
@@ -863,27 +912,27 @@
       string expected_proto = rep_field->is_packed()
                                   ? default_proto_packed_expected
                                   : default_proto_unpacked_expected;
-      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+      RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name,
                                               ".UnpackedInput.DefaultOutput"),
                                  RECOMMENDED, default_proto_unpacked,
                                  expected_proto, is_proto3);
-      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+      RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name,
                                               ".PackedInput.DefaultOutput"),
                                  RECOMMENDED, default_proto_packed,
                                  expected_proto, is_proto3);
-      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+      RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name,
                                               ".UnpackedInput.PackedOutput"),
                                  RECOMMENDED, packed_proto_unpacked,
                                  packed_proto_expected, is_proto3);
-      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+      RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name,
                                               ".PackedInput.PackedOutput"),
                                  RECOMMENDED, packed_proto_packed,
                                  packed_proto_expected, is_proto3);
-      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+      RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name,
                                               ".UnpackedInput.UnpackedOutput"),
                                  RECOMMENDED, unpacked_proto_unpacked,
                                  unpacked_proto_expected, is_proto3);
-      RunValidBinaryProtobufTest(StrCat("ValidDataRepeated", type_name,
+      RunValidBinaryProtobufTest(absl::StrCat("ValidDataRepeated", type_name,
                                               ".PackedInput.UnpackedOutput"),
                                  RECOMMENDED, unpacked_proto_packed,
                                  unpacked_proto_expected, is_proto3);
@@ -897,9 +946,10 @@
       }
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(expected_proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
-      RunValidProtobufTest(StrCat("ValidDataRepeated", type_name),
+      RunValidProtobufTest(absl::StrCat("ValidDataRepeated", type_name),
                            REQUIRED, proto, text, is_proto3);
     }
   }
@@ -974,8 +1024,9 @@
               delim(cat(key1_data, value1_data)));
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
-      RunValidProtobufTest(StrCat("ValidDataMap", key_type_name,
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
+      RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name,
                                         value_type_name, ".Default"),
                            REQUIRED, proto, text, is_proto3);
     }
@@ -987,8 +1038,9 @@
               delim(""));
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
-      RunValidProtobufTest(StrCat("ValidDataMap", key_type_name,
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
+      RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name,
                                         value_type_name, ".MissingDefault"),
                            REQUIRED, proto, text, is_proto3);
     }
@@ -1000,8 +1052,9 @@
               delim(cat(key2_data, value2_data)));
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
-      RunValidProtobufTest(StrCat("ValidDataMap", key_type_name,
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
+      RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name,
                                         value_type_name, ".NonDefault"),
                            REQUIRED, proto, text, is_proto3);
     }
@@ -1013,8 +1066,9 @@
               delim(cat(value2_data, key2_data)));
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
-      RunValidProtobufTest(StrCat("ValidDataMap", key_type_name,
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
+      RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name,
                                         value_type_name, ".Unordered"),
                            REQUIRED, proto, text, is_proto3);
     }
@@ -1030,8 +1084,9 @@
       string proto = cat(proto1, proto2);
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto2);
-      string text = test_message->DebugString();
-      RunValidProtobufTest(StrCat("ValidDataMap", key_type_name,
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
+      RunValidProtobufTest(absl::StrCat("ValidDataMap", key_type_name,
                                         value_type_name, ".DuplicateKey"),
                            REQUIRED, proto, text, is_proto3);
     }
@@ -1043,9 +1098,10 @@
               delim(cat(key1_data, key2_data, value2_data)));
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
       RunValidProtobufTest(
-          StrCat("ValidDataMap", key_type_name, value_type_name,
+          absl::StrCat("ValidDataMap", key_type_name, value_type_name,
                        ".DuplicateKeyInMapEntry"),
           REQUIRED, proto, text, is_proto3);
     }
@@ -1057,9 +1113,10 @@
               delim(cat(key2_data, value1_data, value2_data)));
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
       RunValidProtobufTest(
-          StrCat("ValidDataMap", key_type_name, value_type_name,
+          absl::StrCat("ValidDataMap", key_type_name, value_type_name,
                        ".DuplicateValueInMapEntry"),
           REQUIRED, proto, text, is_proto3);
     }
@@ -1097,7 +1154,8 @@
     string proto = cat(proto1, proto2);
     std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
     test_message->MergeFromString(proto2);
-    string text = test_message->DebugString();
+    string text;
+    TextFormat::PrintToString(*test_message, &text);
     RunValidProtobufTest("ValidDataMap.STRING.MESSAGE.MergeValue", REQUIRED,
                          proto, text, is_proto3);
   }
@@ -1122,13 +1180,14 @@
       const string proto = default_value;
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
       RunValidProtobufTest(
-          StrCat("ValidDataOneof", type_name, ".DefaultValue"), REQUIRED,
+          absl::StrCat("ValidDataOneof", type_name, ".DefaultValue"), REQUIRED,
           proto, text, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataOneofBinary", type_name, ".DefaultValue"),
+          absl::StrCat("ValidDataOneofBinary", type_name, ".DefaultValue"),
           RECOMMENDED, proto, proto, is_proto3);
     }
 
@@ -1137,28 +1196,30 @@
       const string proto = non_default_value;
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
       RunValidProtobufTest(
-          StrCat("ValidDataOneof", type_name, ".NonDefaultValue"),
+          absl::StrCat("ValidDataOneof", type_name, ".NonDefaultValue"),
           REQUIRED, proto, text, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataOneofBinary", type_name, ".NonDefaultValue"),
+          absl::StrCat("ValidDataOneofBinary", type_name, ".NonDefaultValue"),
           RECOMMENDED, proto, proto, is_proto3);
     }
 
     {
       // Tests oneof with multiple values of the same field.
-      const string proto = StrCat(default_value, non_default_value);
+      const string proto = absl::StrCat(default_value, non_default_value);
       const string expected_proto = non_default_value;
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(expected_proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
-      RunValidProtobufTest(StrCat("ValidDataOneof", type_name,
+      RunValidProtobufTest(absl::StrCat("ValidDataOneof", type_name,
                                         ".MultipleValuesForSameField"),
                            REQUIRED, proto, text, is_proto3);
-      RunValidBinaryProtobufTest(StrCat("ValidDataOneofBinary", type_name,
+      RunValidBinaryProtobufTest(absl::StrCat("ValidDataOneofBinary", type_name,
                                               ".MultipleValuesForSameField"),
                                  RECOMMENDED, proto, expected_proto, is_proto3);
     }
@@ -1175,17 +1236,18 @@
           cat(tag(other_field->number(), other_wire_type),
               GetDefaultValue(other_type));
 
-      const string proto = StrCat(other_value, non_default_value);
+      const string proto = absl::StrCat(other_value, non_default_value);
       const string expected_proto = non_default_value;
       std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
       test_message->MergeFromString(expected_proto);
-      string text = test_message->DebugString();
+      string text;
+      TextFormat::PrintToString(*test_message, &text);
 
-      RunValidProtobufTest(StrCat("ValidDataOneof", type_name,
+      RunValidProtobufTest(absl::StrCat("ValidDataOneof", type_name,
                                         ".MultipleValuesForDifferentField"),
                            REQUIRED, proto, text, is_proto3);
       RunValidBinaryProtobufTest(
-          StrCat("ValidDataOneofBinary", type_name,
+          absl::StrCat("ValidDataOneofBinary", type_name,
                        ".MultipleValuesForDifferentField"),
           RECOMMENDED, proto, expected_proto, is_proto3);
     }
@@ -1224,7 +1286,8 @@
 
     std::unique_ptr<Message> test_message = NewTestMessage(is_proto3);
     test_message->MergeFromString(expected_proto);
-    string text = test_message->DebugString();
+    string text;
+    TextFormat::PrintToString(*test_message, &text);
     RunValidProtobufTest("ValidDataOneof.MESSAGE.Merge", REQUIRED, proto, text,
                          is_proto3);
     RunValidBinaryProtobufTest("ValidDataOneofBinary.MESSAGE.Merge",
@@ -1293,6 +1356,60 @@
                              message.SerializeAsString(), is_proto3);
 }
 
+void BinaryAndJsonConformanceSuite::
+    TestBinaryPerformanceForAlternatingUnknownFields() {
+  string unknown_field_1 =
+      cat(tag(UNKNOWN_FIELD, WireFormatLite::WIRETYPE_VARINT), varint(1234));
+  string unknown_field_2 = cat(
+      tag(UNKNOWN_FIELD + 1, WireFormatLite::WIRETYPE_VARINT), varint(5678));
+  for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
+    string proto;
+    for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
+      proto.append(unknown_field_1);
+      proto.append(unknown_field_2);
+    }
+
+    RunValidBinaryProtobufTest(
+        "TestBinaryPerformanceForAlternatingUnknownFields", RECOMMENDED, proto,
+        is_proto3);
+  }
+}
+
+void BinaryAndJsonConformanceSuite::
+    TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+        FieldDescriptor::Type type) {
+  const string type_name =
+      UpperCase(string(".") + FieldDescriptor::TypeName(type));
+  for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
+    int field_number =
+        GetFieldForType(type, true, is_proto3, Packed::kFalse)->number();
+    string rep_field_proto = cat(
+        tag(field_number, WireFormatLite::WireTypeForFieldType(
+                              static_cast<WireFormatLite::FieldType>(type))),
+        GetNonDefaultValue(type));
+
+    RunBinaryPerformanceMergeMessageWithField(
+        "TestBinaryPerformanceMergeMessageWithRepeatedFieldForType" + type_name,
+        rep_field_proto, is_proto3);
+  }
+}
+
+void BinaryAndJsonConformanceSuite::
+    TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+        FieldDescriptor::Type type) {
+  const string type_name =
+      UpperCase(string(".") + FieldDescriptor::TypeName(type));
+  string unknown_field_proto =
+      cat(tag(UNKNOWN_FIELD, WireFormatLite::WireTypeForFieldType(
+                                 static_cast<WireFormatLite::FieldType>(type))),
+          GetNonDefaultValue(type));
+  for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
+    RunBinaryPerformanceMergeMessageWithField(
+        "TestBinaryPerformanceMergeMessageWithUnknownFieldForType" + type_name,
+        unknown_field_proto, is_proto3);
+  }
+}
+
 void BinaryAndJsonConformanceSuite::RunSuiteImpl() {
   // Hack to get the list of test failures based on whether
   // GOOGLE_PROTOBUF_ENABLE_EXPERIMENTAL_PARSER is enabled or not.
@@ -1312,232 +1429,324 @@
       kTypeUrlPrefix, DescriptorPool::generated_pool()));
   type_url_ = GetTypeUrl(TestAllTypesProto3::descriptor());
 
-  for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) {
-    if (i == FieldDescriptor::TYPE_GROUP) continue;
-    TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i));
+  if (!performance_) {
+    for (int i = 1; i <= FieldDescriptor::MAX_TYPE; i++) {
+      if (i == FieldDescriptor::TYPE_GROUP) continue;
+      TestPrematureEOFForType(static_cast<FieldDescriptor::Type>(i));
+    }
+
+    TestIllegalTags();
+
+    int64 kInt64Min = -9223372036854775808ULL;
+    int64 kInt64Max = 9223372036854775807ULL;
+    uint64 kUint64Max = 18446744073709551615ULL;
+    int32 kInt32Max = 2147483647;
+    int32 kInt32Min = -2147483648;
+    uint32 kUint32Max = 4294967295UL;
+
+    TestValidDataForType(
+        FieldDescriptor::TYPE_DOUBLE,
+        {
+            {dbl(0), dbl(0)},
+            {dbl(0.1), dbl(0.1)},
+            {dbl(1.7976931348623157e+308), dbl(1.7976931348623157e+308)},
+            {dbl(2.22507385850720138309e-308),
+             dbl(2.22507385850720138309e-308)},
+        });
+    TestValidDataForType(
+        FieldDescriptor::TYPE_FLOAT,
+        {
+            {flt(0), flt(0)},
+            {flt(0.1), flt(0.1)},
+            {flt(1.00000075e-36), flt(1.00000075e-36)},
+            {flt(3.402823e+38), flt(3.402823e+38)},  // 3.40282347e+38
+            {flt(1.17549435e-38f), flt(1.17549435e-38)},
+        });
+    TestValidDataForType(FieldDescriptor::TYPE_INT64,
+                         {
+                             {varint(0), varint(0)},
+                             {varint(12345), varint(12345)},
+                             {varint(kInt64Max), varint(kInt64Max)},
+                             {varint(kInt64Min), varint(kInt64Min)},
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_UINT64,
+                         {
+                             {varint(0), varint(0)},
+                             {varint(12345), varint(12345)},
+                             {varint(kUint64Max), varint(kUint64Max)},
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_INT32,
+                         {
+                             {varint(0), varint(0)},
+                             {varint(12345), varint(12345)},
+                             {longvarint(12345, 2), varint(12345)},
+                             {longvarint(12345, 7), varint(12345)},
+                             {varint(kInt32Max), varint(kInt32Max)},
+                             {varint(kInt32Min), varint(kInt32Min)},
+                             {varint(1LL << 33), varint(0)},
+                             {varint((1LL << 33) - 1), varint(-1)},
+                             {varint(kInt64Max), varint(-1)},
+                             {varint(kInt64Min + 1), varint(1)},
+                         });
+    TestValidDataForType(
+        FieldDescriptor::TYPE_UINT32,
+        {
+            {varint(0), varint(0)},
+            {varint(12345), varint(12345)},
+            {longvarint(12345, 2), varint(12345)},
+            {longvarint(12345, 7), varint(12345)},
+            {varint(kUint32Max), varint(kUint32Max)},  // UINT32_MAX
+            {varint(1LL << 33), varint(0)},
+            {varint((1LL << 33) + 1), varint(1)},
+            {varint((1LL << 33) - 1), varint((1LL << 32) - 1)},
+            {varint(kInt64Max), varint((1LL << 32) - 1)},
+            {varint(kInt64Min + 1), varint(1)},
+        });
+    TestValidDataForType(FieldDescriptor::TYPE_FIXED64,
+                         {
+                             {u64(0), u64(0)},
+                             {u64(12345), u64(12345)},
+                             {u64(kUint64Max), u64(kUint64Max)},
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_FIXED32,
+                         {
+                             {u32(0), u32(0)},
+                             {u32(12345), u32(12345)},
+                             {u32(kUint32Max), u32(kUint32Max)},  // UINT32_MAX
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_SFIXED64,
+                         {
+                             {u64(0), u64(0)},
+                             {u64(12345), u64(12345)},
+                             {u64(kInt64Max), u64(kInt64Max)},
+                             {u64(kInt64Min), u64(kInt64Min)},
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_SFIXED32,
+                         {
+                             {u32(0), u32(0)},
+                             {u32(12345), u32(12345)},
+                             {u32(kInt32Max), u32(kInt32Max)},
+                             {u32(kInt32Min), u32(kInt32Min)},
+                         });
+    // Bools should be serialized as 0 for false and 1 for true. Parsers should
+    // also interpret any nonzero value as true.
+    TestValidDataForType(FieldDescriptor::TYPE_BOOL,
+                         {
+                             {varint(0), varint(0)},
+                             {varint(1), varint(1)},
+                             {varint(-1), varint(1)},
+                             {varint(12345678), varint(1)},
+                             {varint(1LL << 33), varint(1)},
+                             {varint(kInt64Max), varint(1)},
+                             {varint(kInt64Min), varint(1)},
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_SINT32,
+                         {
+                             {zz32(0), zz32(0)},
+                             {zz32(12345), zz32(12345)},
+                             {zz32(kInt32Max), zz32(kInt32Max)},
+                             {zz32(kInt32Min), zz32(kInt32Min)},
+                             {zz64(kInt32Max + 2LL), zz32(1)},
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_SINT64,
+                         {
+                             {zz64(0), zz64(0)},
+                             {zz64(12345), zz64(12345)},
+                             {zz64(kInt64Max), zz64(kInt64Max)},
+                             {zz64(kInt64Min), zz64(kInt64Min)},
+                         });
+    TestValidDataForType(
+        FieldDescriptor::TYPE_STRING,
+        {
+            {delim(""), delim("")},
+            {delim("Hello world!"), delim("Hello world!")},
+            {delim("\'\"\?\\\a\b\f\n\r\t\v"),
+             delim("\'\"\?\\\a\b\f\n\r\t\v")},       // escape
+            {delim("谷歌"), delim("谷歌")},          // Google in Chinese
+            {delim("\u8C37\u6B4C"), delim("谷歌")},  // unicode escape
+            {delim("\u8c37\u6b4c"), delim("谷歌")},  // lowercase unicode
+            {delim("\xF0\x9F\x98\x81"), delim("\xF0\x9F\x98\x81")},  // emoji: 😁
+        });
+    TestValidDataForType(FieldDescriptor::TYPE_BYTES,
+                         {
+                             {delim(""), delim("")},
+                             {delim("Hello world!"), delim("Hello world!")},
+                             {delim("\x01\x02"), delim("\x01\x02")},
+                             {delim("\xfb"), delim("\xfb")},
+                         });
+    TestValidDataForType(FieldDescriptor::TYPE_ENUM,
+                         {
+                             {varint(0), varint(0)},
+                             {varint(1), varint(1)},
+                             {varint(2), varint(2)},
+                             {varint(-1), varint(-1)},
+                             {varint(kInt64Max), varint(-1)},
+                             {varint(kInt64Min + 1), varint(1)},
+                         });
+    TestValidDataForRepeatedScalarMessage();
+    TestValidDataForType(
+        FieldDescriptor::TYPE_MESSAGE,
+        {
+            {delim(""), delim("")},
+            {delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))),
+             delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))},
+        });
+
+    TestValidDataForMapType(FieldDescriptor::TYPE_INT32,
+                            FieldDescriptor::TYPE_INT32);
+    TestValidDataForMapType(FieldDescriptor::TYPE_INT64,
+                            FieldDescriptor::TYPE_INT64);
+    TestValidDataForMapType(FieldDescriptor::TYPE_UINT32,
+                            FieldDescriptor::TYPE_UINT32);
+    TestValidDataForMapType(FieldDescriptor::TYPE_UINT64,
+                            FieldDescriptor::TYPE_UINT64);
+    TestValidDataForMapType(FieldDescriptor::TYPE_SINT32,
+                            FieldDescriptor::TYPE_SINT32);
+    TestValidDataForMapType(FieldDescriptor::TYPE_SINT64,
+                            FieldDescriptor::TYPE_SINT64);
+    TestValidDataForMapType(FieldDescriptor::TYPE_FIXED32,
+                            FieldDescriptor::TYPE_FIXED32);
+    TestValidDataForMapType(FieldDescriptor::TYPE_FIXED64,
+                            FieldDescriptor::TYPE_FIXED64);
+    TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED32,
+                            FieldDescriptor::TYPE_SFIXED32);
+    TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED64,
+                            FieldDescriptor::TYPE_SFIXED64);
+    TestValidDataForMapType(FieldDescriptor::TYPE_INT32,
+                            FieldDescriptor::TYPE_FLOAT);
+    TestValidDataForMapType(FieldDescriptor::TYPE_INT32,
+                            FieldDescriptor::TYPE_DOUBLE);
+    TestValidDataForMapType(FieldDescriptor::TYPE_BOOL,
+                            FieldDescriptor::TYPE_BOOL);
+    TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
+                            FieldDescriptor::TYPE_STRING);
+    TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
+                            FieldDescriptor::TYPE_BYTES);
+    TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
+                            FieldDescriptor::TYPE_ENUM);
+    TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
+                            FieldDescriptor::TYPE_MESSAGE);
+    // Additional test to check overwriting message value map.
+    TestOverwriteMessageValueMap();
+
+    TestValidDataForOneofType(FieldDescriptor::TYPE_UINT32);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_BOOL);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_UINT64);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_FLOAT);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_DOUBLE);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_STRING);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_BYTES);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_ENUM);
+    TestValidDataForOneofType(FieldDescriptor::TYPE_MESSAGE);
+    // Additional test to check merging oneof message.
+    TestMergeOneofMessage();
+
+    // TODO(haberman):
+    // TestValidDataForType(FieldDescriptor::TYPE_GROUP
+
+    // Unknown fields.
+    {
+      TestAllTypesProto3 messageProto3;
+      TestAllTypesProto2 messageProto2;
+      // TODO(yilunchong): update this behavior when unknown field's behavior
+      // changed in open source. Also delete
+      // Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
+      // from failure list of python_cpp python java
+      TestUnknownMessage(messageProto3, true);
+      TestUnknownMessage(messageProto2, false);
+    }
+
+    RunJsonTests();
   }
-
-  TestIllegalTags();
-
-  int64 kInt64Min = -9223372036854775808ULL;
-  int64 kInt64Max = 9223372036854775807ULL;
-  uint64 kUint64Max = 18446744073709551615ULL;
-  int32 kInt32Max = 2147483647;
-  int32 kInt32Min = -2147483648;
-  uint32 kUint32Max = 4294967295UL;
-
-  TestValidDataForType(
-      FieldDescriptor::TYPE_DOUBLE,
-      {
-          {dbl(0), dbl(0)},
-          {dbl(0.1), dbl(0.1)},
-          {dbl(1.7976931348623157e+308), dbl(1.7976931348623157e+308)},
-          {dbl(2.22507385850720138309e-308), dbl(2.22507385850720138309e-308)},
-      });
-  TestValidDataForType(
-      FieldDescriptor::TYPE_FLOAT,
-      {
-          {flt(0), flt(0)},
-          {flt(0.1), flt(0.1)},
-          {flt(1.00000075e-36), flt(1.00000075e-36)},
-          {flt(3.402823e+38), flt(3.402823e+38)},  // 3.40282347e+38
-          {flt(1.17549435e-38f), flt(1.17549435e-38)},
-      });
-  TestValidDataForType(FieldDescriptor::TYPE_INT64,
-                       {
-                           {varint(0), varint(0)},
-                           {varint(12345), varint(12345)},
-                           {varint(kInt64Max), varint(kInt64Max)},
-                           {varint(kInt64Min), varint(kInt64Min)},
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_UINT64,
-                       {
-                           {varint(0), varint(0)},
-                           {varint(12345), varint(12345)},
-                           {varint(kUint64Max), varint(kUint64Max)},
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_INT32,
-                       {
-                           {varint(0), varint(0)},
-                           {varint(12345), varint(12345)},
-                           {longvarint(12345, 2), varint(12345)},
-                           {longvarint(12345, 7), varint(12345)},
-                           {varint(kInt32Max), varint(kInt32Max)},
-                           {varint(kInt32Min), varint(kInt32Min)},
-                           {varint(1LL << 33), varint(0)},
-                           {varint((1LL << 33) - 1), varint(-1)},
-                           {varint(kInt64Max), varint(-1)},
-                           {varint(kInt64Min + 1), varint(1)},
-                       });
-  TestValidDataForType(
-      FieldDescriptor::TYPE_UINT32,
-      {
-          {varint(0), varint(0)},
-          {varint(12345), varint(12345)},
-          {longvarint(12345, 2), varint(12345)},
-          {longvarint(12345, 7), varint(12345)},
-          {varint(kUint32Max), varint(kUint32Max)},  // UINT32_MAX
-          {varint(1LL << 33), varint(0)},
-          {varint((1LL << 33) + 1), varint(1)},
-          {varint((1LL << 33) - 1), varint((1LL << 32) - 1)},
-          {varint(kInt64Max), varint((1LL << 32) - 1)},
-          {varint(kInt64Min + 1), varint(1)},
-      });
-  TestValidDataForType(FieldDescriptor::TYPE_FIXED64,
-                       {
-                           {u64(0), u64(0)},
-                           {u64(12345), u64(12345)},
-                           {u64(kUint64Max), u64(kUint64Max)},
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_FIXED32,
-                       {
-                           {u32(0), u32(0)},
-                           {u32(12345), u32(12345)},
-                           {u32(kUint32Max), u32(kUint32Max)},  // UINT32_MAX
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_SFIXED64,
-                       {
-                           {u64(0), u64(0)},
-                           {u64(12345), u64(12345)},
-                           {u64(kInt64Max), u64(kInt64Max)},
-                           {u64(kInt64Min), u64(kInt64Min)},
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_SFIXED32,
-                       {
-                           {u32(0), u32(0)},
-                           {u32(12345), u32(12345)},
-                           {u32(kInt32Max), u32(kInt32Max)},
-                           {u32(kInt32Min), u32(kInt32Min)},
-                       });
-  // Bools should be serialized as 0 for false and 1 for true. Parsers should
-  // also interpret any nonzero value as true.
-  TestValidDataForType(FieldDescriptor::TYPE_BOOL,
-                       {
-                           {varint(0), varint(0)},
-                           {varint(1), varint(1)},
-                           {varint(-1), varint(1)},
-                           {varint(12345678), varint(1)},
-                           {varint(1LL << 33), varint(1)},
-                           {varint(kInt64Max), varint(1)},
-                           {varint(kInt64Min), varint(1)},
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_SINT32,
-                       {
-                           {zz32(0), zz32(0)},
-                           {zz32(12345), zz32(12345)},
-                           {zz32(kInt32Max), zz32(kInt32Max)},
-                           {zz32(kInt32Min), zz32(kInt32Min)},
-                           {zz64(kInt32Max + 2LL), zz32(1)},
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_SINT64,
-                       {
-                           {zz64(0), zz64(0)},
-                           {zz64(12345), zz64(12345)},
-                           {zz64(kInt64Max), zz64(kInt64Max)},
-                           {zz64(kInt64Min), zz64(kInt64Min)},
-                       });
-  TestValidDataForType(
-      FieldDescriptor::TYPE_STRING,
-      {
-          {delim(""), delim("")},
-          {delim("Hello world!"), delim("Hello world!")},
-          {delim("\'\"\?\\\a\b\f\n\r\t\v"),
-           delim("\'\"\?\\\a\b\f\n\r\t\v")},       // escape
-          {delim("谷歌"), delim("谷歌")},          // Google in Chinese
-          {delim("\u8C37\u6B4C"), delim("谷歌")},  // unicode escape
-          {delim("\u8c37\u6b4c"), delim("谷歌")},  // lowercase unicode
-          {delim("\xF0\x9F\x98\x81"), delim("\xF0\x9F\x98\x81")},  // emoji: 😁
-      });
-  TestValidDataForType(FieldDescriptor::TYPE_BYTES,
-                       {
-                           {delim(""), delim("")},
-                           {delim("Hello world!"), delim("Hello world!")},
-                           {delim("\x01\x02"), delim("\x01\x02")},
-                           {delim("\xfb"), delim("\xfb")},
-                       });
-  TestValidDataForType(FieldDescriptor::TYPE_ENUM,
-                       {
-                           {varint(0), varint(0)},
-                           {varint(1), varint(1)},
-                           {varint(2), varint(2)},
-                           {varint(-1), varint(-1)},
-                           {varint(kInt64Max), varint(-1)},
-                           {varint(kInt64Min + 1), varint(1)},
-                       });
-  TestValidDataForRepeatedScalarMessage();
-  TestValidDataForType(
-      FieldDescriptor::TYPE_MESSAGE,
-      {
-          {delim(""), delim("")},
-          {delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234))),
-           delim(cat(tag(1, WireFormatLite::WIRETYPE_VARINT), varint(1234)))},
-      });
-
-  TestValidDataForMapType(FieldDescriptor::TYPE_INT32,
-                          FieldDescriptor::TYPE_INT32);
-  TestValidDataForMapType(FieldDescriptor::TYPE_INT64,
-                          FieldDescriptor::TYPE_INT64);
-  TestValidDataForMapType(FieldDescriptor::TYPE_UINT32,
-                          FieldDescriptor::TYPE_UINT32);
-  TestValidDataForMapType(FieldDescriptor::TYPE_UINT64,
-                          FieldDescriptor::TYPE_UINT64);
-  TestValidDataForMapType(FieldDescriptor::TYPE_SINT32,
-                          FieldDescriptor::TYPE_SINT32);
-  TestValidDataForMapType(FieldDescriptor::TYPE_SINT64,
-                          FieldDescriptor::TYPE_SINT64);
-  TestValidDataForMapType(FieldDescriptor::TYPE_FIXED32,
-                          FieldDescriptor::TYPE_FIXED32);
-  TestValidDataForMapType(FieldDescriptor::TYPE_FIXED64,
-                          FieldDescriptor::TYPE_FIXED64);
-  TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED32,
-                          FieldDescriptor::TYPE_SFIXED32);
-  TestValidDataForMapType(FieldDescriptor::TYPE_SFIXED64,
-                          FieldDescriptor::TYPE_SFIXED64);
-  TestValidDataForMapType(FieldDescriptor::TYPE_INT32,
-                          FieldDescriptor::TYPE_FLOAT);
-  TestValidDataForMapType(FieldDescriptor::TYPE_INT32,
-                          FieldDescriptor::TYPE_DOUBLE);
-  TestValidDataForMapType(FieldDescriptor::TYPE_BOOL,
-                          FieldDescriptor::TYPE_BOOL);
-  TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
-                          FieldDescriptor::TYPE_STRING);
-  TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
-                          FieldDescriptor::TYPE_BYTES);
-  TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
-                          FieldDescriptor::TYPE_ENUM);
-  TestValidDataForMapType(FieldDescriptor::TYPE_STRING,
-                          FieldDescriptor::TYPE_MESSAGE);
-  // Additional test to check overwriting message value map.
-  TestOverwriteMessageValueMap();
-
-  TestValidDataForOneofType(FieldDescriptor::TYPE_UINT32);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_BOOL);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_UINT64);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_FLOAT);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_DOUBLE);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_STRING);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_BYTES);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_ENUM);
-  TestValidDataForOneofType(FieldDescriptor::TYPE_MESSAGE);
-  // Additional test to check merging oneof message.
-  TestMergeOneofMessage();
-
-  // TODO(haberman):
-  // TestValidDataForType(FieldDescriptor::TYPE_GROUP
-
-  // Unknown fields.
-  {
-    TestAllTypesProto3 messageProto3;
-    TestAllTypesProto2 messageProto2;
-    // TODO(yilunchong): update this behavior when unknown field's behavior
-    // changed in open source. Also delete
-    // Required.Proto3.ProtobufInput.UnknownVarint.ProtobufOutput
-    // from failure list of python_cpp python java
-    TestUnknownMessage(messageProto3, true);
-    TestUnknownMessage(messageProto2, false);
+  // Flag control performance tests to keep them internal and opt-in only
+  if (performance_) {
+    RunBinaryPerformanceTests();
+    RunJsonPerformanceTests();
   }
+}
 
-  RunJsonTests();
+void BinaryAndJsonConformanceSuite::RunBinaryPerformanceTests() {
+  TestBinaryPerformanceForAlternatingUnknownFields();
+
+  TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_BOOL);
+  TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_DOUBLE);
+  TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_FLOAT);
+  TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_UINT32);
+  TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_UINT64);
+  TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_STRING);
+  TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_BYTES);
+
+  TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      FieldDescriptor::TYPE_BOOL);
+  TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      FieldDescriptor::TYPE_DOUBLE);
+  TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      FieldDescriptor::TYPE_FLOAT);
+  TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      FieldDescriptor::TYPE_UINT32);
+  TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      FieldDescriptor::TYPE_UINT64);
+  TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      FieldDescriptor::TYPE_STRING);
+  TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      FieldDescriptor::TYPE_BYTES);
+}
+
+void BinaryAndJsonConformanceSuite::RunJsonPerformanceTests() {
+  TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_BOOL, "true");
+  TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_DOUBLE, "123");
+  TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_FLOAT, "123");
+  TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_UINT32, "123");
+  TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_UINT64, "123");
+  TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_STRING, "\"foo\"");
+  TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      FieldDescriptor::TYPE_BYTES, "\"foo\"");
+}
+
+// This is currently considered valid input by some languages but not others
+void BinaryAndJsonConformanceSuite::
+    TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+        FieldDescriptor::Type type, string field_value) {
+  const string type_name =
+      UpperCase(string(".") + FieldDescriptor::TypeName(type));
+  for (int is_proto3 = 0; is_proto3 < 2; is_proto3++) {
+    const FieldDescriptor* field =
+        GetFieldForType(type, true, is_proto3, Packed::kFalse);
+    string field_name = field->name();
+
+    string message_field = "\"" + field_name + "\": [" + field_value + "]";
+    string recursive_message =
+        "\"recursive_message\": { " + message_field + "}";
+    string input = "{";
+    input.append(recursive_message);
+    for (size_t i = 1; i < kPerformanceRepeatCount; i++) {
+      input.append("," + recursive_message);
+    }
+    input.append("}");
+
+    string textproto_message_field = field_name + ": " + field_value;
+    string expected_textproto = "recursive_message { ";
+    for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
+      expected_textproto.append(textproto_message_field + " ");
+    }
+    expected_textproto.append("}");
+    RunValidJsonTest(
+        "TestJsonPerformanceMergeMessageWithRepeatedFieldForType" + type_name,
+        RECOMMENDED, input, expected_textproto, is_proto3);
+  }
 }
 
 void BinaryAndJsonConformanceSuite::RunJsonTests() {
@@ -1557,6 +1766,7 @@
   RunJsonTestsForStruct();
   RunJsonTestsForValue();
   RunJsonTestsForAny();
+  RunJsonTestsForUnknownEnumStringValues();
 
   RunValidJsonIgnoreUnknownTest("IgnoreUnknownJsonNumber", REQUIRED,
                                 R"({
@@ -1592,6 +1802,41 @@
   ExpectParseFailureForJson("RejectTopLevelNull", REQUIRED, "null");
 }
 
+void BinaryAndJsonConformanceSuite::RunJsonTestsForUnknownEnumStringValues() {
+  // Tests the handling of unknown enum values when encoded as string labels.
+  // The expected behavior depends on whether unknown fields are ignored:
+  // * when ignored, the parser should ignore the unknown enum string value.
+  // * when not ignored, the parser should fail.
+  struct TestCase {
+    // Used in the test name.
+    string enum_location;
+    // JSON input which will contain the unknown field.
+    string input_json;
+  };
+  const std::vector<TestCase> test_cases = {
+      {"InOptionalField", R"json({
+      "optional_nested_enum": "UNKNOWN_ENUM_VALUE"
+    })json"},
+      {"InRepeatedField", R"json({
+      "repeated_nested_enum": ["UNKNOWN_ENUM_VALUE"]
+    })json"},
+      {"InMapValue", R"json({
+      "map_string_nested_enum": {"key": "UNKNOWN_ENUM_VALUE"}
+    })json"},
+  };
+  for (const TestCase& test_case : test_cases) {
+    // Unknown enum string value is a parse failure when not ignoring unknown
+    // fields.
+    ExpectParseFailureForJson(
+        absl::StrCat("RejectUnknownEnumStringValue", test_case.enum_location),
+        RECOMMENDED, test_case.input_json);
+    // Unknown enum string value is ignored when ignoring unknown fields.
+    RunValidJsonIgnoreUnknownTest(
+        absl::StrCat("IgnoreUnknownEnumStringValue", test_case.enum_location),
+        RECOMMENDED, test_case.input_json, "");
+  }
+}
+
 void BinaryAndJsonConformanceSuite::RunJsonTestsForFieldNameConvention() {
   RunValidJsonTest(
       "FieldNameInSnakeCase", REQUIRED,
@@ -2724,6 +2969,12 @@
       "DurationNull", REQUIRED,
       R"({"optionalDuration": null})",
       "");
+  RunValidJsonTest("DurationNegativeSeconds", REQUIRED,
+                   R"({"optionalDuration": "-5s"})",
+                   "optional_duration: {seconds: -5 nanos: 0}");
+  RunValidJsonTest("DurationNegativeNanos", REQUIRED,
+                   R"({"optionalDuration": "-0.5s"})",
+                   "optional_duration: {seconds: 0 nanos: -500000000}");
 
   ExpectParseFailureForJson(
       "DurationMissingS", REQUIRED,
diff --git a/conformance/binary_json_conformance_suite.h b/conformance/binary_json_conformance_suite.h
index 280ff95..b859921 100644
--- a/conformance/binary_json_conformance_suite.h
+++ b/conformance/binary_json_conformance_suite.h
@@ -31,7 +31,8 @@
 #ifndef CONFORMANCE_BINARY_JSON_CONFORMANCE_SUITE_H
 #define CONFORMANCE_BINARY_JSON_CONFORMANCE_SUITE_H
 
-#include "third_party/jsoncpp/json.h"
+#include "google/protobuf/descriptor.h"
+#include "json/json.h"
 #include "conformance_test.h"
 
 namespace google {
@@ -43,6 +44,8 @@
 
  private:
   void RunSuiteImpl() override;
+  void RunBinaryPerformanceTests();
+  void RunJsonPerformanceTests();
   void RunJsonTests();
   void RunJsonTestsForFieldNameConvention();
   void RunJsonTestsForNonRepeatedTypes();
@@ -53,9 +56,19 @@
   void RunJsonTestsForStruct();
   void RunJsonTestsForValue();
   void RunJsonTestsForAny();
+  void RunJsonTestsForUnknownEnumStringValues();
   void RunValidJsonTest(const std::string& test_name, ConformanceLevel level,
                         const std::string& input_json,
                         const std::string& equivalent_text_format);
+  void RunValidJsonTest(const std::string& test_name, ConformanceLevel level,
+                        const std::string& input_json,
+                        const std::string& equivalent_text_format,
+                        bool is_proto3);
+  void RunValidJsonTestWithMessage(const std::string& test_name,
+                                   ConformanceLevel level,
+                                   const std::string& input_json,
+                                   const std::string& equivalent_text_forma,
+                                   const Message& prototype);
   void RunValidJsonTestWithProtobufInput(
       const std::string& test_name, ConformanceLevel level,
       const protobuf_test_messages::proto3::TestAllTypesProto3& input,
@@ -78,6 +91,10 @@
                                   const std::string& input_protobuf,
                                   const std::string& expected_protobuf,
                                   bool is_proto3);
+  void RunBinaryPerformanceMergeMessageWithField(const std::string& test_name,
+                                                 const std::string& field_proto,
+                                                 bool is_proto3);
+
   void RunValidProtobufTestWithMessage(
       const std::string& test_name, ConformanceLevel level,
       const Message* input, const std::string& equivalent_text_format,
@@ -130,6 +147,13 @@
   void TestValidDataForOneofType(google::protobuf::FieldDescriptor::Type);
   void TestMergeOneofMessage();
   void TestOverwriteMessageValueMap();
+  void TestBinaryPerformanceForAlternatingUnknownFields();
+  void TestBinaryPerformanceMergeMessageWithRepeatedFieldForType(
+      google::protobuf::FieldDescriptor::Type);
+  void TestBinaryPerformanceMergeMessageWithUnknownFieldForType(
+      google::protobuf::FieldDescriptor::Type);
+  void TestJsonPerformanceMergeMessageWithRepeatedFieldForType(
+      google::protobuf::FieldDescriptor::Type, std::string field_value);
 
   std::unique_ptr<google::protobuf::util::TypeResolver> type_resolver_;
   std::string type_url_;
diff --git a/conformance/conformance.proto b/conformance/conformance.proto
index 7248e98..bee04d1 100644
--- a/conformance/conformance.proto
+++ b/conformance/conformance.proto
@@ -29,8 +29,11 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 syntax = "proto3";
+
 package conformance;
+
 option java_package = "com.google.protobuf.conformance";
+option objc_class_prefix = "Conformance";
 
 // This defines the conformance testing protocol.  This protocol exists between
 // the conformance test suite itself and the code being tested.  For each test,
@@ -55,7 +58,7 @@
   UNSPECIFIED = 0;
   PROTOBUF = 1;
   JSON = 2;
-  JSPB = 3;  // Google internal only. Opensource testees just skip it.
+  JSPB = 3;  // Only used inside Google. Opensource testees just skip it.
   TEXT_FORMAT = 4;
 }
 
@@ -69,7 +72,8 @@
   // https://developers.google.com/protocol-buffers/docs/proto3#json_options
   // for more detail.
   JSON_IGNORE_UNKNOWN_PARSING_TEST = 3;
-  // Test jspb wire format. Google internal only. Opensource testees just skip it.
+  // Test jspb wire format. Only used inside Google. Opensource testees just
+  // skip it.
   JSPB_TEST = 4;
   // Test text format. For cpp, java and python, testees can already deal with
   // this type. Testees of other languages can simply skip it.
@@ -92,14 +96,10 @@
   // The payload (whether protobuf of JSON) is always for a
   // protobuf_test_messages.proto3.TestAllTypes proto (as defined in
   // src/google/protobuf/proto3_test_messages.proto).
-  //
-  // TODO(haberman): if/when we expand the conformance tests to support proto2,
-  // we will want to include a field that lets the payload/response be a
-  // protobuf_test_messages.google.protobuf.TestAllTypes message instead.
   oneof payload {
     bytes protobuf_payload = 1;
     string json_payload = 2;
-    // Google internal only.  Opensource testees just skip it.
+    // Only used inside Google.  Opensource testees just skip it.
     string jspb_payload = 7;
     string text_payload = 8;
   }
@@ -113,8 +113,8 @@
   string message_type = 4;
 
   // Each test is given a specific test category. Some category may need
-  // specific support in testee programs. Refer to the definition of TestCategory
-  // for more information.
+  // specific support in testee programs. Refer to the definition of
+  // TestCategory for more information.
   TestCategory test_category = 5;
 
   // Specify details for how to encode jspb.
@@ -140,6 +140,11 @@
     // this field.
     string serialize_error = 6;
 
+    // This should be set if the test program timed out.  The string should
+    // provide more information about what the child process was doing when it
+    // was killed.
+    string timeout_error = 9;
+
     // This should be set if some other error occurred.  This will always
     // indicate that the test failed.  The string can provide more information
     // about the failure.
@@ -158,8 +163,8 @@
     string skipped = 5;
 
     // If the input was successfully parsed and the requested output was JSPB,
-    // serialize to JSPB and set it in this field. JSPB is google internal only
-    // format. Opensource testees can just skip it.
+    // serialize to JSPB and set it in this field. JSPB is only used inside
+    // Google. Opensource testees can just skip it.
     string jspb_payload = 7;
 
     // If the input was successfully parsed and the requested output was
@@ -173,4 +178,3 @@
   // Encode the value field of Any as jspb array if true, otherwise binary.
   bool use_jspb_array_any_format = 1;
 }
-
diff --git a/conformance/conformance_cpp.cc b/conformance/conformance_cpp.cc
index 5782789..eef8a40 100644
--- a/conformance/conformance_cpp.cc
+++ b/conformance/conformance_cpp.cc
@@ -32,165 +32,175 @@
 #include <stdarg.h>
 #include <unistd.h>
 
-#include <google/protobuf/message.h>
-#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>
-#include <google/protobuf/stubs/status.h>
+#include <memory>
+#include <string>
+#include <utility>
 
-using conformance::ConformanceRequest;
-using conformance::ConformanceResponse;
-using google::protobuf::Descriptor;
-using google::protobuf::DescriptorPool;
-using google::protobuf::Message;
-using google::protobuf::MessageFactory;
-using google::protobuf::TextFormat;
-using google::protobuf::util::BinaryToJsonString;
-using google::protobuf::util::JsonParseOptions;
-using google::protobuf::util::JsonToBinaryString;
-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;
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/util/json_util.h"
+#include "google/protobuf/util/type_resolver_util.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "conformance/conformance.pb.h"
+#include "conformance/conformance.pb.h"
+#include "google/protobuf/test_messages_proto2.pb.h"
+#include "google/protobuf/test_messages_proto3.pb.h"
+#include "google/protobuf/test_messages_proto3.pb.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "google/protobuf/stubs/status_macros.h"
 
-static const char kTypeUrlPrefix[] = "type.googleapis.com";
-
-const char* kFailures[] = {
-};
-
-static string GetTypeUrl(const Descriptor* message) {
-  return string(kTypeUrlPrefix) + "/" + message->full_name();
-}
-
-int test_count = 0;
-bool verbose = false;
-TypeResolver* type_resolver;
-string* type_url;
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
+namespace {
+using ::conformance::ConformanceRequest;
+using ::conformance::ConformanceResponse;
+using ::google::protobuf::util::BinaryToJsonString;
+using ::google::protobuf::util::JsonParseOptions;
+using ::google::protobuf::util::JsonToBinaryString;
+using ::google::protobuf::util::NewTypeResolverForDescriptorPool;
+using ::google::protobuf::util::TypeResolver;
+using ::protobuf_test_messages::proto2::TestAllTypesProto2;
+using ::protobuf_test_messages::proto3::TestAllTypesProto3;
 
-using util::Status;
-
-bool CheckedRead(int fd, void *buf, size_t len) {
-  size_t ofs = 0;
+absl::Status ReadFd(int fd, char* buf, size_t len) {
   while (len > 0) {
-    ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
+    ssize_t bytes_read = read(fd, buf, len);
 
-    if (bytes_read == 0) return false;
+    if (bytes_read == 0) {
+      return absl::DataLossError("unexpected EOF");
+    }
 
     if (bytes_read < 0) {
-      GOOGLE_LOG(FATAL) << "Error reading from test runner: " << strerror(errno);
+      return absl::ErrnoToStatus(errno, "error reading from test runner");
     }
 
     len -= bytes_read;
-    ofs += bytes_read;
+    buf += bytes_read;
   }
-
-  return true;
+  return absl::OkStatus();
 }
 
-void CheckedWrite(int fd, const void *buf, size_t len) {
-  if (write(fd, buf, len) != len) {
-    GOOGLE_LOG(FATAL) << "Error writing to test runner: " << strerror(errno);
+absl::Status WriteFd(int fd, const void* buf, size_t len) {
+  if (static_cast<size_t>(write(fd, buf, len)) != len) {
+    return absl::ErrnoToStatus(errno, "error reading to test runner");
   }
+  return absl::OkStatus();
 }
 
-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) {
-    GOOGLE_LOG(FATAL) << "No such message type: " << request.message_type();
+class Harness {
+ public:
+  Harness() {
+    google::protobuf::LinkMessageReflection<TestAllTypesProto2>();
+    google::protobuf::LinkMessageReflection<TestAllTypesProto3>();
+
+    resolver_.reset(NewTypeResolverForDescriptorPool(
+        "type.googleapis.com", DescriptorPool::generated_pool()));
+    type_url_ = absl::StrCat("type.googleapis.com/",
+                             TestAllTypesProto3::GetDescriptor()->full_name());
   }
-  test_message = MessageFactory::generated_factory()->GetPrototype(descriptor)->New();
+
+  absl::StatusOr<ConformanceResponse> RunTest(
+      const ConformanceRequest& request);
+
+  // Returns Ok(true) if we're done processing requests.
+  absl::StatusOr<bool> ServeConformanceRequest();
+
+ private:
+  bool verbose_ = false;
+  std::unique_ptr<TypeResolver> resolver_;
+  std::string type_url_;
+};
+
+absl::StatusOr<ConformanceResponse> Harness::RunTest(
+    const ConformanceRequest& request) {
+  const Descriptor* descriptor =
+      DescriptorPool::generated_pool()->FindMessageTypeByName(
+          request.message_type());
+  if (descriptor == nullptr) {
+    return absl::NotFoundError(
+        absl::StrCat("No such message type: ", request.message_type()));
+  }
+
+  std::unique_ptr<Message> test_message(
+      MessageFactory::generated_factory()->GetPrototype(descriptor)->New());
+  ConformanceResponse response;
 
   switch (request.payload_case()) {
     case ConformanceRequest::kProtobufPayload: {
       if (!test_message->ParseFromString(request.protobuf_payload())) {
-        // Getting parse details would involve something like:
-        //   http://stackoverflow.com/questions/22121922/how-can-i-get-more-details-about-errors-generated-during-protobuf-parsing-c
-        response->set_parse_error("Parse error (no more details available).");
-        return;
+        response.set_parse_error("parse error (no more details available)");
+        return response;
       }
       break;
     }
 
     case ConformanceRequest::kJsonPayload: {
-      string proto_binary;
       JsonParseOptions options;
       options.ignore_unknown_fields =
           (request.test_category() ==
-              conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST);
-      util::Status status =
-          JsonToBinaryString(type_resolver, *type_url, request.json_payload(),
+           conformance::JSON_IGNORE_UNKNOWN_PARSING_TEST);
+
+      std::string proto_binary;
+      absl::Status status =
+          JsonToBinaryString(resolver_.get(), type_url_, request.json_payload(),
                              &proto_binary, options);
       if (!status.ok()) {
-        response->set_parse_error(string("Parse error: ") +
-                                  std::string(status.message()));
-        return;
+        response.set_parse_error(
+            absl::StrCat("parse error: ", status.message()));
+        return response;
       }
 
       if (!test_message->ParseFromString(proto_binary)) {
-        response->set_runtime_error(
-            "Parsing JSON generates invalid proto output.");
-        return;
+        response.set_runtime_error(
+            "parsing JSON generated invalid proto output");
+        return response;
       }
+
       break;
     }
 
     case ConformanceRequest::kTextPayload: {
-      if (!TextFormat::ParseFromString(request.text_payload(), test_message)) {
-        response->set_parse_error("Parse error");
-        return;
+      if (!TextFormat::ParseFromString(request.text_payload(),
+                                       test_message.get())) {
+        response.set_parse_error("parse error (no more details available)");
+        return response;
       }
       break;
     }
 
     case ConformanceRequest::PAYLOAD_NOT_SET:
-      GOOGLE_LOG(FATAL) << "Request didn't have payload.";
-      break;
+      return absl::InvalidArgumentError("request didn't have payload");
 
     default:
-      GOOGLE_LOG(FATAL) << "unknown payload type: " << request.payload_case();
-      break;
-  }
-
-  conformance::FailureSet failures;
-  if (descriptor == failures.GetDescriptor()) {
-    for (const char* s : kFailures) failures.add_failure(s);
-    test_message = &failures;
+      return absl::InvalidArgumentError(
+          absl::StrCat("unknown payload type", request.payload_case()));
   }
 
   switch (request.requested_output_format()) {
     case conformance::UNSPECIFIED:
-      GOOGLE_LOG(FATAL) << "Unspecified output format";
-      break;
+      return absl::InvalidArgumentError("unspecified output format");
 
     case conformance::PROTOBUF: {
-      GOOGLE_CHECK(test_message->SerializeToString(
-          response->mutable_protobuf_payload()));
+      GOOGLE_CHECK(
+          test_message->SerializeToString(response.mutable_protobuf_payload()));
       break;
     }
 
     case conformance::JSON: {
-      string proto_binary;
+      std::string proto_binary;
       GOOGLE_CHECK(test_message->SerializeToString(&proto_binary));
-      util::Status status =
-          BinaryToJsonString(type_resolver, *type_url, proto_binary,
-                             response->mutable_json_payload());
+      absl::Status status =
+          BinaryToJsonString(resolver_.get(), type_url_, proto_binary,
+                             response.mutable_json_payload());
       if (!status.ok()) {
-        response->set_serialize_error(
-            string("Failed to serialize JSON output: ") +
-            std::string(status.message()));
-        return;
+        response.set_serialize_error(absl::StrCat(
+            "failed to serialize JSON output: ", status.message()));
       }
       break;
     }
@@ -199,70 +209,66 @@
       TextFormat::Printer printer;
       printer.SetHideUnknownFields(!request.print_unknown_fields());
       GOOGLE_CHECK(printer.PrintToString(*test_message,
-                                  response->mutable_text_payload()));
+                                  response.mutable_text_payload()));
       break;
     }
 
     default:
-      GOOGLE_LOG(FATAL) << "Unknown output format: "
-                 << request.requested_output_format();
+      return absl::InvalidArgumentError(absl::StrCat(
+          "unknown output format", request.requested_output_format()));
   }
+
+  return response;
 }
 
-bool DoTestIo() {
-  string serialized_input;
-  string serialized_output;
+absl::StatusOr<bool> Harness::ServeConformanceRequest() {
+  uint32_t in_len;
+  if (!ReadFd(STDIN_FILENO, reinterpret_cast<char*>(&in_len), sizeof(in_len))
+           .ok()) {
+    // EOF means we're done.
+    return true;
+  }
+
+  std::string serialized_input;
+  serialized_input.resize(in_len);
+  RETURN_IF_ERROR(ReadFd(STDIN_FILENO, &serialized_input[0], in_len));
+
   ConformanceRequest request;
-  ConformanceResponse response;
-  uint32_t bytes;
+  GOOGLE_CHECK(request.ParseFromString(serialized_input));
 
-  if (!CheckedRead(STDIN_FILENO, &bytes, sizeof(uint32_t))) {
-    // EOF.
-    return false;
+  absl::StatusOr<ConformanceResponse> response = RunTest(request);
+  RETURN_IF_ERROR(response.status());
+
+  std::string serialized_output;
+  response->SerializeToString(&serialized_output);
+
+  uint32_t out_len = static_cast<uint32_t>(serialized_output.size());
+  RETURN_IF_ERROR(WriteFd(STDOUT_FILENO, &out_len, sizeof(out_len)));
+  RETURN_IF_ERROR(WriteFd(STDOUT_FILENO, serialized_output.data(), out_len));
+
+  if (verbose_) {
+    GOOGLE_LOG(INFO) << "conformance-cpp: request=" << request.ShortDebugString()
+              << ", response=" << response->ShortDebugString();
   }
-
-  serialized_input.resize(bytes);
-
-  if (!CheckedRead(STDIN_FILENO, (char*)serialized_input.c_str(), bytes)) {
-    GOOGLE_LOG(ERROR) << "Unexpected EOF on stdin. " << strerror(errno);
-  }
-
-  if (!request.ParseFromString(serialized_input)) {
-    GOOGLE_LOG(FATAL) << "Parse of ConformanceRequest proto failed.";
-    return false;
-  }
-
-  DoTest(request, &response);
-
-  response.SerializeToString(&serialized_output);
-
-  bytes = serialized_output.size();
-  CheckedWrite(STDOUT_FILENO, &bytes, sizeof(uint32_t));
-  CheckedWrite(STDOUT_FILENO, serialized_output.c_str(), bytes);
-
-  if (verbose) {
-    fprintf(stderr, "conformance-cpp: request=%s, response=%s\n",
-            request.ShortDebugString().c_str(),
-            response.ShortDebugString().c_str());
-  }
-
-  test_count++;
-
-  return true;
+  return false;
 }
-
+}  // namespace
 }  // namespace protobuf
 }  // namespace google
 
 int main() {
-  type_resolver = NewTypeResolverForDescriptorPool(
-      kTypeUrlPrefix, DescriptorPool::generated_pool());
-  type_url = new string(GetTypeUrl(TestAllTypesProto3::descriptor()));
-  while (1) {
-    if (!google::protobuf::DoTestIo()) {
-      fprintf(stderr, "conformance-cpp: received EOF from test runner "
-                      "after %d tests, exiting\n", test_count);
-      return 0;
+  google::protobuf::Harness harness;
+  int total_runs = 0;
+  while (true) {
+    auto is_done = harness.ServeConformanceRequest();
+    if (!is_done.ok()) {
+      GOOGLE_LOG(FATAL) << is_done.status();
     }
+    if (*is_done) {
+      break;
+    }
+    total_runs++;
   }
+  GOOGLE_LOG(INFO) << "conformance-cpp: received EOF from test runner after "
+            << total_runs << " tests";
 }
diff --git a/conformance/conformance_nodejs.js b/conformance/conformance_nodejs.js
deleted file mode 100755
index 275fac4..0000000
--- a/conformance/conformance_nodejs.js
+++ /dev/null
@@ -1,189 +0,0 @@
-#!/usr/bin/env node
-// 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.
-
-var conformance = require('conformance_pb');
-var test_messages_proto3 = require('google/protobuf/test_messages_proto3_pb');
-var test_messages_proto2 = require('google/protobuf/test_messages_proto2_pb');
-var fs = require('fs');
-
-var testCount = 0;
-
-function doTest(request) {
-  var testMessage;
-  var response = new conformance.ConformanceResponse();
-
-  try {
-    if (request.getRequestedOutputFormat() == conformance.WireFormat.JSON) {
-      response.setSkipped("JSON not supported.");
-      return response;
-    }
-
-    if (request.getRequestedOutputFormat() ==
-        conformance.WireFormat.TEXT_FORMAT) {
-      response.setSkipped('Text format is not supported as output format.');
-      return response;
-    }
-
-    switch (request.getPayloadCase()) {
-      case conformance.ConformanceRequest.PayloadCase.PROTOBUF_PAYLOAD: {
-        if (request.getMessageType() == "protobuf_test_messages.proto3.TestAllTypesProto3") {
-          try {
-            testMessage = test_messages_proto3.TestAllTypesProto3.deserializeBinary(
-                request.getProtobufPayload());
-          } catch (err) {
-            response.setParseError(err.toString());
-            return response;
-          }
-        } else if (request.getMessageType() == "protobuf_test_messages.proto2.TestAllTypesProto2"){
-          try {
-            testMessage = test_messages_proto2.TestAllTypesProto2.deserializeBinary(
-                request.getProtobufPayload());
-          } catch (err) {
-            response.setParseError(err.toString());
-            return response;
-          }
-        } else {
-          throw "Protobuf request doesn\'t have specific payload type";
-        }
-      } break;
-
-      case conformance.ConformanceRequest.PayloadCase.JSON_PAYLOAD:
-        response.setSkipped("JSON not supported.");
-        return response;
-
-	  case conformance.ConformanceRequest.PayloadCase.TEXT_PAYLOAD:
-	    response.setSkipped("Text format not supported.");
-        return response;
-		
-      case conformance.ConformanceRequest.PayloadCase.PAYLOAD_NOT_SET:
-        response.setRuntimeError("Request didn't have payload");
-        return response;
-    }
-
-    switch (request.getRequestedOutputFormat()) {
-      case conformance.WireFormat.UNSPECIFIED:
-        response.setRuntimeError("Unspecified output format");
-        return response;
-
-      case conformance.WireFormat.PROTOBUF:
-        response.setProtobufPayload(testMessage.serializeBinary());
-
-      case conformance.WireFormat.JSON:
-        response.setSkipped("JSON not supported.");
-        return response;
-
-      default:
-        throw "Request didn't have requested output format";
-    }
-  } catch (err) {
-    response.setRuntimeError(err.toString());
-  }
-
-  return response;
-}
-
-function onEof(totalRead) {
-  if (totalRead == 0) {
-    return undefined;
-  } else {
-    throw "conformance_nodejs: premature EOF on stdin.";
-  }
-}
-
-// Utility function to read a buffer of N bytes.
-function readBuffer(bytes) {
-  var buf = new Buffer(bytes);
-  var totalRead = 0;
-  while (totalRead < bytes) {
-    var read = 0;
-    try {
-      read = fs.readSync(process.stdin.fd, buf, totalRead, bytes - totalRead);
-    } catch (e) {
-      if (e.code == 'EOF') {
-        return onEof(totalRead)
-      } else if (e.code == 'EAGAIN') {
-      } else {
-        throw "conformance_nodejs: Error reading from stdin." + e;
-      }
-    }
-
-    totalRead += read;
-  }
-
-  return buf;
-}
-
-function writeBuffer(buffer) {
-  var totalWritten = 0;
-  while (totalWritten < buffer.length) {
-    totalWritten += fs.writeSync(
-        process.stdout.fd, buffer, totalWritten, buffer.length - totalWritten);
-  }
-}
-
-// Returns true if the test ran successfully, false on legitimate EOF.
-// If EOF is encountered in an unexpected place, raises IOError.
-function doTestIo() {
-  var lengthBuf = readBuffer(4);
-  if (!lengthBuf) {
-    return false;
-  }
-
-  var length = lengthBuf.readInt32LE(0);
-  var serializedRequest = readBuffer(length);
-  if (!serializedRequest) {
-    throw "conformance_nodejs: Failed to read request.";
-  }
-
-  serializedRequest = new Uint8Array(serializedRequest);
-  var request =
-      conformance.ConformanceRequest.deserializeBinary(serializedRequest);
-  var response = doTest(request);
-
-  var serializedResponse = response.serializeBinary();
-
-  lengthBuf = new Buffer(4);
-  lengthBuf.writeInt32LE(serializedResponse.length, 0);
-  writeBuffer(lengthBuf);
-  writeBuffer(new Buffer(serializedResponse));
-
-  testCount += 1
-
-  return true;
-}
-
-while (true) {
-  if (!doTestIo()) {
-    console.error('conformance_nodejs: received EOF from test runner ' +
-                  "after " + testCount + " tests, exiting")
-    break;
-  }
-}
diff --git a/conformance/conformance_objc.m b/conformance/conformance_objc.m
index ab751c8..77fae6a 100644
--- a/conformance/conformance_objc.m
+++ b/conformance/conformance_objc.m
@@ -56,8 +56,7 @@
     return nil;  // EOF.
   }
   if (dataLen != numBytes) {
-    Die(@"Failed to read the request length (%d), only got: %@",
-        numBytes, data);
+    Die(@"Failed to read the request length (%d), only got: %@", numBytes, data);
   }
   return data;
 }
@@ -76,8 +75,9 @@
       Class msgClass = nil;
       if ([request.messageType isEqual:@"protobuf_test_messages.proto3.TestAllTypesProto3"]) {
         msgClass = [Proto3TestAllTypesProto3 class];
-      } else if ([request.messageType isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
-        msgClass = [TestAllTypesProto2 class];
+      } else if ([request.messageType
+                     isEqual:@"protobuf_test_messages.proto2.TestAllTypesProto2"]) {
+        msgClass = [Proto2TestAllTypesProto2 class];
       } else {
         response.runtimeError =
             [NSString stringWithFormat:@"Protobuf request had an unknown message_type: %@",
@@ -87,8 +87,7 @@
       NSError *error = nil;
       testMessage = [msgClass parseFromData:request.protobufPayload error:&error];
       if (!testMessage) {
-        response.parseError =
-            [NSString stringWithFormat:@"Parse error: %@", error];
+        response.parseError = [NSString stringWithFormat:@"Parse error: %@", error];
       }
       break;
     }
@@ -98,9 +97,8 @@
       break;
 
     case ConformanceRequest_Payload_OneOfCase_JspbPayload:
-      response.skipped =
-          @"ConformanceRequest had a jspb_payload ConformanceRequest.payload;"
-          " those aren't supposed to happen with opensource.";
+      response.skipped = @"ConformanceRequest had a jspb_payload ConformanceRequest.payload;"
+                          " those aren't supposed to happen with opensource.";
       break;
 
     case ConformanceRequest_Payload_OneOfCase_TextPayload:
@@ -110,31 +108,31 @@
 
   if (testMessage) {
     switch (request.requestedOutputFormat) {
-      case WireFormat_GPBUnrecognizedEnumeratorValue:
-      case WireFormat_Unspecified:
+      case ConformanceWireFormat_GPBUnrecognizedEnumeratorValue:
+      case ConformanceWireFormat_Unspecified:
         response.runtimeError =
             [NSString stringWithFormat:@"Unrecognized/unspecified output format: %@", request];
         break;
 
-      case WireFormat_Protobuf:
+      case ConformanceWireFormat_Protobuf:
         response.protobufPayload = testMessage.data;
         if (!response.protobufPayload) {
           response.serializeError =
-            [NSString stringWithFormat:@"Failed to make data from: %@", testMessage];
+              [NSString stringWithFormat:@"Failed to make data from: %@", testMessage];
         }
         break;
 
-      case WireFormat_Json:
+      case ConformanceWireFormat_Json:
         response.skipped = @"ObjC doesn't support generating JSON";
         break;
 
-      case WireFormat_Jspb:
+      case ConformanceWireFormat_Jspb:
         response.skipped =
             @"ConformanceRequest had a requested_output_format of JSPB WireFormat; that"
-            " isn't supposed to happen with opensource.";
+             " isn't supposed to happen with opensource.";
         break;
 
-      case WireFormat_TextFormat:
+      case ConformanceWireFormat_TextFormat:
         // ObjC only has partial objc generation, so don't attempt any tests that need
         // support.
         response.skipped = @"ObjC doesn't support generating TextFormat";
@@ -173,8 +171,7 @@
   }
 
   NSError *error = nil;
-  ConformanceRequest *request = [ConformanceRequest parseFromData:data
-                                                            error:&error];
+  ConformanceRequest *request = [ConformanceRequest parseFromData:data error:&error];
   if (!request) {
     Die(@"Failed to parse the message data: %@", error);
   }
diff --git a/conformance/conformance_php.php b/conformance/conformance_php.php
index 9eef0c5..f250ebf 100644
--- a/conformance/conformance_php.php
+++ b/conformance/conformance_php.php
@@ -14,7 +14,7 @@
 require_once("Protobuf_test_messages/Proto3/TestAllTypesProto3/NestedEnum.php");
 
 require_once("GPBMetadata/Conformance.php");
-require_once("GPBMetadata/Google/Protobuf/TestMessagesProto3.php");
+require_once("GPBMetadata/TestMessagesProto3.php");
 
 use  \Conformance\TestCategory;
 use  \Conformance\WireFormat;
@@ -113,7 +113,7 @@
 while(true){
   if (!doTestIO()) {
       fprintf(STDERR,
-             "conformance_php: received EOF from test runner " +
+             "conformance_php: received EOF from test runner " .
              "after %d tests, exiting\n", $test_count);
       exit;
   }
diff --git a/conformance/conformance_python.py b/conformance/conformance_python.py
index 37ee36e..95c29dc 100755
--- a/conformance/conformance_python.py
+++ b/conformance/conformance_python.py
@@ -1,4 +1,4 @@
-#!/usr/bin/env python
+#!/usr/bin/env python3
 # Protocol Buffers - Google's data interchange format
 # Copyright 2008 Google Inc.  All rights reserved.
 # https://developers.google.com/protocol-buffers/
@@ -36,23 +36,21 @@
 
 import struct
 import sys
-import os
 from google.protobuf import json_format
 from google.protobuf import message
-from google.protobuf import test_messages_proto3_pb2
-from google.protobuf import test_messages_proto2_pb2
 from google.protobuf import text_format
-import conformance_pb2
-
-sys.stdout = os.fdopen(sys.stdout.fileno(), 'wb', 0)
-sys.stdin = os.fdopen(sys.stdin.fileno(), 'rb', 0)
+from google.protobuf import test_messages_proto2_pb2
+from google.protobuf import test_messages_proto3_pb2
+from conformance import conformance_pb2
 
 test_count = 0
 verbose = False
 
+
 class ProtocolError(Exception):
   pass
 
+
 def do_test(request):
   response = conformance_pb2.ConformanceResponse()
 
@@ -171,18 +169,16 @@
 
   return response
 
+
 def do_test_io():
-  length_bytes = sys.stdin.read(4)
+  length_bytes = sys.stdin.buffer.read(4)
   if len(length_bytes) == 0:
     return False   # EOF
   elif len(length_bytes) != 4:
     raise IOError("I/O error")
 
-  # "I" is "unsigned int", so this depends on running on a platform with
-  # 32-bit "unsigned int" type.  The Python struct module unfortunately
-  # has no format specifier for uint32_t.
   length = struct.unpack("<I", length_bytes)[0]
-  serialized_request = sys.stdin.read(length)
+  serialized_request = sys.stdin.buffer.read(length)
   if len(serialized_request) != length:
     raise IOError("I/O error")
 
@@ -192,9 +188,9 @@
   response = do_test(request)
 
   serialized_response = response.SerializeToString()
-  sys.stdout.write(struct.pack("<I", len(serialized_response)))
-  sys.stdout.write(serialized_response)
-  sys.stdout.flush()
+  sys.stdout.buffer.write(struct.pack("<I", len(serialized_response)))
+  sys.stdout.buffer.write(serialized_response)
+  sys.stdout.buffer.flush()
 
   if verbose:
     sys.stderr.write("conformance_python: request=%s, response=%s\n" % (
diff --git a/conformance/conformance_test.cc b/conformance/conformance_test.cc
index 2c856f5..00b309a 100644
--- a/conformance/conformance_test.cc
+++ b/conformance/conformance_test.cc
@@ -36,13 +36,15 @@
 #include <set>
 #include <string>
 
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/util/field_comparator.h>
-#include <google/protobuf/util/json_util.h>
-#include <google/protobuf/util/message_differencer.h>
-#include "conformance.pb.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/util/field_comparator.h"
+#include "google/protobuf/util/json_util.h"
+#include "google/protobuf/util/message_differencer.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "conformance/conformance.pb.h"
+#include "conformance/conformance.pb.h"
 
 using conformance::ConformanceRequest;
 using conformance::ConformanceResponse;
@@ -129,7 +131,7 @@
       prototype_message_.GetDescriptor()->file()->syntax() ==
         FileDescriptor::SYNTAX_PROTO3 ? "Proto3" : "Proto2";
 
-  return StrCat(ConformanceLevelToString(level_), ".", rname, ".",
+  return absl::StrCat(ConformanceLevelToString(level_), ".", rname, ".",
                       InputFormatString(input_format_), ".", test_name_, ".",
                       OutputFormatString(output_format_));
 }
@@ -175,12 +177,66 @@
   return "";
 }
 
+void ConformanceTestSuite::TruncateDebugPayload(string* payload) {
+  if (payload != nullptr && payload->size() > 200) {
+    payload->resize(200);
+    payload->append("...(truncated)");
+  }
+}
+
+const ConformanceRequest ConformanceTestSuite::TruncateRequest(
+    const ConformanceRequest& request) {
+  ConformanceRequest debug_request(request);
+  switch (debug_request.payload_case()) {
+    case ConformanceRequest::kProtobufPayload:
+      TruncateDebugPayload(debug_request.mutable_protobuf_payload());
+      break;
+    case ConformanceRequest::kJsonPayload:
+      TruncateDebugPayload(debug_request.mutable_json_payload());
+      break;
+    case ConformanceRequest::kTextPayload:
+      TruncateDebugPayload(debug_request.mutable_text_payload());
+      break;
+    case ConformanceRequest::kJspbPayload:
+      TruncateDebugPayload(debug_request.mutable_jspb_payload());
+      break;
+    default:
+      // Do nothing.
+      break;
+  }
+  return debug_request;
+}
+
+const ConformanceResponse ConformanceTestSuite::TruncateResponse(
+    const ConformanceResponse& response) {
+  ConformanceResponse debug_response(response);
+  switch (debug_response.result_case()) {
+    case ConformanceResponse::kProtobufPayload:
+      TruncateDebugPayload(debug_response.mutable_protobuf_payload());
+      break;
+    case ConformanceResponse::kJsonPayload:
+      TruncateDebugPayload(debug_response.mutable_json_payload());
+      break;
+    case ConformanceResponse::kTextPayload:
+      TruncateDebugPayload(debug_response.mutable_text_payload());
+      break;
+    case ConformanceResponse::kJspbPayload:
+      TruncateDebugPayload(debug_response.mutable_jspb_payload());
+      break;
+    default:
+      // Do nothing.
+      break;
+  }
+  return debug_response;
+}
+
 void ConformanceTestSuite::ReportSuccess(const string& test_name) {
   if (expected_to_fail_.erase(test_name) != 0) {
-    StringAppendF(&output_,
-                  "ERROR: test %s is in the failure list, but test succeeded.  "
-                  "Remove it from the failure list.\n",
-                  test_name.c_str());
+    absl::StrAppendFormat(
+        &output_,
+        "ERROR: test %s is in the failure list, but test succeeded.  "
+        "Remove it from the failure list.\n",
+        test_name);
     unexpected_succeeding_tests_.insert(test_name);
   }
   successes_++;
@@ -190,33 +246,30 @@
                                          ConformanceLevel level,
                                          const ConformanceRequest& request,
                                          const ConformanceResponse& response,
-                                         const char* fmt, ...) {
+                                         absl::string_view message) {
   if (expected_to_fail_.erase(test_name) == 1) {
     expected_failures_++;
     if (!verbose_)
       return;
   } else if (level == RECOMMENDED && !enforce_recommended_) {
-    StringAppendF(&output_, "WARNING, test=%s: ", test_name.c_str());
+    absl::StrAppendFormat(&output_, "WARNING, test=%s: ", test_name);
   } else {
-    StringAppendF(&output_, "ERROR, test=%s: ", test_name.c_str());
+    absl::StrAppendFormat(&output_, "ERROR, test=%s: ", test_name);
     unexpected_failing_tests_.insert(test_name);
   }
-  va_list args;
-  va_start(args, fmt);
-  StringAppendV(&output_, fmt, args);
-  va_end(args);
-  StringAppendF(&output_, " request=%s, response=%s\n",
-                request.ShortDebugString().c_str(),
-                response.ShortDebugString().c_str());
+
+  absl::StrAppendFormat(&output_, "%s, request=%s, response=%s\n", message,
+                        TruncateRequest(request).ShortDebugString(),
+                        TruncateResponse(response).ShortDebugString());
 }
 
 void ConformanceTestSuite::ReportSkip(const string& test_name,
                                       const ConformanceRequest& request,
                                       const ConformanceResponse& response) {
   if (verbose_) {
-    StringAppendF(&output_, "SKIPPED, test=%s request=%s, response=%s\n",
-                  test_name.c_str(), request.ShortDebugString().c_str(),
-                  response.ShortDebugString().c_str());
+    absl::StrAppendFormat(
+        &output_, "SKIPPED, test=%s request=%s, response=%s\n", test_name,
+        request.ShortDebugString(), response.ShortDebugString());
   }
   skipped_.insert(test_name);
 }
@@ -263,6 +316,7 @@
       return;
 
     case ConformanceResponse::kParseError:
+    case ConformanceResponse::kTimeoutError:
     case ConformanceResponse::kRuntimeError:
     case ConformanceResponse::kSerializeError:
       ReportFailure(test_name, level, request, response,
@@ -290,7 +344,7 @@
     GOOGLE_DCHECK_EQ(response.result_case(), ConformanceResponse::kProtobufPayload);
     const string& protobuf_payload = response.protobuf_payload();
     check = equivalent_wire_format == protobuf_payload;
-    differences = StrCat("Expect: ", ToOctString(equivalent_wire_format),
+    differences = absl::StrCat("Expect: ", ToOctString(equivalent_wire_format),
                                ", but got: ", ToOctString(protobuf_payload));
   } else {
     check = differencer.Compare(*reference_message, *test_message);
@@ -301,9 +355,10 @@
       ReportSuccess(test_name);
     }
   } else {
-    ReportFailure(test_name, level, request, response,
-                  "Output was not equivalent to reference message: %s.",
-                  differences.c_str());
+    ReportFailure(
+        test_name, level, request, response,
+        absl::StrCat("Output was not equivalent to reference message: ",
+                     differences));
   }
 }
 
@@ -326,11 +381,10 @@
   }
 
   if (verbose_) {
-    StringAppendF(&output_,
-                  "conformance test: name=%s, request=%s, response=%s\n",
-                  test_name.c_str(),
-                  request.ShortDebugString().c_str(),
-                  response->ShortDebugString().c_str());
+    absl::StrAppendFormat(
+        &output_, "conformance test: name=%s, request=%s, response=%s\n",
+        test_name, TruncateRequest(request).ShortDebugString(),
+        TruncateResponse(*response).ShortDebugString());
   }
 }
 
@@ -341,13 +395,12 @@
   if (set_to_check.empty()) {
     return true;
   } else {
-    StringAppendF(&output_, "\n");
-    StringAppendF(&output_, "%s\n\n", msg.c_str());
-    for (std::set<string>::const_iterator iter = set_to_check.begin();
-         iter != set_to_check.end(); ++iter) {
-      StringAppendF(&output_, "  %s\n", iter->c_str());
+    absl::StrAppendFormat(&output_, "\n");
+    absl::StrAppendFormat(&output_, "%s\n\n", msg);
+    for (absl::string_view v : set_to_check) {
+      absl::StrAppendFormat(&output_, "  %s\n", v);
     }
-    StringAppendF(&output_, "\n");
+    absl::StrAppendFormat(&output_, "\n");
 
     if (!write_to_file.empty()) {
       std::string full_filename;
@@ -362,13 +415,11 @@
       }
       std::ofstream os(*filename);
       if (os) {
-        for (std::set<string>::const_iterator iter = set_to_check.begin();
-             iter != set_to_check.end(); ++iter) {
-          os << *iter << "\n";
+        for (absl::string_view v : set_to_check) {
+          os << v << "\n";
         }
       } else {
-        StringAppendF(&output_, "Failed to open file: %s\n",
-                      filename->c_str());
+        absl::StrAppendFormat(&output_, "Failed to open file: %s\n", *filename);
       }
     }
 
@@ -452,12 +503,12 @@
                   "features is not implemented)");
   }
 
-  StringAppendF(&output_,
-                "CONFORMANCE SUITE %s: %d successes, %zu skipped, "
-                "%d expected failures, %zu unexpected failures.\n",
-                ok ? "PASSED" : "FAILED", successes_, skipped_.size(),
-                expected_failures_, unexpected_failing_tests_.size());
-  StringAppendF(&output_, "\n");
+  absl::StrAppendFormat(&output_,
+                        "CONFORMANCE SUITE %s: %d successes, %zu skipped, "
+                        "%d expected failures, %zu unexpected failures.\n",
+                        ok ? "PASSED" : "FAILED", successes_, skipped_.size(),
+                        expected_failures_, unexpected_failing_tests_.size());
+  absl::StrAppendFormat(&output_, "\n");
 
   output->assign(output_);
 
diff --git a/conformance/conformance_test.h b/conformance/conformance_test.h
index 83d94f8..7539cf5 100644
--- a/conformance/conformance_test.h
+++ b/conformance/conformance_test.h
@@ -42,10 +42,10 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/util/type_resolver.h>
-#include "conformance.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "conformance/conformance.pb.h"
+#include "google/protobuf/wire_format_lite.h"
 
 namespace conformance {
 class ConformanceRequest;
@@ -88,10 +88,12 @@
                  const std::vector<ConformanceTestSuite*>& suites);
 
   ForkPipeRunner(const std::string& executable,
-                 const std::vector<std::string>& executable_args)
+                 const std::vector<std::string>& executable_args,
+                 bool performance)
       : child_pid_(-1),
         executable_(executable),
-        executable_args_(executable_args) {}
+        executable_args_(executable_args),
+        performance_(performance) {}
 
   explicit ForkPipeRunner(const std::string& executable)
       : child_pid_(-1), executable_(executable) {}
@@ -114,6 +116,7 @@
   pid_t child_pid_;
   std::string executable_;
   const std::vector<std::string> executable_args_;
+  bool performance_;
   std::string current_test_name_;
 };
 
@@ -148,10 +151,12 @@
  public:
   ConformanceTestSuite()
       : verbose_(false),
+        performance_(false),
         enforce_recommended_(false),
         failure_list_flag_name_("--failure_list") {}
   virtual ~ConformanceTestSuite() {}
 
+  void SetPerformance(bool performance) { performance_ = performance; }
   void SetVerbose(bool verbose) { verbose_ = verbose; }
 
   // Whether to require the testee to pass RECOMMENDED tests. By default failing
@@ -272,11 +277,17 @@
                       const conformance::ConformanceResponse& response,
                       bool need_report_success, bool require_same_wire_format);
 
+  void TruncateDebugPayload(std::string* payload);
+  const conformance::ConformanceRequest TruncateRequest(
+      const conformance::ConformanceRequest& request);
+  const conformance::ConformanceResponse TruncateResponse(
+      const conformance::ConformanceResponse& response);
+
   void ReportSuccess(const std::string& test_name);
   void ReportFailure(const std::string& test_name, ConformanceLevel level,
                      const conformance::ConformanceRequest& request,
                      const conformance::ConformanceResponse& response,
-                     const char* fmt, ...);
+                     absl::string_view message);
   void ReportSkip(const std::string& test_name,
                   const conformance::ConformanceRequest& request,
                   const conformance::ConformanceResponse& response);
@@ -299,6 +310,7 @@
   int successes_;
   int expected_failures_;
   bool verbose_;
+  bool performance_;
   bool enforce_recommended_;
   std::string output_;
   std::string output_dir_;
diff --git a/conformance/conformance_test_runner.cc b/conformance/conformance_test_runner.cc
index 2aac35c..a60bdee 100644
--- a/conformance/conformance_test_runner.cc
+++ b/conformance/conformance_test_runner.cc
@@ -54,16 +54,19 @@
 //   4. testee sends M bytes representing a ConformanceResponse proto
 
 #include <errno.h>
+#include <signal.h>
 #include <sys/types.h>
 #include <sys/wait.h>
 #include <unistd.h>
 
 #include <algorithm>
+#include <cstdlib>
 #include <fstream>
+#include <future>
 #include <vector>
 
-#include <google/protobuf/stubs/stringprintf.h>
-#include "conformance.pb.h"
+#include "absl/strings/str_format.h"
+#include "conformance/conformance.pb.h"
 #include "conformance_test.h"
 
 using conformance::ConformanceResponse;
@@ -73,10 +76,10 @@
 
 #define STRINGIFY(x) #x
 #define TOSTRING(x) STRINGIFY(x)
-#define GOOGLE_CHECK_SYSCALL(call) \
-  if (call < 0) { \
+#define GOOGLE_CHECK_SYSCALL(call)                            \
+  if (call < 0) {                                      \
     perror(#call " " __FILE__ ":" TOSTRING(__LINE__)); \
-    exit(1); \
+    exit(1);                                           \
   }
 
 namespace google {
@@ -93,8 +96,7 @@
 
   for (string line; getline(infile, line);) {
     // Remove whitespace.
-    line.erase(std::remove_if(line.begin(), line.end(), ::isspace),
-               line.end());
+    line.erase(std::remove_if(line.begin(), line.end(), ::isspace), line.end());
 
     // Remove comments.
     line = line.substr(0, line.find("#"));
@@ -106,8 +108,7 @@
 }
 
 void UsageError() {
-  fprintf(stderr,
-          "Usage: conformance-test-runner [options] <test-program>\n");
+  fprintf(stderr, "Usage: conformance-test-runner [options] <test-program>\n");
   fprintf(stderr, "\n");
   fprintf(stderr, "Options:\n");
   fprintf(stderr,
@@ -122,8 +123,7 @@
           "  --text_format_failure_list <filename>   Use to specify list \n");
   fprintf(stderr,
           "                              of tests that are expected to \n");
-  fprintf(stderr,
-          "                              fail in the \n");
+  fprintf(stderr, "                              fail in the \n");
   fprintf(stderr,
           "                              text_format_conformance_suite.  \n");
   fprintf(stderr,
@@ -139,22 +139,19 @@
           "                              this flag if you want to be\n");
   fprintf(stderr,
           "                              strictly conforming to protobuf\n");
-  fprintf(stderr,
-          "                              spec.\n");
+  fprintf(stderr, "                              spec.\n");
   fprintf(stderr,
           "  --output_dir                <dirname> Directory to write\n"
           "                              output files.\n");
   exit(1);
 }
 
-void ForkPipeRunner::RunTest(
-    const std::string& test_name,
-    const std::string& request,
-    std::string* response) {
+void ForkPipeRunner::RunTest(const std::string &test_name,
+                             const std::string &request,
+                             std::string *response) {
   if (child_pid_ < 0) {
     SpawnTestProgram();
   }
-
   current_test_name_ = test_name;
 
   uint32_t len = request.size();
@@ -169,44 +166,55 @@
     waitpid(child_pid_, &status, WEXITED);
 
     string error_msg;
+    conformance::ConformanceResponse response_obj;
     if (WIFEXITED(status)) {
-      StringAppendF(&error_msg,
-                    "child exited, status=%d", WEXITSTATUS(status));
+      if (WEXITSTATUS(status) == 0) {
+        absl::StrAppendFormat(&error_msg,
+                              "child timed out, killed by signal %d",
+                              WTERMSIG(status));
+        response_obj.set_timeout_error(error_msg);
+      } else {
+        absl::StrAppendFormat(&error_msg, "child exited, status=%d",
+                              WEXITSTATUS(status));
+        response_obj.set_runtime_error(error_msg);
+      }
     } else if (WIFSIGNALED(status)) {
-      StringAppendF(&error_msg,
-                    "child killed by signal %d", WTERMSIG(status));
+      absl::StrAppendFormat(&error_msg, "child killed by signal %d",
+                            WTERMSIG(status));
     }
     GOOGLE_LOG(INFO) << error_msg;
     child_pid_ = -1;
 
-    conformance::ConformanceResponse response_obj;
-    response_obj.set_runtime_error(error_msg);
     response_obj.SerializeToString(response);
     return;
   }
 
   response->resize(len);
-  CheckedRead(read_fd_, (void*)response->c_str(), len);
+  CheckedRead(read_fd_, (void *)response->c_str(), len);
 }
 
-int ForkPipeRunner::Run(
-    int argc, char *argv[], const std::vector<ConformanceTestSuite*>& suites) {
+int ForkPipeRunner::Run(int argc, char *argv[],
+                        const std::vector<ConformanceTestSuite *> &suites) {
   if (suites.empty()) {
     fprintf(stderr, "No test suites found.\n");
     return EXIT_FAILURE;
   }
   bool all_ok = true;
-  for (ConformanceTestSuite* suite : suites) {
+  for (ConformanceTestSuite *suite : suites) {
     string program;
     std::vector<string> program_args;
     string failure_list_filename;
     conformance::FailureSet failure_list;
 
+    bool performance = false;
     for (int arg = 1; arg < argc; ++arg) {
       if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) {
         if (++arg == argc) UsageError();
         failure_list_filename = argv[arg];
         ParseFailureList(argv[arg], &failure_list);
+      } else if (strcmp(argv[arg], "--performance") == 0) {
+        performance = true;
+        suite->SetPerformance(true);
       } else if (strcmp(argv[arg], "--verbose") == 0) {
         suite->SetVerbose(true);
       } else if (strcmp(argv[arg], "--enforce_recommended") == 0) {
@@ -216,7 +224,7 @@
         suite->SetOutputDir(argv[arg]);
       } else if (argv[arg][0] == '-') {
         bool recognized_flag = false;
-        for (ConformanceTestSuite* suite : suites) {
+        for (ConformanceTestSuite *suite : suites) {
           if (strcmp(argv[arg], suite->GetFailureListFlagName().c_str()) == 0) {
             if (++arg == argc) UsageError();
             recognized_flag = true;
@@ -227,7 +235,7 @@
           UsageError();
         }
       } else {
-        program += argv[arg];
+        program += argv[arg++];
         while (arg < argc) {
           program_args.push_back(argv[arg]);
           arg++;
@@ -235,11 +243,11 @@
       }
     }
 
-    ForkPipeRunner runner(program, program_args);
+    ForkPipeRunner runner(program, program_args, performance);
 
     std::string output;
-    all_ok = all_ok &&
-        suite->RunSuite(&runner, &output, failure_list_filename, &failure_list);
+    all_ok = all_ok && suite->RunSuite(&runner, &output, failure_list_filename,
+                                       &failure_list);
 
     fwrite(output.c_str(), 1, output.size(), stderr);
   }
@@ -303,8 +311,10 @@
 
     std::vector<const char *> argv;
     argv.push_back(executable.get());
+    GOOGLE_LOG(INFO) << argv[0];
     for (size_t i = 0; i < executable_args_.size(); ++i) {
       argv.push_back(executable_args_[i].c_str());
+      GOOGLE_LOG(INFO) << executable_args_[i];
     }
     argv.push_back(nullptr);
     // Never returns.
@@ -322,8 +332,36 @@
 bool ForkPipeRunner::TryRead(int fd, void *buf, size_t len) {
   size_t ofs = 0;
   while (len > 0) {
-    ssize_t bytes_read = read(fd, (char*)buf + ofs, len);
-
+    std::future<ssize_t> future = std::async(
+        std::launch::async,
+        [](int fd, void *buf, size_t ofs, size_t len) {
+          return read(fd, (char *)buf + ofs, len);
+        },
+        fd, buf, ofs, len);
+    std::future_status status;
+    if (performance_) {
+      status = future.wait_for(std::chrono::seconds(5));
+      if (status == std::future_status::timeout) {
+        GOOGLE_LOG(ERROR) << current_test_name_ << ": timeout from test program";
+        kill(child_pid_, SIGQUIT);
+        // TODO(sandyzhang): Only log in flag-guarded mode, since reading output
+        // from SIGQUIT is slow and verbose.
+        std::vector<char> err;
+        err.resize(5000);
+        ssize_t err_bytes_read;
+        size_t err_ofs = 0;
+        do {
+          err_bytes_read =
+              read(fd, (void *)&err[err_ofs], err.size() - err_ofs);
+          err_ofs += err_bytes_read;
+        } while (err_bytes_read > 0 && err_ofs < err.size());
+        GOOGLE_LOG(ERROR) << "child_pid_=" << child_pid_ << " SIGQUIT: \n" << &err[0];
+        return false;
+      }
+    } else {
+      future.wait();
+    }
+    ssize_t bytes_read = future.get();
     if (bytes_read == 0) {
       GOOGLE_LOG(ERROR) << current_test_name_ << ": unexpected EOF from test program";
       return false;
diff --git a/conformance/defs.bzl b/conformance/defs.bzl
index 905953a..8daef86 100644
--- a/conformance/defs.bzl
+++ b/conformance/defs.bzl
@@ -1,6 +1,24 @@
-# PLEASE DO NOT DEPEND ON THE CONTENTS OF THIS FILE, IT IS UNSTABLE.
+"""Starlark definitions for Protobuf conformance tests.
 
-def conformance_test(name, testee, failure_list = None, text_format_failure_list = None):
+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,
+        **kwargs):
+    """Conformance test runner.
+
+    Args:
+      name: the name for the test.
+      testee: a conformance test client binary.
+      failure_list: a text file with known failures, one per line.
+      text_format_failure_list: a text file with known failures (one per line)
+          for the text format conformance suite.
+      **kwargs: common arguments to pass to sh_test.
+    """
     args = ["--testee %s" % _strip_bazel(testee)]
     failure_lists = []
     if failure_list:
@@ -12,7 +30,7 @@
 
     native.sh_test(
         name = name,
-        srcs = ["//conformance:conformance_test_runner.sh"],
+        srcs = ["//conformance:bazel_conformance_test_runner.sh"],
         data = [testee] + failure_lists + [
             "//conformance:conformance_test_runner",
         ],
@@ -20,6 +38,8 @@
         deps = [
             "@bazel_tools//tools/bash/runfiles",
         ],
+        tags = ["conformance"],
+        **kwargs
     )
 
 def _strip_bazel(testee):
diff --git a/conformance/failure_list_cpp.txt b/conformance/failure_list_cpp.txt
index d55fa9f..78a50f0 100644
--- a/conformance/failure_list_cpp.txt
+++ b/conformance/failure_list_cpp.txt
@@ -12,13 +12,12 @@
 Recommended.FieldMaskTooManyUnderscore.JsonOutput
 Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedFalse
 Recommended.Proto3.JsonInput.BoolFieldDoubleQuotedTrue
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
-Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
 Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
 Recommended.Proto3.JsonInput.FieldNameDuplicate
 Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing1
 Recommended.Proto3.JsonInput.FieldNameDuplicateDifferentCasing2
 Recommended.Proto3.JsonInput.FieldNameNotQuoted
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
 Recommended.Proto3.JsonInput.MapFieldValueIsNull
 Recommended.Proto3.JsonInput.RepeatedFieldMessageElementIsNull
 Recommended.Proto3.JsonInput.RepeatedFieldPrimitiveElementIsNull
diff --git a/conformance/failure_list_js.txt b/conformance/failure_list_js.txt
deleted file mode 100644
index b7d36b6..0000000
--- a/conformance/failure_list_js.txt
+++ /dev/null
@@ -1,162 +0,0 @@
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.DefaultOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.PackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.UnpackedOutput.ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.ENUM[4].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.ENUM[5].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.FIXED64[2].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.INT32[7].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.INT64[2].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.SFIXED64[2].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.SINT64[2].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.UINT32[8].ProtobufOutput
-Recommended.Proto2.ProtobufInput.ValidDataScalarBinary.UINT64[2].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.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.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.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.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.ENUM[4].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.ENUM[5].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.FIXED64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT32[7].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.INT64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SFIXED64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.SINT64[2].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT32[8].ProtobufOutput
-Recommended.Proto3.ProtobufInput.ValidDataScalarBinary.UINT64[2].ProtobufOutput
-Required.Proto2.ProtobufInput.RepeatedScalarSelectsLast.ENUM.ProtobufOutput
-Required.Proto2.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
-Required.Proto2.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.ENUM[4].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.ENUM[5].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.FIXED64[2].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.INT32[7].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.INT64[2].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.SFIXED64[2].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.SINT64[2].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.UINT32[8].ProtobufOutput
-Required.Proto2.ProtobufInput.ValidDataScalar.UINT64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.ENUM.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.FIXED64.ProtobufOutput
-Required.Proto3.ProtobufInput.RepeatedScalarSelectsLast.UINT64.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.ENUM.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.FIXED64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.INT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SFIXED64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.SINT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT32.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.PackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataRepeated.UINT64.UnpackedInput.ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[4].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.ENUM[5].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.FIXED64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT32[7].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.INT64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SFIXED64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.SINT64[2].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT32[8].ProtobufOutput
-Required.Proto3.ProtobufInput.ValidDataScalar.UINT64[2].ProtobufOutput
diff --git a/conformance/failure_list_php.txt b/conformance/failure_list_php.txt
index 667f80c..4876e10 100644
--- a/conformance/failure_list_php.txt
+++ b/conformance/failure_list_php.txt
@@ -5,9 +5,13 @@
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.JsonOutput
 Recommended.Proto3.JsonInput.BytesFieldBase64Url.ProtobufOutput
 Recommended.Proto3.JsonInput.FieldMaskInvalidCharacter
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
 Required.Proto3.JsonInput.DoubleFieldTooSmall
+Required.Proto3.JsonInput.DurationNegativeNanos.JsonOutput
+Required.Proto3.JsonInput.DurationNegativeNanos.ProtobufOutput
 Required.Proto3.JsonInput.FloatFieldTooLarge
 Required.Proto3.JsonInput.FloatFieldTooSmall
 Required.Proto3.JsonInput.Int32FieldNotInteger
diff --git a/conformance/failure_list_php_c.txt b/conformance/failure_list_php_c.txt
index 63c7e8a..2844486 100644
--- a/conformance/failure_list_php_c.txt
+++ b/conformance/failure_list_php_c.txt
@@ -1,2 +1,4 @@
 Recommended.Proto2.JsonInput.FieldNameExtension.Validator
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
 Required.Proto2.JsonInput.StoresDefaultPrimitive.Validator
diff --git a/conformance/failure_list_python.txt b/conformance/failure_list_python.txt
index e69de29..8bbf094 100644
--- a/conformance/failure_list_python.txt
+++ b/conformance/failure_list_python.txt
@@ -0,0 +1,3 @@
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
diff --git a/conformance/failure_list_python_cpp.txt b/conformance/failure_list_python_cpp.txt
index 9efb6cf..de84bd3 100644
--- a/conformance/failure_list_python_cpp.txt
+++ b/conformance/failure_list_python_cpp.txt
@@ -6,3 +6,6 @@
 #
 # TODO(haberman): insert links to corresponding bugs tracking the issue.
 # Should we use GitHub issues or the Google-internal bug tracker?
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInOptionalField.ProtobufOutput
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
diff --git a/conformance/failure_list_ruby.txt b/conformance/failure_list_ruby.txt
index 4938202..3c74439 100644
--- a/conformance/failure_list_ruby.txt
+++ b/conformance/failure_list_ruby.txt
@@ -27,6 +27,8 @@
 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.JsonInput.IgnoreUnknownEnumStringValueInMapValue.ProtobufOutput
+Recommended.Proto3.JsonInput.IgnoreUnknownEnumStringValueInRepeatedField.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataOneofBinary.MESSAGE.Merge.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.PackedInput.UnpackedOutput.ProtobufOutput
 Recommended.Proto3.ProtobufInput.ValidDataRepeated.BOOL.UnpackedInput.UnpackedOutput.ProtobufOutput
diff --git a/conformance/text_format_conformance_suite.cc b/conformance/text_format_conformance_suite.cc
index 460bc24..81dde5f 100644
--- a/conformance/text_format_conformance_suite.cc
+++ b/conformance/text_format_conformance_suite.cc
@@ -30,11 +30,11 @@
 
 #include "text_format_conformance_suite.h"
 
-#include <google/protobuf/any.pb.h>
-#include <google/protobuf/text_format.h>
+#include "google/protobuf/any.pb.h"
+#include "google/protobuf/text_format.h"
 #include "conformance_test.h"
-#include <google/protobuf/test_messages_proto2.pb.h>
-#include <google/protobuf/test_messages_proto3.pb.h>
+#include "google/protobuf/test_messages_proto2.pb.h"
+#include "google/protobuf/test_messages_proto3.pb.h"
 
 namespace proto2_messages = protobuf_test_messages::proto2;
 
@@ -51,6 +51,10 @@
 namespace google {
 namespace protobuf {
 
+// The number of repetitions to use for performance tests.
+// Corresponds approx to 500KB wireformat bytes.
+static const size_t kPerformanceRepeatCount = 50000;
+
 TextFormatConformanceTestSuite::TextFormatConformanceTestSuite() {
   SetFailureListFlagName("--text_format_failure_list");
 }
@@ -85,10 +89,9 @@
     case ConformanceResponse::kProtobufPayload: {
       if (requested_output != conformance::PROTOBUF) {
         ReportFailure(test_name, level, request, response,
-                      StrCat("Test was asked for ",
+                      absl::StrCat("Test was asked for ",
                                    WireFormatToString(requested_output),
-                                   " output but provided PROTOBUF instead.")
-                          .c_str());
+                                   " output but provided PROTOBUF instead."));
         return false;
       }
 
@@ -103,11 +106,11 @@
 
     case ConformanceResponse::kTextPayload: {
       if (requested_output != conformance::TEXT_FORMAT) {
-        ReportFailure(test_name, level, request, response,
-                      StrCat("Test was asked for ",
-                                   WireFormatToString(requested_output),
-                                   " output but provided TEXT_FORMAT instead.")
-                          .c_str());
+        ReportFailure(
+            test_name, level, request, response,
+            absl::StrCat("Test was asked for ",
+                         WireFormatToString(requested_output),
+                         " output but provided TEXT_FORMAT instead."));
         return false;
       }
 
@@ -141,7 +144,7 @@
   const ConformanceRequest& request = setting.GetRequest();
   ConformanceResponse response;
   string effective_test_name =
-      StrCat(setting.ConformanceLevelToString(level),
+      absl::StrCat(setting.ConformanceLevelToString(level),
                    ".Proto3.TextFormatInput.", test_name);
 
   RunTest(effective_test_name, request, &response);
@@ -167,6 +170,22 @@
   RunValidTextFormatTestWithMessage(test_name, level, input_text, prototype);
 }
 
+void TextFormatConformanceTestSuite::RunValidTextFormatTestWithExpected(
+    const string& test_name, ConformanceLevel level, const string& input_text,
+    const string& expected_text) {
+  TestAllTypesProto3 prototype;
+  RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text,
+                                    prototype);
+}
+
+void TextFormatConformanceTestSuite::RunValidTextFormatTestProto2WithExpected(
+    const string& test_name, ConformanceLevel level, const string& input_text,
+    const string& expected_text) {
+  TestAllTypesProto2 prototype;
+  RunValidTextFormatTestWithMessage(test_name, level, input_text, expected_text,
+                                    prototype);
+}
+
 void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage(
     const string& test_name, ConformanceLevel level, const string& input_text,
     const Message& prototype) {
@@ -180,6 +199,19 @@
   RunValidInputTest(setting2, input_text);
 }
 
+void TextFormatConformanceTestSuite::RunValidTextFormatTestWithMessage(
+    const string& test_name, ConformanceLevel level, const string& input_text,
+    const string& expected_text, const Message& prototype) {
+  ConformanceRequestSetting setting1(
+      level, conformance::TEXT_FORMAT, conformance::PROTOBUF,
+      conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
+  RunValidInputTest(setting1, expected_text);
+  ConformanceRequestSetting setting2(
+      level, conformance::TEXT_FORMAT, conformance::TEXT_FORMAT,
+      conformance::TEXT_FORMAT_TEST, prototype, test_name, input_text);
+  RunValidInputTest(setting2, expected_text);
+}
+
 void TextFormatConformanceTestSuite::RunValidUnknownTextFormatTest(
     const string& test_name, const Message& message) {
   string serialized_input;
@@ -202,276 +234,324 @@
 }
 
 void TextFormatConformanceTestSuite::RunSuiteImpl() {
-  RunValidTextFormatTest("HelloWorld", REQUIRED,
-                         "optional_string: 'Hello, World!'");
-  // Integer fields.
-  RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED,
-                         "optional_int32: 2147483647");
-  RunValidTextFormatTest("Int32FieldMinValue", REQUIRED,
-                         "optional_int32: -2147483648");
-  RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED,
-                         "optional_uint32: 4294967295");
-  RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED,
-                         "optional_int64: 9223372036854775807");
-  RunValidTextFormatTest("Int64FieldMinValue", REQUIRED,
-                         "optional_int64: -9223372036854775808");
-  RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED,
-                         "optional_uint64: 18446744073709551615");
+  if (!performance_) {
+    RunValidTextFormatTest("HelloWorld", REQUIRED,
+                           "optional_string: 'Hello, World!'");
+    // Integer fields.
+    RunValidTextFormatTest("Int32FieldMaxValue", REQUIRED,
+                           "optional_int32: 2147483647");
+    RunValidTextFormatTest("Int32FieldMinValue", REQUIRED,
+                           "optional_int32: -2147483648");
+    RunValidTextFormatTest("Uint32FieldMaxValue", REQUIRED,
+                           "optional_uint32: 4294967295");
+    RunValidTextFormatTest("Int64FieldMaxValue", REQUIRED,
+                           "optional_int64: 9223372036854775807");
+    RunValidTextFormatTest("Int64FieldMinValue", REQUIRED,
+                           "optional_int64: -9223372036854775808");
+    RunValidTextFormatTest("Uint64FieldMaxValue", REQUIRED,
+                           "optional_uint64: 18446744073709551615");
 
-  // Parsers reject out-of-bound integer values.
-  ExpectParseFailure("Int32FieldTooLarge", REQUIRED,
-                     "optional_int32: 2147483648");
-  ExpectParseFailure("Int32FieldTooSmall", REQUIRED,
-                     "optional_int32: -2147483649");
-  ExpectParseFailure("Uint32FieldTooLarge", REQUIRED,
-                     "optional_uint32: 4294967296");
-  ExpectParseFailure("Int64FieldTooLarge", REQUIRED,
-                     "optional_int64: 9223372036854775808");
-  ExpectParseFailure("Int64FieldTooSmall", REQUIRED,
-                     "optional_int64: -9223372036854775809");
-  ExpectParseFailure("Uint64FieldTooLarge", REQUIRED,
-                     "optional_uint64: 18446744073709551616");
+    // Parsers reject out-of-bound integer values.
+    ExpectParseFailure("Int32FieldTooLarge", REQUIRED,
+                       "optional_int32: 2147483648");
+    ExpectParseFailure("Int32FieldTooSmall", REQUIRED,
+                       "optional_int32: -2147483649");
+    ExpectParseFailure("Uint32FieldTooLarge", REQUIRED,
+                       "optional_uint32: 4294967296");
+    ExpectParseFailure("Int64FieldTooLarge", REQUIRED,
+                       "optional_int64: 9223372036854775808");
+    ExpectParseFailure("Int64FieldTooSmall", REQUIRED,
+                       "optional_int64: -9223372036854775809");
+    ExpectParseFailure("Uint64FieldTooLarge", REQUIRED,
+                       "optional_uint64: 18446744073709551616");
 
-  // Floating point fields
-  RunValidTextFormatTest("FloatField", REQUIRED,
-                         "optional_float: 3.192837");
-  RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED,
-                         "optional_float: 3.123456789123456789");
-  RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED,
-                         "optional_float: 3.4028235e+38");
-  RunValidTextFormatTest("FloatFieldMinValue", REQUIRED,
-                         "optional_float: 1.17549e-38");
-  RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED,
-                         "optional_float: NaN");
-  RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED,
-                         "optional_float: inf");
-  RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED,
-                         "optional_float: -inf");
-  RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED,
-                         "optional_float: 4294967296");
-  RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED,
-                         "optional_float: 9223372036854775808");
-  RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED,
-                         "optional_float: 3.4028235e+39");
-  RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED,
-                         "optional_float: 1.17549e-39");
-  RunValidTextFormatTest("FloatFieldLargerThanUint64", REQUIRED,
-                         "optional_float: 18446744073709551616");
+    // Floating point fields
+    RunValidTextFormatTest("FloatField", REQUIRED, "optional_float: 3.192837");
+    RunValidTextFormatTest("FloatFieldWithVeryPreciseNumber", REQUIRED,
+                           "optional_float: 3.123456789123456789");
+    RunValidTextFormatTest("FloatFieldMaxValue", REQUIRED,
+                           "optional_float: 3.4028235e+38");
+    RunValidTextFormatTest("FloatFieldMinValue", REQUIRED,
+                           "optional_float: 1.17549e-38");
+    RunValidTextFormatTest("FloatFieldNaNValue", REQUIRED,
+                           "optional_float: NaN");
+    RunValidTextFormatTest("FloatFieldPosInfValue", REQUIRED,
+                           "optional_float: inf");
+    RunValidTextFormatTest("FloatFieldNegInfValue", REQUIRED,
+                           "optional_float: -inf");
+    RunValidTextFormatTest("FloatFieldWithInt32Max", REQUIRED,
+                           "optional_float: 4294967296");
+    RunValidTextFormatTest("FloatFieldLargerThanInt64", REQUIRED,
+                           "optional_float: 9223372036854775808");
+    RunValidTextFormatTest("FloatFieldTooLarge", REQUIRED,
+                           "optional_float: 3.4028235e+39");
+    RunValidTextFormatTest("FloatFieldTooSmall", REQUIRED,
+                           "optional_float: 1.17549e-39");
+    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'"));
+    // 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(
+          absl::StrCat("StringLiteralConcat", field_type), REQUIRED,
+          absl::StrCat(field_name, ": 'first' \"second\"\n'third'"));
+      RunValidTextFormatTest(
+          absl::StrCat("StringLiteralBasicEscapes", field_type), REQUIRED,
+          absl::StrCat(field_name, ": '\\a\\b\\f\\n\\r\\t\\v\\?\\\\\\'\\\"'"));
+      RunValidTextFormatTest(
+          absl::StrCat("StringLiteralOctalEscapes", field_type), REQUIRED,
+          absl::StrCat(field_name, ": '\\341\\210\\264'"));
+      RunValidTextFormatTest(
+          absl::StrCat("StringLiteralHexEscapes", field_type), REQUIRED,
+          absl::StrCat(field_name, ": '\\xe1\\x88\\xb4'"));
+      RunValidTextFormatTest(
+          absl::StrCat("StringLiteralShortUnicodeEscape", field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\u1234'"));
+      RunValidTextFormatTest(
+          absl::StrCat("StringLiteralLongUnicodeEscapes", field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\U00001234\\U00010437'"));
+      // String literals don't include line feeds.
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralIncludesLF", field_type), REQUIRED,
+          absl::StrCat(field_name, ": 'first line\nsecond line'"));
+      // Unicode escapes don't include code points that lie beyond the planes
+      // (> 0x10ffff).
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralLongUnicodeEscapeTooLarge", field_type),
+          REQUIRED, absl::StrCat(field_name, ": '\\U00110000'"));
+      // Unicode escapes don't include surrogates.
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralShortUnicodeEscapeSurrogatePair",
+                       field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\ud801\\udc37'"));
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateFirstOnly",
+                       field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\ud800'"));
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralShortUnicodeEscapeSurrogateSecondOnly",
+                       field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\udc00'"));
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateFirstOnly",
+                       field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d800'"));
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralLongUnicodeEscapeSurrogateSecondOnly",
+                       field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\U0000dc00'"));
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralLongUnicodeEscapeSurrogatePair",
+                       field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\U00000dc37'"));
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairLongShort",
+                       field_type),
+          RECOMMENDED, absl::StrCat(field_name, ": '\\U0000d801\\udc37'"));
+      ExpectParseFailure(
+          absl::StrCat("StringLiteralUnicodeEscapeSurrogatePairShortLong",
+                       field_type),
+          RECOMMENDED, absl::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;
+      // 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'"));
+      // String fields reject invalid UTF-8 byte sequences; bytes fields don't.
+      (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Octal"),
+                           REQUIRED, absl::StrCat(field_name, ": '\\300'"));
+      (this->*test_method)(absl::StrCat(field_type, "FieldBadUTF8Hex"),
+                           REQUIRED, absl::StrCat(field_name, ": '\\xc0'"));
+    }
+
+    // Group fields
+    RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED,
+                                 "Data { group_int32: 1 }");
+    RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED,
+                                 "Data: { group_int32: 1 }");
+    RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED, "Data {}");
+
+    // Unknown Fields
+    UnknownToTestAllTypes message;
+    // Unable to print unknown Fixed32/Fixed64 fields as if they are known.
+    // Fixed32/Fixed64 fields are not added in the tests.
+    message.set_optional_int32(123);
+    message.set_optional_string("hello");
+    message.set_optional_bool(true);
+    RunValidUnknownTextFormatTest("ScalarUnknownFields", message);
+
+    message.Clear();
+    message.mutable_nested_message()->set_c(111);
+    RunValidUnknownTextFormatTest("MessageUnknownFields", message);
+
+    message.Clear();
+    message.mutable_optionalgroup()->set_a(321);
+    RunValidUnknownTextFormatTest("GroupUnknownFields", message);
+
+    message.add_repeated_int32(1);
+    message.add_repeated_int32(2);
+    message.add_repeated_int32(3);
+    RunValidUnknownTextFormatTest("RepeatedUnknownFields", message);
+
+    // Any fields
+    RunValidTextFormatTest("AnyField", REQUIRED,
+                           R"(
+        optional_any: {
+          [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
+            optional_int32: 12345
+          }
+        }
+        )");
+    RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED,
+                           R"(
+        optional_any: {
+          type_url: "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
+          value: "\b\271`"
+        }
+        )");
+    ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED,
+                       R"(
+        optional_any: {
+          [type.googleapis.com/unknown] {
+            optional_int32: 12345
+          }
+        }
+        )");
+
+    // Map fields
+    TestAllTypesProto3 prototype;
+    (*prototype.mutable_map_string_string())["c"] = "value";
+    (*prototype.mutable_map_string_string())["b"] = "value";
+    (*prototype.mutable_map_string_string())["a"] = "value";
+    RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys",
+                                      REQUIRED,
+                                      R"(
+        map_string_string {
+          key: "a"
+          value: "value"
+        }
+        map_string_string {
+          key: "b"
+          value: "value"
+        }
+        map_string_string {
+          key: "c"
+          value: "value"
+        }
+        )",
+                                      prototype);
+
+    prototype.Clear();
+    (*prototype.mutable_map_int32_int32())[3] = 0;
+    (*prototype.mutable_map_int32_int32())[2] = 0;
+    (*prototype.mutable_map_int32_int32())[1] = 0;
+    RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys",
+                                      REQUIRED,
+                                      R"(
+        map_int32_int32 {
+          key: 1
+          value: 0
+        }
+        map_int32_int32 {
+          key: 2
+          value: 0
+        }
+        map_int32_int32 {
+          key: 3
+          value: 0
+        }
+        )",
+                                      prototype);
+
+    prototype.Clear();
+    (*prototype.mutable_map_bool_bool())[true] = false;
+    (*prototype.mutable_map_bool_bool())[false] = false;
+    RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys",
+                                      REQUIRED,
+                                      R"(
+        map_bool_bool {
+          key: false
+          value: false
+        }
+        map_bool_bool {
+          key: true
+          value: false
+        }
+        )",
+                                      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: {} }
+        }
+        )");
+  }
+  // Flag control performance tests to keep them internal and opt-in only
+  if (performance_) {
+    RunTextFormatPerformanceTests();
+  }
+}
+
+void TextFormatConformanceTestSuite::RunTextFormatPerformanceTests() {
+  TestTextFormatPerformanceMergeMessageWithRepeatedField("Bool",
+                                                         "repeated_bool: true");
+  TestTextFormatPerformanceMergeMessageWithRepeatedField(
+      "Double", "repeated_double: 123");
+  TestTextFormatPerformanceMergeMessageWithRepeatedField(
+      "Int32", "repeated_uint32: 123");
+  TestTextFormatPerformanceMergeMessageWithRepeatedField(
+      "Int64", "repeated_uint64: 123");
+  TestTextFormatPerformanceMergeMessageWithRepeatedField(
+      "String", R"(repeated_string: "foo")");
+  TestTextFormatPerformanceMergeMessageWithRepeatedField(
+      "Bytes", R"(repeated_bytes: "foo")");
+}
+
+// This is currently considered valid input by some languages but not others
+void TextFormatConformanceTestSuite::
+    TestTextFormatPerformanceMergeMessageWithRepeatedField(
+        const string& test_type_name, const string& message_field) {
+  string recursive_message = "recursive_message { " + message_field + " }";
+
+  string input;
+  for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
+    input.append(recursive_message);
   }
 
-  // Group fields
-  RunValidTextFormatTestProto2("GroupFieldNoColon", REQUIRED,
-                               "Data { group_int32: 1 }");
-  RunValidTextFormatTestProto2("GroupFieldWithColon", REQUIRED,
-                               "Data: { group_int32: 1 }");
-  RunValidTextFormatTestProto2("GroupFieldEmpty", REQUIRED,
-                               "Data {}");
+  string expected = "recursive_message { ";
+  for (size_t i = 0; i < kPerformanceRepeatCount; i++) {
+    expected.append(message_field + " ");
+  }
+  expected.append("}");
 
-
-  // Unknown Fields
-  UnknownToTestAllTypes message;
-  // Unable to print unknown Fixed32/Fixed64 fields as if they are known.
-  // Fixed32/Fixed64 fields are not added in the tests.
-  message.set_optional_int32(123);
-  message.set_optional_string("hello");
-  message.set_optional_bool(true);
-  RunValidUnknownTextFormatTest("ScalarUnknownFields", message);
-
-  message.Clear();
-  message.mutable_nested_message()->set_c(111);
-  RunValidUnknownTextFormatTest("MessageUnknownFields", message);
-
-  message.Clear();
-  message.mutable_optionalgroup()->set_a(321);
-  RunValidUnknownTextFormatTest("GroupUnknownFields", message);
-
-  message.add_repeated_int32(1);
-  message.add_repeated_int32(2);
-  message.add_repeated_int32(3);
-  RunValidUnknownTextFormatTest("RepeatedUnknownFields", message);
-
-  // Any fields
-  RunValidTextFormatTest("AnyField", REQUIRED,
-                         R"(
-      optional_any: {
-        [type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3] {
-          optional_int32: 12345
-        }
-      }
-      )");
-  RunValidTextFormatTest("AnyFieldWithRawBytes", REQUIRED,
-                         R"(
-      optional_any: {
-        type_url: "type.googleapis.com/protobuf_test_messages.proto3.TestAllTypesProto3"
-        value: "\b\271`"
-      }
-      )");
-  ExpectParseFailure("AnyFieldWithInvalidType", REQUIRED,
-                     R"(
-      optional_any: {
-        [type.googleapis.com/unknown] {
-          optional_int32: 12345
-        }
-      }
-      )");
-
-  // Map fields
-  TestAllTypesProto3 prototype;
-  (*prototype.mutable_map_string_string())["c"] = "value";
-  (*prototype.mutable_map_string_string())["b"] = "value";
-  (*prototype.mutable_map_string_string())["a"] = "value";
-  RunValidTextFormatTestWithMessage("AlphabeticallySortedMapStringKeys",
-                                    REQUIRED,
-                                    R"(
-      map_string_string {
-        key: "a"
-        value: "value"
-      }
-      map_string_string {
-        key: "b"
-        value: "value"
-      }
-      map_string_string {
-        key: "c"
-        value: "value"
-      }
-      )",
-                                    prototype);
-
-  prototype.Clear();
-  (*prototype.mutable_map_int32_int32())[3] = 0;
-  (*prototype.mutable_map_int32_int32())[2] = 0;
-  (*prototype.mutable_map_int32_int32())[1] = 0;
-  RunValidTextFormatTestWithMessage("AlphabeticallySortedMapIntKeys", REQUIRED,
-                                    R"(
-      map_int32_int32 {
-        key: 1
-        value: 0
-      }
-      map_int32_int32 {
-        key: 2
-        value: 0
-      }
-      map_int32_int32 {
-        key: 3
-        value: 0
-      }
-      )",
-                                    prototype);
-
-  prototype.Clear();
-  (*prototype.mutable_map_bool_bool())[true] = false;
-  (*prototype.mutable_map_bool_bool())[false] = false;
-  RunValidTextFormatTestWithMessage("AlphabeticallySortedMapBoolKeys", REQUIRED,
-                                    R"(
-      map_bool_bool {
-        key: false
-        value: false
-      }
-      map_bool_bool {
-        key: true
-        value: false
-      }
-      )",
-                                    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: {} }
-      }
-      )");
+  RunValidTextFormatTestProto2WithExpected(
+      "TestTextFormatPerformanceMergeMessageWithRepeatedField" +
+          test_type_name + "Proto2",
+      RECOMMENDED, input, expected);
+  RunValidTextFormatTestWithExpected(
+      "TestTextFormatPerformanceMergeMessageWithRepeatedField" +
+          test_type_name + "Proto3",
+      RECOMMENDED, input, expected);
 }
 
 }  // namespace protobuf
diff --git a/conformance/text_format_conformance_suite.h b/conformance/text_format_conformance_suite.h
index e875f31..e594cac 100644
--- a/conformance/text_format_conformance_suite.h
+++ b/conformance/text_format_conformance_suite.h
@@ -42,15 +42,29 @@
 
  private:
   void RunSuiteImpl() override;
+  void RunTextFormatPerformanceTests();
   void RunValidTextFormatTest(const std::string& test_name,
                               ConformanceLevel level, const std::string& input);
   void RunValidTextFormatTestProto2(const std::string& test_name,
                                     ConformanceLevel level,
                                     const std::string& input);
+  void RunValidTextFormatTestWithExpected(const std::string& test_name,
+                                          ConformanceLevel level,
+                                          const std::string& input,
+                                          const std::string& expected);
+  void RunValidTextFormatTestProto2WithExpected(const std::string& test_name,
+                                                ConformanceLevel level,
+                                                const std::string& input,
+                                                const std::string& expected);
   void RunValidTextFormatTestWithMessage(const std::string& test_name,
                                          ConformanceLevel level,
                                          const std::string& input_text,
                                          const Message& prototype);
+  void RunValidTextFormatTestWithMessage(const std::string& test_name,
+                                         ConformanceLevel level,
+                                         const std::string& input_text,
+                                         const std::string& expected_text,
+                                         const Message& prototype);
   void RunValidUnknownTextFormatTest(const std::string& test_name,
                                      const Message& message);
   void ExpectParseFailure(const std::string& test_name, ConformanceLevel level,
@@ -61,6 +75,8 @@
   bool ParseResponse(const conformance::ConformanceResponse& response,
                      const ConformanceRequestSetting& setting,
                      Message* test_message) override;
+  void TestTextFormatPerformanceMergeMessageWithRepeatedField(
+      const std::string& test_type_name, const std::string& message_field);
 };
 
 }  // namespace protobuf
diff --git a/conformance/third_party/jsoncpp/json.h b/conformance/third_party/jsoncpp/json.h
deleted file mode 100644
index 373ec98..0000000
--- a/conformance/third_party/jsoncpp/json.h
+++ /dev/null
@@ -1,2075 +0,0 @@
-/// Json-cpp amalgated header (http://jsoncpp.sourceforge.net/).
-/// It is intended to be used with #include "json/json.h"
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: LICENSE
-// //////////////////////////////////////////////////////////////////////
-
-/*
-The JsonCpp library's source code, including accompanying documentation,
-tests and demonstration applications, are licensed under the following
-conditions...
-
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all
-jurisdictions which recognize such a disclaimer. In such jurisdictions,
-this software is released into the Public Domain.
-
-In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
-2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
-released under the terms of the MIT License (see below).
-
-In jurisdictions which recognize Public Domain property, the user of this
-software may choose to accept it either as 1) Public Domain, 2) under the
-conditions of the MIT License (see below), or 3) under the terms of dual
-Public Domain/MIT License conditions described here, as they choose.
-
-The MIT License is about as close to Public Domain as a license can get, and is
-described in clear, concise terms at:
-
-   http://en.wikipedia.org/wiki/MIT_License
-
-The full text of the MIT License follows:
-
-========================================================================
-Copyright (c) 2007-2010 Baptiste Lepilleur
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy,
-modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-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 OR COPYRIGHT HOLDERS
-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.
-========================================================================
-(END LICENSE TEXT)
-
-The MIT license is compatible with both the GPL and commercial
-software, affording one all of the rights of Public Domain with the
-minor nuisance of being required to keep the above copyright notice
-and license text in the source code. Note also that by accepting the
-Public Domain "license" you can re-license your copy using whatever
-license you like.
-
-*/
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: LICENSE
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-#ifndef JSON_AMALGATED_H_INCLUDED
-# define JSON_AMALGATED_H_INCLUDED
-/// If defined, indicates that the source file is amalgated
-/// to prevent private header inclusion.
-#define JSON_IS_AMALGAMATION
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/version.h
-// //////////////////////////////////////////////////////////////////////
-
-// DO NOT EDIT. This file (and "version") is generated by CMake.
-// Run CMake configure step to update it.
-#ifndef JSON_VERSION_H_INCLUDED
-# define JSON_VERSION_H_INCLUDED
-
-# define JSONCPP_VERSION_STRING "1.6.5"
-# define JSONCPP_VERSION_MAJOR 1
-# define JSONCPP_VERSION_MINOR 6
-# define JSONCPP_VERSION_PATCH 5
-# define JSONCPP_VERSION_QUALIFIER
-# define JSONCPP_VERSION_HEXA ((JSONCPP_VERSION_MAJOR << 24) | (JSONCPP_VERSION_MINOR << 16) | (JSONCPP_VERSION_PATCH << 8))
-
-#endif // JSON_VERSION_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/version.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/config.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef JSON_CONFIG_H_INCLUDED
-#define JSON_CONFIG_H_INCLUDED
-
-/// If defined, indicates that json library is embedded in CppTL library.
-//# define JSON_IN_CPPTL 1
-
-/// If defined, indicates that json may leverage CppTL library
-//#  define JSON_USE_CPPTL 1
-/// If defined, indicates that cpptl vector based map should be used instead of
-/// std::map
-/// as Value container.
-//#  define JSON_USE_CPPTL_SMALLMAP 1
-
-// If non-zero, the library uses exceptions to report bad input instead of C
-// assertion macros. The default is to use exceptions.
-#ifndef JSON_USE_EXCEPTION
-#define JSON_USE_EXCEPTION 1
-#endif
-
-/// If defined, indicates that the source file is amalgated
-/// to prevent private header inclusion.
-/// Remarks: it is automatically defined in the generated amalgated header.
-// #define JSON_IS_AMALGAMATION
-
-#ifdef JSON_IN_CPPTL
-#include <cpptl/config.h>
-#ifndef JSON_USE_CPPTL
-#define JSON_USE_CPPTL 1
-#endif
-#endif
-
-#ifdef JSON_IN_CPPTL
-#define JSON_API CPPTL_API
-#elif defined(JSON_DLL_BUILD)
-#if defined(_MSC_VER)
-#define JSON_API __declspec(dllexport)
-#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
-#endif // if defined(_MSC_VER)
-#elif defined(JSON_DLL)
-#if defined(_MSC_VER)
-#define JSON_API __declspec(dllimport)
-#define JSONCPP_DISABLE_DLL_INTERFACE_WARNING
-#endif // if defined(_MSC_VER)
-#endif // ifdef JSON_IN_CPPTL
-#if !defined(JSON_API)
-#define JSON_API
-#endif
-
-// If JSON_NO_INT64 is defined, then Json only support C++ "int" type for
-// integer
-// Storages, and 64 bits integer support is disabled.
-// #define JSON_NO_INT64 1
-
-#if defined(_MSC_VER) // MSVC
-#  if _MSC_VER <= 1200 // MSVC 6
-    // Microsoft Visual Studio 6 only support conversion from __int64 to double
-    // (no conversion from unsigned __int64).
-#    define JSON_USE_INT64_DOUBLE_CONVERSION 1
-    // Disable warning 4786 for VS6 caused by STL (identifier was truncated to '255'
-    // characters in the debug information)
-    // All projects I've ever seen with VS6 were using this globally (not bothering
-    // with pragma push/pop).
-#    pragma warning(disable : 4786)
-#  endif // MSVC 6
-
-#  if _MSC_VER >= 1500 // MSVC 2008
-    /// Indicates that the following function is deprecated.
-#    define JSONCPP_DEPRECATED(message) __declspec(deprecated(message))
-#  endif
-
-#endif // defined(_MSC_VER)
-
-
-#ifndef JSON_HAS_RVALUE_REFERENCES
-
-#if defined(_MSC_VER) && _MSC_VER >= 1600 // MSVC >= 2010
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif // MSVC >= 2010
-
-#ifdef __clang__
-#if __has_feature(cxx_rvalue_references)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif  // has_feature
-
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
-#if defined(__GXX_EXPERIMENTAL_CXX0X__) || (__cplusplus >= 201103L)
-#define JSON_HAS_RVALUE_REFERENCES 1
-#endif  // GXX_EXPERIMENTAL
-
-#endif // __clang__ || __GNUC__
-
-#endif // not defined JSON_HAS_RVALUE_REFERENCES
-
-#ifndef JSON_HAS_RVALUE_REFERENCES
-#define JSON_HAS_RVALUE_REFERENCES 0
-#endif
-
-#ifdef __clang__
-#elif defined __GNUC__ // not clang (gcc comes later since clang emulates gcc)
-#  if (__GNUC__ > 4 || (__GNUC__ == 4 && __GNUC_MINOR__ >= 5))
-#    define JSONCPP_DEPRECATED(message)  __attribute__ ((deprecated(message)))
-#  elif (__GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ >= 1))
-#    define JSONCPP_DEPRECATED(message)  __attribute__((__deprecated__))
-#  endif  // GNUC version
-#endif // __clang__ || __GNUC__
-
-#if !defined(JSONCPP_DEPRECATED)
-#define JSONCPP_DEPRECATED(message)
-#endif // if !defined(JSONCPP_DEPRECATED)
-
-namespace Json {
-typedef int Int;
-typedef unsigned int UInt;
-#if defined(JSON_NO_INT64)
-typedef int LargestInt;
-typedef unsigned int LargestUInt;
-#undef JSON_HAS_INT64
-#else                 // if defined(JSON_NO_INT64)
-// For Microsoft Visual use specific types as long long is not supported
-#if defined(_MSC_VER) // Microsoft Visual Studio
-typedef __int64 Int64;
-typedef unsigned __int64 UInt64;
-#else                 // if defined(_MSC_VER) // Other platforms, use long long
-typedef long long int Int64;
-typedef unsigned long long int UInt64;
-#endif // if defined(_MSC_VER)
-typedef Int64 LargestInt;
-typedef UInt64 LargestUInt;
-#define JSON_HAS_INT64
-#endif // if defined(JSON_NO_INT64)
-} // end namespace Json
-
-#endif // JSON_CONFIG_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/config.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/forwards.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef JSON_FORWARDS_H_INCLUDED
-#define JSON_FORWARDS_H_INCLUDED
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include "config.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-
-namespace Json {
-
-// writer.h
-class FastWriter;
-class StyledWriter;
-
-// reader.h
-class Reader;
-
-// features.h
-class Features;
-
-// value.h
-typedef unsigned int ArrayIndex;
-class StaticString;
-class Path;
-class PathArgument;
-class Value;
-class ValueIteratorBase;
-class ValueIterator;
-class ValueConstIterator;
-
-} // namespace Json
-
-#endif // JSON_FORWARDS_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/forwards.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/features.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef CPPTL_JSON_FEATURES_H_INCLUDED
-#define CPPTL_JSON_FEATURES_H_INCLUDED
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include "forwards.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-
-namespace Json {
-
-/** \brief Configuration passed to reader and writer.
- * This configuration object can be used to force the Reader or Writer
- * to behave in a standard conforming way.
- */
-class JSON_API Features {
-public:
-  /** \brief A configuration that allows all features and assumes all strings
-   * are UTF-8.
-   * - C & C++ comments are allowed
-   * - Root object can be any JSON value
-   * - Assumes Value strings are encoded in UTF-8
-   */
-  static Features all();
-
-  /** \brief A configuration that is strictly compatible with the JSON
-   * specification.
-   * - Comments are forbidden.
-   * - Root object must be either an array or an object value.
-   * - Assumes Value strings are encoded in UTF-8
-   */
-  static Features strictMode();
-
-  /** \brief Initialize the configuration like JsonConfig::allFeatures;
-   */
-  Features();
-
-  /// \c true if comments are allowed. Default: \c true.
-  bool allowComments_;
-
-  /// \c true if root must be either an array or an object value. Default: \c
-  /// false.
-  bool strictRoot_;
-
-  /// \c true if dropped null placeholders are allowed. Default: \c false.
-  bool allowDroppedNullPlaceholders_;
-
-  /// \c true if numeric object key are allowed. Default: \c false.
-  bool allowNumericKeys_;
-};
-
-} // namespace Json
-
-#endif // CPPTL_JSON_FEATURES_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/features.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/value.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef CPPTL_JSON_H_INCLUDED
-#define CPPTL_JSON_H_INCLUDED
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include "forwards.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <string>
-#include <vector>
-#include <exception>
-
-#ifndef JSON_USE_CPPTL_SMALLMAP
-#include <map>
-#else
-#include <cpptl/smallmap.h>
-#endif
-#ifdef JSON_USE_CPPTL
-#include <cpptl/forwards.h>
-#endif
-
-// Disable warning C4251: <data member>: <type> needs to have dll-interface to
-// be used by...
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#pragma warning(push)
-#pragma warning(disable : 4251)
-#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-
-/** \brief JSON (JavaScript Object Notation).
- */
-namespace Json {
-
-/** Base class for all exceptions we throw.
- *
- * We use nothing but these internally. Of course, STL can throw others.
- */
-class JSON_API Exception : public std::exception {
-public:
-  Exception(std::string const& msg);
-  ~Exception() throw() override;
-  char const* what() const throw() override;
-protected:
-  std::string msg_;
-};
-
-/** Exceptions which the user cannot easily avoid.
- *
- * E.g. out-of-memory (when we use malloc), stack-overflow, malicious input
- *
- * \remark derived from Json::Exception
- */
-class JSON_API RuntimeError : public Exception {
-public:
-  RuntimeError(std::string const& msg);
-};
-
-/** Exceptions thrown by JSON_ASSERT/JSON_FAIL macros.
- *
- * These are precondition-violations (user bugs) and internal errors (our bugs).
- *
- * \remark derived from Json::Exception
- */
-class JSON_API LogicError : public Exception {
-public:
-  LogicError(std::string const& msg);
-};
-
-/// used internally
-void throwRuntimeError(std::string const& msg);
-/// used internally
-void throwLogicError(std::string const& msg);
-
-/** \brief Type of the value held by a Value object.
- */
-enum ValueType {
-  nullValue = 0, ///< 'null' value
-  intValue,      ///< signed integer value
-  uintValue,     ///< unsigned integer value
-  realValue,     ///< double value
-  stringValue,   ///< UTF-8 string value
-  booleanValue,  ///< bool value
-  arrayValue,    ///< array value (ordered list)
-  objectValue    ///< object value (collection of name/value pairs).
-};
-
-enum CommentPlacement {
-  commentBefore = 0,      ///< a comment placed on the line before a value
-  commentAfterOnSameLine, ///< a comment just after a value on the same line
-  commentAfter, ///< a comment on the line after a value (only make sense for
-  /// root value)
-  numberOfCommentPlacement
-};
-
-//# ifdef JSON_USE_CPPTL
-//   typedef CppTL::AnyEnumerator<const char *> EnumMemberNames;
-//   typedef CppTL::AnyEnumerator<const Value &> EnumValues;
-//# endif
-
-/** \brief Lightweight wrapper to tag static string.
- *
- * Value constructor and objectValue member assignement takes advantage of the
- * StaticString and avoid the cost of string duplication when storing the
- * string or the member name.
- *
- * Example of usage:
- * \code
- * Json::Value aValue( StaticString("some text") );
- * Json::Value object;
- * static const StaticString code("code");
- * object[code] = 1234;
- * \endcode
- */
-class JSON_API StaticString {
-public:
-  explicit StaticString(const char* czstring) : c_str_(czstring) {}
-
-  operator const char*() const { return c_str_; }
-
-  const char* c_str() const { return c_str_; }
-
-private:
-  const char* c_str_;
-};
-
-/** \brief Represents a <a HREF="http://www.json.org">JSON</a> value.
- *
- * This class is a discriminated union wrapper that can represents a:
- * - signed integer [range: Value::minInt - Value::maxInt]
- * - unsigned integer (range: 0 - Value::maxUInt)
- * - double
- * - UTF-8 string
- * - boolean
- * - 'null'
- * - an ordered list of Value
- * - collection of name/value pairs (javascript object)
- *
- * The type of the held value is represented by a #ValueType and
- * can be obtained using type().
- *
- * Values of an #objectValue or #arrayValue can be accessed using operator[]()
- * methods.
- * Non-const methods will automatically create the a #nullValue element
- * if it does not exist.
- * The sequence of an #arrayValue will be automatically resized and initialized
- * with #nullValue. resize() can be used to enlarge or truncate an #arrayValue.
- *
- * The get() methods can be used to obtain default value in the case the
- * required element does not exist.
- *
- * It is possible to iterate over the list of a #objectValue values using
- * the getMemberNames() method.
- *
- * \note #Value string-length fit in size_t, but keys must be < 2^30.
- * (The reason is an implementation detail.) A #CharReader will raise an
- * exception if a bound is exceeded to avoid security holes in your app,
- * but the Value API does *not* check bounds. That is the responsibility
- * of the caller.
- */
-class JSON_API Value {
-  friend class ValueIteratorBase;
-public:
-  typedef std::vector<std::string> Members;
-  typedef ValueIterator iterator;
-  typedef ValueConstIterator const_iterator;
-  typedef Json::UInt UInt;
-  typedef Json::Int Int;
-#if defined(JSON_HAS_INT64)
-  typedef Json::UInt64 UInt64;
-  typedef Json::Int64 Int64;
-#endif // defined(JSON_HAS_INT64)
-  typedef Json::LargestInt LargestInt;
-  typedef Json::LargestUInt LargestUInt;
-  typedef Json::ArrayIndex ArrayIndex;
-
-  static const Value& null;  ///< We regret this reference to a global instance; prefer the simpler Value().
-  static const Value& nullRef;  ///< just a kludge for binary-compatibility; same as null
-  /// Minimum signed integer value that can be stored in a Json::Value.
-  static const LargestInt minLargestInt;
-  /// Maximum signed integer value that can be stored in a Json::Value.
-  static const LargestInt maxLargestInt;
-  /// Maximum unsigned integer value that can be stored in a Json::Value.
-  static const LargestUInt maxLargestUInt;
-
-  /// Minimum signed int value that can be stored in a Json::Value.
-  static const Int minInt;
-  /// Maximum signed int value that can be stored in a Json::Value.
-  static const Int maxInt;
-  /// Maximum unsigned int value that can be stored in a Json::Value.
-  static const UInt maxUInt;
-
-#if defined(JSON_HAS_INT64)
-  /// Minimum signed 64 bits int value that can be stored in a Json::Value.
-  static const Int64 minInt64;
-  /// Maximum signed 64 bits int value that can be stored in a Json::Value.
-  static const Int64 maxInt64;
-  /// Maximum unsigned 64 bits int value that can be stored in a Json::Value.
-  static const UInt64 maxUInt64;
-#endif // defined(JSON_HAS_INT64)
-
-private:
-#ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-  class CZString {
-  public:
-    enum DuplicationPolicy {
-      noDuplication = 0,
-      duplicate,
-      duplicateOnCopy
-    };
-    CZString(ArrayIndex index);
-    CZString(char const* str, unsigned length, DuplicationPolicy allocate);
-    CZString(CZString const& other);
-#if JSON_HAS_RVALUE_REFERENCES
-    CZString(CZString&& other);
-#endif
-    ~CZString();
-    CZString& operator=(CZString other);
-    bool operator<(CZString const& other) const;
-    bool operator==(CZString const& other) const;
-    ArrayIndex index() const;
-    //const char* c_str() const; ///< \deprecated
-    char const* data() const;
-    unsigned length() const;
-    bool isStaticString() const;
-
-  private:
-    void swap(CZString& other);
-
-    struct StringStorage {
-      unsigned policy_: 2;
-      unsigned length_: 30; // 1GB max
-    };
-
-    char const* cstr_;  // actually, a prefixed string, unless policy is noDup
-    union {
-      ArrayIndex index_;
-      StringStorage storage_;
-    };
-  };
-
-public:
-#ifndef JSON_USE_CPPTL_SMALLMAP
-  typedef std::map<CZString, Value> ObjectValues;
-#else
-  typedef CppTL::SmallMap<CZString, Value> ObjectValues;
-#endif // ifndef JSON_USE_CPPTL_SMALLMAP
-#endif // ifndef JSONCPP_DOC_EXCLUDE_IMPLEMENTATION
-
-public:
-  /** \brief Create a default Value of the given type.
-
-    This is a very useful constructor.
-    To create an empty array, pass arrayValue.
-    To create an empty object, pass objectValue.
-    Another Value can then be set to this one by assignment.
-This is useful since clear() and resize() will not alter types.
-
-    Examples:
-\code
-Json::Value null_value; // null
-Json::Value arr_value(Json::arrayValue); // []
-Json::Value obj_value(Json::objectValue); // {}
-\endcode
-  */
-  Value(ValueType type = nullValue);
-  Value(Int value);
-  Value(UInt value);
-#if defined(JSON_HAS_INT64)
-  Value(Int64 value);
-  Value(UInt64 value);
-#endif // if defined(JSON_HAS_INT64)
-  Value(double value);
-  Value(const char* value); ///< Copy til first 0. (NULL causes to seg-fault.)
-  Value(const char* begin, const char* end); ///< Copy all, incl zeroes.
-  /** \brief Constructs a value from a static string.
-
-   * Like other value string constructor but do not duplicate the string for
-   * internal storage. The given string must remain alive after the call to this
-   * constructor.
-   * \note This works only for null-terminated strings. (We cannot change the
-   *   size of this class, so we have nowhere to store the length,
-   *   which might be computed later for various operations.)
-   *
-   * Example of usage:
-   * \code
-   * static StaticString foo("some text");
-   * Json::Value aValue(foo);
-   * \endcode
-   */
-  Value(const StaticString& value);
-  Value(const std::string& value); ///< Copy data() til size(). Embedded zeroes too.
-#ifdef JSON_USE_CPPTL
-  Value(const CppTL::ConstString& value);
-#endif
-  Value(bool value);
-  /// Deep copy.
-  Value(const Value& other);
-#if JSON_HAS_RVALUE_REFERENCES
-  /// Move constructor
-  Value(Value&& other);
-#endif
-  ~Value();
-
-  /// Deep copy, then swap(other).
-  /// \note Over-write existing comments. To preserve comments, use #swapPayload().
-  Value& operator=(Value other);
-  /// Swap everything.
-  void swap(Value& other);
-  /// Swap values but leave comments and source offsets in place.
-  void swapPayload(Value& other);
-
-  ValueType type() const;
-
-  /// Compare payload only, not comments etc.
-  bool operator<(const Value& other) const;
-  bool operator<=(const Value& other) const;
-  bool operator>=(const Value& other) const;
-  bool operator>(const Value& other) const;
-  bool operator==(const Value& other) const;
-  bool operator!=(const Value& other) const;
-  int compare(const Value& other) const;
-
-  const char* asCString() const; ///< Embedded zeroes could cause you trouble!
-  std::string asString() const; ///< Embedded zeroes are possible.
-  /** Get raw char* of string-value.
-   *  \return false if !string. (Seg-fault if str or end are NULL.)
-   */
-  bool getString(
-      char const** begin, char const** end) const;
-#ifdef JSON_USE_CPPTL
-  CppTL::ConstString asConstString() const;
-#endif
-  Int asInt() const;
-  UInt asUInt() const;
-#if defined(JSON_HAS_INT64)
-  Int64 asInt64() const;
-  UInt64 asUInt64() const;
-#endif // if defined(JSON_HAS_INT64)
-  LargestInt asLargestInt() const;
-  LargestUInt asLargestUInt() const;
-  float asFloat() const;
-  double asDouble() const;
-  bool asBool() const;
-
-  bool isNull() const;
-  bool isBool() const;
-  bool isInt() const;
-  bool isInt64() const;
-  bool isUInt() const;
-  bool isUInt64() const;
-  bool isIntegral() const;
-  bool isDouble() const;
-  bool isNumeric() const;
-  bool isString() const;
-  bool isArray() const;
-  bool isObject() const;
-
-  bool isConvertibleTo(ValueType other) const;
-
-  /// Number of values in array or object
-  ArrayIndex size() const;
-
-  /// \brief Return true if empty array, empty object, or null;
-  /// otherwise, false.
-  bool empty() const;
-
-  /// Return isNull()
-  bool operator!() const;
-
-  /// Remove all object members and array elements.
-  /// \pre type() is arrayValue, objectValue, or nullValue
-  /// \post type() is unchanged
-  void clear();
-
-  /// Resize the array to size elements.
-  /// New elements are initialized to null.
-  /// May only be called on nullValue or arrayValue.
-  /// \pre type() is arrayValue or nullValue
-  /// \post type() is arrayValue
-  void resize(ArrayIndex size);
-
-  /// Access an array element (zero based index ).
-  /// If the array contains less than index element, then null value are
-  /// inserted
-  /// in the array so that its size is index+1.
-  /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
-  Value& operator[](ArrayIndex index);
-
-  /// Access an array element (zero based index ).
-  /// If the array contains less than index element, then null value are
-  /// inserted
-  /// in the array so that its size is index+1.
-  /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
-  Value& operator[](int index);
-
-  /// Access an array element (zero based index )
-  /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
-  const Value& operator[](ArrayIndex index) const;
-
-  /// Access an array element (zero based index )
-  /// (You may need to say 'value[0u]' to get your compiler to distinguish
-  ///  this from the operator[] which takes a string.)
-  const Value& operator[](int index) const;
-
-  /// If the array contains at least index+1 elements, returns the element
-  /// value,
-  /// otherwise returns defaultValue.
-  Value get(ArrayIndex index, const Value& defaultValue) const;
-  /// Return true if index < size().
-  bool isValidIndex(ArrayIndex index) const;
-  /// \brief Append value to array at the end.
-  ///
-  /// Equivalent to jsonvalue[jsonvalue.size()] = value;
-  Value& append(const Value& value);
-
-  /// Access an object value by name, create a null member if it does not exist.
-  /// \note Because of our implementation, keys are limited to 2^30 -1 chars.
-  ///  Exceeding that will cause an exception.
-  Value& operator[](const char* key);
-  /// Access an object value by name, returns null if there is no member with
-  /// that name.
-  const Value& operator[](const char* key) const;
-  /// Access an object value by name, create a null member if it does not exist.
-  /// \param key may contain embedded nulls.
-  Value& operator[](const std::string& key);
-  /// Access an object value by name, returns null if there is no member with
-  /// that name.
-  /// \param key may contain embedded nulls.
-  const Value& operator[](const std::string& key) const;
-  /** \brief Access an object value by name, create a null member if it does not
-   exist.
-
-   * If the object has no entry for that name, then the member name used to store
-   * the new entry is not duplicated.
-   * Example of use:
-   * \code
-   * Json::Value object;
-   * static const StaticString code("code");
-   * object[code] = 1234;
-   * \endcode
-   */
-  Value& operator[](const StaticString& key);
-#ifdef JSON_USE_CPPTL
-  /// Access an object value by name, create a null member if it does not exist.
-  Value& operator[](const CppTL::ConstString& key);
-  /// Access an object value by name, returns null if there is no member with
-  /// that name.
-  const Value& operator[](const CppTL::ConstString& key) const;
-#endif
-  /// Return the member named key if it exist, defaultValue otherwise.
-  /// \note deep copy
-  Value get(const char* key, const Value& defaultValue) const;
-  /// Return the member named key if it exist, defaultValue otherwise.
-  /// \note deep copy
-  /// \note key may contain embedded nulls.
-  Value get(const char* begin, const char* end, const Value& defaultValue) const;
-  /// Return the member named key if it exist, defaultValue otherwise.
-  /// \note deep copy
-  /// \param key may contain embedded nulls.
-  Value get(const std::string& key, const Value& defaultValue) const;
-#ifdef JSON_USE_CPPTL
-  /// Return the member named key if it exist, defaultValue otherwise.
-  /// \note deep copy
-  Value get(const CppTL::ConstString& key, const Value& defaultValue) const;
-#endif
-  /// Most general and efficient version of isMember()const, get()const,
-  /// and operator[]const
-  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
-  Value const* find(char const* begin, char const* end) const;
-  /// Most general and efficient version of object-mutators.
-  /// \note As stated elsewhere, behavior is undefined if (end-begin) >= 2^30
-  /// \return non-zero, but JSON_ASSERT if this is neither object nor nullValue.
-  Value const* demand(char const* begin, char const* end);
-  /// \brief Remove and return the named member.
-  ///
-  /// Do nothing if it did not exist.
-  /// \return the removed Value, or null.
-  /// \pre type() is objectValue or nullValue
-  /// \post type() is unchanged
-  /// \deprecated
-  Value removeMember(const char* key);
-  /// Same as removeMember(const char*)
-  /// \param key may contain embedded nulls.
-  /// \deprecated
-  Value removeMember(const std::string& key);
-  /// Same as removeMember(const char* begin, const char* end, Value* removed),
-  /// but 'key' is null-terminated.
-  bool removeMember(const char* key, Value* removed);
-  /** \brief Remove the named map member.
-
-      Update 'removed' iff removed.
-      \param key may contain embedded nulls.
-      \return true iff removed (no exceptions)
-  */
-  bool removeMember(std::string const& key, Value* removed);
-  /// Same as removeMember(std::string const& key, Value* removed)
-  bool removeMember(const char* begin, const char* end, Value* removed);
-  /** \brief Remove the indexed array element.
-
-      O(n) expensive operations.
-      Update 'removed' iff removed.
-      \return true iff removed (no exceptions)
-  */
-  bool removeIndex(ArrayIndex i, Value* removed);
-
-  /// Return true if the object has a member named key.
-  /// \note 'key' must be null-terminated.
-  bool isMember(const char* key) const;
-  /// Return true if the object has a member named key.
-  /// \param key may contain embedded nulls.
-  bool isMember(const std::string& key) const;
-  /// Same as isMember(std::string const& key)const
-  bool isMember(const char* begin, const char* end) const;
-#ifdef JSON_USE_CPPTL
-  /// Return true if the object has a member named key.
-  bool isMember(const CppTL::ConstString& key) const;
-#endif
-
-  /// \brief Return a list of the member names.
-  ///
-  /// If null, return an empty list.
-  /// \pre type() is objectValue or nullValue
-  /// \post if type() was nullValue, it remains nullValue
-  Members getMemberNames() const;
-
-  //# ifdef JSON_USE_CPPTL
-  //      EnumMemberNames enumMemberNames() const;
-  //      EnumValues enumValues() const;
-  //# endif
-
-  /// \deprecated Always pass len.
-  JSONCPP_DEPRECATED("Use setComment(std::string const&) instead.")
-  void setComment(const char* comment, CommentPlacement placement);
-  /// Comments must be //... or /* ... */
-  void setComment(const char* comment, size_t len, CommentPlacement placement);
-  /// Comments must be //... or /* ... */
-  void setComment(const std::string& comment, CommentPlacement placement);
-  bool hasComment(CommentPlacement placement) const;
-  /// Include delimiters and embedded newlines.
-  std::string getComment(CommentPlacement placement) const;
-
-  std::string toStyledString() const;
-
-  const_iterator begin() const;
-  const_iterator end() const;
-
-  iterator begin();
-  iterator end();
-
-  // Accessors for the [start, limit) range of bytes within the JSON text from
-  // which this value was parsed, if any.
-  void setOffsetStart(size_t start);
-  void setOffsetLimit(size_t limit);
-  size_t getOffsetStart() const;
-  size_t getOffsetLimit() const;
-
-private:
-  void initBasic(ValueType type, bool allocated = false);
-
-  Value& resolveReference(const char* key);
-  Value& resolveReference(const char* key, const char* end);
-
-  struct CommentInfo {
-    CommentInfo();
-    ~CommentInfo();
-
-    void setComment(const char* text, size_t len);
-
-    char* comment_;
-  };
-
-  // struct MemberNamesTransform
-  //{
-  //   typedef const char *result_type;
-  //   const char *operator()( const CZString &name ) const
-  //   {
-  //      return name.c_str();
-  //   }
-  //};
-
-  union ValueHolder {
-    LargestInt int_;
-    LargestUInt uint_;
-    double real_;
-    bool bool_;
-    char* string_;  // actually ptr to unsigned, followed by str, unless !allocated_
-    ObjectValues* map_;
-  } value_;
-  ValueType type_ : 8;
-  unsigned int allocated_ : 1; // Notes: if declared as bool, bitfield is useless.
-                               // If not allocated_, string_ must be null-terminated.
-  CommentInfo* comments_;
-
-  // [start, limit) byte offsets in the source JSON text from which this Value
-  // was extracted.
-  size_t start_;
-  size_t limit_;
-};
-
-/** \brief Experimental and untested: represents an element of the "path" to
- * access a node.
- */
-class JSON_API PathArgument {
-public:
-  friend class Path;
-
-  PathArgument();
-  PathArgument(ArrayIndex index);
-  PathArgument(const char* key);
-  PathArgument(const std::string& key);
-
-private:
-  enum Kind {
-    kindNone = 0,
-    kindIndex,
-    kindKey
-  };
-  std::string key_;
-  ArrayIndex index_;
-  Kind kind_;
-};
-
-/** \brief Experimental and untested: represents a "path" to access a node.
- *
- * Syntax:
- * - "." => root node
- * - ".[n]" => elements at index 'n' of root node (an array value)
- * - ".name" => member named 'name' of root node (an object value)
- * - ".name1.name2.name3"
- * - ".[0][1][2].name1[3]"
- * - ".%" => member name is provided as parameter
- * - ".[%]" => index is provided as parameter
- */
-class JSON_API Path {
-public:
-  Path(const std::string& path,
-       const PathArgument& a1 = PathArgument(),
-       const PathArgument& a2 = PathArgument(),
-       const PathArgument& a3 = PathArgument(),
-       const PathArgument& a4 = PathArgument(),
-       const PathArgument& a5 = PathArgument());
-
-  const Value& resolve(const Value& root) const;
-  Value resolve(const Value& root, const Value& defaultValue) const;
-  /// Creates the "path" to access the specified node and returns a reference on
-  /// the node.
-  Value& make(Value& root) const;
-
-private:
-  typedef std::vector<const PathArgument*> InArgs;
-  typedef std::vector<PathArgument> Args;
-
-  void makePath(const std::string& path, const InArgs& in);
-  void addPathInArg(const std::string& path,
-                    const InArgs& in,
-                    InArgs::const_iterator& itInArg,
-                    PathArgument::Kind kind);
-  void invalidPath(const std::string& path, int location);
-
-  Args args_;
-};
-
-/** \brief base class for Value iterators.
- *
- */
-class JSON_API ValueIteratorBase {
-public:
-  typedef std::bidirectional_iterator_tag iterator_category;
-  typedef unsigned int size_t;
-  typedef int difference_type;
-  typedef ValueIteratorBase SelfType;
-
-  bool operator==(const SelfType& other) const { return isEqual(other); }
-
-  bool operator!=(const SelfType& other) const { return !isEqual(other); }
-
-  difference_type operator-(const SelfType& other) const {
-    return other.computeDistance(*this);
-  }
-
-  /// Return either the index or the member name of the referenced value as a
-  /// Value.
-  Value key() const;
-
-  /// Return the index of the referenced Value, or -1 if it is not an arrayValue.
-  UInt index() const;
-
-  /// Return the member name of the referenced Value, or "" if it is not an
-  /// objectValue.
-  /// \note Avoid `c_str()` on result, as embedded zeroes are possible.
-  std::string name() const;
-
-  /// Return the member name of the referenced Value. "" if it is not an
-  /// objectValue.
-  /// \deprecated This cannot be used for UTF-8 strings, since there can be embedded nulls.
-  JSONCPP_DEPRECATED("Use `key = name();` instead.")
-  char const* memberName() const;
-  /// Return the member name of the referenced Value, or NULL if it is not an
-  /// objectValue.
-  /// \note Better version than memberName(). Allows embedded nulls.
-  char const* memberName(char const** end) const;
-
-protected:
-  Value& deref() const;
-
-  void increment();
-
-  void decrement();
-
-  difference_type computeDistance(const SelfType& other) const;
-
-  bool isEqual(const SelfType& other) const;
-
-  void copy(const SelfType& other);
-
-private:
-  Value::ObjectValues::iterator current_;
-  // Indicates that iterator is for a null value.
-  bool isNull_;
-
-public:
-  // For some reason, BORLAND needs these at the end, rather
-  // than earlier. No idea why.
-  ValueIteratorBase();
-  explicit ValueIteratorBase(const Value::ObjectValues::iterator& current);
-};
-
-/** \brief const iterator for object and array value.
- *
- */
-class JSON_API ValueConstIterator : public ValueIteratorBase {
-  friend class Value;
-
-public:
-  typedef const Value value_type;
-  //typedef unsigned int size_t;
-  //typedef int difference_type;
-  typedef const Value& reference;
-  typedef const Value* pointer;
-  typedef ValueConstIterator SelfType;
-
-  ValueConstIterator();
-  ValueConstIterator(ValueIterator const& other);
-
-private:
-/*! \internal Use by Value to create an iterator.
- */
-  explicit ValueConstIterator(const Value::ObjectValues::iterator& current);
-public:
-  SelfType& operator=(const ValueIteratorBase& other);
-
-  SelfType operator++(int) {
-    SelfType temp(*this);
-    ++*this;
-    return temp;
-  }
-
-  SelfType operator--(int) {
-    SelfType temp(*this);
-    --*this;
-    return temp;
-  }
-
-  SelfType& operator--() {
-    decrement();
-    return *this;
-  }
-
-  SelfType& operator++() {
-    increment();
-    return *this;
-  }
-
-  reference operator*() const { return deref(); }
-
-  pointer operator->() const { return &deref(); }
-};
-
-/** \brief Iterator for object and array value.
- */
-class JSON_API ValueIterator : public ValueIteratorBase {
-  friend class Value;
-
-public:
-  typedef Value value_type;
-  typedef unsigned int size_t;
-  typedef int difference_type;
-  typedef Value& reference;
-  typedef Value* pointer;
-  typedef ValueIterator SelfType;
-
-  ValueIterator();
-  explicit ValueIterator(const ValueConstIterator& other);
-  ValueIterator(const ValueIterator& other);
-
-private:
-/*! \internal Use by Value to create an iterator.
- */
-  explicit ValueIterator(const Value::ObjectValues::iterator& current);
-public:
-  SelfType& operator=(const SelfType& other);
-
-  SelfType operator++(int) {
-    SelfType temp(*this);
-    ++*this;
-    return temp;
-  }
-
-  SelfType operator--(int) {
-    SelfType temp(*this);
-    --*this;
-    return temp;
-  }
-
-  SelfType& operator--() {
-    decrement();
-    return *this;
-  }
-
-  SelfType& operator++() {
-    increment();
-    return *this;
-  }
-
-  reference operator*() const { return deref(); }
-
-  pointer operator->() const { return &deref(); }
-};
-
-} // namespace Json
-
-
-namespace std {
-/// Specialize std::swap() for Json::Value.
-template<>
-inline void swap(Json::Value& a, Json::Value& b) { a.swap(b); }
-}
-
-
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#pragma warning(pop)
-#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-
-#endif // CPPTL_JSON_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/value.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/reader.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef CPPTL_JSON_READER_H_INCLUDED
-#define CPPTL_JSON_READER_H_INCLUDED
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include "features.h"
-#include "value.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <deque>
-#include <iosfwd>
-#include <stack>
-#include <string>
-#include <istream>
-
-// Disable warning C4251: <data member>: <type> needs to have dll-interface to
-// be used by...
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#pragma warning(push)
-#pragma warning(disable : 4251)
-#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-
-namespace Json {
-
-/** \brief Unserialize a <a HREF="http://www.json.org">JSON</a> document into a
- *Value.
- *
- * \deprecated Use CharReader and CharReaderBuilder.
- */
-class JSON_API Reader {
-public:
-  typedef char Char;
-  typedef const Char* Location;
-
-  /** \brief An error tagged with where in the JSON text it was encountered.
-   *
-   * The offsets give the [start, limit) range of bytes within the text. Note
-   * that this is bytes, not codepoints.
-   *
-   */
-  struct StructuredError {
-    size_t offset_start;
-    size_t offset_limit;
-    std::string message;
-  };
-
-  /** \brief Constructs a Reader allowing all features
-   * for parsing.
-   */
-  Reader();
-
-  /** \brief Constructs a Reader allowing the specified feature set
-   * for parsing.
-   */
-  Reader(const Features& features);
-
-  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
-   * document.
-   * \param document UTF-8 encoded string containing the document to read.
-   * \param root [out] Contains the root value of the document if it was
-   *             successfully parsed.
-   * \param collectComments \c true to collect comment and allow writing them
-   * back during
-   *                        serialization, \c false to discard comments.
-   *                        This parameter is ignored if
-   * Features::allowComments_
-   *                        is \c false.
-   * \return \c true if the document was successfully parsed, \c false if an
-   * error occurred.
-   */
-  bool
-  parse(const std::string& document, Value& root, bool collectComments = true);
-
-  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
-   document.
-   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
-   document to read.
-   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
-   document to read.
-   *               Must be >= beginDoc.
-   * \param root [out] Contains the root value of the document if it was
-   *             successfully parsed.
-   * \param collectComments \c true to collect comment and allow writing them
-   back during
-   *                        serialization, \c false to discard comments.
-   *                        This parameter is ignored if
-   Features::allowComments_
-   *                        is \c false.
-   * \return \c true if the document was successfully parsed, \c false if an
-   error occurred.
-   */
-  bool parse(const char* beginDoc,
-             const char* endDoc,
-             Value& root,
-             bool collectComments = true);
-
-  /// \brief Parse from input stream.
-  /// \see Json::operator>>(std::istream&, Json::Value&).
-  bool parse(std::istream& is, Value& root, bool collectComments = true);
-
-  /** \brief Returns a user friendly string that list errors in the parsed
-   * document.
-   * \return Formatted error message with the list of errors with their location
-   * in
-   *         the parsed document. An empty string is returned if no error
-   * occurred
-   *         during parsing.
-   * \deprecated Use getFormattedErrorMessages() instead (typo fix).
-   */
-  JSONCPP_DEPRECATED("Use getFormattedErrorMessages() instead.")
-  std::string getFormatedErrorMessages() const;
-
-  /** \brief Returns a user friendly string that list errors in the parsed
-   * document.
-   * \return Formatted error message with the list of errors with their location
-   * in
-   *         the parsed document. An empty string is returned if no error
-   * occurred
-   *         during parsing.
-   */
-  std::string getFormattedErrorMessages() const;
-
-  /** \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
-   *         errors.  This can occur if the parser recovers from a non-fatal
-   *         parse error and then encounters additional errors.
-   */
-  std::vector<StructuredError> getStructuredErrors() const;
-
-  /** \brief Add a semantic error message.
-   * \param value JSON Value location associated with the error
-   * \param message The error message.
-   * \return \c true if the error was successfully added, \c false if the
-   * Value offset exceeds the document size.
-   */
-  bool pushError(const Value& value, const std::string& message);
-
-  /** \brief Add a semantic error message with extra context.
-   * \param value JSON Value location associated with the error
-   * \param message The error message.
-   * \param extra Additional JSON Value location to contextualize the error
-   * \return \c true if the error was successfully added, \c false if either
-   * Value offset exceeds the document size.
-   */
-  bool pushError(const Value& value, const std::string& message, const Value& extra);
-
-  /** \brief Return whether there are any errors.
-   * \return \c true if there are no errors to report \c false if
-   * errors have occurred.
-   */
-  bool good() const;
-
-private:
-  enum TokenType {
-    tokenEndOfStream = 0,
-    tokenObjectBegin,
-    tokenObjectEnd,
-    tokenArrayBegin,
-    tokenArrayEnd,
-    tokenString,
-    tokenNumber,
-    tokenTrue,
-    tokenFalse,
-    tokenNull,
-    tokenArraySeparator,
-    tokenMemberSeparator,
-    tokenComment,
-    tokenError
-  };
-
-  class Token {
-  public:
-    TokenType type_;
-    Location start_;
-    Location end_;
-  };
-
-  class ErrorInfo {
-  public:
-    Token token_;
-    std::string message_;
-    Location extra_;
-  };
-
-  typedef std::deque<ErrorInfo> Errors;
-
-  bool readToken(Token& token);
-  void skipSpaces();
-  bool match(Location pattern, int patternLength);
-  bool readComment();
-  bool readCStyleComment();
-  bool readCppStyleComment();
-  bool readString();
-  void readNumber();
-  bool readValue();
-  bool readObject(Token& token);
-  bool readArray(Token& token);
-  bool decodeNumber(Token& token);
-  bool decodeNumber(Token& token, Value& decoded);
-  bool decodeString(Token& token);
-  bool decodeString(Token& token, std::string& decoded);
-  bool decodeDouble(Token& token);
-  bool decodeDouble(Token& token, Value& decoded);
-  bool decodeUnicodeCodePoint(Token& token,
-                              Location& current,
-                              Location end,
-                              unsigned int& unicode);
-  bool decodeUnicodeEscapeSequence(Token& token,
-                                   Location& current,
-                                   Location end,
-                                   unsigned int& unicode);
-  bool addError(const std::string& message, Token& token, Location extra = 0);
-  bool recoverFromError(TokenType skipUntilToken);
-  bool addErrorAndRecover(const std::string& message,
-                          Token& token,
-                          TokenType skipUntilToken);
-  void skipUntilSpace();
-  Value& currentValue();
-  Char getNextChar();
-  void
-  getLocationLineAndColumn(Location location, int& line, int& column) const;
-  std::string getLocationLineAndColumn(Location location) const;
-  void addComment(Location begin, Location end, CommentPlacement placement);
-  void skipCommentTokens(Token& token);
-
-  typedef std::stack<Value*> Nodes;
-  Nodes nodes_;
-  Errors errors_;
-  std::string document_;
-  Location begin_;
-  Location end_;
-  Location current_;
-  Location lastValueEnd_;
-  Value* lastValue_;
-  std::string commentsBefore_;
-  Features features_;
-  bool collectComments_;
-};  // Reader
-
-/** Interface for reading JSON from a char array.
- */
-class JSON_API CharReader {
-public:
-  virtual ~CharReader() {}
-  /** \brief Read a Value from a <a HREF="http://www.json.org">JSON</a>
-   document.
-   * The document must be a UTF-8 encoded string containing the document to read.
-   *
-   * \param beginDoc Pointer on the beginning of the UTF-8 encoded string of the
-   document to read.
-   * \param endDoc Pointer on the end of the UTF-8 encoded string of the
-   document to read.
-   *        Must be >= beginDoc.
-   * \param root [out] Contains the root value of the document if it was
-   *             successfully parsed.
-   * \param errs [out] Formatted error messages (if not NULL)
-   *        a user friendly string that lists errors in the parsed
-   * document.
-   * \return \c true if the document was successfully parsed, \c false if an
-   error occurred.
-   */
-  virtual bool parse(
-      char const* beginDoc, char const* endDoc,
-      Value* root, std::string* errs) = 0;
-
-  class JSON_API Factory {
-  public:
-    virtual ~Factory() {}
-    /** \brief Allocate a CharReader via operator new().
-     * \throw std::exception if something goes wrong (e.g. invalid settings)
-     */
-    virtual CharReader* newCharReader() const = 0;
-  };  // Factory
-};  // CharReader
-
-/** \brief Build a CharReader implementation.
-
-Usage:
-\code
-  using namespace Json;
-  CharReaderBuilder builder;
-  builder["collectComments"] = false;
-  Value value;
-  std::string errs;
-  bool ok = parseFromStream(builder, std::cin, &value, &errs);
-\endcode
-*/
-class JSON_API CharReaderBuilder : public CharReader::Factory {
-public:
-  // Note: We use a Json::Value so that we can add data-members to this class
-  // without a major version bump.
-  /** Configuration of this builder.
-    These are case-sensitive.
-    Available settings (case-sensitive):
-    - `"collectComments": false or true`
-      - true to collect comment and allow writing them
-        back during serialization, false to discard comments.
-        This parameter is ignored if allowComments is false.
-    - `"allowComments": false or true`
-      - true if comments are allowed.
-    - `"strictRoot": false or true`
-      - true if root must be either an array or an object value
-    - `"allowDroppedNullPlaceholders": false or true`
-      - true if dropped null placeholders are allowed. (See StreamWriterBuilder.)
-    - `"allowNumericKeys": false or true`
-      - true if numeric object keys are allowed.
-    - `"allowSingleQuotes": false or true`
-      - true if '' are allowed for strings (both keys and values)
-    - `"stackLimit": integer`
-      - Exceeding stackLimit (recursive depth of `readValue()`) will
-        cause an exception.
-      - This is a security issue (seg-faults caused by deeply nested JSON),
-        so the default is low.
-    - `"failIfExtra": false or true`
-      - If true, `parse()` returns false when extra non-whitespace trails
-        the JSON value in the input string.
-    - `"rejectDupKeys": false or true`
-      - If true, `parse()` returns false when a key is duplicated within an object.
-    - `"allowSpecialFloats": false or true`
-      - If true, special float values (NaNs and infinities) are allowed
-        and their values are lossfree restorable.
-
-    You can examine 'settings_` yourself
-    to see the defaults. You can also write and read them just like any
-    JSON Value.
-    \sa setDefaults()
-    */
-  Json::Value settings_;
-
-  CharReaderBuilder();
-  ~CharReaderBuilder() override;
-
-  CharReader* newCharReader() const override;
-
-  /** \return true if 'settings' are legal and consistent;
-   *   otherwise, indicate bad settings via 'invalid'.
-   */
-  bool validate(Json::Value* invalid) const;
-
-  /** A simple way to update a specific setting.
-   */
-  Value& operator[](std::string key);
-
-  /** Called by ctor, but you can use this to reset settings_.
-   * \pre 'settings' != NULL (but Json::null is fine)
-   * \remark Defaults:
-   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderDefaults
-   */
-  static void setDefaults(Json::Value* settings);
-  /** Same as old Features::strictMode().
-   * \pre 'settings' != NULL (but Json::null is fine)
-   * \remark Defaults:
-   * \snippet src/lib_json/json_reader.cpp CharReaderBuilderStrictMode
-   */
-  static void strictMode(Json::Value* settings);
-};
-
-/** Consume entire stream and use its begin/end.
-  * Someday we might have a real StreamReader, but for now this
-  * is convenient.
-  */
-bool JSON_API parseFromStream(
-    CharReader::Factory const&,
-    std::istream&,
-    Value* root, std::string* errs);
-
-/** \brief Read from 'sin' into 'root'.
-
- Always keep comments from the input JSON.
-
- This can be used to read a file into a particular sub-object.
- For example:
- \code
- Json::Value root;
- cin >> root["dir"]["file"];
- cout << root;
- \endcode
- Result:
- \verbatim
- {
- "dir": {
-     "file": {
-     // The input stream JSON would be nested here.
-     }
- }
- }
- \endverbatim
- \throw std::exception on parse error.
- \see Json::operator<<()
-*/
-JSON_API std::istream& operator>>(std::istream&, Value&);
-
-} // namespace Json
-
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#pragma warning(pop)
-#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-
-#endif // CPPTL_JSON_READER_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/reader.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/writer.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef JSON_WRITER_H_INCLUDED
-#define JSON_WRITER_H_INCLUDED
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include "value.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <vector>
-#include <string>
-#include <ostream>
-
-// Disable warning C4251: <data member>: <type> needs to have dll-interface to
-// be used by...
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#pragma warning(push)
-#pragma warning(disable : 4251)
-#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-
-namespace Json {
-
-class Value;
-
-/**
-
-Usage:
-\code
-  using namespace Json;
-  void writeToStdout(StreamWriter::Factory const& factory, Value const& value) {
-    std::unique_ptr<StreamWriter> const writer(
-      factory.newStreamWriter());
-    writer->write(value, &std::cout);
-    std::cout << std::endl;  // add lf and flush
-  }
-\endcode
-*/
-class JSON_API StreamWriter {
-protected:
-  std::ostream* sout_;  // not owned; will not delete
-public:
-  StreamWriter();
-  virtual ~StreamWriter();
-  /** Write Value into document as configured in sub-class.
-      Do not take ownership of sout, but maintain a reference during function.
-      \pre sout != NULL
-      \return zero on success (For now, we always return zero, so check the stream instead.)
-      \throw std::exception possibly, depending on configuration
-   */
-  virtual int write(Value const& root, std::ostream* sout) = 0;
-
-  /** \brief A simple abstract factory.
-   */
-  class JSON_API Factory {
-  public:
-    virtual ~Factory();
-    /** \brief Allocate a CharReader via operator new().
-     * \throw std::exception if something goes wrong (e.g. invalid settings)
-     */
-    virtual StreamWriter* newStreamWriter() const = 0;
-  };  // Factory
-};  // StreamWriter
-
-/** \brief Write into stringstream, then return string, for convenience.
- * A StreamWriter will be created from the factory, used, and then deleted.
- */
-std::string JSON_API writeString(StreamWriter::Factory const& factory, Value const& root);
-
-
-/** \brief Build a StreamWriter implementation.
-
-Usage:
-\code
-  using namespace Json;
-  Value value = ...;
-  StreamWriterBuilder builder;
-  builder["commentStyle"] = "None";
-  builder["indentation"] = "   ";  // or whatever you like
-  std::unique_ptr<Json::StreamWriter> writer(
-      builder.newStreamWriter());
-  writer->write(value, &std::cout);
-  std::cout << std::endl;  // add lf and flush
-\endcode
-*/
-class JSON_API StreamWriterBuilder : public StreamWriter::Factory {
-public:
-  // Note: We use a Json::Value so that we can add data-members to this class
-  // without a major version bump.
-  /** Configuration of this builder.
-    Available settings (case-sensitive):
-    - "commentStyle": "None" or "All"
-    - "indentation":  "<anything>"
-    - "enableYAMLCompatibility": false or true
-      - slightly change the whitespace around colons
-    - "dropNullPlaceholders": false or true
-      - Drop the "null" string from the writer's output for nullValues.
-        Strictly speaking, this is not valid JSON. But when the output is being
-        fed to a browser's Javascript, it makes for smaller output and the
-        browser can handle the output just fine.
-    - "useSpecialFloats": false or true
-      - If true, outputs non-finite floating point values in the following way:
-        NaN values as "NaN", positive infinity as "Infinity", and negative infinity
-        as "-Infinity".
-
-    You can examine 'settings_` yourself
-    to see the defaults. You can also write and read them just like any
-    JSON Value.
-    \sa setDefaults()
-    */
-  Json::Value settings_;
-
-  StreamWriterBuilder();
-  ~StreamWriterBuilder() override;
-
-  /**
-   * \throw std::exception if something goes wrong (e.g. invalid settings)
-   */
-  StreamWriter* newStreamWriter() const override;
-
-  /** \return true if 'settings' are legal and consistent;
-   *   otherwise, indicate bad settings via 'invalid'.
-   */
-  bool validate(Json::Value* invalid) const;
-  /** A simple way to update a specific setting.
-   */
-  Value& operator[](std::string key);
-
-  /** Called by ctor, but you can use this to reset settings_.
-   * \pre 'settings' != NULL (but Json::null is fine)
-   * \remark Defaults:
-   * \snippet src/lib_json/json_writer.cpp StreamWriterBuilderDefaults
-   */
-  static void setDefaults(Json::Value* settings);
-};
-
-/** \brief Abstract class for writers.
- * \deprecated Use StreamWriter. (And really, this is an implementation detail.)
- */
-class JSON_API Writer {
-public:
-  virtual ~Writer();
-
-  virtual std::string write(const Value& root) = 0;
-};
-
-/** \brief Outputs a Value in <a HREF="http://www.json.org">JSON</a> format
- *without formatting (not human friendly).
- *
- * The JSON document is written in a single line. It is not intended for 'human'
- *consumption,
- * but may be useful to support feature such as RPC where bandwidth is limited.
- * \sa Reader, Value
- * \deprecated Use StreamWriterBuilder.
- */
-class JSON_API FastWriter : public Writer {
-
-public:
-  FastWriter();
-  ~FastWriter() override {}
-
-  void enableYAMLCompatibility();
-
-  /** \brief Drop the "null" string from the writer's output for nullValues.
-   * Strictly speaking, this is not valid JSON. But when the output is being
-   * fed to a browser's Javascript, it makes for smaller output and the
-   * browser can handle the output just fine.
-   */
-  void dropNullPlaceholders();
-
-  void omitEndingLineFeed();
-
-public: // overridden from Writer
-  std::string write(const Value& root) override;
-
-private:
-  void writeValue(const Value& value);
-
-  std::string document_;
-  bool yamlCompatiblityEnabled_;
-  bool dropNullPlaceholders_;
-  bool omitEndingLineFeed_;
-};
-
-/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
- *human friendly way.
- *
- * The rules for line break and indent are as follow:
- * - Object value:
- *     - if empty then print {} without indent and line break
- *     - if not empty the print '{', line break & indent, print one value per
- *line
- *       and then unindent and line break and print '}'.
- * - Array value:
- *     - if empty then print [] without indent and line break
- *     - if the array contains no object value, empty array or some other value
- *types,
- *       and all the values fit on one lines, then print the array on a single
- *line.
- *     - 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 outputted according to their
- *#CommentPlacement.
- *
- * \sa Reader, Value, Value::setComment()
- * \deprecated Use StreamWriterBuilder.
- */
-class JSON_API StyledWriter : public Writer {
-public:
-  StyledWriter();
-  ~StyledWriter() override {}
-
-public: // overridden from Writer
-  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
-   * \param root Value to serialize.
-   * \return String containing the JSON document that represents the root value.
-   */
-  std::string write(const Value& root) override;
-
-private:
-  void writeValue(const Value& value);
-  void writeArrayValue(const Value& value);
-  bool isMultineArray(const Value& value);
-  void pushValue(const std::string& value);
-  void writeIndent();
-  void writeWithIndent(const std::string& value);
-  void indent();
-  void unindent();
-  void writeCommentBeforeValue(const Value& root);
-  void writeCommentAfterValueOnSameLine(const Value& root);
-  bool hasCommentForValue(const Value& value);
-  static std::string normalizeEOL(const std::string& text);
-
-  typedef std::vector<std::string> ChildValues;
-
-  ChildValues childValues_;
-  std::string document_;
-  std::string indentString_;
-  int rightMargin_;
-  int indentSize_;
-  bool addChildValues_;
-};
-
-/** \brief Writes a Value in <a HREF="http://www.json.org">JSON</a> format in a
- human friendly way,
-     to a stream rather than to a string.
- *
- * The rules for line break and indent are as follow:
- * - Object value:
- *     - if empty then print {} without indent and line break
- *     - if not empty the print '{', line break & indent, print one value per
- line
- *       and then unindent and line break and print '}'.
- * - Array value:
- *     - if empty then print [] without indent and line break
- *     - if the array contains no object value, empty array or some other value
- types,
- *       and all the values fit on one lines, then print the array on a single
- line.
- *     - 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 outputted according to their
- #CommentPlacement.
- *
- * \param indentation Each level will be indented by this amount extra.
- * \sa Reader, Value, Value::setComment()
- * \deprecated Use StreamWriterBuilder.
- */
-class JSON_API StyledStreamWriter {
-public:
-  StyledStreamWriter(std::string indentation = "\t");
-  ~StyledStreamWriter() {}
-
-public:
-  /** \brief Serialize a Value in <a HREF="http://www.json.org">JSON</a> format.
-   * \param out Stream to write to. (Can be ostringstream, e.g.)
-   * \param root Value to serialize.
-   * \note There is no point in deriving from Writer, since write() should not
-   * return a value.
-   */
-  void write(std::ostream& out, const Value& root);
-
-private:
-  void writeValue(const Value& value);
-  void writeArrayValue(const Value& value);
-  bool isMultineArray(const Value& value);
-  void pushValue(const std::string& value);
-  void writeIndent();
-  void writeWithIndent(const std::string& value);
-  void indent();
-  void unindent();
-  void writeCommentBeforeValue(const Value& root);
-  void writeCommentAfterValueOnSameLine(const Value& root);
-  bool hasCommentForValue(const Value& value);
-  static std::string normalizeEOL(const std::string& text);
-
-  typedef std::vector<std::string> ChildValues;
-
-  ChildValues childValues_;
-  std::ostream* document_;
-  std::string indentString_;
-  int rightMargin_;
-  std::string indentation_;
-  bool addChildValues_ : 1;
-  bool indented_ : 1;
-};
-
-#if defined(JSON_HAS_INT64)
-std::string JSON_API valueToString(Int value);
-std::string JSON_API valueToString(UInt value);
-#endif // if defined(JSON_HAS_INT64)
-std::string JSON_API valueToString(LargestInt value);
-std::string JSON_API valueToString(LargestUInt value);
-std::string JSON_API valueToString(double value);
-std::string JSON_API valueToString(bool value);
-std::string JSON_API valueToQuotedString(const char* value);
-
-/// \brief Output using the StyledStreamWriter.
-/// \see Json::operator>>()
-JSON_API std::ostream& operator<<(std::ostream&, const Value& root);
-
-} // namespace Json
-
-#if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-#pragma warning(pop)
-#endif // if defined(JSONCPP_DISABLE_DLL_INTERFACE_WARNING)
-
-#endif // JSON_WRITER_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/writer.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: include/json/assertions.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef CPPTL_JSON_ASSERTIONS_H_INCLUDED
-#define CPPTL_JSON_ASSERTIONS_H_INCLUDED
-
-#include <stdlib.h>
-#include <sstream>
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include "config.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-
-/** It should not be possible for a maliciously designed file to
- *  cause an abort() or seg-fault, so these macros are used only
- *  for pre-condition violations and internal logic errors.
- */
-#if JSON_USE_EXCEPTION
-
-// @todo <= add detail about condition in exception
-# define JSON_ASSERT(condition)                                                \
-  {if (!(condition)) {Json::throwLogicError( "assert json failed" );}}
-
-# define JSON_FAIL_MESSAGE(message)                                            \
-  {                                                                            \
-    std::ostringstream oss; oss << message;                                    \
-    Json::throwLogicError(oss.str());                                          \
-    abort();                                                                   \
-  }
-
-#else // JSON_USE_EXCEPTION
-
-# define JSON_ASSERT(condition) assert(condition)
-
-// The call to assert() will show the failure message in debug builds. In
-// release builds we abort, for a core-dump or debugger.
-# define JSON_FAIL_MESSAGE(message)                                            \
-  {                                                                            \
-    std::ostringstream oss; oss << message;                                    \
-    assert(false && oss.str().c_str());                                        \
-    abort();                                                                   \
-  }
-
-
-#endif
-
-#define JSON_ASSERT_MESSAGE(condition, message)                                \
-  if (!(condition)) {                                                          \
-    JSON_FAIL_MESSAGE(message);                                                \
-  }
-
-#endif // CPPTL_JSON_ASSERTIONS_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: include/json/assertions.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-#endif //ifndef JSON_AMALGATED_H_INCLUDED
diff --git a/conformance/third_party/jsoncpp/jsoncpp.cpp b/conformance/third_party/jsoncpp/jsoncpp.cpp
deleted file mode 100644
index 78919ea..0000000
--- a/conformance/third_party/jsoncpp/jsoncpp.cpp
+++ /dev/null
@@ -1,5192 +0,0 @@
-/// Json-cpp amalgated source (http://jsoncpp.sourceforge.net/).
-/// It is intended to be used with #include "json/json.h"
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: LICENSE
-// //////////////////////////////////////////////////////////////////////
-
-/*
-The JsonCpp library's source code, including accompanying documentation,
-tests and demonstration applications, are licensed under the following
-conditions...
-
-The author (Baptiste Lepilleur) explicitly disclaims copyright in all
-jurisdictions which recognize such a disclaimer. In such jurisdictions,
-this software is released into the Public Domain.
-
-In jurisdictions which do not recognize Public Domain property (e.g. Germany as of
-2010), this software is Copyright (c) 2007-2010 by Baptiste Lepilleur, and is
-released under the terms of the MIT License (see below).
-
-In jurisdictions which recognize Public Domain property, the user of this
-software may choose to accept it either as 1) Public Domain, 2) under the
-conditions of the MIT License (see below), or 3) under the terms of dual
-Public Domain/MIT License conditions described here, as they choose.
-
-The MIT License is about as close to Public Domain as a license can get, and is
-described in clear, concise terms at:
-
-   http://en.wikipedia.org/wiki/MIT_License
-
-The full text of the MIT License follows:
-
-========================================================================
-Copyright (c) 2007-2010 Baptiste Lepilleur
-
-Permission is hereby granted, free of charge, to any person
-obtaining a copy of this software and associated documentation
-files (the "Software"), to deal in the Software without
-restriction, including without limitation the rights to use, copy,
-modify, merge, publish, distribute, sublicense, and/or sell copies
-of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be
-included in all copies or substantial portions of the Software.
-
-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 OR COPYRIGHT HOLDERS
-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.
-========================================================================
-(END LICENSE TEXT)
-
-The MIT license is compatible with both the GPL and commercial
-software, affording one all of the rights of Public Domain with the
-minor nuisance of being required to keep the above copyright notice
-and license text in the source code. Note also that by accepting the
-Public Domain "license" you can re-license your copy using whatever
-license you like.
-
-*/
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: LICENSE
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-#include "third_party/jsoncpp/json.h"
-
-#ifndef JSON_IS_AMALGAMATION
-#error "Compile with -I PATH_TO_JSON_DIRECTORY"
-#endif
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: src/lib_json/json_tool.h
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#ifndef LIB_JSONCPP_JSON_TOOL_H_INCLUDED
-#define LIB_JSONCPP_JSON_TOOL_H_INCLUDED
-
-/* This header provides common string manipulation support, such as UTF-8,
- * portable conversion from/to string...
- *
- * It is an internal header that must not be exposed.
- */
-
-namespace Json {
-
-/// Converts a unicode code-point to UTF-8.
-static inline std::string codePointToUTF8(unsigned int cp) {
-  std::string result;
-
-  // based on description from http://en.wikipedia.org/wiki/UTF-8
-
-  if (cp <= 0x7f) {
-    result.resize(1);
-    result[0] = static_cast<char>(cp);
-  } else if (cp <= 0x7FF) {
-    result.resize(2);
-    result[1] = static_cast<char>(0x80 | (0x3f & cp));
-    result[0] = static_cast<char>(0xC0 | (0x1f & (cp >> 6)));
-  } else if (cp <= 0xFFFF) {
-    result.resize(3);
-    result[2] = static_cast<char>(0x80 | (0x3f & cp));
-    result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
-    result[0] = static_cast<char>(0xE0 | (0xf & (cp >> 12)));
-  } else if (cp <= 0x10FFFF) {
-    result.resize(4);
-    result[3] = static_cast<char>(0x80 | (0x3f & cp));
-    result[2] = static_cast<char>(0x80 | (0x3f & (cp >> 6)));
-    result[1] = static_cast<char>(0x80 | (0x3f & (cp >> 12)));
-    result[0] = static_cast<char>(0xF0 | (0x7 & (cp >> 18)));
-  }
-
-  return result;
-}
-
-/// Returns true if ch is a control character (in range [1,31]).
-static inline bool isControlCharacter(char ch) { return ch > 0 && ch <= 0x1F; }
-
-enum {
-  /// Constant that specify the size of the buffer that must be passed to
-  /// uintToString.
-  uintToStringBufferSize = 3 * sizeof(LargestUInt) + 1
-};
-
-// Defines a char buffer for use with uintToString().
-typedef char UIntToStringBuffer[uintToStringBufferSize];
-
-/** Converts an unsigned integer to string.
- * @param value Unsigned integer to convert to string
- * @param current Input/Output string buffer.
- *        Must have at least uintToStringBufferSize chars free.
- */
-static inline void uintToString(LargestUInt value, char*& current) {
-  *--current = 0;
-  do {
-    *--current = static_cast<signed char>(value % 10U + static_cast<unsigned>('0'));
-    value /= 10;
-  } while (value != 0);
-}
-
-/** Change ',' to '.' everywhere in buffer.
- *
- * We had a sophisticated way, but it did not work in WinCE.
- * @see https://github.com/open-source-parsers/jsoncpp/pull/9
- */
-static inline void fixNumericLocale(char* begin, char* end) {
-  while (begin < end) {
-    if (*begin == ',') {
-      *begin = '.';
-    }
-    ++begin;
-  }
-}
-
-} // namespace Json {
-
-#endif // LIB_JSONCPP_JSON_TOOL_H_INCLUDED
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: src/lib_json/json_tool.h
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: src/lib_json/json_reader.cpp
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2011 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include <json/assertions.h>
-#include <json/reader.h>
-#include <json/value.h>
-#include "json_tool.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <utility>
-#include <cstdio>
-#include <cassert>
-#include <cstring>
-#include <istream>
-#include <sstream>
-#include <memory>
-#include <set>
-#include <limits>
-
-#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
-#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
-#elif __cplusplus >= 201103L
-#define snprintf std::snprintf
-#endif
-
-#if defined(__QNXNTO__)
-#define sscanf std::sscanf
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
-// Disable warning about strdup being deprecated.
-#pragma warning(disable : 4996)
-#endif
-
-static int const stackLimit_g = 1000;
-static int       stackDepth_g = 0;  // see readValue()
-
-namespace Json {
-
-#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
-typedef std::unique_ptr<CharReader> CharReaderPtr;
-#else
-typedef std::auto_ptr<CharReader>   CharReaderPtr;
-#endif
-
-// Implementation of class Features
-// ////////////////////////////////
-
-Features::Features()
-    : allowComments_(true), strictRoot_(false),
-      allowDroppedNullPlaceholders_(false), allowNumericKeys_(false) {}
-
-Features Features::all() { return Features(); }
-
-Features Features::strictMode() {
-  Features features;
-  features.allowComments_ = false;
-  features.strictRoot_ = true;
-  features.allowDroppedNullPlaceholders_ = false;
-  features.allowNumericKeys_ = false;
-  return features;
-}
-
-// Implementation of class Reader
-// ////////////////////////////////
-
-static bool containsNewLine(Reader::Location begin, Reader::Location end) {
-  for (; begin < end; ++begin)
-    if (*begin == '\n' || *begin == '\r')
-      return true;
-  return false;
-}
-
-// Class Reader
-// //////////////////////////////////////////////////////////////////
-
-Reader::Reader()
-    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
-      lastValue_(), commentsBefore_(), features_(Features::all()),
-      collectComments_() {}
-
-Reader::Reader(const Features& features)
-    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
-      lastValue_(), commentsBefore_(), features_(features), collectComments_() {
-}
-
-bool
-Reader::parse(const std::string& document, Value& root, bool collectComments) {
-  document_ = document;
-  const char* begin = document_.c_str();
-  const char* end = begin + document_.length();
-  return parse(begin, end, root, collectComments);
-}
-
-bool Reader::parse(std::istream& sin, Value& root, bool collectComments) {
-  // std::istream_iterator<char> begin(sin);
-  // std::istream_iterator<char> end;
-  // Those would allow streamed input from a file, if parse() were a
-  // template function.
-
-  // Since std::string is reference-counted, this at least does not
-  // create an extra copy.
-  std::string doc;
-  std::getline(sin, doc, (char)EOF);
-  return parse(doc, root, collectComments);
-}
-
-bool Reader::parse(const char* beginDoc,
-                   const char* endDoc,
-                   Value& root,
-                   bool collectComments) {
-  if (!features_.allowComments_) {
-    collectComments = false;
-  }
-
-  begin_ = beginDoc;
-  end_ = endDoc;
-  collectComments_ = collectComments;
-  current_ = begin_;
-  lastValueEnd_ = 0;
-  lastValue_ = 0;
-  commentsBefore_ = "";
-  errors_.clear();
-  while (!nodes_.empty())
-    nodes_.pop();
-  nodes_.push(&root);
-
-  stackDepth_g = 0;  // Yes, this is bad coding, but options are limited.
-  bool successful = readValue();
-  Token token;
-  skipCommentTokens(token);
-  if (collectComments_ && !commentsBefore_.empty())
-    root.setComment(commentsBefore_, commentAfter);
-  if (features_.strictRoot_) {
-    if (!root.isArray() && !root.isObject()) {
-      // Set error location to start of doc, ideally should be first token found
-      // in doc
-      token.type_ = tokenError;
-      token.start_ = beginDoc;
-      token.end_ = endDoc;
-      addError(
-          "A valid JSON document must be either an array or an object value.",
-          token);
-      return false;
-    }
-  }
-  return successful;
-}
-
-bool Reader::readValue() {
-  // This is a non-reentrant way to support a stackLimit. Terrible!
-  // But this deprecated class has a security problem: Bad input can
-  // cause a seg-fault. This seems like a fair, binary-compatible way
-  // to prevent the problem.
-  if (stackDepth_g >= stackLimit_g) throwRuntimeError("Exceeded stackLimit in readValue().");
-  ++stackDepth_g;
-
-  Token token;
-  skipCommentTokens(token);
-  bool successful = true;
-
-  if (collectComments_ && !commentsBefore_.empty()) {
-    currentValue().setComment(commentsBefore_, commentBefore);
-    commentsBefore_ = "";
-  }
-
-  switch (token.type_) {
-  case tokenObjectBegin:
-    successful = readObject(token);
-    currentValue().setOffsetLimit(current_ - begin_);
-    break;
-  case tokenArrayBegin:
-    successful = readArray(token);
-    currentValue().setOffsetLimit(current_ - begin_);
-    break;
-  case tokenNumber:
-    successful = decodeNumber(token);
-    break;
-  case tokenString:
-    successful = decodeString(token);
-    break;
-  case tokenTrue:
-    {
-    Value v(true);
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenFalse:
-    {
-    Value v(false);
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenNull:
-    {
-    Value v;
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenArraySeparator:
-  case tokenObjectEnd:
-  case tokenArrayEnd:
-    if (features_.allowDroppedNullPlaceholders_) {
-      // "Un-read" the current token and mark the current value as a null
-      // token.
-      current_--;
-      Value v;
-      currentValue().swapPayload(v);
-      currentValue().setOffsetStart(current_ - begin_ - 1);
-      currentValue().setOffsetLimit(current_ - begin_);
-      break;
-    } // Else, fall through...
-  default:
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    return addError("Syntax error: value, object or array expected.", token);
-  }
-
-  if (collectComments_) {
-    lastValueEnd_ = current_;
-    lastValue_ = &currentValue();
-  }
-
-  --stackDepth_g;
-  return successful;
-}
-
-void Reader::skipCommentTokens(Token& token) {
-  if (features_.allowComments_) {
-    do {
-      readToken(token);
-    } while (token.type_ == tokenComment);
-  } else {
-    readToken(token);
-  }
-}
-
-bool Reader::readToken(Token& token) {
-  skipSpaces();
-  token.start_ = current_;
-  Char c = getNextChar();
-  bool ok = true;
-  switch (c) {
-  case '{':
-    token.type_ = tokenObjectBegin;
-    break;
-  case '}':
-    token.type_ = tokenObjectEnd;
-    break;
-  case '[':
-    token.type_ = tokenArrayBegin;
-    break;
-  case ']':
-    token.type_ = tokenArrayEnd;
-    break;
-  case '"':
-    token.type_ = tokenString;
-    ok = readString();
-    break;
-  case '/':
-    token.type_ = tokenComment;
-    ok = readComment();
-    break;
-  case '0':
-  case '1':
-  case '2':
-  case '3':
-  case '4':
-  case '5':
-  case '6':
-  case '7':
-  case '8':
-  case '9':
-  case '-':
-    token.type_ = tokenNumber;
-    readNumber();
-    break;
-  case 't':
-    token.type_ = tokenTrue;
-    ok = match("rue", 3);
-    break;
-  case 'f':
-    token.type_ = tokenFalse;
-    ok = match("alse", 4);
-    break;
-  case 'n':
-    token.type_ = tokenNull;
-    ok = match("ull", 3);
-    break;
-  case ',':
-    token.type_ = tokenArraySeparator;
-    break;
-  case ':':
-    token.type_ = tokenMemberSeparator;
-    break;
-  case 0:
-    token.type_ = tokenEndOfStream;
-    break;
-  default:
-    ok = false;
-    break;
-  }
-  if (!ok)
-    token.type_ = tokenError;
-  token.end_ = current_;
-  return true;
-}
-
-void Reader::skipSpaces() {
-  while (current_ != end_) {
-    Char c = *current_;
-    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
-      ++current_;
-    else
-      break;
-  }
-}
-
-bool Reader::match(Location pattern, int patternLength) {
-  if (end_ - current_ < patternLength)
-    return false;
-  int index = patternLength;
-  while (index--)
-    if (current_[index] != pattern[index])
-      return false;
-  current_ += patternLength;
-  return true;
-}
-
-bool Reader::readComment() {
-  Location commentBegin = current_ - 1;
-  Char c = getNextChar();
-  bool successful = false;
-  if (c == '*')
-    successful = readCStyleComment();
-  else if (c == '/')
-    successful = readCppStyleComment();
-  if (!successful)
-    return false;
-
-  if (collectComments_) {
-    CommentPlacement placement = commentBefore;
-    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
-      if (c != '*' || !containsNewLine(commentBegin, current_))
-        placement = commentAfterOnSameLine;
-    }
-
-    addComment(commentBegin, current_, placement);
-  }
-  return true;
-}
-
-static std::string normalizeEOL(Reader::Location begin, Reader::Location end) {
-  std::string normalized;
-  normalized.reserve(end - begin);
-  Reader::Location current = begin;
-  while (current != end) {
-    char c = *current++;
-    if (c == '\r') {
-      if (current != end && *current == '\n')
-         // convert dos EOL
-         ++current;
-      // convert Mac EOL
-      normalized += '\n';
-    } else {
-      normalized += c;
-    }
-  }
-  return normalized;
-}
-
-void
-Reader::addComment(Location begin, Location end, CommentPlacement placement) {
-  assert(collectComments_);
-  const std::string& normalized = normalizeEOL(begin, end);
-  if (placement == commentAfterOnSameLine) {
-    assert(lastValue_ != 0);
-    lastValue_->setComment(normalized, placement);
-  } else {
-    commentsBefore_ += normalized;
-  }
-}
-
-bool Reader::readCStyleComment() {
-  while (current_ != end_) {
-    Char c = getNextChar();
-    if (c == '*' && *current_ == '/')
-      break;
-  }
-  return getNextChar() == '/';
-}
-
-bool Reader::readCppStyleComment() {
-  while (current_ != end_) {
-    Char c = getNextChar();
-    if (c == '\n')
-      break;
-    if (c == '\r') {
-      // Consume DOS EOL. It will be normalized in addComment.
-      if (current_ != end_ && *current_ == '\n')
-        getNextChar();
-      // Break on Moc OS 9 EOL.
-      break;
-    }
-  }
-  return true;
-}
-
-void Reader::readNumber() {
-  const char *p = current_;
-  char c = '0'; // stopgap for already consumed character
-  // integral part
-  while (c >= '0' && c <= '9')
-    c = (current_ = p) < end_ ? *p++ : 0;
-  // fractional part
-  if (c == '.') {
-    c = (current_ = p) < end_ ? *p++ : 0;
-    while (c >= '0' && c <= '9')
-      c = (current_ = p) < end_ ? *p++ : 0;
-  }
-  // exponential part
-  if (c == 'e' || c == 'E') {
-    c = (current_ = p) < end_ ? *p++ : 0;
-    if (c == '+' || c == '-')
-      c = (current_ = p) < end_ ? *p++ : 0;
-    while (c >= '0' && c <= '9')
-      c = (current_ = p) < end_ ? *p++ : 0;
-  }
-}
-
-bool Reader::readString() {
-  Char c = 0;
-  while (current_ != end_) {
-    c = getNextChar();
-    if (c == '\\')
-      getNextChar();
-    else if (c == '"')
-      break;
-  }
-  return c == '"';
-}
-
-bool Reader::readObject(Token& tokenStart) {
-  Token tokenName;
-  std::string name;
-  Value init(objectValue);
-  currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
-  while (readToken(tokenName)) {
-    bool initialTokenOk = true;
-    while (tokenName.type_ == tokenComment && initialTokenOk)
-      initialTokenOk = readToken(tokenName);
-    if (!initialTokenOk)
-      break;
-    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
-      return true;
-    name = "";
-    if (tokenName.type_ == tokenString) {
-      if (!decodeString(tokenName, name))
-        return recoverFromError(tokenObjectEnd);
-    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
-      Value numberName;
-      if (!decodeNumber(tokenName, numberName))
-        return recoverFromError(tokenObjectEnd);
-      name = numberName.asString();
-    } else {
-      break;
-    }
-
-    Token colon;
-    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
-      return addErrorAndRecover(
-          "Missing ':' after object member name", colon, tokenObjectEnd);
-    }
-    Value& value = currentValue()[name];
-    nodes_.push(&value);
-    bool ok = readValue();
-    nodes_.pop();
-    if (!ok) // error already set
-      return recoverFromError(tokenObjectEnd);
-
-    Token comma;
-    if (!readToken(comma) ||
-        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
-         comma.type_ != tokenComment)) {
-      return addErrorAndRecover(
-          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
-    }
-    bool finalizeTokenOk = true;
-    while (comma.type_ == tokenComment && finalizeTokenOk)
-      finalizeTokenOk = readToken(comma);
-    if (comma.type_ == tokenObjectEnd)
-      return true;
-  }
-  return addErrorAndRecover(
-      "Missing '}' or object member name", tokenName, tokenObjectEnd);
-}
-
-bool Reader::readArray(Token& tokenStart) {
-  Value init(arrayValue);
-  currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
-  skipSpaces();
-  if (*current_ == ']') // empty array
-  {
-    Token endArray;
-    readToken(endArray);
-    return true;
-  }
-  int index = 0;
-  for (;;) {
-    Value& value = currentValue()[index++];
-    nodes_.push(&value);
-    bool ok = readValue();
-    nodes_.pop();
-    if (!ok) // error already set
-      return recoverFromError(tokenArrayEnd);
-
-    Token token;
-    // Accept Comment after last item in the array.
-    ok = readToken(token);
-    while (token.type_ == tokenComment && ok) {
-      ok = readToken(token);
-    }
-    bool badTokenType =
-        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
-    if (!ok || badTokenType) {
-      return addErrorAndRecover(
-          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
-    }
-    if (token.type_ == tokenArrayEnd)
-      break;
-  }
-  return true;
-}
-
-bool Reader::decodeNumber(Token& token) {
-  Value decoded;
-  if (!decodeNumber(token, decoded))
-    return false;
-  currentValue().swapPayload(decoded);
-  currentValue().setOffsetStart(token.start_ - begin_);
-  currentValue().setOffsetLimit(token.end_ - begin_);
-  return true;
-}
-
-bool Reader::decodeNumber(Token& token, Value& decoded) {
-  // Attempts to parse the number as an integer. If the number is
-  // larger than the maximum supported value of an integer then
-  // we decode the number as a double.
-  Location current = token.start_;
-  bool isNegative = *current == '-';
-  if (isNegative)
-    ++current;
-  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
-  Value::LargestUInt maxIntegerValue =
-      isNegative ? Value::LargestUInt(Value::maxLargestInt) + 1
-                 : Value::maxLargestUInt;
-  Value::LargestUInt threshold = maxIntegerValue / 10;
-  Value::LargestUInt value = 0;
-  while (current < token.end_) {
-    Char c = *current++;
-    if (c < '0' || c > '9')
-      return decodeDouble(token, decoded);
-    Value::UInt digit(c - '0');
-    if (value >= threshold) {
-      // We've hit or exceeded the max value divided by 10 (rounded down). If
-      // a) we've only just touched the limit, b) this is the last digit, and
-      // c) it's small enough to fit in that rounding delta, we're okay.
-      // Otherwise treat this number as a double to avoid overflow.
-      if (value > threshold || current != token.end_ ||
-          digit > maxIntegerValue % 10) {
-        return decodeDouble(token, decoded);
-      }
-    }
-    value = value * 10 + digit;
-  }
-  if (isNegative && value == maxIntegerValue)
-    decoded = Value::minLargestInt;
-  else if (isNegative)
-    decoded = -Value::LargestInt(value);
-  else if (value <= Value::LargestUInt(Value::maxInt))
-    decoded = Value::LargestInt(value);
-  else
-    decoded = value;
-  return true;
-}
-
-bool Reader::decodeDouble(Token& token) {
-  Value decoded;
-  if (!decodeDouble(token, decoded))
-    return false;
-  currentValue().swapPayload(decoded);
-  currentValue().setOffsetStart(token.start_ - begin_);
-  currentValue().setOffsetLimit(token.end_ - begin_);
-  return true;
-}
-
-bool Reader::decodeDouble(Token& token, Value& decoded) {
-  double value = 0;
-  std::string buffer(token.start_, token.end_);
-  std::istringstream is(buffer);
-  if (!(is >> value))
-    return addError("'" + std::string(token.start_, token.end_) +
-                        "' is not a number.",
-                    token);
-  decoded = value;
-  return true;
-}
-
-bool Reader::decodeString(Token& token) {
-  std::string decoded_string;
-  if (!decodeString(token, decoded_string))
-    return false;
-  Value decoded(decoded_string);
-  currentValue().swapPayload(decoded);
-  currentValue().setOffsetStart(token.start_ - begin_);
-  currentValue().setOffsetLimit(token.end_ - begin_);
-  return true;
-}
-
-bool Reader::decodeString(Token& token, std::string& decoded) {
-  decoded.reserve(token.end_ - token.start_ - 2);
-  Location current = token.start_ + 1; // skip '"'
-  Location end = token.end_ - 1;       // do not include '"'
-  while (current != end) {
-    Char c = *current++;
-    if (c == '"')
-      break;
-    else if (c == '\\') {
-      if (current == end)
-        return addError("Empty escape sequence in string", token, current);
-      Char escape = *current++;
-      switch (escape) {
-      case '"':
-        decoded += '"';
-        break;
-      case '/':
-        decoded += '/';
-        break;
-      case '\\':
-        decoded += '\\';
-        break;
-      case 'b':
-        decoded += '\b';
-        break;
-      case 'f':
-        decoded += '\f';
-        break;
-      case 'n':
-        decoded += '\n';
-        break;
-      case 'r':
-        decoded += '\r';
-        break;
-      case 't':
-        decoded += '\t';
-        break;
-      case 'u': {
-        unsigned int unicode;
-        if (!decodeUnicodeCodePoint(token, current, end, unicode))
-          return false;
-        decoded += codePointToUTF8(unicode);
-      } break;
-      default:
-        return addError("Bad escape sequence in string", token, current);
-      }
-    } else {
-      decoded += c;
-    }
-  }
-  return true;
-}
-
-bool Reader::decodeUnicodeCodePoint(Token& token,
-                                    Location& current,
-                                    Location end,
-                                    unsigned int& unicode) {
-
-  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
-    return false;
-  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
-    // surrogate pairs
-    if (end - current < 6)
-      return addError(
-          "additional six characters expected to parse unicode surrogate pair.",
-          token,
-          current);
-    unsigned int surrogatePair;
-    if (*(current++) == '\\' && *(current++) == 'u') {
-      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
-        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
-      } else
-        return false;
-    } else
-      return addError("expecting another \\u token to begin the second half of "
-                      "a unicode surrogate pair",
-                      token,
-                      current);
-  }
-  return true;
-}
-
-bool Reader::decodeUnicodeEscapeSequence(Token& token,
-                                         Location& current,
-                                         Location end,
-                                         unsigned int& unicode) {
-  if (end - current < 4)
-    return addError(
-        "Bad unicode escape sequence in string: four digits expected.",
-        token,
-        current);
-  unicode = 0;
-  for (int index = 0; index < 4; ++index) {
-    Char c = *current++;
-    unicode *= 16;
-    if (c >= '0' && c <= '9')
-      unicode += c - '0';
-    else if (c >= 'a' && c <= 'f')
-      unicode += c - 'a' + 10;
-    else if (c >= 'A' && c <= 'F')
-      unicode += c - 'A' + 10;
-    else
-      return addError(
-          "Bad unicode escape sequence in string: hexadecimal digit expected.",
-          token,
-          current);
-  }
-  return true;
-}
-
-bool
-Reader::addError(const std::string& message, Token& token, Location extra) {
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = extra;
-  errors_.push_back(info);
-  return false;
-}
-
-bool Reader::recoverFromError(TokenType skipUntilToken) {
-  int errorCount = int(errors_.size());
-  Token skip;
-  for (;;) {
-    if (!readToken(skip))
-      errors_.resize(errorCount); // discard errors caused by recovery
-    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
-      break;
-  }
-  errors_.resize(errorCount);
-  return false;
-}
-
-bool Reader::addErrorAndRecover(const std::string& message,
-                                Token& token,
-                                TokenType skipUntilToken) {
-  addError(message, token);
-  return recoverFromError(skipUntilToken);
-}
-
-Value& Reader::currentValue() { return *(nodes_.top()); }
-
-Reader::Char Reader::getNextChar() {
-  if (current_ == end_)
-    return 0;
-  return *current_++;
-}
-
-void Reader::getLocationLineAndColumn(Location location,
-                                      int& line,
-                                      int& column) const {
-  Location current = begin_;
-  Location lastLineStart = current;
-  line = 0;
-  while (current < location && current != end_) {
-    Char c = *current++;
-    if (c == '\r') {
-      if (*current == '\n')
-        ++current;
-      lastLineStart = current;
-      ++line;
-    } else if (c == '\n') {
-      lastLineStart = current;
-      ++line;
-    }
-  }
-  // column & line start at 1
-  column = int(location - lastLineStart) + 1;
-  ++line;
-}
-
-std::string Reader::getLocationLineAndColumn(Location location) const {
-  int line, column;
-  getLocationLineAndColumn(location, line, column);
-  char buffer[18 + 16 + 16 + 1];
-  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-  return buffer;
-}
-
-// Deprecated. Preserved for backward compatibility
-std::string Reader::getFormatedErrorMessages() const {
-  return getFormattedErrorMessages();
-}
-
-std::string Reader::getFormattedErrorMessages() const {
-  std::string formattedMessage;
-  for (Errors::const_iterator itError = errors_.begin();
-       itError != errors_.end();
-       ++itError) {
-    const ErrorInfo& error = *itError;
-    formattedMessage +=
-        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
-    formattedMessage += "  " + error.message_ + "\n";
-    if (error.extra_)
-      formattedMessage +=
-          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
-  }
-  return formattedMessage;
-}
-
-std::vector<Reader::StructuredError> Reader::getStructuredErrors() const {
-  std::vector<Reader::StructuredError> allErrors;
-  for (Errors::const_iterator itError = errors_.begin();
-       itError != errors_.end();
-       ++itError) {
-    const ErrorInfo& error = *itError;
-    Reader::StructuredError structured;
-    structured.offset_start = error.token_.start_ - begin_;
-    structured.offset_limit = error.token_.end_ - begin_;
-    structured.message = error.message_;
-    allErrors.push_back(structured);
-  }
-  return allErrors;
-}
-
-bool Reader::pushError(const Value& value, const std::string& message) {
-  size_t length = end_ - begin_;
-  if(value.getOffsetStart() > length
-    || value.getOffsetLimit() > length)
-    return false;
-  Token token;
-  token.type_ = tokenError;
-  token.start_ = begin_ + value.getOffsetStart();
-  token.end_ = end_ + value.getOffsetLimit();
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = 0;
-  errors_.push_back(info);
-  return true;
-}
-
-bool Reader::pushError(const Value& value, const std::string& message, const Value& extra) {
-  size_t length = end_ - begin_;
-  if(value.getOffsetStart() > length
-    || value.getOffsetLimit() > length
-    || extra.getOffsetLimit() > length)
-    return false;
-  Token token;
-  token.type_ = tokenError;
-  token.start_ = begin_ + value.getOffsetStart();
-  token.end_ = begin_ + value.getOffsetLimit();
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = begin_ + extra.getOffsetStart();
-  errors_.push_back(info);
-  return true;
-}
-
-bool Reader::good() const {
-  return !errors_.size();
-}
-
-// exact copy of Features
-class OurFeatures {
-public:
-  static OurFeatures all();
-  bool allowComments_;
-  bool strictRoot_;
-  bool allowDroppedNullPlaceholders_;
-  bool allowNumericKeys_;
-  bool allowSingleQuotes_;
-  bool failIfExtra_;
-  bool rejectDupKeys_;
-  bool allowSpecialFloats_;
-  int stackLimit_;
-};  // OurFeatures
-
-// exact copy of Implementation of class Features
-// ////////////////////////////////
-
-OurFeatures OurFeatures::all() { return OurFeatures(); }
-
-// Implementation of class Reader
-// ////////////////////////////////
-
-// exact copy of Reader, renamed to OurReader
-class OurReader {
-public:
-  typedef char Char;
-  typedef const Char* Location;
-  struct StructuredError {
-    size_t offset_start;
-    size_t offset_limit;
-    std::string message;
-  };
-
-  OurReader(OurFeatures const& features);
-  bool parse(const char* beginDoc,
-             const char* endDoc,
-             Value& root,
-             bool collectComments = true);
-  std::string getFormattedErrorMessages() const;
-  std::vector<StructuredError> getStructuredErrors() const;
-  bool pushError(const Value& value, const std::string& message);
-  bool pushError(const Value& value, const std::string& message, const Value& extra);
-  bool good() const;
-
-private:
-  OurReader(OurReader const&);  // no impl
-  void operator=(OurReader const&);  // no impl
-
-  enum TokenType {
-    tokenEndOfStream = 0,
-    tokenObjectBegin,
-    tokenObjectEnd,
-    tokenArrayBegin,
-    tokenArrayEnd,
-    tokenString,
-    tokenNumber,
-    tokenTrue,
-    tokenFalse,
-    tokenNull,
-    tokenNaN,
-    tokenPosInf,
-    tokenNegInf,
-    tokenArraySeparator,
-    tokenMemberSeparator,
-    tokenComment,
-    tokenError
-  };
-
-  class Token {
-  public:
-    TokenType type_;
-    Location start_;
-    Location end_;
-  };
-
-  class ErrorInfo {
-  public:
-    Token token_;
-    std::string message_;
-    Location extra_;
-  };
-
-  typedef std::deque<ErrorInfo> Errors;
-
-  bool readToken(Token& token);
-  void skipSpaces();
-  bool match(Location pattern, int patternLength);
-  bool readComment();
-  bool readCStyleComment();
-  bool readCppStyleComment();
-  bool readString();
-  bool readStringSingleQuote();
-  bool readNumber(bool checkInf);
-  bool readValue();
-  bool readObject(Token& token);
-  bool readArray(Token& token);
-  bool decodeNumber(Token& token);
-  bool decodeNumber(Token& token, Value& decoded);
-  bool decodeString(Token& token);
-  bool decodeString(Token& token, std::string& decoded);
-  bool decodeDouble(Token& token);
-  bool decodeDouble(Token& token, Value& decoded);
-  bool decodeUnicodeCodePoint(Token& token,
-                              Location& current,
-                              Location end,
-                              unsigned int& unicode);
-  bool decodeUnicodeEscapeSequence(Token& token,
-                                   Location& current,
-                                   Location end,
-                                   unsigned int& unicode);
-  bool addError(const std::string& message, Token& token, Location extra = 0);
-  bool recoverFromError(TokenType skipUntilToken);
-  bool addErrorAndRecover(const std::string& message,
-                          Token& token,
-                          TokenType skipUntilToken);
-  void skipUntilSpace();
-  Value& currentValue();
-  Char getNextChar();
-  void
-  getLocationLineAndColumn(Location location, int& line, int& column) const;
-  std::string getLocationLineAndColumn(Location location) const;
-  void addComment(Location begin, Location end, CommentPlacement placement);
-  void skipCommentTokens(Token& token);
-
-  typedef std::stack<Value*> Nodes;
-  Nodes nodes_;
-  Errors errors_;
-  std::string document_;
-  Location begin_;
-  Location end_;
-  Location current_;
-  Location lastValueEnd_;
-  Value* lastValue_;
-  std::string commentsBefore_;
-  int stackDepth_;
-
-  OurFeatures const features_;
-  bool collectComments_;
-};  // OurReader
-
-// complete copy of Read impl, for OurReader
-
-OurReader::OurReader(OurFeatures const& features)
-    : errors_(), document_(), begin_(), end_(), current_(), lastValueEnd_(),
-      lastValue_(), commentsBefore_(),
-      stackDepth_(0),
-      features_(features), collectComments_() {
-}
-
-bool OurReader::parse(const char* beginDoc,
-                   const char* endDoc,
-                   Value& root,
-                   bool collectComments) {
-  if (!features_.allowComments_) {
-    collectComments = false;
-  }
-
-  begin_ = beginDoc;
-  end_ = endDoc;
-  collectComments_ = collectComments;
-  current_ = begin_;
-  lastValueEnd_ = 0;
-  lastValue_ = 0;
-  commentsBefore_ = "";
-  errors_.clear();
-  while (!nodes_.empty())
-    nodes_.pop();
-  nodes_.push(&root);
-
-  stackDepth_ = 0;
-  bool successful = readValue();
-  Token token;
-  skipCommentTokens(token);
-  if (features_.failIfExtra_) {
-    if (token.type_ != tokenError && token.type_ != tokenEndOfStream) {
-      addError("Extra non-whitespace after JSON value.", token);
-      return false;
-    }
-  }
-  if (collectComments_ && !commentsBefore_.empty())
-    root.setComment(commentsBefore_, commentAfter);
-  if (features_.strictRoot_) {
-    if (!root.isArray() && !root.isObject()) {
-      // Set error location to start of doc, ideally should be first token found
-      // in doc
-      token.type_ = tokenError;
-      token.start_ = beginDoc;
-      token.end_ = endDoc;
-      addError(
-          "A valid JSON document must be either an array or an object value.",
-          token);
-      return false;
-    }
-  }
-  return successful;
-}
-
-bool OurReader::readValue() {
-  if (stackDepth_ >= features_.stackLimit_) throwRuntimeError("Exceeded stackLimit in readValue().");
-  ++stackDepth_;
-  Token token;
-  skipCommentTokens(token);
-  bool successful = true;
-
-  if (collectComments_ && !commentsBefore_.empty()) {
-    currentValue().setComment(commentsBefore_, commentBefore);
-    commentsBefore_ = "";
-  }
-
-  switch (token.type_) {
-  case tokenObjectBegin:
-    successful = readObject(token);
-    currentValue().setOffsetLimit(current_ - begin_);
-    break;
-  case tokenArrayBegin:
-    successful = readArray(token);
-    currentValue().setOffsetLimit(current_ - begin_);
-    break;
-  case tokenNumber:
-    successful = decodeNumber(token);
-    break;
-  case tokenString:
-    successful = decodeString(token);
-    break;
-  case tokenTrue:
-    {
-    Value v(true);
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenFalse:
-    {
-    Value v(false);
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenNull:
-    {
-    Value v;
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenNaN:
-    {
-    Value v(std::numeric_limits<double>::quiet_NaN());
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenPosInf:
-    {
-    Value v(std::numeric_limits<double>::infinity());
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenNegInf:
-    {
-    Value v(-std::numeric_limits<double>::infinity());
-    currentValue().swapPayload(v);
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    }
-    break;
-  case tokenArraySeparator:
-  case tokenObjectEnd:
-  case tokenArrayEnd:
-    if (features_.allowDroppedNullPlaceholders_) {
-      // "Un-read" the current token and mark the current value as a null
-      // token.
-      current_--;
-      Value v;
-      currentValue().swapPayload(v);
-      currentValue().setOffsetStart(current_ - begin_ - 1);
-      currentValue().setOffsetLimit(current_ - begin_);
-      break;
-    } // else, fall through ...
-  default:
-    currentValue().setOffsetStart(token.start_ - begin_);
-    currentValue().setOffsetLimit(token.end_ - begin_);
-    return addError("Syntax error: value, object or array expected.", token);
-  }
-
-  if (collectComments_) {
-    lastValueEnd_ = current_;
-    lastValue_ = &currentValue();
-  }
-
-  --stackDepth_;
-  return successful;
-}
-
-void OurReader::skipCommentTokens(Token& token) {
-  if (features_.allowComments_) {
-    do {
-      readToken(token);
-    } while (token.type_ == tokenComment);
-  } else {
-    readToken(token);
-  }
-}
-
-bool OurReader::readToken(Token& token) {
-  skipSpaces();
-  token.start_ = current_;
-  Char c = getNextChar();
-  bool ok = true;
-  switch (c) {
-  case '{':
-    token.type_ = tokenObjectBegin;
-    break;
-  case '}':
-    token.type_ = tokenObjectEnd;
-    break;
-  case '[':
-    token.type_ = tokenArrayBegin;
-    break;
-  case ']':
-    token.type_ = tokenArrayEnd;
-    break;
-  case '"':
-    token.type_ = tokenString;
-    ok = readString();
-    break;
-  case '\'':
-    if (features_.allowSingleQuotes_) {
-    token.type_ = tokenString;
-    ok = readStringSingleQuote();
-    break;
-    } // else continue
-  case '/':
-    token.type_ = tokenComment;
-    ok = readComment();
-    break;
-  case '0':
-  case '1':
-  case '2':
-  case '3':
-  case '4':
-  case '5':
-  case '6':
-  case '7':
-  case '8':
-  case '9':
-    token.type_ = tokenNumber;
-    readNumber(false);
-    break;
-  case '-':
-    if (readNumber(true)) {
-      token.type_ = tokenNumber;
-    } else {
-      token.type_ = tokenNegInf;
-      ok = features_.allowSpecialFloats_ && match("nfinity", 7);
-    }
-    break;
-  case 't':
-    token.type_ = tokenTrue;
-    ok = match("rue", 3);
-    break;
-  case 'f':
-    token.type_ = tokenFalse;
-    ok = match("alse", 4);
-    break;
-  case 'n':
-    token.type_ = tokenNull;
-    ok = match("ull", 3);
-    break;
-  case 'N':
-    if (features_.allowSpecialFloats_) {
-      token.type_ = tokenNaN;
-      ok = match("aN", 2);
-    } else {
-      ok = false;
-    }
-    break;
-  case 'I':
-    if (features_.allowSpecialFloats_) {
-      token.type_ = tokenPosInf;
-      ok = match("nfinity", 7);
-    } else {
-      ok = false;
-    }
-    break;
-  case ',':
-    token.type_ = tokenArraySeparator;
-    break;
-  case ':':
-    token.type_ = tokenMemberSeparator;
-    break;
-  case 0:
-    token.type_ = tokenEndOfStream;
-    break;
-  default:
-    ok = false;
-    break;
-  }
-  if (!ok)
-    token.type_ = tokenError;
-  token.end_ = current_;
-  return true;
-}
-
-void OurReader::skipSpaces() {
-  while (current_ != end_) {
-    Char c = *current_;
-    if (c == ' ' || c == '\t' || c == '\r' || c == '\n')
-      ++current_;
-    else
-      break;
-  }
-}
-
-bool OurReader::match(Location pattern, int patternLength) {
-  if (end_ - current_ < patternLength)
-    return false;
-  int index = patternLength;
-  while (index--)
-    if (current_[index] != pattern[index])
-      return false;
-  current_ += patternLength;
-  return true;
-}
-
-bool OurReader::readComment() {
-  Location commentBegin = current_ - 1;
-  Char c = getNextChar();
-  bool successful = false;
-  if (c == '*')
-    successful = readCStyleComment();
-  else if (c == '/')
-    successful = readCppStyleComment();
-  if (!successful)
-    return false;
-
-  if (collectComments_) {
-    CommentPlacement placement = commentBefore;
-    if (lastValueEnd_ && !containsNewLine(lastValueEnd_, commentBegin)) {
-      if (c != '*' || !containsNewLine(commentBegin, current_))
-        placement = commentAfterOnSameLine;
-    }
-
-    addComment(commentBegin, current_, placement);
-  }
-  return true;
-}
-
-void
-OurReader::addComment(Location begin, Location end, CommentPlacement placement) {
-  assert(collectComments_);
-  const std::string& normalized = normalizeEOL(begin, end);
-  if (placement == commentAfterOnSameLine) {
-    assert(lastValue_ != 0);
-    lastValue_->setComment(normalized, placement);
-  } else {
-    commentsBefore_ += normalized;
-  }
-}
-
-bool OurReader::readCStyleComment() {
-  while (current_ != end_) {
-    Char c = getNextChar();
-    if (c == '*' && *current_ == '/')
-      break;
-  }
-  return getNextChar() == '/';
-}
-
-bool OurReader::readCppStyleComment() {
-  while (current_ != end_) {
-    Char c = getNextChar();
-    if (c == '\n')
-      break;
-    if (c == '\r') {
-      // Consume DOS EOL. It will be normalized in addComment.
-      if (current_ != end_ && *current_ == '\n')
-        getNextChar();
-      // Break on Moc OS 9 EOL.
-      break;
-    }
-  }
-  return true;
-}
-
-bool OurReader::readNumber(bool checkInf) {
-  const char *p = current_;
-  if (checkInf && p != end_ && *p == 'I') {
-    current_ = ++p;
-    return false;
-  }
-  char c = '0'; // stopgap for already consumed character
-  // integral part
-  while (c >= '0' && c <= '9')
-    c = (current_ = p) < end_ ? *p++ : 0;
-  // fractional part
-  if (c == '.') {
-    c = (current_ = p) < end_ ? *p++ : 0;
-    while (c >= '0' && c <= '9')
-      c = (current_ = p) < end_ ? *p++ : 0;
-  }
-  // exponential part
-  if (c == 'e' || c == 'E') {
-    c = (current_ = p) < end_ ? *p++ : 0;
-    if (c == '+' || c == '-')
-      c = (current_ = p) < end_ ? *p++ : 0;
-    while (c >= '0' && c <= '9')
-      c = (current_ = p) < end_ ? *p++ : 0;
-  }
-  return true;
-}
-bool OurReader::readString() {
-  Char c = 0;
-  while (current_ != end_) {
-    c = getNextChar();
-    if (c == '\\')
-      getNextChar();
-    else if (c == '"')
-      break;
-  }
-  return c == '"';
-}
-
-
-bool OurReader::readStringSingleQuote() {
-  Char c = 0;
-  while (current_ != end_) {
-    c = getNextChar();
-    if (c == '\\')
-      getNextChar();
-    else if (c == '\'')
-      break;
-  }
-  return c == '\'';
-}
-
-bool OurReader::readObject(Token& tokenStart) {
-  Token tokenName;
-  std::string name;
-  Value init(objectValue);
-  currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
-  while (readToken(tokenName)) {
-    bool initialTokenOk = true;
-    while (tokenName.type_ == tokenComment && initialTokenOk)
-      initialTokenOk = readToken(tokenName);
-    if (!initialTokenOk)
-      break;
-    if (tokenName.type_ == tokenObjectEnd && name.empty()) // empty object
-      return true;
-    name = "";
-    if (tokenName.type_ == tokenString) {
-      if (!decodeString(tokenName, name))
-        return recoverFromError(tokenObjectEnd);
-    } else if (tokenName.type_ == tokenNumber && features_.allowNumericKeys_) {
-      Value numberName;
-      if (!decodeNumber(tokenName, numberName))
-        return recoverFromError(tokenObjectEnd);
-      name = numberName.asString();
-    } else {
-      break;
-    }
-
-    Token colon;
-    if (!readToken(colon) || colon.type_ != tokenMemberSeparator) {
-      return addErrorAndRecover(
-          "Missing ':' after object member name", colon, tokenObjectEnd);
-    }
-    if (name.length() >= (1U<<30)) throwRuntimeError("keylength >= 2^30");
-    if (features_.rejectDupKeys_ && currentValue().isMember(name)) {
-      std::string msg = "Duplicate key: '" + name + "'";
-      return addErrorAndRecover(
-          msg, tokenName, tokenObjectEnd);
-    }
-    Value& value = currentValue()[name];
-    nodes_.push(&value);
-    bool ok = readValue();
-    nodes_.pop();
-    if (!ok) // error already set
-      return recoverFromError(tokenObjectEnd);
-
-    Token comma;
-    if (!readToken(comma) ||
-        (comma.type_ != tokenObjectEnd && comma.type_ != tokenArraySeparator &&
-         comma.type_ != tokenComment)) {
-      return addErrorAndRecover(
-          "Missing ',' or '}' in object declaration", comma, tokenObjectEnd);
-    }
-    bool finalizeTokenOk = true;
-    while (comma.type_ == tokenComment && finalizeTokenOk)
-      finalizeTokenOk = readToken(comma);
-    if (comma.type_ == tokenObjectEnd)
-      return true;
-  }
-  return addErrorAndRecover(
-      "Missing '}' or object member name", tokenName, tokenObjectEnd);
-}
-
-bool OurReader::readArray(Token& tokenStart) {
-  Value init(arrayValue);
-  currentValue().swapPayload(init);
-  currentValue().setOffsetStart(tokenStart.start_ - begin_);
-  skipSpaces();
-  if (*current_ == ']') // empty array
-  {
-    Token endArray;
-    readToken(endArray);
-    return true;
-  }
-  int index = 0;
-  for (;;) {
-    Value& value = currentValue()[index++];
-    nodes_.push(&value);
-    bool ok = readValue();
-    nodes_.pop();
-    if (!ok) // error already set
-      return recoverFromError(tokenArrayEnd);
-
-    Token token;
-    // Accept Comment after last item in the array.
-    ok = readToken(token);
-    while (token.type_ == tokenComment && ok) {
-      ok = readToken(token);
-    }
-    bool badTokenType =
-        (token.type_ != tokenArraySeparator && token.type_ != tokenArrayEnd);
-    if (!ok || badTokenType) {
-      return addErrorAndRecover(
-          "Missing ',' or ']' in array declaration", token, tokenArrayEnd);
-    }
-    if (token.type_ == tokenArrayEnd)
-      break;
-  }
-  return true;
-}
-
-bool OurReader::decodeNumber(Token& token) {
-  Value decoded;
-  if (!decodeNumber(token, decoded))
-    return false;
-  currentValue().swapPayload(decoded);
-  currentValue().setOffsetStart(token.start_ - begin_);
-  currentValue().setOffsetLimit(token.end_ - begin_);
-  return true;
-}
-
-bool OurReader::decodeNumber(Token& token, Value& decoded) {
-  // Attempts to parse the number as an integer. If the number is
-  // larger than the maximum supported value of an integer then
-  // we decode the number as a double.
-  Location current = token.start_;
-  bool isNegative = *current == '-';
-  if (isNegative)
-    ++current;
-  // TODO: Help the compiler do the div and mod at compile time or get rid of them.
-  Value::LargestUInt maxIntegerValue =
-      isNegative ? Value::LargestUInt(-Value::minLargestInt)
-                 : Value::maxLargestUInt;
-  Value::LargestUInt threshold = maxIntegerValue / 10;
-  Value::LargestUInt value = 0;
-  while (current < token.end_) {
-    Char c = *current++;
-    if (c < '0' || c > '9')
-      return decodeDouble(token, decoded);
-    Value::UInt digit(c - '0');
-    if (value >= threshold) {
-      // We've hit or exceeded the max value divided by 10 (rounded down). If
-      // a) we've only just touched the limit, b) this is the last digit, and
-      // c) it's small enough to fit in that rounding delta, we're okay.
-      // Otherwise treat this number as a double to avoid overflow.
-      if (value > threshold || current != token.end_ ||
-          digit > maxIntegerValue % 10) {
-        return decodeDouble(token, decoded);
-      }
-    }
-    value = value * 10 + digit;
-  }
-  if (isNegative)
-    decoded = -Value::LargestInt(value);
-  else if (value <= Value::LargestUInt(Value::maxInt))
-    decoded = Value::LargestInt(value);
-  else
-    decoded = value;
-  return true;
-}
-
-bool OurReader::decodeDouble(Token& token) {
-  Value decoded;
-  if (!decodeDouble(token, decoded))
-    return false;
-  currentValue().swapPayload(decoded);
-  currentValue().setOffsetStart(token.start_ - begin_);
-  currentValue().setOffsetLimit(token.end_ - begin_);
-  return true;
-}
-
-bool OurReader::decodeDouble(Token& token, Value& decoded) {
-  double value = 0;
-  const int bufferSize = 32;
-  int count;
-  int length = int(token.end_ - token.start_);
-
-  // Sanity check to avoid buffer overflow exploits.
-  if (length < 0) {
-    return addError("Unable to parse token length", token);
-  }
-
-  // Avoid using a string constant for the format control string given to
-  // sscanf, as this can cause hard to debug crashes on OS X. See here for more
-  // info:
-  //
-  //     http://developer.apple.com/library/mac/#DOCUMENTATION/DeveloperTools/gcc-4.0.1/gcc/Incompatibilities.html
-  char format[] = "%lf";
-
-  if (length <= bufferSize) {
-    Char buffer[bufferSize + 1];
-    memcpy(buffer, token.start_, length);
-    buffer[length] = 0;
-    count = sscanf(buffer, format, &value);
-  } else {
-    std::string buffer(token.start_, token.end_);
-    count = sscanf(buffer.c_str(), format, &value);
-  }
-
-  if (count != 1)
-    return addError("'" + std::string(token.start_, token.end_) +
-                        "' is not a number.",
-                    token);
-  decoded = value;
-  return true;
-}
-
-bool OurReader::decodeString(Token& token) {
-  std::string decoded_string;
-  if (!decodeString(token, decoded_string))
-    return false;
-  Value decoded(decoded_string);
-  currentValue().swapPayload(decoded);
-  currentValue().setOffsetStart(token.start_ - begin_);
-  currentValue().setOffsetLimit(token.end_ - begin_);
-  return true;
-}
-
-bool OurReader::decodeString(Token& token, std::string& decoded) {
-  decoded.reserve(token.end_ - token.start_ - 2);
-  Location current = token.start_ + 1; // skip '"'
-  Location end = token.end_ - 1;       // do not include '"'
-  while (current != end) {
-    Char c = *current++;
-    if (c == '"')
-      break;
-    else if (c == '\\') {
-      if (current == end)
-        return addError("Empty escape sequence in string", token, current);
-      Char escape = *current++;
-      switch (escape) {
-      case '"':
-        decoded += '"';
-        break;
-      case '/':
-        decoded += '/';
-        break;
-      case '\\':
-        decoded += '\\';
-        break;
-      case 'b':
-        decoded += '\b';
-        break;
-      case 'f':
-        decoded += '\f';
-        break;
-      case 'n':
-        decoded += '\n';
-        break;
-      case 'r':
-        decoded += '\r';
-        break;
-      case 't':
-        decoded += '\t';
-        break;
-      case 'u': {
-        unsigned int unicode;
-        if (!decodeUnicodeCodePoint(token, current, end, unicode))
-          return false;
-        decoded += codePointToUTF8(unicode);
-      } break;
-      default:
-        return addError("Bad escape sequence in string", token, current);
-      }
-    } else {
-      decoded += c;
-    }
-  }
-  return true;
-}
-
-bool OurReader::decodeUnicodeCodePoint(Token& token,
-                                    Location& current,
-                                    Location end,
-                                    unsigned int& unicode) {
-
-  if (!decodeUnicodeEscapeSequence(token, current, end, unicode))
-    return false;
-  if (unicode >= 0xD800 && unicode <= 0xDBFF) {
-    // surrogate pairs
-    if (end - current < 6)
-      return addError(
-          "additional six characters expected to parse unicode surrogate pair.",
-          token,
-          current);
-    unsigned int surrogatePair;
-    if (*(current++) == '\\' && *(current++) == 'u') {
-      if (decodeUnicodeEscapeSequence(token, current, end, surrogatePair)) {
-        unicode = 0x10000 + ((unicode & 0x3FF) << 10) + (surrogatePair & 0x3FF);
-      } else
-        return false;
-    } else
-      return addError("expecting another \\u token to begin the second half of "
-                      "a unicode surrogate pair",
-                      token,
-                      current);
-  }
-  return true;
-}
-
-bool OurReader::decodeUnicodeEscapeSequence(Token& token,
-                                         Location& current,
-                                         Location end,
-                                         unsigned int& unicode) {
-  if (end - current < 4)
-    return addError(
-        "Bad unicode escape sequence in string: four digits expected.",
-        token,
-        current);
-  unicode = 0;
-  for (int index = 0; index < 4; ++index) {
-    Char c = *current++;
-    unicode *= 16;
-    if (c >= '0' && c <= '9')
-      unicode += c - '0';
-    else if (c >= 'a' && c <= 'f')
-      unicode += c - 'a' + 10;
-    else if (c >= 'A' && c <= 'F')
-      unicode += c - 'A' + 10;
-    else
-      return addError(
-          "Bad unicode escape sequence in string: hexadecimal digit expected.",
-          token,
-          current);
-  }
-  return true;
-}
-
-bool
-OurReader::addError(const std::string& message, Token& token, Location extra) {
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = extra;
-  errors_.push_back(info);
-  return false;
-}
-
-bool OurReader::recoverFromError(TokenType skipUntilToken) {
-  int errorCount = int(errors_.size());
-  Token skip;
-  for (;;) {
-    if (!readToken(skip))
-      errors_.resize(errorCount); // discard errors caused by recovery
-    if (skip.type_ == skipUntilToken || skip.type_ == tokenEndOfStream)
-      break;
-  }
-  errors_.resize(errorCount);
-  return false;
-}
-
-bool OurReader::addErrorAndRecover(const std::string& message,
-                                Token& token,
-                                TokenType skipUntilToken) {
-  addError(message, token);
-  return recoverFromError(skipUntilToken);
-}
-
-Value& OurReader::currentValue() { return *(nodes_.top()); }
-
-OurReader::Char OurReader::getNextChar() {
-  if (current_ == end_)
-    return 0;
-  return *current_++;
-}
-
-void OurReader::getLocationLineAndColumn(Location location,
-                                      int& line,
-                                      int& column) const {
-  Location current = begin_;
-  Location lastLineStart = current;
-  line = 0;
-  while (current < location && current != end_) {
-    Char c = *current++;
-    if (c == '\r') {
-      if (*current == '\n')
-        ++current;
-      lastLineStart = current;
-      ++line;
-    } else if (c == '\n') {
-      lastLineStart = current;
-      ++line;
-    }
-  }
-  // column & line start at 1
-  column = int(location - lastLineStart) + 1;
-  ++line;
-}
-
-std::string OurReader::getLocationLineAndColumn(Location location) const {
-  int line, column;
-  getLocationLineAndColumn(location, line, column);
-  char buffer[18 + 16 + 16 + 1];
-  snprintf(buffer, sizeof(buffer), "Line %d, Column %d", line, column);
-  return buffer;
-}
-
-std::string OurReader::getFormattedErrorMessages() const {
-  std::string formattedMessage;
-  for (Errors::const_iterator itError = errors_.begin();
-       itError != errors_.end();
-       ++itError) {
-    const ErrorInfo& error = *itError;
-    formattedMessage +=
-        "* " + getLocationLineAndColumn(error.token_.start_) + "\n";
-    formattedMessage += "  " + error.message_ + "\n";
-    if (error.extra_)
-      formattedMessage +=
-          "See " + getLocationLineAndColumn(error.extra_) + " for detail.\n";
-  }
-  return formattedMessage;
-}
-
-std::vector<OurReader::StructuredError> OurReader::getStructuredErrors() const {
-  std::vector<OurReader::StructuredError> allErrors;
-  for (Errors::const_iterator itError = errors_.begin();
-       itError != errors_.end();
-       ++itError) {
-    const ErrorInfo& error = *itError;
-    OurReader::StructuredError structured;
-    structured.offset_start = error.token_.start_ - begin_;
-    structured.offset_limit = error.token_.end_ - begin_;
-    structured.message = error.message_;
-    allErrors.push_back(structured);
-  }
-  return allErrors;
-}
-
-bool OurReader::pushError(const Value& value, const std::string& message) {
-  size_t length = end_ - begin_;
-  if(value.getOffsetStart() > length
-    || value.getOffsetLimit() > length)
-    return false;
-  Token token;
-  token.type_ = tokenError;
-  token.start_ = begin_ + value.getOffsetStart();
-  token.end_ = end_ + value.getOffsetLimit();
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = 0;
-  errors_.push_back(info);
-  return true;
-}
-
-bool OurReader::pushError(const Value& value, const std::string& message, const Value& extra) {
-  size_t length = end_ - begin_;
-  if(value.getOffsetStart() > length
-    || value.getOffsetLimit() > length
-    || extra.getOffsetLimit() > length)
-    return false;
-  Token token;
-  token.type_ = tokenError;
-  token.start_ = begin_ + value.getOffsetStart();
-  token.end_ = begin_ + value.getOffsetLimit();
-  ErrorInfo info;
-  info.token_ = token;
-  info.message_ = message;
-  info.extra_ = begin_ + extra.getOffsetStart();
-  errors_.push_back(info);
-  return true;
-}
-
-bool OurReader::good() const {
-  return !errors_.size();
-}
-
-
-class OurCharReader : public CharReader {
-  bool const collectComments_;
-  OurReader reader_;
-public:
-  OurCharReader(
-    bool collectComments,
-    OurFeatures const& features)
-  : collectComments_(collectComments)
-  , reader_(features)
-  {}
-  bool parse(
-      char const* beginDoc, char const* endDoc,
-      Value* root, std::string* errs) override {
-    bool ok = reader_.parse(beginDoc, endDoc, *root, collectComments_);
-    if (errs) {
-      *errs = reader_.getFormattedErrorMessages();
-    }
-    return ok;
-  }
-};
-
-CharReaderBuilder::CharReaderBuilder()
-{
-  setDefaults(&settings_);
-}
-CharReaderBuilder::~CharReaderBuilder()
-{}
-CharReader* CharReaderBuilder::newCharReader() const
-{
-  bool collectComments = settings_["collectComments"].asBool();
-  OurFeatures features = OurFeatures::all();
-  features.allowComments_ = settings_["allowComments"].asBool();
-  features.strictRoot_ = settings_["strictRoot"].asBool();
-  features.allowDroppedNullPlaceholders_ = settings_["allowDroppedNullPlaceholders"].asBool();
-  features.allowNumericKeys_ = settings_["allowNumericKeys"].asBool();
-  features.allowSingleQuotes_ = settings_["allowSingleQuotes"].asBool();
-  features.stackLimit_ = settings_["stackLimit"].asInt();
-  features.failIfExtra_ = settings_["failIfExtra"].asBool();
-  features.rejectDupKeys_ = settings_["rejectDupKeys"].asBool();
-  features.allowSpecialFloats_ = settings_["allowSpecialFloats"].asBool();
-  return new OurCharReader(collectComments, features);
-}
-static void getValidReaderKeys(std::set<std::string>* valid_keys)
-{
-  valid_keys->clear();
-  valid_keys->insert("collectComments");
-  valid_keys->insert("allowComments");
-  valid_keys->insert("strictRoot");
-  valid_keys->insert("allowDroppedNullPlaceholders");
-  valid_keys->insert("allowNumericKeys");
-  valid_keys->insert("allowSingleQuotes");
-  valid_keys->insert("stackLimit");
-  valid_keys->insert("failIfExtra");
-  valid_keys->insert("rejectDupKeys");
-  valid_keys->insert("allowSpecialFloats");
-}
-bool CharReaderBuilder::validate(Json::Value* invalid) const
-{
-  Json::Value my_invalid;
-  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
-  Json::Value& inv = *invalid;
-  std::set<std::string> valid_keys;
-  getValidReaderKeys(&valid_keys);
-  Value::Members keys = settings_.getMemberNames();
-  size_t n = keys.size();
-  for (size_t i = 0; i < n; ++i) {
-    std::string const& key = keys[i];
-    if (valid_keys.find(key) == valid_keys.end()) {
-      inv[key] = settings_[key];
-    }
-  }
-  return 0u == inv.size();
-}
-Value& CharReaderBuilder::operator[](std::string key)
-{
-  return settings_[key];
-}
-// static
-void CharReaderBuilder::strictMode(Json::Value* settings)
-{
-//! [CharReaderBuilderStrictMode]
-  (*settings)["allowComments"] = false;
-  (*settings)["strictRoot"] = true;
-  (*settings)["allowDroppedNullPlaceholders"] = false;
-  (*settings)["allowNumericKeys"] = false;
-  (*settings)["allowSingleQuotes"] = false;
-  (*settings)["stackLimit"] = 1000;
-  (*settings)["failIfExtra"] = true;
-  (*settings)["rejectDupKeys"] = true;
-  (*settings)["allowSpecialFloats"] = false;
-//! [CharReaderBuilderStrictMode]
-}
-// static
-void CharReaderBuilder::setDefaults(Json::Value* settings)
-{
-//! [CharReaderBuilderDefaults]
-  (*settings)["collectComments"] = true;
-  (*settings)["allowComments"] = true;
-  (*settings)["strictRoot"] = false;
-  (*settings)["allowDroppedNullPlaceholders"] = false;
-  (*settings)["allowNumericKeys"] = false;
-  (*settings)["allowSingleQuotes"] = false;
-  (*settings)["stackLimit"] = 1000;
-  (*settings)["failIfExtra"] = false;
-  (*settings)["rejectDupKeys"] = false;
-  (*settings)["allowSpecialFloats"] = false;
-//! [CharReaderBuilderDefaults]
-}
-
-//////////////////////////////////
-// global functions
-
-bool parseFromStream(
-    CharReader::Factory const& fact, std::istream& sin,
-    Value* root, std::string* errs)
-{
-  std::ostringstream ssin;
-  ssin << sin.rdbuf();
-  std::string doc = ssin.str();
-  char const* begin = doc.data();
-  char const* end = begin + doc.size();
-  // Note that we do not actually need a null-terminator.
-  CharReaderPtr const reader(fact.newCharReader());
-  return reader->parse(begin, end, root, errs);
-}
-
-std::istream& operator>>(std::istream& sin, Value& root) {
-  CharReaderBuilder b;
-  std::string errs;
-  bool ok = parseFromStream(b, sin, &root, &errs);
-  if (!ok) {
-    fprintf(stderr,
-            "Error from reader: %s",
-            errs.c_str());
-
-    throwRuntimeError(errs);
-  }
-  return sin;
-}
-
-} // namespace Json
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: src/lib_json/json_reader.cpp
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: src/lib_json/json_valueiterator.inl
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2007-2010 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-// included by json_value.cpp
-
-namespace Json {
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueIteratorBase
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueIteratorBase::ValueIteratorBase()
-    : current_(), isNull_(true) {
-}
-
-ValueIteratorBase::ValueIteratorBase(
-    const Value::ObjectValues::iterator& current)
-    : current_(current), isNull_(false) {}
-
-Value& ValueIteratorBase::deref() const {
-  return current_->second;
-}
-
-void ValueIteratorBase::increment() {
-  ++current_;
-}
-
-void ValueIteratorBase::decrement() {
-  --current_;
-}
-
-ValueIteratorBase::difference_type
-ValueIteratorBase::computeDistance(const SelfType& other) const {
-#ifdef JSON_USE_CPPTL_SMALLMAP
-  return other.current_ - current_;
-#else
-  // Iterator for null value are initialized using the default
-  // constructor, which initialize current_ to the default
-  // std::map::iterator. As begin() and end() are two instance
-  // of the default std::map::iterator, they can not be compared.
-  // To allow this, we handle this comparison specifically.
-  if (isNull_ && other.isNull_) {
-    return 0;
-  }
-
-  // Usage of std::distance is not portable (does not compile with Sun Studio 12
-  // RogueWave STL,
-  // which is the one used by default).
-  // Using a portable hand-made version for non random iterator instead:
-  //   return difference_type( std::distance( current_, other.current_ ) );
-  difference_type myDistance = 0;
-  for (Value::ObjectValues::iterator it = current_; it != other.current_;
-       ++it) {
-    ++myDistance;
-  }
-  return myDistance;
-#endif
-}
-
-bool ValueIteratorBase::isEqual(const SelfType& other) const {
-  if (isNull_) {
-    return other.isNull_;
-  }
-  return current_ == other.current_;
-}
-
-void ValueIteratorBase::copy(const SelfType& other) {
-  current_ = other.current_;
-  isNull_ = other.isNull_;
-}
-
-Value ValueIteratorBase::key() const {
-  const Value::CZString czstring = (*current_).first;
-  if (czstring.data()) {
-    if (czstring.isStaticString())
-      return Value(StaticString(czstring.data()));
-    return Value(czstring.data(), czstring.data() + czstring.length());
-  }
-  return Value(czstring.index());
-}
-
-UInt ValueIteratorBase::index() const {
-  const Value::CZString czstring = (*current_).first;
-  if (!czstring.data())
-    return czstring.index();
-  return Value::UInt(-1);
-}
-
-std::string ValueIteratorBase::name() const {
-  char const* keey;
-  char const* end;
-  keey = memberName(&end);
-  if (!keey) return std::string();
-  return std::string(keey, end);
-}
-
-char const* ValueIteratorBase::memberName() const {
-  const char* cname = (*current_).first.data();
-  return cname ? cname : "";
-}
-
-char const* ValueIteratorBase::memberName(char const** end) const {
-  const char* cname = (*current_).first.data();
-  if (!cname) {
-    *end = NULL;
-    return NULL;
-  }
-  *end = cname + (*current_).first.length();
-  return cname;
-}
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueConstIterator
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueConstIterator::ValueConstIterator() {}
-
-ValueConstIterator::ValueConstIterator(
-    const Value::ObjectValues::iterator& current)
-    : ValueIteratorBase(current) {}
-
-ValueConstIterator::ValueConstIterator(ValueIterator const& other)
-    : ValueIteratorBase(other) {}
-
-ValueConstIterator& ValueConstIterator::
-operator=(const ValueIteratorBase& other) {
-  copy(other);
-  return *this;
-}
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class ValueIterator
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-ValueIterator::ValueIterator() {}
-
-ValueIterator::ValueIterator(const Value::ObjectValues::iterator& current)
-    : ValueIteratorBase(current) {}
-
-ValueIterator::ValueIterator(const ValueConstIterator& other)
-    : ValueIteratorBase(other) {
-  throwRuntimeError("ConstIterator to Iterator should never be allowed.");
-}
-
-ValueIterator::ValueIterator(const ValueIterator& other)
-    : ValueIteratorBase(other) {}
-
-ValueIterator& ValueIterator::operator=(const SelfType& other) {
-  copy(other);
-  return *this;
-}
-
-} // namespace Json
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: src/lib_json/json_valueiterator.inl
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: src/lib_json/json_value.cpp
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2011 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include <json/assertions.h>
-#include <json/value.h>
-#include <json/writer.h>
-#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <math.h>
-#include <sstream>
-#include <utility>
-#include <cstring>
-#include <cassert>
-#ifdef JSON_USE_CPPTL
-#include <cpptl/conststring.h>
-#endif
-#include <cstddef> // size_t
-#include <algorithm> // min()
-
-#define JSON_ASSERT_UNREACHABLE assert(false)
-
-namespace Json {
-
-// This is a walkaround to avoid the static initialization of Value::null.
-// kNull must be word-aligned to avoid crashing on ARM.  We use an alignment of
-// 8 (instead of 4) as a bit of future-proofing.
-#if defined(__ARMEL__)
-#define ALIGNAS(byte_alignment) __attribute__((aligned(byte_alignment)))
-#else
-#define ALIGNAS(byte_alignment)
-#endif
-static const unsigned char ALIGNAS(8) kNull[sizeof(Value)] = { 0 };
-const unsigned char& kNullRef = kNull[0];
-const Value& Value::null = reinterpret_cast<const Value&>(kNullRef);
-const Value& Value::nullRef = null;
-
-const Int Value::minInt = Int(~(UInt(-1) / 2));
-const Int Value::maxInt = Int(UInt(-1) / 2);
-const UInt Value::maxUInt = UInt(-1);
-#if defined(JSON_HAS_INT64)
-const Int64 Value::minInt64 = Int64(~(UInt64(-1) / 2));
-const Int64 Value::maxInt64 = Int64(UInt64(-1) / 2);
-const UInt64 Value::maxUInt64 = UInt64(-1);
-// The constant is hard-coded because some compiler have trouble
-// converting Value::maxUInt64 to a double correctly (AIX/xlC).
-// Assumes that UInt64 is a 64 bits integer.
-static const double maxUInt64AsDouble = 18446744073709551615.0;
-#endif // defined(JSON_HAS_INT64)
-const LargestInt Value::minLargestInt = LargestInt(~(LargestUInt(-1) / 2));
-const LargestInt Value::maxLargestInt = LargestInt(LargestUInt(-1) / 2);
-const LargestUInt Value::maxLargestUInt = LargestUInt(-1);
-
-#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-template <typename T, typename U>
-static inline bool InRange(double d, T min, U max) {
-  return d >= min && d <= max;
-}
-#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-static inline double integerToDouble(Json::UInt64 value) {
-  return static_cast<double>(Int64(value / 2)) * 2.0 + Int64(value & 1);
-}
-
-template <typename T> static inline double integerToDouble(T value) {
-  return static_cast<double>(value);
-}
-
-template <typename T, typename U>
-static inline bool InRange(double d, T min, U max) {
-  return d >= integerToDouble(min) && d <= integerToDouble(max);
-}
-#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-
-/** Duplicates the specified string value.
- * @param value Pointer to the string to duplicate. Must be zero-terminated if
- *              length is "unknown".
- * @param length Length of the value. if equals to unknown, then it will be
- *               computed using strlen(value).
- * @return Pointer on the duplicate instance of string.
- */
-static inline char* duplicateStringValue(const char* value,
-                                         size_t length) {
-  // Avoid an integer overflow in the call to malloc below by limiting length
-  // to a sane value.
-  if (length >= (size_t)Value::maxInt)
-    length = Value::maxInt - 1;
-
-  char* newString = static_cast<char*>(malloc(length + 1));
-  if (newString == NULL) {
-    throwRuntimeError(
-        "in Json::Value::duplicateStringValue(): "
-        "Failed to allocate string value buffer");
-  }
-  memcpy(newString, value, length);
-  newString[length] = 0;
-  return newString;
-}
-
-/* Record the length as a prefix.
- */
-static inline char* duplicateAndPrefixStringValue(
-    const char* value,
-    unsigned int length)
-{
-  // Avoid an integer overflow in the call to malloc below by limiting length
-  // to a sane value.
-  JSON_ASSERT_MESSAGE(length <= (unsigned)Value::maxInt - sizeof(unsigned) - 1U,
-                      "in Json::Value::duplicateAndPrefixStringValue(): "
-                      "length too big for prefixing");
-  unsigned actualLength = length + static_cast<unsigned>(sizeof(unsigned)) + 1U;
-  char* newString = static_cast<char*>(malloc(actualLength));
-  if (newString == 0) {
-    throwRuntimeError(
-        "in Json::Value::duplicateAndPrefixStringValue(): "
-        "Failed to allocate string value buffer");
-  }
-  *reinterpret_cast<unsigned*>(newString) = length;
-  memcpy(newString + sizeof(unsigned), value, length);
-  newString[actualLength - 1U] = 0; // to avoid buffer over-run accidents by users later
-  return newString;
-}
-inline static void decodePrefixedString(
-    bool isPrefixed, char const* prefixed,
-    unsigned* length, char const** value)
-{
-  if (!isPrefixed) {
-    *length = static_cast<unsigned>(strlen(prefixed));
-    *value = prefixed;
-  } else {
-    *length = *reinterpret_cast<unsigned const*>(prefixed);
-    *value = prefixed + sizeof(unsigned);
-  }
-}
-/** Free the string duplicated by duplicateStringValue()/duplicateAndPrefixStringValue().
- */
-static inline void releaseStringValue(char* value) { free(value); }
-
-} // namespace Json
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// ValueInternals...
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-#if !defined(JSON_IS_AMALGAMATION)
-
-#include "json_valueiterator.inl"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-
-namespace Json {
-
-Exception::Exception(std::string const& msg)
-  : msg_(msg)
-{}
-Exception::~Exception() throw()
-{}
-char const* Exception::what() const throw()
-{
-  return msg_.c_str();
-}
-RuntimeError::RuntimeError(std::string const& msg)
-  : Exception(msg)
-{}
-LogicError::LogicError(std::string const& msg)
-  : Exception(msg)
-{}
-void throwRuntimeError(std::string const& msg)
-{
-  throw RuntimeError(msg);
-}
-void throwLogicError(std::string const& msg)
-{
-  throw LogicError(msg);
-}
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::CommentInfo
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-Value::CommentInfo::CommentInfo() : comment_(0) {}
-
-Value::CommentInfo::~CommentInfo() {
-  if (comment_)
-    releaseStringValue(comment_);
-}
-
-void Value::CommentInfo::setComment(const char* text, size_t len) {
-  if (comment_) {
-    releaseStringValue(comment_);
-    comment_ = 0;
-  }
-  JSON_ASSERT(text != 0);
-  JSON_ASSERT_MESSAGE(
-      text[0] == '\0' || text[0] == '/',
-      "in Json::Value::setComment(): Comments must start with /");
-  // It seems that /**/ style comments are acceptable as well.
-  comment_ = duplicateStringValue(text, len);
-}
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::CZString
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-// Notes: policy_ indicates if the string was allocated when
-// a string is stored.
-
-Value::CZString::CZString(ArrayIndex aindex) : cstr_(0), index_(aindex) {}
-
-Value::CZString::CZString(char const* str, unsigned ulength, DuplicationPolicy allocate)
-    : cstr_(str) {
-  // allocate != duplicate
-  storage_.policy_ = allocate & 0x3;
-  storage_.length_ = ulength & 0x3FFFFFFF;
-}
-
-Value::CZString::CZString(const CZString& other)
-    : cstr_(other.storage_.policy_ != noDuplication && other.cstr_ != 0
-                ? duplicateStringValue(other.cstr_, other.storage_.length_)
-                : other.cstr_) {
-  storage_.policy_ = (other.cstr_
-                 ? (static_cast<DuplicationPolicy>(other.storage_.policy_) == noDuplication
-                     ? noDuplication : duplicate)
-                 : static_cast<DuplicationPolicy>(other.storage_.policy_));
-  storage_.length_ = other.storage_.length_;
-}
-
-#if JSON_HAS_RVALUE_REFERENCES
-Value::CZString::CZString(CZString&& other)
-  : cstr_(other.cstr_), index_(other.index_) {
-  other.cstr_ = nullptr;
-}
-#endif
-
-Value::CZString::~CZString() {
-  if (cstr_ && storage_.policy_ == duplicate)
-    releaseStringValue(const_cast<char*>(cstr_));
-}
-
-void Value::CZString::swap(CZString& other) {
-  std::swap(cstr_, other.cstr_);
-  std::swap(index_, other.index_);
-}
-
-Value::CZString& Value::CZString::operator=(CZString other) {
-  swap(other);
-  return *this;
-}
-
-bool Value::CZString::operator<(const CZString& other) const {
-  if (!cstr_) return index_ < other.index_;
-  //return strcmp(cstr_, other.cstr_) < 0;
-  // Assume both are strings.
-  unsigned this_len = this->storage_.length_;
-  unsigned other_len = other.storage_.length_;
-  unsigned min_len = std::min(this_len, other_len);
-  int comp = memcmp(this->cstr_, other.cstr_, min_len);
-  if (comp < 0) return true;
-  if (comp > 0) return false;
-  return (this_len < other_len);
-}
-
-bool Value::CZString::operator==(const CZString& other) const {
-  if (!cstr_) return index_ == other.index_;
-  //return strcmp(cstr_, other.cstr_) == 0;
-  // Assume both are strings.
-  unsigned this_len = this->storage_.length_;
-  unsigned other_len = other.storage_.length_;
-  if (this_len != other_len) return false;
-  int comp = memcmp(this->cstr_, other.cstr_, this_len);
-  return comp == 0;
-}
-
-ArrayIndex Value::CZString::index() const { return index_; }
-
-//const char* Value::CZString::c_str() const { return cstr_; }
-const char* Value::CZString::data() const { return cstr_; }
-unsigned Value::CZString::length() const { return storage_.length_; }
-bool Value::CZString::isStaticString() const { return storage_.policy_ == noDuplication; }
-
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// class Value::Value
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-// //////////////////////////////////////////////////////////////////
-
-/*! \internal Default constructor initialization must be equivalent to:
- * memset( this, 0, sizeof(Value) )
- * This optimization is used in ValueInternalMap fast allocator.
- */
-Value::Value(ValueType vtype) {
-  initBasic(vtype);
-  switch (vtype) {
-  case nullValue:
-    break;
-  case intValue:
-  case uintValue:
-    value_.int_ = 0;
-    break;
-  case realValue:
-    value_.real_ = 0.0;
-    break;
-  case stringValue:
-    value_.string_ = 0;
-    break;
-  case arrayValue:
-  case objectValue:
-    value_.map_ = new ObjectValues();
-    break;
-  case booleanValue:
-    value_.bool_ = false;
-    break;
-  default:
-    JSON_ASSERT_UNREACHABLE;
-  }
-}
-
-Value::Value(Int value) {
-  initBasic(intValue);
-  value_.int_ = value;
-}
-
-Value::Value(UInt value) {
-  initBasic(uintValue);
-  value_.uint_ = value;
-}
-#if defined(JSON_HAS_INT64)
-Value::Value(Int64 value) {
-  initBasic(intValue);
-  value_.int_ = value;
-}
-Value::Value(UInt64 value) {
-  initBasic(uintValue);
-  value_.uint_ = value;
-}
-#endif // defined(JSON_HAS_INT64)
-
-Value::Value(double value) {
-  initBasic(realValue);
-  value_.real_ = value;
-}
-
-Value::Value(const char* value) {
-  initBasic(stringValue, true);
-  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(strlen(value)));
-}
-
-Value::Value(const char* beginValue, const char* endValue) {
-  initBasic(stringValue, true);
-  value_.string_ =
-      duplicateAndPrefixStringValue(beginValue, static_cast<unsigned>(endValue - beginValue));
-}
-
-Value::Value(const std::string& value) {
-  initBasic(stringValue, true);
-  value_.string_ =
-      duplicateAndPrefixStringValue(value.data(), static_cast<unsigned>(value.length()));
-}
-
-Value::Value(const StaticString& value) {
-  initBasic(stringValue);
-  value_.string_ = const_cast<char*>(value.c_str());
-}
-
-#ifdef JSON_USE_CPPTL
-Value::Value(const CppTL::ConstString& value) {
-  initBasic(stringValue, true);
-  value_.string_ = duplicateAndPrefixStringValue(value, static_cast<unsigned>(value.length()));
-}
-#endif
-
-Value::Value(bool value) {
-  initBasic(booleanValue);
-  value_.bool_ = value;
-}
-
-Value::Value(Value const& other)
-    : type_(other.type_), allocated_(false)
-      ,
-      comments_(0), start_(other.start_), limit_(other.limit_)
-{
-  switch (type_) {
-  case nullValue:
-  case intValue:
-  case uintValue:
-  case realValue:
-  case booleanValue:
-    value_ = other.value_;
-    break;
-  case stringValue:
-    if (other.value_.string_ && other.allocated_) {
-      unsigned len;
-      char const* str;
-      decodePrefixedString(other.allocated_, other.value_.string_,
-          &len, &str);
-      value_.string_ = duplicateAndPrefixStringValue(str, len);
-      allocated_ = true;
-    } else {
-      value_.string_ = other.value_.string_;
-      allocated_ = false;
-    }
-    break;
-  case arrayValue:
-  case objectValue:
-    value_.map_ = new ObjectValues(*other.value_.map_);
-    break;
-  default:
-    JSON_ASSERT_UNREACHABLE;
-  }
-  if (other.comments_) {
-    comments_ = new CommentInfo[numberOfCommentPlacement];
-    for (int comment = 0; comment < numberOfCommentPlacement; ++comment) {
-      const CommentInfo& otherComment = other.comments_[comment];
-      if (otherComment.comment_)
-        comments_[comment].setComment(
-            otherComment.comment_, strlen(otherComment.comment_));
-    }
-  }
-}
-
-#if JSON_HAS_RVALUE_REFERENCES
-// Move constructor
-Value::Value(Value&& other) {
-  initBasic(nullValue);
-  swap(other);
-}
-#endif
-
-Value::~Value() {
-  switch (type_) {
-  case nullValue:
-  case intValue:
-  case uintValue:
-  case realValue:
-  case booleanValue:
-    break;
-  case stringValue:
-    if (allocated_)
-      releaseStringValue(value_.string_);
-    break;
-  case arrayValue:
-  case objectValue:
-    delete value_.map_;
-    break;
-  default:
-    JSON_ASSERT_UNREACHABLE;
-  }
-
-  if (comments_)
-    delete[] comments_;
-}
-
-Value& Value::operator=(Value other) {
-  swap(other);
-  return *this;
-}
-
-void Value::swapPayload(Value& other) {
-  ValueType temp = type_;
-  type_ = other.type_;
-  other.type_ = temp;
-  std::swap(value_, other.value_);
-  int temp2 = allocated_;
-  allocated_ = other.allocated_;
-  other.allocated_ = temp2 & 0x1;
-}
-
-void Value::swap(Value& other) {
-  swapPayload(other);
-  std::swap(comments_, other.comments_);
-  std::swap(start_, other.start_);
-  std::swap(limit_, other.limit_);
-}
-
-ValueType Value::type() const { return type_; }
-
-int Value::compare(const Value& other) const {
-  if (*this < other)
-    return -1;
-  if (*this > other)
-    return 1;
-  return 0;
-}
-
-bool Value::operator<(const Value& other) const {
-  int typeDelta = type_ - other.type_;
-  if (typeDelta)
-    return typeDelta < 0 ? true : false;
-  switch (type_) {
-  case nullValue:
-    return false;
-  case intValue:
-    return value_.int_ < other.value_.int_;
-  case uintValue:
-    return value_.uint_ < other.value_.uint_;
-  case realValue:
-    return value_.real_ < other.value_.real_;
-  case booleanValue:
-    return value_.bool_ < other.value_.bool_;
-  case stringValue:
-  {
-    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
-      if (other.value_.string_) return true;
-      else return false;
-    }
-    unsigned this_len;
-    unsigned other_len;
-    char const* this_str;
-    char const* other_str;
-    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
-    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
-    unsigned min_len = std::min(this_len, other_len);
-    int comp = memcmp(this_str, other_str, min_len);
-    if (comp < 0) return true;
-    if (comp > 0) return false;
-    return (this_len < other_len);
-  }
-  case arrayValue:
-  case objectValue: {
-    int delta = int(value_.map_->size() - other.value_.map_->size());
-    if (delta)
-      return delta < 0;
-    return (*value_.map_) < (*other.value_.map_);
-  }
-  default:
-    JSON_ASSERT_UNREACHABLE;
-  }
-  return false; // unreachable
-}
-
-bool Value::operator<=(const Value& other) const { return !(other < *this); }
-
-bool Value::operator>=(const Value& other) const { return !(*this < other); }
-
-bool Value::operator>(const Value& other) const { return other < *this; }
-
-bool Value::operator==(const Value& other) const {
-  // if ( type_ != other.type_ )
-  // GCC 2.95.3 says:
-  // attempt to take address of bit-field structure member `Json::Value::type_'
-  // Beats me, but a temp solves the problem.
-  int temp = other.type_;
-  if (type_ != temp)
-    return false;
-  switch (type_) {
-  case nullValue:
-    return true;
-  case intValue:
-    return value_.int_ == other.value_.int_;
-  case uintValue:
-    return value_.uint_ == other.value_.uint_;
-  case realValue:
-    return value_.real_ == other.value_.real_;
-  case booleanValue:
-    return value_.bool_ == other.value_.bool_;
-  case stringValue:
-  {
-    if ((value_.string_ == 0) || (other.value_.string_ == 0)) {
-      return (value_.string_ == other.value_.string_);
-    }
-    unsigned this_len;
-    unsigned other_len;
-    char const* this_str;
-    char const* other_str;
-    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
-    decodePrefixedString(other.allocated_, other.value_.string_, &other_len, &other_str);
-    if (this_len != other_len) return false;
-    int comp = memcmp(this_str, other_str, this_len);
-    return comp == 0;
-  }
-  case arrayValue:
-  case objectValue:
-    return value_.map_->size() == other.value_.map_->size() &&
-           (*value_.map_) == (*other.value_.map_);
-  default:
-    JSON_ASSERT_UNREACHABLE;
-  }
-  return false; // unreachable
-}
-
-bool Value::operator!=(const Value& other) const { return !(*this == other); }
-
-const char* Value::asCString() const {
-  JSON_ASSERT_MESSAGE(type_ == stringValue,
-                      "in Json::Value::asCString(): requires stringValue");
-  if (value_.string_ == 0) return 0;
-  unsigned this_len;
-  char const* this_str;
-  decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
-  return this_str;
-}
-
-bool Value::getString(char const** str, char const** cend) const {
-  if (type_ != stringValue) return false;
-  if (value_.string_ == 0) return false;
-  unsigned length;
-  decodePrefixedString(this->allocated_, this->value_.string_, &length, str);
-  *cend = *str + length;
-  return true;
-}
-
-std::string Value::asString() const {
-  switch (type_) {
-  case nullValue:
-    return "";
-  case stringValue:
-  {
-    if (value_.string_ == 0) return "";
-    unsigned this_len;
-    char const* this_str;
-    decodePrefixedString(this->allocated_, this->value_.string_, &this_len, &this_str);
-    return std::string(this_str, this_len);
-  }
-  case booleanValue:
-    return value_.bool_ ? "true" : "false";
-  case intValue:
-    return valueToString(value_.int_);
-  case uintValue:
-    return valueToString(value_.uint_);
-  case realValue:
-    return valueToString(value_.real_);
-  default:
-    JSON_FAIL_MESSAGE("Type is not convertible to string");
-  }
-}
-
-#ifdef JSON_USE_CPPTL
-CppTL::ConstString Value::asConstString() const {
-  unsigned len;
-  char const* str;
-  decodePrefixedString(allocated_, value_.string_,
-      &len, &str);
-  return CppTL::ConstString(str, len);
-}
-#endif
-
-Value::Int Value::asInt() const {
-  switch (type_) {
-  case intValue:
-    JSON_ASSERT_MESSAGE(isInt(), "LargestInt out of Int range");
-    return Int(value_.int_);
-  case uintValue:
-    JSON_ASSERT_MESSAGE(isInt(), "LargestUInt out of Int range");
-    return Int(value_.uint_);
-  case realValue:
-    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt, maxInt),
-                        "double out of Int range");
-    return Int(value_.real_);
-  case nullValue:
-    return 0;
-  case booleanValue:
-    return value_.bool_ ? 1 : 0;
-  default:
-    break;
-  }
-  JSON_FAIL_MESSAGE("Value is not convertible to Int.");
-}
-
-Value::UInt Value::asUInt() const {
-  switch (type_) {
-  case intValue:
-    JSON_ASSERT_MESSAGE(isUInt(), "LargestInt out of UInt range");
-    return UInt(value_.int_);
-  case uintValue:
-    JSON_ASSERT_MESSAGE(isUInt(), "LargestUInt out of UInt range");
-    return UInt(value_.uint_);
-  case realValue:
-    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt),
-                        "double out of UInt range");
-    return UInt(value_.real_);
-  case nullValue:
-    return 0;
-  case booleanValue:
-    return value_.bool_ ? 1 : 0;
-  default:
-    break;
-  }
-  JSON_FAIL_MESSAGE("Value is not convertible to UInt.");
-}
-
-#if defined(JSON_HAS_INT64)
-
-Value::Int64 Value::asInt64() const {
-  switch (type_) {
-  case intValue:
-    return Int64(value_.int_);
-  case uintValue:
-    JSON_ASSERT_MESSAGE(isInt64(), "LargestUInt out of Int64 range");
-    return Int64(value_.uint_);
-  case realValue:
-    JSON_ASSERT_MESSAGE(InRange(value_.real_, minInt64, maxInt64),
-                        "double out of Int64 range");
-    return Int64(value_.real_);
-  case nullValue:
-    return 0;
-  case booleanValue:
-    return value_.bool_ ? 1 : 0;
-  default:
-    break;
-  }
-  JSON_FAIL_MESSAGE("Value is not convertible to Int64.");
-}
-
-Value::UInt64 Value::asUInt64() const {
-  switch (type_) {
-  case intValue:
-    JSON_ASSERT_MESSAGE(isUInt64(), "LargestInt out of UInt64 range");
-    return UInt64(value_.int_);
-  case uintValue:
-    return UInt64(value_.uint_);
-  case realValue:
-    JSON_ASSERT_MESSAGE(InRange(value_.real_, 0, maxUInt64),
-                        "double out of UInt64 range");
-    return UInt64(value_.real_);
-  case nullValue:
-    return 0;
-  case booleanValue:
-    return value_.bool_ ? 1 : 0;
-  default:
-    break;
-  }
-  JSON_FAIL_MESSAGE("Value is not convertible to UInt64.");
-}
-#endif // if defined(JSON_HAS_INT64)
-
-LargestInt Value::asLargestInt() const {
-#if defined(JSON_NO_INT64)
-  return asInt();
-#else
-  return asInt64();
-#endif
-}
-
-LargestUInt Value::asLargestUInt() const {
-#if defined(JSON_NO_INT64)
-  return asUInt();
-#else
-  return asUInt64();
-#endif
-}
-
-double Value::asDouble() const {
-  switch (type_) {
-  case intValue:
-    return static_cast<double>(value_.int_);
-  case uintValue:
-#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-    return static_cast<double>(value_.uint_);
-#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-    return integerToDouble(value_.uint_);
-#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-  case realValue:
-    return value_.real_;
-  case nullValue:
-    return 0.0;
-  case booleanValue:
-    return value_.bool_ ? 1.0 : 0.0;
-  default:
-    break;
-  }
-  JSON_FAIL_MESSAGE("Value is not convertible to double.");
-}
-
-float Value::asFloat() const {
-  switch (type_) {
-  case intValue:
-    return static_cast<float>(value_.int_);
-  case uintValue:
-#if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-    return static_cast<float>(value_.uint_);
-#else  // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-    return integerToDouble(value_.uint_);
-#endif // if !defined(JSON_USE_INT64_DOUBLE_CONVERSION)
-  case realValue:
-    return static_cast<float>(value_.real_);
-  case nullValue:
-    return 0.0;
-  case booleanValue:
-    return value_.bool_ ? 1.0f : 0.0f;
-  default:
-    break;
-  }
-  JSON_FAIL_MESSAGE("Value is not convertible to float.");
-}
-
-bool Value::asBool() const {
-  switch (type_) {
-  case booleanValue:
-    return value_.bool_;
-  case nullValue:
-    return false;
-  case intValue:
-    return value_.int_ ? true : false;
-  case uintValue:
-    return value_.uint_ ? true : false;
-  case realValue:
-    // This is kind of strange. Not recommended.
-    return (value_.real_ != 0.0) ? true : false;
-  default:
-    break;
-  }
-  JSON_FAIL_MESSAGE("Value is not convertible to bool.");
-}
-
-bool Value::isConvertibleTo(ValueType other) const {
-  switch (other) {
-  case nullValue:
-    return (isNumeric() && asDouble() == 0.0) ||
-           (type_ == booleanValue && value_.bool_ == false) ||
-           (type_ == stringValue && asString() == "") ||
-           (type_ == arrayValue && value_.map_->size() == 0) ||
-           (type_ == objectValue && value_.map_->size() == 0) ||
-           type_ == nullValue;
-  case intValue:
-    return isInt() ||
-           (type_ == realValue && InRange(value_.real_, minInt, maxInt)) ||
-           type_ == booleanValue || type_ == nullValue;
-  case uintValue:
-    return isUInt() ||
-           (type_ == realValue && InRange(value_.real_, 0, maxUInt)) ||
-           type_ == booleanValue || type_ == nullValue;
-  case realValue:
-    return isNumeric() || type_ == booleanValue || type_ == nullValue;
-  case booleanValue:
-    return isNumeric() || type_ == booleanValue || type_ == nullValue;
-  case stringValue:
-    return isNumeric() || type_ == booleanValue || type_ == stringValue ||
-           type_ == nullValue;
-  case arrayValue:
-    return type_ == arrayValue || type_ == nullValue;
-  case objectValue:
-    return type_ == objectValue || type_ == nullValue;
-  }
-  JSON_ASSERT_UNREACHABLE;
-  return false;
-}
-
-/// Number of values in array or object
-ArrayIndex Value::size() const {
-  switch (type_) {
-  case nullValue:
-  case intValue:
-  case uintValue:
-  case realValue:
-  case booleanValue:
-  case stringValue:
-    return 0;
-  case arrayValue: // size of the array is highest index + 1
-    if (!value_.map_->empty()) {
-      ObjectValues::const_iterator itLast = value_.map_->end();
-      --itLast;
-      return (*itLast).first.index() + 1;
-    }
-    return 0;
-  case objectValue:
-    return ArrayIndex(value_.map_->size());
-  }
-  JSON_ASSERT_UNREACHABLE;
-  return 0; // unreachable;
-}
-
-bool Value::empty() const {
-  if (isNull() || isArray() || isObject())
-    return size() == 0u;
-  else
-    return false;
-}
-
-bool Value::operator!() const { return isNull(); }
-
-void Value::clear() {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue ||
-                          type_ == objectValue,
-                      "in Json::Value::clear(): requires complex value");
-  start_ = 0;
-  limit_ = 0;
-  switch (type_) {
-  case arrayValue:
-  case objectValue:
-    value_.map_->clear();
-    break;
-  default:
-    break;
-  }
-}
-
-void Value::resize(ArrayIndex newSize) {
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == arrayValue,
-                      "in Json::Value::resize(): requires arrayValue");
-  if (type_ == nullValue)
-    *this = Value(arrayValue);
-  ArrayIndex oldSize = size();
-  if (newSize == 0)
-    clear();
-  else if (newSize > oldSize)
-    (*this)[newSize - 1];
-  else {
-    for (ArrayIndex index = newSize; index < oldSize; ++index) {
-      value_.map_->erase(index);
-    }
-    assert(size() == newSize);
-  }
-}
-
-Value& Value::operator[](ArrayIndex index) {
-  JSON_ASSERT_MESSAGE(
-      type_ == nullValue || type_ == arrayValue,
-      "in Json::Value::operator[](ArrayIndex): requires arrayValue");
-  if (type_ == nullValue)
-    *this = Value(arrayValue);
-  CZString key(index);
-  ObjectValues::iterator it = value_.map_->lower_bound(key);
-  if (it != value_.map_->end() && (*it).first == key)
-    return (*it).second;
-
-  ObjectValues::value_type defaultValue(key, nullRef);
-  it = value_.map_->insert(it, defaultValue);
-  return (*it).second;
-}
-
-Value& Value::operator[](int index) {
-  JSON_ASSERT_MESSAGE(
-      index >= 0,
-      "in Json::Value::operator[](int index): index cannot be negative");
-  return (*this)[ArrayIndex(index)];
-}
-
-const Value& Value::operator[](ArrayIndex index) const {
-  JSON_ASSERT_MESSAGE(
-      type_ == nullValue || type_ == arrayValue,
-      "in Json::Value::operator[](ArrayIndex)const: requires arrayValue");
-  if (type_ == nullValue)
-    return nullRef;
-  CZString key(index);
-  ObjectValues::const_iterator it = value_.map_->find(key);
-  if (it == value_.map_->end())
-    return nullRef;
-  return (*it).second;
-}
-
-const Value& Value::operator[](int index) const {
-  JSON_ASSERT_MESSAGE(
-      index >= 0,
-      "in Json::Value::operator[](int index) const: index cannot be negative");
-  return (*this)[ArrayIndex(index)];
-}
-
-void Value::initBasic(ValueType vtype, bool allocated) {
-  type_ = vtype;
-  allocated_ = allocated;
-  comments_ = 0;
-  start_ = 0;
-  limit_ = 0;
-}
-
-// Access an object value by name, create a null member if it does not exist.
-// @pre Type of '*this' is object or null.
-// @param key is null-terminated.
-Value& Value::resolveReference(const char* key) {
-  JSON_ASSERT_MESSAGE(
-      type_ == nullValue || type_ == objectValue,
-      "in Json::Value::resolveReference(): requires objectValue");
-  if (type_ == nullValue)
-    *this = Value(objectValue);
-  CZString actualKey(
-      key, static_cast<unsigned>(strlen(key)), CZString::noDuplication); // NOTE!
-  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
-  if (it != value_.map_->end() && (*it).first == actualKey)
-    return (*it).second;
-
-  ObjectValues::value_type defaultValue(actualKey, nullRef);
-  it = value_.map_->insert(it, defaultValue);
-  Value& value = (*it).second;
-  return value;
-}
-
-// @param key is not null-terminated.
-Value& Value::resolveReference(char const* key, char const* cend)
-{
-  JSON_ASSERT_MESSAGE(
-      type_ == nullValue || type_ == objectValue,
-      "in Json::Value::resolveReference(key, end): requires objectValue");
-  if (type_ == nullValue)
-    *this = Value(objectValue);
-  CZString actualKey(
-      key, static_cast<unsigned>(cend-key), CZString::duplicateOnCopy);
-  ObjectValues::iterator it = value_.map_->lower_bound(actualKey);
-  if (it != value_.map_->end() && (*it).first == actualKey)
-    return (*it).second;
-
-  ObjectValues::value_type defaultValue(actualKey, nullRef);
-  it = value_.map_->insert(it, defaultValue);
-  Value& value = (*it).second;
-  return value;
-}
-
-Value Value::get(ArrayIndex index, const Value& defaultValue) const {
-  const Value* value = &((*this)[index]);
-  return value == &nullRef ? defaultValue : *value;
-}
-
-bool Value::isValidIndex(ArrayIndex index) const { return index < size(); }
-
-Value const* Value::find(char const* key, char const* cend) const
-{
-  JSON_ASSERT_MESSAGE(
-      type_ == nullValue || type_ == objectValue,
-      "in Json::Value::find(key, end, found): requires objectValue or nullValue");
-  if (type_ == nullValue) return NULL;
-  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
-  ObjectValues::const_iterator it = value_.map_->find(actualKey);
-  if (it == value_.map_->end()) return NULL;
-  return &(*it).second;
-}
-const Value& Value::operator[](const char* key) const
-{
-  Value const* found = find(key, key + strlen(key));
-  if (!found) return nullRef;
-  return *found;
-}
-Value const& Value::operator[](std::string const& key) const
-{
-  Value const* found = find(key.data(), key.data() + key.length());
-  if (!found) return nullRef;
-  return *found;
-}
-
-Value& Value::operator[](const char* key) {
-  return resolveReference(key, key + strlen(key));
-}
-
-Value& Value::operator[](const std::string& key) {
-  return resolveReference(key.data(), key.data() + key.length());
-}
-
-Value& Value::operator[](const StaticString& key) {
-  return resolveReference(key.c_str());
-}
-
-#ifdef JSON_USE_CPPTL
-Value& Value::operator[](const CppTL::ConstString& key) {
-  return resolveReference(key.c_str(), key.end_c_str());
-}
-Value const& Value::operator[](CppTL::ConstString const& key) const
-{
-  Value const* found = find(key.c_str(), key.end_c_str());
-  if (!found) return nullRef;
-  return *found;
-}
-#endif
-
-Value& Value::append(const Value& value) { return (*this)[size()] = value; }
-
-Value Value::get(char const* key, char const* cend, Value const& defaultValue) const
-{
-  Value const* found = find(key, cend);
-  return !found ? defaultValue : *found;
-}
-Value Value::get(char const* key, Value const& defaultValue) const
-{
-  return get(key, key + strlen(key), defaultValue);
-}
-Value Value::get(std::string const& key, Value const& defaultValue) const
-{
-  return get(key.data(), key.data() + key.length(), defaultValue);
-}
-
-
-bool Value::removeMember(const char* key, const char* cend, Value* removed)
-{
-  if (type_ != objectValue) {
-    return false;
-  }
-  CZString actualKey(key, static_cast<unsigned>(cend-key), CZString::noDuplication);
-  ObjectValues::iterator it = value_.map_->find(actualKey);
-  if (it == value_.map_->end())
-    return false;
-  *removed = it->second;
-  value_.map_->erase(it);
-  return true;
-}
-bool Value::removeMember(const char* key, Value* removed)
-{
-  return removeMember(key, key + strlen(key), removed);
-}
-bool Value::removeMember(std::string const& key, Value* removed)
-{
-  return removeMember(key.data(), key.data() + key.length(), removed);
-}
-Value Value::removeMember(const char* key)
-{
-  JSON_ASSERT_MESSAGE(type_ == nullValue || type_ == objectValue,
-                      "in Json::Value::removeMember(): requires objectValue");
-  if (type_ == nullValue)
-    return nullRef;
-
-  Value removed;  // null
-  removeMember(key, key + strlen(key), &removed);
-  return removed; // still null if removeMember() did nothing
-}
-Value Value::removeMember(const std::string& key)
-{
-  return removeMember(key.c_str());
-}
-
-bool Value::removeIndex(ArrayIndex index, Value* removed) {
-  if (type_ != arrayValue) {
-    return false;
-  }
-  CZString key(index);
-  ObjectValues::iterator it = value_.map_->find(key);
-  if (it == value_.map_->end()) {
-    return false;
-  }
-  *removed = it->second;
-  ArrayIndex oldSize = size();
-  // shift left all items left, into the place of the "removed"
-  for (ArrayIndex i = index; i < (oldSize - 1); ++i){
-    CZString keey(i);
-    (*value_.map_)[keey] = (*this)[i + 1];
-  }
-  // erase the last one ("leftover")
-  CZString keyLast(oldSize - 1);
-  ObjectValues::iterator itLast = value_.map_->find(keyLast);
-  value_.map_->erase(itLast);
-  return true;
-}
-
-#ifdef JSON_USE_CPPTL
-Value Value::get(const CppTL::ConstString& key,
-                 const Value& defaultValue) const {
-  return get(key.c_str(), key.end_c_str(), defaultValue);
-}
-#endif
-
-bool Value::isMember(char const* key, char const* cend) const
-{
-  Value const* value = find(key, cend);
-  return NULL != value;
-}
-bool Value::isMember(char const* key) const
-{
-  return isMember(key, key + strlen(key));
-}
-bool Value::isMember(std::string const& key) const
-{
-  return isMember(key.data(), key.data() + key.length());
-}
-
-#ifdef JSON_USE_CPPTL
-bool Value::isMember(const CppTL::ConstString& key) const {
-  return isMember(key.c_str(), key.end_c_str());
-}
-#endif
-
-Value::Members Value::getMemberNames() const {
-  JSON_ASSERT_MESSAGE(
-      type_ == nullValue || type_ == objectValue,
-      "in Json::Value::getMemberNames(), value must be objectValue");
-  if (type_ == nullValue)
-    return Value::Members();
-  Members members;
-  members.reserve(value_.map_->size());
-  ObjectValues::const_iterator it = value_.map_->begin();
-  ObjectValues::const_iterator itEnd = value_.map_->end();
-  for (; it != itEnd; ++it) {
-    members.push_back(std::string((*it).first.data(),
-                                  (*it).first.length()));
-  }
-  return members;
-}
-//
-//# ifdef JSON_USE_CPPTL
-// EnumMemberNames
-// Value::enumMemberNames() const
-//{
-//   if ( type_ == objectValue )
-//   {
-//      return CppTL::Enum::any(  CppTL::Enum::transform(
-//         CppTL::Enum::keys( *(value_.map_), CppTL::Type<const CZString &>() ),
-//         MemberNamesTransform() ) );
-//   }
-//   return EnumMemberNames();
-//}
-//
-//
-// EnumValues
-// Value::enumValues() const
-//{
-//   if ( type_ == objectValue  ||  type_ == arrayValue )
-//      return CppTL::Enum::anyValues( *(value_.map_),
-//                                     CppTL::Type<const Value &>() );
-//   return EnumValues();
-//}
-//
-//# endif
-
-static bool IsIntegral(double d) {
-  double integral_part;
-  return modf(d, &integral_part) == 0.0;
-}
-
-bool Value::isNull() const { return type_ == nullValue; }
-
-bool Value::isBool() const { return type_ == booleanValue; }
-
-bool Value::isInt() const {
-  switch (type_) {
-  case intValue:
-    return value_.int_ >= minInt && value_.int_ <= maxInt;
-  case uintValue:
-    return value_.uint_ <= UInt(maxInt);
-  case realValue:
-    return value_.real_ >= minInt && value_.real_ <= maxInt &&
-           IsIntegral(value_.real_);
-  default:
-    break;
-  }
-  return false;
-}
-
-bool Value::isUInt() const {
-  switch (type_) {
-  case intValue:
-    return value_.int_ >= 0 && LargestUInt(value_.int_) <= LargestUInt(maxUInt);
-  case uintValue:
-    return value_.uint_ <= maxUInt;
-  case realValue:
-    return value_.real_ >= 0 && value_.real_ <= maxUInt &&
-           IsIntegral(value_.real_);
-  default:
-    break;
-  }
-  return false;
-}
-
-bool Value::isInt64() const {
-#if defined(JSON_HAS_INT64)
-  switch (type_) {
-  case intValue:
-    return true;
-  case uintValue:
-    return value_.uint_ <= UInt64(maxInt64);
-  case realValue:
-    // Note that maxInt64 (= 2^63 - 1) is not exactly representable as a
-    // double, so double(maxInt64) will be rounded up to 2^63. Therefore we
-    // require the value to be strictly less than the limit.
-    return value_.real_ >= double(minInt64) &&
-           value_.real_ < double(maxInt64) && IsIntegral(value_.real_);
-  default:
-    break;
-  }
-#endif // JSON_HAS_INT64
-  return false;
-}
-
-bool Value::isUInt64() const {
-#if defined(JSON_HAS_INT64)
-  switch (type_) {
-  case intValue:
-    return value_.int_ >= 0;
-  case uintValue:
-    return true;
-  case realValue:
-    // Note that maxUInt64 (= 2^64 - 1) is not exactly representable as a
-    // double, so double(maxUInt64) will be rounded up to 2^64. Therefore we
-    // require the value to be strictly less than the limit.
-    return value_.real_ >= 0 && value_.real_ < maxUInt64AsDouble &&
-           IsIntegral(value_.real_);
-  default:
-    break;
-  }
-#endif // JSON_HAS_INT64
-  return false;
-}
-
-bool Value::isIntegral() const {
-#if defined(JSON_HAS_INT64)
-  return isInt64() || isUInt64();
-#else
-  return isInt() || isUInt();
-#endif
-}
-
-bool Value::isDouble() const { return type_ == realValue || isIntegral(); }
-
-bool Value::isNumeric() const { return isIntegral() || isDouble(); }
-
-bool Value::isString() const { return type_ == stringValue; }
-
-bool Value::isArray() const { return type_ == arrayValue; }
-
-bool Value::isObject() const { return type_ == objectValue; }
-
-void Value::setComment(const char* comment, size_t len, CommentPlacement placement) {
-  if (!comments_)
-    comments_ = new CommentInfo[numberOfCommentPlacement];
-  if ((len > 0) && (comment[len-1] == '\n')) {
-    // Always discard trailing newline, to aid indentation.
-    len -= 1;
-  }
-  comments_[placement].setComment(comment, len);
-}
-
-void Value::setComment(const char* comment, CommentPlacement placement) {
-  setComment(comment, strlen(comment), placement);
-}
-
-void Value::setComment(const std::string& comment, CommentPlacement placement) {
-  setComment(comment.c_str(), comment.length(), placement);
-}
-
-bool Value::hasComment(CommentPlacement placement) const {
-  return comments_ != 0 && comments_[placement].comment_ != 0;
-}
-
-std::string Value::getComment(CommentPlacement placement) const {
-  if (hasComment(placement))
-    return comments_[placement].comment_;
-  return "";
-}
-
-void Value::setOffsetStart(size_t start) { start_ = start; }
-
-void Value::setOffsetLimit(size_t limit) { limit_ = limit; }
-
-size_t Value::getOffsetStart() const { return start_; }
-
-size_t Value::getOffsetLimit() const { return limit_; }
-
-std::string Value::toStyledString() const {
-  StyledWriter writer;
-  return writer.write(*this);
-}
-
-Value::const_iterator Value::begin() const {
-  switch (type_) {
-  case arrayValue:
-  case objectValue:
-    if (value_.map_)
-      return const_iterator(value_.map_->begin());
-    break;
-  default:
-    break;
-  }
-  return const_iterator();
-}
-
-Value::const_iterator Value::end() const {
-  switch (type_) {
-  case arrayValue:
-  case objectValue:
-    if (value_.map_)
-      return const_iterator(value_.map_->end());
-    break;
-  default:
-    break;
-  }
-  return const_iterator();
-}
-
-Value::iterator Value::begin() {
-  switch (type_) {
-  case arrayValue:
-  case objectValue:
-    if (value_.map_)
-      return iterator(value_.map_->begin());
-    break;
-  default:
-    break;
-  }
-  return iterator();
-}
-
-Value::iterator Value::end() {
-  switch (type_) {
-  case arrayValue:
-  case objectValue:
-    if (value_.map_)
-      return iterator(value_.map_->end());
-    break;
-  default:
-    break;
-  }
-  return iterator();
-}
-
-// class PathArgument
-// //////////////////////////////////////////////////////////////////
-
-PathArgument::PathArgument() : key_(), index_(), kind_(kindNone) {}
-
-PathArgument::PathArgument(ArrayIndex index)
-    : key_(), index_(index), kind_(kindIndex) {}
-
-PathArgument::PathArgument(const char* key)
-    : key_(key), index_(), kind_(kindKey) {}
-
-PathArgument::PathArgument(const std::string& key)
-    : key_(key.c_str()), index_(), kind_(kindKey) {}
-
-// class Path
-// //////////////////////////////////////////////////////////////////
-
-Path::Path(const std::string& path,
-           const PathArgument& a1,
-           const PathArgument& a2,
-           const PathArgument& a3,
-           const PathArgument& a4,
-           const PathArgument& a5) {
-  InArgs in;
-  in.push_back(&a1);
-  in.push_back(&a2);
-  in.push_back(&a3);
-  in.push_back(&a4);
-  in.push_back(&a5);
-  makePath(path, in);
-}
-
-void Path::makePath(const std::string& path, const InArgs& in) {
-  const char* current = path.c_str();
-  const char* end = current + path.length();
-  InArgs::const_iterator itInArg = in.begin();
-  while (current != end) {
-    if (*current == '[') {
-      ++current;
-      if (*current == '%')
-        addPathInArg(path, in, itInArg, PathArgument::kindIndex);
-      else {
-        ArrayIndex index = 0;
-        for (; current != end && *current >= '0' && *current <= '9'; ++current)
-          index = index * 10 + ArrayIndex(*current - '0');
-        args_.push_back(index);
-      }
-      if (current == end || *current++ != ']')
-        invalidPath(path, int(current - path.c_str()));
-    } else if (*current == '%') {
-      addPathInArg(path, in, itInArg, PathArgument::kindKey);
-      ++current;
-    } else if (*current == '.') {
-      ++current;
-    } else {
-      const char* beginName = current;
-      while (current != end && !strchr("[.", *current))
-        ++current;
-      args_.push_back(std::string(beginName, current));
-    }
-  }
-}
-
-void Path::addPathInArg(const std::string& /*path*/,
-                        const InArgs& in,
-                        InArgs::const_iterator& itInArg,
-                        PathArgument::Kind kind) {
-  if (itInArg == in.end()) {
-    // Error: missing argument %d
-  } else if ((*itInArg)->kind_ != kind) {
-    // Error: bad argument type
-  } else {
-    args_.push_back(**itInArg);
-  }
-}
-
-void Path::invalidPath(const std::string& /*path*/, int /*location*/) {
-  // Error: invalid path.
-}
-
-const Value& Path::resolve(const Value& root) const {
-  const Value* node = &root;
-  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
-    const PathArgument& arg = *it;
-    if (arg.kind_ == PathArgument::kindIndex) {
-      if (!node->isArray() || !node->isValidIndex(arg.index_)) {
-        // Error: unable to resolve path (array value expected at position...
-      }
-      node = &((*node)[arg.index_]);
-    } else if (arg.kind_ == PathArgument::kindKey) {
-      if (!node->isObject()) {
-        // Error: unable to resolve path (object value expected at position...)
-      }
-      node = &((*node)[arg.key_]);
-      if (node == &Value::nullRef) {
-        // Error: unable to resolve path (object has no member named '' at
-        // position...)
-      }
-    }
-  }
-  return *node;
-}
-
-Value Path::resolve(const Value& root, const Value& defaultValue) const {
-  const Value* node = &root;
-  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
-    const PathArgument& arg = *it;
-    if (arg.kind_ == PathArgument::kindIndex) {
-      if (!node->isArray() || !node->isValidIndex(arg.index_))
-        return defaultValue;
-      node = &((*node)[arg.index_]);
-    } else if (arg.kind_ == PathArgument::kindKey) {
-      if (!node->isObject())
-        return defaultValue;
-      node = &((*node)[arg.key_]);
-      if (node == &Value::nullRef)
-        return defaultValue;
-    }
-  }
-  return *node;
-}
-
-Value& Path::make(Value& root) const {
-  Value* node = &root;
-  for (Args::const_iterator it = args_.begin(); it != args_.end(); ++it) {
-    const PathArgument& arg = *it;
-    if (arg.kind_ == PathArgument::kindIndex) {
-      if (!node->isArray()) {
-        // Error: node is not an array at position ...
-      }
-      node = &((*node)[arg.index_]);
-    } else if (arg.kind_ == PathArgument::kindKey) {
-      if (!node->isObject()) {
-        // Error: node is not an object at position...
-      }
-      node = &((*node)[arg.key_]);
-    }
-  }
-  return *node;
-}
-
-} // namespace Json
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: src/lib_json/json_value.cpp
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
-
-// //////////////////////////////////////////////////////////////////////
-// Beginning of content of file: src/lib_json/json_writer.cpp
-// //////////////////////////////////////////////////////////////////////
-
-// Copyright 2011 Baptiste Lepilleur
-// Distributed under MIT license, or public domain if desired and
-// recognized in your jurisdiction.
-// See file LICENSE for detail or copy at http://jsoncpp.sourceforge.net/LICENSE
-
-#if !defined(JSON_IS_AMALGAMATION)
-#include <json/writer.h>
-#include "json_tool.h"
-#endif // if !defined(JSON_IS_AMALGAMATION)
-#include <iomanip>
-#include <memory>
-#include <sstream>
-#include <utility>
-#include <set>
-#include <cassert>
-#include <cstring>
-#include <cstdio>
-
-#if defined(_MSC_VER) && _MSC_VER >= 1200 && _MSC_VER < 1800 // Between VC++ 6.0 and VC++ 11.0
-#include <float.h>
-#define isfinite _finite
-#elif defined(__sun) && defined(__SVR4) //Solaris
-#if !defined(isfinite)
-#include <ieeefp.h>
-#define isfinite finite
-#endif
-#elif defined(_AIX)
-#if !defined(isfinite)
-#include <math.h>
-#define isfinite finite
-#endif
-#elif defined(__hpux)
-#if !defined(isfinite)
-#if defined(__ia64) && !defined(finite)
-#define isfinite(x) ((sizeof(x) == sizeof(float) ? \
-                     _Isfinitef(x) : _IsFinite(x)))
-#else
-#include <math.h>
-#define isfinite finite
-#endif
-#endif
-#else
-#include <cmath>
-#if !(defined(__QNXNTO__)) // QNX already defines isfinite
-#define isfinite std::isfinite
-#endif
-#endif
-
-#if defined(_MSC_VER)
-#if !defined(WINCE) && defined(__STDC_SECURE_LIB__) && _MSC_VER >= 1500 // VC++ 9.0 and above
-#define snprintf sprintf_s
-#elif _MSC_VER >= 1900 // VC++ 14.0 and above
-#define snprintf std::snprintf
-#else
-#define snprintf _snprintf
-#endif
-#elif defined(__ANDROID__) || defined(__QNXNTO__)
-#define snprintf snprintf
-#elif __cplusplus >= 201103L
-#define snprintf std::snprintf
-#endif
-
-#if defined(__BORLANDC__)
-#include <float.h>
-#define isfinite _finite
-#define snprintf _snprintf
-#endif
-
-#if defined(_MSC_VER) && _MSC_VER >= 1400 // VC++ 8.0
-// Disable warning about strdup being deprecated.
-#pragma warning(disable : 4996)
-#endif
-
-namespace Json {
-
-#if __cplusplus >= 201103L || (defined(_CPPLIB_VER) && _CPPLIB_VER >= 520)
-typedef std::unique_ptr<StreamWriter> StreamWriterPtr;
-#else
-typedef std::auto_ptr<StreamWriter>   StreamWriterPtr;
-#endif
-
-static bool containsControlCharacter(const char* str) {
-  while (*str) {
-    if (isControlCharacter(*(str++)))
-      return true;
-  }
-  return false;
-}
-
-static bool containsControlCharacter0(const char* str, unsigned len) {
-  char const* end = str + len;
-  while (end != str) {
-    if (isControlCharacter(*str) || 0==*str)
-      return true;
-    ++str;
-  }
-  return false;
-}
-
-std::string valueToString(LargestInt value) {
-  UIntToStringBuffer buffer;
-  char* current = buffer + sizeof(buffer);
-  if (value == Value::minLargestInt) {
-    uintToString(LargestUInt(Value::maxLargestInt) + 1, current);
-    *--current = '-';
-  } else if (value < 0) {
-    uintToString(LargestUInt(-value), current);
-    *--current = '-';
-  } else {
-    uintToString(LargestUInt(value), current);
-  }
-  assert(current >= buffer);
-  return current;
-}
-
-std::string valueToString(LargestUInt value) {
-  UIntToStringBuffer buffer;
-  char* current = buffer + sizeof(buffer);
-  uintToString(value, current);
-  assert(current >= buffer);
-  return current;
-}
-
-#if defined(JSON_HAS_INT64)
-
-std::string valueToString(Int value) {
-  return valueToString(LargestInt(value));
-}
-
-std::string valueToString(UInt value) {
-  return valueToString(LargestUInt(value));
-}
-
-#endif // # if defined(JSON_HAS_INT64)
-
-std::string valueToString(double value, bool useSpecialFloats, unsigned int precision) {
-  // Allocate a buffer that is more than large enough to store the 16 digits of
-  // precision requested below.
-  char buffer[32];
-  int len = -1;
-
-  char formatString[6];
-  sprintf(formatString, "%%.%dg", precision);
-
-  // Print into the buffer. We need not request the alternative representation
-  // that always has a decimal point because JSON doesn't distinguish the
-  // concepts of reals and integers.
-  if (isfinite(value)) {
-    len = snprintf(buffer, sizeof(buffer), formatString, value);
-  } else {
-    // IEEE standard states that NaN values will not compare to themselves
-    if (value != value) {
-      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "NaN" : "null");
-    } else if (value < 0) {
-      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "-Infinity" : "-1e+9999");
-    } else {
-      len = snprintf(buffer, sizeof(buffer), useSpecialFloats ? "Infinity" : "1e+9999");
-    }
-    // For those, we do not need to call fixNumLoc, but it is fast.
-  }
-  assert(len >= 0);
-  fixNumericLocale(buffer, buffer + len);
-  return buffer;
-}
-
-std::string valueToString(double value) { return valueToString(value, false, 17); }
-
-std::string valueToString(bool value) { return value ? "true" : "false"; }
-
-std::string valueToQuotedString(const char* value) {
-  if (value == NULL)
-    return "";
-  // Not sure how to handle unicode...
-  if (strpbrk(value, "\"\\\b\f\n\r\t") == NULL &&
-      !containsControlCharacter(value))
-    return std::string("\"") + value + "\"";
-  // We have to walk value and escape any special characters.
-  // Appending to std::string is not efficient, but this should be rare.
-  // (Note: forward slashes are *not* rare, but I am not escaping them.)
-  std::string::size_type maxsize =
-      strlen(value) * 2 + 3; // allescaped+quotes+NULL
-  std::string result;
-  result.reserve(maxsize); // to avoid lots of mallocs
-  result += "\"";
-  for (const char* c = value; *c != 0; ++c) {
-    switch (*c) {
-    case '\"':
-      result += "\\\"";
-      break;
-    case '\\':
-      result += "\\\\";
-      break;
-    case '\b':
-      result += "\\b";
-      break;
-    case '\f':
-      result += "\\f";
-      break;
-    case '\n':
-      result += "\\n";
-      break;
-    case '\r':
-      result += "\\r";
-      break;
-    case '\t':
-      result += "\\t";
-      break;
-    // case '/':
-    // Even though \/ is considered a legal escape in JSON, a bare
-    // slash is also legal, so I see no reason to escape it.
-    // (I hope I am not misunderstanding something.
-    // blep notes: actually escaping \/ may be useful in javascript to avoid </
-    // sequence.
-    // Should add a flag to allow this compatibility mode and prevent this
-    // sequence from occurring.
-    default:
-      if (isControlCharacter(*c)) {
-        std::ostringstream oss;
-        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
-            << std::setw(4) << static_cast<int>(*c);
-        result += oss.str();
-      } else {
-        result += *c;
-      }
-      break;
-    }
-  }
-  result += "\"";
-  return result;
-}
-
-// https://github.com/upcaste/upcaste/blob/master/src/upcore/src/cstring/strnpbrk.cpp
-static char const* strnpbrk(char const* s, char const* accept, size_t n) {
-  assert((s || !n) && accept);
-
-  char const* const end = s + n;
-  for (char const* cur = s; cur < end; ++cur) {
-    int const c = *cur;
-    for (char const* a = accept; *a; ++a) {
-      if (*a == c) {
-        return cur;
-      }
-    }
-  }
-  return NULL;
-}
-static std::string valueToQuotedStringN(const char* value, unsigned length) {
-  if (value == NULL)
-    return "";
-  // Not sure how to handle unicode...
-  if (strnpbrk(value, "\"\\\b\f\n\r\t", length) == NULL &&
-      !containsControlCharacter0(value, length))
-    return std::string("\"") + value + "\"";
-  // We have to walk value and escape any special characters.
-  // Appending to std::string is not efficient, but this should be rare.
-  // (Note: forward slashes are *not* rare, but I am not escaping them.)
-  std::string::size_type maxsize =
-      length * 2 + 3; // allescaped+quotes+NULL
-  std::string result;
-  result.reserve(maxsize); // to avoid lots of mallocs
-  result += "\"";
-  char const* end = value + length;
-  for (const char* c = value; c != end; ++c) {
-    switch (*c) {
-    case '\"':
-      result += "\\\"";
-      break;
-    case '\\':
-      result += "\\\\";
-      break;
-    case '\b':
-      result += "\\b";
-      break;
-    case '\f':
-      result += "\\f";
-      break;
-    case '\n':
-      result += "\\n";
-      break;
-    case '\r':
-      result += "\\r";
-      break;
-    case '\t':
-      result += "\\t";
-      break;
-    // case '/':
-    // Even though \/ is considered a legal escape in JSON, a bare
-    // slash is also legal, so I see no reason to escape it.
-    // (I hope I am not misunderstanding something.)
-    // blep notes: actually escaping \/ may be useful in javascript to avoid </
-    // sequence.
-    // Should add a flag to allow this compatibility mode and prevent this
-    // sequence from occurring.
-    default:
-      if ((isControlCharacter(*c)) || (*c == 0)) {
-        std::ostringstream oss;
-        oss << "\\u" << std::hex << std::uppercase << std::setfill('0')
-            << std::setw(4) << static_cast<int>(*c);
-        result += oss.str();
-      } else {
-        result += *c;
-      }
-      break;
-    }
-  }
-  result += "\"";
-  return result;
-}
-
-// Class Writer
-// //////////////////////////////////////////////////////////////////
-Writer::~Writer() {}
-
-// Class FastWriter
-// //////////////////////////////////////////////////////////////////
-
-FastWriter::FastWriter()
-    : yamlCompatiblityEnabled_(false), dropNullPlaceholders_(false),
-      omitEndingLineFeed_(false) {}
-
-void FastWriter::enableYAMLCompatibility() { yamlCompatiblityEnabled_ = true; }
-
-void FastWriter::dropNullPlaceholders() { dropNullPlaceholders_ = true; }
-
-void FastWriter::omitEndingLineFeed() { omitEndingLineFeed_ = true; }
-
-std::string FastWriter::write(const Value& root) {
-  document_ = "";
-  writeValue(root);
-  if (!omitEndingLineFeed_)
-    document_ += "\n";
-  return document_;
-}
-
-void FastWriter::writeValue(const Value& value) {
-  switch (value.type()) {
-  case nullValue:
-    if (!dropNullPlaceholders_)
-      document_ += "null";
-    break;
-  case intValue:
-    document_ += valueToString(value.asLargestInt());
-    break;
-  case uintValue:
-    document_ += valueToString(value.asLargestUInt());
-    break;
-  case realValue:
-    document_ += valueToString(value.asDouble());
-    break;
-  case stringValue:
-  {
-    // Is NULL possible for value.string_?
-    char const* str;
-    char const* end;
-    bool ok = value.getString(&str, &end);
-    if (ok) document_ += valueToQuotedStringN(str, static_cast<unsigned>(end-str));
-    break;
-  }
-  case booleanValue:
-    document_ += valueToString(value.asBool());
-    break;
-  case arrayValue: {
-    document_ += '[';
-    int size = value.size();
-    for (int index = 0; index < size; ++index) {
-      if (index > 0)
-        document_ += ',';
-      writeValue(value[index]);
-    }
-    document_ += ']';
-  } break;
-  case objectValue: {
-    Value::Members members(value.getMemberNames());
-    document_ += '{';
-    for (Value::Members::iterator it = members.begin(); it != members.end();
-         ++it) {
-      const std::string& name = *it;
-      if (it != members.begin())
-        document_ += ',';
-      document_ += valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length()));
-      document_ += yamlCompatiblityEnabled_ ? ": " : ":";
-      writeValue(value[name]);
-    }
-    document_ += '}';
-  } break;
-  }
-}
-
-// Class StyledWriter
-// //////////////////////////////////////////////////////////////////
-
-StyledWriter::StyledWriter()
-    : rightMargin_(74), indentSize_(3), addChildValues_() {}
-
-std::string StyledWriter::write(const Value& root) {
-  document_ = "";
-  addChildValues_ = false;
-  indentString_ = "";
-  writeCommentBeforeValue(root);
-  writeValue(root);
-  writeCommentAfterValueOnSameLine(root);
-  document_ += "\n";
-  return document_;
-}
-
-void StyledWriter::writeValue(const Value& value) {
-  switch (value.type()) {
-  case nullValue:
-    pushValue("null");
-    break;
-  case intValue:
-    pushValue(valueToString(value.asLargestInt()));
-    break;
-  case uintValue:
-    pushValue(valueToString(value.asLargestUInt()));
-    break;
-  case realValue:
-    pushValue(valueToString(value.asDouble()));
-    break;
-  case stringValue:
-  {
-    // Is NULL possible for value.string_?
-    char const* str;
-    char const* end;
-    bool ok = value.getString(&str, &end);
-    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
-    else pushValue("");
-    break;
-  }
-  case booleanValue:
-    pushValue(valueToString(value.asBool()));
-    break;
-  case arrayValue:
-    writeArrayValue(value);
-    break;
-  case objectValue: {
-    Value::Members members(value.getMemberNames());
-    if (members.empty())
-      pushValue("{}");
-    else {
-      writeWithIndent("{");
-      indent();
-      Value::Members::iterator it = members.begin();
-      for (;;) {
-        const std::string& name = *it;
-        const Value& childValue = value[name];
-        writeCommentBeforeValue(childValue);
-        writeWithIndent(valueToQuotedString(name.c_str()));
-        document_ += " : ";
-        writeValue(childValue);
-        if (++it == members.end()) {
-          writeCommentAfterValueOnSameLine(childValue);
-          break;
-        }
-        document_ += ',';
-        writeCommentAfterValueOnSameLine(childValue);
-      }
-      unindent();
-      writeWithIndent("}");
-    }
-  } break;
-  }
-}
-
-void StyledWriter::writeArrayValue(const Value& value) {
-  unsigned size = value.size();
-  if (size == 0)
-    pushValue("[]");
-  else {
-    bool isArrayMultiLine = isMultineArray(value);
-    if (isArrayMultiLine) {
-      writeWithIndent("[");
-      indent();
-      bool hasChildValue = !childValues_.empty();
-      unsigned index = 0;
-      for (;;) {
-        const Value& childValue = value[index];
-        writeCommentBeforeValue(childValue);
-        if (hasChildValue)
-          writeWithIndent(childValues_[index]);
-        else {
-          writeIndent();
-          writeValue(childValue);
-        }
-        if (++index == size) {
-          writeCommentAfterValueOnSameLine(childValue);
-          break;
-        }
-        document_ += ',';
-        writeCommentAfterValueOnSameLine(childValue);
-      }
-      unindent();
-      writeWithIndent("]");
-    } else // output on a single line
-    {
-      assert(childValues_.size() == size);
-      document_ += "[ ";
-      for (unsigned index = 0; index < size; ++index) {
-        if (index > 0)
-          document_ += ", ";
-        document_ += childValues_[index];
-      }
-      document_ += " ]";
-    }
-  }
-}
-
-bool StyledWriter::isMultineArray(const Value& value) {
-  int size = value.size();
-  bool isMultiLine = size * 3 >= rightMargin_;
-  childValues_.clear();
-  for (int index = 0; index < size && !isMultiLine; ++index) {
-    const Value& childValue = value[index];
-    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
-                        childValue.size() > 0);
-  }
-  if (!isMultiLine) // check if line length > max line length
-  {
-    childValues_.reserve(size);
-    addChildValues_ = true;
-    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
-    for (int index = 0; index < size; ++index) {
-      if (hasCommentForValue(value[index])) {
-        isMultiLine = true;
-      }
-      writeValue(value[index]);
-      lineLength += int(childValues_[index].length());
-    }
-    addChildValues_ = false;
-    isMultiLine = isMultiLine || lineLength >= rightMargin_;
-  }
-  return isMultiLine;
-}
-
-void StyledWriter::pushValue(const std::string& value) {
-  if (addChildValues_)
-    childValues_.push_back(value);
-  else
-    document_ += value;
-}
-
-void StyledWriter::writeIndent() {
-  if (!document_.empty()) {
-    char last = document_[document_.length() - 1];
-    if (last == ' ') // already indented
-      return;
-    if (last != '\n') // Comments may add new-line
-      document_ += '\n';
-  }
-  document_ += indentString_;
-}
-
-void StyledWriter::writeWithIndent(const std::string& value) {
-  writeIndent();
-  document_ += value;
-}
-
-void StyledWriter::indent() { indentString_ += std::string(indentSize_, ' '); }
-
-void StyledWriter::unindent() {
-  assert(int(indentString_.size()) >= indentSize_);
-  indentString_.resize(indentString_.size() - indentSize_);
-}
-
-void StyledWriter::writeCommentBeforeValue(const Value& root) {
-  if (!root.hasComment(commentBefore))
-    return;
-
-  document_ += "\n";
-  writeIndent();
-  const std::string& comment = root.getComment(commentBefore);
-  std::string::const_iterator iter = comment.begin();
-  while (iter != comment.end()) {
-    document_ += *iter;
-    if (*iter == '\n' &&
-       (iter != comment.end() && *(iter + 1) == '/'))
-      writeIndent();
-    ++iter;
-  }
-
-  // Comments are stripped of trailing newlines, so add one here
-  document_ += "\n";
-}
-
-void StyledWriter::writeCommentAfterValueOnSameLine(const Value& root) {
-  if (root.hasComment(commentAfterOnSameLine))
-    document_ += " " + root.getComment(commentAfterOnSameLine);
-
-  if (root.hasComment(commentAfter)) {
-    document_ += "\n";
-    document_ += root.getComment(commentAfter);
-    document_ += "\n";
-  }
-}
-
-bool StyledWriter::hasCommentForValue(const Value& value) {
-  return value.hasComment(commentBefore) ||
-         value.hasComment(commentAfterOnSameLine) ||
-         value.hasComment(commentAfter);
-}
-
-// Class StyledStreamWriter
-// //////////////////////////////////////////////////////////////////
-
-StyledStreamWriter::StyledStreamWriter(std::string indentation)
-    : document_(NULL), rightMargin_(74), indentation_(indentation),
-      addChildValues_() {}
-
-void StyledStreamWriter::write(std::ostream& out, const Value& root) {
-  document_ = &out;
-  addChildValues_ = false;
-  indentString_ = "";
-  indented_ = true;
-  writeCommentBeforeValue(root);
-  if (!indented_) writeIndent();
-  indented_ = true;
-  writeValue(root);
-  writeCommentAfterValueOnSameLine(root);
-  *document_ << "\n";
-  document_ = NULL; // Forget the stream, for safety.
-}
-
-void StyledStreamWriter::writeValue(const Value& value) {
-  switch (value.type()) {
-  case nullValue:
-    pushValue("null");
-    break;
-  case intValue:
-    pushValue(valueToString(value.asLargestInt()));
-    break;
-  case uintValue:
-    pushValue(valueToString(value.asLargestUInt()));
-    break;
-  case realValue:
-    pushValue(valueToString(value.asDouble()));
-    break;
-  case stringValue:
-  {
-    // Is NULL possible for value.string_?
-    char const* str;
-    char const* end;
-    bool ok = value.getString(&str, &end);
-    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
-    else pushValue("");
-    break;
-  }
-  case booleanValue:
-    pushValue(valueToString(value.asBool()));
-    break;
-  case arrayValue:
-    writeArrayValue(value);
-    break;
-  case objectValue: {
-    Value::Members members(value.getMemberNames());
-    if (members.empty())
-      pushValue("{}");
-    else {
-      writeWithIndent("{");
-      indent();
-      Value::Members::iterator it = members.begin();
-      for (;;) {
-        const std::string& name = *it;
-        const Value& childValue = value[name];
-        writeCommentBeforeValue(childValue);
-        writeWithIndent(valueToQuotedString(name.c_str()));
-        *document_ << " : ";
-        writeValue(childValue);
-        if (++it == members.end()) {
-          writeCommentAfterValueOnSameLine(childValue);
-          break;
-        }
-        *document_ << ",";
-        writeCommentAfterValueOnSameLine(childValue);
-      }
-      unindent();
-      writeWithIndent("}");
-    }
-  } break;
-  }
-}
-
-void StyledStreamWriter::writeArrayValue(const Value& value) {
-  unsigned size = value.size();
-  if (size == 0)
-    pushValue("[]");
-  else {
-    bool isArrayMultiLine = isMultineArray(value);
-    if (isArrayMultiLine) {
-      writeWithIndent("[");
-      indent();
-      bool hasChildValue = !childValues_.empty();
-      unsigned index = 0;
-      for (;;) {
-        const Value& childValue = value[index];
-        writeCommentBeforeValue(childValue);
-        if (hasChildValue)
-          writeWithIndent(childValues_[index]);
-        else {
-          if (!indented_) writeIndent();
-          indented_ = true;
-          writeValue(childValue);
-          indented_ = false;
-        }
-        if (++index == size) {
-          writeCommentAfterValueOnSameLine(childValue);
-          break;
-        }
-        *document_ << ",";
-        writeCommentAfterValueOnSameLine(childValue);
-      }
-      unindent();
-      writeWithIndent("]");
-    } else // output on a single line
-    {
-      assert(childValues_.size() == size);
-      *document_ << "[ ";
-      for (unsigned index = 0; index < size; ++index) {
-        if (index > 0)
-          *document_ << ", ";
-        *document_ << childValues_[index];
-      }
-      *document_ << " ]";
-    }
-  }
-}
-
-bool StyledStreamWriter::isMultineArray(const Value& value) {
-  int size = value.size();
-  bool isMultiLine = size * 3 >= rightMargin_;
-  childValues_.clear();
-  for (int index = 0; index < size && !isMultiLine; ++index) {
-    const Value& childValue = value[index];
-    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
-                        childValue.size() > 0);
-  }
-  if (!isMultiLine) // check if line length > max line length
-  {
-    childValues_.reserve(size);
-    addChildValues_ = true;
-    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
-    for (int index = 0; index < size; ++index) {
-      if (hasCommentForValue(value[index])) {
-        isMultiLine = true;
-      }
-      writeValue(value[index]);
-      lineLength += int(childValues_[index].length());
-    }
-    addChildValues_ = false;
-    isMultiLine = isMultiLine || lineLength >= rightMargin_;
-  }
-  return isMultiLine;
-}
-
-void StyledStreamWriter::pushValue(const std::string& value) {
-  if (addChildValues_)
-    childValues_.push_back(value);
-  else
-    *document_ << value;
-}
-
-void StyledStreamWriter::writeIndent() {
-  // blep intended this to look at the so-far-written string
-  // to determine whether we are already indented, but
-  // with a stream we cannot do that. So we rely on some saved state.
-  // The caller checks indented_.
-  *document_ << '\n' << indentString_;
-}
-
-void StyledStreamWriter::writeWithIndent(const std::string& value) {
-  if (!indented_) writeIndent();
-  *document_ << value;
-  indented_ = false;
-}
-
-void StyledStreamWriter::indent() { indentString_ += indentation_; }
-
-void StyledStreamWriter::unindent() {
-  assert(indentString_.size() >= indentation_.size());
-  indentString_.resize(indentString_.size() - indentation_.size());
-}
-
-void StyledStreamWriter::writeCommentBeforeValue(const Value& root) {
-  if (!root.hasComment(commentBefore))
-    return;
-
-  if (!indented_) writeIndent();
-  const std::string& comment = root.getComment(commentBefore);
-  std::string::const_iterator iter = comment.begin();
-  while (iter != comment.end()) {
-    *document_ << *iter;
-    if (*iter == '\n' &&
-       (iter != comment.end() && *(iter + 1) == '/'))
-      // writeIndent();  // would include newline
-      *document_ << indentString_;
-    ++iter;
-  }
-  indented_ = false;
-}
-
-void StyledStreamWriter::writeCommentAfterValueOnSameLine(const Value& root) {
-  if (root.hasComment(commentAfterOnSameLine))
-    *document_ << ' ' << root.getComment(commentAfterOnSameLine);
-
-  if (root.hasComment(commentAfter)) {
-    writeIndent();
-    *document_ << root.getComment(commentAfter);
-  }
-  indented_ = false;
-}
-
-bool StyledStreamWriter::hasCommentForValue(const Value& value) {
-  return value.hasComment(commentBefore) ||
-         value.hasComment(commentAfterOnSameLine) ||
-         value.hasComment(commentAfter);
-}
-
-//////////////////////////
-// BuiltStyledStreamWriter
-
-/// Scoped enums are not available until C++11.
-struct CommentStyle {
-  /// Decide whether to write comments.
-  enum Enum {
-    None,  ///< Drop all comments.
-    Most,  ///< Recover odd behavior of previous versions (not implemented yet).
-    All  ///< Keep all comments.
-  };
-};
-
-struct BuiltStyledStreamWriter : public StreamWriter
-{
-  BuiltStyledStreamWriter(
-      std::string const& indentation,
-      CommentStyle::Enum cs,
-      std::string const& colonSymbol,
-      std::string const& nullSymbol,
-      std::string const& endingLineFeedSymbol,
-      bool useSpecialFloats,
-      unsigned int precision);
-  int write(Value const& root, std::ostream* sout) override;
-private:
-  void writeValue(Value const& value);
-  void writeArrayValue(Value const& value);
-  bool isMultineArray(Value const& value);
-  void pushValue(std::string const& value);
-  void writeIndent();
-  void writeWithIndent(std::string const& value);
-  void indent();
-  void unindent();
-  void writeCommentBeforeValue(Value const& root);
-  void writeCommentAfterValueOnSameLine(Value const& root);
-  static bool hasCommentForValue(const Value& value);
-
-  typedef std::vector<std::string> ChildValues;
-
-  ChildValues childValues_;
-  std::string indentString_;
-  int rightMargin_;
-  std::string indentation_;
-  CommentStyle::Enum cs_;
-  std::string colonSymbol_;
-  std::string nullSymbol_;
-  std::string endingLineFeedSymbol_;
-  bool addChildValues_ : 1;
-  bool indented_ : 1;
-  bool useSpecialFloats_ : 1;
-  unsigned int precision_;
-};
-BuiltStyledStreamWriter::BuiltStyledStreamWriter(
-      std::string const& indentation,
-      CommentStyle::Enum cs,
-      std::string const& colonSymbol,
-      std::string const& nullSymbol,
-      std::string const& endingLineFeedSymbol,
-      bool useSpecialFloats,
-      unsigned int precision)
-  : rightMargin_(74)
-  , indentation_(indentation)
-  , cs_(cs)
-  , colonSymbol_(colonSymbol)
-  , nullSymbol_(nullSymbol)
-  , endingLineFeedSymbol_(endingLineFeedSymbol)
-  , addChildValues_(false)
-  , indented_(false)
-  , useSpecialFloats_(useSpecialFloats)
-  , precision_(precision)
-{
-}
-int BuiltStyledStreamWriter::write(Value const& root, std::ostream* sout)
-{
-  sout_ = sout;
-  addChildValues_ = false;
-  indented_ = true;
-  indentString_ = "";
-  writeCommentBeforeValue(root);
-  if (!indented_) writeIndent();
-  indented_ = true;
-  writeValue(root);
-  writeCommentAfterValueOnSameLine(root);
-  *sout_ << endingLineFeedSymbol_;
-  sout_ = NULL;
-  return 0;
-}
-void BuiltStyledStreamWriter::writeValue(Value const& value) {
-  switch (value.type()) {
-  case nullValue:
-    pushValue(nullSymbol_);
-    break;
-  case intValue:
-    pushValue(valueToString(value.asLargestInt()));
-    break;
-  case uintValue:
-    pushValue(valueToString(value.asLargestUInt()));
-    break;
-  case realValue:
-    pushValue(valueToString(value.asDouble(), useSpecialFloats_, precision_));
-    break;
-  case stringValue:
-  {
-    // Is NULL is possible for value.string_?
-    char const* str;
-    char const* end;
-    bool ok = value.getString(&str, &end);
-    if (ok) pushValue(valueToQuotedStringN(str, static_cast<unsigned>(end-str)));
-    else pushValue("");
-    break;
-  }
-  case booleanValue:
-    pushValue(valueToString(value.asBool()));
-    break;
-  case arrayValue:
-    writeArrayValue(value);
-    break;
-  case objectValue: {
-    Value::Members members(value.getMemberNames());
-    if (members.empty())
-      pushValue("{}");
-    else {
-      writeWithIndent("{");
-      indent();
-      Value::Members::iterator it = members.begin();
-      for (;;) {
-        std::string const& name = *it;
-        Value const& childValue = value[name];
-        writeCommentBeforeValue(childValue);
-        writeWithIndent(valueToQuotedStringN(name.data(), static_cast<unsigned>(name.length())));
-        *sout_ << colonSymbol_;
-        writeValue(childValue);
-        if (++it == members.end()) {
-          writeCommentAfterValueOnSameLine(childValue);
-          break;
-        }
-        *sout_ << ",";
-        writeCommentAfterValueOnSameLine(childValue);
-      }
-      unindent();
-      writeWithIndent("}");
-    }
-  } break;
-  }
-}
-
-void BuiltStyledStreamWriter::writeArrayValue(Value const& value) {
-  unsigned size = value.size();
-  if (size == 0)
-    pushValue("[]");
-  else {
-    bool isMultiLine = (cs_ == CommentStyle::All) || isMultineArray(value);
-    if (isMultiLine) {
-      writeWithIndent("[");
-      indent();
-      bool hasChildValue = !childValues_.empty();
-      unsigned index = 0;
-      for (;;) {
-        Value const& childValue = value[index];
-        writeCommentBeforeValue(childValue);
-        if (hasChildValue)
-          writeWithIndent(childValues_[index]);
-        else {
-          if (!indented_) writeIndent();
-          indented_ = true;
-          writeValue(childValue);
-          indented_ = false;
-        }
-        if (++index == size) {
-          writeCommentAfterValueOnSameLine(childValue);
-          break;
-        }
-        *sout_ << ",";
-        writeCommentAfterValueOnSameLine(childValue);
-      }
-      unindent();
-      writeWithIndent("]");
-    } else // output on a single line
-    {
-      assert(childValues_.size() == size);
-      *sout_ << "[";
-      if (!indentation_.empty()) *sout_ << " ";
-      for (unsigned index = 0; index < size; ++index) {
-        if (index > 0)
-          *sout_ << ", ";
-        *sout_ << childValues_[index];
-      }
-      if (!indentation_.empty()) *sout_ << " ";
-      *sout_ << "]";
-    }
-  }
-}
-
-bool BuiltStyledStreamWriter::isMultineArray(Value const& value) {
-  int size = value.size();
-  bool isMultiLine = size * 3 >= rightMargin_;
-  childValues_.clear();
-  for (int index = 0; index < size && !isMultiLine; ++index) {
-    Value const& childValue = value[index];
-    isMultiLine = ((childValue.isArray() || childValue.isObject()) &&
-                        childValue.size() > 0);
-  }
-  if (!isMultiLine) // check if line length > max line length
-  {
-    childValues_.reserve(size);
-    addChildValues_ = true;
-    int lineLength = 4 + (size - 1) * 2; // '[ ' + ', '*n + ' ]'
-    for (int index = 0; index < size; ++index) {
-      if (hasCommentForValue(value[index])) {
-        isMultiLine = true;
-      }
-      writeValue(value[index]);
-      lineLength += int(childValues_[index].length());
-    }
-    addChildValues_ = false;
-    isMultiLine = isMultiLine || lineLength >= rightMargin_;
-  }
-  return isMultiLine;
-}
-
-void BuiltStyledStreamWriter::pushValue(std::string const& value) {
-  if (addChildValues_)
-    childValues_.push_back(value);
-  else
-    *sout_ << value;
-}
-
-void BuiltStyledStreamWriter::writeIndent() {
-  // blep intended this to look at the so-far-written string
-  // to determine whether we are already indented, but
-  // with a stream we cannot do that. So we rely on some saved state.
-  // The caller checks indented_.
-
-  if (!indentation_.empty()) {
-    // In this case, drop newlines too.
-    *sout_ << '\n' << indentString_;
-  }
-}
-
-void BuiltStyledStreamWriter::writeWithIndent(std::string const& value) {
-  if (!indented_) writeIndent();
-  *sout_ << value;
-  indented_ = false;
-}
-
-void BuiltStyledStreamWriter::indent() { indentString_ += indentation_; }
-
-void BuiltStyledStreamWriter::unindent() {
-  assert(indentString_.size() >= indentation_.size());
-  indentString_.resize(indentString_.size() - indentation_.size());
-}
-
-void BuiltStyledStreamWriter::writeCommentBeforeValue(Value const& root) {
-  if (cs_ == CommentStyle::None) return;
-  if (!root.hasComment(commentBefore))
-    return;
-
-  if (!indented_) writeIndent();
-  const std::string& comment = root.getComment(commentBefore);
-  std::string::const_iterator iter = comment.begin();
-  while (iter != comment.end()) {
-    *sout_ << *iter;
-    if (*iter == '\n' &&
-       (iter != comment.end() && *(iter + 1) == '/'))
-      // writeIndent();  // would write extra newline
-      *sout_ << indentString_;
-    ++iter;
-  }
-  indented_ = false;
-}
-
-void BuiltStyledStreamWriter::writeCommentAfterValueOnSameLine(Value const& root) {
-  if (cs_ == CommentStyle::None) return;
-  if (root.hasComment(commentAfterOnSameLine))
-    *sout_ << " " + root.getComment(commentAfterOnSameLine);
-
-  if (root.hasComment(commentAfter)) {
-    writeIndent();
-    *sout_ << root.getComment(commentAfter);
-  }
-}
-
-// static
-bool BuiltStyledStreamWriter::hasCommentForValue(const Value& value) {
-  return value.hasComment(commentBefore) ||
-         value.hasComment(commentAfterOnSameLine) ||
-         value.hasComment(commentAfter);
-}
-
-///////////////
-// StreamWriter
-
-StreamWriter::StreamWriter()
-    : sout_(NULL)
-{
-}
-StreamWriter::~StreamWriter()
-{
-}
-StreamWriter::Factory::~Factory()
-{}
-StreamWriterBuilder::StreamWriterBuilder()
-{
-  setDefaults(&settings_);
-}
-StreamWriterBuilder::~StreamWriterBuilder()
-{}
-StreamWriter* StreamWriterBuilder::newStreamWriter() const
-{
-  std::string indentation = settings_["indentation"].asString();
-  std::string cs_str = settings_["commentStyle"].asString();
-  bool eyc = settings_["enableYAMLCompatibility"].asBool();
-  bool dnp = settings_["dropNullPlaceholders"].asBool();
-  bool usf = settings_["useSpecialFloats"].asBool();
-  unsigned int pre = settings_["precision"].asUInt();
-  CommentStyle::Enum cs = CommentStyle::All;
-  if (cs_str == "All") {
-    cs = CommentStyle::All;
-  } else if (cs_str == "None") {
-    cs = CommentStyle::None;
-  } else {
-    throwRuntimeError("commentStyle must be 'All' or 'None'");
-  }
-  std::string colonSymbol = " : ";
-  if (eyc) {
-    colonSymbol = ": ";
-  } else if (indentation.empty()) {
-    colonSymbol = ":";
-  }
-  std::string nullSymbol = "null";
-  if (dnp) {
-    nullSymbol = "";
-  }
-  if (pre > 17) pre = 17;
-  std::string endingLineFeedSymbol = "";
-  return new BuiltStyledStreamWriter(
-      indentation, cs,
-      colonSymbol, nullSymbol, endingLineFeedSymbol, usf, pre);
-}
-static void getValidWriterKeys(std::set<std::string>* valid_keys)
-{
-  valid_keys->clear();
-  valid_keys->insert("indentation");
-  valid_keys->insert("commentStyle");
-  valid_keys->insert("enableYAMLCompatibility");
-  valid_keys->insert("dropNullPlaceholders");
-  valid_keys->insert("useSpecialFloats");
-  valid_keys->insert("precision");
-}
-bool StreamWriterBuilder::validate(Json::Value* invalid) const
-{
-  Json::Value my_invalid;
-  if (!invalid) invalid = &my_invalid;  // so we do not need to test for NULL
-  Json::Value& inv = *invalid;
-  std::set<std::string> valid_keys;
-  getValidWriterKeys(&valid_keys);
-  Value::Members keys = settings_.getMemberNames();
-  size_t n = keys.size();
-  for (size_t i = 0; i < n; ++i) {
-    std::string const& key = keys[i];
-    if (valid_keys.find(key) == valid_keys.end()) {
-      inv[key] = settings_[key];
-    }
-  }
-  return 0u == inv.size();
-}
-Value& StreamWriterBuilder::operator[](std::string key)
-{
-  return settings_[key];
-}
-// static
-void StreamWriterBuilder::setDefaults(Json::Value* settings)
-{
-  //! [StreamWriterBuilderDefaults]
-  (*settings)["commentStyle"] = "All";
-  (*settings)["indentation"] = "\t";
-  (*settings)["enableYAMLCompatibility"] = false;
-  (*settings)["dropNullPlaceholders"] = false;
-  (*settings)["useSpecialFloats"] = false;
-  (*settings)["precision"] = 17;
-  //! [StreamWriterBuilderDefaults]
-}
-
-std::string writeString(StreamWriter::Factory const& builder, Value const& root) {
-  std::ostringstream sout;
-  StreamWriterPtr const writer(builder.newStreamWriter());
-  writer->write(root, &sout);
-  return sout.str();
-}
-
-std::ostream& operator<<(std::ostream& sout, Value const& root) {
-  StreamWriterBuilder builder;
-  StreamWriterPtr const writer(builder.newStreamWriter());
-  writer->write(root, &sout);
-  return sout;
-}
-
-} // namespace Json
-
-// //////////////////////////////////////////////////////////////////////
-// End of content of file: src/lib_json/json_writer.cpp
-// //////////////////////////////////////////////////////////////////////
-
-
-
-
-
diff --git a/csharp/.editorconfig b/csharp/.editorconfig
index 5e2afd0..a2bf78c 100644
--- a/csharp/.editorconfig
+++ b/csharp/.editorconfig
@@ -14,4 +14,7 @@
 # New line preferences
 end_of_line = lf
 insert_final_newline = false
-trim_trailing_whitespace = true
\ No newline at end of file
+trim_trailing_whitespace = true
+
+[*.cs]
+csharp_space_after_cast = true
diff --git a/csharp/.gitignore b/csharp/.gitignore
index d0d7ae0..56ac149 100644
--- a/csharp/.gitignore
+++ b/csharp/.gitignore
@@ -18,6 +18,7 @@
 # 	Untracked files
 #
 .vs
+.cr
 *.user
 *.suo
 *.nupkg
@@ -32,3 +33,8 @@
 
 # Benchmark output
 BenchmarkDotNet.Artifacts/
+
+# Reinstate generated code for test files
+!any_test.pb.*
+!map*unittest.pb.*
+!unittest*.pb.*
diff --git a/csharp/BUILD.bazel b/csharp/BUILD.bazel
index 2c15084..23fbe41 100644
--- a/csharp/BUILD.bazel
+++ b/csharp/BUILD.bazel
@@ -3,14 +3,87 @@
 # See also code generation logic under /src/google/protobuf/compiler/csharp.
 
 load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//:protobuf.bzl", "internal_csharp_proto_library")
+load("//build_defs:internal_shell.bzl", "inline_sh_test")
+load("//conformance:defs.bzl", "conformance_test")
 
-pkg_files(
-    name = "dist_files",
+################################################################################
+# Tests
+################################################################################
+
+conformance_test(
+    name = "conformance_test",
+    failure_list = "//conformance:failure_list_csharp.txt",
+    testee = "//conformance:conformance_csharp",
+    text_format_failure_list = "//conformance:text_format_failure_list_csharp.txt",
+)
+
+################################################################################
+# CSharp Runtime
+################################################################################
+
+filegroup(
+    name = "srcs",
     srcs = glob([
         "keys/*",
         "protos/*",
         "src/**/*.cs*",  # .cs and .csproj
+    ], exclude = [
+        # Exclude generated files.
+        "src/*/obj/**/*"
     ]) + [
+        "src/Directory.Build.props",
+        "src/Google.Protobuf.Test/testprotos.pb",
+        "src/Google.Protobuf.sln",
+    ],
+    visibility = [
+        "//csharp:__subpackages__",
+        "//conformance:__subpackages__"
+    ],
+)
+
+filegroup(
+    name = "wkt_cs_srcs",
+    srcs = [
+        "src/Google.Protobuf/Reflection/Descriptor.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Any.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Api.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Duration.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Empty.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/FieldMask.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/SourceContext.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Struct.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Timestamp.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Type.pb.cs",
+        "src/Google.Protobuf/WellKnownTypes/Wrappers.pb.cs",
+    ],
+    visibility = ["//src/google/protobuf/compiler/csharp:__pkg__"],
+)
+
+inline_sh_test(
+    name = "tests",
+    srcs = [
+        ":srcs",
+        "src/Google.Protobuf.sln",
+        "//csharp/src/Google.Protobuf.Conformance:srcs",
+    ],
+    cmd = """
+        pushd `dirname $(location src/Google.Protobuf.sln)`/..
+        dotnet restore src/Google.Protobuf.sln
+        dotnet build -c Release src/Google.Protobuf.sln
+        dotnet test -c Release -f netcoreapp3.1 src/Google.Protobuf.Test/Google.Protobuf.Test.csproj
+        popd
+    """,
+)
+
+################################################################################
+# Distribution files
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = [
+        ":srcs",
         ".editorconfig",
         ".gitignore",
         "BUILD.bazel",
@@ -20,15 +93,20 @@
         "NuGet.Config",
         "README.md",
         "build_packages.bat",
+        "build_release.sh",
         "build_tools.sh",
         "buildall.bat",
         "buildall.sh",
         "generate_protos.sh",
         "install_dotnet_sdk.ps1",
-        "src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto",
-        "src/Google.Protobuf.Test/testprotos.pb",
-        "src/Google.Protobuf.sln",
+        "//csharp/src/Google.Protobuf.Conformance:dist_files",
     ],
     strip_prefix = strip_prefix.from_root(""),
     visibility = ["//pkg:__pkg__"],
 )
+
+sh_binary(
+  name = "release",
+  srcs = ["build_release.sh"],
+  args = ["$(location build_release.sh)"],
+)
diff --git a/csharp/Google.Protobuf.Tools.targets b/csharp/Google.Protobuf.Tools.targets
index 682e11b..4dcb8f9 100644
--- a/csharp/Google.Protobuf.Tools.targets
+++ b/csharp/Google.Protobuf.Tools.targets
@@ -1,11 +1,11 @@
-<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">

-    <PropertyGroup>

-        <protoc_tools>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)/../tools/'))</protoc_tools>

-        <protoc_linux64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x64/protoc'))</protoc_linux64>

-        <protoc_linux86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x86/protoc'))</protoc_linux86>

-        <protoc_macosx64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x64/protoc'))</protoc_macosx64>

-        <protoc_macosx86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x86/protoc'))</protoc_macosx86>

-        <protoc_windows64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x64/protoc.exe'))</protoc_windows64>

-        <protoc_windows86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x86/protoc.exe'))</protoc_windows86>

-    </PropertyGroup>

-</Project>

+<Project xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
+    <PropertyGroup>
+        <protoc_tools>$([System.IO.Path]::GetFullPath('$(MSBuildThisFileDirectory)/../tools/'))</protoc_tools>
+        <protoc_linux64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x64/protoc'))</protoc_linux64>
+        <protoc_linux86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/linux_x86/protoc'))</protoc_linux86>
+        <protoc_macosx64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x64/protoc'))</protoc_macosx64>
+        <protoc_macosx86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/macosx_x86/protoc'))</protoc_macosx86>
+        <protoc_windows64>$([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x64/protoc.exe'))</protoc_windows64>
+        <protoc_windows86>$([System.IO.Path]::GetFullPath('$(protoc_tools)/windows_x86/protoc.exe'))</protoc_windows86>
+    </PropertyGroup>
+</Project>
diff --git a/csharp/README.md b/csharp/README.md
index 9aab782..02abb7c 100644
--- a/csharp/README.md
+++ b/csharp/README.md
@@ -16,36 +16,32 @@
 Supported platforms
 ===================
 
-The runtime library is built as a portable class library, supporting:
+The runtime library is built as a class library, supporting targets of:
 
-- .NET 4.5
-- Windows 8
-- Windows Phone Silverlight 8
-- Windows Phone 8.1
-- .NET Core
+- .NET 4.5+ (`net45`)
+- .NET Standard 1.1 and 2.0 (`netstandard1.1` and `netstandard2.0`)
+- .NET 5+ (`net50`)
 
 You should be able to use Protocol Buffers in Visual Studio 2012 and
 all later versions. This includes all code generated by `protoc`,
-which only uses features from C# 3 and earlier.
+which only uses features from C# 3 and earlier. When compiling generated
+code with old compilers (before C# 7.2) you need to define the
+`GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE` symbol in your project
+so that the generated classes don't implement `IBufferMessage`, which uses
+`ref struct` types.
 
 Building
 ========
 
-Open the `src/Google.Protobuf.sln` solution in Visual Studio 2017 or
+Open the `src/Google.Protobuf.sln` solution in Visual Studio 2022 or
 later.
 
 Although *users* of this project are only expected to have Visual
 Studio 2012 or later, *developers* of the library are required to
-have Visual Studio 2017 or later, as the library uses C# 6 features
-in its implementation, as well as the new Visual Studio 2017 csproj
-format. These features have no impact when using the compiled code -
-they're only relevant when building the `Google.Protobuf` assembly.
-
-In order to run and debug the AddressBook example in the IDE, you must
-install the optional component, ".Net Core 1.0 - 1.1 development tools
-for Web" (as it's labelled in current versions of the VS2017
-installer), above and beyond the main .NET Core cross-platform
-development feature.
+have Visual Studio 2022 or later, as the library uses C# 10 features
+in its implementation and runs tests under .NET 6. These features
+have no impact when using the compiled code - they're only relevant
+when building the `Google.Protobuf` assembly.
 
 Testing
 =======
@@ -56,20 +52,11 @@
 .NET 3.5
 ========
 
-We don't officially support .NET 3.5. However, there has been some effort
-to make enabling .NET 3.5 support relatively painless in case you require it.
-There's no guarantee that this will continue in the future, so rely on .NET
-3.5 support at your peril.
-
-To enable .NET 3.5 support, you must edit the `TargetFrameworks` elements of
-[src/Google.Protobuf/Google.Protobuf.csproj](src/Google.Protobuf/Google.Protobuf.csproj)
-(and [src/Google.Protobuf.Test/Google.Protobuf.Test.csproj](src/Google.Protobuf.Test/Google.Protobuf.Test.csproj)
-if you want to run the unit tests):
-
-Open the .csproj file in a text editor and simply add `net35` to the list of
-target frameworks, noting that the `TargetFrameworks` element appears twice in
-the file (once in the first `PropertyGroup` element, and again in the second
-`PropertyGroup` element, i.e., the one with the conditional).
+We don't support .NET 3.5. It *used* to be feasible to build this library
+targeting .NET 3.5, but a number of changes requiring newer runtime/framework
+features have been added over time. While it would no doubt be *possible* to
+rework the current implementation to allow most of the functionality to be built
+in .NET 3.5, this would create an undue maintenance burden.
 
 History of C# protobufs
 =======================
@@ -81,9 +68,9 @@
 
 The previous project differs from this project in a number of ways:
 
-- The old code only supported proto2; the new code only supports
+- The old code only supported proto2; the new code initially only supported
 proto3 (so no unknown fields, no required/optional distinction, no
-extensions)
+extensions); since then proto2 support has been added
 - The old code was based on immutable message types and builders for
 them
 - The old code did not support maps or `oneof`
diff --git a/csharp/build_release.sh b/csharp/build_release.sh
new file mode 100755
index 0000000..8a641b2
--- /dev/null
+++ b/csharp/build_release.sh
@@ -0,0 +1,11 @@
+#!/bin/bash
+
+cd $(dirname $(readlink $BASH_SOURCE))
+
+# Disable some unwanted dotnet options
+set DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
+set DOTNET_CLI_TELEMETRY_OPTOUT=true
+
+# Builds Google.Protobuf NuGet packages
+dotnet restore -s /lib/csharp/ src/Google.Protobuf/Google.Protobuf.csproj
+dotnet pack --no-restore -c Release src/Google.Protobuf.sln -p:ContinuousIntegrationBuild=true
diff --git a/csharp/compatibility_tests/v3.0.0/BUILD.bazel b/csharp/compatibility_tests/v3.0.0/BUILD.bazel
new file mode 100644
index 0000000..1f6c713
--- /dev/null
+++ b/csharp/compatibility_tests/v3.0.0/BUILD.bazel
@@ -0,0 +1,16 @@
+load("//build_defs:internal_shell.bzl", "inline_sh_test")
+
+# Run csharp compatibility test between 3.0.0 and the current version.
+inline_sh_test(
+    name = "tests",
+    srcs = ["test.sh"],
+    tools = ["//:protoc"],
+    deps = glob([
+      "src/**/*.cs*",  # .cs and .csproj
+      "protos/**/*.proto",
+    ]) + [
+      "//csharp:srcs",
+      "//:well_known_protos",
+    ],
+    cmd = "$(location test.sh) 3.0.0 $(rootpath //:protoc)"
+)
diff --git a/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto b/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto
index b6178bf..554a48f 100644
--- a/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto
+++ b/csharp/compatibility_tests/v3.0.0/protos/csharp/protos/unittest_issues.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 // These proto descriptors have at one time been reported as an issue or defect.
diff --git a/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_well_known_types.proto b/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_well_known_types.proto
index c907524..f030700 100644
--- a/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_well_known_types.proto
+++ b/csharp/compatibility_tests/v3.0.0/protos/src/google/protobuf/unittest_well_known_types.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 package protobuf_unittest;
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 0ecdf37..a2d501a 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
@@ -6,6 +6,7 @@
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
     <IsPackable>False</IsPackable>
+    <LangVersion>8.0</LangVersion>
   </PropertyGroup>
 
   <ItemGroup>
diff --git a/csharp/compatibility_tests/v3.0.0/test.sh b/csharp/compatibility_tests/v3.0.0/test.sh
index 459c079..6323a6d 100755
--- a/csharp/compatibility_tests/v3.0.0/test.sh
+++ b/csharp/compatibility_tests/v3.0.0/test.sh
@@ -27,6 +27,8 @@
 
 set -ex
 
+PROTOC=$(realpath ${2:-../../../bazel-bin/protoc})
+
 # Change to the script's directory.
 cd $(dirname $0)
 
@@ -45,7 +47,7 @@
 echo "Running compatibility tests with $OLD_VERSION"
 
 # Check protoc
-[ -f ../../../src/protoc ] || {
+[ -f $PROTOC ] || {
   echo "[ERROR]: Please build protoc first."
   exit 1
 }
@@ -68,12 +70,12 @@
 # Test A.2:
 #   proto set 1: use new version
 #   proto set 2 which may import protos in set 1: use old version
-run_test "../../../src/protoc" "./old_protoc"
+run_test "$PROTOC" "./old_protoc"
 
 # Test A.3:
 #   proto set 1: use old version
 #   proto set 2 which may import protos in set 1: use new version
-run_test "./old_protoc" "../../../src/protoc"
+run_test "./old_protoc" "$PROTOC"
 
 rm old_protoc
 rm keys -r
diff --git a/csharp/generate_protos.sh b/csharp/generate_protos.sh
index b021de2..8be4428 100755
--- a/csharp/generate_protos.sh
+++ b/csharp/generate_protos.sh
@@ -11,17 +11,19 @@
 # Protocol buffer compiler to use. If the PROTOC variable is set,
 # use that. Otherwise, probe for expected locations under both
 # Windows and Unix.
+PROTOC_LOCATIONS=(
+  "bazel-bin/protoc"
+  "solution/Debug/protoc.exe"
+  "cmake/build/Debug/protoc.exe"
+  "cmake/build/Release/protoc.exe"
+)
 if [ -z "$PROTOC" ]; then
-  # TODO(jonskeet): Use an array and a for loop instead?
-  if [ -x solution/Debug/protoc.exe ]; then
-    PROTOC=solution/Debug/protoc.exe
-  elif [ -x cmake/build/Debug/protoc.exe ]; then
-    PROTOC=cmake/build/Debug/protoc.exe
-  elif [ -x cmake/build/Release/protoc.exe ]; then
-    PROTOC=cmake/build/Release/protoc.exe
-  elif [ -x src/protoc ]; then
-    PROTOC=src/protoc
-  else
+  for protoc in "${PROTOC_LOCATIONS[@]}"; do
+    if [ -x "$protoc" ]; then
+      PROTOC="$protoc"
+    fi
+  done
+  if [ -z "$PROTOC" ]; then
     echo "Unable to find protocol buffer compiler."
     exit 1
   fi
@@ -30,6 +32,7 @@
 # descriptor.proto and well-known types
 $PROTOC -Isrc --csharp_out=csharp/src/Google.Protobuf \
     --csharp_opt=base_namespace=Google.Protobuf \
+    --csharp_opt=file_extension=.pb.cs \
     src/google/protobuf/descriptor.proto \
     src/google/protobuf/any.proto \
     src/google/protobuf/api.proto \
@@ -40,7 +43,8 @@
     src/google/protobuf/struct.proto \
     src/google/protobuf/timestamp.proto \
     src/google/protobuf/type.proto \
-    src/google/protobuf/wrappers.proto
+    src/google/protobuf/wrappers.proto \
+    src/google/protobuf/compiler/plugin.proto
 
 # Test protos
 # Note that this deliberately does *not* include old_extensions1.proto
@@ -49,6 +53,7 @@
 $PROTOC -Isrc -Icsharp/protos \
     --experimental_allow_proto3_optional \
     --csharp_out=csharp/src/Google.Protobuf.Test.TestProtos \
+    --csharp_opt=file_extension=.pb.cs \
     --descriptor_set_out=csharp/src/Google.Protobuf.Test/testprotos.pb \
     --include_source_info \
     --include_imports \
@@ -72,18 +77,5 @@
 
 # AddressBook sample protos
 $PROTOC -Iexamples -Isrc --csharp_out=csharp/src/AddressBook \
+    --csharp_opt=file_extension=.pb.cs \
     examples/addressbook.proto
-
-$PROTOC -Iconformance -Isrc --csharp_out=csharp/src/Google.Protobuf.Conformance \
-    conformance/conformance.proto
-
-# Benchmark protos
-$PROTOC -Ibenchmarks \
-  benchmarks/datasets/google_message1/proto3/*.proto \
-  benchmarks/benchmarks.proto \
-  --csharp_out=csharp/src/Google.Protobuf.Benchmarks
-
-# C# only benchmark protos
-$PROTOC -Isrc -Icsharp/src/Google.Protobuf.Benchmarks \
-  csharp/src/Google.Protobuf.Benchmarks/*.proto \
-  --csharp_out=csharp/src/Google.Protobuf.Benchmarks
diff --git a/csharp/protos/unittest_issue6936_a.proto b/csharp/protos/unittest_issue6936_a.proto
index 097d083..45214c7 100644
--- a/csharp/protos/unittest_issue6936_a.proto
+++ b/csharp/protos/unittest_issue6936_a.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 package unittest_issues;
@@ -12,4 +42,4 @@
 
 extend google.protobuf.MessageOptions {
     string opt = 50000;
-}
\ No newline at end of file
+}
diff --git a/csharp/protos/unittest_issue6936_b.proto b/csharp/protos/unittest_issue6936_b.proto
index 8f71683..1d6d945 100644
--- a/csharp/protos/unittest_issue6936_b.proto
+++ b/csharp/protos/unittest_issue6936_b.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 import "unittest_issue6936_a.proto";
@@ -11,4 +41,4 @@
 
 message Foo {
     option (opt) = "foo";
-}
\ No newline at end of file
+}
diff --git a/csharp/protos/unittest_issue6936_c.proto b/csharp/protos/unittest_issue6936_c.proto
index 40004ec..2bc3115 100644
--- a/csharp/protos/unittest_issue6936_c.proto
+++ b/csharp/protos/unittest_issue6936_c.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 import "unittest_issue6936_a.proto";
@@ -13,4 +43,4 @@
 message Bar {
     option (opt) = "bar";
     Foo foo = 1;
-}
\ No newline at end of file
+}
diff --git a/csharp/protos/unittest_issues.proto b/csharp/protos/unittest_issues.proto
index f46c20e..1b5562f 100644
--- a/csharp/protos/unittest_issues.proto
+++ b/csharp/protos/unittest_issues.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 // These proto descriptors have at one time been reported as an issue or defect.
@@ -59,10 +89,12 @@
 // Decorate fields with [deprecated=true] as [System.Obsolete]
 
 message DeprecatedChild {
+    option deprecated = true;
 }
 
 enum DeprecatedEnum {
-    DEPRECATED_ZERO = 0;
+    option deprecated = true;
+    DEPRECATED_ZERO = 0 [deprecated = true];
     one = 1;
 }
 
@@ -169,4 +201,20 @@
     string x = 1;
     string y = 2;
   }
-}
\ No newline at end of file
+}
+
+// Issue 8810
+message DisambiguateCommonMembers {
+  int32 disambiguate_common_members = 1;
+  int32 types = 2;
+  int32 descriptor = 3;
+  int32 equals = 4;
+  int32 to_string = 5;
+  int32 get_hash_code = 6;
+  int32 write_to = 7;
+  int32 clone = 8;
+  int32 calculate_size = 9;
+  int32 merge_from = 10;
+  int32 on_construction = 11;
+  int32 parser = 12;
+}
diff --git a/csharp/src/AddressBook/AddPerson.cs b/csharp/src/AddressBook/AddPerson.cs
index 889d1d0..eb0ecb3 100644
--- a/csharp/src/AddressBook/AddPerson.cs
+++ b/csharp/src/AddressBook/AddPerson.cs
@@ -107,10 +107,8 @@
 
             if (File.Exists(args[0]))
             {
-                using (Stream file = File.OpenRead(args[0]))
-                {
-                    addressBook = AddressBook.Parser.ParseFrom(file);
-                }
+                using Stream file = File.OpenRead(args[0]);
+                addressBook = AddressBook.Parser.ParseFrom(file);
             }
             else
             {
diff --git a/csharp/src/AddressBook/Addressbook.cs b/csharp/src/AddressBook/Addressbook.pb.cs
similarity index 100%
rename from csharp/src/AddressBook/Addressbook.cs
rename to csharp/src/AddressBook/Addressbook.pb.cs
diff --git a/csharp/src/Directory.Build.props b/csharp/src/Directory.Build.props
new file mode 100644
index 0000000..dd69462
--- /dev/null
+++ b/csharp/src/Directory.Build.props
@@ -0,0 +1,7 @@
+<Project>
+
+  <PropertyGroup>
+    <LangVersion>10.0</LangVersion>
+  </PropertyGroup>
+
+</Project>
diff --git a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs
deleted file mode 100644
index c075419..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkDatasetConfig.cs
+++ /dev/null
@@ -1,89 +0,0 @@
-#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 Benchmarks;
-using Google.Protobuf.Reflection;
-using System;
-using System.Collections.Generic;
-using System.IO;
-using System.Linq;
-using System.Reflection;
-
-namespace Google.Protobuf.Benchmarks
-{
-    /// <summary>
-    /// The configuration for a single serialization test, loaded from a dataset.
-    /// </summary>
-    public class BenchmarkDatasetConfig
-    {
-        private static readonly Dictionary<string, MessageParser> parsersByMessageName = 
-            typeof(GoogleMessageBenchmark).Assembly.GetTypes()
-                .Where(t => typeof(IMessage).IsAssignableFrom(t))
-                .ToDictionary(
-                    t => ((MessageDescriptor) t.GetProperty("Descriptor", BindingFlags.Static | BindingFlags.Public).GetValue(null)).FullName,
-                    t => ((MessageParser) t.GetProperty("Parser", BindingFlags.Static | BindingFlags.Public).GetValue(null)));
-
-        public MessageParser Parser { get; }
-        public List<byte[]> Payloads { get; }
-        public string Name { get; }
-
-        public BenchmarkDatasetConfig(string resource, string shortName = null)
-        {
-            var data = LoadData(resource);
-            var dataset = BenchmarkDataset.Parser.ParseFrom(data);
-
-            if (!parsersByMessageName.TryGetValue(dataset.MessageName, out var parser))
-            {
-                throw new ArgumentException($"No parser for message {dataset.MessageName} in this assembly");
-            }
-            Parser = parser;
-            Payloads = new List<byte[]>(dataset.Payload.Select(p => p.ToByteArray()));
-            Name = shortName ?? dataset.Name;
-        }
-
-        private static byte[] LoadData(string resource)
-        {
-            using (var stream = typeof(GoogleMessageBenchmark).Assembly.GetManifestResourceStream($"Google.Protobuf.Benchmarks.{resource}"))
-            {
-                if (stream == null)
-                {
-                    throw new ArgumentException($"Unable to load embedded resource {resource}");
-                }
-                var copy = new MemoryStream();
-                stream.CopyTo(copy);
-                return copy.ToArray();
-            }
-        }
-
-        public override string ToString() => Name;
-    }
-}
diff --git a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs b/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs
deleted file mode 100644
index fe21d0c..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/BenchmarkMessage1Proto3.cs
+++ /dev/null
@@ -1,2632 +0,0 @@
-// <auto-generated>
-//     Generated by the protocol buffer compiler.  DO NOT EDIT!
-//     source: datasets/google_message1/proto3/benchmark_message1_proto3.proto
-// </auto-generated>
-#pragma warning disable 1591, 0612, 3021, 8981
-#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 Benchmarks.Proto3 {
-
-  /// <summary>Holder for reflection information generated from datasets/google_message1/proto3/benchmark_message1_proto3.proto</summary>
-  public static partial class BenchmarkMessage1Proto3Reflection {
-
-    #region Descriptor
-    /// <summary>File descriptor for datasets/google_message1/proto3/benchmark_message1_proto3.proto</summary>
-    public static pbr::FileDescriptor Descriptor {
-      get { return descriptor; }
-    }
-    private static pbr::FileDescriptor descriptor;
-
-    static BenchmarkMessage1Proto3Reflection() {
-      byte[] descriptorData = global::System.Convert.FromBase64String(
-          string.Concat(
-            "Cj9kYXRhc2V0cy9nb29nbGVfbWVzc2FnZTEvcHJvdG8zL2JlbmNobWFya19t",
-            "ZXNzYWdlMV9wcm90bzMucHJvdG8SEWJlbmNobWFya3MucHJvdG8zIoMGCg5H",
-            "b29nbGVNZXNzYWdlMRIOCgZmaWVsZDEYASABKAkSDgoGZmllbGQ5GAkgASgJ",
-            "Eg8KB2ZpZWxkMTgYEiABKAkSDwoHZmllbGQ4MBhQIAEoCBIPCgdmaWVsZDgx",
-            "GFEgASgIEg4KBmZpZWxkMhgCIAEoBRIOCgZmaWVsZDMYAyABKAUSEQoIZmll",
-            "bGQyODAYmAIgASgFEg4KBmZpZWxkNhgGIAEoBRIPCgdmaWVsZDIyGBYgASgD",
-            "Eg4KBmZpZWxkNBgEIAEoCRIOCgZmaWVsZDUYBSADKAYSDwoHZmllbGQ1ORg7",
-            "IAEoCBIOCgZmaWVsZDcYByABKAkSDwoHZmllbGQxNhgQIAEoBRIRCghmaWVs",
-            "ZDEzMBiCASABKAUSDwoHZmllbGQxMhgMIAEoCBIPCgdmaWVsZDE3GBEgASgI",
-            "Eg8KB2ZpZWxkMTMYDSABKAgSDwoHZmllbGQxNBgOIAEoCBIQCghmaWVsZDEw",
-            "NBhoIAEoBRIQCghmaWVsZDEwMBhkIAEoBRIQCghmaWVsZDEwMRhlIAEoBRIQ",
-            "CghmaWVsZDEwMhhmIAEoCRIQCghmaWVsZDEwMxhnIAEoCRIPCgdmaWVsZDI5",
-            "GB0gASgFEg8KB2ZpZWxkMzAYHiABKAgSDwoHZmllbGQ2MBg8IAEoBRIRCghm",
-            "aWVsZDI3MRiPAiABKAUSEQoIZmllbGQyNzIYkAIgASgFEhEKCGZpZWxkMTUw",
-            "GJYBIAEoBRIPCgdmaWVsZDIzGBcgASgFEg8KB2ZpZWxkMjQYGCABKAgSDwoH",
-            "ZmllbGQyNRgZIAEoBRI8CgdmaWVsZDE1GA8gASgLMisuYmVuY2htYXJrcy5w",
-            "cm90bzMuR29vZ2xlTWVzc2FnZTFTdWJNZXNzYWdlEg8KB2ZpZWxkNzgYTiAB",
-            "KAgSDwoHZmllbGQ2NxhDIAEoBRIPCgdmaWVsZDY4GEQgASgFEhEKCGZpZWxk",
-            "MTI4GIABIAEoBRIRCghmaWVsZDEyORiBASABKAkSEQoIZmllbGQxMzEYgwEg",
-            "ASgFIvcCChhHb29nbGVNZXNzYWdlMVN1Yk1lc3NhZ2USDgoGZmllbGQxGAEg",
-            "ASgFEg4KBmZpZWxkMhgCIAEoBRIOCgZmaWVsZDMYAyABKAUSDwoHZmllbGQx",
-            "NRgPIAEoCRIPCgdmaWVsZDEyGAwgASgIEg8KB2ZpZWxkMTMYDSABKAMSDwoH",
-            "ZmllbGQxNBgOIAEoAxIPCgdmaWVsZDE2GBAgASgFEg8KB2ZpZWxkMTkYEyAB",
-            "KAUSDwoHZmllbGQyMBgUIAEoCBIPCgdmaWVsZDI4GBwgASgIEg8KB2ZpZWxk",
-            "MjEYFSABKAYSDwoHZmllbGQyMhgWIAEoBRIPCgdmaWVsZDIzGBcgASgIEhEK",
-            "CGZpZWxkMjA2GM4BIAEoCBIRCghmaWVsZDIwMxjLASABKAcSEQoIZmllbGQy",
-            "MDQYzAEgASgFEhEKCGZpZWxkMjA1GM0BIAEoCRIRCghmaWVsZDIwNxjPASAB",
-            "KAQSEQoIZmllbGQzMDAYrAIgASgEQiUKHmNvbS5nb29nbGUucHJvdG9idWYu",
-            "YmVuY2htYXJrc0gB+AEBYgZwcm90bzM="));
-      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
-          new pbr::FileDescriptor[] { },
-          new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
-            new pbr::GeneratedClrTypeInfo(typeof(global::Benchmarks.Proto3.GoogleMessage1), global::Benchmarks.Proto3.GoogleMessage1.Parser, new[]{ "Field1", "Field9", "Field18", "Field80", "Field81", "Field2", "Field3", "Field280", "Field6", "Field22", "Field4", "Field5", "Field59", "Field7", "Field16", "Field130", "Field12", "Field17", "Field13", "Field14", "Field104", "Field100", "Field101", "Field102", "Field103", "Field29", "Field30", "Field60", "Field271", "Field272", "Field150", "Field23", "Field24", "Field25", "Field15", "Field78", "Field67", "Field68", "Field128", "Field129", "Field131" }, null, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Benchmarks.Proto3.GoogleMessage1SubMessage), global::Benchmarks.Proto3.GoogleMessage1SubMessage.Parser, new[]{ "Field1", "Field2", "Field3", "Field15", "Field12", "Field13", "Field14", "Field16", "Field19", "Field20", "Field28", "Field21", "Field22", "Field23", "Field206", "Field203", "Field204", "Field205", "Field207", "Field300" }, null, null, null, null)
-          }));
-    }
-    #endregion
-
-  }
-  #region Messages
-  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();
-    }
-
-    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_;
-      field18_ = other.field18_;
-      field80_ = other.field80_;
-      field81_ = other.field81_;
-      field2_ = other.field2_;
-      field3_ = other.field3_;
-      field280_ = other.field280_;
-      field6_ = other.field6_;
-      field22_ = other.field22_;
-      field4_ = other.field4_;
-      field5_ = other.field5_.Clone();
-      field59_ = other.field59_;
-      field7_ = other.field7_;
-      field16_ = other.field16_;
-      field130_ = other.field130_;
-      field12_ = other.field12_;
-      field17_ = other.field17_;
-      field13_ = other.field13_;
-      field14_ = other.field14_;
-      field104_ = other.field104_;
-      field100_ = other.field100_;
-      field101_ = other.field101_;
-      field102_ = other.field102_;
-      field103_ = other.field103_;
-      field29_ = other.field29_;
-      field30_ = other.field30_;
-      field60_ = other.field60_;
-      field271_ = other.field271_;
-      field272_ = other.field272_;
-      field150_ = other.field150_;
-      field23_ = other.field23_;
-      field24_ = other.field24_;
-      field25_ = other.field25_;
-      field15_ = other.field15_ != null ? other.field15_.Clone() : null;
-      field78_ = other.field78_;
-      field67_ = other.field67_;
-      field68_ = other.field68_;
-      field128_ = other.field128_;
-      field129_ = other.field129_;
-      field131_ = other.field131_;
-      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public GoogleMessage1 Clone() {
-      return new GoogleMessage1(this);
-    }
-
-    /// <summary>Field number for the "field1" field.</summary>
-    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 {
-        field1_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field9" field.</summary>
-    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 {
-        field9_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field18" field.</summary>
-    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 {
-        field18_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field80" field.</summary>
-    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 {
-        field80_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field81" field.</summary>
-    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 {
-        field81_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field2" field.</summary>
-    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 {
-        field2_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field3" field.</summary>
-    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 {
-        field3_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field280" field.</summary>
-    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 {
-        field280_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field6" field.</summary>
-    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 {
-        field6_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field22" field.</summary>
-    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 {
-        field22_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field4" field.</summary>
-    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 {
-        field4_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field5" field.</summary>
-    public const int Field5FieldNumber = 5;
-    private static readonly pb::FieldCodec<ulong> _repeated_field5_codec
-        = 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_; }
-    }
-
-    /// <summary>Field number for the "field59" field.</summary>
-    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 {
-        field59_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field7" field.</summary>
-    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 {
-        field7_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field16" field.</summary>
-    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 {
-        field16_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field130" field.</summary>
-    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 {
-        field130_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field12" field.</summary>
-    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 {
-        field12_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field17" field.</summary>
-    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 {
-        field17_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field13" field.</summary>
-    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 {
-        field13_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field14" field.</summary>
-    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 {
-        field14_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field104" field.</summary>
-    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 {
-        field104_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field100" field.</summary>
-    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 {
-        field100_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field101" field.</summary>
-    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 {
-        field101_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field102" field.</summary>
-    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 {
-        field102_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field103" field.</summary>
-    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 {
-        field103_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field29" field.</summary>
-    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 {
-        field29_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field30" field.</summary>
-    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 {
-        field30_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field60" field.</summary>
-    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 {
-        field60_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field271" field.</summary>
-    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 {
-        field271_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field272" field.</summary>
-    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 {
-        field272_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field150" field.</summary>
-    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 {
-        field150_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field23" field.</summary>
-    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 {
-        field23_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field24" field.</summary>
-    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 {
-        field24_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field25" field.</summary>
-    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 {
-        field25_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field15" field.</summary>
-    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 {
-        field15_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field78" field.</summary>
-    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 {
-        field78_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field67" field.</summary>
-    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 {
-        field67_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field68" field.</summary>
-    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 {
-        field68_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field128" field.</summary>
-    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 {
-        field128_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field129" field.</summary>
-    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 {
-        field129_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field131" field.</summary>
-    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 {
-        field131_ = value;
-      }
-    }
-
-    [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;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (Field1 != other.Field1) return false;
-      if (Field9 != other.Field9) return false;
-      if (Field18 != other.Field18) return false;
-      if (Field80 != other.Field80) return false;
-      if (Field81 != other.Field81) return false;
-      if (Field2 != other.Field2) return false;
-      if (Field3 != other.Field3) return false;
-      if (Field280 != other.Field280) return false;
-      if (Field6 != other.Field6) return false;
-      if (Field22 != other.Field22) return false;
-      if (Field4 != other.Field4) return false;
-      if(!field5_.Equals(other.field5_)) return false;
-      if (Field59 != other.Field59) return false;
-      if (Field7 != other.Field7) return false;
-      if (Field16 != other.Field16) return false;
-      if (Field130 != other.Field130) return false;
-      if (Field12 != other.Field12) return false;
-      if (Field17 != other.Field17) return false;
-      if (Field13 != other.Field13) return false;
-      if (Field14 != other.Field14) return false;
-      if (Field104 != other.Field104) return false;
-      if (Field100 != other.Field100) return false;
-      if (Field101 != other.Field101) return false;
-      if (Field102 != other.Field102) return false;
-      if (Field103 != other.Field103) return false;
-      if (Field29 != other.Field29) return false;
-      if (Field30 != other.Field30) return false;
-      if (Field60 != other.Field60) return false;
-      if (Field271 != other.Field271) return false;
-      if (Field272 != other.Field272) return false;
-      if (Field150 != other.Field150) return false;
-      if (Field23 != other.Field23) return false;
-      if (Field24 != other.Field24) return false;
-      if (Field25 != other.Field25) return false;
-      if (!object.Equals(Field15, other.Field15)) return false;
-      if (Field78 != other.Field78) return false;
-      if (Field67 != other.Field67) return false;
-      if (Field68 != other.Field68) return false;
-      if (Field128 != other.Field128) return false;
-      if (Field129 != other.Field129) return false;
-      if (Field131 != other.Field131) 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 (Field1.Length != 0) hash ^= Field1.GetHashCode();
-      if (Field9.Length != 0) hash ^= Field9.GetHashCode();
-      if (Field18.Length != 0) hash ^= Field18.GetHashCode();
-      if (Field80 != false) hash ^= Field80.GetHashCode();
-      if (Field81 != false) hash ^= Field81.GetHashCode();
-      if (Field2 != 0) hash ^= Field2.GetHashCode();
-      if (Field3 != 0) hash ^= Field3.GetHashCode();
-      if (Field280 != 0) hash ^= Field280.GetHashCode();
-      if (Field6 != 0) hash ^= Field6.GetHashCode();
-      if (Field22 != 0L) hash ^= Field22.GetHashCode();
-      if (Field4.Length != 0) hash ^= Field4.GetHashCode();
-      hash ^= field5_.GetHashCode();
-      if (Field59 != false) hash ^= Field59.GetHashCode();
-      if (Field7.Length != 0) hash ^= Field7.GetHashCode();
-      if (Field16 != 0) hash ^= Field16.GetHashCode();
-      if (Field130 != 0) hash ^= Field130.GetHashCode();
-      if (Field12 != false) hash ^= Field12.GetHashCode();
-      if (Field17 != false) hash ^= Field17.GetHashCode();
-      if (Field13 != false) hash ^= Field13.GetHashCode();
-      if (Field14 != false) hash ^= Field14.GetHashCode();
-      if (Field104 != 0) hash ^= Field104.GetHashCode();
-      if (Field100 != 0) hash ^= Field100.GetHashCode();
-      if (Field101 != 0) hash ^= Field101.GetHashCode();
-      if (Field102.Length != 0) hash ^= Field102.GetHashCode();
-      if (Field103.Length != 0) hash ^= Field103.GetHashCode();
-      if (Field29 != 0) hash ^= Field29.GetHashCode();
-      if (Field30 != false) hash ^= Field30.GetHashCode();
-      if (Field60 != 0) hash ^= Field60.GetHashCode();
-      if (Field271 != 0) hash ^= Field271.GetHashCode();
-      if (Field272 != 0) hash ^= Field272.GetHashCode();
-      if (Field150 != 0) hash ^= Field150.GetHashCode();
-      if (Field23 != 0) hash ^= Field23.GetHashCode();
-      if (Field24 != false) hash ^= Field24.GetHashCode();
-      if (Field25 != 0) hash ^= Field25.GetHashCode();
-      if (field15_ != null) hash ^= Field15.GetHashCode();
-      if (Field78 != false) hash ^= Field78.GetHashCode();
-      if (Field67 != 0) hash ^= Field67.GetHashCode();
-      if (Field68 != 0) hash ^= Field68.GetHashCode();
-      if (Field128 != 0) hash ^= Field128.GetHashCode();
-      if (Field129.Length != 0) hash ^= Field129.GetHashCode();
-      if (Field131 != 0) hash ^= Field131.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 (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(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(output);
-      }
-    #endif
-    }
-
-    #if !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) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Field1);
-      }
-      if (Field9.Length != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Field9);
-      }
-      if (Field18.Length != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeStringSize(Field18);
-      }
-      if (Field80 != false) {
-        size += 2 + 1;
-      }
-      if (Field81 != false) {
-        size += 2 + 1;
-      }
-      if (Field2 != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field2);
-      }
-      if (Field3 != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field3);
-      }
-      if (Field280 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field280);
-      }
-      if (Field6 != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field6);
-      }
-      if (Field22 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Field22);
-      }
-      if (Field4.Length != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Field4);
-      }
-      size += field5_.CalculateSize(_repeated_field5_codec);
-      if (Field59 != false) {
-        size += 2 + 1;
-      }
-      if (Field7.Length != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Field7);
-      }
-      if (Field16 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field16);
-      }
-      if (Field130 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field130);
-      }
-      if (Field12 != false) {
-        size += 1 + 1;
-      }
-      if (Field17 != false) {
-        size += 2 + 1;
-      }
-      if (Field13 != false) {
-        size += 1 + 1;
-      }
-      if (Field14 != false) {
-        size += 1 + 1;
-      }
-      if (Field104 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field104);
-      }
-      if (Field100 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field100);
-      }
-      if (Field101 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field101);
-      }
-      if (Field102.Length != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeStringSize(Field102);
-      }
-      if (Field103.Length != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeStringSize(Field103);
-      }
-      if (Field29 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field29);
-      }
-      if (Field30 != false) {
-        size += 2 + 1;
-      }
-      if (Field60 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field60);
-      }
-      if (Field271 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field271);
-      }
-      if (Field272 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field272);
-      }
-      if (Field150 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field150);
-      }
-      if (Field23 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field23);
-      }
-      if (Field24 != false) {
-        size += 2 + 1;
-      }
-      if (Field25 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field25);
-      }
-      if (field15_ != null) {
-        size += 1 + pb::CodedOutputStream.ComputeMessageSize(Field15);
-      }
-      if (Field78 != false) {
-        size += 2 + 1;
-      }
-      if (Field67 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field67);
-      }
-      if (Field68 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field68);
-      }
-      if (Field128 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field128);
-      }
-      if (Field129.Length != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeStringSize(Field129);
-      }
-      if (Field131 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field131);
-      }
-      if (_unknownFields != null) {
-        size += _unknownFields.CalculateSize();
-      }
-      return size;
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public void MergeFrom(GoogleMessage1 other) {
-      if (other == null) {
-        return;
-      }
-      if (other.Field1.Length != 0) {
-        Field1 = other.Field1;
-      }
-      if (other.Field9.Length != 0) {
-        Field9 = other.Field9;
-      }
-      if (other.Field18.Length != 0) {
-        Field18 = other.Field18;
-      }
-      if (other.Field80 != false) {
-        Field80 = other.Field80;
-      }
-      if (other.Field81 != false) {
-        Field81 = other.Field81;
-      }
-      if (other.Field2 != 0) {
-        Field2 = other.Field2;
-      }
-      if (other.Field3 != 0) {
-        Field3 = other.Field3;
-      }
-      if (other.Field280 != 0) {
-        Field280 = other.Field280;
-      }
-      if (other.Field6 != 0) {
-        Field6 = other.Field6;
-      }
-      if (other.Field22 != 0L) {
-        Field22 = other.Field22;
-      }
-      if (other.Field4.Length != 0) {
-        Field4 = other.Field4;
-      }
-      field5_.Add(other.field5_);
-      if (other.Field59 != false) {
-        Field59 = other.Field59;
-      }
-      if (other.Field7.Length != 0) {
-        Field7 = other.Field7;
-      }
-      if (other.Field16 != 0) {
-        Field16 = other.Field16;
-      }
-      if (other.Field130 != 0) {
-        Field130 = other.Field130;
-      }
-      if (other.Field12 != false) {
-        Field12 = other.Field12;
-      }
-      if (other.Field17 != false) {
-        Field17 = other.Field17;
-      }
-      if (other.Field13 != false) {
-        Field13 = other.Field13;
-      }
-      if (other.Field14 != false) {
-        Field14 = other.Field14;
-      }
-      if (other.Field104 != 0) {
-        Field104 = other.Field104;
-      }
-      if (other.Field100 != 0) {
-        Field100 = other.Field100;
-      }
-      if (other.Field101 != 0) {
-        Field101 = other.Field101;
-      }
-      if (other.Field102.Length != 0) {
-        Field102 = other.Field102;
-      }
-      if (other.Field103.Length != 0) {
-        Field103 = other.Field103;
-      }
-      if (other.Field29 != 0) {
-        Field29 = other.Field29;
-      }
-      if (other.Field30 != false) {
-        Field30 = other.Field30;
-      }
-      if (other.Field60 != 0) {
-        Field60 = other.Field60;
-      }
-      if (other.Field271 != 0) {
-        Field271 = other.Field271;
-      }
-      if (other.Field272 != 0) {
-        Field272 = other.Field272;
-      }
-      if (other.Field150 != 0) {
-        Field150 = other.Field150;
-      }
-      if (other.Field23 != 0) {
-        Field23 = other.Field23;
-      }
-      if (other.Field24 != false) {
-        Field24 = other.Field24;
-      }
-      if (other.Field25 != 0) {
-        Field25 = other.Field25;
-      }
-      if (other.field15_ != null) {
-        if (field15_ == null) {
-          Field15 = new global::Benchmarks.Proto3.GoogleMessage1SubMessage();
-        }
-        Field15.MergeFrom(other.Field15);
-      }
-      if (other.Field78 != false) {
-        Field78 = other.Field78;
-      }
-      if (other.Field67 != 0) {
-        Field67 = other.Field67;
-      }
-      if (other.Field68 != 0) {
-        Field68 = other.Field68;
-      }
-      if (other.Field128 != 0) {
-        Field128 = other.Field128;
-      }
-      if (other.Field129.Length != 0) {
-        Field129 = other.Field129;
-      }
-      if (other.Field131 != 0) {
-        Field131 = other.Field131;
-      }
-      _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: {
-            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(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
-    }
-
-    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [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>
-  #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();
-    }
-
-    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_;
-      field3_ = other.field3_;
-      field15_ = other.field15_;
-      field12_ = other.field12_;
-      field13_ = other.field13_;
-      field14_ = other.field14_;
-      field16_ = other.field16_;
-      field19_ = other.field19_;
-      field20_ = other.field20_;
-      field28_ = other.field28_;
-      field21_ = other.field21_;
-      field22_ = other.field22_;
-      field23_ = other.field23_;
-      field206_ = other.field206_;
-      field203_ = other.field203_;
-      field204_ = other.field204_;
-      field205_ = other.field205_;
-      field207_ = other.field207_;
-      field300_ = other.field300_;
-      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public GoogleMessage1SubMessage Clone() {
-      return new GoogleMessage1SubMessage(this);
-    }
-
-    /// <summary>Field number for the "field1" field.</summary>
-    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 {
-        field1_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field2" field.</summary>
-    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 {
-        field2_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field3" field.</summary>
-    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 {
-        field3_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field15" field.</summary>
-    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 {
-        field15_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field12" field.</summary>
-    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 {
-        field12_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field13" field.</summary>
-    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 {
-        field13_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field14" field.</summary>
-    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 {
-        field14_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field16" field.</summary>
-    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 {
-        field16_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field19" field.</summary>
-    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 {
-        field19_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field20" field.</summary>
-    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 {
-        field20_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field28" field.</summary>
-    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 {
-        field28_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field21" field.</summary>
-    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 {
-        field21_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field22" field.</summary>
-    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 {
-        field22_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field23" field.</summary>
-    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 {
-        field23_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field206" field.</summary>
-    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 {
-        field206_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field203" field.</summary>
-    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 {
-        field203_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field204" field.</summary>
-    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 {
-        field204_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field205" field.</summary>
-    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 {
-        field205_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "field207" field.</summary>
-    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 {
-        field207_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "field300" field.</summary>
-    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 {
-        field300_ = value;
-      }
-    }
-
-    [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;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (Field1 != other.Field1) return false;
-      if (Field2 != other.Field2) return false;
-      if (Field3 != other.Field3) return false;
-      if (Field15 != other.Field15) return false;
-      if (Field12 != other.Field12) return false;
-      if (Field13 != other.Field13) return false;
-      if (Field14 != other.Field14) return false;
-      if (Field16 != other.Field16) return false;
-      if (Field19 != other.Field19) return false;
-      if (Field20 != other.Field20) return false;
-      if (Field28 != other.Field28) return false;
-      if (Field21 != other.Field21) return false;
-      if (Field22 != other.Field22) return false;
-      if (Field23 != other.Field23) return false;
-      if (Field206 != other.Field206) return false;
-      if (Field203 != other.Field203) return false;
-      if (Field204 != other.Field204) return false;
-      if (Field205 != other.Field205) return false;
-      if (Field207 != other.Field207) return false;
-      if (Field300 != other.Field300) 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 (Field1 != 0) hash ^= Field1.GetHashCode();
-      if (Field2 != 0) hash ^= Field2.GetHashCode();
-      if (Field3 != 0) hash ^= Field3.GetHashCode();
-      if (Field15.Length != 0) hash ^= Field15.GetHashCode();
-      if (Field12 != false) hash ^= Field12.GetHashCode();
-      if (Field13 != 0L) hash ^= Field13.GetHashCode();
-      if (Field14 != 0L) hash ^= Field14.GetHashCode();
-      if (Field16 != 0) hash ^= Field16.GetHashCode();
-      if (Field19 != 0) hash ^= Field19.GetHashCode();
-      if (Field20 != false) hash ^= Field20.GetHashCode();
-      if (Field28 != false) hash ^= Field28.GetHashCode();
-      if (Field21 != 0UL) hash ^= Field21.GetHashCode();
-      if (Field22 != 0) hash ^= Field22.GetHashCode();
-      if (Field23 != false) hash ^= Field23.GetHashCode();
-      if (Field206 != false) hash ^= Field206.GetHashCode();
-      if (Field203 != 0) hash ^= Field203.GetHashCode();
-      if (Field204 != 0) hash ^= Field204.GetHashCode();
-      if (Field205.Length != 0) hash ^= Field205.GetHashCode();
-      if (Field207 != 0UL) hash ^= Field207.GetHashCode();
-      if (Field300 != 0UL) hash ^= Field300.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 (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(output);
-      }
-    #endif
-    }
-
-    #if !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) {
-        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field1);
-      }
-      if (Field2 != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field2);
-      }
-      if (Field3 != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Field3);
-      }
-      if (Field15.Length != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Field15);
-      }
-      if (Field12 != false) {
-        size += 1 + 1;
-      }
-      if (Field13 != 0L) {
-        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Field13);
-      }
-      if (Field14 != 0L) {
-        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Field14);
-      }
-      if (Field16 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field16);
-      }
-      if (Field19 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field19);
-      }
-      if (Field20 != false) {
-        size += 2 + 1;
-      }
-      if (Field28 != false) {
-        size += 2 + 1;
-      }
-      if (Field21 != 0UL) {
-        size += 2 + 8;
-      }
-      if (Field22 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field22);
-      }
-      if (Field23 != false) {
-        size += 2 + 1;
-      }
-      if (Field206 != false) {
-        size += 2 + 1;
-      }
-      if (Field203 != 0) {
-        size += 2 + 4;
-      }
-      if (Field204 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(Field204);
-      }
-      if (Field205.Length != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeStringSize(Field205);
-      }
-      if (Field207 != 0UL) {
-        size += 2 + pb::CodedOutputStream.ComputeUInt64Size(Field207);
-      }
-      if (Field300 != 0UL) {
-        size += 2 + pb::CodedOutputStream.ComputeUInt64Size(Field300);
-      }
-      if (_unknownFields != null) {
-        size += _unknownFields.CalculateSize();
-      }
-      return size;
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public void MergeFrom(GoogleMessage1SubMessage other) {
-      if (other == null) {
-        return;
-      }
-      if (other.Field1 != 0) {
-        Field1 = other.Field1;
-      }
-      if (other.Field2 != 0) {
-        Field2 = other.Field2;
-      }
-      if (other.Field3 != 0) {
-        Field3 = other.Field3;
-      }
-      if (other.Field15.Length != 0) {
-        Field15 = other.Field15;
-      }
-      if (other.Field12 != false) {
-        Field12 = other.Field12;
-      }
-      if (other.Field13 != 0L) {
-        Field13 = other.Field13;
-      }
-      if (other.Field14 != 0L) {
-        Field14 = other.Field14;
-      }
-      if (other.Field16 != 0) {
-        Field16 = other.Field16;
-      }
-      if (other.Field19 != 0) {
-        Field19 = other.Field19;
-      }
-      if (other.Field20 != false) {
-        Field20 = other.Field20;
-      }
-      if (other.Field28 != false) {
-        Field28 = other.Field28;
-      }
-      if (other.Field21 != 0UL) {
-        Field21 = other.Field21;
-      }
-      if (other.Field22 != 0) {
-        Field22 = other.Field22;
-      }
-      if (other.Field23 != false) {
-        Field23 = other.Field23;
-      }
-      if (other.Field206 != false) {
-        Field206 = other.Field206;
-      }
-      if (other.Field203 != 0) {
-        Field203 = other.Field203;
-      }
-      if (other.Field204 != 0) {
-        Field204 = other.Field204;
-      }
-      if (other.Field205.Length != 0) {
-        Field205 = other.Field205;
-      }
-      if (other.Field207 != 0UL) {
-        Field207 = other.Field207;
-      }
-      if (other.Field300 != 0UL) {
-        Field300 = other.Field300;
-      }
-      _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: {
-            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
-    }
-
-    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [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
-
-}
-
-#endregion Designer generated code
diff --git a/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs b/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs
deleted file mode 100644
index a05802d..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/Benchmarks.cs
+++ /dev/null
@@ -1,325 +0,0 @@
-// <auto-generated>
-//     Generated by the protocol buffer compiler.  DO NOT EDIT!
-//     source: benchmarks.proto
-// </auto-generated>
-#pragma warning disable 1591, 0612, 3021, 8981
-#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 Benchmarks {
-
-  /// <summary>Holder for reflection information generated from benchmarks.proto</summary>
-  public static partial class BenchmarksReflection {
-
-    #region Descriptor
-    /// <summary>File descriptor for benchmarks.proto</summary>
-    public static pbr::FileDescriptor Descriptor {
-      get { return descriptor; }
-    }
-    private static pbr::FileDescriptor descriptor;
-
-    static BenchmarksReflection() {
-      byte[] descriptorData = global::System.Convert.FromBase64String(
-          string.Concat(
-            "ChBiZW5jaG1hcmtzLnByb3RvEgpiZW5jaG1hcmtzIkcKEEJlbmNobWFya0Rh",
-            "dGFzZXQSDAoEbmFtZRgBIAEoCRIUCgxtZXNzYWdlX25hbWUYAiABKAkSDwoH",
-            "cGF5bG9hZBgDIAMoDEIgCh5jb20uZ29vZ2xlLnByb3RvYnVmLmJlbmNobWFy",
-            "a3NiBnByb3RvMw=="));
-      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
-          new pbr::FileDescriptor[] { },
-          new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
-            new pbr::GeneratedClrTypeInfo(typeof(global::Benchmarks.BenchmarkDataset), global::Benchmarks.BenchmarkDataset.Parser, new[]{ "Name", "MessageName", "Payload" }, null, null, null, null)
-          }));
-    }
-    #endregion
-
-  }
-  #region Messages
-  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();
-    }
-
-    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_;
-      payload_ = other.payload_.Clone();
-      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public BenchmarkDataset Clone() {
-      return new BenchmarkDataset(this);
-    }
-
-    /// <summary>Field number for the "name" field.</summary>
-    public const int NameFieldNumber = 1;
-    private string name_ = "";
-    /// <summary>
-    /// Name of the benchmark dataset.  This should be unique across all datasets.
-    /// 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 {
-        name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "message_name" field.</summary>
-    public const int MessageNameFieldNumber = 2;
-    private string messageName_ = "";
-    /// <summary>
-    /// Fully-qualified name of the protobuf message for this dataset.
-    /// It will be one of the messages defined benchmark_messages_proto2.proto
-    /// or benchmark_messages_proto3.proto.
-    ///
-    /// Implementations that do not support reflection can implement this with
-    /// an explicit "if/else" chain that lists every known message defined
-    /// in those files.
-    /// </summary>
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public string MessageName {
-      get { return messageName_; }
-      set {
-        messageName_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "payload" field.</summary>
-    public const int PayloadFieldNumber = 3;
-    private static readonly pb::FieldCodec<pb::ByteString> _repeated_payload_codec
-        = pb::FieldCodec.ForBytes(26);
-    private readonly pbc::RepeatedField<pb::ByteString> payload_ = new pbc::RepeatedField<pb::ByteString>();
-    /// <summary>
-    /// The payload(s) for this dataset.  They should be parsed or serialized
-    /// in sequence, in a loop, ie.
-    ///
-    ///  while (!benchmarkDone) {  // Benchmark runner decides when to exit.
-    ///    for (i = 0; i &lt; benchmark.payload.length; i++) {
-    ///      parse(benchmark.payload[i])
-    ///    }
-    ///  }
-    ///
-    /// This is intended to let datasets include a variety of data to provide
-    /// potentially more realistic results than just parsing the same message
-    /// over and over.  A single message parsed repeatedly could yield unusually
-    /// 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;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (Name != other.Name) return false;
-      if (MessageName != other.MessageName) return false;
-      if(!payload_.Equals(other.payload_)) 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 (Name.Length != 0) hash ^= Name.GetHashCode();
-      if (MessageName.Length != 0) hash ^= MessageName.GetHashCode();
-      hash ^= payload_.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 (Name.Length != 0) {
-        output.WriteRawTag(10);
-        output.WriteString(Name);
-      }
-      if (MessageName.Length != 0) {
-        output.WriteRawTag(18);
-        output.WriteString(MessageName);
-      }
-      payload_.WriteTo(output, _repeated_payload_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) {
-      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) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(Name);
-      }
-      if (MessageName.Length != 0) {
-        size += 1 + pb::CodedOutputStream.ComputeStringSize(MessageName);
-      }
-      size += payload_.CalculateSize(_repeated_payload_codec);
-      if (_unknownFields != null) {
-        size += _unknownFields.CalculateSize();
-      }
-      return size;
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public void MergeFrom(BenchmarkDataset other) {
-      if (other == null) {
-        return;
-      }
-      if (other.Name.Length != 0) {
-        Name = other.Name;
-      }
-      if (other.MessageName.Length != 0) {
-        MessageName = other.MessageName;
-      }
-      payload_.Add(other.payload_);
-      _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: {
-            Name = input.ReadString();
-            break;
-          }
-          case 18: {
-            MessageName = input.ReadString();
-            break;
-          }
-          case 26: {
-            payload_.AddEntriesFrom(input, _repeated_payload_codec);
-            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: {
-            MessageName = input.ReadString();
-            break;
-          }
-          case 26: {
-            payload_.AddEntriesFrom(ref input, _repeated_payload_codec);
-            break;
-          }
-        }
-      }
-    }
-    #endif
-
-  }
-
-  #endregion
-
-}
-
-#endregion Designer generated code
diff --git a/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs
deleted file mode 100644
index a755850..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/ByteStringBenchmark.cs
+++ /dev/null
@@ -1,72 +0,0 @@
-#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
deleted file mode 100644
index fee5f65..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/Google.Protobuf.Benchmarks.csproj
+++ /dev/null
@@ -1,26 +0,0 @@
-<Project Sdk="Microsoft.NET.Sdk">
-
-  <PropertyGroup>
-    <OutputType>Exe</OutputType>
-    <TargetFramework>net6.0</TargetFramework>
-    <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
-    <SignAssembly>true</SignAssembly>
-    <IsPackable>False</IsPackable>
-    <DebugType>pdbonly</DebugType>
-    <DebugSymbols>true</DebugSymbols>
-  </PropertyGroup>
-
-  <ItemGroup>
-    <Compile Include="..\Google.Protobuf.Test\ReadOnlySequenceFactory.cs" Link="ReadOnlySequenceFactory.cs" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <PackageReference Include="BenchmarkDotNet" Version="0.13.1" />
-    <ProjectReference Include="..\Google.Protobuf\Google.Protobuf.csproj" />
-  </ItemGroup>
-
-  <ItemGroup>
-    <EmbeddedResource Include="..\..\..\benchmarks\datasets\google_message1\proto3\dataset.google_message1_proto3.pb" />
-  </ItemGroup>
-
-</Project>
diff --git a/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs
deleted file mode 100644
index 40fb3ba..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/GoogleMessageBenchmark.cs
+++ /dev/null
@@ -1,124 +0,0 @@
-#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.Collections.Generic;
-using System.IO;
-using System.Linq;
-
-namespace Google.Protobuf.Benchmarks
-{
-    /// <summary>
-    /// Benchmark for serializing and deserializing of standard datasets that are also
-    /// measured by benchmarks in other languages.
-    /// Over time we may wish to test the various different approaches to serialization and deserialization separately.
-    /// See https://github.com/protocolbuffers/protobuf/blob/main/benchmarks/README.md
-    /// See https://github.com/protocolbuffers/protobuf/blob/main/docs/performance.md
-    /// </summary>
-    [MemoryDiagnoser]
-    public class GoogleMessageBenchmark
-    {
-        /// <summary>
-        /// All the datasets to be tested. Add more datasets to the array as they're available.
-        /// (When C# supports proto2, this will increase significantly.)
-        /// </summary>
-        public static BenchmarkDatasetConfig[] DatasetConfigurations => new[]
-        {
-            // short name is specified to make results table more readable
-            new BenchmarkDatasetConfig("dataset.google_message1_proto3.pb", "goog_msg1_proto3")
-        };
-
-        [ParamsSource(nameof(DatasetConfigurations))]
-        public BenchmarkDatasetConfig Dataset { get; set; }
-
-        private MessageParser parser;
-        /// <summary>
-        /// Each data set can contain multiple messages in a single file.
-        /// Each "write" operation should write each message in turn, and each "parse"
-        /// operation should parse each message in turn.
-        /// </summary>
-        private List<SubTest> subTests;
-
-        [GlobalSetup]
-        public void GlobalSetup()
-        {
-            parser = Dataset.Parser;
-            subTests = Dataset.Payloads.Select(p => new SubTest(p, parser.ParseFrom(p))).ToList();
-        }
-
-        [Benchmark]
-        public void WriteToStream() => subTests.ForEach(item => item.WriteToStream());
-
-        [Benchmark]
-        public void ToByteArray() => subTests.ForEach(item => item.ToByteArray());
-
-        [Benchmark]
-        public void ParseFromByteArray() => subTests.ForEach(item => item.ParseFromByteArray(parser));
-
-        [Benchmark]
-        public void ParseFromStream() => subTests.ForEach(item => item.ParseFromStream(parser));
-
-        private class SubTest
-        {
-            private readonly Stream destinationStream;
-            private readonly Stream sourceStream;
-            private readonly byte[] data;
-            private readonly IMessage message;
-
-            public SubTest(byte[] data, IMessage message)
-            {
-                destinationStream = new MemoryStream(data.Length);
-                sourceStream = new MemoryStream(data);
-                this.data = data;
-                this.message = message;
-            }
-
-            public void Reset() => destinationStream.Position = 0;
-
-            public void WriteToStream()
-            {
-                destinationStream.Position = 0;
-                message.WriteTo(destinationStream);
-            }
-
-            public void ToByteArray() => message.ToByteArray();
-
-            public void ParseFromByteArray(MessageParser parser) => parser.ParseFrom(data);
-
-            public void ParseFromStream(MessageParser parser)
-            {
-                sourceStream.Position = 0;
-                parser.ParseFrom(sourceStream);
-            }
-        }
-    }
-}
diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs
deleted file mode 100644
index 8e6710b..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/ParseMessagesBenchmark.cs
+++ /dev/null
@@ -1,258 +0,0 @@
-#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;
-using Benchmarks.Proto3;
-
-namespace Google.Protobuf.Benchmarks
-{
-    /// <summary>
-    /// Benchmark that tests parsing performance for various messages.
-    /// </summary>
-    [MemoryDiagnoser]
-    public class ParseMessagesBenchmark
-    {
-        const int MaxMessages = 100;
-
-        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 };
-
-        [GlobalSetup]
-        public void GlobalSetup()
-        {
-        }
-
-        [Benchmark]
-        public IMessage ManyWrapperFieldsMessage_ParseFromByteArray()
-        {
-            return manyWrapperFieldsTest.ParseFromByteArray();
-        }
-
-        [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)
-        {
-            manyWrapperFieldsTest.ParseDelimitedMessagesFromByteArray(messageCount);
-        }
-
-        [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);
-        }
-
-        [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()
-            {
-                Int64Field19 = 123,
-                Int64Field37 = 1000032,
-                Int64Field26 = 3453524500,
-                DoubleField79 = 1.2,
-                DoubleField25 = 234,
-                DoubleField9 = 123.3,
-                DoubleField28 = 23,
-                DoubleField7 = 234,
-                DoubleField50 = 2.45
-            };
-        }
-
-        public static ManyPrimitiveFieldsMessage CreateManyPrimitiveFieldsMessage()
-        {
-            // Example data match data of an internal benchmarks
-            return new ManyPrimitiveFieldsMessage()
-            {
-                Int64Field19 = 123,
-                Int64Field37 = 1000032,
-                Int64Field26 = 3453524500,
-                DoubleField79 = 1.2,
-                DoubleField25 = 234,
-                DoubleField9 = 123.3,
-                DoubleField28 = 23,
-                DoubleField7 = 234,
-                DoubleField50 = 2.45
-            };
-        }
-
-        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;
-            private readonly MessageParser parser;
-            private readonly Func<IMessage> factory;
-            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;
-                this.parser = parser;
-                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);
-                for (int i = 0; i < messageCount; i++)
-                {
-                    var msg = factory();
-                    input.ReadMessage(msg);
-                }
-            }
-
-            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();
-                var cos = new CodedOutputStream(ms);
-                for (int i = 0; i < msgCount; i++)
-                {
-                    cos.WriteMessage(msg);
-                }
-                cos.Flush();
-                return ms.ToArray();
-            }
-        }
-    }
-}
diff --git a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
deleted file mode 100644
index 6df1c87..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/ParseRawPrimitivesBenchmark.cs
+++ /dev/null
@@ -1,536 +0,0 @@
-#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;
-
-namespace Google.Protobuf.Benchmarks
-{
-    /// <summary>
-    /// Benchmarks throughput when parsing raw primitives.
-    /// </summary>
-    [MemoryDiagnoser]
-    public class ParseRawPrimitivesBenchmark
-    {
-        // key is the encodedSize of varint values
-        Dictionary<int, byte[]> varintInputBuffers;
-
-        byte[] doubleInputBuffer;
-        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()
-        {
-            // add some extra values that we won't read just to make sure we are far enough from the end of the buffer
-            // which allows the parser fastpath to always kick in.
-            const int paddingValueCount = 100;
-
-            varintInputBuffers = new Dictionary<int, byte[]>();
-            for (int encodedSize = 1; encodedSize <= 10; encodedSize++)
-            {
-                byte[] buffer = CreateBufferWithRandomVarints(random, BytesToParse / encodedSize, encodedSize, paddingValueCount);
-                varintInputBuffers.Add(encodedSize, buffer);
-            }
-
-            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.
-        // Measuring the time taken to parse 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 BytesToParse { get; set; }
-
-        [Benchmark]
-        [Arguments(1)]
-        [Arguments(2)]
-        [Arguments(3)]
-        [Arguments(4)]
-        [Arguments(5)]
-        public int ParseRawVarint32_CodedInputStream(int encodedSize)
-        {
-            CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]);
-            int sum = 0;
-            for (int i = 0; i < BytesToParse / encodedSize; i++)
-            {
-                sum += cis.ReadInt32();
-            }
-            return sum;
-        }
-
-        [Benchmark]
-        [Arguments(1)]
-        [Arguments(2)]
-        [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_CodedInputStream(int encodedSize)
-        {
-            CodedInputStream cis = new CodedInputStream(varintInputBuffers[encodedSize]);
-            long sum = 0;
-            for (int i = 0; i < BytesToParse / encodedSize; i++)
-            {
-                sum += cis.ReadInt64();
-            }
-            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_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);
-            uint sum = 0;
-            for (uint i = 0; i < BytesToParse / encodedSize; i++)
-            {
-                sum += cis.ReadFixed32();
-            }
-            return sum;
-        }
-
-        [Benchmark]
-        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);
-            ulong sum = 0;
-            for (int i = 0; i < BytesToParse / encodedSize; i++)
-            {
-                sum += cis.ReadFixed64();
-            }
-            return sum;
-        }
-
-        [Benchmark]
-        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);
-            float sum = 0;
-            for (int i = 0; i < BytesToParse / encodedSize; i++)
-            {
-               sum += cis.ReadFloat();
-            }
-            return sum;
-        }
-
-        [Benchmark]
-        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);
-            double sum = 0;
-            for (int i = 0; i < BytesToParse / encodedSize; i++)
-            {
-                sum += cis.ReadDouble();
-            }
-            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, false));
-            }
-            cos.Flush();
-            var buffer = ms.ToArray();
-            
-            if (buffer.Length != encodedSize * (valueCount + paddingValueCount))
-            {
-                throw new InvalidOperationException($"Unexpected output buffer length {buffer.Length}"); 
-            }
-            return buffer;
-        }
-
-        private static byte[] CreateBufferWithRandomFloats(Random random, int valueCount, int paddingValueCount)
-        {
-            MemoryStream ms = new MemoryStream();
-            CodedOutputStream cos = new CodedOutputStream(ms);
-            for (int i = 0; i < valueCount + paddingValueCount; i++)
-            {
-                cos.WriteFloat((float)random.NextDouble());
-            }
-            cos.Flush();
-            var buffer = ms.ToArray();
-            return buffer;
-        }
-
-        private static byte[] CreateBufferWithRandomDoubles(Random random, int valueCount, int paddingValueCount)
-        {
-            MemoryStream ms = new MemoryStream();
-            CodedOutputStream cos = new CodedOutputStream(ms);
-            for (int i = 0; i < valueCount + paddingValueCount; i++)
-            {
-                cos.WriteDouble(random.NextDouble());
-            }
-            cos.Flush();
-            var buffer = ms.ToArray();
-            return buffer;
-        }
-
-        private static byte[] CreateBufferWithRandomData(Random random, int valueCount, int encodedSize, int paddingValueCount)
-        {
-            int bufferSize = (valueCount + paddingValueCount) * encodedSize;
-            byte[] buffer = new byte[bufferSize];
-            random.NextBytes(buffer);
-            return buffer;
-        }
-
-        /// <summary>
-        /// Generate a random value that will take exactly "encodedSize" bytes when varint-encoded.
-        /// </summary>
-        public static ulong RandomUnsignedVarint(Random random, int encodedSize, bool fitsIn32Bits)
-        {
-            Span<byte> randomBytesBuffer = stackalloc byte[8];
-
-            if (encodedSize < 1 || encodedSize > 10 || (fitsIn32Bits && encodedSize > 5))
-            {
-                throw new ArgumentException("Illegal encodedSize value requested", nameof(encodedSize));
-            }
-            const int bitsPerByte = 7;
-            
-            ulong result = 0;
-            while (true)
-            {
-                random.NextBytes(randomBytesBuffer);
-                ulong randomValue = BinaryPrimitives.ReadUInt64LittleEndian(randomBytesBuffer);
-
-                // only use the number of random bits we need
-                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)
-                    result |= ulong.MaxValue;
-                    break;
-                }
-
-                // some random values won't require the full "encodedSize" bytes, check that at least
-                // one of the top 7 bits is set. Retrying is fine since it only happens rarely
-                if (encodedSize == 1 || (result & (0x7FUL << ((encodedSize - 1) * bitsPerByte))) != 0)
-                {
-                    break;
-                }
-            }
-            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/Program.cs b/csharp/src/Google.Protobuf.Benchmarks/Program.cs
deleted file mode 100644
index 037752f..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/Program.cs
+++ /dev/null
@@ -1,49 +0,0 @@
-#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.Running;
-
-namespace Google.Protobuf.Benchmarks
-{
-    class Program
-    {
-        // typical usage: dotnet run -c Release -f netcoreapp3.1
-        // (this can profile both .net core and .net framework; for some reason
-        // if you start from "-f net461", it goes horribly wrong)
-        public static void Main(string[] args)
-        {
-            BenchmarkSwitcher.FromAssembly(typeof(Program).Assembly).Run(args);
-        }
-    }
-
-    
-}
diff --git a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs b/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs
deleted file mode 100644
index e2eb2e8..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/WrapperBenchmarkMessages.cs
+++ /dev/null
@@ -1,9604 +0,0 @@
-// <auto-generated>
-//     Generated by the protocol buffer compiler.  DO NOT EDIT!
-//     source: wrapper_benchmark_messages.proto
-// </auto-generated>
-#pragma warning disable 1591, 0612, 3021, 8981
-#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 Google.Protobuf.Benchmarks {
-
-  /// <summary>Holder for reflection information generated from wrapper_benchmark_messages.proto</summary>
-  public static partial class WrapperBenchmarkMessagesReflection {
-
-    #region Descriptor
-    /// <summary>File descriptor for wrapper_benchmark_messages.proto</summary>
-    public static pbr::FileDescriptor Descriptor {
-      get { return descriptor; }
-    }
-    private static pbr::FileDescriptor descriptor;
-
-    static WrapperBenchmarkMessagesReflection() {
-      byte[] descriptorData = global::System.Convert.FromBase64String(
-          string.Concat(
-            "CiB3cmFwcGVyX2JlbmNobWFya19tZXNzYWdlcy5wcm90bxIaZ29vZ2xlLnBy",
-            "b3RvYnVmLmJlbmNobWFya3MaHmdvb2dsZS9wcm90b2J1Zi93cmFwcGVycy5w",
-            "cm90byLeLgoYTWFueVdyYXBwZXJGaWVsZHNNZXNzYWdlEjUKD2RvdWJsZV9m",
-            "aWVsZF85NRhfIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI0",
-            "Cg5kb3VibGVfZmllbGRfMRgBIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3Vi",
-            "bGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNzkYTyABKAsyHC5nb29nbGUucHJv",
-            "dG9idWYuRG91YmxlVmFsdWUSMgoNaW50NjRfZmllbGRfMhgCIAEoCzIbLmdv",
-            "b2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEjUKD2RvdWJsZV9maWVsZF85Nhhg",
-            "IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRIyCg1pbnQ2NF9m",
-            "aWVsZF8zGAMgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSMgoN",
-            "aW50NjRfZmllbGRfNBgEIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZh",
-            "bHVlEjUKD2RvdWJsZV9maWVsZF85NxhhIAEoCzIcLmdvb2dsZS5wcm90b2J1",
-            "Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNjUYQSABKAsyHC5nb29n",
-            "bGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzY2GEIg",
-            "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjQKDmRvdWJsZV9m",
-            "aWVsZF83GAcgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUK",
-            "D2RvdWJsZV9maWVsZF82Mhg+IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3Vi",
-            "bGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTE4GHYgASgLMhwuZ29vZ2xlLnBy",
-            "b3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRvdWJsZV9maWVsZF8xMTkYdyABKAsy",
-            "HC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxk",
-            "XzY3GEMgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRv",
-            "dWJsZV9maWVsZF8xMjAYeCABKAsyHC5nb29nbGUucHJvdG9idWYuRG91Ymxl",
-            "VmFsdWUSNgoQZG91YmxlX2ZpZWxkXzEyMRh5IAEoCzIcLmdvb2dsZS5wcm90",
-            "b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTIyGHogASgLMhwu",
-            "Z29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRvdWJsZV9maWVsZF8x",
-            "MjMYeyABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNgoQZG91",
-            "YmxlX2ZpZWxkXzEyNBh8IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVW",
-            "YWx1ZRI0Cg5kb3VibGVfZmllbGRfOBgIIAEoCzIcLmdvb2dsZS5wcm90b2J1",
-            "Zi5Eb3VibGVWYWx1ZRI0Cg5kb3VibGVfZmllbGRfORgJIAEoCzIcLmdvb2ds",
-            "ZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfOTgYYiAB",
-            "KAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2Zp",
-            "ZWxkXzEwGAogASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUK",
-            "D2RvdWJsZV9maWVsZF8xMRgLIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3Vi",
-            "bGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfOTkYYyABKAsyHC5nb29nbGUucHJv",
-            "dG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzg0GFQgASgLMhwu",
-            "Z29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF8x",
-            "NBgOIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3Vi",
-            "bGVfZmllbGRfNzcYTSABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFs",
-            "dWUSNQoPZG91YmxlX2ZpZWxkXzE1GA8gASgLMhwuZ29vZ2xlLnByb3RvYnVm",
-            "LkRvdWJsZVZhbHVlEjMKDmludDY0X2ZpZWxkXzE5GBMgASgLMhsuZ29vZ2xl",
-            "LnByb3RvYnVmLkludDY0VmFsdWUSNAoPaW50NjRfZmllbGRfMTE1GHMgASgL",
-            "MhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSNgoQZG91YmxlX2ZpZWxk",
-            "XzExNhh0IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI0Cg9p",
-            "bnQ2NF9maWVsZF8xMTcYdSABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRW",
-            "YWx1ZRI1Cg9kb3VibGVfZmllbGRfMjAYFCABKAsyHC5nb29nbGUucHJvdG9i",
-            "dWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzIxGBUgASgLMhwuZ29v",
-            "Z2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD3N0cmluZ19maWVsZF83MxhJ",
-            "IAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5TdHJpbmdWYWx1ZRI1Cg9zdHJpbmdf",
-            "ZmllbGRfNzQYSiABKAsyHC5nb29nbGUucHJvdG9idWYuU3RyaW5nVmFsdWUS",
-            "NQoPZG91YmxlX2ZpZWxkXzIyGBYgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRv",
-            "dWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF82ORhFIAEoCzIcLmdvb2dsZS5w",
-            "cm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNzAYRiABKAsy",
-            "HC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxk",
-            "XzcxGEcgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD2Rv",
-            "dWJsZV9maWVsZF83MhhIIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVW",
-            "YWx1ZRI1Cg9kb3VibGVfZmllbGRfMjUYGSABKAsyHC5nb29nbGUucHJvdG9i",
-            "dWYuRG91YmxlVmFsdWUSMwoOaW50NjRfZmllbGRfMjYYGiABKAsyGy5nb29n",
-            "bGUucHJvdG9idWYuSW50NjRWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNjgYRCAB",
-            "KAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2Zp",
-            "ZWxkXzI4GBwgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYK",
-            "EGRvdWJsZV9maWVsZF8xMDYYaiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91",
-            "YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzI5GB0gASgLMhwuZ29vZ2xlLnBy",
-            "b3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF8zMBgeIAEoCzIc",
-            "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRf",
-            "MTAxGGUgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRv",
-            "dWJsZV9maWVsZF8xMDIYZiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91Ymxl",
-            "VmFsdWUSNgoQZG91YmxlX2ZpZWxkXzEwMxhnIAEoCzIcLmdvb2dsZS5wcm90",
-            "b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTA0GGggASgLMhwu",
-            "Z29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjYKEGRvdWJsZV9maWVsZF8x",
-            "MDUYaSABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91",
-            "YmxlX2ZpZWxkXzMxGB8gASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh",
-            "bHVlEjMKDmludDY0X2ZpZWxkXzMyGCAgASgLMhsuZ29vZ2xlLnByb3RvYnVm",
-            "LkludDY0VmFsdWUSNQoPZG91YmxlX2ZpZWxkXzc1GEsgASgLMhwuZ29vZ2xl",
-            "LnByb3RvYnVmLkRvdWJsZVZhbHVlEjcKEGRvdWJsZV9maWVsZF8xMjkYgQEg",
-            "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEhUKDWVudW1fZmll",
-            "bGRfODAYUCABKAUSFQoNZW51bV9maWVsZF84MRhRIAEoBRIzCg5pbnQ2NF9m",
-            "aWVsZF84MhhSIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEhUK",
-            "DWVudW1fZmllbGRfODMYUyABKAUSMwoOaW50NjRfZmllbGRfODUYVSABKAsy",
-            "Gy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1ZRIzCg5pbnQ2NF9maWVsZF84",
-            "NhhWIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEjMKDmludDY0",
-            "X2ZpZWxkXzg3GFcgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUS",
-            "NAoPaW50NjRfZmllbGRfMTI1GH0gASgLMhsuZ29vZ2xlLnByb3RvYnVmLklu",
-            "dDY0VmFsdWUSMwoOaW50NjRfZmllbGRfMzcYJSABKAsyGy5nb29nbGUucHJv",
-            "dG9idWYuSW50NjRWYWx1ZRI1Cg9kb3VibGVfZmllbGRfMzgYJiABKAsyHC5n",
-            "b29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMQoMaW50ZXJhY3Rpb25zGCcg",
-            "ASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSHgoWcmVwZWF0ZWRf",
-            "aW50X2ZpZWxkXzEwMBhkIAMoBRI1Cg9kb3VibGVfZmllbGRfNDAYKCABKAsy",
-            "HC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSMwoOaW50NjRfZmllbGRf",
-            "NDEYKSABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1ZRI0Cg9pbnQ2",
-            "NF9maWVsZF8xMjYYfiABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1",
-            "ZRI0Cg9pbnQ2NF9maWVsZF8xMjcYfyABKAsyGy5nb29nbGUucHJvdG9idWYu",
-            "SW50NjRWYWx1ZRI3ChBkb3VibGVfZmllbGRfMTI4GIABIAEoCzIcLmdvb2ds",
-            "ZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI2ChBkb3VibGVfZmllbGRfMTA5GG0g",
-            "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjQKD2ludDY0X2Zp",
-            "ZWxkXzExMBhuIAEoCzIbLmdvb2dsZS5wcm90b2J1Zi5JbnQ2NFZhbHVlEjYK",
-            "EGRvdWJsZV9maWVsZF8xMTEYbyABKAsyHC5nb29nbGUucHJvdG9idWYuRG91",
-            "YmxlVmFsdWUSNAoPaW50NjRfZmllbGRfMTEyGHAgASgLMhsuZ29vZ2xlLnBy",
-            "b3RvYnVmLkludDY0VmFsdWUSNgoQZG91YmxlX2ZpZWxkXzExMxhxIAEoCzIc",
-            "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI0Cg9pbnQ2NF9maWVsZF8x",
-            "MTQYciABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRWYWx1ZRI1Cg9kb3Vi",
-            "bGVfZmllbGRfNDIYKiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFs",
-            "dWUSMwoOaW50NjRfZmllbGRfNDMYKyABKAsyGy5nb29nbGUucHJvdG9idWYu",
-            "SW50NjRWYWx1ZRIzCg5pbnQ2NF9maWVsZF80NBgsIAEoCzIbLmdvb2dsZS5w",
-            "cm90b2J1Zi5JbnQ2NFZhbHVlEjUKD2RvdWJsZV9maWVsZF80NRgtIAEoCzIc",
-            "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRf",
-            "NDYYLiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91",
-            "YmxlX2ZpZWxkXzc4GE4gASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh",
-            "bHVlEjUKD2RvdWJsZV9maWVsZF84OBhYIAEoCzIcLmdvb2dsZS5wcm90b2J1",
-            "Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNDcYLyABKAsyHC5nb29n",
-            "bGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzg5GFkg",
-            "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9m",
-            "aWVsZF80OBgwIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1",
-            "Cg9kb3VibGVfZmllbGRfNDkYMSABKAsyHC5nb29nbGUucHJvdG9idWYuRG91",
-            "YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzUwGDIgASgLMhwuZ29vZ2xlLnBy",
-            "b3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF85MBhaIAEoCzIc",
-            "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRf",
-            "NTEYMyABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91",
-            "YmxlX2ZpZWxkXzkxGFsgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh",
-            "bHVlEjUKD2RvdWJsZV9maWVsZF85MhhcIAEoCzIcLmdvb2dsZS5wcm90b2J1",
-            "Zi5Eb3VibGVWYWx1ZRI0Cg9pbnQ2NF9maWVsZF8xMDcYayABKAsyGy5nb29n",
-            "bGUucHJvdG9idWYuSW50NjRWYWx1ZRI1Cg9kb3VibGVfZmllbGRfOTMYXSAB",
-            "KAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNgoQZG91YmxlX2Zp",
-            "ZWxkXzEwOBhsIAEoCzIcLmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1",
-            "Cg9kb3VibGVfZmllbGRfNTIYNCABKAsyHC5nb29nbGUucHJvdG9idWYuRG91",
-            "YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzUzGDUgASgLMhwuZ29vZ2xlLnBy",
-            "b3RvYnVmLkRvdWJsZVZhbHVlEjUKD2RvdWJsZV9maWVsZF85NBheIAEoCzIc",
-            "Lmdvb2dsZS5wcm90b2J1Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRf",
-            "NTQYNiABKAsyHC5nb29nbGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91",
-            "YmxlX2ZpZWxkXzU1GDcgASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZh",
-            "bHVlEjUKD2RvdWJsZV9maWVsZF81Nhg4IAEoCzIcLmdvb2dsZS5wcm90b2J1",
-            "Zi5Eb3VibGVWYWx1ZRI1Cg9kb3VibGVfZmllbGRfNTcYOSABKAsyHC5nb29n",
-            "bGUucHJvdG9idWYuRG91YmxlVmFsdWUSNQoPZG91YmxlX2ZpZWxkXzU4GDog",
-            "ASgLMhwuZ29vZ2xlLnByb3RvYnVmLkRvdWJsZVZhbHVlEjMKDmludDY0X2Zp",
-            "ZWxkXzU5GDsgASgLMhsuZ29vZ2xlLnByb3RvYnVmLkludDY0VmFsdWUSMwoO",
-            "aW50NjRfZmllbGRfNjAYPCABKAsyGy5nb29nbGUucHJvdG9idWYuSW50NjRW",
-            "YWx1ZSLwFQoaTWFueVByaW1pdGl2ZUZpZWxkc01lc3NhZ2USFwoPZG91Ymxl",
-            "X2ZpZWxkXzk1GF8gASgBEhYKDmRvdWJsZV9maWVsZF8xGAEgASgBEhcKD2Rv",
-            "dWJsZV9maWVsZF83ORhPIAEoARIVCg1pbnQ2NF9maWVsZF8yGAIgASgDEhcK",
-            "D2RvdWJsZV9maWVsZF85NhhgIAEoARIVCg1pbnQ2NF9maWVsZF8zGAMgASgD",
-            "EhUKDWludDY0X2ZpZWxkXzQYBCABKAMSFwoPZG91YmxlX2ZpZWxkXzk3GGEg",
-            "ASgBEhcKD2RvdWJsZV9maWVsZF82NRhBIAEoARIXCg9kb3VibGVfZmllbGRf",
-            "NjYYQiABKAESFgoOZG91YmxlX2ZpZWxkXzcYByABKAESFwoPZG91YmxlX2Zp",
-            "ZWxkXzYyGD4gASgBEhgKEGRvdWJsZV9maWVsZF8xMTgYdiABKAESGAoQZG91",
-            "YmxlX2ZpZWxkXzExORh3IAEoARIXCg9kb3VibGVfZmllbGRfNjcYQyABKAES",
-            "GAoQZG91YmxlX2ZpZWxkXzEyMBh4IAEoARIYChBkb3VibGVfZmllbGRfMTIx",
-            "GHkgASgBEhgKEGRvdWJsZV9maWVsZF8xMjIYeiABKAESGAoQZG91YmxlX2Zp",
-            "ZWxkXzEyMxh7IAEoARIYChBkb3VibGVfZmllbGRfMTI0GHwgASgBEhYKDmRv",
-            "dWJsZV9maWVsZF84GAggASgBEhYKDmRvdWJsZV9maWVsZF85GAkgASgBEhcK",
-            "D2RvdWJsZV9maWVsZF85OBhiIAEoARIXCg9kb3VibGVfZmllbGRfMTAYCiAB",
-            "KAESFwoPZG91YmxlX2ZpZWxkXzExGAsgASgBEhcKD2RvdWJsZV9maWVsZF85",
-            "ORhjIAEoARIXCg9kb3VibGVfZmllbGRfODQYVCABKAESFwoPZG91YmxlX2Zp",
-            "ZWxkXzE0GA4gASgBEhcKD2RvdWJsZV9maWVsZF83NxhNIAEoARIXCg9kb3Vi",
-            "bGVfZmllbGRfMTUYDyABKAESFgoOaW50NjRfZmllbGRfMTkYEyABKAMSFwoP",
-            "aW50NjRfZmllbGRfMTE1GHMgASgDEhgKEGRvdWJsZV9maWVsZF8xMTYYdCAB",
-            "KAESFwoPaW50NjRfZmllbGRfMTE3GHUgASgDEhcKD2RvdWJsZV9maWVsZF8y",
-            "MBgUIAEoARIXCg9kb3VibGVfZmllbGRfMjEYFSABKAESFwoPc3RyaW5nX2Zp",
-            "ZWxkXzczGEkgASgJEhcKD3N0cmluZ19maWVsZF83NBhKIAEoCRIXCg9kb3Vi",
-            "bGVfZmllbGRfMjIYFiABKAESFwoPZG91YmxlX2ZpZWxkXzY5GEUgASgBEhcK",
-            "D2RvdWJsZV9maWVsZF83MBhGIAEoARIXCg9kb3VibGVfZmllbGRfNzEYRyAB",
-            "KAESFwoPZG91YmxlX2ZpZWxkXzcyGEggASgBEhcKD2RvdWJsZV9maWVsZF8y",
-            "NRgZIAEoARIWCg5pbnQ2NF9maWVsZF8yNhgaIAEoAxIXCg9kb3VibGVfZmll",
-            "bGRfNjgYRCABKAESFwoPZG91YmxlX2ZpZWxkXzI4GBwgASgBEhgKEGRvdWJs",
-            "ZV9maWVsZF8xMDYYaiABKAESFwoPZG91YmxlX2ZpZWxkXzI5GB0gASgBEhcK",
-            "D2RvdWJsZV9maWVsZF8zMBgeIAEoARIYChBkb3VibGVfZmllbGRfMTAxGGUg",
-            "ASgBEhgKEGRvdWJsZV9maWVsZF8xMDIYZiABKAESGAoQZG91YmxlX2ZpZWxk",
-            "XzEwMxhnIAEoARIYChBkb3VibGVfZmllbGRfMTA0GGggASgBEhgKEGRvdWJs",
-            "ZV9maWVsZF8xMDUYaSABKAESFwoPZG91YmxlX2ZpZWxkXzMxGB8gASgBEhYK",
-            "DmludDY0X2ZpZWxkXzMyGCAgASgDEhcKD2RvdWJsZV9maWVsZF83NRhLIAEo",
-            "ARIZChBkb3VibGVfZmllbGRfMTI5GIEBIAEoARIVCg1lbnVtX2ZpZWxkXzgw",
-            "GFAgASgFEhUKDWVudW1fZmllbGRfODEYUSABKAUSFgoOaW50NjRfZmllbGRf",
-            "ODIYUiABKAMSFQoNZW51bV9maWVsZF84MxhTIAEoBRIWCg5pbnQ2NF9maWVs",
-            "ZF84NRhVIAEoAxIWCg5pbnQ2NF9maWVsZF84NhhWIAEoAxIWCg5pbnQ2NF9m",
-            "aWVsZF84NxhXIAEoAxIXCg9pbnQ2NF9maWVsZF8xMjUYfSABKAMSFgoOaW50",
-            "NjRfZmllbGRfMzcYJSABKAMSFwoPZG91YmxlX2ZpZWxkXzM4GCYgASgBEhQK",
-            "DGludGVyYWN0aW9ucxgnIAEoAxIeChZyZXBlYXRlZF9pbnRfZmllbGRfMTAw",
-            "GGQgAygFEhcKD2RvdWJsZV9maWVsZF80MBgoIAEoARIWCg5pbnQ2NF9maWVs",
-            "ZF80MRgpIAEoAxIXCg9pbnQ2NF9maWVsZF8xMjYYfiABKAMSFwoPaW50NjRf",
-            "ZmllbGRfMTI3GH8gASgDEhkKEGRvdWJsZV9maWVsZF8xMjgYgAEgASgBEhgK",
-            "EGRvdWJsZV9maWVsZF8xMDkYbSABKAESFwoPaW50NjRfZmllbGRfMTEwGG4g",
-            "ASgDEhgKEGRvdWJsZV9maWVsZF8xMTEYbyABKAESFwoPaW50NjRfZmllbGRf",
-            "MTEyGHAgASgDEhgKEGRvdWJsZV9maWVsZF8xMTMYcSABKAESFwoPaW50NjRf",
-            "ZmllbGRfMTE0GHIgASgDEhcKD2RvdWJsZV9maWVsZF80MhgqIAEoARIWCg5p",
-            "bnQ2NF9maWVsZF80MxgrIAEoAxIWCg5pbnQ2NF9maWVsZF80NBgsIAEoAxIX",
-            "Cg9kb3VibGVfZmllbGRfNDUYLSABKAESFwoPZG91YmxlX2ZpZWxkXzQ2GC4g",
-            "ASgBEhcKD2RvdWJsZV9maWVsZF83OBhOIAEoARIXCg9kb3VibGVfZmllbGRf",
-            "ODgYWCABKAESFwoPZG91YmxlX2ZpZWxkXzQ3GC8gASgBEhcKD2RvdWJsZV9m",
-            "aWVsZF84ORhZIAEoARIXCg9kb3VibGVfZmllbGRfNDgYMCABKAESFwoPZG91",
-            "YmxlX2ZpZWxkXzQ5GDEgASgBEhcKD2RvdWJsZV9maWVsZF81MBgyIAEoARIX",
-            "Cg9kb3VibGVfZmllbGRfOTAYWiABKAESFwoPZG91YmxlX2ZpZWxkXzUxGDMg",
-            "ASgBEhcKD2RvdWJsZV9maWVsZF85MRhbIAEoARIXCg9kb3VibGVfZmllbGRf",
-            "OTIYXCABKAESFwoPaW50NjRfZmllbGRfMTA3GGsgASgDEhcKD2RvdWJsZV9m",
-            "aWVsZF85MxhdIAEoARIYChBkb3VibGVfZmllbGRfMTA4GGwgASgBEhcKD2Rv",
-            "dWJsZV9maWVsZF81Mhg0IAEoARIXCg9kb3VibGVfZmllbGRfNTMYNSABKAES",
-            "FwoPZG91YmxlX2ZpZWxkXzk0GF4gASgBEhcKD2RvdWJsZV9maWVsZF81NBg2",
-            "IAEoARIXCg9kb3VibGVfZmllbGRfNTUYNyABKAESFwoPZG91YmxlX2ZpZWxk",
-            "XzU2GDggASgBEhcKD2RvdWJsZV9maWVsZF81Nxg5IAEoARIXCg9kb3VibGVf",
-            "ZmllbGRfNTgYOiABKAESFgoOaW50NjRfZmllbGRfNTkYOyABKAMSFgoOaW50",
-            "NjRfZmllbGRfNjAYPCABKANiBnByb3RvMw=="));
-      descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
-          new pbr::FileDescriptor[] { global::Google.Protobuf.WellKnownTypes.WrappersReflection.Descriptor, },
-          new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Benchmarks.ManyWrapperFieldsMessage), global::Google.Protobuf.Benchmarks.ManyWrapperFieldsMessage.Parser, new[]{ "DoubleField95", "DoubleField1", "DoubleField79", "Int64Field2", "DoubleField96", "Int64Field3", "Int64Field4", "DoubleField97", "DoubleField65", "DoubleField66", "DoubleField7", "DoubleField62", "DoubleField118", "DoubleField119", "DoubleField67", "DoubleField120", "DoubleField121", "DoubleField122", "DoubleField123", "DoubleField124", "DoubleField8", "DoubleField9", "DoubleField98", "DoubleField10", "DoubleField11", "DoubleField99", "DoubleField84", "DoubleField14", "DoubleField77", "DoubleField15", "Int64Field19", "Int64Field115", "DoubleField116", "Int64Field117", "DoubleField20", "DoubleField21", "StringField73", "StringField74", "DoubleField22", "DoubleField69", "DoubleField70", "DoubleField71", "DoubleField72", "DoubleField25", "Int64Field26", "DoubleField68", "DoubleField28", "DoubleField106", "DoubleField29", "DoubleField30", "DoubleField101", "DoubleField102", "DoubleField103", "DoubleField104", "DoubleField105", "DoubleField31", "Int64Field32", "DoubleField75", "DoubleField129", "EnumField80", "EnumField81", "Int64Field82", "EnumField83", "Int64Field85", "Int64Field86", "Int64Field87", "Int64Field125", "Int64Field37", "DoubleField38", "Interactions", "RepeatedIntField100", "DoubleField40", "Int64Field41", "Int64Field126", "Int64Field127", "DoubleField128", "DoubleField109", "Int64Field110", "DoubleField111", "Int64Field112", "DoubleField113", "Int64Field114", "DoubleField42", "Int64Field43", "Int64Field44", "DoubleField45", "DoubleField46", "DoubleField78", "DoubleField88", "DoubleField47", "DoubleField89", "DoubleField48", "DoubleField49", "DoubleField50", "DoubleField90", "DoubleField51", "DoubleField91", "DoubleField92", "Int64Field107", "DoubleField93", "DoubleField108", "DoubleField52", "DoubleField53", "DoubleField94", "DoubleField54", "DoubleField55", "DoubleField56", "DoubleField57", "DoubleField58", "Int64Field59", "Int64Field60" }, null, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Benchmarks.ManyPrimitiveFieldsMessage), global::Google.Protobuf.Benchmarks.ManyPrimitiveFieldsMessage.Parser, new[]{ "DoubleField95", "DoubleField1", "DoubleField79", "Int64Field2", "DoubleField96", "Int64Field3", "Int64Field4", "DoubleField97", "DoubleField65", "DoubleField66", "DoubleField7", "DoubleField62", "DoubleField118", "DoubleField119", "DoubleField67", "DoubleField120", "DoubleField121", "DoubleField122", "DoubleField123", "DoubleField124", "DoubleField8", "DoubleField9", "DoubleField98", "DoubleField10", "DoubleField11", "DoubleField99", "DoubleField84", "DoubleField14", "DoubleField77", "DoubleField15", "Int64Field19", "Int64Field115", "DoubleField116", "Int64Field117", "DoubleField20", "DoubleField21", "StringField73", "StringField74", "DoubleField22", "DoubleField69", "DoubleField70", "DoubleField71", "DoubleField72", "DoubleField25", "Int64Field26", "DoubleField68", "DoubleField28", "DoubleField106", "DoubleField29", "DoubleField30", "DoubleField101", "DoubleField102", "DoubleField103", "DoubleField104", "DoubleField105", "DoubleField31", "Int64Field32", "DoubleField75", "DoubleField129", "EnumField80", "EnumField81", "Int64Field82", "EnumField83", "Int64Field85", "Int64Field86", "Int64Field87", "Int64Field125", "Int64Field37", "DoubleField38", "Interactions", "RepeatedIntField100", "DoubleField40", "Int64Field41", "Int64Field126", "Int64Field127", "DoubleField128", "DoubleField109", "Int64Field110", "DoubleField111", "Int64Field112", "DoubleField113", "Int64Field114", "DoubleField42", "Int64Field43", "Int64Field44", "DoubleField45", "DoubleField46", "DoubleField78", "DoubleField88", "DoubleField47", "DoubleField89", "DoubleField48", "DoubleField49", "DoubleField50", "DoubleField90", "DoubleField51", "DoubleField91", "DoubleField92", "Int64Field107", "DoubleField93", "DoubleField108", "DoubleField52", "DoubleField53", "DoubleField94", "DoubleField54", "DoubleField55", "DoubleField56", "DoubleField57", "DoubleField58", "Int64Field59", "Int64Field60" }, null, null, null, null)
-          }));
-    }
-    #endregion
-
-  }
-  #region Messages
-  /// <summary>
-  /// 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>
-  #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();
-    }
-
-    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;
-      DoubleField79 = other.DoubleField79;
-      Int64Field2 = other.Int64Field2;
-      DoubleField96 = other.DoubleField96;
-      Int64Field3 = other.Int64Field3;
-      Int64Field4 = other.Int64Field4;
-      DoubleField97 = other.DoubleField97;
-      DoubleField65 = other.DoubleField65;
-      DoubleField66 = other.DoubleField66;
-      DoubleField7 = other.DoubleField7;
-      DoubleField62 = other.DoubleField62;
-      DoubleField118 = other.DoubleField118;
-      DoubleField119 = other.DoubleField119;
-      DoubleField67 = other.DoubleField67;
-      DoubleField120 = other.DoubleField120;
-      DoubleField121 = other.DoubleField121;
-      DoubleField122 = other.DoubleField122;
-      DoubleField123 = other.DoubleField123;
-      DoubleField124 = other.DoubleField124;
-      DoubleField8 = other.DoubleField8;
-      DoubleField9 = other.DoubleField9;
-      DoubleField98 = other.DoubleField98;
-      DoubleField10 = other.DoubleField10;
-      DoubleField11 = other.DoubleField11;
-      DoubleField99 = other.DoubleField99;
-      DoubleField84 = other.DoubleField84;
-      DoubleField14 = other.DoubleField14;
-      DoubleField77 = other.DoubleField77;
-      DoubleField15 = other.DoubleField15;
-      Int64Field19 = other.Int64Field19;
-      Int64Field115 = other.Int64Field115;
-      DoubleField116 = other.DoubleField116;
-      Int64Field117 = other.Int64Field117;
-      DoubleField20 = other.DoubleField20;
-      DoubleField21 = other.DoubleField21;
-      StringField73 = other.StringField73;
-      StringField74 = other.StringField74;
-      DoubleField22 = other.DoubleField22;
-      DoubleField69 = other.DoubleField69;
-      DoubleField70 = other.DoubleField70;
-      DoubleField71 = other.DoubleField71;
-      DoubleField72 = other.DoubleField72;
-      DoubleField25 = other.DoubleField25;
-      Int64Field26 = other.Int64Field26;
-      DoubleField68 = other.DoubleField68;
-      DoubleField28 = other.DoubleField28;
-      DoubleField106 = other.DoubleField106;
-      DoubleField29 = other.DoubleField29;
-      DoubleField30 = other.DoubleField30;
-      DoubleField101 = other.DoubleField101;
-      DoubleField102 = other.DoubleField102;
-      DoubleField103 = other.DoubleField103;
-      DoubleField104 = other.DoubleField104;
-      DoubleField105 = other.DoubleField105;
-      DoubleField31 = other.DoubleField31;
-      Int64Field32 = other.Int64Field32;
-      DoubleField75 = other.DoubleField75;
-      DoubleField129 = other.DoubleField129;
-      enumField80_ = other.enumField80_;
-      enumField81_ = other.enumField81_;
-      Int64Field82 = other.Int64Field82;
-      enumField83_ = other.enumField83_;
-      Int64Field85 = other.Int64Field85;
-      Int64Field86 = other.Int64Field86;
-      Int64Field87 = other.Int64Field87;
-      Int64Field125 = other.Int64Field125;
-      Int64Field37 = other.Int64Field37;
-      DoubleField38 = other.DoubleField38;
-      Interactions = other.Interactions;
-      repeatedIntField100_ = other.repeatedIntField100_.Clone();
-      DoubleField40 = other.DoubleField40;
-      Int64Field41 = other.Int64Field41;
-      Int64Field126 = other.Int64Field126;
-      Int64Field127 = other.Int64Field127;
-      DoubleField128 = other.DoubleField128;
-      DoubleField109 = other.DoubleField109;
-      Int64Field110 = other.Int64Field110;
-      DoubleField111 = other.DoubleField111;
-      Int64Field112 = other.Int64Field112;
-      DoubleField113 = other.DoubleField113;
-      Int64Field114 = other.Int64Field114;
-      DoubleField42 = other.DoubleField42;
-      Int64Field43 = other.Int64Field43;
-      Int64Field44 = other.Int64Field44;
-      DoubleField45 = other.DoubleField45;
-      DoubleField46 = other.DoubleField46;
-      DoubleField78 = other.DoubleField78;
-      DoubleField88 = other.DoubleField88;
-      DoubleField47 = other.DoubleField47;
-      DoubleField89 = other.DoubleField89;
-      DoubleField48 = other.DoubleField48;
-      DoubleField49 = other.DoubleField49;
-      DoubleField50 = other.DoubleField50;
-      DoubleField90 = other.DoubleField90;
-      DoubleField51 = other.DoubleField51;
-      DoubleField91 = other.DoubleField91;
-      DoubleField92 = other.DoubleField92;
-      Int64Field107 = other.Int64Field107;
-      DoubleField93 = other.DoubleField93;
-      DoubleField108 = other.DoubleField108;
-      DoubleField52 = other.DoubleField52;
-      DoubleField53 = other.DoubleField53;
-      DoubleField94 = other.DoubleField94;
-      DoubleField54 = other.DoubleField54;
-      DoubleField55 = other.DoubleField55;
-      DoubleField56 = other.DoubleField56;
-      DoubleField57 = other.DoubleField57;
-      DoubleField58 = other.DoubleField58;
-      Int64Field59 = other.Int64Field59;
-      Int64Field60 = other.Int64Field60;
-      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public ManyWrapperFieldsMessage Clone() {
-      return new ManyWrapperFieldsMessage(this);
-    }
-
-    /// <summary>Field number for the "double_field_95" field.</summary>
-    public const int DoubleField95FieldNumber = 95;
-    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 {
-        doubleField95_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_1" field.</summary>
-    public const int DoubleField1FieldNumber = 1;
-    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 {
-        doubleField1_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_79" field.</summary>
-    public const int DoubleField79FieldNumber = 79;
-    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 {
-        doubleField79_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_2" field.</summary>
-    public const int Int64Field2FieldNumber = 2;
-    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 {
-        int64Field2_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_96" field.</summary>
-    public const int DoubleField96FieldNumber = 96;
-    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 {
-        doubleField96_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_3" field.</summary>
-    public const int Int64Field3FieldNumber = 3;
-    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 {
-        int64Field3_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_4" field.</summary>
-    public const int Int64Field4FieldNumber = 4;
-    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 {
-        int64Field4_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_97" field.</summary>
-    public const int DoubleField97FieldNumber = 97;
-    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 {
-        doubleField97_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_65" field.</summary>
-    public const int DoubleField65FieldNumber = 65;
-    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 {
-        doubleField65_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_66" field.</summary>
-    public const int DoubleField66FieldNumber = 66;
-    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 {
-        doubleField66_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_7" field.</summary>
-    public const int DoubleField7FieldNumber = 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 {
-        doubleField7_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_62" field.</summary>
-    public const int DoubleField62FieldNumber = 62;
-    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 {
-        doubleField62_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_118" field.</summary>
-    public const int DoubleField118FieldNumber = 118;
-    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 {
-        doubleField118_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_119" field.</summary>
-    public const int DoubleField119FieldNumber = 119;
-    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 {
-        doubleField119_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_67" field.</summary>
-    public const int DoubleField67FieldNumber = 67;
-    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 {
-        doubleField67_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_120" field.</summary>
-    public const int DoubleField120FieldNumber = 120;
-    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 {
-        doubleField120_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_121" field.</summary>
-    public const int DoubleField121FieldNumber = 121;
-    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 {
-        doubleField121_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_122" field.</summary>
-    public const int DoubleField122FieldNumber = 122;
-    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 {
-        doubleField122_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_123" field.</summary>
-    public const int DoubleField123FieldNumber = 123;
-    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 {
-        doubleField123_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_124" field.</summary>
-    public const int DoubleField124FieldNumber = 124;
-    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 {
-        doubleField124_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_8" field.</summary>
-    public const int DoubleField8FieldNumber = 8;
-    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 {
-        doubleField8_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_9" field.</summary>
-    public const int DoubleField9FieldNumber = 9;
-    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 {
-        doubleField9_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_98" field.</summary>
-    public const int DoubleField98FieldNumber = 98;
-    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 {
-        doubleField98_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_10" field.</summary>
-    public const int DoubleField10FieldNumber = 10;
-    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 {
-        doubleField10_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_11" field.</summary>
-    public const int DoubleField11FieldNumber = 11;
-    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 {
-        doubleField11_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_99" field.</summary>
-    public const int DoubleField99FieldNumber = 99;
-    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 {
-        doubleField99_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_84" field.</summary>
-    public const int DoubleField84FieldNumber = 84;
-    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 {
-        doubleField84_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_14" field.</summary>
-    public const int DoubleField14FieldNumber = 14;
-    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 {
-        doubleField14_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_77" field.</summary>
-    public const int DoubleField77FieldNumber = 77;
-    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 {
-        doubleField77_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_15" field.</summary>
-    public const int DoubleField15FieldNumber = 15;
-    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 {
-        doubleField15_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_19" field.</summary>
-    public const int Int64Field19FieldNumber = 19;
-    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 {
-        int64Field19_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_115" field.</summary>
-    public const int Int64Field115FieldNumber = 115;
-    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 {
-        int64Field115_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_116" field.</summary>
-    public const int DoubleField116FieldNumber = 116;
-    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 {
-        doubleField116_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_117" field.</summary>
-    public const int Int64Field117FieldNumber = 117;
-    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 {
-        int64Field117_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_20" field.</summary>
-    public const int DoubleField20FieldNumber = 20;
-    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 {
-        doubleField20_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_21" field.</summary>
-    public const int DoubleField21FieldNumber = 21;
-    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 {
-        doubleField21_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "string_field_73" field.</summary>
-    public const int StringField73FieldNumber = 73;
-    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 {
-        stringField73_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "string_field_74" field.</summary>
-    public const int StringField74FieldNumber = 74;
-    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 {
-        stringField74_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_22" field.</summary>
-    public const int DoubleField22FieldNumber = 22;
-    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 {
-        doubleField22_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_69" field.</summary>
-    public const int DoubleField69FieldNumber = 69;
-    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 {
-        doubleField69_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_70" field.</summary>
-    public const int DoubleField70FieldNumber = 70;
-    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 {
-        doubleField70_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_71" field.</summary>
-    public const int DoubleField71FieldNumber = 71;
-    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 {
-        doubleField71_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_72" field.</summary>
-    public const int DoubleField72FieldNumber = 72;
-    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 {
-        doubleField72_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_25" field.</summary>
-    public const int DoubleField25FieldNumber = 25;
-    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 {
-        doubleField25_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_26" field.</summary>
-    public const int Int64Field26FieldNumber = 26;
-    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 {
-        int64Field26_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_68" field.</summary>
-    public const int DoubleField68FieldNumber = 68;
-    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 {
-        doubleField68_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_28" field.</summary>
-    public const int DoubleField28FieldNumber = 28;
-    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 {
-        doubleField28_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_106" field.</summary>
-    public const int DoubleField106FieldNumber = 106;
-    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 {
-        doubleField106_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_29" field.</summary>
-    public const int DoubleField29FieldNumber = 29;
-    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 {
-        doubleField29_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_30" field.</summary>
-    public const int DoubleField30FieldNumber = 30;
-    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 {
-        doubleField30_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_101" field.</summary>
-    public const int DoubleField101FieldNumber = 101;
-    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 {
-        doubleField101_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_102" field.</summary>
-    public const int DoubleField102FieldNumber = 102;
-    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 {
-        doubleField102_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_103" field.</summary>
-    public const int DoubleField103FieldNumber = 103;
-    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 {
-        doubleField103_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_104" field.</summary>
-    public const int DoubleField104FieldNumber = 104;
-    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 {
-        doubleField104_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_105" field.</summary>
-    public const int DoubleField105FieldNumber = 105;
-    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 {
-        doubleField105_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_31" field.</summary>
-    public const int DoubleField31FieldNumber = 31;
-    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 {
-        doubleField31_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_32" field.</summary>
-    public const int Int64Field32FieldNumber = 32;
-    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 {
-        int64Field32_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_75" field.</summary>
-    public const int DoubleField75FieldNumber = 75;
-    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 {
-        doubleField75_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_129" field.</summary>
-    public const int DoubleField129FieldNumber = 129;
-    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 {
-        doubleField129_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "enum_field_80" field.</summary>
-    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 {
-        enumField80_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "enum_field_81" field.</summary>
-    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 {
-        enumField81_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_82" field.</summary>
-    public const int Int64Field82FieldNumber = 82;
-    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 {
-        int64Field82_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "enum_field_83" field.</summary>
-    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 {
-        enumField83_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_85" field.</summary>
-    public const int Int64Field85FieldNumber = 85;
-    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 {
-        int64Field85_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_86" field.</summary>
-    public const int Int64Field86FieldNumber = 86;
-    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 {
-        int64Field86_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_87" field.</summary>
-    public const int Int64Field87FieldNumber = 87;
-    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 {
-        int64Field87_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_125" field.</summary>
-    public const int Int64Field125FieldNumber = 125;
-    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 {
-        int64Field125_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_37" field.</summary>
-    public const int Int64Field37FieldNumber = 37;
-    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 {
-        int64Field37_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_38" field.</summary>
-    public const int DoubleField38FieldNumber = 38;
-    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 {
-        doubleField38_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "interactions" field.</summary>
-    public const int InteractionsFieldNumber = 39;
-    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 {
-        interactions_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "repeated_int_field_100" field.</summary>
-    public const int RepeatedIntField100FieldNumber = 100;
-    private static readonly pb::FieldCodec<int> _repeated_repeatedIntField100_codec
-        = 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_; }
-    }
-
-    /// <summary>Field number for the "double_field_40" field.</summary>
-    public const int DoubleField40FieldNumber = 40;
-    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 {
-        doubleField40_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_41" field.</summary>
-    public const int Int64Field41FieldNumber = 41;
-    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 {
-        int64Field41_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_126" field.</summary>
-    public const int Int64Field126FieldNumber = 126;
-    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 {
-        int64Field126_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_127" field.</summary>
-    public const int Int64Field127FieldNumber = 127;
-    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 {
-        int64Field127_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_128" field.</summary>
-    public const int DoubleField128FieldNumber = 128;
-    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 {
-        doubleField128_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_109" field.</summary>
-    public const int DoubleField109FieldNumber = 109;
-    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 {
-        doubleField109_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_110" field.</summary>
-    public const int Int64Field110FieldNumber = 110;
-    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 {
-        int64Field110_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_111" field.</summary>
-    public const int DoubleField111FieldNumber = 111;
-    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 {
-        doubleField111_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_112" field.</summary>
-    public const int Int64Field112FieldNumber = 112;
-    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 {
-        int64Field112_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_113" field.</summary>
-    public const int DoubleField113FieldNumber = 113;
-    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 {
-        doubleField113_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_114" field.</summary>
-    public const int Int64Field114FieldNumber = 114;
-    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 {
-        int64Field114_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_42" field.</summary>
-    public const int DoubleField42FieldNumber = 42;
-    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 {
-        doubleField42_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_43" field.</summary>
-    public const int Int64Field43FieldNumber = 43;
-    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 {
-        int64Field43_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_44" field.</summary>
-    public const int Int64Field44FieldNumber = 44;
-    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 {
-        int64Field44_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_45" field.</summary>
-    public const int DoubleField45FieldNumber = 45;
-    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 {
-        doubleField45_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_46" field.</summary>
-    public const int DoubleField46FieldNumber = 46;
-    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 {
-        doubleField46_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_78" field.</summary>
-    public const int DoubleField78FieldNumber = 78;
-    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 {
-        doubleField78_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_88" field.</summary>
-    public const int DoubleField88FieldNumber = 88;
-    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 {
-        doubleField88_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_47" field.</summary>
-    public const int DoubleField47FieldNumber = 47;
-    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 {
-        doubleField47_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_89" field.</summary>
-    public const int DoubleField89FieldNumber = 89;
-    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 {
-        doubleField89_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_48" field.</summary>
-    public const int DoubleField48FieldNumber = 48;
-    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 {
-        doubleField48_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_49" field.</summary>
-    public const int DoubleField49FieldNumber = 49;
-    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 {
-        doubleField49_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_50" field.</summary>
-    public const int DoubleField50FieldNumber = 50;
-    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 {
-        doubleField50_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_90" field.</summary>
-    public const int DoubleField90FieldNumber = 90;
-    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 {
-        doubleField90_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_51" field.</summary>
-    public const int DoubleField51FieldNumber = 51;
-    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 {
-        doubleField51_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_91" field.</summary>
-    public const int DoubleField91FieldNumber = 91;
-    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 {
-        doubleField91_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_92" field.</summary>
-    public const int DoubleField92FieldNumber = 92;
-    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 {
-        doubleField92_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_107" field.</summary>
-    public const int Int64Field107FieldNumber = 107;
-    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 {
-        int64Field107_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_93" field.</summary>
-    public const int DoubleField93FieldNumber = 93;
-    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 {
-        doubleField93_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_108" field.</summary>
-    public const int DoubleField108FieldNumber = 108;
-    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 {
-        doubleField108_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_52" field.</summary>
-    public const int DoubleField52FieldNumber = 52;
-    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 {
-        doubleField52_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_53" field.</summary>
-    public const int DoubleField53FieldNumber = 53;
-    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 {
-        doubleField53_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_94" field.</summary>
-    public const int DoubleField94FieldNumber = 94;
-    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 {
-        doubleField94_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_54" field.</summary>
-    public const int DoubleField54FieldNumber = 54;
-    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 {
-        doubleField54_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_55" field.</summary>
-    public const int DoubleField55FieldNumber = 55;
-    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 {
-        doubleField55_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_56" field.</summary>
-    public const int DoubleField56FieldNumber = 56;
-    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 {
-        doubleField56_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_57" field.</summary>
-    public const int DoubleField57FieldNumber = 57;
-    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 {
-        doubleField57_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "double_field_58" field.</summary>
-    public const int DoubleField58FieldNumber = 58;
-    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 {
-        doubleField58_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_59" field.</summary>
-    public const int Int64Field59FieldNumber = 59;
-    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 {
-        int64Field59_ = value;
-      }
-    }
-
-
-    /// <summary>Field number for the "int64_field_60" field.</summary>
-    public const int Int64Field60FieldNumber = 60;
-    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 {
-        int64Field60_ = value;
-      }
-    }
-
-
-    [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;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField95, other.DoubleField95)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField1, other.DoubleField1)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField79, other.DoubleField79)) return false;
-      if (Int64Field2 != other.Int64Field2) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField96, other.DoubleField96)) return false;
-      if (Int64Field3 != other.Int64Field3) return false;
-      if (Int64Field4 != other.Int64Field4) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField97, other.DoubleField97)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField65, other.DoubleField65)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField66, other.DoubleField66)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField7, other.DoubleField7)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField62, other.DoubleField62)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField118, other.DoubleField118)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField119, other.DoubleField119)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField67, other.DoubleField67)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField120, other.DoubleField120)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField121, other.DoubleField121)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField122, other.DoubleField122)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField123, other.DoubleField123)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField124, other.DoubleField124)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField8, other.DoubleField8)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField9, other.DoubleField9)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField98, other.DoubleField98)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField10, other.DoubleField10)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField11, other.DoubleField11)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField99, other.DoubleField99)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField84, other.DoubleField84)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField14, other.DoubleField14)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField77, other.DoubleField77)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField15, other.DoubleField15)) return false;
-      if (Int64Field19 != other.Int64Field19) return false;
-      if (Int64Field115 != other.Int64Field115) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField116, other.DoubleField116)) return false;
-      if (Int64Field117 != other.Int64Field117) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField20, other.DoubleField20)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField21, other.DoubleField21)) return false;
-      if (StringField73 != other.StringField73) return false;
-      if (StringField74 != other.StringField74) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField22, other.DoubleField22)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField69, other.DoubleField69)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField70, other.DoubleField70)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField71, other.DoubleField71)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField72, other.DoubleField72)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField25, other.DoubleField25)) return false;
-      if (Int64Field26 != other.Int64Field26) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField68, other.DoubleField68)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField28, other.DoubleField28)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField106, other.DoubleField106)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField29, other.DoubleField29)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField30, other.DoubleField30)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField101, other.DoubleField101)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField102, other.DoubleField102)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField103, other.DoubleField103)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField104, other.DoubleField104)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField105, other.DoubleField105)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField31, other.DoubleField31)) return false;
-      if (Int64Field32 != other.Int64Field32) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField75, other.DoubleField75)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField129, other.DoubleField129)) return false;
-      if (EnumField80 != other.EnumField80) return false;
-      if (EnumField81 != other.EnumField81) return false;
-      if (Int64Field82 != other.Int64Field82) return false;
-      if (EnumField83 != other.EnumField83) return false;
-      if (Int64Field85 != other.Int64Field85) return false;
-      if (Int64Field86 != other.Int64Field86) return false;
-      if (Int64Field87 != other.Int64Field87) return false;
-      if (Int64Field125 != other.Int64Field125) return false;
-      if (Int64Field37 != other.Int64Field37) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField38, other.DoubleField38)) return false;
-      if (Interactions != other.Interactions) return false;
-      if(!repeatedIntField100_.Equals(other.repeatedIntField100_)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField40, other.DoubleField40)) return false;
-      if (Int64Field41 != other.Int64Field41) return false;
-      if (Int64Field126 != other.Int64Field126) return false;
-      if (Int64Field127 != other.Int64Field127) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField128, other.DoubleField128)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField109, other.DoubleField109)) return false;
-      if (Int64Field110 != other.Int64Field110) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField111, other.DoubleField111)) return false;
-      if (Int64Field112 != other.Int64Field112) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField113, other.DoubleField113)) return false;
-      if (Int64Field114 != other.Int64Field114) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField42, other.DoubleField42)) return false;
-      if (Int64Field43 != other.Int64Field43) return false;
-      if (Int64Field44 != other.Int64Field44) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField45, other.DoubleField45)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField46, other.DoubleField46)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField78, other.DoubleField78)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField88, other.DoubleField88)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField47, other.DoubleField47)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField89, other.DoubleField89)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField48, other.DoubleField48)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField49, other.DoubleField49)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField50, other.DoubleField50)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField90, other.DoubleField90)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField51, other.DoubleField51)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField91, other.DoubleField91)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField92, other.DoubleField92)) return false;
-      if (Int64Field107 != other.Int64Field107) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField93, other.DoubleField93)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField108, other.DoubleField108)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField52, other.DoubleField52)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField53, other.DoubleField53)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField94, other.DoubleField94)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField54, other.DoubleField54)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField55, other.DoubleField55)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField56, other.DoubleField56)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField57, other.DoubleField57)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.Equals(DoubleField58, other.DoubleField58)) return false;
-      if (Int64Field59 != other.Int64Field59) return false;
-      if (Int64Field60 != other.Int64Field60) 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 (doubleField95_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField95);
-      if (doubleField1_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField1);
-      if (doubleField79_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField79);
-      if (int64Field2_ != null) hash ^= Int64Field2.GetHashCode();
-      if (doubleField96_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField96);
-      if (int64Field3_ != null) hash ^= Int64Field3.GetHashCode();
-      if (int64Field4_ != null) hash ^= Int64Field4.GetHashCode();
-      if (doubleField97_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField97);
-      if (doubleField65_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField65);
-      if (doubleField66_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField66);
-      if (doubleField7_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField7);
-      if (doubleField62_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField62);
-      if (doubleField118_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField118);
-      if (doubleField119_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField119);
-      if (doubleField67_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField67);
-      if (doubleField120_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField120);
-      if (doubleField121_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField121);
-      if (doubleField122_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField122);
-      if (doubleField123_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField123);
-      if (doubleField124_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField124);
-      if (doubleField8_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField8);
-      if (doubleField9_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField9);
-      if (doubleField98_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField98);
-      if (doubleField10_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField10);
-      if (doubleField11_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField11);
-      if (doubleField99_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField99);
-      if (doubleField84_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField84);
-      if (doubleField14_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField14);
-      if (doubleField77_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField77);
-      if (doubleField15_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField15);
-      if (int64Field19_ != null) hash ^= Int64Field19.GetHashCode();
-      if (int64Field115_ != null) hash ^= Int64Field115.GetHashCode();
-      if (doubleField116_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField116);
-      if (int64Field117_ != null) hash ^= Int64Field117.GetHashCode();
-      if (doubleField20_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField20);
-      if (doubleField21_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField21);
-      if (stringField73_ != null) hash ^= StringField73.GetHashCode();
-      if (stringField74_ != null) hash ^= StringField74.GetHashCode();
-      if (doubleField22_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField22);
-      if (doubleField69_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField69);
-      if (doubleField70_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField70);
-      if (doubleField71_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField71);
-      if (doubleField72_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField72);
-      if (doubleField25_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField25);
-      if (int64Field26_ != null) hash ^= Int64Field26.GetHashCode();
-      if (doubleField68_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField68);
-      if (doubleField28_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField28);
-      if (doubleField106_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField106);
-      if (doubleField29_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField29);
-      if (doubleField30_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField30);
-      if (doubleField101_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField101);
-      if (doubleField102_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField102);
-      if (doubleField103_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField103);
-      if (doubleField104_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField104);
-      if (doubleField105_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField105);
-      if (doubleField31_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField31);
-      if (int64Field32_ != null) hash ^= Int64Field32.GetHashCode();
-      if (doubleField75_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField75);
-      if (doubleField129_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField129);
-      if (EnumField80 != 0) hash ^= EnumField80.GetHashCode();
-      if (EnumField81 != 0) hash ^= EnumField81.GetHashCode();
-      if (int64Field82_ != null) hash ^= Int64Field82.GetHashCode();
-      if (EnumField83 != 0) hash ^= EnumField83.GetHashCode();
-      if (int64Field85_ != null) hash ^= Int64Field85.GetHashCode();
-      if (int64Field86_ != null) hash ^= Int64Field86.GetHashCode();
-      if (int64Field87_ != null) hash ^= Int64Field87.GetHashCode();
-      if (int64Field125_ != null) hash ^= Int64Field125.GetHashCode();
-      if (int64Field37_ != null) hash ^= Int64Field37.GetHashCode();
-      if (doubleField38_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField38);
-      if (interactions_ != null) hash ^= Interactions.GetHashCode();
-      hash ^= repeatedIntField100_.GetHashCode();
-      if (doubleField40_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField40);
-      if (int64Field41_ != null) hash ^= Int64Field41.GetHashCode();
-      if (int64Field126_ != null) hash ^= Int64Field126.GetHashCode();
-      if (int64Field127_ != null) hash ^= Int64Field127.GetHashCode();
-      if (doubleField128_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField128);
-      if (doubleField109_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField109);
-      if (int64Field110_ != null) hash ^= Int64Field110.GetHashCode();
-      if (doubleField111_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField111);
-      if (int64Field112_ != null) hash ^= Int64Field112.GetHashCode();
-      if (doubleField113_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField113);
-      if (int64Field114_ != null) hash ^= Int64Field114.GetHashCode();
-      if (doubleField42_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField42);
-      if (int64Field43_ != null) hash ^= Int64Field43.GetHashCode();
-      if (int64Field44_ != null) hash ^= Int64Field44.GetHashCode();
-      if (doubleField45_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField45);
-      if (doubleField46_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField46);
-      if (doubleField78_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField78);
-      if (doubleField88_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField88);
-      if (doubleField47_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField47);
-      if (doubleField89_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField89);
-      if (doubleField48_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField48);
-      if (doubleField49_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField49);
-      if (doubleField50_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField50);
-      if (doubleField90_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField90);
-      if (doubleField51_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField51);
-      if (doubleField91_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField91);
-      if (doubleField92_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField92);
-      if (int64Field107_ != null) hash ^= Int64Field107.GetHashCode();
-      if (doubleField93_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField93);
-      if (doubleField108_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField108);
-      if (doubleField52_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField52);
-      if (doubleField53_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField53);
-      if (doubleField94_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField94);
-      if (doubleField54_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField54);
-      if (doubleField55_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField55);
-      if (doubleField56_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField56);
-      if (doubleField57_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField57);
-      if (doubleField58_ != null) hash ^= pbc::ProtobufEqualityComparers.BitwiseNullableDoubleEqualityComparer.GetHashCode(DoubleField58);
-      if (int64Field59_ != null) hash ^= Int64Field59.GetHashCode();
-      if (int64Field60_ != null) hash ^= Int64Field60.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 (doubleField1_ != null) {
-        _single_doubleField1_codec.WriteTagAndValue(output, DoubleField1);
-      }
-      if (int64Field2_ != null) {
-        _single_int64Field2_codec.WriteTagAndValue(output, Int64Field2);
-      }
-      if (int64Field3_ != null) {
-        _single_int64Field3_codec.WriteTagAndValue(output, Int64Field3);
-      }
-      if (int64Field4_ != null) {
-        _single_int64Field4_codec.WriteTagAndValue(output, Int64Field4);
-      }
-      if (doubleField7_ != null) {
-        _single_doubleField7_codec.WriteTagAndValue(output, DoubleField7);
-      }
-      if (doubleField8_ != null) {
-        _single_doubleField8_codec.WriteTagAndValue(output, DoubleField8);
-      }
-      if (doubleField9_ != null) {
-        _single_doubleField9_codec.WriteTagAndValue(output, DoubleField9);
-      }
-      if (doubleField10_ != null) {
-        _single_doubleField10_codec.WriteTagAndValue(output, DoubleField10);
-      }
-      if (doubleField11_ != null) {
-        _single_doubleField11_codec.WriteTagAndValue(output, DoubleField11);
-      }
-      if (doubleField14_ != null) {
-        _single_doubleField14_codec.WriteTagAndValue(output, DoubleField14);
-      }
-      if (doubleField15_ != null) {
-        _single_doubleField15_codec.WriteTagAndValue(output, DoubleField15);
-      }
-      if (int64Field19_ != null) {
-        _single_int64Field19_codec.WriteTagAndValue(output, Int64Field19);
-      }
-      if (doubleField20_ != null) {
-        _single_doubleField20_codec.WriteTagAndValue(output, DoubleField20);
-      }
-      if (doubleField21_ != null) {
-        _single_doubleField21_codec.WriteTagAndValue(output, DoubleField21);
-      }
-      if (doubleField22_ != null) {
-        _single_doubleField22_codec.WriteTagAndValue(output, DoubleField22);
-      }
-      if (doubleField25_ != null) {
-        _single_doubleField25_codec.WriteTagAndValue(output, DoubleField25);
-      }
-      if (int64Field26_ != null) {
-        _single_int64Field26_codec.WriteTagAndValue(output, Int64Field26);
-      }
-      if (doubleField28_ != null) {
-        _single_doubleField28_codec.WriteTagAndValue(output, DoubleField28);
-      }
-      if (doubleField29_ != null) {
-        _single_doubleField29_codec.WriteTagAndValue(output, DoubleField29);
-      }
-      if (doubleField30_ != null) {
-        _single_doubleField30_codec.WriteTagAndValue(output, DoubleField30);
-      }
-      if (doubleField31_ != null) {
-        _single_doubleField31_codec.WriteTagAndValue(output, DoubleField31);
-      }
-      if (int64Field32_ != null) {
-        _single_int64Field32_codec.WriteTagAndValue(output, Int64Field32);
-      }
-      if (int64Field37_ != null) {
-        _single_int64Field37_codec.WriteTagAndValue(output, Int64Field37);
-      }
-      if (doubleField38_ != null) {
-        _single_doubleField38_codec.WriteTagAndValue(output, DoubleField38);
-      }
-      if (interactions_ != null) {
-        _single_interactions_codec.WriteTagAndValue(output, Interactions);
-      }
-      if (doubleField40_ != null) {
-        _single_doubleField40_codec.WriteTagAndValue(output, DoubleField40);
-      }
-      if (int64Field41_ != null) {
-        _single_int64Field41_codec.WriteTagAndValue(output, Int64Field41);
-      }
-      if (doubleField42_ != null) {
-        _single_doubleField42_codec.WriteTagAndValue(output, DoubleField42);
-      }
-      if (int64Field43_ != null) {
-        _single_int64Field43_codec.WriteTagAndValue(output, Int64Field43);
-      }
-      if (int64Field44_ != null) {
-        _single_int64Field44_codec.WriteTagAndValue(output, Int64Field44);
-      }
-      if (doubleField45_ != null) {
-        _single_doubleField45_codec.WriteTagAndValue(output, DoubleField45);
-      }
-      if (doubleField46_ != null) {
-        _single_doubleField46_codec.WriteTagAndValue(output, DoubleField46);
-      }
-      if (doubleField47_ != null) {
-        _single_doubleField47_codec.WriteTagAndValue(output, DoubleField47);
-      }
-      if (doubleField48_ != null) {
-        _single_doubleField48_codec.WriteTagAndValue(output, DoubleField48);
-      }
-      if (doubleField49_ != null) {
-        _single_doubleField49_codec.WriteTagAndValue(output, DoubleField49);
-      }
-      if (doubleField50_ != null) {
-        _single_doubleField50_codec.WriteTagAndValue(output, DoubleField50);
-      }
-      if (doubleField51_ != null) {
-        _single_doubleField51_codec.WriteTagAndValue(output, DoubleField51);
-      }
-      if (doubleField52_ != null) {
-        _single_doubleField52_codec.WriteTagAndValue(output, DoubleField52);
-      }
-      if (doubleField53_ != null) {
-        _single_doubleField53_codec.WriteTagAndValue(output, DoubleField53);
-      }
-      if (doubleField54_ != null) {
-        _single_doubleField54_codec.WriteTagAndValue(output, DoubleField54);
-      }
-      if (doubleField55_ != null) {
-        _single_doubleField55_codec.WriteTagAndValue(output, DoubleField55);
-      }
-      if (doubleField56_ != null) {
-        _single_doubleField56_codec.WriteTagAndValue(output, DoubleField56);
-      }
-      if (doubleField57_ != null) {
-        _single_doubleField57_codec.WriteTagAndValue(output, DoubleField57);
-      }
-      if (doubleField58_ != null) {
-        _single_doubleField58_codec.WriteTagAndValue(output, DoubleField58);
-      }
-      if (int64Field59_ != null) {
-        _single_int64Field59_codec.WriteTagAndValue(output, Int64Field59);
-      }
-      if (int64Field60_ != null) {
-        _single_int64Field60_codec.WriteTagAndValue(output, Int64Field60);
-      }
-      if (doubleField62_ != null) {
-        _single_doubleField62_codec.WriteTagAndValue(output, DoubleField62);
-      }
-      if (doubleField65_ != null) {
-        _single_doubleField65_codec.WriteTagAndValue(output, DoubleField65);
-      }
-      if (doubleField66_ != null) {
-        _single_doubleField66_codec.WriteTagAndValue(output, DoubleField66);
-      }
-      if (doubleField67_ != null) {
-        _single_doubleField67_codec.WriteTagAndValue(output, DoubleField67);
-      }
-      if (doubleField68_ != null) {
-        _single_doubleField68_codec.WriteTagAndValue(output, DoubleField68);
-      }
-      if (doubleField69_ != null) {
-        _single_doubleField69_codec.WriteTagAndValue(output, DoubleField69);
-      }
-      if (doubleField70_ != null) {
-        _single_doubleField70_codec.WriteTagAndValue(output, DoubleField70);
-      }
-      if (doubleField71_ != null) {
-        _single_doubleField71_codec.WriteTagAndValue(output, DoubleField71);
-      }
-      if (doubleField72_ != null) {
-        _single_doubleField72_codec.WriteTagAndValue(output, DoubleField72);
-      }
-      if (stringField73_ != null) {
-        _single_stringField73_codec.WriteTagAndValue(output, StringField73);
-      }
-      if (stringField74_ != null) {
-        _single_stringField74_codec.WriteTagAndValue(output, StringField74);
-      }
-      if (doubleField75_ != null) {
-        _single_doubleField75_codec.WriteTagAndValue(output, DoubleField75);
-      }
-      if (doubleField77_ != null) {
-        _single_doubleField77_codec.WriteTagAndValue(output, DoubleField77);
-      }
-      if (doubleField78_ != null) {
-        _single_doubleField78_codec.WriteTagAndValue(output, DoubleField78);
-      }
-      if (doubleField79_ != null) {
-        _single_doubleField79_codec.WriteTagAndValue(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(output, Int64Field82);
-      }
-      if (EnumField83 != 0) {
-        output.WriteRawTag(152, 5);
-        output.WriteInt32(EnumField83);
-      }
-      if (doubleField84_ != null) {
-        _single_doubleField84_codec.WriteTagAndValue(output, DoubleField84);
-      }
-      if (int64Field85_ != null) {
-        _single_int64Field85_codec.WriteTagAndValue(output, Int64Field85);
-      }
-      if (int64Field86_ != null) {
-        _single_int64Field86_codec.WriteTagAndValue(output, Int64Field86);
-      }
-      if (int64Field87_ != null) {
-        _single_int64Field87_codec.WriteTagAndValue(output, Int64Field87);
-      }
-      if (doubleField88_ != null) {
-        _single_doubleField88_codec.WriteTagAndValue(output, DoubleField88);
-      }
-      if (doubleField89_ != null) {
-        _single_doubleField89_codec.WriteTagAndValue(output, DoubleField89);
-      }
-      if (doubleField90_ != null) {
-        _single_doubleField90_codec.WriteTagAndValue(output, DoubleField90);
-      }
-      if (doubleField91_ != null) {
-        _single_doubleField91_codec.WriteTagAndValue(output, DoubleField91);
-      }
-      if (doubleField92_ != null) {
-        _single_doubleField92_codec.WriteTagAndValue(output, DoubleField92);
-      }
-      if (doubleField93_ != null) {
-        _single_doubleField93_codec.WriteTagAndValue(output, DoubleField93);
-      }
-      if (doubleField94_ != null) {
-        _single_doubleField94_codec.WriteTagAndValue(output, DoubleField94);
-      }
-      if (doubleField95_ != null) {
-        _single_doubleField95_codec.WriteTagAndValue(output, DoubleField95);
-      }
-      if (doubleField96_ != null) {
-        _single_doubleField96_codec.WriteTagAndValue(output, DoubleField96);
-      }
-      if (doubleField97_ != null) {
-        _single_doubleField97_codec.WriteTagAndValue(output, DoubleField97);
-      }
-      if (doubleField98_ != null) {
-        _single_doubleField98_codec.WriteTagAndValue(output, DoubleField98);
-      }
-      if (doubleField99_ != null) {
-        _single_doubleField99_codec.WriteTagAndValue(output, DoubleField99);
-      }
-      repeatedIntField100_.WriteTo(output, _repeated_repeatedIntField100_codec);
-      if (doubleField101_ != null) {
-        _single_doubleField101_codec.WriteTagAndValue(output, DoubleField101);
-      }
-      if (doubleField102_ != null) {
-        _single_doubleField102_codec.WriteTagAndValue(output, DoubleField102);
-      }
-      if (doubleField103_ != null) {
-        _single_doubleField103_codec.WriteTagAndValue(output, DoubleField103);
-      }
-      if (doubleField104_ != null) {
-        _single_doubleField104_codec.WriteTagAndValue(output, DoubleField104);
-      }
-      if (doubleField105_ != null) {
-        _single_doubleField105_codec.WriteTagAndValue(output, DoubleField105);
-      }
-      if (doubleField106_ != null) {
-        _single_doubleField106_codec.WriteTagAndValue(output, DoubleField106);
-      }
-      if (int64Field107_ != null) {
-        _single_int64Field107_codec.WriteTagAndValue(output, Int64Field107);
-      }
-      if (doubleField108_ != null) {
-        _single_doubleField108_codec.WriteTagAndValue(output, DoubleField108);
-      }
-      if (doubleField109_ != null) {
-        _single_doubleField109_codec.WriteTagAndValue(output, DoubleField109);
-      }
-      if (int64Field110_ != null) {
-        _single_int64Field110_codec.WriteTagAndValue(output, Int64Field110);
-      }
-      if (doubleField111_ != null) {
-        _single_doubleField111_codec.WriteTagAndValue(output, DoubleField111);
-      }
-      if (int64Field112_ != null) {
-        _single_int64Field112_codec.WriteTagAndValue(output, Int64Field112);
-      }
-      if (doubleField113_ != null) {
-        _single_doubleField113_codec.WriteTagAndValue(output, DoubleField113);
-      }
-      if (int64Field114_ != null) {
-        _single_int64Field114_codec.WriteTagAndValue(output, Int64Field114);
-      }
-      if (int64Field115_ != null) {
-        _single_int64Field115_codec.WriteTagAndValue(output, Int64Field115);
-      }
-      if (doubleField116_ != null) {
-        _single_doubleField116_codec.WriteTagAndValue(output, DoubleField116);
-      }
-      if (int64Field117_ != null) {
-        _single_int64Field117_codec.WriteTagAndValue(output, Int64Field117);
-      }
-      if (doubleField118_ != null) {
-        _single_doubleField118_codec.WriteTagAndValue(output, DoubleField118);
-      }
-      if (doubleField119_ != null) {
-        _single_doubleField119_codec.WriteTagAndValue(output, DoubleField119);
-      }
-      if (doubleField120_ != null) {
-        _single_doubleField120_codec.WriteTagAndValue(output, DoubleField120);
-      }
-      if (doubleField121_ != null) {
-        _single_doubleField121_codec.WriteTagAndValue(output, DoubleField121);
-      }
-      if (doubleField122_ != null) {
-        _single_doubleField122_codec.WriteTagAndValue(output, DoubleField122);
-      }
-      if (doubleField123_ != null) {
-        _single_doubleField123_codec.WriteTagAndValue(output, DoubleField123);
-      }
-      if (doubleField124_ != null) {
-        _single_doubleField124_codec.WriteTagAndValue(output, DoubleField124);
-      }
-      if (int64Field125_ != null) {
-        _single_int64Field125_codec.WriteTagAndValue(output, Int64Field125);
-      }
-      if (int64Field126_ != null) {
-        _single_int64Field126_codec.WriteTagAndValue(output, Int64Field126);
-      }
-      if (int64Field127_ != null) {
-        _single_int64Field127_codec.WriteTagAndValue(output, Int64Field127);
-      }
-      if (doubleField128_ != null) {
-        _single_doubleField128_codec.WriteTagAndValue(output, DoubleField128);
-      }
-      if (doubleField129_ != null) {
-        _single_doubleField129_codec.WriteTagAndValue(output, DoubleField129);
-      }
-      if (_unknownFields != null) {
-        _unknownFields.WriteTo(output);
-      }
-    #endif
-    }
-
-    #if !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) {
-        size += _single_doubleField95_codec.CalculateSizeWithTag(DoubleField95);
-      }
-      if (doubleField1_ != null) {
-        size += _single_doubleField1_codec.CalculateSizeWithTag(DoubleField1);
-      }
-      if (doubleField79_ != null) {
-        size += _single_doubleField79_codec.CalculateSizeWithTag(DoubleField79);
-      }
-      if (int64Field2_ != null) {
-        size += _single_int64Field2_codec.CalculateSizeWithTag(Int64Field2);
-      }
-      if (doubleField96_ != null) {
-        size += _single_doubleField96_codec.CalculateSizeWithTag(DoubleField96);
-      }
-      if (int64Field3_ != null) {
-        size += _single_int64Field3_codec.CalculateSizeWithTag(Int64Field3);
-      }
-      if (int64Field4_ != null) {
-        size += _single_int64Field4_codec.CalculateSizeWithTag(Int64Field4);
-      }
-      if (doubleField97_ != null) {
-        size += _single_doubleField97_codec.CalculateSizeWithTag(DoubleField97);
-      }
-      if (doubleField65_ != null) {
-        size += _single_doubleField65_codec.CalculateSizeWithTag(DoubleField65);
-      }
-      if (doubleField66_ != null) {
-        size += _single_doubleField66_codec.CalculateSizeWithTag(DoubleField66);
-      }
-      if (doubleField7_ != null) {
-        size += _single_doubleField7_codec.CalculateSizeWithTag(DoubleField7);
-      }
-      if (doubleField62_ != null) {
-        size += _single_doubleField62_codec.CalculateSizeWithTag(DoubleField62);
-      }
-      if (doubleField118_ != null) {
-        size += _single_doubleField118_codec.CalculateSizeWithTag(DoubleField118);
-      }
-      if (doubleField119_ != null) {
-        size += _single_doubleField119_codec.CalculateSizeWithTag(DoubleField119);
-      }
-      if (doubleField67_ != null) {
-        size += _single_doubleField67_codec.CalculateSizeWithTag(DoubleField67);
-      }
-      if (doubleField120_ != null) {
-        size += _single_doubleField120_codec.CalculateSizeWithTag(DoubleField120);
-      }
-      if (doubleField121_ != null) {
-        size += _single_doubleField121_codec.CalculateSizeWithTag(DoubleField121);
-      }
-      if (doubleField122_ != null) {
-        size += _single_doubleField122_codec.CalculateSizeWithTag(DoubleField122);
-      }
-      if (doubleField123_ != null) {
-        size += _single_doubleField123_codec.CalculateSizeWithTag(DoubleField123);
-      }
-      if (doubleField124_ != null) {
-        size += _single_doubleField124_codec.CalculateSizeWithTag(DoubleField124);
-      }
-      if (doubleField8_ != null) {
-        size += _single_doubleField8_codec.CalculateSizeWithTag(DoubleField8);
-      }
-      if (doubleField9_ != null) {
-        size += _single_doubleField9_codec.CalculateSizeWithTag(DoubleField9);
-      }
-      if (doubleField98_ != null) {
-        size += _single_doubleField98_codec.CalculateSizeWithTag(DoubleField98);
-      }
-      if (doubleField10_ != null) {
-        size += _single_doubleField10_codec.CalculateSizeWithTag(DoubleField10);
-      }
-      if (doubleField11_ != null) {
-        size += _single_doubleField11_codec.CalculateSizeWithTag(DoubleField11);
-      }
-      if (doubleField99_ != null) {
-        size += _single_doubleField99_codec.CalculateSizeWithTag(DoubleField99);
-      }
-      if (doubleField84_ != null) {
-        size += _single_doubleField84_codec.CalculateSizeWithTag(DoubleField84);
-      }
-      if (doubleField14_ != null) {
-        size += _single_doubleField14_codec.CalculateSizeWithTag(DoubleField14);
-      }
-      if (doubleField77_ != null) {
-        size += _single_doubleField77_codec.CalculateSizeWithTag(DoubleField77);
-      }
-      if (doubleField15_ != null) {
-        size += _single_doubleField15_codec.CalculateSizeWithTag(DoubleField15);
-      }
-      if (int64Field19_ != null) {
-        size += _single_int64Field19_codec.CalculateSizeWithTag(Int64Field19);
-      }
-      if (int64Field115_ != null) {
-        size += _single_int64Field115_codec.CalculateSizeWithTag(Int64Field115);
-      }
-      if (doubleField116_ != null) {
-        size += _single_doubleField116_codec.CalculateSizeWithTag(DoubleField116);
-      }
-      if (int64Field117_ != null) {
-        size += _single_int64Field117_codec.CalculateSizeWithTag(Int64Field117);
-      }
-      if (doubleField20_ != null) {
-        size += _single_doubleField20_codec.CalculateSizeWithTag(DoubleField20);
-      }
-      if (doubleField21_ != null) {
-        size += _single_doubleField21_codec.CalculateSizeWithTag(DoubleField21);
-      }
-      if (stringField73_ != null) {
-        size += _single_stringField73_codec.CalculateSizeWithTag(StringField73);
-      }
-      if (stringField74_ != null) {
-        size += _single_stringField74_codec.CalculateSizeWithTag(StringField74);
-      }
-      if (doubleField22_ != null) {
-        size += _single_doubleField22_codec.CalculateSizeWithTag(DoubleField22);
-      }
-      if (doubleField69_ != null) {
-        size += _single_doubleField69_codec.CalculateSizeWithTag(DoubleField69);
-      }
-      if (doubleField70_ != null) {
-        size += _single_doubleField70_codec.CalculateSizeWithTag(DoubleField70);
-      }
-      if (doubleField71_ != null) {
-        size += _single_doubleField71_codec.CalculateSizeWithTag(DoubleField71);
-      }
-      if (doubleField72_ != null) {
-        size += _single_doubleField72_codec.CalculateSizeWithTag(DoubleField72);
-      }
-      if (doubleField25_ != null) {
-        size += _single_doubleField25_codec.CalculateSizeWithTag(DoubleField25);
-      }
-      if (int64Field26_ != null) {
-        size += _single_int64Field26_codec.CalculateSizeWithTag(Int64Field26);
-      }
-      if (doubleField68_ != null) {
-        size += _single_doubleField68_codec.CalculateSizeWithTag(DoubleField68);
-      }
-      if (doubleField28_ != null) {
-        size += _single_doubleField28_codec.CalculateSizeWithTag(DoubleField28);
-      }
-      if (doubleField106_ != null) {
-        size += _single_doubleField106_codec.CalculateSizeWithTag(DoubleField106);
-      }
-      if (doubleField29_ != null) {
-        size += _single_doubleField29_codec.CalculateSizeWithTag(DoubleField29);
-      }
-      if (doubleField30_ != null) {
-        size += _single_doubleField30_codec.CalculateSizeWithTag(DoubleField30);
-      }
-      if (doubleField101_ != null) {
-        size += _single_doubleField101_codec.CalculateSizeWithTag(DoubleField101);
-      }
-      if (doubleField102_ != null) {
-        size += _single_doubleField102_codec.CalculateSizeWithTag(DoubleField102);
-      }
-      if (doubleField103_ != null) {
-        size += _single_doubleField103_codec.CalculateSizeWithTag(DoubleField103);
-      }
-      if (doubleField104_ != null) {
-        size += _single_doubleField104_codec.CalculateSizeWithTag(DoubleField104);
-      }
-      if (doubleField105_ != null) {
-        size += _single_doubleField105_codec.CalculateSizeWithTag(DoubleField105);
-      }
-      if (doubleField31_ != null) {
-        size += _single_doubleField31_codec.CalculateSizeWithTag(DoubleField31);
-      }
-      if (int64Field32_ != null) {
-        size += _single_int64Field32_codec.CalculateSizeWithTag(Int64Field32);
-      }
-      if (doubleField75_ != null) {
-        size += _single_doubleField75_codec.CalculateSizeWithTag(DoubleField75);
-      }
-      if (doubleField129_ != null) {
-        size += _single_doubleField129_codec.CalculateSizeWithTag(DoubleField129);
-      }
-      if (EnumField80 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField80);
-      }
-      if (EnumField81 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField81);
-      }
-      if (int64Field82_ != null) {
-        size += _single_int64Field82_codec.CalculateSizeWithTag(Int64Field82);
-      }
-      if (EnumField83 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField83);
-      }
-      if (int64Field85_ != null) {
-        size += _single_int64Field85_codec.CalculateSizeWithTag(Int64Field85);
-      }
-      if (int64Field86_ != null) {
-        size += _single_int64Field86_codec.CalculateSizeWithTag(Int64Field86);
-      }
-      if (int64Field87_ != null) {
-        size += _single_int64Field87_codec.CalculateSizeWithTag(Int64Field87);
-      }
-      if (int64Field125_ != null) {
-        size += _single_int64Field125_codec.CalculateSizeWithTag(Int64Field125);
-      }
-      if (int64Field37_ != null) {
-        size += _single_int64Field37_codec.CalculateSizeWithTag(Int64Field37);
-      }
-      if (doubleField38_ != null) {
-        size += _single_doubleField38_codec.CalculateSizeWithTag(DoubleField38);
-      }
-      if (interactions_ != null) {
-        size += _single_interactions_codec.CalculateSizeWithTag(Interactions);
-      }
-      size += repeatedIntField100_.CalculateSize(_repeated_repeatedIntField100_codec);
-      if (doubleField40_ != null) {
-        size += _single_doubleField40_codec.CalculateSizeWithTag(DoubleField40);
-      }
-      if (int64Field41_ != null) {
-        size += _single_int64Field41_codec.CalculateSizeWithTag(Int64Field41);
-      }
-      if (int64Field126_ != null) {
-        size += _single_int64Field126_codec.CalculateSizeWithTag(Int64Field126);
-      }
-      if (int64Field127_ != null) {
-        size += _single_int64Field127_codec.CalculateSizeWithTag(Int64Field127);
-      }
-      if (doubleField128_ != null) {
-        size += _single_doubleField128_codec.CalculateSizeWithTag(DoubleField128);
-      }
-      if (doubleField109_ != null) {
-        size += _single_doubleField109_codec.CalculateSizeWithTag(DoubleField109);
-      }
-      if (int64Field110_ != null) {
-        size += _single_int64Field110_codec.CalculateSizeWithTag(Int64Field110);
-      }
-      if (doubleField111_ != null) {
-        size += _single_doubleField111_codec.CalculateSizeWithTag(DoubleField111);
-      }
-      if (int64Field112_ != null) {
-        size += _single_int64Field112_codec.CalculateSizeWithTag(Int64Field112);
-      }
-      if (doubleField113_ != null) {
-        size += _single_doubleField113_codec.CalculateSizeWithTag(DoubleField113);
-      }
-      if (int64Field114_ != null) {
-        size += _single_int64Field114_codec.CalculateSizeWithTag(Int64Field114);
-      }
-      if (doubleField42_ != null) {
-        size += _single_doubleField42_codec.CalculateSizeWithTag(DoubleField42);
-      }
-      if (int64Field43_ != null) {
-        size += _single_int64Field43_codec.CalculateSizeWithTag(Int64Field43);
-      }
-      if (int64Field44_ != null) {
-        size += _single_int64Field44_codec.CalculateSizeWithTag(Int64Field44);
-      }
-      if (doubleField45_ != null) {
-        size += _single_doubleField45_codec.CalculateSizeWithTag(DoubleField45);
-      }
-      if (doubleField46_ != null) {
-        size += _single_doubleField46_codec.CalculateSizeWithTag(DoubleField46);
-      }
-      if (doubleField78_ != null) {
-        size += _single_doubleField78_codec.CalculateSizeWithTag(DoubleField78);
-      }
-      if (doubleField88_ != null) {
-        size += _single_doubleField88_codec.CalculateSizeWithTag(DoubleField88);
-      }
-      if (doubleField47_ != null) {
-        size += _single_doubleField47_codec.CalculateSizeWithTag(DoubleField47);
-      }
-      if (doubleField89_ != null) {
-        size += _single_doubleField89_codec.CalculateSizeWithTag(DoubleField89);
-      }
-      if (doubleField48_ != null) {
-        size += _single_doubleField48_codec.CalculateSizeWithTag(DoubleField48);
-      }
-      if (doubleField49_ != null) {
-        size += _single_doubleField49_codec.CalculateSizeWithTag(DoubleField49);
-      }
-      if (doubleField50_ != null) {
-        size += _single_doubleField50_codec.CalculateSizeWithTag(DoubleField50);
-      }
-      if (doubleField90_ != null) {
-        size += _single_doubleField90_codec.CalculateSizeWithTag(DoubleField90);
-      }
-      if (doubleField51_ != null) {
-        size += _single_doubleField51_codec.CalculateSizeWithTag(DoubleField51);
-      }
-      if (doubleField91_ != null) {
-        size += _single_doubleField91_codec.CalculateSizeWithTag(DoubleField91);
-      }
-      if (doubleField92_ != null) {
-        size += _single_doubleField92_codec.CalculateSizeWithTag(DoubleField92);
-      }
-      if (int64Field107_ != null) {
-        size += _single_int64Field107_codec.CalculateSizeWithTag(Int64Field107);
-      }
-      if (doubleField93_ != null) {
-        size += _single_doubleField93_codec.CalculateSizeWithTag(DoubleField93);
-      }
-      if (doubleField108_ != null) {
-        size += _single_doubleField108_codec.CalculateSizeWithTag(DoubleField108);
-      }
-      if (doubleField52_ != null) {
-        size += _single_doubleField52_codec.CalculateSizeWithTag(DoubleField52);
-      }
-      if (doubleField53_ != null) {
-        size += _single_doubleField53_codec.CalculateSizeWithTag(DoubleField53);
-      }
-      if (doubleField94_ != null) {
-        size += _single_doubleField94_codec.CalculateSizeWithTag(DoubleField94);
-      }
-      if (doubleField54_ != null) {
-        size += _single_doubleField54_codec.CalculateSizeWithTag(DoubleField54);
-      }
-      if (doubleField55_ != null) {
-        size += _single_doubleField55_codec.CalculateSizeWithTag(DoubleField55);
-      }
-      if (doubleField56_ != null) {
-        size += _single_doubleField56_codec.CalculateSizeWithTag(DoubleField56);
-      }
-      if (doubleField57_ != null) {
-        size += _single_doubleField57_codec.CalculateSizeWithTag(DoubleField57);
-      }
-      if (doubleField58_ != null) {
-        size += _single_doubleField58_codec.CalculateSizeWithTag(DoubleField58);
-      }
-      if (int64Field59_ != null) {
-        size += _single_int64Field59_codec.CalculateSizeWithTag(Int64Field59);
-      }
-      if (int64Field60_ != null) {
-        size += _single_int64Field60_codec.CalculateSizeWithTag(Int64Field60);
-      }
-      if (_unknownFields != null) {
-        size += _unknownFields.CalculateSize();
-      }
-      return size;
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public void MergeFrom(ManyWrapperFieldsMessage other) {
-      if (other == null) {
-        return;
-      }
-      if (other.doubleField95_ != null) {
-        if (doubleField95_ == null || other.DoubleField95 != 0D) {
-          DoubleField95 = other.DoubleField95;
-        }
-      }
-      if (other.doubleField1_ != null) {
-        if (doubleField1_ == null || other.DoubleField1 != 0D) {
-          DoubleField1 = other.DoubleField1;
-        }
-      }
-      if (other.doubleField79_ != null) {
-        if (doubleField79_ == null || other.DoubleField79 != 0D) {
-          DoubleField79 = other.DoubleField79;
-        }
-      }
-      if (other.int64Field2_ != null) {
-        if (int64Field2_ == null || other.Int64Field2 != 0L) {
-          Int64Field2 = other.Int64Field2;
-        }
-      }
-      if (other.doubleField96_ != null) {
-        if (doubleField96_ == null || other.DoubleField96 != 0D) {
-          DoubleField96 = other.DoubleField96;
-        }
-      }
-      if (other.int64Field3_ != null) {
-        if (int64Field3_ == null || other.Int64Field3 != 0L) {
-          Int64Field3 = other.Int64Field3;
-        }
-      }
-      if (other.int64Field4_ != null) {
-        if (int64Field4_ == null || other.Int64Field4 != 0L) {
-          Int64Field4 = other.Int64Field4;
-        }
-      }
-      if (other.doubleField97_ != null) {
-        if (doubleField97_ == null || other.DoubleField97 != 0D) {
-          DoubleField97 = other.DoubleField97;
-        }
-      }
-      if (other.doubleField65_ != null) {
-        if (doubleField65_ == null || other.DoubleField65 != 0D) {
-          DoubleField65 = other.DoubleField65;
-        }
-      }
-      if (other.doubleField66_ != null) {
-        if (doubleField66_ == null || other.DoubleField66 != 0D) {
-          DoubleField66 = other.DoubleField66;
-        }
-      }
-      if (other.doubleField7_ != null) {
-        if (doubleField7_ == null || other.DoubleField7 != 0D) {
-          DoubleField7 = other.DoubleField7;
-        }
-      }
-      if (other.doubleField62_ != null) {
-        if (doubleField62_ == null || other.DoubleField62 != 0D) {
-          DoubleField62 = other.DoubleField62;
-        }
-      }
-      if (other.doubleField118_ != null) {
-        if (doubleField118_ == null || other.DoubleField118 != 0D) {
-          DoubleField118 = other.DoubleField118;
-        }
-      }
-      if (other.doubleField119_ != null) {
-        if (doubleField119_ == null || other.DoubleField119 != 0D) {
-          DoubleField119 = other.DoubleField119;
-        }
-      }
-      if (other.doubleField67_ != null) {
-        if (doubleField67_ == null || other.DoubleField67 != 0D) {
-          DoubleField67 = other.DoubleField67;
-        }
-      }
-      if (other.doubleField120_ != null) {
-        if (doubleField120_ == null || other.DoubleField120 != 0D) {
-          DoubleField120 = other.DoubleField120;
-        }
-      }
-      if (other.doubleField121_ != null) {
-        if (doubleField121_ == null || other.DoubleField121 != 0D) {
-          DoubleField121 = other.DoubleField121;
-        }
-      }
-      if (other.doubleField122_ != null) {
-        if (doubleField122_ == null || other.DoubleField122 != 0D) {
-          DoubleField122 = other.DoubleField122;
-        }
-      }
-      if (other.doubleField123_ != null) {
-        if (doubleField123_ == null || other.DoubleField123 != 0D) {
-          DoubleField123 = other.DoubleField123;
-        }
-      }
-      if (other.doubleField124_ != null) {
-        if (doubleField124_ == null || other.DoubleField124 != 0D) {
-          DoubleField124 = other.DoubleField124;
-        }
-      }
-      if (other.doubleField8_ != null) {
-        if (doubleField8_ == null || other.DoubleField8 != 0D) {
-          DoubleField8 = other.DoubleField8;
-        }
-      }
-      if (other.doubleField9_ != null) {
-        if (doubleField9_ == null || other.DoubleField9 != 0D) {
-          DoubleField9 = other.DoubleField9;
-        }
-      }
-      if (other.doubleField98_ != null) {
-        if (doubleField98_ == null || other.DoubleField98 != 0D) {
-          DoubleField98 = other.DoubleField98;
-        }
-      }
-      if (other.doubleField10_ != null) {
-        if (doubleField10_ == null || other.DoubleField10 != 0D) {
-          DoubleField10 = other.DoubleField10;
-        }
-      }
-      if (other.doubleField11_ != null) {
-        if (doubleField11_ == null || other.DoubleField11 != 0D) {
-          DoubleField11 = other.DoubleField11;
-        }
-      }
-      if (other.doubleField99_ != null) {
-        if (doubleField99_ == null || other.DoubleField99 != 0D) {
-          DoubleField99 = other.DoubleField99;
-        }
-      }
-      if (other.doubleField84_ != null) {
-        if (doubleField84_ == null || other.DoubleField84 != 0D) {
-          DoubleField84 = other.DoubleField84;
-        }
-      }
-      if (other.doubleField14_ != null) {
-        if (doubleField14_ == null || other.DoubleField14 != 0D) {
-          DoubleField14 = other.DoubleField14;
-        }
-      }
-      if (other.doubleField77_ != null) {
-        if (doubleField77_ == null || other.DoubleField77 != 0D) {
-          DoubleField77 = other.DoubleField77;
-        }
-      }
-      if (other.doubleField15_ != null) {
-        if (doubleField15_ == null || other.DoubleField15 != 0D) {
-          DoubleField15 = other.DoubleField15;
-        }
-      }
-      if (other.int64Field19_ != null) {
-        if (int64Field19_ == null || other.Int64Field19 != 0L) {
-          Int64Field19 = other.Int64Field19;
-        }
-      }
-      if (other.int64Field115_ != null) {
-        if (int64Field115_ == null || other.Int64Field115 != 0L) {
-          Int64Field115 = other.Int64Field115;
-        }
-      }
-      if (other.doubleField116_ != null) {
-        if (doubleField116_ == null || other.DoubleField116 != 0D) {
-          DoubleField116 = other.DoubleField116;
-        }
-      }
-      if (other.int64Field117_ != null) {
-        if (int64Field117_ == null || other.Int64Field117 != 0L) {
-          Int64Field117 = other.Int64Field117;
-        }
-      }
-      if (other.doubleField20_ != null) {
-        if (doubleField20_ == null || other.DoubleField20 != 0D) {
-          DoubleField20 = other.DoubleField20;
-        }
-      }
-      if (other.doubleField21_ != null) {
-        if (doubleField21_ == null || other.DoubleField21 != 0D) {
-          DoubleField21 = other.DoubleField21;
-        }
-      }
-      if (other.stringField73_ != null) {
-        if (stringField73_ == null || other.StringField73 != "") {
-          StringField73 = other.StringField73;
-        }
-      }
-      if (other.stringField74_ != null) {
-        if (stringField74_ == null || other.StringField74 != "") {
-          StringField74 = other.StringField74;
-        }
-      }
-      if (other.doubleField22_ != null) {
-        if (doubleField22_ == null || other.DoubleField22 != 0D) {
-          DoubleField22 = other.DoubleField22;
-        }
-      }
-      if (other.doubleField69_ != null) {
-        if (doubleField69_ == null || other.DoubleField69 != 0D) {
-          DoubleField69 = other.DoubleField69;
-        }
-      }
-      if (other.doubleField70_ != null) {
-        if (doubleField70_ == null || other.DoubleField70 != 0D) {
-          DoubleField70 = other.DoubleField70;
-        }
-      }
-      if (other.doubleField71_ != null) {
-        if (doubleField71_ == null || other.DoubleField71 != 0D) {
-          DoubleField71 = other.DoubleField71;
-        }
-      }
-      if (other.doubleField72_ != null) {
-        if (doubleField72_ == null || other.DoubleField72 != 0D) {
-          DoubleField72 = other.DoubleField72;
-        }
-      }
-      if (other.doubleField25_ != null) {
-        if (doubleField25_ == null || other.DoubleField25 != 0D) {
-          DoubleField25 = other.DoubleField25;
-        }
-      }
-      if (other.int64Field26_ != null) {
-        if (int64Field26_ == null || other.Int64Field26 != 0L) {
-          Int64Field26 = other.Int64Field26;
-        }
-      }
-      if (other.doubleField68_ != null) {
-        if (doubleField68_ == null || other.DoubleField68 != 0D) {
-          DoubleField68 = other.DoubleField68;
-        }
-      }
-      if (other.doubleField28_ != null) {
-        if (doubleField28_ == null || other.DoubleField28 != 0D) {
-          DoubleField28 = other.DoubleField28;
-        }
-      }
-      if (other.doubleField106_ != null) {
-        if (doubleField106_ == null || other.DoubleField106 != 0D) {
-          DoubleField106 = other.DoubleField106;
-        }
-      }
-      if (other.doubleField29_ != null) {
-        if (doubleField29_ == null || other.DoubleField29 != 0D) {
-          DoubleField29 = other.DoubleField29;
-        }
-      }
-      if (other.doubleField30_ != null) {
-        if (doubleField30_ == null || other.DoubleField30 != 0D) {
-          DoubleField30 = other.DoubleField30;
-        }
-      }
-      if (other.doubleField101_ != null) {
-        if (doubleField101_ == null || other.DoubleField101 != 0D) {
-          DoubleField101 = other.DoubleField101;
-        }
-      }
-      if (other.doubleField102_ != null) {
-        if (doubleField102_ == null || other.DoubleField102 != 0D) {
-          DoubleField102 = other.DoubleField102;
-        }
-      }
-      if (other.doubleField103_ != null) {
-        if (doubleField103_ == null || other.DoubleField103 != 0D) {
-          DoubleField103 = other.DoubleField103;
-        }
-      }
-      if (other.doubleField104_ != null) {
-        if (doubleField104_ == null || other.DoubleField104 != 0D) {
-          DoubleField104 = other.DoubleField104;
-        }
-      }
-      if (other.doubleField105_ != null) {
-        if (doubleField105_ == null || other.DoubleField105 != 0D) {
-          DoubleField105 = other.DoubleField105;
-        }
-      }
-      if (other.doubleField31_ != null) {
-        if (doubleField31_ == null || other.DoubleField31 != 0D) {
-          DoubleField31 = other.DoubleField31;
-        }
-      }
-      if (other.int64Field32_ != null) {
-        if (int64Field32_ == null || other.Int64Field32 != 0L) {
-          Int64Field32 = other.Int64Field32;
-        }
-      }
-      if (other.doubleField75_ != null) {
-        if (doubleField75_ == null || other.DoubleField75 != 0D) {
-          DoubleField75 = other.DoubleField75;
-        }
-      }
-      if (other.doubleField129_ != null) {
-        if (doubleField129_ == null || other.DoubleField129 != 0D) {
-          DoubleField129 = other.DoubleField129;
-        }
-      }
-      if (other.EnumField80 != 0) {
-        EnumField80 = other.EnumField80;
-      }
-      if (other.EnumField81 != 0) {
-        EnumField81 = other.EnumField81;
-      }
-      if (other.int64Field82_ != null) {
-        if (int64Field82_ == null || other.Int64Field82 != 0L) {
-          Int64Field82 = other.Int64Field82;
-        }
-      }
-      if (other.EnumField83 != 0) {
-        EnumField83 = other.EnumField83;
-      }
-      if (other.int64Field85_ != null) {
-        if (int64Field85_ == null || other.Int64Field85 != 0L) {
-          Int64Field85 = other.Int64Field85;
-        }
-      }
-      if (other.int64Field86_ != null) {
-        if (int64Field86_ == null || other.Int64Field86 != 0L) {
-          Int64Field86 = other.Int64Field86;
-        }
-      }
-      if (other.int64Field87_ != null) {
-        if (int64Field87_ == null || other.Int64Field87 != 0L) {
-          Int64Field87 = other.Int64Field87;
-        }
-      }
-      if (other.int64Field125_ != null) {
-        if (int64Field125_ == null || other.Int64Field125 != 0L) {
-          Int64Field125 = other.Int64Field125;
-        }
-      }
-      if (other.int64Field37_ != null) {
-        if (int64Field37_ == null || other.Int64Field37 != 0L) {
-          Int64Field37 = other.Int64Field37;
-        }
-      }
-      if (other.doubleField38_ != null) {
-        if (doubleField38_ == null || other.DoubleField38 != 0D) {
-          DoubleField38 = other.DoubleField38;
-        }
-      }
-      if (other.interactions_ != null) {
-        if (interactions_ == null || other.Interactions != 0L) {
-          Interactions = other.Interactions;
-        }
-      }
-      repeatedIntField100_.Add(other.repeatedIntField100_);
-      if (other.doubleField40_ != null) {
-        if (doubleField40_ == null || other.DoubleField40 != 0D) {
-          DoubleField40 = other.DoubleField40;
-        }
-      }
-      if (other.int64Field41_ != null) {
-        if (int64Field41_ == null || other.Int64Field41 != 0L) {
-          Int64Field41 = other.Int64Field41;
-        }
-      }
-      if (other.int64Field126_ != null) {
-        if (int64Field126_ == null || other.Int64Field126 != 0L) {
-          Int64Field126 = other.Int64Field126;
-        }
-      }
-      if (other.int64Field127_ != null) {
-        if (int64Field127_ == null || other.Int64Field127 != 0L) {
-          Int64Field127 = other.Int64Field127;
-        }
-      }
-      if (other.doubleField128_ != null) {
-        if (doubleField128_ == null || other.DoubleField128 != 0D) {
-          DoubleField128 = other.DoubleField128;
-        }
-      }
-      if (other.doubleField109_ != null) {
-        if (doubleField109_ == null || other.DoubleField109 != 0D) {
-          DoubleField109 = other.DoubleField109;
-        }
-      }
-      if (other.int64Field110_ != null) {
-        if (int64Field110_ == null || other.Int64Field110 != 0L) {
-          Int64Field110 = other.Int64Field110;
-        }
-      }
-      if (other.doubleField111_ != null) {
-        if (doubleField111_ == null || other.DoubleField111 != 0D) {
-          DoubleField111 = other.DoubleField111;
-        }
-      }
-      if (other.int64Field112_ != null) {
-        if (int64Field112_ == null || other.Int64Field112 != 0L) {
-          Int64Field112 = other.Int64Field112;
-        }
-      }
-      if (other.doubleField113_ != null) {
-        if (doubleField113_ == null || other.DoubleField113 != 0D) {
-          DoubleField113 = other.DoubleField113;
-        }
-      }
-      if (other.int64Field114_ != null) {
-        if (int64Field114_ == null || other.Int64Field114 != 0L) {
-          Int64Field114 = other.Int64Field114;
-        }
-      }
-      if (other.doubleField42_ != null) {
-        if (doubleField42_ == null || other.DoubleField42 != 0D) {
-          DoubleField42 = other.DoubleField42;
-        }
-      }
-      if (other.int64Field43_ != null) {
-        if (int64Field43_ == null || other.Int64Field43 != 0L) {
-          Int64Field43 = other.Int64Field43;
-        }
-      }
-      if (other.int64Field44_ != null) {
-        if (int64Field44_ == null || other.Int64Field44 != 0L) {
-          Int64Field44 = other.Int64Field44;
-        }
-      }
-      if (other.doubleField45_ != null) {
-        if (doubleField45_ == null || other.DoubleField45 != 0D) {
-          DoubleField45 = other.DoubleField45;
-        }
-      }
-      if (other.doubleField46_ != null) {
-        if (doubleField46_ == null || other.DoubleField46 != 0D) {
-          DoubleField46 = other.DoubleField46;
-        }
-      }
-      if (other.doubleField78_ != null) {
-        if (doubleField78_ == null || other.DoubleField78 != 0D) {
-          DoubleField78 = other.DoubleField78;
-        }
-      }
-      if (other.doubleField88_ != null) {
-        if (doubleField88_ == null || other.DoubleField88 != 0D) {
-          DoubleField88 = other.DoubleField88;
-        }
-      }
-      if (other.doubleField47_ != null) {
-        if (doubleField47_ == null || other.DoubleField47 != 0D) {
-          DoubleField47 = other.DoubleField47;
-        }
-      }
-      if (other.doubleField89_ != null) {
-        if (doubleField89_ == null || other.DoubleField89 != 0D) {
-          DoubleField89 = other.DoubleField89;
-        }
-      }
-      if (other.doubleField48_ != null) {
-        if (doubleField48_ == null || other.DoubleField48 != 0D) {
-          DoubleField48 = other.DoubleField48;
-        }
-      }
-      if (other.doubleField49_ != null) {
-        if (doubleField49_ == null || other.DoubleField49 != 0D) {
-          DoubleField49 = other.DoubleField49;
-        }
-      }
-      if (other.doubleField50_ != null) {
-        if (doubleField50_ == null || other.DoubleField50 != 0D) {
-          DoubleField50 = other.DoubleField50;
-        }
-      }
-      if (other.doubleField90_ != null) {
-        if (doubleField90_ == null || other.DoubleField90 != 0D) {
-          DoubleField90 = other.DoubleField90;
-        }
-      }
-      if (other.doubleField51_ != null) {
-        if (doubleField51_ == null || other.DoubleField51 != 0D) {
-          DoubleField51 = other.DoubleField51;
-        }
-      }
-      if (other.doubleField91_ != null) {
-        if (doubleField91_ == null || other.DoubleField91 != 0D) {
-          DoubleField91 = other.DoubleField91;
-        }
-      }
-      if (other.doubleField92_ != null) {
-        if (doubleField92_ == null || other.DoubleField92 != 0D) {
-          DoubleField92 = other.DoubleField92;
-        }
-      }
-      if (other.int64Field107_ != null) {
-        if (int64Field107_ == null || other.Int64Field107 != 0L) {
-          Int64Field107 = other.Int64Field107;
-        }
-      }
-      if (other.doubleField93_ != null) {
-        if (doubleField93_ == null || other.DoubleField93 != 0D) {
-          DoubleField93 = other.DoubleField93;
-        }
-      }
-      if (other.doubleField108_ != null) {
-        if (doubleField108_ == null || other.DoubleField108 != 0D) {
-          DoubleField108 = other.DoubleField108;
-        }
-      }
-      if (other.doubleField52_ != null) {
-        if (doubleField52_ == null || other.DoubleField52 != 0D) {
-          DoubleField52 = other.DoubleField52;
-        }
-      }
-      if (other.doubleField53_ != null) {
-        if (doubleField53_ == null || other.DoubleField53 != 0D) {
-          DoubleField53 = other.DoubleField53;
-        }
-      }
-      if (other.doubleField94_ != null) {
-        if (doubleField94_ == null || other.DoubleField94 != 0D) {
-          DoubleField94 = other.DoubleField94;
-        }
-      }
-      if (other.doubleField54_ != null) {
-        if (doubleField54_ == null || other.DoubleField54 != 0D) {
-          DoubleField54 = other.DoubleField54;
-        }
-      }
-      if (other.doubleField55_ != null) {
-        if (doubleField55_ == null || other.DoubleField55 != 0D) {
-          DoubleField55 = other.DoubleField55;
-        }
-      }
-      if (other.doubleField56_ != null) {
-        if (doubleField56_ == null || other.DoubleField56 != 0D) {
-          DoubleField56 = other.DoubleField56;
-        }
-      }
-      if (other.doubleField57_ != null) {
-        if (doubleField57_ == null || other.DoubleField57 != 0D) {
-          DoubleField57 = other.DoubleField57;
-        }
-      }
-      if (other.doubleField58_ != null) {
-        if (doubleField58_ == null || other.DoubleField58 != 0D) {
-          DoubleField58 = other.DoubleField58;
-        }
-      }
-      if (other.int64Field59_ != null) {
-        if (int64Field59_ == null || other.Int64Field59 != 0L) {
-          Int64Field59 = other.Int64Field59;
-        }
-      }
-      if (other.int64Field60_ != null) {
-        if (int64Field60_ == null || other.Int64Field60 != 0L) {
-          Int64Field60 = other.Int64Field60;
-        }
-      }
-      _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: {
-            double? value = _single_doubleField1_codec.Read(input);
-            if (doubleField1_ == null || value != 0D) {
-              DoubleField1 = value;
-            }
-            break;
-          }
-          case 18: {
-            long? value = _single_int64Field2_codec.Read(input);
-            if (int64Field2_ == null || value != 0L) {
-              Int64Field2 = value;
-            }
-            break;
-          }
-          case 26: {
-            long? value = _single_int64Field3_codec.Read(input);
-            if (int64Field3_ == null || value != 0L) {
-              Int64Field3 = value;
-            }
-            break;
-          }
-          case 34: {
-            long? value = _single_int64Field4_codec.Read(input);
-            if (int64Field4_ == null || value != 0L) {
-              Int64Field4 = value;
-            }
-            break;
-          }
-          case 58: {
-            double? value = _single_doubleField7_codec.Read(input);
-            if (doubleField7_ == null || value != 0D) {
-              DoubleField7 = value;
-            }
-            break;
-          }
-          case 66: {
-            double? value = _single_doubleField8_codec.Read(input);
-            if (doubleField8_ == null || value != 0D) {
-              DoubleField8 = value;
-            }
-            break;
-          }
-          case 74: {
-            double? value = _single_doubleField9_codec.Read(input);
-            if (doubleField9_ == null || value != 0D) {
-              DoubleField9 = value;
-            }
-            break;
-          }
-          case 82: {
-            double? value = _single_doubleField10_codec.Read(input);
-            if (doubleField10_ == null || value != 0D) {
-              DoubleField10 = value;
-            }
-            break;
-          }
-          case 90: {
-            double? value = _single_doubleField11_codec.Read(input);
-            if (doubleField11_ == null || value != 0D) {
-              DoubleField11 = value;
-            }
-            break;
-          }
-          case 114: {
-            double? value = _single_doubleField14_codec.Read(input);
-            if (doubleField14_ == null || value != 0D) {
-              DoubleField14 = value;
-            }
-            break;
-          }
-          case 122: {
-            double? value = _single_doubleField15_codec.Read(input);
-            if (doubleField15_ == null || value != 0D) {
-              DoubleField15 = value;
-            }
-            break;
-          }
-          case 154: {
-            long? value = _single_int64Field19_codec.Read(input);
-            if (int64Field19_ == null || value != 0L) {
-              Int64Field19 = value;
-            }
-            break;
-          }
-          case 162: {
-            double? value = _single_doubleField20_codec.Read(input);
-            if (doubleField20_ == null || value != 0D) {
-              DoubleField20 = value;
-            }
-            break;
-          }
-          case 170: {
-            double? value = _single_doubleField21_codec.Read(input);
-            if (doubleField21_ == null || value != 0D) {
-              DoubleField21 = value;
-            }
-            break;
-          }
-          case 178: {
-            double? value = _single_doubleField22_codec.Read(input);
-            if (doubleField22_ == null || value != 0D) {
-              DoubleField22 = value;
-            }
-            break;
-          }
-          case 202: {
-            double? value = _single_doubleField25_codec.Read(input);
-            if (doubleField25_ == null || value != 0D) {
-              DoubleField25 = value;
-            }
-            break;
-          }
-          case 210: {
-            long? value = _single_int64Field26_codec.Read(input);
-            if (int64Field26_ == null || value != 0L) {
-              Int64Field26 = value;
-            }
-            break;
-          }
-          case 226: {
-            double? value = _single_doubleField28_codec.Read(input);
-            if (doubleField28_ == null || value != 0D) {
-              DoubleField28 = value;
-            }
-            break;
-          }
-          case 234: {
-            double? value = _single_doubleField29_codec.Read(input);
-            if (doubleField29_ == null || value != 0D) {
-              DoubleField29 = value;
-            }
-            break;
-          }
-          case 242: {
-            double? value = _single_doubleField30_codec.Read(input);
-            if (doubleField30_ == null || value != 0D) {
-              DoubleField30 = value;
-            }
-            break;
-          }
-          case 250: {
-            double? value = _single_doubleField31_codec.Read(input);
-            if (doubleField31_ == null || value != 0D) {
-              DoubleField31 = value;
-            }
-            break;
-          }
-          case 258: {
-            long? value = _single_int64Field32_codec.Read(input);
-            if (int64Field32_ == null || value != 0L) {
-              Int64Field32 = value;
-            }
-            break;
-          }
-          case 298: {
-            long? value = _single_int64Field37_codec.Read(input);
-            if (int64Field37_ == null || value != 0L) {
-              Int64Field37 = value;
-            }
-            break;
-          }
-          case 306: {
-            double? value = _single_doubleField38_codec.Read(input);
-            if (doubleField38_ == null || value != 0D) {
-              DoubleField38 = value;
-            }
-            break;
-          }
-          case 314: {
-            long? value = _single_interactions_codec.Read(input);
-            if (interactions_ == null || value != 0L) {
-              Interactions = value;
-            }
-            break;
-          }
-          case 322: {
-            double? value = _single_doubleField40_codec.Read(input);
-            if (doubleField40_ == null || value != 0D) {
-              DoubleField40 = value;
-            }
-            break;
-          }
-          case 330: {
-            long? value = _single_int64Field41_codec.Read(input);
-            if (int64Field41_ == null || value != 0L) {
-              Int64Field41 = value;
-            }
-            break;
-          }
-          case 338: {
-            double? value = _single_doubleField42_codec.Read(input);
-            if (doubleField42_ == null || value != 0D) {
-              DoubleField42 = value;
-            }
-            break;
-          }
-          case 346: {
-            long? value = _single_int64Field43_codec.Read(input);
-            if (int64Field43_ == null || value != 0L) {
-              Int64Field43 = value;
-            }
-            break;
-          }
-          case 354: {
-            long? value = _single_int64Field44_codec.Read(input);
-            if (int64Field44_ == null || value != 0L) {
-              Int64Field44 = value;
-            }
-            break;
-          }
-          case 362: {
-            double? value = _single_doubleField45_codec.Read(input);
-            if (doubleField45_ == null || value != 0D) {
-              DoubleField45 = value;
-            }
-            break;
-          }
-          case 370: {
-            double? value = _single_doubleField46_codec.Read(input);
-            if (doubleField46_ == null || value != 0D) {
-              DoubleField46 = value;
-            }
-            break;
-          }
-          case 378: {
-            double? value = _single_doubleField47_codec.Read(input);
-            if (doubleField47_ == null || value != 0D) {
-              DoubleField47 = value;
-            }
-            break;
-          }
-          case 386: {
-            double? value = _single_doubleField48_codec.Read(input);
-            if (doubleField48_ == null || value != 0D) {
-              DoubleField48 = value;
-            }
-            break;
-          }
-          case 394: {
-            double? value = _single_doubleField49_codec.Read(input);
-            if (doubleField49_ == null || value != 0D) {
-              DoubleField49 = value;
-            }
-            break;
-          }
-          case 402: {
-            double? value = _single_doubleField50_codec.Read(input);
-            if (doubleField50_ == null || value != 0D) {
-              DoubleField50 = value;
-            }
-            break;
-          }
-          case 410: {
-            double? value = _single_doubleField51_codec.Read(input);
-            if (doubleField51_ == null || value != 0D) {
-              DoubleField51 = value;
-            }
-            break;
-          }
-          case 418: {
-            double? value = _single_doubleField52_codec.Read(input);
-            if (doubleField52_ == null || value != 0D) {
-              DoubleField52 = value;
-            }
-            break;
-          }
-          case 426: {
-            double? value = _single_doubleField53_codec.Read(input);
-            if (doubleField53_ == null || value != 0D) {
-              DoubleField53 = value;
-            }
-            break;
-          }
-          case 434: {
-            double? value = _single_doubleField54_codec.Read(input);
-            if (doubleField54_ == null || value != 0D) {
-              DoubleField54 = value;
-            }
-            break;
-          }
-          case 442: {
-            double? value = _single_doubleField55_codec.Read(input);
-            if (doubleField55_ == null || value != 0D) {
-              DoubleField55 = value;
-            }
-            break;
-          }
-          case 450: {
-            double? value = _single_doubleField56_codec.Read(input);
-            if (doubleField56_ == null || value != 0D) {
-              DoubleField56 = value;
-            }
-            break;
-          }
-          case 458: {
-            double? value = _single_doubleField57_codec.Read(input);
-            if (doubleField57_ == null || value != 0D) {
-              DoubleField57 = value;
-            }
-            break;
-          }
-          case 466: {
-            double? value = _single_doubleField58_codec.Read(input);
-            if (doubleField58_ == null || value != 0D) {
-              DoubleField58 = value;
-            }
-            break;
-          }
-          case 474: {
-            long? value = _single_int64Field59_codec.Read(input);
-            if (int64Field59_ == null || value != 0L) {
-              Int64Field59 = value;
-            }
-            break;
-          }
-          case 482: {
-            long? value = _single_int64Field60_codec.Read(input);
-            if (int64Field60_ == null || value != 0L) {
-              Int64Field60 = value;
-            }
-            break;
-          }
-          case 498: {
-            double? value = _single_doubleField62_codec.Read(input);
-            if (doubleField62_ == null || value != 0D) {
-              DoubleField62 = value;
-            }
-            break;
-          }
-          case 522: {
-            double? value = _single_doubleField65_codec.Read(input);
-            if (doubleField65_ == null || value != 0D) {
-              DoubleField65 = value;
-            }
-            break;
-          }
-          case 530: {
-            double? value = _single_doubleField66_codec.Read(input);
-            if (doubleField66_ == null || value != 0D) {
-              DoubleField66 = value;
-            }
-            break;
-          }
-          case 538: {
-            double? value = _single_doubleField67_codec.Read(input);
-            if (doubleField67_ == null || value != 0D) {
-              DoubleField67 = value;
-            }
-            break;
-          }
-          case 546: {
-            double? value = _single_doubleField68_codec.Read(input);
-            if (doubleField68_ == null || value != 0D) {
-              DoubleField68 = value;
-            }
-            break;
-          }
-          case 554: {
-            double? value = _single_doubleField69_codec.Read(input);
-            if (doubleField69_ == null || value != 0D) {
-              DoubleField69 = value;
-            }
-            break;
-          }
-          case 562: {
-            double? value = _single_doubleField70_codec.Read(input);
-            if (doubleField70_ == null || value != 0D) {
-              DoubleField70 = value;
-            }
-            break;
-          }
-          case 570: {
-            double? value = _single_doubleField71_codec.Read(input);
-            if (doubleField71_ == null || value != 0D) {
-              DoubleField71 = value;
-            }
-            break;
-          }
-          case 578: {
-            double? value = _single_doubleField72_codec.Read(input);
-            if (doubleField72_ == null || value != 0D) {
-              DoubleField72 = value;
-            }
-            break;
-          }
-          case 586: {
-            string value = _single_stringField73_codec.Read(input);
-            if (stringField73_ == null || value != "") {
-              StringField73 = value;
-            }
-            break;
-          }
-          case 594: {
-            string value = _single_stringField74_codec.Read(input);
-            if (stringField74_ == null || value != "") {
-              StringField74 = value;
-            }
-            break;
-          }
-          case 602: {
-            double? value = _single_doubleField75_codec.Read(input);
-            if (doubleField75_ == null || value != 0D) {
-              DoubleField75 = value;
-            }
-            break;
-          }
-          case 618: {
-            double? value = _single_doubleField77_codec.Read(input);
-            if (doubleField77_ == null || value != 0D) {
-              DoubleField77 = value;
-            }
-            break;
-          }
-          case 626: {
-            double? value = _single_doubleField78_codec.Read(input);
-            if (doubleField78_ == null || value != 0D) {
-              DoubleField78 = value;
-            }
-            break;
-          }
-          case 634: {
-            double? value = _single_doubleField79_codec.Read(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(input);
-            if (int64Field82_ == null || value != 0L) {
-              Int64Field82 = value;
-            }
-            break;
-          }
-          case 664: {
-            EnumField83 = input.ReadInt32();
-            break;
-          }
-          case 674: {
-            double? value = _single_doubleField84_codec.Read(input);
-            if (doubleField84_ == null || value != 0D) {
-              DoubleField84 = value;
-            }
-            break;
-          }
-          case 682: {
-            long? value = _single_int64Field85_codec.Read(input);
-            if (int64Field85_ == null || value != 0L) {
-              Int64Field85 = value;
-            }
-            break;
-          }
-          case 690: {
-            long? value = _single_int64Field86_codec.Read(input);
-            if (int64Field86_ == null || value != 0L) {
-              Int64Field86 = value;
-            }
-            break;
-          }
-          case 698: {
-            long? value = _single_int64Field87_codec.Read(input);
-            if (int64Field87_ == null || value != 0L) {
-              Int64Field87 = value;
-            }
-            break;
-          }
-          case 706: {
-            double? value = _single_doubleField88_codec.Read(input);
-            if (doubleField88_ == null || value != 0D) {
-              DoubleField88 = value;
-            }
-            break;
-          }
-          case 714: {
-            double? value = _single_doubleField89_codec.Read(input);
-            if (doubleField89_ == null || value != 0D) {
-              DoubleField89 = value;
-            }
-            break;
-          }
-          case 722: {
-            double? value = _single_doubleField90_codec.Read(input);
-            if (doubleField90_ == null || value != 0D) {
-              DoubleField90 = value;
-            }
-            break;
-          }
-          case 730: {
-            double? value = _single_doubleField91_codec.Read(input);
-            if (doubleField91_ == null || value != 0D) {
-              DoubleField91 = value;
-            }
-            break;
-          }
-          case 738: {
-            double? value = _single_doubleField92_codec.Read(input);
-            if (doubleField92_ == null || value != 0D) {
-              DoubleField92 = value;
-            }
-            break;
-          }
-          case 746: {
-            double? value = _single_doubleField93_codec.Read(input);
-            if (doubleField93_ == null || value != 0D) {
-              DoubleField93 = value;
-            }
-            break;
-          }
-          case 754: {
-            double? value = _single_doubleField94_codec.Read(input);
-            if (doubleField94_ == null || value != 0D) {
-              DoubleField94 = value;
-            }
-            break;
-          }
-          case 762: {
-            double? value = _single_doubleField95_codec.Read(input);
-            if (doubleField95_ == null || value != 0D) {
-              DoubleField95 = value;
-            }
-            break;
-          }
-          case 770: {
-            double? value = _single_doubleField96_codec.Read(input);
-            if (doubleField96_ == null || value != 0D) {
-              DoubleField96 = value;
-            }
-            break;
-          }
-          case 778: {
-            double? value = _single_doubleField97_codec.Read(input);
-            if (doubleField97_ == null || value != 0D) {
-              DoubleField97 = value;
-            }
-            break;
-          }
-          case 786: {
-            double? value = _single_doubleField98_codec.Read(input);
-            if (doubleField98_ == null || value != 0D) {
-              DoubleField98 = value;
-            }
-            break;
-          }
-          case 794: {
-            double? value = _single_doubleField99_codec.Read(input);
-            if (doubleField99_ == null || value != 0D) {
-              DoubleField99 = value;
-            }
-            break;
-          }
-          case 802:
-          case 800: {
-            repeatedIntField100_.AddEntriesFrom(input, _repeated_repeatedIntField100_codec);
-            break;
-          }
-          case 810: {
-            double? value = _single_doubleField101_codec.Read(input);
-            if (doubleField101_ == null || value != 0D) {
-              DoubleField101 = value;
-            }
-            break;
-          }
-          case 818: {
-            double? value = _single_doubleField102_codec.Read(input);
-            if (doubleField102_ == null || value != 0D) {
-              DoubleField102 = value;
-            }
-            break;
-          }
-          case 826: {
-            double? value = _single_doubleField103_codec.Read(input);
-            if (doubleField103_ == null || value != 0D) {
-              DoubleField103 = value;
-            }
-            break;
-          }
-          case 834: {
-            double? value = _single_doubleField104_codec.Read(input);
-            if (doubleField104_ == null || value != 0D) {
-              DoubleField104 = value;
-            }
-            break;
-          }
-          case 842: {
-            double? value = _single_doubleField105_codec.Read(input);
-            if (doubleField105_ == null || value != 0D) {
-              DoubleField105 = value;
-            }
-            break;
-          }
-          case 850: {
-            double? value = _single_doubleField106_codec.Read(input);
-            if (doubleField106_ == null || value != 0D) {
-              DoubleField106 = value;
-            }
-            break;
-          }
-          case 858: {
-            long? value = _single_int64Field107_codec.Read(input);
-            if (int64Field107_ == null || value != 0L) {
-              Int64Field107 = value;
-            }
-            break;
-          }
-          case 866: {
-            double? value = _single_doubleField108_codec.Read(input);
-            if (doubleField108_ == null || value != 0D) {
-              DoubleField108 = value;
-            }
-            break;
-          }
-          case 874: {
-            double? value = _single_doubleField109_codec.Read(input);
-            if (doubleField109_ == null || value != 0D) {
-              DoubleField109 = value;
-            }
-            break;
-          }
-          case 882: {
-            long? value = _single_int64Field110_codec.Read(input);
-            if (int64Field110_ == null || value != 0L) {
-              Int64Field110 = value;
-            }
-            break;
-          }
-          case 890: {
-            double? value = _single_doubleField111_codec.Read(input);
-            if (doubleField111_ == null || value != 0D) {
-              DoubleField111 = value;
-            }
-            break;
-          }
-          case 898: {
-            long? value = _single_int64Field112_codec.Read(input);
-            if (int64Field112_ == null || value != 0L) {
-              Int64Field112 = value;
-            }
-            break;
-          }
-          case 906: {
-            double? value = _single_doubleField113_codec.Read(input);
-            if (doubleField113_ == null || value != 0D) {
-              DoubleField113 = value;
-            }
-            break;
-          }
-          case 914: {
-            long? value = _single_int64Field114_codec.Read(input);
-            if (int64Field114_ == null || value != 0L) {
-              Int64Field114 = value;
-            }
-            break;
-          }
-          case 922: {
-            long? value = _single_int64Field115_codec.Read(input);
-            if (int64Field115_ == null || value != 0L) {
-              Int64Field115 = value;
-            }
-            break;
-          }
-          case 930: {
-            double? value = _single_doubleField116_codec.Read(input);
-            if (doubleField116_ == null || value != 0D) {
-              DoubleField116 = value;
-            }
-            break;
-          }
-          case 938: {
-            long? value = _single_int64Field117_codec.Read(input);
-            if (int64Field117_ == null || value != 0L) {
-              Int64Field117 = value;
-            }
-            break;
-          }
-          case 946: {
-            double? value = _single_doubleField118_codec.Read(input);
-            if (doubleField118_ == null || value != 0D) {
-              DoubleField118 = value;
-            }
-            break;
-          }
-          case 954: {
-            double? value = _single_doubleField119_codec.Read(input);
-            if (doubleField119_ == null || value != 0D) {
-              DoubleField119 = value;
-            }
-            break;
-          }
-          case 962: {
-            double? value = _single_doubleField120_codec.Read(input);
-            if (doubleField120_ == null || value != 0D) {
-              DoubleField120 = value;
-            }
-            break;
-          }
-          case 970: {
-            double? value = _single_doubleField121_codec.Read(input);
-            if (doubleField121_ == null || value != 0D) {
-              DoubleField121 = value;
-            }
-            break;
-          }
-          case 978: {
-            double? value = _single_doubleField122_codec.Read(input);
-            if (doubleField122_ == null || value != 0D) {
-              DoubleField122 = value;
-            }
-            break;
-          }
-          case 986: {
-            double? value = _single_doubleField123_codec.Read(input);
-            if (doubleField123_ == null || value != 0D) {
-              DoubleField123 = value;
-            }
-            break;
-          }
-          case 994: {
-            double? value = _single_doubleField124_codec.Read(input);
-            if (doubleField124_ == null || value != 0D) {
-              DoubleField124 = value;
-            }
-            break;
-          }
-          case 1002: {
-            long? value = _single_int64Field125_codec.Read(input);
-            if (int64Field125_ == null || value != 0L) {
-              Int64Field125 = value;
-            }
-            break;
-          }
-          case 1010: {
-            long? value = _single_int64Field126_codec.Read(input);
-            if (int64Field126_ == null || value != 0L) {
-              Int64Field126 = value;
-            }
-            break;
-          }
-          case 1018: {
-            long? value = _single_int64Field127_codec.Read(input);
-            if (int64Field127_ == null || value != 0L) {
-              Int64Field127 = value;
-            }
-            break;
-          }
-          case 1026: {
-            double? value = _single_doubleField128_codec.Read(input);
-            if (doubleField128_ == null || value != 0D) {
-              DoubleField128 = value;
-            }
-            break;
-          }
-          case 1034: {
-            double? value = _single_doubleField129_codec.Read(input);
-            if (doubleField129_ == null || value != 0D) {
-              DoubleField129 = value;
-            }
-            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: {
-            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>
-  #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();
-    }
-
-    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_;
-      doubleField79_ = other.doubleField79_;
-      int64Field2_ = other.int64Field2_;
-      doubleField96_ = other.doubleField96_;
-      int64Field3_ = other.int64Field3_;
-      int64Field4_ = other.int64Field4_;
-      doubleField97_ = other.doubleField97_;
-      doubleField65_ = other.doubleField65_;
-      doubleField66_ = other.doubleField66_;
-      doubleField7_ = other.doubleField7_;
-      doubleField62_ = other.doubleField62_;
-      doubleField118_ = other.doubleField118_;
-      doubleField119_ = other.doubleField119_;
-      doubleField67_ = other.doubleField67_;
-      doubleField120_ = other.doubleField120_;
-      doubleField121_ = other.doubleField121_;
-      doubleField122_ = other.doubleField122_;
-      doubleField123_ = other.doubleField123_;
-      doubleField124_ = other.doubleField124_;
-      doubleField8_ = other.doubleField8_;
-      doubleField9_ = other.doubleField9_;
-      doubleField98_ = other.doubleField98_;
-      doubleField10_ = other.doubleField10_;
-      doubleField11_ = other.doubleField11_;
-      doubleField99_ = other.doubleField99_;
-      doubleField84_ = other.doubleField84_;
-      doubleField14_ = other.doubleField14_;
-      doubleField77_ = other.doubleField77_;
-      doubleField15_ = other.doubleField15_;
-      int64Field19_ = other.int64Field19_;
-      int64Field115_ = other.int64Field115_;
-      doubleField116_ = other.doubleField116_;
-      int64Field117_ = other.int64Field117_;
-      doubleField20_ = other.doubleField20_;
-      doubleField21_ = other.doubleField21_;
-      stringField73_ = other.stringField73_;
-      stringField74_ = other.stringField74_;
-      doubleField22_ = other.doubleField22_;
-      doubleField69_ = other.doubleField69_;
-      doubleField70_ = other.doubleField70_;
-      doubleField71_ = other.doubleField71_;
-      doubleField72_ = other.doubleField72_;
-      doubleField25_ = other.doubleField25_;
-      int64Field26_ = other.int64Field26_;
-      doubleField68_ = other.doubleField68_;
-      doubleField28_ = other.doubleField28_;
-      doubleField106_ = other.doubleField106_;
-      doubleField29_ = other.doubleField29_;
-      doubleField30_ = other.doubleField30_;
-      doubleField101_ = other.doubleField101_;
-      doubleField102_ = other.doubleField102_;
-      doubleField103_ = other.doubleField103_;
-      doubleField104_ = other.doubleField104_;
-      doubleField105_ = other.doubleField105_;
-      doubleField31_ = other.doubleField31_;
-      int64Field32_ = other.int64Field32_;
-      doubleField75_ = other.doubleField75_;
-      doubleField129_ = other.doubleField129_;
-      enumField80_ = other.enumField80_;
-      enumField81_ = other.enumField81_;
-      int64Field82_ = other.int64Field82_;
-      enumField83_ = other.enumField83_;
-      int64Field85_ = other.int64Field85_;
-      int64Field86_ = other.int64Field86_;
-      int64Field87_ = other.int64Field87_;
-      int64Field125_ = other.int64Field125_;
-      int64Field37_ = other.int64Field37_;
-      doubleField38_ = other.doubleField38_;
-      interactions_ = other.interactions_;
-      repeatedIntField100_ = other.repeatedIntField100_.Clone();
-      doubleField40_ = other.doubleField40_;
-      int64Field41_ = other.int64Field41_;
-      int64Field126_ = other.int64Field126_;
-      int64Field127_ = other.int64Field127_;
-      doubleField128_ = other.doubleField128_;
-      doubleField109_ = other.doubleField109_;
-      int64Field110_ = other.int64Field110_;
-      doubleField111_ = other.doubleField111_;
-      int64Field112_ = other.int64Field112_;
-      doubleField113_ = other.doubleField113_;
-      int64Field114_ = other.int64Field114_;
-      doubleField42_ = other.doubleField42_;
-      int64Field43_ = other.int64Field43_;
-      int64Field44_ = other.int64Field44_;
-      doubleField45_ = other.doubleField45_;
-      doubleField46_ = other.doubleField46_;
-      doubleField78_ = other.doubleField78_;
-      doubleField88_ = other.doubleField88_;
-      doubleField47_ = other.doubleField47_;
-      doubleField89_ = other.doubleField89_;
-      doubleField48_ = other.doubleField48_;
-      doubleField49_ = other.doubleField49_;
-      doubleField50_ = other.doubleField50_;
-      doubleField90_ = other.doubleField90_;
-      doubleField51_ = other.doubleField51_;
-      doubleField91_ = other.doubleField91_;
-      doubleField92_ = other.doubleField92_;
-      int64Field107_ = other.int64Field107_;
-      doubleField93_ = other.doubleField93_;
-      doubleField108_ = other.doubleField108_;
-      doubleField52_ = other.doubleField52_;
-      doubleField53_ = other.doubleField53_;
-      doubleField94_ = other.doubleField94_;
-      doubleField54_ = other.doubleField54_;
-      doubleField55_ = other.doubleField55_;
-      doubleField56_ = other.doubleField56_;
-      doubleField57_ = other.doubleField57_;
-      doubleField58_ = other.doubleField58_;
-      int64Field59_ = other.int64Field59_;
-      int64Field60_ = other.int64Field60_;
-      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public ManyPrimitiveFieldsMessage Clone() {
-      return new ManyPrimitiveFieldsMessage(this);
-    }
-
-    /// <summary>Field number for the "double_field_95" field.</summary>
-    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 {
-        doubleField95_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_1" field.</summary>
-    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 {
-        doubleField1_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_79" field.</summary>
-    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 {
-        doubleField79_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_2" field.</summary>
-    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 {
-        int64Field2_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_96" field.</summary>
-    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 {
-        doubleField96_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_3" field.</summary>
-    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 {
-        int64Field3_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_4" field.</summary>
-    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 {
-        int64Field4_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_97" field.</summary>
-    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 {
-        doubleField97_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_65" field.</summary>
-    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 {
-        doubleField65_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_66" field.</summary>
-    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 {
-        doubleField66_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_7" field.</summary>
-    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 {
-        doubleField7_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_62" field.</summary>
-    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 {
-        doubleField62_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_118" field.</summary>
-    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 {
-        doubleField118_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_119" field.</summary>
-    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 {
-        doubleField119_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_67" field.</summary>
-    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 {
-        doubleField67_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_120" field.</summary>
-    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 {
-        doubleField120_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_121" field.</summary>
-    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 {
-        doubleField121_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_122" field.</summary>
-    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 {
-        doubleField122_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_123" field.</summary>
-    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 {
-        doubleField123_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_124" field.</summary>
-    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 {
-        doubleField124_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_8" field.</summary>
-    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 {
-        doubleField8_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_9" field.</summary>
-    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 {
-        doubleField9_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_98" field.</summary>
-    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 {
-        doubleField98_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_10" field.</summary>
-    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 {
-        doubleField10_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_11" field.</summary>
-    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 {
-        doubleField11_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_99" field.</summary>
-    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 {
-        doubleField99_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_84" field.</summary>
-    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 {
-        doubleField84_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_14" field.</summary>
-    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 {
-        doubleField14_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_77" field.</summary>
-    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 {
-        doubleField77_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_15" field.</summary>
-    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 {
-        doubleField15_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_19" field.</summary>
-    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 {
-        int64Field19_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_115" field.</summary>
-    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 {
-        int64Field115_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_116" field.</summary>
-    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 {
-        doubleField116_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_117" field.</summary>
-    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 {
-        int64Field117_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_20" field.</summary>
-    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 {
-        doubleField20_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_21" field.</summary>
-    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 {
-        doubleField21_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "string_field_73" field.</summary>
-    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 {
-        stringField73_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "string_field_74" field.</summary>
-    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 {
-        stringField74_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
-      }
-    }
-
-    /// <summary>Field number for the "double_field_22" field.</summary>
-    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 {
-        doubleField22_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_69" field.</summary>
-    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 {
-        doubleField69_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_70" field.</summary>
-    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 {
-        doubleField70_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_71" field.</summary>
-    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 {
-        doubleField71_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_72" field.</summary>
-    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 {
-        doubleField72_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_25" field.</summary>
-    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 {
-        doubleField25_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_26" field.</summary>
-    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 {
-        int64Field26_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_68" field.</summary>
-    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 {
-        doubleField68_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_28" field.</summary>
-    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 {
-        doubleField28_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_106" field.</summary>
-    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 {
-        doubleField106_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_29" field.</summary>
-    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 {
-        doubleField29_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_30" field.</summary>
-    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 {
-        doubleField30_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_101" field.</summary>
-    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 {
-        doubleField101_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_102" field.</summary>
-    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 {
-        doubleField102_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_103" field.</summary>
-    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 {
-        doubleField103_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_104" field.</summary>
-    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 {
-        doubleField104_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_105" field.</summary>
-    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 {
-        doubleField105_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_31" field.</summary>
-    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 {
-        doubleField31_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_32" field.</summary>
-    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 {
-        int64Field32_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_75" field.</summary>
-    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 {
-        doubleField75_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_129" field.</summary>
-    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 {
-        doubleField129_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "enum_field_80" field.</summary>
-    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 {
-        enumField80_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "enum_field_81" field.</summary>
-    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 {
-        enumField81_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_82" field.</summary>
-    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 {
-        int64Field82_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "enum_field_83" field.</summary>
-    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 {
-        enumField83_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_85" field.</summary>
-    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 {
-        int64Field85_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_86" field.</summary>
-    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 {
-        int64Field86_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_87" field.</summary>
-    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 {
-        int64Field87_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_125" field.</summary>
-    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 {
-        int64Field125_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_37" field.</summary>
-    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 {
-        int64Field37_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_38" field.</summary>
-    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 {
-        doubleField38_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "interactions" field.</summary>
-    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 {
-        interactions_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "repeated_int_field_100" field.</summary>
-    public const int RepeatedIntField100FieldNumber = 100;
-    private static readonly pb::FieldCodec<int> _repeated_repeatedIntField100_codec
-        = 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_; }
-    }
-
-    /// <summary>Field number for the "double_field_40" field.</summary>
-    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 {
-        doubleField40_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_41" field.</summary>
-    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 {
-        int64Field41_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_126" field.</summary>
-    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 {
-        int64Field126_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_127" field.</summary>
-    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 {
-        int64Field127_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_128" field.</summary>
-    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 {
-        doubleField128_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_109" field.</summary>
-    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 {
-        doubleField109_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_110" field.</summary>
-    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 {
-        int64Field110_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_111" field.</summary>
-    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 {
-        doubleField111_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_112" field.</summary>
-    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 {
-        int64Field112_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_113" field.</summary>
-    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 {
-        doubleField113_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_114" field.</summary>
-    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 {
-        int64Field114_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_42" field.</summary>
-    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 {
-        doubleField42_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_43" field.</summary>
-    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 {
-        int64Field43_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_44" field.</summary>
-    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 {
-        int64Field44_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_45" field.</summary>
-    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 {
-        doubleField45_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_46" field.</summary>
-    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 {
-        doubleField46_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_78" field.</summary>
-    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 {
-        doubleField78_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_88" field.</summary>
-    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 {
-        doubleField88_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_47" field.</summary>
-    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 {
-        doubleField47_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_89" field.</summary>
-    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 {
-        doubleField89_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_48" field.</summary>
-    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 {
-        doubleField48_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_49" field.</summary>
-    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 {
-        doubleField49_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_50" field.</summary>
-    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 {
-        doubleField50_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_90" field.</summary>
-    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 {
-        doubleField90_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_51" field.</summary>
-    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 {
-        doubleField51_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_91" field.</summary>
-    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 {
-        doubleField91_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_92" field.</summary>
-    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 {
-        doubleField92_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_107" field.</summary>
-    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 {
-        int64Field107_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_93" field.</summary>
-    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 {
-        doubleField93_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_108" field.</summary>
-    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 {
-        doubleField108_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_52" field.</summary>
-    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 {
-        doubleField52_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_53" field.</summary>
-    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 {
-        doubleField53_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_94" field.</summary>
-    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 {
-        doubleField94_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_54" field.</summary>
-    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 {
-        doubleField54_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_55" field.</summary>
-    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 {
-        doubleField55_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_56" field.</summary>
-    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 {
-        doubleField56_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_57" field.</summary>
-    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 {
-        doubleField57_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "double_field_58" field.</summary>
-    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 {
-        doubleField58_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_59" field.</summary>
-    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 {
-        int64Field59_ = value;
-      }
-    }
-
-    /// <summary>Field number for the "int64_field_60" field.</summary>
-    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 {
-        int64Field60_ = value;
-      }
-    }
-
-    [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;
-      }
-      if (ReferenceEquals(other, this)) {
-        return true;
-      }
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField95, other.DoubleField95)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField1, other.DoubleField1)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField79, other.DoubleField79)) return false;
-      if (Int64Field2 != other.Int64Field2) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField96, other.DoubleField96)) return false;
-      if (Int64Field3 != other.Int64Field3) return false;
-      if (Int64Field4 != other.Int64Field4) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField97, other.DoubleField97)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField65, other.DoubleField65)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField66, other.DoubleField66)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField7, other.DoubleField7)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField62, other.DoubleField62)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField118, other.DoubleField118)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField119, other.DoubleField119)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField67, other.DoubleField67)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField120, other.DoubleField120)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField121, other.DoubleField121)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField122, other.DoubleField122)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField123, other.DoubleField123)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField124, other.DoubleField124)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField8, other.DoubleField8)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField9, other.DoubleField9)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField98, other.DoubleField98)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField10, other.DoubleField10)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField11, other.DoubleField11)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField99, other.DoubleField99)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField84, other.DoubleField84)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField14, other.DoubleField14)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField77, other.DoubleField77)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField15, other.DoubleField15)) return false;
-      if (Int64Field19 != other.Int64Field19) return false;
-      if (Int64Field115 != other.Int64Field115) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField116, other.DoubleField116)) return false;
-      if (Int64Field117 != other.Int64Field117) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField20, other.DoubleField20)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField21, other.DoubleField21)) return false;
-      if (StringField73 != other.StringField73) return false;
-      if (StringField74 != other.StringField74) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField22, other.DoubleField22)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField69, other.DoubleField69)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField70, other.DoubleField70)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField71, other.DoubleField71)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField72, other.DoubleField72)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField25, other.DoubleField25)) return false;
-      if (Int64Field26 != other.Int64Field26) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField68, other.DoubleField68)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField28, other.DoubleField28)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField106, other.DoubleField106)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField29, other.DoubleField29)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField30, other.DoubleField30)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField101, other.DoubleField101)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField102, other.DoubleField102)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField103, other.DoubleField103)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField104, other.DoubleField104)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField105, other.DoubleField105)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField31, other.DoubleField31)) return false;
-      if (Int64Field32 != other.Int64Field32) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField75, other.DoubleField75)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField129, other.DoubleField129)) return false;
-      if (EnumField80 != other.EnumField80) return false;
-      if (EnumField81 != other.EnumField81) return false;
-      if (Int64Field82 != other.Int64Field82) return false;
-      if (EnumField83 != other.EnumField83) return false;
-      if (Int64Field85 != other.Int64Field85) return false;
-      if (Int64Field86 != other.Int64Field86) return false;
-      if (Int64Field87 != other.Int64Field87) return false;
-      if (Int64Field125 != other.Int64Field125) return false;
-      if (Int64Field37 != other.Int64Field37) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField38, other.DoubleField38)) return false;
-      if (Interactions != other.Interactions) return false;
-      if(!repeatedIntField100_.Equals(other.repeatedIntField100_)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField40, other.DoubleField40)) return false;
-      if (Int64Field41 != other.Int64Field41) return false;
-      if (Int64Field126 != other.Int64Field126) return false;
-      if (Int64Field127 != other.Int64Field127) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField128, other.DoubleField128)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField109, other.DoubleField109)) return false;
-      if (Int64Field110 != other.Int64Field110) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField111, other.DoubleField111)) return false;
-      if (Int64Field112 != other.Int64Field112) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField113, other.DoubleField113)) return false;
-      if (Int64Field114 != other.Int64Field114) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField42, other.DoubleField42)) return false;
-      if (Int64Field43 != other.Int64Field43) return false;
-      if (Int64Field44 != other.Int64Field44) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField45, other.DoubleField45)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField46, other.DoubleField46)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField78, other.DoubleField78)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField88, other.DoubleField88)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField47, other.DoubleField47)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField89, other.DoubleField89)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField48, other.DoubleField48)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField49, other.DoubleField49)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField50, other.DoubleField50)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField90, other.DoubleField90)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField51, other.DoubleField51)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField91, other.DoubleField91)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField92, other.DoubleField92)) return false;
-      if (Int64Field107 != other.Int64Field107) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField93, other.DoubleField93)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField108, other.DoubleField108)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField52, other.DoubleField52)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField53, other.DoubleField53)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField94, other.DoubleField94)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField54, other.DoubleField54)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField55, other.DoubleField55)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField56, other.DoubleField56)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField57, other.DoubleField57)) return false;
-      if (!pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.Equals(DoubleField58, other.DoubleField58)) return false;
-      if (Int64Field59 != other.Int64Field59) return false;
-      if (Int64Field60 != other.Int64Field60) 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 (DoubleField95 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField95);
-      if (DoubleField1 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField1);
-      if (DoubleField79 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField79);
-      if (Int64Field2 != 0L) hash ^= Int64Field2.GetHashCode();
-      if (DoubleField96 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField96);
-      if (Int64Field3 != 0L) hash ^= Int64Field3.GetHashCode();
-      if (Int64Field4 != 0L) hash ^= Int64Field4.GetHashCode();
-      if (DoubleField97 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField97);
-      if (DoubleField65 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField65);
-      if (DoubleField66 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField66);
-      if (DoubleField7 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField7);
-      if (DoubleField62 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField62);
-      if (DoubleField118 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField118);
-      if (DoubleField119 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField119);
-      if (DoubleField67 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField67);
-      if (DoubleField120 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField120);
-      if (DoubleField121 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField121);
-      if (DoubleField122 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField122);
-      if (DoubleField123 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField123);
-      if (DoubleField124 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField124);
-      if (DoubleField8 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField8);
-      if (DoubleField9 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField9);
-      if (DoubleField98 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField98);
-      if (DoubleField10 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField10);
-      if (DoubleField11 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField11);
-      if (DoubleField99 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField99);
-      if (DoubleField84 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField84);
-      if (DoubleField14 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField14);
-      if (DoubleField77 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField77);
-      if (DoubleField15 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField15);
-      if (Int64Field19 != 0L) hash ^= Int64Field19.GetHashCode();
-      if (Int64Field115 != 0L) hash ^= Int64Field115.GetHashCode();
-      if (DoubleField116 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField116);
-      if (Int64Field117 != 0L) hash ^= Int64Field117.GetHashCode();
-      if (DoubleField20 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField20);
-      if (DoubleField21 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField21);
-      if (StringField73.Length != 0) hash ^= StringField73.GetHashCode();
-      if (StringField74.Length != 0) hash ^= StringField74.GetHashCode();
-      if (DoubleField22 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField22);
-      if (DoubleField69 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField69);
-      if (DoubleField70 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField70);
-      if (DoubleField71 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField71);
-      if (DoubleField72 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField72);
-      if (DoubleField25 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField25);
-      if (Int64Field26 != 0L) hash ^= Int64Field26.GetHashCode();
-      if (DoubleField68 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField68);
-      if (DoubleField28 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField28);
-      if (DoubleField106 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField106);
-      if (DoubleField29 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField29);
-      if (DoubleField30 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField30);
-      if (DoubleField101 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField101);
-      if (DoubleField102 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField102);
-      if (DoubleField103 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField103);
-      if (DoubleField104 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField104);
-      if (DoubleField105 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField105);
-      if (DoubleField31 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField31);
-      if (Int64Field32 != 0L) hash ^= Int64Field32.GetHashCode();
-      if (DoubleField75 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField75);
-      if (DoubleField129 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField129);
-      if (EnumField80 != 0) hash ^= EnumField80.GetHashCode();
-      if (EnumField81 != 0) hash ^= EnumField81.GetHashCode();
-      if (Int64Field82 != 0L) hash ^= Int64Field82.GetHashCode();
-      if (EnumField83 != 0) hash ^= EnumField83.GetHashCode();
-      if (Int64Field85 != 0L) hash ^= Int64Field85.GetHashCode();
-      if (Int64Field86 != 0L) hash ^= Int64Field86.GetHashCode();
-      if (Int64Field87 != 0L) hash ^= Int64Field87.GetHashCode();
-      if (Int64Field125 != 0L) hash ^= Int64Field125.GetHashCode();
-      if (Int64Field37 != 0L) hash ^= Int64Field37.GetHashCode();
-      if (DoubleField38 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField38);
-      if (Interactions != 0L) hash ^= Interactions.GetHashCode();
-      hash ^= repeatedIntField100_.GetHashCode();
-      if (DoubleField40 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField40);
-      if (Int64Field41 != 0L) hash ^= Int64Field41.GetHashCode();
-      if (Int64Field126 != 0L) hash ^= Int64Field126.GetHashCode();
-      if (Int64Field127 != 0L) hash ^= Int64Field127.GetHashCode();
-      if (DoubleField128 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField128);
-      if (DoubleField109 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField109);
-      if (Int64Field110 != 0L) hash ^= Int64Field110.GetHashCode();
-      if (DoubleField111 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField111);
-      if (Int64Field112 != 0L) hash ^= Int64Field112.GetHashCode();
-      if (DoubleField113 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField113);
-      if (Int64Field114 != 0L) hash ^= Int64Field114.GetHashCode();
-      if (DoubleField42 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField42);
-      if (Int64Field43 != 0L) hash ^= Int64Field43.GetHashCode();
-      if (Int64Field44 != 0L) hash ^= Int64Field44.GetHashCode();
-      if (DoubleField45 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField45);
-      if (DoubleField46 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField46);
-      if (DoubleField78 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField78);
-      if (DoubleField88 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField88);
-      if (DoubleField47 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField47);
-      if (DoubleField89 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField89);
-      if (DoubleField48 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField48);
-      if (DoubleField49 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField49);
-      if (DoubleField50 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField50);
-      if (DoubleField90 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField90);
-      if (DoubleField51 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField51);
-      if (DoubleField91 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField91);
-      if (DoubleField92 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField92);
-      if (Int64Field107 != 0L) hash ^= Int64Field107.GetHashCode();
-      if (DoubleField93 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField93);
-      if (DoubleField108 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField108);
-      if (DoubleField52 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField52);
-      if (DoubleField53 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField53);
-      if (DoubleField94 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField94);
-      if (DoubleField54 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField54);
-      if (DoubleField55 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField55);
-      if (DoubleField56 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField56);
-      if (DoubleField57 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField57);
-      if (DoubleField58 != 0D) hash ^= pbc::ProtobufEqualityComparers.BitwiseDoubleEqualityComparer.GetHashCode(DoubleField58);
-      if (Int64Field59 != 0L) hash ^= Int64Field59.GetHashCode();
-      if (Int64Field60 != 0L) hash ^= Int64Field60.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 (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(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(output);
-      }
-    #endif
-    }
-
-    #if !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) {
-        size += 2 + 8;
-      }
-      if (DoubleField1 != 0D) {
-        size += 1 + 8;
-      }
-      if (DoubleField79 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field2 != 0L) {
-        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Int64Field2);
-      }
-      if (DoubleField96 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field3 != 0L) {
-        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Int64Field3);
-      }
-      if (Int64Field4 != 0L) {
-        size += 1 + pb::CodedOutputStream.ComputeInt64Size(Int64Field4);
-      }
-      if (DoubleField97 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField65 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField66 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField7 != 0D) {
-        size += 1 + 8;
-      }
-      if (DoubleField62 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField118 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField119 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField67 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField120 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField121 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField122 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField123 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField124 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField8 != 0D) {
-        size += 1 + 8;
-      }
-      if (DoubleField9 != 0D) {
-        size += 1 + 8;
-      }
-      if (DoubleField98 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField10 != 0D) {
-        size += 1 + 8;
-      }
-      if (DoubleField11 != 0D) {
-        size += 1 + 8;
-      }
-      if (DoubleField99 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField84 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField14 != 0D) {
-        size += 1 + 8;
-      }
-      if (DoubleField77 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField15 != 0D) {
-        size += 1 + 8;
-      }
-      if (Int64Field19 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field19);
-      }
-      if (Int64Field115 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field115);
-      }
-      if (DoubleField116 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field117 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field117);
-      }
-      if (DoubleField20 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField21 != 0D) {
-        size += 2 + 8;
-      }
-      if (StringField73.Length != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeStringSize(StringField73);
-      }
-      if (StringField74.Length != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeStringSize(StringField74);
-      }
-      if (DoubleField22 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField69 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField70 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField71 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField72 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField25 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field26 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field26);
-      }
-      if (DoubleField68 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField28 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField106 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField29 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField30 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField101 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField102 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField103 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField104 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField105 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField31 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field32 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field32);
-      }
-      if (DoubleField75 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField129 != 0D) {
-        size += 2 + 8;
-      }
-      if (EnumField80 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField80);
-      }
-      if (EnumField81 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField81);
-      }
-      if (Int64Field82 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field82);
-      }
-      if (EnumField83 != 0) {
-        size += 2 + pb::CodedOutputStream.ComputeInt32Size(EnumField83);
-      }
-      if (Int64Field85 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field85);
-      }
-      if (Int64Field86 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field86);
-      }
-      if (Int64Field87 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field87);
-      }
-      if (Int64Field125 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field125);
-      }
-      if (Int64Field37 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field37);
-      }
-      if (DoubleField38 != 0D) {
-        size += 2 + 8;
-      }
-      if (Interactions != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Interactions);
-      }
-      size += repeatedIntField100_.CalculateSize(_repeated_repeatedIntField100_codec);
-      if (DoubleField40 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field41 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field41);
-      }
-      if (Int64Field126 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field126);
-      }
-      if (Int64Field127 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field127);
-      }
-      if (DoubleField128 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField109 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field110 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field110);
-      }
-      if (DoubleField111 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field112 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field112);
-      }
-      if (DoubleField113 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field114 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field114);
-      }
-      if (DoubleField42 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field43 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field43);
-      }
-      if (Int64Field44 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field44);
-      }
-      if (DoubleField45 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField46 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField78 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField88 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField47 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField89 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField48 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField49 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField50 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField90 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField51 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField91 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField92 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field107 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field107);
-      }
-      if (DoubleField93 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField108 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField52 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField53 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField94 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField54 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField55 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField56 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField57 != 0D) {
-        size += 2 + 8;
-      }
-      if (DoubleField58 != 0D) {
-        size += 2 + 8;
-      }
-      if (Int64Field59 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field59);
-      }
-      if (Int64Field60 != 0L) {
-        size += 2 + pb::CodedOutputStream.ComputeInt64Size(Int64Field60);
-      }
-      if (_unknownFields != null) {
-        size += _unknownFields.CalculateSize();
-      }
-      return size;
-    }
-
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
-    public void MergeFrom(ManyPrimitiveFieldsMessage other) {
-      if (other == null) {
-        return;
-      }
-      if (other.DoubleField95 != 0D) {
-        DoubleField95 = other.DoubleField95;
-      }
-      if (other.DoubleField1 != 0D) {
-        DoubleField1 = other.DoubleField1;
-      }
-      if (other.DoubleField79 != 0D) {
-        DoubleField79 = other.DoubleField79;
-      }
-      if (other.Int64Field2 != 0L) {
-        Int64Field2 = other.Int64Field2;
-      }
-      if (other.DoubleField96 != 0D) {
-        DoubleField96 = other.DoubleField96;
-      }
-      if (other.Int64Field3 != 0L) {
-        Int64Field3 = other.Int64Field3;
-      }
-      if (other.Int64Field4 != 0L) {
-        Int64Field4 = other.Int64Field4;
-      }
-      if (other.DoubleField97 != 0D) {
-        DoubleField97 = other.DoubleField97;
-      }
-      if (other.DoubleField65 != 0D) {
-        DoubleField65 = other.DoubleField65;
-      }
-      if (other.DoubleField66 != 0D) {
-        DoubleField66 = other.DoubleField66;
-      }
-      if (other.DoubleField7 != 0D) {
-        DoubleField7 = other.DoubleField7;
-      }
-      if (other.DoubleField62 != 0D) {
-        DoubleField62 = other.DoubleField62;
-      }
-      if (other.DoubleField118 != 0D) {
-        DoubleField118 = other.DoubleField118;
-      }
-      if (other.DoubleField119 != 0D) {
-        DoubleField119 = other.DoubleField119;
-      }
-      if (other.DoubleField67 != 0D) {
-        DoubleField67 = other.DoubleField67;
-      }
-      if (other.DoubleField120 != 0D) {
-        DoubleField120 = other.DoubleField120;
-      }
-      if (other.DoubleField121 != 0D) {
-        DoubleField121 = other.DoubleField121;
-      }
-      if (other.DoubleField122 != 0D) {
-        DoubleField122 = other.DoubleField122;
-      }
-      if (other.DoubleField123 != 0D) {
-        DoubleField123 = other.DoubleField123;
-      }
-      if (other.DoubleField124 != 0D) {
-        DoubleField124 = other.DoubleField124;
-      }
-      if (other.DoubleField8 != 0D) {
-        DoubleField8 = other.DoubleField8;
-      }
-      if (other.DoubleField9 != 0D) {
-        DoubleField9 = other.DoubleField9;
-      }
-      if (other.DoubleField98 != 0D) {
-        DoubleField98 = other.DoubleField98;
-      }
-      if (other.DoubleField10 != 0D) {
-        DoubleField10 = other.DoubleField10;
-      }
-      if (other.DoubleField11 != 0D) {
-        DoubleField11 = other.DoubleField11;
-      }
-      if (other.DoubleField99 != 0D) {
-        DoubleField99 = other.DoubleField99;
-      }
-      if (other.DoubleField84 != 0D) {
-        DoubleField84 = other.DoubleField84;
-      }
-      if (other.DoubleField14 != 0D) {
-        DoubleField14 = other.DoubleField14;
-      }
-      if (other.DoubleField77 != 0D) {
-        DoubleField77 = other.DoubleField77;
-      }
-      if (other.DoubleField15 != 0D) {
-        DoubleField15 = other.DoubleField15;
-      }
-      if (other.Int64Field19 != 0L) {
-        Int64Field19 = other.Int64Field19;
-      }
-      if (other.Int64Field115 != 0L) {
-        Int64Field115 = other.Int64Field115;
-      }
-      if (other.DoubleField116 != 0D) {
-        DoubleField116 = other.DoubleField116;
-      }
-      if (other.Int64Field117 != 0L) {
-        Int64Field117 = other.Int64Field117;
-      }
-      if (other.DoubleField20 != 0D) {
-        DoubleField20 = other.DoubleField20;
-      }
-      if (other.DoubleField21 != 0D) {
-        DoubleField21 = other.DoubleField21;
-      }
-      if (other.StringField73.Length != 0) {
-        StringField73 = other.StringField73;
-      }
-      if (other.StringField74.Length != 0) {
-        StringField74 = other.StringField74;
-      }
-      if (other.DoubleField22 != 0D) {
-        DoubleField22 = other.DoubleField22;
-      }
-      if (other.DoubleField69 != 0D) {
-        DoubleField69 = other.DoubleField69;
-      }
-      if (other.DoubleField70 != 0D) {
-        DoubleField70 = other.DoubleField70;
-      }
-      if (other.DoubleField71 != 0D) {
-        DoubleField71 = other.DoubleField71;
-      }
-      if (other.DoubleField72 != 0D) {
-        DoubleField72 = other.DoubleField72;
-      }
-      if (other.DoubleField25 != 0D) {
-        DoubleField25 = other.DoubleField25;
-      }
-      if (other.Int64Field26 != 0L) {
-        Int64Field26 = other.Int64Field26;
-      }
-      if (other.DoubleField68 != 0D) {
-        DoubleField68 = other.DoubleField68;
-      }
-      if (other.DoubleField28 != 0D) {
-        DoubleField28 = other.DoubleField28;
-      }
-      if (other.DoubleField106 != 0D) {
-        DoubleField106 = other.DoubleField106;
-      }
-      if (other.DoubleField29 != 0D) {
-        DoubleField29 = other.DoubleField29;
-      }
-      if (other.DoubleField30 != 0D) {
-        DoubleField30 = other.DoubleField30;
-      }
-      if (other.DoubleField101 != 0D) {
-        DoubleField101 = other.DoubleField101;
-      }
-      if (other.DoubleField102 != 0D) {
-        DoubleField102 = other.DoubleField102;
-      }
-      if (other.DoubleField103 != 0D) {
-        DoubleField103 = other.DoubleField103;
-      }
-      if (other.DoubleField104 != 0D) {
-        DoubleField104 = other.DoubleField104;
-      }
-      if (other.DoubleField105 != 0D) {
-        DoubleField105 = other.DoubleField105;
-      }
-      if (other.DoubleField31 != 0D) {
-        DoubleField31 = other.DoubleField31;
-      }
-      if (other.Int64Field32 != 0L) {
-        Int64Field32 = other.Int64Field32;
-      }
-      if (other.DoubleField75 != 0D) {
-        DoubleField75 = other.DoubleField75;
-      }
-      if (other.DoubleField129 != 0D) {
-        DoubleField129 = other.DoubleField129;
-      }
-      if (other.EnumField80 != 0) {
-        EnumField80 = other.EnumField80;
-      }
-      if (other.EnumField81 != 0) {
-        EnumField81 = other.EnumField81;
-      }
-      if (other.Int64Field82 != 0L) {
-        Int64Field82 = other.Int64Field82;
-      }
-      if (other.EnumField83 != 0) {
-        EnumField83 = other.EnumField83;
-      }
-      if (other.Int64Field85 != 0L) {
-        Int64Field85 = other.Int64Field85;
-      }
-      if (other.Int64Field86 != 0L) {
-        Int64Field86 = other.Int64Field86;
-      }
-      if (other.Int64Field87 != 0L) {
-        Int64Field87 = other.Int64Field87;
-      }
-      if (other.Int64Field125 != 0L) {
-        Int64Field125 = other.Int64Field125;
-      }
-      if (other.Int64Field37 != 0L) {
-        Int64Field37 = other.Int64Field37;
-      }
-      if (other.DoubleField38 != 0D) {
-        DoubleField38 = other.DoubleField38;
-      }
-      if (other.Interactions != 0L) {
-        Interactions = other.Interactions;
-      }
-      repeatedIntField100_.Add(other.repeatedIntField100_);
-      if (other.DoubleField40 != 0D) {
-        DoubleField40 = other.DoubleField40;
-      }
-      if (other.Int64Field41 != 0L) {
-        Int64Field41 = other.Int64Field41;
-      }
-      if (other.Int64Field126 != 0L) {
-        Int64Field126 = other.Int64Field126;
-      }
-      if (other.Int64Field127 != 0L) {
-        Int64Field127 = other.Int64Field127;
-      }
-      if (other.DoubleField128 != 0D) {
-        DoubleField128 = other.DoubleField128;
-      }
-      if (other.DoubleField109 != 0D) {
-        DoubleField109 = other.DoubleField109;
-      }
-      if (other.Int64Field110 != 0L) {
-        Int64Field110 = other.Int64Field110;
-      }
-      if (other.DoubleField111 != 0D) {
-        DoubleField111 = other.DoubleField111;
-      }
-      if (other.Int64Field112 != 0L) {
-        Int64Field112 = other.Int64Field112;
-      }
-      if (other.DoubleField113 != 0D) {
-        DoubleField113 = other.DoubleField113;
-      }
-      if (other.Int64Field114 != 0L) {
-        Int64Field114 = other.Int64Field114;
-      }
-      if (other.DoubleField42 != 0D) {
-        DoubleField42 = other.DoubleField42;
-      }
-      if (other.Int64Field43 != 0L) {
-        Int64Field43 = other.Int64Field43;
-      }
-      if (other.Int64Field44 != 0L) {
-        Int64Field44 = other.Int64Field44;
-      }
-      if (other.DoubleField45 != 0D) {
-        DoubleField45 = other.DoubleField45;
-      }
-      if (other.DoubleField46 != 0D) {
-        DoubleField46 = other.DoubleField46;
-      }
-      if (other.DoubleField78 != 0D) {
-        DoubleField78 = other.DoubleField78;
-      }
-      if (other.DoubleField88 != 0D) {
-        DoubleField88 = other.DoubleField88;
-      }
-      if (other.DoubleField47 != 0D) {
-        DoubleField47 = other.DoubleField47;
-      }
-      if (other.DoubleField89 != 0D) {
-        DoubleField89 = other.DoubleField89;
-      }
-      if (other.DoubleField48 != 0D) {
-        DoubleField48 = other.DoubleField48;
-      }
-      if (other.DoubleField49 != 0D) {
-        DoubleField49 = other.DoubleField49;
-      }
-      if (other.DoubleField50 != 0D) {
-        DoubleField50 = other.DoubleField50;
-      }
-      if (other.DoubleField90 != 0D) {
-        DoubleField90 = other.DoubleField90;
-      }
-      if (other.DoubleField51 != 0D) {
-        DoubleField51 = other.DoubleField51;
-      }
-      if (other.DoubleField91 != 0D) {
-        DoubleField91 = other.DoubleField91;
-      }
-      if (other.DoubleField92 != 0D) {
-        DoubleField92 = other.DoubleField92;
-      }
-      if (other.Int64Field107 != 0L) {
-        Int64Field107 = other.Int64Field107;
-      }
-      if (other.DoubleField93 != 0D) {
-        DoubleField93 = other.DoubleField93;
-      }
-      if (other.DoubleField108 != 0D) {
-        DoubleField108 = other.DoubleField108;
-      }
-      if (other.DoubleField52 != 0D) {
-        DoubleField52 = other.DoubleField52;
-      }
-      if (other.DoubleField53 != 0D) {
-        DoubleField53 = other.DoubleField53;
-      }
-      if (other.DoubleField94 != 0D) {
-        DoubleField94 = other.DoubleField94;
-      }
-      if (other.DoubleField54 != 0D) {
-        DoubleField54 = other.DoubleField54;
-      }
-      if (other.DoubleField55 != 0D) {
-        DoubleField55 = other.DoubleField55;
-      }
-      if (other.DoubleField56 != 0D) {
-        DoubleField56 = other.DoubleField56;
-      }
-      if (other.DoubleField57 != 0D) {
-        DoubleField57 = other.DoubleField57;
-      }
-      if (other.DoubleField58 != 0D) {
-        DoubleField58 = other.DoubleField58;
-      }
-      if (other.Int64Field59 != 0L) {
-        Int64Field59 = other.Int64Field59;
-      }
-      if (other.Int64Field60 != 0L) {
-        Int64Field60 = other.Int64Field60;
-      }
-      _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 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(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
-    }
-
-    #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
-    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
-    [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
-
-}
-
-#endregion Designer generated code
diff --git a/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs b/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs
deleted file mode 100644
index 5a3bba7..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/WriteMessagesBenchmark.cs
+++ /dev/null
@@ -1,198 +0,0 @@
-#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
deleted file mode 100644
index 66b6b4a..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/WriteRawPrimitivesBenchmark.cs
+++ /dev/null
@@ -1,519 +0,0 @@
-#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.Benchmarks/wrapper_benchmark_messages.proto b/csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto
deleted file mode 100644
index 6802c25..0000000
--- a/csharp/src/Google.Protobuf.Benchmarks/wrapper_benchmark_messages.proto
+++ /dev/null
@@ -1,237 +0,0 @@
-syntax = "proto3";
-
-package google.protobuf.benchmarks;
-
-import "google/protobuf/wrappers.proto";
-
-// a message that has a large number of wrapper fields
-// obfuscated version of an internal message
-message ManyWrapperFieldsMessage {
-  google.protobuf.DoubleValue double_field_95 = 95;
-  google.protobuf.DoubleValue double_field_1 = 1;
-  google.protobuf.DoubleValue double_field_79 = 79;
-  google.protobuf.Int64Value int64_field_2 = 2;
-  google.protobuf.DoubleValue double_field_96 = 96;
-  google.protobuf.Int64Value int64_field_3 = 3;
-  google.protobuf.Int64Value int64_field_4 = 4;
-  google.protobuf.DoubleValue double_field_97 = 97;
-  google.protobuf.DoubleValue double_field_65 = 65;
-  google.protobuf.DoubleValue double_field_66 = 66;
-  google.protobuf.DoubleValue double_field_7 = 7;
-  google.protobuf.DoubleValue double_field_62 = 62;
-  google.protobuf.DoubleValue double_field_118 = 118;
-  google.protobuf.DoubleValue double_field_119 = 119;
-  google.protobuf.DoubleValue double_field_67 = 67;
-  google.protobuf.DoubleValue double_field_120 = 120;
-  google.protobuf.DoubleValue double_field_121 = 121;
-  google.protobuf.DoubleValue double_field_122 = 122;
-  google.protobuf.DoubleValue double_field_123 = 123;
-  google.protobuf.DoubleValue double_field_124 = 124;
-  google.protobuf.DoubleValue double_field_8 = 8;
-  google.protobuf.DoubleValue double_field_9 = 9;
-  google.protobuf.DoubleValue double_field_98 = 98;
-  google.protobuf.DoubleValue double_field_10 = 10;
-  google.protobuf.DoubleValue double_field_11 = 11;
-  google.protobuf.DoubleValue double_field_99 = 99;
-  google.protobuf.DoubleValue double_field_84 = 84;
-  google.protobuf.DoubleValue double_field_14 = 14;
-  google.protobuf.DoubleValue double_field_77 = 77;
-  google.protobuf.DoubleValue double_field_15 = 15;
-  google.protobuf.Int64Value int64_field_19 = 19;
-  google.protobuf.Int64Value int64_field_115 = 115;
-  google.protobuf.DoubleValue double_field_116 = 116;
-  google.protobuf.Int64Value int64_field_117 = 117;
-  google.protobuf.DoubleValue double_field_20 = 20;
-  google.protobuf.DoubleValue double_field_21 = 21;
-  google.protobuf.StringValue string_field_73 = 73;
-  google.protobuf.StringValue string_field_74 = 74;
-  google.protobuf.DoubleValue double_field_22 = 22;
-  google.protobuf.DoubleValue double_field_69 = 69;
-  google.protobuf.DoubleValue double_field_70 = 70;
-  google.protobuf.DoubleValue double_field_71 = 71;
-  google.protobuf.DoubleValue double_field_72 = 72;
-  google.protobuf.DoubleValue double_field_25 = 25;
-  google.protobuf.Int64Value int64_field_26 = 26;
-  google.protobuf.DoubleValue double_field_68 = 68;
-  google.protobuf.DoubleValue double_field_28 = 28;
-  google.protobuf.DoubleValue double_field_106 = 106;
-  google.protobuf.DoubleValue double_field_29 = 29;
-  google.protobuf.DoubleValue double_field_30 = 30;
-  google.protobuf.DoubleValue double_field_101 = 101;
-  google.protobuf.DoubleValue double_field_102 = 102;
-  google.protobuf.DoubleValue double_field_103 = 103;
-  google.protobuf.DoubleValue double_field_104 = 104;
-  google.protobuf.DoubleValue double_field_105 = 105;
-  google.protobuf.DoubleValue double_field_31 = 31;
-  google.protobuf.Int64Value int64_field_32 = 32;
-  google.protobuf.DoubleValue double_field_75 = 75;
-  google.protobuf.DoubleValue double_field_129 = 129;
-  int32 enum_field_80 = 80;
-  int32 enum_field_81 = 81;
-  google.protobuf.Int64Value int64_field_82 = 82;
-  int32 enum_field_83 = 83;
-  google.protobuf.Int64Value int64_field_85 = 85;
-  google.protobuf.Int64Value int64_field_86 = 86;
-  google.protobuf.Int64Value int64_field_87 = 87;
-  google.protobuf.Int64Value int64_field_125 = 125;
-  google.protobuf.Int64Value int64_field_37 = 37;
-  google.protobuf.DoubleValue double_field_38 = 38;
-  google.protobuf.Int64Value interactions = 39;
-  repeated int32 repeated_int_field_100 = 100;
-  google.protobuf.DoubleValue double_field_40 = 40;
-  google.protobuf.Int64Value int64_field_41 = 41;
-  google.protobuf.Int64Value int64_field_126 = 126;
-  google.protobuf.Int64Value int64_field_127 = 127;
-  google.protobuf.DoubleValue double_field_128 = 128;
-  google.protobuf.DoubleValue double_field_109 = 109;
-  google.protobuf.Int64Value int64_field_110 = 110;
-  google.protobuf.DoubleValue double_field_111 = 111;
-  google.protobuf.Int64Value int64_field_112 = 112;
-  google.protobuf.DoubleValue double_field_113 = 113;
-  google.protobuf.Int64Value int64_field_114 = 114;
-  google.protobuf.DoubleValue double_field_42 = 42;
-  google.protobuf.Int64Value int64_field_43 = 43;
-  google.protobuf.Int64Value int64_field_44 = 44;
-  google.protobuf.DoubleValue double_field_45 = 45;
-  google.protobuf.DoubleValue double_field_46 = 46;
-  google.protobuf.DoubleValue double_field_78 = 78;
-  google.protobuf.DoubleValue double_field_88 = 88;
-  google.protobuf.DoubleValue double_field_47 = 47;
-  google.protobuf.DoubleValue double_field_89 = 89;
-  google.protobuf.DoubleValue double_field_48 = 48;
-  google.protobuf.DoubleValue double_field_49 = 49;
-  google.protobuf.DoubleValue double_field_50 = 50;
-  google.protobuf.DoubleValue double_field_90 = 90;
-  google.protobuf.DoubleValue double_field_51 = 51;
-  google.protobuf.DoubleValue double_field_91 = 91;
-  google.protobuf.DoubleValue double_field_92 = 92;
-  google.protobuf.Int64Value int64_field_107 = 107;
-  google.protobuf.DoubleValue double_field_93 = 93;
-  google.protobuf.DoubleValue double_field_108 = 108;
-  google.protobuf.DoubleValue double_field_52 = 52;
-  google.protobuf.DoubleValue double_field_53 = 53;
-  google.protobuf.DoubleValue double_field_94 = 94;
-  google.protobuf.DoubleValue double_field_54 = 54;
-  google.protobuf.DoubleValue double_field_55 = 55;
-  google.protobuf.DoubleValue double_field_56 = 56;
-  google.protobuf.DoubleValue double_field_57 = 57;
-  google.protobuf.DoubleValue double_field_58 = 58;
-  google.protobuf.Int64Value int64_field_59 = 59;
-  google.protobuf.Int64Value int64_field_60 = 60;
-}
-
-// same as ManyWrapperFieldsMessages, but with primitive fields
-// for comparison.
-message ManyPrimitiveFieldsMessage {
-  double double_field_95 = 95;
-  double double_field_1 = 1;
-  double double_field_79 = 79;
-  int64 int64_field_2 = 2;
-  double double_field_96 = 96;
-  int64 int64_field_3 = 3;
-  int64 int64_field_4 = 4;
-  double double_field_97 = 97;
-  double double_field_65 = 65;
-  double double_field_66 = 66;
-  double double_field_7 = 7;
-  double double_field_62 = 62;
-  double double_field_118 = 118;
-  double double_field_119 = 119;
-  double double_field_67 = 67;
-  double double_field_120 = 120;
-  double double_field_121 = 121;
-  double double_field_122 = 122;
-  double double_field_123 = 123;
-  double double_field_124 = 124;
-  double double_field_8 = 8;
-  double double_field_9 = 9;
-  double double_field_98 = 98;
-  double double_field_10 = 10;
-  double double_field_11 = 11;
-  double double_field_99 = 99;
-  double double_field_84 = 84;
-  double double_field_14 = 14;
-  double double_field_77 = 77;
-  double double_field_15 = 15;
-  int64 int64_field_19 = 19;
-  int64 int64_field_115 = 115;
-  double double_field_116 = 116;
-  int64 int64_field_117 = 117;
-  double double_field_20 = 20;
-  double double_field_21 = 21;
-  string string_field_73 = 73;
-  string string_field_74 = 74;
-  double double_field_22 = 22;
-  double double_field_69 = 69;
-  double double_field_70 = 70;
-  double double_field_71 = 71;
-  double double_field_72 = 72;
-  double double_field_25 = 25;
-  int64 int64_field_26 = 26;
-  double double_field_68 = 68;
-  double double_field_28 = 28;
-  double double_field_106 = 106;
-  double double_field_29 = 29;
-  double double_field_30 = 30;
-  double double_field_101 = 101;
-  double double_field_102 = 102;
-  double double_field_103 = 103;
-  double double_field_104 = 104;
-  double double_field_105 = 105;
-  double double_field_31 = 31;
-  int64 int64_field_32 = 32;
-  double double_field_75 = 75;
-  double double_field_129 = 129;
-  int32 enum_field_80 = 80;
-  int32 enum_field_81 = 81;
-  int64 int64_field_82 = 82;
-  int32 enum_field_83 = 83;
-  int64 int64_field_85 = 85;
-  int64 int64_field_86 = 86;
-  int64 int64_field_87 = 87;
-  int64 int64_field_125 = 125;
-  int64 int64_field_37 = 37;
-  double double_field_38 = 38;
-  int64 interactions = 39;
-  repeated int32 repeated_int_field_100 = 100;
-  double double_field_40 = 40;
-  int64 int64_field_41 = 41;
-  int64 int64_field_126 = 126;
-  int64 int64_field_127 = 127;
-  double double_field_128 = 128;
-  double double_field_109 = 109;
-  int64 int64_field_110 = 110;
-  double double_field_111 = 111;
-  int64 int64_field_112 = 112;
-  double double_field_113 = 113;
-  int64 int64_field_114 = 114;
-  double double_field_42 = 42;
-  int64 int64_field_43 = 43;
-  int64 int64_field_44 = 44;
-  double double_field_45 = 45;
-  double double_field_46 = 46;
-  double double_field_78 = 78;
-  double double_field_88 = 88;
-  double double_field_47 = 47;
-  double double_field_89 = 89;
-  double double_field_48 = 48;
-  double double_field_49 = 49;
-  double double_field_50 = 50;
-  double double_field_90 = 90;
-  double double_field_51 = 51;
-  double double_field_91 = 91;
-  double double_field_92 = 92;
-  int64 int64_field_107 = 107;
-  double double_field_93 = 93;
-  double double_field_108 = 108;
-  double double_field_52 = 52;
-  double double_field_53 = 53;
-  double double_field_94 = 94;
-  double double_field_54 = 54;
-  double double_field_55 = 55;
-  double double_field_56 = 56;
-  double double_field_57 = 57;
-  double double_field_58 = 58;
-  int64 int64_field_59 = 59;
-  int64 int64_field_60 = 60;
-}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Conformance/BUILD.bazel b/csharp/src/Google.Protobuf.Conformance/BUILD.bazel
new file mode 100644
index 0000000..12ad0f7
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Conformance/BUILD.bazel
@@ -0,0 +1,97 @@
+load("//build_defs:internal_shell.bzl", "inline_sh_binary")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+
+inline_sh_binary(
+    name = "build_conformance_test",
+    srcs = ["Google.Protobuf.Conformance.csproj"],
+    cmd = "dotnet build -c Release $(SRCS)",
+    visibility = ["//visibility:private"],
+)
+
+CONFORMANCE_DEPS = [
+    "Google.Protobuf.dll",
+    "Google.Protobuf.Conformance.deps.json",
+    "Google.Protobuf.Conformance.pdb",
+    "Google.Protobuf.Conformance.runtimeconfig.json",
+    "Google.Protobuf.Test.dll",
+    "Google.Protobuf.Test.TestProtos.dll",
+    "Microsoft.TestPlatform.CommunicationUtilities.dll",
+    "Microsoft.TestPlatform.CoreUtilities.dll",
+    "Microsoft.TestPlatform.CrossPlatEngine.dll",
+    "Microsoft.TestPlatform.PlatformAbstractions.dll",
+    "Microsoft.TestPlatform.Utilities.dll",
+    "Microsoft.VisualStudio.CodeCoverage.Shim.dll",
+    "Microsoft.VisualStudio.TestPlatform.Common.dll",
+    "Microsoft.VisualStudio.TestPlatform.ObjectModel.dll",
+    "NUnit3.TestAdapter.dll",
+    "Newtonsoft.Json.dll",
+    "NuGet.Frameworks.dll",
+    "nunit.engine.api.dll",
+    "nunit.engine.core.dll",
+    "nunit.engine.dll",
+    "nunit.framework.dll",
+    "testcentric.engine.metadata.dll",
+    "testhost.dll",
+]
+
+filegroup(
+    name = "srcs",
+    srcs = [
+        "Conformance.cs",
+        "Program.cs",
+        "Google.Protobuf.Conformance.csproj",
+    ],
+    visibility = [
+        "//csharp:__subpackages__",
+    ],
+)
+
+genrule(
+    name = "package_conformance_test",
+    srcs = [
+        "Program.cs",
+        "Google.Protobuf.Conformance.csproj",
+        "//conformance:conformance_csharp_proto",
+        "//csharp:srcs",
+    ],
+    visibility = ["//visibility:private"],
+    tools = [":build_conformance_test"],
+    outs = CONFORMANCE_DEPS + ["Google.Protobuf.Conformance.dll"],
+    cmd = """
+        SRCDIR=$$(dirname $(location :Program.cs))
+        cp $(location //conformance:conformance_csharp_proto) $$SRCDIR
+        DOTNET_CLI_HOME=/tmp ./$(location :build_conformance_test)
+        cp -r $$SRCDIR/bin/Release/netcoreapp3.1/* $(RULEDIR)
+    """,
+)
+
+filegroup(
+    name = "conformance_dll",
+    srcs = ["Google.Protobuf.Conformance.dll"],
+    data = [":package_conformance_test"],
+    visibility = ["//conformance:__subpackages__"],
+)
+
+filegroup(
+    name = "conformance_runfiles",
+    srcs = CONFORMANCE_DEPS,
+    data = [":package_conformance_test"],
+    visibility = ["//conformance:__subpackages__"],
+)
+
+################################################################################
+# Distribution files
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = [
+        "BUILD.bazel",
+        "Google.Protobuf.Conformance.csproj",
+        "Conformance.cs",
+        "Program.cs",
+    ],
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//csharp:__pkg__"],
+)
+
diff --git a/csharp/src/Google.Protobuf.Conformance/Conformance.cs b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
index 79977a0..77fd9c9 100644
--- a/csharp/src/Google.Protobuf.Conformance/Conformance.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Conformance.cs
@@ -64,7 +64,7 @@
     [pbr::OriginalName("PROTOBUF")] Protobuf = 1,
     [pbr::OriginalName("JSON")] Json = 2,
     /// <summary>
-    /// Google internal only. Opensource testees just skip it.
+    /// Only used inside Google. Opensource testees just skip it.
     /// </summary>
     [pbr::OriginalName("JSPB")] Jspb = 3,
     [pbr::OriginalName("TEXT_FORMAT")] TextFormat = 4,
@@ -89,7 +89,7 @@
     /// </summary>
     [pbr::OriginalName("JSON_IGNORE_UNKNOWN_PARSING_TEST")] JsonIgnoreUnknownParsingTest = 3,
     /// <summary>
-    /// Test jspb wire format. Google internal only. Opensource testees just skip it.
+    /// Test jspb wire format. Only used inside Google. Opensource testees just skip it.
     /// </summary>
     [pbr::OriginalName("JSPB_TEST")] JspbTest = 4,
     /// <summary>
@@ -382,7 +382,7 @@
     /// <summary>Field number for the "jspb_payload" field.</summary>
     public const int JspbPayloadFieldNumber = 7;
     /// <summary>
-    /// Google internal only.  Opensource testees just skip it.
+    /// Only used inside google.  Opensource testees just skip it.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -1026,8 +1026,8 @@
     public const int JspbPayloadFieldNumber = 7;
     /// <summary>
     /// If the input was successfully parsed and the requested output was JSPB,
-    /// serialize to JSPB and set it in this field. JSPB is google internal only
-    /// format. Opensource testees can just skip it.
+    /// serialize to JSPB and set it in this field. JSPB is only used inside
+    /// Google. Opensource testees can just skip it.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
diff --git a/csharp/src/Google.Protobuf.Conformance/Program.cs b/csharp/src/Google.Protobuf.Conformance/Program.cs
index d721ecf..1c2e9ae 100644
--- a/csharp/src/Google.Protobuf.Conformance/Program.cs
+++ b/csharp/src/Google.Protobuf.Conformance/Program.cs
@@ -43,7 +43,7 @@
     /// </summary>
     class Program
     {
-        private static void Main(string[] args)
+        private static void Main()
         {
             // This way we get the binary streams instead of readers/writers.
             var input = new BinaryReader(Console.OpenStandardInput());
@@ -100,32 +100,22 @@
                             return new ConformanceResponse { Skipped = "CSharp doesn't support skipping unknown fields in json parsing." };
                         }
                         var parser = new JsonParser(new JsonParser.Settings(20, typeRegistry));
-                        switch (request.MessageType)
+                        message = request.MessageType switch
                         {
-                            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})");
-                        }
+                            "protobuf_test_messages.proto3.TestAllTypesProto3" => parser.Parse<ProtobufTestMessages.Proto3.TestAllTypesProto3>(request.JsonPayload),
+                            "protobuf_test_messages.proto2.TestAllTypesProto2" => parser.Parse<ProtobufTestMessages.Proto2.TestAllTypesProto2>(request.JsonPayload),
+                            _ => throw new Exception($" Protobuf request doesn't have specific payload type ({request.MessageType})"),
+                        };
                         break;
                     case ConformanceRequest.PayloadOneofCase.ProtobufPayload:
-                        switch (request.MessageType)
+                        message = request.MessageType switch
                         {
-                            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})");
-                        }
+                            "protobuf_test_messages.proto3.TestAllTypesProto3" => ProtobufTestMessages.Proto3.TestAllTypesProto3.Parser.ParseFrom(request.ProtobufPayload),
+                            "protobuf_test_messages.proto2.TestAllTypesProto2" => ProtobufTestMessages.Proto2.TestAllTypesProto2.Parser
+                                                                .WithExtensionRegistry(proto2ExtensionRegistry)
+                                                                .ParseFrom(request.ProtobufPayload),
+                            _ => 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" };
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 8d9d64b..3d0ba71 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
@@ -7,7 +7,7 @@
   -->
   <PropertyGroup>
     <TargetFrameworks>net462;netstandard1.1;netstandard2.0</TargetFrameworks>
-    <LangVersion>3.0</LangVersion>
+    <LangVersion>10.0</LangVersion>
     <AssemblyOriginatorKeyFile>../../keys/Google.Protobuf.snk</AssemblyOriginatorKeyFile>
     <SignAssembly>true</SignAssembly>
     <IsPackable>False</IsPackable>
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.pb.cs
similarity index 97%
rename from csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.pb.cs
index 57e59a9..d3284a4 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/MapUnittestProto3.pb.cs
@@ -580,23 +580,23 @@
       if (other == null) {
         return;
       }
-      mapInt32Int32_.Add(other.mapInt32Int32_);
-      mapInt64Int64_.Add(other.mapInt64Int64_);
-      mapUint32Uint32_.Add(other.mapUint32Uint32_);
-      mapUint64Uint64_.Add(other.mapUint64Uint64_);
-      mapSint32Sint32_.Add(other.mapSint32Sint32_);
-      mapSint64Sint64_.Add(other.mapSint64Sint64_);
-      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
-      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
-      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
-      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
-      mapInt32Float_.Add(other.mapInt32Float_);
-      mapInt32Double_.Add(other.mapInt32Double_);
-      mapBoolBool_.Add(other.mapBoolBool_);
-      mapStringString_.Add(other.mapStringString_);
-      mapInt32Bytes_.Add(other.mapInt32Bytes_);
-      mapInt32Enum_.Add(other.mapInt32Enum_);
-      mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+      mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
+      mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
+      mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
+      mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
+      mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
+      mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.MergeFrom(other.mapInt32Float_);
+      mapInt32Double_.MergeFrom(other.mapInt32Double_);
+      mapBoolBool_.MergeFrom(other.mapBoolBool_);
+      mapStringString_.MergeFrom(other.mapStringString_);
+      mapInt32Bytes_.MergeFrom(other.mapInt32Bytes_);
+      mapInt32Enum_.MergeFrom(other.mapInt32Enum_);
+      mapInt32ForeignMessage_.MergeFrom(other.mapInt32ForeignMessage_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
@@ -1100,7 +1100,7 @@
       if (other == null) {
         return;
       }
-      mapInt32Message_.Add(other.mapInt32Message_);
+      mapInt32Message_.MergeFrom(other.mapInt32Message_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
@@ -1298,8 +1298,8 @@
       if (other == null) {
         return;
       }
-      map1_.Add(other.map1_);
-      map2_.Add(other.map2_);
+      map1_.MergeFrom(other.map1_);
+      map2_.MergeFrom(other.map2_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
@@ -1723,21 +1723,21 @@
       if (other == null) {
         return;
       }
-      mapInt32Int32_.Add(other.mapInt32Int32_);
-      mapInt64Int64_.Add(other.mapInt64Int64_);
-      mapUint32Uint32_.Add(other.mapUint32Uint32_);
-      mapUint64Uint64_.Add(other.mapUint64Uint64_);
-      mapSint32Sint32_.Add(other.mapSint32Sint32_);
-      mapSint64Sint64_.Add(other.mapSint64Sint64_);
-      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
-      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
-      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
-      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
-      mapInt32Float_.Add(other.mapInt32Float_);
-      mapInt32Double_.Add(other.mapInt32Double_);
-      mapBoolBool_.Add(other.mapBoolBool_);
-      mapInt32Enum_.Add(other.mapInt32Enum_);
-      mapInt32ForeignMessage_.Add(other.mapInt32ForeignMessage_);
+      mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
+      mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
+      mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
+      mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
+      mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
+      mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.MergeFrom(other.mapInt32Float_);
+      mapInt32Double_.MergeFrom(other.mapInt32Double_);
+      mapBoolBool_.MergeFrom(other.mapBoolBool_);
+      mapInt32Enum_.MergeFrom(other.mapInt32Enum_);
+      mapInt32ForeignMessage_.MergeFrom(other.mapInt32ForeignMessage_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
@@ -2031,7 +2031,7 @@
       if (other == null) {
         return;
       }
-      type_.Add(other.type_);
+      type_.MergeFrom(other.type_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
@@ -2224,7 +2224,7 @@
       if (other == null) {
         return;
       }
-      entry_.Add(other.entry_);
+      entry_.MergeFrom(other.entry_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.pb.cs
similarity index 96%
rename from csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.pb.cs
index 35f2b8a..bbfe2e0 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto2.pb.cs
@@ -213,12 +213,14 @@
             "dGlvbmFsX2Jvb2wY7gcgASgIEhcKDnJlcGVhdGVkX2ludDMyGPMHIAMoBRoa",
             "Cg1PcHRpb25hbEdyb3VwEgkKAWEYASABKAUiFgoUTnVsbEh5cG90aGVzaXNQ",
             "cm90bzIiLwoORW51bU9ubHlQcm90bzIiHQoEQm9vbBIKCgZrRmFsc2UQABIJ",
-            "CgVrVHJ1ZRABIh8KD09uZVN0cmluZ1Byb3RvMhIMCgRkYXRhGAEgASgJKkYK",
-            "EUZvcmVpZ25FbnVtUHJvdG8yEg8KC0ZPUkVJR05fRk9PEAASDwoLRk9SRUlH",
-            "Tl9CQVIQARIPCgtGT1JFSUdOX0JBWhACOkoKD2V4dGVuc2lvbl9pbnQzMhIx",
-            "LnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1By",
-            "b3RvMhh4IAEoBUIvCihjb20uZ29vZ2xlLnByb3RvYnVmX3Rlc3RfbWVzc2Fn",
-            "ZXMucHJvdG8ySAH4AQE="));
+            "CgVrVHJ1ZRABIh8KD09uZVN0cmluZ1Byb3RvMhIMCgRkYXRhGAEgASgJIkYK",
+            "EVByb3RvV2l0aEtleXdvcmRzEg4KBmlubGluZRgBIAEoBRIPCgdjb25jZXB0",
+            "GAIgASgJEhAKCHJlcXVpcmVzGAMgAygJKkYKEUZvcmVpZ25FbnVtUHJvdG8y",
+            "Eg8KC0ZPUkVJR05fRk9PEAASDwoLRk9SRUlHTl9CQVIQARIPCgtGT1JFSUdO",
+            "X0JBWhACOkoKD2V4dGVuc2lvbl9pbnQzMhIxLnByb3RvYnVmX3Rlc3RfbWVz",
+            "c2FnZXMucHJvdG8yLlRlc3RBbGxUeXBlc1Byb3RvMhh4IAEoBUI4Cihjb20u",
+            "Z29vZ2xlLnByb3RvYnVmX3Rlc3RfbWVzc2FnZXMucHJvdG8ySAH4AQGiAgZQ",
+            "cm90bzI="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(new[] {typeof(global::ProtobufTestMessages.Proto2.ForeignEnumProto2), }, new pb::Extension[] { TestMessagesProto2Extensions.ExtensionInt32 }, new pbr::GeneratedClrTypeInfo[] {
@@ -231,7 +233,8 @@
             new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes), global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Parser, new[]{ "OptionalInt32", "OptionalString", "NestedMessage", "OptionalGroup", "OptionalBool", "RepeatedInt32" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup), global::ProtobufTestMessages.Proto2.UnknownToTestAllTypes.Types.OptionalGroup.Parser, new[]{ "A" }, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.NullHypothesisProto2), global::ProtobufTestMessages.Proto2.NullHypothesisProto2.Parser, null, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.EnumOnlyProto2), global::ProtobufTestMessages.Proto2.EnumOnlyProto2.Parser, null, null, new[]{ typeof(global::ProtobufTestMessages.Proto2.EnumOnlyProto2.Types.Bool) }, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.OneStringProto2), global::ProtobufTestMessages.Proto2.OneStringProto2.Parser, new[]{ "Data" }, null, null, null, null)
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.OneStringProto2), global::ProtobufTestMessages.Proto2.OneStringProto2.Parser, new[]{ "Data" }, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::ProtobufTestMessages.Proto2.ProtoWithKeywords), global::ProtobufTestMessages.Proto2.ProtoWithKeywords.Parser, new[]{ "Inline", "Concept", "Requires" }, null, null, null, null)
           }));
     }
     #endregion
@@ -4342,25 +4345,25 @@
       unpackedDouble_.Add(other.unpackedDouble_);
       unpackedBool_.Add(other.unpackedBool_);
       unpackedNestedEnum_.Add(other.unpackedNestedEnum_);
-      mapInt32Int32_.Add(other.mapInt32Int32_);
-      mapInt64Int64_.Add(other.mapInt64Int64_);
-      mapUint32Uint32_.Add(other.mapUint32Uint32_);
-      mapUint64Uint64_.Add(other.mapUint64Uint64_);
-      mapSint32Sint32_.Add(other.mapSint32Sint32_);
-      mapSint64Sint64_.Add(other.mapSint64Sint64_);
-      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
-      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
-      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
-      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
-      mapInt32Float_.Add(other.mapInt32Float_);
-      mapInt32Double_.Add(other.mapInt32Double_);
-      mapBoolBool_.Add(other.mapBoolBool_);
-      mapStringString_.Add(other.mapStringString_);
-      mapStringBytes_.Add(other.mapStringBytes_);
-      mapStringNestedMessage_.Add(other.mapStringNestedMessage_);
-      mapStringForeignMessage_.Add(other.mapStringForeignMessage_);
-      mapStringNestedEnum_.Add(other.mapStringNestedEnum_);
-      mapStringForeignEnum_.Add(other.mapStringForeignEnum_);
+      mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
+      mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
+      mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
+      mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
+      mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
+      mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.MergeFrom(other.mapInt32Float_);
+      mapInt32Double_.MergeFrom(other.mapInt32Double_);
+      mapBoolBool_.MergeFrom(other.mapBoolBool_);
+      mapStringString_.MergeFrom(other.mapStringString_);
+      mapStringBytes_.MergeFrom(other.mapStringBytes_);
+      mapStringNestedMessage_.MergeFrom(other.mapStringNestedMessage_);
+      mapStringForeignMessage_.MergeFrom(other.mapStringForeignMessage_);
+      mapStringNestedEnum_.MergeFrom(other.mapStringNestedEnum_);
+      mapStringForeignEnum_.MergeFrom(other.mapStringForeignEnum_);
       if (other.HasData) {
         if (!HasData) {
           Data = new global::ProtobufTestMessages.Proto2.TestAllTypesProto2.Types.Data();
@@ -8300,6 +8303,289 @@
 
   }
 
+  public sealed partial class ProtoWithKeywords : pb::IMessage<ProtoWithKeywords>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<ProtoWithKeywords> _parser = new pb::MessageParser<ProtoWithKeywords>(() => new ProtoWithKeywords());
+    private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<ProtoWithKeywords> 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[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 ProtoWithKeywords() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ProtoWithKeywords(ProtoWithKeywords other) : this() {
+      _hasBits0 = other._hasBits0;
+      inline_ = other.inline_;
+      concept_ = other.concept_;
+      requires_ = other.requires_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ProtoWithKeywords Clone() {
+      return new ProtoWithKeywords(this);
+    }
+
+    /// <summary>Field number for the "inline" field.</summary>
+    public const int InlineFieldNumber = 1;
+    private readonly static int InlineDefaultValue = 0;
+
+    private int inline_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Inline {
+      get { if ((_hasBits0 & 1) != 0) { return inline_; } else { return InlineDefaultValue; } }
+      set {
+        _hasBits0 |= 1;
+        inline_ = value;
+      }
+    }
+    /// <summary>Gets whether the "inline" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasInline {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "inline" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearInline() {
+      _hasBits0 &= ~1;
+    }
+
+    /// <summary>Field number for the "concept" field.</summary>
+    public const int ConceptFieldNumber = 2;
+    private readonly static string ConceptDefaultValue = "";
+
+    private string concept_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string Concept {
+      get { return concept_ ?? ConceptDefaultValue; }
+      set {
+        concept_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "concept" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasConcept {
+      get { return concept_ != null; }
+    }
+    /// <summary>Clears the value of the "concept" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearConcept() {
+      concept_ = null;
+    }
+
+    /// <summary>Field number for the "requires" field.</summary>
+    public const int RequiresFieldNumber = 3;
+    private static readonly pb::FieldCodec<string> _repeated_requires_codec
+        = pb::FieldCodec.ForString(26);
+    private readonly pbc::RepeatedField<string> requires_ = new pbc::RepeatedField<string>();
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pbc::RepeatedField<string> Requires {
+      get { return requires_; }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as ProtoWithKeywords);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(ProtoWithKeywords other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Inline != other.Inline) return false;
+      if (Concept != other.Concept) return false;
+      if(!requires_.Equals(other.requires_)) 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 (HasInline) hash ^= Inline.GetHashCode();
+      if (HasConcept) hash ^= Concept.GetHashCode();
+      hash ^= requires_.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 (HasInline) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Inline);
+      }
+      if (HasConcept) {
+        output.WriteRawTag(18);
+        output.WriteString(Concept);
+      }
+      requires_.WriteTo(output, _repeated_requires_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) {
+      if (HasInline) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Inline);
+      }
+      if (HasConcept) {
+        output.WriteRawTag(18);
+        output.WriteString(Concept);
+      }
+      requires_.WriteTo(ref output, _repeated_requires_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 (HasInline) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Inline);
+      }
+      if (HasConcept) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Concept);
+      }
+      size += requires_.CalculateSize(_repeated_requires_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(ProtoWithKeywords other) {
+      if (other == null) {
+        return;
+      }
+      if (other.HasInline) {
+        Inline = other.Inline;
+      }
+      if (other.HasConcept) {
+        Concept = other.Concept;
+      }
+      requires_.Add(other.requires_);
+      _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: {
+            Inline = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            Concept = input.ReadString();
+            break;
+          }
+          case 26: {
+            requires_.AddEntriesFrom(input, _repeated_requires_codec);
+            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: {
+            Inline = input.ReadInt32();
+            break;
+          }
+          case 18: {
+            Concept = input.ReadString();
+            break;
+          }
+          case 26: {
+            requires_.AddEntriesFrom(ref input, _repeated_requires_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
   #endregion
 
 }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.pb.cs
similarity index 99%
rename from csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.pb.cs
index 520216f..74e2a57 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/TestMessagesProto3.pb.cs
@@ -3753,25 +3753,25 @@
       unpackedDouble_.Add(other.unpackedDouble_);
       unpackedBool_.Add(other.unpackedBool_);
       unpackedNestedEnum_.Add(other.unpackedNestedEnum_);
-      mapInt32Int32_.Add(other.mapInt32Int32_);
-      mapInt64Int64_.Add(other.mapInt64Int64_);
-      mapUint32Uint32_.Add(other.mapUint32Uint32_);
-      mapUint64Uint64_.Add(other.mapUint64Uint64_);
-      mapSint32Sint32_.Add(other.mapSint32Sint32_);
-      mapSint64Sint64_.Add(other.mapSint64Sint64_);
-      mapFixed32Fixed32_.Add(other.mapFixed32Fixed32_);
-      mapFixed64Fixed64_.Add(other.mapFixed64Fixed64_);
-      mapSfixed32Sfixed32_.Add(other.mapSfixed32Sfixed32_);
-      mapSfixed64Sfixed64_.Add(other.mapSfixed64Sfixed64_);
-      mapInt32Float_.Add(other.mapInt32Float_);
-      mapInt32Double_.Add(other.mapInt32Double_);
-      mapBoolBool_.Add(other.mapBoolBool_);
-      mapStringString_.Add(other.mapStringString_);
-      mapStringBytes_.Add(other.mapStringBytes_);
-      mapStringNestedMessage_.Add(other.mapStringNestedMessage_);
-      mapStringForeignMessage_.Add(other.mapStringForeignMessage_);
-      mapStringNestedEnum_.Add(other.mapStringNestedEnum_);
-      mapStringForeignEnum_.Add(other.mapStringForeignEnum_);
+      mapInt32Int32_.MergeFrom(other.mapInt32Int32_);
+      mapInt64Int64_.MergeFrom(other.mapInt64Int64_);
+      mapUint32Uint32_.MergeFrom(other.mapUint32Uint32_);
+      mapUint64Uint64_.MergeFrom(other.mapUint64Uint64_);
+      mapSint32Sint32_.MergeFrom(other.mapSint32Sint32_);
+      mapSint64Sint64_.MergeFrom(other.mapSint64Sint64_);
+      mapFixed32Fixed32_.MergeFrom(other.mapFixed32Fixed32_);
+      mapFixed64Fixed64_.MergeFrom(other.mapFixed64Fixed64_);
+      mapSfixed32Sfixed32_.MergeFrom(other.mapSfixed32Sfixed32_);
+      mapSfixed64Sfixed64_.MergeFrom(other.mapSfixed64Sfixed64_);
+      mapInt32Float_.MergeFrom(other.mapInt32Float_);
+      mapInt32Double_.MergeFrom(other.mapInt32Double_);
+      mapBoolBool_.MergeFrom(other.mapBoolBool_);
+      mapStringString_.MergeFrom(other.mapStringString_);
+      mapStringBytes_.MergeFrom(other.mapStringBytes_);
+      mapStringNestedMessage_.MergeFrom(other.mapStringNestedMessage_);
+      mapStringForeignMessage_.MergeFrom(other.mapStringForeignMessage_);
+      mapStringNestedEnum_.MergeFrom(other.mapStringNestedEnum_);
+      mapStringForeignEnum_.MergeFrom(other.mapStringForeignEnum_);
       if (other.optionalBoolWrapper_ != null) {
         if (optionalBoolWrapper_ == null || other.OptionalBoolWrapper != false) {
           OptionalBoolWrapper = other.OptionalBoolWrapper;
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.pb.cs
similarity index 99%
rename from csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/Unittest.pb.cs
index c1f43ce..7f1aca1 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/Unittest.pb.cs
@@ -24112,7 +24112,7 @@
       if (other == null) {
         return;
       }
-      foo_.Add(other.foo_);
+      foo_.MergeFrom(other.foo_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
@@ -30708,7 +30708,7 @@
         }
         OptionalGroup.MergeFrom(other.OptionalGroup);
       }
-      stringStringMap_.Add(other.stringStringMap_);
+      stringStringMap_.MergeFrom(other.stringStringMap_);
       switch (other.OneofFieldCase) {
         case OneofFieldOneofCase.OneofUint32:
           OneofUint32 = other.OneofUint32;
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestCustomOptionsProto3.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestImport.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportProto3.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublic.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestImportPublicProto3.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936A.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936B.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssue6936C.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.pb.cs
similarity index 87%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.pb.cs
index 3fe2dd6..3278517 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestIssues.pb.cs
@@ -30,37 +30,44 @@
             "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",
-            "QhEKD19vcHRpb25hbF9maWVsZCI5ChJPbmVvZldpdGhOb25lRmllbGQSCwoB",
-            "eBgBIAEoCUgAEg4KBG5vbmUYAiABKAlIAEIGCgR0ZXN0IjUKEU9uZW9mV2l0",
-            "aE5vbmVOYW1lEgsKAXgYASABKAlIABILCgF5GAIgASgJSABCBgoEbm9uZSpV",
-            "CgxOZWdhdGl2ZUVudW0SFgoSTkVHQVRJVkVfRU5VTV9aRVJPEAASFgoJRml2",
-            "ZUJlbG93EPv//////////wESFQoITWludXNPbmUQ////////////ASouCg5E",
-            "ZXByZWNhdGVkRW51bRITCg9ERVBSRUNBVEVEX1pFUk8QABIHCgNvbmUQAUId",
-            "qgIaVW5pdFRlc3QuSXNzdWVzLlRlc3RQcm90b3NiBnByb3RvMw=="));
+            "dWVzLk5lZ2F0aXZlRW51bUICEAEiFQoPRGVwcmVjYXRlZENoaWxkOgIYASK5",
+            "AgoXRGVwcmVjYXRlZEZpZWxkc01lc3NhZ2USGgoOUHJpbWl0aXZlVmFsdWUY",
+            "ASABKAVCAhgBEhoKDlByaW1pdGl2ZUFycmF5GAIgAygFQgIYARI6CgxNZXNz",
+            "YWdlVmFsdWUYAyABKAsyIC51bml0dGVzdF9pc3N1ZXMuRGVwcmVjYXRlZENo",
+            "aWxkQgIYARI6CgxNZXNzYWdlQXJyYXkYBCADKAsyIC51bml0dGVzdF9pc3N1",
+            "ZXMuRGVwcmVjYXRlZENoaWxkQgIYARI2CglFbnVtVmFsdWUYBSABKA4yHy51",
+            "bml0dGVzdF9pc3N1ZXMuRGVwcmVjYXRlZEVudW1CAhgBEjYKCUVudW1BcnJh",
+            "eRgGIAMoDjIfLnVuaXR0ZXN0X2lzc3Vlcy5EZXByZWNhdGVkRW51bUICGAEi",
+            "GQoJSXRlbUZpZWxkEgwKBGl0ZW0YASABKAUiRAoNUmVzZXJ2ZWROYW1lcxIN",
+            "CgV0eXBlcxgBIAEoBRISCgpkZXNjcmlwdG9yGAIgASgFGhAKDlNvbWVOZXN0",
+            "ZWRUeXBlIqABChVUZXN0SnNvbkZpZWxkT3JkZXJpbmcSEwoLcGxhaW5faW50",
+            "MzIYBCABKAUSEwoJbzFfc3RyaW5nGAIgASgJSAASEgoIbzFfaW50MzIYBSAB",
+            "KAVIABIUCgxwbGFpbl9zdHJpbmcYASABKAkSEgoIbzJfaW50MzIYBiABKAVI",
+            "ARITCglvMl9zdHJpbmcYAyABKAlIAUIECgJvMUIECgJvMiJLCgxUZXN0SnNv",
+            "bk5hbWUSDAoEbmFtZRgBIAEoCRIZCgtkZXNjcmlwdGlvbhgCIAEoCVIEZGVz",
+            "YxISCgRndWlkGAMgASgJUgRleGlkIn8KDE9uZW9mTWVyZ2luZxIOCgR0ZXh0",
+            "GAEgASgJSAASNgoGbmVzdGVkGAIgASgLMiQudW5pdHRlc3RfaXNzdWVzLk9u",
+            "ZW9mTWVyZ2luZy5OZXN0ZWRIABoeCgZOZXN0ZWQSCQoBeBgBIAEoBRIJCgF5",
+            "GAIgASgFQgcKBXZhbHVlImsKFk51bGxWYWx1ZU91dHNpZGVTdHJ1Y3QSFgoM",
+            "c3RyaW5nX3ZhbHVlGAEgASgJSAASMAoKbnVsbF92YWx1ZRgCIAEoDjIaLmdv",
+            "b2dsZS5wcm90b2J1Zi5OdWxsVmFsdWVIAEIHCgV2YWx1ZSJFChNOdWxsVmFs",
+            "dWVOb3RJbk9uZW9mEi4KCm51bGxfdmFsdWUYAiABKA4yGi5nb29nbGUucHJv",
+            "dG9idWYuTnVsbFZhbHVlImAKF01peGVkUmVndWxhckFuZE9wdGlvbmFsEhUK",
+            "DXJlZ3VsYXJfZmllbGQYASABKAkSGwoOb3B0aW9uYWxfZmllbGQYAiABKAlI",
+            "AIgBAUIRCg9fb3B0aW9uYWxfZmllbGQiOQoST25lb2ZXaXRoTm9uZUZpZWxk",
+            "EgsKAXgYASABKAlIABIOCgRub25lGAIgASgJSABCBgoEdGVzdCI1ChFPbmVv",
+            "ZldpdGhOb25lTmFtZRILCgF4GAEgASgJSAASCwoBeRgCIAEoCUgAQgYKBG5v",
+            "bmUikwIKGURpc2FtYmlndWF0ZUNvbW1vbk1lbWJlcnMSIwobZGlzYW1iaWd1",
+            "YXRlX2NvbW1vbl9tZW1iZXJzGAEgASgFEg0KBXR5cGVzGAIgASgFEhIKCmRl",
+            "c2NyaXB0b3IYAyABKAUSDgoGZXF1YWxzGAQgASgFEhEKCXRvX3N0cmluZxgF",
+            "IAEoBRIVCg1nZXRfaGFzaF9jb2RlGAYgASgFEhAKCHdyaXRlX3RvGAcgASgF",
+            "Eg0KBWNsb25lGAggASgFEhYKDmNhbGN1bGF0ZV9zaXplGAkgASgFEhIKCm1l",
+            "cmdlX2Zyb20YCiABKAUSFwoPb25fY29uc3RydWN0aW9uGAsgASgFEg4KBnBh",
+            "cnNlchgMIAEoBSpVCgxOZWdhdGl2ZUVudW0SFgoSTkVHQVRJVkVfRU5VTV9a",
+            "RVJPEAASFgoJRml2ZUJlbG93EPv//////////wESFQoITWludXNPbmUQ////",
+            "////////ASo2Cg5EZXByZWNhdGVkRW51bRIXCg9ERVBSRUNBVEVEX1pFUk8Q",
+            "ABoCCAESBwoDb25lEAEaAhgBQh2qAhpVbml0VGVzdC5Jc3N1ZXMuVGVzdFBy",
+            "b3Rvc2IGcHJvdG8z"));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           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[] {
@@ -77,7 +84,8 @@
             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),
             new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofWithNoneField), global::UnitTest.Issues.TestProtos.OneofWithNoneField.Parser, new[]{ "X", "None" }, new[]{ "Test" }, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofWithNoneName), global::UnitTest.Issues.TestProtos.OneofWithNoneName.Parser, new[]{ "X", "Y" }, new[]{ "None" }, null, null, null)
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.OneofWithNoneName), global::UnitTest.Issues.TestProtos.OneofWithNoneName.Parser, new[]{ "X", "Y" }, new[]{ "None" }, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::UnitTest.Issues.TestProtos.DisambiguateCommonMembers), global::UnitTest.Issues.TestProtos.DisambiguateCommonMembers.Parser, new[]{ "DisambiguateCommonMembers_", "Types_", "Descriptor_", "Equals_", "ToString_", "GetHashCode_", "WriteTo_", "Clone_", "CalculateSize_", "MergeFrom_", "OnConstruction_", "Parser_" }, null, null, null, null)
           }));
     }
     #endregion
@@ -90,7 +98,9 @@
     [pbr::OriginalName("MinusOne")] MinusOne = -1,
   }
 
+  [global::System.ObsoleteAttribute]
   public enum DeprecatedEnum {
+    [global::System.ObsoleteAttribute]
     [pbr::OriginalName("DEPRECATED_ZERO")] DeprecatedZero = 0,
     [pbr::OriginalName("one")] One = 1,
   }
@@ -819,6 +829,7 @@
 
   }
 
+  [global::System.ObsoleteAttribute]
   public sealed partial class DeprecatedChild : pb::IMessage<DeprecatedChild>
   #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
       , pb::IBufferMessage
@@ -4347,6 +4358,605 @@
 
   }
 
+  /// <summary>
+  /// Issue 8810
+  /// </summary>
+  public sealed partial class DisambiguateCommonMembers : pb::IMessage<DisambiguateCommonMembers>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<DisambiguateCommonMembers> _parser = new pb::MessageParser<DisambiguateCommonMembers>(() => new DisambiguateCommonMembers());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<DisambiguateCommonMembers> 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[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 DisambiguateCommonMembers() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public DisambiguateCommonMembers(DisambiguateCommonMembers other) : this() {
+      disambiguateCommonMembers_ = other.disambiguateCommonMembers_;
+      types_ = other.types_;
+      descriptor_ = other.descriptor_;
+      equals_ = other.equals_;
+      toString_ = other.toString_;
+      getHashCode_ = other.getHashCode_;
+      writeTo_ = other.writeTo_;
+      clone_ = other.clone_;
+      calculateSize_ = other.calculateSize_;
+      mergeFrom_ = other.mergeFrom_;
+      onConstruction_ = other.onConstruction_;
+      parser_ = other.parser_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public DisambiguateCommonMembers Clone() {
+      return new DisambiguateCommonMembers(this);
+    }
+
+    /// <summary>Field number for the "disambiguate_common_members" field.</summary>
+    public const int DisambiguateCommonMembers_FieldNumber = 1;
+    private int disambiguateCommonMembers_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int DisambiguateCommonMembers_ {
+      get { return disambiguateCommonMembers_; }
+      set {
+        disambiguateCommonMembers_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "types" field.</summary>
+    public const int Types_FieldNumber = 2;
+    private int types_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Types_ {
+      get { return types_; }
+      set {
+        types_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "descriptor" field.</summary>
+    public const int Descriptor_FieldNumber = 3;
+    private int descriptor_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Descriptor_ {
+      get { return descriptor_; }
+      set {
+        descriptor_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "equals" field.</summary>
+    public const int Equals_FieldNumber = 4;
+    private int equals_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Equals_ {
+      get { return equals_; }
+      set {
+        equals_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "to_string" field.</summary>
+    public const int ToString_FieldNumber = 5;
+    private int toString_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int ToString_ {
+      get { return toString_; }
+      set {
+        toString_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "get_hash_code" field.</summary>
+    public const int GetHashCode_FieldNumber = 6;
+    private int getHashCode_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int GetHashCode_ {
+      get { return getHashCode_; }
+      set {
+        getHashCode_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "write_to" field.</summary>
+    public const int WriteTo_FieldNumber = 7;
+    private int writeTo_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int WriteTo_ {
+      get { return writeTo_; }
+      set {
+        writeTo_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "clone" field.</summary>
+    public const int Clone_FieldNumber = 8;
+    private int clone_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Clone_ {
+      get { return clone_; }
+      set {
+        clone_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "calculate_size" field.</summary>
+    public const int CalculateSize_FieldNumber = 9;
+    private int calculateSize_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int CalculateSize_ {
+      get { return calculateSize_; }
+      set {
+        calculateSize_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "merge_from" field.</summary>
+    public const int MergeFrom_FieldNumber = 10;
+    private int mergeFrom_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int MergeFrom_ {
+      get { return mergeFrom_; }
+      set {
+        mergeFrom_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "on_construction" field.</summary>
+    public const int OnConstruction_FieldNumber = 11;
+    private int onConstruction_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int OnConstruction_ {
+      get { return onConstruction_; }
+      set {
+        onConstruction_ = value;
+      }
+    }
+
+    /// <summary>Field number for the "parser" field.</summary>
+    public const int Parser_FieldNumber = 12;
+    private int parser_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Parser_ {
+      get { return parser_; }
+      set {
+        parser_ = value;
+      }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as DisambiguateCommonMembers);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(DisambiguateCommonMembers other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (DisambiguateCommonMembers_ != other.DisambiguateCommonMembers_) return false;
+      if (Types_ != other.Types_) return false;
+      if (Descriptor_ != other.Descriptor_) return false;
+      if (Equals_ != other.Equals_) return false;
+      if (ToString_ != other.ToString_) return false;
+      if (GetHashCode_ != other.GetHashCode_) return false;
+      if (WriteTo_ != other.WriteTo_) return false;
+      if (Clone_ != other.Clone_) return false;
+      if (CalculateSize_ != other.CalculateSize_) return false;
+      if (MergeFrom_ != other.MergeFrom_) return false;
+      if (OnConstruction_ != other.OnConstruction_) return false;
+      if (Parser_ != other.Parser_) 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 (DisambiguateCommonMembers_ != 0) hash ^= DisambiguateCommonMembers_.GetHashCode();
+      if (Types_ != 0) hash ^= Types_.GetHashCode();
+      if (Descriptor_ != 0) hash ^= Descriptor_.GetHashCode();
+      if (Equals_ != 0) hash ^= Equals_.GetHashCode();
+      if (ToString_ != 0) hash ^= ToString_.GetHashCode();
+      if (GetHashCode_ != 0) hash ^= GetHashCode_.GetHashCode();
+      if (WriteTo_ != 0) hash ^= WriteTo_.GetHashCode();
+      if (Clone_ != 0) hash ^= Clone_.GetHashCode();
+      if (CalculateSize_ != 0) hash ^= CalculateSize_.GetHashCode();
+      if (MergeFrom_ != 0) hash ^= MergeFrom_.GetHashCode();
+      if (OnConstruction_ != 0) hash ^= OnConstruction_.GetHashCode();
+      if (Parser_ != 0) hash ^= Parser_.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 (DisambiguateCommonMembers_ != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(DisambiguateCommonMembers_);
+      }
+      if (Types_ != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Types_);
+      }
+      if (Descriptor_ != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Descriptor_);
+      }
+      if (Equals_ != 0) {
+        output.WriteRawTag(32);
+        output.WriteInt32(Equals_);
+      }
+      if (ToString_ != 0) {
+        output.WriteRawTag(40);
+        output.WriteInt32(ToString_);
+      }
+      if (GetHashCode_ != 0) {
+        output.WriteRawTag(48);
+        output.WriteInt32(GetHashCode_);
+      }
+      if (WriteTo_ != 0) {
+        output.WriteRawTag(56);
+        output.WriteInt32(WriteTo_);
+      }
+      if (Clone_ != 0) {
+        output.WriteRawTag(64);
+        output.WriteInt32(Clone_);
+      }
+      if (CalculateSize_ != 0) {
+        output.WriteRawTag(72);
+        output.WriteInt32(CalculateSize_);
+      }
+      if (MergeFrom_ != 0) {
+        output.WriteRawTag(80);
+        output.WriteInt32(MergeFrom_);
+      }
+      if (OnConstruction_ != 0) {
+        output.WriteRawTag(88);
+        output.WriteInt32(OnConstruction_);
+      }
+      if (Parser_ != 0) {
+        output.WriteRawTag(96);
+        output.WriteInt32(Parser_);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !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 (DisambiguateCommonMembers_ != 0) {
+        output.WriteRawTag(8);
+        output.WriteInt32(DisambiguateCommonMembers_);
+      }
+      if (Types_ != 0) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Types_);
+      }
+      if (Descriptor_ != 0) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Descriptor_);
+      }
+      if (Equals_ != 0) {
+        output.WriteRawTag(32);
+        output.WriteInt32(Equals_);
+      }
+      if (ToString_ != 0) {
+        output.WriteRawTag(40);
+        output.WriteInt32(ToString_);
+      }
+      if (GetHashCode_ != 0) {
+        output.WriteRawTag(48);
+        output.WriteInt32(GetHashCode_);
+      }
+      if (WriteTo_ != 0) {
+        output.WriteRawTag(56);
+        output.WriteInt32(WriteTo_);
+      }
+      if (Clone_ != 0) {
+        output.WriteRawTag(64);
+        output.WriteInt32(Clone_);
+      }
+      if (CalculateSize_ != 0) {
+        output.WriteRawTag(72);
+        output.WriteInt32(CalculateSize_);
+      }
+      if (MergeFrom_ != 0) {
+        output.WriteRawTag(80);
+        output.WriteInt32(MergeFrom_);
+      }
+      if (OnConstruction_ != 0) {
+        output.WriteRawTag(88);
+        output.WriteInt32(OnConstruction_);
+      }
+      if (Parser_ != 0) {
+        output.WriteRawTag(96);
+        output.WriteInt32(Parser_);
+      }
+      if (_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 (DisambiguateCommonMembers_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(DisambiguateCommonMembers_);
+      }
+      if (Types_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Types_);
+      }
+      if (Descriptor_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Descriptor_);
+      }
+      if (Equals_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Equals_);
+      }
+      if (ToString_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(ToString_);
+      }
+      if (GetHashCode_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(GetHashCode_);
+      }
+      if (WriteTo_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(WriteTo_);
+      }
+      if (Clone_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Clone_);
+      }
+      if (CalculateSize_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(CalculateSize_);
+      }
+      if (MergeFrom_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(MergeFrom_);
+      }
+      if (OnConstruction_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(OnConstruction_);
+      }
+      if (Parser_ != 0) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Parser_);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(DisambiguateCommonMembers other) {
+      if (other == null) {
+        return;
+      }
+      if (other.DisambiguateCommonMembers_ != 0) {
+        DisambiguateCommonMembers_ = other.DisambiguateCommonMembers_;
+      }
+      if (other.Types_ != 0) {
+        Types_ = other.Types_;
+      }
+      if (other.Descriptor_ != 0) {
+        Descriptor_ = other.Descriptor_;
+      }
+      if (other.Equals_ != 0) {
+        Equals_ = other.Equals_;
+      }
+      if (other.ToString_ != 0) {
+        ToString_ = other.ToString_;
+      }
+      if (other.GetHashCode_ != 0) {
+        GetHashCode_ = other.GetHashCode_;
+      }
+      if (other.WriteTo_ != 0) {
+        WriteTo_ = other.WriteTo_;
+      }
+      if (other.Clone_ != 0) {
+        Clone_ = other.Clone_;
+      }
+      if (other.CalculateSize_ != 0) {
+        CalculateSize_ = other.CalculateSize_;
+      }
+      if (other.MergeFrom_ != 0) {
+        MergeFrom_ = other.MergeFrom_;
+      }
+      if (other.OnConstruction_ != 0) {
+        OnConstruction_ = other.OnConstruction_;
+      }
+      if (other.Parser_ != 0) {
+        Parser_ = other.Parser_;
+      }
+      _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: {
+            DisambiguateCommonMembers_ = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Types_ = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Descriptor_ = input.ReadInt32();
+            break;
+          }
+          case 32: {
+            Equals_ = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            ToString_ = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            GetHashCode_ = input.ReadInt32();
+            break;
+          }
+          case 56: {
+            WriteTo_ = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            Clone_ = input.ReadInt32();
+            break;
+          }
+          case 72: {
+            CalculateSize_ = input.ReadInt32();
+            break;
+          }
+          case 80: {
+            MergeFrom_ = input.ReadInt32();
+            break;
+          }
+          case 88: {
+            OnConstruction_ = input.ReadInt32();
+            break;
+          }
+          case 96: {
+            Parser_ = 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: {
+            DisambiguateCommonMembers_ = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Types_ = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Descriptor_ = input.ReadInt32();
+            break;
+          }
+          case 32: {
+            Equals_ = input.ReadInt32();
+            break;
+          }
+          case 40: {
+            ToString_ = input.ReadInt32();
+            break;
+          }
+          case 48: {
+            GetHashCode_ = input.ReadInt32();
+            break;
+          }
+          case 56: {
+            WriteTo_ = input.ReadInt32();
+            break;
+          }
+          case 64: {
+            Clone_ = input.ReadInt32();
+            break;
+          }
+          case 72: {
+            CalculateSize_ = input.ReadInt32();
+            break;
+          }
+          case 80: {
+            MergeFrom_ = input.ReadInt32();
+            break;
+          }
+          case 88: {
+            OnConstruction_ = input.ReadInt32();
+            break;
+          }
+          case 96: {
+            Parser_ = input.ReadInt32();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
   #endregion
 
 }
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestProto3Optional.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestSelfreferentialOptions.pb.cs
diff --git a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.pb.cs
similarity index 98%
rename from csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
rename to csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.pb.cs
index 3ec8d35..50b9046 100644
--- a/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.cs
+++ b/csharp/src/Google.Protobuf.Test.TestProtos/UnittestWellKnownTypes.pb.cs
@@ -3258,24 +3258,24 @@
       if (other == null) {
         return;
       }
-      anyField_.Add(other.anyField_);
-      apiField_.Add(other.apiField_);
-      durationField_.Add(other.durationField_);
-      emptyField_.Add(other.emptyField_);
-      fieldMaskField_.Add(other.fieldMaskField_);
-      sourceContextField_.Add(other.sourceContextField_);
-      structField_.Add(other.structField_);
-      timestampField_.Add(other.timestampField_);
-      typeField_.Add(other.typeField_);
-      doubleField_.Add(other.doubleField_);
-      floatField_.Add(other.floatField_);
-      int64Field_.Add(other.int64Field_);
-      uint64Field_.Add(other.uint64Field_);
-      int32Field_.Add(other.int32Field_);
-      uint32Field_.Add(other.uint32Field_);
-      boolField_.Add(other.boolField_);
-      stringField_.Add(other.stringField_);
-      bytesField_.Add(other.bytesField_);
+      anyField_.MergeFrom(other.anyField_);
+      apiField_.MergeFrom(other.apiField_);
+      durationField_.MergeFrom(other.durationField_);
+      emptyField_.MergeFrom(other.emptyField_);
+      fieldMaskField_.MergeFrom(other.fieldMaskField_);
+      sourceContextField_.MergeFrom(other.sourceContextField_);
+      structField_.MergeFrom(other.structField_);
+      timestampField_.MergeFrom(other.timestampField_);
+      typeField_.MergeFrom(other.typeField_);
+      doubleField_.MergeFrom(other.doubleField_);
+      floatField_.MergeFrom(other.floatField_);
+      int64Field_.MergeFrom(other.int64Field_);
+      uint64Field_.MergeFrom(other.uint64Field_);
+      int32Field_.MergeFrom(other.int32Field_);
+      uint32Field_.MergeFrom(other.uint32Field_);
+      boolField_.MergeFrom(other.boolField_);
+      stringField_.MergeFrom(other.stringField_);
+      bytesField_.MergeFrom(other.bytesField_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
diff --git a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
index 4876e09..b757287 100644
--- a/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
+++ b/csharp/src/Google.Protobuf.Test/ByteStringTest.cs
@@ -41,9 +41,7 @@
 using System.Runtime.InteropServices;
 using System.Threading;
 using System.Runtime.CompilerServices;
-#if !NET35
 using System.Threading.Tasks;
-#endif
 
 namespace Google.Protobuf
 {
@@ -72,7 +70,7 @@
             Assert.IsFalse(b1 != b1);
             Assert.IsFalse(b1 != b2);
             Assert.IsTrue(ByteString.Empty == ByteString.Empty);
-#pragma warning disable 1718
+#pragma warning restore 1718
             Assert.IsTrue(b1 != b3);
             Assert.IsTrue(b1 != b4);
             Assert.IsTrue(b1 != null);
@@ -278,12 +276,9 @@
             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));
-            }
+            using var manager = new UnmanagedMemoryManager<byte>(s);
+            ByteString bs = ByteString.AttachBytes(manager.Memory);
+            Assert.AreEqual("Hello world", bs.ToString(Encoding.UTF8));
         }
 
         [Test]
@@ -317,12 +312,9 @@
             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());
-            }
+            using var manager = new UnmanagedMemoryManager<byte>(s);
+            ByteString bs = ByteString.AttachBytes(manager.Memory);
+            Assert.AreEqual("SGVsbG8gd29ybGQ=", bs.ToBase64());
         }
 
         [Test]
@@ -349,7 +341,6 @@
             Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
         }
 
-#if !NET35
         [Test]
         public async Task FromStreamAsync_Seekable()
         {
@@ -373,7 +364,6 @@
             ByteString expected = ByteString.CopyFrom(2, 3, 4);
             Assert.AreEqual(expected, actual, $"{expected.ToBase64()} != {actual.ToBase64()}");
         }
-#endif
 
         [Test]
         public void GetHashCode_Regression()
diff --git a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
index b84a1b7..a48f3b1 100644
--- a/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedInputStreamTest.cs
@@ -563,8 +563,8 @@
             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);
+            var ms = new MemoryStream();
+            var 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
@@ -578,8 +578,8 @@
         [Test]
         public void ReadGroup_UnknownFields_WrongEndGroupTag()
         {
-            MemoryStream ms = new MemoryStream();
-            CodedOutputStream output = new CodedOutputStream(ms);
+            var ms = new MemoryStream();
+            var 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));
@@ -654,7 +654,7 @@
             output.Flush();
             ms.Position = 0;
 
-            CodedInputStream input = new CodedInputStream(ms);
+            var input = new CodedInputStream(ms);
 
             Assert.AreEqual(tag, input.ReadTag());
             Assert.Throws<InvalidProtocolBufferException>(() => input.ReadBytes());
@@ -694,26 +694,24 @@
         [Test]
         public void TestSlowPathAvoidance()
         {
-            using (var ms = new MemoryStream())
-            {
-                CodedOutputStream output = new CodedOutputStream(ms);
-                output.WriteTag(1, WireFormat.WireType.LengthDelimited);
-                output.WriteBytes(ByteString.CopyFrom(new byte[100]));
-                output.WriteTag(2, WireFormat.WireType.LengthDelimited);
-                output.WriteBytes(ByteString.CopyFrom(new byte[100]));
-                output.Flush();
+            using var ms = new MemoryStream();
+            var output = new CodedOutputStream(ms);
+            output.WriteTag(1, WireFormat.WireType.LengthDelimited);
+            output.WriteBytes(ByteString.CopyFrom(new byte[100]));
+            output.WriteTag(2, WireFormat.WireType.LengthDelimited);
+            output.WriteBytes(ByteString.CopyFrom(new byte[100]));
+            output.Flush();
 
-                ms.Position = 0;
-                CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0, false);
+            ms.Position = 0;
+            CodedInputStream input = new CodedInputStream(ms, new byte[ms.Length / 2], 0, 0, false);
 
-                uint tag = input.ReadTag();
-                Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));
-                Assert.AreEqual(100, input.ReadBytes().Length);
+            uint tag = input.ReadTag();
+            Assert.AreEqual(1, WireFormat.GetTagFieldNumber(tag));
+            Assert.AreEqual(100, input.ReadBytes().Length);
 
-                tag = input.ReadTag();
-                Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag));
-                Assert.AreEqual(100, input.ReadBytes().Length);
-            }
+            tag = input.ReadTag();
+            Assert.AreEqual(2, WireFormat.GetTagFieldNumber(tag));
+            Assert.AreEqual(100, input.ReadBytes().Length);
         }
 
         [Test]
@@ -927,13 +925,11 @@
         {
             byte[] serializedMessage = GenerateBigSerializedMessage();
             // How many of these big messages do we need to take us near our 2GB limit?
-            int count = Int32.MaxValue / serializedMessage.Length;
+            int count = int.MaxValue / serializedMessage.Length;
             // Now make a MemoryStream that will fake a near-2GB stream of messages by returning
             // our big serialized message 'count' times.
-            using (RepeatingMemoryStream stream = new RepeatingMemoryStream(serializedMessage, count))
-            {
-                Assert.DoesNotThrow(()=>TestAllTypes.Parser.ParseFrom(stream));
-            }
+            using var stream = new RepeatingMemoryStream(serializedMessage, count);
+            Assert.DoesNotThrow(() => TestAllTypes.Parser.ParseFrom(stream));
         }
 
         [Test]
@@ -941,17 +937,15 @@
         {
             byte[] serializedMessage = GenerateBigSerializedMessage();
             // How many of these big messages do we need to take us near our 2GB limit?
-            int count = Int32.MaxValue / serializedMessage.Length;
+            int count = int.MaxValue / serializedMessage.Length;
             // Now add one to take us over the 2GB limit
             count++;
             // Now make a MemoryStream that will fake a near-2GB stream of messages by returning
             // our big serialized message 'count' times.
-            using (RepeatingMemoryStream stream = new RepeatingMemoryStream(serializedMessage, count))
-            {
-                Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(stream),
-                    "Protocol message was too large.  May be malicious.  " +
-                    "Use CodedInputStream.SetSizeLimit() to increase the size limit.");
-            }
+            using var stream = new RepeatingMemoryStream(serializedMessage, count);
+            Assert.Throws<InvalidProtocolBufferException>(() => TestAllTypes.Parser.ParseFrom(stream),
+                "Protocol message was too large.  May be malicious.  " +
+                "Use CodedInputStream.SetSizeLimit() to increase the size limit.");
         }
 
         /// <returns>A serialized big message</returns>
diff --git a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
index 13f83a2..31090c4 100644
--- a/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
+++ b/csharp/src/Google.Protobuf.Test/CodedOutputStreamTest.cs
@@ -94,14 +94,12 @@
                 if ((value >> 32) == 0)
                 {
                     MemoryStream rawOutput = new MemoryStream();
-                    CodedOutputStream output =
-                        new CodedOutputStream(rawOutput, bufferSize);
+                    CodedOutputStream output = new CodedOutputStream(rawOutput, bufferSize);
                     output.WriteRawVarint32((uint) value);
                     output.Flush();
                     Assert.AreEqual(data, rawOutput.ToArray());
 
-                    var bufferWriter = new TestArrayBufferWriter<byte>();
-                    bufferWriter.MaxGrowBy = bufferSize;
+                    var bufferWriter = new TestArrayBufferWriter<byte> { MaxGrowBy = bufferSize };
                     WriteContext.Initialize(bufferWriter, out WriteContext ctx);
                     ctx.WriteUInt32((uint) value);
                     ctx.Flush();
@@ -115,8 +113,7 @@
                     output.Flush();
                     Assert.AreEqual(data, rawOutput.ToArray());
 
-                    var bufferWriter = new TestArrayBufferWriter<byte>();
-                    bufferWriter.MaxGrowBy = bufferSize;
+                    var bufferWriter = new TestArrayBufferWriter<byte> { MaxGrowBy = bufferSize };
                     WriteContext.Initialize(bufferWriter, out WriteContext ctx);
                     ctx.WriteUInt64(value);
                     ctx.Flush();
@@ -190,8 +187,7 @@
                 output.Flush();
                 Assert.AreEqual(data, rawOutput.ToArray());
 
-                var bufferWriter = new TestArrayBufferWriter<byte>();
-                bufferWriter.MaxGrowBy = bufferSize;
+                var bufferWriter = new TestArrayBufferWriter<byte> { MaxGrowBy = bufferSize };
                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);
                 ctx.WriteFixed32(value);
                 ctx.Flush();
@@ -228,8 +224,7 @@
                 output.Flush();
                 Assert.AreEqual(data, rawOutput.ToArray());
 
-                var bufferWriter = new TestArrayBufferWriter<byte>();
-                bufferWriter.MaxGrowBy = blockSize;
+                var bufferWriter = new TestArrayBufferWriter<byte> { MaxGrowBy = blockSize };
                 WriteContext.Initialize(bufferWriter, out WriteContext ctx);
                 ctx.WriteFixed64(value);
                 ctx.Flush();
@@ -270,8 +265,7 @@
                 output.Flush();
                 Assert.AreEqual(rawBytes, rawOutput.ToArray());
 
-                var bufferWriter = new TestArrayBufferWriter<byte>();
-                bufferWriter.MaxGrowBy = blockSize;
+                var bufferWriter = new TestArrayBufferWriter<byte> { MaxGrowBy = blockSize };
                 message.WriteTo(bufferWriter);
                 Assert.AreEqual(rawBytes, bufferWriter.WrittenSpan.ToArray()); 
             }
@@ -383,7 +377,9 @@
         {
             byte[] content = new byte[110];
             for (int i = 0; i < content.Length; i++)
+            {
                 content[i] = (byte)i;
+            }
 
             byte[] child = new byte[120];
             {
diff --git a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
index 1f7b8a3..401b70a 100644
--- a/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Collections/MapFieldTest.cs
@@ -91,10 +91,12 @@
         [Test]
         public void AddPreservesInsertionOrder()
         {
-            var map = new MapField<string, string>();
-            map.Add("a", "v1");
-            map.Add("b", "v2");
-            map.Add("c", "v3");
+            var map = new MapField<string, string>
+            {
+                { "a", "v1" },
+                { "b", "v2" },
+                { "c", "v3" }
+            };
             map.Remove("b");
             map.Add("d", "v4");
             CollectionAssert.AreEqual(new[] { "a", "c", "d" }, map.Keys);
@@ -104,13 +106,17 @@
         [Test]
         public void EqualityIsOrderInsensitive()
         {
-            var map1 = new MapField<string, string>();
-            map1.Add("a", "v1");
-            map1.Add("b", "v2");
+            var map1 = new MapField<string, string>
+            {
+                { "a", "v1" },
+                { "b", "v2" }
+            };
 
-            var map2 = new MapField<string, string>();
-            map2.Add("b", "v2");
-            map2.Add("a", "v1");
+            var map2 = new MapField<string, string>
+            {
+                { "b", "v2" },
+                { "a", "v1" }
+            };
 
             EqualityTester.AssertEquality(map1, map2);
         }
@@ -118,13 +124,17 @@
         [Test]
         public void EqualityIsKeySensitive()
         {
-            var map1 = new MapField<string, string>();
-            map1.Add("first key", "v1");
-            map1.Add("second key", "v2");
+            var map1 = new MapField<string, string>
+            {
+                { "first key", "v1" },
+                { "second key", "v2" }
+            };
 
-            var map2 = new MapField<string, string>();
-            map2.Add("third key", "v1");
-            map2.Add("fourth key", "v2");
+            var map2 = new MapField<string, string>
+            {
+                { "third key", "v1" },
+                { "fourth key", "v2" }
+            };
 
             EqualityTester.AssertInequality(map1, map2);
         }
@@ -143,13 +153,17 @@
         {
             // Note: Without some care, it's a little easier than one might
             // hope to see hash collisions, but only in some environments...
-            var map1 = new MapField<string, string>();
-            map1.Add("a", "first value");
-            map1.Add("b", "second value");
+            var map1 = new MapField<string, string>
+            {
+                { "a", "first value" },
+                { "b", "second value" }
+            };
 
-            var map2 = new MapField<string, string>();
-            map2.Add("a", "third value");
-            map2.Add("b", "fourth value");
+            var map2 = new MapField<string, string>
+            {
+                { "a", "third value" },
+                { "b", "fourth value" }
+            };
 
             EqualityTester.AssertInequality(map1, map2);
         }
@@ -183,8 +197,7 @@
         [Test]
         public void Add_KeyAlreadyExists()
         {
-            var map = new MapField<string, string>();
-            map.Add("foo", "bar");
+            var map = new MapField<string, string> { { "foo", "bar" } };
             Assert.Throws<ArgumentException>(() => map.Add("foo", "baz"));
         }
 
@@ -211,8 +224,7 @@
         [Test]
         public void Remove_Key()
         {
-            var map = new MapField<string, string>();
-            map.Add("foo", "bar");
+            var map = new MapField<string, string> { { "foo", "bar" } };
             Assert.AreEqual(1, map.Count);
             Assert.IsFalse(map.Remove("missing"));
             Assert.AreEqual(1, map.Count);
@@ -224,8 +236,7 @@
         [Test]
         public void Remove_Pair()
         {
-            var map = new MapField<string, string>();
-            map.Add("foo", "bar");
+            var map = new MapField<string, string> { { "foo", "bar" } };
             ICollection<KeyValuePair<string, string>> collection = map;
             Assert.AreEqual(1, map.Count);
             Assert.IsFalse(collection.Remove(NewKeyValuePair("wrong key", "bar")));
@@ -240,8 +251,7 @@
         [Test]
         public void CopyTo_Pair()
         {
-            var map = new MapField<string, string>();
-            map.Add("foo", "bar");
+            var map = new MapField<string, string> { { "foo", "bar" } };
             ICollection<KeyValuePair<string, string>> collection = map;
             KeyValuePair<string, string>[] array = new KeyValuePair<string, string>[3];
             collection.CopyTo(array, 1);
@@ -270,8 +280,7 @@
         [Test]
         public void Indexer_Set()
         {
-            var map = new MapField<string, string>();
-            map["x"] = "y";
+            var map = new MapField<string, string> { ["x"] = "y" };
             Assert.AreEqual("y", map["x"]);
             map["x"] = "z"; // This won't throw, unlike Add.
             Assert.AreEqual("z", map["x"]);
@@ -357,12 +366,10 @@
             IDictionary dictionary = map;
             var array = new DictionaryEntry[3];
             dictionary.CopyTo(array, 1);
-            CollectionAssert.AreEqual(new[] { default(DictionaryEntry), new DictionaryEntry("x", "y"), default(DictionaryEntry) },
-                array);
+            CollectionAssert.AreEqual(new[] { default, new DictionaryEntry("x", "y"), default }, array);
             var objectArray = new object[3];
             dictionary.CopyTo(objectArray, 1);
-            CollectionAssert.AreEqual(new object[] { null, new DictionaryEntry("x", "y"), null },
-                objectArray);
+            CollectionAssert.AreEqual(new object[] { null, new DictionaryEntry("x", "y"), null }, objectArray);
         }
 
         [Test]
@@ -580,8 +587,7 @@
             };
             Assert.AreEqual("x", map[SampleNaNs.Regular]);
             Assert.AreEqual("y", map[SampleNaNs.SignallingFlipped]);
-            string ignored;
-            Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out ignored));
+            Assert.False(map.TryGetValue(SampleNaNs.PayloadFlipped, out _));
         }
 
         [Test]
@@ -635,7 +641,6 @@
             Assert.IsTrue(input.IsAtEnd);
         }
 
-#if !NET35
         [Test]
         public void IDictionaryKeys_Equals_IReadOnlyDictionaryKeys()
         {
@@ -649,7 +654,6 @@
             var map = new MapField<string, string> { { "foo", "bar" }, { "x", "y" } };
             CollectionAssert.AreEquivalent(((IDictionary<string, string>)map).Values, ((IReadOnlyDictionary<string, string>)map).Values);
         }
-#endif
 
         private static KeyValuePair<TKey, TValue> NewKeyValuePair<TKey, TValue>(TKey key, TValue value)
         {
diff --git a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
index ff8f5cc..5a8977d 100644
--- a/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Collections/RepeatedFieldTest.cs
@@ -33,7 +33,6 @@
 using System;
 using System.Collections;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
 using System.IO;
 using System.Linq;
 using System.Text;
@@ -59,8 +58,7 @@
         [Test]
         public void Add_SingleItem()
         {
-            var list = new RepeatedField<string>();
-            list.Add("foo");
+            var list = new RepeatedField<string> { "foo" };
             Assert.AreEqual(1, list.Count);
             Assert.AreEqual("foo", list[0]);
         }
@@ -68,8 +66,7 @@
         [Test]
         public void Add_Sequence()
         {
-            var list = new RepeatedField<string>();
-            list.Add(new[] { "foo", "bar" });
+            var list = new RepeatedField<string> { new[] { "foo", "bar" } };
             Assert.AreEqual(2, list.Count);
             Assert.AreEqual("foo", list[0]);
             Assert.AreEqual("bar", list[1]);
@@ -293,15 +290,13 @@
         public void Enumerator()
         {
             var list = new RepeatedField<string> { "first", "second" };
-            using (var enumerator = list.GetEnumerator())
-            {
-                Assert.IsTrue(enumerator.MoveNext());
-                Assert.AreEqual("first", enumerator.Current);
-                Assert.IsTrue(enumerator.MoveNext());
-                Assert.AreEqual("second", enumerator.Current);
-                Assert.IsFalse(enumerator.MoveNext());
-                Assert.IsFalse(enumerator.MoveNext());
-            }
+            using var enumerator = list.GetEnumerator();
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("first", enumerator.Current);
+            Assert.IsTrue(enumerator.MoveNext());
+            Assert.AreEqual("second", enumerator.Current);
+            Assert.IsFalse(enumerator.MoveNext());
+            Assert.IsFalse(enumerator.MoveNext());
         }
 
         [Test]
@@ -893,5 +888,17 @@
             Assert.DoesNotThrow(() => list.Capacity = 0, "Can set Capacity to 0");
             Assert.AreEqual(0, list.Capacity);
         }
+
+        [Test]
+        public void Clear_CapacityUnaffected()
+        {
+            var list = new RepeatedField<int> { 1 };
+            Assert.AreEqual(1, list.Count);
+            Assert.AreEqual(8, list.Capacity);
+
+            list.Clear();
+            Assert.AreEqual(0, list.Count);
+            Assert.AreEqual(8, list.Capacity);
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs b/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs
deleted file mode 100644
index 48c0725..0000000
--- a/csharp/src/Google.Protobuf.Test/Compatibility/StreamExtensionsTest.cs
+++ /dev/null
@@ -1,67 +0,0 @@
-#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
-
-#if NET35
-using System;
-using System.IO;
-using NUnit.Framework;
-using Google.Protobuf.Compatibility;
-
-namespace Google.Protobuf.Test.Compatibility
-{
-    public class StreamExtensionsTest
-    {
-        [Test]
-        public void CopyToNullArgument()
-        {
-            var memoryStream = new MemoryStream();
-            Assert.Throws<ArgumentNullException>(() => memoryStream.CopyTo(null));
-        }
-
-        [Test]
-        public void CopyToTest()
-        {
-            byte[] bytesToStream = new byte[] { 0x31, 0x08, 0xFF, 0x00 };
-            Stream source = new MemoryStream(bytesToStream);
-            Stream destination = new MemoryStream((int)source.Length);
-            source.CopyTo(destination);
-            destination.Seek(0, SeekOrigin.Begin);
-
-            Assert.AreEqual(0x31, destination.ReadByte());
-            Assert.AreEqual(0x08, destination.ReadByte());
-            Assert.AreEqual(0xFF, destination.ReadByte());
-            Assert.AreEqual(0x00, destination.ReadByte());
-            Assert.AreEqual(-1, destination.ReadByte());
-        }
-    }
-}
-#endif
diff --git a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
index 5d86c20..040a2f1 100644
--- a/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Compatibility/TypeExtensionsTest.cs
@@ -29,12 +29,12 @@
 // (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.Collections.Generic;
 using System.Reflection;
 
-#if !NET35
 namespace Google.Protobuf.Compatibility
 {
     public class TypeExtensionsTest
@@ -114,4 +114,3 @@
         }
     }
 }
-#endif
diff --git a/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs b/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
index fd041e0..6d31441 100644
--- a/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
+++ b/csharp/src/Google.Protobuf.Test/DeprecatedMemberTest.cs
@@ -34,7 +34,9 @@
 using System.Reflection;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
+using UnitTest.Issues.TestProtos;
 
+#pragma warning disable CS0612 // Type or member is obsolete
 namespace Google.Protobuf
 {
     public class DeprecatedMemberTest
@@ -46,10 +48,20 @@
         }
 
         [Test]
-        public void TestDepreatedPrimitiveValue()
-        {
-            AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty("DeprecatedInt32"));
-        }
+        public void TestDepreatedPrimitiveValue() =>
+            AssertIsDeprecated(typeof(TestDeprecatedFields).GetProperty(nameof(TestDeprecatedFields.DeprecatedInt32)));
 
+        [Test]
+        public void TestDeprecatedMessage() =>
+            AssertIsDeprecated(typeof(DeprecatedChild));
+
+        [Test]
+        public void TestDeprecatedEnum() =>
+            AssertIsDeprecated(typeof(DeprecatedEnum));
+
+        [Test]
+        public void TestDeprecatedEnumValue() =>
+            AssertIsDeprecated(typeof(DeprecatedEnum).GetField(nameof(DeprecatedEnum.DeprecatedZero)));
     }
 }
+#pragma warning restore CS0612 // Type or member is obsolete
diff --git a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
index b2c24dd..23237d4 100644
--- a/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
+++ b/csharp/src/Google.Protobuf.Test/ExtensionSetTest.cs
@@ -1,3 +1,35 @@
+#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 System;
 using System.Collections;
 using Google.Protobuf.TestProtos.Proto2;
@@ -72,7 +104,7 @@
             message.SetExtension(OptionalStringExtension, "abcd");
 
             var input = new CodedInputStream(message.ToByteArray());
-            input.ExtensionRegistry = new ExtensionRegistry() { OptionalStringExtension };
+            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;
diff --git a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
index 7f36692..4f2a562 100644
--- a/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
+++ b/csharp/src/Google.Protobuf.Test/FieldCodecTest.cs
@@ -169,7 +169,6 @@
                 // WriteTagAndValue ignores default values
                 var stream = new MemoryStream();
                 CodedOutputStream codedOutput;
-#if !NET35
                 codedOutput = new CodedOutputStream(stream);
                 codec.WriteTagAndValue(codedOutput, codec.DefaultValue);
                 codedOutput.Flush();
@@ -179,7 +178,6 @@
                 {
                     Assert.AreEqual(default(T), codec.DefaultValue);
                 }
-#endif
 
                 // The plain ValueWriter/ValueReader delegates don't.
                 if (codec.DefaultValue != null) // This part isn't appropriate for message types.
diff --git a/csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs b/csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs
index f71744a..4c206e6 100644
--- a/csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs
+++ b/csharp/src/Google.Protobuf.Test/FieldMaskTreeTest.cs
@@ -30,7 +30,6 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using System.Collections.Generic;
 using Google.Protobuf.Collections;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
@@ -432,5 +431,89 @@
             Assert.IsNotNull(destination.Payload);
         }
 
+        [Test]
+        public void MergeWrapperFieldsWithNonNullFieldsInSource()
+        {
+            // Instantiate a destination with wrapper-based field types.
+            var destination = new TestWellKnownTypes()
+            {
+                StringField = "Hello",
+                Int32Field = 12,
+                Int64Field = 24,
+                BoolField = true,
+            };
+
+            // Set up a targeted update.
+            var source = new TestWellKnownTypes()
+            {
+                StringField = "Hi",
+                Int64Field = 240
+            };
+
+            Merge(new FieldMaskTree().AddFieldPath("string_field").AddFieldPath("int64_field"),
+                source,
+                destination,
+                new FieldMask.MergeOptions(),
+                false);
+
+            // Make sure the targeted fields changed.
+            Assert.AreEqual("Hi", destination.StringField);
+            Assert.AreEqual(240, destination.Int64Field);
+
+            // Prove that non-targeted fields stay intact...
+            Assert.AreEqual(12, destination.Int32Field);
+            Assert.IsTrue(destination.BoolField);
+
+            // ...including default values which were not explicitly set in the destination object.
+            Assert.IsNull(destination.FloatField);
+        }
+
+        [Test]
+        [TestCase(false, "Hello", 24)]
+        [TestCase(true, null, null)]
+        public void MergeWrapperFieldsWithNullFieldsInSource(
+            bool replaceMessageFields,
+            string expectedStringValue,
+            long? expectedInt64Value)
+        {
+            // Instantiate a destination with wrapper-based field types.
+            var destination = new TestWellKnownTypes()
+            {
+                StringField = "Hello",
+                Int32Field = 12,
+                Int64Field = 24,
+                BoolField = true,
+            };
+
+            // Set up a targeted update with null valued fields.
+            var source = new TestWellKnownTypes()
+            {
+                StringField = null,
+                Int64Field = null
+            };
+
+            Merge(new FieldMaskTree().AddFieldPath("string_field").AddFieldPath("int64_field"),
+                source,
+                destination,
+                new FieldMask.MergeOptions()
+                {
+                    ReplaceMessageFields = replaceMessageFields
+                },
+                false);
+
+            // Make sure the targeted fields changed according to our expectations, depending on the value of ReplaceMessageFields.
+            // When ReplaceMessageFields is false, the null values are not applied to the destination, because, although wrapped types
+            // are semantically primitives, FieldMaskTree.Merge still treats them as message types in order to maintain consistency with other Protobuf
+            // libraries such as Java and C++.
+            Assert.AreEqual(expectedStringValue, destination.StringField);
+            Assert.AreEqual(expectedInt64Value, destination.Int64Field);
+
+            // Prove that non-targeted fields stay intact...
+            Assert.AreEqual(12, destination.Int32Field);
+            Assert.IsTrue(destination.BoolField);
+
+            // ...including default values which were not explicitly set in the destination object.
+            Assert.IsNull(destination.FloatField);
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
index fa5f927..9d03656 100644
--- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
+++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.Proto2.cs
@@ -1,3 +1,35 @@
+#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 Google.Protobuf.TestProtos.Proto2;
 using Proto2 = Google.Protobuf.TestProtos.Proto2;
 using NUnit.Framework;
@@ -387,11 +419,9 @@
             var message = new TestAllExtensions();
             message.SetExtension(UnittestExtensions.OptionalBoolExtension, true);
             byte[] bytes = message.ToByteArray();
-            using (CodedInputStream input = new CodedInputStream(bytes))
-            {
-                var parsed = TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalBoolExtension }).ParseFrom(input);
-                Assert.AreEqual(message, parsed);
-            }
+            using CodedInputStream input = new CodedInputStream(bytes);
+            var parsed = TestAllExtensions.Parser.WithExtensionRegistry(new ExtensionRegistry() { UnittestExtensions.OptionalBoolExtension }).ParseFrom(input);
+            Assert.AreEqual(message, parsed);
         }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
index 41a0b91..17c5249 100644
--- a/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
+++ b/csharp/src/Google.Protobuf.Test/GeneratedMessageTest.cs
@@ -33,12 +33,10 @@
 using System;
 using System.IO;
 using Google.Protobuf.TestProtos;
-using Proto2 = Google.Protobuf.TestProtos.Proto2;
 using NUnit.Framework;
-using System.Collections;
-using System.Collections.Generic;
 using System.Linq;
 using Google.Protobuf.WellKnownTypes;
+using Google.Protobuf.Collections;
 
 namespace Google.Protobuf
 {
@@ -658,9 +656,11 @@
         [Test]
         public void OneofSerialization_NonDefaultValue()
         {
-            var message = new TestAllTypes();
-            message.OneofString = "this would take a bit of space";
-            message.OneofUint32 = 10;
+            var message = new TestAllTypes
+            {
+                OneofString = "this would take a bit of space",
+                OneofUint32 = 10
+            };
             var bytes = message.ToByteArray();
             Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - no string!
 
@@ -675,9 +675,11 @@
         [Test]
         public void OneofSerialization_DefaultValue()
         {
-            var message = new TestAllTypes();
-            message.OneofString = "this would take a bit of space";
-            message.OneofUint32 = 0; // This is the default value for UInt32; normally wouldn't be serialized
+            var message = new TestAllTypes
+            {
+                OneofString = "this would take a bit of space",
+                OneofUint32 = 0 // This is the default value for UInt32; normally wouldn't be serialized
+            };
             var bytes = message.ToByteArray();
             Assert.AreEqual(3, bytes.Length); // 2 bytes for the tag + 1 for the value - it's still serialized
 
@@ -746,7 +748,6 @@
         [Test]
         public void ExtraEndGroupThrows()
         {
-            var message = SampleMessages.CreateFullTestAllTypes();
             var stream = new MemoryStream();
             var output = new CodedOutputStream(stream);
 
@@ -795,5 +796,44 @@
             EqualityTester.AssertInequality(message1, message2);
             EqualityTester.AssertEquality(message1, message3);
         }
+
+        [Test]
+        [TestCase(false)]
+        [TestCase(true)]
+        public void MapFieldMerging(bool direct)
+        {
+            var message1 = new TestMap
+            {
+                MapStringString =
+                {
+                    { "x1", "y1" },
+                    { "common", "message1" }
+                }
+            };
+            var message2 = new TestMap
+            {
+                MapStringString =
+                {
+                    { "x2", "y2" },
+                    { "common", "message2" }
+                }
+            };
+            if (direct)
+            {
+                message1.MergeFrom(message2);
+            }
+            else
+            {
+                message1.MergeFrom(message2.ToByteArray());
+            }
+
+            var expected = new MapField<string, string>
+            {
+                { "x1", "y1" },
+                { "x2", "y2" },
+                { "common", "message2" }
+            };
+            Assert.AreEqual(expected, message1.MapStringString);
+        }
     }
 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterSettingsTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterSettingsTest.cs
new file mode 100644
index 0000000..f7ea97c
--- /dev/null
+++ b/csharp/src/Google.Protobuf.Test/JsonFormatterSettingsTest.cs
@@ -0,0 +1,111 @@
+#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.Reflection;
+using NUnit.Framework;
+
+// For WrapInQuotes
+
+namespace Google.Protobuf
+{
+    public class JsonFormatterSettingsTest
+    {
+        [Test]
+        public void WithIndentation()
+        {
+            var settings = JsonFormatter.Settings.Default.WithIndentation("\t");
+            Assert.AreEqual("\t", settings.Indentation);
+        }
+
+        [Test]
+        public void WithTypeRegistry()
+        {
+            var typeRegistry = TypeRegistry.Empty;
+            var settings = JsonFormatter.Settings.Default.WithTypeRegistry(typeRegistry);
+            Assert.AreEqual(typeRegistry, settings.TypeRegistry);
+        }
+
+        [Test]
+        public void WithFormatDefaultValues()
+        {
+            var settingsWith = JsonFormatter.Settings.Default.WithFormatDefaultValues(true);
+            Assert.AreEqual(true, settingsWith.FormatDefaultValues);
+
+            var settingsWithout = JsonFormatter.Settings.Default.WithFormatDefaultValues(false);
+            Assert.AreEqual(false, settingsWithout.FormatDefaultValues);
+        }
+
+        [Test]
+        public void WithFormatEnumsAsIntegers()
+        {
+            var settingsWith = JsonFormatter.Settings.Default.WithFormatEnumsAsIntegers(true);
+            Assert.AreEqual(true, settingsWith.FormatEnumsAsIntegers);
+
+            var settingsWithout = JsonFormatter.Settings.Default.WithFormatEnumsAsIntegers(false);
+            Assert.AreEqual(false, settingsWithout.FormatEnumsAsIntegers);
+        }
+
+        [Test]
+        public void WithMethodsPreserveExistingSettings()
+        {
+            var typeRegistry = TypeRegistry.Empty;
+            var baseSettings = JsonFormatter.Settings.Default
+                .WithIndentation("\t")
+                .WithFormatDefaultValues(true)
+                .WithFormatEnumsAsIntegers(true)
+                .WithTypeRegistry(typeRegistry)
+                .WithPreserveProtoFieldNames(true);
+
+            var settings1 = baseSettings.WithIndentation("\t");
+            var settings2 = baseSettings.WithFormatDefaultValues(true);
+            var settings3 = baseSettings.WithFormatEnumsAsIntegers(true);
+            var settings4 = baseSettings.WithTypeRegistry(typeRegistry);
+            var settings5 = baseSettings.WithPreserveProtoFieldNames(true);
+
+            AssertAreEqual(baseSettings, settings1);
+            AssertAreEqual(baseSettings, settings2);
+            AssertAreEqual(baseSettings, settings3);
+            AssertAreEqual(baseSettings, settings4);
+            AssertAreEqual(baseSettings, settings5);
+        }
+
+        private static void AssertAreEqual(JsonFormatter.Settings settings, JsonFormatter.Settings other)
+        {
+            Assert.AreEqual(settings.Indentation, other.Indentation);
+            Assert.AreEqual(settings.FormatDefaultValues, other.FormatDefaultValues);
+            Assert.AreEqual(settings.FormatEnumsAsIntegers, other.FormatEnumsAsIntegers);
+            Assert.AreEqual(settings.TypeRegistry, other.TypeRegistry);
+        }
+    }
+}
diff --git a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
index 3a77990..f4dfde2 100644
--- a/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonFormatterTest.cs
@@ -168,8 +168,7 @@
         [Test]
         public void WithFormatDefaultValues_DoesNotAffectProto3OptionalFields()
         {
-            var message = new TestProto3Optional();
-            message.OptionalInt32 = 0;
+            var message = new TestProto3Optional { 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.
@@ -179,8 +178,7 @@
         [Test]
         public void WithFormatDefaultValues_DoesNotAffectProto2Fields()
         {
-            var message = new TestProtos.Proto2.ForeignMessage();
-            message.C = 0;
+            var message = new TestProtos.Proto2.ForeignMessage { 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.
@@ -677,6 +675,200 @@
         }
 
         [Test]
+        public void WriteValueWithIndentation_EmptyMessage()
+        {
+            var value = new TestEmptyMessage();
+
+            AssertWriteValue(value, "{}", JsonFormatter.Settings.Default.WithIndentation());
+        }
+
+        [Test]
+        public void WriteValueWithIndentation_NestedTestAllTypes()
+        {
+            var value = new NestedTestAllTypes
+            {
+                Payload = new TestAllTypes
+                {
+                    SingleBool = true,
+                    SingleInt32 = 100,
+                    SingleString = "multiple fields",
+                    RepeatedString = { "string1", "string2" },
+                },
+                Child = new NestedTestAllTypes
+                {
+                    Payload = new TestAllTypes
+                    {
+                        SingleString = "single field",
+                    },
+                },
+                RepeatedChild =
+                {
+                    new NestedTestAllTypes { Payload = new TestAllTypes { SingleString = "child 1", RepeatedString = { "string" } } },
+                    new NestedTestAllTypes { Payload = new TestAllTypes { SingleString = "child 2" } },
+                },
+            };
+
+            const string expectedJson = @"
+{
+  'child': {
+    'payload': {
+      'singleString': 'single field'
+    }
+  },
+  'payload': {
+    'singleInt32': 100,
+    'singleBool': true,
+    'singleString': 'multiple fields',
+    'repeatedString': [
+      'string1',
+      'string2'
+    ]
+  },
+  'repeatedChild': [
+    {
+      'payload': {
+        'singleString': 'child 1',
+        'repeatedString': [
+          'string'
+        ]
+      }
+    },
+    {
+      'payload': {
+        'singleString': 'child 2'
+      }
+    }
+  ]
+}";
+            AssertWriteValue(value, expectedJson, JsonFormatter.Settings.Default.WithIndentation());
+        }
+
+        [Test]
+        public void WriteValueWithIndentation_WellKnownTypes()
+        {
+            var value = new TestWellKnownTypes
+            {
+                StructField = new Struct
+                {
+                    Fields =
+                    {
+                        { "string", Value.ForString("foo") },
+                        { "numbers", Value.ForList(Value.ForNumber(1), Value.ForNumber(2), Value.ForNumber(3)) },
+                        { "emptyList", Value.ForList() },
+                        { "emptyStruct", Value.ForStruct(new Struct()) },
+                    },
+                },
+            };
+
+            const string expectedJson = @"
+{
+  'structField': {
+    'string': 'foo',
+    'numbers': [
+      1,
+      2,
+      3
+    ],
+    'emptyList': [],
+    'emptyStruct': {}
+  }
+}";
+            AssertWriteValue(value, expectedJson, JsonFormatter.Settings.Default.WithIndentation());
+        }
+
+        [Test]
+        public void WriteValueWithIndentation_StructSingleField()
+        {
+            var value = new Struct { Fields = { { "structField1", Value.ForString("structFieldValue1") } } };
+
+            const string expectedJson = @"
+{
+  'structField1': 'structFieldValue1'
+}";
+            AssertWriteValue(value, expectedJson, JsonFormatter.Settings.Default.WithIndentation());
+        }
+
+        [Test]
+        public void WriteValueWithIndentation_StructMultipleFields()
+        {
+            var value = new Struct
+            {
+                Fields =
+                {
+                    { "structField1", Value.ForString("structFieldValue1") },
+                    { "structField2", Value.ForString("structFieldValue2") },
+                    { "structField3", Value.ForString("structFieldValue3") },
+                },
+            };
+
+            const string expectedJson = @"
+{
+  'structField1': 'structFieldValue1',
+  'structField2': 'structFieldValue2',
+  'structField3': 'structFieldValue3'
+}";
+            AssertWriteValue(value, expectedJson, JsonFormatter.Settings.Default.WithIndentation());
+        }
+
+        [Test]
+        public void FormatWithIndentation_EmbeddedMessage()
+        {
+            var value = new TestAllTypes { SingleInt32 = 100, SingleInt64 = 3210987654321L };
+            var formatter = new JsonFormatter(JsonFormatter.Settings.Default.WithIndentation());
+            var valueJson = formatter.Format(value, indentationLevel: 1);
+
+            var actualJson = $@"
+{{
+  ""data"": {valueJson}
+}}";
+            const string expectedJson = @"
+{
+  'data': {
+    'singleInt32': 100,
+    'singleInt64': '3210987654321'
+  }
+}";
+            AssertJson(expectedJson, actualJson.Trim());
+        }
+
+        [Test]
+        public void WriteValueWithIndentation_Map()
+        {
+            var value = new TestMap
+            {
+                MapStringString =
+                {
+                    { "key1", "value1" },
+                    { "key2", "value2" },
+                },
+            };
+
+            const string expectedJson = @"
+{
+  'mapStringString': {
+    'key1': 'value1',
+    'key2': 'value2'
+  }
+}";
+
+            AssertWriteValue(value, expectedJson, JsonFormatter.Settings.Default.WithIndentation());
+        }
+
+        [Test]
+        public void WriteValueWithIndentation_List()
+        {
+            var value = new RepeatedField<int> { 1, 2, 3 };
+            AssertWriteValue(value, "[\n  1,\n  2,\n  3\n]", JsonFormatter.Settings.Default.WithIndentation());
+        }
+
+        [Test]
+        public void WriteValueWithIndentation_CustomIndentation()
+        {
+            var value = new RepeatedField<int> { 1, 2, 3 };
+            AssertWriteValue(value, "[\n\t1,\n\t2,\n\t3\n]", JsonFormatter.Settings.Default.WithIndentation("\t"));
+        }
+
+        [Test]
         public void Proto2_DefaultValuesWritten()
         {
             var value = new ProtobufTestMessages.Proto2.TestAllTypesProto2() { FieldName13 = 0 };
@@ -685,7 +877,7 @@
 
         private static void AssertWriteValue(object value, string expectedJson, JsonFormatter.Settings settings = null)
         {
-            var writer = new StringWriter();
+            var writer = new StringWriter { NewLine = "\n" };
             new JsonFormatter(settings ?? JsonFormatter.Settings.Default).WriteValue(writer, value);
             string actual = writer.ToString();
             AssertJson(expectedJson, actual);
@@ -693,13 +885,17 @@
 
         /// <summary>
         /// Checks that the actual JSON is the same as the expected JSON - but after replacing
-        /// all apostrophes in the expected JSON with double quotes. This basically makes the tests easier
-        /// to read.
+        /// all apostrophes in the expected JSON with double quotes, trimming leading whitespace and normalizing new lines.
+        /// This basically makes the tests easier to read.
         /// </summary>
+        /// <remarks>
+        /// Line endings are normalized because indented JSON strings are generated with system-specific line endings,
+        /// while line endings in the test cases are hard-coded, but may be converted during source checkout, depending
+        /// on git settings, causing unpredictability in the test results otherwise.</remarks>
         private static void AssertJson(string expectedJsonWithApostrophes, string actualJson)
         {
-            var expectedJson = expectedJsonWithApostrophes.Replace("'", "\"");
-            Assert.AreEqual(expectedJson, actualJson);
+            var expectedJson = expectedJsonWithApostrophes.Replace("'", "\"").Replace("\r\n", "\n").TrimStart();
+            Assert.AreEqual(expectedJson, actualJson.Replace("\r\n", "\n"));
         }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
index eb8996e..c03b326 100644
--- a/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonParserTest.cs
@@ -576,6 +576,10 @@
         [TestCase("-3.402823e38", -3.402823e38f)]
         [TestCase("1.5e1", 15f)]
         [TestCase("15e-1", 1.5f)]
+        [TestCase("3.4028235e38", float.MaxValue)]
+        [TestCase("-3.4028235e38", float.MinValue)]
+        [TestCase("3.4028235e+38", float.MaxValue)]
+        [TestCase("-3.4028235e+38", float.MinValue)]
         public void NumberToFloat_Valid(string jsonValue, float expectedParsedValue)
         {
             string json = "{ \"singleFloat\": " + jsonValue + "}";
@@ -584,8 +588,10 @@
         }
 
         [Test]
-        [TestCase("3.402824e38", typeof(InvalidProtocolBufferException))]
-        [TestCase("-3.402824e38", typeof(InvalidProtocolBufferException))]
+        [TestCase("3.4028236e38", typeof(InvalidProtocolBufferException))]
+        [TestCase("-3.4028236e38", typeof(InvalidProtocolBufferException))]
+        [TestCase("3.4028236e+38", typeof(InvalidProtocolBufferException))]
+        [TestCase("-3.4028236e+38", typeof(InvalidProtocolBufferException))]
         [TestCase("1,0", typeof(InvalidJsonException))]
         [TestCase("1.0.0", typeof(InvalidJsonException))]
         [TestCase("+1", typeof(InvalidJsonException))]
@@ -641,7 +647,7 @@
         [TestCase("9999-12-31T23:59:59.999999999Z", null)]
         public void Timestamp_Valid(string jsonValue, string expectedFormatted)
         {
-            expectedFormatted = expectedFormatted ?? jsonValue;
+            expectedFormatted ??= jsonValue;
             string json = WrapInQuotes(jsonValue);
             var parsed = Timestamp.Parser.ParseJson(json);
             Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString());
@@ -758,7 +764,7 @@
         [TestCase("-315576000000s", null)]
         public void Duration_Valid(string jsonValue, string expectedFormatted)
         {
-            expectedFormatted = expectedFormatted ?? jsonValue;
+            expectedFormatted ??= jsonValue;
             string json = WrapInQuotes(jsonValue);
             var parsed = Duration.Parser.ParseJson(json);
             Assert.AreEqual(WrapInQuotes(expectedFormatted), parsed.ToString());
@@ -1066,25 +1072,26 @@
   ""mapStringNestedMessage"": null
 }";
 
-            TestAllTypesProto3 message = new TestAllTypesProto3();
-
-            message.OptionalInt32 = 1;
-            message.OptionalInt64 = 1;
-            message.OptionalUint32 = 1;
-            message.OptionalUint64 = 1;
-            message.OptionalSint32 = 1;
-            message.OptionalSint64 = 1;
-            message.OptionalFixed32 = 1;
-            message.OptionalFixed64 = 1;
-            message.OptionalSfixed32 = 1;
-            message.OptionalSfixed64 = 1;
-            message.OptionalFloat = 1;
-            message.OptionalDouble = 1;
-            message.OptionalBool = true;
-            message.OptionalString = "1";
-            message.OptionalBytes = ByteString.CopyFrom(new byte[] { 1 });
-            message.OptionalNestedEnum = TestAllTypesProto3.Types.NestedEnum.Bar;
-            message.OptionalNestedMessage = new TestAllTypesProto3.Types.NestedMessage();
+            var message = new TestAllTypesProto3
+            {
+                OptionalInt32 = 1,
+                OptionalInt64 = 1,
+                OptionalUint32 = 1,
+                OptionalUint64 = 1,
+                OptionalSint32 = 1,
+                OptionalSint64 = 1,
+                OptionalFixed32 = 1,
+                OptionalFixed64 = 1,
+                OptionalSfixed32 = 1,
+                OptionalSfixed64 = 1,
+                OptionalFloat = 1,
+                OptionalDouble = 1,
+                OptionalBool = true,
+                OptionalString = "1",
+                OptionalBytes = ByteString.CopyFrom(new byte[] { 1 }),
+                OptionalNestedEnum = TestAllTypesProto3.Types.NestedEnum.Bar,
+                OptionalNestedMessage = new TestAllTypesProto3.Types.NestedMessage()
+            };
             message.RepeatedInt32.Add(1);
             message.RepeatedInt64.Add(1);
             message.RepeatedUint32.Add(1);
diff --git a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
index df43eff..06521dd 100644
--- a/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
+++ b/csharp/src/Google.Protobuf.Test/JsonTokenizerTest.cs
@@ -29,6 +29,7 @@
 // (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.IO;
@@ -126,7 +127,7 @@
             tokenizer.PushBack(token);
             Assert.AreEqual(0, tokenizer.ObjectDepth);
             // Read the same token again, and get back to depth 1
-            token = tokenizer.Next();
+            _ = tokenizer.Next();
             Assert.AreEqual(1, tokenizer.ObjectDepth);
 
             // Now the same in reverse, with EndObject
diff --git a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
index 22adcaa..01fca3e 100644
--- a/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
+++ b/csharp/src/Google.Protobuf.Test/LegacyGeneratedCodeTest.cs
@@ -29,14 +29,12 @@
 // (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 pb = Google.Protobuf;
+using pbr = Google.Protobuf.Reflection;
 using NUnit.Framework;
 using System.IO;
-using System;
 using Google.Protobuf.Buffers;
 
 namespace Google.Protobuf
diff --git a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
index 05f1e36..f2eb762 100644
--- a/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
+++ b/csharp/src/Google.Protobuf.Test/MessageParsingHelpers.cs
@@ -136,8 +136,7 @@
             // test for different IBufferWriter.GetSpan() segment sizes
             for (int blockSize = 1; blockSize < 256; blockSize *= 2)
             {
-                var segmentedBufferWriter = new TestArrayBufferWriter<byte>();
-                segmentedBufferWriter.MaxGrowBy = blockSize;
+                var segmentedBufferWriter = new TestArrayBufferWriter<byte> { MaxGrowBy = blockSize };
                 message.WriteTo(segmentedBufferWriter);
                 Assert.AreEqual(bytes, segmentedBufferWriter.WrittenSpan.ToArray());
             }
diff --git a/csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs b/csharp/src/Google.Protobuf.Test/ParsingPrimitivesTest.cs
similarity index 62%
rename from csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs
rename to csharp/src/Google.Protobuf.Test/ParsingPrimitivesTest.cs
index 7b946cb..4d0aa9e 100644
--- a/csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs
+++ b/csharp/src/Google.Protobuf.Test/ParsingPrimitivesTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 // Protocol Buffers - Google's data interchange format
-// Copyright 2017 Google Inc.  All rights reserved.
+// Copyright 2022 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
 //
 // Redistribution and use in source and binary forms, with or without
@@ -30,18 +30,34 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-#if NET35
+using NUnit.Framework;
 using System;
-using System.Reflection;
+using System.Linq;
 
-namespace Google.Protobuf.Compatibility
+namespace Google.Protobuf.Test;
+
+internal class ParsingPrimitivesTest
 {
-    // .NET Core (at least netstandard1.0) doesn't have Delegate.CreateDelegate, and .NET 3.5 doesn't have
-    // MethodInfo.CreateDelegate. Proxy from one to the other on .NET 3.5...
-    internal static class MethodInfoExtensions
+    // Note: test cases use integers rather than bytes as they're easier
+    // to specify in attributes.
+
+    [Test]
+    [TestCase("\ufffd", 255)]
+    [TestCase("A\ufffd", 65, 255)]
+    [TestCase("A\ufffd\ufffdB", 65, 255, 255, 66)]
+    // Overlong form of "space"
+    [TestCase("\ufffd\ufffd", 0xc0, 0xa0)]
+    public void ReadRawString_NonUtf8(string expectedText, params int[] bytes)
     {
-        internal static Delegate CreateDelegate(this MethodInfo method, Type type) =>
-            Delegate.CreateDelegate(type, method);
+        var context = CreateContext(bytes);
+        string text = ParsingPrimitives.ReadRawString(ref context.buffer, ref context.state, bytes.Length);
+        Assert.AreEqual(expectedText, text);
+    }
+
+    private static ParseContext CreateContext(int[] bytes)
+    {
+        byte[] actualBytes = bytes.Select(b => (byte) b).ToArray();
+        ParseContext.Initialize(actualBytes.AsSpan(), out var context);
+        return context;
     }
 }
-#endif
diff --git a/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs
index 46a8c57..b5b0b72 100644
--- a/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Proto3OptionalTest.cs
@@ -38,7 +38,7 @@
 
 namespace Google.Protobuf.Test
 {
-    class Proto3OptionalTest
+    public class Proto3OptionalTest
     {
         [Test]
         public void OptionalInt32FieldLifecycle()
diff --git a/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
index f0248ac..d4dfd18 100644
--- a/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
+++ b/csharp/src/Google.Protobuf.Test/ReadOnlySequenceFactory.cs
@@ -33,9 +33,6 @@
 using System;
 using System.Buffers;
 using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
 
 namespace Google.Protobuf
 {
@@ -50,7 +47,7 @@
 
             if (addEmptySegmentDelimiters)
             {
-                segments.Add(new byte[0]);
+                segments.Add(Array.Empty<byte>());
             }
 
             var currentIndex = 0;
@@ -65,7 +62,7 @@
 
                 if (addEmptySegmentDelimiters)
                 {
-                    segments.Add(new byte[0]);
+                    segments.Add(Array.Empty<byte>());
                 }
             }
 
diff --git a/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs
index 9dca501..82f59b1 100644
--- a/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs
+++ b/csharp/src/Google.Protobuf.Test/RefStructCompatibilityTest.cs
@@ -67,7 +67,10 @@
             // 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}";
+            // We suppress CS1691, which flags a warning for the generated line of
+            // #pragma warning disable 1591, 0612, 3021, 8981
+            // because CS8981 is unknown to this version of the compiler.
+            var args = $"-langversion:3 -nologo -nowarn:1691 -target:library {compatibilityFlag} -reference:{testProtosOutputDir}\\Google.Protobuf.dll -out:{testProtosOutputDir}\\TestProtos.RefStructCompatibilityTest.OldCompiler.dll {sources}";
             RunOldCsharpCompilerAndCheckSuccess(args, testProtosProjectDir);
         }
 
@@ -77,43 +80,42 @@
         /// <param name="args"></param>
         /// <param name="workingDirectory"></param>
         private void RunOldCsharpCompilerAndCheckSuccess(string args, string workingDirectory)
-        {  
-            using (var process = new Process())
+        {
+            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) =>
             {
-                // 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)
                 {
-                    if (e.Data != null)
-                    {
-                        Console.WriteLine(e.Data);
-                    }
-                };
-                process.ErrorDataReceived += (sender, e) =>
+                    Console.WriteLine(e.Data);
+                }
+            };
+            process.ErrorDataReceived += (sender, e) =>
+            {
+                if (e.Data != null)
                 {
-                    if (e.Data != null)
-                    {
-                        Console.WriteLine(e.Data);
-                    }
-                };
+                    Console.WriteLine(e.Data);
+                }
+            };
 
-                process.Start();
+            process.Start();
 
-                process.BeginErrorReadLine();
-                process.BeginOutputReadLine();
+            process.BeginErrorReadLine();
+            process.BeginOutputReadLine();
 
-                process.WaitForExit();
-                Assert.AreEqual(0, process.ExitCode);
-            }
+            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 68b9bd3..589c35c 100644
--- a/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Reflection/CustomOptionsTest.cs
@@ -31,13 +31,10 @@
 #endregion
 
 using Google.Protobuf.Reflection;
-using Google.Protobuf.WellKnownTypes;
 using NUnit.Framework;
 using System;
-using System.IO;
 using System.Linq;
 using UnitTest.Issues.TestProtos;
-using static Google.Protobuf.WireFormat;
 using static UnitTest.Issues.TestProtos.ComplexOptionType2.Types;
 using static UnitTest.Issues.TestProtos.UnittestCustomOptionsProto3Extensions;
 using static UnitTest.Issues.TestProtos.DummyMessageContainingEnum.Types;
@@ -65,7 +62,7 @@
                 }
                 else
                 {
-                    v = default(E);
+                    v = default;
                     return false;
                 }
             };
diff --git a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
index 65c8b82..03722d4 100644
--- a/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
+++ b/csharp/src/Google.Protobuf.Test/Reflection/DescriptorsTest.cs
@@ -35,7 +35,6 @@
 using ProtobufUnittest;
 using System;
 using System.Collections.Generic;
-using System.IO;
 using System.Linq;
 using UnitTest.Issues.TestProtos;
 
diff --git a/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs
index f3e5af2..eeb9f89 100644
--- a/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs
+++ b/csharp/src/Google.Protobuf.Test/UnknownFieldSetTest.cs
@@ -30,10 +30,8 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using System;
 using System.IO;
 using Google.Protobuf.TestProtos;
-using Proto2 = Google.Protobuf.TestProtos.Proto2;
 using NUnit.Framework;
 
 namespace Google.Protobuf
@@ -127,8 +125,7 @@
         public void TestClone(IMessage message)
         {
             var emptyMessage = new TestEmptyMessage();
-            var otherEmptyMessage = new TestEmptyMessage();
-            otherEmptyMessage = emptyMessage.Clone();
+            TestEmptyMessage otherEmptyMessage = emptyMessage.Clone();
             Assert.AreEqual(emptyMessage.CalculateSize(), otherEmptyMessage.CalculateSize());
             Assert.AreEqual(emptyMessage.ToByteArray(), otherEmptyMessage.ToByteArray());
 
@@ -169,13 +166,13 @@
             byte[] data = message.ToByteArray();
             int fullSize = message.CalculateSize();
 
-            Action<IMessage> assertEmpty = msg =>
+            void AssertEmpty(IMessage msg)
             {
                 Assert.AreEqual(0, msg.CalculateSize());
                 Assert.AreEqual(goldenEmptyMessage, msg);
-            };
+            }
 
-            Action<IMessage> assertFull = msg => Assert.AreEqual(fullSize, msg.CalculateSize());
+            void AssertFull(IMessage msg) => Assert.AreEqual(fullSize, msg.CalculateSize());
 
             // Test the behavior of the parsers with and without discarding, both generic and non-generic.
             MessageParser<TestEmptyMessage> retainingParser1 = TestEmptyMessage.Parser;
@@ -184,28 +181,28 @@
             MessageParser discardingParser2 = retainingParser2.WithDiscardUnknownFields(true);
 
             // Test parse from byte[]
-            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));
+            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));
-            assertFull(retainingParser2.ParseFrom(data, 0, data.Length));
-            assertEmpty(discardingParser1.ParseFrom(data, 0, data.Length));
-            assertEmpty(discardingParser2.ParseFrom(data, 0, data.Length));
+            AssertFull(retainingParser1.ParseFrom(data, 0, data.Length));
+            AssertFull(retainingParser2.ParseFrom(data, 0, data.Length));
+            AssertEmpty(discardingParser1.ParseFrom(data, 0, data.Length));
+            AssertEmpty(discardingParser2.ParseFrom(data, 0, data.Length));
 
             // Test parse from CodedInputStream
-            assertFull(retainingParser1.ParseFrom(new CodedInputStream(data)));
-            assertFull(retainingParser2.ParseFrom(new CodedInputStream(data)));
-            assertEmpty(discardingParser1.ParseFrom(new CodedInputStream(data)));
-            assertEmpty(discardingParser2.ParseFrom(new CodedInputStream(data)));
+            AssertFull(retainingParser1.ParseFrom(new CodedInputStream(data)));
+            AssertFull(retainingParser2.ParseFrom(new CodedInputStream(data)));
+            AssertEmpty(discardingParser1.ParseFrom(new CodedInputStream(data)));
+            AssertEmpty(discardingParser2.ParseFrom(new CodedInputStream(data)));
 
             // Test parse from Stream
-            assertFull(retainingParser1.ParseFrom(new MemoryStream(data)));
-            assertFull(retainingParser2.ParseFrom(new MemoryStream(data)));
-            assertEmpty(discardingParser1.ParseFrom(new MemoryStream(data)));
-            assertEmpty(discardingParser2.ParseFrom(new MemoryStream(data)));
+            AssertFull(retainingParser1.ParseFrom(new MemoryStream(data)));
+            AssertFull(retainingParser2.ParseFrom(new MemoryStream(data)));
+            AssertEmpty(discardingParser1.ParseFrom(new MemoryStream(data)));
+            AssertEmpty(discardingParser2.ParseFrom(new MemoryStream(data)));
         }
 
         [Test]
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
index c05cb08..187e06a 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/AnyTest.cs
@@ -30,8 +30,11 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
+using Google.Protobuf.Reflection;
 using Google.Protobuf.TestProtos;
 using NUnit.Framework;
+using System.Linq;
+using UnitTest.Issues.TestProtos;
 
 namespace Google.Protobuf.WellKnownTypes
 {
@@ -123,7 +126,6 @@
         [TestCase("foobar", "")]
         public void GetTypeName(string typeUrl, string expectedTypeName)
         {
-            var any = new Any { TypeUrl = typeUrl };
             Assert.AreEqual(expectedTypeName, Any.GetTypeName(typeUrl));
         }
 
@@ -148,10 +150,34 @@
             Assert.False(any.Is(TestOneof.Descriptor));
         }
 
+        [Test]
         public void IsRightType()
         {
             var any = Any.Pack(SampleMessages.CreateFullTestAllTypes());
             Assert.True(any.Is(TestAllTypes.Descriptor));
         }
+
+        [Test]
+        public void Unpack_TypeRegistry()
+        {
+            var messages = new IMessage[]
+            {
+                SampleMessages.CreateFullTestAllTypes(),
+                new TestWellKnownTypes { BoolField = true },
+                new MoreString { Data = { "x" } },
+                new MoreBytes { Data = ByteString.CopyFromUtf8("xyz") },
+                new ReservedNames { Descriptor_ = 10 }
+            };
+            var anyMessages = messages.Select(Any.Pack);
+
+            // The type registry handles the first four of the packed messages, but not the final one.
+            var registry = TypeRegistry.FromFiles(
+                UnittestWellKnownTypesReflection.Descriptor,
+                UnittestProto3Reflection.Descriptor);
+            var unpacked = anyMessages.Select(any => any.Unpack(registry)).ToList();
+            var expected = (IMessage[]) messages.Clone();
+            expected[4] = null;
+            Assert.AreEqual(expected, unpacked);
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs b/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
index 141faf8..8124f0c 100644
--- a/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
+++ b/csharp/src/Google.Protobuf.Test/WellKnownTypes/DurationTest.cs
@@ -128,5 +128,38 @@
             var duration = new Duration { Seconds = 1, Nanos = -1 };
             Assert.AreEqual("{ \"@warning\": \"Invalid Duration\", \"seconds\": \"1\", \"nanos\": -1 }", duration.ToString());
         }
+
+        [Test]
+        public void Comparability()
+        {
+            Duration[] durationsInExpectedSortOrder =
+            {
+                null,
+                new Duration { Seconds = -10, Nanos = -10 },
+                new Duration { Seconds = -10, Nanos = -1 },
+                new Duration { Seconds = -1, Nanos = -10 },
+                new Duration { Seconds = -1, Nanos = -1 },
+                new Duration(),
+                new Duration { Seconds = 1, Nanos = 1 },
+                new Duration { Seconds = 1, Nanos = 10 },
+                new Duration { Seconds = 10, Nanos = 1 },
+                new Duration { Seconds = 10, Nanos = 10 }
+            };
+
+            for (int i = 0; i < durationsInExpectedSortOrder.Length; i++)
+            {
+                var target = durationsInExpectedSortOrder[i];
+                if (target is null)
+                {
+                    continue;
+                }
+                for (int j = 0; j < durationsInExpectedSortOrder.Length; j++)
+                {
+                    var expectedResult = Math.Sign(i - j);
+                    var actualResult = target.CompareTo(durationsInExpectedSortOrder[j]);
+                    Assert.AreEqual(expectedResult, actualResult);
+                }
+            }
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs b/csharp/src/Google.Protobuf.Test/WritingPrimitivesTest.cs
similarity index 62%
copy from csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs
copy to csharp/src/Google.Protobuf.Test/WritingPrimitivesTest.cs
index 7b946cb..069df34 100644
--- a/csharp/src/Google.Protobuf/Compatibility/MethodInfoExtensions.cs
+++ b/csharp/src/Google.Protobuf.Test/WritingPrimitivesTest.cs
@@ -1,6 +1,6 @@
 #region Copyright notice and license
 // Protocol Buffers - Google's data interchange format
-// Copyright 2017 Google Inc.  All rights reserved.
+// Copyright 2022 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
 //
 // Redistribution and use in source and binary forms, with or without
@@ -30,18 +30,32 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-#if NET35
+using NUnit.Framework;
 using System;
-using System.Reflection;
+using System.Collections.Generic;
+using System.Linq;
+using System.Text;
+using System.Threading.Tasks;
 
-namespace Google.Protobuf.Compatibility
+namespace Google.Protobuf.Test;
+
+internal class WritingPrimitivesTest
 {
-    // .NET Core (at least netstandard1.0) doesn't have Delegate.CreateDelegate, and .NET 3.5 doesn't have
-    // MethodInfo.CreateDelegate. Proxy from one to the other on .NET 3.5...
-    internal static class MethodInfoExtensions
+    [Test]
+    public void WriteRawString_IllFormedUnicodeString()
     {
-        internal static Delegate CreateDelegate(this MethodInfo method, Type type) =>
-            Delegate.CreateDelegate(type, method);
+        // See https://codeblog.jonskeet.uk/2014/11/07/when-is-a-string-not-a-string/
+        char c1 = '\u0058';
+        char c2 = '\ud800';
+        char c3 = '\u0059';
+        string text = new string(new[] { c1, c2, c3 });
+        Span<byte> buffer = new byte[10];
+        WriteContext.Initialize(ref buffer, out var context);
+        WritingPrimitives.WriteString(ref context.buffer, ref context.state, text);
+
+        // The high surrogate is written out in a "raw" form, surrounded by the ASCII
+        // characters.
+        byte[] expectedBytes = { 0x5, 0x58, 0xef, 0xbf, 0xbd, 0x59 };
+        Assert.AreEqual(expectedBytes, buffer.Slice(0, context.state.position).ToArray());
     }
 }
-#endif
diff --git a/csharp/src/Google.Protobuf.Test/testprotos.pb b/csharp/src/Google.Protobuf.Test/testprotos.pb
index 83958c6..106ada8 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.sln b/csharp/src/Google.Protobuf.sln
index b571e53..e5f38a6 100644
--- a/csharp/src/Google.Protobuf.sln
+++ b/csharp/src/Google.Protobuf.sln
@@ -1,60 +1,54 @@
-Microsoft Visual Studio Solution File, Format Version 12.00

-# Visual Studio 15

-VisualStudioVersion = 15.0.26114.2

-MinimumVisualStudioVersion = 10.0.40219.1

-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AddressBook", "AddressBook\AddressBook.csproj", "{AFB63919-1E05-43B4-802A-8FB8C9B2F463}"

-EndProject

-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{9B576380-726D-4142-8238-60A43AB0E35A}"

-EndProject

-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.csproj", "{580EB013-D3C7-4578-B845-015F4A3B0591}"

-EndProject

-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.csproj", "{DDDC055B-E185-4181-BAB0-072F0F984569}"

-EndProject

-Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{9695E08F-9829-497D-B95C-B38F28D48690}"

-EndProject

-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Benchmarks", "Google.Protobuf.Benchmarks\Google.Protobuf.Benchmarks.csproj", "{D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}"

-EndProject

-Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Test.TestProtos", "Google.Protobuf.Test.TestProtos\Google.Protobuf.Test.TestProtos.csproj", "{ADF24BEB-A318-4530-8448-356B72B820EA}"

-EndProject

-Global

-	GlobalSection(SolutionConfigurationPlatforms) = preSolution

-		Debug|Any CPU = Debug|Any CPU

-		Release|Any CPU = Release|Any CPU

-	EndGlobalSection

-	GlobalSection(ProjectConfigurationPlatforms) = postSolution

-		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Release|Any CPU.Build.0 = Release|Any CPU

-		{9B576380-726D-4142-8238-60A43AB0E35A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{9B576380-726D-4142-8238-60A43AB0E35A}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{9B576380-726D-4142-8238-60A43AB0E35A}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{9B576380-726D-4142-8238-60A43AB0E35A}.Release|Any CPU.Build.0 = Release|Any CPU

-		{580EB013-D3C7-4578-B845-015F4A3B0591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{580EB013-D3C7-4578-B845-015F4A3B0591}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{580EB013-D3C7-4578-B845-015F4A3B0591}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{580EB013-D3C7-4578-B845-015F4A3B0591}.Release|Any CPU.Build.0 = Release|Any CPU

-		{DDDC055B-E185-4181-BAB0-072F0F984569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{DDDC055B-E185-4181-BAB0-072F0F984569}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{DDDC055B-E185-4181-BAB0-072F0F984569}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{DDDC055B-E185-4181-BAB0-072F0F984569}.Release|Any CPU.Build.0 = Release|Any CPU

-		{9695E08F-9829-497D-B95C-B38F28D48690}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{9695E08F-9829-497D-B95C-B38F28D48690}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.Build.0 = Release|Any CPU

-		{D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{D25E4804-4DEA-45AB-9F8C-BA4DBD8E5A07}.Release|Any CPU.Build.0 = Release|Any CPU

-		{ADF24BEB-A318-4530-8448-356B72B820EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU

-		{ADF24BEB-A318-4530-8448-356B72B820EA}.Debug|Any CPU.Build.0 = Debug|Any CPU

-		{ADF24BEB-A318-4530-8448-356B72B820EA}.Release|Any CPU.ActiveCfg = Release|Any CPU

-		{ADF24BEB-A318-4530-8448-356B72B820EA}.Release|Any CPU.Build.0 = Release|Any CPU

-	EndGlobalSection

-	GlobalSection(SolutionProperties) = preSolution

-		HideSolutionNode = FALSE

-	EndGlobalSection

-	GlobalSection(ExtensibilityGlobals) = postSolution

-		SolutionGuid = {7B06C87B-83E1-4F5F-A0DD-6E9AFAC03DAC}

-	EndGlobalSection

-EndGlobal

+Microsoft Visual Studio Solution File, Format Version 12.00
+# Visual Studio 15
+VisualStudioVersion = 15.0.26114.2
+MinimumVisualStudioVersion = 10.0.40219.1
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "AddressBook", "AddressBook\AddressBook.csproj", "{AFB63919-1E05-43B4-802A-8FB8C9B2F463}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf", "Google.Protobuf\Google.Protobuf.csproj", "{9B576380-726D-4142-8238-60A43AB0E35A}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.Test", "Google.Protobuf.Test\Google.Protobuf.Test.csproj", "{580EB013-D3C7-4578-B845-015F4A3B0591}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.Conformance", "Google.Protobuf.Conformance\Google.Protobuf.Conformance.csproj", "{DDDC055B-E185-4181-BAB0-072F0F984569}"
+EndProject
+Project("{9A19103F-16F7-4668-BE54-9A1E7A4F7556}") = "Google.Protobuf.JsonDump", "Google.Protobuf.JsonDump\Google.Protobuf.JsonDump.csproj", "{9695E08F-9829-497D-B95C-B38F28D48690}"
+EndProject
+Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Google.Protobuf.Test.TestProtos", "Google.Protobuf.Test.TestProtos\Google.Protobuf.Test.TestProtos.csproj", "{ADF24BEB-A318-4530-8448-356B72B820EA}"
+EndProject
+Global
+	GlobalSection(SolutionConfigurationPlatforms) = preSolution
+		Debug|Any CPU = Debug|Any CPU
+		Release|Any CPU = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(ProjectConfigurationPlatforms) = postSolution
+		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{AFB63919-1E05-43B4-802A-8FB8C9B2F463}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9B576380-726D-4142-8238-60A43AB0E35A}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9B576380-726D-4142-8238-60A43AB0E35A}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9B576380-726D-4142-8238-60A43AB0E35A}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9B576380-726D-4142-8238-60A43AB0E35A}.Release|Any CPU.Build.0 = Release|Any CPU
+		{580EB013-D3C7-4578-B845-015F4A3B0591}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{580EB013-D3C7-4578-B845-015F4A3B0591}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{580EB013-D3C7-4578-B845-015F4A3B0591}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{580EB013-D3C7-4578-B845-015F4A3B0591}.Release|Any CPU.Build.0 = Release|Any CPU
+		{DDDC055B-E185-4181-BAB0-072F0F984569}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{DDDC055B-E185-4181-BAB0-072F0F984569}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{DDDC055B-E185-4181-BAB0-072F0F984569}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{DDDC055B-E185-4181-BAB0-072F0F984569}.Release|Any CPU.Build.0 = Release|Any CPU
+		{9695E08F-9829-497D-B95C-B38F28D48690}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{9695E08F-9829-497D-B95C-B38F28D48690}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{9695E08F-9829-497D-B95C-B38F28D48690}.Release|Any CPU.Build.0 = Release|Any CPU
+		{ADF24BEB-A318-4530-8448-356B72B820EA}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
+		{ADF24BEB-A318-4530-8448-356B72B820EA}.Debug|Any CPU.Build.0 = Debug|Any CPU
+		{ADF24BEB-A318-4530-8448-356B72B820EA}.Release|Any CPU.ActiveCfg = Release|Any CPU
+		{ADF24BEB-A318-4530-8448-356B72B820EA}.Release|Any CPU.Build.0 = Release|Any CPU
+	EndGlobalSection
+	GlobalSection(SolutionProperties) = preSolution
+		HideSolutionNode = FALSE
+	EndGlobalSection
+	GlobalSection(ExtensibilityGlobals) = postSolution
+		SolutionGuid = {7B06C87B-83E1-4F5F-A0DD-6E9AFAC03DAC}
+	EndGlobalSection
+EndGlobal
diff --git a/csharp/src/Google.Protobuf/ByteString.cs b/csharp/src/Google.Protobuf/ByteString.cs
index 8c6eb5b..b13b611 100644
--- a/csharp/src/Google.Protobuf/ByteString.cs
+++ b/csharp/src/Google.Protobuf/ByteString.cs
@@ -37,13 +37,8 @@
 using System.Runtime.InteropServices;
 using System.Security;
 using System.Text;
-#if !NET35
 using System.Threading;
 using System.Threading.Tasks;
-#endif
-#if NET35
-using Google.Protobuf.Compatibility;
-#endif
 
 namespace Google.Protobuf
 {
@@ -186,7 +181,6 @@
             return AttachBytes(bytes);
         }
 
-#if !NET35
         /// <summary>
         /// Constructs a <see cref="ByteString"/> from data in the given stream, asynchronously.
         /// </summary>
@@ -195,12 +189,11 @@
         /// <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 static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default(CancellationToken))
+        public static Task<ByteString> FromStreamAsync(Stream stream, CancellationToken cancellationToken = default)
         {
             ProtoPreconditions.CheckNotNull(stream, nameof(stream));
             return ByteStringAsync.FromStreamAsyncCore(stream, cancellationToken);
         }
-#endif
 
         /// <summary>
         /// Constructs a <see cref="ByteString" /> from the given array. The contents
@@ -347,7 +340,7 @@
             {
                 return true;
             }
-            if (ReferenceEquals(lhs, null) || ReferenceEquals(rhs, null))
+            if (lhs is null || rhs is null)
             {
                 return false;
             }
diff --git a/csharp/src/Google.Protobuf/ByteStringAsync.cs b/csharp/src/Google.Protobuf/ByteStringAsync.cs
index 3465cc6..5aa92f0 100644
--- a/csharp/src/Google.Protobuf/ByteStringAsync.cs
+++ b/csharp/src/Google.Protobuf/ByteStringAsync.cs
@@ -43,7 +43,6 @@
     /// </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;
@@ -59,6 +58,5 @@
 #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 96ae84c..aea546a 100644
--- a/csharp/src/Google.Protobuf/CodedInputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedInputStream.cs
@@ -32,10 +32,7 @@
 
 using Google.Protobuf.Collections;
 using System;
-using System.Collections.Generic;
 using System.IO;
-using System.Runtime.CompilerServices;
-using System.Runtime.InteropServices;
 using System.Security;
 
 namespace Google.Protobuf
@@ -650,21 +647,6 @@
         }
 
         /// <summary>
-        /// Called when buffer is empty to read more bytes from the
-        /// 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.
-        /// </summary>
-        /// <param name="mustSucceed"></param>
-        /// <returns></returns>
-        private bool RefillBuffer(bool mustSucceed)
-        {
-            var span = new ReadOnlySpan<byte>(buffer);
-            return state.segmentedBufferHelper.RefillBuffer(ref span, ref state, mustSucceed);
-        }
-
-        /// <summary>
         /// Reads a fixed size of bytes from the input.
         /// </summary>
         /// <exception cref="InvalidProtocolBufferException">
diff --git a/csharp/src/Google.Protobuf/CodedOutputStream.cs b/csharp/src/Google.Protobuf/CodedOutputStream.cs
index 5b8cca1..2a162c6 100644
--- a/csharp/src/Google.Protobuf/CodedOutputStream.cs
+++ b/csharp/src/Google.Protobuf/CodedOutputStream.cs
@@ -30,11 +30,9 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using Google.Protobuf.Collections;
 using System;
 using System.IO;
 using System.Security;
-using System.Text;
 
 namespace Google.Protobuf
 {
diff --git a/csharp/src/Google.Protobuf/Collections/Lists.cs b/csharp/src/Google.Protobuf/Collections/Lists.cs
index 860795c..9007709 100644
--- a/csharp/src/Google.Protobuf/Collections/Lists.cs
+++ b/csharp/src/Google.Protobuf/Collections/Lists.cs
@@ -31,7 +31,6 @@
 #endregion
 
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
 
 namespace Google.Protobuf.Collections
 {
diff --git a/csharp/src/Google.Protobuf/Collections/MapField.cs b/csharp/src/Google.Protobuf/Collections/MapField.cs
index e5217f4..09afb75 100644
--- a/csharp/src/Google.Protobuf/Collections/MapField.cs
+++ b/csharp/src/Google.Protobuf/Collections/MapField.cs
@@ -31,9 +31,7 @@
 #endregion
 
 using Google.Protobuf.Compatibility;
-using Google.Protobuf.Reflection;
 using System;
-using System.Buffers;
 using System.Collections;
 using System.Collections.Generic;
 using System.IO;
@@ -68,18 +66,14 @@
     /// in future versions.
     /// </para>
     /// </remarks>
-    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary
-#if !NET35
-        , IReadOnlyDictionary<TKey, TValue>
-#endif
+    public sealed class MapField<TKey, TValue> : IDeepCloneable<MapField<TKey, TValue>>, IDictionary<TKey, TValue>, IEquatable<MapField<TKey, TValue>>, IDictionary, IReadOnlyDictionary<TKey, TValue>
     {
         private static readonly EqualityComparer<TValue> ValueEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TValue>();
         private static readonly EqualityComparer<TKey> KeyEqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<TKey>();
 
         // TODO: Don't create the map/list until we have an entry. (Assume many maps will be empty.)
-        private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map =
-            new Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>>(KeyEqualityComparer);
-        private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new LinkedList<KeyValuePair<TKey, TValue>>();
+        private readonly Dictionary<TKey, LinkedListNode<KeyValuePair<TKey, TValue>>> map = new(KeyEqualityComparer);
+        private readonly LinkedList<KeyValuePair<TKey, TValue>> list = new();
 
         /// <summary>
         /// Creates a deep clone of this object.
@@ -147,8 +141,7 @@
         public bool Remove(TKey key)
         {
             ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
-            LinkedListNode<KeyValuePair<TKey, TValue>> node;
-            if (map.TryGetValue(key, out node))
+            if (map.TryGetValue(key, out LinkedListNode<KeyValuePair<TKey, TValue>> node))
             {
                 map.Remove(key);
                 node.List.Remove(node);
@@ -170,15 +163,14 @@
         /// <returns><c>true</c> if the map contains an element with the specified key; otherwise, <c>false</c>.</returns>
         public bool TryGetValue(TKey key, out TValue value)
         {
-            LinkedListNode<KeyValuePair<TKey, TValue>> node;
-            if (map.TryGetValue(key, out node))
+            if (map.TryGetValue(key, out LinkedListNode<KeyValuePair<TKey, TValue>> node))
             {
                 value = node.Value.Value;
                 return true;
             }
             else
             {
-                value = default(TValue);
+                value = default;
                 return false;
             }
         }
@@ -195,8 +187,7 @@
             get
             {
                 ProtoPreconditions.CheckNotNullUnconstrained(key, nameof(key));
-                TValue value;
-                if (TryGetValue(key, out value))
+                if (TryGetValue(key, out TValue value))
                 {
                     return value;
                 }
@@ -210,9 +201,8 @@
                 {
                     ProtoPreconditions.CheckNotNullUnconstrained(value, nameof(value));
                 }
-                LinkedListNode<KeyValuePair<TKey, TValue>> node;
                 var pair = new KeyValuePair<TKey, TValue>(key, value);
-                if (map.TryGetValue(key, out node))
+                if (map.TryGetValue(key, out LinkedListNode<KeyValuePair<TKey, TValue>> node))
                 {
                     node.Value = pair;
                 }
@@ -227,12 +217,12 @@
         /// <summary>
         /// Gets a collection containing the keys in the map.
         /// </summary>
-        public ICollection<TKey> Keys { get { return new MapView<TKey>(this, pair => pair.Key, ContainsKey); } }
+        public ICollection<TKey> Keys => new MapView<TKey>(this, pair => pair.Key, ContainsKey);
 
         /// <summary>
         /// Gets a collection containing the values in the map.
         /// </summary>
-        public ICollection<TValue> Values { get { return new MapView<TValue>(this, pair => pair.Value, ContainsValue); } }
+        public ICollection<TValue> Values => new MapView<TValue>(this, pair => pair.Value, ContainsValue);
 
         /// <summary>
         /// Adds the specified entries to the map. The keys and values are not automatically cloned.
@@ -248,15 +238,27 @@
         }
 
         /// <summary>
+        /// Adds the specified entries to the map, replacing any existing entries with the same keys.
+        /// The keys and values are not automatically cloned.
+        /// </summary>
+        /// <remarks>This method primarily exists to be called from MergeFrom methods in generated classes for messages.</remarks>
+        /// <param name="entries">The entries to add to the map.</param>
+        public void MergeFrom(IDictionary<TKey, TValue> entries)
+        {
+            ProtoPreconditions.CheckNotNull(entries, nameof(entries));
+            foreach (var pair in entries)
+            {
+                this[pair.Key] = pair.Value;
+            }
+        }
+
+        /// <summary>
         /// Returns an enumerator that iterates through the collection.
         /// </summary>
         /// <returns>
         /// An enumerator that can be used to iterate through the collection.
         /// </returns>
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-        {
-            return list.GetEnumerator();
-        }
+        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator() => list.GetEnumerator();
 
         /// <summary>
         /// Returns an enumerator that iterates through a collection.
@@ -264,19 +266,13 @@
         /// <returns>
         /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
         /// </returns>
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
+        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 
         /// <summary>
         /// Adds the specified item to the map.
         /// </summary>
         /// <param name="item">The item to add to the map.</param>
-        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item)
-        {
-            Add(item.Key, item.Value);
-        }
+        void ICollection<KeyValuePair<TKey, TValue>>.Add(KeyValuePair<TKey, TValue> item) => Add(item.Key, item.Value);
 
         /// <summary>
         /// Removes all items from the map.
@@ -292,21 +288,16 @@
         /// </summary>
         /// <param name="item">The key/value pair to find.</param>
         /// <returns></returns>
-        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item)
-        {
-            TValue value;
-            return TryGetValue(item.Key, out value) && ValueEqualityComparer.Equals(item.Value, value);
-        }
+        bool ICollection<KeyValuePair<TKey, TValue>>.Contains(KeyValuePair<TKey, TValue> item) =>
+            TryGetValue(item.Key, out TValue value) && ValueEqualityComparer.Equals(item.Value, value);
 
         /// <summary>
         /// Copies the key/value pairs in this map to an array.
         /// </summary>
         /// <param name="array">The array to copy the entries into.</param>
         /// <param name="arrayIndex">The index of the array at which to start copying values.</param>
-        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
-        {
+        void ICollection<KeyValuePair<TKey, TValue>>.CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex) =>
             list.CopyTo(array, arrayIndex);
-        }
 
         /// <summary>
         /// Removes the specified key/value pair from the map.
@@ -320,8 +311,7 @@
             {
                 throw new ArgumentException("Key is null", nameof(item));
             }
-            LinkedListNode<KeyValuePair<TKey, TValue>> node;
-            if (map.TryGetValue(item.Key, out node) &&
+            if (map.TryGetValue(item.Key, out LinkedListNode<KeyValuePair<TKey, TValue>> node) &&
                 EqualityComparer<TValue>.Default.Equals(item.Value, node.Value.Value))
             {
                 map.Remove(item.Key);
@@ -337,12 +327,12 @@
         /// <summary>
         /// Gets the number of elements contained in the map.
         /// </summary>
-        public int Count { get { return list.Count; } }
+        public int Count => list.Count;
 
         /// <summary>
         /// Gets a value indicating whether the map is read-only.
         /// </summary>
-        public bool IsReadOnly { get { return false; } }
+        public bool IsReadOnly => false;
 
         /// <summary>
         /// Determines whether the specified <see cref="System.Object" />, is equal to this instance.
@@ -351,10 +341,7 @@
         /// <returns>
         ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
         /// </returns>
-        public override bool Equals(object other)
-        {
-            return Equals(other as MapField<TKey, TValue>);
-        }
+        public override bool Equals(object other) => Equals(other as MapField<TKey, TValue>);
 
         /// <summary>
         /// Returns a hash code for this instance.
@@ -399,8 +386,7 @@
             var valueComparer = ValueEqualityComparer;
             foreach (var pair in this)
             {
-                TValue value;
-                if (!other.TryGetValue(pair.Key, out value))
+                if (!other.TryGetValue(pair.Key, out TValue value))
                 {
                     return false;
                 }
@@ -532,33 +518,20 @@
         }
 
         #region IDictionary explicit interface implementation
-        void IDictionary.Add(object key, object value)
-        {
-            Add((TKey)key, (TValue)value);
-        }
 
-        bool IDictionary.Contains(object key)
-        {
-            if (!(key is TKey))
-            {
-                return false;
-            }
-            return ContainsKey((TKey)key);
-        }
+        void IDictionary.Add(object key, object value) => Add((TKey)key, (TValue)value);
 
-        IDictionaryEnumerator IDictionary.GetEnumerator()
-        {
-            return new DictionaryEnumerator(GetEnumerator());
-        }
+        bool IDictionary.Contains(object key) => key is TKey k && ContainsKey(k);
+
+        IDictionaryEnumerator IDictionary.GetEnumerator() => new DictionaryEnumerator(GetEnumerator());
 
         void IDictionary.Remove(object key)
         {
             ProtoPreconditions.CheckNotNull(key, nameof(key));
-            if (!(key is TKey))
+            if (key is TKey k)
             {
-                return;
+                Remove(k);
             }
-            Remove((TKey)key);
         }
 
         void ICollection.CopyTo(Array array, int index)
@@ -568,28 +541,27 @@
             temp.CopyTo(array, index);
         }
 
-        bool IDictionary.IsFixedSize { get { return false; } }
+        bool IDictionary.IsFixedSize => false;
 
-        ICollection IDictionary.Keys { get { return (ICollection)Keys; } }
+        ICollection IDictionary.Keys => (ICollection)Keys;
 
-        ICollection IDictionary.Values { get { return (ICollection)Values; } }
+        ICollection IDictionary.Values => (ICollection)Values;
 
-        bool ICollection.IsSynchronized { get { return false; } }
+        bool ICollection.IsSynchronized => false;
 
-        object ICollection.SyncRoot { get { return this; } }
+        object ICollection.SyncRoot => this;
 
         object IDictionary.this[object key]
         {
             get
             {
                 ProtoPreconditions.CheckNotNull(key, nameof(key));
-                if (!(key is TKey))
+                if (key is TKey k)
                 {
-                    return null;
+                    TryGetValue(k, out TValue value);
+                    return value;
                 }
-                TValue value;
-                TryGetValue((TKey)key, out value);
-                return value;
+                return null;
             }
 
             set
@@ -600,11 +572,8 @@
         #endregion
 
         #region IReadOnlyDictionary explicit interface implementation
-#if !NET35
         IEnumerable<TKey> IReadOnlyDictionary<TKey, TValue>.Keys => Keys;
-
         IEnumerable<TValue> IReadOnlyDictionary<TKey, TValue>.Values => Values;
-#endif
         #endregion
 
         private class DictionaryEnumerator : IDictionaryEnumerator
@@ -616,20 +585,14 @@
                 this.enumerator = enumerator;
             }
 
-            public bool MoveNext()
-            {
-                return enumerator.MoveNext();
-            }
+            public bool MoveNext() => enumerator.MoveNext();
 
-            public void Reset()
-            {
-                enumerator.Reset();
-            }
+            public void Reset() => enumerator.Reset();
 
-            public object Current { get { return Entry; } }
-            public DictionaryEntry Entry { get { return new DictionaryEntry(Key, Value); } }
-            public object Key { get { return enumerator.Current.Key; } }
-            public object Value { get { return enumerator.Current.Value; } }
+            public object Current => Entry;
+            public DictionaryEntry Entry => new DictionaryEntry(Key, Value);
+            public object Key => enumerator.Current.Key;
+            public object Value => enumerator.Current.Value;
         }
 
         /// <summary>
@@ -688,28 +651,19 @@
                 this.containsCheck = containsCheck;
             }
 
-            public int Count { get { return parent.Count; } }
+            public int Count => parent.Count; 
 
-            public bool IsReadOnly { get { return true; } }
+            public bool IsReadOnly => true;
 
-            public bool IsSynchronized { get { return false; } }
+            public bool IsSynchronized => false;
 
-            public object SyncRoot { get { return parent; } }
+            public object SyncRoot => parent;
 
-            public void Add(T item)
-            {
-                throw new NotSupportedException();
-            }
+            public void Add(T item) => throw new NotSupportedException();
 
-            public void Clear()
-            {
-                throw new NotSupportedException();
-            }
+            public void Clear() => throw new NotSupportedException();
 
-            public bool Contains(T item)
-            {
-                return containsCheck(item);
-            }
+            public bool Contains(T item) => containsCheck(item);
 
             public void CopyTo(T[] array, int arrayIndex)
             {
@@ -732,15 +686,9 @@
                 return parent.list.Select(projection).GetEnumerator();
             }
 
-            public bool Remove(T item)
-            {
-                throw new NotSupportedException();
-            }
+            public bool Remove(T item) => throw new NotSupportedException();
 
-            IEnumerator IEnumerable.GetEnumerator()
-            {
-                return GetEnumerator();
-            }
+            IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 
             public void CopyTo(Array array, int index)
             {
diff --git a/csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs b/csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs
deleted file mode 100644
index 28530a2..0000000
--- a/csharp/src/Google.Protobuf/Collections/ReadOnlyDictionary.cs
+++ /dev/null
@@ -1,147 +0,0 @@
-#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.Collections;
-using System.Collections.Generic;
-
-namespace Google.Protobuf.Collections
-{
-    /// <summary>
-    /// Read-only wrapper around another dictionary.
-    /// </summary>
-    internal sealed class ReadOnlyDictionary<TKey, TValue> : IDictionary<TKey, TValue>
-    {
-        private readonly IDictionary<TKey, TValue> wrapped;
-
-        public ReadOnlyDictionary(IDictionary<TKey, TValue> wrapped)
-        {
-            this.wrapped = wrapped;
-        }
-
-        public void Add(TKey key, TValue value)
-        {
-            throw new InvalidOperationException();
-        }
-
-        public bool ContainsKey(TKey key)
-        {
-            return wrapped.ContainsKey(key);
-        }
-
-        public ICollection<TKey> Keys
-        {
-            get { return wrapped.Keys; }
-        }
-
-        public bool Remove(TKey key)
-        {
-            throw new InvalidOperationException();
-        }
-
-        public bool TryGetValue(TKey key, out TValue value)
-        {
-            return wrapped.TryGetValue(key, out value);
-        }
-
-        public ICollection<TValue> Values
-        {
-            get { return wrapped.Values; }
-        }
-
-        public TValue this[TKey key]
-        {
-            get { return wrapped[key]; }
-            set { throw new InvalidOperationException(); }
-        }
-
-        public void Add(KeyValuePair<TKey, TValue> item)
-        {
-            throw new InvalidOperationException();
-        }
-
-        public void Clear()
-        {
-            throw new InvalidOperationException();
-        }
-
-        public bool Contains(KeyValuePair<TKey, TValue> item)
-        {
-            return wrapped.Contains(item);
-        }
-
-        public void CopyTo(KeyValuePair<TKey, TValue>[] array, int arrayIndex)
-        {
-            wrapped.CopyTo(array, arrayIndex);
-        }
-
-        public int Count
-        {
-            get { return wrapped.Count; }
-        }
-
-        public bool IsReadOnly
-        {
-            get { return true; }
-        }
-
-        public bool Remove(KeyValuePair<TKey, TValue> item)
-        {
-            throw new InvalidOperationException();
-        }
-
-        public IEnumerator<KeyValuePair<TKey, TValue>> GetEnumerator()
-        {
-            return wrapped.GetEnumerator();
-        }
-
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return ((IEnumerable) wrapped).GetEnumerator();
-        }
-
-        public override bool Equals(object obj)
-        {
-            return wrapped.Equals(obj);
-        }
-
-        public override int GetHashCode()
-        {
-            return wrapped.GetHashCode();
-        }
-
-        public override string ToString()
-        {
-            return wrapped.ToString();
-        }
-    }
-}
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
index 9269c74..56117fd 100644
--- a/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
+++ b/csharp/src/Google.Protobuf/Collections/RepeatedField.cs
@@ -35,7 +35,6 @@
 using System.Collections.Generic;
 using System.IO;
 using System.Security;
-using System.Threading;
 
 namespace Google.Protobuf.Collections
 {
@@ -48,10 +47,7 @@
     /// supported by Protocol Buffers but nor does it guarantee that all operations will work in such cases.
     /// </remarks>
     /// <typeparam name="T">The element type of the repeated field.</typeparam>
-    public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>
-#if !NET35
-        , IReadOnlyList<T>
-#endif
+    public sealed class RepeatedField<T> : IList<T>, IList, IDeepCloneable<RepeatedField<T>>, IEquatable<RepeatedField<T>>, IReadOnlyList<T>
     {
         private static readonly EqualityComparer<T> EqualityComparer = ProtobufEqualityComparers.GetEqualityComparer<T>();
         private static readonly T[] EmptyArray = new T[0];
@@ -77,8 +73,7 @@
             if (array != EmptyArray)
             {
                 clone.array = (T[])array.Clone();
-                IDeepCloneable<T>[] cloneableArray = clone.array as IDeepCloneable<T>[];
-                if (cloneableArray != null)
+                if (clone.array is IDeepCloneable<T>[] cloneableArray)
                 {
                     for (int i = 0; i < count; i++)
                     {
@@ -284,8 +279,9 @@
         }
 
         /// <summary>
-        /// Gets and sets the capacity of the RepeatedField's internal array.  WHen set, the internal array is reallocated to the given capacity.
-        /// <exception cref="ArgumentOutOfRangeException">The new value is less than Count -or- when Count is less than 0.</exception>
+        /// Gets and sets the capacity of the RepeatedField's internal array.
+        /// When set, the internal array is reallocated to the given capacity.
+        /// <exception cref="ArgumentOutOfRangeException">The new value is less than <see cref="Count"/>.</exception>
         /// </summary>
         public int Capacity
         {
@@ -343,7 +339,10 @@
         /// </summary>
         public void Clear()
         {
-            array = EmptyArray;
+            // Clear the content of the array (so that any objects it referred to can be garbage collected)
+            // but keep the capacity the same. This allows large repeated fields to be reused without
+            // array reallocation.
+            Array.Clear(array, 0, count);
             count = 0;
         }
 
@@ -352,10 +351,7 @@
         /// </summary>
         /// <param name="item">The item to find.</param>
         /// <returns><c>true</c> if this collection contains the given item; <c>false</c> otherwise.</returns>
-        public bool Contains(T item)
-        {
-            return IndexOf(item) != -1;
-        }
+        public bool Contains(T item) => IndexOf(item) != -1;
 
         /// <summary>
         /// Copies this collection to the given array.
@@ -381,7 +377,7 @@
             }            
             Array.Copy(array, index + 1, array, index, count - index - 1);
             count--;
-            array[count] = default(T);
+            array[count] = default;
             return true;
         }
 
@@ -405,8 +401,7 @@
 
             // Optimization 1: If the collection we're adding is already a RepeatedField<T>,
             // we know the values are valid.
-            var otherRepeatedField = values as RepeatedField<T>;
-            if (otherRepeatedField != null)
+            if (values is RepeatedField<T> otherRepeatedField)
             {
                 EnsureSize(count + otherRepeatedField.count);
                 Array.Copy(otherRepeatedField.array, 0, array, count, otherRepeatedField.count);
@@ -416,8 +411,7 @@
 
             // Optimization 2: The collection is an ICollection, so we can expand
             // just once and ask the collection to copy itself into the array.
-            var collection = values as ICollection;
-            if (collection != null)
+            if (values is ICollection collection)
             {
                 var extraCount = collection.Count;
                 // For reference types and nullable value types, we need to check that there are no nulls
@@ -487,21 +481,15 @@
         /// <returns>
         ///   <c>true</c> if the specified <see cref="System.Object" /> is equal to this instance; otherwise, <c>false</c>.
         /// </returns>
-        public override bool Equals(object obj)
-        {
-            return Equals(obj as RepeatedField<T>);
-        }
-
+        public override bool Equals(object obj) => Equals(obj as RepeatedField<T>);
+        
         /// <summary>
         /// Returns an enumerator that iterates through a collection.
         /// </summary>
         /// <returns>
         /// An <see cref="T:System.Collections.IEnumerator" /> object that can be used to iterate through the collection.
         /// </returns>
-        IEnumerator IEnumerable.GetEnumerator()
-        {
-            return GetEnumerator();
-        }
+        IEnumerator IEnumerable.GetEnumerator() => GetEnumerator();
 
         /// <summary>
         /// Returns a hash code for this instance.
@@ -526,7 +514,7 @@
         /// <returns><c>true</c> if <paramref name="other"/> refers to an equal repeated field; <c>false</c> otherwise.</returns>
         public bool Equals(RepeatedField<T> other)
         {
-            if (ReferenceEquals(other, null))
+            if (other is null)
             {
                 return false;
             }
@@ -599,7 +587,7 @@
             }
             Array.Copy(array, index + 1, array, index, count - index - 1);
             count--;
-            array[count] = default(T);
+            array[count] = default;
         }
 
         /// <summary>
@@ -645,10 +633,7 @@
         #region Explicit interface implementation for IList and ICollection.
         bool IList.IsFixedSize => false;
 
-        void ICollection.CopyTo(Array array, int index)
-        {
-            Array.Copy(this.array, 0, array, index, count);
-        }
+        void ICollection.CopyTo(Array array, int index) => Array.Copy(this.array, 0, array, index, count);
 
         bool ICollection.IsSynchronized => false;
 
@@ -656,8 +641,8 @@
 
         object IList.this[int index]
         {
-            get { return this[index]; }
-            set { this[index] = (T)value; }
+            get => this[index];
+            set => this[index] = (T)value;
         }
 
         int IList.Add(object value)
@@ -666,32 +651,18 @@
             return count - 1;
         }
 
-        bool IList.Contains(object value)
-        {
-            return (value is T && Contains((T)value));
-        }
+        bool IList.Contains(object value) => (value is T t && Contains(t));
 
-        int IList.IndexOf(object value)
-        {
-            if (!(value is T))
-            {
-                return -1;
-            }
-            return IndexOf((T)value);
-        }
+        int IList.IndexOf(object value) => (value is T t) ? IndexOf(t) : -1;
 
-        void IList.Insert(int index, object value)
-        {
-            Insert(index, (T) value);
-        }
+        void IList.Insert(int index, object value) => Insert(index, (T) value);
 
         void IList.Remove(object value)
         {
-            if (!(value is T))
+            if (value is T t)
             {
-                return;
+                Remove(t);
             }
-            Remove((T)value);
         }
         #endregion        
     }
diff --git a/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
index 95a02c7..8a6fefa 100644
--- a/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
+++ b/csharp/src/Google.Protobuf/Compatibility/PropertyInfoExtensions.cs
@@ -47,11 +47,7 @@
         /// </summary>
         internal static MethodInfo GetGetMethod(this PropertyInfo target)
         {
-#if NET35
-            var method = target.GetGetMethod();
-#else
             var method = target.GetMethod;
-#endif
             return method != null && method.IsPublic ? method : null;
         }
 
@@ -61,11 +57,7 @@
         /// </summary>
         internal static MethodInfo GetSetMethod(this PropertyInfo target)
         {
-#if NET35
-            var method = target.GetSetMethod();
-#else
             var method = target.SetMethod;
-#endif
             return method != null && method.IsPublic ? method : null;
         }
     }
diff --git a/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs
deleted file mode 100644
index bf4bf22..0000000
--- a/csharp/src/Google.Protobuf/Compatibility/StreamExtensions.cs
+++ /dev/null
@@ -1,66 +0,0 @@
-#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
-
-#if NET35
-using System;
-using System.IO;
-
-namespace Google.Protobuf.Compatibility
-{
-    /// <summary>
-    /// Extension methods for <see cref="Stream"/> in order to provide
-    /// backwards compatibility with .NET 3.5
-    /// </summary>
-    public static class StreamExtensions
-    {
-        // 81920 seems to be the default buffer size used in .NET 4.5.1
-        private const int BUFFER_SIZE = 81920;
-
-        /// <summary>
-        /// Write the contents of the current stream to the destination stream
-        /// </summary>
-        public static void CopyTo(this Stream source, Stream destination)
-        {
-            if (destination == null)
-            {
-                throw new ArgumentNullException(nameof(destination));
-            }
-
-            byte[] buffer = new byte[BUFFER_SIZE];
-            int numBytesRead;
-            while ((numBytesRead = source.Read(buffer, 0, buffer.Length)) > 0) {
-                destination.Write(buffer, 0, numBytesRead);
-            }
-        }
-    }
-}
-#endif
diff --git a/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs b/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
index b3acda2..5db5dca 100644
--- a/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
+++ b/csharp/src/Google.Protobuf/Compatibility/TypeExtensions.cs
@@ -34,7 +34,6 @@
 using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 
-#if !NET35
 namespace Google.Protobuf.Compatibility
 {
     /// <summary>
@@ -112,4 +111,3 @@
         }
     }
 }
-#endif
diff --git a/csharp/src/Google.Protobuf/Compiler/Plugin.pb.cs b/csharp/src/Google.Protobuf/Compiler/Plugin.pb.cs
new file mode 100644
index 0000000..f3a6c17
--- /dev/null
+++ b/csharp/src/Google.Protobuf/Compiler/Plugin.pb.cs
@@ -0,0 +1,1490 @@
+// <auto-generated>
+//     Generated by the protocol buffer compiler.  DO NOT EDIT!
+//     source: google/protobuf/compiler/plugin.proto
+// </auto-generated>
+#pragma warning disable 1591, 0612, 3021, 8981
+#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 Google.Protobuf.Compiler {
+
+  /// <summary>Holder for reflection information generated from google/protobuf/compiler/plugin.proto</summary>
+  public static partial class PluginReflection {
+
+    #region Descriptor
+    /// <summary>File descriptor for google/protobuf/compiler/plugin.proto</summary>
+    public static pbr::FileDescriptor Descriptor {
+      get { return descriptor; }
+    }
+    private static pbr::FileDescriptor descriptor;
+
+    static PluginReflection() {
+      byte[] descriptorData = global::System.Convert.FromBase64String(
+          string.Concat(
+            "CiVnb29nbGUvcHJvdG9idWYvY29tcGlsZXIvcGx1Z2luLnByb3RvEhhnb29n",
+            "bGUucHJvdG9idWYuY29tcGlsZXIaIGdvb2dsZS9wcm90b2J1Zi9kZXNjcmlw",
+            "dG9yLnByb3RvIkYKB1ZlcnNpb24SDQoFbWFqb3IYASABKAUSDQoFbWlub3IY",
+            "AiABKAUSDQoFcGF0Y2gYAyABKAUSDgoGc3VmZml4GAQgASgJIroBChRDb2Rl",
+            "R2VuZXJhdG9yUmVxdWVzdBIYChBmaWxlX3RvX2dlbmVyYXRlGAEgAygJEhEK",
+            "CXBhcmFtZXRlchgCIAEoCRI4Cgpwcm90b19maWxlGA8gAygLMiQuZ29vZ2xl",
+            "LnByb3RvYnVmLkZpbGVEZXNjcmlwdG9yUHJvdG8SOwoQY29tcGlsZXJfdmVy",
+            "c2lvbhgDIAEoCzIhLmdvb2dsZS5wcm90b2J1Zi5jb21waWxlci5WZXJzaW9u",
+            "IsECChVDb2RlR2VuZXJhdG9yUmVzcG9uc2USDQoFZXJyb3IYASABKAkSGgoS",
+            "c3VwcG9ydGVkX2ZlYXR1cmVzGAIgASgEEkIKBGZpbGUYDyADKAsyNC5nb29n",
+            "bGUucHJvdG9idWYuY29tcGlsZXIuQ29kZUdlbmVyYXRvclJlc3BvbnNlLkZp",
+            "bGUafwoERmlsZRIMCgRuYW1lGAEgASgJEhcKD2luc2VydGlvbl9wb2ludBgC",
+            "IAEoCRIPCgdjb250ZW50GA8gASgJEj8KE2dlbmVyYXRlZF9jb2RlX2luZm8Y",
+            "ECABKAsyIi5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVkQ29kZUluZm8iOAoH",
+            "RmVhdHVyZRIQCgxGRUFUVVJFX05PTkUQABIbChdGRUFUVVJFX1BST1RPM19P",
+            "UFRJT05BTBABQlcKHGNvbS5nb29nbGUucHJvdG9idWYuY29tcGlsZXJCDFBs",
+            "dWdpblByb3Rvc1opZ29vZ2xlLmdvbGFuZy5vcmcvcHJvdG9idWYvdHlwZXMv",
+            "cGx1Z2lucGI="));
+      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::Google.Protobuf.Compiler.Version), global::Google.Protobuf.Compiler.Version.Parser, new[]{ "Major", "Minor", "Patch", "Suffix" }, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorRequest), global::Google.Protobuf.Compiler.CodeGeneratorRequest.Parser, new[]{ "FileToGenerate", "Parameter", "ProtoFile", "CompilerVersion" }, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse), global::Google.Protobuf.Compiler.CodeGeneratorResponse.Parser, new[]{ "Error", "SupportedFeatures", "File" }, null, new[]{ typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.Feature) }, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File), global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File.Parser, new[]{ "Name", "InsertionPoint", "Content", "GeneratedCodeInfo" }, null, null, null, null)})
+          }));
+    }
+    #endregion
+
+  }
+  #region Messages
+  /// <summary>
+  /// The version number of protocol compiler.
+  /// </summary>
+  public sealed partial class Version : pb::IMessage<Version>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<Version> _parser = new pb::MessageParser<Version>(() => new Version());
+    private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<Version> 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.Compiler.PluginReflection.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 Version() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public Version(Version other) : this() {
+      _hasBits0 = other._hasBits0;
+      major_ = other.major_;
+      minor_ = other.minor_;
+      patch_ = other.patch_;
+      suffix_ = other.suffix_;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public Version Clone() {
+      return new Version(this);
+    }
+
+    /// <summary>Field number for the "major" field.</summary>
+    public const int MajorFieldNumber = 1;
+    private readonly static int MajorDefaultValue = 0;
+
+    private int major_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Major {
+      get { if ((_hasBits0 & 1) != 0) { return major_; } else { return MajorDefaultValue; } }
+      set {
+        _hasBits0 |= 1;
+        major_ = value;
+      }
+    }
+    /// <summary>Gets whether the "major" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasMajor {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "major" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearMajor() {
+      _hasBits0 &= ~1;
+    }
+
+    /// <summary>Field number for the "minor" field.</summary>
+    public const int MinorFieldNumber = 2;
+    private readonly static int MinorDefaultValue = 0;
+
+    private int minor_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Minor {
+      get { if ((_hasBits0 & 2) != 0) { return minor_; } else { return MinorDefaultValue; } }
+      set {
+        _hasBits0 |= 2;
+        minor_ = value;
+      }
+    }
+    /// <summary>Gets whether the "minor" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasMinor {
+      get { return (_hasBits0 & 2) != 0; }
+    }
+    /// <summary>Clears the value of the "minor" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearMinor() {
+      _hasBits0 &= ~2;
+    }
+
+    /// <summary>Field number for the "patch" field.</summary>
+    public const int PatchFieldNumber = 3;
+    private readonly static int PatchDefaultValue = 0;
+
+    private int patch_;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public int Patch {
+      get { if ((_hasBits0 & 4) != 0) { return patch_; } else { return PatchDefaultValue; } }
+      set {
+        _hasBits0 |= 4;
+        patch_ = value;
+      }
+    }
+    /// <summary>Gets whether the "patch" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasPatch {
+      get { return (_hasBits0 & 4) != 0; }
+    }
+    /// <summary>Clears the value of the "patch" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearPatch() {
+      _hasBits0 &= ~4;
+    }
+
+    /// <summary>Field number for the "suffix" field.</summary>
+    public const int SuffixFieldNumber = 4;
+    private readonly static string SuffixDefaultValue = "";
+
+    private string suffix_;
+    /// <summary>
+    /// A suffix for alpha, beta or rc release, e.g., "alpha-1", "rc2". It should
+    /// be empty for mainline stable releases.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string Suffix {
+      get { return suffix_ ?? SuffixDefaultValue; }
+      set {
+        suffix_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "suffix" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasSuffix {
+      get { return suffix_ != null; }
+    }
+    /// <summary>Clears the value of the "suffix" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearSuffix() {
+      suffix_ = null;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as Version);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(Version other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Major != other.Major) return false;
+      if (Minor != other.Minor) return false;
+      if (Patch != other.Patch) return false;
+      if (Suffix != other.Suffix) 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 (HasMajor) hash ^= Major.GetHashCode();
+      if (HasMinor) hash ^= Minor.GetHashCode();
+      if (HasPatch) hash ^= Patch.GetHashCode();
+      if (HasSuffix) hash ^= Suffix.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 (HasMajor) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Major);
+      }
+      if (HasMinor) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Minor);
+      }
+      if (HasPatch) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Patch);
+      }
+      if (HasSuffix) {
+        output.WriteRawTag(34);
+        output.WriteString(Suffix);
+      }
+      if (_unknownFields != null) {
+        _unknownFields.WriteTo(output);
+      }
+    #endif
+    }
+
+    #if !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 (HasMajor) {
+        output.WriteRawTag(8);
+        output.WriteInt32(Major);
+      }
+      if (HasMinor) {
+        output.WriteRawTag(16);
+        output.WriteInt32(Minor);
+      }
+      if (HasPatch) {
+        output.WriteRawTag(24);
+        output.WriteInt32(Patch);
+      }
+      if (HasSuffix) {
+        output.WriteRawTag(34);
+        output.WriteString(Suffix);
+      }
+      if (_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 (HasMajor) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Major);
+      }
+      if (HasMinor) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Minor);
+      }
+      if (HasPatch) {
+        size += 1 + pb::CodedOutputStream.ComputeInt32Size(Patch);
+      }
+      if (HasSuffix) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Suffix);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(Version other) {
+      if (other == null) {
+        return;
+      }
+      if (other.HasMajor) {
+        Major = other.Major;
+      }
+      if (other.HasMinor) {
+        Minor = other.Minor;
+      }
+      if (other.HasPatch) {
+        Patch = other.Patch;
+      }
+      if (other.HasSuffix) {
+        Suffix = other.Suffix;
+      }
+      _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: {
+            Major = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Minor = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Patch = input.ReadInt32();
+            break;
+          }
+          case 34: {
+            Suffix = 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: {
+            Major = input.ReadInt32();
+            break;
+          }
+          case 16: {
+            Minor = input.ReadInt32();
+            break;
+          }
+          case 24: {
+            Patch = input.ReadInt32();
+            break;
+          }
+          case 34: {
+            Suffix = input.ReadString();
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
+  /// <summary>
+  /// An encoded CodeGeneratorRequest is written to the plugin's stdin.
+  /// </summary>
+  public sealed partial class CodeGeneratorRequest : pb::IMessage<CodeGeneratorRequest>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<CodeGeneratorRequest> _parser = new pb::MessageParser<CodeGeneratorRequest>(() => new CodeGeneratorRequest());
+    private pb::UnknownFieldSet _unknownFields;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<CodeGeneratorRequest> 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.Compiler.PluginReflection.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 CodeGeneratorRequest() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public CodeGeneratorRequest(CodeGeneratorRequest other) : this() {
+      fileToGenerate_ = other.fileToGenerate_.Clone();
+      parameter_ = other.parameter_;
+      protoFile_ = other.protoFile_.Clone();
+      compilerVersion_ = other.compilerVersion_ != null ? other.compilerVersion_.Clone() : null;
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public CodeGeneratorRequest Clone() {
+      return new CodeGeneratorRequest(this);
+    }
+
+    /// <summary>Field number for the "file_to_generate" field.</summary>
+    public const int FileToGenerateFieldNumber = 1;
+    private static readonly pb::FieldCodec<string> _repeated_fileToGenerate_codec
+        = pb::FieldCodec.ForString(10);
+    private readonly pbc::RepeatedField<string> fileToGenerate_ = new pbc::RepeatedField<string>();
+    /// <summary>
+    /// The .proto files that were explicitly listed on the command-line.  The
+    /// code generator should generate code only for these files.  Each file's
+    /// descriptor will be included in proto_file, below.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pbc::RepeatedField<string> FileToGenerate {
+      get { return fileToGenerate_; }
+    }
+
+    /// <summary>Field number for the "parameter" field.</summary>
+    public const int ParameterFieldNumber = 2;
+    private readonly static string ParameterDefaultValue = "";
+
+    private string parameter_;
+    /// <summary>
+    /// The generator parameter passed on the command-line.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string Parameter {
+      get { return parameter_ ?? ParameterDefaultValue; }
+      set {
+        parameter_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "parameter" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasParameter {
+      get { return parameter_ != null; }
+    }
+    /// <summary>Clears the value of the "parameter" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearParameter() {
+      parameter_ = null;
+    }
+
+    /// <summary>Field number for the "proto_file" field.</summary>
+    public const int ProtoFileFieldNumber = 15;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Reflection.FileDescriptorProto> _repeated_protoFile_codec
+        = pb::FieldCodec.ForMessage(122, global::Google.Protobuf.Reflection.FileDescriptorProto.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto> protoFile_ = new pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto>();
+    /// <summary>
+    /// FileDescriptorProtos for all files in files_to_generate and everything
+    /// they import.  The files will appear in topological order, so each file
+    /// appears before any file that imports it.
+    ///
+    /// protoc guarantees that all proto_files will be written after
+    /// the fields above, even though this is not technically guaranteed by the
+    /// protobuf wire format.  This theoretically could allow a plugin to stream
+    /// in the FileDescriptorProtos and handle them one by one rather than read
+    /// the entire set into memory at once.  However, as of this writing, this
+    /// is not similarly optimized on protoc's end -- it will store all fields in
+    /// memory at once before sending them to the plugin.
+    ///
+    /// Type names of fields and extensions in the FileDescriptorProto are always
+    /// fully qualified.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pbc::RepeatedField<global::Google.Protobuf.Reflection.FileDescriptorProto> ProtoFile {
+      get { return protoFile_; }
+    }
+
+    /// <summary>Field number for the "compiler_version" field.</summary>
+    public const int CompilerVersionFieldNumber = 3;
+    private global::Google.Protobuf.Compiler.Version compilerVersion_;
+    /// <summary>
+    /// The version number of protocol compiler.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public global::Google.Protobuf.Compiler.Version CompilerVersion {
+      get { return compilerVersion_; }
+      set {
+        compilerVersion_ = value;
+      }
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public override bool Equals(object other) {
+      return Equals(other as CodeGeneratorRequest);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(CodeGeneratorRequest other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if(!fileToGenerate_.Equals(other.fileToGenerate_)) return false;
+      if (Parameter != other.Parameter) return false;
+      if(!protoFile_.Equals(other.protoFile_)) return false;
+      if (!object.Equals(CompilerVersion, other.CompilerVersion)) 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;
+      hash ^= fileToGenerate_.GetHashCode();
+      if (HasParameter) hash ^= Parameter.GetHashCode();
+      hash ^= protoFile_.GetHashCode();
+      if (compilerVersion_ != null) hash ^= CompilerVersion.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
+      fileToGenerate_.WriteTo(output, _repeated_fileToGenerate_codec);
+      if (HasParameter) {
+        output.WriteRawTag(18);
+        output.WriteString(Parameter);
+      }
+      if (compilerVersion_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(CompilerVersion);
+      }
+      protoFile_.WriteTo(output, _repeated_protoFile_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) {
+      fileToGenerate_.WriteTo(ref output, _repeated_fileToGenerate_codec);
+      if (HasParameter) {
+        output.WriteRawTag(18);
+        output.WriteString(Parameter);
+      }
+      if (compilerVersion_ != null) {
+        output.WriteRawTag(26);
+        output.WriteMessage(CompilerVersion);
+      }
+      protoFile_.WriteTo(ref output, _repeated_protoFile_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 += fileToGenerate_.CalculateSize(_repeated_fileToGenerate_codec);
+      if (HasParameter) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Parameter);
+      }
+      size += protoFile_.CalculateSize(_repeated_protoFile_codec);
+      if (compilerVersion_ != null) {
+        size += 1 + pb::CodedOutputStream.ComputeMessageSize(CompilerVersion);
+      }
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(CodeGeneratorRequest other) {
+      if (other == null) {
+        return;
+      }
+      fileToGenerate_.Add(other.fileToGenerate_);
+      if (other.HasParameter) {
+        Parameter = other.Parameter;
+      }
+      protoFile_.Add(other.protoFile_);
+      if (other.compilerVersion_ != null) {
+        if (compilerVersion_ == null) {
+          CompilerVersion = new global::Google.Protobuf.Compiler.Version();
+        }
+        CompilerVersion.MergeFrom(other.CompilerVersion);
+      }
+      _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: {
+            fileToGenerate_.AddEntriesFrom(input, _repeated_fileToGenerate_codec);
+            break;
+          }
+          case 18: {
+            Parameter = input.ReadString();
+            break;
+          }
+          case 26: {
+            if (compilerVersion_ == null) {
+              CompilerVersion = new global::Google.Protobuf.Compiler.Version();
+            }
+            input.ReadMessage(CompilerVersion);
+            break;
+          }
+          case 122: {
+            protoFile_.AddEntriesFrom(input, _repeated_protoFile_codec);
+            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: {
+            fileToGenerate_.AddEntriesFrom(ref input, _repeated_fileToGenerate_codec);
+            break;
+          }
+          case 18: {
+            Parameter = input.ReadString();
+            break;
+          }
+          case 26: {
+            if (compilerVersion_ == null) {
+              CompilerVersion = new global::Google.Protobuf.Compiler.Version();
+            }
+            input.ReadMessage(CompilerVersion);
+            break;
+          }
+          case 122: {
+            protoFile_.AddEntriesFrom(ref input, _repeated_protoFile_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+  }
+
+  /// <summary>
+  /// The plugin writes an encoded CodeGeneratorResponse to stdout.
+  /// </summary>
+  public sealed partial class CodeGeneratorResponse : pb::IMessage<CodeGeneratorResponse>
+  #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+      , pb::IBufferMessage
+  #endif
+  {
+    private static readonly pb::MessageParser<CodeGeneratorResponse> _parser = new pb::MessageParser<CodeGeneratorResponse>(() => new CodeGeneratorResponse());
+    private pb::UnknownFieldSet _unknownFields;
+    private int _hasBits0;
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static pb::MessageParser<CodeGeneratorResponse> 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.Compiler.PluginReflection.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 CodeGeneratorResponse() {
+      OnConstruction();
+    }
+
+    partial void OnConstruction();
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public CodeGeneratorResponse(CodeGeneratorResponse other) : this() {
+      _hasBits0 = other._hasBits0;
+      error_ = other.error_;
+      supportedFeatures_ = other.supportedFeatures_;
+      file_ = other.file_.Clone();
+      _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public CodeGeneratorResponse Clone() {
+      return new CodeGeneratorResponse(this);
+    }
+
+    /// <summary>Field number for the "error" field.</summary>
+    public const int ErrorFieldNumber = 1;
+    private readonly static string ErrorDefaultValue = "";
+
+    private string error_;
+    /// <summary>
+    /// Error message.  If non-empty, code generation failed.  The plugin process
+    /// should exit with status code zero even if it reports an error in this way.
+    ///
+    /// This should be used to indicate errors in .proto files which prevent the
+    /// code generator from generating correct code.  Errors which indicate a
+    /// problem in protoc itself -- such as the input CodeGeneratorRequest being
+    /// unparseable -- should be reported by writing a message to stderr and
+    /// exiting with a non-zero status code.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string Error {
+      get { return error_ ?? ErrorDefaultValue; }
+      set {
+        error_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "error" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasError {
+      get { return error_ != null; }
+    }
+    /// <summary>Clears the value of the "error" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearError() {
+      error_ = null;
+    }
+
+    /// <summary>Field number for the "supported_features" field.</summary>
+    public const int SupportedFeaturesFieldNumber = 2;
+    private readonly static ulong SupportedFeaturesDefaultValue = 0UL;
+
+    private ulong supportedFeatures_;
+    /// <summary>
+    /// A bitmask of supported features that the code generator supports.
+    /// This is a bitwise "or" of values from the Feature enum.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public ulong SupportedFeatures {
+      get { if ((_hasBits0 & 1) != 0) { return supportedFeatures_; } else { return SupportedFeaturesDefaultValue; } }
+      set {
+        _hasBits0 |= 1;
+        supportedFeatures_ = value;
+      }
+    }
+    /// <summary>Gets whether the "supported_features" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasSupportedFeatures {
+      get { return (_hasBits0 & 1) != 0; }
+    }
+    /// <summary>Clears the value of the "supported_features" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearSupportedFeatures() {
+      _hasBits0 &= ~1;
+    }
+
+    /// <summary>Field number for the "file" field.</summary>
+    public const int FileFieldNumber = 15;
+    private static readonly pb::FieldCodec<global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File> _repeated_file_codec
+        = pb::FieldCodec.ForMessage(122, global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File.Parser);
+    private readonly pbc::RepeatedField<global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File> file_ = new pbc::RepeatedField<global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File>();
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public pbc::RepeatedField<global::Google.Protobuf.Compiler.CodeGeneratorResponse.Types.File> 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 CodeGeneratorResponse);
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool Equals(CodeGeneratorResponse other) {
+      if (ReferenceEquals(other, null)) {
+        return false;
+      }
+      if (ReferenceEquals(other, this)) {
+        return true;
+      }
+      if (Error != other.Error) return false;
+      if (SupportedFeatures != other.SupportedFeatures) return false;
+      if(!file_.Equals(other.file_)) 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 (HasError) hash ^= Error.GetHashCode();
+      if (HasSupportedFeatures) hash ^= SupportedFeatures.GetHashCode();
+      hash ^= file_.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 (HasError) {
+        output.WriteRawTag(10);
+        output.WriteString(Error);
+      }
+      if (HasSupportedFeatures) {
+        output.WriteRawTag(16);
+        output.WriteUInt64(SupportedFeatures);
+      }
+      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) {
+      if (HasError) {
+        output.WriteRawTag(10);
+        output.WriteString(Error);
+      }
+      if (HasSupportedFeatures) {
+        output.WriteRawTag(16);
+        output.WriteUInt64(SupportedFeatures);
+      }
+      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;
+      if (HasError) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Error);
+      }
+      if (HasSupportedFeatures) {
+        size += 1 + pb::CodedOutputStream.ComputeUInt64Size(SupportedFeatures);
+      }
+      size += file_.CalculateSize(_repeated_file_codec);
+      if (_unknownFields != null) {
+        size += _unknownFields.CalculateSize();
+      }
+      return size;
+    }
+
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void MergeFrom(CodeGeneratorResponse other) {
+      if (other == null) {
+        return;
+      }
+      if (other.HasError) {
+        Error = other.Error;
+      }
+      if (other.HasSupportedFeatures) {
+        SupportedFeatures = other.SupportedFeatures;
+      }
+      file_.Add(other.file_);
+      _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: {
+            Error = input.ReadString();
+            break;
+          }
+          case 16: {
+            SupportedFeatures = input.ReadUInt64();
+            break;
+          }
+          case 122: {
+            file_.AddEntriesFrom(input, _repeated_file_codec);
+            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: {
+            Error = input.ReadString();
+            break;
+          }
+          case 16: {
+            SupportedFeatures = input.ReadUInt64();
+            break;
+          }
+          case 122: {
+            file_.AddEntriesFrom(ref input, _repeated_file_codec);
+            break;
+          }
+        }
+      }
+    }
+    #endif
+
+    #region Nested types
+    /// <summary>Container for nested types declared in the CodeGeneratorResponse message type.</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public static partial class Types {
+      /// <summary>
+      /// Sync with code_generator.h.
+      /// </summary>
+      public enum Feature {
+        [pbr::OriginalName("FEATURE_NONE")] None = 0,
+        [pbr::OriginalName("FEATURE_PROTO3_OPTIONAL")] Proto3Optional = 1,
+      }
+
+      /// <summary>
+      /// Represents a single generated file.
+      /// </summary>
+      public sealed partial class File : pb::IMessage<File>
+      #if !GOOGLE_PROTOBUF_REFSTRUCT_COMPATIBILITY_MODE
+          , pb::IBufferMessage
+      #endif
+      {
+        private static readonly pb::MessageParser<File> _parser = new pb::MessageParser<File>(() => new File());
+        private pb::UnknownFieldSet _unknownFields;
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static pb::MessageParser<File> 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.Compiler.CodeGeneratorResponse.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 File() {
+          OnConstruction();
+        }
+
+        partial void OnConstruction();
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public File(File other) : this() {
+          name_ = other.name_;
+          insertionPoint_ = other.insertionPoint_;
+          content_ = other.content_;
+          generatedCodeInfo_ = other.generatedCodeInfo_ != null ? other.generatedCodeInfo_.Clone() : null;
+          _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public File Clone() {
+          return new File(this);
+        }
+
+        /// <summary>Field number for the "name" field.</summary>
+        public const int NameFieldNumber = 1;
+        private readonly static string NameDefaultValue = "";
+
+        private string name_;
+        /// <summary>
+        /// The file name, relative to the output directory.  The name must not
+        /// contain "." or ".." components and must be relative, not be absolute (so,
+        /// the file cannot lie outside the output directory).  "/" must be used as
+        /// the path separator, not "\".
+        ///
+        /// If the name is omitted, the content will be appended to the previous
+        /// file.  This allows the generator to break large files into small chunks,
+        /// and allows the generated text to be streamed back to protoc so that large
+        /// files need not reside completely in memory at one time.  Note that as of
+        /// this writing protoc does not optimize for this -- it will read the entire
+        /// CodeGeneratorResponse before writing files to disk.
+        /// </summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public string Name {
+          get { return name_ ?? NameDefaultValue; }
+          set {
+            name_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+        /// <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;
+        }
+
+        /// <summary>Field number for the "insertion_point" field.</summary>
+        public const int InsertionPointFieldNumber = 2;
+        private readonly static string InsertionPointDefaultValue = "";
+
+        private string insertionPoint_;
+        /// <summary>
+        /// If non-empty, indicates that the named file should already exist, and the
+        /// content here is to be inserted into that file at a defined insertion
+        /// point.  This feature allows a code generator to extend the output
+        /// produced by another code generator.  The original generator may provide
+        /// insertion points by placing special annotations in the file that look
+        /// like:
+        ///   @@protoc_insertion_point(NAME)
+        /// The annotation can have arbitrary text before and after it on the line,
+        /// which allows it to be placed in a comment.  NAME should be replaced with
+        /// an identifier naming the point -- this is what other generators will use
+        /// as the insertion_point.  Code inserted at this point will be placed
+        /// immediately above the line containing the insertion point (thus multiple
+        /// insertions to the same point will come out in the order they were added).
+        /// The double-@ is intended to make it unlikely that the generated code
+        /// could contain things that look like insertion points by accident.
+        ///
+        /// For example, the C++ code generator places the following line in the
+        /// .pb.h files that it generates:
+        ///   // @@protoc_insertion_point(namespace_scope)
+        /// This line appears within the scope of the file's package namespace, but
+        /// outside of any particular class.  Another plugin can then specify the
+        /// insertion_point "namespace_scope" to generate additional classes or
+        /// other declarations that should be placed in this scope.
+        ///
+        /// Note that if the line containing the insertion point begins with
+        /// whitespace, the same whitespace will be added to every line of the
+        /// inserted text.  This is useful for languages like Python, where
+        /// indentation matters.  In these languages, the insertion point comment
+        /// should be indented the same amount as any inserted code will need to be
+        /// in order to work correctly in that context.
+        ///
+        /// The code generator that generates the initial file and the one which
+        /// inserts into it must both run as part of a single invocation of protoc.
+        /// Code generators are executed in the order in which they appear on the
+        /// command line.
+        ///
+        /// If |insertion_point| is present, |name| must also be present.
+        /// </summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public string InsertionPoint {
+          get { return insertionPoint_ ?? InsertionPointDefaultValue; }
+          set {
+            insertionPoint_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+        /// <summary>Gets whether the "insertion_point" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool HasInsertionPoint {
+          get { return insertionPoint_ != null; }
+        }
+        /// <summary>Clears the value of the "insertion_point" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void ClearInsertionPoint() {
+          insertionPoint_ = null;
+        }
+
+        /// <summary>Field number for the "content" field.</summary>
+        public const int ContentFieldNumber = 15;
+        private readonly static string ContentDefaultValue = "";
+
+        private string content_;
+        /// <summary>
+        /// The file contents.
+        /// </summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public string Content {
+          get { return content_ ?? ContentDefaultValue; }
+          set {
+            content_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+          }
+        }
+        /// <summary>Gets whether the "content" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool HasContent {
+          get { return content_ != null; }
+        }
+        /// <summary>Clears the value of the "content" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void ClearContent() {
+          content_ = null;
+        }
+
+        /// <summary>Field number for the "generated_code_info" field.</summary>
+        public const int GeneratedCodeInfoFieldNumber = 16;
+        private global::Google.Protobuf.Reflection.GeneratedCodeInfo generatedCodeInfo_;
+        /// <summary>
+        /// 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.
+        /// </summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public global::Google.Protobuf.Reflection.GeneratedCodeInfo GeneratedCodeInfo {
+          get { return generatedCodeInfo_; }
+          set {
+            generatedCodeInfo_ = value;
+          }
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public override bool Equals(object other) {
+          return Equals(other as File);
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool Equals(File other) {
+          if (ReferenceEquals(other, null)) {
+            return false;
+          }
+          if (ReferenceEquals(other, this)) {
+            return true;
+          }
+          if (Name != other.Name) return false;
+          if (InsertionPoint != other.InsertionPoint) return false;
+          if (Content != other.Content) return false;
+          if (!object.Equals(GeneratedCodeInfo, other.GeneratedCodeInfo)) 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 (HasName) hash ^= Name.GetHashCode();
+          if (HasInsertionPoint) hash ^= InsertionPoint.GetHashCode();
+          if (HasContent) hash ^= Content.GetHashCode();
+          if (generatedCodeInfo_ != null) hash ^= GeneratedCodeInfo.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 (HasName) {
+            output.WriteRawTag(10);
+            output.WriteString(Name);
+          }
+          if (HasInsertionPoint) {
+            output.WriteRawTag(18);
+            output.WriteString(InsertionPoint);
+          }
+          if (HasContent) {
+            output.WriteRawTag(122);
+            output.WriteString(Content);
+          }
+          if (generatedCodeInfo_ != null) {
+            output.WriteRawTag(130, 1);
+            output.WriteMessage(GeneratedCodeInfo);
+          }
+          if (_unknownFields != null) {
+            _unknownFields.WriteTo(output);
+          }
+        #endif
+        }
+
+        #if !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 (HasInsertionPoint) {
+            output.WriteRawTag(18);
+            output.WriteString(InsertionPoint);
+          }
+          if (HasContent) {
+            output.WriteRawTag(122);
+            output.WriteString(Content);
+          }
+          if (generatedCodeInfo_ != null) {
+            output.WriteRawTag(130, 1);
+            output.WriteMessage(GeneratedCodeInfo);
+          }
+          if (_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 (HasInsertionPoint) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(InsertionPoint);
+          }
+          if (HasContent) {
+            size += 1 + pb::CodedOutputStream.ComputeStringSize(Content);
+          }
+          if (generatedCodeInfo_ != null) {
+            size += 2 + pb::CodedOutputStream.ComputeMessageSize(GeneratedCodeInfo);
+          }
+          if (_unknownFields != null) {
+            size += _unknownFields.CalculateSize();
+          }
+          return size;
+        }
+
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void MergeFrom(File other) {
+          if (other == null) {
+            return;
+          }
+          if (other.HasName) {
+            Name = other.Name;
+          }
+          if (other.HasInsertionPoint) {
+            InsertionPoint = other.InsertionPoint;
+          }
+          if (other.HasContent) {
+            Content = other.Content;
+          }
+          if (other.generatedCodeInfo_ != null) {
+            if (generatedCodeInfo_ == null) {
+              GeneratedCodeInfo = new global::Google.Protobuf.Reflection.GeneratedCodeInfo();
+            }
+            GeneratedCodeInfo.MergeFrom(other.GeneratedCodeInfo);
+          }
+          _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: {
+                Name = input.ReadString();
+                break;
+              }
+              case 18: {
+                InsertionPoint = input.ReadString();
+                break;
+              }
+              case 122: {
+                Content = input.ReadString();
+                break;
+              }
+              case 130: {
+                if (generatedCodeInfo_ == null) {
+                  GeneratedCodeInfo = new global::Google.Protobuf.Reflection.GeneratedCodeInfo();
+                }
+                input.ReadMessage(GeneratedCodeInfo);
+                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: {
+                InsertionPoint = input.ReadString();
+                break;
+              }
+              case 122: {
+                Content = input.ReadString();
+                break;
+              }
+              case 130: {
+                if (generatedCodeInfo_ == null) {
+                  GeneratedCodeInfo = new global::Google.Protobuf.Reflection.GeneratedCodeInfo();
+                }
+                input.ReadMessage(GeneratedCodeInfo);
+                break;
+              }
+            }
+          }
+        }
+        #endif
+
+      }
+
+    }
+    #endregion
+
+  }
+
+  #endregion
+
+}
+
+#endregion Designer generated code
diff --git a/csharp/src/Google.Protobuf/Extension.cs b/csharp/src/Google.Protobuf/Extension.cs
index d10a668..2807260 100644
--- a/csharp/src/Google.Protobuf/Extension.cs
+++ b/csharp/src/Google.Protobuf/Extension.cs
@@ -77,7 +77,7 @@
             this.codec = codec;
         }
 
-        internal TValue DefaultValue => codec != null ? codec.DefaultValue : default(TValue);
+        internal TValue DefaultValue => codec != null ? codec.DefaultValue : default;
 
         internal override Type TargetType => typeof(TTarget);
 
diff --git a/csharp/src/Google.Protobuf/ExtensionRegistry.cs b/csharp/src/Google.Protobuf/ExtensionRegistry.cs
index e72314b..be381f0 100644
--- a/csharp/src/Google.Protobuf/ExtensionRegistry.cs
+++ b/csharp/src/Google.Protobuf/ExtensionRegistry.cs
@@ -55,7 +55,7 @@
 
             internal static ExtensionComparer Instance = new ExtensionComparer();
         }
-        private IDictionary<ObjectIntPair<Type>, Extension> extensions;
+        private readonly IDictionary<ObjectIntPair<Type>, Extension> extensions;
 
         /// <summary>
         /// Creates a new empty extension registry
diff --git a/csharp/src/Google.Protobuf/ExtensionSet.cs b/csharp/src/Google.Protobuf/ExtensionSet.cs
index 306e45e..aa1acbd 100644
--- a/csharp/src/Google.Protobuf/ExtensionSet.cs
+++ b/csharp/src/Google.Protobuf/ExtensionSet.cs
@@ -61,8 +61,7 @@
         /// </summary>
         public static TValue Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
         {
-            IExtensionValue value;
-            if (TryGetValue(ref set, extension, out value))
+            if (TryGetValue(ref set, extension, out IExtensionValue value))
             {
                 // The stored ExtensionValue can be a different type to what is being requested.
                 // This happens when the same extension proto is compiled in different assemblies.
@@ -98,7 +97,7 @@
                     }
                 }
             }
-            else 
+            else
             {
                 return extension.DefaultValue;
             }
@@ -109,8 +108,7 @@
         /// </summary>
         public static RepeatedField<TValue> Get<TTarget, TValue>(ref ExtensionSet<TTarget> set, RepeatedExtension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
         {
-            IExtensionValue value;
-            if (TryGetValue(ref set, extension, out value))
+            if (TryGetValue(ref set, extension, out IExtensionValue value))
             {
                 if (value is RepeatedExtensionValue<TValue> extensionValue)
                 {
@@ -132,7 +130,7 @@
                     }
                 }
             }
-            else 
+            else
             {
                 return null;
             }
@@ -193,8 +191,7 @@
         /// </summary>
         public static bool Has<TTarget, TValue>(ref ExtensionSet<TTarget> set, Extension<TTarget, TValue> extension) where TTarget : IExtendableMessage<TTarget>
         {
-            IExtensionValue value;
-            return TryGetValue(ref set, extension, out value);
+            return TryGetValue(ref set, extension, out IExtensionValue _);
         }
 
         /// <summary>
@@ -252,20 +249,18 @@
         /// </summary>
         public static bool TryMergeFieldFrom<TTarget>(ref ExtensionSet<TTarget> set, ref ParseContext ctx) where TTarget : IExtendableMessage<TTarget>
         {
-            Extension extension;
             int lastFieldNumber = WireFormat.GetTagFieldNumber(ctx.LastTag);
 
-            IExtensionValue extensionValue;
-            if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out extensionValue))
+            if (set != null && set.ValuesByNumber.TryGetValue(lastFieldNumber, out IExtensionValue extensionValue))
             {
                 extensionValue.MergeFrom(ref ctx);
                 return true;
             }
-            else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out extension))
+            else if (ctx.ExtensionRegistry != null && ctx.ExtensionRegistry.ContainsInputField(ctx.LastTag, typeof(TTarget), out Extension extension))
             {
                 IExtensionValue value = extension.CreateValue();
                 value.MergeFrom(ref ctx);
-                set = (set ?? new ExtensionSet<TTarget>());
+                set ??= new ExtensionSet<TTarget>();
                 set.ValuesByNumber.Add(extension.FieldNumber, value);
                 return true;
             }
@@ -290,8 +285,7 @@
             }
             foreach (var pair in second.ValuesByNumber)
             {
-                IExtensionValue value;
-                if (first.ValuesByNumber.TryGetValue(pair.Key, out value))
+                if (first.ValuesByNumber.TryGetValue(pair.Key, out IExtensionValue value))
                 {
                     value.MergeFrom(pair.Value);
                 }
@@ -365,8 +359,7 @@
             }
             foreach (var pair in ValuesByNumber)
             {
-                IExtensionValue secondValue;
-                if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out secondValue))
+                if (!otherSet.ValuesByNumber.TryGetValue(pair.Key, out IExtensionValue secondValue))
                 {
                     return false;
                 }
diff --git a/csharp/src/Google.Protobuf/ExtensionValue.cs b/csharp/src/Google.Protobuf/ExtensionValue.cs
index 1329b2f..9637f1b 100644
--- a/csharp/src/Google.Protobuf/ExtensionValue.cs
+++ b/csharp/src/Google.Protobuf/ExtensionValue.cs
@@ -32,7 +32,6 @@
 
 using Google.Protobuf.Collections;
 using System;
-using System.Linq;
 
 namespace Google.Protobuf
 {
@@ -50,7 +49,7 @@
     internal sealed class ExtensionValue<T> : IExtensionValue
     {
         private T field;
-        private FieldCodec<T> codec;
+        private readonly FieldCodec<T> codec;
 
         internal ExtensionValue(FieldCodec<T> codec)
         {
diff --git a/csharp/src/Google.Protobuf/FieldCodec.cs b/csharp/src/Google.Protobuf/FieldCodec.cs
index ee6bd6a..d3b0b71 100644
--- a/csharp/src/Google.Protobuf/FieldCodec.cs
+++ b/csharp/src/Google.Protobuf/FieldCodec.cs
@@ -31,7 +31,6 @@
 #endregion
 
 using Google.Protobuf.Collections;
-using Google.Protobuf.Compatibility;
 using Google.Protobuf.WellKnownTypes;
 using System;
 using System.Collections.Generic;
@@ -51,150 +50,105 @@
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<string> ForString(uint tag)
-        {
-            return FieldCodec.ForString(tag, "");
-        }
+        public static FieldCodec<string> ForString(uint tag) => ForString(tag, "");
 
         /// <summary>
         /// Retrieves a codec suitable for a bytes field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<ByteString> ForBytes(uint tag)
-        {
-            return FieldCodec.ForBytes(tag, ByteString.Empty);
-        }
+        public static FieldCodec<ByteString> ForBytes(uint tag) => ForBytes(tag, ByteString.Empty);
 
         /// <summary>
         /// Retrieves a codec suitable for a bool field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<bool> ForBool(uint tag)
-        {
-            return FieldCodec.ForBool(tag, false);
-        }
+        public static FieldCodec<bool> ForBool(uint tag) => ForBool(tag, false);
 
         /// <summary>
         /// Retrieves a codec suitable for an int32 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<int> ForInt32(uint tag)
-        {
-            return FieldCodec.ForInt32(tag, 0);
-        }
+        public static FieldCodec<int> ForInt32(uint tag) => ForInt32(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for an sint32 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<int> ForSInt32(uint tag)
-        {
-            return FieldCodec.ForSInt32(tag, 0);
-        }
+        public static FieldCodec<int> ForSInt32(uint tag) => ForSInt32(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for a fixed32 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<uint> ForFixed32(uint tag)
-        {
-            return FieldCodec.ForFixed32(tag, 0);
-        }
+        public static FieldCodec<uint> ForFixed32(uint tag) => ForFixed32(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for an sfixed32 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<int> ForSFixed32(uint tag)
-        {
-            return FieldCodec.ForSFixed32(tag, 0);
-        }
+        public static FieldCodec<int> ForSFixed32(uint tag) => ForSFixed32(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for a uint32 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<uint> ForUInt32(uint tag)
-        {
-            return FieldCodec.ForUInt32(tag, 0);
-        }
+        public static FieldCodec<uint> ForUInt32(uint tag) => ForUInt32(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for an int64 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<long> ForInt64(uint tag)
-        {
-            return FieldCodec.ForInt64(tag, 0);
-        }
+        public static FieldCodec<long> ForInt64(uint tag) => ForInt64(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for an sint64 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<long> ForSInt64(uint tag)
-        {
-            return FieldCodec.ForSInt64(tag, 0);
-        }
+        public static FieldCodec<long> ForSInt64(uint tag) => ForSInt64(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for a fixed64 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<ulong> ForFixed64(uint tag)
-        {
-            return FieldCodec.ForFixed64(tag, 0);
-        }
+        public static FieldCodec<ulong> ForFixed64(uint tag) => ForFixed64(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for an sfixed64 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<long> ForSFixed64(uint tag)
-        {
-            return FieldCodec.ForSFixed64(tag, 0);
-        }
+        public static FieldCodec<long> ForSFixed64(uint tag) => ForSFixed64(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for a uint64 field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<ulong> ForUInt64(uint tag)
-        {
-            return FieldCodec.ForUInt64(tag, 0);
-        }
+        public static FieldCodec<ulong> ForUInt64(uint tag) => ForUInt64(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for a float field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<float> ForFloat(uint tag)
-        {
-            return FieldCodec.ForFloat(tag, 0);
-        }
+        public static FieldCodec<float> ForFloat(uint tag) => ForFloat(tag, 0);
 
         /// <summary>
         /// Retrieves a codec suitable for a double field with the given tag.
         /// </summary>
         /// <param name="tag">The tag.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<double> ForDouble(uint tag)
-        {
-            return FieldCodec.ForDouble(tag, 0);
-        }
+        public static FieldCodec<double> ForDouble(uint tag) => ForDouble(tag, 0);
 
         // Enums are tricky. We can probably use expression trees to build these delegates automatically,
         // but it's easy to generate the code for it.
@@ -206,10 +160,8 @@
         /// <param name="toInt32">A conversion function from <see cref="Int32"/> to the enum type.</param>
         /// <param name="fromInt32">A conversion function from the enum type to <see cref="Int32"/>.</param>
         /// <returns>A codec for the given tag.</returns>
-        public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32)
-        {
-            return FieldCodec.ForEnum(tag, toInt32, fromInt32, default(T));
-        }
+        public static FieldCodec<T> ForEnum<T>(uint tag, Func<T, int> toInt32, Func<int, T> fromInt32) =>
+            ForEnum(tag, toInt32, fromInt32, default);
 
         /// <summary>
         /// Retrieves a codec suitable for a string field with the given tag.
@@ -565,8 +517,7 @@
             /// </summary>
             internal static FieldCodec<T> GetCodec<T>()
             {
-                object value;
-                if (!Codecs.TryGetValue(typeof(T), out value))
+                if (!Codecs.TryGetValue(typeof(T), out object value))
                 {
                     throw new InvalidOperationException("Invalid type argument requested for wrapper codec: " + typeof(T));
                 }
@@ -575,8 +526,7 @@
 
             internal static ValueReader<T?> GetReader<T>() where T : struct
             {
-                object value;
-                if (!Readers.TryGetValue(typeof(T), out value))
+                if (!Readers.TryGetValue(typeof(T), out object value))
                 {
                     throw new InvalidOperationException("Invalid type argument requested for wrapper reader: " + typeof(T));
                 }
diff --git a/csharp/src/Google.Protobuf/FieldMaskTree.cs b/csharp/src/Google.Protobuf/FieldMaskTree.cs
index 2297e7a..084374f 100644
--- a/csharp/src/Google.Protobuf/FieldMaskTree.cs
+++ b/csharp/src/Google.Protobuf/FieldMaskTree.cs
@@ -120,8 +120,7 @@
                     return this;
                 }
 
-                Node childNode;
-                if (!node.Children.TryGetValue(part, out childNode))
+                if (!node.Children.TryGetValue(part, out Node childNode))
                 {
                     createNewBranch = true;
                     childNode = new Node();
@@ -333,15 +332,24 @@
                         {
                             if (sourceField != null)
                             {
-                                var sourceByteString = ((IMessage)sourceField).ToByteString();
-                                var destinationValue = (IMessage)field.Accessor.GetValue(destination);
-                                if (destinationValue != null)
+                                // Well-known wrapper types are represented as nullable primitive types, so we do not "merge" them.
+                                // Instead, any non-null value just overwrites the previous value directly.
+                                if (field.MessageType.IsWrapperType)
                                 {
-                                    destinationValue.MergeFrom(sourceByteString);
+                                    field.Accessor.SetValue(destination, sourceField);
                                 }
                                 else
                                 {
-                                    field.Accessor.SetValue(destination, field.MessageType.Parser.ParseFrom(sourceByteString));
+                                    var sourceByteString = ((IMessage)sourceField).ToByteString();
+                                    var destinationValue = (IMessage)field.Accessor.GetValue(destination);
+                                    if (destinationValue != null)
+                                    {
+                                        destinationValue.MergeFrom(sourceByteString);
+                                    }
+                                    else
+                                    {
+                                        field.Accessor.SetValue(destination, field.MessageType.Parser.ParseFrom(sourceByteString));
+                                    }
                                 }
                             }
                         }
diff --git a/csharp/src/Google.Protobuf/Google.Protobuf.csproj b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
index bf535bd..8a156c3 100644
--- a/csharp/src/Google.Protobuf/Google.Protobuf.csproj
+++ b/csharp/src/Google.Protobuf/Google.Protobuf.csproj
@@ -1,12 +1,12 @@
 <Project Sdk="Microsoft.NET.Sdk">
+  <!-- If you update this, update the .csproj in the Docker file as well -->
 
   <PropertyGroup>
     <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.21.10</VersionPrefix>
-    <!-- C# 7.2 is required for Span/BufferWriter/ReadOnlySequence -->
-    <LangVersion>7.2</LangVersion>
+    <LangVersion>10.0</LangVersion>
     <Authors>Google Inc.</Authors>
     <TargetFrameworks>netstandard1.1;netstandard2.0;net45;net50</TargetFrameworks>
     <GenerateDocumentationFile>true</GenerateDocumentationFile>
diff --git a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
index 6a3dbd6..333838b 100644
--- a/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
+++ b/csharp/src/Google.Protobuf/InvalidProtocolBufferException.cs
@@ -136,5 +136,5 @@
         {
             return new InvalidProtocolBufferException("Message was missing required fields");
         }
-}
+    }
 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/JsonFormatter.cs b/csharp/src/Google.Protobuf/JsonFormatter.cs
index 16f7c5a..9cecb6a 100644
--- a/csharp/src/Google.Protobuf/JsonFormatter.cs
+++ b/csharp/src/Google.Protobuf/JsonFormatter.cs
@@ -62,9 +62,13 @@
         internal const string AnyTypeUrlField = "@type";
         internal const string AnyDiagnosticValueField = "@value";
         internal const string AnyWellKnownTypeValueField = "value";
-        private const string TypeUrlPrefix = "type.googleapis.com";
         private const string NameValueSeparator = ": ";
-        private const string PropertySeparator = ", ";
+        private const string ValueSeparator = ", ";
+        private const string MultilineValueSeparator = ",";
+        private const char ObjectOpenBracket = '{';
+        private const char ObjectCloseBracket = '}';
+        private const char ListBracketOpen = '[';
+        private const char ListBracketClose = ']';
 
         /// <summary>
         /// Returns a formatter using the default settings.
@@ -141,11 +145,26 @@
         /// Formats the specified message as JSON.
         /// </summary>
         /// <param name="message">The message to format.</param>
+        /// <remarks>This method delegates to <c>Format(IMessage, int)</c> with <c>indentationLevel = 0</c>.</remarks>
         /// <returns>The formatted message.</returns>
-        public string Format(IMessage message)
+        public string Format(IMessage message) => Format(message, indentationLevel: 0);
+
+        /// <summary>
+        /// Formats the specified message as JSON.
+        /// </summary>
+        /// <param name="message">The message to format.</param>
+        /// <param name="indentationLevel">Indentation level to start at.</param>
+        /// <remarks>To keep consistent indentation when embedding a message inside another JSON string, set <paramref name="indentationLevel"/>. E.g:
+        /// <code>
+        /// var response = $@"{{
+        ///   ""data"": { Format(message, indentationLevel: 1) }
+        /// }}"</code>
+        /// </remarks>
+        /// <returns>The formatted message.</returns>
+        public string Format(IMessage message, int indentationLevel)
         {
             var writer = new StringWriter();
-            Format(message, writer);
+            Format(message, writer, indentationLevel);
             return writer.ToString();
         }
 
@@ -154,19 +173,29 @@
         /// </summary>
         /// <param name="message">The message to format.</param>
         /// <param name="writer">The TextWriter to write the formatted message to.</param>
+        /// <remarks>This method delegates to <c>Format(IMessage, TextWriter, int)</c> with <c>indentationLevel = 0</c>.</remarks>
         /// <returns>The formatted message.</returns>
-        public void Format(IMessage message, TextWriter writer)
+        public void Format(IMessage message, TextWriter writer) => Format(message, writer, indentationLevel: 0);
+
+        /// <summary>
+        /// Formats the specified message as JSON. When <see cref="Settings.Indentation"/> is not null, start indenting at the specified <paramref name="indentationLevel"/>.
+        /// </summary>
+        /// <param name="message">The message to format.</param>
+        /// <param name="writer">The TextWriter to write the formatted message to.</param>
+        /// <param name="indentationLevel">Indentation level to start at.</param>
+        /// <remarks>To keep consistent indentation when embedding a message inside another JSON string, set <paramref name="indentationLevel"/>.</remarks>
+        public void Format(IMessage message, TextWriter writer, int indentationLevel)
         {
             ProtoPreconditions.CheckNotNull(message, nameof(message));
             ProtoPreconditions.CheckNotNull(writer, nameof(writer));
 
             if (message.Descriptor.IsWellKnownType)
             {
-                WriteWellKnownTypeValue(writer, message.Descriptor, message);
+                WriteWellKnownTypeValue(writer, message.Descriptor, message, indentationLevel);
             }
             else
             {
-                WriteMessage(writer, message);
+                WriteMessage(writer, message, indentationLevel);
             }
         }
 
@@ -193,7 +222,7 @@
             return diagnosticFormatter.Format(message);
         }
 
-        private void WriteMessage(TextWriter writer, IMessage message)
+        private void WriteMessage(TextWriter writer, IMessage message, int indentationLevel)
         {
             if (message == null)
             {
@@ -202,19 +231,19 @@
             }
             if (DiagnosticOnly)
             {
-                ICustomDiagnosticMessage customDiagnosticMessage = message as ICustomDiagnosticMessage;
-                if (customDiagnosticMessage != null)
+                if (message is ICustomDiagnosticMessage customDiagnosticMessage)
                 {
                     writer.Write(customDiagnosticMessage.ToDiagnosticString());
                     return;
                 }
             }
-            writer.Write("{ ");
-            bool writtenFields = WriteMessageFields(writer, message, false);
-            writer.Write(writtenFields ? " }" : "}");
+
+            WriteBracketOpen(writer, ObjectOpenBracket);
+            bool writtenFields = WriteMessageFields(writer, message, false, indentationLevel + 1);
+            WriteBracketClose(writer, ObjectCloseBracket, writtenFields, indentationLevel);
         }
 
-        private bool WriteMessageFields(TextWriter writer, IMessage message, bool assumeFirstFieldWritten)
+        private bool WriteMessageFields(TextWriter writer, IMessage message, bool assumeFirstFieldWritten, int indentationLevel)
         {
             var fields = message.Descriptor.Fields;
             bool first = !assumeFirstFieldWritten;
@@ -228,10 +257,8 @@
                     continue;
                 }
 
-                if (!first)
-                {
-                    writer.Write(PropertySeparator);
-                }
+                MaybeWriteValueSeparator(writer, first);
+                MaybeWriteValueWhitespace(writer, indentationLevel);
 
                 if (settings.PreserveProtoFieldNames)
                 {
@@ -242,13 +269,23 @@
                     WriteString(writer, accessor.Descriptor.JsonName);
                 }
                 writer.Write(NameValueSeparator);
-                WriteValue(writer, value);
+                WriteValue(writer, value, indentationLevel);
 
                 first = false;
             }
             return !first;
         }
 
+        private void MaybeWriteValueSeparator(TextWriter writer, bool first)
+        {
+            if (first)
+            {
+                return;
+            }
+
+            writer.Write(settings.Indentation == null ? ValueSeparator : MultilineValueSeparator);
+        }
+
         /// <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.
@@ -320,39 +357,20 @@
                 IList list = (IList) value;
                 return list.Count == 0;
             }
-            switch (descriptor.FieldType)
+            return descriptor.FieldType switch
             {
-                case FieldType.Bool:
-                    return (bool) value == false;
-                case FieldType.Bytes:
-                    return (ByteString) value == ByteString.Empty;
-                case FieldType.String:
-                    return (string) value == "";
-                case FieldType.Double:
-                    return (double) value == 0.0;
-                case FieldType.SInt32:
-                case FieldType.Int32:
-                case FieldType.SFixed32:
-                case FieldType.Enum:
-                    return (int) value == 0;
-                case FieldType.Fixed32:
-                case FieldType.UInt32:
-                    return (uint) value == 0;
-                case FieldType.Fixed64:
-                case FieldType.UInt64:
-                    return (ulong) value == 0;
-                case FieldType.SFixed64:
-                case FieldType.Int64:
-                case FieldType.SInt64:
-                    return (long) value == 0;
-                case FieldType.Float:
-                    return (float) value == 0f;
-                case FieldType.Message:
-                case FieldType.Group: // Never expect to get this, but...
-                    return value == null;
-                default:
-                    throw new ArgumentException("Invalid field type");
-            }
+                FieldType.Bool => (bool) value == false,
+                FieldType.Bytes => (ByteString) value == ByteString.Empty,
+                FieldType.String => (string) value == "",
+                FieldType.Double => (double) value == 0.0,
+                FieldType.SInt32 or FieldType.Int32 or FieldType.SFixed32 or FieldType.Enum => (int) value == 0,
+                FieldType.Fixed32 or FieldType.UInt32 => (uint) value == 0,
+                FieldType.Fixed64 or FieldType.UInt64 => (ulong) value == 0,
+                FieldType.SFixed64 or FieldType.Int64 or FieldType.SInt64 => (long) value == 0,
+                FieldType.Float => (float) value == 0f,
+                FieldType.Message or FieldType.Group => value == null,
+                _ => throw new ArgumentException("Invalid field type"),
+            };
         }
 
         /// <summary>
@@ -363,34 +381,46 @@
         /// </summary>
         /// <param name="writer">The writer to write the value to. Must not be null.</param>
         /// <param name="value">The value to write. May be null.</param>
-        public void WriteValue(TextWriter writer, object value)
+        /// <remarks>Delegates to <c>WriteValue(TextWriter, object, int)</c> with <c>indentationLevel = 0</c>.</remarks>
+        public void WriteValue(TextWriter writer, object value) => WriteValue(writer, value, 0);
+
+        /// <summary>
+        /// Writes a single value to the given writer as JSON. Only types understood by
+        /// Protocol Buffers can be written in this way. This method is only exposed for
+        /// advanced use cases; most users should be using <see cref="Format(IMessage)"/>
+        /// or <see cref="Format(IMessage, TextWriter)"/>.
+        /// </summary>
+        /// <param name="writer">The writer to write the value to. Must not be null.</param>
+        /// <param name="value">The value to write. May be null.</param>
+        /// <param name="indentationLevel">The current indentationLevel. Not used when <see cref="Settings.Indentation"/> is null.</param>
+        public void WriteValue(TextWriter writer, object value, int indentationLevel)
         {
             if (value == null || value is NullValue)
             {
                 WriteNull(writer);
             }
-            else if (value is bool)
+            else if (value is bool b)
             {
-                writer.Write((bool)value ? "true" : "false");
+                writer.Write(b ? "true" : "false");
             }
-            else if (value is ByteString)
+            else if (value is ByteString byteString)
             {
                 // Nothing in Base64 needs escaping
                 writer.Write('"');
-                writer.Write(((ByteString)value).ToBase64());
+                writer.Write(byteString.ToBase64());
                 writer.Write('"');
             }
-            else if (value is string)
+            else if (value is string str)
             {
-                WriteString(writer, (string)value);
+                WriteString(writer, str);
             }
-            else if (value is IDictionary)
+            else if (value is IDictionary dictionary)
             {
-                WriteDictionary(writer, (IDictionary)value);
+                WriteDictionary(writer, dictionary, indentationLevel);
             }
-            else if (value is IList)
+            else if (value is IList list)
             {
-                WriteList(writer, (IList)value);
+                WriteList(writer, list, indentationLevel);
             }
             else if (value is int || value is uint)
             {
@@ -437,9 +467,9 @@
                     writer.Write(text);
                 }
             }
-            else if (value is IMessage)
+            else if (value is IMessage message)
             {
-                Format((IMessage)value, writer);
+                Format(message, writer, indentationLevel);
             }
             else
             {
@@ -453,7 +483,7 @@
         /// values are using the embedded well-known types, in order to allow for dynamic messages
         /// in the future.
         /// </summary>
-        private void WriteWellKnownTypeValue(TextWriter writer, MessageDescriptor descriptor, object value)
+        private void WriteWellKnownTypeValue(TextWriter writer, MessageDescriptor descriptor, object value, int indentationLevel)
         {
             // Currently, we can never actually get here, because null values are always handled by the caller. But if we *could*,
             // this would do the right thing.
@@ -469,9 +499,8 @@
             // WriteValue will do the right thing.)
             if (descriptor.IsWrapperType)
             {
-                if (value is IMessage)
+                if (value is IMessage message)
                 {
-                    var message = (IMessage) value;
                     value = message.Descriptor.Fields[WrappersReflection.WrapperValueFieldNumber].Accessor.GetValue(message);
                 }
                 WriteValue(writer, value);
@@ -494,26 +523,26 @@
             }
             if (descriptor.FullName == Struct.Descriptor.FullName)
             {
-                WriteStruct(writer, (IMessage)value);
+                WriteStruct(writer, (IMessage)value, indentationLevel);
                 return;
             }
             if (descriptor.FullName == ListValue.Descriptor.FullName)
             {
                 var fieldAccessor = descriptor.Fields[ListValue.ValuesFieldNumber].Accessor;
-                WriteList(writer, (IList)fieldAccessor.GetValue((IMessage)value));
+                WriteList(writer, (IList)fieldAccessor.GetValue((IMessage)value), indentationLevel);
                 return;
             }
             if (descriptor.FullName == Value.Descriptor.FullName)
             {
-                WriteStructFieldValue(writer, (IMessage)value);
+                WriteStructFieldValue(writer, (IMessage)value, indentationLevel);
                 return;
             }
             if (descriptor.FullName == Any.Descriptor.FullName)
             {
-                WriteAny(writer, (IMessage)value);
+                WriteAny(writer, (IMessage)value, indentationLevel);
                 return;
             }
-            WriteMessage(writer, (IMessage)value);
+            WriteMessage(writer, (IMessage)value, indentationLevel);
         }
 
         private void WriteTimestamp(TextWriter writer, IMessage value)
@@ -541,7 +570,7 @@
             writer.Write(FieldMask.ToJson(paths, DiagnosticOnly));
         }
 
-        private void WriteAny(TextWriter writer, IMessage value)
+        private void WriteAny(TextWriter writer, IMessage value, int indentationLevel)
         {
             if (DiagnosticOnly)
             {
@@ -558,23 +587,23 @@
                 throw new InvalidOperationException($"Type registry has no descriptor for type name '{typeName}'");
             }
             IMessage message = descriptor.Parser.ParseFrom(data);
-            writer.Write("{ ");
+            WriteBracketOpen(writer, ObjectOpenBracket);
             WriteString(writer, AnyTypeUrlField);
             writer.Write(NameValueSeparator);
             WriteString(writer, typeUrl);
 
             if (descriptor.IsWellKnownType)
             {
-                writer.Write(PropertySeparator);
+                writer.Write(ValueSeparator);
                 WriteString(writer, AnyWellKnownTypeValueField);
                 writer.Write(NameValueSeparator);
-                WriteWellKnownTypeValue(writer, descriptor, message);
+                WriteWellKnownTypeValue(writer, descriptor, message, indentationLevel);
             }
             else
             {
-                WriteMessageFields(writer, message, true);
+                WriteMessageFields(writer, message, true, indentationLevel);
             }
-            writer.Write(" }");
+            WriteBracketClose(writer, ObjectCloseBracket, true, indentationLevel);
         }
 
         private void WriteDiagnosticOnlyAny(TextWriter writer, IMessage value)
@@ -585,7 +614,7 @@
             WriteString(writer, AnyTypeUrlField);
             writer.Write(NameValueSeparator);
             WriteString(writer, typeUrl);
-            writer.Write(PropertySeparator);
+            writer.Write(ValueSeparator);
             WriteString(writer, AnyDiagnosticValueField);
             writer.Write(NameValueSeparator);
             writer.Write('"');
@@ -594,9 +623,9 @@
             writer.Write(" }");
         }
 
-        private void WriteStruct(TextWriter writer, IMessage message)
+        private void WriteStruct(TextWriter writer, IMessage message, int indentationLevel)
         {
-            writer.Write("{ ");
+            WriteBracketOpen(writer, ObjectOpenBracket);
             IDictionary fields = (IDictionary) message.Descriptor.Fields[Struct.FieldsFieldNumber].Accessor.GetValue(message);
             bool first = true;
             foreach (DictionaryEntry entry in fields)
@@ -608,19 +637,17 @@
                     throw new InvalidOperationException("Struct fields cannot have an empty key or a null value.");
                 }
 
-                if (!first)
-                {
-                    writer.Write(PropertySeparator);
-                }
+                MaybeWriteValueSeparator(writer, first);
+                MaybeWriteValueWhitespace(writer, indentationLevel + 1);
                 WriteString(writer, key);
                 writer.Write(NameValueSeparator);
-                WriteStructFieldValue(writer, value);
+                WriteStructFieldValue(writer, value, indentationLevel + 1);
                 first = false;
             }
-            writer.Write(first ? "}" : " }");
+            WriteBracketClose(writer, ObjectCloseBracket, !first, indentationLevel);
         }
 
-        private void WriteStructFieldValue(TextWriter writer, IMessage message)
+        private void WriteStructFieldValue(TextWriter writer, IMessage message, int indentationLevel)
         {
             var specifiedField = message.Descriptor.Oneofs[0].Accessor.GetCaseFieldDescriptor(message);
             if (specifiedField == null)
@@ -641,7 +668,7 @@
                 case Value.ListValueFieldNumber:
                     // Structs and ListValues are nested messages, and already well-known types.
                     var nestedMessage = (IMessage) specifiedField.Accessor.GetValue(message);
-                    WriteWellKnownTypeValue(writer, nestedMessage.Descriptor, nestedMessage);
+                    WriteWellKnownTypeValue(writer, nestedMessage.Descriptor, nestedMessage, indentationLevel);
                     return;
                 case Value.NullValueFieldNumber:
                     WriteNull(writer);
@@ -651,43 +678,40 @@
             }
         }
 
-        internal void WriteList(TextWriter writer, IList list)
+        internal void WriteList(TextWriter writer, IList list, int indentationLevel = 0)
         {
-            writer.Write("[ ");
+            WriteBracketOpen(writer, ListBracketOpen);
+
             bool first = true;
             foreach (var value in list)
             {
-                if (!first)
-                {
-                    writer.Write(PropertySeparator);
-                }
-                WriteValue(writer, value);
+                MaybeWriteValueSeparator(writer, first);
+                MaybeWriteValueWhitespace(writer, indentationLevel + 1);
+                WriteValue(writer, value, indentationLevel + 1);
                 first = false;
             }
-            writer.Write(first ? "]" : " ]");
+
+            WriteBracketClose(writer, ListBracketClose, !first, indentationLevel);
         }
 
-        internal void WriteDictionary(TextWriter writer, IDictionary dictionary)
+        internal void WriteDictionary(TextWriter writer, IDictionary dictionary, int indentationLevel = 0)
         {
-            writer.Write("{ ");
+            WriteBracketOpen(writer, ObjectOpenBracket);
+
             bool first = true;
             // This will box each pair. Could use IDictionaryEnumerator, but that's ugly in terms of disposal.
             foreach (DictionaryEntry pair in dictionary)
             {
-                if (!first)
-                {
-                    writer.Write(PropertySeparator);
-                }
                 string keyText;
-                if (pair.Key is string)
+                if (pair.Key is string s)
                 {
-                    keyText = (string) pair.Key;
+                    keyText = s;
                 }
-                else if (pair.Key is bool)
+                else if (pair.Key is bool b)
                 {
-                    keyText = (bool) pair.Key ? "true" : "false";
+                    keyText = b ? "true" : "false";
                 }
-                else if (pair.Key is int || pair.Key is uint | pair.Key is long || pair.Key is ulong)
+                else if (pair.Key is int || pair.Key is uint || pair.Key is long || pair.Key is ulong)
                 {
                     keyText = ((IFormattable) pair.Key).ToString("d", CultureInfo.InvariantCulture);
                 }
@@ -699,12 +723,16 @@
                     }
                     throw new ArgumentException("Unhandled dictionary key type: " + pair.Key.GetType());
                 }
+
+                MaybeWriteValueSeparator(writer, first);
+                MaybeWriteValueWhitespace(writer, indentationLevel + 1);
                 WriteString(writer, keyText);
                 writer.Write(NameValueSeparator);
                 WriteValue(writer, pair.Value);
                 first = false;
             }
-            writer.Write(first ? "}" : " }");
+
+            WriteBracketClose(writer, ObjectCloseBracket, !first, indentationLevel);
         }
 
         /// <summary>
@@ -788,6 +816,49 @@
             writer.Write(Hex[(c >> 0) & 0xf]);
         }
 
+        private void WriteBracketOpen(TextWriter writer, char openChar)
+        {
+            writer.Write(openChar);
+            if (settings.Indentation == null)
+            {
+                writer.Write(' ');
+            }
+        }
+
+        private void WriteBracketClose(TextWriter writer, char closeChar, bool hasFields, int indentationLevel)
+        {
+            if (hasFields)
+            {
+                if (settings.Indentation != null)
+                {
+                    writer.WriteLine();
+                    WriteIndentation(writer, indentationLevel);
+                }
+                else
+                {
+                    writer.Write(" ");
+                }
+            }
+
+            writer.Write(closeChar);
+        }
+
+        private void MaybeWriteValueWhitespace(TextWriter writer, int indentationLevel)
+        {
+            if (settings.Indentation != null) {
+                writer.WriteLine();
+                WriteIndentation(writer, indentationLevel);
+            }
+        }
+
+        private void WriteIndentation(TextWriter writer, int indentationLevel)
+        {
+            for (int i = 0; i < indentationLevel; i++)
+            {
+                writer.Write(settings.Indentation);
+            }
+        }
+
         /// <summary>
         /// Settings controlling JSON formatting.
         /// </summary>
@@ -828,6 +899,10 @@
             /// </summary>
             public bool PreserveProtoFieldNames { get; }
 
+            /// <summary>
+            /// Indentation string, used for formatting. Setting null disables indentation.
+            /// </summary>
+            public string Indentation { get; }
 
             /// <summary>
             /// Creates a new <see cref="Settings"/> object with the specified formatting of default values
@@ -855,40 +930,54 @@
             /// <param name="typeRegistry">The <see cref="TypeRegistry"/> to use when formatting <see cref="Any"/> messages. TypeRegistry.Empty will be used if it is null.</param>
             /// <param name="formatEnumsAsIntegers"><c>true</c> to format the enums as integers; <c>false</c> to format enums as enum names.</param>
             /// <param name="preserveProtoFieldNames"><c>true</c> to preserve proto field names; <c>false</c> to convert them to lowerCamelCase.</param>
+            /// <param name="indentation">The indentation string to use for multi-line formatting. <c>null</c> to disable multi-line format.</param>
             private Settings(bool formatDefaultValues,
                             TypeRegistry typeRegistry,
                             bool formatEnumsAsIntegers,
-                            bool preserveProtoFieldNames)
+                            bool preserveProtoFieldNames,
+                            string indentation = null)
             {
                 FormatDefaultValues = formatDefaultValues;
                 TypeRegistry = typeRegistry ?? TypeRegistry.Empty;
                 FormatEnumsAsIntegers = formatEnumsAsIntegers;
                 PreserveProtoFieldNames = preserveProtoFieldNames;
+                Indentation = indentation;
             }
 
             /// <summary>
             /// Creates a new <see cref="Settings"/> object with the specified formatting of default values and the current settings.
             /// </summary>
             /// <param name="formatDefaultValues"><c>true</c> if default values (0, empty strings etc) should be formatted; <c>false</c> otherwise.</param>
-            public Settings WithFormatDefaultValues(bool formatDefaultValues) => new Settings(formatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames);
+            public Settings WithFormatDefaultValues(bool formatDefaultValues) => new Settings(formatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames, Indentation);
 
             /// <summary>
             /// Creates a new <see cref="Settings"/> object with the specified type registry and the current settings.
             /// </summary>
             /// <param name="typeRegistry">The <see cref="TypeRegistry"/> to use when formatting <see cref="Any"/> messages.</param>
-            public Settings WithTypeRegistry(TypeRegistry typeRegistry) => new Settings(FormatDefaultValues, typeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames);
+            public Settings WithTypeRegistry(TypeRegistry typeRegistry) => new Settings(FormatDefaultValues, typeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames, Indentation);
 
             /// <summary>
             /// Creates a new <see cref="Settings"/> object with the specified enums formatting option and the current settings.
             /// </summary>
             /// <param name="formatEnumsAsIntegers"><c>true</c> to format the enums as integers; <c>false</c> to format enums as enum names.</param>
-            public Settings WithFormatEnumsAsIntegers(bool formatEnumsAsIntegers) => new Settings(FormatDefaultValues, TypeRegistry, formatEnumsAsIntegers, PreserveProtoFieldNames);
+            public Settings WithFormatEnumsAsIntegers(bool formatEnumsAsIntegers) => new Settings(FormatDefaultValues, TypeRegistry, formatEnumsAsIntegers, PreserveProtoFieldNames, Indentation);
 
             /// <summary>
             /// Creates a new <see cref="Settings"/> object with the specified field name formatting option and the current settings.
             /// </summary>
             /// <param name="preserveProtoFieldNames"><c>true</c> to preserve proto field names; <c>false</c> to convert them to lowerCamelCase.</param>
-            public Settings WithPreserveProtoFieldNames(bool preserveProtoFieldNames) => new Settings(FormatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, preserveProtoFieldNames);
+            public Settings WithPreserveProtoFieldNames(bool preserveProtoFieldNames) => new Settings(FormatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, preserveProtoFieldNames, Indentation);
+
+            /// <summary>
+            /// Creates a new <see cref="Settings"/> object with the specified indentation and the current settings.
+            /// </summary>
+            /// <param name="indentation">The string to output for each level of indentation (nesting). The default is two spaces per level. Use null to disable indentation entirely.</param>
+            /// <remarks>A non-null value for <see cref="Indentation"/> will insert additional line-breaks to the JSON output.
+            /// Each line will contain either a single value, or braces. The default line-break is determined by <see cref="Environment.NewLine"/>,
+            /// which is <c>"\n"</c> on Unix platforms, and <c>"\r\n"</c> on Windows. If <see cref="JsonFormatter"/> seems to produce empty lines,
+            /// you need to pass a <see cref="TextWriter"/> that uses a <c>"\n"</c> newline. See <see cref="JsonFormatter.Format(Google.Protobuf.IMessage, TextWriter)"/>.
+            /// </remarks>
+            public Settings WithIndentation(string indentation = "  ") => new Settings(FormatDefaultValues, TypeRegistry, FormatEnumsAsIntegers, PreserveProtoFieldNames, indentation);
         }
 
         // Effectively a cache of mapping from enum values to the original name as specified in the proto file,
@@ -916,9 +1005,8 @@
                     }
                 }
 
-                string originalName;
                 // If this returns false, originalName will be null, which is what we want.
-                nameMapping.TryGetValue(value, out originalName);
+                nameMapping.TryGetValue(value, out string originalName);
                 return originalName;
             }
 
diff --git a/csharp/src/Google.Protobuf/JsonParser.cs b/csharp/src/Google.Protobuf/JsonParser.cs
index cb5f5a8..6cb98d6 100644
--- a/csharp/src/Google.Protobuf/JsonParser.cs
+++ b/csharp/src/Google.Protobuf/JsonParser.cs
@@ -70,8 +70,7 @@
 
         // TODO: Consider introducing a class containing parse state of the parser, tokenizer and depth. That would simplify these handlers
         // and the signatures of various methods.
-        private static readonly Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>>
-            WellKnownTypeHandlers = new Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>>
+        private static readonly Dictionary<string, Action<JsonParser, IMessage, JsonTokenizer>> WellKnownTypeHandlers = new()
         {
             { Timestamp.Descriptor.FullName, (parser, message, tokenizer) => MergeTimestamp(message, tokenizer.Next()) },
             { Duration.Descriptor.FullName, (parser, message, tokenizer) => MergeDuration(message, tokenizer.Next()) },
@@ -156,8 +155,7 @@
             }
             if (message.Descriptor.IsWellKnownType)
             {
-                Action<JsonParser, IMessage, JsonTokenizer> handler;
-                if (WellKnownTypeHandlers.TryGetValue(message.Descriptor.FullName, out handler))
+                if (WellKnownTypeHandlers.TryGetValue(message.Descriptor.FullName, out Action<JsonParser, IMessage, JsonTokenizer> handler))
                 {
                     handler(this, message, tokenizer);
                     return;
@@ -187,8 +185,7 @@
                     throw new InvalidOperationException("Unexpected token type " + token.Type);
                 }
                 string name = token.StringValue;
-                FieldDescriptor field;
-                if (jsonFieldMap.TryGetValue(name, out field))
+                if (jsonFieldMap.TryGetValue(name, out FieldDescriptor field))
                 {
                     if (field.ContainingOneof != null)
                     {
@@ -303,11 +300,7 @@
                 }
                 object key = ParseMapKey(keyField, token.StringValue);
                 object value = ParseSingleValue(valueField, tokenizer);
-                if (value == null)
-                {
-                    throw new InvalidProtocolBufferException("Map values must not be null");
-                }
-                dictionary[key] = value;
+                dictionary[key] = value ?? throw new InvalidProtocolBufferException("Map values must not be null");
             }
         }
 
@@ -649,19 +642,15 @@
                             {
                                 return float.NaN;
                             }
-                            if (value > float.MaxValue || value < float.MinValue)
+                            float converted = (float) value;
+                            // If the value is out of range of float, the cast representation will be infinite.
+                            // If the original value was infinite as well, that's fine - we'll return the 32-bit
+                            // version (with the correct sign).
+                            if (float.IsInfinity(converted) && !double.IsInfinity(value))
                             {
-                                if (double.IsPositiveInfinity(value))
-                                {
-                                    return float.PositiveInfinity;
-                                }
-                                if (double.IsNegativeInfinity(value))
-                                {
-                                    return float.NegativeInfinity;
-                                }
                                 throw new InvalidProtocolBufferException($"Value out of range: {value}");
                             }
-                            return (float) value;
+                            return converted;
                         case FieldType.Enum:
                             CheckInteger(value);
                             // Just return it as an int, and let the CLR convert it.
@@ -853,7 +842,7 @@
                 if (secondsToAdd < 0 && nanosToAdd > 0)
                 {
                     secondsToAdd++;
-                    nanosToAdd = nanosToAdd - Duration.NanosecondsPerSecond;
+                    nanosToAdd -= Duration.NanosecondsPerSecond;
                 }
                 if (secondsToAdd != 0 || nanosToAdd != 0)
                 {
@@ -1049,23 +1038,20 @@
             /// when unknown fields are encountered.
             /// </summary>
             /// <param name="ignoreUnknownFields"><c>true</c> if unknown fields should be ignored when parsing; <c>false</c> to throw an exception.</param>
-            public Settings WithIgnoreUnknownFields(bool ignoreUnknownFields) =>
-                new Settings(RecursionLimit, TypeRegistry, ignoreUnknownFields);
+            public Settings WithIgnoreUnknownFields(bool ignoreUnknownFields) => new(RecursionLimit, TypeRegistry, ignoreUnknownFields);
 
             /// <summary>
             /// Creates a new <see cref="Settings"/> object based on this one, but with the specified recursion limit.
             /// </summary>
             /// <param name="recursionLimit">The new recursion limit.</param>
-            public Settings WithRecursionLimit(int recursionLimit) =>
-                new Settings(recursionLimit, TypeRegistry, IgnoreUnknownFields);
+            public Settings WithRecursionLimit(int recursionLimit) => new(recursionLimit, TypeRegistry, IgnoreUnknownFields);
 
             /// <summary>
             /// Creates a new <see cref="Settings"/> object based on this one, but with the specified type registry.
             /// </summary>
             /// <param name="typeRegistry">The new type registry. Must not be null.</param>
             public Settings WithTypeRegistry(TypeRegistry typeRegistry) =>
-                new Settings(
-                    RecursionLimit,
+                new(RecursionLimit,
                     ProtoPreconditions.CheckNotNull(typeRegistry, nameof(typeRegistry)),
                     IgnoreUnknownFields);
         }
diff --git a/csharp/src/Google.Protobuf/JsonToken.cs b/csharp/src/Google.Protobuf/JsonToken.cs
index 6c0138c..c23a25c 100644
--- a/csharp/src/Google.Protobuf/JsonToken.cs
+++ b/csharp/src/Google.Protobuf/JsonToken.cs
@@ -36,24 +36,14 @@
 {
     internal sealed class JsonToken : IEquatable<JsonToken>
     {
-        // Tokens with no value can be reused.
-        private static readonly JsonToken _true = new JsonToken(TokenType.True);
-        private static readonly JsonToken _false = new JsonToken(TokenType.False);
-        private static readonly JsonToken _null = new JsonToken(TokenType.Null);
-        private static readonly JsonToken startObject = new JsonToken(TokenType.StartObject);
-        private static readonly JsonToken endObject = new JsonToken(TokenType.EndObject);
-        private static readonly JsonToken startArray = new JsonToken(TokenType.StartArray);
-        private static readonly JsonToken endArray = new JsonToken(TokenType.EndArray);
-        private static readonly JsonToken endDocument = new JsonToken(TokenType.EndDocument);
-
-        internal static JsonToken Null { get { return _null; } }
-        internal static JsonToken False { get { return _false; } }
-        internal static JsonToken True { get { return _true; } }
-        internal static JsonToken StartObject{ get { return startObject; } }
-        internal static JsonToken EndObject { get { return endObject; } }
-        internal static JsonToken StartArray { get { return startArray; } }
-        internal static JsonToken EndArray { get { return endArray; } }
-        internal static JsonToken EndDocument { get { return endDocument; } }
+        internal static JsonToken Null { get; } = new JsonToken(TokenType.Null);
+        internal static JsonToken False { get; } = new JsonToken(TokenType.False);
+        internal static JsonToken True { get; } = new JsonToken(TokenType.True);
+        internal static JsonToken StartObject { get; } = new JsonToken(TokenType.StartObject);
+        internal static JsonToken EndObject { get; } = new JsonToken(TokenType.EndObject);
+        internal static JsonToken StartArray { get; } = new JsonToken(TokenType.StartArray);
+        internal static JsonToken EndArray { get; } = new JsonToken(TokenType.EndArray);
+        internal static JsonToken EndDocument { get; } = new JsonToken(TokenType.EndDocument);
 
         internal static JsonToken Name(string name)
         {
@@ -94,9 +84,9 @@
         private readonly string stringValue;
         private readonly double numberValue;
 
-        internal TokenType Type { get { return type; } }
-        internal string StringValue { get { return stringValue; } }
-        internal double NumberValue { get { return numberValue; } }
+        internal TokenType Type => type;
+        internal string StringValue => stringValue;
+        internal double NumberValue => numberValue;
 
         private JsonToken(TokenType type, string stringValue = null, double numberValue = 0)
         {
@@ -105,10 +95,7 @@
             this.numberValue = numberValue;
         }
 
-        public override bool Equals(object obj)
-        {
-            return Equals(obj as JsonToken);
-        }
+        public override bool Equals(object obj) => Equals(obj as JsonToken);
 
         public override int GetHashCode()
         {
@@ -124,38 +111,26 @@
 
         public override string ToString()
         {
-            switch (type)
+            return type switch
             {
-                case TokenType.Null:
-                    return "null";
-                case TokenType.True:
-                    return "true";
-                case TokenType.False:
-                    return "false";
-                case TokenType.Name:
-                    return "name (" + stringValue + ")";
-                case TokenType.StringValue:
-                    return "value (" + stringValue + ")";
-                case TokenType.Number:
-                    return "number (" + numberValue + ")";
-                case TokenType.StartObject:
-                    return "start-object";
-                case TokenType.EndObject:
-                    return "end-object";
-                case TokenType.StartArray:
-                    return "start-array";
-                case TokenType.EndArray:
-                    return "end-array";
-                case TokenType.EndDocument:
-                    return "end-document";
-                default:
-                    throw new InvalidOperationException("Token is of unknown type " + type);
-            }
+                TokenType.Null => "null",
+                TokenType.True => "true",
+                TokenType.False => "false",
+                TokenType.Name => $"name ({stringValue})",
+                TokenType.StringValue => $"value ({stringValue})",
+                TokenType.Number => $"number ({numberValue})",
+                TokenType.StartObject => "start-object",
+                TokenType.EndObject => "end-object",
+                TokenType.StartArray => "start-array",
+                TokenType.EndArray => "end-array",
+                TokenType.EndDocument => "end-document",
+                _ => throw new InvalidOperationException($"Token is of unknown type {type}"),
+            };
         }
 
         public bool Equals(JsonToken other)
         {
-            if (ReferenceEquals(other, null))
+            if (other is null)
             {
                 return false;
             }
diff --git a/csharp/src/Google.Protobuf/JsonTokenizer.cs b/csharp/src/Google.Protobuf/JsonTokenizer.cs
index 13a12c0..ed54734 100644
--- a/csharp/src/Google.Protobuf/JsonTokenizer.cs
+++ b/csharp/src/Google.Protobuf/JsonTokenizer.cs
@@ -29,6 +29,7 @@
 // (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.Collections.Generic;
 using System.Globalization;
@@ -362,29 +363,19 @@
             private char ReadEscapedCharacter()
             {
                 char c = reader.ReadOrFail("Unexpected end of text while reading character escape sequence");
-                switch (c)
+                return c switch
                 {
-                    case 'n':
-                        return '\n';
-                    case '\\':
-                        return '\\';
-                    case 'b':
-                        return '\b';
-                    case 'f':
-                        return '\f';
-                    case 'r':
-                        return '\r';
-                    case 't':
-                        return '\t';
-                    case '"':
-                        return '"';
-                    case '/':
-                        return '/';
-                    case 'u':
-                        return ReadUnicodeEscape();
-                    default:
-                        throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int) c));
-                }
+                    'n' => '\n',
+                    '\\' => '\\',
+                    'b' => '\b',
+                    'f' => '\f',
+                    'r' => '\r',
+                    't' => '\t',
+                    '"' => '"',
+                    '/' => '/',
+                    'u' => ReadUnicodeEscape(),
+                    _ => throw reader.CreateException(string.Format(CultureInfo.InvariantCulture, "Invalid character in character escape sequence: U+{0:x4}", (int)c)),
+                };
             }
 
             /// <summary>
@@ -498,8 +489,7 @@
                     throw reader.CreateException("Invalid numeric literal");
                 }
                 builder.Append(first);
-                int digitCount;
-                char? next = ConsumeDigits(builder, out digitCount);
+                char? next = ConsumeDigits(builder, out int digitCount);
                 if (first == '0' && digitCount != 0)
                 {
                     throw reader.CreateException("Invalid numeric literal: leading 0 for non-zero value.");
@@ -510,8 +500,7 @@
             private char? ReadFrac(StringBuilder builder)
             {
                 builder.Append('.'); // Already consumed this
-                int digitCount;
-                char? next = ConsumeDigits(builder, out digitCount);
+                char? next = ConsumeDigits(builder, out int digitCount);
                 if (digitCount == 0)
                 {
                     throw reader.CreateException("Invalid numeric literal: fraction with no trailing digits");
@@ -535,8 +524,7 @@
                 {
                     reader.PushBack(next.Value);
                 }
-                int digitCount;
-                next = ConsumeDigits(builder, out digitCount);
+                next = ConsumeDigits(builder, out int digitCount);
                 if (digitCount == 0)
                 {
                     throw reader.CreateException("Invalid numeric literal: exponent without value");
@@ -591,20 +579,13 @@
             {
                 containerStack.Pop();
                 var parent = containerStack.Peek();
-                switch (parent)
+                state = parent switch
                 {
-                    case ContainerType.Object:
-                        state = State.ObjectAfterProperty;
-                        break;
-                    case ContainerType.Array:
-                        state = State.ArrayAfterValue;
-                        break;
-                    case ContainerType.Document:
-                        state = State.ExpectedEndOfDocument;
-                        break;
-                    default:
-                        throw new InvalidOperationException("Unexpected container type: " + parent);
-                }
+                    ContainerType.Object => State.ObjectAfterProperty,
+                    ContainerType.Array => State.ArrayAfterValue,
+                    ContainerType.Document => State.ExpectedEndOfDocument,
+                    _ => throw new InvalidOperationException("Unexpected container type: " + parent),
+                };
             }
 
             private enum ContainerType
diff --git a/csharp/src/Google.Protobuf/LimitedInputStream.cs b/csharp/src/Google.Protobuf/LimitedInputStream.cs
index 50ead9c..46d5295 100644
--- a/csharp/src/Google.Protobuf/LimitedInputStream.cs
+++ b/csharp/src/Google.Protobuf/LimitedInputStream.cs
@@ -51,34 +51,20 @@
             bytesLeft = size;
         }
 
-        public override bool CanRead
-        {
-            get { return true; }
-        }
-
-        public override bool CanSeek
-        {
-            get { return false; }
-        }
-
-        public override bool CanWrite
-        {
-            get { return false; }
-        }
+        public override bool CanRead => true;
+        public override bool CanSeek => false;
+        public override bool CanWrite => false;
 
         public override void Flush()
         {
         }
 
-        public override long Length
-        {
-            get { throw new NotSupportedException(); }
-        }
+        public override long Length => throw new NotSupportedException();
 
         public override long Position
         {
-            get { throw new NotSupportedException(); }
-            set { throw new NotSupportedException(); }
+            get => throw new NotSupportedException();
+            set => throw new NotSupportedException();
         }
 
         public override int Read(byte[] buffer, int offset, int count)
@@ -92,19 +78,10 @@
             return 0;
         }
 
-        public override long Seek(long offset, SeekOrigin origin)
-        {
-            throw new NotSupportedException();
-        }
+        public override long Seek(long offset, SeekOrigin origin) => throw new NotSupportedException();
 
-        public override void SetLength(long value)
-        {
-            throw new NotSupportedException();
-        }
+        public override void SetLength(long value) => throw new NotSupportedException();
 
-        public override void Write(byte[] buffer, int offset, int count)
-        {
-            throw new NotSupportedException();
-        }
+        public override void Write(byte[] buffer, int offset, int count) => throw new NotSupportedException();
     }
 }
diff --git a/csharp/src/Google.Protobuf/MessageExtensions.cs b/csharp/src/Google.Protobuf/MessageExtensions.cs
index c4b3f82..22d3a2f 100644
--- a/csharp/src/Google.Protobuf/MessageExtensions.cs
+++ b/csharp/src/Google.Protobuf/MessageExtensions.cs
@@ -107,7 +107,7 @@
         /// <returns>The message data as a byte array.</returns>
         public static byte[] ToByteArray(this IMessage message)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
             byte[] result = new byte[message.CalculateSize()];
             CodedOutputStream output = new CodedOutputStream(result);
             message.WriteTo(output);
@@ -122,8 +122,8 @@
         /// <param name="output">The stream to write to.</param>
         public static void WriteTo(this IMessage message, Stream output)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
-            ProtoPreconditions.CheckNotNull(output, "output");
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(output, nameof(output));
             CodedOutputStream codedOutput = new CodedOutputStream(output);
             message.WriteTo(codedOutput);
             codedOutput.Flush();
@@ -136,8 +136,8 @@
         /// <param name="output">The output stream to write to.</param>
         public static void WriteDelimitedTo(this IMessage message, Stream output)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
-            ProtoPreconditions.CheckNotNull(output, "output");
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(output, nameof(output));
             CodedOutputStream codedOutput = new CodedOutputStream(output);
             codedOutput.WriteLength(message.CalculateSize());
             message.WriteTo(codedOutput);
@@ -151,7 +151,7 @@
         /// <returns>The message data as a byte string.</returns>
         public static ByteString ToByteString(this IMessage message)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
             return ByteString.AttachBytes(message.ToByteArray());
         }
 
@@ -251,30 +251,34 @@
         // Implementations allowing unknown fields to be discarded.
         internal static void MergeFrom(this IMessage message, byte[] data, bool discardUnknownFields, ExtensionRegistry registry)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
-            ProtoPreconditions.CheckNotNull(data, "data");
-            CodedInputStream input = new CodedInputStream(data);
-            input.DiscardUnknownFields = discardUnknownFields;
-            input.ExtensionRegistry = registry;
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(data, nameof(data));
+            CodedInputStream input = new CodedInputStream(data)
+            {
+                DiscardUnknownFields = discardUnknownFields,
+                ExtensionRegistry = registry
+            };
             message.MergeFrom(input);
             input.CheckReadEndOfStreamTag();
         }
 
         internal static void MergeFrom(this IMessage message, byte[] data, int offset, int length, bool discardUnknownFields, ExtensionRegistry registry)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
-            ProtoPreconditions.CheckNotNull(data, "data");
-            CodedInputStream input = new CodedInputStream(data, offset, length);
-            input.DiscardUnknownFields = discardUnknownFields;
-            input.ExtensionRegistry = registry;
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(data, nameof(data));
+            CodedInputStream input = new CodedInputStream(data, offset, length)
+            {
+                DiscardUnknownFields = discardUnknownFields,
+                ExtensionRegistry = registry
+            };
             message.MergeFrom(input);
             input.CheckReadEndOfStreamTag();
         }
 
         internal static void MergeFrom(this IMessage message, ByteString data, bool discardUnknownFields, ExtensionRegistry registry)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
-            ProtoPreconditions.CheckNotNull(data, "data");
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(data, nameof(data));
             CodedInputStream input = data.CreateCodedInput();
             input.DiscardUnknownFields = discardUnknownFields;
             input.ExtensionRegistry = registry;
@@ -284,11 +288,13 @@
 
         internal static void MergeFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
-            ProtoPreconditions.CheckNotNull(input, "input");
-            CodedInputStream codedInput = new CodedInputStream(input);
-            codedInput.DiscardUnknownFields = discardUnknownFields;
-            codedInput.ExtensionRegistry = registry;
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(input, nameof(input));
+            CodedInputStream codedInput = new CodedInputStream(input)
+            {
+                DiscardUnknownFields = discardUnknownFields,
+                ExtensionRegistry = registry
+            };
             message.MergeFrom(codedInput);
             codedInput.CheckReadEndOfStreamTag();
         }
@@ -315,8 +321,8 @@
 
         internal static void MergeDelimitedFrom(this IMessage message, Stream input, bool discardUnknownFields, ExtensionRegistry registry)
         {
-            ProtoPreconditions.CheckNotNull(message, "message");
-            ProtoPreconditions.CheckNotNull(input, "input");
+            ProtoPreconditions.CheckNotNull(message, nameof(message));
+            ProtoPreconditions.CheckNotNull(input, nameof(input));
             int size = (int) CodedInputStream.ReadRawVarint32(input);
             Stream limitedStream = new LimitedInputStream(input, size);
             MergeFrom(message, limitedStream, discardUnknownFields, registry);
diff --git a/csharp/src/Google.Protobuf/MessageParser.cs b/csharp/src/Google.Protobuf/MessageParser.cs
index a10c908..5710292 100644
--- a/csharp/src/Google.Protobuf/MessageParser.cs
+++ b/csharp/src/Google.Protobuf/MessageParser.cs
@@ -43,9 +43,8 @@
     /// </summary>
     public class MessageParser
     {
-        private Func<IMessage> factory;
-        // TODO: When we use a C# 7.1 compiler, make this private protected.
-        internal bool DiscardUnknownFields { get; }
+        private readonly Func<IMessage> factory;
+        private protected bool DiscardUnknownFields { get; }
 
         internal ExtensionRegistry Extensions { get; }
 
@@ -172,6 +171,10 @@
         /// <summary>
         /// Parses a message from the given JSON.
         /// </summary>
+        /// <remarks>This method always uses the default JSON parser; it is not affected by <see cref="WithDiscardUnknownFields(bool)"/>.
+        /// To ignore unknown fields when parsing JSON, create a <see cref="JsonParser"/> using a <see cref="JsonParser.Settings"/>
+        /// with <see cref="JsonParser.Settings.IgnoreUnknownFields"/> set to true and call <see cref="JsonParser.Parse{T}(string)"/> directly.
+        /// </remarks>
         /// <param name="json">The JSON to parse.</param>
         /// <returns>The parsed message.</returns>
         /// <exception cref="InvalidJsonException">The JSON does not comply with RFC 7159</exception>
@@ -204,6 +207,9 @@
         /// <summary>
         /// Creates a new message parser which optionally discards unknown fields when parsing.
         /// </summary>
+        /// <remarks>Note that this does not affect the behavior of <see cref="ParseJson(string)"/>
+        /// at all. To ignore unknown fields when parsing JSON, create a <see cref="JsonParser"/> using a <see cref="JsonParser.Settings"/>
+        /// with <see cref="JsonParser.Settings.IgnoreUnknownFields"/> set to true and call <see cref="JsonParser.Parse{T}(string)"/> directly.</remarks>
         /// <param name="discardUnknownFields">Whether or not to discard unknown fields when parsing.</param>
         /// <returns>A newly configured message parser.</returns>
         public MessageParser WithDiscardUnknownFields(bool discardUnknownFields) =>
diff --git a/csharp/src/Google.Protobuf/ObjectIntPair.cs b/csharp/src/Google.Protobuf/ObjectIntPair.cs
index b61fc68..3270b49 100644
--- a/csharp/src/Google.Protobuf/ObjectIntPair.cs
+++ b/csharp/src/Google.Protobuf/ObjectIntPair.cs
@@ -23,14 +23,7 @@
                    && number == other.number;
         }
 
-        public override bool Equals(object obj)
-        {
-            if (obj is ObjectIntPair<T>)
-            {
-                return Equals((ObjectIntPair<T>)obj);
-            }
-            return false;
-        }
+        public override bool Equals(object obj) => obj is ObjectIntPair<T> pair && Equals(pair);
 
         public override int GetHashCode()
         {
diff --git a/csharp/src/Google.Protobuf/ParseContext.cs b/csharp/src/Google.Protobuf/ParseContext.cs
index 7b278b5..85ea567 100644
--- a/csharp/src/Google.Protobuf/ParseContext.cs
+++ b/csharp/src/Google.Protobuf/ParseContext.cs
@@ -32,14 +32,8 @@
 
 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
 {
@@ -53,7 +47,7 @@
     public ref struct ParseContext
     {
         internal const int DefaultRecursionLimit = 100;
-        internal const int DefaultSizeLimit = Int32.MaxValue;
+        internal const int DefaultSizeLimit = int.MaxValue;
 
         internal ReadOnlySpan<byte> buffer;
         internal ParserInternalState state;
@@ -127,14 +121,15 @@
         /// 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; } }
+        internal uint LastTag => 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; }
+        internal bool DiscardUnknownFields
+        {
+            get => state.DiscardUnknownFields;
+            set => state.DiscardUnknownFields = value;
         }
 
         /// <summary>
@@ -142,8 +137,8 @@
         /// </summary>
         internal ExtensionRegistry ExtensionRegistry
         {
-            get { return state.ExtensionRegistry; }
-            set { state.ExtensionRegistry = value; }
+            get => state.ExtensionRegistry;
+            set => state.ExtensionRegistry = value;
         }
 
         /// <summary>
@@ -156,125 +151,85 @@
         /// </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);
-        }
+        public uint ReadTag() => 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);
-        }
+        public double ReadDouble() => 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);
-        }
+        public float ReadFloat() => 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);
-        }
+        public ulong ReadUInt64() => 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);
-        }
+        public long ReadInt64() => (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);
-        }
+        public int ReadInt32() => (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);
-        }
+        public ulong ReadFixed64() => 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);
-        }
+        public uint ReadFixed32() => 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;
-        }
+        public bool ReadBool() => 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);
-        }
+        public string ReadString() => 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);
-        }
+        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);
-        }
+        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);
-        }
+        public ByteString ReadBytes() => 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);
-        }
+        public uint ReadUInt32() => ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
 
         /// <summary>
         /// Reads an enum field value from the input.
@@ -290,37 +245,25 @@
         /// Reads an sfixed32 field value from the input.
         /// </summary>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public int ReadSFixed32()
-        {
-            return (int)ParsingPrimitives.ParseRawLittleEndian32(ref buffer, ref state);
-        }
+        public int ReadSFixed32() => (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);
-        }
+        public long ReadSFixed64() => (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));
-        }
+        public int ReadSInt32() => 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));
-        }
+        public long ReadSInt64() => ParsingPrimitives.DecodeZigZag64(ParsingPrimitives.ParseRawVarint64(ref buffer, ref state));
 
         /// <summary>
         /// Reads a length for length-delimited data.
@@ -330,10 +273,7 @@
         /// to make the calling code clearer.
         /// </remarks>
         [MethodImpl(MethodImplOptions.AggressiveInlining)]
-        public int ReadLength()
-        {
-            return (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
-        }
+        public int ReadLength() => (int)ParsingPrimitives.ParseRawVarint32(ref buffer, ref state);
 
         internal void CopyStateTo(CodedInputStream input)
         {
diff --git a/csharp/src/Google.Protobuf/ParserInternalState.cs b/csharp/src/Google.Protobuf/ParserInternalState.cs
index cb4f471..af7dd78 100644
--- a/csharp/src/Google.Protobuf/ParserInternalState.cs
+++ b/csharp/src/Google.Protobuf/ParserInternalState.cs
@@ -30,20 +30,8 @@
 // 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
     {
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitives.cs b/csharp/src/Google.Protobuf/ParsingPrimitives.cs
index e270ed8..4321d26 100644
--- a/csharp/src/Google.Protobuf/ParsingPrimitives.cs
+++ b/csharp/src/Google.Protobuf/ParsingPrimitives.cs
@@ -34,13 +34,10 @@
 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
 {
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs
index eabaf96..5e1babf 100644
--- a/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs
+++ b/csharp/src/Google.Protobuf/ParsingPrimitivesMessages.cs
@@ -33,8 +33,6 @@
 using System;
 using System.Buffers;
 using System.Collections.Generic;
-using System.IO;
-using System.Runtime.CompilerServices;
 using System.Security;
 using Google.Protobuf.Collections;
 
diff --git a/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
index 629ec32..e874935 100644
--- a/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
+++ b/csharp/src/Google.Protobuf/ParsingPrimitivesWrappers.cs
@@ -31,15 +31,7 @@
 #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
 {
diff --git a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
index 4328e2e..ae885f8 100644
--- a/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
+++ b/csharp/src/Google.Protobuf/Properties/AssemblyInfo.cs
@@ -47,10 +47,3 @@
     "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
     "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
     "c5ae9cb6")]
-
-[assembly: InternalsVisibleTo("Google.Protobuf.Benchmarks, PublicKey=" +
-    "002400000480000094000000060200000024000052534131000400000100010025800fbcfc63a1" +
-    "7c66b303aae80b03a6beaa176bb6bef883be436f2a1579edd80ce23edf151a1f4ced97af83abcd" +
-    "981207041fd5b2da3b498346fcfcd94910d52f25537c4a43ce3fbe17dc7d43e6cbdb4d8f1242dc" +
-    "b6bd9b5906be74da8daa7d7280f97130f318a16c07baf118839b156299a48522f9fae2371c9665" +
-    "c5ae9cb6")]
diff --git a/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs
index f6fa152..2c5d2c8 100644
--- a/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs
+++ b/csharp/src/Google.Protobuf/Reflection/CustomOptions.cs
@@ -31,7 +31,6 @@
 #endregion
 
 using Google.Protobuf.Collections;
-using System;
 using System.Collections;
 using System.Collections.Generic;
 using System.Diagnostics.CodeAnalysis;
@@ -226,24 +225,21 @@
         {
             if (values == null)
             {
-                value = default(T);
+                value = default;
                 return false;
             }
 
-            IExtensionValue extensionValue;
-            if (values.TryGetValue(field, out extensionValue))
+            if (values.TryGetValue(field, out IExtensionValue extensionValue))
             {
-                if (extensionValue is ExtensionValue<T>)
+                if (extensionValue is ExtensionValue<T> single)
                 {
-                    ExtensionValue<T> single = extensionValue as ExtensionValue<T>;
                     ByteString bytes = single.GetValue().ToByteString();
                     value = new T();
                     value.MergeFrom(bytes);
                     return true;
                 }
-                else if (extensionValue is RepeatedExtensionValue<T>)
+                else if (extensionValue is RepeatedExtensionValue<T> repeated)
                 {
-                    RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>;
                     value = repeated.GetValue()
                         .Select(v => v.ToByteString())
                         .Aggregate(new T(), (t, b) =>
@@ -264,22 +260,19 @@
         {
             if (values == null)
             {
-                value = default(T);
+                value = default;
                 return false;
             }
 
-            IExtensionValue extensionValue;
-            if (values.TryGetValue(field, out extensionValue))
+            if (values.TryGetValue(field, out IExtensionValue extensionValue))
             {
-                if (extensionValue is ExtensionValue<T>)
+                if (extensionValue is ExtensionValue<T> single)
                 {
-                    ExtensionValue<T> single = extensionValue as ExtensionValue<T>;
                     value = single.GetValue();
                     return true;
                 }
-                else if (extensionValue is RepeatedExtensionValue<T>)
+                else if (extensionValue is RepeatedExtensionValue<T> repeated)
                 {
-                    RepeatedExtensionValue<T> repeated = extensionValue as RepeatedExtensionValue<T>;
                     if (repeated.GetValue().Count != 0)
                     {
                         RepeatedField<T> repeatedField = repeated.GetValue();
@@ -317,7 +310,7 @@
                 }
             }
 
-            value = default(T);
+            value = default;
             return false;
         }
     }
diff --git a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs b/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs
similarity index 96%
rename from csharp/src/Google.Protobuf/Reflection/Descriptor.cs
rename to csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs
index 1cb43c0..e252372 100644
--- a/csharp/src/Google.Protobuf/Reflection/Descriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/Descriptor.pb.cs
@@ -26,7 +26,7 @@
           string.Concat(
             "CiBnb29nbGUvcHJvdG9idWYvZGVzY3JpcHRvci5wcm90bxIPZ29vZ2xlLnBy",
             "b3RvYnVmIkcKEUZpbGVEZXNjcmlwdG9yU2V0EjIKBGZpbGUYASADKAsyJC5n",
-            "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLbAwoTRmlsZURl",
+            "b29nbGUucHJvdG9idWYuRmlsZURlc2NyaXB0b3JQcm90byLsAwoTRmlsZURl",
             "c2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg8KB3BhY2thZ2UYAiABKAkS",
             "EgoKZGVwZW5kZW5jeRgDIAMoCRIZChFwdWJsaWNfZGVwZW5kZW5jeRgKIAMo",
             "BRIXCg93ZWFrX2RlcGVuZGVuY3kYCyADKAUSNgoMbWVzc2FnZV90eXBlGAQg",
@@ -37,134 +37,137 @@
             "LnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3RvEi0KB29wdGlvbnMYCCAB",
             "KAsyHC5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMSOQoQc291cmNlX2Nv",
             "ZGVfaW5mbxgJIAEoCzIfLmdvb2dsZS5wcm90b2J1Zi5Tb3VyY2VDb2RlSW5m",
-            "bxIOCgZzeW50YXgYDCABKAkiqQUKD0Rlc2NyaXB0b3JQcm90bxIMCgRuYW1l",
-            "GAEgASgJEjQKBWZpZWxkGAIgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
-            "RGVzY3JpcHRvclByb3RvEjgKCWV4dGVuc2lvbhgGIAMoCzIlLmdvb2dsZS5w",
-            "cm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90bxI1CgtuZXN0ZWRfdHlwZRgD",
-            "IAMoCzIgLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8SNwoJZW51",
-            "bV90eXBlGAQgAygLMiQuZ29vZ2xlLnByb3RvYnVmLkVudW1EZXNjcmlwdG9y",
-            "UHJvdG8SSAoPZXh0ZW5zaW9uX3JhbmdlGAUgAygLMi8uZ29vZ2xlLnByb3Rv",
-            "YnVmLkRlc2NyaXB0b3JQcm90by5FeHRlbnNpb25SYW5nZRI5CgpvbmVvZl9k",
-            "ZWNsGAggAygLMiUuZ29vZ2xlLnByb3RvYnVmLk9uZW9mRGVzY3JpcHRvclBy",
-            "b3RvEjAKB29wdGlvbnMYByABKAsyHy5nb29nbGUucHJvdG9idWYuTWVzc2Fn",
-            "ZU9wdGlvbnMSRgoOcmVzZXJ2ZWRfcmFuZ2UYCSADKAsyLi5nb29nbGUucHJv",
-            "dG9idWYuRGVzY3JpcHRvclByb3RvLlJlc2VydmVkUmFuZ2USFQoNcmVzZXJ2",
-            "ZWRfbmFtZRgKIAMoCRplCg5FeHRlbnNpb25SYW5nZRINCgVzdGFydBgBIAEo",
-            "BRILCgNlbmQYAiABKAUSNwoHb3B0aW9ucxgDIAEoCzImLmdvb2dsZS5wcm90",
-            "b2J1Zi5FeHRlbnNpb25SYW5nZU9wdGlvbnMaKwoNUmVzZXJ2ZWRSYW5nZRIN",
-            "CgVzdGFydBgBIAEoBRILCgNlbmQYAiABKAUiZwoVRXh0ZW5zaW9uUmFuZ2VP",
+            "bxIOCgZzeW50YXgYDCABKAkSDwoHZWRpdGlvbhgNIAEoCSKpBQoPRGVzY3Jp",
+            "cHRvclByb3RvEgwKBG5hbWUYASABKAkSNAoFZmllbGQYAiADKAsyJS5nb29n",
+            "bGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8SOAoJZXh0ZW5zaW9u",
+            "GAYgAygLMiUuZ29vZ2xlLnByb3RvYnVmLkZpZWxkRGVzY3JpcHRvclByb3Rv",
+            "EjUKC25lc3RlZF90eXBlGAMgAygLMiAuZ29vZ2xlLnByb3RvYnVmLkRlc2Ny",
+            "aXB0b3JQcm90bxI3CgllbnVtX3R5cGUYBCADKAsyJC5nb29nbGUucHJvdG9i",
+            "dWYuRW51bURlc2NyaXB0b3JQcm90bxJICg9leHRlbnNpb25fcmFuZ2UYBSAD",
+            "KAsyLy5nb29nbGUucHJvdG9idWYuRGVzY3JpcHRvclByb3RvLkV4dGVuc2lv",
+            "blJhbmdlEjkKCm9uZW9mX2RlY2wYCCADKAsyJS5nb29nbGUucHJvdG9idWYu",
+            "T25lb2ZEZXNjcmlwdG9yUHJvdG8SMAoHb3B0aW9ucxgHIAEoCzIfLmdvb2ds",
+            "ZS5wcm90b2J1Zi5NZXNzYWdlT3B0aW9ucxJGCg5yZXNlcnZlZF9yYW5nZRgJ",
+            "IAMoCzIuLmdvb2dsZS5wcm90b2J1Zi5EZXNjcmlwdG9yUHJvdG8uUmVzZXJ2",
+            "ZWRSYW5nZRIVCg1yZXNlcnZlZF9uYW1lGAogAygJGmUKDkV4dGVuc2lvblJh",
+            "bmdlEg0KBXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBRI3CgdvcHRpb25zGAMg",
+            "ASgLMiYuZ29vZ2xlLnByb3RvYnVmLkV4dGVuc2lvblJhbmdlT3B0aW9ucxor",
+            "Cg1SZXNlcnZlZFJhbmdlEg0KBXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBSJn",
+            "ChVFeHRlbnNpb25SYW5nZU9wdGlvbnMSQwoUdW5pbnRlcnByZXRlZF9vcHRp",
+            "b24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRp",
+            "b24qCQjoBxCAgICAAiLVBQoURmllbGREZXNjcmlwdG9yUHJvdG8SDAoEbmFt",
+            "ZRgBIAEoCRIOCgZudW1iZXIYAyABKAUSOgoFbGFiZWwYBCABKA4yKy5nb29n",
+            "bGUucHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8uTGFiZWwSOAoEdHlw",
+            "ZRgFIAEoDjIqLmdvb2dsZS5wcm90b2J1Zi5GaWVsZERlc2NyaXB0b3JQcm90",
+            "by5UeXBlEhEKCXR5cGVfbmFtZRgGIAEoCRIQCghleHRlbmRlZRgCIAEoCRIV",
+            "Cg1kZWZhdWx0X3ZhbHVlGAcgASgJEhMKC29uZW9mX2luZGV4GAkgASgFEhEK",
+            "CWpzb25fbmFtZRgKIAEoCRIuCgdvcHRpb25zGAggASgLMh0uZ29vZ2xlLnBy",
+            "b3RvYnVmLkZpZWxkT3B0aW9ucxIXCg9wcm90bzNfb3B0aW9uYWwYESABKAgi",
+            "tgIKBFR5cGUSDwoLVFlQRV9ET1VCTEUQARIOCgpUWVBFX0ZMT0FUEAISDgoK",
+            "VFlQRV9JTlQ2NBADEg8KC1RZUEVfVUlOVDY0EAQSDgoKVFlQRV9JTlQzMhAF",
+            "EhAKDFRZUEVfRklYRUQ2NBAGEhAKDFRZUEVfRklYRUQzMhAHEg0KCVRZUEVf",
+            "Qk9PTBAIEg8KC1RZUEVfU1RSSU5HEAkSDgoKVFlQRV9HUk9VUBAKEhAKDFRZ",
+            "UEVfTUVTU0FHRRALEg4KClRZUEVfQllURVMQDBIPCgtUWVBFX1VJTlQzMhAN",
+            "Eg0KCVRZUEVfRU5VTRAOEhEKDVRZUEVfU0ZJWEVEMzIQDxIRCg1UWVBFX1NG",
+            "SVhFRDY0EBASDwoLVFlQRV9TSU5UMzIQERIPCgtUWVBFX1NJTlQ2NBASIkMK",
+            "BUxhYmVsEhIKDkxBQkVMX09QVElPTkFMEAESEgoOTEFCRUxfUkVRVUlSRUQQ",
+            "AhISCg5MQUJFTF9SRVBFQVRFRBADIlQKFE9uZW9mRGVzY3JpcHRvclByb3Rv",
+            "EgwKBG5hbWUYASABKAkSLgoHb3B0aW9ucxgCIAEoCzIdLmdvb2dsZS5wcm90",
+            "b2J1Zi5PbmVvZk9wdGlvbnMipAIKE0VudW1EZXNjcmlwdG9yUHJvdG8SDAoE",
+            "bmFtZRgBIAEoCRI4CgV2YWx1ZRgCIAMoCzIpLmdvb2dsZS5wcm90b2J1Zi5F",
+            "bnVtVmFsdWVEZXNjcmlwdG9yUHJvdG8SLQoHb3B0aW9ucxgDIAEoCzIcLmdv",
+            "b2dsZS5wcm90b2J1Zi5FbnVtT3B0aW9ucxJOCg5yZXNlcnZlZF9yYW5nZRgE",
+            "IAMoCzI2Lmdvb2dsZS5wcm90b2J1Zi5FbnVtRGVzY3JpcHRvclByb3RvLkVu",
+            "dW1SZXNlcnZlZFJhbmdlEhUKDXJlc2VydmVkX25hbWUYBSADKAkaLwoRRW51",
+            "bVJlc2VydmVkUmFuZ2USDQoFc3RhcnQYASABKAUSCwoDZW5kGAIgASgFImwK",
+            "GEVudW1WYWx1ZURlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEg4KBm51",
+            "bWJlchgCIAEoBRIyCgdvcHRpb25zGAMgASgLMiEuZ29vZ2xlLnByb3RvYnVm",
+            "LkVudW1WYWx1ZU9wdGlvbnMikAEKFlNlcnZpY2VEZXNjcmlwdG9yUHJvdG8S",
+            "DAoEbmFtZRgBIAEoCRI2CgZtZXRob2QYAiADKAsyJi5nb29nbGUucHJvdG9i",
+            "dWYuTWV0aG9kRGVzY3JpcHRvclByb3RvEjAKB29wdGlvbnMYAyABKAsyHy5n",
+            "b29nbGUucHJvdG9idWYuU2VydmljZU9wdGlvbnMiwQEKFU1ldGhvZERlc2Ny",
+            "aXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEhIKCmlucHV0X3R5cGUYAiABKAkS",
+            "EwoLb3V0cHV0X3R5cGUYAyABKAkSLwoHb3B0aW9ucxgEIAEoCzIeLmdvb2ds",
+            "ZS5wcm90b2J1Zi5NZXRob2RPcHRpb25zEh8KEGNsaWVudF9zdHJlYW1pbmcY",
+            "BSABKAg6BWZhbHNlEh8KEHNlcnZlcl9zdHJlYW1pbmcYBiABKAg6BWZhbHNl",
+            "IqUGCgtGaWxlT3B0aW9ucxIUCgxqYXZhX3BhY2thZ2UYASABKAkSHAoUamF2",
+            "YV9vdXRlcl9jbGFzc25hbWUYCCABKAkSIgoTamF2YV9tdWx0aXBsZV9maWxl",
+            "cxgKIAEoCDoFZmFsc2USKQodamF2YV9nZW5lcmF0ZV9lcXVhbHNfYW5kX2hh",
+            "c2gYFCABKAhCAhgBEiUKFmphdmFfc3RyaW5nX2NoZWNrX3V0ZjgYGyABKAg6",
+            "BWZhbHNlEkYKDG9wdGltaXplX2ZvchgJIAEoDjIpLmdvb2dsZS5wcm90b2J1",
+            "Zi5GaWxlT3B0aW9ucy5PcHRpbWl6ZU1vZGU6BVNQRUVEEhIKCmdvX3BhY2th",
+            "Z2UYCyABKAkSIgoTY2NfZ2VuZXJpY19zZXJ2aWNlcxgQIAEoCDoFZmFsc2US",
+            "JAoVamF2YV9nZW5lcmljX3NlcnZpY2VzGBEgASgIOgVmYWxzZRIiChNweV9n",
+            "ZW5lcmljX3NlcnZpY2VzGBIgASgIOgVmYWxzZRIjChRwaHBfZ2VuZXJpY19z",
+            "ZXJ2aWNlcxgqIAEoCDoFZmFsc2USGQoKZGVwcmVjYXRlZBgXIAEoCDoFZmFs",
+            "c2USHgoQY2NfZW5hYmxlX2FyZW5hcxgfIAEoCDoEdHJ1ZRIZChFvYmpjX2Ns",
+            "YXNzX3ByZWZpeBgkIAEoCRIYChBjc2hhcnBfbmFtZXNwYWNlGCUgASgJEhQK",
+            "DHN3aWZ0X3ByZWZpeBgnIAEoCRIYChBwaHBfY2xhc3NfcHJlZml4GCggASgJ",
+            "EhUKDXBocF9uYW1lc3BhY2UYKSABKAkSHgoWcGhwX21ldGFkYXRhX25hbWVz",
+            "cGFjZRgsIAEoCRIUCgxydWJ5X3BhY2thZ2UYLSABKAkSQwoUdW5pbnRlcnBy",
+            "ZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJw",
+            "cmV0ZWRPcHRpb24iOgoMT3B0aW1pemVNb2RlEgkKBVNQRUVEEAESDQoJQ09E",
+            "RV9TSVpFEAISEAoMTElURV9SVU5USU1FEAMqCQjoBxCAgICAAkoECCYQJyKE",
+            "AgoOTWVzc2FnZU9wdGlvbnMSJgoXbWVzc2FnZV9zZXRfd2lyZV9mb3JtYXQY",
+            "ASABKAg6BWZhbHNlEi4KH25vX3N0YW5kYXJkX2Rlc2NyaXB0b3JfYWNjZXNz",
+            "b3IYAiABKAg6BWZhbHNlEhkKCmRlcHJlY2F0ZWQYAyABKAg6BWZhbHNlEhEK",
+            "CW1hcF9lbnRyeRgHIAEoCBJDChR1bmludGVycHJldGVkX29wdGlvbhjnByAD",
+            "KAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgH",
+            "EICAgIACSgQIBBAFSgQIBRAGSgQIBhAHSgQICBAJSgQICRAKIr4DCgxGaWVs",
+            "ZE9wdGlvbnMSOgoFY3R5cGUYASABKA4yIy5nb29nbGUucHJvdG9idWYuRmll",
+            "bGRPcHRpb25zLkNUeXBlOgZTVFJJTkcSDgoGcGFja2VkGAIgASgIEj8KBmpz",
+            "dHlwZRgGIAEoDjIkLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlvbnMuSlNU",
+            "eXBlOglKU19OT1JNQUwSEwoEbGF6eRgFIAEoCDoFZmFsc2USHgoPdW52ZXJp",
+            "ZmllZF9sYXp5GA8gASgIOgVmYWxzZRIZCgpkZXByZWNhdGVkGAMgASgIOgVm",
+            "YWxzZRITCgR3ZWFrGAogASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29w",
+            "dGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9w",
+            "dGlvbiIvCgVDVHlwZRIKCgZTVFJJTkcQABIICgRDT1JEEAESEAoMU1RSSU5H",
+            "X1BJRUNFEAIiNQoGSlNUeXBlEg0KCUpTX05PUk1BTBAAEg0KCUpTX1NUUklO",
+            "RxABEg0KCUpTX05VTUJFUhACKgkI6AcQgICAgAJKBAgEEAUiXgoMT25lb2ZP",
             "cHRpb25zEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2ds",
-            "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIi1QUK",
-            "FEZpZWxkRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSDgoGbnVtYmVy",
-            "GAMgASgFEjoKBWxhYmVsGAQgASgOMisuZ29vZ2xlLnByb3RvYnVmLkZpZWxk",
-            "RGVzY3JpcHRvclByb3RvLkxhYmVsEjgKBHR5cGUYBSABKA4yKi5nb29nbGUu",
-            "cHJvdG9idWYuRmllbGREZXNjcmlwdG9yUHJvdG8uVHlwZRIRCgl0eXBlX25h",
-            "bWUYBiABKAkSEAoIZXh0ZW5kZWUYAiABKAkSFQoNZGVmYXVsdF92YWx1ZRgH",
-            "IAEoCRITCgtvbmVvZl9pbmRleBgJIAEoBRIRCglqc29uX25hbWUYCiABKAkS",
-            "LgoHb3B0aW9ucxgIIAEoCzIdLmdvb2dsZS5wcm90b2J1Zi5GaWVsZE9wdGlv",
-            "bnMSFwoPcHJvdG8zX29wdGlvbmFsGBEgASgIIrYCCgRUeXBlEg8KC1RZUEVf",
-            "RE9VQkxFEAESDgoKVFlQRV9GTE9BVBACEg4KClRZUEVfSU5UNjQQAxIPCgtU",
-            "WVBFX1VJTlQ2NBAEEg4KClRZUEVfSU5UMzIQBRIQCgxUWVBFX0ZJWEVENjQQ",
-            "BhIQCgxUWVBFX0ZJWEVEMzIQBxINCglUWVBFX0JPT0wQCBIPCgtUWVBFX1NU",
-            "UklORxAJEg4KClRZUEVfR1JPVVAQChIQCgxUWVBFX01FU1NBR0UQCxIOCgpU",
-            "WVBFX0JZVEVTEAwSDwoLVFlQRV9VSU5UMzIQDRINCglUWVBFX0VOVU0QDhIR",
-            "Cg1UWVBFX1NGSVhFRDMyEA8SEQoNVFlQRV9TRklYRUQ2NBAQEg8KC1RZUEVf",
-            "U0lOVDMyEBESDwoLVFlQRV9TSU5UNjQQEiJDCgVMYWJlbBISCg5MQUJFTF9P",
-            "UFRJT05BTBABEhIKDkxBQkVMX1JFUVVJUkVEEAISEgoOTEFCRUxfUkVQRUFU",
-            "RUQQAyJUChRPbmVvZkRlc2NyaXB0b3JQcm90bxIMCgRuYW1lGAEgASgJEi4K",
-            "B29wdGlvbnMYAiABKAsyHS5nb29nbGUucHJvdG9idWYuT25lb2ZPcHRpb25z",
-            "IqQCChNFbnVtRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSOAoFdmFs",
-            "dWUYAiADKAsyKS5nb29nbGUucHJvdG9idWYuRW51bVZhbHVlRGVzY3JpcHRv",
-            "clByb3RvEi0KB29wdGlvbnMYAyABKAsyHC5nb29nbGUucHJvdG9idWYuRW51",
-            "bU9wdGlvbnMSTgoOcmVzZXJ2ZWRfcmFuZ2UYBCADKAsyNi5nb29nbGUucHJv",
-            "dG9idWYuRW51bURlc2NyaXB0b3JQcm90by5FbnVtUmVzZXJ2ZWRSYW5nZRIV",
-            "Cg1yZXNlcnZlZF9uYW1lGAUgAygJGi8KEUVudW1SZXNlcnZlZFJhbmdlEg0K",
-            "BXN0YXJ0GAEgASgFEgsKA2VuZBgCIAEoBSJsChhFbnVtVmFsdWVEZXNjcmlw",
-            "dG9yUHJvdG8SDAoEbmFtZRgBIAEoCRIOCgZudW1iZXIYAiABKAUSMgoHb3B0",
-            "aW9ucxgDIAEoCzIhLmdvb2dsZS5wcm90b2J1Zi5FbnVtVmFsdWVPcHRpb25z",
-            "IpABChZTZXJ2aWNlRGVzY3JpcHRvclByb3RvEgwKBG5hbWUYASABKAkSNgoG",
-            "bWV0aG9kGAIgAygLMiYuZ29vZ2xlLnByb3RvYnVmLk1ldGhvZERlc2NyaXB0",
-            "b3JQcm90bxIwCgdvcHRpb25zGAMgASgLMh8uZ29vZ2xlLnByb3RvYnVmLlNl",
-            "cnZpY2VPcHRpb25zIsEBChVNZXRob2REZXNjcmlwdG9yUHJvdG8SDAoEbmFt",
-            "ZRgBIAEoCRISCgppbnB1dF90eXBlGAIgASgJEhMKC291dHB1dF90eXBlGAMg",
-            "ASgJEi8KB29wdGlvbnMYBCABKAsyHi5nb29nbGUucHJvdG9idWYuTWV0aG9k",
-            "T3B0aW9ucxIfChBjbGllbnRfc3RyZWFtaW5nGAUgASgIOgVmYWxzZRIfChBz",
-            "ZXJ2ZXJfc3RyZWFtaW5nGAYgASgIOgVmYWxzZSKlBgoLRmlsZU9wdGlvbnMS",
-            "FAoMamF2YV9wYWNrYWdlGAEgASgJEhwKFGphdmFfb3V0ZXJfY2xhc3NuYW1l",
-            "GAggASgJEiIKE2phdmFfbXVsdGlwbGVfZmlsZXMYCiABKAg6BWZhbHNlEikK",
-            "HWphdmFfZ2VuZXJhdGVfZXF1YWxzX2FuZF9oYXNoGBQgASgIQgIYARIlChZq",
-            "YXZhX3N0cmluZ19jaGVja191dGY4GBsgASgIOgVmYWxzZRJGCgxvcHRpbWl6",
-            "ZV9mb3IYCSABKA4yKS5nb29nbGUucHJvdG9idWYuRmlsZU9wdGlvbnMuT3B0",
-            "aW1pemVNb2RlOgVTUEVFRBISCgpnb19wYWNrYWdlGAsgASgJEiIKE2NjX2dl",
-            "bmVyaWNfc2VydmljZXMYECABKAg6BWZhbHNlEiQKFWphdmFfZ2VuZXJpY19z",
-            "ZXJ2aWNlcxgRIAEoCDoFZmFsc2USIgoTcHlfZ2VuZXJpY19zZXJ2aWNlcxgS",
-            "IAEoCDoFZmFsc2USIwoUcGhwX2dlbmVyaWNfc2VydmljZXMYKiABKAg6BWZh",
-            "bHNlEhkKCmRlcHJlY2F0ZWQYFyABKAg6BWZhbHNlEh4KEGNjX2VuYWJsZV9h",
-            "cmVuYXMYHyABKAg6BHRydWUSGQoRb2JqY19jbGFzc19wcmVmaXgYJCABKAkS",
-            "GAoQY3NoYXJwX25hbWVzcGFjZRglIAEoCRIUCgxzd2lmdF9wcmVmaXgYJyAB",
-            "KAkSGAoQcGhwX2NsYXNzX3ByZWZpeBgoIAEoCRIVCg1waHBfbmFtZXNwYWNl",
-            "GCkgASgJEh4KFnBocF9tZXRhZGF0YV9uYW1lc3BhY2UYLCABKAkSFAoMcnVi",
-            "eV9wYWNrYWdlGC0gASgJEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
-            "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIjoKDE9w",
-            "dGltaXplTW9kZRIJCgVTUEVFRBABEg0KCUNPREVfU0laRRACEhAKDExJVEVf",
-            "UlVOVElNRRADKgkI6AcQgICAgAJKBAgmECcihAIKDk1lc3NhZ2VPcHRpb25z",
-            "EiYKF21lc3NhZ2Vfc2V0X3dpcmVfZm9ybWF0GAEgASgIOgVmYWxzZRIuCh9u",
-            "b19zdGFuZGFyZF9kZXNjcmlwdG9yX2FjY2Vzc29yGAIgASgIOgVmYWxzZRIZ",
-            "CgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRIRCgltYXBfZW50cnkYByABKAgS",
-            "QwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3Rv",
-            "YnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAkoECAQQBUoECAUQ",
-            "BkoECAYQB0oECAgQCUoECAkQCiK+AwoMRmllbGRPcHRpb25zEjoKBWN0eXBl",
-            "GAEgASgOMiMuZ29vZ2xlLnByb3RvYnVmLkZpZWxkT3B0aW9ucy5DVHlwZToG",
-            "U1RSSU5HEg4KBnBhY2tlZBgCIAEoCBI/CgZqc3R5cGUYBiABKA4yJC5nb29n",
-            "bGUucHJvdG9idWYuRmllbGRPcHRpb25zLkpTVHlwZToJSlNfTk9STUFMEhMK",
-            "BGxhenkYBSABKAg6BWZhbHNlEh4KD3VudmVyaWZpZWRfbGF6eRgPIAEoCDoF",
-            "ZmFsc2USGQoKZGVwcmVjYXRlZBgDIAEoCDoFZmFsc2USEwoEd2VhaxgKIAEo",
-            "CDoFZmFsc2USQwoUdW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29v",
-            "Z2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24iLwoFQ1R5cGUSCgoG",
-            "U1RSSU5HEAASCAoEQ09SRBABEhAKDFNUUklOR19QSUVDRRACIjUKBkpTVHlw",
-            "ZRINCglKU19OT1JNQUwQABINCglKU19TVFJJTkcQARINCglKU19OVU1CRVIQ",
-            "AioJCOgHEICAgIACSgQIBBAFIl4KDE9uZW9mT3B0aW9ucxJDChR1bmludGVy",
-            "cHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRl",
-            "cnByZXRlZE9wdGlvbioJCOgHEICAgIACIpMBCgtFbnVtT3B0aW9ucxITCgth",
-            "bGxvd19hbGlhcxgCIAEoCBIZCgpkZXByZWNhdGVkGAMgASgIOgVmYWxzZRJD",
-            "ChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9i",
-            "dWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICAgIACSgQIBRAGIn0KEEVu",
-            "dW1WYWx1ZU9wdGlvbnMSGQoKZGVwcmVjYXRlZBgBIAEoCDoFZmFsc2USQwoU",
-            "dW5pbnRlcnByZXRlZF9vcHRpb24Y5wcgAygLMiQuZ29vZ2xlLnByb3RvYnVm",
-            "LlVuaW50ZXJwcmV0ZWRPcHRpb24qCQjoBxCAgICAAiJ7Cg5TZXJ2aWNlT3B0",
-            "aW9ucxIZCgpkZXByZWNhdGVkGCEgASgIOgVmYWxzZRJDChR1bmludGVycHJl",
-            "dGVkX29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnBy",
-            "ZXRlZE9wdGlvbioJCOgHEICAgIACIq0CCg1NZXRob2RPcHRpb25zEhkKCmRl",
-            "cHJlY2F0ZWQYISABKAg6BWZhbHNlEl8KEWlkZW1wb3RlbmN5X2xldmVsGCIg",
-            "ASgOMi8uZ29vZ2xlLnByb3RvYnVmLk1ldGhvZE9wdGlvbnMuSWRlbXBvdGVu",
-            "Y3lMZXZlbDoTSURFTVBPVEVOQ1lfVU5LTk9XThJDChR1bmludGVycHJldGVk",
-            "X29wdGlvbhjnByADKAsyJC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRl",
-            "ZE9wdGlvbiJQChBJZGVtcG90ZW5jeUxldmVsEhcKE0lERU1QT1RFTkNZX1VO",
-            "S05PV04QABITCg9OT19TSURFX0VGRkVDVFMQARIOCgpJREVNUE9URU5UEAIq",
-            "CQjoBxCAgICAAiKeAgoTVW5pbnRlcnByZXRlZE9wdGlvbhI7CgRuYW1lGAIg",
-            "AygLMi0uZ29vZ2xlLnByb3RvYnVmLlVuaW50ZXJwcmV0ZWRPcHRpb24uTmFt",
-            "ZVBhcnQSGAoQaWRlbnRpZmllcl92YWx1ZRgDIAEoCRIaChJwb3NpdGl2ZV9p",
-            "bnRfdmFsdWUYBCABKAQSGgoSbmVnYXRpdmVfaW50X3ZhbHVlGAUgASgDEhQK",
-            "DGRvdWJsZV92YWx1ZRgGIAEoARIUCgxzdHJpbmdfdmFsdWUYByABKAwSFwoP",
-            "YWdncmVnYXRlX3ZhbHVlGAggASgJGjMKCE5hbWVQYXJ0EhEKCW5hbWVfcGFy",
-            "dBgBIAIoCRIUCgxpc19leHRlbnNpb24YAiACKAgi1QEKDlNvdXJjZUNvZGVJ",
-            "bmZvEjoKCGxvY2F0aW9uGAEgAygLMiguZ29vZ2xlLnByb3RvYnVmLlNvdXJj",
-            "ZUNvZGVJbmZvLkxvY2F0aW9uGoYBCghMb2NhdGlvbhIQCgRwYXRoGAEgAygF",
-            "QgIQARIQCgRzcGFuGAIgAygFQgIQARIYChBsZWFkaW5nX2NvbW1lbnRzGAMg",
-            "ASgJEhkKEXRyYWlsaW5nX2NvbW1lbnRzGAQgASgJEiEKGWxlYWRpbmdfZGV0",
-            "YWNoZWRfY29tbWVudHMYBiADKAkipwEKEUdlbmVyYXRlZENvZGVJbmZvEkEK",
-            "CmFubm90YXRpb24YASADKAsyLS5nb29nbGUucHJvdG9idWYuR2VuZXJhdGVk",
-            "Q29kZUluZm8uQW5ub3RhdGlvbhpPCgpBbm5vdGF0aW9uEhAKBHBhdGgYASAD",
-            "KAVCAhABEhMKC3NvdXJjZV9maWxlGAIgASgJEg0KBWJlZ2luGAMgASgFEgsK",
-            "A2VuZBgEIAEoBUJ+ChNjb20uZ29vZ2xlLnByb3RvYnVmQhBEZXNjcmlwdG9y",
-            "UHJvdG9zSAFaLWdvb2dsZS5nb2xhbmcub3JnL3Byb3RvYnVmL3R5cGVzL2Rl",
-            "c2NyaXB0b3JwYvgBAaICA0dQQqoCGkdvb2dsZS5Qcm90b2J1Zi5SZWZsZWN0",
-            "aW9u"));
+            "ZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIikwEK",
+            "C0VudW1PcHRpb25zEhMKC2FsbG93X2FsaWFzGAIgASgIEhkKCmRlcHJlY2F0",
+            "ZWQYAyABKAg6BWZhbHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMo",
+            "CzIkLmdvb2dsZS5wcm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQ",
+            "gICAgAJKBAgFEAYifQoQRW51bVZhbHVlT3B0aW9ucxIZCgpkZXByZWNhdGVk",
+            "GAEgASgIOgVmYWxzZRJDChR1bmludGVycHJldGVkX29wdGlvbhjnByADKAsy",
+            "JC5nb29nbGUucHJvdG9idWYuVW5pbnRlcnByZXRlZE9wdGlvbioJCOgHEICA",
+            "gIACInsKDlNlcnZpY2VPcHRpb25zEhkKCmRlcHJlY2F0ZWQYISABKAg6BWZh",
+            "bHNlEkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5w",
+            "cm90b2J1Zi5VbmludGVycHJldGVkT3B0aW9uKgkI6AcQgICAgAIirQIKDU1l",
+            "dGhvZE9wdGlvbnMSGQoKZGVwcmVjYXRlZBghIAEoCDoFZmFsc2USXwoRaWRl",
+            "bXBvdGVuY3lfbGV2ZWwYIiABKA4yLy5nb29nbGUucHJvdG9idWYuTWV0aG9k",
+            "T3B0aW9ucy5JZGVtcG90ZW5jeUxldmVsOhNJREVNUE9URU5DWV9VTktOT1dO",
+            "EkMKFHVuaW50ZXJwcmV0ZWRfb3B0aW9uGOcHIAMoCzIkLmdvb2dsZS5wcm90",
+            "b2J1Zi5VbmludGVycHJldGVkT3B0aW9uIlAKEElkZW1wb3RlbmN5TGV2ZWwS",
+            "FwoTSURFTVBPVEVOQ1lfVU5LTk9XThAAEhMKD05PX1NJREVfRUZGRUNUUxAB",
+            "Eg4KCklERU1QT1RFTlQQAioJCOgHEICAgIACIp4CChNVbmludGVycHJldGVk",
+            "T3B0aW9uEjsKBG5hbWUYAiADKAsyLS5nb29nbGUucHJvdG9idWYuVW5pbnRl",
+            "cnByZXRlZE9wdGlvbi5OYW1lUGFydBIYChBpZGVudGlmaWVyX3ZhbHVlGAMg",
+            "ASgJEhoKEnBvc2l0aXZlX2ludF92YWx1ZRgEIAEoBBIaChJuZWdhdGl2ZV9p",
+            "bnRfdmFsdWUYBSABKAMSFAoMZG91YmxlX3ZhbHVlGAYgASgBEhQKDHN0cmlu",
+            "Z192YWx1ZRgHIAEoDBIXCg9hZ2dyZWdhdGVfdmFsdWUYCCABKAkaMwoITmFt",
+            "ZVBhcnQSEQoJbmFtZV9wYXJ0GAEgAigJEhQKDGlzX2V4dGVuc2lvbhgCIAIo",
+            "CCLVAQoOU291cmNlQ29kZUluZm8SOgoIbG9jYXRpb24YASADKAsyKC5nb29n",
+            "bGUucHJvdG9idWYuU291cmNlQ29kZUluZm8uTG9jYXRpb24ahgEKCExvY2F0",
+            "aW9uEhAKBHBhdGgYASADKAVCAhABEhAKBHNwYW4YAiADKAVCAhABEhgKEGxl",
+            "YWRpbmdfY29tbWVudHMYAyABKAkSGQoRdHJhaWxpbmdfY29tbWVudHMYBCAB",
+            "KAkSIQoZbGVhZGluZ19kZXRhY2hlZF9jb21tZW50cxgGIAMoCSKcAgoRR2Vu",
+            "ZXJhdGVkQ29kZUluZm8SQQoKYW5ub3RhdGlvbhgBIAMoCzItLmdvb2dsZS5w",
+            "cm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0aW9uGsMBCgpBbm5v",
+            "dGF0aW9uEhAKBHBhdGgYASADKAVCAhABEhMKC3NvdXJjZV9maWxlGAIgASgJ",
+            "Eg0KBWJlZ2luGAMgASgFEgsKA2VuZBgEIAEoBRJICghzZW1hbnRpYxgFIAEo",
+            "DjI2Lmdvb2dsZS5wcm90b2J1Zi5HZW5lcmF0ZWRDb2RlSW5mby5Bbm5vdGF0",
+            "aW9uLlNlbWFudGljIigKCFNlbWFudGljEggKBE5PTkUQABIHCgNTRVQQARIJ",
+            "CgVBTElBUxACQn4KE2NvbS5nb29nbGUucHJvdG9idWZCEERlc2NyaXB0b3JQ",
+            "cm90b3NIAVotZ29vZ2xlLmdvbGFuZy5vcmcvcHJvdG9idWYvdHlwZXMvZGVz",
+            "Y3JpcHRvcnBi+AEBogIDR1BCqgIaR29vZ2xlLlByb3RvYnVmLlJlZmxlY3Rp",
+            "b24="));
       descriptor = pbr::FileDescriptor.FromGeneratedCode(descriptorData,
           new pbr::FileDescriptor[] { },
           new pbr::GeneratedClrTypeInfo(null, null, new pbr::GeneratedClrTypeInfo[] {
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorSet), global::Google.Protobuf.Reflection.FileDescriptorSet.Parser, new[]{ "File" }, null, null, null, null),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax" }, null, null, null, null),
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.FileDescriptorProto), global::Google.Protobuf.Reflection.FileDescriptorProto.Parser, new[]{ "Name", "Package", "Dependency", "PublicDependency", "WeakDependency", "MessageType", "EnumType", "Service", "Extension", "Options", "SourceCodeInfo", "Syntax", "Edition" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto), global::Google.Protobuf.Reflection.DescriptorProto.Parser, new[]{ "Name", "Field", "Extension", "NestedType", "EnumType", "ExtensionRange", "OneofDecl", "Options", "ReservedRange", "ReservedName" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ExtensionRange.Parser, new[]{ "Start", "End", "Options" }, null, null, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange), global::Google.Protobuf.Reflection.DescriptorProto.Types.ReservedRange.Parser, new[]{ "Start", "End" }, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.ExtensionRangeOptions), global::Google.Protobuf.Reflection.ExtensionRangeOptions.Parser, new[]{ "UninterpretedOption" }, null, null, null, null),
@@ -184,7 +187,7 @@
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.MethodOptions), global::Google.Protobuf.Reflection.MethodOptions.Parser, new[]{ "Deprecated", "IdempotencyLevel", "UninterpretedOption" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.MethodOptions.Types.IdempotencyLevel) }, null, null),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption), global::Google.Protobuf.Reflection.UninterpretedOption.Parser, new[]{ "Name", "IdentifierValue", "PositiveIntValue", "NegativeIntValue", "DoubleValue", "StringValue", "AggregateValue" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart), global::Google.Protobuf.Reflection.UninterpretedOption.Types.NamePart.Parser, new[]{ "NamePart_", "IsExtension" }, null, null, null, null)}),
             new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo), global::Google.Protobuf.Reflection.SourceCodeInfo.Parser, new[]{ "Location" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location), global::Google.Protobuf.Reflection.SourceCodeInfo.Types.Location.Parser, new[]{ "Path", "Span", "LeadingComments", "TrailingComments", "LeadingDetachedComments" }, null, null, null, null)}),
-            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End" }, null, null, null, null)})
+            new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Parser, new[]{ "Annotation" }, null, null, null, new pbr::GeneratedClrTypeInfo[] { new pbr::GeneratedClrTypeInfo(typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation), global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Parser, new[]{ "Path", "SourceFile", "Begin", "End", "Semantic" }, null, new[]{ typeof(global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic) }, null, null)})
           }));
     }
     #endregion
@@ -422,6 +425,7 @@
       options_ = other.options_ != null ? other.options_.Clone() : null;
       sourceCodeInfo_ = other.sourceCodeInfo_ != null ? other.sourceCodeInfo_.Clone() : null;
       syntax_ = other.syntax_;
+      edition_ = other.edition_;
       _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
     }
 
@@ -616,7 +620,9 @@
     private string syntax_;
     /// <summary>
     /// The syntax of the proto file.
-    /// The supported values are "proto2" and "proto3".
+    /// The supported values are "proto2", "proto3", and "editions".
+    ///
+    /// If `edition` is present, this value must be "editions".
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -639,6 +645,35 @@
       syntax_ = null;
     }
 
+    /// <summary>Field number for the "edition" field.</summary>
+    public const int EditionFieldNumber = 13;
+    private readonly static string EditionDefaultValue = "";
+
+    private string edition_;
+    /// <summary>
+    /// The edition of the proto file, which is an opaque string.
+    /// </summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public string Edition {
+      get { return edition_ ?? EditionDefaultValue; }
+      set {
+        edition_ = pb::ProtoPreconditions.CheckNotNull(value, "value");
+      }
+    }
+    /// <summary>Gets whether the "edition" field is set</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public bool HasEdition {
+      get { return edition_ != null; }
+    }
+    /// <summary>Clears the value of the "edition" field</summary>
+    [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+    [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+    public void ClearEdition() {
+      edition_ = null;
+    }
+
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
     public override bool Equals(object other) {
@@ -666,6 +701,7 @@
       if (!object.Equals(Options, other.Options)) return false;
       if (!object.Equals(SourceCodeInfo, other.SourceCodeInfo)) return false;
       if (Syntax != other.Syntax) return false;
+      if (Edition != other.Edition) return false;
       return Equals(_unknownFields, other._unknownFields);
     }
 
@@ -685,6 +721,7 @@
       if (options_ != null) hash ^= Options.GetHashCode();
       if (sourceCodeInfo_ != null) hash ^= SourceCodeInfo.GetHashCode();
       if (HasSyntax) hash ^= Syntax.GetHashCode();
+      if (HasEdition) hash ^= Edition.GetHashCode();
       if (_unknownFields != null) {
         hash ^= _unknownFields.GetHashCode();
       }
@@ -730,6 +767,10 @@
         output.WriteRawTag(98);
         output.WriteString(Syntax);
       }
+      if (HasEdition) {
+        output.WriteRawTag(106);
+        output.WriteString(Edition);
+      }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(output);
       }
@@ -767,6 +808,10 @@
         output.WriteRawTag(98);
         output.WriteString(Syntax);
       }
+      if (HasEdition) {
+        output.WriteRawTag(106);
+        output.WriteString(Edition);
+      }
       if (_unknownFields != null) {
         _unknownFields.WriteTo(ref output);
       }
@@ -799,6 +844,9 @@
       if (HasSyntax) {
         size += 1 + pb::CodedOutputStream.ComputeStringSize(Syntax);
       }
+      if (HasEdition) {
+        size += 1 + pb::CodedOutputStream.ComputeStringSize(Edition);
+      }
       if (_unknownFields != null) {
         size += _unknownFields.CalculateSize();
       }
@@ -839,6 +887,9 @@
       if (other.HasSyntax) {
         Syntax = other.Syntax;
       }
+      if (other.HasEdition) {
+        Edition = other.Edition;
+      }
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
@@ -910,6 +961,10 @@
             Syntax = input.ReadString();
             break;
           }
+          case 106: {
+            Edition = input.ReadString();
+            break;
+          }
         }
       }
     #endif
@@ -981,6 +1036,10 @@
             Syntax = input.ReadString();
             break;
           }
+          case 106: {
+            Edition = input.ReadString();
+            break;
+          }
         }
       }
     }
@@ -6582,6 +6641,10 @@
 
     private bool mapEntry_;
     /// <summary>
+    /// NOTE: Do not set the option in .proto files. Always use the maps syntax
+    /// instead. The option should only be implicitly set by the proto compiler
+    /// parser.
+    ///
     /// Whether the message is an automatically generated map entry type for the
     /// maps field.
     ///
@@ -6599,10 +6662,6 @@
     /// use a native map in the target language to hold the keys and values.
     /// The reflection APIs in such implementations still need to work as
     /// if the field is a repeated message field.
-    ///
-    /// NOTE: Do not set the option in .proto files. Always use the maps syntax
-    /// instead. The option should only be implicitly set by the proto compiler
-    /// parser.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -7098,11 +7157,8 @@
     /// check its required fields, regardless of whether or not the message has
     /// been parsed.
     ///
-    /// As of 2021, lazy does no correctness checks on the byte stream during
-    /// parsing.  This may lead to crashes if and when an invalid byte stream is
-    /// finally parsed upon access.
-    ///
-    /// TODO(b/211906113):  Enable validation on lazy fields.
+    /// As of May 2022, lazy verifies the contents of the byte stream during
+    /// parsing.  An invalid byte stream will cause the overall parsing to fail.
     /// </summary>
     [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
     [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
@@ -10758,6 +10814,7 @@
           sourceFile_ = other.sourceFile_;
           begin_ = other.begin_;
           end_ = other.end_;
+          semantic_ = other.semantic_;
           _unknownFields = pb::UnknownFieldSet.Clone(other._unknownFields);
         }
 
@@ -10849,7 +10906,7 @@
         private int end_;
         /// <summary>
         /// Identifies the ending offset in bytes in the generated code that
-        /// relates to the identified offset. The end offset should be one past
+        /// relates to the identified object. The end offset should be one past
         /// the last relevant byte (so the length of the text = end - begin).
         /// </summary>
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
@@ -10874,6 +10931,33 @@
           _hasBits0 &= ~2;
         }
 
+        /// <summary>Field number for the "semantic" field.</summary>
+        public const int SemanticFieldNumber = 5;
+        private readonly static global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic SemanticDefaultValue = global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic.None;
+
+        private global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic semantic_;
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic Semantic {
+          get { if ((_hasBits0 & 4) != 0) { return semantic_; } else { return SemanticDefaultValue; } }
+          set {
+            _hasBits0 |= 4;
+            semantic_ = value;
+          }
+        }
+        /// <summary>Gets whether the "semantic" field is set</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public bool HasSemantic {
+          get { return (_hasBits0 & 4) != 0; }
+        }
+        /// <summary>Clears the value of the "semantic" field</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public void ClearSemantic() {
+          _hasBits0 &= ~4;
+        }
+
         [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
         [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
         public override bool Equals(object other) {
@@ -10893,6 +10977,7 @@
           if (SourceFile != other.SourceFile) return false;
           if (Begin != other.Begin) return false;
           if (End != other.End) return false;
+          if (Semantic != other.Semantic) return false;
           return Equals(_unknownFields, other._unknownFields);
         }
 
@@ -10904,6 +10989,7 @@
           if (HasSourceFile) hash ^= SourceFile.GetHashCode();
           if (HasBegin) hash ^= Begin.GetHashCode();
           if (HasEnd) hash ^= End.GetHashCode();
+          if (HasSemantic) hash ^= Semantic.GetHashCode();
           if (_unknownFields != null) {
             hash ^= _unknownFields.GetHashCode();
           }
@@ -10935,6 +11021,10 @@
             output.WriteRawTag(32);
             output.WriteInt32(End);
           }
+          if (HasSemantic) {
+            output.WriteRawTag(40);
+            output.WriteEnum((int) Semantic);
+          }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(output);
           }
@@ -10958,6 +11048,10 @@
             output.WriteRawTag(32);
             output.WriteInt32(End);
           }
+          if (HasSemantic) {
+            output.WriteRawTag(40);
+            output.WriteEnum((int) Semantic);
+          }
           if (_unknownFields != null) {
             _unknownFields.WriteTo(ref output);
           }
@@ -10978,6 +11072,9 @@
           if (HasEnd) {
             size += 1 + pb::CodedOutputStream.ComputeInt32Size(End);
           }
+          if (HasSemantic) {
+            size += 1 + pb::CodedOutputStream.ComputeEnumSize((int) Semantic);
+          }
           if (_unknownFields != null) {
             size += _unknownFields.CalculateSize();
           }
@@ -11000,6 +11097,9 @@
           if (other.HasEnd) {
             End = other.End;
           }
+          if (other.HasSemantic) {
+            Semantic = other.Semantic;
+          }
           _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
         }
 
@@ -11032,6 +11132,10 @@
                 End = input.ReadInt32();
                 break;
               }
+              case 40: {
+                Semantic = (global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic) input.ReadEnum();
+                break;
+              }
             }
           }
         #endif
@@ -11064,11 +11168,42 @@
                 End = input.ReadInt32();
                 break;
               }
+              case 40: {
+                Semantic = (global::Google.Protobuf.Reflection.GeneratedCodeInfo.Types.Annotation.Types.Semantic) input.ReadEnum();
+                break;
+              }
             }
           }
         }
         #endif
 
+        #region Nested types
+        /// <summary>Container for nested types declared in the Annotation message type.</summary>
+        [global::System.Diagnostics.DebuggerNonUserCodeAttribute]
+        [global::System.CodeDom.Compiler.GeneratedCode("protoc", null)]
+        public static partial class Types {
+          /// <summary>
+          /// Represents the identified object's effect on the element in the original
+          /// .proto file.
+          /// </summary>
+          public enum Semantic {
+            /// <summary>
+            /// There is no effect or the effect is indescribable.
+            /// </summary>
+            [pbr::OriginalName("NONE")] None = 0,
+            /// <summary>
+            /// The element is set or otherwise mutated.
+            /// </summary>
+            [pbr::OriginalName("SET")] Set = 1,
+            /// <summary>
+            /// An alias to the element is returned.
+            /// </summary>
+            [pbr::OriginalName("ALIAS")] Alias = 2,
+          }
+
+        }
+        #endregion
+
       }
 
     }
diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs
index b22048f..3c7fac2 100644
--- a/csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs
+++ b/csharp/src/Google.Protobuf/Reflection/DescriptorDeclaration.cs
@@ -30,11 +30,9 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
 using System.Linq;
-using System.Text;
 using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
 
 namespace Google.Protobuf.Reflection
diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
index 93f2fa9..5128ad9 100644
--- a/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
+++ b/csharp/src/Google.Protobuf/Reflection/DescriptorPool.cs
@@ -51,12 +51,11 @@
         private readonly IDictionary<ObjectIntPair<IDescriptor>, EnumValueDescriptor> enumValuesByNumber =
             new Dictionary<ObjectIntPair<IDescriptor>, EnumValueDescriptor>();
 
-        private readonly HashSet<FileDescriptor> dependencies;
+        private readonly HashSet<FileDescriptor> dependencies = new HashSet<FileDescriptor>();
 
         internal DescriptorPool(IEnumerable<FileDescriptor> dependencyFiles)
         {
-            dependencies = new HashSet<FileDescriptor>();
-            foreach (var dependencyFile in dependencyFiles)
+            foreach (FileDescriptor dependencyFile in dependencyFiles)
             {
                 dependencies.Add(dependencyFile);
                 ImportPublicDependencies(dependencyFile);
@@ -88,10 +87,8 @@
         /// or null if the symbol doesn't exist or has the wrong type</returns>
         internal T FindSymbol<T>(string fullName) where T : class
         {
-            IDescriptor result;
-            descriptorsByName.TryGetValue(fullName, out result);
-            T descriptor = result as T;
-            if (descriptor != null)
+            descriptorsByName.TryGetValue(fullName, out IDescriptor result);
+            if (result is T descriptor)
             {
                 return descriptor;
             }
@@ -131,10 +128,9 @@
                 name = fullName;
             }
 
-            IDescriptor old;
-            if (descriptorsByName.TryGetValue(fullName, out old))
+            if (descriptorsByName.TryGetValue(fullName, out IDescriptor old))
             {
-                if (!(old is PackageDescriptor))
+                if (old is not PackageDescriptor)
                 {
                     throw new DescriptorValidationException(file,
                                                             "\"" + name +
@@ -153,10 +149,9 @@
         internal void AddSymbol(IDescriptor descriptor)
         {
             ValidateSymbolName(descriptor);
-            String fullName = descriptor.FullName;
+            string fullName = descriptor.FullName;
 
-            IDescriptor old;
-            if (descriptorsByName.TryGetValue(fullName, out old))
+            if (descriptorsByName.TryGetValue(fullName, out IDescriptor old))
             {
                 int dotPos = fullName.LastIndexOf('.');
                 string message;
@@ -181,8 +176,7 @@
             descriptorsByName[fullName] = descriptor;
         }
 
-        private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$",
-                                                                  FrameworkPortability.CompiledRegexWhereAvailable);
+        private static readonly Regex ValidationRegex = new Regex("^[_A-Za-z][_A-Za-z0-9]*$", FrameworkPortability.CompiledRegexWhereAvailable);
 
         /// <summary>
         /// Verifies that the descriptor's name is valid (i.e. it contains
@@ -191,7 +185,7 @@
         /// <param name="descriptor"></param>
         private static void ValidateSymbolName(IDescriptor descriptor)
         {
-            if (descriptor.Name == "")
+            if (descriptor.Name.Length == 0)
             {
                 throw new DescriptorValidationException(descriptor, "Missing name.");
             }
@@ -208,15 +202,13 @@
         /// </summary>
         internal FieldDescriptor FindFieldByNumber(MessageDescriptor messageDescriptor, int number)
         {
-            FieldDescriptor ret;
-            fieldsByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(messageDescriptor, number), out ret);
+            fieldsByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(messageDescriptor, number), out FieldDescriptor ret);
             return ret;
         }
 
         internal EnumValueDescriptor FindEnumValueByNumber(EnumDescriptor enumDescriptor, int number)
         {
-            EnumValueDescriptor ret;
-            enumValuesByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(enumDescriptor, number), out ret);
+            enumValuesByNumber.TryGetValue(new ObjectIntPair<IDescriptor>(enumDescriptor, number), out EnumValueDescriptor ret);
             return ret;
         }
 
@@ -229,8 +221,7 @@
         {
             // for extensions, we use the extended type, otherwise we use the containing type
             ObjectIntPair<IDescriptor> key = new ObjectIntPair<IDescriptor>(field.Proto.HasExtendee ? field.ExtendeeType : field.ContainingType, field.FieldNumber);
-            FieldDescriptor old;
-            if (fieldsByNumber.TryGetValue(key, out old))
+            if (fieldsByNumber.TryGetValue(key, out FieldDescriptor old))
             {
                 throw new DescriptorValidationException(field, "Field number " + field.FieldNumber +
                                                                "has already been used in \"" +
diff --git a/csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs b/csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs
index 143671d..f48e8e1 100644
--- a/csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs
+++ b/csharp/src/Google.Protobuf/Reflection/DescriptorValidationException.cs
@@ -40,25 +40,16 @@
     /// </summary>
     public sealed class DescriptorValidationException : Exception
     {
-        private readonly String name;
-        private readonly string description;
-
         /// <value>
         /// The full name of the descriptor where the error occurred.
         /// </value>
-        public String ProblemSymbolName
-        {
-            get { return name; }
-        }
+        public string ProblemSymbolName { get; }
 
         /// <value>
         /// A human-readable description of the error. (The Message property
         /// is made up of the descriptor's name and this description.)
         /// </value>
-        public string Description
-        {
-            get { return description; }
-        }
+        public string Description { get; }
 
         internal DescriptorValidationException(IDescriptor problemDescriptor, string description) :
             base(problemDescriptor.FullName + ": " + description)
@@ -66,15 +57,15 @@
             // Note that problemDescriptor may be partially uninitialized, so we
             // don't want to expose it directly to the user.  So, we only provide
             // the name and the original proto.
-            name = problemDescriptor.FullName;
-            this.description = description;
+            ProblemSymbolName = problemDescriptor.FullName;
+            Description = description;
         }
 
         internal DescriptorValidationException(IDescriptor problemDescriptor, string description, Exception cause) :
             base(problemDescriptor.FullName + ": " + description, cause)
         {
-            name = problemDescriptor.FullName;
-            this.description = description;
+            ProblemSymbolName = problemDescriptor.FullName;
+            Description = description;
         }
     }
 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
index 3f2e1c4..a14cc1d 100644
--- a/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/EnumDescriptor.cs
@@ -41,17 +41,12 @@
     /// </summary>
     public sealed class EnumDescriptor : DescriptorBase
     {
-        private readonly EnumDescriptorProto proto;
-        private readonly MessageDescriptor containingType;
-        private readonly IList<EnumValueDescriptor> values;
-        private readonly Type clrType;
-
         internal EnumDescriptor(EnumDescriptorProto proto, FileDescriptor file, MessageDescriptor parent, int index, Type clrType)
             : base(file, file.ComputeFullName(parent, proto.Name), index)
         {
-            this.proto = proto;
-            this.clrType = clrType;
-            containingType = parent;
+            Proto = proto;
+            ClrType = clrType;
+            ContainingType = parent;
 
             if (proto.Value.Count == 0)
             {
@@ -60,13 +55,13 @@
                 throw new DescriptorValidationException(this, "Enums must contain at least one value.");
             }
 
-            values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value,
+            Values = DescriptorUtil.ConvertAndMakeReadOnly(proto.Value,
                                                            (value, i) => new EnumValueDescriptor(value, file, this, i));
 
             File.DescriptorPool.AddSymbol(this);
         }
 
-        internal EnumDescriptorProto Proto { get { return proto; } }
+        internal EnumDescriptorProto Proto { get; }
 
         /// <summary>
         /// Returns a clone of the underlying <see cref="EnumDescriptorProto"/> describing this enum.
@@ -79,39 +74,29 @@
         /// <summary>
         /// The brief name of the descriptor's target.
         /// </summary>
-        public override string Name { get { return proto.Name; } }
+        public override string Name => Proto.Name;
 
-        internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
-        {
-            switch (fieldNumber)
+        internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
+            fieldNumber switch
             {
-                case EnumDescriptorProto.ValueFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) Values;
-                default:
-                    return null;
-            }
-        }
+                EnumDescriptorProto.ValueFieldNumber => (IReadOnlyList<DescriptorBase>)Values,
+                _ => null,
+            };
 
         /// <summary>
         /// The CLR type for this enum. For generated code, this will be a CLR enum type.
         /// </summary>
-        public Type ClrType { get { return clrType; } }
+        public Type ClrType { get; }
 
         /// <value>
         /// If this is a nested type, get the outer descriptor, otherwise null.
         /// </value>
-        public MessageDescriptor ContainingType
-        {
-            get { return containingType; }
-        }
+        public MessageDescriptor ContainingType { get; }
 
         /// <value>
         /// An unmodifiable list of defined value descriptors for this enum.
         /// </value>
-        public IList<EnumValueDescriptor> Values
-        {
-            get { return values; }
-        }
+        public IList<EnumValueDescriptor> Values { get; }
 
         /// <summary>
         /// Finds an enum value by number. If multiple enum values have the
diff --git a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
index 50b26a4..7a0cce0 100644
--- a/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/EnumValueDescriptor.cs
@@ -40,20 +40,17 @@
     /// </summary>
     public sealed class EnumValueDescriptor : DescriptorBase
     {
-        private readonly EnumDescriptor enumDescriptor;
-        private readonly EnumValueDescriptorProto proto;
-
         internal EnumValueDescriptor(EnumValueDescriptorProto proto, FileDescriptor file,
                                      EnumDescriptor parent, int index)
             : base(file, parent.FullName + "." + proto.Name, index)
         {
-            this.proto = proto;
-            enumDescriptor = parent;
+            Proto = proto;
+            EnumDescriptor = parent;
             file.DescriptorPool.AddSymbol(this);
             file.DescriptorPool.AddEnumValueByNumber(this);
         }
 
-        internal EnumValueDescriptorProto Proto { get { return proto; } }
+        internal EnumValueDescriptorProto Proto { get; }
 
         /// <summary>
         /// Returns a clone of the underlying <see cref="EnumValueDescriptorProto"/> describing this enum value.
@@ -66,17 +63,17 @@
         /// <summary>
         /// Returns the name of the enum value described by this object.
         /// </summary>
-        public override string Name { get { return proto.Name; } }
+        public override string Name => Proto.Name;
 
         /// <summary>
         /// Returns the number associated with this enum value.
         /// </summary>
-        public int Number { get { return Proto.Number; } }
+        public int Number => Proto.Number;
 
         /// <summary>
         /// Returns the enum descriptor that this value is part of.
         /// </summary>
-        public EnumDescriptor EnumDescriptor { get { return enumDescriptor; } }
+        public EnumDescriptor EnumDescriptor { get; }
 
         /// <summary>
         /// The (possibly empty) set of custom options for this enum value.
diff --git a/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs
index ca874f9..1e10060 100644
--- a/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs
+++ b/csharp/src/Google.Protobuf/Reflection/ExtensionCollection.cs
@@ -107,8 +107,7 @@
             {
                 descriptor.CrossLink();
 
-                IList<FieldDescriptor> list;
-                if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out list))
+                if (!declarationOrder.TryGetValue(descriptor.ExtendeeType, out IList<FieldDescriptor> list))
                 {
                     list = new List<FieldDescriptor>();
                     declarationOrder.Add(descriptor.ExtendeeType, list);
diff --git a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
index 85b7d39..156025d 100644
--- a/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FieldAccessorBase.cs
@@ -42,15 +42,14 @@
     internal abstract class FieldAccessorBase : IFieldAccessor
     {
         private readonly Func<IMessage, object> getValueDelegate;
-        private readonly FieldDescriptor descriptor;
 
         internal FieldAccessorBase(PropertyInfo property, FieldDescriptor descriptor)
         {
-            this.descriptor = descriptor;
+            Descriptor = descriptor;
             getValueDelegate = ReflectionUtil.CreateFuncIMessageObject(property.GetGetMethod());
         }
 
-        public FieldDescriptor Descriptor { get { return descriptor; } }
+        public FieldDescriptor Descriptor { get; }
 
         public object GetValue(IMessage message)
         {
diff --git a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
index 84ad49d..e4fd7d2 100644
--- a/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FieldDescriptor.cs
@@ -176,47 +176,28 @@
         /// </summary>
         private static FieldType GetFieldTypeFromProtoType(FieldDescriptorProto.Types.Type type)
         {
-            switch (type)
+            return type switch
             {
-                case FieldDescriptorProto.Types.Type.Double:
-                    return FieldType.Double;
-                case FieldDescriptorProto.Types.Type.Float:
-                    return FieldType.Float;
-                case FieldDescriptorProto.Types.Type.Int64:
-                    return FieldType.Int64;
-                case FieldDescriptorProto.Types.Type.Uint64:
-                    return FieldType.UInt64;
-                case FieldDescriptorProto.Types.Type.Int32:
-                    return FieldType.Int32;
-                case FieldDescriptorProto.Types.Type.Fixed64:
-                    return FieldType.Fixed64;
-                case FieldDescriptorProto.Types.Type.Fixed32:
-                    return FieldType.Fixed32;
-                case FieldDescriptorProto.Types.Type.Bool:
-                    return FieldType.Bool;
-                case FieldDescriptorProto.Types.Type.String:
-                    return FieldType.String;
-                case FieldDescriptorProto.Types.Type.Group:
-                    return FieldType.Group;
-                case FieldDescriptorProto.Types.Type.Message:
-                    return FieldType.Message;
-                case FieldDescriptorProto.Types.Type.Bytes:
-                    return FieldType.Bytes;
-                case FieldDescriptorProto.Types.Type.Uint32:
-                    return FieldType.UInt32;
-                case FieldDescriptorProto.Types.Type.Enum:
-                    return FieldType.Enum;
-                case FieldDescriptorProto.Types.Type.Sfixed32:
-                    return FieldType.SFixed32;
-                case FieldDescriptorProto.Types.Type.Sfixed64:
-                    return FieldType.SFixed64;
-                case FieldDescriptorProto.Types.Type.Sint32:
-                    return FieldType.SInt32;
-                case FieldDescriptorProto.Types.Type.Sint64:
-                    return FieldType.SInt64;
-                default:
-                    throw new ArgumentException("Invalid type specified");
-            }
+                FieldDescriptorProto.Types.Type.Double => FieldType.Double,
+                FieldDescriptorProto.Types.Type.Float => FieldType.Float,
+                FieldDescriptorProto.Types.Type.Int64 => FieldType.Int64,
+                FieldDescriptorProto.Types.Type.Uint64 => FieldType.UInt64,
+                FieldDescriptorProto.Types.Type.Int32 => FieldType.Int32,
+                FieldDescriptorProto.Types.Type.Fixed64 => FieldType.Fixed64,
+                FieldDescriptorProto.Types.Type.Fixed32 => FieldType.Fixed32,
+                FieldDescriptorProto.Types.Type.Bool => FieldType.Bool,
+                FieldDescriptorProto.Types.Type.String => FieldType.String,
+                FieldDescriptorProto.Types.Type.Group => FieldType.Group,
+                FieldDescriptorProto.Types.Type.Message => FieldType.Message,
+                FieldDescriptorProto.Types.Type.Bytes => FieldType.Bytes,
+                FieldDescriptorProto.Types.Type.Uint32 => FieldType.UInt32,
+                FieldDescriptorProto.Types.Type.Enum => FieldType.Enum,
+                FieldDescriptorProto.Types.Type.Sfixed32 => FieldType.SFixed32,
+                FieldDescriptorProto.Types.Type.Sfixed64 => FieldType.SFixed64,
+                FieldDescriptorProto.Types.Type.Sint32 => FieldType.SInt32,
+                FieldDescriptorProto.Types.Type.Sint64 => FieldType.SInt64,
+                _ => throw new ArgumentException("Invalid type specified"),
+            };
         }
 
         /// <summary>
@@ -391,11 +372,11 @@
 
                 if (fieldType == FieldType.Message || fieldType == FieldType.Group)
                 {
-                    if (!(typeDescriptor is MessageDescriptor))
+                    if (typeDescriptor is not MessageDescriptor m)
                     {
                         throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not a message type.");
                     }
-                    messageType = (MessageDescriptor) typeDescriptor;
+                    messageType = m;
 
                     if (Proto.HasDefaultValue)
                     {
@@ -404,11 +385,11 @@
                 }
                 else if (fieldType == FieldType.Enum)
                 {
-                    if (!(typeDescriptor is EnumDescriptor))
+                    if (typeDescriptor is not EnumDescriptor e)
                     {
                         throw new DescriptorValidationException(this, $"\"{Proto.TypeName}\" is not an enum type.");
                     }
-                    enumType = (EnumDescriptor) typeDescriptor;
+                    enumType = e;
                 }
                 else
                 {
diff --git a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
index d7701da..cb711de 100644
--- a/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/FileDescriptor.cs
@@ -35,7 +35,6 @@
 using System;
 using System.Collections.Generic;
 using System.Collections.ObjectModel;
-using System.Diagnostics;
 using System.Linq;
 using System.Threading;
 using static Google.Protobuf.Reflection.SourceCodeInfo.Types;
@@ -173,25 +172,18 @@
             return list[index];
         }
 
-        private IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
-        {
-            switch (fieldNumber)
+        private IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
+            fieldNumber switch
             {
-                case FileDescriptorProto.ServiceFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) Services;
-                case FileDescriptorProto.MessageTypeFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) MessageTypes;
-                case FileDescriptorProto.EnumTypeFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) EnumTypes;
-                default:
-                    return null;
-            }
-        }
+                FileDescriptorProto.ServiceFieldNumber => (IReadOnlyList<DescriptorBase>)Services,
+                FileDescriptorProto.MessageTypeFieldNumber => (IReadOnlyList<DescriptorBase>)MessageTypes,
+                FileDescriptorProto.EnumTypeFieldNumber => (IReadOnlyList<DescriptorBase>)EnumTypes,
+                _ => null,
+            };
 
         internal DescriptorDeclaration GetDeclaration(IDescriptor descriptor)
         {
-            DescriptorDeclaration declaration;
-            declarations.Value.TryGetValue(descriptor, out declaration);
+            declarations.Value.TryGetValue(descriptor, out DescriptorDeclaration declaration);
             return declaration;
         }
 
@@ -227,8 +219,7 @@
                     throw new DescriptorValidationException(@this, "Invalid public dependency index.");
                 }
                 string name = proto.Dependency[index];
-                FileDescriptor file;
-                if (!nameToFileMap.TryGetValue(name, out file))
+                if (!nameToFileMap.TryGetValue(name, out FileDescriptor file))
                 {
                     if (!allowUnknownDependencies)
                     {
@@ -332,7 +323,7 @@
         /// <param name="name">The unqualified type name to look for.</param>
         /// <typeparam name="T">The type of descriptor to look for</typeparam>
         /// <returns>The type's descriptor, or null if not found.</returns>
-        public T FindTypeByName<T>(String name)
+        public T FindTypeByName<T>(string name)
             where T : class, IDescriptor
         {
             // Don't allow looking up nested types.  This will make optimization
@@ -507,8 +498,7 @@
                 var dependencies = new List<FileDescriptor>();
                 foreach (var dependencyName in proto.Dependency)
                 {
-                    FileDescriptor dependency;
-                    if (!descriptorsByName.TryGetValue(dependencyName, out dependency))
+                    if (!descriptorsByName.TryGetValue(dependencyName, out FileDescriptor dependency))
                     {
                         throw new ArgumentException($"Dependency missing: {dependencyName}");
                     }
@@ -565,7 +555,7 @@
         /// <value>
         /// The file descriptor for <c>descriptor.proto</c>.
         /// </value>
-        public static FileDescriptor DescriptorProtoFileDescriptor { get { return DescriptorReflection.Descriptor; } }
+        public static FileDescriptor DescriptorProtoFileDescriptor => DescriptorReflection.Descriptor;
 
         /// <summary>
         /// The (possibly empty) set of custom options for this file.
diff --git a/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs
index d0a495b..dbf16c6 100644
--- a/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs
+++ b/csharp/src/Google.Protobuf/Reflection/GeneratedClrTypeInfo.cs
@@ -29,6 +29,7 @@
 // (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.Diagnostics.CodeAnalysis;
 
@@ -57,7 +58,7 @@
         /// Irrelevant for file descriptors; the CLR type for the message for message descriptors.
         /// </summary>
         [DynamicallyAccessedMembers(MessageAccessibility)]
-        public Type ClrType { get; private set; }
+        public Type ClrType { get; }
 
         /// <summary>
         /// Irrelevant for file descriptors; the parser for message descriptors.
diff --git a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
index 40a6ff8..f2bb61c 100644
--- a/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MessageDescriptor.cs
@@ -36,10 +36,6 @@
 using System.Diagnostics.CodeAnalysis;
 using System.Linq;
 using System.Reflection;
-#if NET35
-// Needed for ReadOnlyDictionary, which does not exist in .NET 3.5
-using Google.Protobuf.Collections;
-#endif
 
 namespace Google.Protobuf.Reflection
 {
@@ -134,20 +130,14 @@
         /// </summary>
         public override string Name => Proto.Name;
 
-        internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
-        {
-            switch (fieldNumber)
+        internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
+            fieldNumber switch
             {
-                case DescriptorProto.FieldFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) fieldsInDeclarationOrder;
-                case DescriptorProto.NestedTypeFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) NestedTypes;
-                case DescriptorProto.EnumTypeFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) EnumTypes;
-                default:
-                    return null;
-            }
-        }
+                DescriptorProto.FieldFieldNumber => (IReadOnlyList<DescriptorBase>)fieldsInDeclarationOrder,
+                DescriptorProto.NestedTypeFieldNumber => (IReadOnlyList<DescriptorBase>)NestedTypes,
+                DescriptorProto.EnumTypeFieldNumber => (IReadOnlyList<DescriptorBase>)EnumTypes,
+                _ => null,
+            };
 
         internal DescriptorProto Proto { get; }
 
@@ -276,7 +266,7 @@
         /// </summary>
         /// <param name="name">The unqualified name of the field (e.g. "foo").</param>
         /// <returns>The field's descriptor, or null if not found.</returns>
-        public FieldDescriptor FindFieldByName(String name) => File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name);
+        public FieldDescriptor FindFieldByName(string name) => File.DescriptorPool.FindSymbol<FieldDescriptor>(FullName + "." + name);
 
         /// <summary>
         /// Finds a field by field number.
diff --git a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
index f5ecf2e..4f0ea43 100644
--- a/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/MethodDescriptor.cs
@@ -40,35 +40,31 @@
     /// </summary>
     public sealed class MethodDescriptor : DescriptorBase
     {
-        private readonly MethodDescriptorProto proto;
-        private readonly ServiceDescriptor service;
-        private MessageDescriptor inputType;
-        private MessageDescriptor outputType;
 
         /// <value>
         /// The service this method belongs to.
         /// </value>
-        public ServiceDescriptor Service { get { return service; } }
+        public ServiceDescriptor Service { get; }
 
         /// <value>
         /// The method's input type.
         /// </value>
-        public MessageDescriptor InputType { get { return inputType; } }
+        public MessageDescriptor InputType { get; private set; }
 
         /// <value>
         /// The method's input type.
         /// </value>
-        public MessageDescriptor OutputType { get { return outputType; } }
+        public MessageDescriptor OutputType { get; private set; }
 
         /// <value>
         /// Indicates if client streams multiple requests.
         /// </value>
-        public bool IsClientStreaming { get { return proto.ClientStreaming; } }
+        public bool IsClientStreaming => Proto.ClientStreaming;
 
         /// <value>
         /// Indicates if server streams multiple responses.
         /// </value>
-        public bool IsServerStreaming { get { return proto.ServerStreaming; } }
+        public bool IsServerStreaming => Proto.ServerStreaming;
 
         /// <summary>
         /// The (possibly empty) set of custom options for this method.
@@ -91,7 +87,7 @@
         public T GetOption<T>(Extension<MethodOptions, T> extension)
         {
             var value = Proto.Options.GetExtension(extension);
-            return value is IDeepCloneable<T> ? (value as IDeepCloneable<T>).Clone() : value;
+            return value is IDeepCloneable<T> c ? c.Clone() : value;
         }
 
         /// <summary>
@@ -107,12 +103,12 @@
                                   ServiceDescriptor parent, int index)
             : base(file, parent.FullName + "." + proto.Name, index)
         {
-            this.proto = proto;
-            service = parent;
+            Proto = proto;
+            Service = parent;
             file.DescriptorPool.AddSymbol(this);
         }
 
-        internal MethodDescriptorProto Proto { get { return proto; } }
+        internal MethodDescriptorProto Proto { get; private set; }
 
         /// <summary>
         /// Returns a clone of the underlying <see cref="MethodDescriptorProto"/> describing this method.
@@ -125,23 +121,23 @@
         /// <summary>
         /// The brief name of the descriptor's target.
         /// </summary>
-        public override string Name { get { return proto.Name; } }
+        public override string Name => Proto.Name;
 
         internal void CrossLink()
         {
             IDescriptor lookup = File.DescriptorPool.LookupSymbol(Proto.InputType, this);
-            if (!(lookup is MessageDescriptor))
+            if (lookup is not MessageDescriptor inpoutType)
             {
                 throw new DescriptorValidationException(this, "\"" + Proto.InputType + "\" is not a message type.");
             }
-            inputType = (MessageDescriptor) lookup;
+            InputType = inpoutType;
 
             lookup = File.DescriptorPool.LookupSymbol(Proto.OutputType, this);
-            if (!(lookup is MessageDescriptor))
+            if (lookup is not MessageDescriptor outputType)
             {
                 throw new DescriptorValidationException(this, "\"" + Proto.OutputType + "\" is not a message type.");
             }
-            outputType = (MessageDescriptor) lookup;
+            OutputType = outputType;
         }
     }
 }
diff --git a/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs b/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs
index 63f5228..880716a 100644
--- a/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs
+++ b/csharp/src/Google.Protobuf/Reflection/OriginalNameAttribute.cs
@@ -60,6 +60,5 @@
             Name = ProtoPreconditions.CheckNotNull(name, nameof(name));
             PreferredAlias = true;
         }
-
     }
 }
diff --git a/csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs
index e547d83..0b6de81 100644
--- a/csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/PackageDescriptor.cs
@@ -39,30 +39,15 @@
     /// </summary>
     internal sealed class PackageDescriptor : IDescriptor
     {
-        private readonly string name;
-        private readonly string fullName;
-        private readonly FileDescriptor file;
-
         internal PackageDescriptor(string name, string fullName, FileDescriptor file)
         {
-            this.file = file;
-            this.fullName = fullName;
-            this.name = name;
+            File = file;
+            FullName = fullName;
+            Name = name;
         }
 
-        public string Name
-        {
-            get { return name; }
-        }
-
-        public string FullName
-        {
-            get { return fullName; }
-        }
-
-        public FileDescriptor File
-        {
-            get { return file; }
-        }
+        public string Name { get; }
+        public string FullName { get; }
+        public FileDescriptor File { get; }
     }
 }
\ No newline at end of file
diff --git a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
index 73efcc2..2a6afdb 100644
--- a/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
+++ b/csharp/src/Google.Protobuf/Reflection/ReflectionUtil.cs
@@ -221,20 +221,18 @@
 
             public object GetExtension(IMessage message)
             {
-                if (!(message is T1))
+                if (message is not T1 extensionMessage)
                 {
                     throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
                 }
 
-                T1 extensionMessage = (T1)message;
-
-                if (extension is Extension<T1, T3>)
+                if (extension is Extension<T1, T3> ext13)
                 {
-                    return extensionMessage.GetExtension(extension as Extension<T1, T3>);
+                    return extensionMessage.GetExtension(ext13);
                 }
-                else if (extension is RepeatedExtension<T1, T3>)
+                else if (extension is RepeatedExtension<T1, T3> repeatedExt13)
                 {
-                    return extensionMessage.GetOrInitializeExtension(extension as RepeatedExtension<T1, T3>);
+                    return extensionMessage.GetOrInitializeExtension(repeatedExt13);
                 }
                 else
                 {
@@ -244,16 +242,14 @@
 
             public bool HasExtension(IMessage message)
             {
-                if (!(message is T1))
+                if (message is not T1 extensionMessage)
                 {
                     throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
                 }
 
-                T1 extensionMessage = (T1)message;
-
-                if (extension is Extension<T1, T3>)
+                if (extension is Extension<T1, T3> ext13)
                 {
-                    return extensionMessage.HasExtension(extension as Extension<T1, T3>);
+                    return extensionMessage.HasExtension(ext13);
                 }
                 else if (extension is RepeatedExtension<T1, T3>)
                 {
@@ -267,16 +263,14 @@
 
             public void SetExtension(IMessage message, object value)
             {
-                if (!(message is T1))
+                if (message is not T1 extensionMessage)
                 {
                     throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
                 }
 
-                T1 extensionMessage = (T1)message;
-
-                if (extension is Extension<T1, T3>)
+                if (extension is Extension<T1, T3> ext13)
                 {
-                    extensionMessage.SetExtension(extension as Extension<T1, T3>, (T3)value);
+                    extensionMessage.SetExtension(ext13, (T3)value);
                 }
                 else if (extension is RepeatedExtension<T1, T3>)
                 {
@@ -290,20 +284,18 @@
 
             public void ClearExtension(IMessage message)
             {
-                if (!(message is T1))
+                if (message is not T1 extensionMessage)
                 {
                     throw new InvalidCastException("Cannot access extension on message that isn't IExtensionMessage");
                 }
 
-                T1 extensionMessage = (T1)message;
-
-                if (extension is Extension<T1, T3>)
+                if (extension is Extension<T1, T3> ext13)
                 {
-                    extensionMessage.ClearExtension(extension as Extension<T1, T3>);
+                    extensionMessage.ClearExtension(ext13);
                 }
-                else if (extension is RepeatedExtension<T1, T3>)
+                else if (extension is RepeatedExtension<T1, T3> repeatedExt13)
                 {
-                    extensionMessage.GetExtension(extension as RepeatedExtension<T1, T3>).Clear();
+                    extensionMessage.GetExtension(repeatedExt13).Clear();
                 }
                 else
                 {
diff --git a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
index afb4a69..2073be3 100644
--- a/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/RepeatedFieldAccessor.cs
@@ -60,6 +60,5 @@
         {
             throw new InvalidOperationException("SetValue is not implemented for repeated fields");
         }
-
     }
 }
diff --git a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
index 944ea11..55d812b 100644
--- a/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/ServiceDescriptor.cs
@@ -33,7 +33,6 @@
 using Google.Protobuf.Collections;
 using System;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
 
 namespace Google.Protobuf.Reflection
 {
@@ -42,14 +41,11 @@
     /// </summary>
     public sealed class ServiceDescriptor : DescriptorBase
     {
-        private readonly ServiceDescriptorProto proto;
-        private readonly IList<MethodDescriptor> methods;
-
         internal ServiceDescriptor(ServiceDescriptorProto proto, FileDescriptor file, int index)
             : base(file, file.ComputeFullName(null, proto.Name), index)
         {
-            this.proto = proto;
-            methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method,
+            Proto = proto;
+            Methods = DescriptorUtil.ConvertAndMakeReadOnly(proto.Method,
                                                             (method, i) => new MethodDescriptor(method, file, this, i));
 
             file.DescriptorPool.AddSymbol(this);
@@ -58,20 +54,16 @@
         /// <summary>
         /// The brief name of the descriptor's target.
         /// </summary>
-        public override string Name { get { return proto.Name; } }
+        public override string Name => Proto.Name;
 
-        internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber)
-        {
-            switch (fieldNumber)
+        internal override IReadOnlyList<DescriptorBase> GetNestedDescriptorListForField(int fieldNumber) =>
+            fieldNumber switch
             {
-                case ServiceDescriptorProto.MethodFieldNumber:
-                    return (IReadOnlyList<DescriptorBase>) methods;
-                default:
-                    return null;
-            }
-        }
+                ServiceDescriptorProto.MethodFieldNumber => (IReadOnlyList<DescriptorBase>)Methods,
+                _ => null,
+            };
 
-        internal ServiceDescriptorProto Proto { get { return proto; } }
+        internal ServiceDescriptorProto Proto { get; }
 
         /// <summary>
         /// Returns a clone of the underlying <see cref="ServiceDescriptorProto"/> describing this service.
@@ -84,20 +76,15 @@
         /// <value>
         /// An unmodifiable list of methods in this service.
         /// </value>
-        public IList<MethodDescriptor> Methods
-        {
-            get { return methods; }
-        }
+        public IList<MethodDescriptor> Methods { get; }
 
         /// <summary>
         /// Finds a method by name.
         /// </summary>
         /// <param name="name">The unqualified name of the method (e.g. "Foo").</param>
         /// <returns>The method's descriptor, or null if not found.</returns>
-        public MethodDescriptor FindMethodByName(String name)
-        {
-            return File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name);
-        }
+        public MethodDescriptor FindMethodByName(string name) =>
+            File.DescriptorPool.FindSymbol<MethodDescriptor>(FullName + "." + name);
 
         /// <summary>
         /// The (possibly empty) set of custom options for this service.
@@ -134,7 +121,7 @@
 
         internal void CrossLink()
         {
-            foreach (MethodDescriptor method in methods)
+            foreach (MethodDescriptor method in Methods)
             {
                 method.CrossLink();
             }
diff --git a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
index ac35e72..284effe 100644
--- a/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
+++ b/csharp/src/Google.Protobuf/Reflection/SingleFieldAccessor.cs
@@ -31,7 +31,6 @@
 #endregion
 
 using System;
-using System.Diagnostics;
 using System.Diagnostics.CodeAnalysis;
 using System.Reflection;
 using Google.Protobuf.Compatibility;
@@ -108,7 +107,7 @@
             // 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"); };
+                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.
                 object defaultValue = GetDefaultValue(descriptor);
@@ -116,42 +115,21 @@
             }
         }
 
-        private static object GetDefaultValue(FieldDescriptor descriptor)
-        {
-            switch (descriptor.FieldType)
+        private static object GetDefaultValue(FieldDescriptor descriptor) =>
+            descriptor.FieldType switch
             {
-                case FieldType.Bool:
-                    return false;
-                case FieldType.Bytes:
-                    return ByteString.Empty;
-                case FieldType.String:
-                    return "";
-                case FieldType.Double:
-                    return 0.0;
-                case FieldType.SInt32:
-                case FieldType.Int32:
-                case FieldType.SFixed32:
-                case FieldType.Enum:
-                    return 0;
-                case FieldType.Fixed32:
-                case FieldType.UInt32:
-                    return (uint)0;
-                case FieldType.Fixed64:
-                case FieldType.UInt64:
-                    return 0UL;
-                case FieldType.SFixed64:
-                case FieldType.Int64:
-                case FieldType.SInt64:
-                    return 0L;
-                case FieldType.Float:
-                    return 0f;
-                case FieldType.Message:
-                case FieldType.Group: // Never expect to get this, but...
-                    return null;
-                default:
-                    throw new ArgumentException("Invalid field type");
-            }
-        }
+                FieldType.Bool => false,
+                FieldType.Bytes => ByteString.Empty,
+                FieldType.String => "",
+                FieldType.Double => 0.0,
+                FieldType.SInt32 or FieldType.Int32 or FieldType.SFixed32 or FieldType.Enum => 0,
+                FieldType.Fixed32 or FieldType.UInt32 => (uint)0,
+                FieldType.Fixed64 or FieldType.UInt64 => 0UL,
+                FieldType.SFixed64 or FieldType.Int64 or FieldType.SInt64 => 0L,
+                FieldType.Float => 0f,
+                FieldType.Message or FieldType.Group => null,
+                _ => throw new ArgumentException("Invalid field type"),
+            };
 
         public override void Clear(IMessage message) => clearDelegate(message);
         public override bool HasValue(IMessage message) => hasDelegate(message);
diff --git a/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs b/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs
index e94e3e6..222bc7e 100644
--- a/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs
+++ b/csharp/src/Google.Protobuf/Reflection/TypeRegistry.cs
@@ -29,6 +29,7 @@
 // (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.Collections.Generic;
 using System.Linq;
 
@@ -60,9 +61,8 @@
         /// if there is no such message descriptor.</returns>
         public MessageDescriptor Find(string fullName)
         {
-            MessageDescriptor ret;
             // Ignore the return value as ret will end up with the right value either way.
-            fullNameToMessageMap.TryGetValue(fullName, out ret);
+            fullNameToMessageMap.TryGetValue(fullName, out MessageDescriptor ret);
             return ret;
         }
 
diff --git a/csharp/src/Google.Protobuf/UnknownField.cs b/csharp/src/Google.Protobuf/UnknownField.cs
index 4793a64..abec108 100644
--- a/csharp/src/Google.Protobuf/UnknownField.cs
+++ b/csharp/src/Google.Protobuf/UnknownField.cs
@@ -30,9 +30,7 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 #endregion
 
-using System;
 using System.Collections.Generic;
-using System.Collections.ObjectModel;
 using Google.Protobuf.Collections;
 
 namespace Google.Protobuf
@@ -73,13 +71,12 @@
             {
                 return true;
             }
-            UnknownField otherField = other as UnknownField;
-            return otherField != null
-                   && Lists.Equals(varintList, otherField.varintList)
-                   && Lists.Equals(fixed32List, otherField.fixed32List)
-                   && Lists.Equals(fixed64List, otherField.fixed64List)
-                   && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
-                   && Lists.Equals(groupList, otherField.groupList);
+            return other is UnknownField otherField
+                && Lists.Equals(varintList, otherField.varintList)
+                && Lists.Equals(fixed32List, otherField.fixed32List)
+                && Lists.Equals(fixed64List, otherField.fixed64List)
+                && Lists.Equals(lengthDelimitedList, otherField.lengthDelimitedList)
+                && Lists.Equals(groupList, otherField.groupList);
         }
 
         /// <summary>
diff --git a/csharp/src/Google.Protobuf/UnknownFieldSet.cs b/csharp/src/Google.Protobuf/UnknownFieldSet.cs
index 9888dd1..b97eb5e 100644
--- a/csharp/src/Google.Protobuf/UnknownFieldSet.cs
+++ b/csharp/src/Google.Protobuf/UnknownFieldSet.cs
@@ -32,9 +32,7 @@
 
 using System;
 using System.Collections.Generic;
-using System.IO;
 using System.Security;
-using Google.Protobuf.Reflection;
 
 namespace Google.Protobuf
 {
@@ -49,14 +47,13 @@
     /// </summary>
     public sealed partial class UnknownFieldSet
     {
-        private readonly IDictionary<int, UnknownField> fields;
+        private readonly IDictionary<int, UnknownField> fields = new Dictionary<int, UnknownField>();
 
         /// <summary>
         /// Creates a new UnknownFieldSet.
         /// </summary>
         internal UnknownFieldSet()
         {
-            this.fields = new Dictionary<int, UnknownField>();
         }
 
         /// <summary>
@@ -125,8 +122,7 @@
             }
             foreach (KeyValuePair<int, UnknownField> leftEntry in fields)
             {
-                UnknownField rightValue;
-                if (!otherFields.TryGetValue(leftEntry.Key, out rightValue))
+                if (!otherFields.TryGetValue(leftEntry.Key, out UnknownField rightValue))
                 {
                     return false;
                 }
@@ -170,8 +166,7 @@
                 return null;
             }
 
-            UnknownField existing;
-            if (fields.TryGetValue(number, out existing))
+            if (fields.TryGetValue(number, out UnknownField existing))
             {
                 return existing;
             }
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Any.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Any.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Any.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Any.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
index 5e7b6d5..04b64ab 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/AnyPartial.cs
@@ -112,7 +112,7 @@
             T target = new T();
             if (GetTypeName(TypeUrl) != target.Descriptor.FullName)
             {
-                result = default(T); // Can't use null as there's no class constraint, but this always *will* be null in real usage.
+                result = default; // Can't use null as there's no class constraint, but this always *will* be null in real usage.
                 return false;
             }
             target.MergeFrom(Value);
@@ -121,6 +121,26 @@
         }
 
         /// <summary>
+        /// Attempts to unpack the content of this Any message into one of the message types
+        /// in the given type registry, based on the type URL.
+        /// </summary>
+        /// <param name="registry">The type registry to consult for messages.</param>
+        /// <returns>The unpacked message, or <c>null</c> if no matching message was found.</returns>
+        public IMessage Unpack(TypeRegistry registry)
+        {
+            string typeName = GetTypeName(TypeUrl);
+            MessageDescriptor descriptor = registry.Find(typeName);
+            if (descriptor == null)
+            {
+                return null;
+            }
+
+            var message = descriptor.Parser.CreateTemplate();
+            message.MergeFrom(Value);
+            return message;
+        }
+
+        /// <summary>
         /// Packs the specified message into an Any message using a type URL prefix of "type.googleapis.com".
         /// </summary>
         /// <param name="message">The message to pack.</param>
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Api.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Api.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Api.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Api.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Duration.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Duration.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Duration.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
index 9a468fc..cdf3c31 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/DurationPartial.cs
@@ -38,7 +38,7 @@
 {
     // Manually-written partial class for the Duration well-known type,
     // providing a conversion to TimeSpan and convenience operators.
-    public partial class Duration : ICustomDiagnosticMessage
+    public partial class Duration : ICustomDiagnosticMessage, IComparable<Duration>
     {
         /// <summary>
         /// The number of nanoseconds in a second.
@@ -266,5 +266,26 @@
                 }
             }
         }
+
+
+        /// <summary>
+        /// Given another duration, returns 0 if the durations are equivalent, -1 if this duration is shorter than the other, and 1 otherwise.
+        /// </summary>
+        /// <remarks>
+        /// This method expects that both durations are normalized; that is, that the values of <see cref="Seconds"/>
+        /// and <see cref="Nanos"/> are within the documented bounds.
+        /// If either value is not normalized, the results of this method are unspecified.
+        /// </remarks>
+        /// <param name="other">The duration to compare with this object.</param>
+        /// <returns>An integer indicating whether this duration is shorter or longer than <paramref name="other"/>.</returns>
+        public int CompareTo(Duration other)
+        {
+            return other == null ? 1
+                : Seconds < other.Seconds ? -1
+                : Seconds > other.Seconds ? 1
+                : Nanos < other.Nanos ? -1
+                : Nanos > other.Nanos ? 1
+                : 0;
+        }
     }
 }
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Empty.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Empty.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Empty.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/FieldMask.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
index 58a33cb..dd00e2d 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/FieldMaskPartial.cs
@@ -63,12 +63,7 @@
             if (firstInvalid == null)
             {
                 var writer = new StringWriter();
-#if NET35
-                var query = paths.Select(JsonFormatter.ToJsonName);
-                JsonFormatter.WriteString(writer, string.Join(",", query.ToArray()));
-#else
                 JsonFormatter.WriteString(writer, string.Join(",", paths.Select(JsonFormatter.ToJsonName)));
-#endif
                 return writer.ToString();
             }
             else
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs b/csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/SourceContext.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.pb.cs
similarity index 99%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Struct.pb.cs
index 8c1eec5..aa25686 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/Struct.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/Struct.pb.cs
@@ -212,7 +212,7 @@
       if (other == null) {
         return;
       }
-      fields_.Add(other.fields_);
+      fields_.MergeFrom(other.fields_);
       _unknownFields = pb::UnknownFieldSet.MergeFrom(_unknownFields, other._unknownFields);
     }
 
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Timestamp.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
index 2f5172f..c52147f 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/TimestampPartial.cs
@@ -59,8 +59,8 @@
         /// <returns>The difference between the two specified timestamps.</returns>
         public static Duration operator -(Timestamp lhs, Timestamp rhs)
         {
-            ProtoPreconditions.CheckNotNull(lhs, "lhs");
-            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            ProtoPreconditions.CheckNotNull(lhs, nameof(lhs));
+            ProtoPreconditions.CheckNotNull(rhs, nameof(rhs));
             checked
             {
                 return Duration.Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos);
@@ -75,8 +75,8 @@
         /// <returns>The result of adding the duration to the timestamp.</returns>
         public static Timestamp operator +(Timestamp lhs, Duration rhs)
         {
-            ProtoPreconditions.CheckNotNull(lhs, "lhs");
-            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            ProtoPreconditions.CheckNotNull(lhs, nameof(lhs));
+            ProtoPreconditions.CheckNotNull(rhs, nameof(rhs));
             checked
             {
                 return Normalize(lhs.Seconds + rhs.Seconds, lhs.Nanos + rhs.Nanos);
@@ -91,8 +91,8 @@
         /// <returns>The result of subtracting the duration from the timestamp.</returns>
         public static Timestamp operator -(Timestamp lhs, Duration rhs)
         {
-            ProtoPreconditions.CheckNotNull(lhs, "lhs");
-            ProtoPreconditions.CheckNotNull(rhs, "rhs");
+            ProtoPreconditions.CheckNotNull(lhs, nameof(lhs));
+            ProtoPreconditions.CheckNotNull(rhs, nameof(rhs));
             checked
             {
                 return Normalize(lhs.Seconds - rhs.Seconds, lhs.Nanos - rhs.Nanos);
@@ -308,7 +308,7 @@
         /// <returns>true if the two timestamps refer to the same nanosecond</returns>
         public static bool operator ==(Timestamp a, Timestamp b)
         {
-            return ReferenceEquals(a, b) || (ReferenceEquals(a, null) ? (ReferenceEquals(b, null) ? true : false) : a.Equals(b));
+            return ReferenceEquals(a, b) || (a is null ? (b is null) : a.Equals(b));
         }
 
         /// <summary>
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Type.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Type.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Type.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Type.pb.cs
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs b/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs
index d34b560..a6846e7 100644
--- a/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs
+++ b/csharp/src/Google.Protobuf/WellKnownTypes/ValuePartial.cs
@@ -41,7 +41,7 @@
         /// <returns>A newly-created Value message with the given value.</returns>
         public static Value ForString(string value)
         {
-            ProtoPreconditions.CheckNotNull(value, "value");
+            ProtoPreconditions.CheckNotNull(value, nameof(value));
             return new Value { StringValue = value };
         }
 
@@ -81,7 +81,7 @@
         /// <returns>A newly-created Value message an initial list value.</returns>
         public static Value ForList(params Value[] values)
         {
-            ProtoPreconditions.CheckNotNull(values, "values");
+            ProtoPreconditions.CheckNotNull(values, nameof(values));
             return new Value { ListValue = new ListValue { Values = { values } } };
         }
 
@@ -92,7 +92,7 @@
         /// <returns>A newly-created Value message an initial struct value.</returns>
         public static Value ForStruct(Struct value)
         {
-            ProtoPreconditions.CheckNotNull(value, "value");
+            ProtoPreconditions.CheckNotNull(value, nameof(value));
             return new Value { StructValue = value };
         }
     }
diff --git a/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs b/csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.pb.cs
similarity index 100%
rename from csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs
rename to csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.pb.cs
diff --git a/csharp/src/Google.Protobuf/WriteBufferHelper.cs b/csharp/src/Google.Protobuf/WriteBufferHelper.cs
index f2a59bc..9230aa6 100644
--- a/csharp/src/Google.Protobuf/WriteBufferHelper.cs
+++ b/csharp/src/Google.Protobuf/WriteBufferHelper.cs
@@ -32,7 +32,6 @@
 
 using System;
 using System.Buffers;
-using System.IO;
 using System.Runtime.CompilerServices;
 using System.Security;
 
diff --git a/csharp/src/Google.Protobuf/WriteContext.cs b/csharp/src/Google.Protobuf/WriteContext.cs
index e822e1d..082c20e 100644
--- a/csharp/src/Google.Protobuf/WriteContext.cs
+++ b/csharp/src/Google.Protobuf/WriteContext.cs
@@ -32,14 +32,8 @@
 
 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
 {
@@ -101,166 +95,112 @@
         /// 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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        public void WriteSInt64(long value) => WritingPrimitives.WriteSInt64(ref buffer, ref state, value);
 
         /// <summary>
         /// Writes a length (in bytes) for length-delimited data.
@@ -269,48 +209,33 @@
         /// 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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        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);
-        }
+        public void WriteRawTag(byte b1, byte b2) => WritingPrimitives.WriteRawTag(ref buffer, ref state, b1, b2);
 
         /// <summary>
         /// Writes the given three-byte tag.
@@ -318,10 +243,7 @@
         /// <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);
-        }
+        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.
@@ -330,10 +252,7 @@
         /// <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);
-        }
+        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.
@@ -343,20 +262,11 @@
         /// <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);
-        }
+        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 Flush() => WriteBufferHelper.Flush(ref buffer, ref state);
 
-        internal void CheckNoSpaceLeft()
-        {
-            WriteBufferHelper.CheckNoSpaceLeft(ref state);
-        }
+        internal void CheckNoSpaceLeft() => WriteBufferHelper.CheckNoSpaceLeft(ref state);
 
         internal void CopyStateTo(CodedOutputStream output)
         {
diff --git a/csharp/src/Google.Protobuf/WriterInternalState.cs b/csharp/src/Google.Protobuf/WriterInternalState.cs
index a779305..ea4515a 100644
--- a/csharp/src/Google.Protobuf/WriterInternalState.cs
+++ b/csharp/src/Google.Protobuf/WriterInternalState.cs
@@ -30,20 +30,8 @@
 // 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
     {
diff --git a/csharp/src/Google.Protobuf/WritingPrimitives.cs b/csharp/src/Google.Protobuf/WritingPrimitives.cs
index 8beefc5..cfba5c7 100644
--- a/csharp/src/Google.Protobuf/WritingPrimitives.cs
+++ b/csharp/src/Google.Protobuf/WritingPrimitives.cs
@@ -32,7 +32,6 @@
 
 using System;
 using System.Buffers.Binary;
-using System.Diagnostics;
 using System.Runtime.CompilerServices;
 using System.Runtime.InteropServices;
 #if GOOGLE_PROTOBUF_SIMD
diff --git a/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs
index cd2d437..6e70ee2 100644
--- a/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs
+++ b/csharp/src/Google.Protobuf/WritingPrimitivesMessages.cs
@@ -30,9 +30,7 @@
 // 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
diff --git a/docs/cmake_protobuf_generate.md b/docs/cmake_protobuf_generate.md
new file mode 100644
index 0000000..d3e9110
--- /dev/null
+++ b/docs/cmake_protobuf_generate.md
@@ -0,0 +1,135 @@
+# How to use `protobuf_generate`
+
+This document explains how to use the function `protobuf_generate` which is provided by protobuf's CMake module.
+
+## Usage
+
+In the same directory that called `find_package(protobuf CONFIG)` and any of its subdirectories, the CMake function `protobuf_generate` is made available by 
+[`protobuf-generate.cmake`](../cmake/protobuf-generate.cmake). It can be used to automatically generate source files from `.proto` schema files at build time.
+
+### Basic example
+
+Let us see how `protobuf_generate` can be used to generate and compile the source files of a proto schema whenever an object target called `proto-objects` is built.
+
+Given the following directory structure:
+
+- `proto/helloworld/helloworld.proto`
+- `CMakeLists.txt`
+
+where `helloworld.proto` is a protobuf schema file and `CMakeLists.txt` contains:
+
+```cmake
+find_package(protobuf CONFIG REQUIRED)
+
+add_library(proto-objects OBJECT "${CMAKE_CURRENT_LIST_DIR}/proto/helloworld/helloworld.proto")
+
+target_link_libraries(proto-objects PUBLIC protobuf::libprotobuf)
+
+set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
+
+target_include_directories(proto-objects PUBLIC "$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>")
+
+protobuf_generate(
+    TARGET proto-objects
+    IMPORT_DIRS "${CMAKE_CURRENT_LIST_DIR}/proto"
+    PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
+```
+
+Building the target `proto-objects` will generate the files:
+
+- `${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.h`
+- `${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.cc`
+
+and (depending on the build system) output:
+
+```shell
+[build] [1/2] Running cpp protocol buffer compiler on /proto/helloworld/helloworld.proto
+[build] [2/2] Building CXX object /build/generated/helloworld/helloworld.pb.cc.o
+```
+
+### gRPC example
+
+`protobuf_generate` can also be customized to invoke plugins like gRPC's `grpc_cpp_plugin`. Given the same directory structure as in the [basic example](#basic-example) 
+and let `CMakeLists.txt` contain:
+
+```cmake
+find_package(gRPC CONFIG REQUIRED)
+
+add_library(proto-objects OBJECT "${CMAKE_CURRENT_LIST_DIR}/proto/helloworld/helloworld.proto")
+
+target_link_libraries(proto-objects PUBLIC protobuf::libprotobuf gRPC::grpc++)
+
+set(PROTO_BINARY_DIR "${CMAKE_CURRENT_BINARY_DIR}/generated")
+set(PROTO_IMPORT_DIRS "${CMAKE_CURRENT_LIST_DIR}/proto")
+
+target_include_directories(proto-objects PUBLIC "$<BUILD_INTERFACE:${PROTO_BINARY_DIR}>")
+
+protobuf_generate(
+    TARGET proto-objects
+    IMPORT_DIRS ${PROTO_IMPORT_DIRS}
+    PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
+
+protobuf_generate(
+    TARGET proto-objects
+    LANGUAGE grpc
+    GENERATE_EXTENSIONS .grpc.pb.h .grpc.pb.cc
+    PLUGIN "protoc-gen-grpc=\$<TARGET_FILE:gRPC::grpc_cpp_plugin>"
+    IMPORT_DIRS ${PROTO_IMPORT_DIRS}
+    PROTOC_OUT_DIR "${PROTO_BINARY_DIR}")
+```
+
+Then building `proto-objects` will generate and compile:
+
+- `${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.h`
+- `${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.pb.cc`
+- `${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.grpc.pb.h`
+- `${CMAKE_CURRENT_BINARY_DIR}/generated/helloworld/helloworld.grpc.pb.cc`
+
+And `protoc` will automatically be re-run whenever the schema files change and `proto-objects` is built.
+
+### Note on unity builds
+
+Since protobuf's generated source files are unsuited for [jumbo/unity builds](https://cmake.org/cmake/help/latest/prop_tgt/UNITY_BUILD.html) it is recommended 
+to exclude them from such builds which can be achieved by adjusting their properties:
+
+```cmake
+protobuf_generate(
+    OUT_VAR PROTO_GENERATED_FILES
+    ...)
+
+set_source_files_properties(${PROTO_GENERATED_FILES} PROPERTIES SKIP_UNITY_BUILD_INCLUSION on)
+```
+
+## How it works
+
+For each source file ending in `proto` of the argument provided to `TARGET` or each file provided through `PROTOS`, `protobuf_generate` will set up
+a [add_custom_command](https://cmake.org/cmake/help/latest/command/add_custom_command.html) which depends on `protobuf::protoc` and the proto files. 
+It declares the generated source files as `OUTPUT` which means that any target that depends on them will automatically cause the custom command to execute 
+when it is brought up to date. The command itself is made up of the arguments for `protoc`, like the output directory, the schema files, the language to 
+generate for, the plugins to use, etc.
+
+## Reference
+
+Arguments accepted by `protobuf_generate`.
+
+Flag arguments:
+
+- `APPEND_PATH` — A flag that causes the base path of all proto schema files to be added to `IMPORT_DIRS`.
+
+Single-value arguments:
+
+- `LANGUAGE` — A single value: cpp or python. Determines what kind of source files are being generated.
+- `OUT_VAR` — Name of a CMake variable that will be filled with the paths to the generated source files.
+- `EXPORT_MACRO` — Name of a macro that is applied to all generated Protobuf message classes and extern variables. It can, for example, be used to declare DLL exports.
+- `PROTOC_OUT_DIR` — Output directory of generated source files. Defaults to `CMAKE_CURRENT_BINARY_DIR`.
+- `PLUGIN` — An optional plugin executable. This could, for example, be the path to `grpc_cpp_plugin`.
+- `PLUGIN_OPTIONS` — Additional options provided to the plugin, such as `generate_mock_code=true` for the gRPC cpp plugin.
+- `DEPENDENCIES` — Arguments forwarded to the `DEPENDS` of the underlying `add_custom_command` invocation.
+- `TARGET` — CMake target that will have the generated files added as sources.
+
+Multi-value arguments:
+
+- `PROTOS` — List of proto schema files. If omitted, then every source file ending in *proto* of `TARGET` will be used.
+- `IMPORT_DIRS` — A common parent directory for the schema files. For example, if the schema file is `proto/helloworld/helloworld.proto` and the import directory `proto/` then the generated files are `${PROTOC_OUT_DIR}/helloworld/helloworld.pb.h` and `${PROTOC_OUT_DIR}/helloworld/helloworld.pb.cc`.
+- `GENERATE_EXTENSIONS` — If LANGUAGE is omitted then this must be set to the extensions that protoc generates.
+- `PROTOC_OPTIONS` — Additional arguments that are forwarded to protoc.
\ No newline at end of file
diff --git a/docs/cpp_build_systems.md b/docs/cpp_build_systems.md
new file mode 100644
index 0000000..b7f827b
--- /dev/null
+++ b/docs/cpp_build_systems.md
@@ -0,0 +1,338 @@
+# How Protobuf supports multiple C++ build systems
+
+This document explains how the Protobuf project supports multiple C++ build
+systems.
+
+## Background
+
+Protobuf primarily uses [Bazel](https://bazel.build) to build the Protobuf C++
+runtime and Protobuf compiler[^historical_sot]. However, there are several
+different build systems in common use for C++, each one of which requires
+essentially a complete copy of the same build definitions.
+
+[^historical_sot]:
+  On a historical note, prior to its [release as Open Source
+  Software](https://opensource.googleblog.com/2008/07/protocol-buffers-googles-data.html),
+  the Protobuf project was developed using Google's internal build system, which
+  was the predecessor to Bazel (the vast majority of Google's contributions
+  continue to be developed this way). The Open Source Protobuf project, however,
+  historically used Autoconf to build the C++ implementation.
+  Over time, other build systems (including Bazel) have been added, thanks in
+  large part to substantial contributions from the Open Source community. Since
+  the Protobuf project deals with multiple languages (all of which ultimately
+  rely upon C++, for the Protobuf compiler), Bazel is a natural choice for a
+  project-wide build system -- in fact, Bazel (and its predecessor, Blaze)
+  was designed in large part to support exactly this type of rich,
+  multi-language build.
+
+Currently, C++ Protobuf can be built with Bazel and CMake. Each of these build
+systems has different semantics and structure, but share in common the list of
+files needed to build the runtime and compiler.
+
+## Design
+
+### Extracting information from Bazel
+
+Bazel's Starlark API provides [aspects](https://bazel.build/rules/aspects) to
+traverse the build graph, inspect build rules, define additional actions, and
+expose information through
+[providers](https://bazel.build/rules/rules#providers). For example, the
+`cc_proto_library` rule uses an aspect to traverse the dependency graph of
+`proto_library` rules, and dynamically attaches actions to generate C++ code
+using the Protobuf compiler and compile using the C++ compiler.
+
+In order to support multiple build systems, the overall build structure is
+defined once for each system, and expose frequently-changing metadata
+from Bazel in a way that can be included from the build definition. Primarily,
+this means exposing the list of source files in a way that can be included
+in other build definitions.
+
+Two aspects are used to extract this information from the Bazel build
+definitions:
+
+*   `cc_file_list_aspect` extracts `srcs`, `hdrs`, and `textual_hdrs` from build
+    rules like `cc_library`. The sources are exposed through a provider named
+    `CcFileList`.
+*   `proto_file_list_aspect` extracts the `srcs` from a `proto_library`, and
+    also generates the expected filenames that would be generated by the
+    Protobuf compiler. This information is exposed through a provider named
+    `ProtoFileList`.
+
+On their own, these aspects have limited utility. However, they can be
+instantiated by custom rules, so that an ordinary `BUILD.bazel` target can
+produce outputs based on the information gleaned from these aspects.
+
+### (Aside) Distribution libraries
+
+Bazel's native `cc_library` rule is typically used on a "fine-grained" level, so
+that, for example, lightweight unit tests can be written with narrow scope.
+Although Bazel does build library artifacts (such as `.so` and `.a` files on
+Linux), they correspond to `cc_library` rules.
+
+Since the entire "Protobuf library" includes many constituent `cc_library`
+rules, a special rule, `cc_dist_library`, combines several fine-grained
+libraries into a single, monolithic library.
+
+For the Protobuf project, these "distribution libraries" are intended to match
+the granularity of the CMake-based builds. Since the Bazel-built
+distribution library covers the rules with the source files needed by other
+builds, the `cc_dist_library` rule invokes the `cc_file_list_aspect` on its
+input libraries. The result is that a `cc_dist_library` rule not only produces
+composite library artifacts, but also collect and provide the list of sources
+that were inputs.
+
+For example:
+
+```
+$ cat cc_dist_library_example/BUILD.bazel 
+load("@rules_cc//cc:defs.bzl", "cc_library")
+load("//pkg:cc_dist_library.bzl", "cc_dist_library")
+
+cc_library(
+    name = "a",
+    srcs = ["a.cc"],
+)
+
+cc_library(
+    name = "b",
+    srcs = ["b.cc"],
+    deps = [":c"],
+)
+
+# N.B.: not part of the cc_dist_library, even though it is in the deps of 'b':
+cc_library(
+    name = "c",
+    srcs = ["c.cc"],
+)
+
+cc_dist_library(
+    name = "lib",
+    deps = [
+        ":a",
+        ":b",
+    ],
+    visibility = ["//visibility:public"],
+)
+
+# Note: the output below has been formatted for clarity:
+$ bazel cquery //cc_dist_library_example:lib \
+    --output=starlark \
+    --starlark:expr='providers(target)["//pkg:cc_dist_library.bzl%CcFileList"]'
+struct(
+    hdrs = depset([]),
+    internal_hdrs = depset([]),
+    srcs = depset([
+        <source file cc_dist_library_example/a.cc>,
+        <source file cc_dist_library_example/b.cc>,
+    ]),
+    textual_hdrs = depset([]),
+)
+```
+
+The upshot is that the "coarse-grained" library can be defined by the Bazel
+build, and then export the list of source files that are needed to reproduce the
+library in a different build system.
+
+One major difference from most Bazel rule types is that the file list aspects do
+not propagate. In other words, they only expose the immediate dependency's
+sources, not transitive sources. This is for two reasons:
+
+1.  Immediate dependencies are conceptually simple, while transitivity requires
+    substantially more thought. For example, if transitive dependencies were
+    considered, then some way would be needed to exclude dependencies that
+    should not be part of the final library (for example, a distribution library
+    for `//:protobuf` could be defined not to include all of
+    `//:protobuf_lite`). While dependency elision is an interesting design
+    problem, the protobuf library is small enough that directly listing
+    dependencies should not be problematic.
+2.  Dealing only with immediate dependencies gives finer-grained control over
+    what goes into the composite library. For example, a Starlark `select()`
+    could conditionally add fine-grained libraries to some builds, but not
+    others.
+
+Another subtlety for tests is due to Bazel internals. Internally, a slightly
+different configuration is used when evaluating `cc_test` rules as compared to
+`cc_dist_library`. If `cc_test` targets are included in a `cc_dist_library`
+rule, and both are evaluated by Bazel, this can result in a build-time error:
+the config used for the test contains additional options that tell Bazel how to
+execute the test that the `cc_file_list_aspect` build config does not. Bazel
+detects this as two conflicting actions generating the same outputs. (For
+`cc_test` rules, the simplest workaround is to provide sources through a
+`filegroup` or similar.)
+
+### File list generation
+
+Lists of input files are generated by Bazel in a format that can be imported to
+other build systems. Currently only CMake-style files can be generated.
+
+The lists of files are derived from Bazel build targets. The sources can be:
+*   `cc_dist_library` rules (as described above)
+*   `proto_library` rules
+*   individual files
+*   `filegroup` rules
+*   `pkg_files` or `pkg_filegroup` rules from
+    https://github.com/bazelbuild/rules_pkg
+
+For example:
+
+```
+$ cat gen_file_lists_example/BUILD.bazel
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("//pkg:build_systems.bzl", "gen_cmake_file_lists")
+
+filegroup(
+    name = "doc_files",
+    srcs = [
+        "README.md",
+        "englilsh_paper.md",
+    ],
+)
+
+proto_library(
+    name = "message",
+    srcs = ["message.proto"],
+)
+
+gen_cmake_file_lists(
+    name = "source_lists",
+    out = "source_lists.cmake",
+    src_libs = {
+        ":doc_files": "docs",
+        ":message": "buff",
+        "//cc_dist_library_example:c": "distlib",
+    },
+)
+
+$ bazel build gen_file_lists_example:source_lists
+$ cat bazel-bin/gen_file_lists_example/source_lists.cmake
+# Auto-generated by //gen_file_lists_example:source_lists
+#
+# This file contains lists of sources based on Bazel rules. It should
+# be included from a hand-written CMake file that defines targets.
+#
+# Changes to this file will be overwritten based on Bazel definitions.
+
+if(${CMAKE_VERSION} VERSION_GREATER 3.10 OR ${CMAKE_VERSION} VERSION_EQUAL 3.10)
+  include_guard()
+endif()
+
+# //gen_file_lists_example:doc_files
+set(docs_files
+  gen_file_lists_example/README.md
+  gen_file_lists_example/englilsh_paper.md
+)
+
+# //gen_file_lists_example:message
+set(buff_proto_srcs
+  gen_file_lists_example/message.proto
+)
+
+# //gen_file_lists_example:message
+set(buff_srcs
+  gen_file_lists_example/message.proto.pb.cc
+)
+
+# //gen_file_lists_example:message
+set(buff_hdrs
+  gen_file_lists_example/message.proto.pb.h
+)
+
+# //gen_file_lists_example:message
+set(buff_files
+  gen_file_lists_example/message-descriptor-set.proto.bin
+)
+
+# //cc_dist_library_example:c
+set(distlib_srcs
+  cc_dist_library_example/a.cc
+  cc_dist_library_example/b.cc
+)
+
+# //cc_dist_library_example:c
+set(distlib_hdrs
+
+)
+```
+
+A hand-written CMake build rule could then use the generated file to define
+libraries, such as:
+
+```
+include(source_lists.cmake)
+add_library(distlib ${distlib_srcs} ${buff_srcs})
+```
+
+### Protobuf usage
+
+The main C++ runtimes (lite and full) and the Protobuf compiler use their
+corresponding `cc_dist_library` rules to generate file lists. For
+`proto_library` targets, the file list generation can extract the source files
+directly. For other targets, notably `cc_test` targets, the file list generators
+use `filegroup` rules.
+
+In general, adding new targets to a non-Bazel build system in Protobuf (or
+adding a new build system altogether) requires some one-time setup:
+
+1.  The overall structure of the new build system has to be defined. It should
+    import lists of files and refer to them by variable, instead of listing
+    files directly.
+2.  (Only if the build system is new) A new rule type has to be added to
+    `//pkg:build_systems.bzl`. Most of the implementation is shared, but a
+    "fragment generator" is need to declare a file list variable, and the rule
+    type itself has to be defined and call the shared implementation.
+
+When files are added or deleted, or when the Protobuf Bazel structure is
+changed, these changes may need to be reflected in the file list logic. These
+are some example scenarios:
+
+*   Files are added to (or removed from) the `srcs` of an existing `cc_library`:
+    no changes needed. If the `cc_library` is already part of a
+    `cc_dist_library`, then regenerating the source lists will reflect the
+    change.
+*   A `cc_library` is added: the new target may need to be added to the Protobuf
+    `cc_dist_library` targets, as appropriate.
+*   A `cc_library` is deleted: if a `cc_dist_library` depends upon the deleted
+    target, then a build-time error will result. The library needs to be removed
+    from the `cc_dist_library`.
+*   A `cc_test` is added or deleted: test sources are handled by `filegroup`
+    rules defined in the same package as the `cc_test` rule. The `filegroup`s
+    are usually given a name like `"test_srcs"`, and often use `glob()` to find
+    sources. This means that adding or removing a test may not require any extra
+    work, but this can be verified within the same package as the test rule.
+*   Test-only proto files are added: the `proto_library` might need to be added
+    to the file list map in `//pkg:BUILD.bazel`, and then the file added to
+    various build systems. However, most test-only protos are already exposed
+    through libraries like `//src/google/protobuf:test_protos`.
+
+If there are changes, then the regenerated file lists need to be copied back
+into the repo. That way, the corresponding build systems can be used with a git
+checkout, without needing to run Bazel first.
+
+### (Aside) Distribution archives
+
+A very similar set of rules is defined in `//pkg` to build source distribution
+archives for releases. In addition to the full sources, Protobuf releases also
+include source archives sliced by language, so that, for example, a Ruby-based
+project can get just the sources needed to build the Ruby runtime. (The
+per-language slices also include sources needed to build the protobuf compiler,
+so they all effectively include the C++ runtime.)
+
+These archives are defined using rules from the
+[rules_pkg](https://github.com/bazelbuild/rules_pkg) project. Although they are
+similar to `cc_dist_library` and the file list generation rules, the goals are
+different: the build system file lists described above only apply to C++, and
+are organized according to what should or should not be included in different
+parts of the build (e.g., no tests are included in the main library). On the
+other hand, the distribution archives deal with languages other than C++, and
+contain all the files that need to be distributed as part of a release (even for
+C++, this is more than just the C++ sources).
+
+While it might be possible to use information from the `CcFileList` and
+`ProtoFileList` providers to define the distribution files, additional files
+(such as the various `BUILD.bazel` files) are also needed in the distribution
+archive. The lists of distribution files can usually be generated by `glob()`,
+anyhow, so sharing logic with the file list aspects may not be beneficial.
+
+Currently, all of the file lists are checked in. However, it would be possible
+to build the file lists on-the-fly and include them in the distribution
+archives, rather than checking them in.
diff --git a/docs/implementing_proto3_presence.md b/docs/implementing_proto3_presence.md
index 7c3e213..4abfbd5 100644
--- a/docs/implementing_proto3_presence.md
+++ b/docs/implementing_proto3_presence.md
@@ -131,11 +131,11 @@
 
 ```
 # One option:
-$ ./src/protoc test.proto --cpp_out=. --experimental_allow_proto3_optional
+$ 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=.
+$ protoc test_proto3_optional.proto --cpp_out=.
 $
 ```
 
@@ -152,7 +152,7 @@
 run into a different error:
 
 ```
-$ ./src/protoc test_proto3_optional.proto --my_codegen_out=.
+$ 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.
@@ -201,7 +201,7 @@
 generator to generate a file containing proto3 optional fields:
 
 ```
-$ ./src/protoc test_proto3_optional.proto --my_codegen_out=.
+$ protoc test_proto3_optional.proto --my_codegen_out=.
 ```
 
 ### Updating Your Code Generator
diff --git a/docs/jvm_aot.md b/docs/jvm_aot.md
index 304c829..d9c1b6b 100644
--- a/docs/jvm_aot.md
+++ b/docs/jvm_aot.md
@@ -1,8 +1,8 @@
-# Ahead Of Time (AOT) compilation for the Java Virtual Machine (JVM)"
+# 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.
+Protobuf for the JVM uses reflection, and some of its target classes are not possible to determine in advance.
+This situation is unlikely to change.
 
 [The Lite version of protobuf for the JVM](https://github.com/protocolbuffers/protobuf/blob/main/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
@@ -10,9 +10,11 @@
 
 ## 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 GraalVM `native-image` tool can be configured with options for the  
+[Java Native Interface](https://www.graalvm.org/22.0/reference-manual/native-image/JNI/) (JNI), 
+http proxying, reflection, and other resources. While these
+configuration options can be manually specified in JSON files, we recommend 
+that you exercise the application 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.
+will generate native-image.properties files that you add to the project's
+META-INF/native-image/ directory. The  Native Image builder uses configuration options provided in META-INF/native-image/ to construct native-image command line arguments.
diff --git a/docs/options.md b/docs/options.md
index b489288..0dbd2de 100644
--- a/docs/options.md
+++ b/docs/options.md
@@ -13,310 +13,441 @@
 
 ## Existing Registered Extensions
 
-1. C# port of protocol buffers
-   * Website: https://github.com/jskeet/protobuf-csharp-port
-   * Extensions: 1000
+1.  C# port of protocol buffers
 
-1. Perl/XS port of protocol buffers
-   * Website: http://code.google.com/p/protobuf-perlxs
-   * Extensions: 1001
+    *   Website: https://github.com/jskeet/protobuf-csharp-port
+    *   Extensions: 1000
 
-1. Objective-C port of protocol buffers
-   * Website: http://code.google.com/p/protobuf-objc
-   * Extensions: 1002
+1.  Perl/XS port of protocol buffers
 
-1. Google Wave Federation Protocol open-source release (FedOne)
-   * Website: http://code.google.com/p/wave-protocol
-   * Extensions: 1003
+    *   Website: http://code.google.com/p/protobuf-perlxs
+    *   Extensions: 1001
 
-1. PHP code generator plugin
-   * Website: ???
-   * Extensions: 1004
+1.  Objective-C port of protocol buffers
 
-1. GWT code generator plugin (third-party!)
-   * Website: http://code.google.com/p/protobuf-gwt/
-   * Extensions: 1005
+    *   Website: http://code.google.com/p/protobuf-objc
+    *   Extensions: 1002
 
-1. Unix Domain RPC code generator plugin
-   * Website: http://go/udrpc
-   * Extensions: 1006
+1.  Google Wave Federation Protocol open-source release (FedOne)
 
-1. Object-C generator plugin (Plausible Labs)
-   * Website: http://www.plausible.coop
-   * Extensions: 1007
+    *   Website: http://code.google.com/p/wave-protocol
+    *   Extensions: 1003
 
-1. TBD (code42.com)
-   * Website: ???
-   * Extensions: 1008
+1.  PHP code generator plugin
 
-1. Goby Underwater Autonomy Project
-   * Website: https://github.com/GobySoft/goby
-   * Extensions: 1009
+    *   Website: ???
+    *   Extensions: 1004
 
-1. Nanopb
-   * Website: http://kapsi.fi/~jpa/nanopb
-   * Extensions: 1010
+1.  GWT code generator plugin (third-party!)
 
-1. Bluefin AUV Communication Extensions
-   * Website: http://www.bluefinrobotics.com
-   * Extensions: 1011
+    *   Website: http://code.google.com/p/protobuf-gwt/
+    *   Extensions: 1005
+
+1.  Unix Domain RPC code generator plugin
+
+    *   Website: http://go/udrpc
+    *   Extensions: 1006
+
+1.  Object-C generator plugin (Plausible Labs)
+
+    *   Website: http://www.plausible.coop
+    *   Extensions: 1007
+
+1.  TBD (code42.com)
+
+    *   Website: ???
+    *   Extensions: 1008
+
+1.  Goby Underwater Autonomy Project
+
+    *   Website: https://github.com/GobySoft/goby
+    *   Extensions: 1009
+
+1.  Nanopb
+
+    *   Website: http://kapsi.fi/~jpa/nanopb
+    *   Extensions: 1010
+
+1.  Bluefin AUV Communication Extensions
+
+    *   Website: http://www.bluefinrobotics.com
+    *   Extensions: 1011
+
+1.  Dynamic Compact Control Language
+
+    *   Website: http://github.com/GobySoft/dccl
+    *   Extensions: 1012
+
+1.  ScaleOut StateServer® Native C++ API
+
+    *   Website: http://www.scaleoutsoftware.com
+    *   Extensions: 1013
+
+1.  FoundationDB SQL Layer
+
+    *   Website: https://github.com/FoundationDB/sql-layer
+    *   Extensions: 1014
+
+1.  Fender
+
+    *   Website: https://github.com/hassox/fender
+    *   Extensions: 1015
+
+1.  Vortex
+
+    *   Website: http://www.prismtech.com/vortex
+    *   Extensions: 1016
+
+1.  tresorit
+
+    *   Website: https://tresorit.com/
+    *   Extensions: 1017
+
+1.  CRIU (Checkpoint Restore In Userspace)
+
+    *   Website: http://criu.org/Main_Page
+    *   Extensions: 1018
+
+1.  protobuf-c
+
+    *   Website: https://github.com/protobuf-c/protobuf-c
+    *   Extensions: 1019
+
+1.  ScalaPB
+
+    *   Website: https://scalapb.github.io/
+    *   Extensions: 1020
+
+1.  protoc-gen-bq-schema
+
+    *   Website: https://github.com/GoogleCloudPlatform/protoc-gen-bq-schema
+    *   Extensions: 1021
+
+1.  grpc-gateway
+
+    *   Website: https://github.com/gengo/grpc-gateway
+    *   Extensions: 1022
+
+1.  Certificate Transparency
+
+    *   Website: https://github.com/google/certificate-transparency
+    *   Extensions: 1023
+
+1.  JUNOS Router Telemetry
+
+    *   Website: http://www.juniper.net
+    *   Extensions: 1024
+
+1.  Spine Event Engine
+
+    *   Website: https://github.com/SpineEventEngine/core-java
+    *   Extensions: 1025
+
+1.  Aruba cloud platform
+
+    *   Website: ???
+    *   Extensions: 1026 -> 1030
+
+1.  Voltha
+
+    *   Website: ???
+    *   Extensions: 1031 -> 1033
+
+1.  gator
+
+    *   Website: ???
+    *   Extensions: 1034
+
+1.  protoc-gen-flowtypes
+
+    *   Website:
+        https://github.com/tmc/grpcutil/tree/master/protoc-gen-flowtypes
+    *   Extensions: 1035
+
+1.  ProfaneDB
+
+    *   Website: https://gitlab.com/ProfaneDB/ProfaneDB
+    *   Extensions: 1036
+
+1.  protobuf-net
+
+    *   Website: https://github.com/mgravell/protobuf-net
+    *   Extensions: 1037
+
+1.  FICO / StreamEngine
+
+    *   Website: http://www.fico.com/
+    *   Extensions: 1038
+
+1.  GopherJS
+
+    *   Website: https://github.com/johanbrandhorst/protobuf
+    *   Extensions: 1039
+
+1.  ygot
+
+    *   Website: https://github.com/openconfig/ygot
+    *   Extensions: 1040
+
+1.  go-grpcmw
+
+    *   Website: https://github.com/MarquisIO/go-grpcmw
+    *   Extensions: 1041
+
+1.  grpc-gateway protoc-gen-swagger
+
+    *   Website: https://github.com/grpc-ecosystem/grpc-gateway
+    *   Extensions: 1042
+
+1.  AN Message
+
+    *   Website: TBD
+    *   Extensions: 1043
+
+1.  protofire
+
+    *   Website: https://github.com/ribrdb/protofire
+    *   Extensions: 1044
+
+1.  Gravity
+
+    *   Website: https://github.com/aphysci/gravity
+    *   Extensions: 1045
+
+1.  SEMI Standards – I&C Technical Committee
+
+    *   Website:
+        http://downloads.semi.org/web/wstdsbal.nsf/9c2b317e76523cca88257641005a47f5/88a5863a580e323088256e7b00707489!OpenDocument
+    *   Extensions: 1046
+
+1.  Elixir plugin
+
+    *   Website: https://github.com/tony612/grpc-elixir
+    *   Extensions: 1047
+
+1.  API client generators
+
+    *   Website: ???
+    *   Extensions: 1048-1056
+
+1.  Netifi Proteus
+
+    *   Website: https://github.com/netifi-proteus
+    *   Extensions: 1057
+
+1.  CGSN Mooring Project
+
+    *   Website: https://bitbucket.org/ooicgsn/cgsn-mooring
+    *   Extensions: 1058
+
+1.  Container Storage Interface
+
+    *   Website: https://github.com/container-storage-interface/spec
+    *   Extensions: 1059-1069
+
+1.  TwirpQL Plugin
+
+    *   Website: https://twirpql.dev
+    *   Extensions: 1070
+
+1.  Protoc-gen-validate
+
+    *   Website: https://github.com/bufbuild/protoc-gen-validate
+    *   Extensions: 1071
+
+1.  Protokt
+
+    *   Website: https://github.com/open-toast/protokt
+    *   Extensions: 1072
+
+1.  Dart port of protocol buffers
+
+    *   Website https://github.com/dart-lang/protobuf
+    *   Extensions: 1073
+
+1.  Ocaml-protoc-plugin
+
+    *   Website: https://github.com/issuu/ocaml-protoc-plugin
+    *   Extensions: 1074
+
+1.  Analyze Re Graphene
+
+    *   Website: https://analyzere.com
+    *   Extensions: 1075
+
+1.  Wire since and until
+
+    *   Website: https://square.github.io/wire/
+    *   Extensions: 1076, 1077
+
+1.  Bazel, Failure Details
+
+    *   Website: https://github.com/bazelbuild/bazel
+    *   Extensions: 1078
+
+1.  grpc-graphql-gateway
+
+    *   Website: https://github.com/ysugimoto/grpc-graphql-gateway
+    *   Extensions: 1079
 
-1. Dynamic Compact Control Language
-   * Website: http://github.com/GobySoft/dccl
-   * Extensions: 1012
+1.  Cloudstate
 
-1. ScaleOut StateServer® Native C++ API
-   * Website: http://www.scaleoutsoftware.com
-   * Extensions: 1013
+    *   Website: https://cloudstate.io
+    *   Extensions: 1080-1084
 
-1. FoundationDB SQL Layer
-   * Website: https://github.com/FoundationDB/sql-layer
-   * Extensions: 1014
+1.  SummaFT protoc-plugins
 
-1. Fender
-   * Website: https://github.com/hassox/fender
-   * Extensions: 1015
+    *   Website: https://summaft.com/
+    *   Extensions: 1085
 
-1. Vortex
-   * Website: http://www.prismtech.com/vortex
-   * Extensions: 1016
+1.  ADLINK EdgeSDK
 
-1. tresorit
-   * Website: https://tresorit.com/
-   * Extensions: 1017
+    *   Website: https://www.adlinktech.com/en/Edge-SDK-IoT
+    *   Extensions: 1086
 
-1. CRIU (Checkpoint Restore In Userspace)
-   * Website: http://criu.org/Main_Page
-   * Extensions: 1018
+1.  Wire wire_package
 
-1. protobuf-c
-   * Website: https://github.com/protobuf-c/protobuf-c
-   * Extensions: 1019
+    *   Website: https://square.github.io/wire/
+    *   Extensions: 1087
 
-1. ScalaPB
-   * Website: https://scalapb.github.io/
-   * Extensions: 1020
+1.  Confluent Schema Registry
 
-1. protoc-gen-bq-schema
-   * Website: https://github.com/GoogleCloudPlatform/protoc-gen-bq-schema
-   * Extensions: 1021
+    *   Website: https://github.com/confluentinc/schema-registry
+    *   Extensions: 1088
 
-1. grpc-gateway
-   * Website: https://github.com/gengo/grpc-gateway
-   * Extensions: 1022
+1.  ScalaPB Validate
 
-1. Certificate Transparency
-   * Website: https://github.com/google/certificate-transparency
-   * Extensions: 1023
+    *   Website: https://scalapb.github.io/docs/validation
+    *   Extension: 1089
 
-1. JUNOS Router Telemetry
-   * Website: http://www.juniper.net
-   * Extensions: 1024
+1.  Astounding (Currently Private)
 
-1. Spine Event Engine
-   * Website: https://github.com/SpineEventEngine/core-java
-   * Extensions: 1025
+    *   Website: https://github.com/PbPipes/Astounding
+    *   Extension: 1090
 
-1. Aruba cloud platform
-   * Website: ???
-   * Extensions: 1026 -> 1030
+1.  Protoc-gen-psql
 
-1. Voltha
-   * Website: ???
-   * Extensions: 1031 -> 1033
+    *   Website: https://github.com/Intrinsec/protoc-gen-psql
+    *   Extension: 1091-1101
 
-1. gator
-   * Website: ???
-   * Extensions: 1034
+1.  Protoc-gen-sanitize
 
-1. protoc-gen-flowtypes
-   * Website: https://github.com/tmc/grpcutil/tree/master/protoc-gen-flowtypes
-   * Extensions: 1035
+    *   Website: https://github.com/Intrinsec/protoc-gen-sanitize
+    *   Extension: 1102-1106
 
-1. ProfaneDB
-   * Website: https://gitlab.com/ProfaneDB/ProfaneDB
-   * Extensions: 1036
+1.  Coach Client Connect (planned release in March 2021)
 
-1. protobuf-net
-   * Website: https://github.com/mgravell/protobuf-net
-   * Extensions: 1037
+    *   Website: https://www.coachclientconnect.com
+    *   Extension: 1107
 
-1. FICO / StreamEngine
-   * Website: http://www.fico.com/
-   * Extensions: 1038
+1.  Kratos API Errors
 
-1. GopherJS
-   * Website: https://github.com/johanbrandhorst/protobuf
-   * Extensions: 1039
+    *   Website: https://go-kratos.dev
+    *   Extension: 1108
 
-1. ygot
-   * Website: https://github.com/openconfig/ygot
-   * Extensions: 1040
+1.  Glitchdot (Currently Private)
 
-1. go-grpcmw
-   * Website: https://github.com/MarquisIO/go-grpcmw
-   * Extensions: 1041
+    *   Website: https://go.glitchdot.com
+    *   Extension: 1109
 
-1. grpc-gateway protoc-gen-swagger
-   * Website: https://github.com/grpc-ecosystem/grpc-gateway
-   * Extensions: 1042
+1.  eigr/protocol
 
-1. AN Message
-   * Website: TBD
-   * Extensions: 1043
+    *   Website: https://eigr.io
+    *   Extension: 1110-1114
 
-1. protofire
-   * Website: https://github.com/ribrdb/protofire
-   * Extensions: 1044
+1.  Container Object Storage Interface (COSI)
 
-1. Gravity
-   * Website: https://github.com/aphysci/gravity
-   * Extensions: 1045
+    *   Website:
+        https://github.com/kubernetes-sigs/container-object-storage-interface-spec
+    *   Extension: 1115-1124
 
-1. SEMI Standards – I&C Technical Committee
-   * Website: http://downloads.semi.org/web/wstdsbal.nsf/9c2b317e76523cca88257641005a47f5/88a5863a580e323088256e7b00707489!OpenDocument
-   * Extensions: 1046
+1.  Protoc-gen-jsonschema
 
-1. Elixir plugin
-   * Website: https://github.com/tony612/grpc-elixir
-   * Extensions: 1047
+    *   Website: https://github.com/chrusty/protoc-gen-jsonschema
+    *   Extension: 1125-1129
 
-1. API client generators
-   * Website: ???
-   * Extensions: 1048-1056
+1.  Protoc-gen-checker
 
-1. Netifi Proteus
-   * Website: https://github.com/netifi-proteus
-   * Extensions: 1057
+    *   Website: https://github.com/Intrinsec/protoc-gen-checker
+    *   Extension: 1130-1139
 
-1. CGSN Mooring Project
-   * Website: https://bitbucket.org/ooicgsn/cgsn-mooring
-   * Extensions: 1058
+1.  Protoc-gen-go-svc
 
-1. Container Storage Interface
-   * Website: https://github.com/container-storage-interface/spec
-   * Extensions: 1059-1069
+    *   Website: https://github.com/dane/protoc-gen-go-svc
+    *   Extension: 1140
 
-1. TwirpQL Plugin
-   * Website: https://twirpql.dev
-   * Extensions: 1070
+1.  Embedded Proto
 
-1. Protoc-gen-validate
-   * Website: https://github.com/envoyproxy/protoc-gen-validate
-   * Extensions: 1071
+    *   Website: https://EmbeddedProto.com
+    *   Extension: 1141
 
-1. Protokt
-   * Website: https://github.com/open-toast/protokt
-   * Extensions: 1072
+1.  Protoc-gen-fieldmask
 
-1. Dart port of protocol buffers
-   * Website https://github.com/dart-lang/protobuf
-   * Extensions: 1073
+    *   Website: https://github.com/yeqown/protoc-gen-fieldmask
+    *   Extension: 1142
 
-1. Ocaml-protoc-plugin
-   * Website: https://github.com/issuu/ocaml-protoc-plugin
-   * Extensions: 1074
+1.  Google Gnostic
 
-1. Analyze Re Graphene
-   * Website: https://analyzere.com
-   * Extensions: 1075
+    *   Website: https://github.com/google/gnostic
+    *   Extension: 1143
 
-1. Wire since and until
-   * Website: https://square.github.io/wire/
-   * Extensions: 1076, 1077
+1.  Protoc-gen-go-micro
 
-1. Bazel, Failure Details
-   * Website: https://github.com/bazelbuild/bazel
-   * Extensions: 1078
+    *   Website: https://github.com/unistack-org/protoc-gen-go-micro
+    *   Extension: 1144
 
-1. grpc-graphql-gateway
-   * Website: https://github.com/ysugimoto/grpc-graphql-gateway
-   * Extensions: 1079
+1.  Protoc-gen-authz
 
-1. Cloudstate
-   * Website: https://cloudstate.io
-   * Extensions: 1080-1084
+    *   Website: https://github.com/Neakxs/protoc-gen-authz
+    *   Extension: 1145
 
-1. SummaFT protoc-plugins
-   * Website: https://summaft.com/
-   * Extensions: 1085
+1.  Protonium
 
-1. ADLINK EdgeSDK
-   * Website: https://www.adlinktech.com/en/Edge-SDK-IoT
-   * Extensions: 1086
+    *   Website: https://github.com/zyp/protonium
+    *   Extension: 1146
 
-1. Wire wire_package
-   * Website: https://square.github.io/wire/
-   * Extensions: 1087
+1.  Protoc-gen-xo
 
-1. Confluent Schema Registry
-   * Website: https://github.com/confluentinc/schema-registry
-   * Extensions: 1088
+    *   Website: https://github.com/xo/ecosystem
+    *   Extension: 1147
 
-1. ScalaPB Validate
-   * Website: https://scalapb.github.io/docs/validation
-   * Extension: 1089
+1.  Ballerina gRPC
 
-1. Astounding (Currently Private)
-   * Website: https://github.com/PbPipes/Astounding
-   * Extension: 1090
+    *   Website: https://github.com/ballerina-platform/module-ballerina-grpc
+    *   Extension: 1148
 
-1. Protoc-gen-psql
-   * Website: https://github.com/Intrinsec/protoc-gen-psql
-   * Extension: 1091-1101
+1.  Protoc-gen-referential-integrity
 
-1. Protoc-gen-sanitize
-   * Website: https://github.com/Intrinsec/protoc-gen-sanitize
-   * Extension: 1102-1106
+    *   Website:
+        https://github.com/ComponentCorp/protoc-gen-referential-integrity
+    *   Extension: 1149
 
-1. Coach Client Connect (planned release in March 2021)
-   * Website: https://www.coachclientconnect.com
-   * Extension: 1107
+1.  Oclea Service Layer RPC
 
-1. Kratos API Errors
-   * Website: https://go-kratos.dev
-   * Extension: 1108
+    *   Website: https://oclea.com/
+    *   Extension: 1150
 
-1. Glitchdot (Currently Private)
-   * Website: https://go.glitchdot.com
-   * Extension: 1109
+1.  mypy-protobuf
 
-1. eigr/protocol
-   * Website: https://eigr.io
-   * Extension: 1110-1114
+    *   Website: https://github.com/nipunn1313/mypy-protobuf
+    *   Extension: 1151-1154
 
-1. Container Object Storage Interface (COSI)
-   * Website: https://github.com/kubernetes-sigs/container-object-storage-interface-spec
-   * Extension: 1115-1124
+1.  Pigweed protobuf compiler
 
-1. Protoc-gen-jsonschema
-   * Website: https://github.com/chrusty/protoc-gen-jsonschema
-   * Extension: 1125-1129
+    *   Website: https://pigweed.dev/pw_protobuf
+    *   Extension: 1155
 
-1. Protoc-gen-checker
-   * Website: https://github.com/Intrinsec/protoc-gen-checker
-   * Extension: 1130-1139
+1.  Perfetto
 
-1. Protoc-gen-go-svc
-   * Website: https://github.com/dane/protoc-gen-go-svc
-   * Extension: 1140
+    *   Website: https://perfetto.dev
+    *   Extension: 1156
 
-1. Embedded Proto
-   * Website: https://EmbeddedProto.com
-   * Extension: 1141
+1.  Buf
 
-1. Protoc-gen-fieldmask
-   * Website: https://github.com/yeqown/protoc-gen-fieldmask
-   * Extension: 1142
- 
-1. Google Gnostic
-   * Website: https://github.com/google/gnostic
-   * Extension: 1143
+    *   Website: http://buf.build/
+    *   Extension: 1157-1166
 
-1. Protoc-gen-go-micro
-   * Website: https://github.com/unistack-org/protoc-gen-go-micro
-   * Extension: 1144
+1.  Connect
 
-1. Protoc-gen-authz
-   * Website: https://github.com/Neakxs/protoc-gen-authz
-   * Extension: 1145
+    *   Website: http://connect.build/
+    *   Extension: 1167-1176
diff --git a/docs/performance.md b/docs/performance.md
deleted file mode 100644
index 245fdf1..0000000
--- a/docs/performance.md
+++ /dev/null
@@ -1,304 +0,0 @@
-# Protobuf Performance
-The following benchmark test results were produced on a workstation utilizing an Intel® Xeon® Processor E5-2630 with 32GB of RAM.
-
-This table contains the results of three separate languages:
-
-* **C++** - For C++, there are three parsing methods:
-	* **new** - This is for using a new operator for creating a message instance.
-    * **new arena** - This is for using arena for creating a new message instance.
-    * **reuse** - This is for reusing the same message instance for parsing.
-* **Java** - For Java, there are three parsing/serialization methods:
-	* **byte[]** - This is for parsing from a Byte Array.
-    * **ByteString** - This is for parsing from a
-    	com.google.protobuf.ByteString.
-    * **InputStream** - This is for parsing from an InputStream.
-* **Python** - For Python, there are three types of Python protobuf for testing:
-	* **C++-generated-code** - This is for using C++ generated code of the
-    	proto file as a dynamic linked library.
-	* **C++-reflection** - This is for using C++ reflection, for which there's no
-    	generated code, but still using C++ protobuf library as a dynamic linked
-        library.
-	* **pure-Python** - This is for the pure version of Python, which does not link with
-    	any C++ protobuf library.
-
-## Parsing performance
-
-<table>
-<tbody><tr>
-<th rowspan="2"> </th>
-<th colspan="3" rowspan="1">C++</th>
-<th colspan="3" rowspan="1">C++ with tcmalloc</th>
-<th colspan="3" rowspan="1">java</th>
-<th colspan="3" rowspan="1">python</th>
-</tr>
-<tr>
-<th colspan="1">new</th>
-<th colspan="1">new arena</th>
-<th colspan="1">reuse</th>
-<th colspan="1">new</th>
-<th colspan="1">new arena</th>
-<th colspan="1">reuse</th>
-<th colspan="1">byte[]</th>
-<th colspan="1">ByteString</th>
-<th colspan="1">InputStream</th>
-<th colspan="1">C++-generated-code</th>
-<th colspan="1">C++-reflection</th>
-<th colspan="1">pure-Python</th>
-</tr>
-<tr>
-<td>google_message1_proto2</td>
-<td>368.717MB/s</td>
-<td>261.847MB/s</td>
-<td>799.403MB/s</td>
-<td>645.183MB/s</td>
-<td>441.023MB/s</td>
-<td>1.122GB/s</td>
-<td>425.437MB/s</td>
-<td>425.937MB/s</td>
-<td>251.018MB/s</td>
-<td>82.8314MB/s</td>
-<td>47.6763MB/s</td>
-<td>3.76299MB/s</td>
-</tr>
-<tr>
-<td>google_message1_proto3</td>
-<td>294.517MB/s</td>
-<td>229.116MB/s</td>
-<td>469.982MB/s</td>
-<td>434.510MB/s</td>
-<td>394.701MB/s</td>
-<td>591.931MB/s</td>
-<td>357.597MB/s</td>
-<td>378.568MB/s</td>
-<td>221.676MB/s</td>
-<td>82.0498MB/s</td>
-<td>39.9467MB/s</td>
-<td>3.77751MB/s</td>
-</tr>
-<tr>
-<td>google_message2</td>
-<td>277.242MB/s</td>
-<td>347.611MB/s</td>
-<td>793.67MB/s</td>
-<td>503.721MB/s</td>
-<td>596.333MB/s</td>
-<td>922.533MB/s</td>
-<td>416.778MB/s</td>
-<td>419.543MB/s</td>
-<td>367.145MB/s</td>
-<td>241.46MB/s</td>
-<td>71.5723MB/s</td>
-<td>2.73538MB/s</td>
-</tr>
-<tr>
-<td>google_message3_1</td>
-<td>213.478MB/s</td>
-<td>291.58MB/s</td>
-<td>543.398MB/s</td>
-<td>539.704MB/s</td>
-<td>717.300MB/s</td>
-<td>927.333MB/s</td>
-<td>684.241MB/s</td>
-<td>704.47MB/s</td>
-<td>648.624MB/s</td>
-<td>209.036MB/s</td>
-<td>142.356MB/s</td>
-<td>15.3324MB/s</td>
-</tr>
-<tr>
-<td>google_message3_2</td>
-<td>672.685MB/s</td>
-<td>802.767MB/s</td>
-<td>1.21505GB/s</td>
-<td>985.790MB/s</td>
-<td>1.136GB/s</td>
-<td>1.367GB/s</td>
-<td>1.54439GB/s</td>
-<td>1.60603GB/s</td>
-<td>1.33443GB/s</td>
-<td>573.835MB/s</td>
-<td>314.33MB/s</td>
-<td>15.0169MB/s</td>
-</tr>
-<tr>
-<td>google_message3_3</td>
-<td>207.681MB/s</td>
-<td>140.591MB/s</td>
-<td>535.181MB/s</td>
-<td>369.743MB/s</td>
-<td>262.301MB/s</td>
-<td>556.644MB/s</td>
-<td>279.385MB/s</td>
-<td>304.853MB/s</td>
-<td>107.575MB/s</td>
-<td>32.248MB/s</td>
-<td>26.1431MB/s</td>
-<td>2.63541MB/s</td>
-</tr>
-<tr>
-<td>google_message3_4</td>
-<td>7.96091GB/s</td>
-<td>7.10024GB/s</td>
-<td>9.3013GB/s</td>
-<td>8.518GB/s</td>
-<td>8.171GB/s</td>
-<td>9.917GB/s</td>
-<td>5.78006GB/s</td>
-<td>5.85198GB/s</td>
-<td>4.62609GB/s</td>
-<td>2.49631GB/s</td>
-<td>2.35442GB/s</td>
-<td>802.061MB/s</td>
-</tr>
-<tr>
-<td>google_message3_5</td>
-<td>76.0072MB/s</td>
-<td>51.6769MB/s</td>
-<td>237.856MB/s</td>
-<td>178.495MB/s</td>
-<td>111.751MB/s</td>
-<td>329.569MB/s</td>
-<td>121.038MB/s</td>
-<td>132.866MB/s</td>
-<td>36.9197MB/s</td>
-<td>10.3962MB/s</td>
-<td>8.84659MB/s</td>
-<td>1.25203MB/s</td>
-</tr>
-<tr>
-<td>google_message4</td>
-<td>331.46MB/s</td>
-<td>404.862MB/s</td>
-<td>427.99MB/s</td>
-<td>589.887MB/s</td>
-<td>720.367MB/s</td>
-<td>705.373MB/s</td>
-<td>606.228MB/s</td>
-<td>589.13MB/s</td>
-<td>530.692MB/s</td>
-<td>305.543MB/s</td>
-<td>174.834MB/s</td>
-<td>7.86485MB/s</td>
-</tr>
-</tbody></table>
-
-## Serialization performance
-
-<table>
-<tbody><tr>
-<th rowspan="2"> </th>
-<th colspan="1" rowspan="2">C++</th>
-<th colspan="1" rowspan="2">C++ with tcmalloc</th>
-<th colspan="3" rowspan="1">java</th>
-<th colspan="3" rowspan="1">python</th>
-</tr>
-<tr>
-<th colspan="1">byte[]</th>
-<th colspan="1">ByteString</th>
-<th colspan="1">InputStream</th>
-<th colspan="1">C++-generated-code</th>
-<th colspan="1">C++-reflection</th>
-<th colspan="1">pure-Python</th>
-</tr>
-<tr>
-<td>google_message1_proto2</td>
-<td>1.39698GB/s</td>
-<td>1.701GB/s</td>
-<td>1.12915GB/s</td>
-<td>1.13589GB/s</td>
-<td>758.609MB/s</td>
-<td>260.911MB/s</td>
-<td>58.4815MB/s</td>
-<td>5.77824MB/s</td>
-</tr>
-<tr>
-<td>google_message1_proto3</td>
-<td>959.305MB/s</td>
-<td>939.404MB/s</td>
-<td>1.15372GB/s</td>
-<td>1.07824GB/s</td>
-<td>802.337MB/s</td>
-<td>239.4MB/s</td>
-<td>33.6336MB/s</td>
-<td>5.80524MB/s</td>
-</tr>
-<tr>
-<td>google_message2</td>
-<td>1.27429GB/s</td>
-<td>1.402GB/s</td>
-<td>1.01039GB/s</td>
-<td>1022.99MB/s</td>
-<td>798.736MB/s</td>
-<td>996.755MB/s</td>
-<td>57.9601MB/s</td>
-<td>4.09246MB/s</td>
-</tr>
-<tr>
-<td>google_message3_1</td>
-<td>1.31916GB/s</td>
-<td>2.049GB/s</td>
-<td>991.496MB/s</td>
-<td>860.332MB/s</td>
-<td>662.88MB/s</td>
-<td>1.48625GB/s</td>
-<td>421.287MB/s</td>
-<td>18.002MB/s</td>
-</tr>
-<tr>
-<td>google_message3_2</td>
-<td>2.15676GB/s</td>
-<td>2.632GB/s</td>
-<td>2.14736GB/s</td>
-<td>2.08136GB/s</td>
-<td>1.55997GB/s</td>
-<td>2.39597GB/s</td>
-<td>326.777MB/s</td>
-<td>16.0527MB/s</td>
-</tr>
-<tr>
-<td>google_message3_3</td>
-<td>650.456MB/s</td>
-<td>1.040GB/s</td>
-<td>593.52MB/s</td>
-<td>580.667MB/s</td>
-<td>346.839MB/s</td>
-<td>123.978MB/s</td>
-<td>35.893MB/s</td>
-<td>2.32834MB/s</td>
-</tr>
-<tr>
-<td>google_message3_4</td>
-<td>8.70154GB/s</td>
-<td>9.825GB/s</td>
-<td>5.88645GB/s</td>
-<td>5.93946GB/s</td>
-<td>2.44388GB/s</td>
-<td>5.9241GB/s</td>
-<td>4.05837GB/s</td>
-<td>876.87MB/s</td>
-</tr>
-<tr>
-<td>google_message3_5</td>
-<td>246.33MB/s</td>
-<td>443.993MB/s</td>
-<td>283.278MB/s</td>
-<td>259.167MB/s</td>
-<td>206.37MB/s</td>
-<td>37.0285MB/s</td>
-<td>12.2228MB/s</td>
-<td>1.1979MB/s</td>
-</tr>
-<tr>
-<td>google_message4</td>
-<td>1.56674GB/s</td>
-<td>2.19601GB/s</td>
-<td>776.907MB/s</td>
-<td>770.707MB/s</td>
-<td>702.931MB/s</td>
-<td>1.49623GB/s</td>
-<td>205.116MB/s</td>
-<td>8.93428MB/s</td>
-</tr>
-</tbody></table>
-
-\* The cpp performance can be improved by using [tcmalloc](https://gperftools.github.io/gperftools/tcmalloc.html), please follow the (instruction)[https://github.com/protocolbuffers/protobuf/blob/main/benchmarks/README.md] to link with tcmalloc to get the faster result.
diff --git a/docs/third_party.md b/docs/third_party.md
index d8478e9..d9ff970 100644
--- a/docs/third_party.md
+++ b/docs/third_party.md
@@ -203,3 +203,4 @@
     * [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)
 * [protoc-gen-fieldmask - A plugin to generate static type fieldmask paths](https://github.com/idodod/protoc-gen-fieldmask)
+* [protoc-gen-bq-schema - A protoc plugin to generate BigQuery schema files](https://github.com/GoogleCloudPlatform/protoc-gen-bq-schema)
diff --git a/examples/.bazelrc b/examples/.bazelrc
new file mode 100644
index 0000000..554440c
--- /dev/null
+++ b/examples/.bazelrc
@@ -0,0 +1 @@
+build --cxxopt=-std=c++14 --host_cxxopt=-std=c++14
diff --git a/examples/AddPerson.java b/examples/AddPerson.java
index 2f6a231..83971ab 100644
--- a/examples/AddPerson.java
+++ b/examples/AddPerson.java
@@ -1,4 +1,4 @@
-// See README.txt for information and build instructions.
+// See README.md for information and build instructions.
 
 import com.example.tutorial.protos.AddressBook;
 import com.example.tutorial.protos.Person;
diff --git a/examples/ListPeople.java b/examples/ListPeople.java
index ab07b79..d0e037a 100644
--- a/examples/ListPeople.java
+++ b/examples/ListPeople.java
@@ -1,4 +1,4 @@
-// See README.txt for information and build instructions.
+// See README.md for information and build instructions.
 
 import com.example.tutorial.protos.AddressBook;
 import com.example.tutorial.protos.Person;
diff --git a/examples/Makefile b/examples/Makefile
index 1c7ec8d..ef7a4ef 100644
--- a/examples/Makefile
+++ b/examples/Makefile
@@ -1,4 +1,4 @@
-# See README.txt.
+# See README.md.
 
 .PHONY: all cpp java python clean
 
@@ -13,13 +13,14 @@
 
 clean:
 	rm -f add_person_cpp list_people_cpp add_person_java list_people_java add_person_python list_people_python
-	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 javac_middleman AddPerson*.class ListPeople*.class com/example/tutorial/protos/*.class
+	rm -f protoc_middleman addressbook.pb.cc addressbook.pb.h addressbook_pb2.py com/example/tutorial/protos/*.java
 	rm -f *.pyc
 	rm -f go/tutorialpb/*.pb.go add_person_go list_people_go
 	rm -f protoc_middleman_dart dart_tutorial/*.pb*.dart
 	rmdir dart_tutorial 2>/dev/null || true
 	rmdir tutorial 2>/dev/null || true
+	rmdir com/example/tutorial/protos 2>/dev/null || true
 	rmdir com/example/tutorial 2>/dev/null || true
 	rmdir com/example 2>/dev/null || true
 	rmdir com 2>/dev/null || true
@@ -40,11 +41,11 @@
 
 add_person_cpp: add_person.cc protoc_middleman
 	pkg-config --cflags protobuf  # fails if protobuf is not installed
-	c++ -std=c++11 add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf`
+	c++ -std=c++14 add_person.cc addressbook.pb.cc -o add_person_cpp `pkg-config --cflags --libs protobuf`
 
 list_people_cpp: list_people.cc protoc_middleman
 	pkg-config --cflags protobuf  # fails if protobuf is not installed
-	c++ -std=c++11 list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
+	c++ -std=c++14 list_people.cc addressbook.pb.cc -o list_people_cpp `pkg-config --cflags --libs protobuf`
 
 add_person_dart: add_person.dart protoc_middleman_dart
 
@@ -63,7 +64,7 @@
 	cd go && go test ./cmd/list_people
 
 javac_middleman: AddPerson.java ListPeople.java protoc_middleman
-	javac -cp $$CLASSPATH AddPerson.java ListPeople.java com/example/tutorial/AddressBookProtos.java
+	javac -cp $$CLASSPATH AddPerson.java ListPeople.java com/example/tutorial/protos/*.java
 	@touch javac_middleman
 
 add_person_java: javac_middleman
diff --git a/examples/README.md b/examples/README.md
index a99883e..64e6d90 100644
--- a/examples/README.md
+++ b/examples/README.md
@@ -28,7 +28,7 @@
     $ bazel-bin/add_person_cpp addressbook.data
 
 To use protobuf in your own bazel project, please follow instructions in the
-[BUILD](BUILD) file and [WORKSPACE](WORKSPACE) file.
+[BUILD.bazel](BUILD.bazel) file and [WORKSPACE](WORKSPACE) file.
 
 ## Build the example using make
 
@@ -37,14 +37,14 @@
 and the protobuf runtime for the language you want to build.
 
 You can simply run "make" to build the example for all languages (except for
-Go). However, since different language has different installation requirement,
+Go). However, since different languages have different installation requirements,
 it will likely fail. It's better to follow individual instructions below to
 build only the language you are interested in.
 
 ### C++
 
 You can follow instructions in [../src/README.md](../src/README.md) to install
-protoc and protobuf C++ runtime from source.
+protoc from source.
 
 Then run "make cpp" in this examples directory to build the C++ example. It
 will create two executables: add_person_cpp and list_people_cpp. These programs
diff --git a/examples/WORKSPACE b/examples/WORKSPACE
index 3897572..e9811ef 100644
--- a/examples/WORKSPACE
+++ b/examples/WORKSPACE
@@ -10,9 +10,11 @@
 #
 # http_archive(
 #     name = "com_google_protobuf",
-#     strip_prefix = "protobuf-main",
-#     urls = ["https://github.com/protocolbuffers/protobuf/archive/main.zip"],
+#     sha256 = "c29d8b4b79389463c546f98b15aa4391d4ed7ec459340c47bffe15db63eb9126",
+#     strip_prefix = "protobuf-3.21.3",
+#     urls = ["https://github.com/protocolbuffers/protobuf/archive/v3.21.3.tar.gz"],
 # )
+
 local_repository(
     name = "com_google_protobuf",
     path = "..",
diff --git a/examples/add_person.cc b/examples/add_person.cc
index 856e90b..d54d0f1 100644
--- a/examples/add_person.cc
+++ b/examples/add_person.cc
@@ -1,4 +1,4 @@
-// See README.txt for information and build instructions.
+// See README.md for information and build instructions.
 
 #include <ctime>
 #include <fstream>
diff --git a/examples/add_person.py b/examples/add_person.py
index aa0fbca..aa53d58 100755
--- a/examples/add_person.py
+++ b/examples/add_person.py
@@ -1,6 +1,6 @@
 #! /usr/bin/env python
 
-# See README.txt for information and build instructions.
+# See README.md for information and build instructions.
 
 import addressbook_pb2
 import sys
diff --git a/examples/addressbook.proto b/examples/addressbook.proto
index 1bff4ad..5f52698 100644
--- a/examples/addressbook.proto
+++ b/examples/addressbook.proto
@@ -1,4 +1,4 @@
-// See README.txt for information and build instructions.
+// See README.md for information and build instructions.
 //
 // Note: START and END tags are used in comments to define sections used in
 // tutorials.  They are not part of the syntax for Protocol Buffers.
diff --git a/examples/list_people.cc b/examples/list_people.cc
index b309c59..6f0cf20 100644
--- a/examples/list_people.cc
+++ b/examples/list_people.cc
@@ -1,4 +1,4 @@
-// See README.txt for information and build instructions.
+// See README.md for information and build instructions.
 
 #include <fstream>
 #include <google/protobuf/util/time_util.h>
diff --git a/examples/list_people.py b/examples/list_people.py
index d2c294c..98a08ed 100755
--- a/examples/list_people.py
+++ b/examples/list_people.py
@@ -1,6 +1,6 @@
 #! /usr/bin/env python
 
-# See README.txt for information and build instructions.
+# See README.md for information and build instructions.
 
 from __future__ import print_function
 import addressbook_pb2
diff --git a/generate_changelog.py b/generate_changelog.py
index fe7e95b..7117ef8 100755
--- a/generate_changelog.py
+++ b/generate_changelog.py
@@ -1,4 +1,33 @@
 #!/usr/bin/env python
+# 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 a friendly list of changes per language since the last release."""
 
diff --git a/generate_descriptor_proto.sh b/generate_descriptor_proto.sh
index dc03fee..91c1217 100755
--- a/generate_descriptor_proto.sh
+++ b/generate_descriptor_proto.sh
@@ -7,7 +7,7 @@
 # generate.
 #
 # HINT:  Flags passed to generate_descriptor_proto.sh will be passed directly
-#   to make when building protoc.  This is particularly useful for passing
+#   to bazel when building protoc.  This is particularly useful for passing
 #   -j4 to run 4 jobs simultaneously.
 
 if test ! -e src/google/protobuf/stubs/common.h; then
@@ -62,12 +62,12 @@
     PROTOC=$BOOTSTRAP_PROTOC
     BOOTSTRAP_PROTOC=""
   else
-    make -j$(nproc) $@ protoc
+    bazel build $@ //:protoc
     if test $? -ne 0; then
       echo "Failed to build protoc."
       exit 1
     fi
-    PROTOC="./protoc"
+    PROTOC="../bazel-bin/protoc"
   fi
 
   $PROTOC --cpp_out=dllexport_decl=PROTOBUF_EXPORT:$TMP ${RUNTIME_PROTO_FILES[@]} && \
diff --git a/java/BUILD.bazel b/java/BUILD.bazel
index b3178c9..2c6582c 100644
--- a/java/BUILD.bazel
+++ b/java/BUILD.bazel
@@ -33,6 +33,7 @@
         "bom/pom.xml",
         "lite.md",
         "pom.xml",
+        "protoc/pom.xml",
     ],
     strip_prefix = strip_prefix.from_root(""),
     visibility = ["//pkg:__pkg__"],
diff --git a/java/core/BUILD.bazel b/java/core/BUILD.bazel
index cfd53f4..9207a55 100644
--- a/java/core/BUILD.bazel
+++ b/java/core/BUILD.bazel
@@ -191,8 +191,8 @@
     maven_coordinates = "com.google.protobuf:protobuf-java:%s" % PROTOBUF_JAVA_VERSION,
     pom_template = "pom_template.xml",
     resources = [
-        "//:built_in_runtime_protos",
         "//:well_known_type_protos",
+        "//src/google/protobuf:descriptor_proto_srcs",
     ],
     tags = ["manual"],
     runtime_deps = [":core"],
@@ -242,8 +242,9 @@
     deps = [
         "//:any_proto",
         "//:descriptor_proto",
-        "//:generic_test_protos",
+        "//:lite_test_protos",
         "//:wrappers_proto",
+        "//src/google/protobuf:generic_test_protos",
     ],
 )
 
@@ -252,7 +253,15 @@
     visibility = [
         "//java:__subpackages__",
     ],
-    deps = ["//:generic_test_protos"],
+    deps = ["//src/google/protobuf:generic_test_protos"],
+)
+
+java_proto_library(
+    name = "lite_test_protos_java_proto",
+    visibility = [
+        "//java:__subpackages__",
+    ],
+    deps = ["//:lite_test_protos"],
 )
 
 java_proto_library(
@@ -271,6 +280,7 @@
         ":core",
         ":generic_test_protos_java_proto",
         ":java_test_protos_java_proto",
+        ":lite_test_protos_java_proto",
         "@maven//:com_google_guava_guava",
         "@maven//:junit_junit",
     ],
@@ -312,11 +322,12 @@
             "src/test/java/com/google/protobuf/TestUtilLite.java",
         ],
     ),
-    data = ["//:testdata"],
+    data = ["//src/google/protobuf:testdata"],
     deps = [
         ":core",
         ":generic_test_protos_java_proto",
         ":java_test_protos_java_proto",
+        ":lite_test_protos_java_proto",
         ":test_util",
         "@maven//:com_google_guava_guava",
         "@maven//:com_google_truth_truth",
@@ -349,7 +360,16 @@
         "//java/kotlin-lite:__pkg__",
         "//java/lite:__pkg__",
     ],
-    deps = ["//:generic_test_protos"],
+    deps = ["//src/google/protobuf:generic_test_protos"],
+)
+
+java_lite_proto_library(
+    name = "lite_test_protos_java_proto_lite",
+    visibility = [
+        "//java/kotlin-lite:__pkg__",
+        "//java/lite:__pkg__",
+    ],
+    deps = ["//:lite_test_protos"],
 )
 
 java_lite_proto_library(
@@ -384,6 +404,7 @@
         ":generic_test_protos_java_proto_lite",
         ":java_test_protos_java_proto_lite",
         ":lite_runtime_only",
+        ":lite_test_protos_java_proto_lite",
         "@maven//:com_google_guava_guava",
         "@maven//:junit_junit",
     ],
@@ -421,6 +442,7 @@
     "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/TextFormatPerformanceTest.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",
@@ -440,12 +462,13 @@
         ["src/test/java/**/*.java"],
         exclude = LITE_TEST_EXCLUSIONS,
     ),
-    data = ["//:testdata"],
+    data = ["//src/google/protobuf:testdata"],
     test_prefix = "Lite",
     deps = [
         ":generic_test_protos_java_proto_lite",
         ":java_test_protos_java_proto_lite",
         ":lite",
+        ":lite_test_protos_java_proto_lite",
         ":test_util_lite",
         "@maven//:com_google_truth_truth",
         "@maven//:junit_junit",
diff --git a/java/core/generate-test-sources-build.xml b/java/core/generate-test-sources-build.xml
index bad6f19..68edf0b 100644
--- a/java/core/generate-test-sources-build.xml
+++ b/java/core/generate-test-sources-build.xml
@@ -43,8 +43,10 @@
         <arg value="${test.proto.dir}/com/google/protobuf/proto2_message.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/proto2_message_lite.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/proto2_unknown_enum_values.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/proto2_text_format_performance_test.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/proto3_message.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/proto3_message_lite.proto"/>
+        <arg value="${test.proto.dir}/com/google/protobuf/proto3_text_format_performance_test.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/test_bad_identifiers.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8.proto"/>
         <arg value="${test.proto.dir}/com/google/protobuf/test_check_utf8_size.proto"/>
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
index bbfb965..d8efa59 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessage.java
@@ -83,7 +83,6 @@
     throw new UnsupportedOperationException("Nested builder is not supported for this type.");
   }
 
-
   @Override
   public List<String> findInitializationErrors() {
     return MessageReflection.findMissingFields(this);
@@ -571,7 +570,7 @@
   protected static int hashLong(long n) {
     return (int) (n ^ (n >>> 32));
   }
-  //
+
   /**
    * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
    * generated code.
@@ -580,7 +579,7 @@
   protected static int hashBoolean(boolean b) {
     return b ? 1231 : 1237;
   }
-  //
+
   /**
    * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
    * generated code.
@@ -589,7 +588,7 @@
   protected static int hashEnum(EnumLite e) {
     return e.getNumber();
   }
-  //
+
   /**
    * @deprecated from v3.0.0-beta-3+, for compatibility with v2.5.0 and v2.6.1
    * generated code.
diff --git a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
index 7ad2a85..d7833da 100644
--- a/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/AbstractMessageLite.java
@@ -106,7 +106,6 @@
     throw new UnsupportedOperationException();
   }
 
-
   int getSerializedSize(Schema schema) {
     int memoizedSerializedSize = getMemoizedSerializedSize();
     if (memoizedSerializedSize == -1) {
diff --git a/java/core/src/main/java/com/google/protobuf/BinaryWriter.java b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java
index cf394e3..66cf51d 100644
--- a/java/core/src/main/java/com/google/protobuf/BinaryWriter.java
+++ b/java/core/src/main/java/com/google/protobuf/BinaryWriter.java
@@ -209,7 +209,7 @@
     }
   }
 
-  private final void writeInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+  private void writeInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
@@ -227,7 +227,7 @@
     }
   }
 
-  private final void writeInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+  private void writeInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
@@ -255,7 +255,7 @@
     }
   }
 
-  private final void writeFixed32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+  private void writeFixed32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
@@ -273,7 +273,7 @@
     }
   }
 
-  private final void writeFixed32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+  private void writeFixed32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
@@ -307,7 +307,7 @@
     }
   }
 
-  private final void writeUInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
+  private void writeUInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
@@ -325,7 +325,7 @@
     }
   }
 
-  private final void writeUInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
+  private void writeUInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
@@ -353,7 +353,7 @@
     }
   }
 
-  private final void writeFixed64List_Internal(int fieldNumber, List<Long> list, boolean packed)
+  private void writeFixed64List_Internal(int fieldNumber, List<Long> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
@@ -371,7 +371,7 @@
     }
   }
 
-  private final void writeFixed64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
+  private void writeFixed64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
@@ -399,7 +399,7 @@
     }
   }
 
-  private final void writeFloatList_Internal(int fieldNumber, List<Float> list, boolean packed)
+  private void writeFloatList_Internal(int fieldNumber, List<Float> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
@@ -417,7 +417,7 @@
     }
   }
 
-  private final void writeFloatList_Internal(int fieldNumber, FloatArrayList list, boolean packed)
+  private void writeFloatList_Internal(int fieldNumber, FloatArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED32_SIZE));
@@ -445,7 +445,7 @@
     }
   }
 
-  private final void writeDoubleList_Internal(int fieldNumber, List<Double> list, boolean packed)
+  private void writeDoubleList_Internal(int fieldNumber, List<Double> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
@@ -463,7 +463,7 @@
     }
   }
 
-  private final void writeDoubleList_Internal(int fieldNumber, DoubleArrayList list, boolean packed)
+  private void writeDoubleList_Internal(int fieldNumber, DoubleArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * FIXED64_SIZE));
@@ -497,7 +497,7 @@
     }
   }
 
-  private final void writeBoolList_Internal(int fieldNumber, List<Boolean> list, boolean packed)
+  private void writeBoolList_Internal(int fieldNumber, List<Boolean> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + list.size());
@@ -515,7 +515,7 @@
     }
   }
 
-  private final void writeBoolList_Internal(int fieldNumber, BooleanArrayList list, boolean packed)
+  private void writeBoolList_Internal(int fieldNumber, BooleanArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + list.size());
@@ -572,7 +572,7 @@
     }
   }
 
-  private final void writeUInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+  private void writeUInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
@@ -590,7 +590,7 @@
     }
   }
 
-  private final void writeUInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+  private void writeUInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
@@ -630,7 +630,7 @@
     }
   }
 
-  private final void writeSInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
+  private void writeSInt32List_Internal(int fieldNumber, List<Integer> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
@@ -648,7 +648,7 @@
     }
   }
 
-  private final void writeSInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
+  private void writeSInt32List_Internal(int fieldNumber, IntArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT32_SIZE));
@@ -759,7 +759,7 @@
     }
   }
 
-  private final void writeSInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
+  private void writeSInt64List_Internal(int fieldNumber, List<Long> list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
@@ -777,7 +777,7 @@
     }
   }
 
-  private final void writeSInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
+  private void writeSInt64List_Internal(int fieldNumber, LongArrayList list, boolean packed)
       throws IOException {
     if (packed) {
       requireSpace((MAX_VARINT32_SIZE * 2) + (list.size() * MAX_VARINT64_SIZE));
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 480f85f..2569d5d 100644
--- a/java/core/src/main/java/com/google/protobuf/ByteString.java
+++ b/java/core/src/main/java/com/google/protobuf/ByteString.java
@@ -75,6 +75,7 @@
  */
 @CheckReturnValue
 public abstract class ByteString implements Iterable<Byte>, Serializable {
+  private static final long serialVersionUID = 1L;
 
   /**
    * When two strings to be concatenated have a combined length shorter than this, we just copy
@@ -385,8 +386,7 @@
   // String -> ByteString
 
   /**
-   * Returns a {@code ByteString} from a hexadecimal String. Alternative CharSequences should use
-   * {@link ByteStrings#decode(CharSequence, BaseEncoding)}
+   * Returns a {@code ByteString} from a hexadecimal String.
    *
    * @param hexString String of hexadecimal digits to create {@code ByteString} from.
    * @throws NumberFormatException if the hexString does not contain a parsable hex String.
@@ -432,7 +432,10 @@
     return copyFrom(bytes, 0, bytes.length);
   }
 
-  /** Wraps the given bytes into a {@code ByteString}. Intended for internal only usage. */
+  /**
+   * Wraps the given bytes into a {@code ByteString}. Intended for internal usage within the
+   * library.
+   */
   static ByteString wrap(ByteBuffer buffer) {
     if (buffer.hasArray()) {
       final int offset = buffer.arrayOffset();
@@ -443,8 +446,8 @@
   }
 
   /**
-   * Wraps the given bytes into a {@code ByteString}. Intended for internal only usage to force a
-   * classload of ByteString before LiteralByteString.
+   * Wraps the given bytes into a {@code ByteString}. Intended for internal usage within the library
+   * to force a classload of ByteString before LiteralByteString.
    */
   static ByteString wrap(byte[] bytes) {
     // TODO(dweis): Return EMPTY when bytes are empty to reduce allocations?
@@ -452,8 +455,8 @@
   }
 
   /**
-   * Wraps the given bytes into a {@code ByteString}. Intended for internal only usage to force a
-   * classload of ByteString before BoundedByteString and LiteralByteString.
+   * Wraps the given bytes into a {@code ByteString}. Intended for internal usage within the library
+   * to force a classload of ByteString before BoundedByteString and LiteralByteString.
    */
   static ByteString wrap(byte[] bytes, int offset, int length) {
     return new BoundedByteString(bytes, offset, length);
@@ -946,6 +949,8 @@
 
   /** Base class for leaf {@link ByteString}s (i.e. non-ropes). */
   abstract static class LeafByteString extends ByteString {
+    private static final long serialVersionUID = 1L;
+
     @Override
     protected final int getTreeDepth() {
       return 0;
@@ -1130,13 +1135,6 @@
       return ByteString.copyFrom(flushedBuffers);
     }
 
-    /** Implement java.util.Arrays.copyOf() for jdk 1.5. */
-    private byte[] copyArray(byte[] buffer, int length) {
-      byte[] result = new byte[length];
-      System.arraycopy(buffer, 0, result, 0, Math.min(buffer.length, length));
-      return result;
-    }
-
     /**
      * Writes the complete contents of this byte array output stream to the specified output stream
      * argument.
@@ -1151,7 +1149,7 @@
       synchronized (this) {
         // Copy the information we need into local variables so as to hold
         // the lock for as short a time as possible.
-        cachedFlushBuffers = flushedBuffers.toArray(new ByteString[flushedBuffers.size()]);
+        cachedFlushBuffers = flushedBuffers.toArray(new ByteString[0]);
         cachedBuffer = buffer;
         cachedBufferPos = bufferPos;
       }
@@ -1159,7 +1157,7 @@
         byteString.writeTo(out);
       }
 
-      out.write(copyArray(cachedBuffer, cachedBufferPos));
+      out.write(Arrays.copyOf(cachedBuffer, cachedBufferPos));
     }
 
     /**
@@ -1210,7 +1208,7 @@
     private void flushLastBuffer() {
       if (bufferPos < buffer.length) {
         if (bufferPos > 0) {
-          byte[] bufferCopy = copyArray(buffer, bufferPos);
+          byte[] bufferCopy = Arrays.copyOf(buffer, bufferPos);
           flushedBuffers.add(new LiteralByteString(bufferCopy));
         }
         // We reuse this buffer for further writes.
@@ -1611,7 +1609,6 @@
   // Keep this class private to avoid deadlocks in classloading across threads as ByteString's
   // static initializer loads LiteralByteString and another thread loads BoundedByteString.
   private static final class BoundedByteString extends LiteralByteString {
-
     private final int bytesOffset;
     private final int bytesLength;
 
diff --git a/java/core/src/main/java/com/google/protobuf/CanIgnoreReturnValue.java b/java/core/src/main/java/com/google/protobuf/CanIgnoreReturnValue.java
index 9e84432..d31f1ed 100644
--- a/java/core/src/main/java/com/google/protobuf/CanIgnoreReturnValue.java
+++ b/java/core/src/main/java/com/google/protobuf/CanIgnoreReturnValue.java
@@ -31,7 +31,6 @@
 package com.google.protobuf;
 
 import static java.lang.annotation.ElementType.METHOD;
-import static java.lang.annotation.ElementType.TYPE;
 import static java.lang.annotation.RetentionPolicy.CLASS;
 
 import java.lang.annotation.Documented;
@@ -45,6 +44,6 @@
  * annotated with {@code @CheckReturnValue} to exempt specific methods from the default.
  */
 @Documented
-@Target({METHOD, TYPE})
+@Target(METHOD) // TODO(kak): consider adding CONSTRUCTOR later if necessary
 @Retention(CLASS)
 @interface CanIgnoreReturnValue {}
diff --git a/java/core/src/main/java/com/google/protobuf/CheckReturnValue.java b/java/core/src/main/java/com/google/protobuf/CheckReturnValue.java
index 38c83d8..99abc32 100644
--- a/java/core/src/main/java/com/google/protobuf/CheckReturnValue.java
+++ b/java/core/src/main/java/com/google/protobuf/CheckReturnValue.java
@@ -41,13 +41,13 @@
 import java.lang.annotation.Target;
 
 /**
- * Indicates that the return value of the annotated method must be checked. An error is triggered
- * when one of these methods is called but the result is not used.
+ * Indicates that the return value of the annotated method must be used. An error is triggered when
+ * one of these methods is called but the result is not used.
  *
  * <p>{@code @CheckReturnValue} may be applied to a class or package to indicate that all methods in
- * that class or package must have their return values checked. For convenience, we provide an
- * annotation, {@link CanIgnoreReturnValue}, to exempt specific methods or classes from this
- * behavior.
+ * that class (including indirectly; that is, methods of inner classes within the annotated class)
+ * or package must have their return values used. For convenience, we provide an annotation, {@link
+ * CanIgnoreReturnValue}, to exempt specific methods or classes from this behavior.
  */
 @Documented
 @Target({METHOD, CONSTRUCTOR, TYPE, PACKAGE})
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 b3074b5..7912d4c 100644
--- a/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
+++ b/java/core/src/main/java/com/google/protobuf/CodedInputStream.java
@@ -254,7 +254,6 @@
    */
   public abstract void skipMessage(CodedOutputStream output) throws IOException;
 
-
   // -----------------------------------------------------------------
 
   /** Read a {@code double} field value from the stream. */
@@ -300,7 +299,6 @@
       final ExtensionRegistryLite extensionRegistry)
       throws IOException;
 
-
   /** Read a {@code group} field value from the stream. */
   public abstract <T extends MessageLite> T readGroup(
       final int fieldNumber, final Parser<T> parser, final ExtensionRegistryLite extensionRegistry)
@@ -322,7 +320,6 @@
       final MessageLite.Builder builder, final ExtensionRegistryLite extensionRegistry)
       throws IOException;
 
-
   /** Read an embedded message field value from the stream. */
   public abstract <T extends MessageLite> T readMessage(
       final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException;
@@ -745,7 +742,6 @@
       }
     }
 
-
     // -----------------------------------------------------------------
 
     @Override
@@ -839,7 +835,6 @@
       --recursionDepth;
     }
 
-
     @Override
     public <T extends MessageLite> T readGroup(
         final int fieldNumber,
@@ -878,7 +873,6 @@
       popLimit(oldLimit);
     }
 
-
     @Override
     public <T extends MessageLite> T readMessage(
         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
@@ -1460,7 +1454,6 @@
       }
     }
 
-
     // -----------------------------------------------------------------
 
     @Override
@@ -1559,7 +1552,6 @@
       --recursionDepth;
     }
 
-
     @Override
     public <T extends MessageLite> T readGroup(
         final int fieldNumber,
@@ -1598,7 +1590,6 @@
       popLimit(oldLimit);
     }
 
-
     @Override
     public <T extends MessageLite> T readMessage(
         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
@@ -2253,7 +2244,6 @@
       }
     }
 
-
     // -----------------------------------------------------------------
 
     @Override
@@ -2359,7 +2349,6 @@
       --recursionDepth;
     }
 
-
     @Override
     public <T extends MessageLite> T readGroup(
         final int fieldNumber,
@@ -2398,7 +2387,6 @@
       popLimit(oldLimit);
     }
 
-
     @Override
     public <T extends MessageLite> T readMessage(
         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
@@ -3454,7 +3442,6 @@
       --recursionDepth;
     }
 
-
     @Override
     public <T extends MessageLite> T readGroup(
         final int fieldNumber,
@@ -3493,7 +3480,6 @@
       popLimit(oldLimit);
     }
 
-
     @Override
     public <T extends MessageLite> T readMessage(
         final Parser<T> parser, final ExtensionRegistryLite extensionRegistry) throws IOException {
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 a36195b..939c70e 100644
--- a/java/core/src/main/java/com/google/protobuf/Descriptors.java
+++ b/java/core/src/main/java/com/google/protobuf/Descriptors.java
@@ -78,6 +78,7 @@
  *
  * @author kenton@google.com Kenton Varda
  */
+@CheckReturnValue
 public final class Descriptors {
   private static final Logger logger = Logger.getLogger(Descriptors.class.getName());
   private static final int[] EMPTY_INT_ARRAY = new int[0];
@@ -461,21 +462,20 @@
     }
 
     /**
-     * This method is to be called by generated code only. It is used to update the
+     * This method is to be called by generated code only. It updates the
      * FileDescriptorProto associated with the descriptor by parsing it again with the given
      * ExtensionRegistry. This is needed to recognize custom options.
      */
     public static void internalUpdateFileDescriptor(
-        final FileDescriptor descriptor, final ExtensionRegistry registry) {
+        FileDescriptor descriptor, ExtensionRegistry registry) {
       ByteString bytes = descriptor.proto.toByteString();
-      FileDescriptorProto proto;
       try {
-        proto = FileDescriptorProto.parseFrom(bytes, registry);
+        FileDescriptorProto proto = FileDescriptorProto.parseFrom(bytes, registry);
+        descriptor.setProto(proto);
       } catch (InvalidProtocolBufferException e) {
         throw new IllegalArgumentException(
             "Failed to parse protocol buffer descriptor for generated code.", e);
       }
-      descriptor.setProto(proto);
     }
 
     /**
@@ -1728,7 +1728,6 @@
       // down-cast and call mergeFrom directly.
       return ((Message.Builder) to).mergeFrom((Message) from);
     }
-
   }
 
   // =================================================================
@@ -1788,6 +1787,27 @@
       return Collections.unmodifiableList(Arrays.asList(values));
     }
 
+    /** Determines if the given field number is reserved. */
+    public boolean isReservedNumber(final int number) {
+      for (final EnumDescriptorProto.EnumReservedRange range : proto.getReservedRangeList()) {
+        if (range.getStart() <= number && number <= range.getEnd()) {
+          return true;
+        }
+      }
+      return false;
+    }
+
+    /** Determines if the given field name is reserved. */
+    public boolean isReservedName(final String name) {
+      checkNotNull(name);
+      for (final String reservedName : proto.getReservedNameList()) {
+        if (reservedName.equals(name)) {
+          return true;
+        }
+      }
+      return false;
+    }
+
     /**
      * Find an enum value by name.
      *
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 87d85a5..738c303 100644
--- a/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/DynamicMessage.java
@@ -86,7 +86,6 @@
         UnknownFieldSet.getDefaultInstance());
   }
 
-
   /** Parse a message of the given type from the given input stream. */
   public static DynamicMessage parseFrom(Descriptor type, CodedInputStream input)
       throws IOException {
diff --git a/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java b/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java
index f0f1564..d5acc4a 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistry.java
@@ -99,7 +99,6 @@
     return EMPTY_REGISTRY;
   }
 
-
   /** Returns an unmodifiable view of the registry. */
   @Override
   public ExtensionRegistry getUnmodifiable() {
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 0a63fad..c51c6dd 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryFactory.java
@@ -70,7 +70,6 @@
     return result != null ? result : EMPTY_REGISTRY_LITE;
   }
 
-
   static boolean isFullRegistry(ExtensionRegistryLite registry) {
     return EXTENSION_REGISTRY_CLASS != null
         && EXTENSION_REGISTRY_CLASS.isAssignableFrom(registry.getClass());
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 caa58e1..4166871 100644
--- a/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
+++ b/java/core/src/main/java/com/google/protobuf/ExtensionRegistryLite.java
@@ -123,23 +123,21 @@
    * ExtensionRegistry} (if the full (non-Lite) proto libraries are available).
    */
   public static ExtensionRegistryLite getEmptyRegistry() {
+    if (!doFullRuntimeInheritanceCheck) {
+      return EMPTY_REGISTRY_LITE;
+    }
     ExtensionRegistryLite result = emptyRegistry;
     if (result == null) {
       synchronized (ExtensionRegistryLite.class) {
         result = emptyRegistry;
         if (result == null) {
-          result =
-              emptyRegistry =
-                  doFullRuntimeInheritanceCheck
-                      ? ExtensionRegistryFactory.createEmpty()
-                      : EMPTY_REGISTRY_LITE;
+          result = emptyRegistry = ExtensionRegistryFactory.createEmpty();
         }
       }
     }
     return result;
   }
 
-
   /** Returns an unmodifiable view of the registry. */
   public ExtensionRegistryLite getUnmodifiable() {
     return new ExtensionRegistryLite(this);
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 b64f63b..7bb3c9a 100644
--- a/java/core/src/main/java/com/google/protobuf/FieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/FieldSet.java
@@ -185,7 +185,6 @@
     return clone;
   }
 
-
   // =================================================================
 
   /** See {@link Message.Builder#clear()}. */
@@ -574,7 +573,6 @@
     }
   }
 
-
   /** See {@link Message#writeTo(CodedOutputStream)}. */
   public void writeTo(final CodedOutputStream output) throws IOException {
     for (int i = 0; i < fields.getNumArrayEntries(); i++) {
@@ -728,6 +726,10 @@
     if (descriptor.isRepeated()) {
       final List<?> valueList = (List<?>) value;
       if (descriptor.isPacked()) {
+        if (valueList.isEmpty()) {
+          // The tag should not be written for empty packed fields.
+          return;
+        }
         output.writeTag(number, WireFormat.WIRETYPE_LENGTH_DELIMITED);
         // Compute the total data size so the length can be written.
         int dataSize = 0;
@@ -893,9 +895,13 @@
     WireFormat.FieldType type = descriptor.getLiteType();
     int number = descriptor.getNumber();
     if (descriptor.isRepeated()) {
+      List<?> valueList = (List<?>) value;
       if (descriptor.isPacked()) {
+        if (valueList.isEmpty()) {
+          return 0;
+        }
         int dataSize = 0;
-        for (final Object element : (List<?>) value) {
+        for (final Object element : valueList) {
           dataSize += computeElementSizeNoTag(type, element);
         }
         return dataSize
@@ -903,7 +909,7 @@
             + CodedOutputStream.computeUInt32SizeNoTag(dataSize);
       } else {
         int size = 0;
-        for (final Object element : (List<?>) value) {
+        for (final Object element : valueList) {
           size += computeElementSize(type, number, element);
         }
         return size;
diff --git a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
index de0ee11..26cc5bb 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessage.java
@@ -36,7 +36,6 @@
 import com.google.protobuf.Descriptors.FieldDescriptor;
 import com.google.protobuf.Descriptors.FileDescriptor;
 import com.google.protobuf.Descriptors.OneofDescriptor;
-
 import java.io.IOException;
 import java.io.InputStream;
 import java.io.ObjectStreamException;
@@ -51,25 +50,23 @@
 import java.util.TreeMap;
 
 /**
- * All generated protocol message classes extend this class.  This class
- * implements most of the Message and Builder interfaces using Java reflection.
- * Users can ignore this class and pretend that generated messages implement
- * the Message interface directly.
+ * All generated protocol message classes extend this class. This class implements most of the
+ * Message and Builder interfaces using Java reflection. Users can ignore this class and pretend
+ * that generated messages implement the Message interface directly.
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class GeneratedMessage extends AbstractMessage
-    implements Serializable {
+public abstract class GeneratedMessage extends AbstractMessage implements Serializable {
   private static final long serialVersionUID = 1L;
 
   /**
-   * For testing. Allows a test to disable the optimization that avoids using
-   * field builders for nested messages until they are requested. By disabling
-   * this optimization, existing tests can be reused to test the field builders.
+   * For testing. Allows a test to disable the optimization that avoids using field builders for
+   * nested messages until they are requested. By disabling this optimization, existing tests can be
+   * reused to test the field builders.
    */
   protected static boolean alwaysUseFieldBuilders = false;
 
-  /** For use by generated code only.  */
+  /** For use by generated code only. */
   protected UnknownFieldSet unknownFields;
 
   protected GeneratedMessage() {
@@ -82,24 +79,22 @@
 
   @Override
   public Parser<? extends GeneratedMessage> getParserForType() {
-    throw new UnsupportedOperationException(
-        "This is supposed to be overridden by subclasses.");
+    throw new UnsupportedOperationException("This is supposed to be overridden by subclasses.");
   }
 
- /**
-  * For testing. Allows a test to disable the optimization that avoids using
-  * field builders for nested messages until they are requested. By disabling
-  * this optimization, existing tests can be reused to test the field builders.
-  * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
-  */
+  /**
+   * For testing. Allows a test to disable the optimization that avoids using field builders for
+   * nested messages until they are requested. By disabling this optimization, existing tests can be
+   * reused to test the field builders. See {@link RepeatedFieldBuilder} and {@link
+   * SingleFieldBuilder}.
+   */
   static void enableAlwaysUseFieldBuildersForTesting() {
     alwaysUseFieldBuilders = true;
   }
 
   /**
-   * Get the FieldAccessorTable for this type.  We can't have the message
-   * class pass this in to the constructor because of bootstrapping trouble
-   * with DescriptorProtos.
+   * Get the FieldAccessorTable for this type. We can't have the message class pass this in to the
+   * constructor because of bootstrapping trouble with DescriptorProtos.
    */
   protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
@@ -109,16 +104,14 @@
   }
 
   /**
-   * Internal helper to return a modifiable map containing all the fields.
-   * The returned Map is modifialbe so that the caller can add additional
-   * extension fields to implement {@link #getAllFields()}.
+   * Internal helper to return a modifiable map containing all the fields. The returned Map is
+   * modifialbe so that the caller can add additional extension fields to implement {@link
+   * #getAllFields()}.
    *
    * @param getBytesForString whether to generate ByteString for string fields
    */
-  private Map<FieldDescriptor, Object> getAllFieldsMutable(
-      boolean getBytesForString) {
-    final TreeMap<FieldDescriptor, Object> result =
-      new TreeMap<FieldDescriptor, Object>();
+  private Map<FieldDescriptor, Object> getAllFieldsMutable(boolean getBytesForString) {
+    final TreeMap<FieldDescriptor, Object> result = new TreeMap<FieldDescriptor, Object>();
     final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
     final List<FieldDescriptor> fields = descriptor.getFields();
 
@@ -174,8 +167,8 @@
       // Check that embedded messages are initialized.
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         if (field.isRepeated()) {
-          @SuppressWarnings("unchecked") final
-          List<Message> messageList = (List<Message>) getField(field);
+          @SuppressWarnings("unchecked")
+          final List<Message> messageList = (List<Message>) getField(field);
           for (final Message element : messageList) {
             if (!element.isInitialized()) {
               return false;
@@ -194,23 +187,19 @@
 
   @Override
   public Map<FieldDescriptor, Object> getAllFields() {
-    return Collections.unmodifiableMap(
-        getAllFieldsMutable(/* getBytesForString = */ false));
+    return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ false));
   }
 
   /**
-   * Returns a collection of all the fields in this message which are set
-   * and their corresponding values.  A singular ("required" or "optional")
-   * field is set iff hasField() returns true for that field.  A "repeated"
-   * field is set iff getRepeatedFieldCount() is greater than zero.  The
-   * values are exactly what would be returned by calling
-   * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field.  The map
-   * is guaranteed to be a sorted map, so iterating over it will return fields
-   * in order by field number.
+   * Returns a collection of all the fields in this message which are set and their corresponding
+   * values. A singular ("required" or "optional") field is set iff hasField() returns true for that
+   * field. A "repeated" field is set iff getRepeatedFieldCount() is greater than zero. The values
+   * are exactly what would be returned by calling {@link #getFieldRaw(Descriptors.FieldDescriptor)}
+   * for each field. The map is guaranteed to be a sorted map, so iterating over it will return
+   * fields in order by field number.
    */
   Map<FieldDescriptor, Object> getAllFieldsRaw() {
-    return Collections.unmodifiableMap(
-        getAllFieldsMutable(/* getBytesForString = */ true));
+    return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ true));
   }
 
   @Override
@@ -234,12 +223,11 @@
   }
 
   /**
-   * Obtains the value of the given field, or the default value if it is
-   * not set.  For primitive fields, the boxed primitive value is returned.
-   * For enum fields, the EnumValueDescriptor for the value is returned. For
-   * embedded message fields, the sub-message is returned.  For repeated
-   * fields, a java.util.List is returned. For present string fields, a
-   * ByteString is returned representing the bytes that the field contains.
+   * Obtains the value of the given field, or the default value if it is not set. For primitive
+   * fields, the boxed primitive value is returned. For enum fields, the EnumValueDescriptor for the
+   * value is returned. For embedded message fields, the sub-message is returned. For repeated
+   * fields, a java.util.List is returned. For present string fields, a ByteString is returned
+   * representing the bytes that the field contains.
    */
   Object getFieldRaw(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).getRaw(this);
@@ -247,31 +235,30 @@
 
   @Override
   public int getRepeatedFieldCount(final FieldDescriptor field) {
-    return internalGetFieldAccessorTable().getField(field)
-      .getRepeatedCount(this);
+    return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this);
   }
 
   @Override
   public Object getRepeatedField(final FieldDescriptor field, final int index) {
-    return internalGetFieldAccessorTable().getField(field)
-      .getRepeated(this, index);
+    return internalGetFieldAccessorTable().getField(field).getRepeated(this, index);
   }
 
   @Override
   public UnknownFieldSet getUnknownFields() {
-    throw new UnsupportedOperationException(
-        "This is supposed to be overridden by subclasses.");
+    throw new UnsupportedOperationException("This is supposed to be overridden by subclasses.");
   }
 
   /**
    * Called by subclasses to parse an unknown field.
+   *
    * @return {@code true} unless the tag is an end-group tag.
    */
   protected boolean parseUnknownField(
       CodedInputStream input,
       UnknownFieldSet.Builder unknownFields,
       ExtensionRegistryLite extensionRegistry,
-      int tag) throws IOException {
+      int tag)
+      throws IOException {
     return unknownFields.mergeFieldFrom(tag, input);
   }
 
@@ -284,8 +271,8 @@
     }
   }
 
-  protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input,
-      ExtensionRegistryLite extensions) throws IOException {
+  protected static <M extends Message> M parseWithIOException(
+      Parser<M> parser, InputStream input, ExtensionRegistryLite extensions) throws IOException {
     try {
       return parser.parseFrom(input, extensions);
     } catch (InvalidProtocolBufferException e) {
@@ -293,8 +280,8 @@
     }
   }
 
-  protected static <M extends Message> M parseWithIOException(Parser<M> parser,
-      CodedInputStream input) throws IOException {
+  protected static <M extends Message> M parseWithIOException(
+      Parser<M> parser, CodedInputStream input) throws IOException {
     try {
       return parser.parseFrom(input);
     } catch (InvalidProtocolBufferException e) {
@@ -302,8 +289,9 @@
     }
   }
 
-  protected static <M extends Message> M parseWithIOException(Parser<M> parser,
-      CodedInputStream input, ExtensionRegistryLite extensions) throws IOException {
+  protected static <M extends Message> M parseWithIOException(
+      Parser<M> parser, CodedInputStream input, ExtensionRegistryLite extensions)
+      throws IOException {
     try {
       return parser.parseFrom(input, extensions);
     } catch (InvalidProtocolBufferException e) {
@@ -311,8 +299,8 @@
     }
   }
 
-  protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
-      InputStream input) throws IOException {
+  protected static <M extends Message> M parseDelimitedWithIOException(
+      Parser<M> parser, InputStream input) throws IOException {
     try {
       return parser.parseDelimitedFrom(input);
     } catch (InvalidProtocolBufferException e) {
@@ -320,8 +308,8 @@
     }
   }
 
-  protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
-      InputStream input, ExtensionRegistryLite extensions) throws IOException {
+  protected static <M extends Message> M parseDelimitedWithIOException(
+      Parser<M> parser, InputStream input, ExtensionRegistryLite extensions) throws IOException {
     try {
       return parser.parseDelimitedFrom(input, extensions);
     } catch (InvalidProtocolBufferException e) {
@@ -341,46 +329,38 @@
       return size;
     }
 
-    memoizedSize = MessageReflection.getSerializedSize(
-        this, getAllFieldsRaw());
+    memoizedSize = MessageReflection.getSerializedSize(this, getAllFieldsRaw());
     return memoizedSize;
   }
 
-
-
-  /**
-   * Used by parsing constructors in generated classes.
-   */
+  /** Used by parsing constructors in generated classes. */
   protected void makeExtensionsImmutable() {
     // Noop for messages without extensions.
   }
 
   /**
-   * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this
-   * interface to AbstractMessage in order to versioning GeneratedMessage but
-   * this move breaks binary compatibility for AppEngine. After AppEngine is
-   * fixed we can exclude this from google3.
+   * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this interface to
+   * AbstractMessage in order to versioning GeneratedMessage but this move breaks binary
+   * compatibility for AppEngine. After AppEngine is fixed we can exclude this from google3.
    */
   protected interface BuilderParent extends AbstractMessage.BuilderParent {}
 
-  /**
-   * TODO(xiaofeng): remove this together with GeneratedMessage.BuilderParent.
-   */
+  /** TODO(xiaofeng): remove this together with GeneratedMessage.BuilderParent. */
   protected abstract Message.Builder newBuilderForType(BuilderParent parent);
 
   @Override
   protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) {
-    return newBuilderForType(new BuilderParent() {
-      @Override
-      public void markDirty() {
-        parent.markDirty();
-      }
-    });
+    return newBuilderForType(
+        new BuilderParent() {
+          @Override
+          public void markDirty() {
+            parent.markDirty();
+          }
+        });
   }
 
-
   @SuppressWarnings("unchecked")
-  public abstract static class Builder <BuilderType extends Builder<BuilderType>>
+  public abstract static class Builder<BuilderType extends Builder<BuilderType>>
       extends AbstractMessage.Builder<BuilderType> {
 
     private BuilderParent builderParent;
@@ -391,8 +371,7 @@
     // to dispatch dirty invalidations. See GeneratedMessage.BuilderListener.
     private boolean isClean;
 
-    private UnknownFieldSet unknownFields =
-        UnknownFieldSet.getDefaultInstance();
+    private UnknownFieldSet unknownFields = UnknownFieldSet.getDefaultInstance();
 
     protected Builder() {
       this(null);
@@ -407,9 +386,7 @@
       builderParent = null;
     }
 
-    /**
-     * Called by the subclass when a message is built.
-     */
+    /** Called by the subclass when a message is built. */
     protected void onBuilt() {
       if (builderParent != null) {
         markClean();
@@ -417,8 +394,8 @@
     }
 
     /**
-     * Called by the subclass or a builder to notify us that a message was
-     * built and may be cached and therefore invalidations are needed.
+     * Called by the subclass or a builder to notify us that a message was built and may be cached
+     * and therefore invalidations are needed.
      */
     @Override
     protected void markClean() {
@@ -436,15 +413,14 @@
 
     @Override
     public BuilderType clone() {
-      BuilderType builder =
-          (BuilderType) getDefaultInstanceForType().newBuilderForType();
+      BuilderType builder = (BuilderType) getDefaultInstanceForType().newBuilderForType();
       builder.mergeFrom(buildPartial());
       return builder;
     }
 
     /**
-     * Called by the initialization and clear code paths to allow subclasses to
-     * reset any of their builtin fields back to the initial values.
+     * Called by the initialization and clear code paths to allow subclasses to reset any of their
+     * builtin fields back to the initial values.
      */
     @Override
     public BuilderType clear() {
@@ -454,9 +430,8 @@
     }
 
     /**
-     * Get the FieldAccessorTable for this type.  We can't have the message
-     * class pass this in to the constructor because of bootstrapping trouble
-     * with DescriptorProtos.
+     * Get the FieldAccessorTable for this type. We can't have the message class pass this in to the
+     * constructor because of bootstrapping trouble with DescriptorProtos.
      */
     protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
@@ -472,8 +447,7 @@
 
     /** Internal helper which returns a mutable map. */
     private Map<FieldDescriptor, Object> getAllFieldsMutable() {
-      final TreeMap<FieldDescriptor, Object> result =
-        new TreeMap<FieldDescriptor, Object>();
+      final TreeMap<FieldDescriptor, Object> result = new TreeMap<FieldDescriptor, Object>();
       final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
       final List<FieldDescriptor> fields = descriptor.getFields();
 
@@ -525,8 +499,7 @@
 
     @Override
     public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
-      return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
-          this, index);
+      return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(this, index);
     }
 
     @Override
@@ -576,21 +549,18 @@
 
     @Override
     public int getRepeatedFieldCount(final FieldDescriptor field) {
-      return internalGetFieldAccessorTable().getField(field)
-          .getRepeatedCount(this);
+      return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this);
     }
 
     @Override
     public Object getRepeatedField(final FieldDescriptor field, final int index) {
-      return internalGetFieldAccessorTable().getField(field)
-          .getRepeated(this, index);
+      return internalGetFieldAccessorTable().getField(field).getRepeated(this, index);
     }
 
     @Override
     public BuilderType setRepeatedField(
         final FieldDescriptor field, final int index, final Object value) {
-      internalGetFieldAccessorTable().getField(field)
-        .setRepeated(this, index, value);
+      internalGetFieldAccessorTable().getField(field).setRepeated(this, index, value);
       return (BuilderType) this;
     }
 
@@ -608,12 +578,9 @@
     }
 
     @Override
-    public BuilderType mergeUnknownFields(
-        final UnknownFieldSet unknownFields) {
+    public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
       this.unknownFields =
-        UnknownFieldSet.newBuilder(this.unknownFields)
-                       .mergeFrom(unknownFields)
-                       .build();
+          UnknownFieldSet.newBuilder(this.unknownFields).mergeFrom(unknownFields).build();
       onChanged();
       return (BuilderType) this;
     }
@@ -630,16 +597,15 @@
         // Check that embedded messages are initialized.
         if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
           if (field.isRepeated()) {
-            @SuppressWarnings("unchecked") final
-            List<Message> messageList = (List<Message>) getField(field);
+            @SuppressWarnings("unchecked")
+            final List<Message> messageList = (List<Message>) getField(field);
             for (final Message element : messageList) {
               if (!element.isInitialized()) {
                 return false;
               }
             }
           } else {
-            if (hasField(field) &&
-                !((Message) getField(field)).isInitialized()) {
+            if (hasField(field) && !((Message) getField(field)).isInitialized()) {
               return false;
             }
           }
@@ -655,20 +621,21 @@
 
     /**
      * Called by subclasses to parse an unknown field.
+     *
      * @return {@code true} unless the tag is an end-group tag.
      */
     protected boolean parseUnknownField(
         final CodedInputStream input,
         final UnknownFieldSet.Builder unknownFields,
         final ExtensionRegistryLite extensionRegistry,
-        final int tag) throws IOException {
+        final int tag)
+        throws IOException {
       return unknownFields.mergeFieldFrom(tag, input);
     }
 
     /**
-     * Implementation of {@link BuilderParent} for giving to our children. This
-     * small inner class makes it so we don't publicly expose the BuilderParent
-     * methods.
+     * Implementation of {@link BuilderParent} for giving to our children. This small inner class
+     * makes it so we don't publicly expose the BuilderParent methods.
      */
     private class BuilderParentImpl implements BuilderParent {
 
@@ -680,6 +647,7 @@
 
     /**
      * Gets the {@link BuilderParent} for giving to our children.
+     *
      * @return The builder parent for our children.
      */
     protected BuilderParent getParentForChildren() {
@@ -690,8 +658,8 @@
     }
 
     /**
-     * Called when a the builder or one of its nested children has changed
-     * and any parent should be notified of its invalidation.
+     * Called when a the builder or one of its nested children has changed and any parent should be
+     * notified of its invalidation.
      */
     protected final void onChanged() {
       if (isClean && builderParent != null) {
@@ -703,22 +671,19 @@
     }
 
     /**
-     * Gets the map field with the given field number. This method should be
-     * overridden in the generated message class if the message contains map
-     * fields.
+     * Gets the map field with the given field number. This method should be overridden in the
+     * generated message class if the message contains map fields.
      *
-     * Unlike other field types, reflection support for map fields can't be
-     * implemented based on generated public API because we need to access a
-     * map field as a list in reflection API but the generated API only allows
-     * us to access it as a map. This method returns the underlying map field
-     * directly and thus enables us to access the map field as a list.
+     * <p>Unlike other field types, reflection support for map fields can't be implemented based on
+     * generated public API because we need to access a map field as a list in reflection API but
+     * the generated API only allows us to access it as a map. This method returns the underlying
+     * map field directly and thus enables us to access the map field as a list.
      */
     @SuppressWarnings({"unused", "rawtypes"})
     protected MapField internalGetMapField(int fieldNumber) {
       // Note that we can't use descriptor names here because this method will
       // be called when descriptor is being initialized.
-      throw new RuntimeException(
-          "No map fields found in " + getClass().getName());
+      throw new RuntimeException("No map fields found in " + getClass().getName());
     }
 
     /** Like {@link #internalGetMapField} but return a mutable version. */
@@ -726,76 +691,57 @@
     protected MapField internalGetMutableMapField(int fieldNumber) {
       // Note that we can't use descriptor names here because this method will
       // be called when descriptor is being initialized.
-      throw new RuntimeException(
-          "No map fields found in " + getClass().getName());
+      throw new RuntimeException("No map fields found in " + getClass().getName());
     }
   }
 
   // =================================================================
   // Extensions-related stuff
 
-  public interface ExtendableMessageOrBuilder<
-      MessageType extends ExtendableMessage> extends MessageOrBuilder {
+  public interface ExtendableMessageOrBuilder<MessageType extends ExtendableMessage>
+      extends MessageOrBuilder {
     // Re-define for return type covariance.
     @Override
     Message getDefaultInstanceForType();
 
     /** Check if a singular extension is present. */
-    <Type> boolean hasExtension(
-        ExtensionLite<MessageType, Type> extension);
+    <Type> boolean hasExtension(ExtensionLite<MessageType, Type> extension);
 
     /** Get the number of elements in a repeated extension. */
-    <Type> int getExtensionCount(
-        ExtensionLite<MessageType, List<Type>> extension);
+    <Type> int getExtensionCount(ExtensionLite<MessageType, List<Type>> extension);
 
     /** Get the value of an extension. */
-    <Type> Type getExtension(
-        ExtensionLite<MessageType, Type> extension);
+    <Type> Type getExtension(ExtensionLite<MessageType, Type> extension);
 
     /** Get one element of a repeated extension. */
-    <Type> Type getExtension(
-        ExtensionLite<MessageType, List<Type>> extension,
-        int index);
+    <Type> Type getExtension(ExtensionLite<MessageType, List<Type>> extension, int index);
 
     /** Check if a singular extension is present. */
-    <Type> boolean hasExtension(
-        Extension<MessageType, Type> extension);
+    <Type> boolean hasExtension(Extension<MessageType, Type> extension);
     /** Check if a singular extension is present. */
-    <Type> boolean hasExtension(
-        GeneratedExtension<MessageType, Type> extension);
+    <Type> boolean hasExtension(GeneratedExtension<MessageType, Type> extension);
     /** Get the number of elements in a repeated extension. */
-    <Type> int getExtensionCount(
-        Extension<MessageType, List<Type>> extension);
+    <Type> int getExtensionCount(Extension<MessageType, List<Type>> extension);
     /** Get the number of elements in a repeated extension. */
-    <Type> int getExtensionCount(
-        GeneratedExtension<MessageType, List<Type>> extension);
+    <Type> int getExtensionCount(GeneratedExtension<MessageType, List<Type>> extension);
     /** Get the value of an extension. */
-    <Type> Type getExtension(
-        Extension<MessageType, Type> extension);
+    <Type> Type getExtension(Extension<MessageType, Type> extension);
     /** Get the value of an extension. */
-    <Type> Type getExtension(
-        GeneratedExtension<MessageType, Type> extension);
+    <Type> Type getExtension(GeneratedExtension<MessageType, Type> extension);
     /** Get one element of a repeated extension. */
-    <Type> Type getExtension(
-        Extension<MessageType, List<Type>> extension,
-        int index);
+    <Type> Type getExtension(Extension<MessageType, List<Type>> extension, int index);
     /** Get one element of a repeated extension. */
-    <Type> Type getExtension(
-        GeneratedExtension<MessageType, List<Type>> extension,
-        int index);
+    <Type> Type getExtension(GeneratedExtension<MessageType, List<Type>> extension, int index);
   }
 
   /**
-   * Generated message classes for message types that contain extension ranges
-   * subclass this.
+   * Generated message classes for message types that contain extension ranges subclass this.
    *
-   * <p>This class implements type-safe accessors for extensions.  They
-   * implement all the same operations that you can do with normal fields --
-   * e.g. "has", "get", and "getCount" -- but for extensions.  The extensions
-   * are identified using instances of the class {@link GeneratedExtension};
-   * the protocol compiler generates a static instance of this class for every
-   * extension in its input.  Through the magic of generics, all is made
-   * type-safe.
+   * <p>This class implements type-safe accessors for extensions. They implement all the same
+   * operations that you can do with normal fields -- e.g. "has", "get", and "getCount" -- but for
+   * extensions. The extensions are identified using instances of the class {@link
+   * GeneratedExtension}; the protocol compiler generates a static instance of this class for every
+   * extension in its input. Through the magic of generics, all is made type-safe.
    *
    * <p>For example, imagine you have the {@code .proto} file:
    *
@@ -820,10 +766,8 @@
    *
    * <p>See also {@link ExtendableBuilder}.
    */
-  public abstract static class ExtendableMessage<
-        MessageType extends ExtendableMessage>
-      extends GeneratedMessage
-      implements ExtendableMessageOrBuilder<MessageType> {
+  public abstract static class ExtendableMessage<MessageType extends ExtendableMessage>
+      extends GeneratedMessage implements ExtendableMessageOrBuilder<MessageType> {
 
     private static final long serialVersionUID = 1L;
 
@@ -833,22 +777,20 @@
       this.extensions = FieldSet.newFieldSet();
     }
 
-    protected ExtendableMessage(
-        ExtendableBuilder<MessageType, ?> builder) {
+    protected ExtendableMessage(ExtendableBuilder<MessageType, ?> builder) {
       super(builder);
       this.extensions = builder.buildExtensions();
     }
 
-    private void verifyExtensionContainingType(
-        final Extension<MessageType, ?> extension) {
-      if (extension.getDescriptor().getContainingType() !=
-          getDescriptorForType()) {
+    private void verifyExtensionContainingType(final Extension<MessageType, ?> extension) {
+      if (extension.getDescriptor().getContainingType() != getDescriptorForType()) {
         // This can only happen if someone uses unchecked operations.
         throw new IllegalArgumentException(
-          "Extension is for type \"" +
-          extension.getDescriptor().getContainingType().getFullName() +
-          "\" which does not match message type \"" +
-          getDescriptorForType().getFullName() + "\".");
+            "Extension is for type \""
+                + extension.getDescriptor().getContainingType().getFullName()
+                + "\" which does not match message type \""
+                + getDescriptorForType().getFullName()
+                + "\".");
       }
     }
 
@@ -886,12 +828,10 @@
       if (value == null) {
         if (descriptor.isRepeated()) {
           return (Type) Collections.emptyList();
-        } else if (descriptor.getJavaType() ==
-                   FieldDescriptor.JavaType.MESSAGE) {
+        } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
           return (Type) extension.getMessageDefaultInstance();
         } else {
-          return (Type) extension.fromReflectionType(
-              descriptor.getDefaultValue());
+          return (Type) extension.fromReflectionType(descriptor.getDefaultValue());
         }
       } else {
         return (Type) extension.fromReflectionType(value);
@@ -907,8 +847,8 @@
 
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
-      return (Type) extension.singularFromReflectionType(
-          extensions.getRepeatedField(descriptor, index));
+      return (Type)
+          extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index));
     }
 
     /** Check if a singular extension is present. */
@@ -924,8 +864,7 @@
     }
     /** Get the number of elements in a repeated extension. */
     @Override
-    public final <Type> int getExtensionCount(
-        final Extension<MessageType, List<Type>> extension) {
+    public final <Type> int getExtensionCount(final Extension<MessageType, List<Type>> extension) {
       return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
     }
     /** Get the number of elements in a repeated extension. */
@@ -941,8 +880,7 @@
     }
     /** Get the value of an extension. */
     @Override
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, Type> extension) {
+    public final <Type> Type getExtension(final GeneratedExtension<MessageType, Type> extension) {
       return getExtension((ExtensionLite<MessageType, Type>) extension);
     }
     /** Get one element of a repeated extension. */
@@ -973,33 +911,33 @@
         CodedInputStream input,
         UnknownFieldSet.Builder unknownFields,
         ExtensionRegistryLite extensionRegistry,
-        int tag) throws IOException {
+        int tag)
+        throws IOException {
       return MessageReflection.mergeFieldFrom(
-          input, unknownFields, extensionRegistry, getDescriptorForType(),
-          new MessageReflection.ExtensionAdapter(extensions), tag);
+          input,
+          unknownFields,
+          extensionRegistry,
+          getDescriptorForType(),
+          new MessageReflection.ExtensionAdapter(extensions),
+          tag);
     }
 
-
-    /**
-     * Used by parsing constructors in generated classes.
-     */
+    /** Used by parsing constructors in generated classes. */
     @Override
     protected void makeExtensionsImmutable() {
       extensions.makeImmutable();
     }
 
     /**
-     * Used by subclasses to serialize extensions.  Extension ranges may be
-     * interleaved with field numbers, but we must write them in canonical
-     * (sorted by field number) order.  ExtensionWriter helps us write
-     * individual ranges of extensions at once.
+     * Used by subclasses to serialize extensions. Extension ranges may be interleaved with field
+     * numbers, but we must write them in canonical (sorted by field number) order. ExtensionWriter
+     * helps us write individual ranges of extensions at once.
      */
     protected class ExtensionWriter {
       // Imagine how much simpler this code would be if Java iterators had
       // a way to get the next element without advancing the iterator.
 
-      private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
-        extensions.iterator();
+      private final Iterator<Map.Entry<FieldDescriptor, Object>> iter = extensions.iterator();
       private Map.Entry<FieldDescriptor, Object> next;
       private final boolean messageSetWireFormat;
 
@@ -1010,19 +948,18 @@
         this.messageSetWireFormat = messageSetWireFormat;
       }
 
-      public void writeUntil(final int end, final CodedOutputStream output)
-                             throws IOException {
+      public void writeUntil(final int end, final CodedOutputStream output) throws IOException {
         while (next != null && next.getKey().getNumber() < end) {
           FieldDescriptor descriptor = next.getKey();
-          if (messageSetWireFormat && descriptor.getLiteJavaType() ==
-                  WireFormat.JavaType.MESSAGE &&
-              !descriptor.isRepeated()) {
+          if (messageSetWireFormat
+              && descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
+              && !descriptor.isRepeated()) {
             if (next instanceof LazyField.LazyEntry<?>) {
-              output.writeRawMessageSetExtension(descriptor.getNumber(),
+              output.writeRawMessageSetExtension(
+                  descriptor.getNumber(),
                   ((LazyField.LazyEntry<?>) next).getField().toByteString());
             } else {
-              output.writeMessageSetExtension(descriptor.getNumber(),
-                                              (Message) next.getValue());
+              output.writeMessageSetExtension(descriptor.getNumber(), (Message) next.getValue());
             }
           } else {
             // TODO(xiangl): Taken care of following code, it may cause
@@ -1046,6 +983,7 @@
     protected ExtensionWriter newExtensionWriter() {
       return new ExtensionWriter(false);
     }
+
     protected ExtensionWriter newMessageSetExtensionWriter() {
       return new ExtensionWriter(true);
     }
@@ -1054,6 +992,7 @@
     protected int extensionsSerializedSize() {
       return extensions.getSerializedSize();
     }
+
     protected int extensionsSerializedSizeAsMessageSet() {
       return extensions.getMessageSetSerializedSize();
     }
@@ -1125,8 +1064,7 @@
     }
 
     @Override
-    public Object getRepeatedField(final FieldDescriptor field,
-                                   final int index) {
+    public Object getRepeatedField(final FieldDescriptor field, final int index) {
       if (field.isExtension()) {
         verifyContainingType(field);
         return extensions.getRepeatedField(field, index);
@@ -1137,23 +1075,19 @@
 
     private void verifyContainingType(final FieldDescriptor field) {
       if (field.getContainingType() != getDescriptorForType()) {
-        throw new IllegalArgumentException(
-          "FieldDescriptor does not match message type.");
+        throw new IllegalArgumentException("FieldDescriptor does not match message type.");
       }
     }
   }
 
   /**
-   * Generated message builders for message types that contain extension ranges
-   * subclass this.
+   * Generated message builders for message types that contain extension ranges subclass this.
    *
-   * <p>This class implements type-safe accessors for extensions.  They
-   * implement all the same operations that you can do with normal fields --
-   * e.g. "get", "set", and "add" -- but for extensions.  The extensions are
-   * identified using instances of the class {@link GeneratedExtension}; the
-   * protocol compiler generates a static instance of this class for every
-   * extension in its input.  Through the magic of generics, all is made
-   * type-safe.
+   * <p>This class implements type-safe accessors for extensions. They implement all the same
+   * operations that you can do with normal fields -- e.g. "get", "set", and "add" -- but for
+   * extensions. The extensions are identified using instances of the class {@link
+   * GeneratedExtension}; the protocol compiler generates a static instance of this class for every
+   * extension in its input. Through the magic of generics, all is made type-safe.
    *
    * <p>For example, imagine you have the {@code .proto} file:
    *
@@ -1182,17 +1116,15 @@
    */
   @SuppressWarnings("unchecked")
   public abstract static class ExtendableBuilder<
-        MessageType extends ExtendableMessage,
-        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
-      extends Builder<BuilderType>
-      implements ExtendableMessageOrBuilder<MessageType> {
+          MessageType extends ExtendableMessage,
+          BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
+      extends Builder<BuilderType> implements ExtendableMessageOrBuilder<MessageType> {
 
     private FieldSet<FieldDescriptor> extensions = FieldSet.emptySet();
 
     protected ExtendableBuilder() {}
 
-    protected ExtendableBuilder(
-        BuilderParent parent) {
+    protected ExtendableBuilder(BuilderParent parent) {
       super(parent);
     }
 
@@ -1221,16 +1153,15 @@
       }
     }
 
-    private void verifyExtensionContainingType(
-        final Extension<MessageType, ?> extension) {
-      if (extension.getDescriptor().getContainingType() !=
-          getDescriptorForType()) {
+    private void verifyExtensionContainingType(final Extension<MessageType, ?> extension) {
+      if (extension.getDescriptor().getContainingType() != getDescriptorForType()) {
         // This can only happen if someone uses unchecked operations.
         throw new IllegalArgumentException(
-          "Extension is for type \"" +
-          extension.getDescriptor().getContainingType().getFullName() +
-          "\" which does not match message type \"" +
-          getDescriptorForType().getFullName() + "\".");
+            "Extension is for type \""
+                + extension.getDescriptor().getContainingType().getFullName()
+                + "\" which does not match message type \""
+                + getDescriptorForType().getFullName()
+                + "\".");
       }
     }
 
@@ -1265,12 +1196,10 @@
       if (value == null) {
         if (descriptor.isRepeated()) {
           return (Type) Collections.emptyList();
-        } else if (descriptor.getJavaType() ==
-                   FieldDescriptor.JavaType.MESSAGE) {
+        } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
           return (Type) extension.getMessageDefaultInstance();
         } else {
-          return (Type) extension.fromReflectionType(
-              descriptor.getDefaultValue());
+          return (Type) extension.fromReflectionType(descriptor.getDefaultValue());
         }
       } else {
         return (Type) extension.fromReflectionType(value);
@@ -1285,14 +1214,13 @@
 
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
-      return (Type) extension.singularFromReflectionType(
-          extensions.getRepeatedField(descriptor, index));
+      return (Type)
+          extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index));
     }
 
     /** Set the value of an extension. */
     public final <Type> BuilderType setExtension(
-        final ExtensionLite<MessageType, Type> extensionLite,
-        final Type value) {
+        final ExtensionLite<MessageType, Type> extensionLite, final Type value) {
       Extension<MessageType, Type> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
@@ -1306,30 +1234,27 @@
     /** Set the value of one element of a repeated extension. */
     public final <Type> BuilderType setExtension(
         final ExtensionLite<MessageType, List<Type>> extensionLite,
-        final int index, final Type value) {
-      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
-
-      verifyExtensionContainingType(extension);
-      ensureExtensionsIsMutable();
-      final FieldDescriptor descriptor = extension.getDescriptor();
-      extensions.setRepeatedField(
-        descriptor, index,
-        extension.singularToReflectionType(value));
-      onChanged();
-      return (BuilderType) this;
-    }
-
-    /** Append a value to a repeated extension. */
-    public final <Type> BuilderType addExtension(
-        final ExtensionLite<MessageType, List<Type>> extensionLite,
+        final int index,
         final Type value) {
       Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       ensureExtensionsIsMutable();
       final FieldDescriptor descriptor = extension.getDescriptor();
-      extensions.addRepeatedField(
-          descriptor, extension.singularToReflectionType(value));
+      extensions.setRepeatedField(descriptor, index, extension.singularToReflectionType(value));
+      onChanged();
+      return (BuilderType) this;
+    }
+
+    /** Append a value to a repeated extension. */
+    public final <Type> BuilderType addExtension(
+        final ExtensionLite<MessageType, List<Type>> extensionLite, final Type value) {
+      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+
+      verifyExtensionContainingType(extension);
+      ensureExtensionsIsMutable();
+      final FieldDescriptor descriptor = extension.getDescriptor();
+      extensions.addRepeatedField(descriptor, extension.singularToReflectionType(value));
       onChanged();
       return (BuilderType) this;
     }
@@ -1359,8 +1284,7 @@
     }
     /** Get the number of elements in a repeated extension. */
     @Override
-    public final <Type> int getExtensionCount(
-        final Extension<MessageType, List<Type>> extension) {
+    public final <Type> int getExtensionCount(final Extension<MessageType, List<Type>> extension) {
       return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
     }
     /** Get the number of elements in a repeated extension. */
@@ -1376,8 +1300,7 @@
     }
     /** Get the value of an extension. */
     @Override
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, Type> extension) {
+    public final <Type> Type getExtension(final GeneratedExtension<MessageType, Type> extension) {
       return getExtension((ExtensionLite<MessageType, Type>) extension);
     }
     /** Get the value of an extension. */
@@ -1404,14 +1327,14 @@
     }
     /** Set the value of one element of a repeated extension. */
     public final <Type> BuilderType setExtension(
-        final Extension<MessageType, List<Type>> extension,
-        final int index, final Type value) {
+        final Extension<MessageType, List<Type>> extension, final int index, final Type value) {
       return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
     }
     /** Set the value of one element of a repeated extension. */
     public <Type> BuilderType setExtension(
         final GeneratedExtension<MessageType, List<Type>> extension,
-        final int index, final Type value) {
+        final int index,
+        final Type value) {
       return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
     }
     /** Append a value to a repeated extension. */
@@ -1425,13 +1348,11 @@
       return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
     }
     /** Clear an extension. */
-    public final <Type> BuilderType clearExtension(
-        final Extension<MessageType, ?> extension) {
+    public final <Type> BuilderType clearExtension(final Extension<MessageType, ?> extension) {
       return clearExtension((ExtensionLite<MessageType, ?>) extension);
     }
     /** Clear an extension. */
-    public <Type> BuilderType clearExtension(
-        final GeneratedExtension<MessageType, ?> extension) {
+    public <Type> BuilderType clearExtension(final GeneratedExtension<MessageType, ?> extension) {
       return clearExtension((ExtensionLite<MessageType, ?>) extension);
     }
 
@@ -1441,8 +1362,7 @@
     }
 
     /**
-     * Called by the build code path to create a copy of the extensions for
-     * building the message.
+     * Called by the build code path to create a copy of the extensions for building the message.
      */
     private FieldSet<FieldDescriptor> buildExtensions() {
       extensions.makeImmutable();
@@ -1456,6 +1376,7 @@
 
     /**
      * Called by subclasses to parse an unknown field or an extension.
+     *
      * @return {@code true} unless the tag is an end-group tag.
      */
     @Override
@@ -1463,10 +1384,15 @@
         final CodedInputStream input,
         final UnknownFieldSet.Builder unknownFields,
         final ExtensionRegistryLite extensionRegistry,
-        final int tag) throws IOException {
+        final int tag)
+        throws IOException {
       return MessageReflection.mergeFieldFrom(
-          input, unknownFields, extensionRegistry, getDescriptorForType(),
-          new MessageReflection.BuilderAdapter(this), tag);
+          input,
+          unknownFields,
+          extensionRegistry,
+          getDescriptorForType(),
+          new MessageReflection.BuilderAdapter(this),
+          tag);
     }
 
     // ---------------------------------------------------------------
@@ -1511,8 +1437,7 @@
     }
 
     @Override
-    public Object getRepeatedField(final FieldDescriptor field,
-                                   final int index) {
+    public Object getRepeatedField(final FieldDescriptor field, final int index) {
       if (field.isExtension()) {
         verifyContainingType(field);
         return extensions.getRepeatedField(field, index);
@@ -1532,8 +1457,7 @@
     }
 
     @Override
-    public BuilderType setField(final FieldDescriptor field,
-                                final Object value) {
+    public BuilderType setField(final FieldDescriptor field, final Object value) {
       if (field.isExtension()) {
         verifyContainingType(field);
         ensureExtensionsIsMutable();
@@ -1559,8 +1483,8 @@
     }
 
     @Override
-    public BuilderType setRepeatedField(final FieldDescriptor field,
-                                        final int index, final Object value) {
+    public BuilderType setRepeatedField(
+        final FieldDescriptor field, final int index, final Object value) {
       if (field.isExtension()) {
         verifyContainingType(field);
         ensureExtensionsIsMutable();
@@ -1573,8 +1497,7 @@
     }
 
     @Override
-    public BuilderType addRepeatedField(final FieldDescriptor field,
-                                        final Object value) {
+    public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
       if (field.isExtension()) {
         verifyContainingType(field);
         ensureExtensionsIsMutable();
@@ -1594,8 +1517,7 @@
 
     private void verifyContainingType(final FieldDescriptor field) {
       if (field.getContainingType() != getDescriptorForType()) {
-        throw new IllegalArgumentException(
-          "FieldDescriptor does not match message type.");
+        throw new IllegalArgumentException("FieldDescriptor does not match message type.");
       }
     }
   }
@@ -1603,8 +1525,8 @@
   // -----------------------------------------------------------------
 
   /**
-   * Gets the descriptor for an extension. The implementation depends on whether
-   * the extension is scoped in the top level of a file or scoped in a Message.
+   * Gets the descriptor for an extension. The implementation depends on whether the extension is
+   * scoped in the top level of a file or scoped in a Message.
    */
   static interface ExtensionDescriptorRetriever {
     FieldDescriptor getDescriptor();
@@ -1612,11 +1534,11 @@
 
   /** For use by generated code only. */
   public static <ContainingType extends Message, Type>
-      GeneratedExtension<ContainingType, Type>
-      newMessageScopedGeneratedExtension(final Message scope,
-                                         final int descriptorIndex,
-                                         final Class singularType,
-                                         final Message defaultInstance) {
+      GeneratedExtension<ContainingType, Type> newMessageScopedGeneratedExtension(
+          final Message scope,
+          final int descriptorIndex,
+          final Class singularType,
+          final Message defaultInstance) {
     // For extensions scoped within a Message, we use the Message to resolve
     // the outer class's descriptor, from which the extension descriptor is
     // obtained.
@@ -1634,22 +1556,21 @@
 
   /** For use by generated code only. */
   public static <ContainingType extends Message, Type>
-     GeneratedExtension<ContainingType, Type>
-     newFileScopedGeneratedExtension(final Class singularType,
-                                     final Message defaultInstance) {
+      GeneratedExtension<ContainingType, Type> newFileScopedGeneratedExtension(
+          final Class singularType, final Message defaultInstance) {
     // For extensions scoped within a file, we rely on the outer class's
     // static initializer to call internalInit() on the extension when the
     // descriptor is available.
     return new GeneratedExtension<ContainingType, Type>(
-        null,  // ExtensionDescriptorRetriever is initialized in internalInit();
+        null, // ExtensionDescriptorRetriever is initialized in internalInit();
         singularType,
         defaultInstance,
         Extension.ExtensionType.IMMUTABLE);
   }
 
-  private abstract static class CachedDescriptorRetriever
-      implements ExtensionDescriptorRetriever {
+  private abstract static class CachedDescriptorRetriever implements ExtensionDescriptorRetriever {
     private volatile FieldDescriptor descriptor;
+
     protected abstract FieldDescriptor loadDescriptor();
 
     @Override
@@ -1668,15 +1589,16 @@
   /**
    * Used in proto1 generated code only.
    *
-   * After enabling bridge, we can define proto2 extensions (the extended type
-   * is a proto2 mutable message) in a proto1 .proto file. For these extensions
-   * we should generate proto2 GeneratedExtensions.
+   * <p>After enabling bridge, we can define proto2 extensions (the extended type is a proto2
+   * mutable message) in a proto1 .proto file. For these extensions we should generate proto2
+   * GeneratedExtensions.
    */
   public static <ContainingType extends Message, Type>
-      GeneratedExtension<ContainingType, Type>
-      newMessageScopedGeneratedExtension(
-          final Message scope, final String name,
-          final Class singularType, final Message defaultInstance) {
+      GeneratedExtension<ContainingType, Type> newMessageScopedGeneratedExtension(
+          final Message scope,
+          final String name,
+          final Class singularType,
+          final Message defaultInstance) {
     // For extensions scoped within a Message, we use the Message to resolve
     // the outer class's descriptor, from which the extension descriptor is
     // obtained.
@@ -1695,15 +1617,16 @@
   /**
    * Used in proto1 generated code only.
    *
-   * After enabling bridge, we can define proto2 extensions (the extended type
-   * is a proto2 mutable message) in a proto1 .proto file. For these extensions
-   * we should generate proto2 GeneratedExtensions.
+   * <p>After enabling bridge, we can define proto2 extensions (the extended type is a proto2
+   * mutable message) in a proto1 .proto file. For these extensions we should generate proto2
+   * GeneratedExtensions.
    */
   public static <ContainingType extends Message, Type>
-     GeneratedExtension<ContainingType, Type>
-     newFileScopedGeneratedExtension(
-         final Class singularType, final Message defaultInstance,
-         final String descriptorOuterClass, final String extensionName) {
+      GeneratedExtension<ContainingType, Type> newFileScopedGeneratedExtension(
+          final Class singularType,
+          final Message defaultInstance,
+          final String descriptorOuterClass,
+          final String extensionName) {
     // For extensions scoped within a file, we load the descriptor outer
     // class and rely on it to get the FileDescriptor which then can be
     // used to obtain the extension's FieldDescriptor.
@@ -1730,8 +1653,8 @@
   }
 
   /**
-   * Type used to represent generated extensions.  The protocol compiler
-   * generates a static singleton instance of this class for each extension.
+   * Type used to represent generated extensions. The protocol compiler generates a static singleton
+   * instance of this class for each extension.
    *
    * <p>For example, imagine you have the {@code .proto} file:
    *
@@ -1747,16 +1670,14 @@
    * }
    * </pre>
    *
-   * <p>Then, {@code MyProto.Foo.bar} has type
-   * {@code GeneratedExtension<MyProto.Foo, Integer>}.
+   * <p>Then, {@code MyProto.Foo.bar} has type {@code GeneratedExtension<MyProto.Foo, Integer>}.
    *
-   * <p>In general, users should ignore the details of this type, and simply use
-   * these static singletons as parameters to the extension accessors defined
-   * in {@link ExtendableMessage} and {@link ExtendableBuilder}.
+   * <p>In general, users should ignore the details of this type, and simply use these static
+   * singletons as parameters to the extension accessors defined in {@link ExtendableMessage} and
+   * {@link ExtendableBuilder}.
    */
-  public static class GeneratedExtension<
-      ContainingType extends Message, Type> extends
-      Extension<ContainingType, Type> {
+  public static class GeneratedExtension<ContainingType extends Message, Type>
+      extends Extension<ContainingType, Type> {
     // TODO(kenton):  Find ways to avoid using Java reflection within this
     //   class.  Also try to avoid suppressing unchecked warnings.
 
@@ -1772,12 +1693,13 @@
     // In the case of non-nested extensions, we initialize the
     // ExtensionDescriptorRetriever to null and rely on the outer class's static
     // initializer to call internalInit() after the descriptor has been parsed.
-    GeneratedExtension(ExtensionDescriptorRetriever descriptorRetriever,
+    GeneratedExtension(
+        ExtensionDescriptorRetriever descriptorRetriever,
         Class singularType,
         Message messageDefaultInstance,
         ExtensionType extensionType) {
-      if (Message.class.isAssignableFrom(singularType) &&
-          !singularType.isInstance(messageDefaultInstance)) {
+      if (Message.class.isAssignableFrom(singularType)
+          && !singularType.isInstance(messageDefaultInstance)) {
         throw new IllegalArgumentException(
             "Bad messageDefaultInstance for " + singularType.getName());
       }
@@ -1786,10 +1708,8 @@
       this.messageDefaultInstance = messageDefaultInstance;
 
       if (ProtocolMessageEnum.class.isAssignableFrom(singularType)) {
-        this.enumValueOf = getMethodOrDie(singularType, "valueOf",
-                                          EnumValueDescriptor.class);
-        this.enumGetValueDescriptor =
-            getMethodOrDie(singularType, "getValueDescriptor");
+        this.enumValueOf = getMethodOrDie(singularType, "valueOf", EnumValueDescriptor.class);
+        this.enumGetValueDescriptor = getMethodOrDie(singularType, "getValueDescriptor");
       } else {
         this.enumValueOf = null;
         this.enumGetValueDescriptor = null;
@@ -1821,15 +1741,14 @@
     @Override
     public FieldDescriptor getDescriptor() {
       if (descriptorRetriever == null) {
-        throw new IllegalStateException(
-            "getDescriptor() called before internalInit()");
+        throw new IllegalStateException("getDescriptor() called before internalInit()");
       }
       return descriptorRetriever.getDescriptor();
     }
 
     /**
-     * If the extension is an embedded message or group, returns the default
-     * instance of the message.
+     * If the extension is an embedded message or group, returns the default instance of the
+     * message.
      */
     @Override
     public Message getMessageDefaultInstance() {
@@ -1842,18 +1761,17 @@
     }
 
     /**
-     * Convert from the type used by the reflection accessors to the type used
-     * by native accessors.  E.g., for enums, the reflection accessors use
-     * EnumValueDescriptors but the native accessors use the generated enum
-     * type.
+     * Convert from the type used by the reflection accessors to the type used by native accessors.
+     * E.g., for enums, the reflection accessors use EnumValueDescriptors but the native accessors
+     * use the generated enum type.
      */
     @Override
     @SuppressWarnings("unchecked")
     protected Object fromReflectionType(final Object value) {
       FieldDescriptor descriptor = getDescriptor();
       if (descriptor.isRepeated()) {
-        if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE ||
-            descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
+        if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE
+            || descriptor.getJavaType() == FieldDescriptor.JavaType.ENUM) {
           // Must convert the whole list.
           final List result = new ArrayList();
           for (final Object element : (List) value) {
@@ -1869,8 +1787,8 @@
     }
 
     /**
-     * Like {@link #fromReflectionType(Object)}, but if the type is a repeated
-     * type, this converts a single element.
+     * Like {@link #fromReflectionType(Object)}, but if the type is a repeated type, this converts a
+     * single element.
      */
     @Override
     protected Object singularFromReflectionType(final Object value) {
@@ -1880,8 +1798,7 @@
           if (singularType.isInstance(value)) {
             return value;
           } else {
-            return messageDefaultInstance.newBuilderForType()
-                .mergeFrom((Message) value).build();
+            return messageDefaultInstance.newBuilderForType().mergeFrom((Message) value).build();
           }
         case ENUM:
           return invokeOrDie(enumValueOf, null, (EnumValueDescriptor) value);
@@ -1891,10 +1808,9 @@
     }
 
     /**
-     * Convert from the type used by the native accessors to the type used
-     * by reflection accessors.  E.g., for enums, the reflection accessors use
-     * EnumValueDescriptors but the native accessors use the generated enum
-     * type.
+     * Convert from the type used by the native accessors to the type used by reflection accessors.
+     * E.g., for enums, the reflection accessors use EnumValueDescriptors but the native accessors
+     * use the generated enum type.
      */
     @Override
     @SuppressWarnings("unchecked")
@@ -1917,8 +1833,8 @@
     }
 
     /**
-     * Like {@link #toReflectionType(Object)}, but if the type is a repeated
-     * type, this converts a single element.
+     * Like {@link #toReflectionType(Object)}, but if the type is a repeated type, this converts a
+     * single element.
      */
     @Override
     protected Object singularToReflectionType(final Object value) {
@@ -1955,8 +1871,7 @@
       if (getDescriptor().getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         return (Type) messageDefaultInstance;
       }
-      return (Type) singularFromReflectionType(
-          getDescriptor().getDefaultValue());
+      return (Type) singularFromReflectionType(getDescriptor().getDefaultValue());
     }
   }
 
@@ -1970,8 +1885,8 @@
       return clazz.getMethod(name, params);
     } catch (NoSuchMethodException e) {
       throw new RuntimeException(
-        "Generated message class \"" + clazz.getName() +
-        "\" missing method \"" + name + "\".", e);
+          "Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".",
+          e);
     }
   }
 
@@ -1982,8 +1897,7 @@
       return method.invoke(object, params);
     } catch (IllegalAccessException e) {
       throw new RuntimeException(
-        "Couldn't use Java reflection to implement protocol message " +
-        "reflection.", e);
+          "Couldn't use Java reflection to implement protocol message " + "reflection.", e);
     } catch (InvocationTargetException e) {
       final Throwable cause = e.getCause();
       if (cause instanceof RuntimeException) {
@@ -1992,45 +1906,42 @@
         throw (Error) cause;
       } else {
         throw new RuntimeException(
-          "Unexpected exception thrown by generated accessor method.", cause);
+            "Unexpected exception thrown by generated accessor method.", cause);
       }
     }
   }
 
   /**
-   * Gets the map field with the given field number. This method should be
-   * overridden in the generated message class if the message contains map
-   * fields.
+   * Gets the map field with the given field number. This method should be overridden in the
+   * generated message class if the message contains map fields.
    *
-   * Unlike other field types, reflection support for map fields can't be
-   * implemented based on generated public API because we need to access a
-   * map field as a list in reflection API but the generated API only allows
-   * us to access it as a map. This method returns the underlying map field
-   * directly and thus enables us to access the map field as a list.
+   * <p>Unlike other field types, reflection support for map fields can't be implemented based on
+   * generated public API because we need to access a map field as a list in reflection API but the
+   * generated API only allows us to access it as a map. This method returns the underlying map
+   * field directly and thus enables us to access the map field as a list.
    */
   @SuppressWarnings({"rawtypes", "unused"})
   protected MapField internalGetMapField(int fieldNumber) {
     // Note that we can't use descriptor names here because this method will
     // be called when descriptor is being initialized.
-    throw new RuntimeException(
-        "No map fields found in " + getClass().getName());
+    throw new RuntimeException("No map fields found in " + getClass().getName());
   }
 
   /**
-   * Users should ignore this class.  This class provides the implementation
-   * with access to the fields of a message object using Java reflection.
+   * Users should ignore this class. This class provides the implementation with access to the
+   * fields of a message object using Java reflection.
    */
   public static final class FieldAccessorTable {
 
     /**
-     * Construct a FieldAccessorTable for a particular message class.  Only
-     * one FieldAccessorTable should ever be constructed per class.
+     * Construct a FieldAccessorTable for a particular message class. Only one FieldAccessorTable
+     * should ever be constructed per class.
      *
-     * @param descriptor     The type's descriptor.
-     * @param camelCaseNames The camelcase names of all fields in the message.
-     *                       These are used to derive the accessor method names.
-     * @param messageClass   The message type.
-     * @param builderClass   The builder type.
+     * @param descriptor The type's descriptor.
+     * @param camelCaseNames The camelcase names of all fields in the message. These are used to
+     *     derive the accessor method names.
+     * @param messageClass The message type.
+     * @param builderClass The builder type.
      */
     public FieldAccessorTable(
         final Descriptor descriptor,
@@ -2042,12 +1953,10 @@
     }
 
     /**
-     * Construct a FieldAccessorTable for a particular message class without
-     * initializing FieldAccessors.
+     * Construct a FieldAccessorTable for a particular message class without initializing
+     * FieldAccessors.
      */
-    public FieldAccessorTable(
-        final Descriptor descriptor,
-        final String[] camelCaseNames) {
+    public FieldAccessorTable(final Descriptor descriptor, final String[] camelCaseNames) {
       this.descriptor = descriptor;
       this.camelCaseNames = camelCaseNames;
       fields = new FieldAccessor[descriptor.getFields().size()];
@@ -2063,16 +1972,19 @@
     /**
      * Ensures the field accessors are initialized. This method is thread-safe.
      *
-     * @param messageClass   The message type.
-     * @param builderClass   The builder type.
+     * @param messageClass The message type.
+     * @param builderClass The builder type.
      * @return this
      */
     public FieldAccessorTable ensureFieldAccessorsInitialized(
-        Class<? extends GeneratedMessage> messageClass,
-        Class<? extends Builder> builderClass) {
-      if (initialized) { return this; }
+        Class<? extends GeneratedMessage> messageClass, Class<? extends Builder> builderClass) {
+      if (initialized) {
+        return this;
+      }
       synchronized (this) {
-        if (initialized) { return this; }
+        if (initialized) {
+          return this;
+        }
         int fieldsSize = fields.length;
         for (int i = 0; i < fieldsSize; i++) {
           FieldDescriptor field = descriptor.getFields().get(i);
@@ -2084,45 +1996,63 @@
           if (field.isRepeated()) {
             if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
               if (field.isMapField() && isMapFieldEnabled(field)) {
-                fields[i] = new MapFieldAccessor(
-                    field, camelCaseNames[i], messageClass, builderClass);
+                fields[i] =
+                    new MapFieldAccessor(field, camelCaseNames[i], messageClass, builderClass);
               } else {
-                fields[i] = new RepeatedMessageFieldAccessor(
-                    field, camelCaseNames[i], messageClass, builderClass);
+                fields[i] =
+                    new RepeatedMessageFieldAccessor(
+                        field, camelCaseNames[i], messageClass, builderClass);
               }
             } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
-              fields[i] = new RepeatedEnumFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass);
+              fields[i] =
+                  new RepeatedEnumFieldAccessor(
+                      field, camelCaseNames[i], messageClass, builderClass);
             } else {
-              fields[i] = new RepeatedFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass);
+              fields[i] =
+                  new RepeatedFieldAccessor(field, camelCaseNames[i], messageClass, builderClass);
             }
           } else {
             if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-              fields[i] = new SingularMessageFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularMessageFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
-              fields[i] = new SingularEnumFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularEnumFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
-              fields[i] = new SingularStringFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularStringFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             } else {
-              fields[i] = new SingularFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             }
           }
         }
 
         int oneofsSize = oneofs.length;
         for (int i = 0; i < oneofsSize; i++) {
-          oneofs[i] = new OneofAccessor(
-              descriptor, camelCaseNames[i + fieldsSize],
-              messageClass, builderClass);
+          oneofs[i] =
+              new OneofAccessor(
+                  descriptor, camelCaseNames[i + fieldsSize], messageClass, builderClass);
         }
         initialized = true;
         camelCaseNames = null;
@@ -2139,13 +2069,11 @@
     /** Get the FieldAccessor for a particular field. */
     private FieldAccessor getField(final FieldDescriptor field) {
       if (field.getContainingType() != descriptor) {
-        throw new IllegalArgumentException(
-          "FieldDescriptor does not match message type.");
+        throw new IllegalArgumentException("FieldDescriptor does not match message type.");
       } else if (field.isExtension()) {
         // If this type had extensions, it would subclass ExtendableMessage,
         // which overrides the reflection interface to handle extensions.
-        throw new IllegalArgumentException(
-          "This type does not have extensions.");
+        throw new IllegalArgumentException("This type does not have extensions.");
       }
       return fields[field.getIndex()];
     }
@@ -2153,51 +2081,65 @@
     /** Get the OneofAccessor for a particular oneof. */
     private OneofAccessor getOneof(final OneofDescriptor oneof) {
       if (oneof.getContainingType() != descriptor) {
-        throw new IllegalArgumentException(
-          "OneofDescriptor does not match message type.");
+        throw new IllegalArgumentException("OneofDescriptor does not match message type.");
       }
       return oneofs[oneof.getIndex()];
     }
 
     /**
-     * Abstract interface that provides access to a single field.  This is
-     * implemented differently depending on the field type and cardinality.
+     * Abstract interface that provides access to a single field. This is implemented differently
+     * depending on the field type and cardinality.
      */
     private interface FieldAccessor {
       Object get(GeneratedMessage message);
+
       Object get(GeneratedMessage.Builder builder);
+
       Object getRaw(GeneratedMessage message);
+
       Object getRaw(GeneratedMessage.Builder builder);
+
       void set(Builder builder, Object value);
+
       Object getRepeated(GeneratedMessage message, int index);
+
       Object getRepeated(GeneratedMessage.Builder builder, int index);
+
       Object getRepeatedRaw(GeneratedMessage message, int index);
+
       Object getRepeatedRaw(GeneratedMessage.Builder builder, int index);
-      void setRepeated(Builder builder,
-                       int index, Object value);
+
+      void setRepeated(Builder builder, int index, Object value);
+
       void addRepeated(Builder builder, Object value);
+
       boolean has(GeneratedMessage message);
+
       boolean has(GeneratedMessage.Builder builder);
+
       int getRepeatedCount(GeneratedMessage message);
+
       int getRepeatedCount(GeneratedMessage.Builder builder);
+
       void clear(Builder builder);
+
       Message.Builder newBuilder();
+
       Message.Builder getBuilder(GeneratedMessage.Builder builder);
-      Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder,
-                                         int index);
+
+      Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index);
     }
 
     /** OneofAccessor provides access to a single oneof. */
     private static class OneofAccessor {
       OneofAccessor(
-          final Descriptor descriptor, final String camelCaseName,
+          final Descriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         this.descriptor = descriptor;
-        caseMethod =
-            getMethodOrDie(messageClass, "get" + camelCaseName + "Case");
-        caseMethodBuilder =
-            getMethodOrDie(builderClass, "get" + camelCaseName + "Case");
+        caseMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Case");
+        caseMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Case");
         clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
       }
 
@@ -2249,27 +2191,32 @@
 
     private static class SingularFieldAccessor implements FieldAccessor {
       SingularFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
         field = descriptor;
         isOneofField = descriptor.getContainingOneof() != null;
-        hasHasMethod = supportFieldPresence(descriptor.getFile())
-            || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
+        hasHasMethod =
+            supportFieldPresence(descriptor.getFile())
+                || (!isOneofField && descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE);
         getMethod = getMethodOrDie(messageClass, "get" + camelCaseName);
         getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName);
         type = getMethod.getReturnType();
         setMethod = getMethodOrDie(builderClass, "set" + camelCaseName, type);
-        hasMethod =
-            hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
+        hasMethod = hasHasMethod ? getMethodOrDie(messageClass, "has" + camelCaseName) : null;
         hasMethodBuilder =
             hasHasMethod ? getMethodOrDie(builderClass, "has" + camelCaseName) : null;
         clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
-        caseMethod = isOneofField ? getMethodOrDie(
-            messageClass, "get" + containingOneofCamelCaseName + "Case") : null;
-        caseMethodBuilder = isOneofField ? getMethodOrDie(
-            builderClass, "get" + containingOneofCamelCaseName + "Case") : null;
+        caseMethod =
+            isOneofField
+                ? getMethodOrDie(messageClass, "get" + containingOneofCamelCaseName + "Case")
+                : null;
+        caseMethodBuilder =
+            isOneofField
+                ? getMethodOrDie(builderClass, "get" + containingOneofCamelCaseName + "Case")
+                : null;
       }
 
       // Note:  We use Java reflection to call public methods rather than
@@ -2300,52 +2247,59 @@
       public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
+
       @Override
       public Object get(GeneratedMessage.Builder builder) {
         return invokeOrDie(getMethodBuilder, builder);
       }
+
       @Override
       public Object getRaw(final GeneratedMessage message) {
         return get(message);
       }
+
       @Override
       public Object getRaw(GeneratedMessage.Builder builder) {
         return get(builder);
       }
+
       @Override
       public void set(final Builder builder, final Object value) {
         invokeOrDie(setMethod, builder, value);
       }
+
       @Override
       public Object getRepeated(final GeneratedMessage message, final int index) {
-        throw new UnsupportedOperationException(
-          "getRepeatedField() called on a singular field.");
+        throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
       }
+
       @Override
       public Object getRepeatedRaw(final GeneratedMessage message, final int index) {
         throw new UnsupportedOperationException(
-          "getRepeatedFieldRaw() called on a singular field.");
+            "getRepeatedFieldRaw() called on a singular field.");
       }
+
       @Override
       public Object getRepeated(GeneratedMessage.Builder builder, int index) {
-        throw new UnsupportedOperationException(
-          "getRepeatedField() called on a singular field.");
+        throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
       }
+
       @Override
       public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
-          "getRepeatedFieldRaw() called on a singular field.");
+            "getRepeatedFieldRaw() called on a singular field.");
       }
+
       @Override
       public void setRepeated(final Builder builder, final int index, final Object value) {
-        throw new UnsupportedOperationException(
-          "setRepeatedField() called on a singular field.");
+        throw new UnsupportedOperationException("setRepeatedField() called on a singular field.");
       }
+
       @Override
       public void addRepeated(final Builder builder, final Object value) {
-        throw new UnsupportedOperationException(
-          "addRepeatedField() called on a singular field.");
+        throw new UnsupportedOperationException("addRepeatedField() called on a singular field.");
       }
+
       @Override
       public boolean has(final GeneratedMessage message) {
         if (!hasHasMethod) {
@@ -2356,6 +2310,7 @@
         }
         return (Boolean) invokeOrDie(hasMethod, message);
       }
+
       @Override
       public boolean has(GeneratedMessage.Builder builder) {
         if (!hasHasMethod) {
@@ -2366,34 +2321,39 @@
         }
         return (Boolean) invokeOrDie(hasMethodBuilder, builder);
       }
+
       @Override
       public int getRepeatedCount(final GeneratedMessage message) {
         throw new UnsupportedOperationException(
-          "getRepeatedFieldSize() called on a singular field.");
+            "getRepeatedFieldSize() called on a singular field.");
       }
+
       @Override
       public int getRepeatedCount(GeneratedMessage.Builder builder) {
         throw new UnsupportedOperationException(
-          "getRepeatedFieldSize() called on a singular field.");
+            "getRepeatedFieldSize() called on a singular field.");
       }
+
       @Override
       public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
+
       @Override
       public Message.Builder newBuilder() {
         throw new UnsupportedOperationException(
-          "newBuilderForField() called on a non-Message type.");
+            "newBuilderForField() called on a non-Message type.");
       }
+
       @Override
       public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
-        throw new UnsupportedOperationException(
-          "getFieldBuilder() called on a non-Message type.");
+        throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
       }
+
       @Override
       public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
-          "getRepeatedFieldBuilder() called on a non-Message type.");
+            "getRepeatedFieldBuilder() called on a non-Message type.");
       }
     }
 
@@ -2410,27 +2370,20 @@
       protected final Method clearMethod;
 
       RepeatedFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
-        getMethod = getMethodOrDie(messageClass,
-                                   "get" + camelCaseName + "List");
-        getMethodBuilder = getMethodOrDie(builderClass,
-                                   "get" + camelCaseName + "List");
-        getRepeatedMethod =
-            getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
+        getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List");
+        getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "List");
+        getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
         getRepeatedMethodBuilder =
             getMethodOrDie(builderClass, "get" + camelCaseName, Integer.TYPE);
         type = getRepeatedMethod.getReturnType();
-        setRepeatedMethod =
-            getMethodOrDie(builderClass, "set" + camelCaseName,
-                           Integer.TYPE, type);
-        addRepeatedMethod =
-            getMethodOrDie(builderClass, "add" + camelCaseName, type);
-        getCountMethod =
-            getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
-        getCountMethodBuilder =
-            getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
+        setRepeatedMethod = getMethodOrDie(builderClass, "set" + camelCaseName, Integer.TYPE, type);
+        addRepeatedMethod = getMethodOrDie(builderClass, "add" + camelCaseName, type);
+        getCountMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Count");
+        getCountMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Count");
 
         clearMethod = getMethodOrDie(builderClass, "clear" + camelCaseName);
       }
@@ -2439,18 +2392,22 @@
       public Object get(final GeneratedMessage message) {
         return invokeOrDie(getMethod, message);
       }
+
       @Override
       public Object get(GeneratedMessage.Builder builder) {
         return invokeOrDie(getMethodBuilder, builder);
       }
+
       @Override
       public Object getRaw(final GeneratedMessage message) {
         return get(message);
       }
+
       @Override
       public Object getRaw(GeneratedMessage.Builder builder) {
         return get(builder);
       }
+
       @Override
       public void set(final Builder builder, final Object value) {
         // Add all the elements individually.  This serves two purposes:
@@ -2462,81 +2419,91 @@
           addRepeated(builder, element);
         }
       }
+
       @Override
       public Object getRepeated(final GeneratedMessage message, final int index) {
         return invokeOrDie(getRepeatedMethod, message, index);
       }
+
       @Override
       public Object getRepeated(GeneratedMessage.Builder builder, int index) {
         return invokeOrDie(getRepeatedMethodBuilder, builder, index);
       }
+
       @Override
       public Object getRepeatedRaw(GeneratedMessage message, int index) {
         return getRepeated(message, index);
       }
+
       @Override
       public Object getRepeatedRaw(GeneratedMessage.Builder builder, int index) {
         return getRepeated(builder, index);
       }
+
       @Override
       public void setRepeated(final Builder builder, final int index, final Object value) {
         invokeOrDie(setRepeatedMethod, builder, index, value);
       }
+
       @Override
       public void addRepeated(final Builder builder, final Object value) {
         invokeOrDie(addRepeatedMethod, builder, value);
       }
+
       @Override
       public boolean has(final GeneratedMessage message) {
-        throw new UnsupportedOperationException(
-          "hasField() called on a repeated field.");
+        throw new UnsupportedOperationException("hasField() called on a repeated field.");
       }
+
       @Override
       public boolean has(GeneratedMessage.Builder builder) {
-        throw new UnsupportedOperationException(
-          "hasField() called on a repeated field.");
+        throw new UnsupportedOperationException("hasField() called on a repeated field.");
       }
+
       @Override
       public int getRepeatedCount(final GeneratedMessage message) {
         return (Integer) invokeOrDie(getCountMethod, message);
       }
+
       @Override
       public int getRepeatedCount(GeneratedMessage.Builder builder) {
         return (Integer) invokeOrDie(getCountMethodBuilder, builder);
       }
+
       @Override
       public void clear(final Builder builder) {
         invokeOrDie(clearMethod, builder);
       }
+
       @Override
       public Message.Builder newBuilder() {
         throw new UnsupportedOperationException(
-          "newBuilderForField() called on a non-Message type.");
+            "newBuilderForField() called on a non-Message type.");
       }
+
       @Override
       public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
-        throw new UnsupportedOperationException(
-          "getFieldBuilder() called on a non-Message type.");
+        throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
       }
+
       @Override
       public Message.Builder getRepeatedBuilder(GeneratedMessage.Builder builder, int index) {
         throw new UnsupportedOperationException(
-          "getRepeatedFieldBuilder() called on a non-Message type.");
+            "getRepeatedFieldBuilder() called on a non-Message type.");
       }
     }
 
     private static class MapFieldAccessor implements FieldAccessor {
       MapFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         field = descriptor;
-        Method getDefaultInstanceMethod =
-            getMethodOrDie(messageClass, "getDefaultInstance");
-        MapField defaultMapField = getMapField(
-            (GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null));
-        mapEntryMessageDefaultInstance =
-            defaultMapField.getMapEntryMessageDefaultInstance();
+        Method getDefaultInstanceMethod = getMethodOrDie(messageClass, "getDefaultInstance");
+        MapField defaultMapField =
+            getMapField((GeneratedMessage) invokeOrDie(getDefaultInstanceMethod, null));
+        mapEntryMessageDefaultInstance = defaultMapField.getMapEntryMessageDefaultInstance();
       }
 
       private final FieldDescriptor field;
@@ -2550,10 +2517,8 @@
         return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
       }
 
-      private MapField<?, ?> getMutableMapField(
-          GeneratedMessage.Builder builder) {
-        return (MapField<?, ?>) builder.internalGetMutableMapField(
-            field.getNumber());
+      private MapField<?, ?> getMutableMapField(GeneratedMessage.Builder builder) {
+        return (MapField<?, ?>) builder.internalGetMutableMapField(field.getNumber());
       }
 
       @Override
@@ -2626,14 +2591,12 @@
 
       @Override
       public boolean has(GeneratedMessage message) {
-        throw new UnsupportedOperationException(
-            "hasField() is not supported for repeated fields.");
+        throw new UnsupportedOperationException("hasField() is not supported for repeated fields.");
       }
 
       @Override
       public boolean has(Builder builder) {
-        throw new UnsupportedOperationException(
-            "hasField() is not supported for repeated fields.");
+        throw new UnsupportedOperationException("hasField() is not supported for repeated fields.");
       }
 
       @Override
@@ -2658,23 +2621,21 @@
 
       @Override
       public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
-        throw new UnsupportedOperationException(
-            "Nested builder not supported for map fields.");
+        throw new UnsupportedOperationException("Nested builder not supported for map fields.");
       }
 
       @Override
       public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
-        throw new UnsupportedOperationException(
-            "Nested builder not supported for map fields.");
+        throw new UnsupportedOperationException("Nested builder not supported for map fields.");
       }
     }
 
     // ---------------------------------------------------------------
 
-    private static final class SingularEnumFieldAccessor
-        extends SingularFieldAccessor {
+    private static final class SingularEnumFieldAccessor extends SingularFieldAccessor {
       SingularEnumFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
@@ -2682,19 +2643,14 @@
 
         enumDescriptor = descriptor.getEnumType();
 
-        valueOfMethod = getMethodOrDie(type, "valueOf",
-                                       EnumValueDescriptor.class);
-        getValueDescriptorMethod =
-          getMethodOrDie(type, "getValueDescriptor");
+        valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class);
+        getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor");
 
         supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
         if (supportUnknownEnumValue) {
-          getValueMethod =
-              getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
-          getValueMethodBuilder =
-              getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
-          setValueMethod =
-              getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
+          getValueMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
+          getValueMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
+          setValueMethod = getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
         }
       }
 
@@ -2729,28 +2685,25 @@
       @Override
       public void set(final Builder builder, final Object value) {
         if (supportUnknownEnumValue) {
-          invokeOrDie(setValueMethod, builder,
-              ((EnumValueDescriptor) value).getNumber());
+          invokeOrDie(setValueMethod, builder, ((EnumValueDescriptor) value).getNumber());
           return;
         }
         super.set(builder, invokeOrDie(valueOfMethod, null, value));
       }
     }
 
-    private static final class RepeatedEnumFieldAccessor
-        extends RepeatedFieldAccessor {
+    private static final class RepeatedEnumFieldAccessor extends RepeatedFieldAccessor {
       RepeatedEnumFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         enumDescriptor = descriptor.getEnumType();
 
-        valueOfMethod = getMethodOrDie(type, "valueOf",
-                                       EnumValueDescriptor.class);
-        getValueDescriptorMethod =
-          getMethodOrDie(type, "getValueDescriptor");
+        valueOfMethod = getMethodOrDie(type, "valueOf", EnumValueDescriptor.class);
+        getValueDescriptorMethod = getMethodOrDie(type, "getValueDescriptor");
 
         supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
         if (supportUnknownEnumValue) {
@@ -2764,6 +2717,7 @@
               getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
         }
       }
+
       private EnumDescriptor enumDescriptor;
 
       private final Method valueOfMethod;
@@ -2798,41 +2752,37 @@
       }
 
       @Override
-      public Object getRepeated(final GeneratedMessage message,
-                                final int index) {
+      public Object getRepeated(final GeneratedMessage message, final int index) {
         if (supportUnknownEnumValue) {
           int value = (Integer) invokeOrDie(getRepeatedValueMethod, message, index);
           return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
         }
-        return invokeOrDie(getValueDescriptorMethod,
-          super.getRepeated(message, index));
+        return invokeOrDie(getValueDescriptorMethod, super.getRepeated(message, index));
       }
+
       @Override
-      public Object getRepeated(final GeneratedMessage.Builder builder,
-                                final int index) {
+      public Object getRepeated(final GeneratedMessage.Builder builder, final int index) {
         if (supportUnknownEnumValue) {
           int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
           return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
         }
-        return invokeOrDie(getValueDescriptorMethod,
-          super.getRepeated(builder, index));
+        return invokeOrDie(getValueDescriptorMethod, super.getRepeated(builder, index));
       }
+
       @Override
-      public void setRepeated(final Builder builder,
-                              final int index, final Object value) {
+      public void setRepeated(final Builder builder, final int index, final Object value) {
         if (supportUnknownEnumValue) {
-          invokeOrDie(setRepeatedValueMethod, builder, index,
-              ((EnumValueDescriptor) value).getNumber());
+          invokeOrDie(
+              setRepeatedValueMethod, builder, index, ((EnumValueDescriptor) value).getNumber());
           return;
         }
-        super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null,
-                          value));
+        super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value));
       }
+
       @Override
       public void addRepeated(final Builder builder, final Object value) {
         if (supportUnknownEnumValue) {
-          invokeOrDie(addRepeatedValueMethod, builder,
-              ((EnumValueDescriptor) value).getNumber());
+          invokeOrDie(addRepeatedValueMethod, builder, ((EnumValueDescriptor) value).getNumber());
           return;
         }
         super.addRepeated(builder, invokeOrDie(valueOfMethod, null, value));
@@ -2844,29 +2794,25 @@
     /**
      * Field accessor for string fields.
      *
-     * <p>This class makes getFooBytes() and setFooBytes() available for
-     * reflection API so that reflection based serialize/parse functions can
-     * access the raw bytes of the field to preserve non-UTF8 bytes in the
-     * string.
+     * <p>This class makes getFooBytes() and setFooBytes() available for reflection API so that
+     * reflection based serialize/parse functions can access the raw bytes of the field to preserve
+     * non-UTF8 bytes in the string.
      *
-     * <p>This ensures the serialize/parse round-trip safety, which is important
-     * for servers which forward messages.
+     * <p>This ensures the serialize/parse round-trip safety, which is important for servers which
+     * forward messages.
      */
-    private static final class SingularStringFieldAccessor
-        extends SingularFieldAccessor {
+    private static final class SingularStringFieldAccessor extends SingularFieldAccessor {
       SingularStringFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
-        super(descriptor, camelCaseName, messageClass, builderClass,
-            containingOneofCamelCaseName);
-        getBytesMethod = getMethodOrDie(messageClass,
-            "get" + camelCaseName + "Bytes");
-        getBytesMethodBuilder = getMethodOrDie(builderClass,
-            "get" + camelCaseName + "Bytes");
-        setBytesMethodBuilder = getMethodOrDie(builderClass,
-            "set" + camelCaseName + "Bytes", ByteString.class);
+        super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+        getBytesMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Bytes");
+        getBytesMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Bytes");
+        setBytesMethodBuilder =
+            getMethodOrDie(builderClass, "set" + camelCaseName + "Bytes", ByteString.class);
       }
 
       private final Method getBytesMethod;
@@ -2895,19 +2841,17 @@
 
     // ---------------------------------------------------------------
 
-    private static final class SingularMessageFieldAccessor
-        extends SingularFieldAccessor {
+    private static final class SingularMessageFieldAccessor extends SingularFieldAccessor {
       SingularMessageFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass,
           final String containingOneofCamelCaseName) {
-        super(descriptor, camelCaseName, messageClass, builderClass,
-            containingOneofCamelCaseName);
+        super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
-        getBuilderMethodBuilder =
-            getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
+        getBuilderMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
       }
 
       private final Method newBuilderMethod;
@@ -2922,7 +2866,8 @@
           // DynamicMessage -- we should accept it.  In this case we can make
           // a copy of the message.
           return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
-                  .mergeFrom((Message) value).buildPartial();
+              .mergeFrom((Message) value)
+              .buildPartial();
         }
       }
 
@@ -2930,27 +2875,29 @@
       public void set(final Builder builder, final Object value) {
         super.set(builder, coerceType(value));
       }
+
       @Override
       public Message.Builder newBuilder() {
         return (Message.Builder) invokeOrDie(newBuilderMethod, null);
       }
+
       @Override
       public Message.Builder getBuilder(GeneratedMessage.Builder builder) {
         return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
       }
     }
 
-    private static final class RepeatedMessageFieldAccessor
-        extends RepeatedFieldAccessor {
+    private static final class RepeatedMessageFieldAccessor extends RepeatedFieldAccessor {
       RepeatedMessageFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessage> messageClass,
           final Class<? extends Builder> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
-        getBuilderMethodBuilder = getMethodOrDie(builderClass,
-            "get" + camelCaseName + "Builder", Integer.TYPE);
+        getBuilderMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName + "Builder", Integer.TYPE);
       }
 
       private final Method newBuilderMethod;
@@ -2965,36 +2912,39 @@
           // DynamicMessage -- we should accept it.  In this case we can make
           // a copy of the message.
           return ((Message.Builder) invokeOrDie(newBuilderMethod, null))
-                  .mergeFrom((Message) value).build();
+              .mergeFrom((Message) value)
+              .build();
         }
       }
 
       @Override
-      public void setRepeated(final Builder builder,
-                              final int index, final Object value) {
+      public void setRepeated(final Builder builder, final int index, final Object value) {
         super.setRepeated(builder, index, coerceType(value));
       }
+
       @Override
       public void addRepeated(final Builder builder, final Object value) {
         super.addRepeated(builder, coerceType(value));
       }
+
       @Override
       public Message.Builder newBuilder() {
         return (Message.Builder) invokeOrDie(newBuilderMethod, null);
       }
+
       @Override
       public Message.Builder getRepeatedBuilder(
           final GeneratedMessage.Builder builder, final int index) {
-        return (Message.Builder) invokeOrDie(
-            getBuilderMethodBuilder, builder, index);
+        return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder, index);
       }
     }
   }
 
   /**
-   * Replaces this object in the output stream with a serialized form.
-   * Part of Java's serialization magic.  Generated sub-classes must override
-   * this method by calling {@code return super.writeReplace();}
+   * Replaces this object in the output stream with a serialized form. Part of Java's serialization
+   * magic. Generated sub-classes must override this method by calling {@code return
+   * super.writeReplace();}
+   *
    * @return a SerializedForm of this message
    */
   protected Object writeReplace() throws ObjectStreamException {
@@ -3002,12 +2952,10 @@
   }
 
   /**
-   * Checks that the {@link Extension} is non-Lite and returns it as a
-   * {@link GeneratedExtension}.
+   * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}.
    */
   private static <MessageType extends ExtendableMessage<MessageType>, T>
-    Extension<MessageType, T> checkNotLite(
-        ExtensionLite<MessageType, T> extension) {
+      Extension<MessageType, T> checkNotLite(ExtensionLite<MessageType, T> extension) {
     if (extension.isLite()) {
       throw new IllegalArgumentException("Expected non-lite extension.");
     }
@@ -3040,8 +2988,8 @@
     }
   }
 
-  protected static void writeStringNoTag(
-      CodedOutputStream output, final Object value) throws IOException {
+  protected static void writeStringNoTag(CodedOutputStream output, final Object value)
+      throws IOException {
     if (value instanceof String) {
       output.writeStringNoTag((String) value);
     } else {
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 1ef2143..55d6dc9 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageLite.java
@@ -188,7 +188,7 @@
   // any unnecessary intermediary allocations while reducing the generated code size.
 
   /** Lazily initializes unknown fields. */
-  private final void ensureUnknownFieldsInitialized() {
+  private void ensureUnknownFieldsInitialized() {
     if (unknownFields == UnknownFieldSetLite.getDefaultInstance()) {
       unknownFields = UnknownFieldSetLite.newInstance();
     }
@@ -295,11 +295,16 @@
    *
    * <p>For use by generated code only.
    */
-  protected abstract Object dynamicMethod(MethodToInvoke method, Object arg0, Object arg1);
+  protected abstract Object dynamicMethod(
+      MethodToInvoke method,
+          Object arg0,
+          Object arg1);
 
   /** Same as {@link #dynamicMethod(MethodToInvoke, Object, Object)} with {@code null} padding. */
   @CanIgnoreReturnValue
-  protected Object dynamicMethod(MethodToInvoke method, Object arg0) {
+  protected Object dynamicMethod(
+      MethodToInvoke method,
+          Object arg0) {
     return dynamicMethod(method, arg0, null);
   }
 
@@ -581,7 +586,6 @@
     }
   }
 
-
   // =================================================================
   // Extensions-related stuff
 
@@ -1245,7 +1249,6 @@
       return ((Builder) to).mergeFrom((GeneratedMessageLite) from);
     }
 
-
     @Override
     public int compareTo(ExtensionDescriptor other) {
       return number - other.number;
@@ -1286,7 +1289,6 @@
     }
   }
 
-
   /**
    * Lite equivalent to {@link GeneratedMessage.GeneratedExtension}.
    *
@@ -1350,11 +1352,11 @@
     }
 
     @SuppressWarnings("unchecked")
-    Object fromFieldSetType(final Object value) {
+    Object fromFieldSetType(Object value) {
       if (descriptor.isRepeated()) {
         if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
-          final List result = new ArrayList<>();
-          for (final Object element : (List) value) {
+          List<Object> result = new ArrayList<>();
+          for (Object element : (List) value) {
             result.add(singularFromFieldSetType(element));
           }
           return result;
@@ -1366,7 +1368,7 @@
       }
     }
 
-    Object singularFromFieldSetType(final Object value) {
+    Object singularFromFieldSetType(Object value) {
       if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
         return descriptor.enumTypeMap.findValueByNumber((Integer) value);
       } else {
@@ -1374,12 +1376,11 @@
       }
     }
 
-    @SuppressWarnings("unchecked")
-    Object toFieldSetType(final Object value) {
+    Object toFieldSetType(Object value) {
       if (descriptor.isRepeated()) {
         if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
-          final List result = new ArrayList<>();
-          for (final Object element : (List) value) {
+          List<Object> result = new ArrayList<>();
+          for (Object element : (List) value) {
             result.add(singularToFieldSetType(element));
           }
           return result;
@@ -1391,7 +1392,7 @@
       }
     }
 
-    Object singularToFieldSetType(final Object value) {
+    Object singularToFieldSetType(Object value) {
       if (descriptor.getLiteJavaType() == WireFormat.JavaType.ENUM) {
         return ((Internal.EnumLite) value).getNumber();
       } else {
@@ -1429,7 +1430,6 @@
 
     // since v3.6.1
     private final Class<?> messageClass;
-    // only included for backwards compatibility before messageClass was added
     private final String messageClassName;
     private final byte[] asBytes;
 
@@ -1440,7 +1440,7 @@
      */
     SerializedForm(MessageLite regularForm) {
       messageClass = regularForm.getClass();
-      messageClassName = messageClass.getName();
+      messageClassName = regularForm.getClass().getName();
       asBytes = regularForm.toByteArray();
     }
 
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 355bf46..9ed4d53 100644
--- a/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
+++ b/java/core/src/main/java/com/google/protobuf/GeneratedMessageV3.java
@@ -69,15 +69,13 @@
 import java.util.TreeMap;
 
 /**
- * All generated protocol message classes extend this class.  This class
- * implements most of the Message and Builder interfaces using Java reflection.
- * Users can ignore this class and pretend that generated messages implement
- * the Message interface directly.
+ * All generated protocol message classes extend this class. This class implements most of the
+ * Message and Builder interfaces using Java reflection. Users can ignore this class and pretend
+ * that generated messages implement the Message interface directly.
  *
  * @author kenton@google.com Kenton Varda
  */
-public abstract class GeneratedMessageV3 extends AbstractMessage
-    implements Serializable {
+public abstract class GeneratedMessageV3 extends AbstractMessage implements Serializable {
   private static final long serialVersionUID = 1L;
 
   /**
@@ -87,7 +85,11 @@
    */
   protected static boolean alwaysUseFieldBuilders = false;
 
-  /** For use by generated code only.  */
+  /**
+   * For use by generated code only.
+   *
+   * <p>TODO(b/258340024): mark this private and final (breaking change)
+   */
   protected UnknownFieldSet unknownFields;
 
   protected GeneratedMessageV3() {
@@ -98,33 +100,36 @@
     unknownFields = builder.getUnknownFields();
   }
 
+  /** TODO(b/258340024): Remove this unnecessary intermediate implementation of this method. */
   @Override
   public Parser<? extends GeneratedMessageV3> getParserForType() {
-    throw new UnsupportedOperationException(
-        "This is supposed to be overridden by subclasses.");
+    throw new UnsupportedOperationException("This is supposed to be overridden by subclasses.");
   }
 
- /**
-  * @see #setAlwaysUseFieldBuildersForTesting(boolean)
-  */
+  /**
+   * TODO(b/249158148): Stop using SingleFieldBuilder and remove this setting
+   *
+   * @see #setAlwaysUseFieldBuildersForTesting(boolean)
+   */
   static void enableAlwaysUseFieldBuildersForTesting() {
     setAlwaysUseFieldBuildersForTesting(true);
   }
 
   /**
-   * For testing. Allows a test to disable/re-enable the optimization that avoids
-   * using field builders for nested messages until they are requested. By disabling
-   * this optimization, existing tests can be reused to test the field builders.
-   * See {@link RepeatedFieldBuilder} and {@link SingleFieldBuilder}.
+   * For testing. Allows a test to disable/re-enable the optimization that avoids using field
+   * builders for nested messages until they are requested. By disabling this optimization, existing
+   * tests can be reused to test the field builders. See {@link RepeatedFieldBuilder} and {@link
+   * SingleFieldBuilder}.
+   *
+   * <p>TODO(b/249158148): Stop using SingleFieldBuilder and remove this setting
    */
   static void setAlwaysUseFieldBuildersForTesting(boolean useBuilders) {
     alwaysUseFieldBuilders = useBuilders;
   }
 
   /**
-   * Get the FieldAccessorTable for this type.  We can't have the message
-   * class pass this in to the constructor because of bootstrapping trouble
-   * with DescriptorProtos.
+   * Get the FieldAccessorTable for this type. We can't have the message class pass this in to the
+   * constructor because of bootstrapping trouble with DescriptorProtos.
    */
   protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
@@ -140,8 +145,7 @@
   protected void mergeFromAndMakeImmutableInternal(
       CodedInputStream input, ExtensionRegistryLite extensionRegistry)
       throws InvalidProtocolBufferException {
-    Schema<GeneratedMessageV3> schema =
-        (Schema<GeneratedMessageV3>) Protobuf.getInstance().schemaFor(this);
+    Schema<GeneratedMessageV3> schema = Protobuf.getInstance().schemaFor(this);
     try {
       schema.mergeFrom(this, CodedInputStreamReader.forCodedInput(input), extensionRegistry);
     } catch (InvalidProtocolBufferException e) {
@@ -153,16 +157,14 @@
   }
 
   /**
-   * Internal helper to return a modifiable map containing all the fields.
-   * The returned Map is modifiable so that the caller can add additional
-   * extension fields to implement {@link #getAllFields()}.
+   * Internal helper to return a modifiable map containing all the fields. The returned Map is
+   * modifiable so that the caller can add additional extension fields to implement {@link
+   * #getAllFields()}.
    *
    * @param getBytesForString whether to generate ByteString for string fields
    */
-  private Map<FieldDescriptor, Object> getAllFieldsMutable(
-      boolean getBytesForString) {
-    final TreeMap<FieldDescriptor, Object> result =
-      new TreeMap<FieldDescriptor, Object>();
+  private Map<FieldDescriptor, Object> getAllFieldsMutable(boolean getBytesForString) {
+    final TreeMap<FieldDescriptor, Object> result = new TreeMap<>();
     final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
     final List<FieldDescriptor> fields = descriptor.getFields();
 
@@ -206,6 +208,7 @@
     return result;
   }
 
+  // TODO(b/258342840): compute this at {@code build()} time in the Builder class.
   @Override
   public boolean isInitialized() {
     for (final FieldDescriptor field : getDescriptorForType().getFields()) {
@@ -218,8 +221,8 @@
       // Check that embedded messages are initialized.
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
         if (field.isRepeated()) {
-          @SuppressWarnings("unchecked") final
-          List<Message> messageList = (List<Message>) getField(field);
+          @SuppressWarnings("unchecked")
+          final List<Message> messageList = (List<Message>) getField(field);
           for (final Message element : messageList) {
             if (!element.isInitialized()) {
               return false;
@@ -238,23 +241,19 @@
 
   @Override
   public Map<FieldDescriptor, Object> getAllFields() {
-    return Collections.unmodifiableMap(
-        getAllFieldsMutable(/* getBytesForString = */ false));
+    return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ false));
   }
 
   /**
-   * Returns a collection of all the fields in this message which are set
-   * and their corresponding values.  A singular ("required" or "optional")
-   * field is set iff hasField() returns true for that field.  A "repeated"
-   * field is set iff getRepeatedFieldCount() is greater than zero.  The
-   * values are exactly what would be returned by calling
-   * {@link #getFieldRaw(Descriptors.FieldDescriptor)} for each field.  The map
-   * is guaranteed to be a sorted map, so iterating over it will return fields
-   * in order by field number.
+   * Returns a collection of all the fields in this message which are set and their corresponding
+   * values. A singular ("required" or "optional") field is set iff hasField() returns true for that
+   * field. A "repeated" field is set iff getRepeatedFieldCount() is greater than zero. The values
+   * are exactly what would be returned by calling {@link #getFieldRaw(Descriptors.FieldDescriptor)}
+   * for each field. The map is guaranteed to be a sorted map, so iterating over it will return
+   * fields in order by field number.
    */
   Map<FieldDescriptor, Object> getAllFieldsRaw() {
-    return Collections.unmodifiableMap(
-        getAllFieldsMutable(/* getBytesForString = */ true));
+    return Collections.unmodifiableMap(getAllFieldsMutable(/* getBytesForString = */ true));
   }
 
   @Override
@@ -278,12 +277,11 @@
   }
 
   /**
-   * Obtains the value of the given field, or the default value if it is
-   * not set.  For primitive fields, the boxed primitive value is returned.
-   * For enum fields, the EnumValueDescriptor for the value is returned. For
-   * embedded message fields, the sub-message is returned.  For repeated
-   * fields, a java.util.List is returned. For present string fields, a
-   * ByteString is returned representing the bytes that the field contains.
+   * Obtains the value of the given field, or the default value if it is not set. For primitive
+   * fields, the boxed primitive value is returned. For enum fields, the EnumValueDescriptor for the
+   * value is returned. For embedded message fields, the sub-message is returned. For repeated
+   * fields, a java.util.List is returned. For present string fields, a ByteString is returned
+   * representing the bytes that the field contains.
    */
   Object getFieldRaw(final FieldDescriptor field) {
     return internalGetFieldAccessorTable().getField(field).getRaw(this);
@@ -291,21 +289,26 @@
 
   @Override
   public int getRepeatedFieldCount(final FieldDescriptor field) {
-    return internalGetFieldAccessorTable().getField(field)
-      .getRepeatedCount(this);
+    return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this);
   }
 
   @Override
   public Object getRepeatedField(final FieldDescriptor field, final int index) {
-    return internalGetFieldAccessorTable().getField(field)
-      .getRepeated(this, index);
+    return internalGetFieldAccessorTable().getField(field).getRepeated(this, index);
   }
 
+  // TODO(b/258340024): This method should be final.
   @Override
   public UnknownFieldSet getUnknownFields() {
     return unknownFields;
   }
 
+  // TODO(b/258348681): This should go away when Schema classes cannot modify immutable
+  // GeneratedMessageV3 objects anymore.
+  void setUnknownFields(UnknownFieldSet unknownFields) {
+    this.unknownFields = unknownFields;
+  }
+
   /**
    * Called by subclasses to parse an unknown field.
    *
@@ -340,6 +343,7 @@
     return parseUnknownField(input, unknownFields, extensionRegistry, tag);
   }
 
+  /** Used by generated code. */
   protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input)
       throws IOException {
     try {
@@ -349,8 +353,9 @@
     }
   }
 
-  protected static <M extends Message> M parseWithIOException(Parser<M> parser, InputStream input,
-      ExtensionRegistryLite extensions) throws IOException {
+  /** Used by generated code. */
+  protected static <M extends Message> M parseWithIOException(
+      Parser<M> parser, InputStream input, ExtensionRegistryLite extensions) throws IOException {
     try {
       return parser.parseFrom(input, extensions);
     } catch (InvalidProtocolBufferException e) {
@@ -358,8 +363,9 @@
     }
   }
 
-  protected static <M extends Message> M parseWithIOException(Parser<M> parser,
-      CodedInputStream input) throws IOException {
+  /** Used by generated code. */
+  protected static <M extends Message> M parseWithIOException(
+      Parser<M> parser, CodedInputStream input) throws IOException {
     try {
       return parser.parseFrom(input);
     } catch (InvalidProtocolBufferException e) {
@@ -367,8 +373,10 @@
     }
   }
 
-  protected static <M extends Message> M parseWithIOException(Parser<M> parser,
-      CodedInputStream input, ExtensionRegistryLite extensions) throws IOException {
+  /** Used by generated code. */
+  protected static <M extends Message> M parseWithIOException(
+      Parser<M> parser, CodedInputStream input, ExtensionRegistryLite extensions)
+      throws IOException {
     try {
       return parser.parseFrom(input, extensions);
     } catch (InvalidProtocolBufferException e) {
@@ -376,8 +384,9 @@
     }
   }
 
-  protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
-      InputStream input) throws IOException {
+  /** Used by generated code. */
+  protected static <M extends Message> M parseDelimitedWithIOException(
+      Parser<M> parser, InputStream input) throws IOException {
     try {
       return parser.parseDelimitedFrom(input);
     } catch (InvalidProtocolBufferException e) {
@@ -385,8 +394,9 @@
     }
   }
 
-  protected static <M extends Message> M parseDelimitedWithIOException(Parser<M> parser,
-      InputStream input, ExtensionRegistryLite extensions) throws IOException {
+  /** Used by generated code. */
+  protected static <M extends Message> M parseDelimitedWithIOException(
+      Parser<M> parser, InputStream input, ExtensionRegistryLite extensions) throws IOException {
     try {
       return parser.parseDelimitedFrom(input, extensions);
     } catch (InvalidProtocolBufferException e) {
@@ -402,6 +412,7 @@
     return IntArrayList.emptyList();
   }
 
+  // TODO(b/258340024): Unused. Remove.
   protected static IntList newIntList() {
     return new IntArrayList();
   }
@@ -416,6 +427,7 @@
     return LongArrayList.emptyList();
   }
 
+  // TODO(b/258340024): Unused. Remove.
   protected static LongList newLongList() {
     return new LongArrayList();
   }
@@ -430,6 +442,7 @@
     return FloatArrayList.emptyList();
   }
 
+  // TODO(b/258340024): Unused. Remove.
   protected static FloatList newFloatList() {
     return new FloatArrayList();
   }
@@ -444,6 +457,7 @@
     return DoubleArrayList.emptyList();
   }
 
+  // TODO(b/258340024): Unused. Remove.
   protected static DoubleList newDoubleList() {
     return new DoubleArrayList();
   }
@@ -458,6 +472,7 @@
     return BooleanArrayList.emptyList();
   }
 
+  // TODO(b/258340024): Unused. Remove.
   protected static BooleanList newBooleanList() {
     return new BooleanArrayList();
   }
@@ -468,7 +483,6 @@
         size == 0 ? AbstractProtobufList.DEFAULT_CAPACITY : size * 2);
   }
 
-
   @Override
   public void writeTo(final CodedOutputStream output) throws IOException {
     MessageReflection.writeMessageTo(this, getAllFieldsRaw(), output, false);
@@ -486,26 +500,20 @@
     return memoizedSize;
   }
 
-
-
   /**
    * This class is used to make a generated protected method inaccessible from user's code (e.g.,
    * the {@link #newInstance} method below). When this class is used as a parameter's type in a
-   * generated protected method, the method is visible to user's code in the same package, but
-   * since the constructor of this class is private to protobuf runtime, user's code can't obtain
-   * an instance of this class and as such can't actually make a method call on the protected
-   * method.
+   * generated protected method, the method is visible to user's code in the same package, but since
+   * the constructor of this class is private to protobuf runtime, user's code can't obtain an
+   * instance of this class and as such can't actually make a method call on the protected method.
    */
   protected static final class UnusedPrivateParameter {
     static final UnusedPrivateParameter INSTANCE = new UnusedPrivateParameter();
 
-    private UnusedPrivateParameter() {
-    }
+    private UnusedPrivateParameter() {}
   }
 
-  /**
-   * Creates a new instance of this message type. Overridden in the generated code.
-   */
+  /** Creates a new instance of this message type. Overridden in the generated code. */
   @SuppressWarnings({"unused"})
   protected Object newInstance(UnusedPrivateParameter unused) {
     throw new UnsupportedOperationException("This method must be overridden by the subclass.");
@@ -513,38 +521,41 @@
 
   /**
    * Used by parsing constructors in generated classes.
+   *
+   * <p>TODO(b/258340024): remove unused method (extensions should be immutable after build)
    */
   protected void makeExtensionsImmutable() {
     // Noop for messages without extensions.
   }
 
   /**
-   * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this
-   * interface to AbstractMessage in order to versioning GeneratedMessageV3 but
-   * this move breaks binary compatibility for AppEngine. After AppEngine is
-   * fixed we can exclude this from google3.
+   * TODO(xiaofeng): remove this after b/29368482 is fixed. We need to move this interface to
+   * AbstractMessage in order to versioning GeneratedMessageV3 but this move breaks binary
+   * compatibility for AppEngine. After AppEngine is fixed we can exclude this from google3.
+   *
+   * <p>TODO(b/258340024): Remove at breaking change since b/29368482 was fixed in 2020
    */
   protected interface BuilderParent extends AbstractMessage.BuilderParent {}
 
-  /**
-   * TODO(xiaofeng): remove this together with GeneratedMessageV3.BuilderParent.
-   */
+  /** TODO(b/258340024): remove this together with GeneratedMessageV3.BuilderParent. */
   protected abstract Message.Builder newBuilderForType(BuilderParent parent);
 
+  /** TODO(b/258340024): generated class should implement this directly */
   @Override
   protected Message.Builder newBuilderForType(final AbstractMessage.BuilderParent parent) {
-    return newBuilderForType(new BuilderParent() {
-      @Override
-      public void markDirty() {
-        parent.markDirty();
-      }
-    });
+    return newBuilderForType(
+        new BuilderParent() {
+          @Override
+          public void markDirty() {
+            parent.markDirty();
+          }
+        });
   }
 
-
+  /** Builder class for {@link GeneratedMessageV3}. */
   @SuppressWarnings("unchecked")
-  public abstract static class Builder <BuilderType extends Builder<BuilderType>>
-      extends AbstractMessage.Builder<BuilderType> {
+  public abstract static class Builder<BuilderT extends Builder<BuilderT>>
+      extends AbstractMessage.Builder<BuilderT> {
 
     private BuilderParent builderParent;
 
@@ -580,9 +591,7 @@
       builderParent = null;
     }
 
-    /**
-     * Called by the subclass when a message is built.
-     */
+    /** Called by the subclass when a message is built. */
     protected void onBuilt() {
       if (builderParent != null) {
         markClean();
@@ -590,8 +599,8 @@
     }
 
     /**
-     * Called by the subclass or a builder to notify us that a message was
-     * built and may be cached and therefore invalidations are needed.
+     * Called by the subclass or a builder to notify us that a message was built and may be cached
+     * and therefore invalidations are needed.
      */
     @Override
     protected void markClean() {
@@ -608,28 +617,26 @@
     }
 
     @Override
-    public BuilderType clone() {
-      BuilderType builder =
-          (BuilderType) getDefaultInstanceForType().newBuilderForType();
+    public BuilderT clone() {
+      BuilderT builder = (BuilderT) getDefaultInstanceForType().newBuilderForType();
       builder.mergeFrom(buildPartial());
       return builder;
     }
 
     /**
-     * Called by the initialization and clear code paths to allow subclasses to
-     * reset any of their builtin fields back to the initial values.
+     * Called by the initialization and clear code paths to allow subclasses to reset any of their
+     * builtin fields back to the initial values.
      */
     @Override
-    public BuilderType clear() {
+    public BuilderT clear() {
       unknownFieldsOrBuilder = UnknownFieldSet.getDefaultInstance();
       onChanged();
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     /**
-     * Get the FieldAccessorTable for this type.  We can't have the message
-     * class pass this in to the constructor because of bootstrapping trouble
-     * with DescriptorProtos.
+     * Get the FieldAccessorTable for this type. We can't have the message class pass this in to the
+     * constructor because of bootstrapping trouble with DescriptorProtos.
      */
     protected abstract FieldAccessorTable internalGetFieldAccessorTable();
 
@@ -645,8 +652,7 @@
 
     /** Internal helper which returns a mutable map. */
     private Map<FieldDescriptor, Object> getAllFieldsMutable() {
-      final TreeMap<FieldDescriptor, Object> result =
-        new TreeMap<FieldDescriptor, Object>();
+      final TreeMap<FieldDescriptor, Object> result = new TreeMap<>();
       final Descriptor descriptor = internalGetFieldAccessorTable().descriptor;
       final List<FieldDescriptor> fields = descriptor.getFields();
 
@@ -698,8 +704,7 @@
 
     @Override
     public Message.Builder getRepeatedFieldBuilder(final FieldDescriptor field, int index) {
-      return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(
-          this, index);
+      return internalGetFieldAccessorTable().getField(field).getRepeatedBuilder(this, index);
     }
 
     @Override
@@ -723,93 +728,88 @@
       if (field.isRepeated()) {
         // The underlying list object is still modifiable at this point.
         // Make sure not to expose the modifiable list to the caller.
-        return Collections.unmodifiableList((List) object);
+        return Collections.unmodifiableList((List<?>) object);
       } else {
         return object;
       }
     }
 
     @Override
-    public BuilderType setField(final FieldDescriptor field, final Object value) {
+    public BuilderT setField(final FieldDescriptor field, final Object value) {
       internalGetFieldAccessorTable().getField(field).set(this, value);
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     @Override
-    public BuilderType clearField(final FieldDescriptor field) {
+    public BuilderT clearField(final FieldDescriptor field) {
       internalGetFieldAccessorTable().getField(field).clear(this);
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     @Override
-    public BuilderType clearOneof(final OneofDescriptor oneof) {
+    public BuilderT clearOneof(final OneofDescriptor oneof) {
       internalGetFieldAccessorTable().getOneof(oneof).clear(this);
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     @Override
     public int getRepeatedFieldCount(final FieldDescriptor field) {
-      return internalGetFieldAccessorTable().getField(field)
-          .getRepeatedCount(this);
+      return internalGetFieldAccessorTable().getField(field).getRepeatedCount(this);
     }
 
     @Override
     public Object getRepeatedField(final FieldDescriptor field, final int index) {
-      return internalGetFieldAccessorTable().getField(field)
-          .getRepeated(this, index);
+      return internalGetFieldAccessorTable().getField(field).getRepeated(this, index);
     }
 
     @Override
-    public BuilderType setRepeatedField(
+    public BuilderT setRepeatedField(
         final FieldDescriptor field, final int index, final Object value) {
-      internalGetFieldAccessorTable().getField(field)
-        .setRepeated(this, index, value);
-      return (BuilderType) this;
+      internalGetFieldAccessorTable().getField(field).setRepeated(this, index, value);
+      return (BuilderT) this;
     }
 
     @Override
-    public BuilderType addRepeatedField(final FieldDescriptor field, final Object value) {
+    public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) {
       internalGetFieldAccessorTable().getField(field).addRepeated(this, value);
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
-    private BuilderType setUnknownFieldsInternal(final UnknownFieldSet unknownFields) {
+    private BuilderT setUnknownFieldsInternal(final UnknownFieldSet unknownFields) {
       unknownFieldsOrBuilder = unknownFields;
       onChanged();
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     @Override
-    public BuilderType setUnknownFields(final UnknownFieldSet unknownFields) {
+    public BuilderT setUnknownFields(final UnknownFieldSet unknownFields) {
       return setUnknownFieldsInternal(unknownFields);
     }
 
     /**
-     * This method is obsolete, but we must retain it for compatibility with
-     * older generated code.
+     * This method is obsolete, but we must retain it for compatibility with older generated code.
      */
-    protected BuilderType setUnknownFieldsProto3(final UnknownFieldSet unknownFields) {
+    protected BuilderT setUnknownFieldsProto3(final UnknownFieldSet unknownFields) {
       return setUnknownFieldsInternal(unknownFields);
     }
 
     @Override
-    public BuilderType mergeUnknownFields(final UnknownFieldSet unknownFields) {
+    public BuilderT mergeUnknownFields(final UnknownFieldSet unknownFields) {
       if (UnknownFieldSet.getDefaultInstance().equals(unknownFields)) {
-        return (BuilderType) this;
+        return (BuilderT) this;
       }
 
       if (UnknownFieldSet.getDefaultInstance().equals(unknownFieldsOrBuilder)) {
         unknownFieldsOrBuilder = unknownFields;
         onChanged();
-        return (BuilderType) this;
+        return (BuilderT) this;
       }
 
       getUnknownFieldSetBuilder().mergeFrom(unknownFields);
       onChanged();
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
-
     @Override
     public boolean isInitialized() {
       for (final FieldDescriptor field : getDescriptorForType().getFields()) {
@@ -822,16 +822,15 @@
         // Check that embedded messages are initialized.
         if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
           if (field.isRepeated()) {
-            @SuppressWarnings("unchecked") final
-            List<Message> messageList = (List<Message>) getField(field);
+            @SuppressWarnings("unchecked")
+            final List<Message> messageList = (List<Message>) getField(field);
             for (final Message element : messageList) {
               if (!element.isInitialized()) {
                 return false;
               }
             }
           } else {
-            if (hasField(field) &&
-                !((Message) getField(field)).isInitialized()) {
+            if (hasField(field) && !((Message) getField(field)).isInitialized()) {
               return false;
             }
           }
@@ -889,9 +888,8 @@
     }
 
     /**
-     * Implementation of {@link BuilderParent} for giving to our children. This
-     * small inner class makes it so we don't publicly expose the BuilderParent
-     * methods.
+     * Implementation of {@link BuilderParent} for giving to our children. This small inner class
+     * makes it so we don't publicly expose the BuilderParent methods.
      */
     private class BuilderParentImpl implements BuilderParent {
 
@@ -903,6 +901,7 @@
 
     /**
      * Gets the {@link BuilderParent} for giving to our children.
+     *
      * @return The builder parent for our children.
      */
     protected BuilderParent getParentForChildren() {
@@ -913,8 +912,8 @@
     }
 
     /**
-     * Called when a the builder or one of its nested children has changed
-     * and any parent should be notified of its invalidation.
+     * Called when a builder or one of its nested children has changed and any parent should be
+     * notified of its invalidation.
      */
     protected final void onChanged() {
       if (isClean && builderParent != null) {
@@ -926,22 +925,19 @@
     }
 
     /**
-     * Gets the map field with the given field number. This method should be
-     * overridden in the generated message class if the message contains map
-     * fields.
+     * Gets the map field with the given field number. This method should be overridden in the
+     * generated message class if the message contains map fields.
      *
-     * Unlike other field types, reflection support for map fields can't be
-     * implemented based on generated public API because we need to access a
-     * map field as a list in reflection API but the generated API only allows
-     * us to access it as a map. This method returns the underlying map field
-     * directly and thus enables us to access the map field as a list.
+     * <p>Unlike other field types, reflection support for map fields can't be implemented based on
+     * generated public API because we need to access a map field as a list in reflection API but
+     * the generated API only allows us to access it as a map. This method returns the underlying
+     * map field directly and thus enables us to access the map field as a list.
      */
     @SuppressWarnings({"unused", "rawtypes"})
     protected MapField internalGetMapField(int fieldNumber) {
       // Note that we can't use descriptor names here because this method will
       // be called when descriptor is being initialized.
-      throw new RuntimeException(
-          "No map fields found in " + getClass().getName());
+      throw new RuntimeException("No map fields found in " + getClass().getName());
     }
 
     /** Like {@link #internalGetMapField} but return a mutable version. */
@@ -949,76 +945,92 @@
     protected MapField internalGetMutableMapField(int fieldNumber) {
       // Note that we can't use descriptor names here because this method will
       // be called when descriptor is being initialized.
-      throw new RuntimeException(
-          "No map fields found in " + getClass().getName());
+      throw new RuntimeException("No map fields found in " + getClass().getName());
     }
   }
 
   // =================================================================
   // Extensions-related stuff
 
-  public interface ExtendableMessageOrBuilder<
-      MessageType extends ExtendableMessage> extends MessageOrBuilder {
+  /** Extends {@link MessageOrBuilder} with extension-related functions. */
+  public interface ExtendableMessageOrBuilder<MessageT extends ExtendableMessage<MessageT>>
+      extends MessageOrBuilder {
     // Re-define for return type covariance.
     @Override
     Message getDefaultInstanceForType();
 
     /** Check if a singular extension is present. */
-    <Type> boolean hasExtension(
-        ExtensionLite<MessageType, Type> extension);
+    <T> boolean hasExtension(ExtensionLite<MessageT, T> extension);
 
     /** Get the number of elements in a repeated extension. */
-    <Type> int getExtensionCount(
-        ExtensionLite<MessageType, List<Type>> extension);
+    <T> int getExtensionCount(ExtensionLite<MessageT, List<T>> extension);
 
     /** Get the value of an extension. */
-    <Type> Type getExtension(
-        ExtensionLite<MessageType, Type> extension);
+    <T> T getExtension(ExtensionLite<MessageT, T> extension);
 
     /** Get one element of a repeated extension. */
-    <Type> Type getExtension(
-        ExtensionLite<MessageType, List<Type>> extension,
+    <T> T getExtension(ExtensionLite<MessageT, List<T>> extension, int index);
+
+    /**
+     * Check if a singular extension is present.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> boolean hasExtension(
+        Extension<MessageT, T> extension);
+    /**
+     * Check if a singular extension is present.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> boolean hasExtension(
+        GeneratedExtension<MessageT, T> extension);
+    /**
+     * Get the number of elements in a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> int getExtensionCount(
+        Extension<MessageT, List<T>> extension);
+    /**
+     * Get the number of elements in a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> int getExtensionCount(
+        GeneratedExtension<MessageT, List<T>> extension);
+    /**
+     * Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> T getExtension(
+        Extension<MessageT, T> extension);
+    /**
+     * Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> T getExtension(
+        GeneratedExtension<MessageT, T> extension);
+    /**
+     * Get one element of a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> T getExtension(
+        Extension<MessageT, List<T>> extension,
         int index);
-
-    /** Check if a singular extension is present. */
-    <Type> boolean hasExtension(
-        Extension<MessageType, Type> extension);
-    /** Check if a singular extension is present. */
-    <Type> boolean hasExtension(
-        GeneratedExtension<MessageType, Type> extension);
-    /** Get the number of elements in a repeated extension. */
-    <Type> int getExtensionCount(
-        Extension<MessageType, List<Type>> extension);
-    /** Get the number of elements in a repeated extension. */
-    <Type> int getExtensionCount(
-        GeneratedExtension<MessageType, List<Type>> extension);
-    /** Get the value of an extension. */
-    <Type> Type getExtension(
-        Extension<MessageType, Type> extension);
-    /** Get the value of an extension. */
-    <Type> Type getExtension(
-        GeneratedExtension<MessageType, Type> extension);
-    /** Get one element of a repeated extension. */
-    <Type> Type getExtension(
-        Extension<MessageType, List<Type>> extension,
-        int index);
-    /** Get one element of a repeated extension. */
-    <Type> Type getExtension(
-        GeneratedExtension<MessageType, List<Type>> extension,
+    /**
+     * Get one element of a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    <T> T getExtension(
+        GeneratedExtension<MessageT, List<T>> extension,
         int index);
   }
 
   /**
-   * Generated message classes for message types that contain extension ranges
-   * subclass this.
+   * Generated message classes for message types that contain extension ranges subclass this.
    *
-   * <p>This class implements type-safe accessors for extensions.  They
-   * implement all the same operations that you can do with normal fields --
-   * e.g. "has", "get", and "getCount" -- but for extensions.  The extensions
-   * are identified using instances of the class {@link GeneratedExtension};
-   * the protocol compiler generates a static instance of this class for every
-   * extension in its input.  Through the magic of generics, all is made
-   * type-safe.
+   * <p>This class implements type-safe accessors for extensions. They implement all the same
+   * operations that you can do with normal fields -- e.g. "has", "get", and "getCount" -- but for
+   * extensions. The extensions are identified using instances of the class {@link
+   * GeneratedExtension}; the protocol compiler generates a static instance of this class for every
+   * extension in its input. Through the magic of generics, all is made type-safe.
    *
    * <p>For example, imagine you have the {@code .proto} file:
    *
@@ -1043,10 +1055,8 @@
    *
    * <p>See also {@link ExtendableBuilder}.
    */
-  public abstract static class ExtendableMessage<
-        MessageType extends ExtendableMessage>
-      extends GeneratedMessageV3
-      implements ExtendableMessageOrBuilder<MessageType> {
+  public abstract static class ExtendableMessage<MessageT extends ExtendableMessage<MessageT>>
+      extends GeneratedMessageV3 implements ExtendableMessageOrBuilder<MessageT> {
 
     private static final long serialVersionUID = 1L;
 
@@ -1056,30 +1066,27 @@
       this.extensions = FieldSet.newFieldSet();
     }
 
-    protected ExtendableMessage(
-        ExtendableBuilder<MessageType, ?> builder) {
+    protected ExtendableMessage(ExtendableBuilder<MessageT, ?> builder) {
       super(builder);
       this.extensions = builder.buildExtensions();
     }
 
-    private void verifyExtensionContainingType(
-        final Extension<MessageType, ?> extension) {
-      if (extension.getDescriptor().getContainingType() !=
-          getDescriptorForType()) {
+    private void verifyExtensionContainingType(final Extension<MessageT, ?> extension) {
+      if (extension.getDescriptor().getContainingType() != getDescriptorForType()) {
         // This can only happen if someone uses unchecked operations.
         throw new IllegalArgumentException(
-          "Extension is for type \"" +
-          extension.getDescriptor().getContainingType().getFullName() +
-          "\" which does not match message type \"" +
-          getDescriptorForType().getFullName() + "\".");
+            "Extension is for type \""
+                + extension.getDescriptor().getContainingType().getFullName()
+                + "\" which does not match message type \""
+                + getDescriptorForType().getFullName()
+                + "\".");
       }
     }
 
     /** Check if a singular extension is present. */
     @Override
-    @SuppressWarnings("unchecked")
-    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
-      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+    public final <T> boolean hasExtension(final ExtensionLite<MessageT, T> extensionLite) {
+      Extension<MessageT, T> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       return extensions.hasField(extension.getDescriptor());
@@ -1087,10 +1094,8 @@
 
     /** Get the number of elements in a repeated extension. */
     @Override
-    @SuppressWarnings("unchecked")
-    public final <Type> int getExtensionCount(
-        final ExtensionLite<MessageType, List<Type>> extensionLite) {
-      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+    public final <T> int getExtensionCount(final ExtensionLite<MessageT, List<T>> extensionLite) {
+      Extension<MessageT, List<T>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       final FieldDescriptor descriptor = extension.getDescriptor();
@@ -1100,85 +1105,107 @@
     /** Get the value of an extension. */
     @Override
     @SuppressWarnings("unchecked")
-    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
-      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+    public final <T> T getExtension(final ExtensionLite<MessageT, T> extensionLite) {
+      Extension<MessageT, T> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
       final Object value = extensions.getField(descriptor);
       if (value == null) {
         if (descriptor.isRepeated()) {
-          return (Type) Collections.emptyList();
-        } else if (descriptor.getJavaType() ==
-                   FieldDescriptor.JavaType.MESSAGE) {
-          return (Type) extension.getMessageDefaultInstance();
+          return (T) Collections.emptyList();
+        } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          return (T) extension.getMessageDefaultInstance();
         } else {
-          return (Type) extension.fromReflectionType(
-              descriptor.getDefaultValue());
+          return (T) extension.fromReflectionType(descriptor.getDefaultValue());
         }
       } else {
-        return (Type) extension.fromReflectionType(value);
+        return (T) extension.fromReflectionType(value);
       }
     }
 
     /** Get one element of a repeated extension. */
     @Override
     @SuppressWarnings("unchecked")
-    public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
-      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+    public final <T> T getExtension(
+        final ExtensionLite<MessageT, List<T>> extensionLite, final int index) {
+      Extension<MessageT, List<T>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
-      return (Type) extension.singularFromReflectionType(
-          extensions.getRepeatedField(descriptor, index));
+      return (T)
+          extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index));
     }
 
-    /** Check if a singular extension is present. */
+    /**
+     * Check if a singular extension is present.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
-      return hasExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> boolean hasExtension(final Extension<MessageT, T> extension) {
+      return hasExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Check if a singular extension is present. */
+    /**
+     * Check if a singular extension is present.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> boolean hasExtension(
-        final GeneratedExtension<MessageType, Type> extension) {
-      return hasExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> boolean hasExtension(
+        final GeneratedExtension<MessageT, T> extension) {
+      return hasExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Get the number of elements in a repeated extension. */
+    /**
+     * Get the number of elements in a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> int getExtensionCount(
-        final Extension<MessageType, List<Type>> extension) {
-      return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+    public final <T> int getExtensionCount(
+        final Extension<MessageT, List<T>> extension) {
+      return getExtensionCount((ExtensionLite<MessageT, List<T>>) extension);
     }
-    /** Get the number of elements in a repeated extension. */
+    /**
+     * Get the number of elements in a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> int getExtensionCount(
-        final GeneratedExtension<MessageType, List<Type>> extension) {
-      return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+    public final <T> int getExtensionCount(
+        final GeneratedExtension<MessageT, List<T>> extension) {
+      return getExtensionCount((ExtensionLite<MessageT, List<T>>) extension);
     }
-    /** Get the value of an extension. */
+    /**
+     * Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
-      return getExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> T getExtension(final Extension<MessageT, T> extension) {
+      return getExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Get the value of an extension. */
+    /**
+     * Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, Type> extension) {
-      return getExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> T getExtension(
+        final GeneratedExtension<MessageT, T> extension) {
+      return getExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Get one element of a repeated extension. */
+    /**
+     * Get one element of a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(
-        final Extension<MessageType, List<Type>> extension, final int index) {
-      return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+    public final <T> T getExtension(
+        final Extension<MessageT, List<T>> extension, final int index) {
+      return getExtension((ExtensionLite<MessageT, List<T>>) extension, index);
     }
-    /** Get one element of a repeated extension. */
+    /**
+     * Get one element of a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
-      return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+    public final <T> T getExtension(
+        final GeneratedExtension<MessageT, List<T>> extension, final int index) {
+      return getExtension((ExtensionLite<MessageT, List<T>>) extension, index);
     }
 
     /** Called by subclasses to check if all extensions are initialized. */
@@ -1186,38 +1213,49 @@
       return extensions.isInitialized();
     }
 
+    // TODO(b/258342840): compute this in the builder at {@code build()} time.
     @Override
     public boolean isInitialized() {
       return super.isInitialized() && extensionsAreInitialized();
     }
 
+    // TODO(b/248153893): remove mutating method from immutable type
     @Override
     protected boolean parseUnknownField(
         CodedInputStream input,
         UnknownFieldSet.Builder unknownFields,
         ExtensionRegistryLite extensionRegistry,
-        int tag) throws IOException {
+        int tag)
+        throws IOException {
       return MessageReflection.mergeFieldFrom(
-          input, input.shouldDiscardUnknownFields() ? null : unknownFields, extensionRegistry,
-          getDescriptorForType(), new MessageReflection.ExtensionAdapter(extensions), tag);
+          input,
+          input.shouldDiscardUnknownFields() ? null : unknownFields,
+          extensionRegistry,
+          getDescriptorForType(),
+          new MessageReflection.ExtensionAdapter(extensions),
+          tag);
     }
 
     /**
      * Delegates to parseUnknownField. This method is obsolete, but we must retain it for
      * compatibility with older generated code.
+     *
+     * <p>TODO(b/248153893): remove mutating method from immutable type
      */
     @Override
     protected boolean parseUnknownFieldProto3(
         CodedInputStream input,
         UnknownFieldSet.Builder unknownFields,
         ExtensionRegistryLite extensionRegistry,
-        int tag) throws IOException {
+        int tag)
+        throws IOException {
       return parseUnknownField(input, unknownFields, extensionRegistry, tag);
     }
 
-
     /**
      * Used by parsing constructors in generated classes.
+     *
+     * <p>TODO(b/258340024): remove unused method (extensions should be immutable after build)
      */
     @Override
     protected void makeExtensionsImmutable() {
@@ -1225,17 +1263,15 @@
     }
 
     /**
-     * Used by subclasses to serialize extensions.  Extension ranges may be
-     * interleaved with field numbers, but we must write them in canonical
-     * (sorted by field number) order.  ExtensionWriter helps us write
-     * individual ranges of extensions at once.
+     * Used by subclasses to serialize extensions. Extension ranges may be interleaved with field
+     * numbers, but we must write them in canonical (sorted by field number) order. ExtensionWriter
+     * helps us write individual ranges of extensions at once.
      */
     protected class ExtensionWriter {
       // Imagine how much simpler this code would be if Java iterators had
       // a way to get the next element without advancing the iterator.
 
-      private final Iterator<Map.Entry<FieldDescriptor, Object>> iter =
-        extensions.iterator();
+      private final Iterator<Map.Entry<FieldDescriptor, Object>> iter = extensions.iterator();
       private Map.Entry<FieldDescriptor, Object> next;
       private final boolean messageSetWireFormat;
 
@@ -1246,19 +1282,18 @@
         this.messageSetWireFormat = messageSetWireFormat;
       }
 
-      public void writeUntil(final int end, final CodedOutputStream output)
-                             throws IOException {
+      public void writeUntil(final int end, final CodedOutputStream output) throws IOException {
         while (next != null && next.getKey().getNumber() < end) {
           FieldDescriptor descriptor = next.getKey();
-          if (messageSetWireFormat && descriptor.getLiteJavaType() ==
-                  WireFormat.JavaType.MESSAGE &&
-              !descriptor.isRepeated()) {
+          if (messageSetWireFormat
+              && descriptor.getLiteJavaType() == WireFormat.JavaType.MESSAGE
+              && !descriptor.isRepeated()) {
             if (next instanceof LazyField.LazyEntry<?>) {
-              output.writeRawMessageSetExtension(descriptor.getNumber(),
+              output.writeRawMessageSetExtension(
+                  descriptor.getNumber(),
                   ((LazyField.LazyEntry<?>) next).getField().toByteString());
             } else {
-              output.writeMessageSetExtension(descriptor.getNumber(),
-                                              (Message) next.getValue());
+              output.writeMessageSetExtension(descriptor.getNumber(), (Message) next.getValue());
             }
           } else {
             // TODO(xiangl): Taken care of following code, it may cause
@@ -1282,6 +1317,7 @@
     protected ExtensionWriter newExtensionWriter() {
       return new ExtensionWriter(false);
     }
+
     protected ExtensionWriter newMessageSetExtensionWriter() {
       return new ExtensionWriter(true);
     }
@@ -1290,6 +1326,7 @@
     protected int extensionsSerializedSize() {
       return extensions.getSerializedSize();
     }
+
     protected int extensionsSerializedSizeAsMessageSet() {
       return extensions.getMessageSetSerializedSize();
     }
@@ -1361,8 +1398,7 @@
     }
 
     @Override
-    public Object getRepeatedField(final FieldDescriptor field,
-                                   final int index) {
+    public Object getRepeatedField(final FieldDescriptor field, final int index) {
       if (field.isExtension()) {
         verifyContainingType(field);
         return extensions.getRepeatedField(field, index);
@@ -1373,23 +1409,19 @@
 
     private void verifyContainingType(final FieldDescriptor field) {
       if (field.getContainingType() != getDescriptorForType()) {
-        throw new IllegalArgumentException(
-          "FieldDescriptor does not match message type.");
+        throw new IllegalArgumentException("FieldDescriptor does not match message type.");
       }
     }
   }
 
   /**
-   * Generated message builders for message types that contain extension ranges
-   * subclass this.
+   * Generated message builders for message types that contain extension ranges subclass this.
    *
-   * <p>This class implements type-safe accessors for extensions.  They
-   * implement all the same operations that you can do with normal fields --
-   * e.g. "get", "set", and "add" -- but for extensions.  The extensions are
-   * identified using instances of the class {@link GeneratedExtension}; the
-   * protocol compiler generates a static instance of this class for every
-   * extension in its input.  Through the magic of generics, all is made
-   * type-safe.
+   * <p>This class implements type-safe accessors for extensions. They implement all the same
+   * operations that you can do with normal fields -- e.g. "get", "set", and "add" -- but for
+   * extensions. The extensions are identified using instances of the class {@link
+   * GeneratedExtension}; the protocol compiler generates a static instance of this class for every
+   * extension in its input. Through the magic of generics, all is made type-safe.
    *
    * <p>For example, imagine you have the {@code .proto} file:
    *
@@ -1418,17 +1450,15 @@
    */
   @SuppressWarnings("unchecked")
   public abstract static class ExtendableBuilder<
-        MessageType extends ExtendableMessage,
-        BuilderType extends ExtendableBuilder<MessageType, BuilderType>>
-      extends Builder<BuilderType>
-      implements ExtendableMessageOrBuilder<MessageType> {
+          MessageT extends ExtendableMessage<MessageT>,
+          BuilderT extends ExtendableBuilder<MessageT, BuilderT>>
+      extends Builder<BuilderT> implements ExtendableMessageOrBuilder<MessageT> {
 
     private FieldSet.Builder<FieldDescriptor> extensions;
 
     protected ExtendableBuilder() {}
 
-    protected ExtendableBuilder(
-        BuilderParent parent) {
+    protected ExtendableBuilder(BuilderParent parent) {
       super(parent);
     }
 
@@ -1438,7 +1468,7 @@
     }
 
     @Override
-    public BuilderType clear() {
+    public BuilderT clear() {
       extensions = null;
       return super.clear();
     }
@@ -1449,33 +1479,31 @@
       }
     }
 
-    private void verifyExtensionContainingType(
-        final Extension<MessageType, ?> extension) {
-      if (extension.getDescriptor().getContainingType() !=
-          getDescriptorForType()) {
+    private void verifyExtensionContainingType(final Extension<MessageT, ?> extension) {
+      if (extension.getDescriptor().getContainingType() != getDescriptorForType()) {
         // This can only happen if someone uses unchecked operations.
         throw new IllegalArgumentException(
-          "Extension is for type \"" +
-          extension.getDescriptor().getContainingType().getFullName() +
-          "\" which does not match message type \"" +
-          getDescriptorForType().getFullName() + "\".");
+            "Extension is for type \""
+                + extension.getDescriptor().getContainingType().getFullName()
+                + "\" which does not match message type \""
+                + getDescriptorForType().getFullName()
+                + "\".");
       }
     }
 
     /** Check if a singular extension is present. */
     @Override
-    public final <Type> boolean hasExtension(final ExtensionLite<MessageType, Type> extensionLite) {
-      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+    public final <T> boolean hasExtension(final ExtensionLite<MessageT, T> extensionLite) {
+      Extension<MessageT, T> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
-      return extensions == null ? false : extensions.hasField(extension.getDescriptor());
+      return extensions != null && extensions.hasField(extension.getDescriptor());
     }
 
     /** Get the number of elements in a repeated extension. */
     @Override
-    public final <Type> int getExtensionCount(
-        final ExtensionLite<MessageType, List<Type>> extensionLite) {
-      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+    public final <T> int getExtensionCount(final ExtensionLite<MessageT, List<T>> extensionLite) {
+      Extension<MessageT, List<T>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       final FieldDescriptor descriptor = extension.getDescriptor();
@@ -1484,195 +1512,233 @@
 
     /** Get the value of an extension. */
     @Override
-    public final <Type> Type getExtension(final ExtensionLite<MessageType, Type> extensionLite) {
-      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+    public final <T> T getExtension(final ExtensionLite<MessageT, T> extensionLite) {
+      Extension<MessageT, T> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
       final Object value = extensions == null ? null : extensions.getField(descriptor);
       if (value == null) {
         if (descriptor.isRepeated()) {
-          return (Type) Collections.emptyList();
-        } else if (descriptor.getJavaType() ==
-                   FieldDescriptor.JavaType.MESSAGE) {
-          return (Type) extension.getMessageDefaultInstance();
+          return (T) Collections.emptyList();
+        } else if (descriptor.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
+          return (T) extension.getMessageDefaultInstance();
         } else {
-          return (Type) extension.fromReflectionType(
-              descriptor.getDefaultValue());
+          return (T) extension.fromReflectionType(descriptor.getDefaultValue());
         }
       } else {
-        return (Type) extension.fromReflectionType(value);
+        return (T) extension.fromReflectionType(value);
       }
     }
 
     /** Get one element of a repeated extension. */
     @Override
-    public final <Type> Type getExtension(
-        final ExtensionLite<MessageType, List<Type>> extensionLite, final int index) {
-      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+    public final <T> T getExtension(
+        final ExtensionLite<MessageT, List<T>> extensionLite, final int index) {
+      Extension<MessageT, List<T>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       FieldDescriptor descriptor = extension.getDescriptor();
       if (extensions == null) {
         throw new IndexOutOfBoundsException();
       }
-      return (Type)
+      return (T)
           extension.singularFromReflectionType(extensions.getRepeatedField(descriptor, index));
     }
 
     /** Set the value of an extension. */
-    public final <Type> BuilderType setExtension(
-        final ExtensionLite<MessageType, Type> extensionLite,
-        final Type value) {
-      Extension<MessageType, Type> extension = checkNotLite(extensionLite);
+    public final <T> BuilderT setExtension(
+        final ExtensionLite<MessageT, T> extensionLite, final T value) {
+      Extension<MessageT, T> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       ensureExtensionsIsMutable();
       final FieldDescriptor descriptor = extension.getDescriptor();
       extensions.setField(descriptor, extension.toReflectionType(value));
       onChanged();
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     /** Set the value of one element of a repeated extension. */
-    public final <Type> BuilderType setExtension(
-        final ExtensionLite<MessageType, List<Type>> extensionLite,
-        final int index, final Type value) {
-      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+    public final <T> BuilderT setExtension(
+        final ExtensionLite<MessageT, List<T>> extensionLite, final int index, final T value) {
+      Extension<MessageT, List<T>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       ensureExtensionsIsMutable();
       final FieldDescriptor descriptor = extension.getDescriptor();
-      extensions.setRepeatedField(
-        descriptor, index,
-        extension.singularToReflectionType(value));
+      extensions.setRepeatedField(descriptor, index, extension.singularToReflectionType(value));
       onChanged();
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     /** Append a value to a repeated extension. */
-    public final <Type> BuilderType addExtension(
-        final ExtensionLite<MessageType, List<Type>> extensionLite,
-        final Type value) {
-      Extension<MessageType, List<Type>> extension = checkNotLite(extensionLite);
+    public final <T> BuilderT addExtension(
+        final ExtensionLite<MessageT, List<T>> extensionLite, final T value) {
+      Extension<MessageT, List<T>> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       ensureExtensionsIsMutable();
       final FieldDescriptor descriptor = extension.getDescriptor();
-      extensions.addRepeatedField(
-          descriptor, extension.singularToReflectionType(value));
+      extensions.addRepeatedField(descriptor, extension.singularToReflectionType(value));
       onChanged();
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
     /** Clear an extension. */
-    public final BuilderType clearExtension(final ExtensionLite<MessageType, ?> extensionLite) {
-      Extension<MessageType, ?> extension = checkNotLite(extensionLite);
+    public final <T> BuilderT clearExtension(final ExtensionLite<MessageT, T> extensionLite) {
+      Extension<MessageT, T> extension = checkNotLite(extensionLite);
 
       verifyExtensionContainingType(extension);
       ensureExtensionsIsMutable();
       extensions.clearField(extension.getDescriptor());
       onChanged();
-      return (BuilderType) this;
+      return (BuilderT) this;
     }
 
-    /** Check if a singular extension is present. */
+    /**
+     * Check if a singular extension is present.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> boolean hasExtension(final Extension<MessageType, Type> extension) {
-      return hasExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> boolean hasExtension(final Extension<MessageT, T> extension) {
+      return hasExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Check if a singular extension is present. */
+    /**
+     * Check if a singular extension is present.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> boolean hasExtension(
-        final GeneratedExtension<MessageType, Type> extension) {
-      return hasExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> boolean hasExtension(
+        final GeneratedExtension<MessageT, T> extension) {
+      return hasExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Get the number of elements in a repeated extension. */
+    /**
+     * Get the number of elements in a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> int getExtensionCount(
-        final Extension<MessageType, List<Type>> extension) {
-      return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+    public final <T> int getExtensionCount(
+        final Extension<MessageT, List<T>> extension) {
+      return getExtensionCount((ExtensionLite<MessageT, List<T>>) extension);
     }
-    /** Get the number of elements in a repeated extension. */
+    /**
+     * Get the number of elements in a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> int getExtensionCount(
-        final GeneratedExtension<MessageType, List<Type>> extension) {
-      return getExtensionCount((ExtensionLite<MessageType, List<Type>>) extension);
+    public final <T> int getExtensionCount(
+        final GeneratedExtension<MessageT, List<T>> extension) {
+      return getExtensionCount((ExtensionLite<MessageT, List<T>>) extension);
     }
-    /** Get the value of an extension. */
+    /**
+     * Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(final Extension<MessageType, Type> extension) {
-      return getExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> T getExtension(final Extension<MessageT, T> extension) {
+      return getExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Get the value of an extension. */
+    /** Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, Type> extension) {
-      return getExtension((ExtensionLite<MessageType, Type>) extension);
+    public final <T> T getExtension(
+        final GeneratedExtension<MessageT, T> extension) {
+      return getExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Get the value of an extension. */
+    /**
+     * Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(
-        final Extension<MessageType, List<Type>> extension, final int index) {
-      return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+    public final <T> T getExtension(
+        final Extension<MessageT, List<T>> extension, final int index) {
+      return getExtension((ExtensionLite<MessageT, List<T>>) extension, index);
     }
-    /** Get the value of an extension. */
+    /**
+     * Get the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
     @Override
-    public final <Type> Type getExtension(
-        final GeneratedExtension<MessageType, List<Type>> extension, final int index) {
-      return getExtension((ExtensionLite<MessageType, List<Type>>) extension, index);
+    public final <T> T getExtension(
+        final GeneratedExtension<MessageT, List<T>> extension, final int index) {
+      return getExtension((ExtensionLite<MessageT, List<T>>) extension, index);
     }
-    /** Set the value of an extension. */
-    public final <Type> BuilderType setExtension(
-        final Extension<MessageType, Type> extension, final Type value) {
-      return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+    /**
+     * Set the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public final <T> BuilderT setExtension(
+        final Extension<MessageT, T> extension, final T value) {
+      return setExtension((ExtensionLite<MessageT, T>) extension, value);
     }
-    /** Set the value of an extension. */
-    public <Type> BuilderType setExtension(
-        final GeneratedExtension<MessageType, Type> extension, final Type value) {
-      return setExtension((ExtensionLite<MessageType, Type>) extension, value);
+    /**
+     * Set the value of an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public <T> BuilderT setExtension(
+        final GeneratedExtension<MessageT, T> extension, final T value) {
+      return setExtension((ExtensionLite<MessageT, T>) extension, value);
     }
-    /** Set the value of one element of a repeated extension. */
-    public final <Type> BuilderType setExtension(
-        final Extension<MessageType, List<Type>> extension,
-        final int index, final Type value) {
-      return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+    /**
+     * Set the value of one element of a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public final <T> BuilderT setExtension(
+        final Extension<MessageT, List<T>> extension,
+        final int index, final T value) {
+      return setExtension((ExtensionLite<MessageT, List<T>>) extension, index, value);
     }
-    /** Set the value of one element of a repeated extension. */
-    public <Type> BuilderType setExtension(
-        final GeneratedExtension<MessageType, List<Type>> extension,
-        final int index, final Type value) {
-      return setExtension((ExtensionLite<MessageType, List<Type>>) extension, index, value);
+    /**
+     * Set the value of one element of a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public <T> BuilderT setExtension(
+        final GeneratedExtension<MessageT, List<T>> extension,
+        final int index, final T value) {
+      return setExtension((ExtensionLite<MessageT, List<T>>) extension, index, value);
     }
-    /** Append a value to a repeated extension. */
-    public final <Type> BuilderType addExtension(
-        final Extension<MessageType, List<Type>> extension, final Type value) {
-      return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+    /**
+     * Append a value to a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public final <T> BuilderT addExtension(
+        final Extension<MessageT, List<T>> extension, final T value) {
+      return addExtension((ExtensionLite<MessageT, List<T>>) extension, value);
     }
-    /** Append a value to a repeated extension. */
-    public <Type> BuilderType addExtension(
-        final GeneratedExtension<MessageType, List<Type>> extension, final Type value) {
-      return addExtension((ExtensionLite<MessageType, List<Type>>) extension, value);
+    /**
+     * Append a value to a repeated extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public <T> BuilderT addExtension(
+        final GeneratedExtension<MessageT, List<T>> extension, final T value) {
+      return addExtension((ExtensionLite<MessageT, List<T>>) extension, value);
     }
-    /** Clear an extension. */
-    public final <Type> BuilderType clearExtension(
-        final Extension<MessageType, ?> extension) {
-      return clearExtension((ExtensionLite<MessageType, ?>) extension);
+    /**
+     * Clear an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public final <T> BuilderT clearExtension(
+        final Extension<MessageT, T> extension) {
+      return clearExtension((ExtensionLite<MessageT, T>) extension);
     }
-    /** Clear an extension. */
-    public <Type> BuilderType clearExtension(
-        final GeneratedExtension<MessageType, ?> extension) {
-      return clearExtension((ExtensionLite<MessageType, ?>) extension);
+    /**
+     * Clears an extension.
+     * <p>TODO(b/258340024): handled by ExtensionLite version
+     */
+    public <T> BuilderT clearExtension(
+        final GeneratedExtension<MessageT, T> extension) {
+      return clearExtension((ExtensionLite<MessageT, T>) extension);
     }
 
     /** Called by subclasses to check if all extensions are initialized. */
     protected boolean extensionsAreInitialized() {
-      return extensions == null ? true : extensions.isInitialized();
+      return extensions == null || extensions.isInitialized();
     }
 
     /**
-     * Called by the build code path to create a copy of the extensions for
-     * building the message.
+     * Called by the build code path to create a copy of the extensions for building the message.
      */
     private FieldSet<FieldDescriptor> buildExtensions() {
       return extensions == null
@@ -1762,8 +1828,7 @@
     }
 
     @Override
-    public Object getRepeatedField(final FieldDescriptor field,
-                                   final int index) {
+    public Object getRepeatedField(final FieldDescriptor field, final int index) {
       if (field.isExtension()) {
         verifyContainingType(field);
         if (extensions == null) {
@@ -1805,62 +1870,60 @@
     public boolean hasField(final FieldDescriptor field) {
       if (field.isExtension()) {
         verifyContainingType(field);
-        return extensions == null ? false : extensions.hasField(field);
+        return extensions != null && extensions.hasField(field);
       } else {
         return super.hasField(field);
       }
     }
 
     @Override
-    public BuilderType setField(final FieldDescriptor field,
-                                final Object value) {
+    public BuilderT setField(final FieldDescriptor field, final Object value) {
       if (field.isExtension()) {
         verifyContainingType(field);
         ensureExtensionsIsMutable();
         extensions.setField(field, value);
         onChanged();
-        return (BuilderType) this;
+        return (BuilderT) this;
       } else {
         return super.setField(field, value);
       }
     }
 
     @Override
-    public BuilderType clearField(final FieldDescriptor field) {
+    public BuilderT clearField(final FieldDescriptor field) {
       if (field.isExtension()) {
         verifyContainingType(field);
         ensureExtensionsIsMutable();
         extensions.clearField(field);
         onChanged();
-        return (BuilderType) this;
+        return (BuilderT) this;
       } else {
         return super.clearField(field);
       }
     }
 
     @Override
-    public BuilderType setRepeatedField(final FieldDescriptor field,
-                                        final int index, final Object value) {
+    public BuilderT setRepeatedField(
+        final FieldDescriptor field, final int index, final Object value) {
       if (field.isExtension()) {
         verifyContainingType(field);
         ensureExtensionsIsMutable();
         extensions.setRepeatedField(field, index, value);
         onChanged();
-        return (BuilderType) this;
+        return (BuilderT) this;
       } else {
         return super.setRepeatedField(field, index, value);
       }
     }
 
     @Override
-    public BuilderType addRepeatedField(final FieldDescriptor field,
-                                        final Object value) {
+    public BuilderT addRepeatedField(final FieldDescriptor field, final Object value) {
       if (field.isExtension()) {
         verifyContainingType(field);
         ensureExtensionsIsMutable();
         extensions.addRepeatedField(field, value);
         onChanged();
-        return (BuilderType) this;
+        return (BuilderT) this;
       } else {
         return super.addRepeatedField(field, value);
       }
@@ -1875,7 +1938,7 @@
       }
     }
 
-    protected final void mergeExtensionFields(final ExtendableMessage other) {
+    protected final void mergeExtensionFields(final ExtendableMessage<?> other) {
       if (other.extensions != null) {
         ensureExtensionsIsMutable();
         extensions.mergeFrom(other.extensions);
@@ -1899,8 +1962,7 @@
 
     private void verifyContainingType(final FieldDescriptor field) {
       if (field.getContainingType() != getDescriptorForType()) {
-        throw new IllegalArgumentException(
-          "FieldDescriptor does not match message type.");
+        throw new IllegalArgumentException("FieldDescriptor does not match message type.");
       }
     }
   }
@@ -1908,26 +1970,24 @@
   // -----------------------------------------------------------------
 
   /**
-   * Gets the descriptor for an extension. The implementation depends on whether
-   * the extension is scoped in the top level of a file or scoped in a Message.
+   * Gets the descriptor for an extension. The implementation depends on whether the extension is
+   * scoped in the top level of a file or scoped in a Message.
    */
-  static interface ExtensionDescriptorRetriever {
+  interface ExtensionDescriptorRetriever {
     FieldDescriptor getDescriptor();
   }
 
-
   // =================================================================
 
   /** Calls Class.getMethod and throws a RuntimeException if it fails. */
-  @SuppressWarnings("unchecked")
   private static Method getMethodOrDie(
-      final Class clazz, final String name, final Class... params) {
+      final Class<?> clazz, final String name, final Class<?>... params) {
     try {
       return clazz.getMethod(name, params);
     } catch (NoSuchMethodException e) {
       throw new RuntimeException(
-        "Generated message class \"" + clazz.getName() +
-        "\" missing method \"" + name + "\".", e);
+          "Generated message class \"" + clazz.getName() + "\" missing method \"" + name + "\".",
+          e);
     }
   }
 
@@ -1939,8 +1999,7 @@
       return method.invoke(object, params);
     } catch (IllegalAccessException e) {
       throw new RuntimeException(
-        "Couldn't use Java reflection to implement protocol message " +
-        "reflection.", e);
+          "Couldn't use Java reflection to implement protocol message " + "reflection.", e);
     } catch (InvocationTargetException e) {
       final Throwable cause = e.getCause();
       if (cause instanceof RuntimeException) {
@@ -1949,7 +2008,7 @@
         throw (Error) cause;
       } else {
         throw new RuntimeException(
-          "Unexpected exception thrown by generated accessor method.", cause);
+            "Unexpected exception thrown by generated accessor method.", cause);
       }
     }
   }
@@ -1967,42 +2026,39 @@
   protected MapField internalGetMapField(int fieldNumber) {
     // Note that we can't use descriptor names here because this method will
     // be called when descriptor is being initialized.
-    throw new RuntimeException(
-        "No map fields found in " + getClass().getName());
+    throw new RuntimeException("No map fields found in " + getClass().getName());
   }
 
   /**
-   * Users should ignore this class.  This class provides the implementation
-   * with access to the fields of a message object using Java reflection.
+   * Users should ignore this class. This class provides the implementation with access to the
+   * fields of a message object using Java reflection.
    */
   public static final class FieldAccessorTable {
 
     /**
-     * Construct a FieldAccessorTable for a particular message class.  Only
-     * one FieldAccessorTable should ever be constructed per class.
+     * Construct a FieldAccessorTable for a particular message class. Only one FieldAccessorTable
+     * should ever be constructed per class.
      *
-     * @param descriptor     The type's descriptor.
-     * @param camelCaseNames The camelcase names of all fields in the message.
-     *                       These are used to derive the accessor method names.
-     * @param messageClass   The message type.
-     * @param builderClass   The builder type.
+     * @param descriptor The type's descriptor.
+     * @param camelCaseNames The camelcase names of all fields in the message. These are used to
+     *     derive the accessor method names.
+     * @param messageClass The message type.
+     * @param builderClass The builder type.
      */
     public FieldAccessorTable(
         final Descriptor descriptor,
         final String[] camelCaseNames,
         final Class<? extends GeneratedMessageV3> messageClass,
-        final Class<? extends Builder> builderClass) {
+        final Class<? extends Builder<?>> builderClass) {
       this(descriptor, camelCaseNames);
       ensureFieldAccessorsInitialized(messageClass, builderClass);
     }
 
     /**
-     * Construct a FieldAccessorTable for a particular message class without
-     * initializing FieldAccessors.
+     * Construct a FieldAccessorTable for a particular message class without initializing
+     * FieldAccessors.
      */
-    public FieldAccessorTable(
-        final Descriptor descriptor,
-        final String[] camelCaseNames) {
+    public FieldAccessorTable(final Descriptor descriptor, final String[] camelCaseNames) {
       this.descriptor = descriptor;
       this.camelCaseNames = camelCaseNames;
       fields = new FieldAccessor[descriptor.getFields().size()];
@@ -2013,16 +2069,19 @@
     /**
      * Ensures the field accessors are initialized. This method is thread-safe.
      *
-     * @param messageClass   The message type.
-     * @param builderClass   The builder type.
+     * @param messageClass The message type.
+     * @param builderClass The builder type.
      * @return this
      */
     public FieldAccessorTable ensureFieldAccessorsInitialized(
-        Class<? extends GeneratedMessageV3> messageClass,
-        Class<? extends Builder> builderClass) {
-      if (initialized) { return this; }
+        Class<? extends GeneratedMessageV3> messageClass, Class<? extends Builder<?>> builderClass) {
+      if (initialized) {
+        return this;
+      }
       synchronized (this) {
-        if (initialized) { return this; }
+        if (initialized) {
+          return this;
+        }
         int fieldsSize = fields.length;
         for (int i = 0; i < fieldsSize; i++) {
           FieldDescriptor field = descriptor.getFields().get(i);
@@ -2034,36 +2093,53 @@
           if (field.isRepeated()) {
             if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
               if (field.isMapField()) {
-                fields[i] = new MapFieldAccessor(
-                    field, camelCaseNames[i], messageClass, builderClass);
+                fields[i] = new MapFieldAccessor(field, messageClass);
               } else {
-                fields[i] = new RepeatedMessageFieldAccessor(
-                    field, camelCaseNames[i], messageClass, builderClass);
+                fields[i] =
+                    new RepeatedMessageFieldAccessor(
+                        field, camelCaseNames[i], messageClass, builderClass);
               }
             } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
-              fields[i] = new RepeatedEnumFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass);
+              fields[i] =
+                  new RepeatedEnumFieldAccessor(
+                      field, camelCaseNames[i], messageClass, builderClass);
             } else {
-              fields[i] = new RepeatedFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass);
+              fields[i] =
+                  new RepeatedFieldAccessor(field, camelCaseNames[i], messageClass, builderClass);
             }
           } else {
             if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-              fields[i] = new SingularMessageFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularMessageFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             } else if (field.getJavaType() == FieldDescriptor.JavaType.ENUM) {
-              fields[i] = new SingularEnumFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularEnumFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             } else if (field.getJavaType() == FieldDescriptor.JavaType.STRING) {
-              fields[i] = new SingularStringFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularStringFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             } else {
-              fields[i] = new SingularFieldAccessor(
-                  field, camelCaseNames[i], messageClass, builderClass,
-                  containingOneofCamelCaseName);
+              fields[i] =
+                  new SingularFieldAccessor(
+                      field,
+                      camelCaseNames[i],
+                      messageClass,
+                      builderClass,
+                      containingOneofCamelCaseName);
             }
           }
         }
@@ -2089,13 +2165,11 @@
     /** Get the FieldAccessor for a particular field. */
     private FieldAccessor getField(final FieldDescriptor field) {
       if (field.getContainingType() != descriptor) {
-        throw new IllegalArgumentException(
-          "FieldDescriptor does not match message type.");
+        throw new IllegalArgumentException("FieldDescriptor does not match message type.");
       } else if (field.isExtension()) {
         // If this type had extensions, it would subclass ExtendableMessage,
         // which overrides the reflection interface to handle extensions.
-        throw new IllegalArgumentException(
-          "This type does not have extensions.");
+        throw new IllegalArgumentException("This type does not have extensions.");
       }
       return fields[field.getIndex()];
     }
@@ -2103,38 +2177,47 @@
     /** Get the OneofAccessor for a particular oneof. */
     private OneofAccessor getOneof(final OneofDescriptor oneof) {
       if (oneof.getContainingType() != descriptor) {
-        throw new IllegalArgumentException(
-          "OneofDescriptor does not match message type.");
+        throw new IllegalArgumentException("OneofDescriptor does not match message type.");
       }
       return oneofs[oneof.getIndex()];
     }
 
     /**
-     * Abstract interface that provides access to a single field.  This is
-     * implemented differently depending on the field type and cardinality.
+     * Abstract interface that provides access to a single field. This is implemented differently
+     * depending on the field type and cardinality.
      */
     private interface FieldAccessor {
       Object get(GeneratedMessageV3 message);
-      Object get(GeneratedMessageV3.Builder builder);
+
+      Object get(GeneratedMessageV3.Builder<?> builder);
+
       Object getRaw(GeneratedMessageV3 message);
-      Object getRaw(GeneratedMessageV3.Builder builder);
-      void set(Builder builder, Object value);
+
+      void set(Builder<?> builder, Object value);
+
       Object getRepeated(GeneratedMessageV3 message, int index);
-      Object getRepeated(GeneratedMessageV3.Builder builder, int index);
-      Object getRepeatedRaw(GeneratedMessageV3 message, int index);
-      Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index);
-      void setRepeated(Builder builder,
-                       int index, Object value);
-      void addRepeated(Builder builder, Object value);
+
+      Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index);
+
+      void setRepeated(Builder<?> builder, int index, Object value);
+
+      void addRepeated(Builder<?> builder, Object value);
+
       boolean has(GeneratedMessageV3 message);
-      boolean has(GeneratedMessageV3.Builder builder);
+
+      boolean has(GeneratedMessageV3.Builder<?> builder);
+
       int getRepeatedCount(GeneratedMessageV3 message);
-      int getRepeatedCount(GeneratedMessageV3.Builder builder);
-      void clear(Builder builder);
+
+      int getRepeatedCount(GeneratedMessageV3.Builder<?> builder);
+
+      void clear(Builder<?> builder);
+
       Message.Builder newBuilder();
-      Message.Builder getBuilder(GeneratedMessageV3.Builder builder);
-      Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder,
-                                         int index);
+
+      Message.Builder getBuilder(GeneratedMessageV3.Builder<?> builder);
+
+      Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder<?> builder, int index);
     }
 
     /** OneofAccessor provides access to a single oneof. */
@@ -2144,7 +2227,7 @@
           final int oneofIndex,
           final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass) {
+          final Class<? extends Builder<?>> builderClass) {
         this.descriptor = descriptor;
         OneofDescriptor oneofDescriptor = descriptor.getOneofs().get(oneofIndex);
         if (oneofDescriptor.isSynthetic()) {
@@ -2169,22 +2252,16 @@
         if (fieldDescriptor != null) {
           return message.hasField(fieldDescriptor);
         } else {
-          if (((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() == 0) {
-            return false;
-          }
+          return ((Internal.EnumLite) invokeOrDie(caseMethod, message)).getNumber() != 0;
         }
-        return true;
       }
 
-      public boolean has(GeneratedMessageV3.Builder builder) {
+      public boolean has(GeneratedMessageV3.Builder<?> builder) {
         if (fieldDescriptor != null) {
           return builder.hasField(fieldDescriptor);
         } else {
-          if (((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() == 0) {
-            return false;
-          }
+          return ((Internal.EnumLite) invokeOrDie(caseMethodBuilder, builder)).getNumber() != 0;
         }
-        return true;
       }
 
       public FieldDescriptor get(final GeneratedMessageV3 message) {
@@ -2199,7 +2276,7 @@
         return null;
       }
 
-      public FieldDescriptor get(GeneratedMessageV3.Builder builder) {
+      public FieldDescriptor get(GeneratedMessageV3.Builder<?> builder) {
         if (fieldDescriptor != null) {
           return builder.hasField(fieldDescriptor) ? fieldDescriptor : null;
         } else {
@@ -2212,7 +2289,7 @@
         return null;
       }
 
-      public void clear(final Builder builder) {
+      public void clear(final Builder<?> builder) {
         // TODO(b/230609037): remove the unused variable
         Object unused = invokeOrDie(clearMethod, builder);
       }
@@ -2240,20 +2317,20 @@
       }
 
       private static final class ReflectionInvoker implements MethodInvoker {
-        protected final Method getMethod;
-        protected final Method getMethodBuilder;
-        protected final Method setMethod;
-        protected final Method hasMethod;
-        protected final Method hasMethodBuilder;
-        protected final Method clearMethod;
-        protected final Method caseMethod;
-        protected final Method caseMethodBuilder;
+        private final Method getMethod;
+        private final Method getMethodBuilder;
+        private final Method setMethod;
+        private final Method hasMethod;
+        private final Method hasMethodBuilder;
+        private final Method clearMethod;
+        private final Method caseMethod;
+        private final Method caseMethodBuilder;
 
         ReflectionInvoker(
             final FieldDescriptor descriptor,
             final String camelCaseName,
             final Class<? extends GeneratedMessageV3> messageClass,
-            final Class<? extends Builder> builderClass,
+            final Class<? extends Builder<?>> builderClass,
             final String containingOneofCamelCaseName,
             boolean isOneofField,
             boolean hasHasMethod) {
@@ -2322,7 +2399,7 @@
           final FieldDescriptor descriptor,
           final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass,
+          final Class<? extends Builder<?>> builderClass,
           final String containingOneofCamelCaseName) {
         isOneofField =
             descriptor.getContainingOneof() != null
@@ -2362,48 +2439,42 @@
       public Object get(final GeneratedMessageV3 message) {
         return invoker.get(message);
       }
+
       @Override
-      public Object get(GeneratedMessageV3.Builder builder) {
+      public Object get(GeneratedMessageV3.Builder<?> builder) {
         return invoker.get(builder);
       }
+
       @Override
       public Object getRaw(final GeneratedMessageV3 message) {
         return get(message);
       }
+
       @Override
-      public Object getRaw(GeneratedMessageV3.Builder builder) {
-        return get(builder);
-      }
-      @Override
-      public void set(final Builder builder, final Object value) {
+      public void set(final Builder<?> builder, final Object value) {
         invoker.set(builder, value);
       }
+
       @Override
       public Object getRepeated(final GeneratedMessageV3 message, final int index) {
         throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
       }
+
       @Override
-      public Object getRepeatedRaw(final GeneratedMessageV3 message, final int index) {
-        throw new UnsupportedOperationException(
-            "getRepeatedFieldRaw() called on a singular field.");
-      }
-      @Override
-      public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
+      public Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index) {
         throw new UnsupportedOperationException("getRepeatedField() called on a singular field.");
       }
+
       @Override
-      public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) {
-        throw new UnsupportedOperationException(
-            "getRepeatedFieldRaw() called on a singular field.");
-      }
-      @Override
-      public void setRepeated(final Builder builder, final int index, final Object value) {
+      public void setRepeated(final Builder<?> builder, final int index, final Object value) {
         throw new UnsupportedOperationException("setRepeatedField() called on a singular field.");
       }
+
       @Override
-      public void addRepeated(final Builder builder, final Object value) {
+      public void addRepeated(final Builder<?> builder, final Object value) {
         throw new UnsupportedOperationException("addRepeatedField() called on a singular field.");
       }
+
       @Override
       public boolean has(final GeneratedMessageV3 message) {
         if (!hasHasMethod) {
@@ -2414,8 +2485,9 @@
         }
         return invoker.has(message);
       }
+
       @Override
-      public boolean has(GeneratedMessageV3.Builder builder) {
+      public boolean has(GeneratedMessageV3.Builder<?> builder) {
         if (!hasHasMethod) {
           if (isOneofField) {
             return invoker.getOneofFieldNumber(builder) == field.getNumber();
@@ -2424,31 +2496,37 @@
         }
         return invoker.has(builder);
       }
+
       @Override
       public int getRepeatedCount(final GeneratedMessageV3 message) {
         throw new UnsupportedOperationException(
             "getRepeatedFieldSize() called on a singular field.");
       }
+
       @Override
-      public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
+      public int getRepeatedCount(GeneratedMessageV3.Builder<?> builder) {
         throw new UnsupportedOperationException(
             "getRepeatedFieldSize() called on a singular field.");
       }
+
       @Override
-      public void clear(final Builder builder) {
+      public void clear(final Builder<?> builder) {
         invoker.clear(builder);
       }
+
       @Override
       public Message.Builder newBuilder() {
         throw new UnsupportedOperationException(
             "newBuilderForField() called on a non-Message type.");
       }
+
       @Override
-      public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+      public Message.Builder getBuilder(GeneratedMessageV3.Builder<?> builder) {
         throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
       }
+
       @Override
-      public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
+      public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder<?> builder, int index) {
         throw new UnsupportedOperationException(
             "getRepeatedFieldBuilder() called on a non-Message type.");
       }
@@ -2456,9 +2534,9 @@
 
     private static class RepeatedFieldAccessor implements FieldAccessor {
       interface MethodInvoker {
-        public Object get(final GeneratedMessageV3 message);
+        Object get(final GeneratedMessageV3 message);
 
-        public Object get(GeneratedMessageV3.Builder<?> builder);
+        Object get(GeneratedMessageV3.Builder<?> builder);
 
         Object getRepeated(final GeneratedMessageV3 message, final int index);
 
@@ -2477,21 +2555,21 @@
       }
 
       private static final class ReflectionInvoker implements MethodInvoker {
-        protected final Method getMethod;
-        protected final Method getMethodBuilder;
-        protected final Method getRepeatedMethod;
-        protected final Method getRepeatedMethodBuilder;
-        protected final Method setRepeatedMethod;
-        protected final Method addRepeatedMethod;
-        protected final Method getCountMethod;
-        protected final Method getCountMethodBuilder;
-        protected final Method clearMethod;
+        private final Method getMethod;
+        private final Method getMethodBuilder;
+        private final Method getRepeatedMethod;
+        private final Method getRepeatedMethodBuilder;
+        private final Method setRepeatedMethod;
+        private final Method addRepeatedMethod;
+        private final Method getCountMethod;
+        private final Method getCountMethodBuilder;
+        private final Method clearMethod;
 
         ReflectionInvoker(
             final FieldDescriptor descriptor,
             final String camelCaseName,
             final Class<? extends GeneratedMessageV3> messageClass,
-            final Class<? extends Builder> builderClass) {
+            final Class<? extends Builder<?>> builderClass) {
           getMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "List");
           getMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "List");
           getRepeatedMethod = getMethodOrDie(messageClass, "get" + camelCaseName, Integer.TYPE);
@@ -2517,8 +2595,7 @@
         }
 
         @Override
-        public Object getRepeated(
-            final GeneratedMessageV3 message, final int index) {
+        public Object getRepeated(final GeneratedMessageV3 message, final int index) {
           return invokeOrDie(getRepeatedMethod, message, index);
         }
 
@@ -2535,8 +2612,7 @@
         }
 
         @Override
-        public void addRepeated(
-            final GeneratedMessageV3.Builder<?> builder, final Object value) {
+        public void addRepeated(final GeneratedMessageV3.Builder<?> builder, final Object value) {
           // TODO(b/230609037): remove the unused variable
           Object unused = invokeOrDie(addRepeatedMethod, builder, value);
         }
@@ -2558,13 +2634,14 @@
         }
       }
 
-      protected final Class type;
+      protected final Class<?> type;
       protected final MethodInvoker invoker;
 
       RepeatedFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass) {
+          final Class<? extends Builder<?>> builderClass) {
         ReflectionInvoker reflectionInvoker =
             new ReflectionInvoker(descriptor, camelCaseName, messageClass, builderClass);
         type = reflectionInvoker.getRepeatedMethod.getReturnType();
@@ -2579,20 +2656,19 @@
       public Object get(final GeneratedMessageV3 message) {
         return invoker.get(message);
       }
+
       @Override
-      public Object get(GeneratedMessageV3.Builder builder) {
+      public Object get(GeneratedMessageV3.Builder<?> builder) {
         return invoker.get(builder);
       }
+
       @Override
       public Object getRaw(final GeneratedMessageV3 message) {
         return get(message);
       }
+
       @Override
-      public Object getRaw(GeneratedMessageV3.Builder builder) {
-        return get(builder);
-      }
-      @Override
-      public void set(final Builder builder, final Object value) {
+      public void set(final Builder<?> builder, final Object value) {
         // Add all the elements individually.  This serves two purposes:
         // 1) Verifies that each element has the correct type.
         // 2) Insures that the caller cannot modify the list later on and
@@ -2602,61 +2678,65 @@
           addRepeated(builder, element);
         }
       }
+
       @Override
       public Object getRepeated(final GeneratedMessageV3 message, final int index) {
         return invoker.getRepeated(message, index);
       }
+
       @Override
-      public Object getRepeated(GeneratedMessageV3.Builder builder, int index) {
+      public Object getRepeated(GeneratedMessageV3.Builder<?> builder, int index) {
         return invoker.getRepeated(builder, index);
       }
+
       @Override
-      public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
-        return getRepeated(message, index);
-      }
-      @Override
-      public Object getRepeatedRaw(GeneratedMessageV3.Builder builder, int index) {
-        return getRepeated(builder, index);
-      }
-      @Override
-      public void setRepeated(final Builder builder, final int index, final Object value) {
+      public void setRepeated(final Builder<?> builder, final int index, final Object value) {
         invoker.setRepeated(builder, index, value);
       }
+
       @Override
-      public void addRepeated(final Builder builder, final Object value) {
+      public void addRepeated(final Builder<?> builder, final Object value) {
         invoker.addRepeated(builder, value);
       }
+
       @Override
       public boolean has(final GeneratedMessageV3 message) {
         throw new UnsupportedOperationException("hasField() called on a repeated field.");
       }
+
       @Override
-      public boolean has(GeneratedMessageV3.Builder builder) {
+      public boolean has(GeneratedMessageV3.Builder<?> builder) {
         throw new UnsupportedOperationException("hasField() called on a repeated field.");
       }
+
       @Override
       public int getRepeatedCount(final GeneratedMessageV3 message) {
         return invoker.getRepeatedCount(message);
       }
+
       @Override
-      public int getRepeatedCount(GeneratedMessageV3.Builder builder) {
+      public int getRepeatedCount(GeneratedMessageV3.Builder<?> builder) {
         return invoker.getRepeatedCount(builder);
       }
+
       @Override
-      public void clear(final Builder builder) {
+      public void clear(final Builder<?> builder) {
         invoker.clear(builder);
       }
+
       @Override
       public Message.Builder newBuilder() {
         throw new UnsupportedOperationException(
             "newBuilderForField() called on a non-Message type.");
       }
+
       @Override
-      public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+      public Message.Builder getBuilder(GeneratedMessageV3.Builder<?> builder) {
         throw new UnsupportedOperationException("getFieldBuilder() called on a non-Message type.");
       }
+
       @Override
-      public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder builder, int index) {
+      public Message.Builder getRepeatedBuilder(GeneratedMessageV3.Builder<?> builder, int index) {
         throw new UnsupportedOperationException(
             "getRepeatedFieldBuilder() called on a non-Message type.");
       }
@@ -2664,16 +2744,12 @@
 
     private static class MapFieldAccessor implements FieldAccessor {
       MapFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
-          final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass) {
+          final FieldDescriptor descriptor, final Class<? extends GeneratedMessageV3> messageClass) {
         field = descriptor;
-        Method getDefaultInstanceMethod =
-            getMethodOrDie(messageClass, "getDefaultInstance");
-        MapField defaultMapField = getMapField(
-            (GeneratedMessageV3) invokeOrDie(getDefaultInstanceMethod, null));
-        mapEntryMessageDefaultInstance =
-            defaultMapField.getMapEntryMessageDefaultInstance();
+        Method getDefaultInstanceMethod = getMethodOrDie(messageClass, "getDefaultInstance");
+        MapField<?, ?> defaultMapField =
+            getMapField((GeneratedMessageV3) invokeOrDie(getDefaultInstanceMethod, null));
+        mapEntryMessageDefaultInstance = defaultMapField.getMapEntryMessageDefaultInstance();
       }
 
       private final FieldDescriptor field;
@@ -2683,14 +2759,12 @@
         return (MapField<?, ?>) message.internalGetMapField(field.getNumber());
       }
 
-      private MapField<?, ?> getMapField(GeneratedMessageV3.Builder builder) {
+      private MapField<?, ?> getMapField(GeneratedMessageV3.Builder<?> builder) {
         return (MapField<?, ?>) builder.internalGetMapField(field.getNumber());
       }
 
-      private MapField<?, ?> getMutableMapField(
-          GeneratedMessageV3.Builder builder) {
-        return (MapField<?, ?>) builder.internalGetMutableMapField(
-            field.getNumber());
+      private MapField<?, ?> getMutableMapField(GeneratedMessageV3.Builder<?> builder) {
+        return (MapField<?, ?>) builder.internalGetMutableMapField(field.getNumber());
       }
 
       private Message coerceType(Message value) {
@@ -2708,9 +2782,8 @@
       }
 
       @Override
-      @SuppressWarnings("unchecked")
       public Object get(GeneratedMessageV3 message) {
-        List result = new ArrayList<>();
+        List<Object> result = new ArrayList<>();
         for (int i = 0; i < getRepeatedCount(message); i++) {
           result.add(getRepeated(message, i));
         }
@@ -2718,9 +2791,8 @@
       }
 
       @Override
-      @SuppressWarnings("unchecked")
-      public Object get(Builder builder) {
-        List result = new ArrayList<>();
+      public Object get(Builder<?> builder) {
+        List<Object> result = new ArrayList<>();
         for (int i = 0; i < getRepeatedCount(builder); i++) {
           result.add(getRepeated(builder, i));
         }
@@ -2733,14 +2805,9 @@
       }
 
       @Override
-      public Object getRaw(GeneratedMessageV3.Builder builder) {
-        return get(builder);
-      }
-
-      @Override
-      public void set(Builder builder, Object value) {
+      public void set(Builder<?> builder, Object value) {
         clear(builder);
-        for (Object entry : (List) value) {
+        for (Object entry : (List<?>) value) {
           addRepeated(builder, entry);
         }
       }
@@ -2751,40 +2818,28 @@
       }
 
       @Override
-      public Object getRepeated(Builder builder, int index) {
+      public Object getRepeated(Builder<?> builder, int index) {
         return getMapField(builder).getList().get(index);
       }
 
       @Override
-      public Object getRepeatedRaw(GeneratedMessageV3 message, int index) {
-        return getRepeated(message, index);
-      }
-
-      @Override
-      public Object getRepeatedRaw(Builder builder, int index) {
-        return getRepeated(builder, index);
-      }
-
-      @Override
-      public void setRepeated(Builder builder, int index, Object value) {
+      public void setRepeated(Builder<?> builder, int index, Object value) {
         getMutableMapField(builder).getMutableList().set(index, coerceType((Message) value));
       }
 
       @Override
-      public void addRepeated(Builder builder, Object value) {
+      public void addRepeated(Builder<?> builder, Object value) {
         getMutableMapField(builder).getMutableList().add(coerceType((Message) value));
       }
 
       @Override
       public boolean has(GeneratedMessageV3 message) {
-        throw new UnsupportedOperationException(
-            "hasField() is not supported for repeated fields.");
+        throw new UnsupportedOperationException("hasField() is not supported for repeated fields.");
       }
 
       @Override
-      public boolean has(Builder builder) {
-        throw new UnsupportedOperationException(
-            "hasField() is not supported for repeated fields.");
+      public boolean has(Builder<?> builder) {
+        throw new UnsupportedOperationException("hasField() is not supported for repeated fields.");
       }
 
       @Override
@@ -2793,40 +2848,39 @@
       }
 
       @Override
-      public int getRepeatedCount(Builder builder) {
+      public int getRepeatedCount(Builder<?> builder) {
         return getMapField(builder).getList().size();
       }
 
       @Override
-      public void clear(Builder builder) {
+      public void clear(Builder<?> builder) {
         getMutableMapField(builder).getMutableList().clear();
       }
 
       @Override
-      public com.google.protobuf.Message.Builder newBuilder() {
+      public Message.Builder newBuilder() {
         return mapEntryMessageDefaultInstance.newBuilderForType();
       }
 
       @Override
-      public com.google.protobuf.Message.Builder getBuilder(Builder builder) {
-        throw new UnsupportedOperationException(
-            "Nested builder not supported for map fields.");
+      public Message.Builder getBuilder(Builder<?> builder) {
+        throw new UnsupportedOperationException("Nested builder not supported for map fields.");
       }
 
       @Override
-      public com.google.protobuf.Message.Builder getRepeatedBuilder(Builder builder, int index) {
+      public Message.Builder getRepeatedBuilder(Builder<?> builder, int index) {
         throw new UnsupportedOperationException("Map fields cannot be repeated");
       }
     }
 
     // ---------------------------------------------------------------
 
-    private static final class SingularEnumFieldAccessor
-        extends SingularFieldAccessor {
+    private static final class SingularEnumFieldAccessor extends SingularFieldAccessor {
       SingularEnumFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass,
+          final Class<? extends Builder<?>> builderClass,
           final String containingOneofCamelCaseName) {
         super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
 
@@ -2837,21 +2891,18 @@
 
         supportUnknownEnumValue = descriptor.getFile().supportsUnknownEnumValue();
         if (supportUnknownEnumValue) {
-          getValueMethod =
-              getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
-          getValueMethodBuilder =
-              getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
-          setValueMethod =
-              getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
+          getValueMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Value");
+          getValueMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Value");
+          setValueMethod = getMethodOrDie(builderClass, "set" + camelCaseName + "Value", int.class);
         }
       }
 
-      private EnumDescriptor enumDescriptor;
+      private final EnumDescriptor enumDescriptor;
 
-      private Method valueOfMethod;
-      private Method getValueDescriptorMethod;
+      private final Method valueOfMethod;
+      private final Method getValueDescriptorMethod;
 
-      private boolean supportUnknownEnumValue;
+      private final boolean supportUnknownEnumValue;
       private Method getValueMethod;
       private Method getValueMethodBuilder;
       private Method setValueMethod;
@@ -2866,7 +2917,7 @@
       }
 
       @Override
-      public Object get(final GeneratedMessageV3.Builder builder) {
+      public Object get(final GeneratedMessageV3.Builder<?> builder) {
         if (supportUnknownEnumValue) {
           int value = (Integer) invokeOrDie(getValueMethodBuilder, builder);
           return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
@@ -2875,7 +2926,7 @@
       }
 
       @Override
-      public void set(final Builder builder, final Object value) {
+      public void set(final Builder<?> builder, final Object value) {
         if (supportUnknownEnumValue) {
           // TODO(b/230609037): remove the unused variable
           Object unused =
@@ -2886,12 +2937,12 @@
       }
     }
 
-    private static final class RepeatedEnumFieldAccessor
-        extends RepeatedFieldAccessor {
+    private static final class RepeatedEnumFieldAccessor extends RepeatedFieldAccessor {
       RepeatedEnumFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass) {
+          final Class<? extends Builder<?>> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         enumDescriptor = descriptor.getEnumType();
@@ -2911,21 +2962,22 @@
               getMethodOrDie(builderClass, "add" + camelCaseName + "Value", int.class);
         }
       }
-      private EnumDescriptor enumDescriptor;
+
+      private final EnumDescriptor enumDescriptor;
 
       private final Method valueOfMethod;
       private final Method getValueDescriptorMethod;
 
-      private boolean supportUnknownEnumValue;
+      private final boolean supportUnknownEnumValue;
+
       private Method getRepeatedValueMethod;
       private Method getRepeatedValueMethodBuilder;
       private Method setRepeatedValueMethod;
       private Method addRepeatedValueMethod;
 
       @Override
-      @SuppressWarnings("unchecked")
       public Object get(final GeneratedMessageV3 message) {
-        final List newList = new ArrayList<>();
+        final List<Object> newList = new ArrayList<>();
         final int size = getRepeatedCount(message);
         for (int i = 0; i < size; i++) {
           newList.add(getRepeated(message, i));
@@ -2934,9 +2986,8 @@
       }
 
       @Override
-      @SuppressWarnings("unchecked")
-      public Object get(final GeneratedMessageV3.Builder builder) {
-        final List newList = new ArrayList<>();
+      public Object get(final GeneratedMessageV3.Builder<?> builder) {
+        final List<Object> newList = new ArrayList<>();
         final int size = getRepeatedCount(builder);
         for (int i = 0; i < size; i++) {
           newList.add(getRepeated(builder, i));
@@ -2954,7 +3005,7 @@
       }
 
       @Override
-      public Object getRepeated(final GeneratedMessageV3.Builder builder, final int index) {
+      public Object getRepeated(final GeneratedMessageV3.Builder<?> builder, final int index) {
         if (supportUnknownEnumValue) {
           int value = (Integer) invokeOrDie(getRepeatedValueMethodBuilder, builder, index);
           return enumDescriptor.findValueByNumberCreatingIfUnknown(value);
@@ -2963,7 +3014,7 @@
       }
 
       @Override
-      public void setRepeated(final Builder builder, final int index, final Object value) {
+      public void setRepeated(final Builder<?> builder, final int index, final Object value) {
         if (supportUnknownEnumValue) {
           // TODO(b/230609037): remove the unused variable
           Object unused =
@@ -2976,8 +3027,9 @@
         }
         super.setRepeated(builder, index, invokeOrDie(valueOfMethod, null, value));
       }
+
       @Override
-      public void addRepeated(final Builder builder, final Object value) {
+      public void addRepeated(final Builder<?> builder, final Object value) {
         if (supportUnknownEnumValue) {
           // TODO(b/230609037): remove the unused variable
           Object unused =
@@ -2994,33 +3046,27 @@
     /**
      * Field accessor for string fields.
      *
-     * <p>This class makes getFooBytes() and setFooBytes() available for
-     * reflection API so that reflection based serialize/parse functions can
-     * access the raw bytes of the field to preserve non-UTF8 bytes in the
-     * string.
+     * <p>This class makes getFooBytes() and setFooBytes() available for reflection API so that
+     * reflection based serialize/parse functions can access the raw bytes of the field to preserve
+     * non-UTF8 bytes in the string.
      *
-     * <p>This ensures the serialize/parse round-trip safety, which is important
-     * for servers which forward messages.
+     * <p>This ensures the serialize/parse round-trip safety, which is important for servers which
+     * forward messages.
      */
-    private static final class SingularStringFieldAccessor
-        extends SingularFieldAccessor {
+    private static final class SingularStringFieldAccessor extends SingularFieldAccessor {
       SingularStringFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass,
+          final Class<? extends Builder<?>> builderClass,
           final String containingOneofCamelCaseName) {
-        super(descriptor, camelCaseName, messageClass, builderClass,
-            containingOneofCamelCaseName);
-        getBytesMethod = getMethodOrDie(messageClass,
-            "get" + camelCaseName + "Bytes");
-        getBytesMethodBuilder = getMethodOrDie(builderClass,
-            "get" + camelCaseName + "Bytes");
-        setBytesMethodBuilder = getMethodOrDie(builderClass,
-            "set" + camelCaseName + "Bytes", ByteString.class);
+        super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
+        getBytesMethod = getMethodOrDie(messageClass, "get" + camelCaseName + "Bytes");
+        setBytesMethodBuilder =
+            getMethodOrDie(builderClass, "set" + camelCaseName + "Bytes", ByteString.class);
       }
 
       private final Method getBytesMethod;
-      private final Method getBytesMethodBuilder;
       private final Method setBytesMethodBuilder;
 
       @Override
@@ -3029,12 +3075,7 @@
       }
 
       @Override
-      public Object getRaw(GeneratedMessageV3.Builder builder) {
-        return invokeOrDie(getBytesMethodBuilder, builder);
-      }
-
-      @Override
-      public void set(GeneratedMessageV3.Builder builder, Object value) {
+      public void set(GeneratedMessageV3.Builder<?> builder, Object value) {
         if (value instanceof ByteString) {
           // TODO(b/230609037): remove the unused variable
           Object unused = invokeOrDie(setBytesMethodBuilder, builder, value);
@@ -3046,19 +3087,17 @@
 
     // ---------------------------------------------------------------
 
-    private static final class SingularMessageFieldAccessor
-        extends SingularFieldAccessor {
+    private static final class SingularMessageFieldAccessor extends SingularFieldAccessor {
       SingularMessageFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass,
+          final Class<? extends Builder<?>> builderClass,
           final String containingOneofCamelCaseName) {
-        super(descriptor, camelCaseName, messageClass, builderClass,
-            containingOneofCamelCaseName);
+        super(descriptor, camelCaseName, messageClass, builderClass, containingOneofCamelCaseName);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
-        getBuilderMethodBuilder =
-            getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
+        getBuilderMethodBuilder = getMethodOrDie(builderClass, "get" + camelCaseName + "Builder");
       }
 
       private final Method newBuilderMethod;
@@ -3079,30 +3118,32 @@
       }
 
       @Override
-      public void set(final Builder builder, final Object value) {
+      public void set(final Builder<?> builder, final Object value) {
         super.set(builder, coerceType(value));
       }
+
       @Override
       public Message.Builder newBuilder() {
         return (Message.Builder) invokeOrDie(newBuilderMethod, null);
       }
+
       @Override
-      public Message.Builder getBuilder(GeneratedMessageV3.Builder builder) {
+      public Message.Builder getBuilder(GeneratedMessageV3.Builder<?> builder) {
         return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder);
       }
     }
 
-    private static final class RepeatedMessageFieldAccessor
-        extends RepeatedFieldAccessor {
+    private static final class RepeatedMessageFieldAccessor extends RepeatedFieldAccessor {
       RepeatedMessageFieldAccessor(
-          final FieldDescriptor descriptor, final String camelCaseName,
+          final FieldDescriptor descriptor,
+          final String camelCaseName,
           final Class<? extends GeneratedMessageV3> messageClass,
-          final Class<? extends Builder> builderClass) {
+          final Class<? extends Builder<?>> builderClass) {
         super(descriptor, camelCaseName, messageClass, builderClass);
 
         newBuilderMethod = getMethodOrDie(type, "newBuilder");
-        getBuilderMethodBuilder = getMethodOrDie(builderClass,
-            "get" + camelCaseName + "Builder", Integer.TYPE);
+        getBuilderMethodBuilder =
+            getMethodOrDie(builderClass, "get" + camelCaseName + "Builder", Integer.TYPE);
       }
 
       private final Method newBuilderMethod;
@@ -3123,30 +3164,33 @@
       }
 
       @Override
-      public void setRepeated(final Builder builder, final int index, final Object value) {
+      public void setRepeated(final Builder<?> builder, final int index, final Object value) {
         super.setRepeated(builder, index, coerceType(value));
       }
+
       @Override
-      public void addRepeated(final Builder builder, final Object value) {
+      public void addRepeated(final Builder<?> builder, final Object value) {
         super.addRepeated(builder, coerceType(value));
       }
+
       @Override
       public Message.Builder newBuilder() {
         return (Message.Builder) invokeOrDie(newBuilderMethod, null);
       }
+
       @Override
       public Message.Builder getRepeatedBuilder(
-          final GeneratedMessageV3.Builder builder, final int index) {
-        return (Message.Builder) invokeOrDie(
-            getBuilderMethodBuilder, builder, index);
+          final GeneratedMessageV3.Builder<?> builder, final int index) {
+        return (Message.Builder) invokeOrDie(getBuilderMethodBuilder, builder, index);
       }
     }
   }
 
   /**
-   * Replaces this object in the output stream with a serialized form.
-   * Part of Java's serialization magic.  Generated sub-classes must override
-   * this method by calling {@code return super.writeReplace();}
+   * Replaces this object in the output stream with a serialized form. Part of Java's serialization
+   * magic. Generated sub-classes must override this method by calling {@code return
+   * super.writeReplace();}
+   *
    * @return a SerializedForm of this message
    */
   protected Object writeReplace() throws ObjectStreamException {
@@ -3156,13 +3200,13 @@
   /**
    * Checks that the {@link Extension} is non-Lite and returns it as a {@link GeneratedExtension}.
    */
-  private static <MessageType extends ExtendableMessage<MessageType>, T>
-      Extension<MessageType, T> checkNotLite(ExtensionLite<MessageType, T> extension) {
+  private static <MessageT extends ExtendableMessage<MessageT>, T>
+      Extension<MessageT, T> checkNotLite(ExtensionLite<MessageT, T> extension) {
     if (extension.isLite()) {
       throw new IllegalArgumentException("Expected non-lite extension.");
     }
 
-    return (Extension<MessageType, T>) extension;
+    return (Extension<MessageT, T>) extension;
   }
 
   protected static boolean isStringEmpty(final Object value) {
@@ -3198,8 +3242,8 @@
     }
   }
 
-  protected static void writeStringNoTag(
-      CodedOutputStream output, final Object value) throws IOException {
+  protected static void writeStringNoTag(CodedOutputStream output, final Object value)
+      throws IOException {
     if (value instanceof String) {
       output.writeStringNoTag((String) value);
     } else {
@@ -3211,7 +3255,8 @@
       CodedOutputStream out,
       MapField<Integer, V> field,
       MapEntry<Integer, V> defaultEntry,
-      int fieldNumber) throws IOException {
+      int fieldNumber)
+      throws IOException {
     Map<Integer, V> m = field.getMap();
     if (!out.isSerializationDeterministic()) {
       serializeMapTo(out, m, defaultEntry, fieldNumber);
@@ -3226,11 +3271,8 @@
     }
     Arrays.sort(keys);
     for (int key : keys) {
-      out.writeMessage(fieldNumber,
-          defaultEntry.newBuilderForType()
-              .setKey(key)
-              .setValue(m.get(key))
-              .build());
+      out.writeMessage(
+          fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
     }
   }
 
@@ -3253,11 +3295,8 @@
     }
     Arrays.sort(keys);
     for (long key : keys) {
-      out.writeMessage(fieldNumber,
-          defaultEntry.newBuilderForType()
-              .setKey(key)
-              .setValue(m.get(key))
-              .build());
+      out.writeMessage(
+          fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
     }
   }
 
@@ -3279,11 +3318,8 @@
     keys = m.keySet().toArray(keys);
     Arrays.sort(keys);
     for (String key : keys) {
-      out.writeMessage(fieldNumber,
-          defaultEntry.newBuilderForType()
-              .setKey(key)
-              .setValue(m.get(key))
-              .build());
+      out.writeMessage(
+          fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
     }
   }
 
@@ -3310,28 +3346,23 @@
       boolean key)
       throws IOException {
     if (m.containsKey(key)) {
-      out.writeMessage(fieldNumber,
-          defaultEntry.newBuilderForType()
-              .setKey(key)
-              .setValue(m.get(key))
-              .build());
+      out.writeMessage(
+          fieldNumber, defaultEntry.newBuilderForType().setKey(key).setValue(m.get(key)).build());
     }
   }
 
   /** Serialize the map using the iteration order. */
   private static <K, V> void serializeMapTo(
-      CodedOutputStream out,
-      Map<K, V> m,
-      MapEntry<K, V> defaultEntry,
-      int fieldNumber)
+      CodedOutputStream out, Map<K, V> m, MapEntry<K, V> defaultEntry, int fieldNumber)
       throws IOException {
     for (Map.Entry<K, V> entry : m.entrySet()) {
-      out.writeMessage(fieldNumber,
-          defaultEntry.newBuilderForType()
+      out.writeMessage(
+          fieldNumber,
+          defaultEntry
+              .newBuilderForType()
               .setKey(entry.getKey())
               .setValue(entry.getValue())
               .build());
     }
   }
 }
-
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 b6bbcb1..7a7270b 100644
--- a/java/core/src/main/java/com/google/protobuf/Internal.java
+++ b/java/core/src/main/java/com/google/protobuf/Internal.java
@@ -375,7 +375,6 @@
     }
   }
 
-
   /** An empty byte array constant used in generated code. */
   public static final byte[] EMPTY_BYTE_ARRAY = new byte[0];
 
@@ -386,7 +385,6 @@
   public static final CodedInputStream EMPTY_CODED_INPUT_STREAM =
       CodedInputStream.newInstance(EMPTY_BYTE_ARRAY);
 
-
   /** Helper method to merge two MessageLite instances. */
   static Object mergeMessage(Object destination, Object source) {
     return ((MessageLite) destination).toBuilder().mergeFrom((MessageLite) source).buildPartial();
@@ -600,6 +598,7 @@
     void addInt(int element);
 
     /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */
+    @CanIgnoreReturnValue
     int setInt(int index, int element);
 
     /** Returns a mutable clone of this list with the specified capacity. */
@@ -620,6 +619,7 @@
     void addBoolean(boolean element);
 
     /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */
+    @CanIgnoreReturnValue
     boolean setBoolean(int index, boolean element);
 
     /** Returns a mutable clone of this list with the specified capacity. */
@@ -640,6 +640,7 @@
     void addLong(long element);
 
     /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */
+    @CanIgnoreReturnValue
     long setLong(int index, long element);
 
     /** Returns a mutable clone of this list with the specified capacity. */
@@ -660,6 +661,7 @@
     void addDouble(double element);
 
     /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */
+    @CanIgnoreReturnValue
     double setDouble(int index, double element);
 
     /** Returns a mutable clone of this list with the specified capacity. */
@@ -680,11 +682,11 @@
     void addFloat(float element);
 
     /** Like {@link #set(int, Object)} but more efficient in that it doesn't box the element. */
+    @CanIgnoreReturnValue
     float setFloat(int index, float element);
 
     /** Returns a mutable clone of this list with the specified capacity. */
     @Override
     FloatList mutableCopyWithCapacity(int capacity);
   }
-
 }
diff --git a/java/core/src/main/java/com/google/protobuf/MapField.java b/java/core/src/main/java/com/google/protobuf/MapField.java
index 2fe8867..ee9c5ad 100644
--- a/java/core/src/main/java/com/google/protobuf/MapField.java
+++ b/java/core/src/main/java/com/google/protobuf/MapField.java
@@ -122,7 +122,6 @@
     }
   }
 
-
   private final Converter<K, V> converter;
 
   private MapField(Converter<K, V> converter, StorageMode mode, Map<K, V> mapData) {
@@ -137,19 +136,16 @@
     this(new ImmutableMessageConverter<K, V>(defaultEntry), mode, mapData);
   }
 
-
   /** Returns an immutable empty MapField. */
   public static <K, V> MapField<K, V> emptyMapField(MapEntry<K, V> defaultEntry) {
     return new MapField<K, V>(defaultEntry, StorageMode.MAP, Collections.<K, V>emptyMap());
   }
 
-
   /** Creates a new mutable empty MapField. */
   public static <K, V> MapField<K, V> newMapField(MapEntry<K, V> defaultEntry) {
     return new MapField<K, V>(defaultEntry, StorageMode.MAP, new LinkedHashMap<K, V>());
   }
 
-
   private Message convertKeyAndValueToMessage(K key, V value) {
     return converter.convertKeyAndValueToMessage(key, value);
   }
diff --git a/java/core/src/main/java/com/google/protobuf/Message.java b/java/core/src/main/java/com/google/protobuf/Message.java
index 3db1c77..3835586 100644
--- a/java/core/src/main/java/com/google/protobuf/Message.java
+++ b/java/core/src/main/java/com/google/protobuf/Message.java
@@ -39,18 +39,18 @@
  *
  * <p>See also {@link MessageLite}, which defines most of the methods that typical users care about.
  * {@link Message} adds methods that are not available in the "lite" runtime. The biggest added
- * features are introspection and reflection; that is, getting descriptors for the message type
- * and accessing the field values dynamically.
+ * features are introspection and reflection; that is, getting descriptors for the message type and
+ * accessing the field values dynamically.
  *
  * @author kenton@google.com Kenton Varda
  */
+@CheckReturnValue
 public interface Message extends MessageLite, MessageOrBuilder {
 
   // (From MessageLite, re-declared here only for return type covariance.)
   @Override
   Parser<? extends Message> getParserForType();
 
-
   // -----------------------------------------------------------------
   // Comparison and hashing
 
@@ -102,6 +102,7 @@
     // (From MessageLite.Builder, re-declared here only for return type
     // covariance.)
     @Override
+    @CanIgnoreReturnValue
     Builder clear();
 
     /**
@@ -121,6 +122,7 @@
      *
      * <p>This is equivalent to the {@code Message::MergeFrom} method in C++.
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(Message other);
 
     // (From MessageLite.Builder, re-declared here only for return type
@@ -135,9 +137,11 @@
     Builder clone();
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(CodedInputStream input) throws IOException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
         throws IOException;
 
@@ -190,18 +194,21 @@
      * Sets a field to the given value. The value must be of the correct type for this field, that
      * is, the same type that {@link Message#getField(Descriptors.FieldDescriptor)} returns.
      */
+    @CanIgnoreReturnValue
     Builder setField(Descriptors.FieldDescriptor field, Object value);
 
     /**
      * Clears the field. This is exactly equivalent to calling the generated "clear" accessor method
      * corresponding to the field.
      */
+    @CanIgnoreReturnValue
     Builder clearField(Descriptors.FieldDescriptor field);
 
     /**
      * Clears the oneof. This is exactly equivalent to calling the generated "clear" accessor method
      * corresponding to the oneof.
      */
+    @CanIgnoreReturnValue
     Builder clearOneof(Descriptors.OneofDescriptor oneof);
 
     /**
@@ -212,6 +219,7 @@
      * @throws IllegalArgumentException if the field is not a repeated field, or {@code
      *     field.getContainingType() != getDescriptorForType()}.
      */
+    @CanIgnoreReturnValue
     Builder setRepeatedField(Descriptors.FieldDescriptor field, int index, Object value);
 
     /**
@@ -220,12 +228,15 @@
      * @throws IllegalArgumentException if the field is not a repeated field, or {@code
      *     field.getContainingType() != getDescriptorForType()}
      */
+    @CanIgnoreReturnValue
     Builder addRepeatedField(Descriptors.FieldDescriptor field, Object value);
 
     /** Set the {@link UnknownFieldSet} for this message. */
+    @CanIgnoreReturnValue
     Builder setUnknownFields(UnknownFieldSet unknownFields);
 
     /** Merge some unknown fields into the {@link UnknownFieldSet} for this message. */
+    @CanIgnoreReturnValue
     Builder mergeUnknownFields(UnknownFieldSet unknownFields);
 
     // ---------------------------------------------------------------
@@ -234,30 +245,38 @@
     // (From MessageLite.Builder, re-declared here only for return type
     // covariance.)
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(InputStream input) throws IOException;
 
     @Override
+    @CanIgnoreReturnValue
     Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
         throws IOException;
 
diff --git a/java/core/src/main/java/com/google/protobuf/MessageLite.java b/java/core/src/main/java/com/google/protobuf/MessageLite.java
index f9b2f66..a622875 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageLite.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageLite.java
@@ -59,6 +59,7 @@
  *
  * @author kenton@google.com Kenton Varda
  */
+@CheckReturnValue
 public interface MessageLite extends MessageLiteOrBuilder {
 
   /**
@@ -122,7 +123,6 @@
    */
   void writeDelimitedTo(OutputStream output) throws IOException;
 
-
   // =================================================================
   // Builders
 
@@ -138,6 +138,7 @@
   /** Abstract interface implemented by Protocol Message builders. */
   interface Builder extends MessageLiteOrBuilder, Cloneable {
     /** Resets all fields to their default values. */
+    @CanIgnoreReturnValue
     Builder clear();
 
     /**
@@ -181,11 +182,12 @@
      * <p>Note: The caller should call {@link CodedInputStream#checkLastTagWas(int)} after calling
      * this to verify that the last tag seen was the appropriate end-group tag, or zero for EOF.
      *
-     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct according
+     *     to the protobuf wire format specification. The data is corrupt, incomplete, or was never
+     *     a protobuf in the first place.
      * @throws IOException an I/O error reading from the stream
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(CodedInputStream input) throws IOException;
 
     /**
@@ -193,11 +195,12 @@
      * that you want to be able to parse must be registered in {@code extensionRegistry}. Extensions
      * not in the registry will be treated as unknown fields.
      *
-     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct according
+     *     to the protobuf wire format specification. The data is corrupt, incomplete, or was never
+     *     a protobuf in the first place.
      * @throws IOException an I/O error reading from the stream
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(CodedInputStream input, ExtensionRegistryLite extensionRegistry)
         throws IOException;
 
@@ -209,10 +212,11 @@
      * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}.
      *
      * @throws InvalidProtocolBufferException the bytes in data are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     *     according to the protobuf wire format specification. The data is corrupt, incomplete, or
+     *     was never a protobuf in the first place.
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(ByteString data) throws InvalidProtocolBufferException;
 
     /**
@@ -220,10 +224,11 @@
      * is just a small wrapper around {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
      *
      * @throws InvalidProtocolBufferException the bytes in data are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     *     according to the protobuf wire format specification. The data is corrupt, incomplete, or
+     *     was never a protobuf in the first place.
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(ByteString data, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException;
 
@@ -232,10 +237,11 @@
      * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}.
      *
      * @throws InvalidProtocolBufferException the bytes in data are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     *     according to the protobuf wire format specification. The data is corrupt, incomplete, or
+     *     was never a protobuf in the first place.
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data) throws InvalidProtocolBufferException;
 
     /**
@@ -243,10 +249,11 @@
      * is just a small wrapper around {@link #mergeFrom(CodedInputStream)}.
      *
      * @throws InvalidProtocolBufferException the bytes in data are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     *     according to the protobuf wire format specification. The data is corrupt, incomplete, or
+     *     was never a protobuf in the first place.
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data, int off, int len) throws InvalidProtocolBufferException;
 
     /**
@@ -254,10 +261,11 @@
      * is just a small wrapper around {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
      *
      * @throws InvalidProtocolBufferException the bytes in data are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     *     according to the protobuf wire format specification. The data is corrupt, incomplete, or
+     *     was never a protobuf in the first place.
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException;
 
@@ -266,10 +274,11 @@
      * is just a small wrapper around {@link #mergeFrom(CodedInputStream,ExtensionRegistryLite)}.
      *
      * @throws InvalidProtocolBufferException the bytes in data are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     *     according to the protobuf wire format specification. The data is corrupt, incomplete, or
+     *     was never a protobuf in the first place.
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(byte[] data, int off, int len, ExtensionRegistryLite extensionRegistry)
         throws InvalidProtocolBufferException;
 
@@ -283,12 +292,13 @@
      *
      * <p>Despite usually reading the entire input, this does not close the stream.
      *
-     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct according
+     *     to the protobuf wire format specification. The data is corrupt, incomplete, or was never
+     *     a protobuf in the first place.
      * @throws IOException an I/O error reading from the stream
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(InputStream input) throws IOException;
 
     /**
@@ -298,6 +308,7 @@
      *
      * @return this
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
         throws IOException;
 
@@ -317,6 +328,7 @@
      *
      * <p>This is equivalent to the {@code Message::MergeFrom} method in C++.
      */
+    @CanIgnoreReturnValue
     Builder mergeFrom(MessageLite other);
 
     /**
@@ -326,9 +338,9 @@
      *
      * @return true if successful, or false if the stream is at EOF when the method starts. Any
      *     other error (including reaching EOF during parsing) causes an exception to be thrown.
-     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct according
+     *     to the protobuf wire format specification. The data is corrupt, incomplete, or was never
+     *     a protobuf in the first place.
      * @throws IOException an I/O error reading from the stream
      */
     boolean mergeDelimitedFrom(InputStream input) throws IOException;
@@ -338,9 +350,9 @@
      *
      * @return true if successful, or false if the stream is at EOF when the method starts. Any
      *     other error (including reaching EOF during parsing) causes an exception to be thrown.
-     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct
-     *     according to the protobuf wire format specification. The data is corrupt, incomplete,
-     *     or was never a protobuf in the first place.
+     * @throws InvalidProtocolBufferException the bytes read are not syntactically correct according
+     *     to the protobuf wire format specification. The data is corrupt, incomplete, or was never
+     *     a protobuf in the first place.
      * @throws IOException an I/O error reading from the stream
      */
     boolean mergeDelimitedFrom(InputStream input, ExtensionRegistryLite extensionRegistry)
diff --git a/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java b/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
index 7a5ef3e..927b95f 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageLiteOrBuilder.java
@@ -36,6 +36,7 @@
  *
  * @author jonp@google.com (Jon Perlow)
  */
+@CheckReturnValue
 public interface MessageLiteOrBuilder {
   /**
    * Get an instance of the type with no fields set. Because no fields are set, all getters for
diff --git a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
index 0254df9..2a4d867 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageOrBuilder.java
@@ -39,6 +39,7 @@
  *
  * @author jonp@google.com (Jon Perlow)
  */
+@CheckReturnValue
 public interface MessageOrBuilder extends MessageLiteOrBuilder {
 
   // (From MessageLite, re-declared here only for return type covariance.)
diff --git a/java/core/src/main/java/com/google/protobuf/MessageReflection.java b/java/core/src/main/java/com/google/protobuf/MessageReflection.java
index 294d841..0404042 100644
--- a/java/core/src/main/java/com/google/protobuf/MessageReflection.java
+++ b/java/core/src/main/java/com/google/protobuf/MessageReflection.java
@@ -673,7 +673,6 @@
     }
   }
 
-
   static class ExtensionAdapter implements MergeTarget {
 
     private final FieldSet<Descriptors.FieldDescriptor> extensions;
diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
index d56af6b..757bc66 100644
--- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilder.java
@@ -277,6 +277,7 @@
    * @param message the message to set
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilder<MType, BType, IType> setMessage(int index, MType message) {
     checkNotNull(message);
     ensureMutableMessageList();
@@ -298,6 +299,7 @@
    * @param message the message to add
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilder<MType, BType, IType> addMessage(MType message) {
     checkNotNull(message);
     ensureMutableMessageList();
@@ -319,6 +321,7 @@
    * @param message the message to add
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilder<MType, BType, IType> addMessage(int index, MType message) {
     checkNotNull(message);
     ensureMutableMessageList();
@@ -338,6 +341,7 @@
    * @param values the messages to add
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilder<MType, BType, IType> addAllMessages(
       Iterable<? extends MType> values) {
     for (final MType value : values) {
diff --git a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java
index f6acc77..25b2123 100644
--- a/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java
+++ b/java/core/src/main/java/com/google/protobuf/RepeatedFieldBuilderV3.java
@@ -277,6 +277,7 @@
    * @param message the message to set
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilderV3<MType, BType, IType> setMessage(int index, MType message) {
     checkNotNull(message);
     ensureMutableMessageList();
@@ -298,6 +299,7 @@
    * @param message the message to add
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilderV3<MType, BType, IType> addMessage(MType message) {
     checkNotNull(message);
     ensureMutableMessageList();
@@ -319,6 +321,7 @@
    * @param message the message to add
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilderV3<MType, BType, IType> addMessage(int index, MType message) {
     checkNotNull(message);
     ensureMutableMessageList();
@@ -338,6 +341,7 @@
    * @param values the messages to add
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public RepeatedFieldBuilderV3<MType, BType, IType> addAllMessages(
       Iterable<? extends MType> values) {
     for (final MType value : values) {
diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
index acdc1de..ebcc3bc 100644
--- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
+++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilder.java
@@ -156,6 +156,7 @@
    * @param message the message to set
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public SingleFieldBuilder<MType, BType, IType> setMessage(MType message) {
     this.message = checkNotNull(message);
     if (builder != null) {
@@ -172,6 +173,7 @@
    * @param value the value to merge from
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public SingleFieldBuilder<MType, BType, IType> mergeFrom(MType value) {
     if (builder == null && message == message.getDefaultInstanceForType()) {
       message = value;
@@ -188,6 +190,7 @@
    * @return the builder
    */
   @SuppressWarnings("unchecked")
+  @CanIgnoreReturnValue
   public SingleFieldBuilder<MType, BType, IType> clear() {
     message =
         (MType)
@@ -199,6 +202,9 @@
       builder = null;
     }
     onChanged();
+    // After clearing, parent is dirty, but this field builder is now clean and any changes should
+    // trickle up.
+    isClean = true;
     return this;
   }
 
diff --git a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java
index a6c639c..6101dfe 100644
--- a/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java
+++ b/java/core/src/main/java/com/google/protobuf/SingleFieldBuilderV3.java
@@ -156,6 +156,7 @@
    * @param message the message to set
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public SingleFieldBuilderV3<MType, BType, IType> setMessage(MType message) {
     this.message = checkNotNull(message);
     if (builder != null) {
@@ -172,6 +173,7 @@
    * @param value the value to merge from
    * @return the builder
    */
+  @CanIgnoreReturnValue
   public SingleFieldBuilderV3<MType, BType, IType> mergeFrom(MType value) {
     if (builder == null && message == message.getDefaultInstanceForType()) {
       message = value;
@@ -188,6 +190,7 @@
    * @return the builder
    */
   @SuppressWarnings("unchecked")
+  @CanIgnoreReturnValue
   public SingleFieldBuilderV3<MType, BType, IType> clear() {
     message =
         (MType)
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 a8af845..65e403e 100644
--- a/java/core/src/main/java/com/google/protobuf/TextFormat.java
+++ b/java/core/src/main/java/com/google/protobuf/TextFormat.java
@@ -61,7 +61,6 @@
 
   private static final String DEBUG_STRING_SILENT_MARKER = "\t ";
 
-
   /**
    * 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
@@ -116,8 +115,8 @@
 
   /**
    * Generates a human readable form of this message, useful for debugging and other purposes, with
-   * no newline characters. This is just a trivial wrapper around
-   * {@link TextFormat.Printer#shortDebugString(MessageOrBuilder)}.
+   * no newline characters. This is just a trivial wrapper around {@link
+   * TextFormat.Printer#shortDebugString(MessageOrBuilder)}.
    */
   public static String shortDebugString(final MessageOrBuilder message) {
     return printer().shortDebugString(message);
@@ -133,7 +132,7 @@
   public static String shortDebugString(final FieldDescriptor field, final Object value) {
     return printer().shortDebugString(field, value);
   }
-  //
+
   /**
    * Generates a human readable form of the unknown fields, useful for debugging and other
    * purposes, with no newline characters.
@@ -192,7 +191,7 @@
   public static String printToUnicodeString(final UnknownFieldSet fields) {
     return printer().escapingNonAscii(false).printToString(fields);
   }
-  //
+
   /** @deprecated Use {@code printer().printField(FieldDescriptor, Object, Appendable)} */
   @Deprecated
   public static void printField(
@@ -200,13 +199,13 @@
       throws IOException {
     printer().printField(field, value, output);
   }
-  //
+
   /** @deprecated Use {@code printer().printFieldToString(FieldDescriptor, Object)} */
   @Deprecated
   public static String printFieldToString(final FieldDescriptor field, final Object value) {
     return printer().printFieldToString(field, value);
   }
-  //
+
   /**
    * Outputs a unicode textual representation of the value of given field value.
    *
@@ -459,16 +458,13 @@
       }
     }
 
-    /**
-     * An adapter class that can take a {@link MapEntry} and returns its key and entry.
-     */
+    /** An adapter class that can take a {@link MapEntry} and returns its key and entry. */
     private static class MapEntryAdapter implements Comparable<MapEntryAdapter> {
       private Object entry;
 
       @SuppressWarnings({"rawtypes"})
       private MapEntry mapEntry;
 
-
       private final FieldDescriptor.JavaType fieldType;
 
       MapEntryAdapter(Object entry, FieldDescriptor fieldDescriptor) {
@@ -741,9 +737,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(" {");
@@ -953,6 +949,7 @@
      * the next token is parsed.
      */
     private boolean containsSilentMarkerAfterCurrentToken = false;
+
     private boolean containsSilentMarkerAfterPrevToken = false;
 
     /** Construct a tokenizer that parses tokens from the given text. */
@@ -1378,7 +1375,6 @@
     private ParseException floatParseException(final NumberFormatException e) {
       return parseException("Couldn't parse number: " + e.getMessage());
     }
-
   }
 
   /** Thrown when parsing an invalid text format message. */
@@ -1502,7 +1498,6 @@
     PARSER.merge(input, extensionRegistry, builder);
   }
 
-
   /**
    * Parse a text-format message from {@code input} and merge the contents into {@code builder}.
    * Extensions will be recognized if they are registered in {@code extensionRegistry}.
@@ -1533,7 +1528,6 @@
     return output;
   }
 
-
   /**
    * Parser for text-format proto2 instances. This class is thread-safe. The implementation largely
    * follows google/protobuf/text_format.cc.
@@ -1551,7 +1545,8 @@
      * the current token is part of the field value, so the silent marker is indicated by
      * containsSilentMarkerAfterPrevToken.
      */
-    private void detectSilentMarker(Tokenizer tokenizer) {
+    private void detectSilentMarker(
+        Tokenizer tokenizer, Descriptor immediateMessageType, String fieldName) {
     }
 
     /**
@@ -1628,8 +1623,8 @@
        * unknown field is encountered. If this is set, the parser will only log a warning. Allow
        * unknown fields will also allow unknown extensions.
        *
-       * <p>Use of this parameter is discouraged which may hide some errors (e.g.
-       * spelling error on field name).
+       * <p>Use of this parameter is discouraged which may hide some errors (e.g. spelling error on
+       * field name).
        */
       public Builder setAllowUnknownFields(boolean allowUnknownFields) {
         this.allowUnknownFields = allowUnknownFields;
@@ -1637,10 +1632,9 @@
       }
 
       /**
-       * Set whether this parser will allow unknown extensions. By default, an
-       * exception is thrown if unknown extension is encountered. If this is set true,
-       * the parser will only log a warning. Allow unknown extensions does not mean
-       * allow normal unknown fields.
+       * Set whether this parser will allow unknown extensions. By default, an exception is thrown
+       * if unknown extension is encountered. If this is set true, the parser will only log a
+       * warning. Allow unknown extensions does not mean allow normal unknown fields.
        */
       public Builder setAllowUnknownExtensions(boolean allowUnknownExtensions) {
         this.allowUnknownExtensions = allowUnknownExtensions;
@@ -1704,7 +1698,6 @@
       merge(toStringBuilder(input), extensionRegistry, builder);
     }
 
-
     private static final int BUFFER_SIZE = 4096;
 
     // TODO(chrisn): See if working around java.io.Reader#read(CharBuffer)
@@ -1725,7 +1718,8 @@
 
     static final class UnknownField {
       static enum Type {
-        FIELD, EXTENSION;
+        FIELD,
+        EXTENSION;
       }
 
       final String message;
@@ -1786,7 +1780,6 @@
         throws ParseException {
       final Tokenizer tokenizer = new Tokenizer(input);
       MessageReflection.BuilderAdapter target = new MessageReflection.BuilderAdapter(builder);
-
       List<UnknownField> unknownFields = new ArrayList<UnknownField>();
 
       while (!tokenizer.atEnd()) {
@@ -1795,7 +1788,6 @@
       checkUnknownFields(unknownFields);
     }
 
-
     /** Parse a single field from {@code tokenizer} and merge it into {@code builder}. */
     private void mergeField(
         final Tokenizer tokenizer,
@@ -1803,12 +1795,7 @@
         final MessageReflection.MergeTarget target,
         List<UnknownField> unknownFields)
         throws ParseException {
-      mergeField(
-          tokenizer,
-          extensionRegistry,
-          target,
-          parseInfoTreeBuilder,
-          unknownFields);
+      mergeField(tokenizer, extensionRegistry, target, parseInfoTreeBuilder, unknownFields);
     }
 
     /** Parse a single field from {@code tokenizer} and merge it into {@code target}. */
@@ -1820,38 +1807,40 @@
         List<UnknownField> unknownFields)
         throws ParseException {
       FieldDescriptor field = null;
+      String name;
       int startLine = tokenizer.getLine();
       int startColumn = tokenizer.getColumn();
       final Descriptor type = target.getDescriptorForType();
       ExtensionRegistry.ExtensionInfo extension = null;
 
       if ("google.protobuf.Any".equals(type.getFullName()) && tokenizer.tryConsume("[")) {
-        mergeAnyFieldValue(tokenizer, extensionRegistry, target, parseTreeBuilder, unknownFields,
-            type);
+        mergeAnyFieldValue(
+            tokenizer, extensionRegistry, target, parseTreeBuilder, unknownFields, type);
         return;
       }
 
       if (tokenizer.tryConsume("[")) {
         // An extension.
-        final StringBuilder name = new StringBuilder(tokenizer.consumeIdentifier());
+        StringBuilder nameBuilder = new StringBuilder(tokenizer.consumeIdentifier());
         while (tokenizer.tryConsume(".")) {
-          name.append('.');
-          name.append(tokenizer.consumeIdentifier());
+          nameBuilder.append('.');
+          nameBuilder.append(tokenizer.consumeIdentifier());
         }
+        name = nameBuilder.toString();
 
-        extension = target.findExtensionByName(extensionRegistry, name.toString());
+        extension = target.findExtensionByName(extensionRegistry, name);
 
         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(
@@ -1866,7 +1855,7 @@
 
         tokenizer.consume("]");
       } else {
-        final String name = tokenizer.consumeIdentifier();
+        name = tokenizer.consumeIdentifier();
         field = type.findFieldByName(name);
 
         // Group names are expected to be capitalized as they appear in the
@@ -1890,13 +1879,14 @@
         }
 
         if (field == null) {
-          String message = (tokenizer.getPreviousLine() + 1)
-                           + ":"
-                           + (tokenizer.getPreviousColumn() + 1)
-                           + ":\t"
-                           + type.getFullName()
-                           + "."
-                           + name;
+          String message =
+              (tokenizer.getPreviousLine() + 1)
+                  + ":"
+                  + (tokenizer.getPreviousColumn() + 1)
+                  + ":\t"
+                  + type.getFullName()
+                  + "."
+                  + name;
           unknownFields.add(new UnknownField(message, UnknownField.Type.FIELD));
         }
       }
@@ -1909,18 +1899,18 @@
         // start with "{" or "<" which indicates the beginning of a message body.
         // If there is no ":" or there is a "{" or "<" after ":", this field has
         // to be a message or the input is ill-formed.
-        detectSilentMarker(tokenizer);
+        detectSilentMarker(tokenizer, type, name);
         if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("{") && !tokenizer.lookingAt("<")) {
           skipFieldValue(tokenizer);
         } else {
-          skipFieldMessage(tokenizer);
+          skipFieldMessage(tokenizer, type);
         }
         return;
       }
 
       // Handle potential ':'.
       if (field.getJavaType() == FieldDescriptor.JavaType.MESSAGE) {
-        detectSilentMarker(tokenizer);
+        detectSilentMarker(tokenizer, type, field.getFullName());
         tokenizer.tryConsume(":"); // optional
         if (parseTreeBuilder != null) {
           TextFormatParseInfoTree.Builder childParseTreeBuilder =
@@ -1944,7 +1934,7 @@
               unknownFields);
         }
       } else {
-        detectSilentMarker(tokenizer);
+        detectSilentMarker(tokenizer, type, field.getFullName());
         tokenizer.consume(":"); // required
         consumeFieldValues(
             tokenizer,
@@ -1967,6 +1957,29 @@
       }
     }
 
+    private String consumeFullTypeName(Tokenizer tokenizer) throws ParseException {
+      // If there is not a leading `[`, this is just a type name.
+      if (!tokenizer.tryConsume("[")) {
+        return tokenizer.consumeIdentifier();
+      }
+
+      // Otherwise, this is an extension or google.protobuf.Any type URL: we consume proto path
+      // elements until we've addressed the type.
+      String name = tokenizer.consumeIdentifier();
+      while (tokenizer.tryConsume(".")) {
+        name += "." + tokenizer.consumeIdentifier();
+      }
+      if (tokenizer.tryConsume("/")) {
+        name += "/" + tokenizer.consumeIdentifier();
+        while (tokenizer.tryConsume(".")) {
+          name += "." + tokenizer.consumeIdentifier();
+        }
+      }
+      tokenizer.consume("]");
+
+      return name;
+    }
+
     /**
      * Parse a one or more field values from {@code tokenizer} and merge it into {@code builder}.
      */
@@ -2058,8 +2071,13 @@
           // (java_proto_library for any_java_proto depends on the protobuf_impl).
           Message anyBuilder = DynamicMessage.getDefaultInstance(field.getMessageType());
           MessageReflection.MergeTarget anyField = target.newMergeTargetForField(field, anyBuilder);
-          mergeAnyFieldValue(tokenizer, extensionRegistry, anyField, parseTreeBuilder,
-              unknownFields, field.getMessageType());
+          mergeAnyFieldValue(
+              tokenizer,
+              extensionRegistry,
+              anyField,
+              parseTreeBuilder,
+              unknownFields,
+              field.getMessageType());
           value = anyField.finish();
           tokenizer.consume(endToken);
         } else {
@@ -2206,7 +2224,7 @@
           throw tokenizer.parseExceptionPreviousToken("Expected a valid type URL.");
         }
       }
-      detectSilentMarker(tokenizer);
+      detectSilentMarker(tokenizer, anyDescriptor, typeUrlBuilder.toString());
       tokenizer.tryConsume(":");
       final String anyEndToken;
       if (tokenizer.tryConsume("<")) {
@@ -2243,16 +2261,8 @@
     }
 
     /** Skips the next field including the field's name and value. */
-    private void skipField(Tokenizer tokenizer) throws ParseException {
-      if (tokenizer.tryConsume("[")) {
-        // Extension name.
-        do {
-          tokenizer.consumeIdentifier();
-        } while (tokenizer.tryConsume("."));
-        tokenizer.consume("]");
-      } else {
-        tokenizer.consumeIdentifier();
-      }
+    private void skipField(Tokenizer tokenizer, Descriptor type) throws ParseException {
+      String name = consumeFullTypeName(tokenizer);
 
       // Try to guess the type of this field.
       // If this field is not a message, there should be a ":" between the
@@ -2260,11 +2270,11 @@
       // start with "{" or "<" which indicates the beginning of a message body.
       // If there is no ":" or there is a "{" or "<" after ":", this field has
       // to be a message or the input is ill-formed.
-      detectSilentMarker(tokenizer);
+      detectSilentMarker(tokenizer, type, name);
       if (tokenizer.tryConsume(":") && !tokenizer.lookingAt("<") && !tokenizer.lookingAt("{")) {
         skipFieldValue(tokenizer);
       } else {
-        skipFieldMessage(tokenizer);
+        skipFieldMessage(tokenizer, type);
       }
       // For historical reasons, fields may optionally be separated by commas or
       // semicolons.
@@ -2276,7 +2286,7 @@
     /**
      * Skips the whole body of a message including the beginning delimiter and the ending delimiter.
      */
-    private void skipFieldMessage(Tokenizer tokenizer) throws ParseException {
+    private void skipFieldMessage(Tokenizer tokenizer, Descriptor type) throws ParseException {
       final String delimiter;
       if (tokenizer.tryConsume("<")) {
         delimiter = ">";
@@ -2285,7 +2295,7 @@
         delimiter = "}";
       }
       while (!tokenizer.lookingAt(">") && !tokenizer.lookingAt("}")) {
-        skipField(tokenizer);
+        skipField(tokenizer, type);
       }
       tokenizer.consume(delimiter);
     }
@@ -2469,9 +2479,10 @@
                 }
                 Character.UnicodeBlock unicodeBlock = Character.UnicodeBlock.of(codepoint);
                 if (unicodeBlock != null
-                        && (unicodeBlock.equals(Character.UnicodeBlock.LOW_SURROGATES)
-                    || unicodeBlock.equals(Character.UnicodeBlock.HIGH_SURROGATES)
-                    || unicodeBlock.equals(Character.UnicodeBlock.HIGH_PRIVATE_USE_SURROGATES))) {
+                    && (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()
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 422ff1f..3a9461f 100644
--- a/java/core/src/main/java/com/google/protobuf/TypeRegistry.java
+++ b/java/core/src/main/java/com/google/protobuf/TypeRegistry.java
@@ -55,7 +55,6 @@
     return EmptyTypeRegistryHolder.EMPTY;
   }
 
-
   public static Builder newBuilder() {
     return new Builder();
   }
diff --git a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
index 45b5a6b..d27d0b5 100644
--- a/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
+++ b/java/core/src/main/java/com/google/protobuf/UnknownFieldSet.java
@@ -89,7 +89,6 @@
   private static final UnknownFieldSet defaultInstance =
       new UnknownFieldSet(new TreeMap<Integer, Field>());
 
-
   @Override
   public boolean equals(Object other) {
     if (this == other) {
diff --git a/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
index 16521e1..164010e 100644
--- a/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
+++ b/java/core/src/main/java/com/google/protobuf/UnsafeByteOperations.java
@@ -43,7 +43,7 @@
  * ByteString} can lead to unexpected and undesirable consequences in your application, and will
  * likely be difficult to debug. Proceed with caution!
  *
- * <p>This can have a number of significant side affects that have spooky-action-at-a-distance-like
+ * <p>This can have a number of significant side effects that have spooky-action-at-a-distance-like
  * behavior. In particular, if the bytes value changes out from under a Protocol Buffer:
  *
  * <ul>
@@ -117,5 +117,4 @@
   public static void unsafeWriteTo(ByteString bytes, ByteOutput output) throws IOException {
     bytes.writeTo(output);
   }
-
 }
diff --git a/java/core/src/test/java/com/google/protobuf/AnyTest.java b/java/core/src/test/java/com/google/protobuf/AnyTest.java
index ee13ef1..11b214b 100644
--- a/java/core/src/test/java/com/google/protobuf/AnyTest.java
+++ b/java/core/src/test/java/com/google/protobuf/AnyTest.java
@@ -43,7 +43,6 @@
 /** Unit tests for Any message. */
 @RunWith(JUnit4.class)
 public class AnyTest {
-
   @Test
   public void testAnyGeneratedApi() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -58,7 +57,6 @@
     TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
     TestUtil.assertAllFieldsSet(result);
 
-
     // Unpacking to a wrong type will throw an exception.
     try {
       container.getValue().unpack(TestAny.class);
@@ -80,6 +78,40 @@
   }
 
   @Test
+  public void testAnyGeneratedExemplarApi() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    TestAny container = TestAny.newBuilder().setValue(Any.pack(message)).build();
+
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
+    assertThat(container.getValue().isSameTypeAs(TestAny.getDefaultInstance())).isFalse();
+
+    TestAllTypes result = container.getValue().unpackSameTypeAs(TestAllTypes.getDefaultInstance());
+    TestUtil.assertAllFieldsSet(result);
+
+    // Unpacking to a wrong exemplar will throw an exception.
+    try {
+      container.getValue().unpackSameTypeAs(TestAny.getDefaultInstance());
+      assertWithMessage("Exception is expected.").fail();
+    } catch (InvalidProtocolBufferException e) {
+      // expected.
+    }
+
+    // Test that unpacking throws an exception if parsing fails.
+    TestAny.Builder containerBuilder = container.toBuilder();
+    containerBuilder.getValueBuilder().setValue(ByteString.copyFrom(new byte[] {0x11}));
+    container = containerBuilder.build();
+    try {
+      container.getValue().unpackSameTypeAs(TestAllTypes.getDefaultInstance());
+      assertWithMessage("Exception is expected.").fail();
+    } catch (InvalidProtocolBufferException e) {
+      // expected.
+    }
+  }
+
+  @Test
   public void testCustomTypeUrls() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestUtil.setAllFields(builder);
@@ -91,7 +123,9 @@
         .isEqualTo("xxx.com/" + TestAllTypes.getDescriptor().getFullName());
 
     assertThat(container.getValue().is(TestAllTypes.class)).isTrue();
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
     assertThat(container.getValue().is(TestAny.class)).isFalse();
+    assertThat(container.getValue().isSameTypeAs(TestAny.getDefaultInstance())).isFalse();
 
     TestAllTypes result = container.getValue().unpack(TestAllTypes.class);
     TestUtil.assertAllFieldsSet(result);
@@ -102,7 +136,9 @@
         .isEqualTo("yyy.com/" + TestAllTypes.getDescriptor().getFullName());
 
     assertThat(container.getValue().is(TestAllTypes.class)).isTrue();
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
     assertThat(container.getValue().is(TestAny.class)).isFalse();
+    assertThat(container.getValue().isSameTypeAs(TestAny.getDefaultInstance())).isFalse();
 
     result = container.getValue().unpack(TestAllTypes.class);
     TestUtil.assertAllFieldsSet(result);
@@ -113,13 +149,55 @@
         .isEqualTo("/" + TestAllTypes.getDescriptor().getFullName());
 
     assertThat(container.getValue().is(TestAllTypes.class)).isTrue();
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
     assertThat(container.getValue().is(TestAny.class)).isFalse();
+    assertThat(container.getValue().isSameTypeAs(TestAny.getDefaultInstance())).isFalse();
 
     result = container.getValue().unpack(TestAllTypes.class);
     TestUtil.assertAllFieldsSet(result);
   }
 
   @Test
+  public void testCustomTypeUrlsWithExemplars() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    TestAny container = TestAny.newBuilder().setValue(Any.pack(message, "xxx.com")).build();
+
+    assertThat(container.getValue().getTypeUrl())
+        .isEqualTo("xxx.com/" + TestAllTypes.getDescriptor().getFullName());
+
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
+    assertThat(container.getValue().isSameTypeAs(TestAny.getDefaultInstance())).isFalse();
+
+    TestAllTypes result = container.getValue().unpackSameTypeAs(TestAllTypes.getDefaultInstance());
+    TestUtil.assertAllFieldsSet(result);
+
+    container = TestAny.newBuilder().setValue(Any.pack(message, "yyy.com/")).build();
+
+    assertThat(container.getValue().getTypeUrl())
+        .isEqualTo("yyy.com/" + TestAllTypes.getDescriptor().getFullName());
+
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
+    assertThat(container.getValue().isSameTypeAs(TestAny.getDefaultInstance())).isFalse();
+
+    result = container.getValue().unpackSameTypeAs(TestAllTypes.getDefaultInstance());
+    TestUtil.assertAllFieldsSet(result);
+
+    container = TestAny.newBuilder().setValue(Any.pack(message, "")).build();
+
+    assertThat(container.getValue().getTypeUrl())
+        .isEqualTo("/" + TestAllTypes.getDescriptor().getFullName());
+
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
+    assertThat(container.getValue().isSameTypeAs(TestAny.getDefaultInstance())).isFalse();
+
+    result = container.getValue().unpackSameTypeAs(TestAllTypes.getDefaultInstance());
+    TestUtil.assertAllFieldsSet(result);
+  }
+
+  @Test
   public void testCachedUnpackResult() throws Exception {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
     TestUtil.setAllFields(builder);
@@ -133,4 +211,19 @@
     TestAllTypes result2 = container.getValue().unpack(TestAllTypes.class);
     assertThat(Objects.equals(result1, result2)).isTrue();
   }
+
+  @Test
+  public void testCachedUnpackExemplarResult() throws Exception {
+    TestAllTypes.Builder builder = TestAllTypes.newBuilder();
+    TestUtil.setAllFields(builder);
+    TestAllTypes message = builder.build();
+
+    TestAny container = TestAny.newBuilder().setValue(Any.pack(message)).build();
+
+    assertThat(container.getValue().isSameTypeAs(TestAllTypes.getDefaultInstance())).isTrue();
+
+    TestAllTypes result1 = container.getValue().unpackSameTypeAs(TestAllTypes.getDefaultInstance());
+    TestAllTypes result2 = container.getValue().unpackSameTypeAs(TestAllTypes.getDefaultInstance());
+    assertThat(Objects.equals(result1, result2)).isTrue();
+  }
 }
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 db3a0c2..12ff6dd 100644
--- a/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
+++ b/java/core/src/test/java/com/google/protobuf/CodedInputStreamTest.java
@@ -424,7 +424,6 @@
     }
   }
 
-
   /**
    * Test that a bug in skipRawBytes() has been fixed: if the skip skips exactly up to a limit, this
    * should not break things.
@@ -672,7 +671,6 @@
         // success.
       }
 
-
       CodedInputStream input = inputType.newDecoder(data100);
       input.setRecursionLimit(8);
       try {
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 a88baca..ee11953 100644
--- a/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DescriptorsTest.java
@@ -61,6 +61,7 @@
 import protobuf_unittest.UnittestProto.TestJsonName;
 import protobuf_unittest.UnittestProto.TestMultipleExtensionRanges;
 import protobuf_unittest.UnittestProto.TestRequired;
+import protobuf_unittest.UnittestProto.TestReservedEnumFields;
 import protobuf_unittest.UnittestProto.TestReservedFields;
 import protobuf_unittest.UnittestProto.TestService;
 import java.util.Collections;
@@ -323,7 +324,6 @@
     assertThat(service.getFullName()).isEqualTo("protobuf_unittest.TestService");
     assertThat(service.getFile()).isEqualTo(UnittestProto.getDescriptor());
 
-
     MethodDescriptor fooMethod = service.getMethods().get(0);
     assertThat(fooMethod.getName()).isEqualTo("Foo");
     assertThat(fooMethod.getInputType()).isEqualTo(UnittestProto.FooRequest.getDescriptor());
@@ -336,7 +336,6 @@
     assertThat(barMethod.getOutputType()).isEqualTo(UnittestProto.BarResponse.getDescriptor());
     assertThat(service.findMethodByName("Bar")).isEqualTo(barMethod);
 
-
     assertThat(service.findMethodByName("NoSuchMethod")).isNull();
 
     for (int i = 0; i < service.getMethods().size(); i++) {
@@ -344,7 +343,6 @@
     }
   }
 
-
   @Test
   public void testCustomOptions() throws Exception {
     // Get the descriptor indirectly from a dependent proto class. This is to
@@ -463,15 +461,15 @@
   /** Tests that parsing an unknown enum throws an exception */
   @Test
   public void testParseUnknownEnum() {
-    FieldDescriptorProto.Builder field = FieldDescriptorProto.newBuilder()
-        .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
-        .setTypeName("UnknownEnum")
-        .setType(FieldDescriptorProto.Type.TYPE_ENUM)
-        .setName("bar")
-        .setNumber(1);
-    DescriptorProto.Builder messageType = DescriptorProto.newBuilder()
-        .setName("Foo")
-        .addField(field);
+    FieldDescriptorProto.Builder field =
+        FieldDescriptorProto.newBuilder()
+            .setLabel(FieldDescriptorProto.Label.LABEL_OPTIONAL)
+            .setTypeName("UnknownEnum")
+            .setType(FieldDescriptorProto.Type.TYPE_ENUM)
+            .setName("bar")
+            .setNumber(1);
+    DescriptorProto.Builder messageType =
+        DescriptorProto.newBuilder().setName("Foo").addField(field);
     FileDescriptorProto fooProto =
         FileDescriptorProto.newBuilder()
             .setName("foo.proto")
@@ -486,7 +484,6 @@
     }
   }
 
-
   /**
    * Tests the translate/crosslink for an example where a message field's name and type name are the
    * same.
@@ -560,8 +557,10 @@
         Descriptors.FileDescriptor.buildFrom(barProto, new FileDescriptor[] {fooFile});
 
     // Items in the FileDescriptor array can be in any order.
-    Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {fooFile, barFile});
-    Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {barFile, fooFile});
+    FileDescriptor unused1 =
+        Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {fooFile, barFile});
+    FileDescriptor unused2 =
+        Descriptors.FileDescriptor.buildFrom(bazProto, new FileDescriptor[] {barFile, fooFile});
   }
 
   @Test
@@ -623,7 +622,8 @@
                             .setName("bar")
                             .setNumber(1)))
             .build();
-    Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true);
+    FileDescriptor unused =
+        Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[0], true);
   }
 
   @Test
@@ -657,7 +657,8 @@
         Descriptors.FileDescriptor.buildFrom(forwardProto, new FileDescriptor[] {barFile});
 
     try {
-      Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile});
+      FileDescriptor unused =
+          Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile});
       assertWithMessage("DescriptorValidationException expected").fail();
     } catch (DescriptorValidationException e) {
       assertThat(e).hasMessageThat().contains("Bar");
@@ -695,7 +696,8 @@
     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});
+    FileDescriptor unused =
+        Descriptors.FileDescriptor.buildFrom(fooProto, new FileDescriptor[] {forwardFile});
   }
 
   /** Tests the translate/crosslink for an example with a more complex namespace referencing. */
@@ -793,6 +795,20 @@
   }
 
   @Test
+  public void testReservedEnumFields() {
+    EnumDescriptor d = TestReservedEnumFields.getDescriptor();
+    assertThat(d.isReservedNumber(2)).isTrue();
+    assertThat(d.isReservedNumber(8)).isFalse();
+    assertThat(d.isReservedNumber(9)).isTrue();
+    assertThat(d.isReservedNumber(10)).isTrue();
+    assertThat(d.isReservedNumber(11)).isTrue();
+    assertThat(d.isReservedNumber(12)).isFalse();
+    assertThat(d.isReservedName("foo")).isFalse();
+    assertThat(d.isReservedName("bar")).isTrue();
+    assertThat(d.isReservedName("baz")).isTrue();
+  }
+
+  @Test
   public void testToString() {
     assertThat(
             UnittestProto.TestAllTypes.getDescriptor()
@@ -826,7 +842,8 @@
                             .build())
                     .build())
             .build();
-    Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
+    FileDescriptor unused =
+        Descriptors.FileDescriptor.buildFrom(fileDescriptorProto, new FileDescriptor[0]);
   }
 
   @Test
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 8e1abc0..abe7caf 100644
--- a/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/DynamicMessageTest.java
@@ -44,6 +44,7 @@
 import protobuf_unittest.UnittestProto.TestAllTypes.NestedMessage;
 import protobuf_unittest.UnittestProto.TestEmptyMessage;
 import protobuf_unittest.UnittestProto.TestPackedTypes;
+import java.util.ArrayList;
 import org.junit.Test;
 import org.junit.function.ThrowingRunnable;
 import org.junit.runner.RunWith;
@@ -231,6 +232,19 @@
   }
 
   @Test
+  public void testDynamicMessagePackedEmptySerialization() throws Exception {
+    Message message =
+        DynamicMessage.newBuilder(TestPackedTypes.getDescriptor())
+            .setField(
+                TestPackedTypes.getDescriptor()
+                    .findFieldByNumber(TestPackedTypes.PACKED_INT64_FIELD_NUMBER),
+                new ArrayList<Long>())
+            .build();
+
+    assertThat(message.toByteString()).isEqualTo(ByteString.EMPTY);
+  }
+
+  @Test
   public void testDynamicMessagePackedParsing() throws Exception {
     TestPackedTypes.Builder builder = TestPackedTypes.newBuilder();
     TestUtil.setPackedFields(builder);
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 c4830af..b26c809 100644
--- a/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
+++ b/java/core/src/test/java/com/google/protobuf/FieldPresenceTest.java
@@ -500,5 +500,4 @@
     assertThat(builder.isInitialized()).isTrue();
     assertThat(builder.buildPartial().isInitialized()).isTrue();
   }
-
 }
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 55864af..3fc47c3 100644
--- a/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
+++ b/java/core/src/test/java/com/google/protobuf/GeneratedMessageTest.java
@@ -801,7 +801,6 @@
     assertThat(fieldBuilder.build().getField(field)).isEqualTo(expected);
   }
 
-
   @Test
   public void testGetBuilderForNonMessageExtensionField() {
     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
@@ -1529,7 +1528,7 @@
       assertThat(builder.getFooInt()).isEqualTo(123);
       TestOneof2 message = builder.buildPartial();
       assertThat(message.hasFooInt()).isTrue();
-      assertThat(123).isEqualTo(message.getFooInt());
+      assertThat(message.getFooInt()).isEqualTo(123);
 
       assertThat(builder.clearFooInt().hasFooInt()).isFalse();
       TestOneof2 message2 = builder.build();
@@ -1943,7 +1942,7 @@
 
   @Test
   public void
-  extendableBuilder_extensionFieldContainingBuilder_setRepeatedFieldOverwritesElement() {
+      extendableBuilder_extensionFieldContainingBuilder_setRepeatedFieldOverwritesElement() {
     TestAllExtensions.Builder builder = TestAllExtensions.newBuilder();
     builder.addRepeatedField(REPEATED_NESTED_MESSAGE_EXTENSION, NestedMessage.getDefaultInstance());
     // Calling getRepeatedFieldBuilder and ignoring the returned Builder should have no
diff --git a/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java b/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
index 98cee80..953ff57 100644
--- a/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LazyFieldLiteTest.java
@@ -238,7 +238,6 @@
         .isEqualTo(messageWithExtensions);
   }
 
-
   // Help methods.
 
   private LazyFieldLite createLazyFieldLiteFromMessage(MessageLite message) {
@@ -262,5 +261,4 @@
     assertThat(unexpected).isNotSameInstanceAs(actual);
     assertThat((unexpected != null && unexpected.equals(actual))).isFalse();
   }
-
 }
diff --git a/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java b/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
index 1270ef0..9ea7f93 100644
--- a/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
+++ b/java/core/src/test/java/com/google/protobuf/LiteEqualsAndHashTest.java
@@ -30,14 +30,13 @@
 
 package com.google.protobuf;
 
+import junit.framework.TestCase;
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Bar;
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.BarPrime;
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.Foo;
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestOneofEquals;
 import protobuf_unittest.lite_equals_and_hash.LiteEqualsAndHash.TestRecursiveOneof;
 
-import junit.framework.TestCase;
-
 /**
  * Test generate equal and hash methods for the lite runtime.
  *
@@ -120,6 +119,6 @@
 
   public void testRecursiveHashcode() {
     // This tests that we don't infinite loop.
-    TestRecursiveOneof.getDefaultInstance().hashCode();
+    int unused = TestRecursiveOneof.getDefaultInstance().hashCode();
   }
 }
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 2f74f96..0f08f9d 100644
--- a/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
+++ b/java/core/src/test/java/com/google/protobuf/MapForProto2Test.java
@@ -67,26 +67,26 @@
     builder.getMutableInt32ToInt32Field().put(1, 11);
     builder.getMutableInt32ToInt32Field().put(2, 22);
     builder.getMutableInt32ToInt32Field().put(3, 33);
-  //
+
     builder.getMutableInt32ToStringField().put(1, "11");
     builder.getMutableInt32ToStringField().put(2, "22");
     builder.getMutableInt32ToStringField().put(3, "33");
-  //
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
     builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
     builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
-  //
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
-  //
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(11).build());
     builder.getMutableInt32ToMessageField().put(
         2, MessageValue.newBuilder().setValue(22).build());
     builder.getMutableInt32ToMessageField().put(
         3, MessageValue.newBuilder().setValue(33).build());
-  //
+
     builder.getMutableStringToInt32Field().put("1", 11);
     builder.getMutableStringToInt32Field().put("2", 22);
     builder.getMutableStringToInt32Field().put("3", 33);
@@ -175,25 +175,25 @@
     builder.getMutableInt32ToInt32Field().put(1, 111);
     builder.getMutableInt32ToInt32Field().remove(2);
     builder.getMutableInt32ToInt32Field().put(4, 44);
-  //
+
     builder.getMutableInt32ToStringField().put(1, "111");
     builder.getMutableInt32ToStringField().remove(2);
     builder.getMutableInt32ToStringField().put(4, "44");
-  //
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
     builder.getMutableInt32ToBytesField().remove(2);
     builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
-  //
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().remove(2);
     builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
-  //
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(111).build());
     builder.getMutableInt32ToMessageField().remove(2);
     builder.getMutableInt32ToMessageField().put(
         4, MessageValue.newBuilder().setValue(44).build());
-  //
+
     builder.getMutableStringToInt32Field().put("1", 111);
     builder.getMutableStringToInt32Field().remove("2");
     builder.getMutableStringToInt32Field().put("4", 44);
@@ -234,7 +234,7 @@
     assertMapValuesSet(usingAccessors);
 
     assertThat(usingAccessors).isEqualTo(usingMutableMap);
-    //
+
     usingMutableMapBuilder = usingMutableMap.toBuilder();
     updateMapValuesUsingMutableMap(usingMutableMapBuilder);
     usingMutableMap = usingMutableMapBuilder.build();
@@ -340,7 +340,7 @@
     assertThat(builder.getInt32ToInt32Field()).isEqualTo(newMap(1, 2));
     builder.getMutableInt32ToInt32Field().put(2, 3);
     assertThat(builder.getInt32ToInt32Field()).isEqualTo(newMap(1, 2, 2, 3));
-  //
+
     Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
     enumMap.put(1, TestMap.EnumValue.BAR);
     assertThat(builder.build().getInt32ToEnumField())
@@ -355,7 +355,7 @@
     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
     assertThat(builder.getInt32ToEnumField())
             .isEqualTo(newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO));
-  //
+
     Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
     stringMap.put(1, "1");
     assertThat(builder.build().getInt32ToStringField()).isEqualTo(newMap(1, "1"));
@@ -368,7 +368,7 @@
     assertThat(builder.getInt32ToStringField()).isEqualTo(newMap(1, "1"));
     builder.getMutableInt32ToStringField().put(2, "2");
     assertThat(builder.getInt32ToStringField()).isEqualTo(newMap(1, "1", 2, "2"));
-  //
+
     Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
     messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
     assertThat(builder.build().getInt32ToMessageField())
@@ -386,7 +386,7 @@
         newMap(1, TestMap.MessageValue.getDefaultInstance(),
             2, TestMap.MessageValue.getDefaultInstance()));
   }
-  //
+
   @Test
   public void testMutableMapLifecycle_collections() {
     TestMap.Builder builder = TestMap.newBuilder();
@@ -433,13 +433,13 @@
     assertThat(builder.getInt32ToInt32Field()).isEqualTo(newMap(1, 2));
     assertThat(builder.build().getInt32ToInt32Field()).isEqualTo(newMap(1, 2));
   }
-  //
+
   private static <K, V> Map<K, V> newMap(K key1, V value1) {
     Map<K, V> map = new HashMap<K, V>();
     map.put(key1, value1);
     return map;
   }
-  //
+
   private static <K, V> Map<K, V> newMap(K key1, V value1, K key2, V value2) {
     Map<K, V> map = new HashMap<K, V>();
     map.put(key1, value1);
@@ -635,7 +635,6 @@
     // to be different.
   }
 
-
   // The following methods are used to test reflection API.
 
   private static FieldDescriptor f(String name) {
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 1bb7166..aca0b2a 100644
--- a/java/core/src/test/java/com/google/protobuf/MapTest.java
+++ b/java/core/src/test/java/com/google/protobuf/MapTest.java
@@ -66,26 +66,26 @@
     builder.getMutableInt32ToInt32Field().put(1, 11);
     builder.getMutableInt32ToInt32Field().put(2, 22);
     builder.getMutableInt32ToInt32Field().put(3, 33);
-  //
+
     builder.getMutableInt32ToStringField().put(1, "11");
     builder.getMutableInt32ToStringField().put(2, "22");
     builder.getMutableInt32ToStringField().put(3, "33");
-  //
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("11"));
     builder.getMutableInt32ToBytesField().put(2, TestUtil.toBytes("22"));
     builder.getMutableInt32ToBytesField().put(3, TestUtil.toBytes("33"));
-  //
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.FOO);
     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().put(3, TestMap.EnumValue.BAZ);
-  //
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(11).build());
     builder.getMutableInt32ToMessageField().put(
         2, MessageValue.newBuilder().setValue(22).build());
     builder.getMutableInt32ToMessageField().put(
         3, MessageValue.newBuilder().setValue(33).build());
-  //
+
     builder.getMutableStringToInt32Field().put("1", 11);
     builder.getMutableStringToInt32Field().put("2", 22);
     builder.getMutableStringToInt32Field().put("3", 33);
@@ -174,25 +174,25 @@
     builder.getMutableInt32ToInt32Field().put(1, 111);
     builder.getMutableInt32ToInt32Field().remove(2);
     builder.getMutableInt32ToInt32Field().put(4, 44);
-  //
+
     builder.getMutableInt32ToStringField().put(1, "111");
     builder.getMutableInt32ToStringField().remove(2);
     builder.getMutableInt32ToStringField().put(4, "44");
-  //
+
     builder.getMutableInt32ToBytesField().put(1, TestUtil.toBytes("111"));
     builder.getMutableInt32ToBytesField().remove(2);
     builder.getMutableInt32ToBytesField().put(4, TestUtil.toBytes("44"));
-  //
+
     builder.getMutableInt32ToEnumField().put(1, TestMap.EnumValue.BAR);
     builder.getMutableInt32ToEnumField().remove(2);
     builder.getMutableInt32ToEnumField().put(4, TestMap.EnumValue.QUX);
-  //
+
     builder.getMutableInt32ToMessageField().put(
         1, MessageValue.newBuilder().setValue(111).build());
     builder.getMutableInt32ToMessageField().remove(2);
     builder.getMutableInt32ToMessageField().put(
         4, MessageValue.newBuilder().setValue(44).build());
-  //
+
     builder.getMutableStringToInt32Field().put("1", 111);
     builder.getMutableStringToInt32Field().remove("2");
     builder.getMutableStringToInt32Field().put("4", 44);
@@ -233,7 +233,7 @@
     assertMapValuesSet(usingAccessors);
 
     assertThat(usingAccessors).isEqualTo(usingMutableMap);
-    //
+
     usingMutableMapBuilder = usingMutableMap.toBuilder();
     updateMapValuesUsingMutableMap(usingMutableMapBuilder);
     usingMutableMap = usingMutableMapBuilder.build();
@@ -339,7 +339,7 @@
     assertThat(builder.getInt32ToInt32Field()).isEqualTo(newMap(1, 2));
     builder.getMutableInt32ToInt32Field().put(2, 3);
     assertThat(builder.getInt32ToInt32Field()).isEqualTo(newMap(1, 2, 2, 3));
-  //
+
     Map<Integer, TestMap.EnumValue> enumMap = builder.getMutableInt32ToEnumField();
     enumMap.put(1, TestMap.EnumValue.BAR);
     assertThat(builder.build().getInt32ToEnumField())
@@ -354,7 +354,7 @@
     builder.getMutableInt32ToEnumField().put(2, TestMap.EnumValue.FOO);
     assertThat(builder.getInt32ToEnumField()).isEqualTo(
         newMap(1, TestMap.EnumValue.BAR, 2, TestMap.EnumValue.FOO));
-  //
+
     Map<Integer, String> stringMap = builder.getMutableInt32ToStringField();
     stringMap.put(1, "1");
     assertThat(builder.build().getInt32ToStringField()).isEqualTo(newMap(1, "1"));
@@ -367,7 +367,7 @@
     assertThat(builder.getInt32ToStringField()).isEqualTo(newMap(1, "1"));
     builder.putInt32ToStringField(2, "2");
     assertThat(builder.getInt32ToStringField()).isEqualTo(newMap(1, "1", 2, "2"));
-  //
+
     Map<Integer, TestMap.MessageValue> messageMap = builder.getMutableInt32ToMessageField();
     messageMap.put(1, TestMap.MessageValue.getDefaultInstance());
     assertThat( builder.build().getInt32ToMessageField())
@@ -385,7 +385,7 @@
         newMap(1, TestMap.MessageValue.getDefaultInstance(),
             2, TestMap.MessageValue.getDefaultInstance()));
   }
-  //
+
   @Test
   public void testMutableMapLifecycle_collections() {
     TestMap.Builder builder = TestMap.newBuilder();
diff --git a/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java b/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
index a3637f9..54e3de3 100644
--- a/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
+++ b/java/core/src/test/java/com/google/protobuf/NestedBuildersTest.java
@@ -69,7 +69,7 @@
     // belt.
     assertThat(vehicleBuilder.getEngine().getTimingBelt()).isEqualTo(expected);
   }
-  
+
   @Test
   public void testMessagesAndBuilders() {
     Vehicle.Builder vehicleBuilder = Vehicle.newBuilder();
diff --git a/java/core/src/test/java/com/google/protobuf/ParserTest.java b/java/core/src/test/java/com/google/protobuf/ParserTest.java
index 69c5795..510374f 100644
--- a/java/core/src/test/java/com/google/protobuf/ParserTest.java
+++ b/java/core/src/test/java/com/google/protobuf/ParserTest.java
@@ -117,7 +117,6 @@
     assertRoundTripEquals(TestUtil.getAllSet());
   }
 
-
   @Test
   public void testParsePartial() throws Exception {
     assertParsePartial(TestRequired.parser(), TestRequired.newBuilder().setA(1).buildPartial());
@@ -199,7 +198,6 @@
     assertThat(emptyMessage.toByteString()).isEqualTo(TestUtil.getAllSet().toByteString());
   }
 
-
   @Test
   public void testOptimizeForSize() throws Exception {
     TestOptimizedForSize.Builder builder = TestOptimizedForSize.newBuilder();
diff --git a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java
index d2215b0..872eaf4 100644
--- a/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java
+++ b/java/core/src/test/java/com/google/protobuf/SingleFieldBuilderV3Test.java
@@ -82,7 +82,7 @@
     assertThat(mockParent.getInvalidationCount()).isEqualTo(0);
     assertThat(builder.getBuilder().getOptionalInt32()).isEqualTo(1);
     assertThat(builder.getMessage().getOptionalInt32()).isEqualTo(1);
-    builder.build();
+    TestAllTypes unused = builder.build();
     builder.getBuilder().setOptionalInt32(2);
     assertThat(builder.getBuilder().getOptionalInt32()).isEqualTo(2);
     assertThat(builder.getMessage().getOptionalInt32()).isEqualTo(2);
diff --git a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
index fdeccc2..bb73a6b 100644
--- a/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
+++ b/java/core/src/test/java/com/google/protobuf/SmallSortedMapTest.java
@@ -34,6 +34,7 @@
 import static com.google.common.truth.Truth.assertWithMessage;
 import static java.lang.Math.min;
 
+import java.util.AbstractMap;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.HashMap;
@@ -48,52 +49,6 @@
 
 @RunWith(JUnit4.class)
 public class SmallSortedMapTest {
-  // java.util.AbstractMap.SimpleEntry is private in JDK 1.5. We re-implement it
-  // here for JDK 1.5 users.
-  private static class SimpleEntry<K, V> implements Map.Entry<K, V> {
-    private final K key;
-    private V value;
-
-    SimpleEntry(K key, V value) {
-      this.key = key;
-      this.value = value;
-    }
-
-    @Override
-    public K getKey() {
-      return key;
-    }
-
-    @Override
-    public V getValue() {
-      return value;
-    }
-
-    @Override
-    public V setValue(V value) {
-      V oldValue = this.value;
-      this.value = value;
-      return oldValue;
-    }
-
-    private static boolean eq(Object o1, Object o2) {
-      return o1 == null ? o2 == null : o1.equals(o2);
-    }
-
-    @Override
-    public boolean equals(Object o) {
-      if (!(o instanceof Map.Entry)) {
-        return false;
-      }
-      Map.Entry<?, ?> e = (Map.Entry<?, ?>) o;
-      return eq(key, e.getKey()) && eq(value, e.getValue());
-    }
-
-    @Override
-    public int hashCode() {
-      return ((key == null) ? 0 : key.hashCode()) ^ ((value == null) ? 0 : value.hashCode());
-    }
-  }
 
   @Test
   public void testPutAndGetArrayEntriesOnly() {
@@ -242,8 +197,8 @@
     }
     Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
     for (int i = 0; i < 6; i++) {
-      assertThat(entrySet).contains(new SimpleEntry<Integer, Integer>(i, i + 1));
-      assertThat(entrySet).doesNotContain(new SimpleEntry<Integer, Integer>(i, i));
+      assertThat(entrySet).contains(new AbstractMap.SimpleEntry<Integer, Integer>(i, i + 1));
+      assertThat(entrySet).doesNotContain(new AbstractMap.SimpleEntry<Integer, Integer>(i, i));
     }
   }
 
@@ -252,7 +207,7 @@
     SmallSortedMap<Integer, Integer> map = SmallSortedMap.newInstanceForTest(3);
     Set<Map.Entry<Integer, Integer>> entrySet = map.entrySet();
     for (int i = 0; i < 6; i++) {
-      Map.Entry<Integer, Integer> entry = new SimpleEntry<>(i, i + 1);
+      Map.Entry<Integer, Integer> entry = new AbstractMap.SimpleEntry<>(i, i + 1);
       assertThat(entrySet.add(entry)).isTrue();
       assertThat(entrySet.add(entry)).isFalse();
     }
@@ -272,7 +227,7 @@
       assertThat(map.put(i, i + 1)).isNull();
     }
     for (int i = 0; i < 6; i++) {
-      Map.Entry<Integer, Integer> entry = new SimpleEntry<>(i, i + 1);
+      Map.Entry<Integer, Integer> entry = new AbstractMap.SimpleEntry<>(i, i + 1);
       assertThat(entrySet.remove(entry)).isTrue();
       assertThat(entrySet.remove(entry)).isFalse();
     }
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 38d2471..39cf822 100644
--- a/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
+++ b/java/core/src/test/java/com/google/protobuf/TestBadIdentifiers.java
@@ -49,7 +49,7 @@
         TestBadIdentifiersProto.Override.getDefaultInstance();
   }
 
-  @SuppressWarnings("IgnoredPureGetter") // TODO(b/221602772): Fix this
+  @SuppressWarnings({"IgnoredPureGetter", "CheckReturnValue"}) // TODO(b/221602772): Fix this
   public void testGetDescriptor() {
     TestBadIdentifiersProto.getDescriptor();
     TestBadIdentifiersProto.Descriptor.getDefaultInstance().getDescriptor();
@@ -99,7 +99,6 @@
     assertEquals("", message.getFieldName33());
     assertEquals(0, message.get2Conflict34());
     assertEquals(0, message.get2Conflict35());
-
   }
 
   public void testNumberFields() throws Exception {
@@ -120,6 +119,5 @@
     assertEquals(0, message.get32());
     assertEquals(0, message.get64Count());
     assertEquals(0, message.get64List().size());
-
   }
 }
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 46a4d17..71a540a 100644
--- a/java/core/src/test/java/com/google/protobuf/TestUtil.java
+++ b/java/core/src/test/java/com/google/protobuf/TestUtil.java
@@ -235,6 +235,7 @@
 import protobuf_unittest.UnittestProto.TestUnpackedTypes;
 import java.io.File;
 import java.io.IOException;
+import java.io.InputStream;
 import java.io.RandomAccessFile;
 import java.util.ArrayList;
 import java.util.Collections;
@@ -3842,7 +3843,11 @@
 
   private static ByteString readBytesFromResource(String name) {
     try {
-      return ByteString.readFrom(TestUtil.class.getResourceAsStream(name));
+      InputStream in = TestUtil.class.getResourceAsStream(name);
+      if (in == null) { //
+        throw new RuntimeException("Tests data file " + name + " is missing.");
+      }
+      return ByteString.readFrom(in);
     } catch (IOException e) {
       throw new RuntimeException(e);
     }
diff --git a/java/core/src/test/java/com/google/protobuf/TextFormatPerformanceTest.java b/java/core/src/test/java/com/google/protobuf/TextFormatPerformanceTest.java
new file mode 100644
index 0000000..94e51be
--- /dev/null
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatPerformanceTest.java
@@ -0,0 +1,112 @@
+// 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;
+
+import static com.google.common.truth.Truth.assertThat;
+
+import com.google.protobuf.testing.textformat.performance.proto2.Proto2TextFormatPerformanceProto;
+import com.google.protobuf.testing.textformat.performance.proto3.Proto3TextFormatPerformanceProto;
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
+
+@RunWith(JUnit4.class)
+public class TextFormatPerformanceTest {
+  // 10 Seconds is longer than we'd really like, but necesssary to keep this test from being flaky.
+  // This test is mostly to make sure it doesn't explode to many 10s of seconds for some reason.
+  private static final long MAX_PARSE_TIME_MS = 10_000L;
+
+  private static final int REPEAT_COUNT = 400000;
+  private static final String CONTAINS_SUB_MESSAGE_WITH_REPEATED_INT32 =
+      repeat("sub_msg { value: 123 }", REPEAT_COUNT);
+  private static final String CONTAINS_EXTENSION_SUB_MESSAGE_WITH_REPEATED_INT32 =
+      repeat(
+          "[protobuf.testing.textformat.performance.proto2.sub_msg_ext] { value: 123 }",
+          REPEAT_COUNT);
+
+  // OSS Tests are still using JDK 8, which doesn't have JDK 11 String.repeat()
+  private static String repeat(String text, int count) {
+    StringBuilder builder = new StringBuilder(text.length() * count);
+    for (int i = 0; i < count; ++i) {
+      builder.append(text);
+    }
+    return builder.toString();
+  }
+
+  @Test(timeout = MAX_PARSE_TIME_MS)
+  public void testProto2ImmutableTextFormatParsing() throws Exception {
+    Proto2TextFormatPerformanceProto.ContainsSubMessageWithRepeatedInt32.Builder builder =
+        Proto2TextFormatPerformanceProto.ContainsSubMessageWithRepeatedInt32.newBuilder();
+
+    TextFormat.merge(CONTAINS_SUB_MESSAGE_WITH_REPEATED_INT32, builder);
+
+    Proto2TextFormatPerformanceProto.ContainsSubMessageWithRepeatedInt32 msg = builder.build();
+    assertThat(msg.getSubMsg().getValueCount()).isEqualTo(REPEAT_COUNT);
+    for (int i = 0; i < msg.getSubMsg().getValueCount(); ++i) {
+      assertThat(msg.getSubMsg().getValue(i)).isEqualTo(123);
+    }
+  }
+
+  @Test(timeout = MAX_PARSE_TIME_MS)
+  public void testProto2ImmutableExtensionTextFormatParsing() throws Exception {
+    ExtensionRegistry registry = ExtensionRegistry.newInstance();
+    Proto2TextFormatPerformanceProto.registerAllExtensions(registry);
+
+    Proto2TextFormatPerformanceProto.ContainsExtensionSubMessage.Builder builder =
+        Proto2TextFormatPerformanceProto.ContainsExtensionSubMessage.newBuilder();
+
+    TextFormat.merge(CONTAINS_EXTENSION_SUB_MESSAGE_WITH_REPEATED_INT32, registry, builder);
+
+    Proto2TextFormatPerformanceProto.ContainsExtensionSubMessage msg = builder.build();
+    assertThat(msg.getExtension(Proto2TextFormatPerformanceProto.subMsgExt).getValueCount())
+        .isEqualTo(REPEAT_COUNT);
+    for (int i = 0;
+        i < msg.getExtension(Proto2TextFormatPerformanceProto.subMsgExt).getValueCount();
+        ++i) {
+      assertThat(msg.getExtension(Proto2TextFormatPerformanceProto.subMsgExt).getValue(i))
+          .isEqualTo(123);
+    }
+  }
+
+  @Test(timeout = MAX_PARSE_TIME_MS)
+  public void testProto3ImmutableTextFormatParsing() throws Exception {
+    Proto3TextFormatPerformanceProto.ContainsSubMessageWithRepeatedInt32.Builder builder =
+        Proto3TextFormatPerformanceProto.ContainsSubMessageWithRepeatedInt32.newBuilder();
+
+    TextFormat.merge(CONTAINS_SUB_MESSAGE_WITH_REPEATED_INT32, builder);
+
+    Proto3TextFormatPerformanceProto.ContainsSubMessageWithRepeatedInt32 msg = builder.build();
+    assertThat(msg.getSubMsg().getValueCount()).isEqualTo(REPEAT_COUNT);
+    for (int i = 0; i < msg.getSubMsg().getValueCount(); ++i) {
+      assertThat(msg.getSubMsg().getValue(i)).isEqualTo(123);
+    }
+  }
+}
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 cde1776..cf0061e 100644
--- a/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
+++ b/java/core/src/test/java/com/google/protobuf/TextFormatTest.java
@@ -67,9 +67,7 @@
 import org.junit.runner.RunWith;
 import org.junit.runners.JUnit4;
 
-/**
- * Test case for {@link TextFormat}.
- */
+/** Test case for {@link TextFormat}. */
 @RunWith(JUnit4.class)
 public class TextFormatTest {
 
@@ -726,7 +724,6 @@
     assertThat(actual).isEqualTo(expected);
   }
 
-
   @Test
   public void testMergeAny_customBuiltTypeRegistry() throws Exception {
     TestAny.Builder builder = TestAny.newBuilder();
@@ -761,7 +758,6 @@
                 .build());
   }
 
-
   private void assertParseError(String error, String text) {
     // Test merge().
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -825,6 +821,7 @@
     }
   }
 
+  @CanIgnoreReturnValue
   private TestAllTypes assertParseSuccessWithOverwriteForbidden(String text)
       throws TextFormat.ParseException {
     TestAllTypes.Builder builder = TestAllTypes.newBuilder();
@@ -1400,7 +1397,6 @@
         .isEqualTo("1: \"\\343\\201\\202\"\n");
   }
 
-
   @Test
   public void testParseUnknownExtensions() throws Exception {
     TestUtil.TestLogHandler logHandler = new TestUtil.TestLogHandler();
@@ -1450,6 +1446,18 @@
             + "unknown_field3: 3\n");
   }
 
+  @Test
+  public void testParseUnknownExtensionWithAnyMessage() throws Exception {
+    assertParseSuccessWithUnknownExtensions(
+        "[unknown_extension]: { "
+            + "  any_value { "
+            + "    [type.googleapis.com/protobuf_unittest.OneString] { "
+            + "      data: 123 "
+            + "    } "
+            + " } "
+            + "}");
+  }
+
   // See additional coverage in testOneofOverwriteForbidden and testMapOverwriteForbidden.
   @Test
   public void testParseNonRepeatedFields() throws Exception {
@@ -1762,6 +1770,7 @@
     }
   }
 
+  @SuppressWarnings("LenientFormatStringValidation")
   private void assertLocation(
       TextFormatParseInfoTree tree,
       final Descriptor descriptor,
@@ -1775,6 +1784,7 @@
       TextFormatParseLocation expected = TextFormatParseLocation.create(line, column);
       assertThat(location).isEqualTo(expected);
     } else if (line != -1 && column != -1) {
+      // Expected 0 args, but got 3.
       assertWithMessage(
               "Tree/descriptor/fieldname did not contain index %d, line %d column %d expected",
               index, line, column)
@@ -1831,5 +1841,4 @@
     assertThat(TextFormat.printer().printToString(message))
         .isEqualTo("optional_float: -0.0\noptional_double: -0.0\n");
   }
-
 }
diff --git a/java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java b/java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java
index c9defb3..29ecf92 100644
--- a/java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java
+++ b/java/core/src/test/java/com/google/protobuf/TypeRegistryTest.java
@@ -65,5 +65,4 @@
                 .getDescriptorForTypeUrl("type.googleapis.com/" + descriptor.getFullName()))
         .isSameInstanceAs(descriptor);
   }
-
 }
diff --git a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
index 4ec9688..b788ddb 100644
--- a/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
+++ b/java/core/src/test/proto/com/google/protobuf/map_for_proto2_lite_test.proto
@@ -30,8 +30,11 @@
 
 syntax = "proto2";
 
+package map_for_proto2_lite_test;
 
 option java_outer_classname = "MapForProto2TestProto";
+option optimize_for = LITE_RUNTIME;
+option java_package = "map_lite_test";
 
 message TestMap {
   message MessageValue {
@@ -125,6 +128,3 @@
   // null is not a 'reserved word' per se but as a literal needs similar care
   map<string, SampleEnum> null = 10;
 }
-package map_for_proto2_lite_test;
-option java_package = "map_lite_test";
-option optimize_for = LITE_RUNTIME;
diff --git a/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto b/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto
index 0de6f7b..2ad44a7 100644
--- a/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto
+++ b/java/core/src/test/proto/com/google/protobuf/multiple_files_test.proto
@@ -38,8 +38,8 @@
 // See:  http://go/proto2-generic-services-default
 package protobuf_unittest;
 
-import "google/protobuf/unittest.proto";
 import "google/protobuf/descriptor.proto";
+import "google/protobuf/unittest.proto";
 
 option java_generic_services = true;  // auto-added
 option java_multiple_files = true;
@@ -49,7 +49,9 @@
   message NestedMessage {
     optional int32 i = 1;
   }
-  enum NestedEnum { BAZ = 3; }
+  enum NestedEnum {
+    BAZ = 3;
+  }
   optional NestedMessage nested = 1;
   repeated TestAllTypes foreign = 2;
   optional NestedEnum nested_enum = 3;
diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_message.proto b/java/core/src/test/proto/com/google/protobuf/proto2_message.proto
index 86c48b0..dad00ed 100644
--- a/java/core/src/test/proto/com/google/protobuf/proto2_message.proto
+++ b/java/core/src/test/proto/com/google/protobuf/proto2_message.proto
@@ -36,7 +36,6 @@
 option java_package = "com.google.protobuf.testing";
 option java_outer_classname = "Proto2Testing";
 
-
 message Proto2SpecialFieldName {
   optional double regular_name = 1;
   optional int32 cached_size = 2;
diff --git a/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto b/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto
index 7dfd40e..57efc17 100644
--- a/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto
+++ b/java/core/src/test/proto/com/google/protobuf/proto2_message_lite.proto
@@ -36,7 +36,6 @@
 option java_package = "com.google.protobuf.testing";
 option java_outer_classname = "Proto2TestingLite";
 
-
 message Proto2MessageLite {
 
   enum TestEnum {
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/java/core/src/test/proto/com/google/protobuf/proto2_text_format_performance_test.proto
similarity index 75%
copy from src/google/protobuf/util/internal/error_listener.cc
copy to java/core/src/test/proto/com/google/protobuf/proto2_text_format_performance_test.proto
index 538307b..2f5431d 100644
--- a/src/google/protobuf/util/internal/error_listener.cc
+++ b/java/core/src/test/proto/com/google/protobuf/proto2_text_format_performance_test.proto
@@ -28,15 +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.
 
-#include <google/protobuf/util/internal/error_listener.h>
+syntax = "proto2";
 
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
+package protobuf.testing.textformat.performance.proto2;
 
+option java_package = "com.google.protobuf.testing.textformat.performance.proto2";
+option java_outer_classname = "Proto2TextFormatPerformanceProto";
 
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
+message ContainsSubMessageWithRepeatedInt32 {
+  optional RepeatedInt32 sub_msg = 1;
+}
+
+message RepeatedInt32 {
+  repeated int32 value = 2;
+}
+
+message ContainsExtensionSubMessage {
+  extensions 1 to max;
+}
+
+extend ContainsExtensionSubMessage {
+  optional RepeatedInt32 sub_msg_ext = 1;
+}
diff --git a/src/google/protobuf/util/internal/testdata/proto3.proto b/java/core/src/test/proto/com/google/protobuf/proto3_text_format_performance_test.proto
similarity index 82%
copy from src/google/protobuf/util/internal/testdata/proto3.proto
copy to java/core/src/test/proto/com/google/protobuf/proto3_text_format_performance_test.proto
index 01434b0..a3c1962 100644
--- a/src/google/protobuf/util/internal/testdata/proto3.proto
+++ b/java/core/src/test/proto/com/google/protobuf/proto3_text_format_performance_test.proto
@@ -30,13 +30,15 @@
 
 syntax = "proto3";
 
-package proto_util_converter.testing;
+package protobuf.testing.textformat.performance.proto3;
 
-message Proto3Message {
-  enum NestedEnum {
-    FOO = 0;
-    BAR = 1;
-    BAZ = 2;
-  }
-  NestedEnum enum_value = 1;
+option java_package = "com.google.protobuf.testing.textformat.performance.proto3";
+option java_outer_classname = "Proto3TextFormatPerformanceProto";
+
+message ContainsSubMessageWithRepeatedInt32 {
+  optional RepeatedInt32 sub_msg = 1;
+}
+
+message RepeatedInt32 {
+  repeated int32 value = 2;
 }
diff --git a/java/internal/BUILD.bazel b/java/internal/BUILD.bazel
index 662dabd..ff111e7 100644
--- a/java/internal/BUILD.bazel
+++ b/java/internal/BUILD.bazel
@@ -1,13 +1,24 @@
-package(default_visibility = ["//java:__subpackages__"])
-
 load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
 
+package(default_visibility = ["//java:__subpackages__"])
+
 pkg_files(
     name = "dist_files",
     srcs = [
         "BUILD.bazel",
+        "JavaVersionTest.java",
         "testing.bzl",
     ],
     strip_prefix = strip_prefix.from_root(""),
     visibility = ["//java:__pkg__"],
 )
+
+java_test(
+    name = "java_version",
+    srcs = ["JavaVersionTest.java"],
+    test_class = "JavaVersionTest",
+    deps = [
+        "@maven//:com_google_truth_truth",
+        "@maven//:junit_junit",
+    ],
+)
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/java/internal/JavaVersionTest.java
similarity index 69%
copy from src/google/protobuf/util/internal/error_listener.cc
copy to java/internal/JavaVersionTest.java
index 538307b..c7957c0 100644
--- a/src/google/protobuf/util/internal/error_listener.cc
+++ b/java/internal/JavaVersionTest.java
@@ -28,15 +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.
 
-#include <google/protobuf/util/internal/error_listener.h>
+// Test that Kokoro is using the expected version of Java.
+import static com.google.common.truth.Truth.assertWithMessage;
 
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
+import org.junit.Test;
+import org.junit.runner.RunWith;
+import org.junit.runners.JUnit4;
 
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
+@RunWith(JUnit4.class)
+public class JavaVersionTest {
+  @Test
+  public void testJavaVersion() throws Exception {
+    String exp = System.getenv("KOKORO_JAVA_VERSION");
+    if(exp == null || exp.isEmpty()) {
+      System.err.println("No kokoro java version found, skipping check");
+      return;
+    }
+    String version = System.getProperty("java.version");
+    assertWithMessage("Expected Python " + exp + " but found Python " + version)
+      .that(version.startsWith(exp))
+      .isTrue();
+  }
+}
diff --git a/java/internal/testing.bzl b/java/internal/testing.bzl
index 76e1e45..b2a781b 100644
--- a/java/internal/testing.bzl
+++ b/java/internal/testing.bzl
@@ -50,7 +50,7 @@
         if not test_name.endswith("Test") or test_name.startswith("Abstract"):
             continue
         if test_prefix:
-            test_name = "%s%s" % (test_prefix, test_name)  
+            test_name = "%s%s" % (test_prefix, test_name)
         test_names = test_names + [test_name]
         suite_name = prefix + '_' + test_name
         _gen_suite(
diff --git a/java/kotlin-lite/BUILD.bazel b/java/kotlin-lite/BUILD.bazel
index d3d9ddf..39f8b33 100644
--- a/java/kotlin-lite/BUILD.bazel
+++ b/java/kotlin-lite/BUILD.bazel
@@ -140,7 +140,7 @@
 internal_gen_kt_protos(
     name = "gen_kotlin_unittest_lite",
     lite = True,
-    deps = ["//:kt_unittest_lite"],
+    deps = ["//src/google/protobuf:lite_test_protos"],
 )
 
 kt_jvm_library(
@@ -152,6 +152,7 @@
     deps = [
         ":evil_names_proto2_java_proto_lite",
         "//java/core:generic_test_protos_java_proto_lite",
+        "//java/core:lite_test_protos_java_proto_lite",
         "//java/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests",
         "//java/kotlin:shared_runtime",
         "//java/lite",
@@ -161,7 +162,7 @@
 internal_gen_kt_protos(
     name = "gen_kotlin_proto3_unittest_lite",
     lite = True,
-    deps = ["//:kt_proto3_unittest"],
+    deps = ["//src/google/protobuf:kt_proto3_unittest_protos"],
 )
 
 kt_jvm_library(
@@ -175,6 +176,7 @@
         ":evil_names_proto3_java_proto_lite",
         ":multiple_files_proto3_java_proto_lite",
         "//java/core:generic_test_protos_java_proto_lite",
+        "//java/core:lite_test_protos_java_proto_lite",
         "//java/kotlin:only_for_use_in_proto_generated_code_its_generator_and_tests",
         "//java/kotlin:shared_runtime",
         "//java/lite",
diff --git a/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt b/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt
index 6c208b2..714c81e 100644
--- a/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt
+++ b/java/kotlin-lite/src/main/kotlin/com/google/protobuf/ExtendableMessageLiteExtensions.kt
@@ -37,22 +37,19 @@
 operator fun <
   M : GeneratedMessageLite.ExtendableMessage<M, *>,
   MOrBT : GeneratedMessageLite.ExtendableMessageOrBuilder<M, *>,
-  T : Any
-  > MOrBT.get(extension: ExtensionLite<M, T>): T = getExtension(extension)
+  T : Any> MOrBT.get(extension: ExtensionLite<M, T>): T = getExtension(extension)
 
 /** 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) {
+  T : Any> B.set(extension: ExtensionLite<M, T>, value: T) {
   setExtension(extension, value)
 }
 
 /** Returns true if the specified extension is set. */
 operator fun <
   M : GeneratedMessageLite.ExtendableMessage<M, *>,
-  MorBT : GeneratedMessageLite.ExtendableMessageOrBuilder<M, *>
-  > MorBT.contains(
+  MorBT : GeneratedMessageLite.ExtendableMessageOrBuilder<M, *>> MorBT.contains(
   extension: ExtensionLite<M, *>
 ): Boolean = hasExtension(extension)
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
index 53291b4..8923859 100644
--- a/java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt
+++ b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/ExtendableMessageLiteExtensionsTest.kt
@@ -48,31 +48,27 @@
 
   @Test
   fun getOnBuilder() {
-    val builder = ExampleExtensibleMessage.newBuilder()
-      .setExtension(TestProto.int32Extension, 6)
+    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()
+    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()
+    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)
+    val builder = ExampleExtensibleMessage.newBuilder().setExtension(TestProto.int32Extension, 6)
     assertThat(TestProto.int32Extension in builder).isTrue()
   }
 
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
index c343ccd..93efe9c 100644
--- a/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt
+++ b/java/kotlin-lite/src/test/kotlin/com/google/protobuf/Proto2LiteTest.kt
@@ -46,13 +46,6 @@
 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
@@ -62,6 +55,13 @@
 import protobuf_unittest.MapLiteUnittest.MapEnumLite
 import protobuf_unittest.MapLiteUnittest.TestMapLite
 import protobuf_unittest.testMapLite
+import `in`.com.google.protobuf.kotlin.generator.EvilNamesProto2
+import `in`.com.google.protobuf.kotlin.generator.HardKeywordsAllTypesProto2
+import `in`.com.google.protobuf.kotlin.generator.Interface
+import `in`.com.google.protobuf.kotlin.generator.HardKeywordsAllTypesProto2Kt
+import `in`.com.google.protobuf.kotlin.generator.evilNamesProto2
+import `in`.com.google.protobuf.kotlin.generator.hardKeywordsAllTypesProto2
+import `in`.com.google.protobuf.kotlin.generator.interface_
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -178,6 +178,7 @@
       .isEqualTo(TestUtilLite.getAllLiteSetBuilder().build())
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testGetters() {
     testAllTypesLite {
@@ -198,6 +199,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testDefaultGetters() {
     testAllTypesLite {
@@ -208,6 +210,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testRepeatedGettersAndSetters() {
     testAllTypesLite {
@@ -298,6 +301,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHazzers() {
     testAllTypesLite {
@@ -328,6 +332,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testClears() {
     testAllTypesLite {
@@ -399,38 +404,57 @@
   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] =
+          setExtension(UnittestLite.optionalInt32ExtensionLite, 101)
+          setExtension(UnittestLite.optionalInt64ExtensionLite, 102L)
+          setExtension(UnittestLite.optionalUint32ExtensionLite, 103)
+          setExtension(UnittestLite.optionalUint64ExtensionLite, 104L)
+          setExtension(UnittestLite.optionalSint32ExtensionLite, 105)
+          setExtension(UnittestLite.optionalSint64ExtensionLite, 106L)
+          setExtension(UnittestLite.optionalFixed32ExtensionLite, 107)
+          setExtension(UnittestLite.optionalFixed64ExtensionLite, 108L)
+          setExtension(UnittestLite.optionalSfixed32ExtensionLite, 109)
+          setExtension(UnittestLite.optionalSfixed64ExtensionLite, 110L)
+          setExtension(UnittestLite.optionalFloatExtensionLite, 111F)
+          setExtension(UnittestLite.optionalDoubleExtensionLite, 112.0)
+          setExtension(UnittestLite.optionalBoolExtensionLite, true)
+          setExtension(UnittestLite.optionalStringExtensionLite, "115")
+          setExtension(UnittestLite.optionalBytesExtensionLite, toBytes("116"))
+          setExtension(
+            UnittestLite.optionalGroupExtensionLite,
+            optionalGroupExtensionLite { a = 117 }
+          )
+          setExtension(
+            UnittestLite.optionalNestedMessageExtensionLite,
             TestAllTypesLiteKt.nestedMessage { bb = 118 }
-          this[UnittestLite.optionalForeignMessageExtensionLite] = foreignMessageLite { c = 119 }
-          this[UnittestLite.optionalImportMessageExtensionLite] =
+          )
+          setExtension(
+            UnittestLite.optionalForeignMessageExtensionLite,
+            foreignMessageLite { c = 119 }
+          )
+          setExtension(
+            UnittestLite.optionalImportMessageExtensionLite,
             ImportMessageLite.newBuilder().setD(120).build()
-          this[UnittestLite.optionalPublicImportMessageExtensionLite] =
+          )
+          setExtension(
+            UnittestLite.optionalPublicImportMessageExtensionLite,
             PublicImportMessageLite.newBuilder().setE(126).build()
-          this[UnittestLite.optionalLazyMessageExtensionLite] =
+          )
+          setExtension(
+            UnittestLite.optionalLazyMessageExtensionLite,
             TestAllTypesLiteKt.nestedMessage { bb = 127 }
-          this[UnittestLite.optionalUnverifiedLazyMessageExtensionLite] =
+          )
+          setExtension(
+            UnittestLite.optionalUnverifiedLazyMessageExtensionLite,
             TestAllTypesLiteKt.nestedMessage { bb = 128 }
-          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"
+          )
+          setExtension(UnittestLite.optionalNestedEnumExtensionLite, NestedEnum.BAZ)
+          setExtension(
+            UnittestLite.optionalForeignEnumExtensionLite,
+            ForeignEnumLite.FOREIGN_LITE_BAZ
+          )
+          setExtension(UnittestLite.optionalImportEnumExtensionLite, ImportEnumLite.IMPORT_LITE_BAZ)
+          setExtension(UnittestLite.optionalStringPieceExtensionLite, "124")
+          setExtension(UnittestLite.optionalCordExtensionLite, "125")
           this[UnittestLite.repeatedInt32ExtensionLite].add(201)
           this[UnittestLite.repeatedInt64ExtensionLite].add(202L)
           this[UnittestLite.repeatedUint32ExtensionLite].add(203)
@@ -520,6 +544,7 @@
       .isEqualTo(TestUtilLite.getAllLiteExtensionsSet())
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionGetters() {
     testAllExtensionsLite {
@@ -543,6 +568,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testRepeatedExtensionGettersAndSetters() {
     testAllExtensionsLite {
@@ -632,6 +658,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionContains() {
     testAllExtensionsLite {
@@ -663,6 +690,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionClears() {
     testAllExtensionsLite {
@@ -751,6 +779,7 @@
       )
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapGettersAndSetters() {
     testMapLite {
@@ -806,6 +835,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapRemove() {
     testMapLite {
@@ -831,6 +861,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapClear() {
     testMapLite {
@@ -877,7 +908,6 @@
           boolean = 1L
           sealed = "foo"
           interface_ = 1F
-          in_ = 1
           object_ = "foo"
           cachedSize_ = "foo"
           serializedSize_ = true
@@ -903,7 +933,6 @@
           .setBoolean(1L)
           .setSealed("foo")
           .setInterface(1F)
-          .setIn(1)
           .setObject("foo")
           .setCachedSize_("foo")
           .setSerializedSize_(true)
@@ -914,15 +943,13 @@
     assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build())
   }
 
+  @Suppress("CheckResult")
   @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)
 
@@ -946,15 +973,13 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordHazzers() {
     hardKeywordsAllTypesProto2 {
       as_ = 1
       assertThat(hasAs_()).isTrue()
 
-      in_ = "foo"
-      assertThat(hasIn_()).isTrue()
-
       break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
       assertThat(hasBreak_()).isTrue()
 
@@ -963,6 +988,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordClears() {
     hardKeywordsAllTypesProto2 {
@@ -970,10 +996,6 @@
       clearAs_()
       assertThat(hasAs_()).isFalse()
 
-      in_ = "foo"
-      clearIn_()
-      assertThat(hasIn_()).isFalse()
-
       break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
       clearBreak_()
       assertThat(hasBreak_()).isFalse()
diff --git a/java/kotlin/BUILD.bazel b/java/kotlin/BUILD.bazel
index 67fc6e0..c809117 100644
--- a/java/kotlin/BUILD.bazel
+++ b/java/kotlin/BUILD.bazel
@@ -25,6 +25,7 @@
     deps = [
         ":only_for_use_in_proto_generated_code_its_generator_and_tests",
         "//java/lite",
+        "@maven//:com_google_errorprone_error_prone_annotations",
     ],
 )
 
@@ -59,7 +60,7 @@
     maven_coordinates = "com.google.protobuf:protobuf-kotlin:%s" % PROTOBUF_JAVA_VERSION,
     pom_template = "//java/kotlin:pom_template.xml",
     resources = [
-        "//:built_in_runtime_protos",
+        "//src/google/protobuf:descriptor_proto_srcs",
         "//:well_known_type_protos",
     ],
     tags = ["manual"],
@@ -224,7 +225,7 @@
 internal_gen_kt_protos(
     name = "gen_kotlin_unittest",
     visibility = ["//java:__subpackages__"],
-    deps = ["//:kt_unittest"],
+    deps = ["//src/google/protobuf:kt_unittest_protos"],
 )
 
 kt_jvm_library(
@@ -240,12 +241,13 @@
         ":well_known_protos_kotlin",
         "//java/core",
         "//java/core:generic_test_protos_java_proto",
+        "//java/core:lite_test_protos_java_proto",
     ],
 )
 
 internal_gen_kt_protos(
     name = "gen_kotlin_proto3_unittest",
-    deps = ["//:kt_proto3_unittest"],
+    deps = ["//src/google/protobuf:kt_proto3_unittest_protos"],
 )
 
 kt_jvm_library(
@@ -262,6 +264,7 @@
         ":shared_runtime",
         "//java/core",
         "//java/core:generic_test_protos_java_proto",
+        "//java/core:lite_test_protos_java_proto",
     ],
 )
 
diff --git a/java/kotlin/pom.xml b/java/kotlin/pom.xml
index cc563cf..e75d0bf 100644
--- a/java/kotlin/pom.xml
+++ b/java/kotlin/pom.xml
@@ -35,6 +35,11 @@
       <scope>test</scope>
     </dependency>
     <dependency>
+      <groupId>com.google.errorprone</groupId>
+      <artifactId>error_prone_annotations</artifactId>
+      <version>2.5.1</version>
+    </dependency>
+    <dependency>
       <groupId>com.google.guava</groupId>
       <artifactId>guava</artifactId>
       <scope>test</scope>
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt
index 9f7f75b..f2ae6ae 100644
--- a/java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/DslList.kt
@@ -35,13 +35,13 @@
  * 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
+ * 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 {
+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())
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt
index d35195e..e62ffec 100644
--- a/java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/DslMap.kt
@@ -35,13 +35,13 @@
  * 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
+ * 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 {
+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.
 
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt
index c9b2dd4..403cc04 100644
--- a/java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/DslProxy.kt
@@ -31,9 +31,9 @@
 package com.google.protobuf.kotlin
 
 /**
- * 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>`.
+ * 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 {
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt
index 4f64843..2723f27 100644
--- a/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ExtendableMessageExtensions.kt
@@ -33,12 +33,11 @@
 import com.google.protobuf.ExtensionLite
 import com.google.protobuf.GeneratedMessageV3
 
-/** Sets the current value of the proto extension in this builder.*/
+/** 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) {
+  T : Any> B.set(extension: ExtensionLite<M, T>, value: T) {
   setExtension(extension, value)
 }
 
@@ -46,11 +45,11 @@
 operator fun <
   M : GeneratedMessageV3.ExtendableMessage<M>,
   MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder<M>,
-  T : Any
-  > MorBT.get(extension: ExtensionLite<M, T>): T = getExtension(extension)
+  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)
+  MorBT : GeneratedMessageV3.ExtendableMessageOrBuilder<M>> MorBT.contains(
+  extension: ExtensionLite<M, *>
+): Boolean = hasExtension(extension)
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt
index c8ed63d..a1cb808 100644
--- a/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/OnlyForUseByGeneratedProtoCode.kt
@@ -32,8 +32,8 @@
 
 /**
  * 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.
+ * generated code. See https://kotlinlang.org/docs/reference/opt-in-requirements.html for details on
+ * how this API works.
  */
 @RequiresOptIn(
   message =
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt
index e922624..0c199ae 100644
--- a/java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/ProtoDslMarker.kt
@@ -30,9 +30,7 @@
 
 package com.google.protobuf.kotlin
 
-/**
- * Indicates an API that is part of a DSL to generate protocol buffer messages.
- */
+/** Indicates an API that is part of a DSL to generate protocol buffer messages. */
 @DslMarker
 @Target(AnnotationTarget.CLASS)
 @Retention(AnnotationRetention.BINARY)
diff --git a/java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt b/java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt
index cf45e89..d5b016c 100644
--- a/java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt
+++ b/java/kotlin/src/main/kotlin/com/google/protobuf/UnmodifiableCollections.kt
@@ -34,29 +34,24 @@
 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
+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 {
+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>
+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>> {
+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.
 
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt
index a5f0c49..9044ce3 100644
--- a/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/DslListTest.kt
@@ -67,9 +67,7 @@
   fun dslListIsNotEvenSecretlyMutable() {
     val dslList = DslList<Int, DummyProxy>(mutableListOf(1, 2, 3))
     val dslListAsJavaUtil = dslList as java.util.List<Int>
-    assertFailsWith<UnsupportedOperationException> {
-      dslListAsJavaUtil.add(4)
-    }
+    assertFailsWith<UnsupportedOperationException> { dslListAsJavaUtil.add(4) }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -79,9 +77,7 @@
     val iterator = dslList.iterator() as java.util.Iterator<Int>
     iterator.next()
 
-    assertFailsWith<UnsupportedOperationException> {
-      iterator.remove()
-    }
+    assertFailsWith<UnsupportedOperationException> { iterator.remove() }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -91,9 +87,7 @@
     val iterator = dslList.listIterator() as java.util.ListIterator<Int>
     iterator.next()
 
-    assertFailsWith<UnsupportedOperationException> {
-      iterator.remove()
-    }
+    assertFailsWith<UnsupportedOperationException> { iterator.remove() }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -103,9 +97,7 @@
     val iterator = dslList.listIterator(1) as java.util.ListIterator<Int>
     iterator.next()
 
-    assertFailsWith<UnsupportedOperationException> {
-      iterator.remove()
-    }
+    assertFailsWith<UnsupportedOperationException> { iterator.remove() }
   }
 
   @Test
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt
index e7f7a19..3487f22 100644
--- a/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/DslMapTest.kt
@@ -44,8 +44,7 @@
 
   @Test
   fun matchesMap() {
-    assertThat(DslMap<Int, Int, DummyProxy>(mapOf(1 to -1, 2 to -2)))
-      .containsExactly(1, -1, 2, -2)
+    assertThat(DslMap<Int, Int, DummyProxy>(mapOf(1 to -1, 2 to -2))).containsExactly(1, -1, 2, -2)
   }
 
   @Test
@@ -91,9 +90,7 @@
   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)
-    }
+    assertFailsWith<UnsupportedOperationException> { dslMapAsJavaUtilMap.put(2, -2) }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -101,9 +98,7 @@
   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)
-    }
+    assertFailsWith<UnsupportedOperationException> { dslMapKeysAsJavaUtilSet.remove(1) }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -113,9 +108,7 @@
     val dslMapKeysAsJavaUtilSet = dslMap.keys as java.util.Set<Int>
     val itr = dslMapKeysAsJavaUtilSet.iterator()
     itr.next()
-    assertFailsWith<UnsupportedOperationException> {
-      itr.remove()
-    }
+    assertFailsWith<UnsupportedOperationException> { itr.remove() }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -123,9 +116,7 @@
   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)
-    }
+    assertFailsWith<UnsupportedOperationException> { dslMapValuesAsJavaUtilCollection.remove(1) }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -135,9 +126,7 @@
     val dslMapValuesAsJavaUtilCollection = dslMap.values as java.util.Collection<Int>
     val itr = dslMapValuesAsJavaUtilCollection.iterator()
     itr.next()
-    assertFailsWith<UnsupportedOperationException> {
-      itr.remove()
-    }
+    assertFailsWith<UnsupportedOperationException> { itr.remove() }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -146,9 +135,7 @@
     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)
-    }
+    assertFailsWith<UnsupportedOperationException> { dslMapEntriesAsJavaUtilSet.remove(entry) }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -158,9 +145,7 @@
     val dslMapEntriesAsJavaUtilSet = dslMap.entries as java.util.Set<Map.Entry<Int, Int>>
     val itr = dslMapEntriesAsJavaUtilSet.iterator()
     itr.next()
-    assertFailsWith<UnsupportedOperationException> {
-      itr.remove()
-    }
+    assertFailsWith<UnsupportedOperationException> { itr.remove() }
   }
 
   @Suppress("PLATFORM_CLASS_MAPPED_TO_KOTLIN", "UNCHECKED_CAST")
@@ -168,9 +153,7 @@
   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
-    }
+    assertFailsWith<UnsupportedOperationException> { dslMapEntryAsJavaUtilMapEntry.value = 2 }
   }
 
   @Test
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt
index 623bc58..f4ad142 100644
--- a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtendableMessageExtensionsTest.kt
@@ -48,31 +48,27 @@
 
   @Test
   fun getOnBuilder() {
-    val builder = ExampleExtensibleMessage.newBuilder()
-      .setExtension(TestProto.int32Extension, 6)
+    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()
+    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()
+    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)
+    val builder = ExampleExtensibleMessage.newBuilder().setExtension(TestProto.int32Extension, 6)
     assertThat(TestProto.int32Extension in builder).isTrue()
   }
 
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt
index 239f27a..e311b82 100644
--- a/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/ExtensionListTest.kt
@@ -48,90 +48,92 @@
   @Test
   fun matchesList() {
     assertThat(
-      ExtensionList<Int, ExampleExtensibleMessage>(
-        TestProto.repeatedExtension, listOf(1, 2, 3)
+        ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(1, 2, 3))
       )
-    ).containsExactly(1, 2, 3).inOrder()
+      .containsExactly(1, 2, 3)
+      .inOrder()
   }
 
   @Test
   fun reflectsChangesInList() {
     val mutableList = mutableListOf(1, 2, 3)
-    val extensionList = ExtensionList<Int, ExampleExtensibleMessage>(
-      TestProto.repeatedExtension, mutableList
-    )
+    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)
-    )
+    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 extensionList =
+      ExtensionList<Int, ExampleExtensibleMessage>(
+        TestProto.repeatedExtension,
+        mutableListOf(1, 2, 3)
+      )
     val extensionListAsJavaUtil = extensionList as java.util.List<Int>
-    assertFailsWith<UnsupportedOperationException> {
-      extensionListAsJavaUtil.add(4)
-    }
+    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 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()
-    }
+    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 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()
-    }
+    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 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()
-    }
+    assertFailsWith<UnsupportedOperationException> { iterator.remove() }
   }
 
   @Test
   fun expectedToString() {
     assertThat(
-      ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(1, 2))
-        .toString()
-    ).isEqualTo("[1, 2]")
+        ExtensionList<Int, ExampleExtensibleMessage>(TestProto.repeatedExtension, listOf(1, 2))
+          .toString()
+      )
+      .isEqualTo("[1, 2]")
   }
 
   @Test
diff --git a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
index af797cc..71e500d 100644
--- a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto2Test.kt
@@ -33,13 +33,6 @@
 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
@@ -67,6 +60,13 @@
 import protobuf_unittest.testEnumMap
 import protobuf_unittest.testIntIntMap
 import protobuf_unittest.testMaps
+import `in`.com.google.protobuf.kotlin.generator.EvilNamesProto2
+import `in`.com.google.protobuf.kotlin.generator.HardKeywordsAllTypesProto2
+import `in`.com.google.protobuf.kotlin.generator.Interface
+import `in`.com.google.protobuf.kotlin.generator.HardKeywordsAllTypesProto2Kt
+import `in`.com.google.protobuf.kotlin.generator.evilNamesProto2
+import `in`.com.google.protobuf.kotlin.generator.hardKeywordsAllTypesProto2
+import `in`.com.google.protobuf.kotlin.generator.interface_
 import org.junit.Test
 import org.junit.runner.RunWith
 import org.junit.runners.JUnit4
@@ -183,6 +183,7 @@
       .isEqualTo(TestUtil.getAllSetBuilder().build())
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testGetters() {
     testAllTypes {
@@ -203,6 +204,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testDefaultGetters() {
     testAllTypes {
@@ -213,6 +215,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testRepeatedGettersAndSetters() {
     testAllTypes {
@@ -294,6 +297,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHazzers() {
     testAllTypes {
@@ -324,6 +328,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testClears() {
     testAllTypes {
@@ -482,26 +487,26 @@
           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"
+          setExtension(UnittestProto.defaultInt32Extension, 401)
+          setExtension(UnittestProto.defaultInt64Extension, 402L)
+          setExtension(UnittestProto.defaultUint32Extension, 403)
+          setExtension(UnittestProto.defaultUint64Extension, 404L)
+          setExtension(UnittestProto.defaultSint32Extension, 405)
+          setExtension(UnittestProto.defaultSint64Extension, 406L)
+          setExtension(UnittestProto.defaultFixed32Extension, 407)
+          setExtension(UnittestProto.defaultFixed64Extension, 408L)
+          setExtension(UnittestProto.defaultSfixed32Extension, 409)
+          setExtension(UnittestProto.defaultSfixed64Extension, 410L)
+          setExtension(UnittestProto.defaultFloatExtension, 411F)
+          setExtension(UnittestProto.defaultDoubleExtension, 412.0)
+          setExtension(UnittestProto.defaultBoolExtension, false)
+          setExtension(UnittestProto.defaultStringExtension, "415")
+          setExtension(UnittestProto.defaultBytesExtension, toBytes("416"))
+          setExtension(UnittestProto.defaultNestedEnumExtension, NestedEnum.FOO)
+          setExtension(UnittestProto.defaultForeignEnumExtension, ForeignEnum.FOREIGN_FOO)
+          setExtension(UnittestProto.defaultImportEnumExtension, ImportEnum.IMPORT_FOO)
+          setExtension(UnittestProto.defaultStringPieceExtension, "424")
+          setExtension(UnittestProto.defaultCordExtension, "425")
           this[UnittestProto.oneofUint32Extension] = 601
           this[UnittestProto.oneofNestedMessageExtension] =
             TestAllTypesKt.nestedMessage { bb = 602 }
@@ -512,6 +517,7 @@
       .isEqualTo(TestUtil.getAllExtensionsSet())
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionGetters() {
     testAllExtensions {
@@ -534,6 +540,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testRepeatedExtensionGettersAndSetters() {
     testAllExtensions {
@@ -614,6 +621,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionContains() {
     testAllExtensions {
@@ -644,6 +652,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testExtensionClears() {
     testAllExtensions {
@@ -725,6 +734,7 @@
       )
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapGettersAndSetters() {
     val intMap = testIntIntMap {
@@ -776,6 +786,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapRemove() {
     val intMap = testIntIntMap {
@@ -803,6 +814,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testMapClear() {
     val intMap = testIntIntMap {
@@ -851,7 +863,6 @@
           boolean = 1L
           sealed = "foo"
           interface_ = 1F
-          in_ = 1
           object_ = "foo"
           cachedSize_ = "foo"
           serializedSize_ = true
@@ -877,7 +888,6 @@
           .setBoolean(1L)
           .setSealed("foo")
           .setInterface(1F)
-          .setIn(1)
           .setObject("foo")
           .setCachedSize_("foo")
           .setSerializedSize_(true)
@@ -888,15 +898,13 @@
     assertThat(interface_ {}).isEqualTo(Interface.newBuilder().build())
   }
 
+  @Suppress("CheckResult")
   @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)
 
@@ -920,15 +928,13 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordHazzers() {
     hardKeywordsAllTypesProto2 {
       as_ = 1
       assertThat(hasAs_()).isTrue()
 
-      in_ = "foo"
-      assertThat(hasIn_()).isTrue()
-
       break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
       assertThat(hasBreak_()).isTrue()
 
@@ -937,6 +943,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordClears() {
     hardKeywordsAllTypesProto2 {
@@ -944,10 +951,6 @@
       clearAs_()
       assertThat(hasAs_()).isFalse()
 
-      in_ = "foo"
-      clearIn_()
-      assertThat(hasIn_()).isFalse()
-
       break_ = HardKeywordsAllTypesProto2.NestedEnum.FOO
       clearBreak_()
       assertThat(hasBreak_()).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
index d6d0ab5..8ce0094 100644
--- a/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt
+++ b/java/kotlin/src/test/kotlin/com/google/protobuf/Proto3Test.kt
@@ -31,13 +31,13 @@
 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 com.google.protobuf.kotlin.generator.`in`.EvilNamesProto3OuterClass.Class
+import com.google.protobuf.kotlin.generator.`in`.EvilNamesProto3OuterClass.EvilNamesProto3
+import com.google.protobuf.kotlin.generator.`in`.EvilNamesProto3OuterClass.HardKeywordsAllTypesProto3
+import com.google.protobuf.kotlin.generator.`in`.HardKeywordsAllTypesProto3Kt
+import com.google.protobuf.kotlin.generator.`in`.class_
+import com.google.protobuf.kotlin.generator.`in`.evilNamesProto3
+import com.google.protobuf.kotlin.generator.`in`.hardKeywordsAllTypesProto3
 import proto3_unittest.TestAllTypesKt
 import proto3_unittest.TestAllTypesKt.nestedMessage
 import proto3_unittest.UnittestProto3.TestAllTypes
@@ -54,6 +54,7 @@
 
 @RunWith(JUnit4::class)
 class Proto3Test {
+  @Suppress("CheckResult")
   @Test
   fun testGettersAndSetters() {
     testAllTypes {
@@ -65,11 +66,17 @@
       assertThat(optionalNestedMessage).isEqualTo(TestAllTypesKt.nestedMessage { bb = 118 })
       optionalNestedEnum = NestedEnum.BAZ
       assertThat(optionalNestedEnum).isEqualTo(NestedEnum.BAZ)
+      assertThat(optionalNestedEnumValue).isEqualTo(3)
+      optionalNestedEnumValue = 1
+      assertThat(optionalNestedEnumValue).isEqualTo(1)
+      assertThat(optionalNestedEnum).isEqualTo(NestedEnum.FOO)
+
       oneofUint32 = 601
       assertThat(oneofUint32).isEqualTo(601)
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testRepeatedGettersAndSetters() {
     testAllTypes {
@@ -259,6 +266,7 @@
     assertThat(class_ {}).isEqualTo(Class.newBuilder().build())
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordGettersAndSetters() {
     hardKeywordsAllTypesProto3 {
@@ -291,6 +299,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordHazzers() {
     hardKeywordsAllTypesProto3 {
@@ -308,6 +317,7 @@
     }
   }
 
+  @Suppress("CheckResult")
   @Test
   fun testHardKeywordClears() {
     hardKeywordsAllTypesProto3 {
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
index 3735baf..4ada5ea 100644
--- 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
@@ -33,7 +33,8 @@
 
 package protobuf.kotlin.generator;
 
-option java_package = "com.google.protobuf.kotlin.generator";
+option java_package = "in.com.google.protobuf.kotlin.generator";
+option java_multiple_files = true;
 
 message EvilNamesProto2 {
   optional bool initialized = 1;
@@ -61,13 +62,14 @@
   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 List {}
+
 message HardKeywordsAllTypesProto2 {
   message NestedMessage {
     optional int32 while = 1;
@@ -79,7 +81,6 @@
   }
 
   optional int32 as = 1;
-  optional string in = 2;
   optional NestedEnum break = 3;
   map<int32, int32> continue = 4;
   optional NestedMessage do = 5;
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
index f6b06d3..9feb219 100644
--- 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
@@ -33,7 +33,7 @@
 
 package protobuf.kotlin.generator;
 
-option java_package = "com.google.protobuf.kotlin.generator";
+option java_package = "com.google.protobuf.kotlin.generator.in";
 
 message EvilNamesProto3 {
   bool initialized = 1;
diff --git a/java/lite/BUILD.bazel b/java/lite/BUILD.bazel
index 9ae3c51..f84b5c5 100644
--- a/java/lite/BUILD.bazel
+++ b/java/lite/BUILD.bazel
@@ -72,6 +72,7 @@
         ":lite",
         "//java/core:generic_test_protos_java_proto_lite",
         "//java/core:java_test_protos_java_proto_lite",
+        "//java/core:lite_test_protos_java_proto_lite",
         "//java/core:test_util_lite",
         "@maven//:com_google_truth_truth",
         "@maven//:junit_junit",
diff --git a/java/lite/pom.xml b/java/lite/pom.xml
index db67296..26603ec 100644
--- a/java/lite/pom.xml
+++ b/java/lite/pom.xml
@@ -229,6 +229,7 @@
                     <exclude>TestBadIdentifiers.java</exclude>
                     <exclude>TextFormatParseInfoTreeTest.java</exclude>
                     <exclude>TextFormatParseLocationTest.java</exclude>
+                    <exclude>TextFormatPerformanceTest.java</exclude>
                     <exclude>TextFormatTest.java</exclude>
                     <exclude>TestUtil.java</exclude>
                     <exclude>TypeRegistryTest.java</exclude>
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 801303b..a4f95a2 100644
--- a/java/lite/src/test/java/com/google/protobuf/LiteTest.java
+++ b/java/lite/src/test/java/com/google/protobuf/LiteTest.java
@@ -51,6 +51,7 @@
 import com.google.protobuf.UnittestLite.TestAllTypesLiteOrBuilder;
 import com.google.protobuf.UnittestLite.TestHugeFieldNumbersLite;
 import com.google.protobuf.UnittestLite.TestNestedExtensionLite;
+import com.google.protobuf.testing.Proto3TestingLite.Proto3MessageLite;
 import map_lite_test.MapTestProto.TestMap;
 import map_lite_test.MapTestProto.TestMap.MessageValue;
 import protobuf_unittest.NestedExtensionLite;
@@ -225,6 +226,22 @@
   }
 
   @Test
+  public void testProto3EnumListValueCopyOnWrite() {
+    Proto3MessageLite.Builder builder = Proto3MessageLite.newBuilder();
+
+    Proto3MessageLite message = builder.build();
+    builder.addFieldEnumList30Value(Proto3MessageLite.TestEnum.ONE_VALUE);
+    assertThat(message.getFieldEnumList30List()).isEmpty();
+    assertThat(builder.getFieldEnumList30List()).containsExactly(Proto3MessageLite.TestEnum.ONE);
+    assertThat(message.getFieldEnumList30List()).isEmpty();
+    Proto3MessageLite messageAfterBuild = builder.build();
+    builder.clearFieldEnumList30();
+    assertThat(builder.getFieldEnumList30List()).isEmpty();
+    assertThat(messageAfterBuild.getFieldEnumList30List())
+        .containsExactly(Proto3MessageLite.TestEnum.ONE);
+  }
+
+  @Test
   public void testSanityCopyOnWrite() throws InvalidProtocolBufferException {
     // Since builders are implemented as a thin wrapper around a message
     // instance, we attempt to verify that we can't cause the builder to modify
@@ -1509,7 +1526,6 @@
     assertToStringEquals("optional_double: 3.14\noptional_float: 2.72", proto);
   }
 
-
   @Test
   public void testToStringStringFields() throws Exception {
     TestAllTypesLite proto =
diff --git a/java/pom.xml b/java/pom.xml
index 77b8314..dd29244 100644
--- a/java/pom.xml
+++ b/java/pom.xml
@@ -33,7 +33,7 @@
     <!-- These are relative to the submodules -->
     <protobuf.basedir>${project.basedir}/../..</protobuf.basedir>
     <protobuf.source.dir>${protobuf.basedir}/src</protobuf.source.dir>
-    <protoc>${protobuf.source.dir}/protoc</protoc>
+    <protoc>${protobuf.basedir}/protoc</protoc>
     <test.proto.dir>src/test/proto</test.proto.dir>
     <generated.sources.dir>${project.build.directory}/generated-sources</generated.sources.dir>
     <generated.testsources.dir>${project.build.directory}/generated-test-sources</generated.testsources.dir>
diff --git a/java/protoc/README.md b/java/protoc/README.md
new file mode 100644
index 0000000..a31ffbe
--- /dev/null
+++ b/java/protoc/README.md
@@ -0,0 +1,42 @@
+# Publish pre-compiled protoc artifacts
+``protoc`` is the compiler for ``.proto`` files. It generates language bindings
+for the messages and/or RPC services from ``.proto`` files.
+
+Because ``protoc`` is a native executable, the scripts under this directory
+publish a ``protoc`` executable (a.k.a. artifact) to Maven repositories. The
+artifact can be used by build automation tools so that users would not need to
+compile and install ``protoc`` for their systems.
+
+If you would like us to publish protoc artifact for a new platform, please
+open an issue to request it.
+
+## Maven Location
+The published protoc artifacts are available on Maven here:
+
+    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
+Protobuf project.
+
+## Artifact name
+The name of a published ``protoc`` artifact is in the following format:
+``protoc-<version>-<os>-<arch>.exe``, e.g., ``protoc-3.6.1-linux-x86_64.exe``.
+
+Note that artifacts for linux/macos also have the `.exe` suffix but they are
+not windows binaries.
+
+## System requirement
+Install [Apache Maven](http://maven.apache.org/) if you don't have it.
+
+The scripts only work under Unix-like environments, e.g., Linux, MacOSX, and
+Cygwin or MinGW for Windows. Please see ``README.md`` of the Protobuf project
+for how to set up the build environment.
+
+## Tested build environments
+We have successfully built artifacts on the following environments:
+- Linux x86_32 and x86_64:
+  - Centos 6.9 (within Docker 1.6.1)
+  - Ubuntu 14.04.5 64-bit
+- Linux aarch_64: Cross compiled with `g++-aarch64-linux-gnu` on Ubuntu 14.04.5 64-bit
+- Mac OS X x86_32 and x86_64: Mac OS X 10.9.5
diff --git a/java/protoc/pom.xml b/java/protoc/pom.xml
new file mode 100644
index 0000000..9b61b98
--- /dev/null
+++ b/java/protoc/pom.xml
@@ -0,0 +1,33 @@
+<?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</groupId>
+    <artifactId>google</artifactId>
+    <version>5</version>
+  </parent>
+  <groupId>com.google.protobuf</groupId>
+  <artifactId>protoc</artifactId>
+  <version>3.21.6</version>
+  <packaging>pom</packaging>
+  <name>Protobuf Compiler</name>
+  <description>
+    Protobuf Compiler (protoc) is a compiler for .proto files. It generates
+    language-specific code for Protobuf messages and RPC interfaces.
+  </description>
+  <inceptionYear>2008</inceptionYear>
+  <url>https://developers.google.com/protocol-buffers/</url>
+  <licenses>
+    <license>
+      <name>BSD-3-Clause</name>
+      <url>https://opensource.org/licenses/BSD-3-Clause</url>
+      <distribution>repo</distribution>
+    </license>
+  </licenses>
+  <scm>
+    <url>https://github.com/protocolbuffers/protobuf</url>
+    <connection>
+      scm:git:https://github.com/protocolbuffers/protobuf.git
+    </connection>
+  </scm>
+</project>
diff --git a/java/util/pom_template.xml b/java/util/pom_template.xml
index b20e62a..13fe3ec 100644
--- a/java/util/pom_template.xml
+++ b/java/util/pom_template.xml
@@ -12,7 +12,8 @@
 
   <name>Protocol Buffers [Util]</name>
   <description>Utilities for Protocol Buffers</description>
-
-  {dependencies}
+  <dependencies>
+    {dependencies}
+  </dependencies>
 
 </project>
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 9f36494..55e3079 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
@@ -101,9 +101,8 @@
   /**
    * Constructs a FieldMask for a list of field paths in a certain type.
    *
-   * @throws IllegalArgumentException if any of the field path is not valid.
+   * @throws IllegalArgumentException if any of the field path is not valid
    */
-  // TODO(xiaofeng): Consider renaming fromStrings()
   public static FieldMask fromStringList(Class<? extends Message> type, Iterable<String> paths) {
     return fromStringList(Internal.getDefaultInstance(type).getDescriptorForType(), paths);
   }
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 6bed2e3..992980b 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
@@ -534,7 +534,6 @@
       this.types = types;
     }
 
-
     /** A Builder is used to build {@link TypeRegistry}. */
     public static class Builder {
       private Builder() {}
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 95f3665..0b09fcc 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
@@ -343,7 +343,8 @@
   public static Timestamp fromDate(Date date) {
     if (date instanceof java.sql.Timestamp) {
       java.sql.Timestamp sqlTimestamp = (java.sql.Timestamp) date;
-      long integralSeconds = sqlTimestamp.getTime() / 1000L; // truncate the fractional seconds
+      long time = sqlTimestamp.getTime();
+      long integralSeconds = (time < 0 && time % 1000 != 0) ? time / 1000L - 1 : time / 1000L ; // truncate the fractional seconds
       return Timestamp.newBuilder()
           .setSeconds(integralSeconds)
           .setNanos(sqlTimestamp.getNanos())
diff --git a/java/util/src/main/java/com/google/protobuf/util/Values.java b/java/util/src/main/java/com/google/protobuf/util/Values.java
index f03d70e..370aafa 100644
--- a/java/util/src/main/java/com/google/protobuf/util/Values.java
+++ b/java/util/src/main/java/com/google/protobuf/util/Values.java
@@ -75,10 +75,7 @@
    * element in the iterable.
    */
   public static Value of(Iterable<Value> values) {
-    Value.Builder valueBuilder = Value.newBuilder();
-    ListValue.Builder listValue = valueBuilder.getListValueBuilder();
-    listValue.addAllValues(values);
-    return valueBuilder.build();
+    return Value.newBuilder().setListValue(ListValue.newBuilder().addAllValues(values)).build();
   }
 
   private Values() {}
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 c31031e..45ae68a 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
@@ -1019,7 +1019,6 @@
     assertRoundTripEquals(message);
   }
 
-
   @Test
   public void testAnyFieldsWithCustomAddedTypeRegistry() throws Exception {
     TestAllTypes content = TestAllTypes.newBuilder().setOptionalInt32(1234).build();
diff --git a/java/util/src/test/java/com/google/protobuf/util/StructsTest.java b/java/util/src/test/java/com/google/protobuf/util/StructsTest.java
index 9eb4cc6..b57a116 100644
--- a/java/util/src/test/java/com/google/protobuf/util/StructsTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/StructsTest.java
@@ -61,5 +61,4 @@
     assertThat(Structs.of("k1", Values.of(1), "k2", Values.of(2), "k3", Values.of(3)))
         .isEqualTo(expected.build());
   }
-
 }
diff --git a/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java b/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java
index ea90a6b..51f7a85 100644
--- a/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java
+++ b/java/util/src/test/java/com/google/protobuf/util/TimestampsTest.java
@@ -475,6 +475,20 @@
     Timestamp timestamp = Timestamps.fromDate(date);
     assertThat(Timestamps.toString(timestamp)).isEqualTo("1970-01-01T00:00:01.111Z");
   }
+  
+  @Test
+  public void testFromSqlTimestamp_beforeEpoch() {
+    Date date = new java.sql.Timestamp(-1111);
+    Timestamp timestamp = Timestamps.fromDate(date);
+    assertThat(Timestamps.toString(timestamp)).isEqualTo("1969-12-31T23:59:58.889Z");
+  }
+
+  @Test
+  public void testFromSqlTimestamp_beforeEpochWholeSecond() {
+    Date date = new java.sql.Timestamp(-2000);
+    Timestamp timestamp = Timestamps.fromDate(date);
+    assertThat(Timestamps.toString(timestamp)).isEqualTo("1969-12-31T23:59:58Z");
+  }
 
   @Test
   public void testTimeOperations() throws Exception {
diff --git a/kokoro/common/bazel_flags.sh b/kokoro/common/bazel_flags.sh
new file mode 100755
index 0000000..6a2777f
--- /dev/null
+++ b/kokoro/common/bazel_flags.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# Helper for setting up common bazel flags in Kokoro.
+#
+# This script prints extra flags to a bazel invocation when it is run from
+# Kokoro.  When the special environment variables are not present (e.g., if you
+# run Kokoro build scripts locally), this script only flips some debug settings.
+#
+# Example of running directly:
+#   bazel test $(path/to/bazel_flags.sh) //...
+
+function bazel_flags::gen_invocation_id() {
+  # Create a new invocation ID and store in the artifacts dir.
+  local _invocation_id=$(uuidgen | tr A-Z a-z)
+
+  # Put the new invocation ID at the start of the output IDs file. Some
+  # Google-internal tools only look at the first entry, so this ensures the most
+  # recent entry is first.
+  local _ids_file=${KOKORO_ARTIFACTS_DIR}/bazel_invocation_ids
+  local _temp_ids=$(mktemp)
+  echo ${_invocation_id} > ${_temp_ids}
+  [[ -e ${_ids_file} ]] && cat ${_ids_file} >> ${_temp_ids}
+  mv -f ${_temp_ids} ${_ids_file}
+
+  echo -n ${_invocation_id}
+}
+
+# Prints flags to use on Kokoro.
+function bazel_flags::kokoro_flags() {
+  [[ -n ${KOKORO_JOB_NAME:-} ]] || return
+
+  local -a _flags
+  _flags+=(
+    --invocation_id=$(bazel_flags::gen_invocation_id)
+    --remote_cache=https://storage.googleapis.com/protobuf-bazel-cache/${KOKORO_JOB_NAME}
+  )
+  if [[ -n ${KOKORO_BAZEL_AUTH_CREDENTIAL:-} ]]; then
+    _flags+=( --google_credentials=${KOKORO_BAZEL_AUTH_CREDENTIAL} )
+  else
+    _flags+=( --google_default_credentials=true )
+  fi
+
+  echo "${_flags[@]}"
+}
+
+echo "$(bazel_flags::kokoro_flags) --keep_going --test_output=errors"
diff --git a/kokoro/caplog.sh b/kokoro/common/caplog.sh
similarity index 98%
rename from kokoro/caplog.sh
rename to kokoro/common/caplog.sh
index fe81949..33ee1ab 100644
--- a/kokoro/caplog.sh
+++ b/kokoro/common/caplog.sh
@@ -19,7 +19,7 @@
 #
 # Use the provided functions below as build/test fixtures, e.g.:
 #
-#   source kokoro/capture_logs.sh
+#   source kokoro/common/capture_logs.sh
 #   caplog build/step1 <build command>
 #   caplog tests/step2 <test command>
 #
diff --git a/kokoro/common/cmake.sh b/kokoro/common/cmake.sh
new file mode 100755
index 0000000..99be3be
--- /dev/null
+++ b/kokoro/common/cmake.sh
@@ -0,0 +1,84 @@
+#!/bin/bash
+#
+# Build tests under CMake.
+#
+# This script is used from macos and linux builds. It runs cmake and ctest in
+# the current directory. Any additional setup should be done before running this
+# script.
+#
+# This script uses `caplog` to save logfiles. See caplog.sh for details.
+
+set -eu -o pipefail
+: ${SCRIPT_ROOT:=$(cd $(dirname $0)/../..; pwd)}
+
+################################################################################
+# If you are using this script to run tests, you can set some environment
+# variables to control behavior:
+#
+# By default, find the sources based on this script's path.
+: ${SOURCE_DIR:=${SCRIPT_ROOT}}
+#
+# By default, put outputs under <git root>/cmake/build.
+: ${BUILD_DIR:=${SOURCE_DIR}/cmake/build}
+#
+# CMAKE_BUILD_TYPE is supported in cmake 3.22+. If set, we pass the value of this
+# variable explicitly for compatibility with older versions of cmake. See:
+#   https://cmake.org/cmake/help/latest/variable/CMAKE_BUILD_TYPE.html
+# (N.B.: not to be confused with CMAKE_CONFIG_TYPE.)
+if [[ -n ${CMAKE_BUILD_TYPE:-} ]]; then
+  CMAKE_BUILD_TYPE_FLAG="-DCMAKE_BUILD_TYPE=${CMAKE_BUILD_TYPE}"
+else
+  CMAKE_BUILD_TYPE_FLAG=
+fi
+#
+# For several other CMake options, see docs here:
+#   https://cmake.org/cmake/help/latest/manual/cmake-env-variables.7.html
+#
+# Some variables you may want to override (see cmake docs for details):
+#   CMAKE_BUILD_PARALLEL_LEVEL
+#   CMAKE_CONFIG_TYPE (N.B.: not to be confused with CMAKE_BUILD_TYPE)
+#   CMAKE_GENERATOR
+#   CTEST_PARALLEL_LEVEL
+################################################################################
+
+echo "Building using..."
+echo "       Sources: ${SOURCE_DIR}"
+echo "  Build output: ${BUILD_DIR}"
+if [[ ${SOURCE_DIR} != ${SCRIPT_ROOT} ]]; then
+  echo " Build scripts: ${SCRIPT_ROOT}"
+fi
+set -x
+source ${SCRIPT_ROOT}/kokoro/common/caplog.sh
+
+#
+# Configure under $BUILD_DIR:
+#
+mkdir -p "${BUILD_DIR}"
+
+(
+  cd "${BUILD_DIR}"
+  caplog 01_configure \
+    cmake -S "${SOURCE_DIR}" \
+    ${CMAKE_BUILD_TYPE_FLAG} \
+    ${CAPLOG_CMAKE_ARGS:-}
+)
+if [[ -n ${CAPLOG_DIR:-} ]]; then
+  # Save configuration logs.
+  mkdir -p "${CAPLOG_DIR}/CMakeFiles"
+  cp "${BUILD_DIR}"/CMakeFiles/CMake*.log "${CAPLOG_DIR}/CMakeFiles"
+fi
+
+#
+# Build:
+#
+caplog 02_build \
+  cmake --build "${BUILD_DIR}"
+
+#
+# Run tests
+#
+(
+  cd "${BUILD_DIR}"
+  caplog 03_combined_testlog \
+    ctest ${CAPLOG_CTEST_ARGS:-}
+)
diff --git a/kokoro/docs/publish-python.sh b/kokoro/docs/publish-python.sh
index 684afa6..9f88017 100755
--- a/kokoro/docs/publish-python.sh
+++ b/kokoro/docs/publish-python.sh
@@ -14,9 +14,9 @@
 sudo add-apt-repository universe
 sudo apt-get update
 sudo apt-get -y install unzip
-wget https://github.com/protocolbuffers/protobuf/releases/download/v21.0-rc1/protoc-21.0-rc-1-linux-x86_64.zip
-unzip protoc-21.0-rc-1-linux-x86_64.zip bin/protoc
-mv bin/protoc ../src/protoc
+wget https://github.com/protocolbuffers/protobuf/releases/download/v21.1/protoc-21.1-linux-x86_64.zip
+unzip protoc-21.1-linux-x86_64.zip bin/protoc
+mv bin/protoc ../protoc
 python3 -m venv venv
 source venv/bin/activate
 python setup.py install
@@ -30,7 +30,7 @@
 cd ..
 deactivate
 
-python3 -m pip install protobuf==4.21.0rc1 gcp-docuploader
+python3 -m pip install protobuf==4.21.1 gcp-docuploader==0.6.3
 
 # install a json parser
 sudo apt-get -y install jq
diff --git a/kokoro/linux/32-bit/Dockerfile b/kokoro/linux/32-bit/Dockerfile
deleted file mode 100644
index 1278889..0000000
--- a/kokoro/linux/32-bit/Dockerfile
+++ /dev/null
@@ -1,143 +0,0 @@
-# This Dockerfile specifies the recipe for creating an image for the tests
-# to run in.
-#
-# We install as many test dependencies here as we can, because these setup
-# steps can be cached.  They do *not* run every time we run the build.
-# The Docker image is only rebuilt when the Dockerfile (ie. this file)
-# changes.
-
-# Base Dockerfile for gRPC dev images
-FROM 32bit/debian:latest
-
-# Apt source for php
-RUN echo "deb http://ppa.launchpad.net/ondrej/php/ubuntu trusty main" | tee /etc/apt/sources.list.d/various-php.list && \
-  apt-key adv --keyserver keyserver.ubuntu.com --recv-keys F4FCBB07
-
-# Install dependencies.  We start with the basic ones require to build protoc
-# and the C++ build
-RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
-  autoconf \
-  autotools-dev \
-  build-essential \
-  bzip2 \
-  ccache \
-  curl \
-  gcc \
-  git \
-  libc6 \
-  libc6-dbg \
-  libc6-dev \
-  libgtest-dev \
-  libtool \
-  make \
-  parallel \
-  time \
-  wget \
-  unzip \
-  # -- For python --
-  python-setuptools \
-  python-pip \
-  python-dev \
-  # -- For C++ benchmarks --
-  cmake  \
-  # -- For PHP --
-  php5.5     \
-  php5.5-dev \
-  php5.5-xml \
-  php5.6     \
-  php5.6-dev \
-  php5.6-xml \
-  php7.0     \
-  php7.0-dev \
-  php7.0-xml \
-  phpunit    \
-  valgrind   \
-  libxml2-dev \
-  && apt-get clean
-
-##################
-# PHP dependencies.
-RUN wget http://am1.php.net/get/php-5.5.38.tar.bz2/from/this/mirror
-RUN mv mirror php-5.5.38.tar.bz2
-RUN tar -xvf php-5.5.38.tar.bz2
-RUN cd php-5.5.38 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.5-zts && \
-    make && make install && make clean && cd ..
-RUN cd php-5.5.38 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.5 && \
-    make && make install && make clean && cd ..
-
-RUN wget http://am1.php.net/get/php-5.6.30.tar.bz2/from/this/mirror
-RUN mv mirror php-5.6.30.tar.bz2
-RUN tar -xvf php-5.6.30.tar.bz2
-RUN cd php-5.6.30 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-5.6-zts && \
-    make && make install && cd ..
-RUN cd php-5.6.30 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-5.6 && \
-    make && make install && cd ..
-
-RUN wget http://am1.php.net/get/php-7.0.18.tar.bz2/from/this/mirror
-RUN mv mirror php-7.0.18.tar.bz2
-RUN tar -xvf php-7.0.18.tar.bz2
-RUN cd php-7.0.18 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.0-zts && \
-    make && make install && cd ..
-RUN cd php-7.0.18 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.0 && \
-    make && make install && cd ..
-
-RUN wget http://am1.php.net/get/php-7.1.4.tar.bz2/from/this/mirror
-RUN mv mirror php-7.1.4.tar.bz2
-RUN tar -xvf php-7.1.4.tar.bz2
-RUN cd php-7.1.4 && ./configure --enable-maintainer-zts --prefix=/usr/local/php-7.1-zts && \
-    make && make install && cd ..
-RUN cd php-7.1.4 && make clean && ./configure --enable-bcmath --prefix=/usr/local/php-7.1 && \
-    make && make install && cd ..
-
-RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
-RUN php composer-setup.php
-RUN mv composer.phar /usr/bin/composer
-RUN php -r "unlink('composer-setup.php');"
-RUN composer config -g -- disable-tls true
-RUN composer config -g -- secure-http false
-RUN cd /tmp && \
-  git clone https://github.com/google/protobuf.git && \
-  cd protobuf/php && \
-  git reset --hard 49b44bff2b6257a119f9c6a342d6151c736586b8 && \
-  ln -sfn /usr/local/php-5.5/bin/php /usr/bin/php && \
-  ln -sfn /usr/local/php-5.5/bin/php-config /usr/bin/php-config && \
-  ln -sfn /usr/local/php-5.5/bin/phpize /usr/bin/phpize && \
-  composer install && \
-  mv vendor /usr/local/vendor-5.5 && \
-  ln -sfn /usr/local/php-5.6/bin/php /usr/bin/php && \
-  ln -sfn /usr/local/php-5.6/bin/php-config /usr/bin/php-config && \
-  ln -sfn /usr/local/php-5.6/bin/phpize /usr/bin/phpize && \
-  composer install && \
-  mv vendor /usr/local/vendor-5.6 && \
-  ln -sfn /usr/local/php-7.0/bin/php /usr/bin/php && \
-  ln -sfn /usr/local/php-7.0/bin/php-config /usr/bin/php-config && \
-  ln -sfn /usr/local/php-7.0/bin/phpize /usr/bin/phpize && \
-  composer install && \
-  mv vendor /usr/local/vendor-7.0 && \
-  ln -sfn /usr/local/php-7.1/bin/php /usr/bin/php && \
-  ln -sfn /usr/local/php-7.1/bin/php-config /usr/bin/php-config && \
-  ln -sfn /usr/local/php-7.1/bin/phpize /usr/bin/phpize && \
-  composer install && \
-  mv vendor /usr/local/vendor-7.1
-
-##################
-# Python dependencies
-
-# These packages exist in apt-get, but their versions are too old, so we have
-# to get updates from pip.
-
-RUN pip install pip --upgrade
-RUN pip install virtualenv tox yattag
-
-##################
-# Prepare ccache
-
-RUN ln -s /usr/bin/ccache /usr/local/bin/gcc
-RUN ln -s /usr/bin/ccache /usr/local/bin/g++
-RUN ln -s /usr/bin/ccache /usr/local/bin/cc
-RUN ln -s /usr/bin/ccache /usr/local/bin/c++
-RUN ln -s /usr/bin/ccache /usr/local/bin/clang
-RUN ln -s /usr/bin/ccache /usr/local/bin/clang++
-
-# Define the default command.
-CMD ["bash"]
diff --git a/kokoro/linux/32-bit/build.sh b/kokoro/linux/32-bit/build.sh
index 8c0a41e..85dd81d 100755
--- a/kokoro/linux/32-bit/build.sh
+++ b/kokoro/linux/32-bit/build.sh
@@ -4,15 +4,20 @@
 # running the "pull request 32" 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.
+# a script to run inside that image.
+
+set -ex
 
 # Change to repo root
 cd $(dirname $0)/../../..
+GIT_REPO_ROOT=$(pwd)
 
-export DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/php_32bit
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="php_all_32"
-./kokoro/linux/build_and_run_docker.sh
+CONTAINER_IMAGE=gcr.io/protobuf-build/php/32bit@sha256:824cbdff02ee543eb69ee4b02c8c58cc7887f70f49e41725a35765d92a898b4f
+
+git submodule update --init --recursive
+
+docker run \
+  "$@" \
+  -v $GIT_REPO_ROOT:/workspace \
+  $CONTAINER_IMAGE \
+  bash -l "/workspace/kokoro/linux/32-bit/test_php.sh"
diff --git a/kokoro/linux/benchmark/continuous.cfg b/kokoro/linux/32-bit/common.cfg
similarity index 67%
rename from kokoro/linux/benchmark/continuous.cfg
rename to kokoro/linux/32-bit/common.cfg
index 8cc8f96..28b66c0 100644
--- a/kokoro/linux/benchmark/continuous.cfg
+++ b/kokoro/linux/32-bit/common.cfg
@@ -1,8 +1,8 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/benchmark/build.sh"
-timeout_mins: 240
+build_file: "protobuf/kokoro/linux/32-bit/build.sh"
+timeout_mins: 120
 
 action {
   define_artifacts {
diff --git a/kokoro/linux/32-bit/continuous.cfg b/kokoro/linux/32-bit/continuous.cfg
index 28b66c0..8523c22 100644
--- a/kokoro/linux/32-bit/continuous.cfg
+++ b/kokoro/linux/32-bit/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/32-bit/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/32-bit/presubmit.cfg b/kokoro/linux/32-bit/presubmit.cfg
index 28b66c0..8523c22 100644
--- a/kokoro/linux/32-bit/presubmit.cfg
+++ b/kokoro/linux/32-bit/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/32-bit/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/32-bit/test_php.sh b/kokoro/linux/32-bit/test_php.sh
new file mode 100644
index 0000000..746ed4c
--- /dev/null
+++ b/kokoro/linux/32-bit/test_php.sh
@@ -0,0 +1,58 @@
+#!/bin/bash
+
+set -eux
+
+# Change to repo root
+cd $(dirname $0)/../../..
+
+use_php() {
+  VERSION=$1
+  export PATH=/usr/local/php-${VERSION}/bin:$PATH
+}
+
+build_php() {
+  use_php $1
+  pushd php
+  rm -rf vendor
+  php -v
+  php -m
+  composer update
+  composer test
+  popd
+}
+
+test_php_c() {
+  pushd php
+  rm -rf vendor
+  php -v
+  php -m
+  composer update
+  composer test_c
+  popd
+}
+
+build_php_c() {
+  use_php $1
+  test_php_c
+}
+
+mkdir -p build
+pushd build
+cmake ..
+cmake --build . -- -j20
+ctest --verbose --parallel 20
+export PROTOC=$(pwd)/protoc
+popd
+
+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
+
+# Cleanup after CMake build
+rm -rf build
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
index 425cc90..f7c45f9 100755
--- 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
@@ -5,12 +5,9 @@
 
 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 ..
+cmake .
 make -j8
 
 # check that the resulting test binary is indeed an aarch64 ELF
diff --git a/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh b/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh
index ba34fa7..efaf40f 100755
--- a/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh
+++ b/kokoro/linux/aarch64/dockcross_helpers/run_dockcross_manylinux2014_aarch64.sh
@@ -13,7 +13,11 @@
 fi
 
 # Pin the dockcross image since newer versions of the image break the build
-PINNED_DOCKCROSS_IMAGE_VERSION=dockcross/manylinux2014-aarch64:20210803-41e5c69
+# We use an older version of dockcross image that has gcc4.9.4 because it was built
+# before https://github.com/dockcross/dockcross/pull/449
+# Thanks to that, wheel build with this image aren't actually
+# compliant with manylinux2014, but only with manylinux_2_24
+PINNED_DOCKCROSS_IMAGE_VERSION=dockcross/manylinux2014-aarch64:20200929-608e6ac
 
 # running dockcross image without any arguments generates a wrapper
 # scripts that can be used to run commands under the dockcross image
diff --git a/kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh b/kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
index 77942a4..7f07968 100755
--- a/kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
+++ b/kokoro/linux/aarch64/protoc_crosscompile_aarch64.sh
@@ -4,6 +4,5 @@
 
 set -ex
 
-./autogen.sh
-CXXFLAGS="-fPIC -g -O2" ./configure --host=aarch64
+cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -Dprotobuf_WITH_ZLIB=0 -Dprotobuf_BUILD_TESTS=OFF .
 make -j8
diff --git a/kokoro/linux/aarch64/python_crosscompile_aarch64.sh b/kokoro/linux/aarch64/python_crosscompile_aarch64.sh
index db2e776..a04c7e4 100755
--- a/kokoro/linux/aarch64/python_crosscompile_aarch64.sh
+++ b/kokoro/linux/aarch64/python_crosscompile_aarch64.sh
@@ -8,13 +8,16 @@
 
 PYTHON="/opt/python/cp38-cp38/bin/python"
 
-./autogen.sh
-CXXFLAGS="-fPIC -g -O2" ./configure --host=aarch64
+# Initialize any submodules.
+git submodule update --init --recursive
+
+# Build protoc and libprotobuf
+cmake -DCMAKE_POSITION_INDEPENDENT_CODE=ON -Dprotobuf_WITH_ZLIB=0 -Dprotobuf_BUILD_TESTS=OFF .
 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
+echo 'exec qemu-aarch64 "../protoc" "$@"' >>protoc_qemu_wrapper.sh
 chmod ugo+x protoc_qemu_wrapper.sh
 
 # PROTOC variable is by build_py step that runs under ./python directory
diff --git a/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh b/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
index 5026d04..4c75ad8 100755
--- a/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
+++ b/kokoro/linux/aarch64/python_run_tests_with_qemu_aarch64.sh
@@ -7,7 +7,7 @@
 cd python
 
 PYTHON="/opt/python/cp38-cp38/bin/python"
-${PYTHON} -m pip install --user pytest auditwheel
+${PYTHON} -m pip install --user pytest auditwheel numpy
 
 # 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)
@@ -16,7 +16,7 @@
 # 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
+LD_LIBRARY_PATH=. 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)
diff --git a/kokoro/linux/aarch64/test_ruby_aarch64.sh b/kokoro/linux/aarch64/test_ruby_aarch64.sh
index 91ee5f2..e256e4e 100755
--- a/kokoro/linux/aarch64/test_ruby_aarch64.sh
+++ b/kokoro/linux/aarch64/test_ruby_aarch64.sh
@@ -24,4 +24,4 @@
 #   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
+docker run $DOCKER_TTY_ARGS --rm --user "$(id -u):$(id -g)" -e "HOME=/home/fake-user" -e "PROTOC=/work/protoc" -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
diff --git a/kokoro/linux/bazel.sh b/kokoro/linux/bazel.sh
new file mode 100755
index 0000000..9f16569
--- /dev/null
+++ b/kokoro/linux/bazel.sh
@@ -0,0 +1,60 @@
+#!/bin/bash
+
+set -ex
+
+if [[ -z "${CONTAINER_IMAGE}" ]]; then
+  CONTAINER_IMAGE=gcr.io/protobuf-build/bazel/linux@sha256:2bfd061284eff8234f2fcca16d71d43c69ccf3a22206628b54c204a6a9aac277
+fi
+
+cd $(dirname $0)/../..
+GIT_REPO_ROOT=`pwd`
+
+ENVS=()
+
+# Check for specific versions pinned to the docker image.  In these cases we
+# want to forward the environment variable to tests, so that they can verify
+# that the correct version is being picked up by Bazel.
+ENVS+=("--test_env=KOKORO_JAVA_VERSION")
+ENVS+=("--test_env=KOKORO_PYTHON_VERSION")
+ENVS+=("--test_env=KOKORO_RUBY_VERSION")
+
+if [ -n "$BAZEL_ENV" ]; then
+  for env in $BAZEL_ENV; do
+    ENVS+="--action_env=${env}"
+  done
+fi
+
+function run {
+  local CONFIG=$1
+  local BAZEL_CONFIG=$2
+
+  tmpfile=$(mktemp -u)
+
+  rm -rf $GIT_REPO_ROOT/bazel-out $GIT_REPO_ROOT/bazel-bin
+  rm -rf $GIT_REPO_ROOT/logs
+
+  docker run \
+    --cidfile $tmpfile \
+    --cap-add=SYS_PTRACE \
+    -v $GIT_REPO_ROOT:/workspace \
+    $CONTAINER_IMAGE \
+    test \
+    $(${GIT_REPO_ROOT}/kokoro/common/bazel_flags.sh) \
+    ${ENVS[@]} \
+    $PLATFORM_CONFIG \
+    $BAZEL_CONFIG \
+    $BAZEL_EXTRA_FLAGS \
+    $BAZEL_TARGETS
+
+  # Save logs for Kokoro
+  docker cp \
+    `cat $tmpfile`:/workspace/logs $KOKORO_ARTIFACTS_DIR/$CONFIG
+}
+
+if [ -n "$BAZEL_CONFIGS" ]; then
+  for config in $BAZEL_CONFIGS; do
+    run $config "--config=$config"
+  done
+else
+    run
+fi
diff --git a/kokoro/linux/bazel/build.sh b/kokoro/linux/bazel/build.sh
deleted file mode 100755
index a338a99..0000000
--- a/kokoro/linux/bazel/build.sh
+++ /dev/null
@@ -1,47 +0,0 @@
-#!/bin/bash
-#
-# Build file to set up and run tests
-set -ex
-
-# Install Bazel 4.0.0.
-use_bazel.sh 4.0.0
-bazel version
-
-# Print bazel testlogs to stdout when tests failed.
-function print_test_logs {
-  # TODO(yannic): Only print logs of failing tests.
-  testlogs_dir=$(bazel info bazel-testlogs)
-  testlogs=$(find "${testlogs_dir}" -name "*.log")
-  for log in $testlogs; do
-    cat "${log}"
-  done
-}
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-git submodule update --init --recursive
-
-#  Disabled for now, re-enable if appropriate.
-#  //:build_files_updated_unittest \
-
-trap print_test_logs EXIT
-bazel test -k --copt=-Werror --host_copt=-Werror \
-  //build_defs:all \
-  //java:tests \
-  //:protoc \
-  //:protobuf \
-  //:protobuf_python \
-  //:protobuf_test
-trap - EXIT
-
-pushd examples
-bazel build //...
-popd
-
-# Verify that we can build successfully from generated tar files.
-./autogen.sh && ./configure && make -j$(nproc) dist
-DIST=`ls *.tar.gz`
-tar -xf $DIST
-cd ${DIST//.tar.gz}
-bazel build //:protobuf //:protobuf_java
diff --git a/kokoro/linux/bazel/common.cfg b/kokoro/linux/bazel/common.cfg
new file mode 100644
index 0000000..54447d9
--- /dev/null
+++ b/kokoro/linux/bazel/common.cfg
@@ -0,0 +1,31 @@
+# Default setup for the all of our Kokoro builds.
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/bazel/linux-san:b6bfa3bb505e83f062af0cb0ed23abf1e89b9edb"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//src/... @com_google_protobuf_examples//..."
+}
+
+env_vars {
+  key: "BAZEL_CONFIGS"
+  value: "opt dbg asan kokoro-msan tsan ubsan"
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--distinct_host_configuration=false"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/bazel/continuous.cfg b/kokoro/linux/bazel/continuous.cfg
index 13cfef1..8523c22 100644
--- a/kokoro/linux/bazel/continuous.cfg
+++ b/kokoro/linux/bazel/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/bazel/build.sh"
-timeout_mins: 15
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/bazel/presubmit.cfg b/kokoro/linux/bazel/presubmit.cfg
index 13cfef1..8523c22 100644
--- a/kokoro/linux/bazel/presubmit.cfg
+++ b/kokoro/linux/bazel/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/bazel/build.sh"
-timeout_mins: 15
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/bazel_distcheck/build.sh b/kokoro/linux/bazel_distcheck/build.sh
deleted file mode 100755
index 4eb6e11..0000000
--- a/kokoro/linux/bazel_distcheck/build.sh
+++ /dev/null
@@ -1,87 +0,0 @@
-#!/bin/bash
-#
-# Build file to set up and run tests using bazel-build dist archive
-#
-# Note that the builds use WORKSPACE to fetch external sources, not
-# git submodules.
-
-set -eux
-
-BUILD_ONLY_TARGETS=(
-  //pkg:all
-  //:protoc
-  //:protobuf
-  //:protobuf_python
-)
-
-TEST_TARGETS=(
-  //build_defs:all
-  //conformance:all
-  //java:tests
-  //:protobuf_test
-)
-
-use_bazel.sh 5.0.0 || true
-bazel version
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-# Construct temp directory for running the dist build.
-# If you want to run locally and keep the build dir, create a directory
-# and pass it in the DIST_WORK_ROOT env var.
-if [[ -z ${DIST_WORK_ROOT:-} ]]; then
-  : ${DIST_WORK_ROOT:=$(mktemp -d)}
-  function dist_cleanup() {
-    rm -rf ${DIST_WORK_ROOT}
-  }
-  trap dist_cleanup EXIT
-fi
-
-# Let Bazel share the distdir.
-TMP_DISTDIR=${DIST_WORK_ROOT}/bazel-distdir
-mkdir -p ${TMP_DISTDIR}
-
-# Build distribution archive
-date
-bazel fetch --distdir=${TMP_DISTDIR} //pkg:dist_all_tar
-bazel build --distdir=${TMP_DISTDIR} //pkg:dist_all_tar
-DIST_ARCHIVE=$(readlink $(bazel info bazel-bin)/pkg/dist_all_tar.tar.gz)
-bazel shutdown
-
-# The `pkg_tar` rule emits a symlink based on the rule name. The actual
-# file is named with the current version.
-date
-echo "Resolved archive path: ${DIST_ARCHIVE}"
-
-# Extract the dist archive.
-date
-DIST_WORKSPACE=${DIST_WORK_ROOT}/protobuf
-mkdir -p ${DIST_WORKSPACE}
-tar -C ${DIST_WORKSPACE} --strip-components=1 -axf ${DIST_ARCHIVE}
-
-# Perform build steps in the extracted dist sources.
-
-cd ${DIST_WORKSPACE}
-FAILED=false
-
-date
-bazel fetch --distdir=${TMP_DISTDIR} "${BUILD_ONLY_TARGETS[@]}" "${TEST_TARGETS[@]}"
-
-date
-bazel build --distdir=${TMP_DISTDIR} -k \
-  "${BUILD_ONLY_TARGETS[@]}" || FAILED=true
-
-date
-bazel test --distdir=${TMP_DISTDIR} --test_output=errors -k \
-  "${TEST_TARGETS[@]}" || FAILED=true
-
-date
-cd examples
-bazel build --distdir=${TMP_DISTDIR} //... || FAILED=true
-
-if ${FAILED}; then
-   echo FAILED
-   exit 1
-fi
-echo PASS
diff --git a/kokoro/linux/bazel_distcheck/continuous.cfg b/kokoro/linux/bazel_distcheck/continuous.cfg
deleted file mode 100644
index 4ea8b21..0000000
--- a/kokoro/linux/bazel_distcheck/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/bazel_distcheck/build.sh"
-timeout_mins: 15
diff --git a/kokoro/linux/bazel_distcheck/presubmit.cfg b/kokoro/linux/bazel_distcheck/presubmit.cfg
deleted file mode 100644
index 4ea8b21..0000000
--- a/kokoro/linux/bazel_distcheck/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/bazel_distcheck/build.sh"
-timeout_mins: 15
diff --git a/kokoro/linux/benchmark/build.sh b/kokoro/linux/benchmark/build.sh
deleted file mode 100755
index f470989..0000000
--- a/kokoro/linux/benchmark/build.sh
+++ /dev/null
@@ -1,18 +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 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="benchmark"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/benchmark/run.sh b/kokoro/linux/benchmark/run.sh
deleted file mode 100755
index 963f779..0000000
--- a/kokoro/linux/benchmark/run.sh
+++ /dev/null
@@ -1,99 +0,0 @@
-#!/bin/bash
-#
-# Change to repo root
-cd $(dirname $0)/../../..
-
-set -ex
-
-export OUTPUT_DIR=testoutput
-repo_root="$(pwd)"
-
-# TODO(jtattermusch): Add back support for benchmarking with tcmalloc for C++ and python.
-# This feature was removed since it used to use tcmalloc from https://github.com/gperftools/gperftools.git
-# which is very outdated. See https://github.com/protocolbuffers/protobuf/issues/8725.
-
-# download datasets for benchmark
-pushd benchmarks
-datasets=$(for file in $(find . -type f -name "dataset.*.pb" -not -path "./tmp/*"); do echo "$(pwd)/$file"; done | xargs)
-echo $datasets
-popd
-
-# build Python protobuf
-./autogen.sh
-./configure CXXFLAGS="-fPIC -O2"
-make -j8
-pushd python
-python3 -m venv env
-source env/bin/activate
-python3 setup.py build --cpp_implementation
-pip3 install --install-option="--cpp_implementation" .
-popd
-
-# build and run Python benchmark
-# 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
-echo "[" > tmp/python_result.json
-echo "benchmarking pure python..."
-./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_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_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"
-popd
-
-# build CPP protobuf
-./configure
-make clean && make -j8
-
-pushd java
-mvn package -B -Dmaven.test.skip=true
-popd
-
-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 ./cpp-benchmark --benchmark_min_time=5.0 --benchmark_out_format=json --benchmark_out="tmp/cpp_result.json" $datasets
-
-# 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 and run java benchmark (java 11 is required)
-make java-benchmark
-echo "benchmarking java..."
-./java-benchmark -Cresults.file.options.file="tmp/java_result.json" $datasets
-
-# TODO(jtattermusch): re-enable JS benchmarks once https://github.com/protocolbuffers/protobuf/issues/8747 is fixed.
-# build and run js benchmark
-# make js-benchmark
-# echo "benchmarking js..."
-# ./js-benchmark $datasets  --json_output=$(pwd)/tmp/node_result.json
-
-# TODO(jtattermusch): add php-c-benchmark. Currently its build is broken.
-
-# 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
-
-# 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="${repo_root}/src/.libs" python3 -m util.result_parser \
-	-cpp="../tmp/cpp_result.json" -java="../tmp/java_result.json" -python="../tmp/python_result.json"
-popd
-
diff --git a/kokoro/linux/build_and_run_docker.sh b/kokoro/linux/build_and_run_docker.sh
deleted file mode 100755
index cdbd6e2..0000000
--- a/kokoro/linux/build_and_run_docker.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#!/bin/bash
-#
-# Builds docker image and runs a command under it.
-# This is a generic script that is configured with the following variables:
-#
-# DOCKERHUB_ORGANIZATION - The organization on docker hub storing the
-# Dockerfile.
-# DOCKERFILE_DIR - Directory in which Dockerfile file is located.
-# DOCKER_RUN_SCRIPT - Script to run under docker (relative to protobuf repo root)
-# OUTPUT_DIR - Directory that will be copied from inside docker after finishing.
-# $@ - Extra args to pass to docker run
-
-set -ex
-
-cd $(dirname $0)/../..
-git_root=$(pwd)
-cd -
-
-# Use image name based on Dockerfile sha1
-if [ -z "$DOCKERHUB_ORGANIZATION" ]
-then
-  DOCKERHUB_ORGANIZATION=grpctesting/protobuf
-  DOCKER_IMAGE_NAME=${DOCKERHUB_ORGANIZATION}_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
-else
-  # TODO(teboring): Remove this when all tests have been migrated to separate
-  # docker images.
-  DOCKERFILE_PREFIX=$(basename $DOCKERFILE_DIR)
-  DOCKER_IMAGE_NAME=${DOCKERHUB_ORGANIZATION}/${DOCKERFILE_PREFIX}_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
-fi
-
-# Pull dockerimage from Dockerhub. This sometimes fails intermittently, so we
-# keep trying until we succeed.
-until docker pull $DOCKER_IMAGE_NAME; do sleep 10; done
-
-# Ensure existence of ccache directory
-CCACHE_DIR=/tmp/protobuf-ccache
-mkdir -p $CCACHE_DIR
-
-# Choose random name for docker container
-CONTAINER_NAME="build_and_run_docker_$(uuidgen)"
-
-echo $git_root
-
-# Run command inside docker
-docker run \
-  "$@" \
-  -e CCACHE_DIR=$CCACHE_DIR \
-  -e KOKORO_BUILD_NUMBER=$KOKORO_BUILD_NUMBER \
-  -e KOKORO_BUILD_ID=$KOKORO_BUILD_ID \
-  -e EXTERNAL_GIT_ROOT="/var/local/kokoro/protobuf" \
-  -e TEST_SET="$TEST_SET" \
-  -v "$git_root:/var/local/kokoro/protobuf:ro" \
-  -v $CCACHE_DIR:$CCACHE_DIR \
-  -w /var/local/git/protobuf \
-  --name=$CONTAINER_NAME \
-  $DOCKER_IMAGE_NAME \
-  bash -l "/var/local/kokoro/protobuf/$DOCKER_RUN_SCRIPT" || FAILED="true"
-
-# remove the container, possibly killing it first
-docker rm -f $CONTAINER_NAME || true
-
-[ -z "$FAILED" ] || {
-  exit 1
-}
diff --git a/kokoro/linux/cmake/build.sh b/kokoro/linux/cmake/build.sh
new file mode 100755
index 0000000..ee06d95
--- /dev/null
+++ b/kokoro/linux/cmake/build.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# Build file to set up and run tests using CMake
+
+set -eux
+
+# Change to repo root
+cd $(dirname $0)/../../..
+GIT_REPO_ROOT=`pwd`
+
+CONTAINER_IMAGE=gcr.io/protobuf-build/cmake/linux@sha256:79e6ed9d7f3f8e56167a3309a521e5b7e6a212bfb19855c65ee1cbb6f9099671
+
+# Update git submodules
+git submodule update --init --recursive
+
+tmpfile=$(mktemp -u)
+
+docker run \
+  --cidfile $tmpfile \
+  -v $GIT_REPO_ROOT:/workspace \
+  $CONTAINER_IMAGE \
+  /test.sh -Dprotobuf_BUILD_CONFORMANCE=ON -Dprotobuf_BUILD_EXAMPLES=ON
+
+# Save logs for Kokoro
+docker cp \
+  `cat $tmpfile`:/workspace/logs $KOKORO_ARTIFACTS_DIR
diff --git a/kokoro/linux/cmake/common.cfg b/kokoro/linux/cmake/common.cfg
new file mode 100644
index 0000000..f03bd39
--- /dev/null
+++ b/kokoro/linux/cmake/common.cfg
@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cmake/build.sh"
+timeout_mins: 1440
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/cmake/continuous.cfg b/kokoro/linux/cmake/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cmake/presubmit.cfg b/kokoro/linux/cmake/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cmake_install/build.sh b/kokoro/linux/cmake_install/build.sh
new file mode 100755
index 0000000..7fdf267
--- /dev/null
+++ b/kokoro/linux/cmake_install/build.sh
@@ -0,0 +1,30 @@
+#!/bin/bash
+#
+# Build file to build, install, and test using CMake.
+
+set -eux
+
+# Change to repo root
+cd $(dirname $0)/../../..
+GIT_REPO_ROOT=`pwd`
+
+CONTAINER_IMAGE=gcr.io/protobuf-build/cmake/linux@sha256:79e6ed9d7f3f8e56167a3309a521e5b7e6a212bfb19855c65ee1cbb6f9099671
+
+# Update git submodules
+git submodule update --init --recursive
+
+tmpfile=$(mktemp -u)
+
+docker run \
+  --cidfile $tmpfile \
+  -v $GIT_REPO_ROOT:/workspace \
+  $CONTAINER_IMAGE \
+  "/install.sh && /test.sh \
+  -Dprotobuf_REMOVE_INSTALLED_HEADERS=ON \
+  -Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF \
+  -Dprotobuf_BUILD_CONFORMANCE=ON"
+
+
+# Save logs for Kokoro
+docker cp \
+  `cat $tmpfile`:/workspace/logs $KOKORO_ARTIFACTS_DIR
diff --git a/kokoro/linux/cmake_install/common.cfg b/kokoro/linux/cmake_install/common.cfg
new file mode 100644
index 0000000..f1ae0b3
--- /dev/null
+++ b/kokoro/linux/cmake_install/common.cfg
@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cmake_install/build.sh"
+timeout_mins: 1440
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/cmake_install/continuous.cfg b/kokoro/linux/cmake_install/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake_install/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cmake_install/presubmit.cfg b/kokoro/linux/cmake_install/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake_install/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cmake_ninja/build.sh b/kokoro/linux/cmake_ninja/build.sh
new file mode 100755
index 0000000..21cc01e
--- /dev/null
+++ b/kokoro/linux/cmake_ninja/build.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# Build file to set up and run tests using CMake with the Ninja generator.
+
+set -eux
+
+# Change to repo root
+cd $(dirname $0)/../../..
+GIT_REPO_ROOT=`pwd`
+
+CONTAINER_IMAGE=gcr.io/protobuf-build/cmake/linux@sha256:79e6ed9d7f3f8e56167a3309a521e5b7e6a212bfb19855c65ee1cbb6f9099671
+
+# Update git submodules
+git submodule update --init --recursive
+
+tmpfile=$(mktemp -u)
+
+docker run \
+  --cidfile $tmpfile \
+  -v $GIT_REPO_ROOT:/workspace \
+  $CONTAINER_IMAGE \
+  /test.sh -G Ninja -Dprotobuf_BUILD_CONFORMANCE=ON
+
+# Save logs for Kokoro
+docker cp \
+  `cat $tmpfile`:/workspace/logs $KOKORO_ARTIFACTS_DIR
diff --git a/kokoro/linux/cmake_ninja/common.cfg b/kokoro/linux/cmake_ninja/common.cfg
new file mode 100644
index 0000000..144fc90
--- /dev/null
+++ b/kokoro/linux/cmake_ninja/common.cfg
@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cmake_ninja/build.sh"
+timeout_mins: 1440
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/cmake_ninja/continuous.cfg b/kokoro/linux/cmake_ninja/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake_ninja/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cmake_ninja/presubmit.cfg b/kokoro/linux/cmake_ninja/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake_ninja/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cmake_shared/build.sh b/kokoro/linux/cmake_shared/build.sh
new file mode 100755
index 0000000..1fda3df
--- /dev/null
+++ b/kokoro/linux/cmake_shared/build.sh
@@ -0,0 +1,26 @@
+#!/bin/bash
+#
+# Build file to set up and run tests via CMake using shared libraries
+
+set -eux
+
+# Change to repo root
+cd $(dirname $0)/../../..
+GIT_REPO_ROOT=`pwd`
+
+CONTAINER_IMAGE=gcr.io/protobuf-build/cmake/linux@sha256:79e6ed9d7f3f8e56167a3309a521e5b7e6a212bfb19855c65ee1cbb6f9099671
+
+# Update git submodules
+git submodule update --init --recursive
+
+tmpfile=$(mktemp -u)
+
+docker run \
+  --cidfile $tmpfile \
+  -v $GIT_REPO_ROOT:/workspace \
+  $CONTAINER_IMAGE \
+  /test.sh -Dprotobuf_BUILD_CONFORMANCE=ON -Dprotobuf_BUILD_SHARED_LIBS=ON
+
+# Save logs for Kokoro
+docker cp \
+  `cat $tmpfile`:/workspace/logs $KOKORO_ARTIFACTS_DIR
diff --git a/kokoro/linux/cmake_shared/common.cfg b/kokoro/linux/cmake_shared/common.cfg
new file mode 100644
index 0000000..f03bd39
--- /dev/null
+++ b/kokoro/linux/cmake_shared/common.cfg
@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/cmake/build.sh"
+timeout_mins: 1440
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/cmake_shared/continuous.cfg b/kokoro/linux/cmake_shared/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake_shared/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cmake_shared/presubmit.cfg b/kokoro/linux/cmake_shared/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/linux/cmake_shared/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cpp_aarch64/build.sh b/kokoro/linux/cpp_aarch64/build.sh
deleted file mode 100755
index a43ab1c..0000000
--- a/kokoro/linux/cpp_aarch64/build.sh
+++ /dev/null
@@ -1,11 +0,0 @@
-#!/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/common.cfg b/kokoro/linux/cpp_aarch64/common.cfg
new file mode 100644
index 0000000..f77f73b
--- /dev/null
+++ b/kokoro/linux/cpp_aarch64/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/emulation/linux:aarch64-4e847d7a01c1792471b6dd985ab0bf2677332e6f"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//src/..."
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/cpp_aarch64/continuous.cfg b/kokoro/linux/cpp_aarch64/continuous.cfg
index 0f1be4a..8523c22 100644
--- a/kokoro/linux/cpp_aarch64/continuous.cfg
+++ b/kokoro/linux/cpp_aarch64/continuous.cfg
@@ -1,5 +1 @@
-# 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
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cpp_aarch64/presubmit.cfg b/kokoro/linux/cpp_aarch64/presubmit.cfg
index 0f1be4a..8523c22 100644
--- a/kokoro/linux/cpp_aarch64/presubmit.cfg
+++ b/kokoro/linux/cpp_aarch64/presubmit.cfg
@@ -1,5 +1 @@
-# 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
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cpp_distcheck/build.sh b/kokoro/linux/cpp_distcheck/build.sh
deleted file mode 100755
index a28843e..0000000
--- a/kokoro/linux/cpp_distcheck/build.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-#
-# Build file to set up and run tests
-
-set -ex  # exit immediately on error
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-./tests.sh cpp_distcheck
-
-# Run tests under release docker image.
-DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
-until docker pull $DOCKER_IMAGE_NAME; do sleep 10; done
-
-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/cpp_distcheck/continuous.cfg b/kokoro/linux/cpp_distcheck/continuous.cfg
deleted file mode 100644
index 4289f6a..0000000
--- a/kokoro/linux/cpp_distcheck/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/cpp_distcheck/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/linux/cpp_distcheck/presubmit.cfg b/kokoro/linux/cpp_distcheck/presubmit.cfg
deleted file mode 100644
index 4289f6a..0000000
--- a/kokoro/linux/cpp_distcheck/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/cpp_distcheck/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/linux/cpp_tcmalloc/build.sh b/kokoro/linux/cpp_tcmalloc/build.sh
deleted file mode 100755
index 3c77b11..0000000
--- a/kokoro/linux/cpp_tcmalloc/build.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-#
-# Build file to set up and run tests
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-export DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/cpp_tcmalloc
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="cpp_tcmalloc"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/cpp_tcmalloc/common.cfg b/kokoro/linux/cpp_tcmalloc/common.cfg
new file mode 100644
index 0000000..fb76204
--- /dev/null
+++ b/kokoro/linux/cpp_tcmalloc/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 1440
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/tcmalloc/linux:64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//src/..."
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/cpp_tcmalloc/continuous.cfg b/kokoro/linux/cpp_tcmalloc/continuous.cfg
index 46312a9..8523c22 100644
--- a/kokoro/linux/cpp_tcmalloc/continuous.cfg
+++ b/kokoro/linux/cpp_tcmalloc/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/cpp_tcmalloc/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/cpp_tcmalloc/presubmit.cfg b/kokoro/linux/cpp_tcmalloc/presubmit.cfg
index 46312a9..8523c22 100644
--- a/kokoro/linux/cpp_tcmalloc/presubmit.cfg
+++ b/kokoro/linux/cpp_tcmalloc/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/cpp_tcmalloc/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/csharp/build.sh b/kokoro/linux/csharp/build.sh
deleted file mode 100755
index 9a2eb48..0000000
--- a/kokoro/linux/csharp/build.sh
+++ /dev/null
@@ -1,18 +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 DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/csharp
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="csharp"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/csharp/common.cfg b/kokoro/linux/csharp/common.cfg
new file mode 100644
index 0000000..2332c00
--- /dev/null
+++ b/kokoro/linux/csharp/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 1440
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/csharp/linux:3.1.415-6.0.100-6bbe70439ba5b0404bb12662cebc0296909389fa"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//csharp/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--action_env=DOTNET_CLI_TELEMETRY_OPTOUT=1 "
+         "--test_env=DOTNET_CLI_HOME=/home/bazel"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/csharp/continuous.cfg b/kokoro/linux/csharp/continuous.cfg
index 3d17767..8523c22 100644
--- a/kokoro/linux/csharp/continuous.cfg
+++ b/kokoro/linux/csharp/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/csharp/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/csharp/presubmit.cfg b/kokoro/linux/csharp/presubmit.cfg
index 3d17767..8523c22 100644
--- a/kokoro/linux/csharp/presubmit.cfg
+++ b/kokoro/linux/csharp/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/csharp/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/benchmark/continuous.cfg b/kokoro/linux/csharp_aarch64/common.cfg
similarity index 66%
copy from kokoro/linux/benchmark/continuous.cfg
copy to kokoro/linux/csharp_aarch64/common.cfg
index 8cc8f96..df28ef3 100644
--- a/kokoro/linux/benchmark/continuous.cfg
+++ b/kokoro/linux/csharp_aarch64/common.cfg
@@ -1,8 +1,8 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/benchmark/build.sh"
-timeout_mins: 240
+build_file: "protobuf/kokoro/linux/csharp_aarch64/build.sh"
+timeout_mins: 120
 
 action {
   define_artifacts {
diff --git a/kokoro/linux/csharp_aarch64/continuous.cfg b/kokoro/linux/csharp_aarch64/continuous.cfg
index df28ef3..8523c22 100644
--- a/kokoro/linux/csharp_aarch64/continuous.cfg
+++ b/kokoro/linux/csharp_aarch64/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/csharp_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/csharp_aarch64/presubmit.cfg b/kokoro/linux/csharp_aarch64/presubmit.cfg
index df28ef3..8523c22 100644
--- a/kokoro/linux/csharp_aarch64/presubmit.cfg
+++ b/kokoro/linux/csharp_aarch64/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/csharp_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/dist_install/build.sh b/kokoro/linux/dist_install/build.sh
deleted file mode 100755
index c456ee8..0000000
--- a/kokoro/linux/dist_install/build.sh
+++ /dev/null
@@ -1,15 +0,0 @@
-#!/bin/bash
-#
-# Build file to set up and run tests
-
-set -ex  # exit immediately on error
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-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"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/dist_install/continuous.cfg b/kokoro/linux/dist_install/continuous.cfg
deleted file mode 100644
index b1e0b20..0000000
--- a/kokoro/linux/dist_install/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/dist_install/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/linux/dist_install/presubmit.cfg b/kokoro/linux/dist_install/presubmit.cfg
deleted file mode 100644
index b1e0b20..0000000
--- a/kokoro/linux/dist_install/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/dist_install/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/linux/dockerfile/push_testing_images.sh b/kokoro/linux/dockerfile/push_testing_images.sh
deleted file mode 100755
index 2d82bab..0000000
--- a/kokoro/linux/dockerfile/push_testing_images.sh
+++ /dev/null
@@ -1,29 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-cd $(dirname $0)/../../..
-git_root=$(pwd)
-cd kokoro/linux/dockerfile
-
-DOCKERHUB_ORGANIZATION=protobuftesting
-
-for DOCKERFILE_DIR in test/*
-do
-  # Generate image name based on Dockerfile checksum. That works well as long
-  # as can count on dockerfiles being written in a way that changing the logical
-  # contents of the docker image always changes the SHA (e.g. using "ADD file"
-  # cmd in the dockerfile in not ok as contents of the added file will not be
-  # reflected in the SHA).
-  DOCKER_IMAGE_NAME=$(basename $DOCKERFILE_DIR)_$(sha1sum $DOCKERFILE_DIR/Dockerfile | cut -f1 -d\ )
-
-  echo $DOCKER_IMAGE_NAME
-  # skip the image if it already exists in the repo
-  curl --silent -f -lSL https://registry.hub.docker.com/v2/repositories/${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}/tags/latest > /dev/null \
-      && continue
-
-  docker build -t ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME} ${DOCKERFILE_DIR}
-
-  # "docker login" needs to be run in advance
-  docker push ${DOCKERHUB_ORGANIZATION}/${DOCKER_IMAGE_NAME}
-done
diff --git a/kokoro/linux/dockerfile/test/cpp_tcmalloc/Dockerfile b/kokoro/linux/dockerfile/test/cpp_tcmalloc/Dockerfile
deleted file mode 100644
index 0ce9982..0000000
--- a/kokoro/linux/dockerfile/test/cpp_tcmalloc/Dockerfile
+++ /dev/null
@@ -1,29 +0,0 @@
-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 \
-  && apt-get clean
-
-# Install dependencies for TC malloc
-RUN apt-get install -y \
-  google-perftools \
-  libgoogle-perftools4 \
-  libgoogle-perftools-dev
diff --git a/kokoro/linux/dockerfile/test/csharp/Dockerfile b/kokoro/linux/dockerfile/test/csharp/Dockerfile
deleted file mode 100644
index c07fcbc..0000000
--- a/kokoro/linux/dockerfile/test/csharp/Dockerfile
+++ /dev/null
@@ -1,41 +0,0 @@
-FROM debian: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
-
-# 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 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 3.1.415 && \
-    ./dotnet-install.sh --version 6.0.100 && \
-    ln -s /root/.dotnet/dotnet /usr/local/bin
-
-RUN wget -q www.nuget.org/NuGet.exe -O /usr/local/bin/nuget.exe
-
-ENV DOTNET_SKIP_FIRST_TIME_EXPERIENCE true
diff --git a/kokoro/linux/dockerfile/test/java_stretch/Dockerfile b/kokoro/linux/dockerfile/test/java_stretch/Dockerfile
deleted file mode 100644
index 0716927..0000000
--- a/kokoro/linux/dockerfile/test/java_stretch/Dockerfile
+++ /dev/null
@@ -1,39 +0,0 @@
-# Despite the name of this image, we are no longer on stretch.
-# We should consider renaming this image, and/or evaluating what
-# software versions we actually need.
-FROM debian:bullseye
-
-# 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 \
-  autotools-dev \
-  build-essential \
-  bzip2 \
-  ccache \
-  cmake \
-  curl \
-  gcc \
-  git \
-  libc6 \
-  libc6-dbg \
-  libc6-dev \
-  libgtest-dev \
-  libtool \
-  make \
-  parallel \
-  pkg-config \
-  time \
-  wget \
-  # Java dependencies
-  maven \
-  openjdk-11-jdk \
-  openjdk-17-jdk \
-  # Required for the gtest build.
-  python2 \
-  # Python dependencies
-  python3-dev \
-  python3-setuptools \
-  python3-pip \
-  python3-venv \
-  && apt-get clean
diff --git a/kokoro/linux/dockerfile/test/php/Dockerfile b/kokoro/linux/dockerfile/test/php/Dockerfile
deleted file mode 100644
index 4c9d69d..0000000
--- a/kokoro/linux/dockerfile/test/php/Dockerfile
+++ /dev/null
@@ -1,255 +0,0 @@
-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 \
-  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 http://ftp.gnu.org/gnu/bison/bison-2.6.4.tar.gz -O /var/local/bison-2.6.4.tar.gz
-RUN cd /var/local \
-  && tar -zxvf bison-2.6.4.tar.gz \
-  && cd /var/local/bison-2.6.4 \
-  && ./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 5.6
-RUN cd php-src \
-  && git checkout PHP-5.6.39 \
-  && ./buildconf --force
-RUN cd php-src \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-5.6 \
-  && make \
-  && make install \
-  && make clean
-
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \
-  && chmod +x phpunit \
-  && 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 \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.0 \
-  && make \
-  && make install \
-  && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.0-zts \
-  && make \
-  && make install \
-  && make clean
-
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-6.phar \
-  && chmod +x phpunit \
-  && cp phpunit /usr/local/php-7.0/bin \
-  && 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 \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.1 \
-  && make \
-  && make install \
-  && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.1-zts \
-  && make \
-  && make install \
-  && make clean
-
-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 \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.2 \
-  && make \
-  && make install \
-  && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.2-zts \
-  && make \
-  && make install \
-  && make clean
-
-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 \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.3 \
-  && make \
-  && make install \
-  && make clean
-RUN cd php-src \
-  && ./configure \
-  --enable-maintainer-zts \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.3-zts \
-  && make \
-  && make install \
-  && make clean
-
-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
-
-# php 7.4
-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
-
-RUN wget https://github.com/php/php-src/archive/php-7.4.0.tar.gz -O /var/local/php-7.4.0.tar.gz
-
-RUN cd /var/local \
-  && tar -zxvf php-7.4.0.tar.gz
-
-RUN cd /var/local/php-src-php-7.4.0 \
-  && ./buildconf --force \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --disable-mbregex \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.4 \
-  && make \
-  && make install \
-  && make clean
-RUN cd /var/local/php-src-php-7.4.0 \
-  && ./buildconf --force \
-  && ./configure \
-  --enable-maintainer-zts \
-  --enable-mbstring \
-  --disable-mbregex \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.4-zts \
-  && make \
-  && make install \
-  && make clean
-
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-8.phar \
-  && chmod +x phpunit \
-  && cp phpunit /usr/local/php-7.4/bin \
-  && mv phpunit /usr/local/php-7.4-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/php80/Dockerfile b/kokoro/linux/dockerfile/test/php80/Dockerfile
deleted file mode 100644
index 5b382d0..0000000
--- a/kokoro/linux/dockerfile/test/php80/Dockerfile
+++ /dev/null
@@ -1,124 +0,0 @@
-FROM debian:stretch
-
-# 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 \
-  php \
-  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
-
-# php 8.1
-RUN cd php-src \
-  && git checkout php-8.1.2 \
-  && ./buildconf --force
-RUN cd php-src \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --with-gmp \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-8.1 \
-  && 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.1-zts \
-  && make \
-  && make install \
-  && make clean
-
-# 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
deleted file mode 100644
index 2fd620e..0000000
--- a/kokoro/linux/dockerfile/test/php_32bit/Dockerfile
+++ /dev/null
@@ -1,260 +0,0 @@
-FROM i386/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 \
-  libsqlite3-dev \
-  && apt-get clean
-
-# Install php dependencies
-RUN apt-get clean && apt-get update && apt-get install -y --force-yes \
-  bison \
-  php5 \
-  libcurl4-openssl-dev \
-  libssl-dev \
-  libxml2-dev \
-  unzip \
-  zlib1g-dev \
-  pkg-config \
-  && apt-get clean
-
-# Install other dependencies
-RUN wget http://ftp.gnu.org/gnu/bison/bison-2.6.4.tar.gz -O /var/local/bison-2.6.4.tar.gz
-RUN cd /var/local \
-  && tar -zxvf bison-2.6.4.tar.gz \
-  && cd /var/local/bison-2.6.4 \
-  && ./configure \
-  && make \
-  && make install
-
-# Install composer
-RUN php -r "copy('https://getcomposer.org/installer', 'composer-setup.php');"
-RUN php composer-setup.php
-RUN mv composer.phar /usr/bin/composer
-RUN php -r "unlink('composer-setup.php');"
-
-# Download php source code
-RUN git clone https://github.com/php/php-src
-
-# php 5.6
-RUN cd php-src \
-  && git checkout PHP-5.6.39 \
-  && ./buildconf --force
-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 wget -O phpunit https://phar.phpunit.de/phpunit-5.phar \
-  && chmod +x phpunit \
-  && mv phpunit /usr/local/php-5.6/bin
-
-# php 7.0
-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 /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 \
-  && make \
-  && make install \
-  && make clean
-
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-6.phar \
-  && chmod +x phpunit \
-  && cp phpunit /usr/local/php-7.0/bin \
-  && mv phpunit /usr/local/php-7.0-zts/bin
-
-# php 7.1
-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 /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 \
-  && make \
-  && make install \
-  && make clean
-
-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 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 /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 \
-  && make \
-  && make install \
-  && make clean
-
-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 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 /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 \
-  && make \
-  && make install \
-  && make clean
-
-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
-
-# php 7.4
-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
-
-RUN wget https://github.com/php/php-src/archive/php-7.4.0.tar.gz -O /var/local/php-7.4.0.tar.gz
-
-RUN cd /var/local \
-  && tar -zxvf php-7.4.0.tar.gz
-
-RUN cd /var/local/php-src-php-7.4.0 \
-  && ./buildconf --force \
-  && ./configure \
-  --enable-bcmath \
-  --enable-mbstring \
-  --disable-mbregex \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.4 \
-  && make \
-  && make install \
-  && make clean
-RUN cd /var/local/php-src-php-7.4.0 \
-  && ./buildconf --force \
-  && ./configure \
-  --enable-maintainer-zts \
-  --enable-mbstring \
-  --disable-mbregex \
-  --with-openssl \
-  --with-zlib \
-  --prefix=/usr/local/php-7.4-zts \
-  && make \
-  && make install \
-  && make clean
-
-RUN wget -O phpunit https://phar.phpunit.de/phpunit-8.phar \
-  && chmod +x phpunit \
-  && cp phpunit /usr/local/php-7.4/bin \
-  && mv phpunit /usr/local/php-7.4-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/python310/Dockerfile b/kokoro/linux/dockerfile/test/python310/Dockerfile
deleted file mode 100644
index e16e93b..0000000
--- a/kokoro/linux/dockerfile/test/python310/Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-FROM python:3.10-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/python37/Dockerfile b/kokoro/linux/dockerfile/test/python37/Dockerfile
deleted file mode 100644
index ee108dd..0000000
--- a/kokoro/linux/dockerfile/test/python37/Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-FROM python:3.7-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/python38/Dockerfile b/kokoro/linux/dockerfile/test/python38/Dockerfile
deleted file mode 100644
index 56efc9d..0000000
--- a/kokoro/linux/dockerfile/test/python38/Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-FROM python:3.8-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/python39/Dockerfile b/kokoro/linux/dockerfile/test/python39/Dockerfile
deleted file mode 100644
index ee7554d..0000000
--- a/kokoro/linux/dockerfile/test/python39/Dockerfile
+++ /dev/null
@@ -1,31 +0,0 @@
-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
deleted file mode 100644
index 0e34fe5..0000000
--- a/kokoro/linux/dockerfile/test/ruby/Dockerfile
+++ /dev/null
@@ -1,44 +0,0 @@
-FROM debian:stretch
-
-# 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 \
-  # Java dependencies
-  maven \
-  openjdk-8-jdk \
-  && apt-get clean
-
-# Install rvm
-RUN gpg --keyserver hkp://keyserver.ubuntu.com --recv-keys \
-    409B6B1796C275462A1703113804BB82D39DC0E3 \
-    7D2BAF1CF37B13E2069D6956105BD0E739499BDB
-RUN \curl -sSL https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer | bash -s master
-
-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 "rvm install 3.1.0"
-RUN /bin/bash -l -c "rvm install jruby-9.2.20.1"
-RUN /bin/bash -l -c "rvm install jruby-9.3.3.0"
-RUN /bin/bash -l -c "rvm install jruby-9.3.4.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
deleted file mode 100755
index ed5ad53..0000000
--- a/kokoro/linux/java_aarch64/build.sh
+++ /dev/null
@@ -1,16 +0,0 @@
-#!/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/java_aarch64/common.cfg b/kokoro/linux/java_aarch64/common.cfg
new file mode 100644
index 0000000..75e3f0b
--- /dev/null
+++ b/kokoro/linux/java_aarch64/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/emulation/linux:aarch64-4e847d7a01c1792471b6dd985ab0bf2677332e6f"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//java/..."
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/java_aarch64/continuous.cfg b/kokoro/linux/java_aarch64/continuous.cfg
index 5db46d4..8523c22 100644
--- a/kokoro/linux/java_aarch64/continuous.cfg
+++ b/kokoro/linux/java_aarch64/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/java_aarch64/presubmit.cfg b/kokoro/linux/java_aarch64/presubmit.cfg
index 5db46d4..8523c22 100644
--- a/kokoro/linux/java_aarch64/presubmit.cfg
+++ b/kokoro/linux/java_aarch64/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/java_jdk11/build.sh b/kokoro/linux/java_jdk11/build.sh
deleted file mode 100755
index d73aa7c..0000000
--- a/kokoro/linux/java_jdk11/build.sh
+++ /dev/null
@@ -1,22 +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.
-
-# fail on error
-set -e
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-export DOCKERHUB_ORGANIZATION=protobuftesting
-# The image of the Dockerfile sha1 is fetched from the organization
-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="java_jdk11"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/java_jdk11/common.cfg b/kokoro/linux/java_jdk11/common.cfg
new file mode 100644
index 0000000..3db5cd0
--- /dev/null
+++ b/kokoro/linux/java_jdk11/common.cfg
@@ -0,0 +1,16 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//java/..."
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/java_jdk11/continuous.cfg b/kokoro/linux/java_jdk11/continuous.cfg
index f8af54d..8523c22 100644
--- a/kokoro/linux/java_jdk11/continuous.cfg
+++ b/kokoro/linux/java_jdk11/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_jdk11/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/java_jdk11/presubmit.cfg b/kokoro/linux/java_jdk11/presubmit.cfg
index 366048c..8523c22 100644
--- a/kokoro/linux/java_jdk11/presubmit.cfg
+++ b/kokoro/linux/java_jdk11/presubmit.cfg
@@ -1,12 +1 @@
-# Config file for running Linkage Monitor in Kokoro
-# https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_jdk11/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/java_jdk17/build.sh b/kokoro/linux/java_jdk17/build.sh
deleted file mode 100755
index 677245a..0000000
--- a/kokoro/linux/java_jdk17/build.sh
+++ /dev/null
@@ -1,22 +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.
-
-# Fail on error
-set -e
-
-# Change to repo root
-cd $(dirname $0)/../../..
-
-export DOCKERHUB_ORGANIZATION=protobuftesting
-# The image of the Dockerfile sha1 is fetched from the organization
-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="java_jdk17"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/java_jdk17/common.cfg b/kokoro/linux/java_jdk17/common.cfg
new file mode 100644
index 0000000..cd31eda
--- /dev/null
+++ b/kokoro/linux/java_jdk17/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/java/linux:17-64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//java/..."
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/java_jdk17/continuous.cfg b/kokoro/linux/java_jdk17/continuous.cfg
index 6bac25c..8523c22 100644
--- a/kokoro/linux/java_jdk17/continuous.cfg
+++ b/kokoro/linux/java_jdk17/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_jdk17/build.sh"
-timeout_mins: 60
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/java_jdk17/presubmit.cfg b/kokoro/linux/java_jdk17/presubmit.cfg
index ee80517..8523c22 100644
--- a/kokoro/linux/java_jdk17/presubmit.cfg
+++ b/kokoro/linux/java_jdk17/presubmit.cfg
@@ -1,12 +1 @@
-# Config file for running Linkage Monitor in Kokoro
-# https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_jdk17/build.sh"
-timeout_mins: 60
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/java_linkage_monitor/build.sh b/kokoro/linux/java_linkage_monitor/build.sh
index c447453..de98697 100755
--- a/kokoro/linux/java_linkage_monitor/build.sh
+++ b/kokoro/linux/java_linkage_monitor/build.sh
@@ -4,16 +4,26 @@
 # 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.
+# a script to run inside that image.
+
+set -eux
+
+use_bazel.sh 4.2.2
 
 # Change to repo root
 cd $(dirname $0)/../../..
 
-export DOCKERHUB_ORGANIZATION=protobuftesting
-# The image of the Dockerfile sha1 is fetched from the organization
-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="java_linkage_monitor"
-./kokoro/linux/build_and_run_docker.sh
+bazel build //:protoc
+
+# The java build setup expects protoc in the root directory.
+cp bazel-bin/protoc .
+
+cd java
+# Installs the snapshot version locally
+mvn -e -B -Dhttps.protocols=TLSv1.2 install -Dmaven.test.skip=true
+
+# Linkage Monitor uses the snapshot versions installed in $HOME/.m2 to verify compatibility
+JAR=linkage-monitor-latest-all-deps.jar
+curl -v -O "https://storage.googleapis.com/cloud-opensource-java-linkage-monitor/${JAR}"
+# Fails if there's new linkage errors compared with baseline
+java -jar $JAR com.google.cloud:libraries-bom
diff --git a/kokoro/linux/java_linkage_monitor/common.cfg b/kokoro/linux/java_linkage_monitor/common.cfg
new file mode 100644
index 0000000..c02a52f
--- /dev/null
+++ b/kokoro/linux/java_linkage_monitor/common.cfg
@@ -0,0 +1,12 @@
+# Config file for running Linkage Monitor in Kokoro
+# https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/java_linkage_monitor/build.sh"
+timeout_mins: 120
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.xml"
+  }
+}
diff --git a/kokoro/linux/java_linkage_monitor/continuous.cfg b/kokoro/linux/java_linkage_monitor/continuous.cfg
index d0486cc..8523c22 100644
--- a/kokoro/linux/java_linkage_monitor/continuous.cfg
+++ b/kokoro/linux/java_linkage_monitor/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_linkage_monitor/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/java_linkage_monitor/presubmit.cfg b/kokoro/linux/java_linkage_monitor/presubmit.cfg
index c02a52f..8523c22 100644
--- a/kokoro/linux/java_linkage_monitor/presubmit.cfg
+++ b/kokoro/linux/java_linkage_monitor/presubmit.cfg
@@ -1,12 +1 @@
-# Config file for running Linkage Monitor in Kokoro
-# https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/java_linkage_monitor/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/jruby92/build.sh b/kokoro/linux/jruby92/build.sh
deleted file mode 100755
index 5820115..0000000
--- a/kokoro/linux/jruby92/build.sh
+++ /dev/null
@@ -1,18 +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 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="jruby92"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/jruby92/common.cfg b/kokoro/linux/jruby92/common.cfg
new file mode 100644
index 0000000..9db8f50
--- /dev/null
+++ b/kokoro/linux/jruby92/common.cfg
@@ -0,0 +1,26 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/ruby/linux:jruby-9.2.20.1-64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//ruby/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=ruby_platform=java"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/jruby92/continuous.cfg b/kokoro/linux/jruby92/continuous.cfg
index 3339584..8523c22 100644
--- a/kokoro/linux/jruby92/continuous.cfg
+++ b/kokoro/linux/jruby92/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/jruby92/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/jruby92/presubmit.cfg b/kokoro/linux/jruby92/presubmit.cfg
index 3339584..8523c22 100644
--- a/kokoro/linux/jruby92/presubmit.cfg
+++ b/kokoro/linux/jruby92/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/jruby92/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/jruby93/build.sh b/kokoro/linux/jruby93/build.sh
deleted file mode 100755
index 24c54d0..0000000
--- a/kokoro/linux/jruby93/build.sh
+++ /dev/null
@@ -1,18 +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 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="jruby93"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/jruby93/common.cfg b/kokoro/linux/jruby93/common.cfg
new file mode 100644
index 0000000..a5a9bd2
--- /dev/null
+++ b/kokoro/linux/jruby93/common.cfg
@@ -0,0 +1,26 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/ruby/linux:jruby-9.3.4.0-64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//ruby/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=ruby_platform=java"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/jruby93/continuous.cfg b/kokoro/linux/jruby93/continuous.cfg
index 706d848..8523c22 100644
--- a/kokoro/linux/jruby93/continuous.cfg
+++ b/kokoro/linux/jruby93/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/jruby93/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/jruby93/presubmit.cfg b/kokoro/linux/jruby93/presubmit.cfg
index 706d848..8523c22 100644
--- a/kokoro/linux/jruby93/presubmit.cfg
+++ b/kokoro/linux/jruby93/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/jruby93/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/make_test_output.py b/kokoro/linux/make_test_output.py
deleted file mode 100644
index 9853685..0000000
--- a/kokoro/linux/make_test_output.py
+++ /dev/null
@@ -1,94 +0,0 @@
-"""Gathers output from test runs and create an XML file in JUnit format.
-
-The output files from the individual tests have been written in a directory
-structure like:
-
-  $DIR/joblog  (output from "parallel --joblog joblog")
-  $DIR/logs/1/cpp/stdout
-  $DIR/logs/1/cpp/stderr
-  $DIR/logs/1/csharp/stdout
-  $DIR/logs/1/csharp/stderr
-  $DIR/logs/1/java_jdk7/stdout
-  $DIR/logs/1/java_jdk7/stderr
-  etc.
-
-This script bundles them into a single output XML file so Jenkins can show
-detailed test results.  It runs as the last step before the Jenkins build
-finishes.
-"""
-
-import os
-import sys
-from yattag import Doc
-from collections import defaultdict
-
-
-def readtests(basedir):
-  tests = defaultdict(dict)
-
-  # Sample input (note: separators are tabs).
-  #
-  # Seq	Host	Starttime	Runtime	Send	Receive	Exitval	Signal	Command
-  # 1	:	1456263838.313	0.005	0	0	0	0	echo A
-  with open(basedir + "/joblog") as jobs:
-    firstline = next(jobs)
-    for line in jobs:
-      values = line.split("\t")
-
-      name = values[8].split()[-1]
-      test = tests[name]
-      test["name"] = name
-      test["time"] = values[3]
-
-      exitval = values[6]
-      if int(exitval):
-        # We don't have a more specific message.  User should look at stderr.
-        test["failure"] = "TEST FAILURE"
-      else:
-        test["failure"] = False
-
-  for testname in os.listdir(basedir + "/logs/1"):
-    test = tests[testname]
-
-    with open(basedir + "/logs/1/" + testname + "/stdout") as f:
-      test["stdout"] = f.read()
-
-    with open(basedir + "/logs/1/" + testname + "/stderr") as f:
-      test["stderr"] = f.read()
-
-  # The cpp test is special since it doesn't run under parallel so doesn't show
-  # up in the job log.
-  tests["cpp"]["name"] = "cpp"
-
-  with open(basedir + '/logs/1/cpp/build_time', 'r') as f:
-    tests["cpp"]["time"] = f.read().strip()
-  tests["cpp"]["failure"] = False
-
-  ret = tests.values()
-  ret.sort(key=lambda x: x["name"])
-
-  return ret
-
-
-def genxml(tests):
-  doc, tag, text = Doc().tagtext()
-
-  with tag("testsuites"):
-    with tag("testsuite", name="Protobuf Tests"):
-      for test in tests:
-        with tag("testcase", name=test["name"], classname=test["name"],
-                             time=test["time"]):
-          with tag("system-out"):
-            text(test["stdout"])
-          with tag("system-err"):
-            text(test["stderr"])
-          if test["failure"]:
-            with tag("failure"):
-              text(test["failure"])
-
-  return doc.getvalue()
-
-
-sys.stderr.write("make_test_output.py: writing XML from directory: " +
-                 sys.argv[1] + "\n")
-print(genxml(readtests(sys.argv[1])))
diff --git a/kokoro/linux/benchmark/continuous.cfg b/kokoro/linux/php_aarch64/common.cfg
similarity index 67%
copy from kokoro/linux/benchmark/continuous.cfg
copy to kokoro/linux/php_aarch64/common.cfg
index 8cc8f96..ff20682 100644
--- a/kokoro/linux/benchmark/continuous.cfg
+++ b/kokoro/linux/php_aarch64/common.cfg
@@ -1,8 +1,8 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/benchmark/build.sh"
-timeout_mins: 240
+build_file: "protobuf/kokoro/linux/php_aarch64/build.sh"
+timeout_mins: 120
 
 action {
   define_artifacts {
diff --git a/kokoro/linux/php_aarch64/continuous.cfg b/kokoro/linux/php_aarch64/continuous.cfg
index ff20682..8523c22 100644
--- a/kokoro/linux/php_aarch64/continuous.cfg
+++ b/kokoro/linux/php_aarch64/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/php_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/php_aarch64/presubmit.cfg b/kokoro/linux/php_aarch64/presubmit.cfg
index ff20682..8523c22 100644
--- a/kokoro/linux/php_aarch64/presubmit.cfg
+++ b/kokoro/linux/php_aarch64/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/php_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/php_all/build.sh b/kokoro/linux/php_all/build.sh
index cfcab00..bfad04c 100755
--- a/kokoro/linux/php_all/build.sh
+++ b/kokoro/linux/php_all/build.sh
@@ -8,16 +8,16 @@
 # Change to repo base.
 cd $(dirname $0)/../../..
 
-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:8.0.5-dbg-fd99596d4c4c9b78f984ee667a9b26b91a28eb8d "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"
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:7.0.33-dbg-fd99596d4c4c9b78f984ee667a9b26b91a28eb8d "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-fd99596d4c4c9b78f984ee667a9b26b91a28eb8d "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-fd99596d4c4c9b78f984ee667a9b26b91a28eb8d "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-fd99596d4c4c9b78f984ee667a9b26b91a28eb8d "composer test && composer test_c"
 
 # Run specialized memory leak & multirequest tests.
-docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:8.0.5-dbg-14a06550010c0649bf69b6c9b803c1ca609bbb6d "composer test_c && tests/multirequest.sh && tests/memory_leak_test.sh"
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:8.0.5-dbg-fd99596d4c4c9b78f984ee667a9b26b91a28eb8d "composer test_c && tests/multirequest.sh && tests/memory_leak_test.sh"
 
 # 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"
+docker run $(test -t 0 && echo "-it") -v$PWD:/workspace gcr.io/protobuf-build/php/linux:8.0.5-fd99596d4c4c9b78f984ee667a9b26b91a28eb8d "composer test && composer test_c"
diff --git a/kokoro/linux/benchmark/continuous.cfg b/kokoro/linux/php_all/common.cfg
similarity index 67%
copy from kokoro/linux/benchmark/continuous.cfg
copy to kokoro/linux/php_all/common.cfg
index 8cc8f96..dfa8037 100644
--- a/kokoro/linux/benchmark/continuous.cfg
+++ b/kokoro/linux/php_all/common.cfg
@@ -1,8 +1,8 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/benchmark/build.sh"
-timeout_mins: 240
+build_file: "protobuf/kokoro/linux/php_all/build.sh"
+timeout_mins: 120
 
 action {
   define_artifacts {
diff --git a/kokoro/linux/php_all/continuous.cfg b/kokoro/linux/php_all/continuous.cfg
index dfa8037..8523c22 100644
--- a/kokoro/linux/php_all/continuous.cfg
+++ b/kokoro/linux/php_all/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/php_all/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/php_all/presubmit.cfg b/kokoro/linux/php_all/presubmit.cfg
index dfa8037..8523c22 100644
--- a/kokoro/linux/php_all/presubmit.cfg
+++ b/kokoro/linux/php_all/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/php_all/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/pull_request_in_docker.sh b/kokoro/linux/pull_request_in_docker.sh
deleted file mode 100755
index a048c47..0000000
--- a/kokoro/linux/pull_request_in_docker.sh
+++ /dev/null
@@ -1,25 +0,0 @@
-#!/bin/bash
-#
-# This is the script that runs inside Docker, once the image has been built,
-# to execute all tests for the "pull request" project.
-
-WORKSPACE_BASE=`pwd`
-MY_DIR="$(dirname "$0")"
-TEST_SCRIPT=./tests.sh
-BUILD_DIR=/tmp/protobuf
-
-set -e  # exit immediately on error
-set -x  # display all commands
-
-# The protobuf repository is mounted into our Docker image, but read-only.
-# We clone into a directory inside Docker (this is faster than cp).
-rm -rf $BUILD_DIR
-mkdir -p $BUILD_DIR
-cd $BUILD_DIR
-git clone /var/local/kokoro/protobuf
-cd protobuf
-
-# Initialize any submodules:
-git submodule update --init --recursive
-
-$TEST_SCRIPT $TEST_SET
diff --git a/kokoro/linux/python310/build.sh b/kokoro/linux/python310/build.sh
deleted file mode 100755
index 0d8a2c9..0000000
--- a/kokoro/linux/python310/build.sh
+++ /dev/null
@@ -1,18 +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 DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python310
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="python310"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python310/common.cfg b/kokoro/linux/python310/common.cfg
new file mode 100644
index 0000000..a6fd200
--- /dev/null
+++ b/kokoro/linux/python310/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.10-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//python/... @upb//python/... //python:python_version"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python310/continuous.cfg b/kokoro/linux/python310/continuous.cfg
index 6ec74d8..8523c22 100644
--- a/kokoro/linux/python310/continuous.cfg
+++ b/kokoro/linux/python310/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python310/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python310/presubmit.cfg b/kokoro/linux/python310/presubmit.cfg
index 6ec74d8..8523c22 100644
--- a/kokoro/linux/python310/presubmit.cfg
+++ b/kokoro/linux/python310/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python310/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python310_cpp/build.sh b/kokoro/linux/python310_cpp/build.sh
deleted file mode 100755
index 2903a2d..0000000
--- a/kokoro/linux/python310_cpp/build.sh
+++ /dev/null
@@ -1,18 +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 DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python310
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="python310_cpp"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python310_cpp/common.cfg b/kokoro/linux/python310_cpp/common.cfg
new file mode 100644
index 0000000..d186163
--- /dev/null
+++ b/kokoro/linux/python310_cpp/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.10-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  # Note: upb tests don't work since the C++ extension takes precedence here.
+  value: "//python/... //python:python_version"
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=use_fast_cpp_protos=true"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python310_cpp/continuous.cfg b/kokoro/linux/python310_cpp/continuous.cfg
index 7ec8441..8523c22 100644
--- a/kokoro/linux/python310_cpp/continuous.cfg
+++ b/kokoro/linux/python310_cpp/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python310_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python310_cpp/presubmit.cfg b/kokoro/linux/python310_cpp/presubmit.cfg
index 7ec8441..8523c22 100644
--- a/kokoro/linux/python310_cpp/presubmit.cfg
+++ b/kokoro/linux/python310_cpp/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python310_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python37/build.sh b/kokoro/linux/python37/build.sh
deleted file mode 100755
index 2117a27..0000000
--- a/kokoro/linux/python37/build.sh
+++ /dev/null
@@ -1,18 +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 DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="python37"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python37/common.cfg b/kokoro/linux/python37/common.cfg
new file mode 100644
index 0000000..101bce4
--- /dev/null
+++ b/kokoro/linux/python37/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.7-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//python/... @upb//python/... //python:python_version"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python37/continuous.cfg b/kokoro/linux/python37/continuous.cfg
index 9fa20c1..8523c22 100644
--- a/kokoro/linux/python37/continuous.cfg
+++ b/kokoro/linux/python37/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python37/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python37/presubmit.cfg b/kokoro/linux/python37/presubmit.cfg
index 9fa20c1..8523c22 100644
--- a/kokoro/linux/python37/presubmit.cfg
+++ b/kokoro/linux/python37/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python37/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python37_cpp/build.sh b/kokoro/linux/python37_cpp/build.sh
deleted file mode 100755
index 3126b48..0000000
--- a/kokoro/linux/python37_cpp/build.sh
+++ /dev/null
@@ -1,18 +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 DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python37
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="python37_cpp"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python37_cpp/common.cfg b/kokoro/linux/python37_cpp/common.cfg
new file mode 100644
index 0000000..d35be20
--- /dev/null
+++ b/kokoro/linux/python37_cpp/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.7-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  # Note: upb tests don't work since the C++ extension takes precedence here.
+  value: "//python/... //python:python_version"
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=use_fast_cpp_protos=true"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python37_cpp/continuous.cfg b/kokoro/linux/python37_cpp/continuous.cfg
index 49c441f..8523c22 100644
--- a/kokoro/linux/python37_cpp/continuous.cfg
+++ b/kokoro/linux/python37_cpp/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python37_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python37_cpp/presubmit.cfg b/kokoro/linux/python37_cpp/presubmit.cfg
index 49c441f..8523c22 100644
--- a/kokoro/linux/python37_cpp/presubmit.cfg
+++ b/kokoro/linux/python37_cpp/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python37_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python38/build.sh b/kokoro/linux/python38/build.sh
deleted file mode 100755
index 299c7ba..0000000
--- a/kokoro/linux/python38/build.sh
+++ /dev/null
@@ -1,18 +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 DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="python38"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python38/common.cfg b/kokoro/linux/python38/common.cfg
new file mode 100644
index 0000000..ee15892
--- /dev/null
+++ b/kokoro/linux/python38/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.8-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//python/... @upb//python/... //python:python_version"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python38/continuous.cfg b/kokoro/linux/python38/continuous.cfg
index 76425d2..8523c22 100644
--- a/kokoro/linux/python38/continuous.cfg
+++ b/kokoro/linux/python38/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python38/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python38/presubmit.cfg b/kokoro/linux/python38/presubmit.cfg
index 76425d2..8523c22 100644
--- a/kokoro/linux/python38/presubmit.cfg
+++ b/kokoro/linux/python38/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python38/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python38_cpp/build.sh b/kokoro/linux/python38_cpp/build.sh
deleted file mode 100755
index b43859b..0000000
--- a/kokoro/linux/python38_cpp/build.sh
+++ /dev/null
@@ -1,18 +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 DOCKERHUB_ORGANIZATION=protobuftesting
-export DOCKERFILE_DIR=kokoro/linux/dockerfile/test/python38
-export DOCKER_RUN_SCRIPT=kokoro/linux/pull_request_in_docker.sh
-export OUTPUT_DIR=testoutput
-export TEST_SET="python38_cpp"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python38_cpp/common.cfg b/kokoro/linux/python38_cpp/common.cfg
new file mode 100644
index 0000000..f641b8c
--- /dev/null
+++ b/kokoro/linux/python38_cpp/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.8-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  # Note: upb tests don't work since the C++ extension takes precedence here.
+  value: "//python/... //python:python_version"
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=use_fast_cpp_protos=true"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python38_cpp/continuous.cfg b/kokoro/linux/python38_cpp/continuous.cfg
index 1e8888c..8523c22 100644
--- a/kokoro/linux/python38_cpp/continuous.cfg
+++ b/kokoro/linux/python38_cpp/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python38_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python38_cpp/presubmit.cfg b/kokoro/linux/python38_cpp/presubmit.cfg
index 1e8888c..8523c22 100644
--- a/kokoro/linux/python38_cpp/presubmit.cfg
+++ b/kokoro/linux/python38_cpp/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python38_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python39/build.sh b/kokoro/linux/python39/build.sh
deleted file mode 100755
index 497dc66..0000000
--- a/kokoro/linux/python39/build.sh
+++ /dev/null
@@ -1,18 +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 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="python39"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python39/common.cfg b/kokoro/linux/python39/common.cfg
new file mode 100644
index 0000000..af53e38
--- /dev/null
+++ b/kokoro/linux/python39/common.cfg
@@ -0,0 +1,21 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.9-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//python/... @upb//python/... //python:python_version"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python39/continuous.cfg b/kokoro/linux/python39/continuous.cfg
index b03bc90..8523c22 100644
--- a/kokoro/linux/python39/continuous.cfg
+++ b/kokoro/linux/python39/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python39/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python39/presubmit.cfg b/kokoro/linux/python39/presubmit.cfg
index b03bc90..8523c22 100644
--- a/kokoro/linux/python39/presubmit.cfg
+++ b/kokoro/linux/python39/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python39/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python39_cpp/build.sh b/kokoro/linux/python39_cpp/build.sh
deleted file mode 100755
index f45d2ec..0000000
--- a/kokoro/linux/python39_cpp/build.sh
+++ /dev/null
@@ -1,18 +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 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="python39_cpp"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/python39_cpp/common.cfg b/kokoro/linux/python39_cpp/common.cfg
new file mode 100644
index 0000000..e039310
--- /dev/null
+++ b/kokoro/linux/python39_cpp/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/python/linux:3.9-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  # Note: upb tests don't work since the C++ extension takes precedence here.
+  value: "//python/... //python:python_version"
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=use_fast_cpp_protos=true"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/python39_cpp/continuous.cfg b/kokoro/linux/python39_cpp/continuous.cfg
index dd84fbe..8523c22 100644
--- a/kokoro/linux/python39_cpp/continuous.cfg
+++ b/kokoro/linux/python39_cpp/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python39_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python39_cpp/presubmit.cfg b/kokoro/linux/python39_cpp/presubmit.cfg
index dd84fbe..8523c22 100644
--- a/kokoro/linux/python39_cpp/presubmit.cfg
+++ b/kokoro/linux/python39_cpp/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python39_cpp/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/benchmark/continuous.cfg b/kokoro/linux/python_aarch64/common.cfg
similarity index 66%
copy from kokoro/linux/benchmark/continuous.cfg
copy to kokoro/linux/python_aarch64/common.cfg
index 8cc8f96..dee4a47 100644
--- a/kokoro/linux/benchmark/continuous.cfg
+++ b/kokoro/linux/python_aarch64/common.cfg
@@ -1,8 +1,8 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/benchmark/build.sh"
-timeout_mins: 240
+build_file: "protobuf/kokoro/linux/python_aarch64/build.sh"
+timeout_mins: 120
 
 action {
   define_artifacts {
diff --git a/kokoro/linux/python_aarch64/continuous.cfg b/kokoro/linux/python_aarch64/continuous.cfg
index dee4a47..8523c22 100644
--- a/kokoro/linux/python_aarch64/continuous.cfg
+++ b/kokoro/linux/python_aarch64/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/python_aarch64/presubmit.cfg b/kokoro/linux/python_aarch64/presubmit.cfg
index dee4a47..8523c22 100644
--- a/kokoro/linux/python_aarch64/presubmit.cfg
+++ b/kokoro/linux/python_aarch64/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/python_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby25/build.sh b/kokoro/linux/ruby25/build.sh
deleted file mode 100755
index 1e82ec5..0000000
--- a/kokoro/linux/ruby25/build.sh
+++ /dev/null
@@ -1,18 +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 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="ruby25"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/ruby25/common.cfg b/kokoro/linux/ruby25/common.cfg
new file mode 100644
index 0000000..ec975cd
--- /dev/null
+++ b/kokoro/linux/ruby25/common.cfg
@@ -0,0 +1,26 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/ruby/linux:ruby-2.5.1-64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//ruby/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=ruby_platform=c"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/ruby25/continuous.cfg b/kokoro/linux/ruby25/continuous.cfg
index dee2db0..8523c22 100644
--- a/kokoro/linux/ruby25/continuous.cfg
+++ b/kokoro/linux/ruby25/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby25/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby25/presubmit.cfg b/kokoro/linux/ruby25/presubmit.cfg
index dee2db0..8523c22 100644
--- a/kokoro/linux/ruby25/presubmit.cfg
+++ b/kokoro/linux/ruby25/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby25/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby26/build.sh b/kokoro/linux/ruby26/build.sh
deleted file mode 100755
index 72d2d45..0000000
--- a/kokoro/linux/ruby26/build.sh
+++ /dev/null
@@ -1,18 +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 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="ruby26"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/ruby26/common.cfg b/kokoro/linux/ruby26/common.cfg
new file mode 100644
index 0000000..d09a405
--- /dev/null
+++ b/kokoro/linux/ruby26/common.cfg
@@ -0,0 +1,26 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/ruby/linux:ruby-2.6.0-64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//ruby/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=ruby_platform=c"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/ruby26/continuous.cfg b/kokoro/linux/ruby26/continuous.cfg
index 4779065..8523c22 100644
--- a/kokoro/linux/ruby26/continuous.cfg
+++ b/kokoro/linux/ruby26/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby26/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby26/presubmit.cfg b/kokoro/linux/ruby26/presubmit.cfg
index 4779065..8523c22 100644
--- a/kokoro/linux/ruby26/presubmit.cfg
+++ b/kokoro/linux/ruby26/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby26/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby27/build.sh b/kokoro/linux/ruby27/build.sh
deleted file mode 100755
index c38ee36..0000000
--- a/kokoro/linux/ruby27/build.sh
+++ /dev/null
@@ -1,18 +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 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="ruby27"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/ruby27/common.cfg b/kokoro/linux/ruby27/common.cfg
new file mode 100644
index 0000000..51afa75
--- /dev/null
+++ b/kokoro/linux/ruby27/common.cfg
@@ -0,0 +1,26 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/ruby/linux:ruby-2.7.0-64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//ruby/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=ruby_platform=c"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/ruby27/continuous.cfg b/kokoro/linux/ruby27/continuous.cfg
index 9cce8c9..8523c22 100644
--- a/kokoro/linux/ruby27/continuous.cfg
+++ b/kokoro/linux/ruby27/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby27/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby27/presubmit.cfg b/kokoro/linux/ruby27/presubmit.cfg
index 9cce8c9..8523c22 100644
--- a/kokoro/linux/ruby27/presubmit.cfg
+++ b/kokoro/linux/ruby27/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby27/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby30/build.sh b/kokoro/linux/ruby30/build.sh
deleted file mode 100755
index 9e44575..0000000
--- a/kokoro/linux/ruby30/build.sh
+++ /dev/null
@@ -1,18 +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 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="ruby30"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/ruby30/common.cfg b/kokoro/linux/ruby30/common.cfg
new file mode 100644
index 0000000..338505e
--- /dev/null
+++ b/kokoro/linux/ruby30/common.cfg
@@ -0,0 +1,26 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/ruby/linux:ruby-3.0.2-2f706fd1ab49f4e97af769388be486069b63efee"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//ruby/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=ruby_platform=c"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/ruby30/continuous.cfg b/kokoro/linux/ruby30/continuous.cfg
index b03a335..8523c22 100644
--- a/kokoro/linux/ruby30/continuous.cfg
+++ b/kokoro/linux/ruby30/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby30/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby30/presubmit.cfg b/kokoro/linux/ruby30/presubmit.cfg
index b03a335..8523c22 100644
--- a/kokoro/linux/ruby30/presubmit.cfg
+++ b/kokoro/linux/ruby30/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby30/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby31/build.sh b/kokoro/linux/ruby31/build.sh
deleted file mode 100644
index c22bdae..0000000
--- a/kokoro/linux/ruby31/build.sh
+++ /dev/null
@@ -1,18 +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 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="ruby31"
-./kokoro/linux/build_and_run_docker.sh
diff --git a/kokoro/linux/ruby31/common.cfg b/kokoro/linux/ruby31/common.cfg
new file mode 100644
index 0000000..588fe13
--- /dev/null
+++ b/kokoro/linux/ruby31/common.cfg
@@ -0,0 +1,26 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 120
+
+env_vars {
+  key: "CONTAINER_IMAGE"
+  value: "gcr.io/protobuf-build/ruby/linux:ruby-3.1.0-64e8944e4f18d7d6c9649112a8a93be57e693cd8"
+}
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//ruby/..."
+}
+
+env_vars {
+  key: "BAZEL_EXTRA_FLAGS"
+  value: "--define=ruby_platform=c"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/linux/ruby31/continuous.cfg b/kokoro/linux/ruby31/continuous.cfg
index 0477912..8523c22 100644
--- a/kokoro/linux/ruby31/continuous.cfg
+++ b/kokoro/linux/ruby31/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby31/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby31/presubmit.cfg b/kokoro/linux/ruby31/presubmit.cfg
index 0477912..8523c22 100644
--- a/kokoro/linux/ruby31/presubmit.cfg
+++ b/kokoro/linux/ruby31/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby31/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/benchmark/continuous.cfg b/kokoro/linux/ruby_aarch64/common.cfg
similarity index 66%
copy from kokoro/linux/benchmark/continuous.cfg
copy to kokoro/linux/ruby_aarch64/common.cfg
index 8cc8f96..ae82696 100644
--- a/kokoro/linux/benchmark/continuous.cfg
+++ b/kokoro/linux/ruby_aarch64/common.cfg
@@ -1,8 +1,8 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/linux/benchmark/build.sh"
-timeout_mins: 240
+build_file: "protobuf/kokoro/linux/ruby_aarch64/build.sh"
+timeout_mins: 120
 
 action {
   define_artifacts {
diff --git a/kokoro/linux/ruby_aarch64/continuous.cfg b/kokoro/linux/ruby_aarch64/continuous.cfg
index ae82696..8523c22 100644
--- a/kokoro/linux/ruby_aarch64/continuous.cfg
+++ b/kokoro/linux/ruby_aarch64/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/ruby_aarch64/presubmit.cfg b/kokoro/linux/ruby_aarch64/presubmit.cfg
index ae82696..8523c22 100644
--- a/kokoro/linux/ruby_aarch64/presubmit.cfg
+++ b/kokoro/linux/ruby_aarch64/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/linux/ruby_aarch64/build.sh"
-timeout_mins: 120
-
-action {
-  define_artifacts {
-    regex: "**/sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/linux/staleness/release.cfg b/kokoro/linux/staleness/release.cfg
new file mode 100644
index 0000000..d109c50
--- /dev/null
+++ b/kokoro/linux/staleness/release.cfg
@@ -0,0 +1,18 @@
+# We run our staleness tests as release-type jobs only. They are not really
+# part of the release process, but the release job type allows us to run the
+# tests on a schedule only (not presubmit or postsubmit).
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/linux/bazel.sh"
+timeout_mins: 15
+
+env_vars {
+  key: "BAZEL_TARGETS"
+  value: "//src:cmake_lists_staleness_test"
+}
+
+action {
+  define_artifacts {
+    regex: "**/sponge_log.*"
+  }
+}
diff --git a/kokoro/macos-next/cpp/build.sh b/kokoro/macos-next/cpp/build.sh
index 490e990..451c850 100755
--- a/kokoro/macos-next/cpp/build.sh
+++ b/kokoro/macos-next/cpp/build.sh
@@ -9,47 +9,21 @@
   cd /Volumes/BuildData/tmpfs/src
 fi
 
-# These vars can be changed when running manually, e.g.:
-#
-#   % BUILD_CONFIG=RelWithDebInfo path/to/build.sh
+# Default environment variables used by cmake build:
+: ${CMAKE_CONFIG_TYPE:=Debug}
+export CMAKE_CONFIG_TYPE
+: ${CTEST_PARALLEL_LEVEL:=4}
+export CTEST_PARALLEL_LEVEL
 
-# By default, build using Debug config.
-: ${BUILD_CONFIG:=Debug}
-
-# By default, find the sources based on this script path.
-: ${SOURCE_DIR:=$(cd $(dirname $0)/../../..; pwd)}
-
-# By default, put outputs under <git root>/cmake/build.
-: ${BUILD_DIR:=${SOURCE_DIR}/cmake/build}
-
-source ${SOURCE_DIR}/kokoro/caplog.sh
+# Run from the project root directory.
+cd $(dirname $0)/../../..
 
 #
 # Update submodules
 #
-git -C "${SOURCE_DIR}" submodule update --init --recursive
+git submodule update --init --recursive
 
 #
-# Configure and build in a separate directory
+# Run build
 #
-mkdir -p "${BUILD_DIR}"
-
-caplog 01_configure \
-  cmake -S "${SOURCE_DIR}" -B "${BUILD_DIR}" ${CAPLOG_CMAKE_ARGS:-}
-
-if [[ -n ${CAPLOG_DIR:-} ]]; then
-  mkdir -p "${CAPLOG_DIR}/CMakeFiles"
-  cp "${BUILD_DIR}"/CMakeFiles/CMake*.log "${CAPLOG_DIR}/CMakeFiles"
-fi
-
-caplog 02_build \
-  cmake --build "${BUILD_DIR}" --config "${BUILD_CONFIG}"
-
-#
-# Run tests
-#
-(
-  cd "${BUILD_DIR}"
-  caplog 03_combined_testlog \
-    ctest -C "${BUILD_CONFIG}" -j4 ${CAPLOG_CTEST_ARGS:-}
-)
+kokoro/common/cmake.sh
diff --git a/kokoro/macos-next/cpp/common.cfg b/kokoro/macos-next/cpp/common.cfg
new file mode 100644
index 0000000..166caa5
--- /dev/null
+++ b/kokoro/macos-next/cpp/common.cfg
@@ -0,0 +1,13 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos-next/cpp/build.sh"
+timeout_mins: 1440
+
+# Upload logs
+action: {
+  define_artifacts: {
+    regex: "**/*sponge_log.log"
+    regex: "**/*sponge_log.xml"
+  }
+}
diff --git a/kokoro/macos-next/cpp/continuous.cfg b/kokoro/macos-next/cpp/continuous.cfg
index 166caa5..8523c22 100644
--- a/kokoro/macos-next/cpp/continuous.cfg
+++ b/kokoro/macos-next/cpp/continuous.cfg
@@ -1,13 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos-next/cpp/build.sh"
-timeout_mins: 1440
-
-# Upload logs
-action: {
-  define_artifacts: {
-    regex: "**/*sponge_log.log"
-    regex: "**/*sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos-next/cpp/presubmit.cfg b/kokoro/macos-next/cpp/presubmit.cfg
index 166caa5..8523c22 100644
--- a/kokoro/macos-next/cpp/presubmit.cfg
+++ b/kokoro/macos-next/cpp/presubmit.cfg
@@ -1,13 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos-next/cpp/build.sh"
-timeout_mins: 1440
-
-# Upload logs
-action: {
-  define_artifacts: {
-    regex: "**/*sponge_log.log"
-    regex: "**/*sponge_log.xml"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/cpp/build.sh b/kokoro/macos/cpp/build.sh
index bae2ebb..9c3b8aa 100755
--- a/kokoro/macos/cpp/build.sh
+++ b/kokoro/macos/cpp/build.sh
@@ -2,10 +2,16 @@
 #
 # Build file to set up and run tests
 
-# Change to repo root
+set -eux
+set -o pipefail
+
+# Run from the project root directory.
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh cpp
+#
+# Run build
+#
+bazel test $(kokoro/common/bazel_flags.sh) //src/...
diff --git a/kokoro/macos/cpp/common.cfg b/kokoro/macos/cpp/common.cfg
new file mode 100644
index 0000000..2651551
--- /dev/null
+++ b/kokoro/macos/cpp/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/cpp/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/cpp/continuous.cfg b/kokoro/macos/cpp/continuous.cfg
index 4bea1cb..8523c22 100644
--- a/kokoro/macos/cpp/continuous.cfg
+++ b/kokoro/macos/cpp/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/cpp/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/cpp/presubmit.cfg b/kokoro/macos/cpp/presubmit.cfg
index 4bea1cb..8523c22 100644
--- a/kokoro/macos/cpp/presubmit.cfg
+++ b/kokoro/macos/cpp/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/cpp/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/cpp_distcheck/build.sh b/kokoro/macos/cpp_distcheck/build.sh
deleted file mode 100755
index d729b63..0000000
--- a/kokoro/macos/cpp_distcheck/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 cpp_distcheck
diff --git a/kokoro/macos/cpp_distcheck/continuous.cfg b/kokoro/macos/cpp_distcheck/continuous.cfg
deleted file mode 100644
index 89441bc..0000000
--- a/kokoro/macos/cpp_distcheck/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/cpp_distcheck/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/cpp_distcheck/presubmit.cfg b/kokoro/macos/cpp_distcheck/presubmit.cfg
deleted file mode 100644
index 89441bc..0000000
--- a/kokoro/macos/cpp_distcheck/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/cpp_distcheck/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/objectivec_ios_debug/build.sh b/kokoro/macos/objectivec_ios_debug/build.sh
index 1055d72..77b704f 100755
--- a/kokoro/macos/objectivec_ios_debug/build.sh
+++ b/kokoro/macos/objectivec_ios_debug/build.sh
@@ -8,4 +8,5 @@
 # Prepare worker environment to run tests
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh objectivec_ios_debug
+objectivec/DevTools/full_mac_build.sh \
+  --core-only --skip-xcode-osx --skip-xcode-tvos --skip-objc-conformance --skip-xcode-release
diff --git a/kokoro/macos/objectivec_ios_debug/common.cfg b/kokoro/macos/objectivec_ios_debug/common.cfg
new file mode 100644
index 0000000..b4ccc45
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_debug/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_ios_debug/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/objectivec_ios_debug/continuous.cfg b/kokoro/macos/objectivec_ios_debug/continuous.cfg
index 473d545..8523c22 100644
--- a/kokoro/macos/objectivec_ios_debug/continuous.cfg
+++ b/kokoro/macos/objectivec_ios_debug/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/objectivec_ios_debug/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/objectivec_ios_debug/presubmit.cfg b/kokoro/macos/objectivec_ios_debug/presubmit.cfg
index 473d545..8523c22 100644
--- a/kokoro/macos/objectivec_ios_debug/presubmit.cfg
+++ b/kokoro/macos/objectivec_ios_debug/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/objectivec_ios_debug/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/objectivec_ios_release/build.sh b/kokoro/macos/objectivec_ios_release/build.sh
index 76ce3ba..adbc4f2 100755
--- a/kokoro/macos/objectivec_ios_release/build.sh
+++ b/kokoro/macos/objectivec_ios_release/build.sh
@@ -8,4 +8,5 @@
 # Prepare worker environment to run tests
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh objectivec_ios_release
+objectivec/DevTools/full_mac_build.sh \
+  --core-only --skip-xcode-osx --skip-xcode-tvos --skip-objc-conformance --skip-xcode-debug
diff --git a/kokoro/macos/objectivec_ios_release/common.cfg b/kokoro/macos/objectivec_ios_release/common.cfg
new file mode 100644
index 0000000..3a6ac86
--- /dev/null
+++ b/kokoro/macos/objectivec_ios_release/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_ios_release/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/objectivec_ios_release/continuous.cfg b/kokoro/macos/objectivec_ios_release/continuous.cfg
index 3cbfb68..8523c22 100644
--- a/kokoro/macos/objectivec_ios_release/continuous.cfg
+++ b/kokoro/macos/objectivec_ios_release/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/objectivec_ios_release/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/objectivec_ios_release/presubmit.cfg b/kokoro/macos/objectivec_ios_release/presubmit.cfg
index 3cbfb68..8523c22 100644
--- a/kokoro/macos/objectivec_ios_release/presubmit.cfg
+++ b/kokoro/macos/objectivec_ios_release/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/objectivec_ios_release/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/objectivec_osx/build.sh b/kokoro/macos/objectivec_osx/build.sh
index 000be27..7f5d561 100755
--- a/kokoro/macos/objectivec_osx/build.sh
+++ b/kokoro/macos/objectivec_osx/build.sh
@@ -8,4 +8,5 @@
 # Prepare worker environment to run tests
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh objectivec_osx
+objectivec/DevTools/full_mac_build.sh \
+  --core-only --skip-xcode-ios --skip-xcode-tvos
diff --git a/kokoro/macos/objectivec_osx/common.cfg b/kokoro/macos/objectivec_osx/common.cfg
new file mode 100644
index 0000000..ee5c2db
--- /dev/null
+++ b/kokoro/macos/objectivec_osx/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/objectivec_osx/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/objectivec_osx/continuous.cfg b/kokoro/macos/objectivec_osx/continuous.cfg
index 41bd46a..8523c22 100644
--- a/kokoro/macos/objectivec_osx/continuous.cfg
+++ b/kokoro/macos/objectivec_osx/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/objectivec_osx/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/objectivec_osx/presubmit.cfg b/kokoro/macos/objectivec_osx/presubmit.cfg
index 41bd46a..8523c22 100644
--- a/kokoro/macos/objectivec_osx/presubmit.cfg
+++ b/kokoro/macos/objectivec_osx/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/objectivec_osx/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/php7.0_mac/build.sh b/kokoro/macos/php7.0_mac/build.sh
deleted file mode 100755
index c6717e0..0000000
--- a/kokoro/macos/php7.0_mac/build.sh
+++ /dev/null
@@ -1,12 +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
-
-# TODO(mkruskal) Re-enable this once we can get a working PHP 7.0 installed.
-#./tests.sh php7.0_mac
diff --git a/kokoro/macos/php7.0_mac/continuous.cfg b/kokoro/macos/php7.0_mac/continuous.cfg
deleted file mode 100644
index c2c1811..0000000
--- a/kokoro/macos/php7.0_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.0_mac/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/php7.0_mac/presubmit.cfg b/kokoro/macos/php7.0_mac/presubmit.cfg
deleted file mode 100644
index c2c1811..0000000
--- a/kokoro/macos/php7.0_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.0_mac/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/php7.3_mac/build.sh b/kokoro/macos/php7.3_mac/build.sh
deleted file mode 100755
index 2688ddb..0000000
--- a/kokoro/macos/php7.3_mac/build.sh
+++ /dev/null
@@ -1,12 +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
-
-# TODO(mkruskal) Re-enable this once we can get a working PHP 7.0 installed.
-#./tests.sh php7.3_mac
diff --git a/kokoro/macos/php7.3_mac/presubmit.cfg b/kokoro/macos/php7.3_mac/presubmit.cfg
deleted file mode 100644
index 9a71745..0000000
--- a/kokoro/macos/php7.3_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.3_mac/build.sh"
-timeout_mins: 1440
diff --git a/kokoro/macos/php74/build.sh b/kokoro/macos/php74/build.sh
new file mode 100755
index 0000000..f044434
--- /dev/null
+++ b/kokoro/macos/php74/build.sh
@@ -0,0 +1,22 @@
+#!/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
+
+# Install Dependencies
+# PHP 7.4 is already installed on the machine
+brew cleanup
+brew install coreutils
+
+# Configure path
+PHP_FOLDER=$(find $HOMEBREW_PREFIX -type d -regex ".*php.*/7.4.[0-9_.]*" | sort -n | tail -n 1)
+test ! -z "$PHP_FOLDER"
+export PATH="$PHP_FOLDER/bin:$PATH"
+
+# Test
+kokoro/macos/test_php.sh
diff --git a/kokoro/macos/php74/common.cfg b/kokoro/macos/php74/common.cfg
new file mode 100644
index 0000000..b9d5b82
--- /dev/null
+++ b/kokoro/macos/php74/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php74/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/php74/continuous.cfg b/kokoro/macos/php74/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/macos/php74/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/php74/presubmit.cfg b/kokoro/macos/php74/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/macos/php74/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/php80/build.sh b/kokoro/macos/php80/build.sh
new file mode 100755
index 0000000..e703ffc
--- /dev/null
+++ b/kokoro/macos/php80/build.sh
@@ -0,0 +1,21 @@
+#!/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
+
+# Install Dependencies
+brew cleanup
+brew install coreutils php@8.0
+
+# Configure path
+PHP_FOLDER=$(find $HOMEBREW_PREFIX -type d -regex ".*php.*/8.0.[0-9_.]*" | sort -n | tail -n 1)
+test ! -z "$PHP_FOLDER"
+export PATH="$PHP_FOLDER/bin:$PATH"
+
+# Test
+kokoro/macos/test_php.sh
diff --git a/kokoro/macos/php80/common.cfg b/kokoro/macos/php80/common.cfg
new file mode 100644
index 0000000..294fd52
--- /dev/null
+++ b/kokoro/macos/php80/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/php80/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/php80/continuous.cfg b/kokoro/macos/php80/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/macos/php80/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/php80/presubmit.cfg b/kokoro/macos/php80/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/macos/php80/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/prepare_build_macos_rc b/kokoro/macos/prepare_build_macos_rc
index 9b9b2df..7156d58 100755
--- a/kokoro/macos/prepare_build_macos_rc
+++ b/kokoro/macos/prepare_build_macos_rc
@@ -5,13 +5,7 @@
 set -eux
 
 export HOMEBREW_PREFIX=$(brew --prefix)
-
-##
-# Remove any pre-existing protobuf installation.
-brew uninstall protobuf
-
-##
-# Select Xcode version
+export HOMEBREW_NO_INSTALLED_DEPENDENTS_CHECK=1 # Do not automatically update packages.
 
 ##
 # Select Xcode version
@@ -19,25 +13,8 @@
 sudo xcode-select -s "${DEVELOPER_DIR}"
 
 ##
-# Select C/C++ compilers
-
-export CC=gcc
-export CXX=g++
-
-##
-# Install Python 2 by default
-
-eval "$(pyenv init -)"
-pyenv install -v -s 2.7.18 && pyenv global 2.7.18
-
-##
-# Install Tox
-
-if [[ "${KOKORO_INSTALL_TOX:-}" == "yes" ]] ; then
-  pyenv install -v -s 3.7.13
-  pyenv global 3.7.13
-  sudo python -m pip install --upgrade pip tox tox-pyenv
-fi
+# Use Python 2 by default (for googletest)
+pyenv global 2.7.18
 
 ##
 # Setup RVM
@@ -47,3 +24,19 @@
     git config --global --add safe.directory $HOMEBREW_PREFIX/Library/Taps/homebrew/homebrew-services
     sudo chown -R $(whoami) $HOME/.rvm/
 fi
+
+# "Install" valgrind if it doesn't exist
+##
+if [ ! -x "$(command -v valgrind)" ]; then
+    echo "#! /bin/bash" > valgrind
+    chmod ug+x valgrind
+    sudo mv valgrind /usr/local/bin/valgrind
+fi
+
+##
+# Install Virtual Python Environment
+
+if [[ "${KOKORO_INSTALL_VENV:-}" == "yes" ]] ; then
+    python3 -m venv venv
+    source venv/bin/activate
+fi
diff --git a/kokoro/macos/python/build.sh b/kokoro/macos/python/build.sh
index 388e24b..a3edcea 100755
--- a/kokoro/macos/python/build.sh
+++ b/kokoro/macos/python/build.sh
@@ -6,7 +6,9 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
-KOKORO_INSTALL_TOX=yes
+KOKORO_INSTALL_VENV=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh python
+bazel test //python/... @upb//python/... //python:python_version \
+  $(kokoro/common/bazel_flags.sh) \
+  --macos_minimum_os=10.9
diff --git a/kokoro/macos/python/common.cfg b/kokoro/macos/python/common.cfg
new file mode 100644
index 0000000..dd9f8ac
--- /dev/null
+++ b/kokoro/macos/python/common.cfg
@@ -0,0 +1,33 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/python/build.sh"
+timeout_mins: 1440
+
+action {
+  define_artifacts {
+    regex: "**/*"
+  }
+}
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/python/continuous.cfg b/kokoro/macos/python/continuous.cfg
index 0fc8b50..8523c22 100644
--- a/kokoro/macos/python/continuous.cfg
+++ b/kokoro/macos/python/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/python/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/python/presubmit.cfg b/kokoro/macos/python/presubmit.cfg
index 0fc8b50..8523c22 100644
--- a/kokoro/macos/python/presubmit.cfg
+++ b/kokoro/macos/python/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/python/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/python_cpp/build.sh b/kokoro/macos/python_cpp/build.sh
index f86dd6f..9e83c3f 100755
--- a/kokoro/macos/python_cpp/build.sh
+++ b/kokoro/macos/python_cpp/build.sh
@@ -6,8 +6,10 @@
 cd $(dirname $0)/../../..
 
 # Prepare worker environment to run tests
-KOKORO_INSTALL_TOX=yes
+KOKORO_INSTALL_VENV=yes
 source kokoro/macos/prepare_build_macos_rc
-g++ --version
 
-./tests.sh python_cpp
+bazel test //python/... //python:python_version \
+  $(kokoro/common/bazel_flags.sh) \
+  --macos_minimum_os=10.9 \
+  --define=use_fast_cpp_protos=true
diff --git a/kokoro/macos/python_cpp/common.cfg b/kokoro/macos/python_cpp/common.cfg
new file mode 100644
index 0000000..12270c5
--- /dev/null
+++ b/kokoro/macos/python_cpp/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/python_cpp/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/python_cpp/continuous.cfg b/kokoro/macos/python_cpp/continuous.cfg
index 22f4a0e..8523c22 100644
--- a/kokoro/macos/python_cpp/continuous.cfg
+++ b/kokoro/macos/python_cpp/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/python_cpp/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/python_cpp/presubmit.cfg b/kokoro/macos/python_cpp/presubmit.cfg
index 22f4a0e..8523c22 100644
--- a/kokoro/macos/python_cpp/presubmit.cfg
+++ b/kokoro/macos/python_cpp/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/python_cpp/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby25/build.sh b/kokoro/macos/ruby25/build.sh
index 48c8940..81ce2c3 100755
--- a/kokoro/macos/ruby25/build.sh
+++ b/kokoro/macos/ruby25/build.sh
@@ -9,4 +9,5 @@
 KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh ruby25
+cd ruby
+./travis-test.sh ruby-2.5.1
diff --git a/kokoro/macos/ruby25/common.cfg b/kokoro/macos/ruby25/common.cfg
new file mode 100644
index 0000000..ba17345
--- /dev/null
+++ b/kokoro/macos/ruby25/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby25/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/ruby25/continuous.cfg b/kokoro/macos/ruby25/continuous.cfg
index b3755e4..8523c22 100644
--- a/kokoro/macos/ruby25/continuous.cfg
+++ b/kokoro/macos/ruby25/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby25/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby25/presubmit.cfg b/kokoro/macos/ruby25/presubmit.cfg
index b3755e4..8523c22 100644
--- a/kokoro/macos/ruby25/presubmit.cfg
+++ b/kokoro/macos/ruby25/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby25/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby26/build.sh b/kokoro/macos/ruby26/build.sh
index 1b94fe1..ee815b6 100755
--- a/kokoro/macos/ruby26/build.sh
+++ b/kokoro/macos/ruby26/build.sh
@@ -9,4 +9,5 @@
 KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh ruby26
+cd ruby
+./travis-test.sh ruby-2.6.0
diff --git a/kokoro/macos/ruby26/common.cfg b/kokoro/macos/ruby26/common.cfg
new file mode 100644
index 0000000..deeaf51
--- /dev/null
+++ b/kokoro/macos/ruby26/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby26/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/ruby26/continuous.cfg b/kokoro/macos/ruby26/continuous.cfg
index 688f63c..8523c22 100644
--- a/kokoro/macos/ruby26/continuous.cfg
+++ b/kokoro/macos/ruby26/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby26/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby26/presubmit.cfg b/kokoro/macos/ruby26/presubmit.cfg
index 688f63c..8523c22 100644
--- a/kokoro/macos/ruby26/presubmit.cfg
+++ b/kokoro/macos/ruby26/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby26/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby27/build.sh b/kokoro/macos/ruby27/build.sh
index baebdb7..ca6badb 100755
--- a/kokoro/macos/ruby27/build.sh
+++ b/kokoro/macos/ruby27/build.sh
@@ -9,4 +9,5 @@
 KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh ruby27
+cd ruby
+./travis-test.sh ruby-2.7.0
diff --git a/kokoro/macos/ruby27/common.cfg b/kokoro/macos/ruby27/common.cfg
new file mode 100644
index 0000000..1451eb0
--- /dev/null
+++ b/kokoro/macos/ruby27/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby27/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/ruby27/continuous.cfg b/kokoro/macos/ruby27/continuous.cfg
index b10b455..8523c22 100644
--- a/kokoro/macos/ruby27/continuous.cfg
+++ b/kokoro/macos/ruby27/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby27/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby27/presubmit.cfg b/kokoro/macos/ruby27/presubmit.cfg
index b10b455..8523c22 100644
--- a/kokoro/macos/ruby27/presubmit.cfg
+++ b/kokoro/macos/ruby27/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby27/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby30/build.sh b/kokoro/macos/ruby30/build.sh
index b1e0641..01bdc47 100755
--- a/kokoro/macos/ruby30/build.sh
+++ b/kokoro/macos/ruby30/build.sh
@@ -9,4 +9,5 @@
 KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh ruby30
+cd ruby
+./travis-test.sh ruby-3.0.2
diff --git a/kokoro/macos/ruby30/common.cfg b/kokoro/macos/ruby30/common.cfg
new file mode 100644
index 0000000..79dc7a5
--- /dev/null
+++ b/kokoro/macos/ruby30/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby30/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/ruby30/continuous.cfg b/kokoro/macos/ruby30/continuous.cfg
index d505117..8523c22 100644
--- a/kokoro/macos/ruby30/continuous.cfg
+++ b/kokoro/macos/ruby30/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby30/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby30/presubmit.cfg b/kokoro/macos/ruby30/presubmit.cfg
index d505117..8523c22 100644
--- a/kokoro/macos/ruby30/presubmit.cfg
+++ b/kokoro/macos/ruby30/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby30/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby31/build.sh b/kokoro/macos/ruby31/build.sh
index 3cf61f6..6e4beda 100644
--- a/kokoro/macos/ruby31/build.sh
+++ b/kokoro/macos/ruby31/build.sh
@@ -12,4 +12,5 @@
 KOKORO_INSTALL_RVM=yes
 source kokoro/macos/prepare_build_macos_rc
 
-./tests.sh ruby31
+cd ruby
+./travis-test.sh ruby-3.1.0
diff --git a/kokoro/macos/ruby31/common.cfg b/kokoro/macos/ruby31/common.cfg
new file mode 100644
index 0000000..e2d1d1b
--- /dev/null
+++ b/kokoro/macos/ruby31/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/macos/ruby31/build.sh"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/macos/ruby31/continuous.cfg b/kokoro/macos/ruby31/continuous.cfg
index 19e16b3..8523c22 100644
--- a/kokoro/macos/ruby31/continuous.cfg
+++ b/kokoro/macos/ruby31/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby31/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/ruby31/presubmit.cfg b/kokoro/macos/ruby31/presubmit.cfg
index 19e16b3..8523c22 100644
--- a/kokoro/macos/ruby31/presubmit.cfg
+++ b/kokoro/macos/ruby31/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/macos/ruby31/build.sh"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/test_php.sh b/kokoro/macos/test_php.sh
new file mode 100755
index 0000000..74d88f6
--- /dev/null
+++ b/kokoro/macos/test_php.sh
@@ -0,0 +1,16 @@
+#!/bin/bash
+
+set -eux
+
+pushd php
+rm -rf vendor
+php -v
+php -m
+composer update
+composer test_c
+popd
+
+git clean -fXd
+bazel test $(kokoro/common/bazel_flags.sh) \
+  --action_env=PATH --test_env=PATH \
+  //php:conformance_test_c
diff --git a/kokoro/release/collect_all_artifacts.sh b/kokoro/release/collect_all_artifacts.sh
index 6e0d152..20c6d8d 100755
--- a/kokoro/release/collect_all_artifacts.sh
+++ b/kokoro/release/collect_all_artifacts.sh
@@ -40,8 +40,8 @@
 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 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
+cp ${INPUT_ARTIFACTS_DIR}/kokoro/release/protoc/target/linux/x86_32/protoc.exe protoc/linux_x86/protoc
+cp ${INPUT_ARTIFACTS_DIR}/kokoro/release/protoc/target/linux/x86_64/protoc.exe protoc/linux_x64/protoc
 
 mkdir -p protoc/macosx_x64
 cp ${INPUT_ARTIFACTS_DIR}/build64/src/protoc protoc/macosx_x64/protoc
diff --git a/kokoro/release/csharp/windows/common.cfg b/kokoro/release/csharp/windows/common.cfg
new file mode 100644
index 0000000..f508c65
--- /dev/null
+++ b/kokoro/release/csharp/windows/common.cfg
@@ -0,0 +1,11 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/release/csharp/windows/build_nuget.bat"
+timeout_mins: 60
+
+action {
+  define_artifacts {
+    regex: "**/*.nupkg"
+  }
+}
diff --git a/kokoro/release/csharp/windows/continuous.cfg b/kokoro/release/csharp/windows/continuous.cfg
index f508c65..8523c22 100644
--- a/kokoro/release/csharp/windows/continuous.cfg
+++ b/kokoro/release/csharp/windows/continuous.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/release/csharp/windows/build_nuget.bat"
-timeout_mins: 60
-
-action {
-  define_artifacts {
-    regex: "**/*.nupkg"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/release/csharp/windows/presubmit.cfg b/kokoro/release/csharp/windows/presubmit.cfg
index f508c65..8523c22 100644
--- a/kokoro/release/csharp/windows/presubmit.cfg
+++ b/kokoro/release/csharp/windows/presubmit.cfg
@@ -1,11 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/release/csharp/windows/build_nuget.bat"
-timeout_mins: 60
-
-action {
-  define_artifacts {
-    regex: "**/*.nupkg"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/protoc-artifacts/build-protoc.sh b/kokoro/release/protoc/build-protoc.sh
similarity index 73%
rename from protoc-artifacts/build-protoc.sh
rename to kokoro/release/protoc/build-protoc.sh
index 4602842..c0785ee 100755
--- a/protoc-artifacts/build-protoc.sh
+++ b/kokoro/release/protoc/build-protoc.sh
@@ -19,28 +19,20 @@
 #   macos  osx     x86_64
 #   mingw  windows x86_32
 #   mingw  windows x86_64
-#
-# Before running this script, make sure you have generated the configure script
-# in the parent directory (i.e., run ./autogen.sh there).
 
 OS=$1
 ARCH=$2
-MAKE_TARGET=$3
+BAZEL_TARGET=$3
 
 if [[ $# < 3 ]]; then
   echo "Not enough arguments provided."
   exit 1
 fi
 
-case $MAKE_TARGET in
-  protoc-gen-javalite)
-    ;;
-  protoc)
-    ;;
-  *)
-    echo "Target ""$MAKE_TARGET"" invalid."
+if [[ $BAZEL_TARGET != protoc ]]; then
+    echo "Target ""$BAZEL_TARGET"" invalid."
     exit 1
-esac
+fi
 
 # Under Cygwin, bash doesn't have these in PATH when called from Maven which
 # runs in Windows version of Java.
@@ -146,22 +138,22 @@
     host_machine="$(uname -m)";
     dump_cmd='ldd '"$1"
     if [[ "$ARCH" == x86_32 ]]; then
-      white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux\.so\.2"
+      white_list="linux-gate\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libgcc_s\.so\.1\|libstdc++\.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"
+      white_list="linux-vdso\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libgcc_s\.so\.1\|libstdc++\.so\.6\|ld-linux-x86-64\.so\.2"
     elif [[ "$ARCH" == s390_64 ]]; then
       if [[ $host_machine != s390x ]];then
         dump_cmd='objdump -p '"$1"' | grep NEEDED'
       fi
-      white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libz\.so\.1\|ld64\.so\.1"
+      white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libgcc_s\.so\.1\|libstdc++\.so\.6\|libz\.so\.1\|ld64\.so\.1"
     elif [[ "$ARCH" == ppcle_64 ]]; then
       if [[ $host_machine != ppc64le ]];then
         dump_cmd='objdump -p '"$1"' | grep NEEDED'
       fi
-      white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libz\.so\.1\|ld64\.so\.2"
+      white_list="linux-vdso64\.so\.1\|libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libgcc_s\.so\.1\|libstdc++\.so\.6\|libz\.so\.1\|ld64\.so\.2"
     elif [[ "$ARCH" == aarch_64 ]]; then
       dump_cmd='objdump -p '"$1"' | grep NEEDED'
-      white_list="libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|ld-linux-aarch64\.so\.1"
+      white_list="libpthread\.so\.0\|libm\.so\.6\|libc\.so\.6\|libgcc_s\.so\.1\|libstdc++\.so\.6\|ld-linux-aarch64\.so\.1"
     fi
   elif [[ "$OS" == osx ]]; then
     dump_cmd='otool -L '"$1"' | fgrep dylib'
@@ -185,19 +177,14 @@
 }
 ############################################################################
 
-echo "Building protoc, OS=$OS ARCH=$ARCH TARGET=$MAKE_TARGET"
+echo "Building protoc, OS=$OS ARCH=$ARCH TARGET=$BAZEL_TARGET"
 
-CONFIGURE_ARGS="--disable-shared"
+BAZEL_ARGS=("--dynamic_mode=off" "--compilation_mode=opt" "--copt=-g0" "--copt=-fpic")
 
 if [[ "$OS" == windows ]]; then
-  MAKE_TARGET="${MAKE_TARGET}.exe"
+  BAZEL_TARGET="${BAZEL_TARGET}.exe"
 fi
 
-# Override the default value set in configure.ac that has '-g' which produces
-# huge binary.
-CXXFLAGS="-DNDEBUG"
-LDFLAGS=""
-
 if [[ "$(uname)" == CYGWIN* ]]; then
   assertEq "$OS" windows $LINENO
   # Use mingw32 compilers because executables produced by Cygwin compiler
@@ -217,28 +204,13 @@
   assertEq "$ARCH" x86_64 $LINENO
 elif [[ "$(uname)" == Linux* ]]; then
   if [[ "$OS" == linux ]]; then
-    if [[ "$ARCH" == x86_64 ]]; then
-      CXXFLAGS="$CXXFLAGS -m64"
-    elif [[ "$ARCH" == x86_32 ]]; then
-      CXXFLAGS="$CXXFLAGS -m32"
-    elif [[ "$ARCH" == aarch_64 ]]; then
-      CONFIGURE_ARGS="$CONFIGURE_ARGS --host=aarch64-linux-gnu"
-    elif [[ "$ARCH" == ppcle_64 ]]; then
-      CXXFLAGS="$CXXFLAGS -m64"
-      CONFIGURE_ARGS="$CONFIGURE_ARGS --host=powerpc64le-linux-gnu"
-    elif [[ "$ARCH" == s390_64 ]]; then
-      CXXFLAGS="$CXXFLAGS -m64"
-      CONFIGURE_ARGS="$CONFIGURE_ARGS --host=s390x-linux-gnu"
-    else
-      fail "Unsupported arch: $ARCH"
-    fi
+    BAZEL_ARGS+=("--config=linux-$ARCH")
   elif [[ "$OS" == windows ]]; then
     # Cross-compilation for Windows
-    CONFIGURE_ARGS="$CONFIGURE_ARGS"
     if [[ "$ARCH" == x86_64 ]]; then
-      CONFIGURE_ARGS="$CONFIGURE_ARGS --host=x86_64-w64-mingw32"
+      BAZEL_ARGS+=("--config=win64")
     elif [[ "$ARCH" == x86_32 ]]; then
-      CONFIGURE_ARGS="$CONFIGURE_ARGS --host=i686-w64-mingw32"
+      BAZEL_ARGS+=("--config=win32")
     else
       fail "Unsupported arch: $ARCH"
     fi
@@ -248,43 +220,24 @@
 elif [[ "$(uname)" == Darwin* ]]; then
   assertEq "$OS" osx $LINENO
   # Make the binary compatible with OSX 10.7 and later
-  CXXFLAGS="$CXXFLAGS -mmacosx-version-min=10.7"
-  if [[ "$ARCH" == x86_64 ]]; then
-    CXXFLAGS="$CXXFLAGS -m64"
-  elif [[ "$ARCH" == x86_32 ]]; then
-    CXXFLAGS="$CXXFLAGS -m32"
-  else
-    fail "Unsupported arch: $ARCH"
-  fi
+  BAZEL_ARGS+=("--config=osx-$ARCH" "--macos_minimum_os=10.7")
 else
   fail "Unsupported system: $(uname)"
 fi
 
-# Statically link libgcc and libstdc++.
-# -s to produce stripped binary.
-if [[ "$OS" == windows ]]; then
-  # Also static link libpthread required by mingw64
-  LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++ -Wl,-Bstatic -lstdc++ -lpthread -s"
-elif [[ "$OS" != osx ]]; then
-  # And they don't work under Mac.
-  LDFLAGS="$LDFLAGS -static-libgcc -static-libstdc++ -s"
-fi
-
-export CXXFLAGS LDFLAGS
-
 # Nested double quotes are unintuitive, but it works.
 cd "$(dirname "$0")"
 
 WORKING_DIR="$(pwd)"
-BUILD_DIR="build/$OS/$ARCH"
-TARGET_FILE="target/$OS/$ARCH/$MAKE_TARGET.exe"
+TARGET_FILE="target/$OS/$ARCH/$BAZEL_TARGET.exe"
+DOCKER_IMAGE=gcr.io/protobuf-build/bazel/linux@sha256:2bfd061284eff8234f2fcca16d71d43c69ccf3a22206628b54c204a6a9aac277
 
-mkdir -p "$BUILD_DIR" && cd "$BUILD_DIR" &&
-  ../../../../configure $CONFIGURE_ARGS &&
-  cd src && make $MAKE_TARGET -j8 &&
-  cd "$WORKING_DIR" && mkdir -p $(dirname $TARGET_FILE) &&
-  cp $BUILD_DIR/src/$MAKE_TARGET $TARGET_FILE ||
-  exit 1
+tmpfile=$(mktemp -u) &&
+docker run --cidfile $tmpfile -v $WORKING_DIR/../../..:/workspace $DOCKER_IMAGE \
+    build //:$BAZEL_TARGET "${BAZEL_ARGS[@]}" &&
+mkdir -p $(dirname $TARGET_FILE) &&
+docker cp \
+  `cat $tmpfile`:/workspace/bazel-bin/$BAZEL_TARGET $TARGET_FILE || exit 1
 
 if [[ "$OS" == osx ]]; then
   # Since Mac linker doesn't accept "-s", we need to run strip
diff --git a/kokoro/release/protoc/linux/build.sh b/kokoro/release/protoc/linux/build.sh
index 44a95aa..a9d58b7 100755
--- a/kokoro/release/protoc/linux/build.sh
+++ b/kokoro/release/protoc/linux/build.sh
@@ -1,44 +1,29 @@
 #!/bin/bash
 
-set -x
+# This is not the source of truth for release protoc executables, and will soon
+# be deprecated.
+
+set -ex
 
 # Change to repo root.
 cd $(dirname $0)/../../../..
+GIT_REPO_ROOT=$(pwd)
 
 # Initialize any submodules.
 git submodule update --init --recursive
 
-# Generate the configure script.
-./autogen.sh
-
 # Cross-build for aarch64, ppc64le and s390x. Note: we do these builds first to avoid
 # file permission issues. The Docker builds will create directories owned by
 # root, which causes problems if we try to add new artifacts to those
 # directories afterward.
 
-sudo apt install -y g++-aarch64-linux-gnu
-protoc-artifacts/build-protoc.sh linux aarch_64 protoc
 
-sudo apt install -y g++-powerpc64le-linux-gnu
-protoc-artifacts/build-protoc.sh linux ppcle_64 protoc
+kokoro/release/protoc/build-protoc.sh linux aarch_64 protoc
 
-sudo apt install -y g++-s390x-linux-gnu
-protoc-artifacts/build-protoc.sh linux s390_64 protoc
+kokoro/release/protoc/build-protoc.sh linux ppcle_64 protoc
 
-# Use docker image to build linux artifacts.
-DOCKER_IMAGE_NAME=protobuf/protoc_$(sha1sum protoc-artifacts/Dockerfile | cut -f1 -d " ")
-docker pull $DOCKER_IMAGE_NAME
+kokoro/release/protoc/build-protoc.sh linux s390_64 protoc
 
-docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \
-    bash -l /var/local/protobuf/protoc-artifacts/build-protoc.sh \
-    linux x86_64 protoc || {
-  echo "Failed to build protoc for linux + x86_64."
-  exit 1
-}
+kokoro/release/protoc/build-protoc.sh linux x86_64 protoc
 
-docker run -v $(pwd):/var/local/protobuf --rm $DOCKER_IMAGE_NAME \
-    bash -l /var/local/protobuf/protoc-artifacts/build-protoc.sh \
-    linux x86_32 protoc || {
-  echo "Failed to build protoc for linux + x86_32."
-  exit 1
-}
+kokoro/release/protoc/build-protoc.sh linux x86_32 protoc
diff --git a/kokoro/release/protoc/macos/build.sh b/kokoro/release/protoc/macos/build.sh
index 47c9bfa..2a31431 100755
--- a/kokoro/release/protoc/macos/build.sh
+++ b/kokoro/release/protoc/macos/build.sh
@@ -4,12 +4,9 @@
 CXXFLAGS_COMMON="-std=c++14 -DNDEBUG -mmacosx-version-min=10.9"
 
 cd github/protobuf
-./autogen.sh
 
-mkdir build64 && cd build64
-export CXXFLAGS="$CXXFLAGS_COMMON -m64"
-../configure --disable-shared
-make -j4
-file src/protoc
-otool -L src/protoc | grep dylib
-cd ..
+bazel build //:protoc --dynamic_mode=off
+mkdir -p build64/src
+cp bazel-bin/protoc build64/src/protoc
+file bazel-bin/protoc
+otool -L bazel-bin/protoc | grep dylib
diff --git a/kokoro/release/protoc/windows/build.bat b/kokoro/release/protoc/windows/build.bat
index 75ea546..50ad223 100644
--- a/kokoro/release/protoc/windows/build.bat
+++ b/kokoro/release/protoc/windows/build.bat
@@ -1,10 +1,13 @@
-set PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH%
-set generator32=Visual Studio 14
-set generator64=Visual Studio 14 Win64
+set generator32=Visual Studio 15
+set generator64=Visual Studio 15 Win64
 set vcplatform32=win32
 set vcplatform64=x64
 set configuration=Release
 
+:: VS2017 is installed, but will not be selected by default. This command sets
+:: up the environment so that CMake will find and use it:
+call "%ProgramFiles(x86)%\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
+
 echo Building protoc
 cd github\protobuf
 
@@ -15,13 +18,13 @@
 
 mkdir build32
 cd build32
-cmake -G "%generator32%" -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_UNICODE=ON ../cmake
+cmake -G "%generator32%" -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_UNICODE=ON ..
 msbuild protobuf.sln /p:Platform=%vcplatform32% || goto error
 cd ..
 
 mkdir build64
 cd build64
-cmake -G "%generator64%" -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_UNICODE=ON ../cmake
+cmake -G "%generator64%" -Dprotobuf_BUILD_TESTS=OFF -Dprotobuf_BUILD_SHARED_LIBS=OFF -Dprotobuf_UNICODE=ON ..
 msbuild protobuf.sln /p:Platform=%vcplatform64% || goto error
 cd ..
 
diff --git a/kokoro/release/python/linux/build_artifacts.sh b/kokoro/release/python/linux/build_artifacts.sh
deleted file mode 100755
index 9a3fc58..0000000
--- a/kokoro/release/python/linux/build_artifacts.sh
+++ /dev/null
@@ -1,90 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-# change to repo root
-pushd $(dirname $0)/../../../..
-
-# Create stage dir
-ORIGINAL_DIR=`pwd`
-pushd ..
-cp -R $ORIGINAL_DIR stage
-export STAGE_DIR="`pwd`/stage"
-popd
-
-export REPO_DIR=protobuf
-export BUILD_VERSION=`grep -i "version" python/google/protobuf/__init__.py | grep -o "'.*'" | tr -d "'"`
-
-export BUILD_COMMIT=`git rev-parse HEAD`
-export PLAT=x86_64
-export UNICODE_WIDTH=32
-export MACOSX_DEPLOYMENT_TARGET=10.9
-
-rm -rf artifacts/
-rm -rf multibuild/
-mkdir artifacts
-export ARTIFACT_DIR=$(pwd)/artifacts
-
-git clone https://github.com/matthew-brett/multibuild.git
-# Pin multibuild scripts at a known commit to avoid potentially unwanted future changes from
-# silently creeping in (see https://github.com/protocolbuffers/protobuf/issues/9180).
-# IMPORTANT: always pin multibuild at the same commit for:
-# - linux/build_artifacts.sh
-# - linux/build_artifacts.sh
-# - windows/build_artifacts.bat
-(cd multibuild; git checkout b89bb903e94308be79abefa4f436bf123ebb1313)
-cp kokoro/release/python/linux/config.sh config.sh
-
-build_artifact_version() {
-  MB_PYTHON_VERSION=$1
-  cp -R $STAGE_DIR $REPO_DIR
-
-  source multibuild/common_utils.sh
-  source multibuild/travis_steps.sh
-  before_install
-
-  clean_code $REPO_DIR $BUILD_COMMIT
-
-  build_wheel $REPO_DIR/python $PLAT
-
-  mv wheelhouse/* $ARTIFACT_DIR
-
-  # Clean up env
-  rm -rf venv
-  sudo rm -rf $REPO_DIR
-}
-
-build_x86_64_manylinux1_artifact_version() {
-  # Explicitly request building manylinux1 wheels, which is no longer the default.
-  # https://github.com/protocolbuffers/protobuf/issues/9180
-  MB_ML_VER=1
-  build_artifact_version $@
-}
-
-build_x86_64_manylinux2010_artifact_version() {
-  # Explicitly request building manylinux2010 wheels
-  MB_ML_VER=2010
-  build_artifact_version $@
-}
-
-build_crosscompiled_aarch64_manylinux2014_artifact_version() {
-  # crosscompilation is only supported with the dockcross manylinux2014 image
-  DOCKER_IMAGE=dockcross/manylinux2014-aarch64:20210706-65bf2dd
-  MB_ML_VER=2014
-  PLAT=aarch64
-
-  # TODO(jtatermusch): currently when crosscompiling, "auditwheel repair" will be disabled
-  # since auditwheel doesn't work for crosscomiled wheels.
-  build_artifact_version $@
-}
-
-build_x86_64_manylinux1_artifact_version 3.6
-build_x86_64_manylinux1_artifact_version 3.7
-build_x86_64_manylinux1_artifact_version 3.8
-build_x86_64_manylinux1_artifact_version 3.9
-build_x86_64_manylinux2010_artifact_version 3.10
-
-build_crosscompiled_aarch64_manylinux2014_artifact_version 3.7
-build_crosscompiled_aarch64_manylinux2014_artifact_version 3.8
-build_crosscompiled_aarch64_manylinux2014_artifact_version 3.9
-build_crosscompiled_aarch64_manylinux2014_artifact_version 3.10
diff --git a/kokoro/release/python/linux/config.sh b/kokoro/release/python/linux/config.sh
deleted file mode 100644
index 8920495..0000000
--- a/kokoro/release/python/linux/config.sh
+++ /dev/null
@@ -1,93 +0,0 @@
-# Define custom utilities
-# Test for OSX with [ -n "$IS_OSX" ]
-
-function pre_build {
-    # Any stuff that you need to do before you start building the wheels
-    # Runs in the root directory of this repository.
-    pushd protobuf
-
-    if [ "$PLAT" == "aarch64" ]
-    then
-      local configure_host_flag="--host=aarch64"
-    fi
-
-    # Build protoc and libprotobuf
-    ./autogen.sh
-    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
-    popd
-
-    popd
-}
-
-function bdist_wheel_cmd {
-    # Builds wheel with bdist_wheel, puts into wheelhouse
-    #
-    # It may sometimes be useful to use bdist_wheel for the wheel building
-    # process.  For example, versioneer has problems with versions which are
-    # fixed with bdist_wheel:
-    # https://github.com/warner/python-versioneer/issues/121
-    local abs_wheelhouse=$1
-
-    # Modify build version
-    pwd
-    ls
-
-    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
-}
-
-function build_wheel {
-    build_wheel_cmd "bdist_wheel_cmd" $@
-}
-
-function run_tests {
-    # Runs tests on installed distribution from an empty directory
-    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/linux/continuous.cfg b/kokoro/release/python/linux/continuous.cfg
deleted file mode 100644
index c0b9a01..0000000
--- a/kokoro/release/python/linux/continuous.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-# Config file for running tests in Kokoro
-build_file: "protobuf/kokoro/release/python/linux/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
diff --git a/kokoro/release/python/linux/presubmit.cfg b/kokoro/release/python/linux/presubmit.cfg
deleted file mode 100644
index c0b9a01..0000000
--- a/kokoro/release/python/linux/presubmit.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-# Config file for running tests in Kokoro
-build_file: "protobuf/kokoro/release/python/linux/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
diff --git a/kokoro/release/python/macos/build_artifacts.sh b/kokoro/release/python/macos/build_artifacts.sh
deleted file mode 100755
index d79d2f6..0000000
--- a/kokoro/release/python/macos/build_artifacts.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-#!/bin/bash
-
-set -ex
-
-# Remove any pre-existing protobuf installation.
-brew uninstall -f protobuf
-
-# change to repo root
-pushd $(dirname $0)/../../../..
-
-# Create stage dir
-ORIGINAL_DIR=`pwd`
-pushd ..
-cp -R $ORIGINAL_DIR stage
-export STAGE_DIR="`pwd`/stage"
-popd
-
-export REPO_DIR=protobuf
-export BUILD_VERSION=`grep -i "version" python/google/protobuf/__init__.py | grep -o "'.*'" | tr -d "'"`
-export BUILD_COMMIT=`git rev-parse HEAD`
-export PLAT=x86_64
-export UNICODE_WIDTH=32
-export MACOSX_DEPLOYMENT_TARGET=10.9
-export TRAVIS_OS_NAME="osx"
-
-rm -rf artifacts/
-rm -rf multibuild/
-mkdir artifacts
-export ARTIFACT_DIR=$(pwd)/artifacts
-
-git clone https://github.com/matthew-brett/multibuild.git
-# Pin multibuild scripts at a known commit to avoid potentially unwanted future changes from
-# silently creeping in (see https://github.com/protocolbuffers/protobuf/issues/9180).
-# IMPORTANT: always pin multibuild at the same commit for:
-# - linux/build_artifacts.sh
-# - linux/build_artifacts.sh
-# - windows/build_artifacts.bat
-(cd multibuild; git checkout b89bb903e94308be79abefa4f436bf123ebb1313)
-cp kokoro/release/python/macos/config.sh config.sh
-
-OLD_PATH=$PATH
-
-build_artifact_version() {
-  MB_PYTHON_VERSION=$1
-
-  # Clean up env
-  rm -rf venv
-  sudo rm -rf $REPO_DIR
-  cp -R $STAGE_DIR $REPO_DIR
-  export PATH=$OLD_PATH
-
-  source multibuild/common_utils.sh
-  source multibuild/travis_steps.sh
-  before_install
-
-  clean_code $REPO_DIR $BUILD_COMMIT
-
-  build_wheel $REPO_DIR/python $PLAT
-
-  mv wheelhouse/* $ARTIFACT_DIR
-}
-
-export MB_PYTHON_OSX_VER=10.9
-build_artifact_version 3.7
-build_artifact_version 3.8
-build_artifact_version 3.9
-build_artifact_version 3.10
diff --git a/kokoro/release/python/macos/config.sh b/kokoro/release/python/macos/config.sh
deleted file mode 100644
index 74e6569..0000000
--- a/kokoro/release/python/macos/config.sh
+++ /dev/null
@@ -1,67 +0,0 @@
-# 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.
-    pushd protobuf
-
-    # Build protoc and protobuf libraries
-    bazel build //:protoc
-    export PROTOC=$PWD/bazel-bin/protoc
-    mkdir src/.libs
-    ln -s $PWD/bazel-bin/libprotobuf.a src/.libs/libprotobuf.a
-    ln -s $PWD/bazel-bin/libprotobuf_lite.a src/.libs/libprotobuf-lite.a
-
-    # Generate python dependencies.
-    pushd python
-    python setup.py build_py
-    popd
-
-    popd
-}
-
-function bdist_wheel_cmd {
-    # Builds wheel with bdist_wheel, puts into wheelhouse
-    #
-    # It may sometimes be useful to use bdist_wheel for the wheel building
-    # process.  For example, versioneer has problems with versions which are
-    # fixed with bdist_wheel:
-    # https://github.com/warner/python-versioneer/issues/121
-    local abs_wheelhouse=$1
-
-    # Modify build version
-    pwd
-    ls
-    python setup.py bdist_wheel --cpp_implementation --compile_static_extension
-    cp dist/*.whl $abs_wheelhouse
-}
-
-function build_wheel {
-    build_wheel_cmd "bdist_wheel_cmd" $@
-}
-
-function run_tests {
-    # Runs tests on installed distribution from an empty directory
-    python --version
-    python -c "from google.protobuf.pyext import _message;"
-}
diff --git a/kokoro/release/python/macos/presubmit.cfg b/kokoro/release/python/macos/presubmit.cfg
deleted file mode 100644
index 85cf81b..0000000
--- a/kokoro/release/python/macos/presubmit.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-# Configuration for Mac OSX release builds
-build_file: "protobuf/kokoro/release/python/macos/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
diff --git a/kokoro/release/python/macos/release.cfg b/kokoro/release/python/macos/release.cfg
deleted file mode 100644
index 85cf81b..0000000
--- a/kokoro/release/python/macos/release.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-# Configuration for Mac OSX release builds
-build_file: "protobuf/kokoro/release/python/macos/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
diff --git a/kokoro/release/python/windows/build_artifacts.bat b/kokoro/release/python/windows/build_artifacts.bat
deleted file mode 100644
index 121283a..0000000
--- a/kokoro/release/python/windows/build_artifacts.bat
+++ /dev/null
@@ -1,88 +0,0 @@
-REM Move scripts to root
-set REPO_DIR_STAGE=%cd%\github\protobuf-stage
-xcopy /S  github\protobuf "%REPO_DIR_STAGE%\"
-cd github\protobuf
-copy kokoro\release\python\windows\build_single_artifact.bat build_single_artifact.bat
-
-REM Set environment variables
-set PACKAGE_NAME=protobuf
-set REPO_DIR=protobuf
-set BUILD_DLL=OFF
-set UNICODE=ON
-set OTHER_TEST_DEP="setuptools==38.5.1"
-set OLD_PATH=C:\Program Files (x86)\MSBuild\14.0\bin\;%PATH%
-
-REM Fetch multibuild
-git clone https://github.com/matthew-brett/multibuild.git
-REM Pin multibuild scripts at a known commit to avoid potentially unwanted future changes from
-REM silently creeping in (see https://github.com/protocolbuffers/protobuf/issues/9180).
-REM IMPORTANT: always pin multibuild at the same commit for:
-REM - linux/build_artifacts.sh
-REM - linux/build_artifacts.sh
-REM - windows/build_artifacts.bat
-cd multibuild
-git checkout b89bb903e94308be79abefa4f436bf123ebb1313
-cd ..
-
-REM Install zlib
-mkdir zlib
-curl -L -o zlib.zip http://www.winimage.com/zLibDll/zlib123dll.zip
-curl -L -o zlib-src.zip http://www.winimage.com/zLibDll/zlib123.zip
-7z x zlib.zip -ozlib
-7z x zlib-src.zip -ozlib\include
-SET ZLIB_ROOT=%cd%\zlib
-del /Q zlib.zip
-del /Q zlib-src.zip
-
-REM Create directory for artifacts
-SET ARTIFACT_DIR=%cd%\artifacts
-mkdir %ARTIFACT_DIR%
-
-REM Build wheel
-
-SET PYTHON=C:\python37_32bit
-SET PYTHON_VERSION=3.7
-SET PYTHON_ARCH=32
-CALL build_single_artifact.bat || goto :error
-
-SET PYTHON=C:\python37
-SET PYTHON_VERSION=3.7
-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
-CALL build_single_artifact.bat || goto :error
-
-SET PYTHON=C:\python38
-SET PYTHON_VERSION=3.8
-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
-
-SET PYTHON=C:\python310_32bit
-SET PYTHON_VERSION=3.10
-SET PYTHON_ARCH=32
-CALL build_single_artifact.bat || goto :error
-
-SET PYTHON=C:\python310
-SET PYTHON_VERSION=3.10
-SET PYTHON_ARCH=64
-CALL build_single_artifact.bat || goto :error
-
-goto :EOF
-
-:error
-exit /b %errorlevel%
diff --git a/kokoro/release/python/windows/build_single_artifact.bat b/kokoro/release/python/windows/build_single_artifact.bat
deleted file mode 100644
index af2d265..0000000
--- a/kokoro/release/python/windows/build_single_artifact.bat
+++ /dev/null
@@ -1,78 +0,0 @@
-setlocal
-
-if %PYTHON%==C:\python37_32bit set generator=Visual Studio 14
-if %PYTHON%==C:\python37_32bit set vcplatform=Win32
-
-if %PYTHON%==C:\python37 set generator=Visual Studio 14 Win64
-if %PYTHON%==C:\python37 set vcplatform=x64
-
-if %PYTHON%==C:\python38_32bit set generator=Visual Studio 14
-if %PYTHON%==C:\python38_32bit set vcplatform=Win32
-
-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
-
-if %PYTHON%==C:\python310_32bit set generator=Visual Studio 14
-if %PYTHON%==C:\python310_32bit set vcplatform=Win32
-
-if %PYTHON%==C:\python310 set generator=Visual Studio 14 Win64
-if %PYTHON%==C:\python310 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=C:\Program Files\CMake\bin;%PYTHON%;%PYTHON%\Scripts;%OLD_PATH%
-python -m pip install -U pip
-pip install wheel
-
-REM Check that we have the expected version and architecture for Python
-python --version
-python -c "import struct; print(struct.calcsize('P') * 8)"
-
-rmdir /s/q %REPO_DIR%
-xcopy /s  %REPO_DIR_STAGE% "%REPO_DIR%\"
-
-REM Checkout release commit
-cd %REPO_DIR%
-
-REM ======================
-REM Build Protobuf Library
-REM ======================
-
-mkdir src\.libs
-
-mkdir vcprojects
-pushd vcprojects
-cmake -G "%generator%" -Dprotobuf_BUILD_SHARED_LIBS=%BUILD_DLL% -Dprotobuf_UNICODE=%UNICODE% -Dprotobuf_BUILD_TESTS=OFF ../cmake || goto :error
-msbuild protobuf.sln /p:Platform=%vcplatform% /p:Configuration=Release || goto :error
-dir /s /b
-popd
-copy vcprojects\Release\libprotobuf.lib src\.libs\libprotobuf.a
-copy vcprojects\Release\libprotobuf-lite.lib src\.libs\libprotobuf-lite.a
-SET PATH=%cd%\vcprojects\Release;%PATH%
-dir vcprojects\Release
-
-REM ======================
-REM Build python library
-REM ======================
-
-cd python
-
-REM sed -i 's/\ extra_compile_args\ =\ \[\]/\ extra_compile_args\ =\ \[\'\/MT\'\]/g' setup.py
-
-python setup.py bdist_wheel --cpp_implementation --compile_static_extension
-dir dist
-copy dist\* %ARTIFACT_DIR%
-dir %ARTIFACT_DIR%
-cd ..\..
-
-goto :EOF
-
-:error
-exit /b %errorlevel%
diff --git a/kokoro/release/python/windows/continuous.cfg b/kokoro/release/python/windows/continuous.cfg
deleted file mode 100644
index 5261606..0000000
--- a/kokoro/release/python/windows/continuous.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-# Configuration for Windows protoc release builds
-build_file: "protobuf/kokoro/release/python/windows/build_artifacts.bat"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
diff --git a/kokoro/release/python/windows/install_python_interpreters.ps1 b/kokoro/release/python/windows/install_python_interpreters.ps1
deleted file mode 100644
index 3f8db95..0000000
--- a/kokoro/release/python/windows/install_python_interpreters.ps1
+++ /dev/null
@@ -1,114 +0,0 @@
-#!/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
-
-# Python 3.10
-$Python310x86Config = @{
-    PythonVersion = "3.10.0"
-    PythonInstaller = "python-3.10.0"
-    PythonInstallPath = "C:\python310_32bit"
-    PythonInstallerHash = "133aa48145032e341ad2a000cd3bff50"
-}
-Install-Python @Python310x86Config
-
-$Python310x64Config = @{
-    PythonVersion = "3.10.0"
-    PythonInstaller = "python-3.10.0-amd64"
-    PythonInstallPath = "C:\python310"
-    PythonInstallerHash = "c3917c08a7fe85db7203da6dcaa99a70"
-}
-Install-Python @Python310x64Config
diff --git a/kokoro/release/python/windows/presubmit.cfg b/kokoro/release/python/windows/presubmit.cfg
deleted file mode 100644
index 5261606..0000000
--- a/kokoro/release/python/windows/presubmit.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-# Configuration for Windows protoc release builds
-build_file: "protobuf/kokoro/release/python/windows/build_artifacts.bat"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
diff --git a/kokoro/release/python/windows/release.cfg b/kokoro/release/python/windows/release.cfg
deleted file mode 100644
index 5261606..0000000
--- a/kokoro/release/python/windows/release.cfg
+++ /dev/null
@@ -1,8 +0,0 @@
-# Configuration for Windows protoc release builds
-build_file: "protobuf/kokoro/release/python/windows/build_artifacts.bat"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
diff --git a/kokoro/release/python/linux/release.cfg b/kokoro/release/ruby/linux/common.cfg
similarity index 62%
rename from kokoro/release/python/linux/release.cfg
rename to kokoro/release/ruby/linux/common.cfg
index b31b3f1..dbc71b2 100644
--- a/kokoro/release/python/linux/release.cfg
+++ b/kokoro/release/ruby/linux/common.cfg
@@ -1,5 +1,5 @@
 # Configuration for Linux release builds
-build_file: "protobuf/kokoro/release/python/linux/build_artifacts.sh"
+build_file: "protobuf/kokoro/release/ruby/linux/build_artifacts.sh"
 
 action {
   define_artifacts {
diff --git a/kokoro/release/ruby/linux/continuous.cfg b/kokoro/release/ruby/linux/continuous.cfg
index dbc71b2..8523c22 100644
--- a/kokoro/release/ruby/linux/continuous.cfg
+++ b/kokoro/release/ruby/linux/continuous.cfg
@@ -1,8 +1 @@
-# Configuration for Linux release builds
-build_file: "protobuf/kokoro/release/ruby/linux/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/release/ruby/linux/presubmit.cfg b/kokoro/release/ruby/linux/presubmit.cfg
index dbc71b2..8523c22 100644
--- a/kokoro/release/ruby/linux/presubmit.cfg
+++ b/kokoro/release/ruby/linux/presubmit.cfg
@@ -1,8 +1 @@
-# Configuration for Linux release builds
-build_file: "protobuf/kokoro/release/ruby/linux/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/release/ruby/linux/ruby/ruby_build.sh b/kokoro/release/ruby/linux/ruby/ruby_build.sh
index 761b54f..34a85ab 100755
--- a/kokoro/release/ruby/linux/ruby/ruby_build.sh
+++ b/kokoro/release/ruby/linux/ruby/ruby_build.sh
@@ -5,8 +5,13 @@
 # Build protoc
 use_bazel.sh 5.1.1
 bazel build //:protoc
-cp bazel-bin/protoc src/protoc
-export PROTOC=$PWD/src/protoc
+
+# The java build setup expects protoc in the root directory.
+cp bazel-bin/protoc .
+export PROTOC=$PWD/protoc
+
+# Pull in dependencies.
+git submodule update --init --recursive
 
 umask 0022
 pushd ruby
diff --git a/kokoro/release/python/macos/continuous.cfg b/kokoro/release/ruby/macos/common.cfg
similarity index 63%
rename from kokoro/release/python/macos/continuous.cfg
rename to kokoro/release/ruby/macos/common.cfg
index 85cf81b..cb1c08b 100644
--- a/kokoro/release/python/macos/continuous.cfg
+++ b/kokoro/release/ruby/macos/common.cfg
@@ -1,5 +1,5 @@
 # Configuration for Mac OSX release builds
-build_file: "protobuf/kokoro/release/python/macos/build_artifacts.sh"
+build_file: "protobuf/kokoro/release/ruby/macos/build_artifacts.sh"
 
 action {
   define_artifacts {
diff --git a/kokoro/release/ruby/macos/continuous.cfg b/kokoro/release/ruby/macos/continuous.cfg
index cb1c08b..8523c22 100644
--- a/kokoro/release/ruby/macos/continuous.cfg
+++ b/kokoro/release/ruby/macos/continuous.cfg
@@ -1,8 +1 @@
-# Configuration for Mac OSX release builds
-build_file: "protobuf/kokoro/release/ruby/macos/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/release/ruby/macos/presubmit.cfg b/kokoro/release/ruby/macos/presubmit.cfg
index cb1c08b..8523c22 100644
--- a/kokoro/release/ruby/macos/presubmit.cfg
+++ b/kokoro/release/ruby/macos/presubmit.cfg
@@ -1,8 +1 @@
-# Configuration for Mac OSX release builds
-build_file: "protobuf/kokoro/release/ruby/macos/build_artifacts.sh"
-
-action {
-  define_artifacts {
-    regex: "github/protobuf/artifacts/**"
-  }
-}
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/release/ruby/macos/ruby/ruby_build.sh b/kokoro/release/ruby/macos/ruby/ruby_build.sh
index bbfc631..d13c120 100755
--- a/kokoro/release/ruby/macos/ruby/ruby_build.sh
+++ b/kokoro/release/ruby/macos/ruby/ruby_build.sh
@@ -6,6 +6,9 @@
 bazel build //:protoc
 export PROTOC=$PWD/bazel-bin/protoc
 
+# Pull in dependencies.
+git submodule update --init --recursive
+
 umask 0022
 pushd ruby
 bundle update && bundle exec rake gem:native
diff --git a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
index 2906642..4002d6d 100755
--- a/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
+++ b/kokoro/release/ruby/macos/ruby/ruby_build_environment.sh
@@ -8,13 +8,9 @@
 
 set +ex  # rvm script is very verbose and exits with errorcode
 
-curl -sSL https://rvm.io/mpapis.asc | gpg --import -
-curl -sSL https://rvm.io/pkuczynski.asc | gpg --import -
-
-# Old OpenSSL versions cannot handle the SSL certificate used by
-# https://get.rvm.io, so as a workaround we download RVM directly from
-# GitHub. See this issue for details: https://github.com/rvm/rvm/issues/5133
-curl -sSL https://raw.githubusercontent.com/rvm/rvm/master/binscripts/rvm-installer | bash -s master --ruby
+# Fix permissions
+sudo chown -R $(whoami) $HOME/.rvm/
+sudo chown -R $(whoami) /Library/Ruby/
 
 source $HOME/.rvm/scripts/rvm
 set -e  # rvm commands are very verbose
diff --git a/kokoro/windows/bazel/build.bat b/kokoro/windows/bazel/build.bat
new file mode 100644
index 0000000..a783a07
--- /dev/null
+++ b/kokoro/windows/bazel/build.bat
@@ -0,0 +1,41 @@
+@rem enter repo root
+cd /d %~dp0\..\..\..
+
+call kokoro\windows\prepare_build_win64.bat || goto :error
+
+@rem Allow Bazel to create short paths.
+fsutil 8dot3name set 0
+
+@rem TODO(b/241475022) Use docker to guarantee better stability.
+
+@rem Reinstall Bazel due to corrupt installation in kokoro.
+bazel version
+choco install bazel -y -i --version 5.1.0
+bazel version
+
+@rem Set invocation ID so that bazel run is known to kokoro
+uuidgen > %KOKORO_ARTIFACTS_DIR%\bazel_invocation_ids
+SET /p BAZEL_INTERNAL_INVOCATION_ID=<%KOKORO_ARTIFACTS_DIR%\bazel_invocation_ids
+
+@rem Make paths as short as possible to avoid long path issues.
+set BAZEL_STARTUP=--output_user_root=C:/tmp --windows_enable_symlinks
+set BAZEL_FLAGS=--enable_runfiles --keep_going --test_output=errors ^
+  --verbose_failures ^
+  --invocation_id=%BAZEL_INTERNAL_INVOCATION_ID% ^
+  --google_credentials=%KOKORO_BAZEL_AUTH_CREDENTIAL%  ^
+  --remote_cache=https://storage.googleapis.com/protobuf-bazel-cache/%KOKORO_JOB_NAME%
+
+@rem Build libraries first.
+bazel %BAZEL_STARTUP% build //:protoc //:protobuf //:protobuf_lite %BAZEL_FLAGS% || goto :error
+
+@rem Run C++ tests.
+@rem TODO(b/241484899) Enable conformance tests on windows.
+bazel %BAZEL_STARTUP% test %BAZEL_FLAGS% ^
+  --test_tag_filters=-conformance --build_tag_filters=-conformance ^
+  //src/...  @com_google_protobuf_examples//... || goto :error
+
+goto :EOF
+
+:error
+echo Failed!
+exit /b 1
diff --git a/kokoro/windows/bazel/common.cfg b/kokoro/windows/bazel/common.cfg
new file mode 100644
index 0000000..52703cc
--- /dev/null
+++ b/kokoro/windows/bazel/common.cfg
@@ -0,0 +1,27 @@
+# Config file for running tests in Kokoro
+
+# Location of the build script in repository
+build_file: "protobuf/kokoro/windows/bazel/build.bat"
+timeout_mins: 1440
+
+before_action {
+  fetch_keystore {
+    keystore_resource {
+      keystore_config_id: 77103
+      keyname: "kokoro_gcp_service"
+    }
+  }
+}
+bazel_setting {
+  project_id: "protobuf-build"
+  bes_backend_address: "buildeventservice.googleapis.com"
+  foundry_backend_address: "remotebuildexecution.googleapis.com"
+  upsalite_frontend_address: "https://source.cloud.google.com"
+  local_execution: true
+
+  # Need to be same as the fetch_keystore entry in the previous step.
+  auth_credential: {
+    keystore_config_id: 77103
+    keyname: "kokoro_gcp_service"
+  }
+}
diff --git a/kokoro/windows/bazel/continuous.cfg b/kokoro/windows/bazel/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/bazel/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/bazel/presubmit.cfg b/kokoro/windows/bazel/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/bazel/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/cmake/build.bat b/kokoro/windows/cmake/build.bat
new file mode 100644
index 0000000..d24e635
--- /dev/null
+++ b/kokoro/windows/cmake/build.bat
@@ -0,0 +1,33 @@
+@rem enter repo root
+cd /d %~dp0\..\..\..
+
+call kokoro\windows\prepare_build_win64.bat || goto :error
+
+@rem TODO(b/241475022) Use docker to guarantee better stability.
+@rem TODO(b/241484899) Run conformance tests in windows.
+
+md build
+md %KOKORO_ARTIFACTS_DIR%\logs
+
+cd build
+
+cmake .. ^
+	-G "Visual Studio 15 2017" -A x64 ^
+  -Dprotobuf_BUILD_EXAMPLES=ON ^
+	-Dprotobuf_BUILD_CONFORMANCE=OFF ^
+	-Dprotobuf_WITH_ZLIB=OFF ^
+	-Dprotobuf_TEST_XML_OUTDIR=%KOKORO_ARTIFACTS_DIR%\logs\ || goto :error
+
+cmake --build . || goto :error
+
+ctest --verbose -C Debug || goto :error
+
+goto :success
+
+:error
+cd /d %~dp0\..\..\..
+echo Failed!
+exit /b 1
+
+:success
+cd ..
diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/windows/cmake/common.cfg
similarity index 65%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/windows/cmake/common.cfg
index 9a71745..37e89e0 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/windows/cmake/common.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh"
+build_file: "protobuf/kokoro/windows/cmake/build.bat"
 timeout_mins: 1440
diff --git a/kokoro/windows/cmake/continuous.cfg b/kokoro/windows/cmake/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/cmake/presubmit.cfg b/kokoro/windows/cmake/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/cmake_install/build.bat b/kokoro/windows/cmake_install/build.bat
new file mode 100644
index 0000000..c5878de
--- /dev/null
+++ b/kokoro/windows/cmake_install/build.bat
@@ -0,0 +1,45 @@
+@rem enter repo root
+cd /d %~dp0\..\..\..
+
+call kokoro\windows\prepare_build_win64.bat || goto :error
+
+@rem TODO(b/241475022) Use docker to guarantee better stability.
+@rem TODO(b/241484899) Run conformance tests in windows.
+
+md build
+md %KOKORO_ARTIFACTS_DIR%\logs
+
+cd build
+
+@rem First install protobuf from source.
+cmake .. ^
+	-G "Visual Studio 15 2017" -A x64  ^
+	-Dprotobuf_BUILD_CONFORMANCE=OFF ^
+	-Dprotobuf_WITH_ZLIB=OFF || goto :error
+
+cmake --build . --target install || goto :error
+
+@rem Next run tests forcing the use of our installation.
+
+rm -rf *
+
+cmake .. ^
+	-G "Visual Studio 15 2017" -A x64 ^
+	-Dprotobuf_REMOVE_INSTALLED_HEADERS=ON ^
+  	-Dprotobuf_BUILD_PROTOBUF_BINARIES=OFF ^
+	-Dprotobuf_BUILD_CONFORMANCE=OFF ^
+	-Dprotobuf_TEST_XML_OUTDIR=%KOKORO_ARTIFACTS_DIR%\logs\ || goto :error
+
+cmake --build . --target ALL_BUILD || goto :error
+
+ctest --verbose -C Debug || goto :error
+
+goto :success
+
+:error
+cd /d %~dp0\..\..\..
+echo Failed!
+exit /b 1
+
+:success
+cd ..
diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/windows/cmake_install/common.cfg
similarity index 62%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/windows/cmake_install/common.cfg
index 9a71745..2efc0dc 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/windows/cmake_install/common.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh"
+build_file: "protobuf/kokoro/windows/cmake_install/build.bat"
 timeout_mins: 1440
diff --git a/kokoro/windows/cmake_install/continuous.cfg b/kokoro/windows/cmake_install/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake_install/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/cmake_install/presubmit.cfg b/kokoro/windows/cmake_install/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake_install/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/cmake_shared/build.bat b/kokoro/windows/cmake_shared/build.bat
new file mode 100644
index 0000000..d4bb2b1
--- /dev/null
+++ b/kokoro/windows/cmake_shared/build.bat
@@ -0,0 +1,33 @@
+@rem enter repo root
+cd /d %~dp0\..\..\..
+
+call kokoro\windows\prepare_build_win64.bat || goto :error
+
+@rem TODO(b/241475022) Use docker to guarantee better stability.
+@rem TODO(b/241484899) Run conformance tests in windows.
+
+md build
+md %KOKORO_ARTIFACTS_DIR%\logs
+
+cd build
+
+cmake .. ^
+	-G "Visual Studio 15 2017" -A x64  ^
+	-Dprotobuf_BUILD_SHARED_LIBS=ON ^
+	-Dprotobuf_BUILD_CONFORMANCE=OFF ^
+	-Dprotobuf_WITH_ZLIB=OFF ^
+	-Dprotobuf_TEST_XML_OUTDIR=%KOKORO_ARTIFACTS_DIR%\logs\ || goto :error
+
+cmake --build . || goto :error
+
+ctest --verbose -C Debug || goto :error
+
+goto :success
+
+:error
+cd /d %~dp0\..\..\..
+echo Failed!
+exit /b 1
+
+:success
+cd ..
diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/windows/cmake_shared/common.cfg
similarity index 63%
copy from kokoro/macos/php7.3_mac/continuous.cfg
copy to kokoro/windows/cmake_shared/common.cfg
index 9a71745..0ba52e2 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/windows/cmake_shared/common.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh"
+build_file: "protobuf/kokoro/windows/cmake_shared/build.bat"
 timeout_mins: 1440
diff --git a/kokoro/windows/cmake_shared/continuous.cfg b/kokoro/windows/cmake_shared/continuous.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake_shared/continuous.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/cmake_shared/presubmit.cfg b/kokoro/windows/cmake_shared/presubmit.cfg
new file mode 100644
index 0000000..8523c22
--- /dev/null
+++ b/kokoro/windows/cmake_shared/presubmit.cfg
@@ -0,0 +1 @@
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/macos/php7.3_mac/continuous.cfg b/kokoro/windows/csharp/common.cfg
similarity index 65%
rename from kokoro/macos/php7.3_mac/continuous.cfg
rename to kokoro/windows/csharp/common.cfg
index 9a71745..f586585 100644
--- a/kokoro/macos/php7.3_mac/continuous.cfg
+++ b/kokoro/windows/csharp/common.cfg
@@ -1,5 +1,5 @@
 # Config file for running tests in Kokoro
 
 # Location of the build script in repository
-build_file: "protobuf/kokoro/macos/php7.3_mac/build.sh"
+build_file: "protobuf/kokoro/windows/csharp/build.bat"
 timeout_mins: 1440
diff --git a/kokoro/windows/csharp/continuous.cfg b/kokoro/windows/csharp/continuous.cfg
index f586585..8523c22 100644
--- a/kokoro/windows/csharp/continuous.cfg
+++ b/kokoro/windows/csharp/continuous.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/windows/csharp/build.bat"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/csharp/presubmit.cfg b/kokoro/windows/csharp/presubmit.cfg
index f586585..8523c22 100644
--- a/kokoro/windows/csharp/presubmit.cfg
+++ b/kokoro/windows/csharp/presubmit.cfg
@@ -1,5 +1 @@
-# Config file for running tests in Kokoro
-
-# Location of the build script in repository
-build_file: "protobuf/kokoro/windows/csharp/build.bat"
-timeout_mins: 1440
+# Keep this file empty! Use common.cfg instead.
diff --git a/kokoro/windows/prepare_build_win64.bat b/kokoro/windows/prepare_build_win64.bat
new file mode 100644
index 0000000..07db865
--- /dev/null
+++ b/kokoro/windows/prepare_build_win64.bat
@@ -0,0 +1,21 @@
+@rem Update Chocolatey
+choco upgrade -y --no-progress chocolatey
+choco install -y python --version 3.10.0
+choco install -y --no-progress --pre cmake
+
+@rem Enable long paths.
+Powershell.exe -Command "New-ItemProperty -Path HKLM:\SYSTEM\CurrentControlSet\Control\FileSystem -Name LongPathsEnabled -Value 1 -PropertyType DWORD -Force"
+
+@rem Update git submodules.
+git submodule update --init --recursive
+
+@rem Select Visual Studio 2017.
+call "C:\Program Files (x86)\Microsoft Visual Studio\2017\Community\VC\Auxiliary\Build\vcvarsall.bat" x64
+
+@rem Convert Windows line breaks to Unix line breaks
+@rem This allows text-matching tests to pass
+@find . -type f -print0 | xargs -0 d2u
+
+@rem Use python3
+C:\python310\python.exe -m venv venv
+call venv\Scripts\activate.bat
\ No newline at end of file
diff --git a/m4/ac_system_extensions.m4 b/m4/ac_system_extensions.m4
deleted file mode 100644
index 1ca2eeb..0000000
--- a/m4/ac_system_extensions.m4
+++ /dev/null
@@ -1,37 +0,0 @@
-dnl Provide AC_USE_SYSTEM_EXTENSIONS for old autoconf machines.
-AC_DEFUN([ACX_USE_SYSTEM_EXTENSIONS],[
-  ifdef([AC_USE_SYSTEM_EXTENSIONS],[
-    AC_USE_SYSTEM_EXTENSIONS
-  ],[
-    AC_BEFORE([$0], [AC_COMPILE_IFELSE])
-    AC_BEFORE([$0], [AC_RUN_IFELSE])
-
-    AC_REQUIRE([AC_GNU_SOURCE])
-    AC_REQUIRE([AC_AIX])
-    AC_REQUIRE([AC_MINIX])
-
-    AH_VERBATIM([__EXTENSIONS__],
-[/* Enable extensions on Solaris.  */
-#ifndef __EXTENSIONS__
-# undef __EXTENSIONS__
-#endif
-#ifndef _POSIX_PTHREAD_SEMANTICS
-# undef _POSIX_PTHREAD_SEMANTICS
-#endif
-#ifndef _TANDEM_SOURCE
-# undef _TANDEM_SOURCE
-#endif])
-    AC_CACHE_CHECK([whether it is safe to define __EXTENSIONS__],
-      [ac_cv_safe_to_define___extensions__],
-      [AC_COMPILE_IFELSE(
-         [AC_LANG_PROGRAM([
-#           define __EXTENSIONS__ 1
-            AC_INCLUDES_DEFAULT])],
-         [ac_cv_safe_to_define___extensions__=yes],
-         [ac_cv_safe_to_define___extensions__=no])])
-    test $ac_cv_safe_to_define___extensions__ = yes &&
-      AC_DEFINE([__EXTENSIONS__])
-    AC_DEFINE([_POSIX_PTHREAD_SEMANTICS])
-    AC_DEFINE([_TANDEM_SOURCE])
-  ])
-])
diff --git a/m4/acx_check_suncc.m4 b/m4/acx_check_suncc.m4
deleted file mode 100644
index 0a9a577..0000000
--- a/m4/acx_check_suncc.m4
+++ /dev/null
@@ -1,73 +0,0 @@
-dnl Check for the presence of the Sun Studio compiler.
-dnl If Sun Studio compiler is found, set appropriate flags.
-dnl Additionally, Sun Studio doesn't default to 64-bit by itself,
-dnl nor does it automatically look in standard Solaris places for
-dnl 64-bit libs, so we must add those options and paths to the search
-dnl paths.
-
-dnl TODO(kenton):  This is pretty hacky.  It sets CXXFLAGS, which the autoconf
-dnl docs say should never be overridden except by the user.  It also isn't
-dnl cross-compile safe.  We should fix these problems, but since I don't have
-dnl Sun CC at my disposal for testing, someone else will have to do it.
-
-AC_DEFUN([ACX_CHECK_SUNCC],[
-
-  AC_LANG_PUSH([C++])
-  AC_CHECK_DECL([__SUNPRO_CC], [SUNCC="yes"], [SUNCC="no"])
-  AC_LANG_POP()
-
-
-  AC_ARG_ENABLE([64bit-solaris],
-    [AS_HELP_STRING([--disable-64bit-solaris],
-      [Build 64 bit binary on Solaris @<:@default=on@:>@])],
-             [ac_enable_64bit="$enableval"],
-             [ac_enable_64bit="yes"])
-
-  AS_IF([test "$SUNCC" = "yes" -a "x${ac_cv_env_CXXFLAGS_set}" = "x"],[
-    dnl Sun Studio has a crashing bug with -xO4 in some cases. Keep this
-    dnl at -xO3 until a proper test to detect those crashes can be done.
-    CXXFLAGS="-g0 -xO3 -xlibmil -xdepend -xbuiltin -mt -template=no%extdef ${CXXFLAGS}"
-  ])
-
-  case $host_os in
-    *solaris*)
-      AC_CHECK_PROGS(ISAINFO, [isainfo], [no])
-      AS_IF([test "x$ISAINFO" != "xno"],
-            [isainfo_b=`${ISAINFO} -b`],
-            [isainfo_b="x"])
-
-      AS_IF([test "$isainfo_b" != "x"],[
-
-        isainfo_k=`${ISAINFO} -k`
-
-        AS_IF([test "x$ac_enable_64bit" = "xyes"],[
-
-          AS_IF([test "x$libdir" = "x\${exec_prefix}/lib"],[
-           dnl The user hasn't overridden the default libdir, so we'll
-           dnl the dir suffix to match solaris 32/64-bit policy
-           libdir="${libdir}/${isainfo_k}"
-          ])
-
-          dnl This should just be set in CPPFLAGS and in LDFLAGS, but libtool
-          dnl does the wrong thing if you don't put it into CXXFLAGS. sigh.
-          dnl (It also needs it in CFLAGS, or it does a different wrong thing!)
-          CXXFLAGS="${CXXFLAGS} -m64"
-          ac_cv_env_CXXFLAGS_set=set
-          ac_cv_env_CXXFLAGS_value='-m64'
-
-          CFLAGS="${CFLAGS} -m64"
-          ac_cv_env_CFLAGS_set=set
-          ac_cv_env_CFLAGS_value='-m64'
-
-          AS_IF([test "$target_cpu" = "sparc" -a "x$SUNCC" = "xyes" ],[
-            CXXFLAGS="-xmemalign=8s ${CXXFLAGS}"
-          ])
-        ])
-      ])
-    ;;
-  esac
-
-  AS_IF([test "$target_cpu" = "sparc" -a "x$SUNCC" = "xyes" ],[
-    CXXFLAGS="-xregs=no%appl ${CXXFLAGS}"
-  ])
-])
diff --git a/m4/ax_cxx_compile_stdcxx.m4 b/m4/ax_cxx_compile_stdcxx.m4
deleted file mode 100644
index d3288e2..0000000
--- a/m4/ax_cxx_compile_stdcxx.m4
+++ /dev/null
@@ -1,1001 +0,0 @@
-# ===========================================================================
-#   http://www.gnu.org/software/autoconf-archive/ax_cxx_compile_stdcxx.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   AX_CXX_COMPILE_STDCXX(VERSION, [ext|noext], [mandatory|optional])
-#
-# DESCRIPTION
-#
-#   Check for baseline language coverage in the compiler for the specified
-#   version of the C++ standard.  If necessary, add switches to CXX and
-#   CXXCPP to enable support.  VERSION may be '11' (for the C++11 standard)
-#   or '14' (for the C++14 standard).
-#
-#   The second argument, if specified, indicates whether you insist on an
-#   extended mode (e.g. -std=gnu++11) or a strict conformance mode (e.g.
-#   -std=c++11).  If neither is specified, you get whatever works, with
-#   preference for an extended mode.
-#
-#   The third argument, if specified 'mandatory' or if left unspecified,
-#   indicates that baseline support for the specified C++ standard is
-#   required and that the macro should error out if no mode with that
-#   support is found.  If specified 'optional', then configuration proceeds
-#   regardless, after defining HAVE_CXX${VERSION} if and only if a
-#   supporting mode is found.
-#
-# LICENSE
-#
-#   Copyright (c) 2008 Benjamin Kosnik <bkoz@redhat.com>
-#   Copyright (c) 2012 Zack Weinberg <zackw@panix.com>
-#   Copyright (c) 2013 Roy Stogner <roystgnr@ices.utexas.edu>
-#   Copyright (c) 2014, 2015 Google Inc.; contributed by Alexey Sokolov <sokolov@google.com>
-#   Copyright (c) 2015 Paul Norman <penorman@mac.com>
-#   Copyright (c) 2015 Moritz Klammler <moritz@klammler.eu>
-#   Copyright (c) 2016 Krzesimir Nowak <qdlacz@gmail.com>
-#
-#   Copying and distribution of this file, with or without modification, are
-#   permitted in any medium without royalty provided the copyright notice
-#   and this notice are preserved.  This file is offered as-is, without any
-#   warranty.
-
-#serial 6
-
-dnl  This macro is based on the code from the AX_CXX_COMPILE_STDCXX_11 macro
-dnl  (serial version number 13).
-
-AX_REQUIRE_DEFINED([AC_MSG_WARN])
-AC_DEFUN([AX_CXX_COMPILE_STDCXX], [dnl
-  m4_if([$1], [11], [ax_cxx_compile_alternatives="11 0x"],
-        [$1], [14], [ax_cxx_compile_alternatives="14 1y"],
-        [$1], [17], [ax_cxx_compile_alternatives="17 1z"],
-        [m4_fatal([invalid first argument `$1' to AX_CXX_COMPILE_STDCXX])])dnl
-  m4_if([$2], [], [],
-        [$2], [ext], [],
-        [$2], [noext], [],
-        [m4_fatal([invalid second argument `$2' to AX_CXX_COMPILE_STDCXX])])dnl
-  m4_if([$3], [], [ax_cxx_compile_cxx$1_required=true],
-        [$3], [mandatory], [ax_cxx_compile_cxx$1_required=true],
-        [$3], [optional], [ax_cxx_compile_cxx$1_required=false],
-        [m4_fatal([invalid third argument `$3' to AX_CXX_COMPILE_STDCXX])])
-  AC_LANG_PUSH([C++])dnl
-  ac_success=no
-  AC_CACHE_CHECK(whether $CXX supports C++$1 features by default,
-  ax_cv_cxx_compile_cxx$1,
-  [AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
-    [ax_cv_cxx_compile_cxx$1=yes],
-    [ax_cv_cxx_compile_cxx$1=no])])
-  if test x$ax_cv_cxx_compile_cxx$1 = xyes; then
-    ac_success=yes
-  fi
-
-  m4_if([$2], [noext], [], [dnl
-  if test x$ac_success = xno; then
-    for alternative in ${ax_cxx_compile_alternatives}; do
-      switch="-std=gnu++${alternative}"
-      cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
-      AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
-                     $cachevar,
-        [ac_save_CXX="$CXX"
-         CXX="$CXX $switch"
-         AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
-          [eval $cachevar=yes],
-          [eval $cachevar=no])
-         CXX="$ac_save_CXX"])
-      if eval test x\$$cachevar = xyes; then
-        CXX="$CXX $switch"
-        if test -n "$CXXCPP" ; then
-          CXXCPP="$CXXCPP $switch"
-        fi
-        ac_success=yes
-        break
-      fi
-    done
-  fi])
-
-  m4_if([$2], [ext], [], [dnl
-  if test x$ac_success = xno; then
-    dnl HP's aCC needs +std=c++11 according to:
-    dnl http://h21007.www2.hp.com/portal/download/files/unprot/aCxx/PDF_Release_Notes/769149-001.pdf
-    dnl Cray's crayCC needs "-h std=c++11"
-    for alternative in ${ax_cxx_compile_alternatives}; do
-      for switch in -std=c++${alternative} +std=c++${alternative} "-h std=c++${alternative}"; do
-        cachevar=AS_TR_SH([ax_cv_cxx_compile_cxx$1_$switch])
-        AC_CACHE_CHECK(whether $CXX supports C++$1 features with $switch,
-                       $cachevar,
-          [ac_save_CXX="$CXX"
-           CXX="$CXX $switch"
-           AC_COMPILE_IFELSE([AC_LANG_SOURCE([_AX_CXX_COMPILE_STDCXX_testbody_$1])],
-            [eval $cachevar=yes],
-            [eval $cachevar=no])
-           CXX="$ac_save_CXX"])
-        if eval test x\$$cachevar = xyes; then
-          CXX="$CXX $switch"
-          if test -n "$CXXCPP" ; then
-            CXXCPP="$CXXCPP $switch"
-          fi
-          ac_success=yes
-          break
-        fi
-      done
-      if test x$ac_success = xyes; then
-        break
-      fi
-    done
-  fi])
-  AC_LANG_POP([C++])
-  if test x$ax_cxx_compile_cxx$1_required = xtrue; then
-    if test x$ac_success = xno; then
-      AC_MSG_ERROR([*** A compiler with support for C++$1 language features is required.])
-    fi
-  fi
-  if test x$ac_success = xno; then
-    HAVE_CXX$1=0
-    AC_MSG_NOTICE([No compiler with C++$1 support was found])
-  else
-    HAVE_CXX$1=1
-    AC_DEFINE(HAVE_CXX$1,1,
-              [define if the compiler supports basic C++$1 syntax])
-  fi
-  AC_SUBST(HAVE_CXX$1)
-  m4_if([$1], [17], [AC_MSG_WARN([C++17 is not yet standardized, so the checks may change in incompatible ways anytime])])
-])
-
-
-dnl  Test body for checking C++11 support
-
-m4_define([_AX_CXX_COMPILE_STDCXX_testbody_11],
-  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
-)
-
-
-dnl  Test body for checking C++14 support
-
-m4_define([_AX_CXX_COMPILE_STDCXX_testbody_14],
-  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
-  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
-)
-
-m4_define([_AX_CXX_COMPILE_STDCXX_testbody_17],
-  _AX_CXX_COMPILE_STDCXX_testbody_new_in_11
-  _AX_CXX_COMPILE_STDCXX_testbody_new_in_14
-  _AX_CXX_COMPILE_STDCXX_testbody_new_in_17
-)
-
-dnl  Tests for new features in C++11
-
-m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_11], [[
-
-// If the compiler admits that it is not ready for C++11, why torture it?
-// Hopefully, this will speed up the test.
-
-#ifndef __cplusplus
-
-#error "This is not a C++ compiler"
-
-#elif __cplusplus < 201103L
-
-#error "This is not a C++11 compiler"
-
-#else
-
-#include <utility>
-
-namespace cxx11
-{
-
-  namespace test_static_assert
-  {
-
-    template <typename T>
-    struct check
-    {
-      static_assert(sizeof(int) <= sizeof(T), "not big enough");
-    };
-
-  }
-
-  namespace test_final_override
-  {
-
-    struct Base
-    {
-      virtual void f() {}
-    };
-
-    struct Derived : public Base
-    {
-      virtual void f() override {}
-    };
-
-  }
-
-  namespace test_double_right_angle_brackets
-  {
-
-    template < typename T >
-    struct check {};
-
-    typedef check<void> single_type;
-    typedef check<check<void>> double_type;
-    typedef check<check<check<void>>> triple_type;
-    typedef check<check<check<check<void>>>> quadruple_type;
-
-  }
-
-  namespace test_decltype
-  {
-
-    int
-    f()
-    {
-      int a = 1;
-      decltype(a) b = 2;
-      return a + b;
-    }
-
-  }
-
-  namespace test_type_deduction
-  {
-
-    template < typename T1, typename T2 >
-    struct is_same
-    {
-      static const bool value = false;
-    };
-
-    template < typename T >
-    struct is_same<T, T>
-    {
-      static const bool value = true;
-    };
-
-    template < typename T1, typename T2 >
-    auto
-    add(T1 a1, T2 a2) -> decltype(a1 + a2)
-    {
-      return a1 + a2;
-    }
-
-    int
-    test(const int c, volatile int v)
-    {
-      static_assert(is_same<int, decltype(0)>::value == true, "");
-      static_assert(is_same<int, decltype(c)>::value == false, "");
-      static_assert(is_same<int, decltype(v)>::value == false, "");
-      auto ac = c;
-      auto av = v;
-      auto sumi = ac + av + 'x';
-      auto sumf = ac + av + 1.0;
-      static_assert(is_same<int, decltype(ac)>::value == true, "");
-      static_assert(is_same<int, decltype(av)>::value == true, "");
-      static_assert(is_same<int, decltype(sumi)>::value == true, "");
-      static_assert(is_same<int, decltype(sumf)>::value == false, "");
-      static_assert(is_same<int, decltype(add(c, v))>::value == true, "");
-      return (sumf > 0.0) ? sumi : add(c, v);
-    }
-
-  }
-
-  namespace test_noexcept
-  {
-
-    int f() { return 0; }
-    int g() noexcept { return 0; }
-
-    static_assert(noexcept(f()) == false, "");
-    static_assert(noexcept(g()) == true, "");
-
-  }
-
-  namespace test_constexpr
-  {
-
-    template < typename CharT >
-    unsigned long constexpr
-    strlen_c_r(const CharT *const s, const unsigned long acc) noexcept
-    {
-      return *s ? strlen_c_r(s + 1, acc + 1) : acc;
-    }
-
-    template < typename CharT >
-    unsigned long constexpr
-    strlen_c(const CharT *const s) noexcept
-    {
-      return strlen_c_r(s, 0UL);
-    }
-
-    static_assert(strlen_c("") == 0UL, "");
-    static_assert(strlen_c("1") == 1UL, "");
-    static_assert(strlen_c("example") == 7UL, "");
-    static_assert(strlen_c("another\0example") == 7UL, "");
-
-  }
-
-  namespace test_rvalue_references
-  {
-
-    template < int N >
-    struct answer
-    {
-      static constexpr int value = N;
-    };
-
-    answer<1> f(int&)       { return answer<1>(); }
-    answer<2> f(const int&) { return answer<2>(); }
-    answer<3> f(int&&)      { return answer<3>(); }
-
-    void
-    test()
-    {
-      int i = 0;
-      const int c = 0;
-      static_assert(decltype(f(i))::value == 1, "");
-      static_assert(decltype(f(c))::value == 2, "");
-      static_assert(decltype(f(0))::value == 3, "");
-    }
-
-  }
-
-  namespace test_uniform_initialization
-  {
-
-    struct test
-    {
-      static const int zero {};
-      static const int one {1};
-    };
-
-    static_assert(test::zero == 0, "");
-    static_assert(test::one == 1, "");
-
-  }
-
-  namespace test_lambdas
-  {
-
-    void
-    test1()
-    {
-      auto lambda1 = [](){};
-      auto lambda2 = lambda1;
-      lambda1();
-      lambda2();
-    }
-
-    int
-    test2()
-    {
-      auto a = [](int i, int j){ return i + j; }(1, 2);
-      auto b = []() -> int { return '0'; }();
-      auto c = [=](){ return a + b; }();
-      auto d = [&](){ return c; }();
-      auto e = [a, &b](int x) mutable {
-        const auto identity = [](int y){ return y; };
-        for (auto i = 0; i < a; ++i)
-          a += b--;
-        return x + identity(a + b);
-      }(0);
-      return a + b + c + d + e;
-    }
-
-    int
-    test3()
-    {
-      const auto nullary = [](){ return 0; };
-      const auto unary = [](int x){ return x; };
-      using nullary_t = decltype(nullary);
-      using unary_t = decltype(unary);
-      const auto higher1st = [](nullary_t f){ return f(); };
-      const auto higher2nd = [unary](nullary_t f1){
-        return [unary, f1](unary_t f2){ return f2(unary(f1())); };
-      };
-      return higher1st(nullary) + higher2nd(nullary)(unary);
-    }
-
-  }
-
-  namespace test_variadic_templates
-  {
-
-    template <int...>
-    struct sum;
-
-    template <int N0, int... N1toN>
-    struct sum<N0, N1toN...>
-    {
-      static constexpr auto value = N0 + sum<N1toN...>::value;
-    };
-
-    template <>
-    struct sum<>
-    {
-      static constexpr auto value = 0;
-    };
-
-    static_assert(sum<>::value == 0, "");
-    static_assert(sum<1>::value == 1, "");
-    static_assert(sum<23>::value == 23, "");
-    static_assert(sum<1, 2>::value == 3, "");
-    static_assert(sum<5, 5, 11>::value == 21, "");
-    static_assert(sum<2, 3, 5, 7, 11, 13>::value == 41, "");
-
-  }
-
-  // http://stackoverflow.com/questions/13728184/template-aliases-and-sfinae
-  // Clang 3.1 fails with headers of libstd++ 4.8.3 when using std::function
-  // because of this.
-  namespace test_template_alias_sfinae
-  {
-
-    struct foo {};
-
-    template<typename T>
-    using member = typename T::member_type;
-
-    template<typename T>
-    void func(...) {}
-
-    template<typename T>
-    void func(member<T>*) {}
-
-    void test();
-
-    void test() { func<foo>(0); }
-
-  }
-
-  namespace test_std_move_and_forward
-  {
-    struct message {};
-    char foo(message&) { return '\0'; }
-    int foo(message&&) { return 0; }
-
-    template<typename Arg, typename RT>
-    void check(Arg&& arg, RT rt) {
-      static_assert(sizeof(rt) == sizeof(foo(std::forward<Arg>(arg))), "");
-    }
-    void test() {
-      message a;
-      check(a, char());
-      check(std::move(a), int());
-    }
-  }
-
-}  // namespace cxx11
-
-#endif  // __cplusplus >= 201103L
-
-]])
-
-
-dnl  Tests for new features in C++14
-
-m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_14], [[
-
-// If the compiler admits that it is not ready for C++14, why torture it?
-// Hopefully, this will speed up the test.
-
-#ifndef __cplusplus
-
-#error "This is not a C++ compiler"
-
-#elif __cplusplus < 201402L
-
-#error "This is not a C++14 compiler"
-
-#else
-
-namespace cxx14
-{
-
-  namespace test_polymorphic_lambdas
-  {
-
-    int
-    test()
-    {
-      const auto lambda = [](auto&&... args){
-        const auto istiny = [](auto x){
-          return (sizeof(x) == 1UL) ? 1 : 0;
-        };
-        const int aretiny[] = { istiny(args)... };
-        return aretiny[0];
-      };
-      return lambda(1, 1L, 1.0f, '1');
-    }
-
-  }
-
-  namespace test_binary_literals
-  {
-
-    constexpr auto ivii = 0b0000000000101010;
-    static_assert(ivii == 42, "wrong value");
-
-  }
-
-  namespace test_generalized_constexpr
-  {
-
-    template < typename CharT >
-    constexpr unsigned long
-    strlen_c(const CharT *const s) noexcept
-    {
-      auto length = 0UL;
-      for (auto p = s; *p; ++p)
-        ++length;
-      return length;
-    }
-
-    static_assert(strlen_c("") == 0UL, "");
-    static_assert(strlen_c("x") == 1UL, "");
-    static_assert(strlen_c("test") == 4UL, "");
-    static_assert(strlen_c("another\0test") == 7UL, "");
-
-  }
-
-  namespace test_lambda_init_capture
-  {
-
-    int
-    test()
-    {
-      auto x = 0;
-      const auto lambda1 = [a = x](int b){ return a + b; };
-      const auto lambda2 = [a = lambda1(x)](){ return a; };
-      return lambda2();
-    }
-
-  }
-
-  namespace test_digit_separators
-  {
-
-    constexpr auto ten_million = 100'000'000;
-    static_assert(ten_million == 100000000, "");
-
-  }
-
-  namespace test_return_type_deduction
-  {
-
-    auto f(int& x) { return x; }
-    decltype(auto) g(int& x) { return x; }
-
-    template < typename T1, typename T2 >
-    struct is_same
-    {
-      static constexpr auto value = false;
-    };
-
-    template < typename T >
-    struct is_same<T, T>
-    {
-      static constexpr auto value = true;
-    };
-
-    int
-    test()
-    {
-      auto x = 0;
-      static_assert(is_same<int, decltype(f(x))>::value, "");
-      static_assert(is_same<int&, decltype(g(x))>::value, "");
-      return x;
-    }
-
-  }
-
-}  // namespace cxx14
-
-#endif  // __cplusplus >= 201402L
-
-]])
-
-
-dnl  Tests for new features in C++17
-
-m4_define([_AX_CXX_COMPILE_STDCXX_testbody_new_in_17], [[
-
-// If the compiler admits that it is not ready for C++17, why torture it?
-// Hopefully, this will speed up the test.
-
-#ifndef __cplusplus
-
-#error "This is not a C++ compiler"
-
-#elif __cplusplus <= 201402L
-
-#error "This is not a C++17 compiler"
-
-#else
-
-#if defined(__clang__)
-  #define REALLY_CLANG
-#else
-  #if defined(__GNUC__)
-    #define REALLY_GCC
-  #endif
-#endif
-
-#include <initializer_list>
-#include <utility>
-#include <type_traits>
-
-namespace cxx17
-{
-
-#if !defined(REALLY_CLANG)
-  namespace test_constexpr_lambdas
-  {
-
-    // TODO: test it with clang++ from git
-
-    constexpr int foo = [](){return 42;}();
-
-  }
-#endif // !defined(REALLY_CLANG)
-
-  namespace test::nested_namespace::definitions
-  {
-
-  }
-
-  namespace test_fold_expression
-  {
-
-    template<typename... Args>
-    int multiply(Args... args)
-    {
-      return (args * ... * 1);
-    }
-
-    template<typename... Args>
-    bool all(Args... args)
-    {
-      return (args && ...);
-    }
-
-  }
-
-  namespace test_extended_static_assert
-  {
-
-    static_assert (true);
-
-  }
-
-  namespace test_auto_brace_init_list
-  {
-
-    auto foo = {5};
-    auto bar {5};
-
-    static_assert(std::is_same<std::initializer_list<int>, decltype(foo)>::value);
-    static_assert(std::is_same<int, decltype(bar)>::value);
-  }
-
-  namespace test_typename_in_template_template_parameter
-  {
-
-    template<template<typename> typename X> struct D;
-
-  }
-
-  namespace test_fallthrough_nodiscard_maybe_unused_attributes
-  {
-
-    int f1()
-    {
-      return 42;
-    }
-
-    [[nodiscard]] int f2()
-    {
-      [[maybe_unused]] auto unused = f1();
-
-      switch (f1())
-      {
-      case 17:
-        f1();
-        [[fallthrough]];
-      case 42:
-        f1();
-      }
-      return f1();
-    }
-
-  }
-
-  namespace test_extended_aggregate_initialization
-  {
-
-    struct base1
-    {
-      int b1, b2 = 42;
-    };
-
-    struct base2
-    {
-      base2() {
-        b3 = 42;
-      }
-      int b3;
-    };
-
-    struct derived : base1, base2
-    {
-        int d;
-    };
-
-    derived d1 {{1, 2}, {}, 4};  // full initialization
-    derived d2 {{}, {}, 4};      // value-initialized bases
-
-  }
-
-  namespace test_general_range_based_for_loop
-  {
-
-    struct iter
-    {
-      int i;
-
-      int& operator* ()
-      {
-        return i;
-      }
-
-      const int& operator* () const
-      {
-        return i;
-      }
-
-      iter& operator++()
-      {
-        ++i;
-        return *this;
-      }
-    };
-
-    struct sentinel
-    {
-      int i;
-    };
-
-    bool operator== (const iter& i, const sentinel& s)
-    {
-      return i.i == s.i;
-    }
-
-    bool operator!= (const iter& i, const sentinel& s)
-    {
-      return !(i == s);
-    }
-
-    struct range
-    {
-      iter begin() const
-      {
-        return {0};
-      }
-
-      sentinel end() const
-      {
-        return {5};
-      }
-    };
-
-    void f()
-    {
-      range r {};
-
-      for (auto i : r)
-      {
-        [[maybe_unused]] auto v = i;
-      }
-    }
-
-  }
-
-  namespace test_lambda_capture_asterisk_this_by_value
-  {
-
-    struct t
-    {
-      int i;
-      int foo()
-      {
-        return [*this]()
-        {
-          return i;
-        }();
-      }
-    };
-
-  }
-
-  namespace test_enum_class_construction
-  {
-
-    enum class byte : unsigned char
-    {};
-
-    byte foo {42};
-
-  }
-
-  namespace test_constexpr_if
-  {
-
-    template <bool cond>
-    int f ()
-    {
-      if constexpr(cond)
-      {
-        return 13;
-      }
-      else
-      {
-        return 42;
-      }
-    }
-
-  }
-
-  namespace test_selection_statement_with_initializer
-  {
-
-    int f()
-    {
-      return 13;
-    }
-
-    int f2()
-    {
-      if (auto i = f(); i > 0)
-      {
-        return 3;
-      }
-
-      switch (auto i = f(); i + 4)
-      {
-      case 17:
-        return 2;
-
-      default:
-        return 1;
-      }
-    }
-
-  }
-
-#if !defined(REALLY_CLANG)
-  namespace test_template_argument_deduction_for_class_templates
-  {
-
-    // TODO: test it with clang++ from git
-
-    template <typename T1, typename T2>
-    struct pair
-    {
-      pair (T1 p1, T2 p2)
-        : m1 {p1},
-          m2 {p2}
-      {}
-
-      T1 m1;
-      T2 m2;
-    };
-
-    void f()
-    {
-      [[maybe_unused]] auto p = pair{13, 42u};
-    }
-
-  }
-#endif // !defined(REALLY_CLANG)
-
-  namespace test_non_type_auto_template_parameters
-  {
-
-    template <auto n>
-    struct B
-    {};
-
-    B<5> b1;
-    B<'a'> b2;
-
-  }
-
-#if !defined(REALLY_CLANG)
-  namespace test_structured_bindings
-  {
-
-    // TODO: test it with clang++ from git
-
-    int arr[2] = { 1, 2 };
-    std::pair<int, int> pr = { 1, 2 };
-
-    auto f1() -> int(&)[2]
-    {
-      return arr;
-    }
-
-    auto f2() -> std::pair<int, int>&
-    {
-      return pr;
-    }
-
-    struct S
-    {
-      int x1 : 2;
-      volatile double y1;
-    };
-
-    S f3()
-    {
-      return {};
-    }
-
-    auto [ x1, y1 ] = f1();
-    auto& [ xr1, yr1 ] = f1();
-    auto [ x2, y2 ] = f2();
-    auto& [ xr2, yr2 ] = f2();
-    const auto [ x3, y3 ] = f3();
-
-  }
-#endif // !defined(REALLY_CLANG)
-
-#if !defined(REALLY_CLANG)
-  namespace test_exception_spec_type_system
-  {
-
-    // TODO: test it with clang++ from git
-
-    struct Good {};
-    struct Bad {};
-
-    void g1() noexcept;
-    void g2();
-
-    template<typename T>
-    Bad
-    f(T*, T*);
-
-    template<typename T1, typename T2>
-    Good
-    f(T1*, T2*);
-
-    static_assert (std::is_same_v<Good, decltype(f(g1, g2))>);
-
-  }
-#endif // !defined(REALLY_CLANG)
-
-  namespace test_inline_variables
-  {
-
-    template<class T> void f(T)
-    {}
-
-    template<class T> inline T g(T)
-    {
-      return T{};
-    }
-
-    template<> inline void f<>(int)
-    {}
-
-    template<> int g<>(int)
-    {
-      return 5;
-    }
-
-  }
-
-}  // namespace cxx17
-
-#endif  // __cplusplus <= 201402L
-
-]])
diff --git a/m4/ax_prog_cc_for_build.m4 b/m4/ax_prog_cc_for_build.m4
deleted file mode 100644
index 77fd346..0000000
--- a/m4/ax_prog_cc_for_build.m4
+++ /dev/null
@@ -1,125 +0,0 @@
-# ===========================================================================
-#   http://www.gnu.org/software/autoconf-archive/ax_prog_cc_for_build.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   AX_PROG_CC_FOR_BUILD
-#
-# DESCRIPTION
-#
-#   This macro searches for a C compiler that generates native executables,
-#   that is a C compiler that surely is not a cross-compiler. This can be
-#   useful if you have to generate source code at compile-time like for
-#   example GCC does.
-#
-#   The macro sets the CC_FOR_BUILD and CPP_FOR_BUILD macros to anything
-#   needed to compile or link (CC_FOR_BUILD) and preprocess (CPP_FOR_BUILD).
-#   The value of these variables can be overridden by the user by specifying
-#   a compiler with an environment variable (like you do for standard CC).
-#
-#   It also sets BUILD_EXEEXT and BUILD_OBJEXT to the executable and object
-#   file extensions for the build platform, and GCC_FOR_BUILD to `yes' if
-#   the compiler we found is GCC. All these variables but GCC_FOR_BUILD are
-#   substituted in the Makefile.
-#
-# LICENSE
-#
-#   Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
-#
-#   Copying and distribution of this file, with or without modification, are
-#   permitted in any medium without royalty provided the copyright notice
-#   and this notice are preserved. This file is offered as-is, without any
-#   warranty.
-
-#serial 8
-
-AU_ALIAS([AC_PROG_CC_FOR_BUILD], [AX_PROG_CC_FOR_BUILD])
-AC_DEFUN([AX_PROG_CC_FOR_BUILD], [dnl
-AC_REQUIRE([AC_PROG_CC])dnl
-AC_REQUIRE([AC_PROG_CPP])dnl
-AC_REQUIRE([AC_EXEEXT])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-
-dnl Use the standard macros, but make them use other variable names
-dnl
-pushdef([ac_cv_prog_CPP], ac_cv_build_prog_CPP)dnl
-pushdef([ac_cv_prog_gcc], ac_cv_build_prog_gcc)dnl
-pushdef([ac_cv_prog_cc_works], ac_cv_build_prog_cc_works)dnl
-pushdef([ac_cv_prog_cc_cross], ac_cv_build_prog_cc_cross)dnl
-pushdef([ac_cv_prog_cc_g], ac_cv_build_prog_cc_g)dnl
-pushdef([ac_cv_exeext], ac_cv_build_exeext)dnl
-pushdef([ac_cv_objext], ac_cv_build_objext)dnl
-pushdef([ac_exeext], ac_build_exeext)dnl
-pushdef([ac_objext], ac_build_objext)dnl
-pushdef([CC], CC_FOR_BUILD)dnl
-pushdef([CPP], CPP_FOR_BUILD)dnl
-pushdef([CFLAGS], CFLAGS_FOR_BUILD)dnl
-pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
-pushdef([LDFLAGS], LDFLAGS_FOR_BUILD)dnl
-pushdef([host], build)dnl
-pushdef([host_alias], build_alias)dnl
-pushdef([host_cpu], build_cpu)dnl
-pushdef([host_vendor], build_vendor)dnl
-pushdef([host_os], build_os)dnl
-pushdef([ac_cv_host], ac_cv_build)dnl
-pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
-pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
-pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
-pushdef([ac_cv_host_os], ac_cv_build_os)dnl
-pushdef([ac_cpp], ac_build_cpp)dnl
-pushdef([ac_compile], ac_build_compile)dnl
-pushdef([ac_link], ac_build_link)dnl
-
-save_cross_compiling=$cross_compiling
-save_ac_tool_prefix=$ac_tool_prefix
-cross_compiling=no
-ac_tool_prefix=
-
-AC_PROG_CC
-AC_PROG_CPP
-AC_EXEEXT
-
-ac_tool_prefix=$save_ac_tool_prefix
-cross_compiling=$save_cross_compiling
-
-dnl Restore the old definitions
-dnl
-popdef([ac_link])dnl
-popdef([ac_compile])dnl
-popdef([ac_cpp])dnl
-popdef([ac_cv_host_os])dnl
-popdef([ac_cv_host_vendor])dnl
-popdef([ac_cv_host_cpu])dnl
-popdef([ac_cv_host_alias])dnl
-popdef([ac_cv_host])dnl
-popdef([host_os])dnl
-popdef([host_vendor])dnl
-popdef([host_cpu])dnl
-popdef([host_alias])dnl
-popdef([host])dnl
-popdef([LDFLAGS])dnl
-popdef([CPPFLAGS])dnl
-popdef([CFLAGS])dnl
-popdef([CPP])dnl
-popdef([CC])dnl
-popdef([ac_objext])dnl
-popdef([ac_exeext])dnl
-popdef([ac_cv_objext])dnl
-popdef([ac_cv_exeext])dnl
-popdef([ac_cv_prog_cc_g])dnl
-popdef([ac_cv_prog_cc_cross])dnl
-popdef([ac_cv_prog_cc_works])dnl
-popdef([ac_cv_prog_gcc])dnl
-popdef([ac_cv_prog_CPP])dnl
-
-dnl Finally, set Makefile variables
-dnl
-BUILD_EXEEXT=$ac_build_exeext
-BUILD_OBJEXT=$ac_build_objext
-AC_SUBST(BUILD_EXEEXT)dnl
-AC_SUBST(BUILD_OBJEXT)dnl
-AC_SUBST([CFLAGS_FOR_BUILD])dnl
-AC_SUBST([CPPFLAGS_FOR_BUILD])dnl
-AC_SUBST([LDFLAGS_FOR_BUILD])dnl
-])
diff --git a/m4/ax_prog_cxx_for_build.m4 b/m4/ax_prog_cxx_for_build.m4
deleted file mode 100644
index 8cc0f73..0000000
--- a/m4/ax_prog_cxx_for_build.m4
+++ /dev/null
@@ -1,110 +0,0 @@
-# ===========================================================================
-#   http://www.gnu.org/software/autoconf-archive/ax_prog_cxx_for_build.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   AX_PROG_CXX_FOR_BUILD
-#
-# DESCRIPTION
-#
-#   This macro searches for a C++ compiler that generates native
-#   executables, that is a C++ compiler that surely is not a cross-compiler.
-#   This can be useful if you have to generate source code at compile-time
-#   like for example GCC does.
-#
-#   The macro sets the CXX_FOR_BUILD and CXXCPP_FOR_BUILD macros to anything
-#   needed to compile or link (CXX_FOR_BUILD) and preprocess
-#   (CXXCPP_FOR_BUILD). The value of these variables can be overridden by
-#   the user by specifying a compiler with an environment variable (like you
-#   do for standard CXX).
-#
-# LICENSE
-#
-#   Copyright (c) 2008 Paolo Bonzini <bonzini@gnu.org>
-#   Copyright (c) 2012 Avionic Design GmbH
-#
-#   Based on the AX_PROG_CC_FOR_BUILD macro by Paolo Bonzini.
-#
-#   Copying and distribution of this file, with or without modification, are
-#   permitted in any medium without royalty provided the copyright notice
-#   and this notice are preserved. This file is offered as-is, without any
-#   warranty.
-
-#serial 2
-
-AU_ALIAS([AC_PROG_CXX_FOR_BUILD], [AX_PROG_CXX_FOR_BUILD])
-AC_DEFUN([AX_PROG_CXX_FOR_BUILD], [dnl
-AC_REQUIRE([AX_PROG_CC_FOR_BUILD])dnl
-AC_REQUIRE([AC_PROG_CXX])dnl
-AC_REQUIRE([AC_PROG_CXXCPP])dnl
-AC_REQUIRE([AC_CANONICAL_HOST])dnl
-
-dnl Use the standard macros, but make them use other variable names
-dnl
-pushdef([ac_cv_prog_CXXCPP], ac_cv_build_prog_CXXCPP)dnl
-pushdef([ac_cv_prog_gxx], ac_cv_build_prog_gxx)dnl
-pushdef([ac_cv_prog_cxx_works], ac_cv_build_prog_cxx_works)dnl
-pushdef([ac_cv_prog_cxx_cross], ac_cv_build_prog_cxx_cross)dnl
-pushdef([ac_cv_prog_cxx_g], ac_cv_build_prog_cxx_g)dnl
-pushdef([CXX], CXX_FOR_BUILD)dnl
-pushdef([CXXCPP], CXXCPP_FOR_BUILD)dnl
-pushdef([CXXFLAGS], CXXFLAGS_FOR_BUILD)dnl
-pushdef([CPPFLAGS], CPPFLAGS_FOR_BUILD)dnl
-pushdef([CXXCPPFLAGS], CXXCPPFLAGS_FOR_BUILD)dnl
-pushdef([host], build)dnl
-pushdef([host_alias], build_alias)dnl
-pushdef([host_cpu], build_cpu)dnl
-pushdef([host_vendor], build_vendor)dnl
-pushdef([host_os], build_os)dnl
-pushdef([ac_cv_host], ac_cv_build)dnl
-pushdef([ac_cv_host_alias], ac_cv_build_alias)dnl
-pushdef([ac_cv_host_cpu], ac_cv_build_cpu)dnl
-pushdef([ac_cv_host_vendor], ac_cv_build_vendor)dnl
-pushdef([ac_cv_host_os], ac_cv_build_os)dnl
-pushdef([ac_cxxcpp], ac_build_cxxcpp)dnl
-pushdef([ac_compile], ac_build_compile)dnl
-pushdef([ac_link], ac_build_link)dnl
-
-save_cross_compiling=$cross_compiling
-save_ac_tool_prefix=$ac_tool_prefix
-cross_compiling=no
-ac_tool_prefix=
-
-AC_PROG_CXX
-AC_PROG_CXXCPP
-
-ac_tool_prefix=$save_ac_tool_prefix
-cross_compiling=$save_cross_compiling
-
-dnl Restore the old definitions
-dnl
-popdef([ac_link])dnl
-popdef([ac_compile])dnl
-popdef([ac_cxxcpp])dnl
-popdef([ac_cv_host_os])dnl
-popdef([ac_cv_host_vendor])dnl
-popdef([ac_cv_host_cpu])dnl
-popdef([ac_cv_host_alias])dnl
-popdef([ac_cv_host])dnl
-popdef([host_os])dnl
-popdef([host_vendor])dnl
-popdef([host_cpu])dnl
-popdef([host_alias])dnl
-popdef([host])dnl
-popdef([CXXCPPFLAGS])dnl
-popdef([CPPFLAGS])dnl
-popdef([CXXFLAGS])dnl
-popdef([CXXCPP])dnl
-popdef([CXX])dnl
-popdef([ac_cv_prog_cxx_g])dnl
-popdef([ac_cv_prog_cxx_cross])dnl
-popdef([ac_cv_prog_cxx_works])dnl
-popdef([ac_cv_prog_gxx])dnl
-popdef([ac_cv_prog_CXXCPP])dnl
-
-dnl Finally, set Makefile variables
-dnl
-AC_SUBST([CXXFLAGS_FOR_BUILD])dnl
-AC_SUBST([CXXCPPFLAGS_FOR_BUILD])dnl
-])
diff --git a/m4/ax_pthread.m4 b/m4/ax_pthread.m4
deleted file mode 100644
index 1598d07..0000000
--- a/m4/ax_pthread.m4
+++ /dev/null
@@ -1,507 +0,0 @@
-# ===========================================================================
-#        https://www.gnu.org/software/autoconf-archive/ax_pthread.html
-# ===========================================================================
-#
-# SYNOPSIS
-#
-#   AX_PTHREAD([ACTION-IF-FOUND[, ACTION-IF-NOT-FOUND]])
-#
-# DESCRIPTION
-#
-#   This macro figures out how to build C programs using POSIX threads. It
-#   sets the PTHREAD_LIBS output variable to the threads library and linker
-#   flags, and the PTHREAD_CFLAGS output variable to any special C compiler
-#   flags that are needed. (The user can also force certain compiler
-#   flags/libs to be tested by setting these environment variables.)
-#
-#   Also sets PTHREAD_CC to any special C compiler that is needed for
-#   multi-threaded programs (defaults to the value of CC otherwise). (This
-#   is necessary on AIX to use the special cc_r compiler alias.)
-#
-#   NOTE: You are assumed to not only compile your program with these flags,
-#   but also to link with them as well. For example, you might link with
-#   $PTHREAD_CC $CFLAGS $PTHREAD_CFLAGS $LDFLAGS ... $PTHREAD_LIBS $LIBS
-#
-#   If you are only building threaded programs, you may wish to use these
-#   variables in your default LIBS, CFLAGS, and CC:
-#
-#     LIBS="$PTHREAD_LIBS $LIBS"
-#     CFLAGS="$CFLAGS $PTHREAD_CFLAGS"
-#     CC="$PTHREAD_CC"
-#
-#   In addition, if the PTHREAD_CREATE_JOINABLE thread-attribute constant
-#   has a nonstandard name, this macro defines PTHREAD_CREATE_JOINABLE to
-#   that name (e.g. PTHREAD_CREATE_UNDETACHED on AIX).
-#
-#   Also HAVE_PTHREAD_PRIO_INHERIT is defined if pthread is found and the
-#   PTHREAD_PRIO_INHERIT symbol is defined when compiling with
-#   PTHREAD_CFLAGS.
-#
-#   ACTION-IF-FOUND is a list of shell commands to run if a threads library
-#   is found, and ACTION-IF-NOT-FOUND is a list of commands to run it if it
-#   is not found. If ACTION-IF-FOUND is not specified, the default action
-#   will define HAVE_PTHREAD.
-#
-#   Please let the authors know if this macro fails on any platform, or if
-#   you have any other suggestions or comments. This macro was based on work
-#   by SGJ on autoconf scripts for FFTW (http://www.fftw.org/) (with help
-#   from M. Frigo), as well as ac_pthread and hb_pthread macros posted by
-#   Alejandro Forero Cuervo to the autoconf macro repository. We are also
-#   grateful for the helpful feedback of numerous users.
-#
-#   Updated for Autoconf 2.68 by Daniel Richard G.
-#
-# LICENSE
-#
-#   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
-#   Free Software Foundation, either version 3 of the License, or (at your
-#   option) any later version.
-#
-#   This program is distributed in the hope that it will be useful, but
-#   WITHOUT ANY WARRANTY; without even the implied warranty of
-#   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General
-#   Public License for more details.
-#
-#   You should have received a copy of the GNU General Public License along
-#   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
-#   scripts that are the output of Autoconf when processing the Macro. You
-#   need not follow the terms of the GNU General Public License when using
-#   or distributing such scripts, even though portions of the text of the
-#   Macro appear in them. The GNU General Public License (GPL) does govern
-#   all other use of the material that constitutes the Autoconf Macro.
-#
-#   This special exception to the GPL applies to versions of the Autoconf
-#   Macro released by the Autoconf Archive. When you make and distribute a
-#   modified version of the Autoconf Macro, you may extend this special
-#   exception to the GPL to apply to your modified version as well.
-
-#serial 27
-
-AU_ALIAS([ACX_PTHREAD], [AX_PTHREAD])
-AC_DEFUN([AX_PTHREAD], [
-AC_REQUIRE([AC_CANONICAL_HOST])
-AC_REQUIRE([AC_PROG_CC])
-AC_REQUIRE([AC_PROG_SED])
-AC_LANG_PUSH([C])
-ax_pthread_ok=no
-
-# We used to check for pthread.h first, but this fails if pthread.h
-# requires special compiler flags (e.g. on Tru64 or Sequent).
-# It gets checked for in the link test anyway.
-
-# First of all, check if the user has set any of the PTHREAD_LIBS,
-# 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"
-fi
-
-# We must check for the threads library under a number of different
-# names; the ordering is very important because some systems
-# (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 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"
-
-# The ordering *is* (sometimes) important.  Some notes on the
-# individual items follow:
-
-# pthreads: AIX (must check this before -lpthread)
-# none: in case threads are in libc; should be tried before -Kthread and
-#       other compiler flags to prevent continual compiler warnings
-# -Kthread: Sequent (threads in libc, but -Kthread needed for pthread.h)
-# -pthread: Linux/gcc (kernel threads), BSD/gcc (userland threads), Tru64
-#           (Note: HP C rejects this with "bad form for `-t' option")
-# -pthreads: Solaris/gcc (Note: HP C also rejects)
-# -mt: Sun Workshop C (may only link SunOS threads [-lthread], but it
-#      doesn't hurt to check since this sometimes defines pthreads and
-#      -D_REENTRANT too), HP C (must be checked before -lpthread, which
-#      is present but should not be used directly; and before -mthreads,
-#      because the compiler interprets this as "-mt" + "-hreads")
-# -mthreads: Mingw32/gcc, Lynx/gcc
-# pthread: Linux, etcetera
-# --thread-safe: KAI C++
-# pthread-config: use pthread-config program (for GNU Pth library)
-
-case $host_os in
-
-        freebsd*)
-
-        # -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"
-        ;;
-
-        hpux*)
-
-        # 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"
-        ;;
-
-        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.)
-
-        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*)
-
-        # 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,-lpthread pthread $ax_pthread_flags"
-        ;;
-esac
-
-# Are we compiling with Clang?
-
-AC_CACHE_CHECK([whether $CC is Clang],
-    [ax_cv_PTHREAD_CLANG],
-    [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])
-     fi
-    ])
-ax_pthread_clang="$ax_cv_PTHREAD_CLANG"
-
-
-# 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
-
-        # (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.)
-
-        # 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
-
-fi # $ax_pthread_clang = yes
-
-
-
-# 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"
-
-        # 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([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"
-
-        # 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"
-
-AC_SUBST([PTHREAD_LIBS])
-AC_SUBST([PTHREAD_CFLAGS])
-AC_SUBST([PTHREAD_CC])
-
-# 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])
-        :
-else
-        ax_pthread_ok=no
-        $2
-fi
-AC_LANG_POP
-])dnl AX_PTHREAD
diff --git a/m4/stl_hash.m4 b/m4/stl_hash.m4
deleted file mode 100644
index d7def1a..0000000
--- a/m4/stl_hash.m4
+++ /dev/null
@@ -1,71 +0,0 @@
-# We check two things: where the include file is for
-# unordered_map/hash_map (we prefer the first form), and what
-# namespace unordered/hash_map lives in within that include file.  We
-# include AC_TRY_COMPILE for all the combinations we've seen in the
-# wild.  We define HASH_MAP_H to the location of the header file, and
-# HASH_NAMESPACE to the namespace the class (unordered_map or
-# hash_map) is in.
-
-# This also checks if unordered map exists.
-AC_DEFUN([AC_CXX_STL_HASH],
-  [
-   AC_MSG_CHECKING(the location of hash_map)
-   AC_LANG_SAVE
-   AC_LANG_CPLUSPLUS
-   ac_cv_cxx_hash_map=""
-   # First try unordered_map, but not on gcc's before 4.2 -- I've
-   # seen unexplainable unordered_map bugs with -O2 on older gcc's.
-   AC_TRY_COMPILE([#if defined(__GNUC__) && (__GNUC__ < 4 || (__GNUC__ == 4 && __GNUC_MINOR__ < 2))
-                   # error GCC too old for unordered_map
-                   #endif
-                   ],
-                   [/* no program body necessary */],
-                   [stl_hash_old_gcc=no],
-                   [stl_hash_old_gcc=yes])
-   for location in unordered_map tr1/unordered_map; do
-     for namespace in std std::tr1; do
-       if test -z "$ac_cv_cxx_hash_map" -a "$stl_hash_old_gcc" != yes; then
-         # Some older gcc's have a buggy tr1, so test a bit of code.
-         AC_TRY_COMPILE([#include <$location>],
-                        [const ${namespace}::unordered_map<int, int> t;
-                         return t.find(5) == t.end();],
-                        [ac_cv_cxx_hash_map="<$location>";
-                         ac_cv_cxx_hash_namespace="$namespace";
-                         ac_cv_cxx_hash_map_class="unordered_map";])
-       fi
-     done
-   done
-   # Now try hash_map
-   for location in ext/hash_map hash_map; do
-     for namespace in __gnu_cxx "" std stdext; do
-       if test -z "$ac_cv_cxx_hash_map"; then
-         AC_TRY_COMPILE([#include <$location>],
-                        [${namespace}::hash_map<int, int> t],
-                        [ac_cv_cxx_hash_map="<$location>";
-                         ac_cv_cxx_hash_namespace="$namespace";
-                         ac_cv_cxx_hash_map_class="hash_map";])
-       fi
-     done
-   done
-   ac_cv_cxx_hash_set=`echo "$ac_cv_cxx_hash_map" | sed s/map/set/`;
-   ac_cv_cxx_hash_set_class=`echo "$ac_cv_cxx_hash_map_class" | sed s/map/set/`;
-   if test -n "$ac_cv_cxx_hash_map"; then
-      AC_DEFINE(HAVE_HASH_MAP, 1, [define if the compiler has hash_map])
-      AC_DEFINE(HAVE_HASH_SET, 1, [define if the compiler has hash_set])
-      AC_DEFINE_UNQUOTED(HASH_MAP_H,$ac_cv_cxx_hash_map,
-                         [the location of <unordered_map> or <hash_map>])
-      AC_DEFINE_UNQUOTED(HASH_SET_H,$ac_cv_cxx_hash_set,
-                         [the location of <unordered_set> or <hash_set>])
-      AC_DEFINE_UNQUOTED(HASH_NAMESPACE,$ac_cv_cxx_hash_namespace,
-                         [the namespace of hash_map/hash_set])
-      AC_DEFINE_UNQUOTED(HASH_MAP_CLASS,$ac_cv_cxx_hash_map_class,
-                         [the name of <hash_map>])
-      AC_DEFINE_UNQUOTED(HASH_SET_CLASS,$ac_cv_cxx_hash_set_class,
-                         [the name of <hash_set>])
-      AC_MSG_RESULT([$ac_cv_cxx_hash_map])
-   else
-      AC_MSG_RESULT()
-      AC_MSG_WARN([could not find an STL hash_map])
-   fi
-])
-
diff --git a/maven_install.json b/maven_install.json
index 9c5860a..efb3f03 100644
--- a/maven_install.json
+++ b/maven_install.json
@@ -1,24 +1,251 @@
 {
     "dependency_tree": {
         "__AUTOGENERATED_FILE_DO_NOT_MODIFY_THIS_FILE_MANUALLY": "THERE_IS_NO_DATA_ONLY_ZUUL",
-        "__INPUT_ARTIFACTS_HASH": -228414992,
-        "__RESOLVED_ARTIFACTS_HASH": -722345565,
+        "__INPUT_ARTIFACTS_HASH": -1875290602,
+        "__RESOLVED_ARTIFACTS_HASH": -1248440885,
         "conflict_resolution": {
-            "com.google.errorprone:error_prone_annotations:2.3.2": "com.google.errorprone:error_prone_annotations:2.11.0",
-            "junit:junit:4.12": "junit:junit:4.13.2"
+            "com.google.errorprone:error_prone_annotations:2.5.1": "com.google.errorprone:error_prone_annotations:2.11.0"
         },
         "dependencies": [
             {
-                "coord": "com.google.auto.value:auto-value-annotations:1.7.4",
+                "coord": "com.google.auto.value:auto-value-annotations:1.8.1",
                 "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",
+                "file": "v1/https/repo1.maven.org/maven2/com/google/auto/value/auto-value-annotations/1.8.1/auto-value-annotations-1.8.1.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"
+                    "https://repo1.maven.org/maven2/com/google/auto/value/auto-value-annotations/1.8.1/auto-value-annotations-1.8.1.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/auto/value/auto-value-annotations/1.8.1/auto-value-annotations-1.8.1.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"
+                "sha256": "37ec09b47d7ed35a99d13927db5c86fc9071f620f943ead5d757144698310852",
+                "url": "https://repo1.maven.org/maven2/com/google/auto/value/auto-value-annotations/1.8.1/auto-value-annotations-1.8.1.jar"
+            },
+            {
+                "coord": "com.google.caliper:caliper-api:1.0-beta-3",
+                "dependencies": [
+                    "com.google.guava:guava:31.1-jre",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "directDependencies": [
+                    "com.google.guava:guava:31.1-jre",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/caliper/caliper-api/1.0-beta-3/caliper-api-1.0-beta-3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/caliper/caliper-api/1.0-beta-3/caliper-api-1.0-beta-3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/caliper/caliper-api/1.0-beta-3/caliper-api-1.0-beta-3.jar"
+                ],
+                "sha256": "374f0c6c0c1f8784cb69d885e1dcbb7498c34ca20369e0597264568530642928",
+                "url": "https://repo1.maven.org/maven2/com/google/caliper/caliper-api/1.0-beta-3/caliper-api-1.0-beta-3.jar"
+            },
+            {
+                "coord": "com.google.caliper:caliper-core:1.0-beta-3",
+                "dependencies": [
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.code.gson:gson:2.8.9",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "com.squareup.okio:okio:1.6.0",
+                    "javax.inject:javax.inject:1",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "directDependencies": [
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/caliper/caliper-core/1.0-beta-3/caliper-core-1.0-beta-3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/caliper/caliper-core/1.0-beta-3/caliper-core-1.0-beta-3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/caliper/caliper-core/1.0-beta-3/caliper-core-1.0-beta-3.jar"
+                ],
+                "sha256": "514deac8f8b09dd4262733e0a4406a333208c899dc7ea726b03600b9bb94f192",
+                "url": "https://repo1.maven.org/maven2/com/google/caliper/caliper-core/1.0-beta-3/caliper-core-1.0-beta-3.jar"
+            },
+            {
+                "coord": "com.google.caliper:caliper-runner:1.0-beta-3",
+                "dependencies": [
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.code.gson:gson:2.8.9",
+                    "com.google.dagger:dagger-producers:2.22.1",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "com.squareup.okio:okio:1.6.0",
+                    "javax.inject:javax.inject:1",
+                    "joda-time:joda-time:2.10.10",
+                    "org.checkerframework:checker-compat-qual:2.5.3"
+                ],
+                "directDependencies": [
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.dagger:dagger-producers:2.22.1",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/caliper/caliper-runner/1.0-beta-3/caliper-runner-1.0-beta-3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/caliper/caliper-runner/1.0-beta-3/caliper-runner-1.0-beta-3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/caliper/caliper-runner/1.0-beta-3/caliper-runner-1.0-beta-3.jar"
+                ],
+                "sha256": "3ab58890aa01343361adedf859500d280f67813df0cedfcd165b169533b9b1fa",
+                "url": "https://repo1.maven.org/maven2/com/google/caliper/caliper-runner/1.0-beta-3/caliper-runner-1.0-beta-3.jar"
+            },
+            {
+                "coord": "com.google.caliper:caliper-util:1.0-beta-3",
+                "dependencies": [
+                    "com.google.code.gson:gson:2.8.9",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "javax.inject:javax.inject:1",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "directDependencies": [
+                    "com.google.code.gson:gson:2.8.9",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/caliper/caliper-util/1.0-beta-3/caliper-util-1.0-beta-3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/caliper/caliper-util/1.0-beta-3/caliper-util-1.0-beta-3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/caliper/caliper-util/1.0-beta-3/caliper-util-1.0-beta-3.jar"
+                ],
+                "sha256": "6e9af500c7020450dfdb5003d09501d512d395f431c54c7ee8f79e712463fe66",
+                "url": "https://repo1.maven.org/maven2/com/google/caliper/caliper-util/1.0-beta-3/caliper-util-1.0-beta-3.jar"
+            },
+            {
+                "coord": "com.google.caliper:caliper-worker-jvm:1.0-beta-3",
+                "dependencies": [
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.caliper:caliper-worker:1.0-beta-3",
+                    "com.google.code.gson:gson:2.8.9",
+                    "com.google.code.java-allocation-instrumenter:java-allocation-instrumenter:3.3.0",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "com.squareup.okio:okio:1.6.0",
+                    "com.sun.jersey:jersey-client:1.19.4",
+                    "com.sun.jersey:jersey-core:1.19.4",
+                    "javax.annotation:javax.annotation-api:1.3.2",
+                    "javax.inject:javax.inject:1",
+                    "javax.ws.rs:jsr311-api:1.1.1",
+                    "joda-time:joda-time:2.10.10",
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-commons:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm-util:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "directDependencies": [
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-worker:1.0-beta-3",
+                    "com.google.code.java-allocation-instrumenter:java-allocation-instrumenter:3.3.0",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.sun.jersey:jersey-client:1.19.4"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/caliper/caliper-worker-jvm/1.0-beta-3/caliper-worker-jvm-1.0-beta-3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/caliper/caliper-worker-jvm/1.0-beta-3/caliper-worker-jvm-1.0-beta-3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/caliper/caliper-worker-jvm/1.0-beta-3/caliper-worker-jvm-1.0-beta-3.jar"
+                ],
+                "sha256": "e14e1ecfdf939c82abdb902105be41ff3f83c18cb968116232015f2662d065a4",
+                "url": "https://repo1.maven.org/maven2/com/google/caliper/caliper-worker-jvm/1.0-beta-3/caliper-worker-jvm-1.0-beta-3.jar"
+            },
+            {
+                "coord": "com.google.caliper:caliper-worker:1.0-beta-3",
+                "dependencies": [
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.code.gson:gson:2.8.9",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "com.squareup.okio:okio:1.6.0",
+                    "javax.inject:javax.inject:1",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "directDependencies": [
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "joda-time:joda-time:2.10.10"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/caliper/caliper-worker/1.0-beta-3/caliper-worker-1.0-beta-3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/caliper/caliper-worker/1.0-beta-3/caliper-worker-1.0-beta-3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/caliper/caliper-worker/1.0-beta-3/caliper-worker-1.0-beta-3.jar"
+                ],
+                "sha256": "315d8e51df1f60551645a0e3bf2c504d2c79762f688e6f728eb9d1d9cd9a491b",
+                "url": "https://repo1.maven.org/maven2/com/google/caliper/caliper-worker/1.0-beta-3/caliper-worker-1.0-beta-3.jar"
+            },
+            {
+                "coord": "com.google.caliper:caliper:1.0-beta-3",
+                "dependencies": [
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
+                    "com.google.caliper:caliper-api:1.0-beta-3",
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-runner:1.0-beta-3",
+                    "com.google.caliper:caliper-util:1.0-beta-3",
+                    "com.google.caliper:caliper-worker-jvm:1.0-beta-3",
+                    "com.google.caliper:caliper-worker:1.0-beta-3",
+                    "com.google.code.gson:gson:2.8.9",
+                    "com.google.code.java-allocation-instrumenter:java-allocation-instrumenter:3.3.0",
+                    "com.google.dagger:dagger-producers:2.22.1",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.squareup.okhttp:okhttp:2.7.5",
+                    "com.squareup.okio:okio:1.6.0",
+                    "com.sun.jersey:jersey-client:1.19.4",
+                    "com.sun.jersey:jersey-core:1.19.4",
+                    "javax.annotation:javax.annotation-api:1.3.2",
+                    "javax.inject:javax.inject:1",
+                    "javax.ws.rs:jsr311-api:1.1.1",
+                    "joda-time:joda-time:2.10.10",
+                    "org.checkerframework:checker-compat-qual:2.5.3",
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-commons:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm-util:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "directDependencies": [
+                    "com.google.caliper:caliper-core:1.0-beta-3",
+                    "com.google.caliper:caliper-runner:1.0-beta-3",
+                    "com.google.caliper:caliper-worker-jvm:1.0-beta-3",
+                    "com.google.code.java-allocation-instrumenter:java-allocation-instrumenter:3.3.0",
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "com.sun.jersey:jersey-client:1.19.4"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/caliper/caliper/1.0-beta-3/caliper-1.0-beta-3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/caliper/caliper/1.0-beta-3/caliper-1.0-beta-3.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/caliper/caliper/1.0-beta-3/caliper-1.0-beta-3.jar"
+                ],
+                "sha256": "d54e1bfdbe9359a79e175c217b8d472555cf20da9c5c0a18bdb1ea7db979ed8e",
+                "url": "https://repo1.maven.org/maven2/com/google/caliper/caliper/1.0-beta-3/caliper-1.0-beta-3.jar"
             },
             {
                 "coord": "com.google.code.findbugs:jsr305:3.0.2",
@@ -45,6 +272,72 @@
                 "url": "https://repo1.maven.org/maven2/com/google/code/gson/gson/2.8.9/gson-2.8.9.jar"
             },
             {
+                "coord": "com.google.code.java-allocation-instrumenter:java-allocation-instrumenter:3.3.0",
+                "dependencies": [
+                    "com.google.guava:guava:31.1-jre",
+                    "javax.annotation:javax.annotation-api:1.3.2",
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-commons:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm-util:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "directDependencies": [
+                    "com.google.guava:guava:31.1-jre",
+                    "javax.annotation:javax.annotation-api:1.3.2",
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-commons:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm-util:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/code/java-allocation-instrumenter/java-allocation-instrumenter/3.3.0/java-allocation-instrumenter-3.3.0.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/code/java-allocation-instrumenter/java-allocation-instrumenter/3.3.0/java-allocation-instrumenter-3.3.0.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/code/java-allocation-instrumenter/java-allocation-instrumenter/3.3.0/java-allocation-instrumenter-3.3.0.jar"
+                ],
+                "sha256": "1ef5535a8bd41cf3072469f381b9ee6ab28275311a7499f53d6e52adf976fef0",
+                "url": "https://repo1.maven.org/maven2/com/google/code/java-allocation-instrumenter/java-allocation-instrumenter/3.3.0/java-allocation-instrumenter-3.3.0.jar"
+            },
+            {
+                "coord": "com.google.dagger:dagger-producers:2.22.1",
+                "dependencies": [
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "javax.inject:javax.inject:1",
+                    "org.checkerframework:checker-compat-qual:2.5.3"
+                ],
+                "directDependencies": [
+                    "com.google.dagger:dagger:2.22.1",
+                    "com.google.guava:guava:31.1-jre",
+                    "javax.inject:javax.inject:1",
+                    "org.checkerframework:checker-compat-qual:2.5.3"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.22.1/dagger-producers-2.22.1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.22.1/dagger-producers-2.22.1.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/dagger/dagger-producers/2.22.1/dagger-producers-2.22.1.jar"
+                ],
+                "sha256": "f834a0082014213a68ff06a0f048d750178d02196c58b0b15beb367d32b97e35",
+                "url": "https://repo1.maven.org/maven2/com/google/dagger/dagger-producers/2.22.1/dagger-producers-2.22.1.jar"
+            },
+            {
+                "coord": "com.google.dagger:dagger:2.22.1",
+                "dependencies": [
+                    "javax.inject:javax.inject:1"
+                ],
+                "directDependencies": [
+                    "javax.inject:javax.inject:1"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/google/dagger/dagger/2.22.1/dagger-2.22.1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/google/dagger/dagger/2.22.1/dagger-2.22.1.jar",
+                    "https://repo.maven.apache.org/maven2/com/google/dagger/dagger/2.22.1/dagger-2.22.1.jar"
+                ],
+                "sha256": "329d4340f24c4f5717af016c097e90668bfea2a5376e6aa9964b01cef3fd241a",
+                "url": "https://repo1.maven.org/maven2/com/google/dagger/dagger/2.22.1/dagger-2.22.1.jar"
+            },
+            {
                 "coord": "com.google.errorprone:error_prone_annotations:2.11.0",
                 "dependencies": [],
                 "directDependencies": [],
@@ -150,7 +443,7 @@
             {
                 "coord": "com.google.truth:truth:1.1.2",
                 "dependencies": [
-                    "com.google.auto.value:auto-value-annotations:1.7.4",
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
                     "com.google.errorprone:error_prone_annotations:2.11.0",
                     "com.google.guava:guava:31.1-jre",
                     "junit:junit:4.13.2",
@@ -158,7 +451,7 @@
                     "org.ow2.asm:asm:9.0"
                 ],
                 "directDependencies": [
-                    "com.google.auto.value:auto-value-annotations:1.7.4",
+                    "com.google.auto.value:auto-value-annotations:1.8.1",
                     "com.google.errorprone:error_prone_annotations:2.11.0",
                     "com.google.guava:guava:31.1-jre",
                     "junit:junit:4.13.2",
@@ -174,6 +467,115 @@
                 "url": "https://repo1.maven.org/maven2/com/google/truth/truth/1.1.2/truth-1.1.2.jar"
             },
             {
+                "coord": "com.squareup.okhttp:okhttp:2.7.5",
+                "dependencies": [
+                    "com.squareup.okio:okio:1.6.0"
+                ],
+                "directDependencies": [
+                    "com.squareup.okio:okio:1.6.0"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/squareup/okhttp/okhttp/2.7.5/okhttp-2.7.5.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/squareup/okhttp/okhttp/2.7.5/okhttp-2.7.5.jar",
+                    "https://repo.maven.apache.org/maven2/com/squareup/okhttp/okhttp/2.7.5/okhttp-2.7.5.jar"
+                ],
+                "sha256": "88ac9fd1bb51f82bcc664cc1eb9c225c90dc4389d660231b4cc737bebfe7d0aa",
+                "url": "https://repo1.maven.org/maven2/com/squareup/okhttp/okhttp/2.7.5/okhttp-2.7.5.jar"
+            },
+            {
+                "coord": "com.squareup.okio:okio:1.6.0",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/com/squareup/okio/okio/1.6.0/okio-1.6.0.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/squareup/okio/okio/1.6.0/okio-1.6.0.jar",
+                    "https://repo.maven.apache.org/maven2/com/squareup/okio/okio/1.6.0/okio-1.6.0.jar"
+                ],
+                "sha256": "114bdc1f47338a68bcbc95abf2f5cdc72beeec91812f2fcd7b521c1937876266",
+                "url": "https://repo1.maven.org/maven2/com/squareup/okio/okio/1.6.0/okio-1.6.0.jar"
+            },
+            {
+                "coord": "com.sun.jersey:jersey-client:1.19.4",
+                "dependencies": [
+                    "com.sun.jersey:jersey-core:1.19.4",
+                    "javax.ws.rs:jsr311-api:1.1.1"
+                ],
+                "directDependencies": [
+                    "com.sun.jersey:jersey-core:1.19.4"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/sun/jersey/jersey-client/1.19.4/jersey-client-1.19.4.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/sun/jersey/jersey-client/1.19.4/jersey-client-1.19.4.jar",
+                    "https://repo.maven.apache.org/maven2/com/sun/jersey/jersey-client/1.19.4/jersey-client-1.19.4.jar"
+                ],
+                "sha256": "639c825c5db580f8115bf49ffc893093526d2ed1079fbc929b6a5fbd0b2eda40",
+                "url": "https://repo1.maven.org/maven2/com/sun/jersey/jersey-client/1.19.4/jersey-client-1.19.4.jar"
+            },
+            {
+                "coord": "com.sun.jersey:jersey-core:1.19.4",
+                "dependencies": [
+                    "javax.ws.rs:jsr311-api:1.1.1"
+                ],
+                "directDependencies": [
+                    "javax.ws.rs:jsr311-api:1.1.1"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/com/sun/jersey/jersey-core/1.19.4/jersey-core-1.19.4.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/com/sun/jersey/jersey-core/1.19.4/jersey-core-1.19.4.jar",
+                    "https://repo.maven.apache.org/maven2/com/sun/jersey/jersey-core/1.19.4/jersey-core-1.19.4.jar"
+                ],
+                "sha256": "64b03198e0264849d0fc341857ebcc9c882b1909a2dc35a0972fe7d901b826e5",
+                "url": "https://repo1.maven.org/maven2/com/sun/jersey/jersey-core/1.19.4/jersey-core-1.19.4.jar"
+            },
+            {
+                "coord": "javax.annotation:javax.annotation-api:1.3.2",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar",
+                    "https://repo.maven.apache.org/maven2/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar"
+                ],
+                "sha256": "e04ba5195bcd555dc95650f7cc614d151e4bcd52d29a10b8aa2197f3ab89ab9b",
+                "url": "https://repo1.maven.org/maven2/javax/annotation/javax.annotation-api/1.3.2/javax.annotation-api-1.3.2.jar"
+            },
+            {
+                "coord": "javax.inject:javax.inject:1",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar",
+                    "https://repo.maven.apache.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar"
+                ],
+                "sha256": "91c77044a50c481636c32d916fd89c9118a72195390452c81065080f957de7ff",
+                "url": "https://repo1.maven.org/maven2/javax/inject/javax.inject/1/javax.inject-1.jar"
+            },
+            {
+                "coord": "javax.ws.rs:jsr311-api:1.1.1",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1.jar",
+                    "https://repo.maven.apache.org/maven2/javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1.jar"
+                ],
+                "sha256": "ab1534b73b5fa055808e6598a5e73b599ccda28c3159c3c0908977809422ee4a",
+                "url": "https://repo1.maven.org/maven2/javax/ws/rs/jsr311-api/1.1.1/jsr311-api-1.1.1.jar"
+            },
+            {
+                "coord": "joda-time:joda-time:2.10.10",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/joda-time/joda-time/2.10.10/joda-time-2.10.10.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/joda-time/joda-time/2.10.10/joda-time-2.10.10.jar",
+                    "https://repo.maven.apache.org/maven2/joda-time/joda-time/2.10.10/joda-time-2.10.10.jar"
+                ],
+                "sha256": "dd8e7c92185a678d1b7b933f31209b6203c8ffa91e9880475a1be0346b9617e3",
+                "url": "https://repo1.maven.org/maven2/joda-time/joda-time/2.10.10/joda-time-2.10.10.jar"
+            },
+            {
                 "coord": "junit:junit:4.13.2",
                 "dependencies": [
                     "org.hamcrest:hamcrest-core:1.3"
@@ -214,6 +616,18 @@
                 "url": "https://repo1.maven.org/maven2/net/bytebuddy/byte-buddy/1.12.7/byte-buddy-1.12.7.jar"
             },
             {
+                "coord": "org.checkerframework:checker-compat-qual:2.5.3",
+                "dependencies": [],
+                "directDependencies": [],
+                "file": "v1/https/repo1.maven.org/maven2/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar",
+                    "https://repo.maven.apache.org/maven2/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar"
+                ],
+                "sha256": "d76b9afea61c7c082908023f0cbc1427fab9abd2df915c8b8a3e7a509bccbc6d",
+                "url": "https://repo1.maven.org/maven2/org/checkerframework/checker-compat-qual/2.5.3/checker-compat-qual-2.5.3.jar"
+            },
+            {
                 "coord": "org.checkerframework:checker-qual:3.12.0",
                 "dependencies": [],
                 "directDependencies": [],
@@ -270,6 +684,79 @@
                 "url": "https://repo1.maven.org/maven2/org/objenesis/objenesis/3.2/objenesis-3.2.jar"
             },
             {
+                "coord": "org.ow2.asm:asm-analysis:7.2",
+                "dependencies": [
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "directDependencies": [
+                    "org.ow2.asm:asm-tree:7.2"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/org/ow2/asm/asm-analysis/7.2/asm-analysis-7.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/ow2/asm/asm-analysis/7.2/asm-analysis-7.2.jar",
+                    "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-analysis/7.2/asm-analysis-7.2.jar"
+                ],
+                "sha256": "be922aae60ff1ff1768e8e6544a38a7f92bd0a6d6b0b9791f94955d1bd453de2",
+                "url": "https://repo1.maven.org/maven2/org/ow2/asm/asm-analysis/7.2/asm-analysis-7.2.jar"
+            },
+            {
+                "coord": "org.ow2.asm:asm-commons:7.2",
+                "dependencies": [
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "directDependencies": [
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/org/ow2/asm/asm-commons/7.2/asm-commons-7.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/ow2/asm/asm-commons/7.2/asm-commons-7.2.jar",
+                    "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-commons/7.2/asm-commons-7.2.jar"
+                ],
+                "sha256": "0e86b8b179c5fb223d1a880a0ff4960b6978223984b94e62e71135f2d8ea3558",
+                "url": "https://repo1.maven.org/maven2/org/ow2/asm/asm-commons/7.2/asm-commons-7.2.jar"
+            },
+            {
+                "coord": "org.ow2.asm:asm-tree:7.2",
+                "dependencies": [
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "directDependencies": [
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/org/ow2/asm/asm-tree/7.2/asm-tree-7.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/ow2/asm/asm-tree/7.2/asm-tree-7.2.jar",
+                    "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-tree/7.2/asm-tree-7.2.jar"
+                ],
+                "sha256": "c063f5a67fa03cdc9bd79fd1c2ea6816cc4a19473ecdfbd9e9153b408c6f2656",
+                "url": "https://repo1.maven.org/maven2/org/ow2/asm/asm-tree/7.2/asm-tree-7.2.jar"
+            },
+            {
+                "coord": "org.ow2.asm:asm-util:7.2",
+                "dependencies": [
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "directDependencies": [
+                    "org.ow2.asm:asm-analysis:7.2",
+                    "org.ow2.asm:asm-tree:7.2",
+                    "org.ow2.asm:asm:9.0"
+                ],
+                "file": "v1/https/repo1.maven.org/maven2/org/ow2/asm/asm-util/7.2/asm-util-7.2.jar",
+                "mirror_urls": [
+                    "https://repo1.maven.org/maven2/org/ow2/asm/asm-util/7.2/asm-util-7.2.jar",
+                    "https://repo.maven.apache.org/maven2/org/ow2/asm/asm-util/7.2/asm-util-7.2.jar"
+                ],
+                "sha256": "6e24913b021ffacfe8e7e053d6e0ccc731941148cfa078d4f1ed3d96904530f8",
+                "url": "https://repo1.maven.org/maven2/org/ow2/asm/asm-util/7.2/asm-util-7.2.jar"
+            },
+            {
                 "coord": "org.ow2.asm:asm:9.0",
                 "dependencies": [],
                 "directDependencies": [],
diff --git a/objectivec/.clang-format b/objectivec/.clang-format
index d3ff76b..f6cb8ad 100644
--- a/objectivec/.clang-format
+++ b/objectivec/.clang-format
@@ -1,7 +1 @@
 BasedOnStyle: Google
-
-# Ignore pddm directives.
-CommentPragmas: '^%'
-
-# Following the rest of the protobuf code.
-ColumnLimit: 80
diff --git a/objectivec/BUILD.bazel b/objectivec/BUILD.bazel
index c18788f..153894f 100644
--- a/objectivec/BUILD.bazel
+++ b/objectivec/BUILD.bazel
@@ -1,5 +1,6 @@
 load("@rules_cc//cc:defs.bzl", "objc_library")
 load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//conformance:defs.bzl", "conformance_test")
 
 objc_library(
     name = "objectivec",
@@ -90,6 +91,20 @@
     visibility = ["//visibility:public"],
 )
 
+################################################################################
+# Tests
+################################################################################
+
+conformance_test(
+    name = "conformance_test",
+    failure_list = "//conformance:failure_list_objc.txt",
+    testee = "//conformance:conformance_objc",
+)
+
+################################################################################
+# Distribution files
+################################################################################
+
 pkg_files(
     name = "dist_files",
     srcs = glob([
diff --git a/objectivec/DevTools/check_version_stamps.sh b/objectivec/DevTools/check_version_stamps.sh
index a3524cb..5972e35 100755
--- a/objectivec/DevTools/check_version_stamps.sh
+++ b/objectivec/DevTools/check_version_stamps.sh
@@ -16,7 +16,7 @@
     exit 1
 }
 
-readonly GeneratorSrc="${ProtoRootDir}/src/google/protobuf/compiler/objectivec/objectivec_file.cc"
+readonly GeneratorSrc="${ProtoRootDir}/src/google/protobuf/compiler/objectivec/file.cc"
 readonly RuntimeSrc="${ProtoRootDir}/objectivec/GPBBootstrap.h"
 
 check_constant() {
diff --git a/objectivec/DevTools/compile_testing_protos.sh b/objectivec/DevTools/compile_testing_protos.sh
index 69c32f9..fb8a853 100755
--- a/objectivec/DevTools/compile_testing_protos.sh
+++ b/objectivec/DevTools/compile_testing_protos.sh
@@ -26,45 +26,15 @@
 esac
 
 # -----------------------------------------------------------------------------
-# Reusing a bunch of the protos from the protocolbuffers/protobuf tree, this
-# can include some extras as there is no harm in ensuring work for C++
-# generation.
-
-CORE_PROTO_FILES=(
-  src/google/protobuf/any_test.proto
-  src/google/protobuf/unittest_arena.proto
-  src/google/protobuf/unittest_custom_options.proto
-  src/google/protobuf/unittest_enormous_descriptor.proto
-  src/google/protobuf/unittest_embed_optimize_for.proto
-  src/google/protobuf/unittest_empty.proto
-  src/google/protobuf/unittest_import.proto
-  src/google/protobuf/unittest_import_lite.proto
-  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_generic_services.proto
-  src/google/protobuf/unittest_optimize_for.proto
-  src/google/protobuf/unittest.proto
-  src/google/protobuf/unittest_import_public.proto
-  src/google/protobuf/unittest_import_public_lite.proto
-  src/google/protobuf/unittest_drop_unknown_fields.proto
-  src/google/protobuf/unittest_preserve_unknown_enum.proto
-  src/google/protobuf/map_lite_unittest.proto
-  src/google/protobuf/map_proto2_unittest.proto
-  src/google/protobuf/map_unittest.proto
-  # The unittest_custom_options.proto extends the messages in descriptor.proto
-  # so we build it in to test extending in general. The library doesn't provide
-  # a descriptor as it doesn't use the classes/enums.
-  src/google/protobuf/descriptor.proto
-)
-
-# -----------------------------------------------------------------------------
 # The objc unittest specific proto files.
 
 OBJC_TEST_PROTO_FILES=(
+  objectivec/Tests/any_test.proto
+  objectivec/Tests/map_proto2_unittest.proto
+  objectivec/Tests/map_unittest.proto
   objectivec/Tests/unittest_cycle.proto
-  objectivec/Tests/unittest_deprecated.proto
   objectivec/Tests/unittest_deprecated_file.proto
+  objectivec/Tests/unittest_deprecated.proto
   objectivec/Tests/unittest_extension_chain_a.proto
   objectivec/Tests/unittest_extension_chain_b.proto
   objectivec/Tests/unittest_extension_chain_c.proto
@@ -72,24 +42,30 @@
   objectivec/Tests/unittest_extension_chain_e.proto
   objectivec/Tests/unittest_extension_chain_f.proto
   objectivec/Tests/unittest_extension_chain_g.proto
-  objectivec/Tests/unittest_objc.proto
-  objectivec/Tests/unittest_objc_startup.proto
+  objectivec/Tests/unittest_import_public.proto
+  objectivec/Tests/unittest_import.proto
+  objectivec/Tests/unittest_mset.proto
   objectivec/Tests/unittest_objc_options.proto
+  objectivec/Tests/unittest_objc_startup.proto
+  objectivec/Tests/unittest_objc.proto
+  objectivec/Tests/unittest_preserve_unknown_enum.proto
   objectivec/Tests/unittest_runtime_proto2.proto
   objectivec/Tests/unittest_runtime_proto3.proto
+  objectivec/Tests/unittest.proto
 )
 
 OBJC_EXTENSIONS=( .pbobjc.h .pbobjc.m )
 
 # -----------------------------------------------------------------------------
 # Ensure the output dir exists
-mkdir -p "${OUTPUT_DIR}/google/protobuf"
+mkdir -p "${OUTPUT_DIR}"
 
 # -----------------------------------------------------------------------------
 # Move to the top of the protobuf directories and ensure there is a protoc
 # binary to use.
 cd "${SRCROOT}/.."
-[[ -x src/protoc ]] || \
+readonly PROTOC="bazel-bin/protoc"
+[[ -x "${PROTOC}" ]] || \
   die "Could not find the protoc binary; make sure you have built it (objectivec/DevTools/full_mac_build.sh -h)."
 
 # -----------------------------------------------------------------------------
@@ -97,7 +73,7 @@
 
 # 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
+for PROTO_FILE in "${OBJC_TEST_PROTO_FILES[@]}"; do
   DIR=${PROTO_FILE%/*}
   BASE_NAME=${PROTO_FILE##*/}
   # Drop the extension
@@ -105,7 +81,7 @@
   OBJC_NAME=$(echo "${BASE_NAME}" | awk -F _ '{for(i=1; i<=NF; i++) printf "%s", toupper(substr($i,1,1)) substr($i,2);}')
 
   for EXT in "${OBJC_EXTENSIONS[@]}"; do
-    if [[ ! -f "${OUTPUT_DIR}/google/protobuf/${OBJC_NAME}${EXT}" ]]; then
+    if [[ ! -f "${OUTPUT_DIR}/${DIR}/${OBJC_NAME}${EXT}" ]]; then
       RUN_PROTOC=yes
     fi
   done
@@ -118,9 +94,7 @@
   # (these patterns catch some extra stuff, but better to over sample than
   # under)
   readonly NewestInput=$(find \
-     src/google/protobuf/*.proto \
-     objectivec/Tests/*.proto \
-     src/.libs src/*.la src/protoc \
+     objectivec/Tests/*.proto "${PROTOC}" \
      objectivec/DevTools/compile_testing_protos.sh \
         -type f -print0 \
         | xargs -0 stat -f "%m %N" \
@@ -150,28 +124,13 @@
     | xargs -0 rm -rf
 
 # -----------------------------------------------------------------------------
-# Helper to invoke protoc
-compile_protos() {
-  src/protoc                                   \
-    --objc_out="${OUTPUT_DIR}/google/protobuf" \
-    --proto_path=src/google/protobuf/          \
-    --proto_path=src                           \
-    --experimental_allow_proto3_optional       \
-    "$@"
-}
-
-# -----------------------------------------------------------------------------
-# Generate most of the proto files that exist in the C++ src tree.
-
-# Note: there is overlap in package.Message names between some of the test
-# files, so they can't be generated all at once. This works because the overlap
-# isn't linked into a single binary.
-for a_proto in "${CORE_PROTO_FILES[@]}" ; do
-  compile_protos "${a_proto}"
-done
-
-# -----------------------------------------------------------------------------
 # Generate the Objective C specific testing protos.
-compile_protos \
-  --proto_path="objectivec/Tests" \
+
+"${PROTOC}"                                                                 \
+  --objc_out="${OUTPUT_DIR}"                                                \
+  --objc_opt=expected_prefixes_path=objectivec/Tests/expected_prefixes.txt  \
+  --objc_opt=prefixes_must_be_registered=yes                                \
+  --objc_opt=require_prefixes=yes                                           \
+  --proto_path=.                                                            \
+  --proto_path=src                                                          \
   "${OBJC_TEST_PROTO_FILES[@]}"
diff --git a/objectivec/DevTools/full_mac_build.sh b/objectivec/DevTools/full_mac_build.sh
index 98b71a6..4fed4f5 100755
--- a/objectivec/DevTools/full_mac_build.sh
+++ b/objectivec/DevTools/full_mac_build.sh
@@ -8,6 +8,11 @@
 # Some base locations.
 readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
 readonly ProtoRootDir="${ScriptDir}/../.."
+readonly BazelFlags="--announce_rc --macos_minimum_os=10.9 \
+  $(${ScriptDir}/../../kokoro/common/bazel_flags.sh)"
+
+# Invoke with BAZEL=bazelisk to use that instead.
+readonly BazelBin="${BAZEL:=bazel}"
 
 printUsage() {
   NAME=$(basename "${0}")
@@ -24,13 +29,9 @@
          Show this message
    -c, --clean
          Issue a clean before the normal build.
-   -a, --autogen
-         Start by rerunning autogen & configure.
    -r, --regenerate-descriptors
          Run generate_descriptor_proto.sh to regenerate all the checked in
          proto sources.
-   -j #, --jobs #
-         Force the number of parallel jobs (useful for debugging build issues).
    --core-only
          Skip some of the core protobuf build/checks to shorten the build time.
    --skip-xcode
@@ -60,25 +61,7 @@
   echo "========================================================================"
 }
 
-# Thanks to libtool, builds can fail in odd ways and since it eats some output
-# it can be hard to spot, so force error output if make exits with a non zero.
-wrapped_make() {
-  set +e  # Don't stop if the command fails.
-  make $*
-  MAKE_EXIT_STATUS=$?
-  if [ ${MAKE_EXIT_STATUS} -ne 0 ]; then
-    echo "Error: 'make $*' exited with status ${MAKE_EXIT_STATUS}"
-    exit ${MAKE_EXIT_STATUS}
-  fi
-  set -e
-}
-
-NUM_MAKE_JOBS=$(/usr/sbin/sysctl -n hw.ncpu)
-if [[ "${NUM_MAKE_JOBS}" -lt 2 ]] ; then
-  NUM_MAKE_JOBS=2
-fi
-
-DO_AUTOGEN=no
+BAZEL=bazel
 DO_CLEAN=no
 REGEN_DESCRIPTORS=no
 CORE_ONLY=no
@@ -98,16 +81,9 @@
     -c | --clean )
       DO_CLEAN=yes
       ;;
-    -a | --autogen )
-      DO_AUTOGEN=yes
-      ;;
     -r | --regenerate-descriptors )
       REGEN_DESCRIPTORS=yes
       ;;
-    -j | --jobs )
-      shift
-      NUM_MAKE_JOBS="${1}"
-      ;;
     --core-only )
       CORE_ONLY=yes
       ;;
@@ -154,21 +130,9 @@
 # Into the proto dir.
 cd "${ProtoRootDir}"
 
-# if no Makefile, force the autogen.
-if [[ ! -f Makefile ]] ; then
-  DO_AUTOGEN=yes
-fi
-
-if [[ "${DO_AUTOGEN}" == "yes" ]] ; then
-  header "Running autogen & configure"
-  ./autogen.sh
-  ./configure \
-    CPPFLAGS="-mmacosx-version-min=10.9 -Wunused-const-variable -Wunused-function"
-fi
-
 if [[ "${DO_CLEAN}" == "yes" ]] ; then
   header "Cleaning"
-  wrapped_make clean
+  "${BazelBin}" clean
   if [[ "${DO_XCODE_IOS_TESTS}" == "yes" ]] ; then
     XCODEBUILD_CLEAN_BASE_IOS=(
       xcodebuild
@@ -212,26 +176,21 @@
 
 if [[ "${REGEN_DESCRIPTORS}" == "yes" ]] ; then
   header "Regenerating the descriptor sources."
-  ./generate_descriptor_proto.sh -j "${NUM_MAKE_JOBS}"
+  ./generate_descriptor_proto.sh
 fi
 
 if [[ "${CORE_ONLY}" == "yes" ]] ; then
   header "Building core Only"
-  wrapped_make -j "${NUM_MAKE_JOBS}"
+  "${BazelBin}" build //:protoc //:protobuf //:protobuf_lite $BazelFlags
 else
   header "Building"
   # Can't issue these together, when fully parallel, something sometimes chokes
   # at random.
-  wrapped_make -j "${NUM_MAKE_JOBS}" all
-  wrapped_make -j "${NUM_MAKE_JOBS}" check
-  # Fire off the conformance tests also.
-  cd conformance
-  wrapped_make -j "${NUM_MAKE_JOBS}" test_cpp
-  cd ..
+  "${BazelBin}" test //src/... $BazelFlags
 fi
 
 # Ensure the WKT sources checked in are current.
-objectivec/generate_well_known_types.sh --check-only -j "${NUM_MAKE_JOBS}"
+BAZEL="${BazelBin}" objectivec/generate_well_known_types.sh --check-only $BazelFlags
 
 header "Checking on the ObjC Runtime Code"
 # Some of the kokoro machines don't have python3 yet, so fall back to python if need be.
@@ -264,38 +223,11 @@
   # just pick a mix of OS Versions and 32/64 bit.
   # NOTE: Different Xcode have different simulated hardware/os support.
   case "${XCODE_VERSION}" in
-    [6-8].* )
-      echo "ERROR: The unittests include Swift code that is now Swift 4.0." 1>&2
-      echo "ERROR: Xcode 9.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2
+    [6-9].* | 1[0-2].* )
+      echo "ERROR: Xcode 13.3.1 or higher is required." 1>&2
       exit 11
       ;;
-    9.[0-2]* )
-      XCODEBUILD_TEST_BASE_IOS+=(
-          -destination "platform=iOS Simulator,name=iPhone 4s,OS=8.1" # 32bit
-          -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit
-          # 9.0-9.2 all seem to often fail running destinations in parallel
-          -disable-concurrent-testing
-      )
-      ;;
-    9.[3-4]* )
-      XCODEBUILD_TEST_BASE_IOS+=(
-          # Xcode 9.3 chokes targeting iOS 8.x - http://www.openradar.me/39335367
-          -destination "platform=iOS Simulator,name=iPhone 4s,OS=9.0" # 32bit
-          -destination "platform=iOS Simulator,name=iPhone 7,OS=latest" # 64bit
-          # 9.3 also seems to often fail running destinations in parallel
-          -disable-concurrent-testing
-      )
-      ;;
-    10.*)
-      XCODEBUILD_TEST_BASE_IOS+=(
-          -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 at least)
-          -disable-concurrent-destination-testing
-      )
-      ;;
-    11.* | 12.* | 13.* | 14.*)
+    13.* | 14.*)
       # 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
@@ -332,9 +264,8 @@
     XCODEBUILD_TEST_BASE_OSX+=( -quiet )
   fi
   case "${XCODE_VERSION}" in
-    [6-8].* )
-      echo "ERROR: The unittests include Swift code that is now Swift 4.0." 1>&2
-      echo "ERROR: Xcode 9.0 or higher is required to build the test suite, but the library works with Xcode 7.x." 1>&2
+    [6-9].* | 1[0-2].* )
+      echo "ERROR: Xcode 13.3.1 or higher is required." 1>&2
       exit 11
       ;;
   esac
@@ -354,15 +285,10 @@
       -scheme ProtocolBuffers
   )
   case "${XCODE_VERSION}" in
-    [6-9].* )
-      echo "ERROR: Xcode 10.0 or higher is required to build the test suite." 1>&2
+    [6-9].* | 1[0-2].* )
+      echo "ERROR: Xcode 13.3.1 or higher is required." 1>&2
       exit 11
       ;;
-    10.* | 11.* | 12.*)
-      XCODEBUILD_TEST_BASE_TVOS+=(
-        -destination "platform=tvOS Simulator,name=Apple TV 4K,OS=latest"
-      )
-      ;;
     13.* | 14.*)
       XCODEBUILD_TEST_BASE_TVOS+=(
         -destination "platform=tvOS Simulator,name=Apple TV 4K (2nd generation),OS=latest"
@@ -391,9 +317,7 @@
 
 if [[ "${DO_OBJC_CONFORMANCE_TESTS}" == "yes" ]] ; then
   header "Running ObjC Conformance Tests"
-  cd conformance
-  wrapped_make -j "${NUM_MAKE_JOBS}" test_objc
-  cd ..
+  "${BazelBin}" test //objectivec:conformance_test $BazelFlags
 fi
 
 echo ""
diff --git a/objectivec/DevTools/pddm.py b/objectivec/DevTools/pddm.py
index 60ff089..11925b1 100755
--- a/objectivec/DevTools/pddm.py
+++ b/objectivec/DevTools/pddm.py
@@ -485,14 +485,13 @@
         if self._macro_collection:
           # Always add a blank line, seems to read better. (If need be, add an
           # option to the EXPAND to indicate if this should be done.)
-          result.extend([_GENERATED_CODE_LINE, '// clang-format off', ''])
+          result.extend([_GENERATED_CODE_LINE, ''])
           macro = line[directive_len:].strip()
           try:
             expand_result = self._macro_collection.Expand(macro)
             # Since expansions are line oriented, strip trailing whitespace
             # from the lines.
             lines = [x.rstrip() for x in expand_result.split('\n')]
-            lines.append('// clang-format on')
             result.append('\n'.join(lines))
           except PDDMError as e:
             raise PDDMError('%s\n...while expanding "%s" from the section'
diff --git a/objectivec/DevTools/pddm_tests.py b/objectivec/DevTools/pddm_tests.py
index d5b88c9..2d9c47f 100755
--- a/objectivec/DevTools/pddm_tests.py
+++ b/objectivec/DevTools/pddm_tests.py
@@ -418,24 +418,18 @@
 foo
 //%PDDM-EXPAND mumble(abc)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 abc: doAbc(int abc);
-// clang-format on
 //%PDDM-EXPAND-END mumble(abc)
 bar
 //%PDDM-EXPAND mumble(def)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 def: doDef(int def);
-// clang-format on
 //%PDDM-EXPAND mumble(ghi)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 ghi: doGhi(int ghi);
-// clang-format on
 //%PDDM-EXPAND-END (2 expansions)
 baz
 //%PDDM-DEFINE mumble(a_)
diff --git a/objectivec/GPBAny.pbobjc.h b/objectivec/GPBAny.pbobjc.h
index 7fb4129..bb19e5f 100644
--- a/objectivec/GPBAny.pbobjc.h
+++ b/objectivec/GPBAny.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/any.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -68,6 +69,10 @@
  *     if (any.is(Foo.class)) {
  *       foo = any.unpack(Foo.class);
  *     }
+ *     // or ...
+ *     if (any.isSameTypeAs(Foo.getDefaultInstance())) {
+ *       foo = any.unpack(Foo.getDefaultInstance());
+ *     }
  *
  * Example 3: Pack and unpack a message in Python.
  *
@@ -98,7 +103,6 @@
  * in the type URL, for example "foo.bar.com/x/y.z" will yield type
  * name "y.z".
  *
- *
  * JSON
  *
  * The JSON representation of an `Any` value uses the regular
@@ -172,3 +176,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBAny.pbobjc.m b/objectivec/GPBAny.pbobjc.m
index 7632c8c..5091217 100644
--- a/objectivec/GPBAny.pbobjc.m
+++ b/objectivec/GPBAny.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/any.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -78,7 +79,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBAny__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
 #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
     static const char *extraTextFormatInfo =
         "\001\001\004\241!!\000";
@@ -98,3 +99,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBApi.pbobjc.h b/objectivec/GPBApi.pbobjc.h
index 871e908..bbae2ed 100644
--- a/objectivec/GPBApi.pbobjc.h
+++ b/objectivec/GPBApi.pbobjc.h
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/api.proto
 
 #import "GPBDescriptor.h"
@@ -7,10 +8,10 @@
 #import "GPBSourceContext.pbobjc.h"
 #import "GPBType.pbobjc.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -74,12 +75,12 @@
 
 /** The methods of this interface, in unspecified order. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMethod*> *methodsArray;
-/** The number of items in @c methodsArray without causing the array to be created. */
+/** The number of items in @c methodsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger methodsArray_Count;
 
 /** Any metadata attached to the interface. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/** The number of items in @c optionsArray without causing the array to be created. */
+/** The number of items in @c optionsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 /**
@@ -115,7 +116,7 @@
 
 /** Included interfaces. See [Mixin][]. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBMixin*> *mixinsArray;
-/** The number of items in @c mixinsArray without causing the array to be created. */
+/** The number of items in @c mixinsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger mixinsArray_Count;
 
 /** The source syntax of the service. */
@@ -169,7 +170,7 @@
 
 /** Any metadata attached to the method. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/** The number of items in @c optionsArray without causing the array to be created. */
+/** The number of items in @c optionsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 /** The source syntax of this method. */
@@ -296,3 +297,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBApi.pbobjc.m b/objectivec/GPBApi.pbobjc.m
index 7f86a08..33ca398 100644
--- a/objectivec/GPBApi.pbobjc.m
+++ b/objectivec/GPBApi.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/api.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -143,7 +144,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBApi__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -264,7 +265,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBMethod__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
 #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
     static const char *extraTextFormatInfo =
         "\002\002\007\244\241!!\000\004\010\244\241!!\000";
@@ -337,7 +338,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBMixin__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -352,3 +353,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBArray.h b/objectivec/GPBArray.h
index 5aea75c..4985dbe 100644
--- a/objectivec/GPBArray.h
+++ b/objectivec/GPBArray.h
@@ -34,9 +34,11 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-EXPAND DECLARE_ARRAYS()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int32
 
@@ -135,7 +137,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -147,7 +150,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 /**
  * Adds a value to this array.
@@ -307,7 +311,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -319,7 +324,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 /**
  * Adds a value to this array.
@@ -479,7 +485,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -491,7 +498,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 /**
  * Adds a value to this array.
@@ -651,7 +659,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -663,7 +672,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 /**
  * Adds a value to this array.
@@ -823,7 +833,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -835,7 +846,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 /**
  * Adds a value to this array.
@@ -995,7 +1007,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -1007,7 +1020,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 /**
  * Adds a value to this array.
@@ -1167,7 +1181,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -1179,7 +1194,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 /**
  * Adds a value to this array.
@@ -1370,7 +1386,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx,
+                                                       BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -1382,7 +1399,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+                        usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx,
+                                                         BOOL *stop))block;
 
 // These methods bypass the validationFunc to provide access to values that were not
 // known at the time the binary was compiled.
@@ -1404,7 +1422,8 @@
  *   **idx**:   The index of the current value.
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
-- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx,
+                                                          BOOL *stop))block;
 
 /**
  * Enumerates the values on this array with the given block.
@@ -1416,7 +1435,8 @@
  *   **stop**:  A pointer to a boolean that when set stops the enumeration.
  **/
 - (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
-                           usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block;
+                           usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx,
+                                                          BOOL *stop))block;
 
 // If value is not a valid enumerator as defined by validationFunc, these
 // methods will assert in debug, and will log in release and assign the value
@@ -1536,7 +1556,6 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END DECLARE_ARRAYS()
 
 NS_ASSUME_NONNULL_END
@@ -1781,7 +1800,8 @@
 //% *   **idx**:   The index of the current value.
 //% *   **stop**:  A pointer to a boolean that when set stops the enumeration.
 //% **/
-//%- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx,
+//%                                                          BOOL *stop))block;
 //%
 //%/**
 //% * Enumerates the values on this array with the given block.
@@ -1793,7 +1813,8 @@
 //% *   **stop**:  A pointer to a boolean that when set stops the enumeration.
 //% **/
 //%- (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
-//%                           usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%                           usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx,
+//%                                                          BOOL *stop))block;
 //%
 //%// If value is not a valid enumerator as defined by validationFunc, these
 //%// methods will assert in debug, and will log in release and assign the value
@@ -1823,7 +1844,8 @@
 //% *   **idx**:   The index of the current value.
 //% *   **stop**:  A pointer to a boolean that when set stops the enumeration.
 //% **/
-//%- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx,
+//%                                                       BOOL *stop))block;
 //%
 //%/**
 //% * Enumerates the values on this array with the given block.
@@ -1835,7 +1857,8 @@
 //% *   **stop**:  A pointer to a boolean that when set stops the enumeration.
 //% **/
 //%- (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-//%                        usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block;
+//%                        usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx,
+//%                                                         BOOL *stop))block;
 
 //%PDDM-DEFINE ARRAY_MUTABLE_INTERFACE(NAME, TYPE, HELPER_NAME)
 //%/**
@@ -1967,3 +1990,5 @@
 //%
 //%// No validation applies to these methods.
 //%
+
+// clang-format on
diff --git a/objectivec/GPBArray.m b/objectivec/GPBArray.m
index bb9a077..eba7d15 100644
--- a/objectivec/GPBArray.m
+++ b/objectivec/GPBArray.m
@@ -47,6 +47,9 @@
   return (value != kGPBUnrecognizedEnumeratorValue);
 }
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-DEFINE VALIDATE_RANGE(INDEX, COUNT)
 //%  if (INDEX >= COUNT) {
 //%    [NSException raise:NSRangeException
@@ -194,12 +197,12 @@
 //%  return result;
 //%}
 //%
-//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block {
+//%- (void)enumerate##ACCESSOR_NAME##ValuesWithBlock:(void(NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block {
 //%  [self enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 //%}
 //%
 //%- (void)enumerate##ACCESSOR_NAME##ValuesWithOptions:(NSEnumerationOptions)opts
-//%                  ACCESSOR_NAME$S      usingBlock:(void (NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block {
+//%                  ACCESSOR_NAME$S      usingBlock:(void(NS_NOESCAPE ^)(TYPE value, NSUInteger idx, BOOL *stop))block {
 //%  // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
 //%  BOOL stop = NO;
 //%  if ((opts & NSEnumerationReverse) == 0) {
@@ -292,10 +295,8 @@
 //%  _values[idx2] = temp;
 //%}
 //%
-
 //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int32, int32_t, %d)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int32
 
@@ -406,12 +407,12 @@
   return result;
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -542,10 +543,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt32, uint32_t, %u)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - UInt32
 
@@ -656,12 +655,12 @@
   return result;
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(uint32_t value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -792,10 +791,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Int64, int64_t, %lld)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int64
 
@@ -906,12 +903,12 @@
   return result;
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(int64_t value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -1042,10 +1039,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(UInt64, uint64_t, %llu)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - UInt64
 
@@ -1156,12 +1151,12 @@
   return result;
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(uint64_t value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -1292,10 +1287,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Float, float, %f)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Float
 
@@ -1406,12 +1399,12 @@
   return result;
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(float value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -1542,10 +1535,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Double, double, %lf)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Double
 
@@ -1656,12 +1647,12 @@
   return result;
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(double value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -1792,10 +1783,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_INTERFACE_SIMPLE(Bool, BOOL, %d)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool
 
@@ -1906,12 +1895,12 @@
   return result;
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(BOOL value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -2042,9 +2031,10 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END (7 expansions)
 
+// clang-format on
+
 #pragma mark - Enum
 
 @implementation GPBEnumArray {
@@ -2066,19 +2056,15 @@
   return [[[self alloc] initWithValidationFunction:func] autorelease];
 }
 
-+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
-                                   rawValue:(int32_t)value {
-  return [[[self alloc] initWithValidationFunction:func
-                                         rawValues:&value
-                                             count:1] autorelease];
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func rawValue:(int32_t)value {
+  return [[[self alloc] initWithValidationFunction:func rawValues:&value count:1] autorelease];
 }
 
 + (instancetype)arrayWithValueArray:(GPBEnumArray *)array {
-  return [[(GPBEnumArray*)[self alloc] initWithValueArray:array] autorelease];
+  return [[(GPBEnumArray *)[self alloc] initWithValueArray:array] autorelease];
 }
 
-+ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func
-                                   capacity:(NSUInteger)count {
++ (instancetype)arrayWithValidationFunction:(GPBEnumValidationFunc)func capacity:(NSUInteger)count {
   return [[[self alloc] initWithValidationFunction:func capacity:count] autorelease];
 }
 
@@ -2101,7 +2087,7 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                 rawValues:(const int32_t [])values
+                                 rawValues:(const int32_t[])values
                                      count:(NSUInteger)count {
   self = [self initWithValidationFunction:func];
   if (self) {
@@ -2113,17 +2099,16 @@
         _count = count;
       } else {
         [self release];
-        [NSException raise:NSMallocException
-                    format:@"Failed to allocate %lu bytes",
-                           (unsigned long)(count * sizeof(int32_t))];
+        [NSException
+             raise:NSMallocException
+            format:@"Failed to allocate %lu bytes", (unsigned long)(count * sizeof(int32_t))];
       }
     }
   }
   return self;
 }
 
-- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                  capacity:(NSUInteger)count {
+- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func capacity:(NSUInteger)count {
   self = [self initWithValidationFunction:func];
   if (self && count) {
     [self internalResizeToCapacity:count];
@@ -2132,15 +2117,16 @@
 }
 
 - (instancetype)copyWithZone:(NSZone *)zone {
-  return [[GPBEnumArray allocWithZone:zone]
-             initWithValidationFunction:_validationFunc
-                              rawValues:_values
-                                  count:_count];
+  return [[GPBEnumArray allocWithZone:zone] initWithValidationFunction:_validationFunc
+                                                             rawValues:_values
+                                                                 count:_count];
 }
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-EXPAND ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)dealloc {
   NSAssert(!_autocreator,
@@ -2180,12 +2166,12 @@
   return result;
 }
 
-- (void)enumerateRawValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateRawValuesWithBlock:(void(NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
   [self enumerateRawValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateRawValuesWithOptions:(NSEnumerationOptions)opts
-                           usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+                           usingBlock:(void(NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   if ((opts & NSEnumerationReverse) == 0) {
@@ -2200,21 +2186,22 @@
     }
   }
 }
-// clang-format on
 //%PDDM-EXPAND-END ARRAY_IMMUTABLE_CORE(Enum, int32_t, Raw, %d)
 
+// clang-format on
+
 - (int32_t)valueAtIndex:(NSUInteger)index {
+  // clang-format off
 //%PDDM-EXPAND VALIDATE_RANGE(index, _count)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   if (index >= _count) {
     [NSException raise:NSRangeException
                 format:@"Index (%lu) beyond bounds (%lu)",
                        (unsigned long)index, (unsigned long)_count];
   }
-// clang-format on
 //%PDDM-EXPAND-END VALIDATE_RANGE(index, _count)
+  // clang-format on
   int32_t result = _values[index];
   if (!_validationFunc(result)) {
     result = kGPBUnrecognizedEnumeratorValue;
@@ -2223,26 +2210,28 @@
 }
 
 - (int32_t)rawValueAtIndex:(NSUInteger)index {
+  // clang-format off
 //%PDDM-EXPAND VALIDATE_RANGE(index, _count)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   if (index >= _count) {
     [NSException raise:NSRangeException
                 format:@"Index (%lu) beyond bounds (%lu)",
                        (unsigned long)index, (unsigned long)_count];
   }
-// clang-format on
 //%PDDM-EXPAND-END VALIDATE_RANGE(index, _count)
+  // clang-format on
   return _values[index];
 }
 
-- (void)enumerateValuesWithBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateValuesWithBlock:(void(NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))
+                                     block {
   [self enumerateValuesWithOptions:(NSEnumerationOptions)0 usingBlock:block];
 }
 
 - (void)enumerateValuesWithOptions:(NSEnumerationOptions)opts
-                        usingBlock:(void (NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))block {
+                        usingBlock:(void(NS_NOESCAPE ^)(int32_t value, NSUInteger idx, BOOL *stop))
+                                       block {
   // NSEnumerationConcurrent isn't currently supported (and Apple's docs say that is ok).
   BOOL stop = NO;
   GPBEnumValidationFunc func = _validationFunc;
@@ -2271,9 +2260,10 @@
   }
 }
 
+// clang-format off
+
 //%PDDM-EXPAND ARRAY_MUTABLE_CORE(Enum, int32_t, Raw, %d)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)internalResizeToCapacity:(NSUInteger)newCapacity {
   _values = reallocf(_values, newCapacity * sizeof(int32_t));
@@ -2379,10 +2369,8 @@
   _values[idx2] = temp;
 }
 
-// clang-format on
 //%PDDM-EXPAND MUTATION_METHODS(Enum, int32_t, , EnumValidationList, EnumValidationOne)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)addValue:(int32_t)value {
   [self addValues:&value count:1];
@@ -2449,7 +2437,6 @@
   }
   _values[index] = value;
 }
-// clang-format on
 //%PDDM-EXPAND-END (2 expansions)
 
 //%PDDM-DEFINE MUTATION_HOOK_EnumValidationList()
@@ -2470,6 +2457,8 @@
 //%  }
 //%
 
+// clang-format on
+
 @end
 
 #pragma mark - NSArray Subclass
@@ -2479,8 +2468,7 @@
 }
 
 - (void)dealloc {
-  NSAssert(!_autocreator,
-           @"%@: Autocreator must be cleared before release, autocreator: %@",
+  NSAssert(!_autocreator, @"%@: Autocreator must be cleared before release, autocreator: %@",
            [self class], _autocreator);
   [_array release];
   [super dealloc];
@@ -2556,17 +2544,17 @@
 }
 
 - (NSUInteger)countByEnumeratingWithState:(NSFastEnumerationState *)state
-                                  objects:(id __unsafe_unretained [])buffer
+                                  objects:(id __unsafe_unretained[])buffer
                                     count:(NSUInteger)len {
   return [_array countByEnumeratingWithState:state objects:buffer count:len];
 }
 
-- (void)enumerateObjectsUsingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block {
+- (void)enumerateObjectsUsingBlock:(void(NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block {
   [_array enumerateObjectsUsingBlock:block];
 }
 
 - (void)enumerateObjectsWithOptions:(NSEnumerationOptions)opts
-                         usingBlock:(void (NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block {
+                         usingBlock:(void(NS_NOESCAPE ^)(id obj, NSUInteger idx, BOOL *stop))block {
   [_array enumerateObjectsWithOptions:opts usingBlock:block];
 }
 
diff --git a/objectivec/GPBArray_PackagePrivate.h b/objectivec/GPBArray_PackagePrivate.h
index 07eab89..35a4538 100644
--- a/objectivec/GPBArray_PackagePrivate.h
+++ b/objectivec/GPBArray_PackagePrivate.h
@@ -54,7 +54,6 @@
 
 //%PDDM-EXPAND DECLARE_ARRAY_EXTRAS()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int32
 
@@ -120,7 +119,6 @@
 }
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END DECLARE_ARRAY_EXTRAS()
 
 #pragma mark - NSArray Subclass
diff --git a/objectivec/GPBBootstrap.h b/objectivec/GPBBootstrap.h
index ea5986b..6e3499b 100644
--- a/objectivec/GPBBootstrap.h
+++ b/objectivec/GPBBootstrap.h
@@ -42,7 +42,7 @@
 // Used in the generated code to give sizes to enums. int32_t was chosen based
 // on the fact that Protocol Buffers enums are limited to this range.
 #if !__has_feature(objc_fixed_enum)
- #error All supported Xcode versions should support objc_fixed_enum.
+#error All supported Xcode versions should support objc_fixed_enum.
 #endif
 
 // If the headers are imported into Objective-C++, we can run into an issue
@@ -52,9 +52,11 @@
 // providing a local definition. The default case has to use NS_ENUM for the
 // magic that is Swift bridging of enums.
 #if (defined(__cplusplus) && __cplusplus && __cplusplus < 201103L)
- #define GPB_ENUM(X) enum X : int32_t X; enum X : int32_t
+#define GPB_ENUM(X)   \
+  enum X : int32_t X; \
+  enum X : int32_t
 #else
- #define GPB_ENUM(X) NS_ENUM(int32_t, X)
+#define GPB_ENUM(X) NS_ENUM(int32_t, X)
 #endif
 
 /**
@@ -132,13 +134,12 @@
 // 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 30004
+#define GOOGLE_PROTOBUF_OBJC_VERSION 30005
 
 // Minimum runtime version supported for compiling/running against.
 // - Gets changed when support for the older generated code is dropped.
 #define GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION 30001
 
-
 // This is a legacy constant now frozen in time for old generated code. If
 // GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION ever gets moved above 30001 then
 // this should also change to break code compiled with an old runtime that
diff --git a/objectivec/GPBCodedInputStream.h b/objectivec/GPBCodedInputStream.h
index 1886ccf..cbfaaf1 100644
--- a/objectivec/GPBCodedInputStream.h
+++ b/objectivec/GPBCodedInputStream.h
@@ -30,8 +30,9 @@
 
 #import <Foundation/Foundation.h>
 
+#import "GPBExtensionRegistry.h"
+
 @class GPBMessage;
-@class GPBExtensionRegistry;
 
 NS_ASSUME_NONNULL_BEGIN
 
@@ -184,7 +185,7 @@
  *                          extensions for message.
  **/
 - (void)readMessage:(GPBMessage *)message
-  extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry;
+    extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry;
 
 /**
  * Reads and discards a single field, given its tag value.
diff --git a/objectivec/GPBCodedInputStream.m b/objectivec/GPBCodedInputStream.m
index c459391..ad5c75e 100644
--- a/objectivec/GPBCodedInputStream.m
+++ b/objectivec/GPBCodedInputStream.m
@@ -36,8 +36,7 @@
 #import "GPBUtilities_PackagePrivate.h"
 #import "GPBWireFormat.h"
 
-NSString *const GPBCodedInputStreamException =
-    GPBNSStringifySymbol(GPBCodedInputStreamException);
+NSString *const GPBCodedInputStreamException = GPBNSStringifySymbol(GPBCodedInputStreamException);
 
 NSString *const GPBCodedInputStreamUnderlyingErrorKey =
     GPBNSStringifySymbol(GPBCodedInputStreamUnderlyingErrorKey);
@@ -55,16 +54,14 @@
 static void RaiseException(NSInteger code, NSString *reason) {
   NSDictionary *errorInfo = nil;
   if ([reason length]) {
-    errorInfo = @{ GPBErrorReasonKey: reason };
+    errorInfo = @{GPBErrorReasonKey : reason};
   }
   NSError *error = [NSError errorWithDomain:GPBCodedInputStreamErrorDomain
                                        code:code
                                    userInfo:errorInfo];
 
-  NSDictionary *exceptionInfo =
-      @{ GPBCodedInputStreamUnderlyingErrorKey: error };
-  [[NSException exceptionWithName:GPBCodedInputStreamException
-                           reason:reason
+  NSDictionary *exceptionInfo = @{GPBCodedInputStreamUnderlyingErrorKey : error};
+  [[NSException exceptionWithName:GPBCodedInputStreamException reason:reason
                          userInfo:exceptionInfo] raise];
 }
 
@@ -105,7 +102,7 @@
 static int64_t ReadRawLittleEndian64(GPBCodedInputStreamState *state) {
   CheckSize(state, sizeof(int64_t));
   // Not using OSReadLittleInt64 because it has undocumented dependency
-  // on reads being aligned.  
+  // on reads being aligned.
   int64_t value;
   memcpy(&value, state->bytes + state->bufferPos, sizeof(int64_t));
   value = OSSwapLittleToHostInt64(value);
@@ -215,8 +212,7 @@
   state->lastTag = ReadRawVarint32(state);
   // Tags have to include a valid wireformat.
   if (!GPBWireFormatIsValidTag(state->lastTag)) {
-    RaiseException(GPBCodedInputStreamErrorInvalidTag,
-                   @"Invalid wireformat in tag.");
+    RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Invalid wireformat in tag.");
   }
   // Zero is not a valid field number.
   if (GPBWireFormatGetTagFieldNumber(state->lastTag) == 0) {
@@ -226,8 +222,7 @@
   return state->lastTag;
 }
 
-NSString *GPBCodedInputStreamReadRetainedString(
-    GPBCodedInputStreamState *state) {
+NSString *GPBCodedInputStreamReadRetainedString(GPBCodedInputStreamState *state) {
   int32_t size = ReadRawVarint32(state);
   NSString *result;
   if (size == 0) {
@@ -254,28 +249,24 @@
   int32_t size = ReadRawVarint32(state);
   if (size < 0) return nil;
   CheckSize(state, size);
-  NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos
-                                          length:size];
+  NSData *result = [[NSData alloc] initWithBytes:state->bytes + state->bufferPos length:size];
   state->bufferPos += size;
   return result;
 }
 
-NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(
-    GPBCodedInputStreamState *state) {
+NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *state) {
   int32_t size = ReadRawVarint32(state);
   if (size < 0) return nil;
   CheckSize(state, size);
   // Cast is safe because freeWhenDone is NO.
-  NSData *result = [[NSData alloc]
-      initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos)
-                   length:size
-             freeWhenDone:NO];
+  NSData *result = [[NSData alloc] initWithBytesNoCopy:(void *)(state->bytes + state->bufferPos)
+                                                length:size
+                                          freeWhenDone:NO];
   state->bufferPos += size;
   return result;
 }
 
-size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
-                                    size_t byteLimit) {
+size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit) {
   byteLimit += state->bufferPos;
   size_t oldLimit = state->currentLimit;
   if (byteLimit > oldLimit) {
@@ -285,8 +276,7 @@
   return oldLimit;
 }
 
-void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state,
-                                 size_t oldLimit) {
+void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, size_t oldLimit) {
   state->currentLimit = oldLimit;
 }
 
@@ -295,12 +285,10 @@
 }
 
 BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state) {
-  return (state->bufferPos == state->bufferSize) ||
-         (state->bufferPos == state->currentLimit);
+  return (state->bufferPos == state->bufferSize) || (state->bufferPos == state->currentLimit);
 }
 
-void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
-                                        int32_t value) {
+void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t value) {
   if (state->lastTag != value) {
     RaiseException(GPBCodedInputStreamErrorInvalidTag, @"Unexpected tag read");
   }
@@ -360,8 +348,8 @@
     case GPBWireFormatStartGroup:
       [self skipMessage];
       GPBCodedInputStreamCheckLastTagWas(
-          &state_, GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag),
-                                        GPBWireFormatEndGroup));
+          &state_,
+          GPBWireFormatMakeTag(GPBWireFormatGetTagFieldNumber(tag), GPBWireFormatEndGroup));
       return YES;
     case GPBWireFormatEndGroup:
       return NO;
@@ -434,27 +422,26 @@
 
 - (void)readGroup:(int32_t)fieldNumber
               message:(GPBMessage *)message
-    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+    extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
   CheckRecursionLimit(&state_);
   ++state_.recursionDepth;
   [message mergeFromCodedInputStream:self extensionRegistry:extensionRegistry];
-  GPBCodedInputStreamCheckLastTagWas(
-      &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
+  GPBCodedInputStreamCheckLastTagWas(&state_,
+                                     GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
   --state_.recursionDepth;
 }
 
-- (void)readUnknownGroup:(int32_t)fieldNumber
-                 message:(GPBUnknownFieldSet *)message {
+- (void)readUnknownGroup:(int32_t)fieldNumber message:(GPBUnknownFieldSet *)message {
   CheckRecursionLimit(&state_);
   ++state_.recursionDepth;
   [message mergeFromCodedInputStream:self];
-  GPBCodedInputStreamCheckLastTagWas(
-      &state_, GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
+  GPBCodedInputStreamCheckLastTagWas(&state_,
+                                     GPBWireFormatMakeTag(fieldNumber, GPBWireFormatEndGroup));
   --state_.recursionDepth;
 }
 
 - (void)readMessage:(GPBMessage *)message
-    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+    extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
   CheckRecursionLimit(&state_);
   int32_t length = ReadRawVarint32(&state_);
   size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
@@ -466,15 +453,14 @@
 }
 
 - (void)readMapEntry:(id)mapDictionary
-    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+    extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
                 field:(GPBFieldDescriptor *)field
         parentMessage:(GPBMessage *)parentMessage {
   CheckRecursionLimit(&state_);
   int32_t length = ReadRawVarint32(&state_);
   size_t oldLimit = GPBCodedInputStreamPushLimit(&state_, length);
   ++state_.recursionDepth;
-  GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field,
-                         parentMessage);
+  GPBDictionaryReadEntry(mapDictionary, self, extensionRegistry, field, parentMessage);
   GPBCodedInputStreamCheckLastTagWas(&state_, 0);
   --state_.recursionDepth;
   GPBCodedInputStreamPopLimit(&state_, oldLimit);
diff --git a/objectivec/GPBCodedInputStream_PackagePrivate.h b/objectivec/GPBCodedInputStream_PackagePrivate.h
index 43ec6e7..2dfc902 100644
--- a/objectivec/GPBCodedInputStream_PackagePrivate.h
+++ b/objectivec/GPBCodedInputStream_PackagePrivate.h
@@ -61,16 +61,15 @@
 // support for older data.
 - (void)readGroup:(int32_t)fieldNumber
               message:(GPBMessage *)message
-    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+    extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry;
 
 // Reads a group field value from the stream and merges it into the given
 // UnknownFieldSet.
-- (void)readUnknownGroup:(int32_t)fieldNumber
-                 message:(GPBUnknownFieldSet *)message;
+- (void)readUnknownGroup:(int32_t)fieldNumber message:(GPBUnknownFieldSet *)message;
 
 // Reads a map entry.
 - (void)readMapEntry:(id)mapDictionary
-    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+    extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
                 field:(GPBFieldDescriptor *)field
         parentMessage:(GPBMessage *)parentMessage;
 @end
@@ -97,16 +96,13 @@
     __attribute((ns_returns_retained));
 NSData *GPBCodedInputStreamReadRetainedBytes(GPBCodedInputStreamState *state)
     __attribute((ns_returns_retained));
-NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(
-    GPBCodedInputStreamState *state) __attribute((ns_returns_retained));
+NSData *GPBCodedInputStreamReadRetainedBytesNoCopy(GPBCodedInputStreamState *state)
+    __attribute((ns_returns_retained));
 
-size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state,
-                                    size_t byteLimit);
-void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state,
-                                 size_t oldLimit);
+size_t GPBCodedInputStreamPushLimit(GPBCodedInputStreamState *state, size_t byteLimit);
+void GPBCodedInputStreamPopLimit(GPBCodedInputStreamState *state, size_t oldLimit);
 size_t GPBCodedInputStreamBytesUntilLimit(GPBCodedInputStreamState *state);
 BOOL GPBCodedInputStreamIsAtEnd(GPBCodedInputStreamState *state);
-void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state,
-                                        int32_t value);
+void GPBCodedInputStreamCheckLastTagWas(GPBCodedInputStreamState *state, int32_t value);
 
 CF_EXTERN_C_END
diff --git a/objectivec/GPBCodedOutputStream.h b/objectivec/GPBCodedOutputStream.h
index 5dde974..304a24e 100644
--- a/objectivec/GPBCodedOutputStream.h
+++ b/objectivec/GPBCodedOutputStream.h
@@ -171,13 +171,13 @@
  * @param offset The offset into the blob to start writing out.
  * @param length The number of bytes from the blob to write out.
  **/
-- (void)writeRawPtr:(const void *)data
-             offset:(size_t)offset
-             length:(size_t)length;
+- (void)writeRawPtr:(const void *)data offset:(size_t)offset length:(size_t)length;
+
+// Disable clang-format for the macros.
+// clang-format off
 
 //%PDDM-EXPAND _WRITE_DECLS()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 /**
  * Write a double for the given field number.
@@ -631,9 +631,10 @@
 - (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
                          value:(GPBUnknownFieldSet *)value;
 
-// clang-format on
 //%PDDM-EXPAND-END _WRITE_DECLS()
 
+// clang-format on
+
 /**
 Write a MessageSet extension field to the stream. For historical reasons,
 the wire format differs from normal fields.
@@ -656,6 +657,9 @@
 
 NS_ASSUME_NONNULL_END
 
+// Disable clang-format for the macros.
+// clang-format off
+
 // Write methods for types that can be in packed arrays.
 //%PDDM-DEFINE _WRITE_PACKABLE_DECLS(NAME, ARRAY_TYPE, TYPE)
 //%/**
@@ -755,3 +759,5 @@
 //%_WRITE_UNPACKABLE_DECLS(Bytes, NSData)
 //%_WRITE_GROUP_DECLS(Group, GPBMessage)
 //%_WRITE_GROUP_DECLS(UnknownGroup, GPBUnknownFieldSet)
+
+// clang-format on
diff --git a/objectivec/GPBCodedOutputStream.m b/objectivec/GPBCodedOutputStream.m
index 4e2a514..c21e7d2 100644
--- a/objectivec/GPBCodedOutputStream.m
+++ b/objectivec/GPBCodedOutputStream.m
@@ -67,8 +67,7 @@
     [NSException raise:GPBCodedOutputStreamException_OutOfSpace format:@""];
   }
   if (state->position != 0) {
-    NSInteger written =
-        [state->output write:state->bytes maxLength:state->position];
+    NSInteger written = [state->output write:state->bytes maxLength:state->position];
     if (written != (NSInteger)state->position) {
       [NSException raise:GPBCodedOutputStreamException_WriteFailed format:@""];
     }
@@ -118,27 +117,24 @@
   }
 }
 
-static void GPBWriteUInt32(GPBOutputBufferState *state, int32_t fieldNumber,
-                           uint32_t value) {
+static void GPBWriteUInt32(GPBOutputBufferState *state, int32_t fieldNumber, uint32_t value) {
   GPBWriteTagWithFormat(state, fieldNumber, GPBWireFormatVarint);
   GPBWriteRawVarint32(state, value);
 }
 
-static void GPBWriteTagWithFormat(GPBOutputBufferState *state,
-                                  uint32_t fieldNumber, GPBWireFormat format) {
+static void GPBWriteTagWithFormat(GPBOutputBufferState *state, uint32_t fieldNumber,
+                                  GPBWireFormat format) {
   GPBWriteRawVarint32(state, GPBWireFormatMakeTag(fieldNumber, format));
 }
 
-static void GPBWriteRawLittleEndian32(GPBOutputBufferState *state,
-                                      int32_t value) {
+static void GPBWriteRawLittleEndian32(GPBOutputBufferState *state, int32_t value) {
   GPBWriteRawByte(state, (value)&0xFF);
   GPBWriteRawByte(state, (value >> 8) & 0xFF);
   GPBWriteRawByte(state, (value >> 16) & 0xFF);
   GPBWriteRawByte(state, (value >> 24) & 0xFF);
 }
 
-static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state,
-                                      int64_t value) {
+static void GPBWriteRawLittleEndian64(GPBOutputBufferState *state, int64_t value) {
   GPBWriteRawByte(state, (int32_t)(value)&0xFF);
   GPBWriteRawByte(state, (int32_t)(value >> 8) & 0xFF);
   GPBWriteRawByte(state, (int32_t)(value >> 16) & 0xFF);
@@ -170,8 +166,7 @@
 // This initializer isn't exposed, but it is the designated initializer.
 // Setting OutputStream and NSData is to control the buffering behavior/size
 // of the work, but that is more obvious via the bufferSize: version.
-- (instancetype)initWithOutputStream:(NSOutputStream *)output
-                                data:(NSMutableData *)data {
+- (instancetype)initWithOutputStream:(NSOutputStream *)output data:(NSMutableData *)data {
   if ((self = [super init])) {
     buffer_ = [data retain];
     state_.bytes = [data mutableBytes];
@@ -184,8 +179,7 @@
 
 + (instancetype)streamWithOutputStream:(NSOutputStream *)output {
   NSMutableData *data = [NSMutableData dataWithLength:PAGE_SIZE];
-  return [[[self alloc] initWithOutputStream:output
-                                        data:data] autorelease];
+  return [[[self alloc] initWithOutputStream:output data:data] autorelease];
 }
 
 + (instancetype)streamWithData:(NSMutableData *)data {
@@ -277,8 +271,7 @@
     return;
   }
 
-  const char *quickString =
-      CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
+  const char *quickString = CFStringGetCStringPtr((CFStringRef)value, kCFStringEncodingUTF8);
 
   // Fast path: Most strings are short, if the buffer already has space,
   // add to it directly.
@@ -300,9 +293,8 @@
                 remainingRange:NULL];
     }
     if (result) {
-      NSAssert2((usedBufferLength == length),
-                @"Our UTF8 calc was wrong? %tu vs %zd", usedBufferLength,
-                length);
+      NSAssert2((usedBufferLength == length), @"Our UTF8 calc was wrong? %tu vs %zd",
+                usedBufferLength, length);
       state_.position += usedBufferLength;
       return;
     }
@@ -311,9 +303,8 @@
   } else {
     // Slow path: just get it as data and write it out.
     NSData *utf8Data = [value dataUsingEncoding:NSUTF8StringEncoding];
-    NSAssert2(([utf8Data length] == length),
-              @"Strings UTF8 length was wrong? %tu vs %zd", [utf8Data length],
-              length);
+    NSAssert2(([utf8Data length] == length), @"Strings UTF8 length was wrong? %tu vs %zd",
+              [utf8Data length], length);
     [self writeRawData:utf8Data];
   }
 }
@@ -333,14 +324,12 @@
   [self writeGroupNoTag:fieldNumber value:value];
 }
 
-- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber
-                         value:(const GPBUnknownFieldSet *)value {
+- (void)writeUnknownGroupNoTag:(int32_t)fieldNumber value:(const GPBUnknownFieldSet *)value {
   [value writeToCodedOutputStream:self];
   GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatEndGroup);
 }
 
-- (void)writeUnknownGroup:(int32_t)fieldNumber
-                    value:(GPBUnknownFieldSet *)value {
+- (void)writeUnknownGroup:(int32_t)fieldNumber value:(GPBUnknownFieldSet *)value {
   GPBWriteTagWithFormat(&state_, fieldNumber, GPBWireFormatStartGroup);
   [self writeUnknownGroupNoTag:fieldNumber value:value];
 }
@@ -418,6 +407,8 @@
   GPBWriteRawVarint64(&state_, GPBEncodeZigZag64(value));
 }
 
+// clang-format off
+
 //%PDDM-DEFINE WRITE_PACKABLE_DEFNS(NAME, ARRAY_TYPE, TYPE, ACCESSOR_NAME)
 //%- (void)write##NAME##Array:(int32_t)fieldNumber
 //%       NAME$S     values:(GPB##ARRAY_TYPE##Array *)values
@@ -425,19 +416,16 @@
 //%  if (tag != 0) {
 //%    if (values.count == 0) return;
 //%    __block size_t dataSize = 0;
-//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
-//%#pragma unused(idx, stop)
+//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, __unused NSUInteger idx,__unused  BOOL *stop) {
 //%      dataSize += GPBCompute##NAME##SizeNoTag(value);
 //%    }];
 //%    GPBWriteRawVarint32(&state_, tag);
 //%    GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
-//%#pragma unused(idx, stop)
+//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, __unused NSUInteger idx, __unused BOOL *stop) {
 //%      [self write##NAME##NoTag:value];
 //%    }];
 //%  } else {
-//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
-//%#pragma unused(idx, stop)
+//%    [values enumerate##ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, __unused NSUInteger idx, __unused BOOL *stop) {
 //%      [self write##NAME:fieldNumber value:value];
 //%    }];
 //%  }
@@ -452,7 +440,6 @@
 //%
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Double, Double, double, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeDoubleArray:(int32_t)fieldNumber
                   values:(GPBDoubleArray *)values
@@ -460,28 +447,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(double value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeDoubleSizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(double value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeDoubleNoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(double value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeDouble:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Float, Float, float, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeFloatArray:(int32_t)fieldNumber
                  values:(GPBFloatArray *)values
@@ -489,28 +471,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(float value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeFloatSizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(float value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeFloatNoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(float value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeFloat:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt64, UInt64, uint64_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeUInt64Array:(int32_t)fieldNumber
                   values:(GPBUInt64Array *)values
@@ -518,28 +495,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeUInt64SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeUInt64NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeUInt64:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int64, Int64, int64_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeInt64Array:(int32_t)fieldNumber
                  values:(GPBInt64Array *)values
@@ -547,28 +519,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeInt64SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeInt64NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeInt64:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Int32, Int32, int32_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeInt32Array:(int32_t)fieldNumber
                  values:(GPBInt32Array *)values
@@ -576,28 +543,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeInt32SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeInt32NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeInt32:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(UInt32, UInt32, uint32_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeUInt32Array:(int32_t)fieldNumber
                   values:(GPBUInt32Array *)values
@@ -605,28 +567,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeUInt32SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeUInt32NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeUInt32:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed64, UInt64, uint64_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeFixed64Array:(int32_t)fieldNumber
                    values:(GPBUInt64Array *)values
@@ -634,28 +591,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeFixed64SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeFixed64NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeFixed64:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Fixed32, UInt32, uint32_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeFixed32Array:(int32_t)fieldNumber
                    values:(GPBUInt32Array *)values
@@ -663,28 +615,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeFixed32SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeFixed32NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeFixed32:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt32, Int32, int32_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeSInt32Array:(int32_t)fieldNumber
                   values:(GPBInt32Array *)values
@@ -692,28 +639,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeSInt32SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSInt32NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSInt32:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SInt64, Int64, int64_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeSInt64Array:(int32_t)fieldNumber
                   values:(GPBInt64Array *)values
@@ -721,28 +663,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeSInt64SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSInt64NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSInt64:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed64, Int64, int64_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeSFixed64Array:(int32_t)fieldNumber
                     values:(GPBInt64Array *)values
@@ -750,28 +687,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeSFixed64SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSFixed64NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSFixed64:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(SFixed32, Int32, int32_t, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeSFixed32Array:(int32_t)fieldNumber
                     values:(GPBInt32Array *)values
@@ -779,28 +711,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeSFixed32SizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSFixed32NoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeSFixed32:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Bool, Bool, BOOL, )
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeBoolArray:(int32_t)fieldNumber
                 values:(GPBBoolArray *)values
@@ -808,28 +735,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(BOOL value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeBoolSizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(BOOL value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeBoolNoTag:value];
     }];
   } else {
-    [values enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateValuesWithBlock:^(BOOL value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeBool:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_PACKABLE_DEFNS(Enum, Enum, int32_t, Raw)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeEnumArray:(int32_t)fieldNumber
                 values:(GPBEnumArray *)values
@@ -837,28 +759,23 @@
   if (tag != 0) {
     if (values.count == 0) return;
     __block size_t dataSize = 0;
-    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateRawValuesWithBlock:^(int32_t value, __unused NSUInteger idx,__unused  BOOL *stop) {
       dataSize += GPBComputeEnumSizeNoTag(value);
     }];
     GPBWriteRawVarint32(&state_, tag);
     GPBWriteRawVarint32(&state_, (int32_t)dataSize);
-    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateRawValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeEnumNoTag:value];
     }];
   } else {
-    [values enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+    [values enumerateRawValuesWithBlock:^(int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
       [self writeEnum:fieldNumber value:value];
     }];
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(String, NSString)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeStringArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (NSString *value in values) {
@@ -866,10 +783,8 @@
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Message, GPBMessage)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeMessageArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (GPBMessage *value in values) {
@@ -877,10 +792,8 @@
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Bytes, NSData)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeBytesArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (NSData *value in values) {
@@ -888,10 +801,8 @@
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(Group, GPBMessage)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (GPBMessage *value in values) {
@@ -899,10 +810,8 @@
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND WRITE_UNPACKABLE_DEFNS(UnknownGroup, GPBUnknownFieldSet)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)writeUnknownGroupArray:(int32_t)fieldNumber values:(NSArray *)values {
   for (GPBUnknownFieldSet *value in values) {
@@ -910,26 +819,22 @@
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND-END (19 expansions)
 
-- (void)writeMessageSetExtension:(int32_t)fieldNumber
-                           value:(GPBMessage *)value {
-  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
-                        GPBWireFormatStartGroup);
+// clang-format on
+
+- (void)writeMessageSetExtension:(int32_t)fieldNumber value:(GPBMessage *)value {
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatStartGroup);
   GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
   [self writeMessage:GPBWireFormatMessageSetMessage value:value];
-  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
-                        GPBWireFormatEndGroup);
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatEndGroup);
 }
 
 - (void)writeRawMessageSetExtension:(int32_t)fieldNumber value:(NSData *)value {
-  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
-                        GPBWireFormatStartGroup);
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatStartGroup);
   GPBWriteUInt32(&state_, GPBWireFormatMessageSetTypeId, fieldNumber);
   [self writeBytes:GPBWireFormatMessageSetMessage value:value];
-  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem,
-                        GPBWireFormatEndGroup);
+  GPBWriteTagWithFormat(&state_, GPBWireFormatMessageSetItem, GPBWireFormatEndGroup);
 }
 
 - (void)flush {
@@ -946,9 +851,7 @@
   [self writeRawPtr:[data bytes] offset:0 length:[data length]];
 }
 
-- (void)writeRawPtr:(const void *)value
-             offset:(size_t)offset
-             length:(size_t)length {
+- (void)writeRawPtr:(const void *)value offset:(size_t)offset length:(size_t)length {
   if (value == nil || length == 0) {
     return;
   }
@@ -963,8 +866,7 @@
     // Write extends past current buffer.  Fill the rest of this buffer and
     // flush.
     size_t bytesWritten = bufferBytesLeft;
-    memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset,
-           bytesWritten);
+    memcpy(state_.bytes + state_.position, ((uint8_t *)value) + offset, bytesWritten);
     offset += bytesWritten;
     length -= bytesWritten;
     state_.position = bufferLength;
@@ -1017,23 +919,13 @@
 
 @end
 
-size_t GPBComputeDoubleSizeNoTag(Float64 value) {
-#pragma unused(value)
-  return LITTLE_ENDIAN_64_SIZE;
-}
+size_t GPBComputeDoubleSizeNoTag(__unused Float64 value) { return LITTLE_ENDIAN_64_SIZE; }
 
-size_t GPBComputeFloatSizeNoTag(Float32 value) {
-#pragma unused(value)
-  return LITTLE_ENDIAN_32_SIZE;
-}
+size_t GPBComputeFloatSizeNoTag(__unused Float32 value) { return LITTLE_ENDIAN_32_SIZE; }
 
-size_t GPBComputeUInt64SizeNoTag(uint64_t value) {
-  return GPBComputeRawVarint64Size(value);
-}
+size_t GPBComputeUInt64SizeNoTag(uint64_t value) { return GPBComputeRawVarint64Size(value); }
 
-size_t GPBComputeInt64SizeNoTag(int64_t value) {
-  return GPBComputeRawVarint64Size(value);
-}
+size_t GPBComputeInt64SizeNoTag(int64_t value) { return GPBComputeRawVarint64Size(value); }
 
 size_t GPBComputeInt32SizeNoTag(int32_t value) {
   if (value >= 0) {
@@ -1048,33 +940,20 @@
   return GPBComputeInt32SizeNoTag((int32_t)value);
 }
 
-size_t GPBComputeFixed64SizeNoTag(uint64_t value) {
-#pragma unused(value)
-  return LITTLE_ENDIAN_64_SIZE;
-}
+size_t GPBComputeFixed64SizeNoTag(__unused uint64_t value) { return LITTLE_ENDIAN_64_SIZE; }
 
-size_t GPBComputeFixed32SizeNoTag(uint32_t value) {
-#pragma unused(value)
-  return LITTLE_ENDIAN_32_SIZE;
-}
+size_t GPBComputeFixed32SizeNoTag(__unused uint32_t value) { return LITTLE_ENDIAN_32_SIZE; }
 
-size_t GPBComputeBoolSizeNoTag(BOOL value) {
-#pragma unused(value)
-  return 1;
-}
+size_t GPBComputeBoolSizeNoTag(__unused BOOL value) { return 1; }
 
 size_t GPBComputeStringSizeNoTag(NSString *value) {
   NSUInteger length = [value lengthOfBytesUsingEncoding:NSUTF8StringEncoding];
   return GPBComputeRawVarint32SizeForInteger(length) + length;
 }
 
-size_t GPBComputeGroupSizeNoTag(GPBMessage *value) {
-  return [value serializedSize];
-}
+size_t GPBComputeGroupSizeNoTag(GPBMessage *value) { return [value serializedSize]; }
 
-size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) {
-  return value.serializedSize;
-}
+size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) { return value.serializedSize; }
 
 size_t GPBComputeMessageSizeNoTag(GPBMessage *value) {
   size_t size = [value serializedSize];
@@ -1086,23 +965,13 @@
   return GPBComputeRawVarint32SizeForInteger(valueLength) + valueLength;
 }
 
-size_t GPBComputeUInt32SizeNoTag(int32_t value) {
-  return GPBComputeRawVarint32Size(value);
-}
+size_t GPBComputeUInt32SizeNoTag(int32_t value) { return GPBComputeRawVarint32Size(value); }
 
-size_t GPBComputeEnumSizeNoTag(int32_t value) {
-  return GPBComputeInt32SizeNoTag(value);
-}
+size_t GPBComputeEnumSizeNoTag(int32_t value) { return GPBComputeInt32SizeNoTag(value); }
 
-size_t GPBComputeSFixed32SizeNoTag(int32_t value) {
-#pragma unused(value)
-  return LITTLE_ENDIAN_32_SIZE;
-}
+size_t GPBComputeSFixed32SizeNoTag(__unused int32_t value) { return LITTLE_ENDIAN_32_SIZE; }
 
-size_t GPBComputeSFixed64SizeNoTag(int64_t value) {
-#pragma unused(value)
-  return LITTLE_ENDIAN_64_SIZE;
-}
+size_t GPBComputeSFixed64SizeNoTag(__unused int64_t value) { return LITTLE_ENDIAN_64_SIZE; }
 
 size_t GPBComputeSInt32SizeNoTag(int32_t value) {
   return GPBComputeRawVarint32Size(GPBEncodeZigZag32(value));
@@ -1152,10 +1021,8 @@
   return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeGroupSizeNoTag(value);
 }
 
-size_t GPBComputeUnknownGroupSize(int32_t fieldNumber,
-                                  GPBUnknownFieldSet *value) {
-  return GPBComputeTagSize(fieldNumber) * 2 +
-         GPBComputeUnknownGroupSizeNoTag(value);
+size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, GPBUnknownFieldSet *value) {
+  return GPBComputeTagSize(fieldNumber) * 2 + GPBComputeUnknownGroupSizeNoTag(value);
 }
 
 size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) {
@@ -1187,27 +1054,23 @@
 }
 
 size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) {
-  return GPBComputeTagSize(fieldNumber) +
-         GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
+  return GPBComputeTagSize(fieldNumber) + GPBComputeRawVarint64Size(GPBEncodeZigZag64(value));
 }
 
-size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber,
-                                         GPBMessage *value) {
+size_t GPBComputeMessageSetExtensionSize(int32_t fieldNumber, GPBMessage *value) {
   return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
          GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
          GPBComputeMessageSize(GPBWireFormatMessageSetMessage, value);
 }
 
-size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber,
-                                            NSData *value) {
+size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value) {
   return GPBComputeTagSize(GPBWireFormatMessageSetItem) * 2 +
          GPBComputeUInt32Size(GPBWireFormatMessageSetTypeId, fieldNumber) +
          GPBComputeBytesSize(GPBWireFormatMessageSetMessage, value);
 }
 
 size_t GPBComputeTagSize(int32_t fieldNumber) {
-  return GPBComputeRawVarint32Size(
-      GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint));
+  return GPBComputeRawVarint32Size(GPBWireFormatMakeTag(fieldNumber, GPBWireFormatVarint));
 }
 
 size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) {
diff --git a/objectivec/GPBCodedOutputStream_PackagePrivate.h b/objectivec/GPBCodedOutputStream_PackagePrivate.h
index 2e7bb4c..98e2d95 100644
--- a/objectivec/GPBCodedOutputStream_PackagePrivate.h
+++ b/objectivec/GPBCodedOutputStream_PackagePrivate.h
@@ -34,46 +34,27 @@
 
 CF_EXTERN_C_BEGIN
 
-size_t GPBComputeDoubleSize(int32_t fieldNumber, double value)
+size_t GPBComputeDoubleSize(int32_t fieldNumber, double value) __attribute__((const));
+size_t GPBComputeFloatSize(int32_t fieldNumber, float value) __attribute__((const));
+size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value) __attribute__((const));
+size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value) __attribute__((const));
+size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value) __attribute__((const));
+size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value) __attribute__((const));
+size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value) __attribute__((const));
+size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value) __attribute__((const));
+size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value) __attribute__((const));
+size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value) __attribute__((const));
+size_t GPBComputeUnknownGroupSize(int32_t fieldNumber, GPBUnknownFieldSet *value)
     __attribute__((const));
-size_t GPBComputeFloatSize(int32_t fieldNumber, float value)
-    __attribute__((const));
-size_t GPBComputeUInt64Size(int32_t fieldNumber, uint64_t value)
-    __attribute__((const));
-size_t GPBComputeInt64Size(int32_t fieldNumber, int64_t value)
-    __attribute__((const));
-size_t GPBComputeInt32Size(int32_t fieldNumber, int32_t value)
-    __attribute__((const));
-size_t GPBComputeFixed64Size(int32_t fieldNumber, uint64_t value)
-    __attribute__((const));
-size_t GPBComputeFixed32Size(int32_t fieldNumber, uint32_t value)
-    __attribute__((const));
-size_t GPBComputeBoolSize(int32_t fieldNumber, BOOL value)
-    __attribute__((const));
-size_t GPBComputeStringSize(int32_t fieldNumber, NSString *value)
-    __attribute__((const));
-size_t GPBComputeGroupSize(int32_t fieldNumber, GPBMessage *value)
-    __attribute__((const));
-size_t GPBComputeUnknownGroupSize(int32_t fieldNumber,
-                                  GPBUnknownFieldSet *value)
-    __attribute__((const));
-size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value)
-    __attribute__((const));
-size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value)
-    __attribute__((const));
-size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value)
-    __attribute__((const));
-size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value)
-    __attribute__((const));
-size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value)
-    __attribute__((const));
-size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value)
-    __attribute__((const));
-size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value)
-    __attribute__((const));
+size_t GPBComputeMessageSize(int32_t fieldNumber, GPBMessage *value) __attribute__((const));
+size_t GPBComputeBytesSize(int32_t fieldNumber, NSData *value) __attribute__((const));
+size_t GPBComputeUInt32Size(int32_t fieldNumber, uint32_t value) __attribute__((const));
+size_t GPBComputeSFixed32Size(int32_t fieldNumber, int32_t value) __attribute__((const));
+size_t GPBComputeSFixed64Size(int32_t fieldNumber, int64_t value) __attribute__((const));
+size_t GPBComputeSInt32Size(int32_t fieldNumber, int32_t value) __attribute__((const));
+size_t GPBComputeSInt64Size(int32_t fieldNumber, int64_t value) __attribute__((const));
 size_t GPBComputeTagSize(int32_t fieldNumber) __attribute__((const));
-size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType)
-    __attribute__((const));
+size_t GPBComputeWireFormatTagSize(int field_number, GPBDataType dataType) __attribute__((const));
 
 size_t GPBComputeDoubleSizeNoTag(double value) __attribute__((const));
 size_t GPBComputeFloatSizeNoTag(float value) __attribute__((const));
@@ -85,8 +66,7 @@
 size_t GPBComputeBoolSizeNoTag(BOOL value) __attribute__((const));
 size_t GPBComputeStringSizeNoTag(NSString *value) __attribute__((const));
 size_t GPBComputeGroupSizeNoTag(GPBMessage *value) __attribute__((const));
-size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value)
-    __attribute__((const));
+size_t GPBComputeUnknownGroupSizeNoTag(GPBUnknownFieldSet *value) __attribute__((const));
 size_t GPBComputeMessageSizeNoTag(GPBMessage *value) __attribute__((const));
 size_t GPBComputeBytesSizeNoTag(NSData *value) __attribute__((const));
 size_t GPBComputeUInt32SizeNoTag(int32_t value) __attribute__((const));
@@ -103,8 +83,7 @@
 size_t GPBComputeRawVarint64Size(int64_t value) __attribute__((const));
 
 // Note that this will calculate the size of 64 bit values truncated to 32.
-size_t GPBComputeRawVarint32SizeForInteger(NSInteger value)
-    __attribute__((const));
+size_t GPBComputeRawVarint32SizeForInteger(NSInteger value) __attribute__((const));
 
 // Compute the number of bytes that would be needed to encode a
 // MessageSet extension to the stream.  For historical reasons,
@@ -118,8 +97,7 @@
 size_t GPBComputeRawMessageSetExtensionSize(int32_t fieldNumber, NSData *value)
     __attribute__((const));
 
-size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value)
-    __attribute__((const));
+size_t GPBComputeEnumSize(int32_t fieldNumber, int32_t value) __attribute__((const));
 
 CF_EXTERN_C_END
 
diff --git a/objectivec/GPBDescriptor.h b/objectivec/GPBDescriptor.h
index fd66b0e..8baa230 100644
--- a/objectivec/GPBDescriptor.h
+++ b/objectivec/GPBDescriptor.h
@@ -62,14 +62,17 @@
 /**
  * Describes a proto message.
  **/
-@interface GPBDescriptor : NSObject<NSCopying>
+@interface GPBDescriptor : NSObject <NSCopying>
+
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
 
 /** Name of the message. */
 @property(nonatomic, readonly, copy) NSString *name;
 /** Fields declared in the message. */
-@property(nonatomic, readonly, strong, nullable) NSArray<GPBFieldDescriptor*> *fields;
+@property(nonatomic, readonly, strong, nullable) NSArray<GPBFieldDescriptor *> *fields;
 /** Oneofs declared in the message. */
-@property(nonatomic, readonly, strong, nullable) NSArray<GPBOneofDescriptor*> *oneofs;
+@property(nonatomic, readonly, strong, nullable) NSArray<GPBOneofDescriptor *> *oneofs;
 /** Extension range declared for the message. */
 @property(nonatomic, readonly, nullable) const GPBExtensionRange *extensionRanges;
 /** Number of extension ranges declared for the message. */
@@ -123,12 +126,23 @@
  **/
 @interface GPBFileDescriptor : NSObject
 
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+
 /** The package declared in the proto file. */
 @property(nonatomic, readonly, copy) NSString *package;
 /** The objc prefix declared in the proto file. */
 @property(nonatomic, readonly, copy, nullable) NSString *objcPrefix;
-/** The syntax of the proto file. */
-@property(nonatomic, readonly) GPBFileSyntax syntax;
+/**
+ * The syntax of the proto file.
+ *
+ * This should not be used for making decisions about support
+ * features/behaviors, what proto2 vs. proto3 syntax has meant has evolved over
+ * time, and not more specific methods on the descriptors should be used
+ * instead.
+ */
+@property(nonatomic, readonly) GPBFileSyntax syntax
+    __attribute__((deprecated("Syntax is not a good way to decide things about behaviors.")));
 
 @end
 
@@ -136,10 +150,14 @@
  * Describes a oneof field.
  **/
 @interface GPBOneofDescriptor : NSObject
+
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+
 /** Name of the oneof field. */
 @property(nonatomic, readonly) NSString *name;
 /** Fields declared in the oneof. */
-@property(nonatomic, readonly) NSArray<GPBFieldDescriptor*> *fields;
+@property(nonatomic, readonly) NSArray<GPBFieldDescriptor *> *fields;
 
 /**
  * Gets the field for the given number.
@@ -166,6 +184,9 @@
  **/
 @interface GPBFieldDescriptor : NSObject
 
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+
 /** Name of the field. */
 @property(nonatomic, readonly, copy) NSString *name;
 /** Number associated with the field. */
@@ -215,10 +236,25 @@
  **/
 @interface GPBEnumDescriptor : NSObject
 
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+
 /** Name of the enum. */
 @property(nonatomic, readonly, copy) NSString *name;
 /** Function that validates that raw values are valid enum values. */
 @property(nonatomic, readonly) GPBEnumValidationFunc enumVerifier;
+/**
+ * Is this a closed enum, meaning that it:
+ * - Has a fixed set of named values.
+ * - Encountering values not in this set causes them to be treated as unknown
+ *   fields.
+ * - The first value (i.e., the default) may be nonzero.
+ *
+ * NOTE: This is only accurate if the generate sources for a proto file were
+ * generated with a protobuf release after the v21.9 version, as the ObjC
+ * generator wasn't capturing this information.
+ */
+@property(nonatomic, readonly) BOOL isClosed;
 
 /**
  * Returns the enum value name for the given raw enum.
@@ -293,7 +329,11 @@
 /**
  * Describes a proto extension.
  **/
-@interface GPBExtensionDescriptor : NSObject<NSCopying>
+@interface GPBExtensionDescriptor : NSObject <NSCopying>
+
+- (instancetype)init NS_UNAVAILABLE;
++ (instancetype)new NS_UNAVAILABLE;
+
 /** Field number under which the extension is stored. */
 @property(nonatomic, readonly) uint32_t fieldNumber;
 /** The containing message class, i.e. the class extended by this extension. */
diff --git a/objectivec/GPBDescriptor.m b/objectivec/GPBDescriptor.m
index c29b955..13d26fc 100644
--- a/objectivec/GPBDescriptor.m
+++ b/objectivec/GPBDescriptor.m
@@ -32,9 +32,35 @@
 
 #import <objc/runtime.h>
 
+#import "GPBMessage_PackagePrivate.h"
 #import "GPBUtilities_PackagePrivate.h"
 #import "GPBWireFormat.h"
-#import "GPBMessage_PackagePrivate.h"
+
+@interface GPBDescriptor ()
+- (instancetype)initWithClass:(Class)messageClass
+                         file:(GPBFileDescriptor *)file
+                       fields:(NSArray *)fields
+                  storageSize:(uint32_t)storage
+                   wireFormat:(BOOL)wireFormat;
+@end
+
+@interface GPBFieldDescriptor ()
+// Single initializer
+// description has to be long lived, it is held as a raw pointer.
+- (instancetype)initWithFieldDescription:(void *)description
+                                    file:(GPBFileDescriptor *)file
+                          decriptorFlags:(GPBDescriptorInitializationFlags)decriptorFlags;
+
+@end
+
+@interface GPBEnumDescriptor ()
+- (instancetype)initWithName:(NSString *)name
+                  valueNames:(const char *)valueNames
+                      values:(const int32_t *)values
+                       count:(uint32_t)valueCount
+                enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                       flags:(GPBEnumDescriptorInitializationFlags)flags;
+@end
 
 // Direct access is use for speed, to avoid even internally declaring things
 // read/write, etc. The warning is enabled in the project to ensure code calling
@@ -48,16 +74,15 @@
 static const char kClassNameSuffixKey = 0;
 
 // Utility function to generate selectors on the fly.
-static SEL SelFromStrings(const char *prefix, const char *middle,
-                          const char *suffix, BOOL takesArg) {
+static SEL SelFromStrings(const char *prefix, const char *middle, const char *suffix,
+                          BOOL takesArg) {
   if (prefix == NULL && suffix == NULL && !takesArg) {
     return sel_getUid(middle);
   }
   const size_t prefixLen = prefix != NULL ? strlen(prefix) : 0;
   const size_t middleLen = strlen(middle);
   const size_t suffixLen = suffix != NULL ? strlen(suffix) : 0;
-  size_t totalLen =
-      prefixLen + middleLen + suffixLen + 1;  // include space for null on end.
+  size_t totalLen = prefixLen + middleLen + suffixLen + 1;  // include space for null on end.
   if (takesArg) {
     totalLen += 1;
   }
@@ -82,12 +107,10 @@
   return result;
 }
 
-static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
-                                          NSArray *allMessageFields)
+static NSArray *NewFieldsArrayForHasIndex(int hasIndex, NSArray *allMessageFields)
     __attribute__((ns_returns_retained));
 
-static NSArray *NewFieldsArrayForHasIndex(int hasIndex,
-                                          NSArray *allMessageFields) {
+static NSArray *NewFieldsArrayForHasIndex(int hasIndex, NSArray *allMessageFields) {
   NSMutableArray *result = [[NSMutableArray alloc] init];
   for (GPBFieldDescriptor *fieldDesc in allMessageFields) {
     if (fieldDesc->description_->hasIndex == hasIndex) {
@@ -111,45 +134,30 @@
 @synthesize file = file_;
 @synthesize wireFormat = wireFormat_;
 
-+ (instancetype)
-    allocDescriptorForClass:(Class)messageClass
-                  rootClass:(Class)rootClass
-                       file:(GPBFileDescriptor *)file
-                     fields:(void *)fieldDescriptions
-                 fieldCount:(uint32_t)fieldCount
-                storageSize:(uint32_t)storageSize
-                      flags:(GPBDescriptorInitializationFlags)flags {
++ (instancetype)allocDescriptorForClass:(Class)messageClass
+                              rootClass:(Class)rootClass
+                                   file:(GPBFileDescriptor *)file
+                                 fields:(void *)fieldDescriptions
+                             fieldCount:(uint32_t)fieldCount
+                            storageSize:(uint32_t)storageSize
+                                  flags:(GPBDescriptorInitializationFlags)flags {
   // The rootClass is no longer used, but it is passed in to ensure it
   // was started up during initialization also.
   (void)rootClass;
-  NSMutableArray *fields = nil;
-  GPBFileSyntax syntax = file.syntax;
-  BOOL fieldsIncludeDefault =
-      (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
-  BOOL usesClassRefs =
-      (flags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0;
-  BOOL proto3OptionalKnown =
-      (flags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) != 0;
+  NSMutableArray *fields =
+      (fieldCount ? [[NSMutableArray alloc] initWithCapacity:fieldCount] : nil);
+  BOOL fieldsIncludeDefault = (flags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
 
   void *desc;
   for (uint32_t i = 0; i < fieldCount; ++i) {
-    if (fields == nil) {
-      fields = [[NSMutableArray alloc] initWithCapacity:fieldCount];
-    }
     // Need correctly typed pointer for array indexing below to work.
     if (fieldsIncludeDefault) {
-      GPBMessageFieldDescriptionWithDefault *fieldDescWithDefault = fieldDescriptions;
-      desc = &(fieldDescWithDefault[i]);
+      desc = &(((GPBMessageFieldDescriptionWithDefault *)fieldDescriptions)[i]);
     } else {
-      GPBMessageFieldDescription *fieldDesc = fieldDescriptions;
-      desc = &(fieldDesc[i]);
+      desc = &(((GPBMessageFieldDescription *)fieldDescriptions)[i]);
     }
     GPBFieldDescriptor *fieldDescriptor =
-        [[GPBFieldDescriptor alloc] initWithFieldDescription:desc
-                                             includesDefault:fieldsIncludeDefault
-                                               usesClassRefs:usesClassRefs
-                                         proto3OptionalKnown:proto3OptionalKnown
-                                                      syntax:syntax];
+        [[GPBFieldDescriptor alloc] initWithFieldDescription:desc file:file decriptorFlags:flags];
     [fields addObject:fieldDescriptor];
     [fieldDescriptor release];
   }
@@ -193,10 +201,9 @@
   for (uint32_t i = 0, hasIndex = firstHasIndex; i < count; ++i, --hasIndex) {
     const char *name = oneofNames[i];
     NSArray *fieldsForOneof = NewFieldsArrayForHasIndex(hasIndex, fields_);
-    NSCAssert(fieldsForOneof.count > 0,
-              @"No fields for this oneof? (%s:%d)", name, hasIndex);
-    GPBOneofDescriptor *oneofDescriptor =
-        [[GPBOneofDescriptor alloc] initWithName:name fields:fieldsForOneof];
+    NSCAssert(fieldsForOneof.count > 0, @"No fields for this oneof? (%s:%d)", name, hasIndex);
+    GPBOneofDescriptor *oneofDescriptor = [[GPBOneofDescriptor alloc] initWithName:name
+                                                                            fields:fieldsForOneof];
     [oneofs addObject:oneofDescriptor];
     [oneofDescriptor release];
     [fieldsForOneof release];
@@ -210,8 +217,7 @@
     NSValue *extraInfoValue = [NSValue valueWithPointer:extraTextFormatInfo];
     for (GPBFieldDescriptor *fieldDescriptor in fields_) {
       if (fieldDescriptor->description_->flags & GPBFieldTextFormatNameCustom) {
-        objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey,
-                                 extraInfoValue,
+        objc_setAssociatedObject(fieldDescriptor, &kTextFormatExtraValueKey, extraInfoValue,
                                  OBJC_ASSOCIATION_RETAIN_NONATOMIC);
       }
     }
@@ -224,9 +230,7 @@
 }
 
 - (void)setupContainingMessageClass:(Class)messageClass {
-  objc_setAssociatedObject(self, &kParentClassValueKey,
-                           messageClass,
-                           OBJC_ASSOCIATION_ASSIGN);
+  objc_setAssociatedObject(self, &kParentClassValueKey, messageClass, OBJC_ASSOCIATION_ASSIGN);
 }
 
 - (void)setupContainingMessageClassName:(const char *)msgClassName {
@@ -240,9 +244,7 @@
 
 - (void)setupMessageClassNameSuffix:(NSString *)suffix {
   if (suffix.length) {
-    objc_setAssociatedObject(self, &kClassNameSuffixKey,
-                             suffix,
-                             OBJC_ASSOCIATION_RETAIN_NONATOMIC);
+    objc_setAssociatedObject(self, &kClassNameSuffixKey, suffix, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
   }
 }
 
@@ -260,9 +262,7 @@
   GPBFileDescriptor *file = self.file;
   NSString *objcPrefix = file.objcPrefix;
   if (objcPrefix && ![className hasPrefix:objcPrefix]) {
-    NSAssert(0,
-             @"Class didn't have correct prefix? (%@ - %@)",
-             className, objcPrefix);
+    NSAssert(0, @"Class didn't have correct prefix? (%@ - %@)", className, objcPrefix);
     return nil;
   }
   GPBDescriptor *parent = self.containingType;
@@ -274,19 +274,16 @@
     NSString *suffix = objc_getAssociatedObject(parent, &kClassNameSuffixKey);
     if (suffix) {
       if (![parentClassName hasSuffix:suffix]) {
-        NSAssert(0,
-                 @"ParentMessage class didn't have correct suffix? (%@ - %@)",
-                 className, suffix);
+        NSAssert(0, @"ParentMessage class didn't have correct suffix? (%@ - %@)", className,
+                 suffix);
         return nil;
       }
-      parentClassName =
-          [parentClassName substringToIndex:(parentClassName.length - suffix.length)];
+      parentClassName = [parentClassName substringToIndex:(parentClassName.length - suffix.length)];
     }
     NSString *parentPrefix = [parentClassName stringByAppendingString:@"_"];
     if (![className hasPrefix:parentPrefix]) {
-      NSAssert(0,
-               @"Class didn't have the correct parent name prefix? (%@ - %@)",
-               parentPrefix, className);
+      NSAssert(0, @"Class didn't have the correct parent name prefix? (%@ - %@)", parentPrefix,
+               className);
       return nil;
     }
     name = [className substringFromIndex:parentPrefix.length];
@@ -298,9 +295,7 @@
   NSString *suffix = objc_getAssociatedObject(self, &kClassNameSuffixKey);
   if (suffix) {
     if (![name hasSuffix:suffix]) {
-      NSAssert(0,
-               @"Message class didn't have correct suffix? (%@ - %@)",
-               name, suffix);
+      NSAssert(0, @"Message class didn't have correct suffix? (%@ - %@)", name, suffix);
       return nil;
     }
     name = [name substringToIndex:(name.length - suffix.length)];
@@ -316,8 +311,7 @@
   return result;
 }
 
-- (id)copyWithZone:(NSZone *)zone {
-#pragma unused(zone)
+- (id)copyWithZone:(__unused NSZone *)zone {
   return [self retain];
 }
 
@@ -372,8 +366,7 @@
   return self;
 }
 
-- (instancetype)initWithPackage:(NSString *)package
-                         syntax:(GPBFileSyntax)syntax {
+- (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax {
   self = [super init];
   if (self) {
     package_ = [package copy];
@@ -414,7 +407,7 @@
 }
 
 - (NSString *)name {
-  return (NSString * _Nonnull)@(name_);
+  return (NSString *_Nonnull)@(name_);
 }
 
 - (GPBFieldDescriptor *)fieldWithNumber:(uint32_t)fieldNumber {
@@ -444,19 +437,17 @@
     // Maps are repeated messages on the wire.
     format = GPBWireFormatForType(GPBDataTypeMessage, NO);
   } else {
-    format = GPBWireFormatForType(description->dataType,
-                                  ((description->flags & GPBFieldPacked) != 0));
+    format =
+        GPBWireFormatForType(description->dataType, ((description->flags & GPBFieldPacked) != 0));
   }
   return GPBWireFormatMakeTag(description->number, format);
 }
 
 uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self) {
   GPBMessageFieldDescription *description = self->description_;
-  NSCAssert((description->flags & GPBFieldRepeated) != 0,
-            @"Only valid on repeated fields");
+  NSCAssert((description->flags & GPBFieldRepeated) != 0, @"Only valid on repeated fields");
   GPBWireFormat format =
-      GPBWireFormatForType(description->dataType,
-                           ((description->flags & GPBFieldPacked) == 0));
+      GPBWireFormatForType(description->dataType, ((description->flags & GPBFieldPacked) == 0));
   return GPBWireFormatMakeTag(description->number, format);
 }
 
@@ -467,33 +458,18 @@
   Class msgClass_;
 
   // Enum ivars.
-  // If protos are generated with GenerateEnumDescriptors on then it will
-  // be a enumDescriptor, otherwise it will be a enumVerifier.
-  union {
-    GPBEnumDescriptor *enumDescriptor_;
-    GPBEnumValidationFunc enumVerifier_;
-  } enumHandling_;
+  GPBEnumDescriptor *enumDescriptor_;
 }
 
 @synthesize msgClass = msgClass_;
 @synthesize containingOneof = containingOneof_;
 
-- (instancetype)init {
-  // Throw an exception if people attempt to not use the designated initializer.
-  self = [super init];
-  if (self != nil) {
-    [self doesNotRecognizeSelector:_cmd];
-    self = nil;
-  }
-  return self;
-}
-
 - (instancetype)initWithFieldDescription:(void *)description
-                         includesDefault:(BOOL)includesDefault
-                           usesClassRefs:(BOOL)usesClassRefs
-                     proto3OptionalKnown:(BOOL)proto3OptionalKnown
-                                  syntax:(GPBFileSyntax)syntax {
+                                    file:(GPBFileDescriptor *)file
+                          decriptorFlags:(GPBDescriptorInitializationFlags)decriptorFlags {
   if ((self = [super init])) {
+    BOOL includesDefault =
+        (decriptorFlags & GPBDescriptorInitializationFlag_FieldsWithDefault) != 0;
     GPBMessageFieldDescription *coreDesc;
     if (includesDefault) {
       coreDesc = &(((GPBMessageFieldDescriptionWithDefault *)description)->core);
@@ -510,21 +486,40 @@
 
     // 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 ((decriptorFlags & GPBDescriptorInitializationFlag_Proto3OptionalKnown) == 0) {
       // 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);
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+      BOOL clearOnZero = ((file.syntax == GPBFileSyntaxProto3) && !isMapOrArray &&
+                          (coreDesc->hasIndex >= 0) && !isMessage);
+#pragma clang diagnostic pop
       if (clearOnZero) {
         coreDesc->flags |= GPBFieldClearHasIvarOnZero;
       }
     }
 
+    // If the ClosedEnum flag wasn't known (i.e. generated code from an older
+    // version), compute the flag for the rest of the runtime.
+    if ((decriptorFlags & GPBDescriptorInitializationFlag_ClosedEnumSupportKnown) == 0) {
+      // NOTE: This isn't correct, it is using the syntax of the file that
+      // declared the field, not the syntax of the file that declared the
+      // enum; but for older generated code, that's all we have and that happens
+      // to be what the runtime was doing (even though it was wrong). This is
+      // only wrong in the rare cases an enum is declared in a proto3 syntax
+      // file but used for a field in the proto2 syntax file.
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wdeprecated-declarations"
+      BOOL isClosedEnum = (dataType == GPBDataTypeEnum && file.syntax != GPBFileSyntaxProto3);
+#pragma clang diagnostic pop
+      if (isClosedEnum) {
+        coreDesc->flags |= GPBFieldClosedEnum;
+      }
+    }
+
     if (isMapOrArray) {
       // map<>/repeated fields get a *Count property (inplace of a has*) to
       // support checking if there are any entries without triggering
@@ -534,8 +529,7 @@
       // 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->flags & GPBFieldClearHasIvarOnZero) == 0)) {
+      if ((coreDesc->hasIndex >= 0) && ((coreDesc->flags & GPBFieldClearHasIvarOnZero) == 0)) {
         hasOrCountSel_ = SelFromStrings("has", coreDesc->name, NULL, NO);
         setHasSel_ = SelFromStrings("setHas", coreDesc->name, NULL, YES);
       }
@@ -546,7 +540,7 @@
       // Note: Only fetch the class here, can't send messages to it because
       // that could cause cycles back to this class within +initialize if
       // two messages have each other in fields (i.e. - they build a graph).
-      if (usesClassRefs) {
+      if ((decriptorFlags & GPBDescriptorInitializationFlag_UsesClassRefs) != 0) {
         msgClass_ = coreDesc->dataTypeSpecific.clazz;
       } else {
         // Backwards compatibility for sources generated with older protoc.
@@ -555,13 +549,14 @@
         NSAssert(msgClass_, @"Class %s not defined", className);
       }
     } else if (dataType == GPBDataTypeEnum) {
-      if ((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0) {
-        enumHandling_.enumDescriptor_ =
-            coreDesc->dataTypeSpecific.enumDescFunc();
-      } else {
-        enumHandling_.enumVerifier_ =
-            coreDesc->dataTypeSpecific.enumVerifier;
-      }
+      enumDescriptor_ = coreDesc->dataTypeSpecific.enumDescFunc();
+#if defined(DEBUG) && DEBUG
+      NSAssert((coreDesc->flags & GPBFieldHasEnumDescriptor) != 0,
+               @"Field must have GPBFieldHasEnumDescriptor set");
+      NSAssert(((decriptorFlags & GPBDescriptorInitializationFlag_ClosedEnumSupportKnown) != 0) ||
+                   (((coreDesc->flags & GPBFieldClosedEnum) != 0) == enumDescriptor_.isClosed),
+               @"Internal error, ClosedEnum flag doesn't agree with EnumDescriptor");
+#endif  // DEBUG
     }
 
     // Non map<>/repeated fields can have defaults in proto2 syntax.
@@ -576,8 +571,7 @@
           memcpy(&length, bytes, sizeof(length));
           length = ntohl(length);
           bytes += sizeof(length);
-          defaultValue_.valueData =
-              [[NSData alloc] initWithBytes:bytes length:length];
+          defaultValue_.valueData = [[NSData alloc] initWithBytes:bytes length:length];
         }
       }
     }
@@ -586,8 +580,7 @@
 }
 
 - (void)dealloc {
-  if (description_->dataType == GPBDataTypeBytes &&
-      !(description_->flags & GPBFieldRepeated)) {
+  if (description_->dataType == GPBDataTypeBytes && !(description_->flags & GPBFieldRepeated)) {
     [defaultValue_.valueData release];
   }
   [super dealloc];
@@ -606,7 +599,7 @@
 }
 
 - (NSString *)name {
-  return (NSString * _Nonnull)@(description_->name);
+  return (NSString *_Nonnull)@(description_->name);
 }
 
 - (BOOL)isRequired {
@@ -666,21 +659,12 @@
 }
 
 - (BOOL)isValidEnumValue:(int32_t)value {
-  NSAssert(description_->dataType == GPBDataTypeEnum,
-           @"Field Must be of type GPBDataTypeEnum");
-  if (description_->flags & GPBFieldHasEnumDescriptor) {
-    return enumHandling_.enumDescriptor_.enumVerifier(value);
-  } else {
-    return enumHandling_.enumVerifier_(value);
-  }
+  NSAssert(description_->dataType == GPBDataTypeEnum, @"Field Must be of type GPBDataTypeEnum");
+  return enumDescriptor_.enumVerifier(value);
 }
 
 - (GPBEnumDescriptor *)enumDescriptor {
-  if (description_->flags & GPBFieldHasEnumDescriptor) {
-    return enumHandling_.enumDescriptor_;
-  } else {
-    return nil;
-  }
+  return enumDescriptor_;
 }
 
 - (GPBGenericValue)defaultValue {
@@ -703,19 +687,17 @@
 
 - (NSString *)textFormatName {
   if ((description_->flags & GPBFieldTextFormatNameCustom) != 0) {
-    NSValue *extraInfoValue =
-        objc_getAssociatedObject(self, &kTextFormatExtraValueKey);
+    NSValue *extraInfoValue = objc_getAssociatedObject(self, &kTextFormatExtraValueKey);
     // Support can be left out at generation time.
     if (!extraInfoValue) {
       return nil;
     }
     const uint8_t *extraTextFormatInfo = [extraInfoValue pointerValue];
-    return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self),
-                                   self.name);
+    return GPBDecodeTextFormatName(extraTextFormatInfo, GPBFieldNumber(self), self.name);
   }
 
   // The logic here has to match SetCommonFieldVariables() from
-  // objectivec_field.cc in the proto compiler.
+  // objectivec/field.cc in the proto compiler.
   NSString *name = self.name;
   NSUInteger len = [name length];
 
@@ -726,8 +708,7 @@
   }
 
   // Remove "Array" from the end for repeated fields.
-  if (((description_->flags & GPBFieldRepeated) != 0) &&
-      [name hasSuffix:@"Array"]) {
+  if (((description_->flags & GPBFieldRepeated) != 0) && [name hasSuffix:@"Array"]) {
     name = [name substringToIndex:(len - 5)];
     len = [name length];
   }
@@ -739,9 +720,8 @@
     if (firstChar >= 'a' && firstChar <= 'z') {
       NSString *firstCharString =
           [NSString stringWithFormat:@"%C", (unichar)(firstChar - 'a' + 'A')];
-      NSString *result =
-          [name stringByReplacingCharactersInRange:NSMakeRange(0, 1)
-                                        withString:firstCharString];
+      NSString *result = [name stringByReplacingCharactersInRange:NSMakeRange(0, 1)
+                                                       withString:firstCharString];
       return result;
     }
     return name;
@@ -779,54 +759,87 @@
   const uint8_t *extraTextFormatInfo_;
   uint32_t *nameOffsets_;
   uint32_t valueCount_;
+  uint32_t flags_;
 }
 
 @synthesize name = name_;
 @synthesize enumVerifier = enumVerifier_;
 
-+ (instancetype)
-    allocDescriptorForName:(NSString *)name
-                valueNames:(const char *)valueNames
-                    values:(const int32_t *)values
-                     count:(uint32_t)valueCount
-              enumVerifier:(GPBEnumValidationFunc)enumVerifier {
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                                 flags:(GPBEnumDescriptorInitializationFlags)flags {
   GPBEnumDescriptor *descriptor = [[self alloc] initWithName:name
                                                   valueNames:valueNames
                                                       values:values
                                                        count:valueCount
-                                                enumVerifier:enumVerifier];
+                                                enumVerifier:enumVerifier
+                                                       flags:flags];
   return descriptor;
 }
 
-+ (instancetype)
-    allocDescriptorForName:(NSString *)name
-                valueNames:(const char *)valueNames
-                    values:(const int32_t *)values
-                     count:(uint32_t)valueCount
-              enumVerifier:(GPBEnumValidationFunc)enumVerifier
-       extraTextFormatInfo:(const char *)extraTextFormatInfo {
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                                 flags:(GPBEnumDescriptorInitializationFlags)flags
+                   extraTextFormatInfo:(const char *)extraTextFormatInfo {
   // Call the common case.
   GPBEnumDescriptor *descriptor = [self allocDescriptorForName:name
                                                     valueNames:valueNames
                                                         values:values
                                                          count:valueCount
-                                                  enumVerifier:enumVerifier];
+                                                  enumVerifier:enumVerifier
+                                                         flags:flags];
   // Set the extra info.
   descriptor->extraTextFormatInfo_ = (const uint8_t *)extraTextFormatInfo;
   return descriptor;
 }
 
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier {
+  return [self allocDescriptorForName:name
+                           valueNames:valueNames
+                               values:values
+                                count:valueCount
+                         enumVerifier:enumVerifier
+                                flags:GPBEnumDescriptorInitializationFlag_None];
+}
+
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                   extraTextFormatInfo:(const char *)extraTextFormatInfo {
+  return [self allocDescriptorForName:name
+                           valueNames:valueNames
+                               values:values
+                                count:valueCount
+                         enumVerifier:enumVerifier
+                                flags:GPBEnumDescriptorInitializationFlag_None
+                  extraTextFormatInfo:extraTextFormatInfo];
+}
+
 - (instancetype)initWithName:(NSString *)name
                   valueNames:(const char *)valueNames
                       values:(const int32_t *)values
                        count:(uint32_t)valueCount
-                enumVerifier:(GPBEnumValidationFunc)enumVerifier {
+                enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                       flags:(GPBEnumDescriptorInitializationFlags)flags {
   if ((self = [super init])) {
     name_ = [name copy];
     valueNames_ = valueNames;
     values_ = values;
     valueCount_ = valueCount;
     enumVerifier_ = enumVerifier;
+    flags_ = flags;
   }
   return self;
 }
@@ -837,6 +850,10 @@
   [super dealloc];
 }
 
+- (BOOL)isClosed {
+  return (flags_ & GPBEnumDescriptorInitializationFlag_IsClosed) != 0;
+}
+
 - (void)calcValueNameOffsets {
   @synchronized(self) {
     if (nameOffsets_ != NULL) {
@@ -892,27 +909,26 @@
 }
 
 - (BOOL)getValue:(int32_t *)outValue forEnumTextFormatName:(NSString *)textFormatName {
-    if (nameOffsets_ == NULL) [self calcValueNameOffsets];
-    if (nameOffsets_ == NULL) return NO;
+  if (nameOffsets_ == NULL) [self calcValueNameOffsets];
+  if (nameOffsets_ == NULL) return NO;
 
-    for (uint32_t i = 0; i < valueCount_; ++i) {
-        NSString *valueTextFormatName = [self getEnumTextFormatNameForIndex:i];
-        if ([valueTextFormatName isEqual:textFormatName]) {
-            if (outValue) {
-                *outValue = values_[i];
-            }
-            return YES;
-        }
+  for (uint32_t i = 0; i < valueCount_; ++i) {
+    NSString *valueTextFormatName = [self getEnumTextFormatNameForIndex:i];
+    if ([valueTextFormatName isEqual:textFormatName]) {
+      if (outValue) {
+        *outValue = values_[i];
+      }
+      return YES;
     }
-    return NO;
+  }
+  return NO;
 }
 
 - (NSString *)textFormatNameForValue:(int32_t)number {
   // Find the EnumValue descriptor and its index.
   BOOL foundIt = NO;
   uint32_t valueDescriptorIndex;
-  for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_;
-       ++valueDescriptorIndex) {
+  for (valueDescriptorIndex = 0; valueDescriptorIndex < valueCount_; ++valueDescriptorIndex) {
     if (values_[valueDescriptorIndex] == number) {
       foundIt = YES;
       break;
@@ -955,10 +971,9 @@
 
   // See if it is in the map of special format handling.
   if (extraTextFormatInfo_) {
-    result = GPBDecodeTextFormatName(extraTextFormatInfo_,
-                                     (int32_t)index, shortName);
+    result = GPBDecodeTextFormatName(extraTextFormatInfo_, (int32_t)index, shortName);
   }
-  // Logic here needs to match what objectivec_enum.cc does in the proto
+  // Logic here needs to match what objectivec/enum.cc does in the proto
   // compiler.
   if (result == nil) {
     NSUInteger len = [shortName length];
@@ -1005,16 +1020,14 @@
     GPBDataType type = description_->dataType;
     if (type == GPBDataTypeBytes) {
       // Data stored as a length prefixed c-string in descriptor records.
-      const uint8_t *bytes =
-          (const uint8_t *)description_->defaultValue.valueData;
+      const uint8_t *bytes = (const uint8_t *)description_->defaultValue.valueData;
       if (bytes) {
         uint32_t length;
         memcpy(&length, bytes, sizeof(length));
         // The length is stored in network byte order.
         length = ntohl(length);
         bytes += sizeof(length);
-        defaultValue_.valueData =
-            [[NSData alloc] initWithBytes:bytes length:length];
+        defaultValue_.valueData = [[NSData alloc] initWithBytes:bytes length:length];
       }
     } else if (type == GPBDataTypeMessage || type == GPBDataTypeGroup) {
       // The default is looked up in -defaultValue instead since extensions
@@ -1032,21 +1045,19 @@
 }
 
 - (void)dealloc {
-  if ((description_->dataType == GPBDataTypeBytes) &&
-      !GPBExtensionIsRepeated(description_)) {
+  if ((description_->dataType == GPBDataTypeBytes) && !GPBExtensionIsRepeated(description_)) {
     [defaultValue_.valueData release];
   }
   [super dealloc];
 }
 
-- (instancetype)copyWithZone:(NSZone *)zone {
-#pragma unused(zone)
+- (instancetype)copyWithZone:(__unused NSZone *)zone {
   // Immutable.
   return [self retain];
 }
 
 - (NSString *)singletonName {
-  return (NSString * _Nonnull)@(description_->singletonName);
+  return (NSString *_Nonnull)@(description_->singletonName);
 }
 
 - (const char *)singletonNameC {
@@ -1062,15 +1073,12 @@
 }
 
 - (GPBWireFormat)wireType {
-  return GPBWireFormatForType(description_->dataType,
-                              GPBExtensionIsPacked(description_));
+  return GPBWireFormatForType(description_->dataType, GPBExtensionIsPacked(description_));
 }
 
 - (GPBWireFormat)alternateWireType {
-  NSAssert(GPBExtensionIsRepeated(description_),
-           @"Only valid on repeated extensions");
-  return GPBWireFormatForType(description_->dataType,
-                              !GPBExtensionIsPacked(description_));
+  NSAssert(GPBExtensionIsRepeated(description_), @"Only valid on repeated extensions");
+  return GPBWireFormatForType(description_->dataType, !GPBExtensionIsPacked(description_));
 }
 
 - (BOOL)isRepeated {
@@ -1126,8 +1134,7 @@
       return @(defaultValue_.valueUInt64);
     case GPBDataTypeBytes:
       // Like message fields, the default is zero length data.
-      return (defaultValue_.valueData ? defaultValue_.valueData
-                                      : GPBEmptyNSData());
+      return (defaultValue_.valueData ? defaultValue_.valueData : GPBEmptyNSData());
     case GPBDataTypeString:
       // Like message fields, the default is zero length string.
       return (defaultValue_.valueString ? defaultValue_.valueString : @"");
diff --git a/objectivec/GPBDescriptor_PackagePrivate.h b/objectivec/GPBDescriptor_PackagePrivate.h
index 408f8d4..50128b6 100644
--- a/objectivec/GPBDescriptor_PackagePrivate.h
+++ b/objectivec/GPBDescriptor_PackagePrivate.h
@@ -37,12 +37,12 @@
 
 // Describes attributes of the field.
 typedef NS_OPTIONS(uint16_t, GPBFieldFlags) {
-  GPBFieldNone            = 0,
+  GPBFieldNone = 0,
   // These map to standard protobuf concepts.
-  GPBFieldRequired        = 1 << 0,
-  GPBFieldRepeated        = 1 << 1,
-  GPBFieldPacked          = 1 << 2,
-  GPBFieldOptional        = 1 << 3,
+  GPBFieldRequired = 1 << 0,
+  GPBFieldRepeated = 1 << 1,
+  GPBFieldPacked = 1 << 2,
+  GPBFieldOptional = 1 << 3,
   GPBFieldHasDefaultValue = 1 << 4,
 
   // Indicate that the field should "clear" when set to zero value. This is the
@@ -52,7 +52,7 @@
   // 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,
-  // Indicates the field has an enum descriptor.
+  // This flag has never had any meaning, it was set on all enum fields.
   GPBFieldHasEnumDescriptor = 1 << 7,
 
   // These are not standard protobuf concepts, they are specific to the
@@ -60,19 +60,31 @@
 
   // These bits are used to mark the field as a map and what the key
   // type is.
-  GPBFieldMapKeyMask     = 0xF << 8,
-  GPBFieldMapKeyInt32    =  1 << 8,
-  GPBFieldMapKeyInt64    =  2 << 8,
-  GPBFieldMapKeyUInt32   =  3 << 8,
-  GPBFieldMapKeyUInt64   =  4 << 8,
-  GPBFieldMapKeySInt32   =  5 << 8,
-  GPBFieldMapKeySInt64   =  6 << 8,
-  GPBFieldMapKeyFixed32  =  7 << 8,
-  GPBFieldMapKeyFixed64  =  8 << 8,
-  GPBFieldMapKeySFixed32 =  9 << 8,
+  GPBFieldMapKeyMask = 0xF << 8,
+  GPBFieldMapKeyInt32 = 1 << 8,
+  GPBFieldMapKeyInt64 = 2 << 8,
+  GPBFieldMapKeyUInt32 = 3 << 8,
+  GPBFieldMapKeyUInt64 = 4 << 8,
+  GPBFieldMapKeySInt32 = 5 << 8,
+  GPBFieldMapKeySInt64 = 6 << 8,
+  GPBFieldMapKeyFixed32 = 7 << 8,
+  GPBFieldMapKeyFixed64 = 8 << 8,
+  GPBFieldMapKeySFixed32 = 9 << 8,
   GPBFieldMapKeySFixed64 = 10 << 8,
-  GPBFieldMapKeyBool     = 11 << 8,
-  GPBFieldMapKeyString   = 12 << 8,
+  GPBFieldMapKeyBool = 11 << 8,
+  GPBFieldMapKeyString = 12 << 8,
+
+  // If the enum for this field is "closed", meaning that it:
+  // - Has a fixed set of named values.
+  // - Encountering values not in this set causes them to be treated as unknown
+  //   fields.
+  // - The first value (i.e., the default) may be nonzero.
+  // NOTE: This could be tracked just on the GPBEnumDescriptor, but to support
+  // previously generated code, there would be not data to get the behavior
+  // correct, so instead it is tracked on the field. If old source compatibility
+  // is removed, this could be removed and the GPBEnumDescription fetched from
+  // the GPBFieldDescriptor instead.
+  GPBFieldClosedEnum = 1 << 12,
 };
 
 // NOTE: The structures defined here have their members ordered to minimize
@@ -88,11 +100,9 @@
     // kept around right now for backwards compatibility.
     // clazz is used iff GPBDescriptorInitializationFlag_UsesClassRefs is set.
     char *className;  // Name of the class of the message.
-    Class clazz;  // Class of the message.
-    // For enums only: If EnumDescriptors are compiled in, it will be that,
-    // otherwise it will be the verifier.
+    Class clazz;      // Class of the message.
+    // For enums only.
     GPBEnumDescriptorFunc enumDescFunc;
-    GPBEnumValidationFunc enumVerifier;
   } dataTypeSpecific;
   // The field number for the ivar.
   uint32_t number;
@@ -120,10 +130,10 @@
 
 // Describes attributes of the extension.
 typedef NS_OPTIONS(uint8_t, GPBExtensionOptions) {
-  GPBExtensionNone          = 0,
+  GPBExtensionNone = 0,
   // These map to standard protobuf concepts.
-  GPBExtensionRepeated      = 1 << 0,
-  GPBExtensionPacked        = 1 << 1,
+  GPBExtensionRepeated = 1 << 0,
+  GPBExtensionPacked = 1 << 1,
   GPBExtensionSetWireFormat = 1 << 2,
 };
 
@@ -132,10 +142,10 @@
   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.
+  // 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;
@@ -150,9 +160,9 @@
   union {
     const char *messageOrGroupClassName;
     union {
-     const char *name;
-     Class clazz;
-   } messageOrGroupClass;
+      const char *name;
+      Class clazz;
+    } messageOrGroupClass;
   };
   GPBEnumDescriptorFunc enumDescriptorFunc;
   int32_t fieldNumber;
@@ -161,20 +171,26 @@
 } GPBExtensionDescription;
 
 typedef NS_OPTIONS(uint32_t, GPBDescriptorInitializationFlags) {
-  GPBDescriptorInitializationFlag_None              = 0,
+  GPBDescriptorInitializationFlag_None = 0,
   GPBDescriptorInitializationFlag_FieldsWithDefault = 1 << 0,
-  GPBDescriptorInitializationFlag_WireFormat        = 1 << 1,
+  GPBDescriptorInitializationFlag_WireFormat = 1 << 1,
 
   // 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,
+
+  // This flag is used to indicate that the generated sources already contain
+  // the `GPBFieldCloseEnum` flag and it doesn't have to be computed at startup.
+  // This allows the older generated code to still work with the current runtime
+  // library.
+  GPBDescriptorInitializationFlag_ClosedEnumSupportKnown = 1 << 4,
 };
 
 @interface GPBDescriptor () {
@@ -185,20 +201,13 @@
 }
 
 // fieldDescriptions have to be long lived, they are held as raw pointers.
-+ (instancetype)
-    allocDescriptorForClass:(Class)messageClass
-                  rootClass:(Class)rootClass
-                       file:(GPBFileDescriptor *)file
-                     fields:(void *)fieldDescriptions
-                 fieldCount:(uint32_t)fieldCount
-                storageSize:(uint32_t)storageSize
-                      flags:(GPBDescriptorInitializationFlags)flags;
-
-- (instancetype)initWithClass:(Class)messageClass
-                         file:(GPBFileDescriptor *)file
-                       fields:(NSArray *)fields
-                  storageSize:(uint32_t)storage
-                   wireFormat:(BOOL)wireFormat;
++ (instancetype)allocDescriptorForClass:(Class)messageClass
+                              rootClass:(Class)rootClass
+                                   file:(GPBFileDescriptor *)file
+                                 fields:(void *)fieldDescriptions
+                             fieldCount:(uint32_t)fieldCount
+                            storageSize:(uint32_t)storageSize
+                                  flags:(GPBDescriptorInitializationFlags)flags;
 
 // Called right after init to provide extra information to avoid init having
 // an explosion of args. These pointers are recorded, so they are expected
@@ -220,8 +229,7 @@
 - (instancetype)initWithPackage:(NSString *)package
                      objcPrefix:(NSString *)objcPrefix
                          syntax:(GPBFileSyntax)syntax;
-- (instancetype)initWithPackage:(NSString *)package
-                         syntax:(GPBFileSyntax)syntax;
+- (instancetype)initWithPackage:(NSString *)package syntax:(GPBFileSyntax)syntax;
 @end
 
 @interface GPBOneofDescriptor () {
@@ -244,39 +252,44 @@
   SEL hasOrCountSel_;  // *Count for map<>/repeated fields, has* otherwise.
   SEL setHasSel_;
 }
-
-// Single initializer
-// description has to be long lived, it is held as a raw pointer.
-- (instancetype)initWithFieldDescription:(void *)description
-                         includesDefault:(BOOL)includesDefault
-                           usesClassRefs:(BOOL)usesClassRefs
-                     proto3OptionalKnown:(BOOL)proto3OptionalKnown
-                                  syntax:(GPBFileSyntax)syntax;
-
 @end
 
+typedef NS_OPTIONS(uint32_t, GPBEnumDescriptorInitializationFlags) {
+  GPBEnumDescriptorInitializationFlag_None = 0,
+
+  // Marks this enum as a closed enum.
+  GPBEnumDescriptorInitializationFlag_IsClosed = 1 << 1,
+};
+
 @interface GPBEnumDescriptor ()
 // valueNames, values and extraTextFormatInfo have to be long lived, they are
 // held as raw pointers.
-+ (instancetype)
-    allocDescriptorForName:(NSString *)name
-                valueNames:(const char *)valueNames
-                    values:(const int32_t *)values
-                     count:(uint32_t)valueCount
-              enumVerifier:(GPBEnumValidationFunc)enumVerifier;
-+ (instancetype)
-    allocDescriptorForName:(NSString *)name
-                valueNames:(const char *)valueNames
-                    values:(const int32_t *)values
-                     count:(uint32_t)valueCount
-              enumVerifier:(GPBEnumValidationFunc)enumVerifier
-       extraTextFormatInfo:(const char *)extraTextFormatInfo;
-
-- (instancetype)initWithName:(NSString *)name
-                  valueNames:(const char *)valueNames
-                      values:(const int32_t *)values
-                       count:(uint32_t)valueCount
-                enumVerifier:(GPBEnumValidationFunc)enumVerifier;
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                                 flags:(GPBEnumDescriptorInitializationFlags)flags;
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                                 flags:(GPBEnumDescriptorInitializationFlags)flags
+                   extraTextFormatInfo:(const char *)extraTextFormatInfo;
+// Deprecated. Calls above with `flags = 0`
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier;
+// Deprecated. Calls above with `flags = 0`
++ (instancetype)allocDescriptorForName:(NSString *)name
+                            valueNames:(const char *)valueNames
+                                values:(const int32_t *)values
+                                 count:(uint32_t)valueCount
+                          enumVerifier:(GPBEnumValidationFunc)enumVerifier
+                   extraTextFormatInfo:(const char *)extraTextFormatInfo;
 @end
 
 @interface GPBExtensionDescriptor () {
@@ -309,8 +322,7 @@
 #pragma clang diagnostic ignored "-Wdirect-ivar-access"
 
 GPB_INLINE BOOL GPBFieldIsMapOrArray(GPBFieldDescriptor *field) {
-  return (field->description_->flags &
-          (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
+  return (field->description_->flags & (GPBFieldRepeated | GPBFieldMapKeyMask)) != 0;
 }
 
 GPB_INLINE GPBDataType GPBGetFieldDataType(GPBFieldDescriptor *field) {
@@ -325,6 +337,10 @@
   return field->description_->number;
 }
 
+GPB_INLINE BOOL GPBFieldIsClosedEnum(GPBFieldDescriptor *field) {
+  return (field->description_->flags & GPBFieldClosedEnum) != 0;
+}
+
 #pragma clang diagnostic pop
 
 uint32_t GPBFieldTag(GPBFieldDescriptor *self);
@@ -335,10 +351,6 @@
 // would be the wire type for packed.
 uint32_t GPBFieldAlternateTag(GPBFieldDescriptor *self);
 
-GPB_INLINE BOOL GPBHasPreservingUnknownEnumSemantics(GPBFileSyntax syntax) {
-  return syntax == GPBFileSyntaxProto3;
-}
-
 GPB_INLINE BOOL GPBExtensionIsRepeated(GPBExtensionDescription *description) {
   return (description->options & GPBExtensionRepeated) != 0;
 }
@@ -353,22 +365,13 @@
 
 // Helper for compile time assets.
 #ifndef GPBInternalCompileAssert
-  #if __has_feature(c_static_assert) || __has_extension(c_static_assert)
-    #define GPBInternalCompileAssert(test, msg) _Static_assert((test), #msg)
-  #else
-    // Pre-Xcode 7 support.
-    #define GPBInternalCompileAssertSymbolInner(line, msg) GPBInternalCompileAssert ## line ## __ ## msg
-    #define GPBInternalCompileAssertSymbol(line, msg) GPBInternalCompileAssertSymbolInner(line, msg)
-    #define GPBInternalCompileAssert(test, msg) \
-        typedef char GPBInternalCompileAssertSymbol(__LINE__, msg) [ ((test) ? 1 : -1) ]
-  #endif  // __has_feature(c_static_assert) || __has_extension(c_static_assert)
-#endif // GPBInternalCompileAssert
+#define GPBInternalCompileAssert(test, msg) _Static_assert((test), #msg)
+#endif  // GPBInternalCompileAssert
 
 // Sanity check that there isn't padding between the field description
 // structures with and without a default.
 GPBInternalCompileAssert(sizeof(GPBMessageFieldDescriptionWithDefault) ==
-                         (sizeof(GPBGenericValue) +
-                          sizeof(GPBMessageFieldDescription)),
+                             (sizeof(GPBGenericValue) + sizeof(GPBMessageFieldDescription)),
                          DescriptionsWithDefault_different_size_than_expected);
 
 CF_EXTERN_C_END
diff --git a/objectivec/GPBDictionary.h b/objectivec/GPBDictionary.h
index 28d880d..90440e3 100644
--- a/objectivec/GPBDictionary.h
+++ b/objectivec/GPBDictionary.h
@@ -43,9 +43,11 @@
 
 NS_ASSUME_NONNULL_BEGIN
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-EXPAND DECLARE_DICTIONARIES()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - UInt32 -> UInt32
 
@@ -5479,7 +5481,6 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END DECLARE_DICTIONARIES()
 
 NS_ASSUME_NONNULL_END
@@ -5770,3 +5771,5 @@
 //% **/
 //%- (void)setRawValue:(VALUE_TYPE)rawValue forKey:(KEY_TYPE##KisP$S##KisP)key;
 //%
+
+// clang-format on
diff --git a/objectivec/GPBDictionary.m b/objectivec/GPBDictionary.m
index 187a970..3a10015 100644
--- a/objectivec/GPBDictionary.m
+++ b/objectivec/GPBDictionary.m
@@ -51,18 +51,6 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdirect-ivar-access"
 
-// Used to include code only visible to specific versions of the static
-// analyzer. Useful for wrapping code that only exists to silence the analyzer.
-// Determine the values you want to use for BEGIN_APPLE_BUILD_VERSION,
-// END_APPLE_BUILD_VERSION using:
-//   xcrun clang -dM -E -x c /dev/null | grep __apple_build_version__
-// Example usage:
-//  #if GPB_STATIC_ANALYZER_ONLY(5621, 5623) ... #endif
-#define GPB_STATIC_ANALYZER_ONLY(BEGIN_APPLE_BUILD_VERSION, END_APPLE_BUILD_VERSION) \
-    (defined(__clang_analyzer__) && \
-     (__apple_build_version__ >= BEGIN_APPLE_BUILD_VERSION && \
-      __apple_build_version__ <= END_APPLE_BUILD_VERSION))
-
 enum {
   kMapKeyFieldNumber = 1,
   kMapValueFieldNumber = 2,
@@ -73,6 +61,9 @@
   return (value != kGPBUnrecognizedEnumeratorValue);
 }
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-DEFINE SERIALIZE_SUPPORT_2_TYPE(VALUE_NAME, VALUE_TYPE, GPBDATATYPE_NAME1, GPBDATATYPE_NAME2)
 //%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE value, uint32_t fieldNum, GPBDataType dataType) {
 //%  if (dataType == GPBDataType##GPBDATATYPE_NAME1) {
@@ -122,15 +113,13 @@
 //%}
 //%
 //%PDDM-DEFINE SIMPLE_SERIALIZE_SUPPORT(VALUE_NAME, VALUE_TYPE, VisP)
-//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) {
+//%static size_t ComputeDict##VALUE_NAME##FieldSize(VALUE_TYPE VisP##value, uint32_t fieldNum, __unused GPBDataType dataType) {
 //%  NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType);
-//%  #pragma unused(dataType)  // For when asserts are off in release.
 //%  return GPBCompute##VALUE_NAME##Size(fieldNum, value);
 //%}
 //%
-//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, GPBDataType dataType) {
+//%static void WriteDict##VALUE_NAME##Field(GPBCodedOutputStream *stream, VALUE_TYPE VisP##value, uint32_t fieldNum, __unused GPBDataType dataType) {
 //%  NSCAssert(dataType == GPBDataType##VALUE_NAME, @"bad type: %d", dataType);
-//%  #pragma unused(dataType)  // For when asserts are off in release.
 //%  [stream write##VALUE_NAME##:fieldNum value:value];
 //%}
 //%
@@ -147,7 +136,6 @@
 //%SERIALIZE_SUPPORT_3_TYPE(Object, id, Message, String, Bytes)
 //%PDDM-EXPAND SERIALIZE_SUPPORT_HELPERS()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 static size_t ComputeDictInt32FieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) {
   if (dataType == GPBDataTypeInt32) {
@@ -241,63 +229,53 @@
   }
 }
 
-static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, GPBDataType dataType) {
+static size_t ComputeDictBoolFieldSize(BOOL value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeBoolSize(fieldNum, value);
 }
 
-static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, GPBDataType dataType) {
+static void WriteDictBoolField(GPBCodedOutputStream *stream, BOOL value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeBool, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeBool:fieldNum value:value];
 }
 
-static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+static size_t ComputeDictEnumFieldSize(int32_t value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeEnumSize(fieldNum, value);
 }
 
-static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, GPBDataType dataType) {
+static void WriteDictEnumField(GPBCodedOutputStream *stream, int32_t value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeEnum, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeEnum:fieldNum value:value];
 }
 
-static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, GPBDataType dataType) {
+static size_t ComputeDictFloatFieldSize(float value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeFloatSize(fieldNum, value);
 }
 
-static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, GPBDataType dataType) {
+static void WriteDictFloatField(GPBCodedOutputStream *stream, float value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeFloat, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeFloat:fieldNum value:value];
 }
 
-static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, GPBDataType dataType) {
+static size_t ComputeDictDoubleFieldSize(double value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeDoubleSize(fieldNum, value);
 }
 
-static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, GPBDataType dataType) {
+static void WriteDictDoubleField(GPBCodedOutputStream *stream, double value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeDouble, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeDouble:fieldNum value:value];
 }
 
-static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, GPBDataType dataType) {
+static size_t ComputeDictStringFieldSize(NSString *value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   return GPBComputeStringSize(fieldNum, value);
 }
 
-static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, GPBDataType dataType) {
+static void WriteDictStringField(GPBCodedOutputStream *stream, NSString *value, uint32_t fieldNum, __unused GPBDataType dataType) {
   NSCAssert(dataType == GPBDataTypeString, @"bad type: %d", dataType);
-  #pragma unused(dataType)  // For when asserts are off in release.
   [stream writeString:fieldNum value:value];
 }
 
@@ -326,9 +304,10 @@
   }
 }
 
-// clang-format on
 //%PDDM-EXPAND-END SERIALIZE_SUPPORT_HELPERS()
 
+// clang-format on
+
 size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
   GPBDataType mapValueType = GPBGetFieldDataType(field);
   size_t result = 0;
@@ -346,8 +325,7 @@
 }
 
 void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream,
-                                              NSDictionary *dict,
-                                              GPBFieldDescriptor *field) {
+                                              NSDictionary *dict, GPBFieldDescriptor *field) {
   NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
   GPBDataType mapValueType = GPBGetFieldDataType(field);
   uint32_t tag = GPBWireFormatMakeTag(GPBFieldNumber(field), GPBWireFormatLengthDelimited);
@@ -368,10 +346,10 @@
   }
 }
 
-BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field) {
+BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict,
+                                              __unused GPBFieldDescriptor *field) {
   NSCAssert(field.mapKeyDataType == GPBDataTypeString, @"Unexpected key type");
   NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeMessage, @"Unexpected value type");
-  #pragma unused(field)  // For when asserts are off in release.
   GPBMessage *msg;
   NSEnumerator *objects = [dict objectEnumerator];
   while ((msg = [objects nextObject])) {
@@ -383,11 +361,8 @@
 }
 
 // Note: if the type is an object, it the retain pass back to the caller.
-static void ReadValue(GPBCodedInputStream *stream,
-                      GPBGenericValue *valueToFill,
-                      GPBDataType type,
-                      GPBExtensionRegistry *registry,
-                      GPBFieldDescriptor *field) {
+static void ReadValue(GPBCodedInputStream *stream, GPBGenericValue *valueToFill, GPBDataType type,
+                      id<GPBExtensionRegistry> registry, GPBFieldDescriptor *field) {
   switch (type) {
     case GPBDataTypeBool:
       valueToFill->valueBool = GPBCodedInputStreamReadBool(&stream->state_);
@@ -452,10 +427,8 @@
   }
 }
 
-void GPBDictionaryReadEntry(id mapDictionary,
-                            GPBCodedInputStream *stream,
-                            GPBExtensionRegistry *registry,
-                            GPBFieldDescriptor *field,
+void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
+                            id<GPBExtensionRegistry> registry, GPBFieldDescriptor *field,
                             GPBMessage *parentMessage) {
   GPBDataType keyDataType = field.mapKeyDataType;
   GPBDataType valueDataType = GPBGetFieldDataType(field);
@@ -469,8 +442,7 @@
   }
 
   GPBCodedInputStreamState *state = &stream->state_;
-  uint32_t keyTag =
-      GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO));
+  uint32_t keyTag = GPBWireFormatMakeTag(kMapKeyFieldNumber, GPBWireFormatForType(keyDataType, NO));
   uint32_t valueTag =
       GPBWireFormatMakeTag(kMapValueFieldNumber, GPBWireFormatForType(valueDataType, NO));
 
@@ -485,7 +457,7 @@
       // zero signals EOF / limit reached
       break;
     } else {  // Unknown
-      if (![stream skipField:tag]){
+      if (![stream skipField:tag]) {
         hitError = YES;
         break;
       }
@@ -525,26 +497,11 @@
     }
 
     if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
-#if GPB_STATIC_ANALYZER_ONLY(6020053, 7000181)
-     // Limited to Xcode 6.4 - 7.2, are known to fail here. The upper end can
-     // be raised as needed for new Xcodes.
-     //
-     // This is only needed on a "shallow" analyze; on a "deep" analyze, the
-     // existing code path gets this correct. In shallow, the analyzer decides
-     // GPBDataTypeIsObject(valueDataType) is both false and true on a single
-     // path through this function, allowing nil to be used for the
-     // setObject:forKey:.
-     if (value.valueString == nil) {
-       value.valueString = [@"" retain];
-     }
-#endif
       // mapDictionary is an NSMutableDictionary
-      [(NSMutableDictionary *)mapDictionary setObject:value.valueString
-                                               forKey:key.valueString];
+      [(NSMutableDictionary *)mapDictionary setObject:value.valueString forKey:key.valueString];
     } else {
       if (valueDataType == GPBDataTypeEnum) {
-        if (GPBHasPreservingUnknownEnumSemantics([parentMessage descriptor].file.syntax) ||
-            [field isValidEnumValue:value.valueEnum]) {
+        if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:value.valueEnum]) {
           [mapDictionary setGPBGenericValue:&value forGPBGenericValueKey:&key];
         } else {
           NSData *data = [mapDictionary serializedDataForUnknownValue:value.valueEnum
@@ -570,6 +527,9 @@
 // Macros for the common basic cases.
 //
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-DEFINE DICTIONARY_IMPL_FOR_POD_KEY(KEY_NAME, KEY_TYPE)
 //%DICTIONARY_POD_IMPL_FOR_KEY(KEY_NAME, KEY_TYPE, , POD)
 //%DICTIONARY_POD_KEY_TO_OBJECT_IMPL(KEY_NAME, KEY_TYPE, Object, id)
@@ -627,8 +587,7 @@
 //%  return self;
 //%}
 //%
-//%- (instancetype)initWithCapacity:(NSUInteger)numItems {
-//%  #pragma unused(numItems)
+//%- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
 //%  return [self initWith##VNAME##s:NULL forKeys:NULL count:0];
 //%}
 //%
@@ -693,8 +652,7 @@
 //%}
 //%
 //%- (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-//%                                  capacity:(NSUInteger)numItems {
-//%  #pragma unused(numItems)
+//%                                  capacity:(__unused NSUInteger)numItems {
 //%  return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
 //%}
 //%
@@ -860,8 +818,7 @@
 //%}
 //%
 //%- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-//%  [self enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock:^(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, BOOL *stop) {
-//%      #pragma unused(stop)
+//%  [self enumerateKeysAnd##ACCESSOR_NAME##VNAME##sUsingBlock:^(KEY_TYPE KisP##key, VALUE_TYPE VNAME_VAR, __unused BOOL *stop) {
 //%      block(TEXT_FORMAT_OBJ##KEY_NAME(key), TEXT_FORMAT_OBJ##VALUE_NAME(VNAME_VAR));
 //%  }];
 //%}
@@ -915,8 +872,7 @@
 //%
 //%BOOL_DICT_INITS_##HELPER(VALUE_NAME, VALUE_TYPE)
 //%
-//%- (instancetype)initWithCapacity:(NSUInteger)numItems {
-//%  #pragma unused(numItems)
+//%- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
 //%  return [self initWith##VNAME##s:NULL forKeys:NULL count:0];
 //%}
 //%
@@ -1429,7 +1385,6 @@
 
 //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt32, uint32_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - UInt32 -> UInt32
 
@@ -1467,8 +1422,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -1574,8 +1528,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt32sUsingBlock:^(uint32_t key, uint32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt32sUsingBlock:^(uint32_t key, uint32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%u", value]);
   }];
 }
@@ -1650,8 +1603,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -1757,8 +1709,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt32sUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt32sUsingBlock:^(uint32_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%d", value]);
   }];
 }
@@ -1833,8 +1784,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -1940,8 +1890,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt64sUsingBlock:^(uint32_t key, uint64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt64sUsingBlock:^(uint32_t key, uint64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%llu", value]);
   }];
 }
@@ -2016,8 +1965,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -2123,8 +2071,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt64sUsingBlock:^(uint32_t key, int64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt64sUsingBlock:^(uint32_t key, int64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%lld", value]);
   }];
 }
@@ -2199,8 +2146,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithBools:NULL forKeys:NULL count:0];
 }
 
@@ -2306,8 +2252,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndBoolsUsingBlock:^(uint32_t key, BOOL value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndBoolsUsingBlock:^(uint32_t key, BOOL value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], (value ? @"true" : @"false"));
   }];
 }
@@ -2382,8 +2327,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithFloats:NULL forKeys:NULL count:0];
 }
 
@@ -2489,8 +2433,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndFloatsUsingBlock:^(uint32_t key, float value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndFloatsUsingBlock:^(uint32_t key, float value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
   }];
 }
@@ -2565,8 +2508,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithDoubles:NULL forKeys:NULL count:0];
 }
 
@@ -2672,8 +2614,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndDoublesUsingBlock:^(uint32_t key, double value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndDoublesUsingBlock:^(uint32_t key, double value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
   }];
 }
@@ -2761,8 +2702,7 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                  capacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+                                  capacity:(__unused NSUInteger)numItems {
   return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
 }
 
@@ -2880,8 +2820,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndRawValuesUsingBlock:^(uint32_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndRawValuesUsingBlock:^(uint32_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], @(value));
   }];
 }
@@ -3004,8 +2943,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithObjects:NULL forKeys:NULL count:0];
 }
 
@@ -3135,8 +3073,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndObjectsUsingBlock:^(uint32_t key, id object, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndObjectsUsingBlock:^(uint32_t key, id object, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%u", key], object);
   }];
 }
@@ -3176,10 +3113,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int32, int32_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int32 -> UInt32
 
@@ -3217,8 +3152,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -3324,8 +3258,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt32sUsingBlock:^(int32_t key, uint32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt32sUsingBlock:^(int32_t key, uint32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%u", value]);
   }];
 }
@@ -3400,8 +3333,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -3507,8 +3439,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt32sUsingBlock:^(int32_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt32sUsingBlock:^(int32_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%d", value]);
   }];
 }
@@ -3583,8 +3514,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -3690,8 +3620,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt64sUsingBlock:^(int32_t key, uint64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt64sUsingBlock:^(int32_t key, uint64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%llu", value]);
   }];
 }
@@ -3766,8 +3695,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -3873,8 +3801,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt64sUsingBlock:^(int32_t key, int64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt64sUsingBlock:^(int32_t key, int64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%lld", value]);
   }];
 }
@@ -3949,8 +3876,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithBools:NULL forKeys:NULL count:0];
 }
 
@@ -4056,8 +3982,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndBoolsUsingBlock:^(int32_t key, BOOL value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndBoolsUsingBlock:^(int32_t key, BOOL value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], (value ? @"true" : @"false"));
   }];
 }
@@ -4132,8 +4057,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithFloats:NULL forKeys:NULL count:0];
 }
 
@@ -4239,8 +4163,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndFloatsUsingBlock:^(int32_t key, float value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndFloatsUsingBlock:^(int32_t key, float value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
   }];
 }
@@ -4315,8 +4238,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithDoubles:NULL forKeys:NULL count:0];
 }
 
@@ -4422,8 +4344,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndDoublesUsingBlock:^(int32_t key, double value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndDoublesUsingBlock:^(int32_t key, double value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
   }];
 }
@@ -4511,8 +4432,7 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                  capacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+                                  capacity:(__unused NSUInteger)numItems {
   return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
 }
 
@@ -4630,8 +4550,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndRawValuesUsingBlock:^(int32_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndRawValuesUsingBlock:^(int32_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], @(value));
   }];
 }
@@ -4754,8 +4673,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithObjects:NULL forKeys:NULL count:0];
 }
 
@@ -4885,8 +4803,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndObjectsUsingBlock:^(int32_t key, id object, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndObjectsUsingBlock:^(int32_t key, id object, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%d", key], object);
   }];
 }
@@ -4926,10 +4843,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(UInt64, uint64_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - UInt64 -> UInt32
 
@@ -4967,8 +4882,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -5074,8 +4988,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt32sUsingBlock:^(uint64_t key, uint32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt32sUsingBlock:^(uint64_t key, uint32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%u", value]);
   }];
 }
@@ -5150,8 +5063,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -5257,8 +5169,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt32sUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt32sUsingBlock:^(uint64_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%d", value]);
   }];
 }
@@ -5333,8 +5244,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -5440,8 +5350,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt64sUsingBlock:^(uint64_t key, uint64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt64sUsingBlock:^(uint64_t key, uint64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%llu", value]);
   }];
 }
@@ -5516,8 +5425,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -5623,8 +5531,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt64sUsingBlock:^(uint64_t key, int64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt64sUsingBlock:^(uint64_t key, int64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%lld", value]);
   }];
 }
@@ -5699,8 +5606,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithBools:NULL forKeys:NULL count:0];
 }
 
@@ -5806,8 +5712,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndBoolsUsingBlock:^(uint64_t key, BOOL value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndBoolsUsingBlock:^(uint64_t key, BOOL value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], (value ? @"true" : @"false"));
   }];
 }
@@ -5882,8 +5787,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithFloats:NULL forKeys:NULL count:0];
 }
 
@@ -5989,8 +5893,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndFloatsUsingBlock:^(uint64_t key, float value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndFloatsUsingBlock:^(uint64_t key, float value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
   }];
 }
@@ -6065,8 +5968,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithDoubles:NULL forKeys:NULL count:0];
 }
 
@@ -6172,8 +6074,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndDoublesUsingBlock:^(uint64_t key, double value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndDoublesUsingBlock:^(uint64_t key, double value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
   }];
 }
@@ -6261,8 +6162,7 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                  capacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+                                  capacity:(__unused NSUInteger)numItems {
   return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
 }
 
@@ -6380,8 +6280,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndRawValuesUsingBlock:^(uint64_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndRawValuesUsingBlock:^(uint64_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], @(value));
   }];
 }
@@ -6504,8 +6403,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithObjects:NULL forKeys:NULL count:0];
 }
 
@@ -6635,8 +6533,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndObjectsUsingBlock:^(uint64_t key, id object, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndObjectsUsingBlock:^(uint64_t key, id object, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%llu", key], object);
   }];
 }
@@ -6676,10 +6573,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_IMPL_FOR_POD_KEY(Int64, int64_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int64 -> UInt32
 
@@ -6717,8 +6612,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -6824,8 +6718,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt32sUsingBlock:^(int64_t key, uint32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt32sUsingBlock:^(int64_t key, uint32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%u", value]);
   }];
 }
@@ -6900,8 +6793,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -7007,8 +6899,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt32sUsingBlock:^(int64_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt32sUsingBlock:^(int64_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%d", value]);
   }];
 }
@@ -7083,8 +6974,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -7190,8 +7080,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt64sUsingBlock:^(int64_t key, uint64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt64sUsingBlock:^(int64_t key, uint64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%llu", value]);
   }];
 }
@@ -7266,8 +7155,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -7373,8 +7261,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt64sUsingBlock:^(int64_t key, int64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt64sUsingBlock:^(int64_t key, int64_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%lld", value]);
   }];
 }
@@ -7449,8 +7336,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithBools:NULL forKeys:NULL count:0];
 }
 
@@ -7556,8 +7442,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndBoolsUsingBlock:^(int64_t key, BOOL value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndBoolsUsingBlock:^(int64_t key, BOOL value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], (value ? @"true" : @"false"));
   }];
 }
@@ -7632,8 +7517,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithFloats:NULL forKeys:NULL count:0];
 }
 
@@ -7739,8 +7623,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndFloatsUsingBlock:^(int64_t key, float value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndFloatsUsingBlock:^(int64_t key, float value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
   }];
 }
@@ -7815,8 +7698,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithDoubles:NULL forKeys:NULL count:0];
 }
 
@@ -7922,8 +7804,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndDoublesUsingBlock:^(int64_t key, double value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndDoublesUsingBlock:^(int64_t key, double value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
   }];
 }
@@ -8011,8 +7892,7 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                  capacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+                                  capacity:(__unused NSUInteger)numItems {
   return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
 }
 
@@ -8130,8 +8010,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndRawValuesUsingBlock:^(int64_t key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndRawValuesUsingBlock:^(int64_t key, int32_t value, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], @(value));
   }];
 }
@@ -8254,8 +8133,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithObjects:NULL forKeys:NULL count:0];
 }
 
@@ -8385,8 +8263,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndObjectsUsingBlock:^(int64_t key, id object, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndObjectsUsingBlock:^(int64_t key, id object, __unused BOOL *stop) {
       block([NSString stringWithFormat:@"%lld", key], object);
   }];
 }
@@ -8426,10 +8303,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_POD_IMPL_FOR_KEY(String, NSString, *, OBJECT)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - String -> UInt32
 
@@ -8471,8 +8346,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -8578,8 +8452,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt32sUsingBlock:^(NSString *key, uint32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt32sUsingBlock:^(NSString *key, uint32_t value, __unused BOOL *stop) {
       block(key, [NSString stringWithFormat:@"%u", value]);
   }];
 }
@@ -8662,8 +8535,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -8769,8 +8641,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt32sUsingBlock:^(NSString *key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt32sUsingBlock:^(NSString *key, int32_t value, __unused BOOL *stop) {
       block(key, [NSString stringWithFormat:@"%d", value]);
   }];
 }
@@ -8853,8 +8724,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -8960,8 +8830,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndUInt64sUsingBlock:^(NSString *key, uint64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndUInt64sUsingBlock:^(NSString *key, uint64_t value, __unused BOOL *stop) {
       block(key, [NSString stringWithFormat:@"%llu", value]);
   }];
 }
@@ -9044,8 +8913,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -9151,8 +9019,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndInt64sUsingBlock:^(NSString *key, int64_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndInt64sUsingBlock:^(NSString *key, int64_t value, __unused BOOL *stop) {
       block(key, [NSString stringWithFormat:@"%lld", value]);
   }];
 }
@@ -9235,8 +9102,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithBools:NULL forKeys:NULL count:0];
 }
 
@@ -9342,8 +9208,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndBoolsUsingBlock:^(NSString *key, BOOL value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndBoolsUsingBlock:^(NSString *key, BOOL value, __unused BOOL *stop) {
       block(key, (value ? @"true" : @"false"));
   }];
 }
@@ -9426,8 +9291,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithFloats:NULL forKeys:NULL count:0];
 }
 
@@ -9533,8 +9397,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndFloatsUsingBlock:^(NSString *key, float value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndFloatsUsingBlock:^(NSString *key, float value, __unused BOOL *stop) {
       block(key, [NSString stringWithFormat:@"%.*g", FLT_DIG, value]);
   }];
 }
@@ -9617,8 +9480,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithDoubles:NULL forKeys:NULL count:0];
 }
 
@@ -9724,8 +9586,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndDoublesUsingBlock:^(NSString *key, double value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndDoublesUsingBlock:^(NSString *key, double value, __unused BOOL *stop) {
       block(key, [NSString stringWithFormat:@"%.*lg", DBL_DIG, value]);
   }];
 }
@@ -9821,8 +9682,7 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                  capacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+                                  capacity:(__unused NSUInteger)numItems {
   return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
 }
 
@@ -9940,8 +9800,7 @@
 }
 
 - (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
-  [self enumerateKeysAndRawValuesUsingBlock:^(NSString *key, int32_t value, BOOL *stop) {
-      #pragma unused(stop)
+  [self enumerateKeysAndRawValuesUsingBlock:^(NSString *key, int32_t value, __unused BOOL *stop) {
       block(key, @(value));
   }];
 }
@@ -10032,13 +9891,11 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END (5 expansions)
 
 
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt32, uint32_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> UInt32
 
@@ -10081,8 +9938,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -10246,10 +10102,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int32, int32_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Int32
 
@@ -10292,8 +10146,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt32s:NULL forKeys:NULL count:0];
 }
 
@@ -10457,10 +10310,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(UInt64, uint64_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> UInt64
 
@@ -10503,8 +10354,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithUInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -10668,10 +10518,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Int64, int64_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Int64
 
@@ -10714,8 +10562,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithInt64s:NULL forKeys:NULL count:0];
 }
 
@@ -10879,10 +10726,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Bool, BOOL)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Bool
 
@@ -10925,8 +10770,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithBools:NULL forKeys:NULL count:0];
 }
 
@@ -11090,10 +10934,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Float, float)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Float
 
@@ -11136,8 +10978,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithFloats:NULL forKeys:NULL count:0];
 }
 
@@ -11301,10 +11142,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_POD_IMPL(Double, double)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Double
 
@@ -11347,8 +11186,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithDoubles:NULL forKeys:NULL count:0];
 }
 
@@ -11512,10 +11350,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_BOOL_KEY_TO_OBJECT_IMPL(Object, id)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Object
 
@@ -11557,8 +11393,7 @@
   return self;
 }
 
-- (instancetype)initWithCapacity:(NSUInteger)numItems {
-  #pragma unused(numItems)
+- (instancetype)initWithCapacity:(__unused NSUInteger)numItems {
   return [self initWithObjects:NULL forKeys:NULL count:0];
 }
 
@@ -11744,9 +11579,10 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END (8 expansions)
 
+// clang-format on
+
 #pragma mark - Bool -> Enum
 
 @implementation GPBBoolEnumDictionary {
@@ -11767,8 +11603,8 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                rawValues:(const int32_t [])rawValues
-                                   forKeys:(const BOOL [])keys
+                                 rawValues:(const int32_t[])rawValues
+                                   forKeys:(const BOOL[])keys
                                      count:(NSUInteger)count {
   self = [super init];
   if (self) {
@@ -11801,15 +11637,13 @@
 }
 
 - (instancetype)initWithValidationFunction:(GPBEnumValidationFunc)func
-                                  capacity:(NSUInteger)numItems {
-#pragma unused(numItems)
+                                  capacity:(__unused NSUInteger)numItems {
   return [self initWithValidationFunction:func rawValues:NULL forKeys:NULL count:0];
 }
 
 #if !defined(NS_BLOCK_ASSERTIONS)
 - (void)dealloc {
-  NSAssert(!_autocreator,
-           @"%@: Autocreator must be cleared before release, autocreator: %@",
+  NSAssert(!_autocreator, @"%@: Autocreator must be cleared before release, autocreator: %@",
            [self class], _autocreator);
   [super dealloc];
 }
@@ -11858,7 +11692,7 @@
   return (_valueSet[0] ? 1 : 0) + (_valueSet[1] ? 1 : 0);
 }
 
-- (BOOL)getEnum:(int32_t*)value forKey:(BOOL)key {
+- (BOOL)getEnum:(int32_t *)value forKey:(BOOL)key {
   int idx = (key ? 1 : 0);
   if (_valueSet[idx]) {
     if (value) {
@@ -11873,7 +11707,7 @@
   return NO;
 }
 
-- (BOOL)getRawValue:(int32_t*)rawValue forKey:(BOOL)key {
+- (BOOL)getRawValue:(int32_t *)rawValue forKey:(BOOL)key {
   int idx = (key ? 1 : 0);
   if (_valueSet[idx]) {
     if (rawValue) {
@@ -11884,8 +11718,8 @@
   return NO;
 }
 
-- (void)enumerateKeysAndRawValuesUsingBlock:
-    (void (NS_NOESCAPE ^)(BOOL key, int32_t value, BOOL *stop))block {
+- (void)enumerateKeysAndRawValuesUsingBlock:(void(NS_NOESCAPE ^)(BOOL key, int32_t value,
+                                                                 BOOL *stop))block {
   BOOL stop = NO;
   if (_valueSet[0]) {
     block(NO, _values[0], &stop);
@@ -11895,8 +11729,8 @@
   }
 }
 
-- (void)enumerateKeysAndEnumsUsingBlock:
-    (void (NS_NOESCAPE ^)(BOOL key, int32_t rawValue, BOOL *stop))block {
+- (void)enumerateKeysAndEnumsUsingBlock:(void(NS_NOESCAPE ^)(BOOL key, int32_t rawValue,
+                                                             BOOL *stop))block {
   BOOL stop = NO;
   GPBEnumValidationFunc func = _validationFunc;
   int32_t validatedValue;
@@ -11916,9 +11750,10 @@
   }
 }
 
+// clang-format off
+
 //%PDDM-EXPAND SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (NSData *)serializedDataForUnknownValue:(int32_t)value
                                    forKey:(GPBGenericValue *)key
@@ -11933,9 +11768,10 @@
   return data;
 }
 
-// clang-format on
 //%PDDM-EXPAND-END SERIAL_DATA_FOR_ENTRY_POD_Enum(Bool)
 
+// clang-format on
+
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field {
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   NSUInteger count = 0;
@@ -11972,7 +11808,7 @@
   }
 }
 
-- (void)enumerateForTextFormat:(void (NS_NOESCAPE ^)(id keyObj, id valueObj))block {
+- (void)enumerateForTextFormat:(void(NS_NOESCAPE ^)(id keyObj, id valueObj))block {
   if (_valueSet[0]) {
     block(@"false", @(_values[0]));
   }
@@ -11981,8 +11817,7 @@
   }
 }
 
-- (void)setGPBGenericValue:(GPBGenericValue *)value
-     forGPBGenericValueKey:(GPBGenericValue *)key {
+- (void)setGPBGenericValue:(GPBGenericValue *)value forGPBGenericValueKey:(GPBGenericValue *)key {
   int idx = (key->valueBool ? 1 : 0);
   _values[idx] = value->valueInt32;
   _valueSet[idx] = YES;
@@ -12005,8 +11840,7 @@
 - (void)setEnum:(int32_t)value forKey:(BOOL)key {
   if (!_validationFunc(value)) {
     [NSException raise:NSInvalidArgumentException
-                format:@"GPBBoolEnumDictionary: Attempt to set an unknown enum value (%d)",
-     value];
+                format:@"GPBBoolEnumDictionary: Attempt to set an unknown enum value (%d)", value];
   }
   int idx = (key ? 1 : 0);
   _values[idx] = value;
@@ -12043,8 +11877,7 @@
 }
 
 - (void)dealloc {
-  NSAssert(!_autocreator,
-           @"%@: Autocreator must be cleared before release, autocreator: %@",
+  NSAssert(!_autocreator, @"%@: Autocreator must be cleared before release, autocreator: %@",
            [self class], _autocreator);
   [_dictionary release];
   [super dealloc];
@@ -12052,14 +11885,12 @@
 
 #pragma mark Required NSDictionary overrides
 
-- (instancetype)initWithObjects:(const id [])objects
-                        forKeys:(const id<NSCopying> [])keys
+- (instancetype)initWithObjects:(const id[])objects
+                        forKeys:(const id<NSCopying>[])keys
                           count:(NSUInteger)count {
   self = [super init];
   if (self) {
-    _dictionary = [[NSMutableDictionary alloc] initWithObjects:objects
-                                                       forKeys:keys
-                                                         count:count];
+    _dictionary = [[NSMutableDictionary alloc] initWithObjects:objects forKeys:keys count:count];
   }
   return self;
 }
@@ -12132,16 +11963,12 @@
   }
 }
 
-- (void)enumerateKeysAndObjectsUsingBlock:(void (NS_NOESCAPE ^)(id key,
-                                                    id obj,
-                                                    BOOL *stop))block {
+- (void)enumerateKeysAndObjectsUsingBlock:(void(NS_NOESCAPE ^)(id key, id obj, BOOL *stop))block {
   [_dictionary enumerateKeysAndObjectsUsingBlock:block];
 }
 
 - (void)enumerateKeysAndObjectsWithOptions:(NSEnumerationOptions)opts
-                                usingBlock:(void (NS_NOESCAPE ^)(id key,
-                                                     id obj,
-                                                     BOOL *stop))block {
+                                usingBlock:(void(NS_NOESCAPE ^)(id key, id obj, BOOL *stop))block {
   [_dictionary enumerateKeysAndObjectsWithOptions:opts usingBlock:block];
 }
 
diff --git a/objectivec/GPBDictionary_PackagePrivate.h b/objectivec/GPBDictionary_PackagePrivate.h
index 15e4283..3735fa5 100644
--- a/objectivec/GPBDictionary_PackagePrivate.h
+++ b/objectivec/GPBDictionary_PackagePrivate.h
@@ -34,18 +34,20 @@
 
 @class GPBCodedInputStream;
 @class GPBCodedOutputStream;
-@class GPBExtensionRegistry;
+@protocol GPBExtensionRegistry;
 @class GPBFieldDescriptor;
 
 @protocol GPBDictionaryInternalsProtocol
 - (size_t)computeSerializedSizeAsField:(GPBFieldDescriptor *)field;
 - (void)writeToCodedOutputStream:(GPBCodedOutputStream *)outputStream
                          asField:(GPBFieldDescriptor *)field;
-- (void)setGPBGenericValue:(GPBGenericValue *)value
-     forGPBGenericValueKey:(GPBGenericValue *)key;
+- (void)setGPBGenericValue:(GPBGenericValue *)value forGPBGenericValueKey:(GPBGenericValue *)key;
 - (void)enumerateForTextFormat:(void (^)(id keyObj, id valueObj))block;
 @end
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-DEFINE DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(KEY_NAME)
 //%DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(KEY_NAME)
 //%DICTIONARY_PRIVATE_INTERFACES(KEY_NAME, Object, Object)
@@ -82,7 +84,6 @@
 
 //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt32)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 @interface GPBUInt32UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
  @package
@@ -144,10 +145,8 @@
     __attribute__((ns_returns_retained));
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int32)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 @interface GPBInt32UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
  @package
@@ -209,10 +208,8 @@
     __attribute__((ns_returns_retained));
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(UInt64)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 @interface GPBUInt64UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
  @package
@@ -274,10 +271,8 @@
     __attribute__((ns_returns_retained));
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Int64)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 @interface GPBInt64UInt32Dictionary () <GPBDictionaryInternalsProtocol> {
  @package
@@ -339,10 +334,8 @@
     __attribute__((ns_returns_retained));
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_PRIV_INTERFACES_FOR_POD_KEY(Bool)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 @interface GPBBoolUInt32Dictionary () <GPBDictionaryInternalsProtocol> {
  @package
@@ -404,10 +397,8 @@
     __attribute__((ns_returns_retained));
 @end
 
-// clang-format on
 //%PDDM-EXPAND DICTIONARY_POD_PRIV_INTERFACES_FOR_KEY(String)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 @interface GPBStringUInt32Dictionary () <GPBDictionaryInternalsProtocol> {
  @package
@@ -460,13 +451,14 @@
                               keyDataType:(GPBDataType)keyDataType;
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END (6 expansions)
 
+// clang-format on
+
 #pragma mark - NSDictionary Subclass
 
 @interface GPBAutocreatedDictionary : NSMutableDictionary {
-  @package
+ @package
   GPB_UNSAFE_UNRETAINED GPBMessage *_autocreator;
 }
 @end
@@ -477,24 +469,20 @@
 
 // Helper to compute size when an NSDictionary is used for the map instead
 // of a custom type.
-size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict,
-                                              GPBFieldDescriptor *field);
+size_t GPBDictionaryComputeSizeInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field);
 
 // Helper to write out when an NSDictionary is used for the map instead
 // of a custom type.
-void GPBDictionaryWriteToStreamInternalHelper(
-    GPBCodedOutputStream *outputStream, NSDictionary *dict,
-    GPBFieldDescriptor *field);
+void GPBDictionaryWriteToStreamInternalHelper(GPBCodedOutputStream *outputStream,
+                                              NSDictionary *dict, GPBFieldDescriptor *field);
 
 // Helper to check message initialization when an NSDictionary is used for
 // the map instead of a custom type.
-BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict,
-                                              GPBFieldDescriptor *field);
+BOOL GPBDictionaryIsInitializedInternalHelper(NSDictionary *dict, GPBFieldDescriptor *field);
 
 // Helper to read a map instead.
 void GPBDictionaryReadEntry(id mapDictionary, GPBCodedInputStream *stream,
-                            GPBExtensionRegistry *registry,
-                            GPBFieldDescriptor *field,
+                            id<GPBExtensionRegistry> registry, GPBFieldDescriptor *field,
                             GPBMessage *parentMessage);
 
 CF_EXTERN_C_END
diff --git a/objectivec/GPBDuration.pbobjc.h b/objectivec/GPBDuration.pbobjc.h
index d6236b0..05c63d8 100644
--- a/objectivec/GPBDuration.pbobjc.h
+++ b/objectivec/GPBDuration.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/duration.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -131,3 +132,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBDuration.pbobjc.m b/objectivec/GPBDuration.pbobjc.m
index 11ba5e5..c3edc24 100644
--- a/objectivec/GPBDuration.pbobjc.m
+++ b/objectivec/GPBDuration.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/duration.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -78,7 +79,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBDuration__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -93,3 +94,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBEmpty.pbobjc.h b/objectivec/GPBEmpty.pbobjc.h
index 5878223..3de240d 100644
--- a/objectivec/GPBEmpty.pbobjc.h
+++ b/objectivec/GPBEmpty.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/empty.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -58,3 +59,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBEmpty.pbobjc.m b/objectivec/GPBEmpty.pbobjc.m
index 8aefddb..e5f3fd0 100644
--- a/objectivec/GPBEmpty.pbobjc.m
+++ b/objectivec/GPBEmpty.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/empty.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -54,7 +55,7 @@
                                         fields:NULL
                                     fieldCount:0
                                    storageSize:sizeof(GPBEmpty__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -69,3 +70,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBExtensionInternals.h b/objectivec/GPBExtensionInternals.h
index 2b980ae..e3bec7c 100644
--- a/objectivec/GPBExtensionInternals.h
+++ b/objectivec/GPBExtensionInternals.h
@@ -32,19 +32,9 @@
 
 #import "GPBDescriptor.h"
 
-@class GPBCodedInputStream;
 @class GPBCodedOutputStream;
-@class GPBExtensionRegistry;
 
-void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension,
-                                      BOOL isPackedOnStream,
-                                      GPBCodedInputStream *input,
-                                      GPBExtensionRegistry *extensionRegistry,
-                                      GPBMessage *message);
+size_t GPBComputeExtensionSerializedSizeIncludingTag(GPBExtensionDescriptor *extension, id value);
 
-size_t GPBComputeExtensionSerializedSizeIncludingTag(
-    GPBExtensionDescriptor *extension, id value);
-
-void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension,
-                                          id value,
+void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, id value,
                                           GPBCodedOutputStream *output);
diff --git a/objectivec/GPBExtensionInternals.m b/objectivec/GPBExtensionInternals.m
index bacec57..fafb9c2 100644
--- a/objectivec/GPBExtensionInternals.m
+++ b/objectivec/GPBExtensionInternals.m
@@ -38,12 +38,6 @@
 #import "GPBMessage_PackagePrivate.h"
 #import "GPBUtilities_PackagePrivate.h"
 
-static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
-                                        GPBCodedInputStream *input,
-                                        GPBExtensionRegistry *extensionRegistry,
-                                        GPBMessage *existingValue)
-    __attribute__((ns_returns_retained));
-
 GPB_INLINE size_t DataTypeSize(GPBDataType dataType) {
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wswitch-enum"
@@ -65,11 +59,11 @@
 }
 
 static size_t ComputePBSerializedSizeNoTagOfObject(GPBDataType dataType, id object) {
-#define FIELD_CASE(TYPE, ACCESSOR)                                     \
-  case GPBDataType##TYPE:                                              \
+#define FIELD_CASE(TYPE, ACCESSOR) \
+  case GPBDataType##TYPE:          \
     return GPBCompute##TYPE##SizeNoTag([(NSNumber *)object ACCESSOR]);
-#define FIELD_CASE2(TYPE)                                              \
-  case GPBDataType##TYPE:                                              \
+#define FIELD_CASE2(TYPE) \
+  case GPBDataType##TYPE: \
     return GPBCompute##TYPE##SizeNoTag(object);
   switch (dataType) {
     FIELD_CASE(Bool, boolValue)
@@ -95,14 +89,13 @@
 #undef FIELD_CASE2
 }
 
-static size_t ComputeSerializedSizeIncludingTagOfObject(
-    GPBExtensionDescription *description, id object) {
-#define FIELD_CASE(TYPE, ACCESSOR)                                   \
-  case GPBDataType##TYPE:                                            \
-    return GPBCompute##TYPE##Size(description->fieldNumber,          \
-                                  [(NSNumber *)object ACCESSOR]);
-#define FIELD_CASE2(TYPE)                                            \
-  case GPBDataType##TYPE:                                            \
+static size_t ComputeSerializedSizeIncludingTagOfObject(GPBExtensionDescription *description,
+                                                        id object) {
+#define FIELD_CASE(TYPE, ACCESSOR) \
+  case GPBDataType##TYPE:          \
+    return GPBCompute##TYPE##Size(description->fieldNumber, [(NSNumber *)object ACCESSOR]);
+#define FIELD_CASE2(TYPE) \
+  case GPBDataType##TYPE: \
     return GPBCompute##TYPE##Size(description->fieldNumber, object);
   switch (description->dataType) {
     FIELD_CASE(Bool, boolValue)
@@ -124,8 +117,7 @@
     FIELD_CASE2(Group)
     case GPBDataTypeMessage:
       if (GPBExtensionIsWireFormat(description)) {
-        return GPBComputeMessageSetExtensionSize(description->fieldNumber,
-                                                 object);
+        return GPBComputeMessageSetExtensionSize(description->fieldNumber, object);
       } else {
         return GPBComputeMessageSize(description->fieldNumber, object);
       }
@@ -134,8 +126,8 @@
 #undef FIELD_CASE2
 }
 
-static size_t ComputeSerializedSizeIncludingTagOfArray(
-    GPBExtensionDescription *description, NSArray *values) {
+static size_t ComputeSerializedSizeIncludingTagOfArray(GPBExtensionDescription *description,
+                                                       NSArray *values) {
   if (GPBExtensionIsPacked(description)) {
     size_t size = 0;
     size_t typeSize = DataTypeSize(description->dataType);
@@ -143,8 +135,7 @@
       size = values.count * typeSize;
     } else {
       for (id value in values) {
-        size +=
-            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
+        size += ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
       }
     }
     return size + GPBComputeTagSize(description->fieldNumber) +
@@ -158,13 +149,12 @@
   }
 }
 
-static void WriteObjectIncludingTagToCodedOutputStream(
-    id object, GPBExtensionDescription *description,
-    GPBCodedOutputStream *output) {
-#define FIELD_CASE(TYPE, ACCESSOR)                      \
-  case GPBDataType##TYPE:                               \
-    [output write##TYPE:description->fieldNumber        \
-                  value:[(NSNumber *)object ACCESSOR]]; \
+static void WriteObjectIncludingTagToCodedOutputStream(id object,
+                                                       GPBExtensionDescription *description,
+                                                       GPBCodedOutputStream *output) {
+#define FIELD_CASE(TYPE, ACCESSOR)                                                     \
+  case GPBDataType##TYPE:                                                              \
+    [output write##TYPE:description->fieldNumber value:[(NSNumber *)object ACCESSOR]]; \
     return;
 #define FIELD_CASE2(TYPE)                                       \
   case GPBDataType##TYPE:                                       \
@@ -200,9 +190,8 @@
 #undef FIELD_CASE2
 }
 
-static void WriteObjectNoTagToCodedOutputStream(
-    id object, GPBExtensionDescription *description,
-    GPBCodedOutputStream *output) {
+static void WriteObjectNoTagToCodedOutputStream(id object, GPBExtensionDescription *description,
+                                                GPBCodedOutputStream *output) {
 #define FIELD_CASE(TYPE, ACCESSOR)                             \
   case GPBDataType##TYPE:                                      \
     [output write##TYPE##NoTag:[(NSNumber *)object ACCESSOR]]; \
@@ -237,20 +226,18 @@
 #undef FIELD_CASE2
 }
 
-static void WriteArrayIncludingTagsToCodedOutputStream(
-    NSArray *values, GPBExtensionDescription *description,
-    GPBCodedOutputStream *output) {
+static void WriteArrayIncludingTagsToCodedOutputStream(NSArray *values,
+                                                       GPBExtensionDescription *description,
+                                                       GPBCodedOutputStream *output) {
   if (GPBExtensionIsPacked(description)) {
-    [output writeTag:description->fieldNumber
-              format:GPBWireFormatLengthDelimited];
+    [output writeTag:description->fieldNumber format:GPBWireFormatLengthDelimited];
     size_t dataSize = 0;
     size_t typeSize = DataTypeSize(description->dataType);
     if (typeSize != 0) {
       dataSize = values.count * typeSize;
     } else {
       for (id value in values) {
-        dataSize +=
-            ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
+        dataSize += ComputePBSerializedSizeNoTagOfObject(description->dataType, value);
       }
     }
     [output writeRawVarintSizeTAs32:dataSize];
@@ -270,48 +257,7 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdirect-ivar-access"
 
-void GPBExtensionMergeFromInputStream(GPBExtensionDescriptor *extension,
-                                      BOOL isPackedOnStream,
-                                      GPBCodedInputStream *input,
-                                      GPBExtensionRegistry *extensionRegistry,
-                                      GPBMessage *message) {
-  GPBExtensionDescription *description = extension->description_;
-  GPBCodedInputStreamState *state = &input->state_;
-  if (isPackedOnStream) {
-    NSCAssert(GPBExtensionIsRepeated(description),
-              @"How was it packed if it isn't repeated?");
-    int32_t length = GPBCodedInputStreamReadInt32(state);
-    size_t limit = GPBCodedInputStreamPushLimit(state, length);
-    while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
-      id value = NewSingleValueFromInputStream(extension,
-                                               input,
-                                               extensionRegistry,
-                                               nil);
-      [message addExtension:extension value:value];
-      [value release];
-    }
-    GPBCodedInputStreamPopLimit(state, limit);
-  } else {
-    id existingValue = nil;
-    BOOL isRepeated = GPBExtensionIsRepeated(description);
-    if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) {
-      existingValue = [message getExistingExtension:extension];
-    }
-    id value = NewSingleValueFromInputStream(extension,
-                                             input,
-                                             extensionRegistry,
-                                             existingValue);
-    if (isRepeated) {
-      [message addExtension:extension value:value];
-    } else {
-      [message setExtension:extension value:value];
-    }
-    [value release];
-  }
-}
-
-void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension,
-                                          id value,
+void GPBWriteExtensionValueToOutputStream(GPBExtensionDescriptor *extension, id value,
                                           GPBCodedOutputStream *output) {
   GPBExtensionDescription *description = extension->description_;
   if (GPBExtensionIsRepeated(description)) {
@@ -321,8 +267,7 @@
   }
 }
 
-size_t GPBComputeExtensionSerializedSizeIncludingTag(
-    GPBExtensionDescriptor *extension, id value) {
+size_t GPBComputeExtensionSerializedSizeIncludingTag(GPBExtensionDescriptor *extension, id value) {
   GPBExtensionDescription *description = extension->description_;
   if (GPBExtensionIsRepeated(description)) {
     return ComputeSerializedSizeIncludingTagOfArray(description, value);
@@ -331,61 +276,4 @@
   }
 }
 
-// Note that this returns a retained value intentionally.
-static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
-                                        GPBCodedInputStream *input,
-                                        GPBExtensionRegistry *extensionRegistry,
-                                        GPBMessage *existingValue) {
-  GPBExtensionDescription *description = extension->description_;
-  GPBCodedInputStreamState *state = &input->state_;
-  switch (description->dataType) {
-    case GPBDataTypeBool:     return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
-    case GPBDataTypeFixed32:  return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
-    case GPBDataTypeSFixed32: return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
-    case GPBDataTypeFloat:    return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
-    case GPBDataTypeFixed64:  return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
-    case GPBDataTypeSFixed64: return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
-    case GPBDataTypeDouble:   return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
-    case GPBDataTypeInt32:    return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
-    case GPBDataTypeInt64:    return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
-    case GPBDataTypeSInt32:   return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
-    case GPBDataTypeSInt64:   return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
-    case GPBDataTypeUInt32:   return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
-    case GPBDataTypeUInt64:   return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
-    case GPBDataTypeBytes:    return GPBCodedInputStreamReadRetainedBytes(state);
-    case GPBDataTypeString:   return GPBCodedInputStreamReadRetainedString(state);
-    case GPBDataTypeEnum:     return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadEnum(state)];
-    case GPBDataTypeGroup:
-    case GPBDataTypeMessage: {
-      GPBMessage *message;
-      if (existingValue) {
-        message = [existingValue retain];
-      } else {
-        GPBDescriptor *descriptor = [extension.msgClass descriptor];
-        message = [[descriptor.messageClass alloc] init];
-      }
-
-      if (description->dataType == GPBDataTypeGroup) {
-        [input readGroup:description->fieldNumber
-                 message:message
-            extensionRegistry:extensionRegistry];
-      } else {
-        // description->dataType == GPBDataTypeMessage
-        if (GPBExtensionIsWireFormat(description)) {
-          // For MessageSet fields the message length will have already been
-          // read.
-          [message mergeFromCodedInputStream:input
-                           extensionRegistry:extensionRegistry];
-        } else {
-          [input readMessage:message extensionRegistry:extensionRegistry];
-        }
-      }
-
-      return message;
-    }
-  }
-
-  return nil;
-}
-
 #pragma clang diagnostic pop
diff --git a/objectivec/GPBExtensionRegistry.h b/objectivec/GPBExtensionRegistry.h
index d79632d..2c1270b 100644
--- a/objectivec/GPBExtensionRegistry.h
+++ b/objectivec/GPBExtensionRegistry.h
@@ -41,6 +41,24 @@
  * GPBExtensionRegistry in which you have registered any extensions that you
  * want to be able to parse. Otherwise, those extensions will just be treated
  * like unknown fields.
+ **/
+@protocol GPBExtensionRegistry <NSObject>
+
+/**
+ * Looks for the extension registered for the given field number on a given
+ * GPBDescriptor.
+ *
+ * @param descriptor  The descriptor to look for a registered extension on.
+ * @param fieldNumber The field number of the extension to look for.
+ *
+ * @return The registered GPBExtensionDescriptor or nil if none was found.
+ **/
+- (nullable GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
+                                                fieldNumber:(NSInteger)fieldNumber;
+@end
+
+/**
+ * A concrete implementation of `GPBExtensionRegistry`.
  *
  * The *Root classes provide `+extensionRegistry` for the extensions defined
  * in a given file *and* all files it imports. You can also create a
@@ -54,7 +72,7 @@
  * MyMessage *msg = [MyMessage parseData:data extensionRegistry:registry error:&parseError];
  * ```
  **/
-@interface GPBExtensionRegistry : NSObject<NSCopying>
+@interface GPBExtensionRegistry : NSObject <NSCopying, GPBExtensionRegistry>
 
 /**
  * Adds the given GPBExtensionDescriptor to this registry.
@@ -70,18 +88,6 @@
  **/
 - (void)addExtensions:(GPBExtensionRegistry *)registry;
 
-/**
- * Looks for the extension registered for the given field number on a given
- * GPBDescriptor.
- *
- * @param descriptor  The descriptor to look for a registered extension on.
- * @param fieldNumber The field number of the extension to look for.
- *
- * @return The registered GPBExtensionDescriptor or nil if none was found.
- **/
-- (nullable GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
-                                                fieldNumber:(NSInteger)fieldNumber;
-
 @end
 
 NS_ASSUME_NONNULL_END
diff --git a/objectivec/GPBExtensionRegistry.m b/objectivec/GPBExtensionRegistry.m
index e3ff7c4..04f1bca 100644
--- a/objectivec/GPBExtensionRegistry.m
+++ b/objectivec/GPBExtensionRegistry.m
@@ -40,8 +40,8 @@
 - (instancetype)init {
   if ((self = [super init])) {
     // The keys are ObjC classes, so straight up ptr comparisons are fine.
-    mutableClassMap_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
-                                             &kCFTypeDictionaryValueCallBacks);
+    mutableClassMap_ =
+        CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
   }
   return self;
 }
@@ -69,13 +69,13 @@
   }
 
   Class containingMessageClass = extension.containingMessageClass;
-  CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-      CFDictionaryGetValue(mutableClassMap_, containingMessageClass);
+  CFMutableDictionaryRef extensionMap =
+      (CFMutableDictionaryRef)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);
+    extensionMap =
+        CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
     CFDictionarySetValue(mutableClassMap_, containingMessageClass, extensionMap);
     CFRelease(extensionMap);
   }
@@ -87,13 +87,11 @@
 - (GPBExtensionDescriptor *)extensionForDescriptor:(GPBDescriptor *)descriptor
                                        fieldNumber:(NSInteger)fieldNumber {
   Class messageClass = descriptor.messageClass;
-  CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-      CFDictionaryGetValue(mutableClassMap_, messageClass);
+  CFMutableDictionaryRef extensionMap =
+      (CFMutableDictionaryRef)CFDictionaryGetValue(mutableClassMap_, messageClass);
   ssize_t key = fieldNumber;
   GPBExtensionDescriptor *result =
-      (extensionMap
-       ? CFDictionaryGetValue(extensionMap, (const void *)key)
-       : nil);
+      (extensionMap ? CFDictionaryGetValue(extensionMap, (const void *)key) : nil);
   return result;
 }
 
@@ -107,8 +105,8 @@
   Class containingMessageClass = key;
   CFMutableDictionaryRef otherExtensionMap = (CFMutableDictionaryRef)value;
 
-  CFMutableDictionaryRef extensionMap = (CFMutableDictionaryRef)
-      CFDictionaryGetValue(mutableClassMap, containingMessageClass);
+  CFMutableDictionaryRef extensionMap =
+      (CFMutableDictionaryRef)CFDictionaryGetValue(mutableClassMap, containingMessageClass);
   if (extensionMap == nil) {
     extensionMap = CFDictionaryCreateMutableCopy(kCFAllocatorDefault, 0, otherExtensionMap);
     CFDictionarySetValue(mutableClassMap, containingMessageClass, extensionMap);
diff --git a/objectivec/GPBFieldMask.pbobjc.h b/objectivec/GPBFieldMask.pbobjc.h
index c4667b4..3e7d349 100644
--- a/objectivec/GPBFieldMask.pbobjc.h
+++ b/objectivec/GPBFieldMask.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/field_mask.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -247,7 +248,7 @@
 
 /** The set of field mask paths. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *pathsArray;
-/** The number of items in @c pathsArray without causing the array to be created. */
+/** The number of items in @c pathsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger pathsArray_Count;
 
 @end
@@ -259,3 +260,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBFieldMask.pbobjc.m b/objectivec/GPBFieldMask.pbobjc.m
index ab25d3f..83edddf 100644
--- a/objectivec/GPBFieldMask.pbobjc.m
+++ b/objectivec/GPBFieldMask.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/field_mask.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -67,7 +68,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBFieldMask__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -82,3 +83,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBMessage.h b/objectivec/GPBMessage.h
index 01253a4..5b7ce0c 100644
--- a/objectivec/GPBMessage.h
+++ b/objectivec/GPBMessage.h
@@ -31,12 +31,12 @@
 #import <Foundation/Foundation.h>
 
 #import "GPBBootstrap.h"
+#import "GPBExtensionRegistry.h"
 
 @class GPBDescriptor;
 @class GPBCodedInputStream;
 @class GPBCodedOutputStream;
 @class GPBExtensionDescriptor;
-@class GPBExtensionRegistry;
 @class GPBFieldDescriptor;
 @class GPBUnknownFieldSet;
 
@@ -80,7 +80,7 @@
  *       @c +parseFromData:extensionRegistry:error: to provide an extension
  *       registry.
  **/
-@interface GPBMessage : NSObject<NSSecureCoding, NSCopying>
+@interface GPBMessage : NSObject <NSSecureCoding, NSCopying>
 
 // If you add an instance method/property to this class that may conflict with
 // fields declared in protos, you need to update objective_helpers.cc. The main
@@ -90,15 +90,13 @@
  * The set of unknown fields for this message.
  *
  * Only messages from proto files declared with "proto2" syntax support unknown
- * fields. For "proto3" syntax, any unknown fields found while parsing are
- * dropped.
+ * fields.
  **/
 @property(nonatomic, copy, nullable) GPBUnknownFieldSet *unknownFields;
 
 /**
  * Whether the message, along with all submessages, have the required fields
- * set. This is only applicable for files declared with "proto2" syntax, as
- * there are no required fields for "proto3" syntax.
+ * set.
  **/
 @property(nonatomic, readonly, getter=isInitialized) BOOL initialized;
 
@@ -147,7 +145,7 @@
  * @return A new instance of the generated class.
  **/
 + (nullable instancetype)parseFromData:(NSData *)data
-                     extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry
+                     extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
                                  error:(NSError **)errorPtr;
 
 /**
@@ -171,7 +169,7 @@
  **/
 + (nullable instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
                                  extensionRegistry:
-                                     (nullable GPBExtensionRegistry *)extensionRegistry
+                                     (nullable id<GPBExtensionRegistry>)extensionRegistry
                                              error:(NSError **)errorPtr;
 
 /**
@@ -196,7 +194,7 @@
  **/
 + (nullable instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
                                           extensionRegistry:
-                                              (nullable GPBExtensionRegistry *)extensionRegistry
+                                              (nullable id<GPBExtensionRegistry>)extensionRegistry
                                                       error:(NSError **)errorPtr;
 
 /**
@@ -239,7 +237,7 @@
  * @return An initialized instance of the generated class.
  **/
 - (nullable instancetype)initWithData:(NSData *)data
-                    extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry
+                    extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry
                                 error:(NSError **)errorPtr;
 
 /**
@@ -264,7 +262,7 @@
  **/
 - (nullable instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
                                 extensionRegistry:
-                                    (nullable GPBExtensionRegistry *)extensionRegistry
+                                    (nullable id<GPBExtensionRegistry>)extensionRegistry
                                             error:(NSError **)errorPtr;
 
 /**
@@ -278,7 +276,7 @@
  *                                         unsuccessful.
  **/
 - (void)mergeFromData:(NSData *)data
-    extensionRegistry:(nullable GPBExtensionRegistry *)extensionRegistry;
+    extensionRegistry:(nullable id<GPBExtensionRegistry>)extensionRegistry;
 
 /**
  * Merges the fields from another message (of the same type) into this
@@ -412,6 +410,12 @@
  * repeated fields. If the extension is a Message one will be auto created for
  * you and returned similar to fields.
  *
+ * NOTE: For Enum extensions, if the enum was _closed_, then unknown values
+ * were parsed into the message's unknown fields instead of ending up in the
+ * extensions, just like what happens with singular/repeated fields. For open
+ * enums, the _raw_ value will be in the NSNumber, meaning if one does a
+ * `switch` on the values, a `default` case should also be included.
+ *
  * @param extension The extension descriptor of the extension to fetch.
  *
  * @return The extension matching the given descriptor, or nil if none found.
@@ -427,8 +431,7 @@
  * @param extension The extension descriptor under which to set the value.
  * @param value     The value to be set as the extension.
  **/
-- (void)setExtension:(GPBExtensionDescriptor *)extension
-               value:(nullable id)value;
+- (void)setExtension:(GPBExtensionDescriptor *)extension value:(nullable id)value;
 
 /**
  * Adds the given value to the extension for this message. This only applies
@@ -449,9 +452,7 @@
  * @param index     The index of the extension to be replaced.
  * @param value     The value to be replaced in the repeated extension.
  **/
-- (void)setExtension:(GPBExtensionDescriptor *)extension
-               index:(NSUInteger)index
-               value:(id)value;
+- (void)setExtension:(GPBExtensionDescriptor *)extension index:(NSUInteger)index value:(id)value;
 
 /**
  * Clears the given extension for this message.
diff --git a/objectivec/GPBMessage.m b/objectivec/GPBMessage.m
index ee94dee..3342179 100644
--- a/objectivec/GPBMessage.m
+++ b/objectivec/GPBMessage.m
@@ -30,8 +30,9 @@
 
 #import "GPBMessage_PackagePrivate.h"
 
-#import <objc/runtime.h>
 #import <objc/message.h>
+#import <objc/runtime.h>
+#import <os/lock.h>
 #import <stdatomic.h>
 
 #import "GPBArray_PackagePrivate.h"
@@ -51,8 +52,7 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdirect-ivar-access"
 
-NSString *const GPBMessageErrorDomain =
-    GPBNSStringifySymbol(GPBMessageErrorDomain);
+NSString *const GPBMessageErrorDomain = GPBNSStringifySymbol(GPBMessageErrorDomain);
 
 NSString *const GPBErrorReasonKey = @"Reason";
 
@@ -71,8 +71,7 @@
  @package
   GPBUnknownFieldSet *unknownFields_;
   NSMutableDictionary *extensionMap_;
-  // Readonly access to autocreatedExtensionMap_ is protected via
-  // readOnlySemaphore_.
+  // Readonly access to autocreatedExtensionMap_ is protected via readOnlyLock_.
   NSMutableDictionary *autocreatedExtensionMap_;
 
   // If the object was autocreated, we remember the creator so that if we get
@@ -81,43 +80,39 @@
   GPBFieldDescriptor *autocreatorField_;
   GPBExtensionDescriptor *autocreatorExtension_;
 
-  // 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:
+  // Messages 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 lock.
+  //
+  // Long ago, this was an OSSpinLock, but then it came to light that there were issues for that on
+  // iOS:
   //   http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/
   //   https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html
-  // Use of readOnlySemaphore_ must be prefaced by a call to
-  // GPBPrepareReadOnlySemaphore to ensure it has been created. This allows
-  // readOnlySemaphore_ to be only created when actually needed.
-  _Atomic(dispatch_semaphore_t) readOnlySemaphore_;
+  // It was changed to a dispatch_semaphore_t, but that has potential for priority inversion issues.
+  // The minOS versions are now high enough that os_unfair_lock can be used, and should provide
+  // all the support we need. For more information in the concurrency/locking space see:
+  //   https://gist.github.com/tclementdev/6af616354912b0347cdf6db159c37057
+  //   https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html
+  //   https://developer.apple.com/videos/play/wwdc2017/706/
+  os_unfair_lock readOnlyLock_;
 }
 @end
 
-static id CreateArrayForField(GPBFieldDescriptor *field,
-                              GPBMessage *autocreator)
+static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator)
     __attribute__((ns_returns_retained));
-static id GetOrCreateArrayIvarWithField(GPBMessage *self,
-                                        GPBFieldDescriptor *field);
+static id GetOrCreateArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
 static id GetArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
-static id CreateMapForField(GPBFieldDescriptor *field,
-                            GPBMessage *autocreator)
+static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator)
     __attribute__((ns_returns_retained));
-static id GetOrCreateMapIvarWithField(GPBMessage *self,
-                                      GPBFieldDescriptor *field);
+static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
 static id GetMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
-static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
-                                              NSZone *zone)
+static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone)
     __attribute__((ns_returns_retained));
+static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self);
 
 #ifdef DEBUG
 static NSError *MessageError(NSInteger code, NSDictionary *userInfo) {
-  return [NSError errorWithDomain:GPBMessageErrorDomain
-                             code:code
-                         userInfo:userInfo];
+  return [NSError errorWithDomain:GPBMessageErrorDomain code:code userInfo:userInfo];
 }
 #endif
 
@@ -133,7 +128,7 @@
     NSString *reason = exception.reason;
     NSDictionary *userInfo = nil;
     if ([reason length]) {
-      userInfo = @{ GPBErrorReasonKey : reason };
+      userInfo = @{GPBErrorReasonKey : reason};
     }
 
     error = [NSError errorWithDomain:GPBMessageErrorDomain
@@ -143,24 +138,20 @@
   return error;
 }
 
-static void CheckExtension(GPBMessage *self,
-                           GPBExtensionDescriptor *extension) {
+static void CheckExtension(GPBMessage *self, GPBExtensionDescriptor *extension) {
   if (![self isKindOfClass:extension.containingMessageClass]) {
-    [NSException
-         raise:NSInvalidArgumentException
-        format:@"Extension %@ used on wrong class (%@ instead of %@)",
-               extension.singletonName,
-               [self class], extension.containingMessageClass];
+    [NSException raise:NSInvalidArgumentException
+                format:@"Extension %@ used on wrong class (%@ instead of %@)",
+                       extension.singletonName, [self class], extension.containingMessageClass];
   }
 }
 
-static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap,
-                                              NSZone *zone) {
+static NSMutableDictionary *CloneExtensionMap(NSDictionary *extensionMap, NSZone *zone) {
   if (extensionMap.count == 0) {
     return nil;
   }
-  NSMutableDictionary *result = [[NSMutableDictionary allocWithZone:zone]
-      initWithCapacity:extensionMap.count];
+  NSMutableDictionary *result =
+      [[NSMutableDictionary allocWithZone:zone] initWithCapacity:extensionMap.count];
 
   for (GPBExtensionDescriptor *extension in extensionMap) {
     id value = [extensionMap objectForKey:extension];
@@ -168,8 +159,7 @@
 
     if (extension.repeated) {
       if (isMessageExtension) {
-        NSMutableArray *list =
-            [[NSMutableArray alloc] initWithCapacity:[value count]];
+        NSMutableArray *list = [[NSMutableArray alloc] initWithCapacity:[value count]];
         for (GPBMessage *listValue in value) {
           GPBMessage *copiedValue = [listValue copyWithZone:zone];
           [list addObject:copiedValue];
@@ -196,8 +186,7 @@
   return result;
 }
 
-static id CreateArrayForField(GPBFieldDescriptor *field,
-                              GPBMessage *autocreator) {
+static id CreateArrayForField(GPBFieldDescriptor *field, GPBMessage *autocreator) {
   id result;
   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   switch (fieldDataType) {
@@ -230,8 +219,7 @@
       break;
 
     case GPBDataTypeEnum:
-      result = [[GPBEnumArray alloc]
-                  initWithValidationFunction:field.enumDescriptor.enumVerifier];
+      result = [[GPBEnumArray alloc] initWithValidationFunction:field.enumDescriptor.enumVerifier];
       break;
 
     case GPBDataTypeBytes:
@@ -249,7 +237,7 @@
   if (autocreator) {
     if (GPBDataTypeIsObject(fieldDataType)) {
       GPBAutocreatedArray *autoArray = result;
-      autoArray->_autocreator =  autocreator;
+      autoArray->_autocreator = autocreator;
     } else {
       GPBInt32Array *gpbArray = result;
       gpbArray->_autocreator = autocreator;
@@ -259,8 +247,7 @@
   return result;
 }
 
-static id CreateMapForField(GPBFieldDescriptor *field,
-                            GPBMessage *autocreator) {
+static id CreateMapForField(GPBFieldDescriptor *field, GPBMessage *autocreator) {
   id result;
   GPBDataType keyDataType = field.mapKeyDataType;
   GPBDataType valueDataType = GPBGetFieldDataType(field);
@@ -545,10 +532,9 @@
   }
 
   if (autocreator) {
-    if ((keyDataType == GPBDataTypeString) &&
-        GPBDataTypeIsObject(valueDataType)) {
+    if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
       GPBAutocreatedDictionary *autoDict = result;
-      autoDict->_autocreator =  autocreator;
+      autoDict->_autocreator = autocreator;
     } else {
       GPBInt32Int32Dictionary *gpbDict = result;
       gpbDict->_autocreator = autocreator;
@@ -570,8 +556,7 @@
 // repeated/map field parsed into the autorelease pool which is both a memory
 // and performance hit.
 
-static id GetOrCreateArrayIvarWithField(GPBMessage *self,
-                                        GPBFieldDescriptor *field) {
+static id GetOrCreateArrayIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
   id array = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   if (!array) {
     // No lock needed, this is called from places expecting to mutate
@@ -611,8 +596,7 @@
   return expected;
 }
 
-static id GetOrCreateMapIvarWithField(GPBMessage *self,
-                                      GPBFieldDescriptor *field) {
+static id GetOrCreateMapIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
   id dict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
   if (!dict) {
     // No lock needed, this is called from places expecting to mutate
@@ -641,8 +625,7 @@
   }
 
   // Some other thread set it, release the one created and return what got set.
-  if ((field.mapKeyDataType == GPBDataTypeString) &&
-      GPBFieldDataTypeIsObject(field)) {
+  if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
     GPBAutocreatedDictionary *autoDict = autocreated;
     autoDict->_autocreator = nil;
   } else {
@@ -655,8 +638,136 @@
 
 #endif  // !defined(__clang_analyzer__)
 
-GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
-                                            GPBMessage *autocreator,
+static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
+                                        GPBMessage *messageToGetExtension,
+                                        GPBCodedInputStream *input,
+                                        id<GPBExtensionRegistry> extensionRegistry,
+                                        GPBMessage *existingValue)
+    __attribute__((ns_returns_retained));
+
+// Note that this returns a retained value intentionally.
+static id NewSingleValueFromInputStream(GPBExtensionDescriptor *extension,
+                                        GPBMessage *messageToGetExtension,
+                                        GPBCodedInputStream *input,
+                                        id<GPBExtensionRegistry> extensionRegistry,
+                                        GPBMessage *existingValue) {
+  GPBExtensionDescription *description = extension->description_;
+  GPBCodedInputStreamState *state = &input->state_;
+  switch (description->dataType) {
+    case GPBDataTypeBool:
+      return [[NSNumber alloc] initWithBool:GPBCodedInputStreamReadBool(state)];
+    case GPBDataTypeFixed32:
+      return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadFixed32(state)];
+    case GPBDataTypeSFixed32:
+      return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSFixed32(state)];
+    case GPBDataTypeFloat:
+      return [[NSNumber alloc] initWithFloat:GPBCodedInputStreamReadFloat(state)];
+    case GPBDataTypeFixed64:
+      return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadFixed64(state)];
+    case GPBDataTypeSFixed64:
+      return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSFixed64(state)];
+    case GPBDataTypeDouble:
+      return [[NSNumber alloc] initWithDouble:GPBCodedInputStreamReadDouble(state)];
+    case GPBDataTypeInt32:
+      return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadInt32(state)];
+    case GPBDataTypeInt64:
+      return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadInt64(state)];
+    case GPBDataTypeSInt32:
+      return [[NSNumber alloc] initWithInt:GPBCodedInputStreamReadSInt32(state)];
+    case GPBDataTypeSInt64:
+      return [[NSNumber alloc] initWithLongLong:GPBCodedInputStreamReadSInt64(state)];
+    case GPBDataTypeUInt32:
+      return [[NSNumber alloc] initWithUnsignedInt:GPBCodedInputStreamReadUInt32(state)];
+    case GPBDataTypeUInt64:
+      return [[NSNumber alloc] initWithUnsignedLongLong:GPBCodedInputStreamReadUInt64(state)];
+    case GPBDataTypeBytes:
+      return GPBCodedInputStreamReadRetainedBytes(state);
+    case GPBDataTypeString:
+      return GPBCodedInputStreamReadRetainedString(state);
+    case GPBDataTypeEnum: {
+      int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
+      GPBEnumDescriptor *enumDescriptor = extension.enumDescriptor;
+      // If run with source generated before the closed enum support, all enums
+      // will be considers not closed, so casing to the enum type for a switch
+      // could cause things to fall off the end of a switch.
+      if (!enumDescriptor.isClosed || enumDescriptor.enumVerifier(val)) {
+        return [[NSNumber alloc] initWithInt:val];
+      } else {
+        GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(messageToGetExtension);
+        [unknownFields mergeVarintField:extension->description_->fieldNumber value:val];
+        return nil;
+      }
+    }
+    case GPBDataTypeGroup:
+    case GPBDataTypeMessage: {
+      GPBMessage *message;
+      if (existingValue) {
+        message = [existingValue retain];
+      } else {
+        GPBDescriptor *descriptor = [extension.msgClass descriptor];
+        message = [[descriptor.messageClass alloc] init];
+      }
+
+      if (description->dataType == GPBDataTypeGroup) {
+        [input readGroup:description->fieldNumber
+                      message:message
+            extensionRegistry:extensionRegistry];
+      } else {
+        // description->dataType == GPBDataTypeMessage
+        if (GPBExtensionIsWireFormat(description)) {
+          // For MessageSet fields the message length will have already been
+          // read.
+          [message mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
+        } else {
+          [input readMessage:message extensionRegistry:extensionRegistry];
+        }
+      }
+
+      return message;
+    }
+  }
+
+  return nil;
+}
+
+static void ExtensionMergeFromInputStream(GPBExtensionDescriptor *extension, BOOL isPackedOnStream,
+                                          GPBCodedInputStream *input,
+                                          id<GPBExtensionRegistry> extensionRegistry,
+                                          GPBMessage *message) {
+  GPBExtensionDescription *description = extension->description_;
+  GPBCodedInputStreamState *state = &input->state_;
+  if (isPackedOnStream) {
+    NSCAssert(GPBExtensionIsRepeated(description), @"How was it packed if it isn't repeated?");
+    int32_t length = GPBCodedInputStreamReadInt32(state);
+    size_t limit = GPBCodedInputStreamPushLimit(state, length);
+    while (GPBCodedInputStreamBytesUntilLimit(state) > 0) {
+      id value = NewSingleValueFromInputStream(extension, message, input, extensionRegistry, nil);
+      if (value) {
+        [message addExtension:extension value:value];
+        [value release];
+      }
+    }
+    GPBCodedInputStreamPopLimit(state, limit);
+  } else {
+    id existingValue = nil;
+    BOOL isRepeated = GPBExtensionIsRepeated(description);
+    if (!isRepeated && GPBDataTypeIsMessage(description->dataType)) {
+      existingValue = [message getExistingExtension:extension];
+    }
+    id value =
+        NewSingleValueFromInputStream(extension, message, input, extensionRegistry, existingValue);
+    if (value) {
+      if (isRepeated) {
+        [message addExtension:extension value:value];
+      } else {
+        [message setExtension:extension value:value];
+      }
+      [value release];
+    }
+  }
+}
+
+GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator,
                                             GPBFieldDescriptor *field) {
   GPBMessage *message = [[msgClass alloc] init];
   message->autocreator_ = autocreator;
@@ -664,13 +775,12 @@
   return message;
 }
 
-static GPBMessage *CreateMessageWithAutocreatorForExtension(
-    Class msgClass, GPBMessage *autocreator, GPBExtensionDescriptor *extension)
+static GPBMessage *CreateMessageWithAutocreatorForExtension(Class msgClass, GPBMessage *autocreator,
+                                                            GPBExtensionDescriptor *extension)
     __attribute__((ns_returns_retained));
 
-static GPBMessage *CreateMessageWithAutocreatorForExtension(
-    Class msgClass, GPBMessage *autocreator,
-    GPBExtensionDescriptor *extension) {
+static GPBMessage *CreateMessageWithAutocreatorForExtension(Class msgClass, GPBMessage *autocreator,
+                                                            GPBExtensionDescriptor *extension) {
   GPBMessage *message = [[msgClass alloc] init];
   message->autocreator_ = autocreator;
   message->autocreatorExtension_ = [extension retain];
@@ -689,8 +799,7 @@
     // This will recursively make all parent messages visible until it reaches a
     // super-creator that's visible.
     if (self->autocreatorField_) {
-      GPBSetObjectIvarWithFieldPrivate(self->autocreator_,
-                                        self->autocreatorField_, self);
+      GPBSetObjectIvarWithFieldPrivate(self->autocreator_, self->autocreatorField_, self);
     } else {
       [self->autocreator_ setExtension:self->autocreatorExtension_ value:self];
     }
@@ -726,8 +835,7 @@
     if (field.fieldType == GPBFieldTypeMap) {
       id curDict = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       if (curDict == dictionary) {
-        if ((field.mapKeyDataType == GPBDataTypeString) &&
-            GPBFieldDataTypeIsObject(field)) {
+        if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
           GPBAutocreatedDictionary *autoDict = dictionary;
           autoDict->_autocreator = nil;
         } else {
@@ -751,18 +859,15 @@
   // Either the autocreator must have its "has" flag set to YES, or it must be
   // NO and not equal to ourselves.
   BOOL autocreatorHas =
-      (self->autocreatorField_
-           ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_)
-           : [self->autocreator_ hasExtension:self->autocreatorExtension_]);
+      (self->autocreatorField_ ? GPBGetHasIvarField(self->autocreator_, self->autocreatorField_)
+                               : [self->autocreator_ hasExtension:self->autocreatorExtension_]);
   GPBMessage *autocreatorFieldValue =
       (self->autocreatorField_
-           ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_,
-                                                   self->autocreatorField_)
+           ? GPBGetObjectIvarWithFieldNoAutocreate(self->autocreator_, self->autocreatorField_)
            : [self->autocreator_->autocreatedExtensionMap_
                  objectForKey:self->autocreatorExtension_]);
   NSCAssert(autocreatorHas || autocreatorFieldValue != self,
-            @"Cannot clear autocreator because it still refers to self, self: %@.",
-            self);
+            @"Cannot clear autocreator because it still refers to self, self: %@.", self);
 
 #endif  // DEBUG && !defined(NS_BLOCK_ASSERTIONS)
 
@@ -773,31 +878,6 @@
   self->autocreatorExtension_ = nil;
 }
 
-// Call this before using the readOnlySemaphore_. This ensures it is created only once.
-void GPBPrepareReadOnlySemaphore(GPBMessage *self) {
-#pragma clang diagnostic push
-#pragma clang diagnostic ignored "-Wdirect-ivar-access"
-
-  // Create the semaphore on demand (rather than init) as developers might not cause them
-  // to be needed, and the heap usage can add up.  The atomic swap is used to avoid needing
-  // another lock around creating it.
-  if (self->readOnlySemaphore_ == nil) {
-    dispatch_semaphore_t worker = dispatch_semaphore_create(1);
-    dispatch_semaphore_t expected = nil;
-    if (!atomic_compare_exchange_strong(&self->readOnlySemaphore_, &expected, worker)) {
-      dispatch_release(worker);
-    }
-#if defined(__clang_analyzer__)
-    // The Xcode 9.2 (and 9.3 beta) static analyzer thinks worker is leaked
-    // (doesn't seem to know about atomic_compare_exchange_strong); so just
-    // for the analyzer, let it think worker is also released in this case.
-    else { dispatch_release(worker); }
-#endif
-  }
-
-#pragma clang diagnostic pop
-}
-
 static GPBUnknownFieldSet *GetOrMakeUnknownFields(GPBMessage *self) {
   if (!self->unknownFields_) {
     self->unknownFields_ = [[GPBUnknownFieldSet alloc] init];
@@ -848,9 +928,8 @@
   if (!descriptor) {
     // Use a dummy file that marks it as proto2 syntax so when used generically
     // it supports unknowns/etc.
-    fileDescriptor =
-        [[GPBFileDescriptor alloc] initWithPackage:@"internal"
-                                            syntax:GPBFileSyntaxProto2];
+    fileDescriptor = [[GPBFileDescriptor alloc] initWithPackage:@"internal"
+                                                         syntax:GPBFileSyntaxProto2];
 
     descriptor = [GPBDescriptor allocDescriptorForClass:[GPBMessage class]
                                               rootClass:Nil
@@ -869,8 +948,9 @@
 
 - (instancetype)init {
   if ((self = [super init])) {
-    messageStorage_ = (GPBMessage_StoragePtr)(
-        ((uint8_t *)self) + class_getInstanceSize([self class]));
+    messageStorage_ =
+        (GPBMessage_StoragePtr)(((uint8_t *)self) + class_getInstanceSize([self class]));
+    readOnlyLock_ = OS_UNFAIR_LOCK_INIT;
   }
 
   return self;
@@ -881,7 +961,7 @@
 }
 
 - (instancetype)initWithData:(NSData *)data
-           extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+           extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
                        error:(NSError **)errorPtr {
   if ((self = [self init])) {
     @try {
@@ -889,8 +969,7 @@
       if (errorPtr) {
         *errorPtr = nil;
       }
-    }
-    @catch (NSException *exception) {
+    } @catch (NSException *exception) {
       [self release];
       self = nil;
       if (errorPtr) {
@@ -911,8 +990,7 @@
 }
 
 - (instancetype)initWithCodedInputStream:(GPBCodedInputStream *)input
-                       extensionRegistry:
-                           (GPBExtensionRegistry *)extensionRegistry
+                       extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
                                    error:(NSError **)errorPtr {
   if ((self = [self init])) {
     @try {
@@ -920,8 +998,7 @@
       if (errorPtr) {
         *errorPtr = nil;
       }
-    }
-    @catch (NSException *exception) {
+    } @catch (NSException *exception) {
       [self release];
       self = nil;
       if (errorPtr) {
@@ -944,9 +1021,6 @@
 - (void)dealloc {
   [self internalClear:NO];
   NSCAssert(!autocreator_, @"Autocreator was not cleared before dealloc.");
-  if (readOnlySemaphore_) {
-    dispatch_release(readOnlySemaphore_);
-  }
   [super dealloc];
 }
 
@@ -979,13 +1053,11 @@
             if (field.mapKeyDataType == GPBDataTypeString) {
               // Map is an NSDictionary.
               NSDictionary *existingDict = value;
-              NSMutableDictionary *newDict = [[NSMutableDictionary alloc]
-                  initWithCapacity:existingDict.count];
+              NSMutableDictionary *newDict =
+                  [[NSMutableDictionary alloc] initWithCapacity:existingDict.count];
               newValue = newDict;
-              [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key,
-                                                                GPBMessage *msg,
-                                                                BOOL *stop) {
-#pragma unused(stop)
+              [existingDict enumerateKeysAndObjectsUsingBlock:^(NSString *key, GPBMessage *msg,
+                                                                __unused BOOL *stop) {
                 GPBMessage *copiedMsg = [msg copyWithZone:zone];
                 [newDict setObject:copiedMsg forKey:key];
                 [copiedMsg release];
@@ -1008,8 +1080,7 @@
               newValue = [value copyWithZone:zone];
             }
           } else {
-            if ((field.mapKeyDataType == GPBDataTypeString) &&
-                GPBFieldDataTypeIsObject(field)) {
+            if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
               // NSDictionary
               newValue = [value mutableCopyWithZone:zone];
             } else {
@@ -1041,8 +1112,7 @@
         id *typePtr = (id *)&storage[field->description_->offset];
         *typePtr = NULL;
       }
-    } else if (GPBFieldDataTypeIsObject(field) &&
-               GPBGetHasIvarField(self, field)) {
+    } else if (GPBFieldDataTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
       // A set string/data value (message picked off above), copy it.
       id value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       id newValue = [value copyWithZone:zone];
@@ -1093,8 +1163,7 @@
             }
           }
         } else {
-          if ((field.mapKeyDataType == GPBDataTypeString) &&
-              GPBFieldDataTypeIsObject(field)) {
+          if ((field.mapKeyDataType == GPBDataTypeString) && GPBFieldDataTypeIsObject(field)) {
             if ([arrayOrMap isKindOfClass:[GPBAutocreatedDictionary class]]) {
               GPBAutocreatedDictionary *autoDict = arrayOrMap;
               if (autoDict->_autocreator == self) {
@@ -1115,8 +1184,7 @@
       GPBClearAutocreatedMessageIvarWithField(self, field);
       GPBMessage *value = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
       [value release];
-    } else if (GPBFieldDataTypeIsObject(field) &&
-               GPBGetHasIvarField(self, field)) {
+    } else if (GPBFieldDataTypeIsObject(field) && GPBGetHasIvarField(self, field)) {
       id value = GPBGetObjectIvarWithField(self, field);
       [value release];
     }
@@ -1168,8 +1236,7 @@
             return NO;
           }
         } else {
-          NSAssert(field.isOptional,
-                   @"%@: Single message field %@ not required or optional?",
+          NSAssert(field.isOptional, @"%@: Single message field %@ not required or optional?",
                    [self class], field.name);
           if (GPBGetHasIvarField(self, field)) {
             GPBMessage *message = GPBGetMessageMessageField(self, field);
@@ -1187,15 +1254,13 @@
         }
       } else {  // fieldType == GPBFieldTypeMap
         if (field.mapKeyDataType == GPBDataTypeString) {
-          NSDictionary *map =
-              GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+          NSDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
           if (map && !GPBDictionaryIsInitializedInternalHelper(map, field)) {
             return NO;
           }
         } else {
           // Real type is GPB*ObjectDictionary, exact type doesn't matter.
-          GPBInt32ObjectDictionary *map =
-              GPBGetObjectIvarWithFieldNoAutocreate(self, field);
+          GPBInt32ObjectDictionary *map = GPBGetObjectIvarWithFieldNoAutocreate(self, field);
           if (map && ![map isInitialized]) {
             return NO;
           }
@@ -1206,9 +1271,7 @@
 
   __block BOOL result = YES;
   [extensionMap_
-      enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension,
-                                          id obj,
-                                          BOOL *stop) {
+      enumerateKeysAndObjectsUsingBlock:^(GPBExtensionDescriptor *extension, id obj, BOOL *stop) {
         if (GPBExtensionIsMessage(extension)) {
           if (extension.isRepeated) {
             for (GPBMessage *msg in obj) {
@@ -1241,18 +1304,15 @@
   }
 #endif
   NSMutableData *data = [NSMutableData dataWithLength:[self serializedSize]];
-  GPBCodedOutputStream *stream =
-      [[GPBCodedOutputStream alloc] initWithData:data];
+  GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data];
   @try {
     [self writeToCodedOutputStream:stream];
-  }
-  @catch (NSException *exception) {
+  } @catch (NSException *exception) {
     // This really shouldn't happen. The only way writeToCodedOutputStream:
     // could throw is if something in the library has a bug and the
     // serializedSize was wrong.
 #ifdef DEBUG
-    NSLog(@"%@: Internal exception while building message data: %@",
-          [self class], exception);
+    NSLog(@"%@: Internal exception while building message data: %@", [self class], exception);
 #endif
     data = nil;
   }
@@ -1263,20 +1323,17 @@
 - (NSData *)delimitedData {
   size_t serializedSize = [self serializedSize];
   size_t varintSize = GPBComputeRawVarint32SizeForInteger(serializedSize);
-  NSMutableData *data =
-      [NSMutableData dataWithLength:(serializedSize + varintSize)];
-  GPBCodedOutputStream *stream =
-      [[GPBCodedOutputStream alloc] initWithData:data];
+  NSMutableData *data = [NSMutableData dataWithLength:(serializedSize + varintSize)];
+  GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithData:data];
   @try {
     [self writeDelimitedToCodedOutputStream:stream];
-  }
-  @catch (NSException *exception) {
+  } @catch (NSException *exception) {
     // This really shouldn't happen.  The only way writeToCodedOutputStream:
     // could throw is if something in the library has a bug and the
     // serializedSize was wrong.
 #ifdef DEBUG
-    NSLog(@"%@: Internal exception while building message delimitedData: %@",
-          [self class], exception);
+    NSLog(@"%@: Internal exception while building message delimitedData: %@", [self class],
+          exception);
 #endif
     // If it happens, truncate.
     data.length = 0;
@@ -1286,8 +1343,7 @@
 }
 
 - (void)writeToOutputStream:(NSOutputStream *)output {
-  GPBCodedOutputStream *stream =
-      [[GPBCodedOutputStream alloc] initWithOutputStream:output];
+  GPBCodedOutputStream *stream = [[GPBCodedOutputStream alloc] initWithOutputStream:output];
   [self writeToCodedOutputStream:stream];
   [stream release];
 }
@@ -1322,8 +1378,7 @@
 }
 
 - (void)writeDelimitedToOutputStream:(NSOutputStream *)output {
-  GPBCodedOutputStream *codedOutput =
-      [[GPBCodedOutputStream alloc] initWithOutputStream:output];
+  GPBCodedOutputStream *codedOutput = [[GPBCodedOutputStream alloc] initWithOutputStream:output];
   [self writeDelimitedToCodedOutputStream:codedOutput];
   [codedOutput release];
 }
@@ -1333,8 +1388,7 @@
   [self writeToCodedOutputStream:output];
 }
 
-- (void)writeField:(GPBFieldDescriptor *)field
-    toCodedOutputStream:(GPBCodedOutputStream *)output {
+- (void)writeField:(GPBFieldDescriptor *)field toCodedOutputStream:(GPBCodedOutputStream *)output {
   GPBFieldType fieldType = field.fieldType;
   if (fieldType == GPBFieldTypeSingle) {
     BOOL has = GPBGetHasIvarField(self, field);
@@ -1344,6 +1398,9 @@
   }
   uint32_t fieldNumber = GPBFieldNumber(field);
 
+  switch (GPBGetFieldDataType(field)) {
+      // clang-format off
+
 //%PDDM-DEFINE FIELD_CASE(TYPE, REAL_TYPE)
 //%FIELD_CASE_FULL(TYPE, REAL_TYPE, REAL_TYPE)
 //%PDDM-DEFINE FIELD_CASE_FULL(TYPE, REAL_TYPE, ARRAY_TYPE)
@@ -1386,12 +1443,8 @@
 //%      }
 //%      break;
 //%
-
-  switch (GPBGetFieldDataType(field)) {
-
 //%PDDM-EXPAND FIELD_CASE(Bool, Bool)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeBool:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1410,10 +1463,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(Fixed32, UInt32)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeFixed32:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1432,10 +1483,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(SFixed32, Int32)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeSFixed32:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1454,10 +1503,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(Float, Float)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeFloat:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1476,10 +1523,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(Fixed64, UInt64)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeFixed64:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1498,10 +1543,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(SFixed64, Int64)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeSFixed64:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1520,10 +1563,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(Double, Double)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeDouble:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1542,10 +1583,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(Int32, Int32)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeInt32:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1564,10 +1603,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(Int64, Int64)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeInt64:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1586,10 +1623,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(SInt32, Int32)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeSInt32:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1608,10 +1643,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(SInt64, Int64)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeSInt64:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1630,10 +1663,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(UInt32, UInt32)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeUInt32:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1652,10 +1683,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE(UInt64, UInt64)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeUInt64:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1674,10 +1703,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE_FULL(Enum, Int32, Enum)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeEnum:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1696,10 +1723,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE2(Bytes)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeBytes:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1722,10 +1747,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE2(String)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeString:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1748,10 +1771,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE2(Message)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeMessage:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1774,10 +1795,8 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND FIELD_CASE2(Group)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
     case GPBDataTypeGroup:
       if (fieldType == GPBFieldTypeRepeated) {
@@ -1800,8 +1819,9 @@
       }
       break;
 
-// clang-format on
 //%PDDM-EXPAND-END (18 expansions)
+
+// clang-format off
   }
 }
 
@@ -1824,8 +1844,7 @@
   }
 
   // Check for an autocreated value.
-  GPBPrepareReadOnlySemaphore(self);
-  dispatch_semaphore_wait(readOnlySemaphore_, DISPATCH_TIME_FOREVER);
+  os_unfair_lock_lock(&readOnlyLock_);
   value = [autocreatedExtensionMap_ objectForKey:extension];
   if (!value) {
     // Auto create the message extensions to match normal fields.
@@ -1842,7 +1861,7 @@
     [value release];
   }
 
-  dispatch_semaphore_signal(readOnlySemaphore_);
+  os_unfair_lock_unlock(&readOnlyLock_);
   return value;
 }
 
@@ -1973,7 +1992,7 @@
 #pragma mark - mergeFrom
 
 - (void)mergeFromData:(NSData *)data
-    extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+    extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
   GPBCodedInputStream *input = [[GPBCodedInputStream alloc] initWithData:data];
   [self mergeFromCodedInputStream:input extensionRegistry:extensionRegistry];
   [input checkLastTagWas:0];
@@ -1983,7 +2002,7 @@
 #pragma mark - mergeDelimitedFrom
 
 - (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
-                         extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+                         extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
   GPBCodedInputStreamState *state = &input->state_;
   if (GPBCodedInputStreamIsAtEnd(state)) {
     return;
@@ -2003,7 +2022,7 @@
 }
 
 + (instancetype)parseFromData:(NSData *)data
-            extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+            extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
                         error:(NSError **)errorPtr {
   return [[[self alloc] initWithData:data
                    extensionRegistry:extensionRegistry
@@ -2011,7 +2030,7 @@
 }
 
 + (instancetype)parseFromCodedInputStream:(GPBCodedInputStream *)input
-                        extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+                        extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
                                     error:(NSError **)errorPtr {
   return
       [[[self alloc] initWithCodedInputStream:input
@@ -2023,7 +2042,7 @@
 
 + (instancetype)parseDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
                                  extensionRegistry:
-                                     (GPBExtensionRegistry *)extensionRegistry
+                                     (id<GPBExtensionRegistry>)extensionRegistry
                                              error:(NSError **)errorPtr {
   GPBMessage *message = [[[self alloc] init] autorelease];
   @try {
@@ -2065,7 +2084,7 @@
 }
 
 - (void)parseMessageSet:(GPBCodedInputStream *)input
-      extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+      extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
   uint32_t typeId = 0;
   NSData *rawBytes = nil;
   GPBExtensionDescriptor *extension = nil;
@@ -2098,11 +2117,11 @@
     if (extension != nil) {
       GPBCodedInputStream *newInput =
           [[GPBCodedInputStream alloc] initWithData:rawBytes];
-      GPBExtensionMergeFromInputStream(extension,
-                                       extension.packable,
-                                       newInput,
-                                       extensionRegistry,
-                                       self);
+      ExtensionMergeFromInputStream(extension,
+                                    extension.packable,
+                                    newInput,
+                                    extensionRegistry,
+                                    self);
       [newInput release];
     } else {
       GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
@@ -2117,7 +2136,7 @@
 }
 
 - (BOOL)parseUnknownField:(GPBCodedInputStream *)input
-        extensionRegistry:(GPBExtensionRegistry *)extensionRegistry
+        extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry
                       tag:(uint32_t)tag {
   GPBWireFormat wireType = GPBWireFormatGetTagWireType(tag);
   int32_t fieldNumber = GPBWireFormatGetTagFieldNumber(tag);
@@ -2133,11 +2152,11 @@
     }
   } else {
     if (extension.wireType == wireType) {
-      GPBExtensionMergeFromInputStream(extension,
-                                       extension.packable,
-                                       input,
-                                       extensionRegistry,
-                                       self);
+      ExtensionMergeFromInputStream(extension,
+                                    extension.packable,
+                                    input,
+                                    extensionRegistry,
+                                    self);
       return YES;
     }
     // Primitive, repeated types can be packed on unpacked on the wire, and are
@@ -2145,11 +2164,11 @@
     if ([extension isRepeated] &&
         !GPBDataTypeIsObject(extension->description_->dataType) &&
         (extension.alternateWireType == wireType)) {
-      GPBExtensionMergeFromInputStream(extension,
-                                       !extension.packable,
-                                       input,
-                                       extensionRegistry,
-                                       self);
+      ExtensionMergeFromInputStream(extension,
+                                    !extension.packable,
+                                    input,
+                                    extensionRegistry,
+                                    self);
       return YES;
     }
   }
@@ -2169,8 +2188,8 @@
 #pragma mark - MergeFromCodedInputStream Support
 
 static void MergeSingleFieldFromCodedInputStream(
-    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
-    GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
+    GPBMessage *self, GPBFieldDescriptor *field,
+    GPBCodedInputStream *input, id<GPBExtensionRegistry>extensionRegistry) {
   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   switch (fieldDataType) {
 #define CASE_SINGLE_POD(NAME, TYPE, FUNC_TYPE)                             \
@@ -2239,8 +2258,7 @@
 
     case GPBDataTypeEnum: {
       int32_t val = GPBCodedInputStreamReadEnum(&input->state_);
-      if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
-          [field isValidEnumValue:val]) {
+      if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
         GPBSetInt32IvarWithFieldPrivate(self, field, val);
       } else {
         GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
@@ -2251,7 +2269,7 @@
 }
 
 static void MergeRepeatedPackedFieldFromCodedInputStream(
-    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
+    GPBMessage *self, GPBFieldDescriptor *field,
     GPBCodedInputStream *input) {
   GPBDataType fieldDataType = GPBGetFieldDataType(field);
   GPBCodedInputStreamState *state = &input->state_;
@@ -2290,8 +2308,7 @@
 
       case GPBDataTypeEnum: {
         int32_t val = GPBCodedInputStreamReadEnum(state);
-        if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
-            [field isValidEnumValue:val]) {
+        if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
           [(GPBEnumArray*)genericArray addRawValue:val];
         } else {
           GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
@@ -2305,8 +2322,8 @@
 }
 
 static void MergeRepeatedNotPackedFieldFromCodedInputStream(
-    GPBMessage *self, GPBFieldDescriptor *field, GPBFileSyntax syntax,
-    GPBCodedInputStream *input, GPBExtensionRegistry *extensionRegistry) {
+    GPBMessage *self, GPBFieldDescriptor *field,
+    GPBCodedInputStream *input, id<GPBExtensionRegistry>extensionRegistry) {
   GPBCodedInputStreamState *state = &input->state_;
   id genericArray = GetOrCreateArrayIvarWithField(self, field);
   switch (GPBGetFieldDataType(field)) {
@@ -2358,8 +2375,7 @@
     }
     case GPBDataTypeEnum: {
       int32_t val = GPBCodedInputStreamReadEnum(state);
-      if (GPBHasPreservingUnknownEnumSemantics(syntax) ||
-          [field isValidEnumValue:val]) {
+      if (!GPBFieldIsClosedEnum(field) || [field isValidEnumValue:val]) {
         [(GPBEnumArray*)genericArray addRawValue:val];
       } else {
         GPBUnknownFieldSet *unknownFields = GetOrMakeUnknownFields(self);
@@ -2371,9 +2387,8 @@
 }
 
 - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
-                extensionRegistry:(GPBExtensionRegistry *)extensionRegistry {
+                extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry {
   GPBDescriptor *descriptor = [self descriptor];
-  GPBFileSyntax syntax = descriptor.file.syntax;
   GPBCodedInputStreamState *state = &input->state_;
   uint32_t tag = 0;
   NSUInteger startingIndex = 0;
@@ -2391,7 +2406,7 @@
       if (GPBFieldTag(fieldDescriptor) == tag) {
         GPBFieldType fieldType = fieldDescriptor.fieldType;
         if (fieldType == GPBFieldTypeSingle) {
-          MergeSingleFieldFromCodedInputStream(self, fieldDescriptor, syntax,
+          MergeSingleFieldFromCodedInputStream(self, fieldDescriptor,
                                                input, extensionRegistry);
           // Well formed protos will only have a single field once, advance
           // the starting index to the next field.
@@ -2399,13 +2414,13 @@
         } else if (fieldType == GPBFieldTypeRepeated) {
           if (fieldDescriptor.isPackable) {
             MergeRepeatedPackedFieldFromCodedInputStream(
-                self, fieldDescriptor, syntax, input);
+                self, fieldDescriptor, input);
             // Well formed protos will only have a repeated field that is
             // packed once, advance the starting index to the next field.
             startingIndex += 1;
           } else {
             MergeRepeatedNotPackedFieldFromCodedInputStream(
-                self, fieldDescriptor, syntax, input, extensionRegistry);
+                self, fieldDescriptor, input, extensionRegistry);
           }
         } else {  // fieldType == GPBFieldTypeMap
           // GPB*Dictionary or NSDictionary, exact type doesn't matter at this
@@ -2436,13 +2451,13 @@
           BOOL alternateIsPacked = !fieldDescriptor.isPackable;
           if (alternateIsPacked) {
             MergeRepeatedPackedFieldFromCodedInputStream(
-                self, fieldDescriptor, syntax, input);
+                self, fieldDescriptor, input);
             // Well formed protos will only have a repeated field that is
             // packed once, advance the starting index to the next field.
             startingIndex += 1;
           } else {
             MergeRepeatedNotPackedFieldFromCodedInputStream(
-                self, fieldDescriptor, syntax, input, extensionRegistry);
+                self, fieldDescriptor, input, extensionRegistry);
           }
           merged = YES;
           break;
@@ -2991,8 +3006,7 @@
 #define CASE_REPEATED_POD_EXTRA(NAME, TYPE, ARRAY_TYPE, ARRAY_ACCESSOR_NAME)  \
         case GPBDataType##NAME: {                                             \
           GPB##ARRAY_TYPE##Array *array = genericArray;                       \
-          [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) { \
-            _Pragma("unused(idx, stop)");                                     \
+          [array enumerate##ARRAY_ACCESSOR_NAME##ValuesWithBlock:^(TYPE value, __unused NSUInteger idx, __unused BOOL *stop) { \
             dataSize += GPBCompute##NAME##SizeNoTag(value);                   \
           }];                                                                 \
           break;                                                              \
diff --git a/objectivec/GPBMessage_PackagePrivate.h b/objectivec/GPBMessage_PackagePrivate.h
index ca10983..70b47a5 100644
--- a/objectivec/GPBMessage_PackagePrivate.h
+++ b/objectivec/GPBMessage_PackagePrivate.h
@@ -78,13 +78,12 @@
 // or zero for EOF.
 // NOTE: This will throw if there is an error while parsing.
 - (void)mergeFromCodedInputStream:(GPBCodedInputStream *)input
-                extensionRegistry:(GPBExtensionRegistry *)extensionRegistry;
+                extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry;
 
 // Parses the next delimited message of this type from the input and merges it
 // with this message.
 - (void)mergeDelimitedFromCodedInputStream:(GPBCodedInputStream *)input
-                         extensionRegistry:
-                             (GPBExtensionRegistry *)extensionRegistry;
+                         extensionRegistry:(id<GPBExtensionRegistry>)extensionRegistry;
 
 - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data;
 
@@ -92,14 +91,12 @@
 
 CF_EXTERN_C_BEGIN
 
-
 // Call this before using the readOnlySemaphore_. This ensures it is created only once.
 void GPBPrepareReadOnlySemaphore(GPBMessage *self);
 
 // Returns a new instance that was automatically created by |autocreator| for
 // its field |field|.
-GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass,
-                                            GPBMessage *autocreator,
+GPBMessage *GPBCreateMessageWithAutocreator(Class msgClass, GPBMessage *autocreator,
                                             GPBFieldDescriptor *field)
     __attribute__((ns_returns_retained));
 
diff --git a/objectivec/GPBProtocolBuffers.h b/objectivec/GPBProtocolBuffers.h
index 619c082..e5f4713 100644
--- a/objectivec/GPBProtocolBuffers.h
+++ b/objectivec/GPBProtocolBuffers.h
@@ -28,7 +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.
 
+// clang-format off
 #import "GPBBootstrap.h"
+// clang-format on
 
 #import "GPBArray.h"
 #import "GPBCodedInputStream.h"
diff --git a/objectivec/GPBProtocolBuffers.m b/objectivec/GPBProtocolBuffers.m
index 0545ae9..c2833c5 100644
--- a/objectivec/GPBProtocolBuffers.m
+++ b/objectivec/GPBProtocolBuffers.m
@@ -31,7 +31,6 @@
 // If you want to build protocol buffers in your own project without adding the
 // project dependency, you can just add this file.
 
-
 // This warning seems to treat code differently when it is #imported than when
 // it is inline in the file.  GPBDictionary.m compiles cleanly in other targets,
 // but when #imported here it triggers a bunch of warnings that don't make
diff --git a/objectivec/GPBProtocolBuffers_RuntimeSupport.h b/objectivec/GPBProtocolBuffers_RuntimeSupport.h
index 04dde62..804a68a 100644
--- a/objectivec/GPBProtocolBuffers_RuntimeSupport.h
+++ b/objectivec/GPBProtocolBuffers_RuntimeSupport.h
@@ -31,7 +31,9 @@
 // This header is meant to only be used by the generated source, it should not
 // be included in code using protocol buffers.
 
+// clang-format off
 #import "GPBBootstrap.h"
+// clang-format on
 
 #import "GPBDescriptor_PackagePrivate.h"
 #import "GPBExtensionInternals.h"
diff --git a/objectivec/GPBRootObject.m b/objectivec/GPBRootObject.m
index bad2f9a..d013b2d 100644
--- a/objectivec/GPBRootObject.m
+++ b/objectivec/GPBRootObject.m
@@ -31,6 +31,7 @@
 #import "GPBRootObject_PackagePrivate.h"
 
 #import <objc/runtime.h>
+#import <os/lock.h>
 
 #import <CoreFoundation/CoreFoundation.h>
 
@@ -73,26 +74,19 @@
 // to worry about deallocation. All of the items are added to it at
 // startup, and so the keys don't need to be retained/released.
 // Keys are NULL terminated char *.
-static const void *GPBRootExtensionKeyRetain(CFAllocatorRef allocator,
-                                             const void *value) {
-#pragma unused(allocator)
+static const void *GPBRootExtensionKeyRetain(__unused CFAllocatorRef allocator, const void *value) {
   return value;
 }
 
-static void GPBRootExtensionKeyRelease(CFAllocatorRef allocator,
-                                       const void *value) {
-#pragma unused(allocator)
-#pragma unused(value)
-}
+static void GPBRootExtensionKeyRelease(__unused CFAllocatorRef allocator,
+                                       __unused const void *value) {}
 
 static CFStringRef GPBRootExtensionCopyKeyDescription(const void *value) {
   const char *key = (const char *)value;
-  return CFStringCreateWithCString(kCFAllocatorDefault, key,
-                                   kCFStringEncodingUTF8);
+  return CFStringCreateWithCString(kCFAllocatorDefault, key, kCFStringEncodingUTF8);
 }
 
-static Boolean GPBRootExtensionKeyEqual(const void *value1,
-                                        const void *value2) {
+static Boolean GPBRootExtensionKeyEqual(const void *value1, const void *value2) {
   const char *key1 = (const char *)value1;
   const char *key2 = (const char *)value2;
   return strcmp(key1, key2) == 0;
@@ -103,31 +97,34 @@
   return jenkins_one_at_a_time_hash(key);
 }
 
-// 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:
+// Long ago, this was an OSSpinLock, but then it came to light that there were issues for that on
+// iOS:
 //   http://mjtsai.com/blog/2015/12/16/osspinlock-is-unsafe/
 //   https://lists.swift.org/pipermail/swift-dev/Week-of-Mon-20151214/000372.html
-static dispatch_semaphore_t gExtensionSingletonDictionarySemaphore;
+// It was changed to a dispatch_semaphore_t, but that has potential for priority inversion issues.
+// The minOS versions are now high enough that os_unfair_lock can be used, and should provide
+// all the support we need. For more information in the concurrency/locking space see:
+//   https://gist.github.com/tclementdev/6af616354912b0347cdf6db159c37057
+//   https://developer.apple.com/library/archive/documentation/Performance/Conceptual/EnergyGuide-iOS/PrioritizeWorkWithQoS.html
+//   https://developer.apple.com/videos/play/wwdc2017/706/
+static os_unfair_lock gExtensionSingletonDictionaryLock = OS_UNFAIR_LOCK_INIT;
 static CFMutableDictionaryRef gExtensionSingletonDictionary = NULL;
 static GPBExtensionRegistry *gDefaultExtensionRegistry = NULL;
 
 + (void)initialize {
   // Ensure the global is started up.
   if (!gExtensionSingletonDictionary) {
-    gExtensionSingletonDictionarySemaphore = dispatch_semaphore_create(1);
     CFDictionaryKeyCallBacks keyCallBacks = {
-      // See description above for reason for using custom dictionary.
-      0,
-      GPBRootExtensionKeyRetain,
-      GPBRootExtensionKeyRelease,
-      GPBRootExtensionCopyKeyDescription,
-      GPBRootExtensionKeyEqual,
-      GPBRootExtensionKeyHash,
+        // See description above for reason for using custom dictionary.
+        0,
+        GPBRootExtensionKeyRetain,
+        GPBRootExtensionKeyRelease,
+        GPBRootExtensionCopyKeyDescription,
+        GPBRootExtensionKeyEqual,
+        GPBRootExtensionKeyHash,
     };
-    gExtensionSingletonDictionary =
-        CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks,
-                                  &kCFTypeDictionaryValueCallBacks);
+    gExtensionSingletonDictionary = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &keyCallBacks,
+                                                              &kCFTypeDictionaryValueCallBacks);
     gDefaultExtensionRegistry = [[GPBExtensionRegistry alloc] init];
   }
 
@@ -147,10 +144,9 @@
 
 + (void)globallyRegisterExtension:(GPBExtensionDescriptor *)field {
   const char *key = [field singletonNameC];
-  dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore,
-                          DISPATCH_TIME_FOREVER);
+  os_unfair_lock_lock(&gExtensionSingletonDictionaryLock);
   CFDictionarySetValue(gExtensionSingletonDictionary, key, field);
-  dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore);
+  os_unfair_lock_unlock(&gExtensionSingletonDictionaryLock);
 }
 
 static id ExtensionForName(id self, SEL _cmd) {
@@ -182,21 +178,20 @@
   key[classNameLen + 1 + selNameLen] = '\0';
 
   // NOTE: Even though this method is called from another C function,
-  // gExtensionSingletonDictionarySemaphore and gExtensionSingletonDictionary
+  // gExtensionSingletonDictionaryLock and gExtensionSingletonDictionary
   // will always be initialized. This is because this call flow is just to
   // lookup the Extension, meaning the code is calling an Extension class
   // message on a Message or Root class. This guarantees that the class was
   // initialized and Message classes ensure their Root was also initialized.
   NSAssert(gExtensionSingletonDictionary, @"Startup order broken!");
 
-  dispatch_semaphore_wait(gExtensionSingletonDictionarySemaphore,
-                          DISPATCH_TIME_FOREVER);
+  os_unfair_lock_lock(&gExtensionSingletonDictionaryLock);
   id extension = (id)CFDictionaryGetValue(gExtensionSingletonDictionary, key);
   // We can't remove the key from the dictionary here (as an optimization),
   // two threads could have gone into +resolveClassMethod: for the same method,
   // and ended up here; there's no way to ensure both return YES without letting
   // both try to wire in the method.
-  dispatch_semaphore_signal(gExtensionSingletonDictionarySemaphore);
+  os_unfair_lock_unlock(&gExtensionSingletonDictionaryLock);
   return extension;
 }
 
@@ -212,11 +207,9 @@
   // file.
   id extension = ExtensionForName(self, sel);
   if (extension != nil) {
-    const char *encoding =
-        GPBMessageEncodingForSelector(@selector(getClassValue), NO);
+    const char *encoding = GPBMessageEncodingForSelector(@selector(getClassValue), NO);
     Class metaClass = objc_getMetaClass(class_getName(self));
-    IMP imp = imp_implementationWithBlock(^(id obj) {
-#pragma unused(obj)
+    IMP imp = imp_implementationWithBlock(^(__unused id obj) {
       return extension;
     });
     BOOL methodAdded = class_addMethod(metaClass, sel, imp, encoding);
@@ -234,7 +227,6 @@
   return NO;
 }
 
-
 + (BOOL)resolveClassMethod:(SEL)sel {
   if (GPBResolveExtensionClassMethod(self, sel)) {
     return YES;
diff --git a/objectivec/GPBSourceContext.pbobjc.h b/objectivec/GPBSourceContext.pbobjc.h
index b17fec0..a55939a 100644
--- a/objectivec/GPBSourceContext.pbobjc.h
+++ b/objectivec/GPBSourceContext.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/source_context.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -63,3 +64,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBSourceContext.pbobjc.m b/objectivec/GPBSourceContext.pbobjc.m
index 376d442..cc8bb0b 100644
--- a/objectivec/GPBSourceContext.pbobjc.m
+++ b/objectivec/GPBSourceContext.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/source_context.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -67,7 +68,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBSourceContext__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -82,3 +83,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBStruct.pbobjc.h b/objectivec/GPBStruct.pbobjc.h
index dd6ab28..9bedafc 100644
--- a/objectivec/GPBStruct.pbobjc.h
+++ b/objectivec/GPBStruct.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/struct.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -87,7 +88,7 @@
 
 /** Unordered map of dynamically typed values. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableDictionary<NSString*, GPBValue*> *fields;
-/** The number of items in @c fields without causing the array to be created. */
+/** The number of items in @c fields without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger fields_Count;
 
 @end
@@ -178,7 +179,7 @@
 
 /** Repeated field of dynamically typed values. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBValue*> *valuesArray;
-/** The number of items in @c valuesArray without causing the array to be created. */
+/** The number of items in @c valuesArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger valuesArray_Count;
 
 @end
@@ -190,3 +191,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBStruct.pbobjc.m b/objectivec/GPBStruct.pbobjc.m
index 726cfb8..9aa14da 100644
--- a/objectivec/GPBStruct.pbobjc.m
+++ b/objectivec/GPBStruct.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/struct.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -60,7 +61,8 @@
                                        valueNames:valueNames
                                            values:values
                                             count:(uint32_t)(sizeof(values) / sizeof(int32_t))
-                                     enumVerifier:GPBNullValue_IsValidValue];
+                                     enumVerifier:GPBNullValue_IsValidValue
+                                            flags:GPBEnumDescriptorInitializationFlag_None];
     GPBEnumDescriptor *expected = nil;
     if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
       [worker release];
@@ -112,7 +114,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBStruct__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -212,7 +214,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     static const char *oneofs[] = {
       "kind",
     };
@@ -280,7 +282,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBListValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -295,3 +297,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBTimestamp.pbobjc.h b/objectivec/GPBTimestamp.pbobjc.h
index 8203383..a374a0a 100644
--- a/objectivec/GPBTimestamp.pbobjc.h
+++ b/objectivec/GPBTimestamp.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/timestamp.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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,7 +95,6 @@
  *     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
  *         .setNanos((int) ((millis % 1000) * 1000000)).build();
  *
- *
  * Example 5: Compute Timestamp from Java `Instant.now()`.
  *
  *     Instant now = Instant.now();
@@ -103,7 +103,6 @@
  *         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
  *             .setNanos(now.getNano()).build();
  *
- *
  * Example 6: Compute Timestamp from current time in Python.
  *
  *     timestamp = Timestamp()
@@ -162,3 +161,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBTimestamp.pbobjc.m b/objectivec/GPBTimestamp.pbobjc.m
index 72d348f..81bdcd9 100644
--- a/objectivec/GPBTimestamp.pbobjc.m
+++ b/objectivec/GPBTimestamp.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/timestamp.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -78,7 +79,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBTimestamp__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -93,3 +94,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBType.pbobjc.h b/objectivec/GPBType.pbobjc.h
index b023050..6eb1d04 100644
--- a/objectivec/GPBType.pbobjc.h
+++ b/objectivec/GPBType.pbobjc.h
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/type.proto
 
 #import "GPBDescriptor.h"
@@ -7,10 +8,10 @@
 #import "GPBAny.pbobjc.h"
 #import "GPBSourceContext.pbobjc.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -195,17 +196,17 @@
 
 /** The list of fields. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBField*> *fieldsArray;
-/** The number of items in @c fieldsArray without causing the array to be created. */
+/** The number of items in @c fieldsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger fieldsArray_Count;
 
 /** The list of types appearing in `oneof` definitions in this type. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<NSString*> *oneofsArray;
-/** The number of items in @c oneofsArray without causing the array to be created. */
+/** The number of items in @c oneofsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger oneofsArray_Count;
 
 /** The protocol buffer options. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/** The number of items in @c optionsArray without causing the array to be created. */
+/** The number of items in @c optionsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 /** The source context. */
@@ -279,7 +280,7 @@
 
 /** The protocol buffer options. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/** The number of items in @c optionsArray without causing the array to be created. */
+/** The number of items in @c optionsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 /** The field JSON name. */
@@ -334,12 +335,12 @@
 
 /** Enum value definitions. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBEnumValue*> *enumvalueArray;
-/** The number of items in @c enumvalueArray without causing the array to be created. */
+/** The number of items in @c enumvalueArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger enumvalueArray_Count;
 
 /** Protocol buffer options. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/** The number of items in @c optionsArray without causing the array to be created. */
+/** The number of items in @c optionsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 /** The source context. */
@@ -385,7 +386,7 @@
 
 /** Protocol buffer options. */
 @property(nonatomic, readwrite, strong, null_resettable) NSMutableArray<GPBOption*> *optionsArray;
-/** The number of items in @c optionsArray without causing the array to be created. */
+/** The number of items in @c optionsArray without causing the container to be created. */
 @property(nonatomic, readonly) NSUInteger optionsArray_Count;
 
 @end
@@ -430,3 +431,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBType.pbobjc.m b/objectivec/GPBType.pbobjc.m
index f5fc1ef..7a4b657 100644
--- a/objectivec/GPBType.pbobjc.m
+++ b/objectivec/GPBType.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/type.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -62,7 +63,8 @@
                                        valueNames:valueNames
                                            values:values
                                             count:(uint32_t)(sizeof(values) / sizeof(int32_t))
-                                     enumVerifier:GPBSyntax_IsValidValue];
+                                     enumVerifier:GPBSyntax_IsValidValue
+                                            flags:GPBEnumDescriptorInitializationFlag_None];
     GPBEnumDescriptor *expected = nil;
     if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
       [worker release];
@@ -81,6 +83,122 @@
   }
 }
 
+#pragma mark - Enum GPBField_Kind
+
+GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) {
+  static _Atomic(GPBEnumDescriptor*) descriptor = nil;
+  if (!descriptor) {
+    static const char *valueNames =
+        "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt"
+        "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type"
+        "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty"
+        "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000"
+        "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ"
+        "eSint64\000";
+    static const int32_t values[] = {
+        GPBField_Kind_TypeUnknown,
+        GPBField_Kind_TypeDouble,
+        GPBField_Kind_TypeFloat,
+        GPBField_Kind_TypeInt64,
+        GPBField_Kind_TypeUint64,
+        GPBField_Kind_TypeInt32,
+        GPBField_Kind_TypeFixed64,
+        GPBField_Kind_TypeFixed32,
+        GPBField_Kind_TypeBool,
+        GPBField_Kind_TypeString,
+        GPBField_Kind_TypeGroup,
+        GPBField_Kind_TypeMessage,
+        GPBField_Kind_TypeBytes,
+        GPBField_Kind_TypeUint32,
+        GPBField_Kind_TypeEnum,
+        GPBField_Kind_TypeSfixed32,
+        GPBField_Kind_TypeSfixed64,
+        GPBField_Kind_TypeSint32,
+        GPBField_Kind_TypeSint64,
+    };
+    GPBEnumDescriptor *worker =
+        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind)
+                                       valueNames:valueNames
+                                           values:values
+                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
+                                     enumVerifier:GPBField_Kind_IsValidValue
+                                            flags:GPBEnumDescriptorInitializationFlag_None];
+    GPBEnumDescriptor *expected = nil;
+    if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
+      [worker release];
+    }
+  }
+  return descriptor;
+}
+
+BOOL GPBField_Kind_IsValidValue(int32_t value__) {
+  switch (value__) {
+    case GPBField_Kind_TypeUnknown:
+    case GPBField_Kind_TypeDouble:
+    case GPBField_Kind_TypeFloat:
+    case GPBField_Kind_TypeInt64:
+    case GPBField_Kind_TypeUint64:
+    case GPBField_Kind_TypeInt32:
+    case GPBField_Kind_TypeFixed64:
+    case GPBField_Kind_TypeFixed32:
+    case GPBField_Kind_TypeBool:
+    case GPBField_Kind_TypeString:
+    case GPBField_Kind_TypeGroup:
+    case GPBField_Kind_TypeMessage:
+    case GPBField_Kind_TypeBytes:
+    case GPBField_Kind_TypeUint32:
+    case GPBField_Kind_TypeEnum:
+    case GPBField_Kind_TypeSfixed32:
+    case GPBField_Kind_TypeSfixed64:
+    case GPBField_Kind_TypeSint32:
+    case GPBField_Kind_TypeSint64:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
+#pragma mark - Enum GPBField_Cardinality
+
+GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) {
+  static _Atomic(GPBEnumDescriptor*) descriptor = nil;
+  if (!descriptor) {
+    static const char *valueNames =
+        "CardinalityUnknown\000CardinalityOptional\000C"
+        "ardinalityRequired\000CardinalityRepeated\000";
+    static const int32_t values[] = {
+        GPBField_Cardinality_CardinalityUnknown,
+        GPBField_Cardinality_CardinalityOptional,
+        GPBField_Cardinality_CardinalityRequired,
+        GPBField_Cardinality_CardinalityRepeated,
+    };
+    GPBEnumDescriptor *worker =
+        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality)
+                                       valueNames:valueNames
+                                           values:values
+                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
+                                     enumVerifier:GPBField_Cardinality_IsValidValue
+                                            flags:GPBEnumDescriptorInitializationFlag_None];
+    GPBEnumDescriptor *expected = nil;
+    if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
+      [worker release];
+    }
+  }
+  return descriptor;
+}
+
+BOOL GPBField_Cardinality_IsValidValue(int32_t value__) {
+  switch (value__) {
+    case GPBField_Cardinality_CardinalityUnknown:
+    case GPBField_Cardinality_CardinalityOptional:
+    case GPBField_Cardinality_CardinalityRequired:
+    case GPBField_Cardinality_CardinalityRepeated:
+      return YES;
+    default:
+      return NO;
+  }
+}
+
 #pragma mark - GPBType
 
 @implementation GPBType
@@ -170,7 +288,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBType__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -325,7 +443,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBField__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
 #if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS
     static const char *extraTextFormatInfo =
         "\001\006\004\241!!\000";
@@ -365,120 +483,6 @@
   GPBSetMessageRawEnumField(message, field, value);
 }
 
-#pragma mark - Enum GPBField_Kind
-
-GPBEnumDescriptor *GPBField_Kind_EnumDescriptor(void) {
-  static _Atomic(GPBEnumDescriptor*) descriptor = nil;
-  if (!descriptor) {
-    static const char *valueNames =
-        "TypeUnknown\000TypeDouble\000TypeFloat\000TypeInt"
-        "64\000TypeUint64\000TypeInt32\000TypeFixed64\000Type"
-        "Fixed32\000TypeBool\000TypeString\000TypeGroup\000Ty"
-        "peMessage\000TypeBytes\000TypeUint32\000TypeEnum\000"
-        "TypeSfixed32\000TypeSfixed64\000TypeSint32\000Typ"
-        "eSint64\000";
-    static const int32_t values[] = {
-        GPBField_Kind_TypeUnknown,
-        GPBField_Kind_TypeDouble,
-        GPBField_Kind_TypeFloat,
-        GPBField_Kind_TypeInt64,
-        GPBField_Kind_TypeUint64,
-        GPBField_Kind_TypeInt32,
-        GPBField_Kind_TypeFixed64,
-        GPBField_Kind_TypeFixed32,
-        GPBField_Kind_TypeBool,
-        GPBField_Kind_TypeString,
-        GPBField_Kind_TypeGroup,
-        GPBField_Kind_TypeMessage,
-        GPBField_Kind_TypeBytes,
-        GPBField_Kind_TypeUint32,
-        GPBField_Kind_TypeEnum,
-        GPBField_Kind_TypeSfixed32,
-        GPBField_Kind_TypeSfixed64,
-        GPBField_Kind_TypeSint32,
-        GPBField_Kind_TypeSint64,
-    };
-    GPBEnumDescriptor *worker =
-        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Kind)
-                                       valueNames:valueNames
-                                           values:values
-                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
-                                     enumVerifier:GPBField_Kind_IsValidValue];
-    GPBEnumDescriptor *expected = nil;
-    if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
-      [worker release];
-    }
-  }
-  return descriptor;
-}
-
-BOOL GPBField_Kind_IsValidValue(int32_t value__) {
-  switch (value__) {
-    case GPBField_Kind_TypeUnknown:
-    case GPBField_Kind_TypeDouble:
-    case GPBField_Kind_TypeFloat:
-    case GPBField_Kind_TypeInt64:
-    case GPBField_Kind_TypeUint64:
-    case GPBField_Kind_TypeInt32:
-    case GPBField_Kind_TypeFixed64:
-    case GPBField_Kind_TypeFixed32:
-    case GPBField_Kind_TypeBool:
-    case GPBField_Kind_TypeString:
-    case GPBField_Kind_TypeGroup:
-    case GPBField_Kind_TypeMessage:
-    case GPBField_Kind_TypeBytes:
-    case GPBField_Kind_TypeUint32:
-    case GPBField_Kind_TypeEnum:
-    case GPBField_Kind_TypeSfixed32:
-    case GPBField_Kind_TypeSfixed64:
-    case GPBField_Kind_TypeSint32:
-    case GPBField_Kind_TypeSint64:
-      return YES;
-    default:
-      return NO;
-  }
-}
-
-#pragma mark - Enum GPBField_Cardinality
-
-GPBEnumDescriptor *GPBField_Cardinality_EnumDescriptor(void) {
-  static _Atomic(GPBEnumDescriptor*) descriptor = nil;
-  if (!descriptor) {
-    static const char *valueNames =
-        "CardinalityUnknown\000CardinalityOptional\000C"
-        "ardinalityRequired\000CardinalityRepeated\000";
-    static const int32_t values[] = {
-        GPBField_Cardinality_CardinalityUnknown,
-        GPBField_Cardinality_CardinalityOptional,
-        GPBField_Cardinality_CardinalityRequired,
-        GPBField_Cardinality_CardinalityRepeated,
-    };
-    GPBEnumDescriptor *worker =
-        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol(GPBField_Cardinality)
-                                       valueNames:valueNames
-                                           values:values
-                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))
-                                     enumVerifier:GPBField_Cardinality_IsValidValue];
-    GPBEnumDescriptor *expected = nil;
-    if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {
-      [worker release];
-    }
-  }
-  return descriptor;
-}
-
-BOOL GPBField_Cardinality_IsValidValue(int32_t value__) {
-  switch (value__) {
-    case GPBField_Cardinality_CardinalityUnknown:
-    case GPBField_Cardinality_CardinalityOptional:
-    case GPBField_Cardinality_CardinalityRequired:
-    case GPBField_Cardinality_CardinalityRepeated:
-      return YES;
-    default:
-      return NO;
-  }
-}
-
 #pragma mark - GPBEnum
 
 @implementation GPBEnum
@@ -557,7 +561,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBEnum__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -636,7 +640,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBEnumValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -692,7 +696,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBOption__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -707,3 +711,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBUnknownField.h b/objectivec/GPBUnknownField.h
index 5b96023..a188990 100644
--- a/objectivec/GPBUnknownField.h
+++ b/objectivec/GPBUnknownField.h
@@ -40,7 +40,7 @@
  * Store an unknown field. These are used in conjunction with
  * GPBUnknownFieldSet.
  **/
-@interface GPBUnknownField : NSObject<NSCopying>
+@interface GPBUnknownField : NSObject <NSCopying>
 
 /** Initialize a field with the given number. */
 - (instancetype)initWithNumber:(int32_t)number;
@@ -58,10 +58,10 @@
 @property(nonatomic, readonly, strong) GPBUInt64Array *fixed64List;
 
 /** An array of data values for this field. */
-@property(nonatomic, readonly, strong) NSArray<NSData*> *lengthDelimitedList;
+@property(nonatomic, readonly, strong) NSArray<NSData *> *lengthDelimitedList;
 
 /** An array of groups of values for this field. */
-@property(nonatomic, readonly, strong) NSArray<GPBUnknownFieldSet*> *groupList;
+@property(nonatomic, readonly, strong) NSArray<GPBUnknownFieldSet *> *groupList;
 
 /**
  * Add a value to the varintList.
diff --git a/objectivec/GPBUnknownField.m b/objectivec/GPBUnknownField.m
index 7fa8cad..62cfb22 100644
--- a/objectivec/GPBUnknownField.m
+++ b/objectivec/GPBUnknownField.m
@@ -40,8 +40,8 @@
   GPBUInt64Array *mutableVarintList_;
   GPBUInt32Array *mutableFixed32List_;
   GPBUInt64Array *mutableFixed64List_;
-  NSMutableArray<NSData*> *mutableLengthDelimitedList_;
-  NSMutableArray<GPBUnknownFieldSet*> *mutableGroupList_;
+  NSMutableArray<NSData *> *mutableLengthDelimitedList_;
+  NSMutableArray<GPBUnknownFieldSet *> *mutableGroupList_;
 }
 
 @synthesize number = number_;
@@ -75,16 +75,14 @@
 #pragma clang diagnostic ignored "-Wdirect-ivar-access"
 
 - (id)copyWithZone:(NSZone *)zone {
-  GPBUnknownField *result =
-      [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
+  GPBUnknownField *result = [[GPBUnknownField allocWithZone:zone] initWithNumber:number_];
   result->mutableFixed32List_ = [mutableFixed32List_ copyWithZone:zone];
   result->mutableFixed64List_ = [mutableFixed64List_ copyWithZone:zone];
-  result->mutableLengthDelimitedList_ =
-      [mutableLengthDelimitedList_ mutableCopyWithZone:zone];
+  result->mutableLengthDelimitedList_ = [mutableLengthDelimitedList_ mutableCopyWithZone:zone];
   result->mutableVarintList_ = [mutableVarintList_ copyWithZone:zone];
   if (mutableGroupList_.count) {
-    result->mutableGroupList_ = [[NSMutableArray allocWithZone:zone]
-        initWithCapacity:mutableGroupList_.count];
+    result->mutableGroupList_ =
+        [[NSMutableArray allocWithZone:zone] initWithCapacity:mutableGroupList_.count];
     for (GPBUnknownFieldSet *group in mutableGroupList_) {
       GPBUnknownFieldSet *copied = [group copyWithZone:zone];
       [result->mutableGroupList_ addObject:copied];
@@ -99,26 +97,21 @@
   if (![object isKindOfClass:[GPBUnknownField class]]) return NO;
   GPBUnknownField *field = (GPBUnknownField *)object;
   if (number_ != field->number_) return NO;
-  BOOL equalVarint =
-      (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) ||
-      [mutableVarintList_ isEqual:field->mutableVarintList_];
+  BOOL equalVarint = (mutableVarintList_.count == 0 && field->mutableVarintList_.count == 0) ||
+                     [mutableVarintList_ isEqual:field->mutableVarintList_];
   if (!equalVarint) return NO;
-  BOOL equalFixed32 = (mutableFixed32List_.count == 0 &&
-                       field->mutableFixed32List_.count == 0) ||
+  BOOL equalFixed32 = (mutableFixed32List_.count == 0 && field->mutableFixed32List_.count == 0) ||
                       [mutableFixed32List_ isEqual:field->mutableFixed32List_];
   if (!equalFixed32) return NO;
-  BOOL equalFixed64 = (mutableFixed64List_.count == 0 &&
-                       field->mutableFixed64List_.count == 0) ||
+  BOOL equalFixed64 = (mutableFixed64List_.count == 0 && field->mutableFixed64List_.count == 0) ||
                       [mutableFixed64List_ isEqual:field->mutableFixed64List_];
   if (!equalFixed64) return NO;
   BOOL equalLDList =
-      (mutableLengthDelimitedList_.count == 0 &&
-       field->mutableLengthDelimitedList_.count == 0) ||
+      (mutableLengthDelimitedList_.count == 0 && field->mutableLengthDelimitedList_.count == 0) ||
       [mutableLengthDelimitedList_ isEqual:field->mutableLengthDelimitedList_];
   if (!equalLDList) return NO;
-  BOOL equalGroupList =
-      (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) ||
-      [mutableGroupList_ isEqual:field->mutableGroupList_];
+  BOOL equalGroupList = (mutableGroupList_.count == 0 && field->mutableGroupList_.count == 0) ||
+                        [mutableGroupList_ isEqual:field->mutableGroupList_];
   if (!equalGroupList) return NO;
   return YES;
 }
@@ -161,20 +154,17 @@
   __block size_t result = 0;
   int32_t number = number_;
   [mutableVarintList_
-      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+      enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
         result += GPBComputeUInt64Size(number, value);
       }];
 
   [mutableFixed32List_
-      enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+      enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
         result += GPBComputeFixed32Size(number, value);
       }];
 
   [mutableFixed64List_
-      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+      enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
         result += GPBComputeFixed64Size(number, value);
       }];
 
@@ -205,23 +195,19 @@
 
 - (NSString *)description {
   NSMutableString *description =
-      [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d {\n",
-       [self class], self, number_];
+      [NSMutableString stringWithFormat:@"<%@ %p>: Field: %d {\n", [self class], self, number_];
   [mutableVarintList_
-      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+      enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
         [description appendFormat:@"\t%llu\n", value];
       }];
 
   [mutableFixed32List_
-      enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+      enumerateValuesWithBlock:^(uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
         [description appendFormat:@"\t%u\n", value];
       }];
 
   [mutableFixed64List_
-      enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-#pragma unused(idx, stop)
+      enumerateValuesWithBlock:^(uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
         [description appendFormat:@"\t%llu\n", value];
       }];
 
@@ -269,16 +255,14 @@
     if (mutableLengthDelimitedList_ == nil) {
       mutableLengthDelimitedList_ = [otherLengthDelimitedList mutableCopy];
     } else {
-      [mutableLengthDelimitedList_
-          addObjectsFromArray:otherLengthDelimitedList];
+      [mutableLengthDelimitedList_ addObjectsFromArray:otherLengthDelimitedList];
     }
   }
 
   NSArray *otherGroupList = other.groupList;
   if (otherGroupList.count > 0) {
     if (mutableGroupList_ == nil) {
-      mutableGroupList_ =
-          [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
+      mutableGroupList_ = [[NSMutableArray alloc] initWithCapacity:otherGroupList.count];
     }
     // Make our own mutable copies.
     for (GPBUnknownFieldSet *group in otherGroupList) {
@@ -299,8 +283,7 @@
 
 - (void)addFixed32:(uint32_t)value {
   if (mutableFixed32List_ == nil) {
-    mutableFixed32List_ =
-        [[GPBUInt32Array alloc] initWithValues:&value count:1];
+    mutableFixed32List_ = [[GPBUInt32Array alloc] initWithValues:&value count:1];
   } else {
     [mutableFixed32List_ addValue:value];
   }
@@ -308,8 +291,7 @@
 
 - (void)addFixed64:(uint64_t)value {
   if (mutableFixed64List_ == nil) {
-    mutableFixed64List_ =
-        [[GPBUInt64Array alloc] initWithValues:&value count:1];
+    mutableFixed64List_ = [[GPBUInt64Array alloc] initWithValues:&value count:1];
   } else {
     [mutableFixed64List_ addValue:value];
   }
@@ -317,8 +299,7 @@
 
 - (void)addLengthDelimited:(NSData *)value {
   if (mutableLengthDelimitedList_ == nil) {
-    mutableLengthDelimitedList_ =
-        [[NSMutableArray alloc] initWithObjects:&value count:1];
+    mutableLengthDelimitedList_ = [[NSMutableArray alloc] initWithObjects:&value count:1];
   } else {
     [mutableLengthDelimitedList_ addObject:value];
   }
diff --git a/objectivec/GPBUnknownFieldSet.h b/objectivec/GPBUnknownFieldSet.h
index 1b5f24f..5901f18 100644
--- a/objectivec/GPBUnknownFieldSet.h
+++ b/objectivec/GPBUnknownFieldSet.h
@@ -37,10 +37,9 @@
 /**
  * A collection of unknown fields. Fields parsed from the binary representation
  * of a message that are unknown end up in an instance of this set. This only
- * applies for files declared with the "proto2" syntax. Files declared with the
- * "proto3" syntax discard the unknown values.
+ * applies for files declared with the "proto2" syntax.
  **/
-@interface GPBUnknownFieldSet : NSObject<NSCopying>
+@interface GPBUnknownFieldSet : NSObject <NSCopying>
 
 /**
  * Tests to see if the given field number has a value.
diff --git a/objectivec/GPBUnknownFieldSet.m b/objectivec/GPBUnknownFieldSet.m
index a7335f0..dcd4b44 100644
--- a/objectivec/GPBUnknownFieldSet.m
+++ b/objectivec/GPBUnknownFieldSet.m
@@ -40,8 +40,7 @@
 
 static void checkNumber(int32_t number) {
   if (number == 0) {
-    [NSException raise:NSInvalidArgumentException
-                format:@"Zero is not a valid field number."];
+    [NSException raise:NSInvalidArgumentException format:@"Zero is not a valid field number."];
   }
 }
 
@@ -50,8 +49,7 @@
   CFMutableDictionaryRef fields_;
 }
 
-static void CopyWorker(const void *key, const void *value, void *context) {
-#pragma unused(key)
+static void CopyWorker(__unused const void *key, const void *value, void *context) {
   GPBUnknownField *field = value;
   GPBUnknownFieldSet *result = context;
 
@@ -111,8 +109,7 @@
 
 - (GPBUnknownField *)getField:(int32_t)number {
   ssize_t key = number;
-  GPBUnknownField *result =
-      fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil;
+  GPBUnknownField *result = fields_ ? CFDictionaryGetValue(fields_, (void *)key) : nil;
   return result;
 }
 
@@ -125,8 +122,7 @@
   size_t count = CFDictionaryGetCount(fields_);
   ssize_t keys[count];
   GPBUnknownField *values[count];
-  CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
-                               (const void **)values);
+  CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values);
   struct GPBFieldPair {
     ssize_t key;
     GPBUnknownField *value;
@@ -135,12 +131,11 @@
     pairs[i].key = keys[i];
     pairs[i].value = values[i];
   };
-  qsort_b(pairs, count, sizeof(struct GPBFieldPair),
-          ^(const void *first, const void *second) {
-            const struct GPBFieldPair *a = first;
-            const struct GPBFieldPair *b = second;
-            return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
-          });
+  qsort_b(pairs, count, sizeof(struct GPBFieldPair), ^(const void *first, const void *second) {
+    const struct GPBFieldPair *a = first;
+    const struct GPBFieldPair *b = second;
+    return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
+  });
   for (size_t i = 0; i < count; ++i) {
     values[i] = pairs[i].value;
   };
@@ -154,8 +149,7 @@
   size_t count = CFDictionaryGetCount(fields_);
   ssize_t keys[count];
   GPBUnknownField *values[count];
-  CFDictionaryGetKeysAndValues(fields_, (const void **)keys,
-                               (const void **)values);
+  CFDictionaryGetKeysAndValues(fields_, (const void **)keys, (const void **)values);
   if (count > 1) {
     struct GPBFieldPair {
       ssize_t key;
@@ -166,12 +160,11 @@
       pairs[i].key = keys[i];
       pairs[i].value = values[i];
     };
-    qsort_b(pairs, count, sizeof(struct GPBFieldPair),
-            ^(const void *first, const void *second) {
-              const struct GPBFieldPair *a = first;
-              const struct GPBFieldPair *b = second;
-              return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
-            });
+    qsort_b(pairs, count, sizeof(struct GPBFieldPair), ^(const void *first, const void *second) {
+      const struct GPBFieldPair *a = first;
+      const struct GPBFieldPair *b = second;
+      return (a->key > b->key) ? 1 : ((a->key == b->key) ? 0 : -1);
+    });
     for (size_t i = 0; i < count; ++i) {
       GPBUnknownField *value = pairs[i].value;
       [value writeToOutput:output];
@@ -182,17 +175,16 @@
 }
 
 - (NSString *)description {
-  NSMutableString *description = [NSMutableString
-      stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self];
+  NSMutableString *description =
+      [NSMutableString stringWithFormat:@"<%@ %p>: TextFormat: {\n", [self class], self];
   NSString *textFormat = GPBTextFormatForUnknownFieldSet(self, @"  ");
   [description appendString:textFormat];
   [description appendString:@"}"];
   return description;
 }
 
-static void GPBUnknownFieldSetSerializedSize(const void *key, const void *value,
+static void GPBUnknownFieldSetSerializedSize(__unused const void *key, const void *value,
                                              void *context) {
-#pragma unused(key)
   GPBUnknownField *field = value;
   size_t *result = context;
   *result += [field serializedSize];
@@ -201,16 +193,13 @@
 - (size_t)serializedSize {
   size_t result = 0;
   if (fields_) {
-    CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize,
-                              &result);
+    CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSize, &result);
   }
   return result;
 }
 
-static void GPBUnknownFieldSetWriteAsMessageSetTo(const void *key,
-                                                  const void *value,
+static void GPBUnknownFieldSetWriteAsMessageSetTo(__unused const void *key, const void *value,
                                                   void *context) {
-#pragma unused(key)
   GPBUnknownField *field = value;
   GPBCodedOutputStream *output = context;
   [field writeAsMessageSetExtensionToOutput:output];
@@ -218,15 +207,12 @@
 
 - (void)writeAsMessageSetTo:(GPBCodedOutputStream *)output {
   if (fields_) {
-    CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo,
-                              output);
+    CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetWriteAsMessageSetTo, output);
   }
 }
 
-static void GPBUnknownFieldSetSerializedSizeAsMessageSet(const void *key,
-                                                         const void *value,
-                                                         void *context) {
-#pragma unused(key)
+static void GPBUnknownFieldSetSerializedSizeAsMessageSet(__unused const void *key,
+                                                         const void *value, void *context) {
   GPBUnknownField *field = value;
   size_t *result = context;
   *result += [field serializedSizeAsMessageSetExtension];
@@ -235,16 +221,14 @@
 - (size_t)serializedSizeAsMessageSet {
   size_t result = 0;
   if (fields_) {
-    CFDictionaryApplyFunction(
-        fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result);
+    CFDictionaryApplyFunction(fields_, GPBUnknownFieldSetSerializedSizeAsMessageSet, &result);
   }
   return result;
 }
 
 - (NSData *)data {
   NSMutableData *data = [NSMutableData dataWithLength:self.serializedSize];
-  GPBCodedOutputStream *output =
-      [[GPBCodedOutputStream alloc] initWithData:data];
+  GPBCodedOutputStream *output = [[GPBCodedOutputStream alloc] initWithData:data];
   [self writeToCodedOutputStream:output];
   [output release];
   return data;
@@ -260,8 +244,8 @@
   if (!fields_) {
     // Use a custom dictionary here because the keys are numbers and conversion
     // back and forth from NSNumber isn't worth the cost.
-    fields_ = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL,
-                                        &kCFTypeDictionaryValueCallBacks);
+    fields_ =
+        CFDictionaryCreateMutable(kCFAllocatorDefault, 0, NULL, &kCFTypeDictionaryValueCallBacks);
   }
   ssize_t key = number;
   CFDictionarySetValue(fields_, (const void *)key, field);
@@ -269,8 +253,7 @@
 
 - (GPBUnknownField *)mutableFieldForNumber:(int32_t)number create:(BOOL)create {
   ssize_t key = number;
-  GPBUnknownField *existing =
-      fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil;
+  GPBUnknownField *existing = fields_ ? CFDictionaryGetValue(fields_, (const void *)key) : nil;
   if (!existing && create) {
     existing = [[GPBUnknownField alloc] initWithNumber:number];
     // This retains existing.
@@ -280,10 +263,8 @@
   return existing;
 }
 
-static void GPBUnknownFieldSetMergeUnknownFields(const void *key,
-                                                 const void *value,
+static void GPBUnknownFieldSetMergeUnknownFields(__unused const void *key, const void *value,
                                                  void *context) {
-#pragma unused(key)
   GPBUnknownField *field = value;
   GPBUnknownFieldSet *self = context;
 
@@ -304,8 +285,7 @@
 
 - (void)mergeUnknownFields:(GPBUnknownFieldSet *)other {
   if (other && other->fields_) {
-    CFDictionaryApplyFunction(other->fields_,
-                              GPBUnknownFieldSetMergeUnknownFields, self);
+    CFDictionaryApplyFunction(other->fields_, GPBUnknownFieldSetMergeUnknownFields, self);
   }
 }
 
@@ -362,8 +342,7 @@
 }
 
 - (void)mergeMessageSetMessage:(int32_t)number data:(NSData *)messageData {
-  [[self mutableFieldForNumber:number create:YES]
-      addLengthDelimited:messageData];
+  [[self mutableFieldForNumber:number create:YES] addLengthDelimited:messageData];
 }
 
 - (void)addUnknownMapEntry:(int32_t)fieldNum value:(NSData *)data {
diff --git a/objectivec/GPBUtilities.h b/objectivec/GPBUtilities.h
index 75759b2..e49ada5 100644
--- a/objectivec/GPBUtilities.h
+++ b/objectivec/GPBUtilities.h
@@ -50,8 +50,7 @@
  *
  * @return An NSString with the TextFormat of the message.
  **/
-NSString *GPBTextFormatForMessage(GPBMessage *message,
-                                  NSString * __nullable lineIndent);
+NSString *GPBTextFormatForMessage(GPBMessage *message, NSString *__nullable lineIndent);
 
 /**
  * Generates a string that should be a valid "TextFormat" for the C++ version
@@ -63,8 +62,8 @@
  *
  * @return An NSString with the TextFormat of the unknown field set.
  **/
-NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet * __nullable unknownSet,
-                                          NSString * __nullable lineIndent);
+NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *__nullable unknownSet,
+                                          NSString *__nullable lineIndent);
 
 /**
  * Checks if the given field number is set on a message.
@@ -102,9 +101,11 @@
  **/
 void GPBClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof);
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-EXPAND GPB_ACCESSORS()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 
 //
@@ -395,9 +396,10 @@
                            GPBFieldDescriptor *field,
                            id dictionary);
 
-// clang-format on
 //%PDDM-EXPAND-END GPB_ACCESSORS()
 
+// clang-format on
+
 /**
  * Returns an empty NSData to assign to byte fields when you wish to assign them
  * to empty. Prevents allocating a lot of little [NSData data] objects.
@@ -413,6 +415,8 @@
 
 CF_EXTERN_C_END
 
+// Disable clang-format for the macros.
+// clang-format off
 
 //%PDDM-DEFINE GPB_ACCESSORS()
 //%
@@ -549,3 +553,5 @@
 //% **/
 //%void GPBSetMessage##NAME##Field(GPBMessage *self, GPBFieldDescriptor *field, TYPE TisP##value);
 //%
+
+// clang-format on
diff --git a/objectivec/GPBUtilities.m b/objectivec/GPBUtilities.m
index b72d0e2..0928dea 100644
--- a/objectivec/GPBUtilities.m
+++ b/objectivec/GPBUtilities.m
@@ -45,28 +45,24 @@
 #pragma clang diagnostic push
 #pragma clang diagnostic ignored "-Wdirect-ivar-access"
 
-static void AppendTextFormatForMessage(GPBMessage *message,
-                                       NSMutableString *toStr,
+static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr,
                                        NSString *lineIndent);
 
 // Are two datatypes the same basic type representation (ex Int32 and SInt32).
 // Marked unused because currently only called from asserts/debug.
-static BOOL DataTypesEquivalent(GPBDataType type1,
-                                GPBDataType type2) __attribute__ ((unused));
+static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) __attribute__((unused));
 
 // Basic type representation for a type (ex: for SInt32 it is Int32).
 // Marked unused because currently only called from asserts/debug.
-static GPBDataType BaseDataType(GPBDataType type) __attribute__ ((unused));
+static GPBDataType BaseDataType(GPBDataType type) __attribute__((unused));
 
 // String name for a data type.
 // Marked unused because currently only called from asserts/debug.
-static NSString *TypeToString(GPBDataType dataType) __attribute__ ((unused));
+static NSString *TypeToString(GPBDataType dataType) __attribute__((unused));
 
 // Helper for clearing oneofs.
-static void GPBMaybeClearOneofPrivate(GPBMessage *self,
-                                      GPBOneofDescriptor *oneof,
-                                      int32_t oneofHasIndex,
-                                      uint32_t fieldNumberNotToClear);
+static void GPBMaybeClearOneofPrivate(GPBMessage *self, GPBOneofDescriptor *oneof,
+                                      int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
 
 NSData *GPBEmptyNSData(void) {
   static dispatch_once_t onceToken;
@@ -118,52 +114,53 @@
           id rawFieldMap = GPBGetObjectIvarWithFieldNoAutocreate(msg, field);
           switch (field.mapKeyDataType) {
             case GPBDataTypeBool:
-              [(GPBBoolObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
-                  BOOL key, id _Nonnull object, BOOL * _Nonnull stop) {
-                #pragma unused(key, stop)
-                [todo addObject:object];
-              }];
+              [(GPBBoolObjectDictionary *)rawFieldMap
+                  enumerateKeysAndObjectsUsingBlock:^(__unused BOOL key, id _Nonnull object,
+                                                      __unused BOOL *_Nonnull stop) {
+                    [todo addObject:object];
+                  }];
               break;
             case GPBDataTypeFixed32:
             case GPBDataTypeUInt32:
-              [(GPBUInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
-                  uint32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
-                #pragma unused(key, stop)
-                [todo addObject:object];
-              }];
+              [(GPBUInt32ObjectDictionary *)rawFieldMap
+                  enumerateKeysAndObjectsUsingBlock:^(__unused uint32_t key, id _Nonnull object,
+                                                      __unused BOOL *_Nonnull stop) {
+                    [todo addObject:object];
+                  }];
               break;
             case GPBDataTypeInt32:
             case GPBDataTypeSFixed32:
             case GPBDataTypeSInt32:
-              [(GPBInt32ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
-                  int32_t key, id _Nonnull object, BOOL * _Nonnull stop) {
-                #pragma unused(key, stop)
-                [todo addObject:object];
-              }];
+              [(GPBInt32ObjectDictionary *)rawFieldMap
+                  enumerateKeysAndObjectsUsingBlock:^(__unused int32_t key, id _Nonnull object,
+                                                      __unused BOOL *_Nonnull stop) {
+                    [todo addObject:object];
+                  }];
               break;
             case GPBDataTypeFixed64:
             case GPBDataTypeUInt64:
-              [(GPBUInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
-                  uint64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
-                #pragma unused(key, stop)
-                [todo addObject:object];
-              }];
+              [(GPBUInt64ObjectDictionary *)rawFieldMap
+                  enumerateKeysAndObjectsUsingBlock:^(__unused uint64_t key, id _Nonnull object,
+                                                      __unused BOOL *_Nonnull stop) {
+                    [todo addObject:object];
+                  }];
               break;
             case GPBDataTypeInt64:
             case GPBDataTypeSFixed64:
             case GPBDataTypeSInt64:
-              [(GPBInt64ObjectDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
-                  int64_t key, id _Nonnull object, BOOL * _Nonnull stop) {
-                #pragma unused(key, stop)
-                [todo addObject:object];
-              }];
+              [(GPBInt64ObjectDictionary *)rawFieldMap
+                  enumerateKeysAndObjectsUsingBlock:^(__unused int64_t key, id _Nonnull object,
+                                                      __unused BOOL *_Nonnull stop) {
+                    [todo addObject:object];
+                  }];
               break;
             case GPBDataTypeString:
-              [(NSDictionary*)rawFieldMap enumerateKeysAndObjectsUsingBlock:^(
-                  NSString * _Nonnull key, GPBMessage * _Nonnull obj, BOOL * _Nonnull stop) {
-                #pragma unused(key, stop)
-                [todo addObject:obj];
-              }];
+              [(NSDictionary *)rawFieldMap
+                  enumerateKeysAndObjectsUsingBlock:^(__unused NSString *_Nonnull key,
+                                                      GPBMessage *_Nonnull obj,
+                                                      __unused BOOL *_Nonnull stop) {
+                    [todo addObject:obj];
+                  }];
               break;
             case GPBDataTypeFloat:
             case GPBDataTypeDouble:
@@ -175,8 +172,8 @@
           }
           break;
         }  // switch(field.mapKeyDataType)
-      }  // switch(field.fieldType)
-    }  // for(fields)
+      }    // switch(field.fieldType)
+    }      // for(fields)
 
     // Handle any extensions holding messages.
     for (GPBExtensionDescriptor *extension in [msg extensionsCurrentlySet]) {
@@ -195,7 +192,6 @@
   }  // while(todo.count)
 }
 
-
 // -- About Version Checks --
 // There's actually 3 places these checks all come into play:
 // 1. When the generated source is compile into .o files, the header check
@@ -228,8 +224,7 @@
                 format:@"Proto generation source compiled against runtime"
                        @" version %d, but this version of the runtime only"
                        @" supports back to %d!",
-                       objcRuntimeVersion,
-                       GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION];
+                       objcRuntimeVersion, GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION];
   }
 }
 
@@ -288,18 +283,16 @@
 }
 
 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
+#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)",
+  NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)",
             [self class]);
   if (idx < 0) {
     NSCAssert(fieldNumber != 0, @"Invalid field number.");
@@ -309,21 +302,18 @@
     NSCAssert(idx != GPBNoHasBit, @"Invalid has bit.");
     uint32_t byteIndex = idx / 32;
     uint32_t bitMask = (1U << (idx % 32));
-    BOOL hasIvar =
-        (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
+    BOOL hasIvar = (self->messageStorage_->_has_storage_[byteIndex] & bitMask) ? YES : NO;
     return hasIvar;
   }
 }
 
 uint32_t GPBGetHasOneof(GPBMessage *self, int32_t idx) {
-  NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.",
-            [self class], idx);
+  NSCAssert(idx < 0, @"%@: invalid index (%d) for oneof.", [self class], idx);
   uint32_t result = self->messageStorage_->_has_storage_[-idx];
   return result;
 }
 
-void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
-                   BOOL value) {
+void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, BOOL value) {
   if (idx < 0) {
     NSCAssert(fieldNumber != 0, @"Invalid field number.");
     uint32_t *has_storage = self->messageStorage_->_has_storage_;
@@ -341,10 +331,8 @@
   }
 }
 
-static void GPBMaybeClearOneofPrivate(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.
@@ -354,9 +342,8 @@
   // Like GPBClearMessageField(), free the memory if an objecttype is set,
   // pod types don't need to do anything.
   GPBFieldDescriptor *fieldSet = [oneof fieldWithNumber:fieldNumberSet];
-  NSCAssert(fieldSet,
-            @"%@: oneof set to something (%u) not in the oneof?",
-            [self class], fieldNumberSet);
+  NSCAssert(fieldSet, @"%@: oneof set to something (%u) not in the oneof?", [self class],
+            fieldNumberSet);
   if (fieldSet && GPBFieldStoresObject(fieldSet)) {
     uint8_t *storage = (uint8_t *)self->messageStorage_;
     id *typePtr = (id *)&storage[fieldSet->description_->offset];
@@ -371,6 +358,8 @@
 
 #pragma mark - IVar accessors
 
+// clang-format off
+
 //%PDDM-DEFINE IVAR_POD_ACCESSORS_DEFN(NAME, TYPE)
 //%TYPE GPBGetMessage##NAME##Field(GPBMessage *self,
 //% TYPE$S            NAME$S       GPBFieldDescriptor *field) {
@@ -501,11 +490,12 @@
 //%}
 //%
 
+// clang-format on
+
 // Object types are handled slightly differently, they need to be released
 // and retained.
 
-void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self,
-                                             GPBFieldDescriptor *field) {
+void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, GPBFieldDescriptor *field) {
   if (GPBGetHasIvarField(self, field)) {
     return;
   }
@@ -518,14 +508,12 @@
 }
 
 // This exists only for bridging some aliased types, nothing else should use it.
-static void GPBSetObjectIvarWithField(GPBMessage *self,
-                                      GPBFieldDescriptor *field, id value) {
+static void GPBSetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value) {
   if (self == nil || field == nil) return;
   GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
 }
 
-static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
-                                          GPBFieldDescriptor *field, id value);
+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 GPBSetRetainedObjectIvarWithFieldPrivate
@@ -533,23 +521,19 @@
 // with the -retain in GPBSetObjectIvarWithField.
 #if !defined(__clang_analyzer__)
 // This exists only for bridging some aliased types, nothing else should use it.
-static void GPBSetCopyObjectIvarWithField(GPBMessage *self,
-                                          GPBFieldDescriptor *field, id value) {
+static void GPBSetCopyObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field, id value) {
   if (self == nil || field == nil) return;
   GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value copy]);
 }
 #endif  // !defined(__clang_analyzer__)
 
-void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self,
-                                      GPBFieldDescriptor *field, id value) {
+void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field, id value) {
   GPBSetRetainedObjectIvarWithFieldPrivate(self, field, [value retain]);
 }
 
-void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
-                                              GPBFieldDescriptor *field,
+void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field,
                                               id value) {
-  NSCAssert(self->messageStorage_ != NULL,
-            @"%@: All messages should have storage (from init)",
+  NSCAssert(self->messageStorage_ != NULL, @"%@: All messages should have storage (from init)",
             [self class]);
 #if defined(__clang_analyzer__)
   if (self->messageStorage_ == NULL) return;
@@ -558,8 +542,7 @@
   BOOL isMapOrArray = GPBFieldIsMapOrArray(field);
   BOOL fieldIsMessage = GPBDataTypeIsMessage(fieldType);
 #if defined(DEBUG) && DEBUG
-  if (value == nil && !isMapOrArray && !fieldIsMessage &&
-      field.hasDefaultValue) {
+  if (value == nil && !isMapOrArray && !fieldIsMessage && field.hasDefaultValue) {
     // Setting a message to nil is an obvious way to "clear" the value
     // as there is no way to set a non-empty default value for messages.
     //
@@ -580,8 +563,8 @@
           @"empty, or call '%@.%@ = NO' to reset it to it's default value of "
           @"'%@'. Defaulting to resetting default value.",
           className, propName, className, propName,
-          (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()",
-          className, hasSel, field.defaultValue.valueString);
+          (fieldType == GPBDataTypeString) ? @"@\"\"" : @"GPBEmptyNSData()", className, hasSel,
+          field.defaultValue.valueString);
     // Note: valueString, depending on the type, it could easily be
     // valueData/valueMessage.
   }
@@ -598,8 +581,7 @@
     BOOL setHasValue = (value != nil);
     // 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)) {
+    if (((fieldDesc->flags & GPBFieldClearHasIvarOnZero) != 0) && ([value length] == 0)) {
       setHasValue = NO;
       // The value passed in was retained, it must be released since we
       // aren't saving anything in the field.
@@ -633,10 +615,9 @@
             gpbArray->_autocreator = nil;
           }
         }
-      } else { // GPBFieldTypeMap
+      } else {  // GPBFieldTypeMap
         // If the old map was autocreated by us, then clear it.
-        if ((field.mapKeyDataType == GPBDataTypeString) &&
-            GPBDataTypeIsObject(fieldType)) {
+        if ((field.mapKeyDataType == GPBDataTypeString) && GPBDataTypeIsObject(fieldType)) {
           if ([oldValue isKindOfClass:[GPBAutocreatedDictionary class]]) {
             GPBAutocreatedDictionary *autoDict = oldValue;
             if (autoDict->_autocreator == self) {
@@ -664,8 +645,7 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self,
-                                         GPBFieldDescriptor *field) {
+id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, GPBFieldDescriptor *field) {
   if (self->messageStorage_ == nil) {
     return nil;
   }
@@ -676,80 +656,67 @@
 
 // Only exists for public api, no core code should use this.
 int32_t GPBGetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
-  #if defined(DEBUG) && DEBUG
-    NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
-              @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
-              field.name, [self class]);
-    NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
-              @"Attempting to get value of type Enum from field %@ "
-              @"of %@ which is of type %@.",
-              [self class], field.name,
-              TypeToString(GPBGetFieldDataType(field)));
-  #endif
+#if defined(DEBUG) && DEBUG
+  NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
+            @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
+  NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
+            @"Attempting to get value of type Enum from field %@ "
+            @"of %@ which is of type %@.",
+            [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
+#endif
 
   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]) {
+  if (!GPBFieldIsClosedEnum(field) && ![field isValidEnumValue:result]) {
     result = kGPBUnrecognizedEnumeratorValue;
   }
   return result;
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field,
-                            int32_t value) {
-  #if defined(DEBUG) && DEBUG
-    NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
-              @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
-              field.name, [self class]);
-    NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
-              @"Attempting to set field %@ of %@ which is of type %@ with "
-              @"value of type Enum.",
-              [self class], field.name,
-              TypeToString(GPBGetFieldDataType(field)));
-  #endif
+void GPBSetMessageEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) {
+#if defined(DEBUG) && DEBUG
+  NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
+            @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
+  NSCAssert(GPBGetFieldDataType(field) == GPBDataTypeEnum,
+            @"Attempting to set field %@ of %@ which is of type %@ with "
+            @"value of type Enum.",
+            [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
+#endif
   GPBSetEnumIvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self,
-                                    GPBFieldDescriptor *field, int32_t value) {
+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];
+                format:@"%@.%@: Attempt to set an unknown enum value (%d)", [self class],
+                       field.name, value];
   }
   GPBSetInt32IvarWithFieldPrivate(self, field, value);
 }
 
 // Only exists for public api, no core code should use this.
-int32_t GPBGetMessageRawEnumField(GPBMessage *self,
-                                  GPBFieldDescriptor *field) {
+int32_t GPBGetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field) {
   int32_t result = GPBGetMessageInt32Field(self, field);
   return result;
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field,
-                               int32_t value) {
+void GPBSetMessageRawEnumField(GPBMessage *self, GPBFieldDescriptor *field, int32_t value) {
   GPBSetInt32IvarWithFieldPrivate(self, field, value);
 }
 
-BOOL GPBGetMessageBoolField(GPBMessage *self,
-                            GPBFieldDescriptor *field) {
+BOOL GPBGetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field) {
 #if defined(DEBUG) && DEBUG
   NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
-            @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
-            field.name, [self class]);
+            @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
   NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
             @"Attempting to get value of type bool from field %@ "
             @"of %@ which is of type %@.",
-            [self class], field.name,
-            TypeToString(GPBGetFieldDataType(field)));
+            [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
 #endif
   if (GPBGetHasIvarField(self, field)) {
     // Bools are stored in the has bits to avoid needing explicit space in the
@@ -764,26 +731,20 @@
 }
 
 // Only exists for public api, no core code should use this.
-void GPBSetMessageBoolField(GPBMessage *self,
-                            GPBFieldDescriptor *field,
-                            BOOL value) {
+void GPBSetMessageBoolField(GPBMessage *self, GPBFieldDescriptor *field, BOOL value) {
   if (self == nil || field == nil) return;
-  #if defined(DEBUG) && DEBUG
-    NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
-              @"FieldDescriptor %@ doesn't appear to be for %@ messages.",
-              field.name, [self class]);
-    NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
-              @"Attempting to set field %@ of %@ which is of type %@ with "
-              @"value of type bool.",
-              [self class], field.name,
-              TypeToString(GPBGetFieldDataType(field)));
-  #endif
+#if defined(DEBUG) && DEBUG
+  NSCAssert([[self descriptor] fieldWithNumber:field.number] == field,
+            @"FieldDescriptor %@ doesn't appear to be for %@ messages.", field.name, [self class]);
+  NSCAssert(DataTypesEquivalent(GPBGetFieldDataType(field), GPBDataTypeBool),
+            @"Attempting to set field %@ of %@ which is of type %@ with "
+            @"value of type bool.",
+            [self class], field.name, TypeToString(GPBGetFieldDataType(field)));
+#endif
   GPBSetBoolIvarWithFieldPrivate(self, field, value);
 }
 
-void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self,
-                                    GPBFieldDescriptor *field,
-                                    BOOL value) {
+void GPBSetBoolIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field, BOOL value) {
   GPBMessageFieldDescription *fieldDesc = field->description_;
   GPBOneofDescriptor *oneof = field->containingOneof_;
   if (oneof) {
@@ -798,15 +759,15 @@
 
   // 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));
+  BOOL hasValue = ((value != (BOOL)0) || ((fieldDesc->flags & GPBFieldClearHasIvarOnZero) == 0));
   GPBSetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number, hasValue);
   GPBBecomeVisibleToAutocreator(self);
 }
 
+// clang-format off
+
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int32, int32_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 int32_t GPBGetMessageInt32Field(GPBMessage *self,
                                 GPBFieldDescriptor *field) {
@@ -876,10 +837,8 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt32, uint32_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 uint32_t GPBGetMessageUInt32Field(GPBMessage *self,
                                   GPBFieldDescriptor *field) {
@@ -949,10 +908,8 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Int64, int64_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 int64_t GPBGetMessageInt64Field(GPBMessage *self,
                                 GPBFieldDescriptor *field) {
@@ -1022,10 +979,8 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(UInt64, uint64_t)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 uint64_t GPBGetMessageUInt64Field(GPBMessage *self,
                                   GPBFieldDescriptor *field) {
@@ -1095,10 +1050,8 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Float, float)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 float GPBGetMessageFloatField(GPBMessage *self,
                               GPBFieldDescriptor *field) {
@@ -1168,10 +1121,8 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_POD_ACCESSORS_DEFN(Double, double)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 double GPBGetMessageDoubleField(GPBMessage *self,
                                 GPBFieldDescriptor *field) {
@@ -1241,14 +1192,12 @@
   GPBBecomeVisibleToAutocreator(self);
 }
 
-// clang-format on
 //%PDDM-EXPAND-END (6 expansions)
 
 // Aliases are function calls that are virtually the same.
 
 //%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(String, NSString)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // Only exists for public api, no core code should use this.
 NSString *GPBGetMessageStringField(GPBMessage *self,
@@ -1279,10 +1228,8 @@
   GPBSetCopyObjectIvarWithField(self, field, (id)value);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_ALIAS_DEFN_COPY_OBJECT(Bytes, NSData)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // Only exists for public api, no core code should use this.
 NSData *GPBGetMessageBytesField(GPBMessage *self,
@@ -1313,10 +1260,8 @@
   GPBSetCopyObjectIvarWithField(self, field, (id)value);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Message, GPBMessage)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // Only exists for public api, no core code should use this.
 GPBMessage *GPBGetMessageMessageField(GPBMessage *self,
@@ -1347,10 +1292,8 @@
   GPBSetObjectIvarWithField(self, field, (id)value);
 }
 
-// clang-format on
 //%PDDM-EXPAND IVAR_ALIAS_DEFN_OBJECT(Group, GPBMessage)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // Only exists for public api, no core code should use this.
 GPBMessage *GPBGetMessageGroupField(GPBMessage *self,
@@ -1381,9 +1324,10 @@
   GPBSetObjectIvarWithField(self, field, (id)value);
 }
 
-// clang-format on
 //%PDDM-EXPAND-END (4 expansions)
 
+// clang-format on
+
 // GPBGetMessageRepeatedField is defined in GPBMessage.m
 
 // Only exists for public api, no core code should use this.
@@ -1391,8 +1335,7 @@
 #if defined(DEBUG) && DEBUG
   if (field.fieldType != GPBFieldTypeRepeated) {
     [NSException raise:NSInvalidArgumentException
-                format:@"%@.%@ is not a repeated field.",
-                       [self class], field.name];
+                format:@"%@.%@ is not a repeated field.", [self class], field.name];
   }
   Class expectedClass = Nil;
   switch (GPBGetFieldDataType(field)) {
@@ -1435,8 +1378,8 @@
   }
   if (array && ![array isKindOfClass:expectedClass]) {
     [NSException raise:NSInvalidArgumentException
-                format:@"%@.%@: Expected %@ object, got %@.",
-                       [self class], field.name, expectedClass, [array class]];
+                format:@"%@.%@: Expected %@ object, got %@.", [self class], field.name,
+                       expectedClass, [array class]];
   }
 #endif
   GPBSetObjectIvarWithField(self, field, array);
@@ -1468,7 +1411,7 @@
     case GPBDataTypeBytes:
     case GPBDataTypeString:
       return type;
-   }
+  }
 }
 
 static BOOL DataTypesEquivalent(GPBDataType type1, GPBDataType type2) {
@@ -1510,13 +1453,11 @@
 // GPBGetMessageMapField is defined in GPBMessage.m
 
 // Only exists for public api, no core code should use this.
-void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field,
-                           id dictionary) {
+void GPBSetMessageMapField(GPBMessage *self, GPBFieldDescriptor *field, id dictionary) {
 #if defined(DEBUG) && DEBUG
   if (field.fieldType != GPBFieldTypeMap) {
     [NSException raise:NSInvalidArgumentException
-                format:@"%@.%@ is not a map<> field.",
-                       [self class], field.name];
+                format:@"%@.%@ is not a map<> field.", [self class], field.name];
   }
   if (dictionary) {
     GPBDataType keyDataType = field.mapKeyDataType;
@@ -1527,20 +1468,17 @@
       keyStr = @"String";
     }
     Class expectedClass = Nil;
-    if ((keyDataType == GPBDataTypeString) &&
-        GPBDataTypeIsObject(valueDataType)) {
+    if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
       expectedClass = [NSMutableDictionary class];
     } else {
-      NSString *className =
-          [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
+      NSString *className = [NSString stringWithFormat:@"GPB%@%@Dictionary", keyStr, valueStr];
       expectedClass = NSClassFromString(className);
       NSCAssert(expectedClass, @"Missing a class (%@)?", expectedClass);
     }
     if (![dictionary isKindOfClass:expectedClass]) {
       [NSException raise:NSInvalidArgumentException
-                  format:@"%@.%@: Expected %@ object, got %@.",
-                         [self class], field.name, expectedClass,
-                         [dictionary class]];
+                  format:@"%@.%@: Expected %@ object, got %@.", [self class], field.name,
+                         expectedClass, [dictionary class]];
     }
   }
 #endif
@@ -1550,13 +1488,12 @@
 #pragma mark - Misc Dynamic Runtime Utils
 
 const char *GPBMessageEncodingForSelector(SEL selector, BOOL instanceSel) {
-  Protocol *protocol =
-      objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
+  Protocol *protocol = objc_getProtocol(GPBStringifySymbol(GPBMessageSignatureProtocol));
   NSCAssert(protocol, @"Missing GPBMessageSignatureProtocol");
   struct objc_method_description description =
       protocol_getMethodDescription(protocol, selector, NO, instanceSel);
-  NSCAssert(description.name != Nil && description.types != nil,
-            @"Missing method for selector %@", NSStringFromSelector(selector));
+  NSCAssert(description.name != Nil && description.types != nil, @"Missing method for selector %@",
+            NSStringFromSelector(selector));
   return description.types;
 }
 
@@ -1568,19 +1505,30 @@
   for (NSUInteger i = 0; i < len; ++i) {
     unichar aChar = [toPrint characterAtIndex:i];
     switch (aChar) {
-      case '\n': [destStr appendString:@"\\n"];  break;
-      case '\r': [destStr appendString:@"\\r"];  break;
-      case '\t': [destStr appendString:@"\\t"];  break;
-      case '\"': [destStr appendString:@"\\\""]; break;
-      case '\'': [destStr appendString:@"\\\'"]; break;
-      case '\\': [destStr appendString:@"\\\\"]; break;
+      case '\n':
+        [destStr appendString:@"\\n"];
+        break;
+      case '\r':
+        [destStr appendString:@"\\r"];
+        break;
+      case '\t':
+        [destStr appendString:@"\\t"];
+        break;
+      case '\"':
+        [destStr appendString:@"\\\""];
+        break;
+      case '\'':
+        [destStr appendString:@"\\\'"];
+        break;
+      case '\\':
+        [destStr appendString:@"\\\\"];
+        break;
       default:
         // This differs slightly from the C++ code in that the C++ doesn't
         // generate UTF8; it looks at the string in UTF8, but escapes every
         // byte > 0x7E.
         if (aChar < 0x20) {
-          [destStr appendFormat:@"\\%d%d%d",
-                                (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
+          [destStr appendFormat:@"\\%d%d%d", (aChar / 64), ((aChar % 64) / 8), (aChar % 8)];
         } else {
           [destStr appendFormat:@"%C", aChar];
         }
@@ -1596,12 +1544,24 @@
   [destStr appendString:@"\""];
   for (const char *srcEnd = src + srcLen; src < srcEnd; src++) {
     switch (*src) {
-      case '\n': [destStr appendString:@"\\n"];  break;
-      case '\r': [destStr appendString:@"\\r"];  break;
-      case '\t': [destStr appendString:@"\\t"];  break;
-      case '\"': [destStr appendString:@"\\\""]; break;
-      case '\'': [destStr appendString:@"\\\'"]; break;
-      case '\\': [destStr appendString:@"\\\\"]; break;
+      case '\n':
+        [destStr appendString:@"\\n"];
+        break;
+      case '\r':
+        [destStr appendString:@"\\r"];
+        break;
+      case '\t':
+        [destStr appendString:@"\\t"];
+        break;
+      case '\"':
+        [destStr appendString:@"\\\""];
+        break;
+      case '\'':
+        [destStr appendString:@"\\\'"];
+        break;
+      case '\\':
+        [destStr appendString:@"\\\\"];
+        break;
       default:
         if (isprint(*src)) {
           [destStr appendFormat:@"%c", *src];
@@ -1617,31 +1577,28 @@
   [destStr appendString:@"\""];
 }
 
-static void AppendTextFormatForMapMessageField(
-    id map, GPBFieldDescriptor *field, NSMutableString *toStr,
-    NSString *lineIndent, NSString *fieldName, NSString *lineEnding) {
+static void AppendTextFormatForMapMessageField(id map, GPBFieldDescriptor *field,
+                                               NSMutableString *toStr, NSString *lineIndent,
+                                               NSString *fieldName, NSString *lineEnding) {
   GPBDataType keyDataType = field.mapKeyDataType;
   GPBDataType valueDataType = GPBGetFieldDataType(field);
   BOOL isMessageValue = GPBDataTypeIsMessage(valueDataType);
 
   NSString *msgStartFirst =
       [NSString stringWithFormat:@"%@%@ {%@\n", lineIndent, fieldName, lineEnding];
-  NSString *msgStart =
-      [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
+  NSString *msgStart = [NSString stringWithFormat:@"%@%@ {\n", lineIndent, fieldName];
   NSString *msgEnd = [NSString stringWithFormat:@"%@}\n", lineIndent];
 
   NSString *keyLine = [NSString stringWithFormat:@"%@  key: ", lineIndent];
-  NSString *valueLine = [NSString stringWithFormat:@"%@  value%s ", lineIndent,
-                                                   (isMessageValue ? "" : ":")];
+  NSString *valueLine =
+      [NSString stringWithFormat:@"%@  value%s ", lineIndent, (isMessageValue ? "" : ":")];
 
   __block BOOL isFirst = YES;
 
-  if ((keyDataType == GPBDataTypeString) &&
-      GPBDataTypeIsObject(valueDataType)) {
+  if ((keyDataType == GPBDataTypeString) && GPBDataTypeIsObject(valueDataType)) {
     // map is an NSDictionary.
     NSDictionary *dict = map;
-    [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, BOOL *stop) {
-      #pragma unused(stop)
+    [dict enumerateKeysAndObjectsUsingBlock:^(NSString *key, id value, __unused BOOL *stop) {
       [toStr appendString:(isFirst ? msgStartFirst : msgStart)];
       isFirst = NO;
 
@@ -1741,10 +1698,8 @@
   }
 }
 
-static void AppendTextFormatForMessageField(GPBMessage *message,
-                                            GPBFieldDescriptor *field,
-                                            NSMutableString *toStr,
-                                            NSString *lineIndent) {
+static void AppendTextFormatForMessageField(GPBMessage *message, GPBFieldDescriptor *field,
+                                            NSMutableString *toStr, NSString *lineIndent) {
   id arrayOrMap;
   NSUInteger count;
   GPBFieldType fieldType = field.fieldType;
@@ -1792,8 +1747,7 @@
   }
 
   if (fieldType == GPBFieldTypeMap) {
-    AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent,
-                                       fieldName, lineEnding);
+    AppendTextFormatForMapMessageField(arrayOrMap, field, toStr, lineIndent, fieldName, lineEnding);
     return;
   }
 
@@ -1804,8 +1758,7 @@
   BOOL isMessageField = GPBDataTypeIsMessage(fieldDataType);
   for (NSUInteger j = 0; j < count; ++j) {
     // Start the line.
-    [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName,
-                        (isMessageField ? "" : ":")];
+    [toStr appendFormat:@"%@%@%s ", lineIndent, fieldName, (isMessageField ? "" : ":")];
 
     // The value.
     switch (fieldDataType) {
@@ -1871,9 +1824,8 @@
 
       case GPBDataTypeGroup:
       case GPBDataTypeMessage: {
-        GPBMessage *v =
-            (isRepeated ? [(NSArray *)array objectAtIndex:j]
-                        : GPBGetObjectIvarWithField(message, field));
+        GPBMessage *v = (isRepeated ? [(NSArray *)array objectAtIndex:j]
+                                    : GPBGetObjectIvarWithField(message, field));
         [toStr appendFormat:@"{%@\n", lineEnding];
         NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
         AppendTextFormatForMessage(v, toStr, subIndent);
@@ -1890,11 +1842,9 @@
   }  // for(count)
 }
 
-static void AppendTextFormatForMessageExtensionRange(GPBMessage *message,
-                                                     NSArray *activeExtensions,
+static void AppendTextFormatForMessageExtensionRange(GPBMessage *message, NSArray *activeExtensions,
                                                      GPBExtensionRange range,
-                                                     NSMutableString *toStr,
-                                                     NSString *lineIndent) {
+                                                     NSMutableString *toStr, NSString *lineIndent) {
   uint32_t start = range.start;
   uint32_t end = range.end;
   for (GPBExtensionDescriptor *extension in activeExtensions) {
@@ -1963,8 +1913,7 @@
 #undef FIELD_CASE
 
         case GPBDataTypeBool:
-          [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true"
-                                                                : @"false")];
+          [toStr appendString:([(NSNumber *)curValue boolValue] ? @"true" : @"false")];
           break;
 
         case GPBDataTypeString:
@@ -1995,32 +1944,29 @@
   }  // for..in(activeExtensions)
 }
 
-static void AppendTextFormatForMessage(GPBMessage *message,
-                                       NSMutableString *toStr,
+static void AppendTextFormatForMessage(GPBMessage *message, NSMutableString *toStr,
                                        NSString *lineIndent) {
   GPBDescriptor *descriptor = [message descriptor];
   NSArray *fieldsArray = descriptor->fields_;
   NSUInteger fieldCount = fieldsArray.count;
   const GPBExtensionRange *extensionRanges = descriptor.extensionRanges;
   NSUInteger extensionRangesCount = descriptor.extensionRangesCount;
-  NSArray *activeExtensions = [[message extensionsCurrentlySet]
-      sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
+  NSArray *activeExtensions =
+      [[message extensionsCurrentlySet] sortedArrayUsingSelector:@selector(compareByFieldNumber:)];
   for (NSUInteger i = 0, j = 0; i < fieldCount || j < extensionRangesCount;) {
     if (i == fieldCount) {
-      AppendTextFormatForMessageExtensionRange(
-          message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
+      AppendTextFormatForMessageExtensionRange(message, activeExtensions, extensionRanges[j++],
+                                               toStr, lineIndent);
     } else if (j == extensionRangesCount ||
                GPBFieldNumber(fieldsArray[i]) < extensionRanges[j].start) {
-      AppendTextFormatForMessageField(message, fieldsArray[i++], toStr,
-                                      lineIndent);
+      AppendTextFormatForMessageField(message, fieldsArray[i++], toStr, lineIndent);
     } else {
-      AppendTextFormatForMessageExtensionRange(
-          message, activeExtensions, extensionRanges[j++], toStr, lineIndent);
+      AppendTextFormatForMessageExtensionRange(message, activeExtensions, extensionRanges[j++],
+                                               toStr, lineIndent);
     }
   }
 
-  NSString *unknownFieldsStr =
-      GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
+  NSString *unknownFieldsStr = GPBTextFormatForUnknownFieldSet(message.unknownFields, lineIndent);
   if ([unknownFieldsStr length] > 0) {
     [toStr appendFormat:@"%@# --- Unknown fields ---\n", lineIndent];
     [toStr appendString:unknownFieldsStr];
@@ -2036,8 +1982,7 @@
   return buildString;
 }
 
-NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet,
-                                          NSString *lineIndent) {
+NSString *GPBTextFormatForUnknownFieldSet(GPBUnknownFieldSet *unknownSet, NSString *lineIndent) {
   if (unknownSet == nil) return @"";
   if (lineIndent == nil) lineIndent = @"";
 
@@ -2045,17 +1990,15 @@
   for (GPBUnknownField *field in [unknownSet sortedFields]) {
     int32_t fieldNumber = [field number];
 
-#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT)                                   \
-  [field.PROPNAME                                                             \
-      enumerateValuesWithBlock:^(CTYPE value, NSUInteger idx, BOOL * stop) {  \
-    _Pragma("unused(idx, stop)");                                             \
-    [result                                                                   \
-        appendFormat:@"%@%d: " #FORMAT "\n", lineIndent, fieldNumber, value]; \
+#define PRINT_LOOP(PROPNAME, CTYPE, FORMAT)                                                    \
+  [field.PROPNAME                                                                              \
+      enumerateValuesWithBlock:^(CTYPE value, __unused NSUInteger idx, __unused BOOL * stop) { \
+        [result appendFormat:@"%@%d: " FORMAT "\n", lineIndent, fieldNumber, value];           \
       }];
 
-    PRINT_LOOP(varintList, uint64_t, %llu);
-    PRINT_LOOP(fixed32List, uint32_t, 0x%X);
-    PRINT_LOOP(fixed64List, uint64_t, 0x%llX);
+    PRINT_LOOP(varintList, uint64_t, "%llu");
+    PRINT_LOOP(fixed32List, uint32_t, "0x%X");
+    PRINT_LOOP(fixed64List, uint64_t, "0x%llX");
 
 #undef PRINT_LOOP
 
@@ -2070,8 +2013,7 @@
     for (GPBUnknownFieldSet *subUnknownSet in field.groupList) {
       [result appendFormat:@"%@%d: {\n", lineIndent, fieldNumber];
       NSString *subIndent = [lineIndent stringByAppendingString:@"  "];
-      NSString *subUnknownSetStr =
-          GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
+      NSString *subUnknownSetStr = GPBTextFormatForUnknownFieldSet(subUnknownSet, subIndent);
       [result appendString:subUnknownSetStr];
       [result appendFormat:@"%@}\n", lineIndent];
     }
@@ -2114,8 +2056,7 @@
               return result;
             }
           }
-          [NSException raise:NSParseErrorException
-                      format:@"Unable to read varint32"];
+          [NSException raise:NSParseErrorException format:@"Unable to read varint32"];
         }
       }
     }
@@ -2123,8 +2064,7 @@
   return result;
 }
 
-NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key,
-                                  NSString *inputStr) {
+NSString *GPBDecodeTextFormatName(const uint8_t *decodeData, int32_t key, NSString *inputStr) {
   // decodData form:
   //  varint32: num entries
   //  for each entry:
@@ -2182,15 +2122,14 @@
     return result;
   }
 
-  NSMutableString *result =
-      [NSMutableString stringWithCapacity:[inputStr length]];
+  NSMutableString *result = [NSMutableString stringWithCapacity:[inputStr length]];
 
-  const uint8_t kAddUnderscore  = 0b10000000;
-  const uint8_t kOpMask         = 0b01100000;
+  const uint8_t kAddUnderscore = 0b10000000;
+  const uint8_t kOpMask = 0b01100000;
   // const uint8_t kOpAsIs        = 0b00000000;
-  const uint8_t kOpFirstUpper     = 0b01000000;
-  const uint8_t kOpFirstLower     = 0b00100000;
-  const uint8_t kOpAllUpper       = 0b01100000;
+  const uint8_t kOpFirstUpper = 0b01000000;
+  const uint8_t kOpFirstLower = 0b00100000;
+  const uint8_t kOpAllUpper = 0b01100000;
   const uint8_t kSegmentLenMask = 0b00011111;
 
   NSInteger i = 0;
@@ -2233,26 +2172,21 @@
 #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)
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int32_t value,
+                                      __unused GPBFileSyntax 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
+void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof, int32_t oneofHasIndex,
+                        __unused uint32_t 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 __unused = 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);
 }
 
diff --git a/objectivec/GPBUtilities_PackagePrivate.h b/objectivec/GPBUtilities_PackagePrivate.h
index 3d3d734..f04ed83 100644
--- a/objectivec/GPBUtilities_PackagePrivate.h
+++ b/objectivec/GPBUtilities_PackagePrivate.h
@@ -40,17 +40,15 @@
 #define GPBStringify(S) #S
 #define GPBStringifySymbol(S) GPBStringify(S)
 
-#define GPBNSStringify(S) @#S
+#define GPBNSStringify(S) @ #S
 #define GPBNSStringifySymbol(S) GPBNSStringify(S)
 
 // Macros for generating a Class from a class name. These are used in
 // the generated GPB descriptor classes wherever an Objective C class
 // reference is needed for a generated class.
 #define GPBObjCClassSymbol(name) OBJC_CLASS_$_##name
-#define GPBObjCClass(name) \
-    ((__bridge Class)&(GPBObjCClassSymbol(name)))
-#define GPBObjCClassDeclaration(name) \
-    extern const GPBObjcClass_t GPBObjCClassSymbol(name)
+#define GPBObjCClass(name) ((__bridge Class) & (GPBObjCClassSymbol(name)))
+#define GPBObjCClassDeclaration(name) extern const GPBObjcClass_t GPBObjCClassSymbol(name)
 
 // Constant to internally mark when there is no has bit.
 #define GPBNoHasBit INT32_MAX
@@ -120,7 +118,7 @@
 // negative values must be sign-extended to 64 bits to be varint encoded,
 // thus always taking 10 bytes on the wire.)
 GPB_INLINE int32_t GPBDecodeZigZag32(uint32_t n) {
-  return (int32_t)(GPBLogicalRightShift32((int32_t)n, 1) ^ -((int32_t)(n) & 1));
+  return (int32_t)(GPBLogicalRightShift32((int32_t)n, 1) ^ -((int32_t)(n)&1));
 }
 
 // Decode a ZigZag-encoded 64-bit value.  ZigZag encodes signed integers
@@ -128,7 +126,7 @@
 // negative values must be sign-extended to 64 bits to be varint encoded,
 // thus always taking 10 bytes on the wire.)
 GPB_INLINE int64_t GPBDecodeZigZag64(uint64_t n) {
-  return (int64_t)(GPBLogicalRightShift64((int64_t)n, 1) ^ -((int64_t)(n) & 1));
+  return (int64_t)(GPBLogicalRightShift64((int64_t)n, 1) ^ -((int64_t)(n)&1));
 }
 
 // Encode a ZigZag-encoded 32-bit value.  ZigZag encodes signed integers
@@ -197,102 +195,84 @@
 }
 
 BOOL GPBGetHasIvar(GPBMessage *self, int32_t index, uint32_t fieldNumber);
-void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber,
-                   BOOL value);
+void GPBSetHasIvar(GPBMessage *self, int32_t idx, uint32_t fieldNumber, BOOL value);
 uint32_t GPBGetHasOneof(GPBMessage *self, int32_t index);
 
-GPB_INLINE BOOL
-GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) {
+GPB_INLINE BOOL GPBGetHasIvarField(GPBMessage *self, GPBFieldDescriptor *field) {
   GPBMessageFieldDescription *fieldDesc = field->description_;
   return GPBGetHasIvar(self, fieldDesc->hasIndex, fieldDesc->number);
 }
 
 #pragma clang diagnostic pop
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-DEFINE GPB_IVAR_SET_DECL(NAME, TYPE)
 //%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 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 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 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 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 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 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 GPBSetDoubleIvarWithFieldPrivate(GPBMessage *self,
                                       GPBFieldDescriptor *field,
                                       double value);
-// clang-format on
 //%PDDM-EXPAND-END (7 expansions)
 
-void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self,
-                                    GPBFieldDescriptor *field,
-                                    int32_t value);
+// clang-format on
+
+void GPBSetEnumIvarWithFieldPrivate(GPBMessage *self, GPBFieldDescriptor *field, int32_t value);
 
 id GPBGetObjectIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
 
-void GPBSetObjectIvarWithFieldPrivate(GPBMessage *self,
-                                      GPBFieldDescriptor *field, id value);
-void GPBSetRetainedObjectIvarWithFieldPrivate(GPBMessage *self,
-                                              GPBFieldDescriptor *field,
-                                              id __attribute__((ns_consumed))
-                                              value);
+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);
+id GPBGetObjectIvarWithFieldNoAutocreate(GPBMessage *self, GPBFieldDescriptor *field);
 
 // 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,
-                                             GPBFieldDescriptor *field);
+void GPBClearAutocreatedMessageIvarWithField(GPBMessage *self, GPBFieldDescriptor *field);
 
 // Returns an Objective C encoding for |selector|. |instanceSel| should be
 // YES if it's an instance selector (as opposed to a class selector).
@@ -302,17 +282,13 @@
 // Helper for text format name encoding.
 // 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);
-
+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,
+void GPBSetInt32IvarWithFieldInternal(GPBMessage *self, GPBFieldDescriptor *field, int32_t value,
                                       GPBFileSyntax syntax);
-void GPBMaybeClearOneof(GPBMessage *self, GPBOneofDescriptor *oneof,
-                        int32_t oneofHasIndex, uint32_t fieldNumberNotToClear);
+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
diff --git a/objectivec/GPBWellKnownTypes.h b/objectivec/GPBWellKnownTypes.h
index 80d9db0..765ad24 100644
--- a/objectivec/GPBWellKnownTypes.h
+++ b/objectivec/GPBWellKnownTypes.h
@@ -141,8 +141,7 @@
  *
  * @return A newly configured GPBAny with the given message, or nil on failure.
  */
-+ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message
-                                  error:(NSError **)errorPtr;
++ (nullable instancetype)anyWithMessage:(nonnull GPBMessage *)message error:(NSError **)errorPtr;
 
 /**
  * Convenience method to create a GPBAny containing the serialized message.
@@ -168,8 +167,7 @@
  *
  * @return A newly configured GPBAny with the given message, or nil on failure.
  */
-- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message
-                                   error:(NSError **)errorPtr;
+- (nullable instancetype)initWithMessage:(nonnull GPBMessage *)message error:(NSError **)errorPtr;
 
 /**
  * Initializes a GPBAny to contain the serialized message.
@@ -195,8 +193,7 @@
  *
  * @return Whether the packing was successful or not.
  */
-- (BOOL)packWithMessage:(nonnull GPBMessage *)message
-                  error:(NSError **)errorPtr;
+- (BOOL)packWithMessage:(nonnull GPBMessage *)message error:(NSError **)errorPtr;
 
 /**
  * Packs the serialized message into this GPBAny.
@@ -225,8 +222,7 @@
  * @return An instance of the given class populated with the contained data, or
  *         nil on failure.
  */
-- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass
-                                      error:(NSError **)errorPtr;
+- (nullable GPBMessage *)unpackMessageClass:(Class)messageClass error:(NSError **)errorPtr;
 
 @end
 
diff --git a/objectivec/GPBWellKnownTypes.m b/objectivec/GPBWellKnownTypes.m
index 2808afe..90e82d3 100644
--- a/objectivec/GPBWellKnownTypes.m
+++ b/objectivec/GPBWellKnownTypes.m
@@ -36,18 +36,15 @@
 
 #import "GPBUtilities_PackagePrivate.h"
 
-NSString *const GPBWellKnownTypesErrorDomain =
-    GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain);
+NSString *const GPBWellKnownTypesErrorDomain = GPBNSStringifySymbol(GPBWellKnownTypesErrorDomain);
 
 static NSString *kTypePrefixGoogleApisCom = @"type.googleapis.com/";
 
-static NSTimeInterval TimeIntervalFromSecondsAndNanos(int64_t seconds,
-                                                      int32_t nanos) {
+static NSTimeInterval TimeIntervalFromSecondsAndNanos(int64_t seconds, int32_t nanos) {
   return seconds + (NSTimeInterval)nanos / 1e9;
 }
 
-static int32_t SecondsAndNanosFromTimeInterval(NSTimeInterval time,
-                                               int64_t *outSeconds,
+static int32_t SecondsAndNanosFromTimeInterval(NSTimeInterval time, int64_t *outSeconds,
                                                BOOL nanosMustBePositive) {
   NSTimeInterval seconds;
   NSTimeInterval nanos = modf(time, &seconds);
@@ -79,8 +76,7 @@
 
 static NSString *ParseTypeFromURL(NSString *typeURLString) {
   NSRange range = [typeURLString rangeOfString:@"/" options:NSBackwardsSearch];
-  if ((range.location == NSNotFound) ||
-      (NSMaxRange(range) == typeURLString.length)) {
+  if ((range.location == NSNotFound) || (NSMaxRange(range) == typeURLString.length)) {
     return nil;
   }
   NSString *result = [typeURLString substringFromIndex:range.location + 1];
@@ -98,8 +94,7 @@
 - (instancetype)initWithTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
   if ((self = [super init])) {
     int64_t seconds;
-    int32_t nanos = SecondsAndNanosFromTimeInterval(
-        timeIntervalSince1970, &seconds, YES);
+    int32_t nanos = SecondsAndNanosFromTimeInterval(timeIntervalSince1970, &seconds, YES);
     self.seconds = seconds;
     self.nanos = nanos;
   }
@@ -120,8 +115,7 @@
 
 - (void)setTimeIntervalSince1970:(NSTimeInterval)timeIntervalSince1970 {
   int64_t seconds;
-  int32_t nanos =
-      SecondsAndNanosFromTimeInterval(timeIntervalSince1970, &seconds, YES);
+  int32_t nanos = SecondsAndNanosFromTimeInterval(timeIntervalSince1970, &seconds, YES);
   self.seconds = seconds;
   self.nanos = nanos;
 }
@@ -135,8 +129,7 @@
 - (instancetype)initWithTimeInterval:(NSTimeInterval)timeInterval {
   if ((self = [super init])) {
     int64_t seconds;
-    int32_t nanos = SecondsAndNanosFromTimeInterval(
-        timeInterval, &seconds, NO);
+    int32_t nanos = SecondsAndNanosFromTimeInterval(timeInterval, &seconds, NO);
     self.seconds = seconds;
     self.nanos = nanos;
   }
@@ -153,8 +146,7 @@
 
 - (void)setTimeInterval:(NSTimeInterval)timeInterval {
   int64_t seconds;
-  int32_t nanos =
-      SecondsAndNanosFromTimeInterval(timeInterval, &seconds, NO);
+  int32_t nanos = SecondsAndNanosFromTimeInterval(timeInterval, &seconds, NO);
   self.seconds = seconds;
   self.nanos = nanos;
 }
@@ -173,26 +165,19 @@
 
 @implementation GPBAny (GBPWellKnownTypes)
 
-+ (instancetype)anyWithMessage:(GPBMessage *)message
-                         error:(NSError **)errorPtr {
-  return [self anyWithMessage:message
-                typeURLPrefix:kTypePrefixGoogleApisCom
-                        error:errorPtr];
++ (instancetype)anyWithMessage:(GPBMessage *)message error:(NSError **)errorPtr {
+  return [self anyWithMessage:message typeURLPrefix:kTypePrefixGoogleApisCom error:errorPtr];
 }
 
 + (instancetype)anyWithMessage:(GPBMessage *)message
                  typeURLPrefix:(NSString *)typeURLPrefix
                          error:(NSError **)errorPtr {
-  return [[[self alloc] initWithMessage:message
-                          typeURLPrefix:typeURLPrefix
+  return [[[self alloc] initWithMessage:message typeURLPrefix:typeURLPrefix
                                   error:errorPtr] autorelease];
 }
 
-- (instancetype)initWithMessage:(GPBMessage *)message
-                          error:(NSError **)errorPtr {
-  return [self initWithMessage:message
-                 typeURLPrefix:kTypePrefixGoogleApisCom
-                         error:errorPtr];
+- (instancetype)initWithMessage:(GPBMessage *)message error:(NSError **)errorPtr {
+  return [self initWithMessage:message typeURLPrefix:kTypePrefixGoogleApisCom error:errorPtr];
 }
 
 - (instancetype)initWithMessage:(GPBMessage *)message
@@ -200,9 +185,7 @@
                           error:(NSError **)errorPtr {
   self = [self init];
   if (self) {
-    if (![self packWithMessage:message
-                 typeURLPrefix:typeURLPrefix
-                         error:errorPtr]) {
+    if (![self packWithMessage:message typeURLPrefix:typeURLPrefix error:errorPtr]) {
       [self release];
       self = nil;
     }
@@ -210,11 +193,8 @@
   return self;
 }
 
-- (BOOL)packWithMessage:(GPBMessage *)message
-                  error:(NSError **)errorPtr {
-  return [self packWithMessage:message
-                 typeURLPrefix:kTypePrefixGoogleApisCom
-                         error:errorPtr];
+- (BOOL)packWithMessage:(GPBMessage *)message error:(NSError **)errorPtr {
+  return [self packWithMessage:message typeURLPrefix:kTypePrefixGoogleApisCom error:errorPtr];
 }
 
 - (BOOL)packWithMessage:(GPBMessage *)message
@@ -223,10 +203,9 @@
   NSString *fullName = [message descriptor].fullName;
   if (fullName.length == 0) {
     if (errorPtr) {
-      *errorPtr =
-          [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
-                              code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL
-                          userInfo:nil];
+      *errorPtr = [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
+                                      code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL
+                                  userInfo:nil];
     }
     return NO;
   }
@@ -238,15 +217,13 @@
   return YES;
 }
 
-- (GPBMessage *)unpackMessageClass:(Class)messageClass
-                             error:(NSError **)errorPtr {
+- (GPBMessage *)unpackMessageClass:(Class)messageClass error:(NSError **)errorPtr {
   NSString *fullName = [messageClass descriptor].fullName;
   if (fullName.length == 0) {
     if (errorPtr) {
-      *errorPtr =
-          [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
-                              code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL
-                      userInfo:nil];
+      *errorPtr = [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
+                                      code:GPBWellKnownTypesErrorCodeFailedToComputeTypeURL
+                                  userInfo:nil];
     }
     return nil;
   }
@@ -254,10 +231,9 @@
   NSString *expectedFullName = ParseTypeFromURL(self.typeURL);
   if ((expectedFullName == nil) || ![expectedFullName isEqual:fullName]) {
     if (errorPtr) {
-      *errorPtr =
-          [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
-                              code:GPBWellKnownTypesErrorCodeTypeURLMismatch
-                          userInfo:nil];
+      *errorPtr = [NSError errorWithDomain:GPBWellKnownTypesErrorDomain
+                                      code:GPBWellKnownTypesErrorCodeTypeURLMismatch
+                                  userInfo:nil];
     }
     return nil;
   }
@@ -265,8 +241,7 @@
   // Any is proto3, which means no extensions, so this assumes anything put
   // within an any also won't need extensions. A second helper could be added
   // if needed.
-  return [messageClass parseFromData:self.value
-                               error:errorPtr];
+  return [messageClass parseFromData:self.value error:errorPtr];
 }
 
 @end
diff --git a/objectivec/GPBWrappers.pbobjc.h b/objectivec/GPBWrappers.pbobjc.h
index e6741ae..11e220b 100644
--- a/objectivec/GPBWrappers.pbobjc.h
+++ b/objectivec/GPBWrappers.pbobjc.h
@@ -1,14 +1,15 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/wrappers.proto
 
 #import "GPBDescriptor.h"
 #import "GPBMessage.h"
 #import "GPBRootObject.h"
 
-#if GOOGLE_PROTOBUF_OBJC_VERSION < 30004
+#if GOOGLE_PROTOBUF_OBJC_VERSION < 30005
 #error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.
 #endif
-#if 30004 < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION
+#if 30005 < 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
 
@@ -205,3 +206,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/GPBWrappers.pbobjc.m b/objectivec/GPBWrappers.pbobjc.m
index b02a071..817a74c 100644
--- a/objectivec/GPBWrappers.pbobjc.m
+++ b/objectivec/GPBWrappers.pbobjc.m
@@ -1,4 +1,5 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
+// clang-format off
 // source: google/protobuf/wrappers.proto
 
 #import "GPBProtocolBuffers_RuntimeSupport.h"
@@ -67,7 +68,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBDoubleValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -112,7 +113,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBFloatValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -157,7 +158,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBInt64Value__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -202,7 +203,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBUInt64Value__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -247,7 +248,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBInt32Value__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -292,7 +293,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBUInt32Value__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -336,7 +337,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBBoolValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -381,7 +382,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBStringValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -426,7 +427,7 @@
                                         fields:fields
                                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
                                    storageSize:sizeof(GPBBytesValue__storage_)
-                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown)];
+                                         flags:(GPBDescriptorInitializationFlags)(GPBDescriptorInitializationFlag_UsesClassRefs | GPBDescriptorInitializationFlag_Proto3OptionalKnown | GPBDescriptorInitializationFlag_ClosedEnumSupportKnown)];
     #if defined(DEBUG) && DEBUG
       NSAssert(descriptor == nil, @"Startup recursed!");
     #endif  // DEBUG
@@ -441,3 +442,5 @@
 #pragma clang diagnostic pop
 
 // @@protoc_insertion_point(global_scope)
+
+// clang-format on
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
index 365fdc3..cb1a5bd 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 47;
+	objectVersion = 55;
 	objects = {
 
 /* Begin PBXBuildFile section */
@@ -26,7 +26,7 @@
 		8B8B615D17DF7056002EE618 /* GPBARCUnittestProtos.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */; settings = {COMPILER_FLAGS = "-fobjc-arc"; }; };
 		8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */; };
 		8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */; };
-		8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */; };
+		8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */; };
 		8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; };
 		8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; };
 		8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; };
@@ -61,8 +61,6 @@
 		F40EE4BF206BF8B90071091A /* GPBCompileTest21.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE486206BF8AF0071091A /* GPBCompileTest21.m */; };
 		F40EE4C0206BF8B90071091A /* GPBCompileTest22.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE48A206BF8B00071091A /* GPBCompileTest22.m */; };
 		F40EE4C1206BF8B90071091A /* GPBCompileTest23.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE487206BF8B00071091A /* GPBCompileTest23.m */; };
-		F40EE50B206C06640071091A /* GPBCompileTest24.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE508206C06440071091A /* GPBCompileTest24.m */; };
-		F40EE50C206C06640071091A /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE507206C06440071091A /* GPBCompileTest25.m */; };
 		F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; };
 		F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */; };
 		F4353D231ABB1537005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D211ABB1537005A6198 /* GPBDictionary.m */; };
@@ -141,7 +139,7 @@
 		7461B4E80F94F99000A0C422 /* GPBWireFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormat.m; sourceTree = "<group>"; };
 		7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libProtocolBuffers.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedInputStreamTests.m; sourceTree = "<group>"; };
-		7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOuputStreamTests.m; sourceTree = "<group>"; };
+		7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStreamTests.m; sourceTree = "<group>"; };
 		7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = "<group>"; };
 		7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = "<group>"; };
 		7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = "<group>"; };
@@ -161,21 +159,11 @@
 		8B42494D1A92A16600BC1EC6 /* timestamp.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = timestamp.proto; path = ../src/google/protobuf/timestamp.proto; sourceTree = "<group>"; };
 		8B79657814992E3E002FFBFC /* GPBRootObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBRootObject.h; sourceTree = "<group>"; };
 		8B79657914992E3E002FFBFC /* GPBRootObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBRootObject.m; sourceTree = "<group>"; };
-		8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_custom_options.proto; path = ../../src/google/protobuf/unittest_custom_options.proto; sourceTree = "<group>"; };
-		8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_embed_optimize_for.proto; path = ../../src/google/protobuf/unittest_embed_optimize_for.proto; sourceTree = "<group>"; };
-		8B7E6A7614893DBA00F8884A /* unittest_empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_empty.proto; path = ../../src/google/protobuf/unittest_empty.proto; sourceTree = "<group>"; };
-		8B7E6A7814893DBB00F8884A /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_import.proto; path = ../../src/google/protobuf/unittest_import.proto; sourceTree = "<group>"; };
-		8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_mset.proto; path = ../../src/google/protobuf/unittest_mset.proto; sourceTree = "<group>"; };
-		8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_no_generic_services.proto; path = ../../src/google/protobuf/unittest_no_generic_services.proto; sourceTree = "<group>"; };
-		8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_optimize_for.proto; path = ../../src/google/protobuf/unittest_optimize_for.proto; sourceTree = "<group>"; };
-		8B7E6A7E14893DBC00F8884A /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest.proto; path = ../../src/google/protobuf/unittest.proto; sourceTree = "<group>"; };
 		8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBARCUnittestProtos.m; sourceTree = "<group>"; };
 		8B96157214C8B06000A2AC0B /* GPBDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor.h; sourceTree = "<group>"; };
 		8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptor.m; sourceTree = "<group>"; };
-		8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = "<group>"; };
 		8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
-		8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
 		8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
 		8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
 		8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = "<group>"; };
@@ -205,8 +193,6 @@
 		F40EE491206BF8B10071091A /* GPBCompileTest03.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest03.m; sourceTree = "<group>"; };
 		F40EE492206BF8B10071091A /* GPBCompileTest06.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest06.m; sourceTree = "<group>"; };
 		F40EE493206BF8B20071091A /* GPBCompileTest11.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest11.m; sourceTree = "<group>"; };
-		F40EE507206C06440071091A /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
-		F40EE508206C06440071091A /* GPBCompileTest24.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest24.m; sourceTree = "<group>"; };
 		F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = "<group>"; };
 		F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = "<group>"; };
 		F4353D201ABB1537005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = "<group>"; };
@@ -229,6 +215,23 @@
 		F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = "<group>"; };
 		F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = "<group>"; };
 		F44929001C866B1900C2548A /* GPBCodedOutputStream_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedOutputStream_PackagePrivate.h; sourceTree = "<group>"; };
+		F44FEABE28B5465900EC57B3 /* unittest_deprecated_file.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_deprecated_file.proto; sourceTree = "<group>"; };
+		F44FEABF28B5465900EC57B3 /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_mset.proto; sourceTree = "<group>"; };
+		F44FEAC028B5465900EC57B3 /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_import.proto; sourceTree = "<group>"; };
+		F44FEAC228B5465900EC57B3 /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest.proto; sourceTree = "<group>"; };
+		F44FEAC428B5465900EC57B3 /* unittest_preserve_unknown_enum.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_preserve_unknown_enum.proto; sourceTree = "<group>"; };
+		F44FEAC528B5465900EC57B3 /* any_test.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = any_test.proto; sourceTree = "<group>"; };
+		F44FEAC628B5465900EC57B3 /* unittest_import_public.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_import_public.proto; sourceTree = "<group>"; };
+		F44FEAC728B5465900EC57B3 /* map_unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = map_unittest.proto; sourceTree = "<group>"; };
+		F44FEAC828B5465900EC57B3 /* unittest_extension_chain_g.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_g.proto; sourceTree = "<group>"; };
+		F44FEAC928B5465900EC57B3 /* unittest_extension_chain_e.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_e.proto; sourceTree = "<group>"; };
+		F44FEACA28B5465900EC57B3 /* unittest_extension_chain_d.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_d.proto; sourceTree = "<group>"; };
+		F44FEACB28B5465900EC57B3 /* unittest_extension_chain_a.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_a.proto; sourceTree = "<group>"; };
+		F44FEACC28B5465900EC57B3 /* unittest_extension_chain_c.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_c.proto; sourceTree = "<group>"; };
+		F44FEACD28B5465900EC57B3 /* unittest_deprecated.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_deprecated.proto; sourceTree = "<group>"; };
+		F44FEACE28B5465A00EC57B3 /* unittest_extension_chain_b.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_b.proto; sourceTree = "<group>"; };
+		F44FEACF28B5465A00EC57B3 /* map_proto2_unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = map_proto2_unittest.proto; sourceTree = "<group>"; };
+		F44FEAD028B5465A00EC57B3 /* unittest_extension_chain_f.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_f.proto; sourceTree = "<group>"; };
 		F451D3F51A8AAE8700B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = "<group>"; };
 		F4584D7E1ECCB38900803AB6 /* GPBExtensionRegistryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionRegistryTest.m; sourceTree = "<group>"; };
 		F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = "<group>"; };
@@ -442,12 +445,13 @@
 		7461B6940F94FDDD00A0C422 /* Tests */ = {
 			isa = PBXGroup;
 			children = (
+				F44FEAC528B5465900EC57B3 /* any_test.proto */,
 				8B210CCD159383D60032D72D /* golden_message */,
 				8B210CCF159386920032D72D /* golden_packed_fields_message */,
 				8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */,
 				F401DC321A8E5C0200FCC765 /* GPBArrayTests.m */,
 				7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */,
-				7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */,
+				7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */,
 				F40EE488206BF8B00071091A /* GPBCompileTest01.m */,
 				F40EE481206BF8AE0071091A /* GPBCompileTest02.m */,
 				F40EE491206BF8B10071091A /* GPBCompileTest03.m */,
@@ -471,8 +475,6 @@
 				F40EE486206BF8AF0071091A /* GPBCompileTest21.m */,
 				F40EE48A206BF8B00071091A /* GPBCompileTest22.m */,
 				F40EE487206BF8B00071091A /* GPBCompileTest23.m */,
-				F40EE508206C06440071091A /* GPBCompileTest24.m */,
-				F40EE507206C06440071091A /* GPBCompileTest25.m */,
 				5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
 				F4353D1C1AB8822D005A6198 /* GPBDescriptorTests.m */,
 				F4C4B9E21E1D974F00D3B61D /* GPBDictionaryTests.m */,
@@ -485,9 +487,9 @@
 				F4353D321AC06F10005A6198 /* GPBDictionaryTests+UInt64.m */,
 				F4584D7E1ECCB38900803AB6 /* GPBExtensionRegistryTest.m */,
 				7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
+				8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */,
 				F4487C821AAF6AB300531423 /* GPBMessageTests+Merge.m */,
 				F4487C741AADF7F500531423 /* GPBMessageTests+Runtime.m */,
-				8BFF9D1923AD582200E63E32 /* GPBMessageTests+ClassNames.m */,
 				F4487C7E1AAF62CD00531423 /* GPBMessageTests+Serialization.m */,
 				F4B51B1D1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm */,
 				F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
@@ -500,25 +502,31 @@
 				7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
 				8B4248DB1A92933A00BC1EC6 /* GPBWellKnownTypesTest.m */,
 				7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
+				F44FEACF28B5465A00EC57B3 /* map_proto2_unittest.proto */,
+				F44FEAC728B5465900EC57B3 /* map_unittest.proto */,
 				F4F53F89219CC4F2001EABF4 /* text_format_extensions_unittest_data.txt */,
 				F45E57C61AE6DC6A000B7D99 /* text_format_map_unittest_data.txt */,
 				F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */,
-				8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */,
 				F4AC9E1D1A8BEB3500BD6E83 /* unittest_cycle.proto */,
-				8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */,
-				8B7E6A7614893DBA00F8884A /* unittest_empty.proto */,
-				8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */,
-				8B7E6A7814893DBB00F8884A /* unittest_import.proto */,
-				8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */,
-				8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */,
-				8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */,
+				F44FEABE28B5465900EC57B3 /* unittest_deprecated_file.proto */,
+				F44FEACD28B5465900EC57B3 /* unittest_deprecated.proto */,
+				F44FEACB28B5465900EC57B3 /* unittest_extension_chain_a.proto */,
+				F44FEACE28B5465A00EC57B3 /* unittest_extension_chain_b.proto */,
+				F44FEACC28B5465900EC57B3 /* unittest_extension_chain_c.proto */,
+				F44FEACA28B5465900EC57B3 /* unittest_extension_chain_d.proto */,
+				F44FEAC928B5465900EC57B3 /* unittest_extension_chain_e.proto */,
+				F44FEAD028B5465A00EC57B3 /* unittest_extension_chain_f.proto */,
+				F44FEAC828B5465900EC57B3 /* unittest_extension_chain_g.proto */,
+				F44FEAC628B5465900EC57B3 /* unittest_import_public.proto */,
+				F44FEAC028B5465900EC57B3 /* unittest_import.proto */,
+				F44FEABF28B5465900EC57B3 /* unittest_mset.proto */,
 				8B35468421A616F6000BD30D /* unittest_objc_options.proto */,
 				F4CF31701B162ED800BD9B06 /* unittest_objc_startup.proto */,
 				8B09AAF614B663A7007B4184 /* unittest_objc.proto */,
-				8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */,
+				F44FEAC428B5465900EC57B3 /* unittest_preserve_unknown_enum.proto */,
 				F4487C781AADFB3100531423 /* unittest_runtime_proto2.proto */,
 				F4487C791AADFB3200531423 /* unittest_runtime_proto3.proto */,
-				8B7E6A7E14893DBC00F8884A /* unittest.proto */,
+				F44FEAC228B5465900EC57B3 /* unittest.proto */,
 				8B4248B91A8C256900BC1EC6 /* UnitTests-Bridging-Header.h */,
 				7401C1A90F950347006D8281 /* UnitTests-Info.plist */,
 			);
@@ -643,10 +651,10 @@
 			attributes = {
 				LastSwiftUpdateCheck = 0710;
 				LastTestingUpgradeCheck = 0600;
-				LastUpgradeCheck = 0930;
+				LastUpgradeCheck = 1400;
 				TargetAttributes = {
 					8BBEA4A5147C727100C4ADB7 = {
-						LastSwiftMigration = 0940;
+						LastSwiftMigration = "";
 						TestTargetID = 8B9A5EA41831993600A9D33B;
 					};
 					F45BBC141B0CE3C6002D064D = {
@@ -655,12 +663,12 @@
 				};
 			};
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_OSX" */;
-			compatibilityVersion = "Xcode 6.3";
-			developmentRegion = English;
+			compatibilityVersion = "Xcode 13.0";
+			developmentRegion = en;
 			hasScannedForEncodings = 1;
 			knownRegions = (
-				English,
 				en,
+				Base,
 			);
 			mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
 			projectDirPath = "";
@@ -692,6 +700,7 @@
 /* Begin PBXShellScriptBuildPhase section */
 		F4B62A781AF91F6000AFCEDC /* Script: Check Runtime Stamps */ = {
 			isa = PBXShellScriptBuildPhase;
+			alwaysOutOfDate = 1;
 			buildActionMask = 2147483647;
 			files = (
 			);
@@ -744,7 +753,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */,
-				F40EE50B206C06640071091A /* GPBCompileTest24.m in Sources */,
 				F40EE4BE206BF8B90071091A /* GPBCompileTest20.m in Sources */,
 				F401DC331A8E5C0200FCC765 /* GPBArrayTests.m in Sources */,
 				F40EE4B4206BF8B90071091A /* GPBCompileTest10.m in Sources */,
@@ -753,7 +761,7 @@
 				F40EE4B2206BF8B90071091A /* GPBCompileTest08.m in Sources */,
 				F40EE4BB206BF8B90071091A /* GPBCompileTest17.m in Sources */,
 				F4353D391AC06F10005A6198 /* GPBDictionaryTests+UInt64.m in Sources */,
-				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */,
+				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */,
 				F40EE4C1206BF8B90071091A /* GPBCompileTest23.m in Sources */,
 				8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */,
 				F4B51B1E1BBC610700744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */,
@@ -772,7 +780,6 @@
 				F4F8D8831D789FD9002CE128 /* GPBUnittestProtos2.m in Sources */,
 				F4353D1D1AB8822D005A6198 /* GPBDescriptorTests.m in Sources */,
 				8B4248BB1A8C256A00BC1EC6 /* GPBSwiftTests.swift in Sources */,
-				F40EE50C206C06640071091A /* GPBCompileTest25.m in Sources */,
 				F4584D821ECCB52A00803AB6 /* GPBExtensionRegistryTest.m in Sources */,
 				8BFF9D1A23AD582300E63E32 /* GPBMessageTests+ClassNames.m in Sources */,
 				5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
@@ -829,6 +836,7 @@
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				COMBINE_HIDPI_IMAGES = YES;
+				DEAD_CODE_STRIPPING = YES;
 				PRODUCT_NAME = ProtocolBuffers;
 				USER_HEADER_SEARCH_PATHS = "$(SRCROOT)";
 			};
@@ -839,6 +847,7 @@
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				COMBINE_HIDPI_IMAGES = YES;
+				DEAD_CODE_STRIPPING = YES;
 				PRODUCT_NAME = ProtocolBuffers;
 				USER_HEADER_SEARCH_PATHS = "$(SRCROOT)";
 			};
@@ -850,15 +859,23 @@
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				COMBINE_HIDPI_IMAGES = YES;
+				DEAD_CODE_STRIPPING = YES;
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+					"@loader_path/../Frameworks",
+				);
 				OTHER_LDFLAGS = "-ObjC";
 				PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:identifier}";
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 4.0;
-				USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)";
+				SWIFT_VERSION = 5.0;
+				USER_HEADER_SEARCH_PATHS = (
+					"${PROJECT_DERIVED_FILE_DIR}/protos",
+					"$(SRCROOT)",
+				);
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",
@@ -874,14 +891,22 @@
 				CLANG_ENABLE_MODULES = YES;
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				COMBINE_HIDPI_IMAGES = YES;
+				DEAD_CODE_STRIPPING = YES;
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/../Frameworks @loader_path/../Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/../Frameworks",
+					"@loader_path/../Frameworks",
+				);
 				OTHER_LDFLAGS = "-ObjC";
 				PRODUCT_BUNDLE_IDENTIFIER = "com.yourcompany.${PRODUCT_NAME:identifier}";
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
-				SWIFT_VERSION = 4.0;
-				USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)";
+				SWIFT_VERSION = 5.0;
+				USER_HEADER_SEARCH_PATHS = (
+					"${PROJECT_DERIVED_FILE_DIR}/protos",
+					"$(SRCROOT)",
+				);
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",
@@ -895,6 +920,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
 				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
@@ -912,12 +938,14 @@
 				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				DEAD_CODE_STRIPPING = YES;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				ENABLE_TESTABILITY = YES;
 				GCC_C_LANGUAGE_STANDARD = c99;
@@ -946,7 +974,7 @@
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PROFILING_CODE = NO;
-				MACOSX_DEPLOYMENT_TARGET = 10.9;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
 				ONLY_ACTIVE_ARCH = YES;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = macosx;
@@ -966,6 +994,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
 				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
@@ -983,12 +1012,14 @@
 				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
 				CLANG_WARN_SUSPICIOUS_MOVE = YES;
 				CLANG_WARN_UNREACHABLE_CODE = YES_AGGRESSIVE;
 				CLANG_WARN__DUPLICATE_METHOD_MATCH = YES;
+				DEAD_CODE_STRIPPING = YES;
 				ENABLE_NS_ASSERTIONS = NO;
 				ENABLE_STRICT_OBJC_MSGSEND = YES;
 				GCC_C_LANGUAGE_STANDARD = c99;
@@ -1015,10 +1046,11 @@
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PROFILING_CODE = NO;
-				MACOSX_DEPLOYMENT_TARGET = 10.9;
+				MACOSX_DEPLOYMENT_TARGET = 10.12;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = macosx;
-				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+				SWIFT_COMPILATION_MODE = wholemodule;
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
 				USE_HEADERMAP = NO;
 				WARNING_CFLAGS = (
 					"-Wdocumentation-unknown-command",
@@ -1036,6 +1068,7 @@
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				COMBINE_HIDPI_IMAGES = YES;
+				DEAD_CODE_STRIPPING = YES;
 				PRODUCT_NAME = TestSingleSourceBuild;
 				USER_HEADER_SEARCH_PATHS = "$(SRCROOT)";
 			};
@@ -1046,6 +1079,7 @@
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
 				COMBINE_HIDPI_IMAGES = YES;
+				DEAD_CODE_STRIPPING = YES;
 				PRODUCT_NAME = TestSingleSourceBuild;
 				USER_HEADER_SEARCH_PATHS = "$(SRCROOT)";
 			};
@@ -1055,6 +1089,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
 			};
 			name = Debug;
 		};
@@ -1062,6 +1097,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				CLANG_ENABLE_OBJC_WEAK = YES;
+				DEAD_CODE_STRIPPING = YES;
 			};
 			name = Release;
 		};
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
index 6653a1b..1c15772 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1400"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -293,8 +293,6 @@
             </SkippedTests>
          </TestableReference>
       </Testables>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Release"
@@ -315,8 +313,6 @@
             ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
index 328771b..0a9089b 100644
--- a/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
+++ b/objectivec/ProtocolBuffers_OSX.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1400"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -54,8 +54,17 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      codeCoverageEnabled = "YES"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      codeCoverageEnabled = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+            BuildableName = "libProtocolBuffers.a"
+            BlueprintName = "ProtocolBuffers"
+            ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -73,17 +82,6 @@
             </SkippedTests>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
-            BuildableName = "libProtocolBuffers.a"
-            BlueprintName = "ProtocolBuffers"
-            ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -104,8 +102,6 @@
             ReferencedContainer = "container:ProtocolBuffers_OSX.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
index 03e0580..a58aa53 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 47;
+	objectVersion = 55;
 	objects = {
 
 /* Begin PBXBuildFile section */
@@ -27,7 +27,7 @@
 		8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */; };
 		8B9A5EEC18330A0F00A9D33B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A5E9F1831913D00A9D33B /* UIKit.framework */; };
 		8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */; };
-		8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */; };
+		8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */; };
 		8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; };
 		8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; };
 		8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; };
@@ -61,8 +61,6 @@
 		F40EE504206BF91E0071091A /* GPBCompileTest21.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CB206BF9170071091A /* GPBCompileTest21.m */; };
 		F40EE505206BF91E0071091A /* GPBCompileTest22.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CF206BF9170071091A /* GPBCompileTest22.m */; };
 		F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CC206BF9170071091A /* GPBCompileTest23.m */; };
-		F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50E206C06880071091A /* GPBCompileTest24.m */; };
-		F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50D206C06880071091A /* GPBCompileTest25.m */; };
 		F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; };
 		F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */; };
 		F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D251ABB156F005A6198 /* GPBDictionary.m */; };
@@ -142,7 +140,7 @@
 		7461B4E80F94F99000A0C422 /* GPBWireFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormat.m; sourceTree = "<group>"; };
 		7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libProtocolBuffers.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedInputStreamTests.m; sourceTree = "<group>"; };
-		7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOuputStreamTests.m; sourceTree = "<group>"; };
+		7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStreamTests.m; sourceTree = "<group>"; };
 		7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = "<group>"; };
 		7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = "<group>"; };
 		7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = "<group>"; };
@@ -162,23 +160,13 @@
 		8B42494A1A92A0BA00BC1EC6 /* duration.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = duration.proto; path = ../src/google/protobuf/duration.proto; sourceTree = "<group>"; };
 		8B79657814992E3E002FFBFC /* GPBRootObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBRootObject.h; sourceTree = "<group>"; };
 		8B79657914992E3E002FFBFC /* GPBRootObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBRootObject.m; sourceTree = "<group>"; };
-		8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_custom_options.proto; path = ../../src/google/protobuf/unittest_custom_options.proto; sourceTree = "<group>"; };
-		8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_embed_optimize_for.proto; path = ../../src/google/protobuf/unittest_embed_optimize_for.proto; sourceTree = "<group>"; };
-		8B7E6A7614893DBA00F8884A /* unittest_empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_empty.proto; path = ../../src/google/protobuf/unittest_empty.proto; sourceTree = "<group>"; };
-		8B7E6A7814893DBB00F8884A /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_import.proto; path = ../../src/google/protobuf/unittest_import.proto; sourceTree = "<group>"; };
-		8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_mset.proto; path = ../../src/google/protobuf/unittest_mset.proto; sourceTree = "<group>"; };
-		8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_no_generic_services.proto; path = ../../src/google/protobuf/unittest_no_generic_services.proto; sourceTree = "<group>"; };
-		8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_optimize_for.proto; path = ../../src/google/protobuf/unittest_optimize_for.proto; sourceTree = "<group>"; };
-		8B7E6A7E14893DBC00F8884A /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest.proto; path = ../../src/google/protobuf/unittest.proto; sourceTree = "<group>"; };
 		8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBARCUnittestProtos.m; sourceTree = "<group>"; };
 		8B96157214C8B06000A2AC0B /* GPBDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor.h; sourceTree = "<group>"; };
 		8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptor.m; sourceTree = "<group>"; };
 		8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
 		8B9A5E9F1831913D00A9D33B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
-		8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = "<group>"; };
 		8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
-		8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
 		8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
 		8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
 		8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = "<group>"; };
@@ -206,8 +194,6 @@
 		F40EE4D6206BF9190071091A /* GPBCompileTest03.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest03.m; sourceTree = "<group>"; };
 		F40EE4D7206BF9190071091A /* GPBCompileTest06.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest06.m; sourceTree = "<group>"; };
 		F40EE4D8206BF9190071091A /* GPBCompileTest11.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest11.m; sourceTree = "<group>"; };
-		F40EE50D206C06880071091A /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
-		F40EE50E206C06880071091A /* GPBCompileTest24.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest24.m; sourceTree = "<group>"; };
 		F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = "<group>"; };
 		F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = "<group>"; };
 		F4353D241ABB156F005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = "<group>"; };
@@ -232,6 +218,23 @@
 		F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = "<group>"; };
 		F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = "<group>"; };
 		F44929021C866B3B00C2548A /* GPBCodedOutputStream_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedOutputStream_PackagePrivate.h; sourceTree = "<group>"; };
+		F44FEAD128B546E200EC57B3 /* unittest_preserve_unknown_enum.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_preserve_unknown_enum.proto; sourceTree = "<group>"; };
+		F44FEAD228B546E200EC57B3 /* map_proto2_unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = map_proto2_unittest.proto; sourceTree = "<group>"; };
+		F44FEAD328B546E200EC57B3 /* map_unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = map_unittest.proto; sourceTree = "<group>"; };
+		F44FEAD428B546E200EC57B3 /* unittest_extension_chain_a.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_a.proto; sourceTree = "<group>"; };
+		F44FEAD528B546E300EC57B3 /* unittest_extension_chain_d.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_d.proto; sourceTree = "<group>"; };
+		F44FEAD628B546E300EC57B3 /* unittest_deprecated.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_deprecated.proto; sourceTree = "<group>"; };
+		F44FEAD728B546E300EC57B3 /* any_test.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = any_test.proto; sourceTree = "<group>"; };
+		F44FEAD828B546E300EC57B3 /* unittest_extension_chain_b.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_b.proto; sourceTree = "<group>"; };
+		F44FEADB28B546E300EC57B3 /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_import.proto; sourceTree = "<group>"; };
+		F44FEADC28B546E300EC57B3 /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_mset.proto; sourceTree = "<group>"; };
+		F44FEADD28B546E300EC57B3 /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest.proto; sourceTree = "<group>"; };
+		F44FEADE28B546E300EC57B3 /* unittest_extension_chain_f.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_f.proto; sourceTree = "<group>"; };
+		F44FEADF28B546E300EC57B3 /* unittest_deprecated_file.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_deprecated_file.proto; sourceTree = "<group>"; };
+		F44FEAE028B546E300EC57B3 /* unittest_import_public.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_import_public.proto; sourceTree = "<group>"; };
+		F44FEAE128B546E300EC57B3 /* unittest_extension_chain_g.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_g.proto; sourceTree = "<group>"; };
+		F44FEAE228B546E300EC57B3 /* unittest_extension_chain_c.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_c.proto; sourceTree = "<group>"; };
+		F44FEAE328B546E300EC57B3 /* unittest_extension_chain_e.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_e.proto; sourceTree = "<group>"; };
 		F451D3F61A8AAEA600B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = "<group>"; };
 		F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionRegistryTest.m; path = Tests/GPBExtensionRegistryTest.m; sourceTree = SOURCE_ROOT; };
 		F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = "<group>"; };
@@ -448,12 +451,13 @@
 		7461B6940F94FDDD00A0C422 /* Tests */ = {
 			isa = PBXGroup;
 			children = (
+				F44FEAD728B546E300EC57B3 /* any_test.proto */,
 				8B210CCD159383D60032D72D /* golden_message */,
 				8B210CCF159386920032D72D /* golden_packed_fields_message */,
 				8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */,
 				F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */,
 				7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */,
-				7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */,
+				7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */,
 				F40EE4CD206BF9170071091A /* GPBCompileTest01.m */,
 				F40EE4C6206BF9170071091A /* GPBCompileTest02.m */,
 				F40EE4D6206BF9190071091A /* GPBCompileTest03.m */,
@@ -477,8 +481,6 @@
 				F40EE4CB206BF9170071091A /* GPBCompileTest21.m */,
 				F40EE4CF206BF9170071091A /* GPBCompileTest22.m */,
 				F40EE4CC206BF9170071091A /* GPBCompileTest23.m */,
-				F40EE50E206C06880071091A /* GPBCompileTest24.m */,
-				F40EE50D206C06880071091A /* GPBCompileTest25.m */,
 				5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
 				F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */,
 				F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */,
@@ -491,9 +493,9 @@
 				F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */,
 				F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */,
 				7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
+				8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */,
 				F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */,
 				F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */,
-				8BFF9D1B23AD593B00E63E32 /* GPBMessageTests+ClassNames.m */,
 				F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */,
 				F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */,
 				F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
@@ -506,25 +508,31 @@
 				7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
 				8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */,
 				7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
+				F44FEAD228B546E200EC57B3 /* map_proto2_unittest.proto */,
+				F44FEAD328B546E200EC57B3 /* map_unittest.proto */,
 				F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */,
 				F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */,
 				F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */,
-				8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */,
 				F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */,
-				8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */,
-				8B7E6A7614893DBA00F8884A /* unittest_empty.proto */,
-				8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */,
-				8B7E6A7814893DBB00F8884A /* unittest_import.proto */,
-				8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */,
-				8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */,
-				8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */,
+				F44FEADF28B546E300EC57B3 /* unittest_deprecated_file.proto */,
+				F44FEAD628B546E300EC57B3 /* unittest_deprecated.proto */,
+				F44FEAD428B546E200EC57B3 /* unittest_extension_chain_a.proto */,
+				F44FEAD828B546E300EC57B3 /* unittest_extension_chain_b.proto */,
+				F44FEAE228B546E300EC57B3 /* unittest_extension_chain_c.proto */,
+				F44FEAD528B546E300EC57B3 /* unittest_extension_chain_d.proto */,
+				F44FEAE328B546E300EC57B3 /* unittest_extension_chain_e.proto */,
+				F44FEADE28B546E300EC57B3 /* unittest_extension_chain_f.proto */,
+				F44FEAE128B546E300EC57B3 /* unittest_extension_chain_g.proto */,
+				F44FEAE028B546E300EC57B3 /* unittest_import_public.proto */,
+				F44FEADB28B546E300EC57B3 /* unittest_import.proto */,
+				F44FEADC28B546E300EC57B3 /* unittest_mset.proto */,
 				8B35468621A61EB2000BD30D /* unittest_objc_options.proto */,
 				F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */,
 				8B09AAF614B663A7007B4184 /* unittest_objc.proto */,
-				8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */,
+				F44FEAD128B546E200EC57B3 /* unittest_preserve_unknown_enum.proto */,
 				F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */,
 				F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */,
-				8B7E6A7E14893DBC00F8884A /* unittest.proto */,
+				F44FEADD28B546E300EC57B3 /* unittest.proto */,
 				8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */,
 				7401C1A90F950347006D8281 /* UnitTests-Info.plist */,
 			);
@@ -650,7 +658,7 @@
 			attributes = {
 				LastSwiftUpdateCheck = 0710;
 				LastTestingUpgradeCheck = 0600;
-				LastUpgradeCheck = 0930;
+				LastUpgradeCheck = 1400;
 				TargetAttributes = {
 					8BBEA4A5147C727100C4ADB7 = {
 						LastSwiftMigration = 0940;
@@ -662,12 +670,12 @@
 				};
 			};
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_iOS" */;
-			compatibilityVersion = "Xcode 6.3";
-			developmentRegion = English;
+			compatibilityVersion = "Xcode 13.0";
+			developmentRegion = en;
 			hasScannedForEncodings = 1;
 			knownRegions = (
-				English,
 				en,
+				Base,
 			);
 			mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
 			projectDirPath = "";
@@ -699,6 +707,7 @@
 /* Begin PBXShellScriptBuildPhase section */
 		F4B62A791AF91F7500AFCEDC /* Script: Check Runtime Stamps */ = {
 			isa = PBXShellScriptBuildPhase;
+			alwaysOutOfDate = 1;
 			buildActionMask = 2147483647;
 			files = (
 			);
@@ -751,7 +760,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */,
-				F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */,
 				F40EE503206BF91E0071091A /* GPBCompileTest20.m in Sources */,
 				F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */,
 				F40EE4F9206BF91E0071091A /* GPBCompileTest10.m in Sources */,
@@ -760,7 +768,7 @@
 				F40EE4F7206BF91E0071091A /* GPBCompileTest08.m in Sources */,
 				F40EE500206BF91E0071091A /* GPBCompileTest17.m in Sources */,
 				F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */,
-				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */,
+				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */,
 				F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */,
 				8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */,
 				F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */,
@@ -779,7 +787,6 @@
 				F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */,
 				F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */,
 				8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */,
-				F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */,
 				F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */,
 				8BFF9D1C23AD593C00E63E32 /* GPBMessageTests+ClassNames.m in Sources */,
 				5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
@@ -863,7 +870,11 @@
 					"$(inherited)",
 				);
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+					"@loader_path/Frameworks",
+				);
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(DEVELOPER_DIR)/usr/lib\"",
@@ -872,9 +883,12 @@
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
-				USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)";
+				USER_HEADER_SEARCH_PATHS = (
+					"${PROJECT_DERIVED_FILE_DIR}/protos",
+					"$(SRCROOT)",
+				);
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",
@@ -894,7 +908,11 @@
 					"$(inherited)",
 				);
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+					"@loader_path/Frameworks",
+				);
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(DEVELOPER_DIR)/usr/lib\"",
@@ -902,9 +920,12 @@
 				OTHER_LDFLAGS = "-ObjC";
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
-				SWIFT_VERSION = 4.0;
+				SWIFT_VERSION = 5.0;
 				TARGETED_DEVICE_FAMILY = "1,2";
-				USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)";
+				USER_HEADER_SEARCH_PATHS = (
+					"${PROJECT_DERIVED_FILE_DIR}/protos",
+					"$(SRCROOT)",
+				);
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",
@@ -918,6 +939,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
 				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
@@ -935,6 +957,7 @@
 				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -970,7 +993,7 @@
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PROFILING_CODE = NO;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				ONLY_ACTIVE_ARCH = YES;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = iphoneos;
@@ -989,6 +1012,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
 				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
@@ -1006,6 +1030,7 @@
 				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -1039,10 +1064,11 @@
 				GCC_WARN_UNUSED_PARAMETER = YES;
 				GCC_WARN_UNUSED_VARIABLE = YES;
 				GENERATE_PROFILING_CODE = NO;
-				IPHONEOS_DEPLOYMENT_TARGET = 9.0;
+				IPHONEOS_DEPLOYMENT_TARGET = 12.0;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = iphoneos;
-				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
+				SWIFT_COMPILATION_MODE = wholemodule;
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
 				WARNING_CFLAGS = (
 					"-Wdocumentation-unknown-command",
 					"-Wundef",
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
index 1a02f7e..c2fb719 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1400"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -293,17 +293,6 @@
             </SkippedTests>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "8B9A5EA41831993600A9D33B"
-            BuildableName = "iOSTestHarness.app"
-            BlueprintName = "iOSTestHarness"
-            ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Release"
@@ -315,8 +304,6 @@
       debugDocumentVersioning = "YES"
       debugServiceExtension = "internal"
       allowLocationSimulation = "YES">
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
index bacbcba..bd5e037 100644
--- a/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
+++ b/objectivec/ProtocolBuffers_iOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1400"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -54,8 +54,8 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      codeCoverageEnabled = "YES"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      codeCoverageEnabled = "YES">
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -73,17 +73,6 @@
             </SkippedTests>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "8B9A5EA41831993600A9D33B"
-            BuildableName = "iOSTestHarness.app"
-            BlueprintName = "iOSTestHarness"
-            ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -104,8 +93,6 @@
             ReferencedContainer = "container:ProtocolBuffers_iOS.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
index c7a8d85..ce3b2d5 100644
--- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
+++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/project.pbxproj
@@ -3,7 +3,7 @@
 	archiveVersion = 1;
 	classes = {
 	};
-	objectVersion = 47;
+	objectVersion = 55;
 	objects = {
 
 /* Begin PBXBuildFile section */
@@ -27,7 +27,7 @@
 		8B96157414C8C38C00A2AC0B /* GPBDescriptor.m in Sources */ = {isa = PBXBuildFile; fileRef = 8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */; };
 		8B9A5EEC18330A0F00A9D33B /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 8B9A5E9F1831913D00A9D33B /* UIKit.framework */; };
 		8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */; };
-		8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */; };
+		8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */; };
 		8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */; };
 		8BBEA4B0147C727D00C4ADB7 /* GPBTestUtilities.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */; };
 		8BBEA4B6147C727D00C4ADB7 /* GPBUnknownFieldSetTest.m in Sources */ = {isa = PBXBuildFile; fileRef = 7461B6B80F94FDF900A0C422 /* GPBUnknownFieldSetTest.m */; };
@@ -61,8 +61,6 @@
 		F40EE504206BF91E0071091A /* GPBCompileTest21.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CB206BF9170071091A /* GPBCompileTest21.m */; };
 		F40EE505206BF91E0071091A /* GPBCompileTest22.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CF206BF9170071091A /* GPBCompileTest22.m */; };
 		F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE4CC206BF9170071091A /* GPBCompileTest23.m */; };
-		F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50E206C06880071091A /* GPBCompileTest24.m */; };
-		F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */ = {isa = PBXBuildFile; fileRef = F40EE50D206C06880071091A /* GPBCompileTest25.m */; };
 		F41C175D1833D3310064ED4D /* GPBPerfTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F41C175C1833D3310064ED4D /* GPBPerfTests.m */; };
 		F4353D1F1AB88243005A6198 /* GPBDescriptorTests.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */; };
 		F4353D271ABB156F005A6198 /* GPBDictionary.m in Sources */ = {isa = PBXBuildFile; fileRef = F4353D251ABB156F005A6198 /* GPBDictionary.m */; };
@@ -142,7 +140,7 @@
 		7461B4E80F94F99000A0C422 /* GPBWireFormat.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBWireFormat.m; sourceTree = "<group>"; };
 		7461B52E0F94FAF800A0C422 /* libProtocolBuffers.a */ = {isa = PBXFileReference; explicitFileType = archive.ar; includeInIndex = 0; path = libProtocolBuffers.a; sourceTree = BUILT_PRODUCTS_DIR; };
 		7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedInputStreamTests.m; sourceTree = "<group>"; };
-		7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOuputStreamTests.m; sourceTree = "<group>"; };
+		7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCodedOutputStreamTests.m; sourceTree = "<group>"; };
 		7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBMessageTests.m; sourceTree = "<group>"; };
 		7461B6AB0F94FDF800A0C422 /* GPBTestUtilities.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBTestUtilities.h; sourceTree = "<group>"; };
 		7461B6AC0F94FDF800A0C422 /* GPBTestUtilities.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBTestUtilities.m; sourceTree = "<group>"; };
@@ -162,23 +160,13 @@
 		8B42494A1A92A0BA00BC1EC6 /* duration.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = duration.proto; path = ../src/google/protobuf/duration.proto; sourceTree = "<group>"; };
 		8B79657814992E3E002FFBFC /* GPBRootObject.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBRootObject.h; sourceTree = "<group>"; };
 		8B79657914992E3E002FFBFC /* GPBRootObject.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBRootObject.m; sourceTree = "<group>"; };
-		8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_custom_options.proto; path = ../../src/google/protobuf/unittest_custom_options.proto; sourceTree = "<group>"; };
-		8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_embed_optimize_for.proto; path = ../../src/google/protobuf/unittest_embed_optimize_for.proto; sourceTree = "<group>"; };
-		8B7E6A7614893DBA00F8884A /* unittest_empty.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_empty.proto; path = ../../src/google/protobuf/unittest_empty.proto; sourceTree = "<group>"; };
-		8B7E6A7814893DBB00F8884A /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_import.proto; path = ../../src/google/protobuf/unittest_import.proto; sourceTree = "<group>"; };
-		8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_mset.proto; path = ../../src/google/protobuf/unittest_mset.proto; sourceTree = "<group>"; };
-		8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_no_generic_services.proto; path = ../../src/google/protobuf/unittest_no_generic_services.proto; sourceTree = "<group>"; };
-		8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_optimize_for.proto; path = ../../src/google/protobuf/unittest_optimize_for.proto; sourceTree = "<group>"; };
-		8B7E6A7E14893DBC00F8884A /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest.proto; path = ../../src/google/protobuf/unittest.proto; sourceTree = "<group>"; };
 		8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBARCUnittestProtos.m; sourceTree = "<group>"; };
 		8B96157214C8B06000A2AC0B /* GPBDescriptor.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBDescriptor.h; sourceTree = "<group>"; };
 		8B96157314C8C38C00A2AC0B /* GPBDescriptor.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptor.m; sourceTree = "<group>"; };
 		8B9742421A8AAA7800DCE92C /* CoreGraphics.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreGraphics.framework; path = System/Library/Frameworks/CoreGraphics.framework; sourceTree = SDKROOT; };
 		8B9A5E9F1831913D00A9D33B /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
-		8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_lite.proto; path = ../../src/google/protobuf/unittest_lite.proto; sourceTree = "<group>"; };
 		8BBEA4A6147C727100C4ADB7 /* UnitTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = UnitTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; };
 		8BCF338814ED799900BC5317 /* GPBProtocolBuffers.m */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.objc; path = GPBProtocolBuffers.m; sourceTree = "<group>"; };
-		8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */ = {isa = PBXFileReference; lastKnownFileType = text; name = unittest_enormous_descriptor.proto; path = ../../src/google/protobuf/unittest_enormous_descriptor.proto; sourceTree = "<group>"; };
 		8BD3981E14BE59D70081D629 /* GPBUnittestProtos.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBUnittestProtos.m; sourceTree = "<group>"; };
 		8BEB5AE01498033E0078BF9D /* GPBRuntimeTypes.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBRuntimeTypes.h; sourceTree = "<group>"; };
 		8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+ClassNames.m"; sourceTree = "<group>"; };
@@ -206,8 +194,6 @@
 		F40EE4D6206BF9190071091A /* GPBCompileTest03.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest03.m; sourceTree = "<group>"; };
 		F40EE4D7206BF9190071091A /* GPBCompileTest06.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest06.m; sourceTree = "<group>"; };
 		F40EE4D8206BF9190071091A /* GPBCompileTest11.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest11.m; sourceTree = "<group>"; };
-		F40EE50D206C06880071091A /* GPBCompileTest25.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest25.m; sourceTree = "<group>"; };
-		F40EE50E206C06880071091A /* GPBCompileTest24.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBCompileTest24.m; sourceTree = "<group>"; };
 		F41C175C1833D3310064ED4D /* GPBPerfTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBPerfTests.m; sourceTree = "<group>"; };
 		F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBDescriptorTests.m; sourceTree = "<group>"; };
 		F4353D241ABB156F005A6198 /* GPBDictionary.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBDictionary.h; sourceTree = "<group>"; };
@@ -232,6 +218,23 @@
 		F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Serialization.m"; sourceTree = "<group>"; };
 		F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = "GPBMessageTests+Merge.m"; sourceTree = "<group>"; };
 		F44929021C866B3B00C2548A /* GPBCodedOutputStream_PackagePrivate.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = GPBCodedOutputStream_PackagePrivate.h; sourceTree = "<group>"; };
+		F44FEAE528B5471300EC57B3 /* unittest_extension_chain_a.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_a.proto; sourceTree = "<group>"; };
+		F44FEAE728B5471300EC57B3 /* unittest_extension_chain_c.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_c.proto; sourceTree = "<group>"; };
+		F44FEAE828B5471300EC57B3 /* unittest_extension_chain_g.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_g.proto; sourceTree = "<group>"; };
+		F44FEAE928B5471300EC57B3 /* unittest_import.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_import.proto; sourceTree = "<group>"; };
+		F44FEAEA28B5471300EC57B3 /* unittest_deprecated_file.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_deprecated_file.proto; sourceTree = "<group>"; };
+		F44FEAEB28B5471300EC57B3 /* unittest_import_public.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_import_public.proto; sourceTree = "<group>"; };
+		F44FEAEC28B5471300EC57B3 /* unittest_extension_chain_f.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_f.proto; sourceTree = "<group>"; };
+		F44FEAED28B5471300EC57B3 /* unittest_deprecated.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_deprecated.proto; sourceTree = "<group>"; };
+		F44FEAEE28B5471300EC57B3 /* unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest.proto; sourceTree = "<group>"; };
+		F44FEAEF28B5471300EC57B3 /* any_test.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = any_test.proto; sourceTree = "<group>"; };
+		F44FEAF028B5471300EC57B3 /* unittest_extension_chain_b.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_b.proto; sourceTree = "<group>"; };
+		F44FEAF128B5471300EC57B3 /* unittest_mset.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_mset.proto; sourceTree = "<group>"; };
+		F44FEAF228B5471300EC57B3 /* unittest_preserve_unknown_enum.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_preserve_unknown_enum.proto; sourceTree = "<group>"; };
+		F44FEAF328B5471300EC57B3 /* unittest_extension_chain_d.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_d.proto; sourceTree = "<group>"; };
+		F44FEAF428B5471300EC57B3 /* unittest_extension_chain_e.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = unittest_extension_chain_e.proto; sourceTree = "<group>"; };
+		F44FEAF528B5472700EC57B3 /* map_proto2_unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = map_proto2_unittest.proto; sourceTree = "<group>"; };
+		F44FEAF628B5472700EC57B3 /* map_unittest.proto */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.protobuf; path = map_unittest.proto; sourceTree = "<group>"; };
 		F451D3F61A8AAEA600B8A22C /* GPBProtocolBuffers_RuntimeSupport.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = GPBProtocolBuffers_RuntimeSupport.h; sourceTree = "<group>"; };
 		F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = GPBExtensionRegistryTest.m; path = Tests/GPBExtensionRegistryTest.m; sourceTree = SOURCE_ROOT; };
 		F45C69CB16DFD08D0081955B /* GPBExtensionInternals.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = GPBExtensionInternals.m; sourceTree = "<group>"; };
@@ -448,12 +451,13 @@
 		7461B6940F94FDDD00A0C422 /* Tests */ = {
 			isa = PBXGroup;
 			children = (
+				F44FEAEF28B5471300EC57B3 /* any_test.proto */,
 				8B210CCD159383D60032D72D /* golden_message */,
 				8B210CCF159386920032D72D /* golden_packed_fields_message */,
 				8B8B615C17DF7056002EE618 /* GPBARCUnittestProtos.m */,
 				F401DC341A8E5C6F00FCC765 /* GPBArrayTests.m */,
 				7461B69B0F94FDF800A0C422 /* GPBCodedInputStreamTests.m */,
-				7461B69D0F94FDF800A0C422 /* GPBCodedOuputStreamTests.m */,
+				7461B69D0F94FDF800A0C422 /* GPBCodedOutputStreamTests.m */,
 				F40EE4CD206BF9170071091A /* GPBCompileTest01.m */,
 				F40EE4C6206BF9170071091A /* GPBCompileTest02.m */,
 				F40EE4D6206BF9190071091A /* GPBCompileTest03.m */,
@@ -477,8 +481,6 @@
 				F40EE4CB206BF9170071091A /* GPBCompileTest21.m */,
 				F40EE4CF206BF9170071091A /* GPBCompileTest22.m */,
 				F40EE4CC206BF9170071091A /* GPBCompileTest23.m */,
-				F40EE50E206C06880071091A /* GPBCompileTest24.m */,
-				F40EE50D206C06880071091A /* GPBCompileTest25.m */,
 				5102DABB1891A052002037B6 /* GPBConcurrencyTests.m */,
 				F4353D1E1AB88243005A6198 /* GPBDescriptorTests.m */,
 				F4C4B9E51E1D97BB00D3B61D /* GPBDictionaryTests.m */,
@@ -491,9 +493,9 @@
 				F4353D401AC06F31005A6198 /* GPBDictionaryTests+UInt64.m */,
 				F4584D801ECCB39E00803AB6 /* GPBExtensionRegistryTest.m */,
 				7461B6A30F94FDF800A0C422 /* GPBMessageTests.m */,
+				8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */,
 				F4487C841AAF6AC500531423 /* GPBMessageTests+Merge.m */,
 				F4487C761AADF84900531423 /* GPBMessageTests+Runtime.m */,
-				8BFF9D1D23AD599400E63E32 /* GPBMessageTests+ClassNames.m */,
 				F4487C801AAF62FC00531423 /* GPBMessageTests+Serialization.m */,
 				F4B51B1B1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm */,
 				F41C175C1833D3310064ED4D /* GPBPerfTests.m */,
@@ -506,25 +508,31 @@
 				7461B6BA0F94FDF900A0C422 /* GPBUtilitiesTests.m */,
 				8B4248E51A929C9900BC1EC6 /* GPBWellKnownTypesTest.m */,
 				7461B6BC0F94FDF900A0C422 /* GPBWireFormatTests.m */,
+				F44FEAF528B5472700EC57B3 /* map_proto2_unittest.proto */,
+				F44FEAF628B5472700EC57B3 /* map_unittest.proto */,
 				F4F53F8B219CC5DF001EABF4 /* text_format_extensions_unittest_data.txt */,
 				F45E57C81AE6DC98000B7D99 /* text_format_map_unittest_data.txt */,
 				F43C88CF191D77FC009E917D /* text_format_unittest_data.txt */,
-				8B7E6A7414893DBA00F8884A /* unittest_custom_options.proto */,
 				F4AC9E1C1A8BEB1000BD6E83 /* unittest_cycle.proto */,
-				8B7E6A7514893DBA00F8884A /* unittest_embed_optimize_for.proto */,
-				8B7E6A7614893DBA00F8884A /* unittest_empty.proto */,
-				8BD3981D14BE54220081D629 /* unittest_enormous_descriptor.proto */,
-				8B7E6A7814893DBB00F8884A /* unittest_import.proto */,
-				8BBD9DB016DD1DC8008E1EC1 /* unittest_lite.proto */,
-				8B7E6A7B14893DBC00F8884A /* unittest_mset.proto */,
-				8B7E6A7C14893DBC00F8884A /* unittest_no_generic_services.proto */,
+				F44FEAEA28B5471300EC57B3 /* unittest_deprecated_file.proto */,
+				F44FEAED28B5471300EC57B3 /* unittest_deprecated.proto */,
+				F44FEAE528B5471300EC57B3 /* unittest_extension_chain_a.proto */,
+				F44FEAF028B5471300EC57B3 /* unittest_extension_chain_b.proto */,
+				F44FEAE728B5471300EC57B3 /* unittest_extension_chain_c.proto */,
+				F44FEAF328B5471300EC57B3 /* unittest_extension_chain_d.proto */,
+				F44FEAF428B5471300EC57B3 /* unittest_extension_chain_e.proto */,
+				F44FEAEC28B5471300EC57B3 /* unittest_extension_chain_f.proto */,
+				F44FEAE828B5471300EC57B3 /* unittest_extension_chain_g.proto */,
+				F44FEAEB28B5471300EC57B3 /* unittest_import_public.proto */,
+				F44FEAE928B5471300EC57B3 /* unittest_import.proto */,
+				F44FEAF128B5471300EC57B3 /* unittest_mset.proto */,
 				8B35468621A61EB2000BD30D /* unittest_objc_options.proto */,
 				F4CF31711B162EF500BD9B06 /* unittest_objc_startup.proto */,
 				8B09AAF614B663A7007B4184 /* unittest_objc.proto */,
-				8B7E6A7D14893DBC00F8884A /* unittest_optimize_for.proto */,
+				F44FEAF228B5471300EC57B3 /* unittest_preserve_unknown_enum.proto */,
 				F4487C7A1AADFB5500531423 /* unittest_runtime_proto2.proto */,
 				F4487C7B1AADFB5500531423 /* unittest_runtime_proto3.proto */,
-				8B7E6A7E14893DBC00F8884A /* unittest.proto */,
+				F44FEAEE28B5471300EC57B3 /* unittest.proto */,
 				8B4248B21A8BD96D00BC1EC6 /* UnitTests-Bridging-Header.h */,
 				7401C1A90F950347006D8281 /* UnitTests-Info.plist */,
 			);
@@ -650,7 +658,7 @@
 			attributes = {
 				LastSwiftUpdateCheck = 0710;
 				LastTestingUpgradeCheck = 0600;
-				LastUpgradeCheck = 0930;
+				LastUpgradeCheck = 1400;
 				TargetAttributes = {
 					8BBEA4A5147C727100C4ADB7 = {
 						LastSwiftMigration = 0940;
@@ -662,12 +670,12 @@
 				};
 			};
 			buildConfigurationList = C01FCF4E08A954540054247B /* Build configuration list for PBXProject "ProtocolBuffers_tvOS" */;
-			compatibilityVersion = "Xcode 6.3";
-			developmentRegion = English;
+			compatibilityVersion = "Xcode 13.0";
+			developmentRegion = en;
 			hasScannedForEncodings = 1;
 			knownRegions = (
-				English,
 				en,
+				Base,
 			);
 			mainGroup = 29B97314FDCFA39411CA2CEA /* CustomTemplate */;
 			projectDirPath = "";
@@ -699,6 +707,7 @@
 /* Begin PBXShellScriptBuildPhase section */
 		F4B62A791AF91F7500AFCEDC /* Script: Check Runtime Stamps */ = {
 			isa = PBXShellScriptBuildPhase;
+			alwaysOutOfDate = 1;
 			buildActionMask = 2147483647;
 			files = (
 			);
@@ -751,7 +760,6 @@
 			buildActionMask = 2147483647;
 			files = (
 				8BBEA4A9147C727D00C4ADB7 /* GPBCodedInputStreamTests.m in Sources */,
-				F40EE511206C068D0071091A /* GPBCompileTest24.m in Sources */,
 				F40EE503206BF91E0071091A /* GPBCompileTest20.m in Sources */,
 				F401DC351A8E5C6F00FCC765 /* GPBArrayTests.m in Sources */,
 				F40EE4F9206BF91E0071091A /* GPBCompileTest10.m in Sources */,
@@ -760,7 +768,7 @@
 				F40EE4F7206BF91E0071091A /* GPBCompileTest08.m in Sources */,
 				F40EE500206BF91E0071091A /* GPBCompileTest17.m in Sources */,
 				F4353D471AC06F31005A6198 /* GPBDictionaryTests+UInt64.m in Sources */,
-				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOuputStreamTests.m in Sources */,
+				8BBEA4AA147C727D00C4ADB7 /* GPBCodedOutputStreamTests.m in Sources */,
 				F40EE506206BF91E0071091A /* GPBCompileTest23.m in Sources */,
 				8BBEA4AC147C727D00C4ADB7 /* GPBMessageTests.m in Sources */,
 				F4487C811AAF62FC00531423 /* GPBMessageTests+Serialization.m in Sources */,
@@ -779,7 +787,6 @@
 				F4F8D8861D78A193002CE128 /* GPBUnittestProtos2.m in Sources */,
 				F4B51B1C1BBC5C7100744318 /* GPBObjectiveCPlusPlusTest.mm in Sources */,
 				8B4248B41A8BD96E00BC1EC6 /* GPBSwiftTests.swift in Sources */,
-				F40EE512206C068D0071091A /* GPBCompileTest25.m in Sources */,
 				F4584D831ECCB53600803AB6 /* GPBExtensionRegistryTest.m in Sources */,
 				8BFF9D1E23AD599400E63E32 /* GPBMessageTests+ClassNames.m in Sources */,
 				5102DABC1891A073002037B6 /* GPBConcurrencyTests.m in Sources */,
@@ -859,7 +866,11 @@
 					"$(inherited)",
 				);
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+					"@loader_path/Frameworks",
+				);
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(DEVELOPER_DIR)/usr/lib\"",
@@ -868,8 +879,11 @@
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
 				SWIFT_OPTIMIZATION_LEVEL = "-Onone";
-				SWIFT_VERSION = 4.0;
-				USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)";
+				SWIFT_VERSION = 5.0;
+				USER_HEADER_SEARCH_PATHS = (
+					"${PROJECT_DERIVED_FILE_DIR}/protos",
+					"$(SRCROOT)",
+				);
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",
@@ -889,7 +903,11 @@
 					"$(inherited)",
 				);
 				INFOPLIST_FILE = "Tests/UnitTests-Info.plist";
-				LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks";
+				LD_RUNPATH_SEARCH_PATHS = (
+					"$(inherited)",
+					"@executable_path/Frameworks",
+					"@loader_path/Frameworks",
+				);
 				LIBRARY_SEARCH_PATHS = (
 					"$(inherited)",
 					"\"$(DEVELOPER_DIR)/usr/lib\"",
@@ -897,8 +915,11 @@
 				OTHER_LDFLAGS = "-ObjC";
 				PRODUCT_NAME = UnitTests;
 				SWIFT_OBJC_BRIDGING_HEADER = "Tests/UnitTests-Bridging-Header.h";
-				SWIFT_VERSION = 4.0;
-				USER_HEADER_SEARCH_PATHS = "${PROJECT_DERIVED_FILE_DIR}/protos $(SRCROOT)";
+				SWIFT_VERSION = 5.0;
+				USER_HEADER_SEARCH_PATHS = (
+					"${PROJECT_DERIVED_FILE_DIR}/protos",
+					"$(SRCROOT)",
+				);
 				WARNING_CFLAGS = (
 					"$(inherited)",
 					"-Wno-documentation-unknown-command",
@@ -912,6 +933,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
 				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
@@ -929,6 +951,7 @@
 				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -967,7 +990,7 @@
 				ONLY_ACTIVE_ARCH = YES;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = appletvos;
-				TVOS_DEPLOYMENT_TARGET = 9.0;
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 				WARNING_CFLAGS = (
 					"-Wdocumentation-unknown-command",
 					"-Wundef",
@@ -983,6 +1006,7 @@
 			isa = XCBuildConfiguration;
 			buildSettings = {
 				ALWAYS_SEARCH_USER_PATHS = NO;
+				CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES;
 				CLANG_ANALYZER_NONNULL = YES;
 				CLANG_ANALYZER_SECURITY_FLOATLOOPCOUNTER = YES;
 				CLANG_ANALYZER_SECURITY_INSECUREAPI_RAND = YES;
@@ -1000,6 +1024,7 @@
 				CLANG_WARN_OBJC_IMPLICIT_ATOMIC_PROPERTIES = YES;
 				CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES;
 				CLANG_WARN_OBJC_MISSING_PROPERTY_SYNTHESIS = YES;
+				CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES;
 				CLANG_WARN_RANGE_LOOP_ANALYSIS = YES;
 				CLANG_WARN_STRICT_PROTOTYPES = YES;
 				CLANG_WARN_SUSPICIOUS_IMPLICIT_CONVERSION = YES;
@@ -1035,8 +1060,9 @@
 				GENERATE_PROFILING_CODE = NO;
 				RUN_CLANG_STATIC_ANALYZER = YES;
 				SDKROOT = appletvos;
-				SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule";
-				TVOS_DEPLOYMENT_TARGET = 9.0;
+				SWIFT_COMPILATION_MODE = wholemodule;
+				SWIFT_OPTIMIZATION_LEVEL = "-O";
+				TVOS_DEPLOYMENT_TARGET = 12.0;
 				WARNING_CFLAGS = (
 					"-Wdocumentation-unknown-command",
 					"-Wundef",
diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
index b11dc6e..e1a98c4 100644
--- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
+++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/PerformanceTests.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1400"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -41,6 +41,15 @@
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
       shouldUseLaunchSchemeArgsEnv = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+            BuildableName = "libProtocolBuffers.a"
+            BlueprintName = "ProtocolBuffers"
+            ReferencedContainer = "container:ProtocolBuffers_tvOS.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -310,17 +319,6 @@
             </SkippedTests>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
-            BuildableName = "libProtocolBuffers.a"
-            BlueprintName = "ProtocolBuffers"
-            ReferencedContainer = "container:ProtocolBuffers_tvOS.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Release"
@@ -341,8 +339,6 @@
             ReferencedContainer = "container:ProtocolBuffers_tvOS.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
index 25d047a..1b4a59d 100644
--- a/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
+++ b/objectivec/ProtocolBuffers_tvOS.xcodeproj/xcshareddata/xcschemes/ProtocolBuffers.xcscheme
@@ -1,6 +1,6 @@
 <?xml version="1.0" encoding="UTF-8"?>
 <Scheme
-   LastUpgradeVersion = "0930"
+   LastUpgradeVersion = "1400"
    version = "1.3">
    <BuildAction
       parallelizeBuildables = "YES"
@@ -54,8 +54,17 @@
       buildConfiguration = "Debug"
       selectedDebuggerIdentifier = "Xcode.DebuggerFoundation.Debugger.LLDB"
       selectedLauncherIdentifier = "Xcode.DebuggerFoundation.Launcher.LLDB"
-      codeCoverageEnabled = "YES"
-      shouldUseLaunchSchemeArgsEnv = "YES">
+      shouldUseLaunchSchemeArgsEnv = "YES"
+      codeCoverageEnabled = "YES">
+      <MacroExpansion>
+         <BuildableReference
+            BuildableIdentifier = "primary"
+            BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
+            BuildableName = "libProtocolBuffers.a"
+            BlueprintName = "ProtocolBuffers"
+            ReferencedContainer = "container:ProtocolBuffers_tvOS.xcodeproj">
+         </BuildableReference>
+      </MacroExpansion>
       <Testables>
          <TestableReference
             skipped = "NO">
@@ -73,17 +82,6 @@
             </SkippedTests>
          </TestableReference>
       </Testables>
-      <MacroExpansion>
-         <BuildableReference
-            BuildableIdentifier = "primary"
-            BlueprintIdentifier = "7461B52D0F94FAF800A0C422"
-            BuildableName = "libProtocolBuffers.a"
-            BlueprintName = "ProtocolBuffers"
-            ReferencedContainer = "container:ProtocolBuffers_tvOS.xcodeproj">
-         </BuildableReference>
-      </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </TestAction>
    <LaunchAction
       buildConfiguration = "Debug"
@@ -104,8 +102,6 @@
             ReferencedContainer = "container:ProtocolBuffers_tvOS.xcodeproj">
          </BuildableReference>
       </MacroExpansion>
-      <AdditionalOptions>
-      </AdditionalOptions>
    </LaunchAction>
    <ProfileAction
       buildConfiguration = "Release"
diff --git a/objectivec/README.md b/objectivec/README.md
index a0fcd19..95f561c 100644
--- a/objectivec/README.md
+++ b/objectivec/README.md
@@ -11,7 +11,7 @@
 The Objective C implementation requires:
 
 - Objective C 2.0 Runtime (32bit & 64bit iOS, 64bit OS X).
-- Xcode 10.3 (or later).
+- Xcode 13.3.1 (or later).
 - The library code does *not* use ARC (for performance reasons), but it all can
   be called from ARC code.
 
@@ -25,7 +25,7 @@
 
      $ objectivec/DevTools/full_mac_build.sh
 
-This will generate the `src/protoc` binary.
+This will generate the `protoc` binary.
 
 Building
 --------
@@ -200,12 +200,13 @@
         entry can be made as "no_package:PATH=prefix", where PATH is the
       path for the .proto file.
 
-  * `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.
+  * `use_package_as_prefix`, `package_as_prefix_forced_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
@@ -213,10 +214,16 @@
     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.
 
+    `package_as_prefix_forced_prefix` can be used to provide a value that will
+    be used before all prefixes derived from the packages to help group all of
+    these types with a common prefix. Thus it only makes sense to use it when
+    `use_package_as_prefix` is also enabled. For example, setting this to
+    "XYZ\_" and generating a file with the package "something" defining
+    "MyMessage", would have Objective-C class be `XYZ_Something_MyMessage`.
+
     `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.
+    that could change in the future as it helps avoid collisions when more
+    protos get added to the build. Note that this would be a breaking change.
 
   * `headers_use_forward_declarations`: The `value` for this can be `yes` or
     `no`, and indicates if the generated headers use forward declarations for
diff --git a/objectivec/Tests/GPBARCUnittestProtos.m b/objectivec/Tests/GPBARCUnittestProtos.m
index 29f6ccf..fa23692 100644
--- a/objectivec/Tests/GPBARCUnittestProtos.m
+++ b/objectivec/Tests/GPBARCUnittestProtos.m
@@ -34,30 +34,16 @@
 
 // Makes sure all the generated headers compile with ARC on.
 
-// The unittest_custom_options.proto extends the messages in descriptor.proto
-// so we build it in to test extending in general. The library doesn't provide
-// a descriptor as it doesn't use the classes/enums.
-#import "google/protobuf/Descriptor.pbobjc.h"
-
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestCustomOptions.pbobjc.h"
-#import "google/protobuf/UnittestCycle.pbobjc.h"
-#import "google/protobuf/UnittestDeprecated.pbobjc.h"
-#import "google/protobuf/UnittestDeprecatedFile.pbobjc.h"
-#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
-#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.h"
-#import "google/protobuf/UnittestEmpty.pbobjc.h"
-#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.h"
-#import "google/protobuf/UnittestImport.pbobjc.h"
-#import "google/protobuf/UnittestImportLite.pbobjc.h"
-#import "google/protobuf/UnittestImportPublic.pbobjc.h"
-#import "google/protobuf/UnittestImportPublicLite.pbobjc.h"
-#import "google/protobuf/UnittestLite.pbobjc.h"
-#import "google/protobuf/UnittestMset.pbobjc.h"
-#import "google/protobuf/UnittestNoGenericServices.pbobjc.h"
-#import "google/protobuf/UnittestObjc.pbobjc.h"
-#import "google/protobuf/UnittestObjcStartup.pbobjc.h"
-#import "google/protobuf/UnittestOptimizeFor.pbobjc.h"
-#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestCycle.pbobjc.h"
+#import "objectivec/Tests/UnittestDeprecated.pbobjc.h"
+#import "objectivec/Tests/UnittestDeprecatedFile.pbobjc.h"
+#import "objectivec/Tests/UnittestImport.pbobjc.h"
+#import "objectivec/Tests/UnittestImportPublic.pbobjc.h"
+#import "objectivec/Tests/UnittestMset.pbobjc.h"
+#import "objectivec/Tests/UnittestObjc.pbobjc.h"
+#import "objectivec/Tests/UnittestObjcOptions.pbobjc.h"
+#import "objectivec/Tests/UnittestObjcStartup.pbobjc.h"
+#import "objectivec/Tests/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto3.pbobjc.h"
diff --git a/objectivec/Tests/GPBArrayTests.m b/objectivec/Tests/GPBArrayTests.m
index 9b004bc..efb512e 100644
--- a/objectivec/Tests/GPBArrayTests.m
+++ b/objectivec/Tests/GPBArrayTests.m
@@ -40,8 +40,7 @@
 @interface GPBEnumArray (TestingTweak)
 + (instancetype)arrayWithValue:(int32_t)value;
 + (instancetype)arrayWithCapacity:(NSUInteger)count;
-- (instancetype)initWithValues:(const int32_t [])values
-                         count:(NSUInteger)count;
+- (instancetype)initWithValues:(const int32_t[])values count:(NSUInteger)count;
 @end
 
 static BOOL TestingEnum_IsValidValue(int32_t value) {
@@ -77,16 +76,16 @@
   return [[[self alloc] initWithValidationFunction:TestingEnum_IsValidValue
                                           capacity:count] autorelease];
 }
-- (instancetype)initWithValues:(const int32_t [])values
-                         count:(NSUInteger)count {
-  return [self initWithValidationFunction:TestingEnum_IsValidValue
-                                rawValues:values
-                                    count:count];
+- (instancetype)initWithValues:(const int32_t[])values count:(NSUInteger)count {
+  return [self initWithValidationFunction:TestingEnum_IsValidValue rawValues:values count:count];
 }
 @end
 
 #pragma mark - PDDM Macros
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-DEFINE ARRAY_TESTS(NAME, TYPE, VAL1, VAL2, VAL3, VAL4)
 //%ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, )
 //%PDDM-DEFINE ARRAY_TESTS2(NAME, TYPE, VAL1, VAL2, VAL3, VAL4, HELPER)
@@ -102,13 +101,11 @@
 //%  XCTAssertNotNil(array);
 //%  XCTAssertEqual(array.count, 0U);
 //%  XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-//%  [array enumerateValuesWithBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
-//%    #pragma unused(value, idx, stop)
+//%  [array enumerateValuesWithBlock:^(__unused TYPE value, __unused NSUInteger idx, __unused BOOL *stop) {
 //%    XCTFail(@"Shouldn't get here!");
 //%  }];
 //%  [array enumerateValuesWithOptions:NSEnumerationReverse
-//%                         usingBlock:^(TYPE value, NSUInteger idx, BOOL *stop) {
-//%    #pragma unused(value, idx, stop)
+//%                         usingBlock:^(__unused TYPE value, __unused NSUInteger idx, __unused BOOL *stop) {
 //%    XCTFail(@"Shouldn't get here!");
 //%  }];
 //%  [array release];
@@ -433,7 +430,6 @@
 //%
 //%PDDM-EXPAND ARRAY_TESTS(Int32, int32_t, 1, 2, 3, 4)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int32
 
@@ -447,13 +443,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -776,10 +770,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_TESTS(UInt32, uint32_t, 11U, 12U, 13U, 14U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - UInt32
 
@@ -793,13 +785,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(uint32_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused uint32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -1122,10 +1112,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_TESTS(Int64, int64_t, 31LL, 32LL, 33LL, 34LL)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Int64
 
@@ -1139,13 +1127,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(int64_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused int64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -1468,10 +1454,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_TESTS(UInt64, uint64_t, 41ULL, 42ULL, 43ULL, 44ULL)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - UInt64
 
@@ -1485,13 +1469,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(uint64_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused uint64_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -1814,10 +1796,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_TESTS(Float, float, 51.f, 52.f, 53.f, 54.f)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Float
 
@@ -1831,13 +1811,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(float value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused float value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(float value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused float value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -2160,10 +2138,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_TESTS(Double, double, 61., 62., 63., 64.)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Double
 
@@ -2177,13 +2153,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(double value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused double value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(double value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused double value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -2506,10 +2480,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_TESTS(Bool, BOOL, TRUE, TRUE, FALSE, FALSE)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool
 
@@ -2523,13 +2495,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused BOOL value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(BOOL value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused BOOL value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -2852,10 +2822,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND ARRAY_TESTS2(Enum, int32_t, 71, 72, 73, 74, Raw)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Enum
 
@@ -2869,13 +2837,11 @@
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 0U);
   XCTAssertThrowsSpecificNamed([array valueAtIndex:0], NSException, NSRangeException);
-  [array enumerateValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+  [array enumerateValuesWithBlock:^(__unused int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array enumerateValuesWithOptions:NSEnumerationReverse
-                         usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-    #pragma unused(value, idx, stop)
+                         usingBlock:^(__unused int32_t value, __unused NSUInteger idx, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [array release];
@@ -3198,9 +3164,10 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END (8 expansions)
 
+// clang-format on
+
 #pragma mark - Non macro-based Enum tests
 
 // These are hand written tests to cover the verification and raw methods.
@@ -3211,15 +3178,13 @@
 @implementation GPBEnumArrayCustomTests
 
 - (void)testRawBasics {
-  static const int32_t kValues[] = { 71, 272, 73, 374 };
-  static const int32_t kValuesFiltered[] = {
-      71, kGPBUnrecognizedEnumeratorValue, 73, kGPBUnrecognizedEnumeratorValue
-  };
+  static const int32_t kValues[] = {71, 272, 73, 374};
+  static const int32_t kValuesFiltered[] = {71, kGPBUnrecognizedEnumeratorValue, 73,
+                                            kGPBUnrecognizedEnumeratorValue};
   XCTAssertEqual(GPBARRAYSIZE(kValues), GPBARRAYSIZE(kValuesFiltered));
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
-                                             rawValues:kValues
-                                                 count:GPBARRAYSIZE(kValues)];
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                               rawValues:kValues
+                                                                   count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 4U);
   GPBEnumValidationFunc func = TestingEnum_IsValidValue;
@@ -3248,19 +3213,19 @@
   idx2 = 0;
   [array enumerateRawValuesWithOptions:NSEnumerationReverse
                             usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-    XCTAssertEqual(idx, (3 - idx2));
-    XCTAssertEqual(value, kValues[idx]);
-    XCTAssertNotEqual(stop, NULL);
-    ++idx2;
-  }];
+                              XCTAssertEqual(idx, (3 - idx2));
+                              XCTAssertEqual(value, kValues[idx]);
+                              XCTAssertNotEqual(stop, NULL);
+                              ++idx2;
+                            }];
   idx2 = 0;
   [array enumerateValuesWithOptions:NSEnumerationReverse
                          usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-    XCTAssertEqual(idx, (3 - idx2));
-    XCTAssertEqual(value, kValuesFiltered[idx]);
-    XCTAssertNotEqual(stop, NULL);
-    ++idx2;
-  }];
+                           XCTAssertEqual(idx, (3 - idx2));
+                           XCTAssertEqual(value, kValuesFiltered[idx]);
+                           XCTAssertNotEqual(stop, NULL);
+                           ++idx2;
+                         }];
   // Stopping the enumeration.
   idx2 = 0;
   [array enumerateRawValuesWithBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
@@ -3275,38 +3240,35 @@
   idx2 = 0;
   [array enumerateRawValuesWithOptions:NSEnumerationReverse
                             usingBlock:^(int32_t value, NSUInteger idx, BOOL *stop) {
-    XCTAssertEqual(idx, (3 - idx2));
-    XCTAssertEqual(value, kValues[idx]);
-    XCTAssertNotEqual(stop, NULL);
-    if (idx2 == 1) *stop = YES;
-    XCTAssertNotEqual(idx, 1U);
-    XCTAssertNotEqual(idx, 0U);
-    ++idx2;
-  }];
+                              XCTAssertEqual(idx, (3 - idx2));
+                              XCTAssertEqual(value, kValues[idx]);
+                              XCTAssertNotEqual(stop, NULL);
+                              if (idx2 == 1) *stop = YES;
+                              XCTAssertNotEqual(idx, 1U);
+                              XCTAssertNotEqual(idx, 0U);
+                              ++idx2;
+                            }];
   [array release];
 }
 
 - (void)testEquality {
-  const int32_t kValues1[] = { 71, 72, 173 };  // With unknown value
-  const int32_t kValues2[] = { 71, 74, 173 };  // With unknown value
-  const int32_t kValues3[] = { 71, 72, 173, 74 };  // With unknown value
-  GPBEnumArray *array1 =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
-                                             rawValues:kValues1
-                                                 count:GPBARRAYSIZE(kValues1)];
+  const int32_t kValues1[] = {71, 72, 173};      // With unknown value
+  const int32_t kValues2[] = {71, 74, 173};      // With unknown value
+  const int32_t kValues3[] = {71, 72, 173, 74};  // With unknown value
+  GPBEnumArray *array1 = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                                rawValues:kValues1
+                                                                    count:GPBARRAYSIZE(kValues1)];
   XCTAssertNotNil(array1);
   GPBEnumArray *array1prime =
       [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue2
                                              rawValues:kValues1
                                                  count:GPBARRAYSIZE(kValues1)];
   XCTAssertNotNil(array1prime);
-  GPBEnumArray *array2 =
-      [[GPBEnumArray alloc] initWithValues:kValues2
-                                     count:GPBARRAYSIZE(kValues2)];
+  GPBEnumArray *array2 = [[GPBEnumArray alloc] initWithValues:kValues2
+                                                        count:GPBARRAYSIZE(kValues2)];
   XCTAssertNotNil(array2);
-  GPBEnumArray *array3 =
-      [[GPBEnumArray alloc] initWithValues:kValues3
-                                     count:GPBARRAYSIZE(kValues3)];
+  GPBEnumArray *array3 = [[GPBEnumArray alloc] initWithValues:kValues3
+                                                        count:GPBARRAYSIZE(kValues3)];
   XCTAssertNotNil(array3);
 
   // 1/1Prime should be different objects, but equal.
@@ -3329,13 +3291,11 @@
 }
 
 - (void)testCopy {
-  const int32_t kValues[] = { 71, 72 };
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValues:kValues
-                                     count:GPBARRAYSIZE(kValues)];
+  const int32_t kValues[] = {71, 72};
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValues:kValues count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
 
-  [array addRawValue:1000]; // Unknown
+  [array addRawValue:1000];  // Unknown
   XCTAssertEqual(array.count, 3U);
   XCTAssertEqual([array rawValueAtIndex:0], 71);
   XCTAssertEqual([array rawValueAtIndex:1], 72);
@@ -3360,11 +3320,10 @@
 }
 
 - (void)testArrayFromArray {
-  const int32_t kValues[] = { 71, 172, 173, 74 };  // Unknowns
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
-                                             rawValues:kValues
-                                                 count:GPBARRAYSIZE(kValues)];
+  const int32_t kValues[] = {71, 172, 173, 74};  // Unknowns
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                               rawValues:kValues
+                                                                   count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
 
   GPBEnumArray *array2 = [GPBEnumArray arrayWithValueArray:array];
@@ -3378,38 +3337,34 @@
 }
 
 - (void)testUnknownAdds {
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
   XCTAssertNotNil(array);
 
-  XCTAssertThrowsSpecificNamed([array addValue:172],
-                               NSException, NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed([array addValue:172], NSException, NSInvalidArgumentException);
   XCTAssertEqual(array.count, 0U);
 
-  const int32_t kValues1[] = { 172, 173 };  // Unknown
-  XCTAssertThrowsSpecificNamed([array addValues:kValues1 count:GPBARRAYSIZE(kValues1)],
-                               NSException, NSInvalidArgumentException);
+  const int32_t kValues1[] = {172, 173};  // Unknown
+  XCTAssertThrowsSpecificNamed([array addValues:kValues1 count:GPBARRAYSIZE(kValues1)], NSException,
+                               NSInvalidArgumentException);
   XCTAssertEqual(array.count, 0U);
   [array release];
 }
 
 - (void)testRawAdds {
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue];
   XCTAssertNotNil(array);
 
   XCTAssertEqual(array.count, 0U);
   [array addRawValue:71];  // Valid
   XCTAssertEqual(array.count, 1U);
 
-  const int32_t kValues1[] = { 172, 173 };  // Unknown
+  const int32_t kValues1[] = {172, 173};  // Unknown
   [array addRawValues:kValues1 count:GPBARRAYSIZE(kValues1)];
   XCTAssertEqual(array.count, 3U);
 
-  const int32_t kValues2[] = { 74, 71 };
-  GPBEnumArray *array2 =
-      [[GPBEnumArray alloc] initWithValues:kValues2
-                                     count:GPBARRAYSIZE(kValues2)];
+  const int32_t kValues2[] = {74, 71};
+  GPBEnumArray *array2 = [[GPBEnumArray alloc] initWithValues:kValues2
+                                                        count:GPBARRAYSIZE(kValues2)];
   XCTAssertNotNil(array2);
   [array addRawValuesFromArray:array2];
   XCTAssertEqual(array.count, 5U);
@@ -3425,37 +3380,35 @@
 }
 
 - (void)testUnknownInserts {
-  const int32_t kValues[] = { 71, 72, 73 };
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
-                                             rawValues:kValues
-                                                 count:GPBARRAYSIZE(kValues)];
+  const int32_t kValues[] = {71, 72, 73};
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                               rawValues:kValues
+                                                                   count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 3U);
 
   // First
-  XCTAssertThrowsSpecificNamed([array insertValue:174 atIndex:0],
-                               NSException, NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed([array insertValue:174 atIndex:0], NSException,
+                               NSInvalidArgumentException);
   XCTAssertEqual(array.count, 3U);
 
   // Middle
-  XCTAssertThrowsSpecificNamed([array insertValue:274 atIndex:1],
-                               NSException, NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed([array insertValue:274 atIndex:1], NSException,
+                               NSInvalidArgumentException);
   XCTAssertEqual(array.count, 3U);
 
   // End
-  XCTAssertThrowsSpecificNamed([array insertValue:374 atIndex:3],
-                               NSException, NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed([array insertValue:374 atIndex:3], NSException,
+                               NSInvalidArgumentException);
   XCTAssertEqual(array.count, 3U);
   [array release];
 }
 
 - (void)testRawInsert {
-  const int32_t kValues[] = { 71, 72, 73 };
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
-                                             rawValues:kValues
-                                                 count:GPBARRAYSIZE(kValues)];
+  const int32_t kValues[] = {71, 72, 73};
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                               rawValues:kValues
+                                                                   count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
   XCTAssertEqual(array.count, 3U);
 
@@ -3472,8 +3425,7 @@
   XCTAssertEqual(array.count, 6U);
 
   // Too far.
-  XCTAssertThrowsSpecificNamed([array insertRawValue:74 atIndex:7],
-                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array insertRawValue:74 atIndex:7], NSException, NSRangeException);
 
   XCTAssertEqual([array rawValueAtIndex:0], 174);
   XCTAssertEqual([array valueAtIndex:0], kGPBUnrecognizedEnumeratorValue);
@@ -3488,17 +3440,16 @@
 }
 
 - (void)testUnknownInplaceMutation {
-  const int32_t kValues[] = { 71, 72, 73, 74 };
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
-                                             rawValues:kValues
-                                                 count:GPBARRAYSIZE(kValues)];
+  const int32_t kValues[] = {71, 72, 73, 74};
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                               rawValues:kValues
+                                                                   count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
 
-  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:1 withValue:172],
-                               NSException, NSInvalidArgumentException);
-  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:3 withValue:274],
-                               NSException, NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:1 withValue:172], NSException,
+                               NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:3 withValue:274], NSException,
+                               NSInvalidArgumentException);
   XCTAssertEqual(array.count, 4U);
   XCTAssertEqual([array valueAtIndex:0], 71);
   XCTAssertEqual([array valueAtIndex:1], 72);
@@ -3507,13 +3458,11 @@
   [array release];
 }
 
-
 - (void)testRawInplaceMutation {
-  const int32_t kValues[] = { 71, 72, 73, 74 };
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
-                                             rawValues:kValues
-                                                 count:GPBARRAYSIZE(kValues)];
+  const int32_t kValues[] = {71, 72, 73, 74};
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValidationFunction:TestingEnum_IsValidValue
+                                                               rawValues:kValues
+                                                                   count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
 
   [array replaceValueAtIndex:1 withRawValue:172];  // Unknown
@@ -3526,16 +3475,14 @@
   XCTAssertEqual([array rawValueAtIndex:3], 274);
   XCTAssertEqual([array valueAtIndex:3], kGPBUnrecognizedEnumeratorValue);
 
-  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withRawValue:74],
-                               NSException, NSRangeException);
+  XCTAssertThrowsSpecificNamed([array replaceValueAtIndex:4 withRawValue:74], NSException,
+                               NSRangeException);
   [array release];
 }
 
 - (void)testRawInternalResizing {
-  const int32_t kValues[] = { 71, 172, 173, 74 };  // Unknown
-  GPBEnumArray *array =
-      [[GPBEnumArray alloc] initWithValues:kValues
-                                     count:GPBARRAYSIZE(kValues)];
+  const int32_t kValues[] = {71, 172, 173, 74};  // Unknown
+  GPBEnumArray *array = [[GPBEnumArray alloc] initWithValues:kValues count:GPBARRAYSIZE(kValues)];
   XCTAssertNotNil(array);
 
   // Add/remove to trigger the intneral buffer to grow/shrink.
@@ -3611,13 +3558,13 @@
     GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
 
     NSArray *cpy = [array copy];
-    XCTAssertTrue(cpy != array); // Ptr compare
+    XCTAssertTrue(cpy != array);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSArray class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)0);
 
     NSArray *cpy2 = [array copy];
-    XCTAssertTrue(cpy2 != array); // Ptr compare
+    XCTAssertTrue(cpy2 != array);  // Ptr compare
     // Can't compare cpy and cpy2 because NSArray has a singleton empty
     // array it uses, so the ptrs are the same.
     XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]);
@@ -3633,14 +3580,14 @@
     GPBAutocreatedArray *array = [[GPBAutocreatedArray alloc] init];
 
     NSMutableArray *cpy = [array mutableCopy];
-    XCTAssertTrue(cpy != array); // Ptr compare
+    XCTAssertTrue(cpy != array);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSMutableArray class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)0);
 
     NSMutableArray *cpy2 = [array mutableCopy];
-    XCTAssertTrue(cpy2 != array); // Ptr compare
-    XCTAssertTrue(cpy2 != cpy); // Ptr compare
+    XCTAssertTrue(cpy2 != array);  // Ptr compare
+    XCTAssertTrue(cpy2 != cpy);    // Ptr compare
     XCTAssertTrue([cpy2 isKindOfClass:[NSMutableArray class]]);
     XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(cpy2.count, (NSUInteger)0);
@@ -3656,7 +3603,7 @@
     [array addObject:@"bar"];
 
     NSArray *cpy = [array copy];
-    XCTAssertTrue(cpy != array); // Ptr compare
+    XCTAssertTrue(cpy != array);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSArray class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)2);
@@ -3664,8 +3611,8 @@
     XCTAssertEqualObjects(cpy[1], @"bar");
 
     NSArray *cpy2 = [array copy];
-    XCTAssertTrue(cpy2 != array); // Ptr compare
-    XCTAssertTrue(cpy2 != cpy); // Ptr compare
+    XCTAssertTrue(cpy2 != array);  // Ptr compare
+    XCTAssertTrue(cpy2 != cpy);    // Ptr compare
     XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]);
     XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(cpy2.count, (NSUInteger)2);
@@ -3683,7 +3630,7 @@
     [array addObject:@"bar"];
 
     NSMutableArray *cpy = [array mutableCopy];
-    XCTAssertTrue(cpy != array); // Ptr compare
+    XCTAssertTrue(cpy != array);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSArray class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)2);
@@ -3691,8 +3638,8 @@
     XCTAssertEqualObjects(cpy[1], @"bar");
 
     NSMutableArray *cpy2 = [array mutableCopy];
-    XCTAssertTrue(cpy2 != array); // Ptr compare
-    XCTAssertTrue(cpy2 != cpy); // Ptr compare
+    XCTAssertTrue(cpy2 != array);  // Ptr compare
+    XCTAssertTrue(cpy2 != cpy);    // Ptr compare
     XCTAssertTrue([cpy2 isKindOfClass:[NSArray class]]);
     XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(cpy2.count, (NSUInteger)2);
diff --git a/objectivec/Tests/GPBCodedInputStreamTests.m b/objectivec/Tests/GPBCodedInputStreamTests.m
index 6cd5a1f..0504062 100644
--- a/objectivec/Tests/GPBCodedInputStreamTests.m
+++ b/objectivec/Tests/GPBCodedInputStreamTests.m
@@ -34,7 +34,7 @@
 #import "GPBCodedOutputStream.h"
 #import "GPBUnknownFieldSet_PackagePrivate.h"
 #import "GPBUtilities_PackagePrivate.h"
-#import "google/protobuf/Unittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
 
 @interface CodedInputStreamTests : GPBTestCase
 @end
@@ -82,8 +82,10 @@
   [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x7FFFFFFF];
   [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F) value:(int32_t)0x80000000];
 
-  [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x7FFFFFFFFFFFFFFFL];
-  [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01) value:0x8000000000000000L];
+  [self assertReadZigZag64:bytes(0xFE, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)
+                     value:0x7FFFFFFFFFFFFFFFL];
+  [self assertReadZigZag64:bytes(0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0x01)
+                     value:0x8000000000000000L];
 }
 
 - (void)assertReadVarint:(NSData*)data value:(int64_t)value {
@@ -201,30 +203,25 @@
                    value:(0x22 << 0) | (0x22 << 7) | (0x22 << 14) | (0x74 << 21)];
   // 2961488830
   [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
-                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
-                         (0x04 << 21) | (0x0bLL << 28)];
+                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bLL << 28)];
 
   // 64-bit
   // 7256456126
   [self assertReadVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
-                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
-                         (0x04 << 21) | (0x1bLL << 28)];
+                   value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x1bLL << 28)];
   // 41256202580718336
   [self assertReadVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
-                   value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
-                         (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
-                         (0x24LL << 42) | (0x49LL << 49)];
+                   value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | (0x43LL << 28) |
+                         (0x49LL << 35) | (0x24LL << 42) | (0x49LL << 49)];
   // 11964378330978735131
-  [self
-      assertReadVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
-                             0xa6, 0x01)
-                 value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) |
-                       (0x3bLL << 28) | (0x56LL << 35) | (0x00LL << 42) |
-                       (0x05LL << 49) | (0x26LL << 56) | (0x01ULL << 63)];
+  [self assertReadVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01)
+                   value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bLL << 28) |
+                         (0x56LL << 35) | (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) |
+                         (0x01ULL << 63)];
 
   // Failures
-  [self assertReadVarintFailure:bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-                                      0x80, 0x80, 0x80, 0x00)];
+  [self assertReadVarintFailure:bytes(0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
+                                      0x00)];
   [self assertReadVarintFailure:bytes(0x80)];
 }
 
@@ -268,16 +265,12 @@
 }
 
 - (void)testReadLittleEndian {
-  [self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
-                           value:0x12345678];
-  [self assertReadLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
-                           value:0x9abcdef0];
+  [self assertReadLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12) value:0x12345678];
+  [self assertReadLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a) value:0x9abcdef0];
 
-  [self assertReadLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34,
-                                       0x12)
+  [self assertReadLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12)
                            value:0x123456789abcdef0LL];
-  [self assertReadLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc,
-                                       0x9a)
+  [self assertReadLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a)
                            value:0x9abcdef012345678LL];
 }
 
@@ -287,8 +280,7 @@
   NSData* rawBytes = message.data;
   XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
 
-  TestAllTypes* message2 =
-      [TestAllTypes parseFromData:rawBytes extensionRegistry:nil error:NULL];
+  TestAllTypes* message2 = [TestAllTypes parseFromData:rawBytes extensionRegistry:nil error:NULL];
   [self assertAllFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
 }
 
@@ -300,8 +292,7 @@
   // skipField() to skip each field on the other.  Expect the same tags.
   GPBCodedInputStream* input1 = [GPBCodedInputStream streamWithData:rawBytes];
   GPBCodedInputStream* input2 = [GPBCodedInputStream streamWithData:rawBytes];
-  GPBUnknownFieldSet* unknownFields =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease];
 
   while (YES) {
     int32_t tag = [input1 readTag];
@@ -329,10 +320,9 @@
   // Serialize and parse it.  Make sure to parse from an InputStream, not
   // directly from a ByteString, so that CodedInputStream uses buffered
   // reading.
-  NSData *messageData = message.data;
+  NSData* messageData = message.data;
   XCTAssertNotNil(messageData);
-  GPBCodedInputStream* stream =
-      [GPBCodedInputStream streamWithData:messageData];
+  GPBCodedInputStream* stream = [GPBCodedInputStream streamWithData:messageData];
   TestAllTypes* message2 = [TestAllTypes parseFromCodedInputStream:stream
                                                  extensionRegistry:nil
                                                              error:NULL];
@@ -350,8 +340,7 @@
 
 - (void)testReadMaliciouslyLargeBlob {
   NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-  GPBCodedOutputStream* output =
-      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+  GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
 
   int32_t tag = GPBWireFormatMakeTag(1, GPBWireFormatLengthDelimited);
   [output writeRawVarint32:tag];
@@ -360,8 +349,7 @@
   [output writeRawData:[NSData dataWithBytes:bytes length:32]];
   [output flush];
 
-  NSData* data =
-      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  NSData* data = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
   GPBCodedInputStream* input =
       [GPBCodedInputStream streamWithData:[NSMutableData dataWithData:data]];
   XCTAssertEqual(tag, [input readTag]);
@@ -370,23 +358,21 @@
 }
 
 - (void)testReadEmptyString {
-  NSData *data = bytes(0x00);
+  NSData* data = bytes(0x00);
   GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
   XCTAssertEqualObjects(@"", [input readString]);
 }
 
 - (void)testInvalidGroupEndTagThrows {
-  NSData *data = bytes(0x0B, 0x1A, 0x02, 0x4B, 0x50, 0x14);
+  NSData* data = bytes(0x0B, 0x1A, 0x02, 0x4B, 0x50, 0x14);
   GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
-  XCTAssertThrowsSpecificNamed([input skipMessage],
-                               NSException,
-                               GPBCodedInputStreamException,
+  XCTAssertThrowsSpecificNamed([input skipMessage], NSException, GPBCodedInputStreamException,
                                @"should throw a GPBCodedInputStreamException exception ");
 }
 
 - (void)testBytesWithNegativeSize {
-  NSData *data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F);
-  GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:data];
+  NSData* data = bytes(0xFF, 0xFF, 0xFF, 0xFF, 0x0F);
+  GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
   XCTAssertNil([input readBytes]);
 }
 
@@ -396,11 +382,10 @@
 // again, it will help validate that class' handing of bad utf8.
 - (void)testReadMalformedString {
   NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-  GPBCodedOutputStream* output =
-      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+  GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
 
-  int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
-                                     GPBWireFormatLengthDelimited);
+  int32_t tag =
+      GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString, GPBWireFormatLengthDelimited);
   [output writeRawVarint32:tag];
   [output writeRawVarint32:5];
   // Create an invalid utf-8 byte array.
@@ -408,10 +393,9 @@
   [output writeRawData:[NSData dataWithBytes:bytes length:sizeof(bytes)]];
   [output flush];
 
-  NSData *data =
-      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  NSData* data = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
   GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
-  NSError *error = nil;
+  NSError* error = nil;
   TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
                                                 extensionRegistry:nil
                                                             error:&error];
@@ -425,27 +409,25 @@
   // correctly. (Again, this is inpart in case a custom string class is ever
   // used again.)
   const char* strs[] = {
-    "\xEF\xBB\xBF String with BOM",
-    "String with \xEF\xBB\xBF in middle",
-    "String with end bom \xEF\xBB\xBF",
-    "\xEF\xBB\xBF\xe2\x99\xa1",  // BOM White Heart
-    "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
+      "\xEF\xBB\xBF String with BOM",
+      "String with \xEF\xBB\xBF in middle",
+      "String with end bom \xEF\xBB\xBF",
+      "\xEF\xBB\xBF\xe2\x99\xa1",  // BOM White Heart
+      "\xEF\xBB\xBF\xEF\xBB\xBF String with Two BOM",
   };
   for (size_t i = 0; i < GPBARRAYSIZE(strs); ++i) {
     NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-    GPBCodedOutputStream* output =
-        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+    GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
 
-    int32_t tag = GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString,
-                                       GPBWireFormatLengthDelimited);
+    int32_t tag =
+        GPBWireFormatMakeTag(TestAllTypes_FieldNumber_DefaultString, GPBWireFormatLengthDelimited);
     [output writeRawVarint32:tag];
     size_t length = strlen(strs[i]);
     [output writeRawVarint32:(int32_t)length];
     [output writeRawData:[NSData dataWithBytes:strs[i] length:length]];
     [output flush];
 
-    NSData* data =
-        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    NSData* data = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
     GPBCodedInputStream* input = [GPBCodedInputStream streamWithData:data];
     TestAllTypes* message = [TestAllTypes parseFromCodedInputStream:input
                                                   extensionRegistry:nil
diff --git a/objectivec/Tests/GPBCodedOuputStreamTests.m b/objectivec/Tests/GPBCodedOutputStreamTests.m
similarity index 70%
rename from objectivec/Tests/GPBCodedOuputStreamTests.m
rename to objectivec/Tests/GPBCodedOutputStreamTests.m
index a9934ac..a619cae 100644
--- a/objectivec/Tests/GPBCodedOuputStreamTests.m
+++ b/objectivec/Tests/GPBCodedOutputStreamTests.m
@@ -30,26 +30,23 @@
 
 #import "GPBTestUtilities.h"
 
-#import "GPBCodedOutputStream_PackagePrivate.h"
 #import "GPBCodedInputStream.h"
+#import "GPBCodedOutputStream_PackagePrivate.h"
 #import "GPBUtilities_PackagePrivate.h"
-#import "google/protobuf/Unittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
 
 @interface GPBCodedOutputStream (InternalMethods)
 // Declared in the .m file, expose for testing.
-- (instancetype)initWithOutputStream:(NSOutputStream *)output
-                                data:(NSMutableData *)data;
+- (instancetype)initWithOutputStream:(NSOutputStream*)output data:(NSMutableData*)data;
 @end
 
 @interface GPBCodedOutputStream (Helper)
-+ (instancetype)streamWithOutputStream:(NSOutputStream *)output
-                            bufferSize:(size_t)bufferSize;
++ (instancetype)streamWithOutputStream:(NSOutputStream*)output bufferSize:(size_t)bufferSize;
 @end
 
 @implementation GPBCodedOutputStream (Helper)
-+ (instancetype)streamWithOutputStream:(NSOutputStream *)output
-                            bufferSize:(size_t)bufferSize {
-  NSMutableData *data = [NSMutableData dataWithLength:bufferSize];
++ (instancetype)streamWithOutputStream:(NSOutputStream*)output bufferSize:(size_t)bufferSize {
+  NSMutableData* data = [NSMutableData dataWithLength:bufferSize];
   return [[[self alloc] initWithOutputStream:output data:data] autorelease];
 }
 @end
@@ -81,20 +78,17 @@
 
 - (void)assertWriteLittleEndian32:(NSData*)data value:(int32_t)value {
   NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-  GPBCodedOutputStream* output =
-      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+  GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
   [output writeRawLittleEndian32:(int32_t)value];
   [output flush];
 
-  NSData* actual =
-      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
   XCTAssertEqualObjects(data, actual);
 
   // Try different block sizes.
   for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
     rawOutput = [NSOutputStream outputStreamToMemory];
-    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
-                                               bufferSize:blockSize];
+    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput bufferSize:blockSize];
     [output writeRawLittleEndian32:(int32_t)value];
     [output flush];
 
@@ -105,20 +99,17 @@
 
 - (void)assertWriteLittleEndian64:(NSData*)data value:(int64_t)value {
   NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-  GPBCodedOutputStream* output =
-      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+  GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
   [output writeRawLittleEndian64:value];
   [output flush];
 
-  NSData* actual =
-      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
   XCTAssertEqualObjects(data, actual);
 
   // Try different block sizes.
   for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
     rawOutput = [NSOutputStream outputStreamToMemory];
-    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
-                                               bufferSize:blockSize];
+    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput bufferSize:blockSize];
     [output writeRawLittleEndian64:value];
     [output flush];
 
@@ -131,29 +122,24 @@
   // Only do 32-bit write if the value fits in 32 bits.
   if (GPBLogicalRightShift64(value, 32) == 0) {
     NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-    GPBCodedOutputStream* output =
-        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+    GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
     [output writeRawVarint32:(int32_t)value];
     [output flush];
 
-    NSData* actual =
-        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
     XCTAssertEqualObjects(data, actual);
 
     // Also try computing size.
-    XCTAssertEqual(GPBComputeRawVarint32Size((int32_t)value),
-                   (size_t)data.length);
+    XCTAssertEqual(GPBComputeRawVarint32Size((int32_t)value), (size_t)data.length);
   }
 
   {
     NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-    GPBCodedOutputStream* output =
-        [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+    GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
     [output writeRawVarint64:value];
     [output flush];
 
-    NSData* actual =
-        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
     XCTAssertEqualObjects(data, actual);
 
     // Also try computing size.
@@ -165,52 +151,45 @@
     // Only do 32-bit write if the value fits in 32 bits.
     if (GPBLogicalRightShift64(value, 32) == 0) {
       NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-      GPBCodedOutputStream* output =
-          [GPBCodedOutputStream streamWithOutputStream:rawOutput
-                                            bufferSize:blockSize];
+      GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                                                       bufferSize:blockSize];
 
       [output writeRawVarint32:(int32_t)value];
       [output flush];
 
-      NSData* actual =
-          [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+      NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
       XCTAssertEqualObjects(data, actual);
     }
 
     {
       NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-      GPBCodedOutputStream* output =
-          [GPBCodedOutputStream streamWithOutputStream:rawOutput
-                                            bufferSize:blockSize];
+      GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                                                       bufferSize:blockSize];
 
       [output writeRawVarint64:value];
       [output flush];
 
-      NSData* actual =
-          [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+      NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
       XCTAssertEqualObjects(data, actual);
     }
   }
 }
 
 - (void)assertWriteStringNoTag:(NSData*)data
-                         value:(NSString *)value
-                       context:(NSString *)contextMessage {
+                         value:(NSString*)value
+                       context:(NSString*)contextMessage {
   NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-  GPBCodedOutputStream* output =
-      [GPBCodedOutputStream streamWithOutputStream:rawOutput];
+  GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput];
   [output writeStringNoTag:value];
   [output flush];
 
-  NSData* actual =
-      [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+  NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
   XCTAssertEqualObjects(data, actual, @"%@", contextMessage);
 
   // Try different block sizes.
   for (int blockSize = 1; blockSize <= 16; blockSize *= 2) {
     rawOutput = [NSOutputStream outputStreamToMemory];
-    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
-                                               bufferSize:blockSize];
+    output = [GPBCodedOutputStream streamWithOutputStream:rawOutput bufferSize:blockSize];
     [output writeStringNoTag:value];
     [output flush];
 
@@ -243,51 +222,41 @@
 
   // 1887747006 (no sign bit)
   [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x07)
-                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
-                          (0x04 << 21) | (0x07LL << 28)];
+                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x07LL << 28)];
   // 2961488830 (sign bit)
   [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x0b)
-                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
-                          (0x04 << 21) | (0x0bLL << 28)];
+                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x0bLL << 28)];
 }
 
 - (void)testWriteVarint6 {
   // 64-bit
   // 7256456126
   [self assertWriteVarint:bytes(0xbe, 0xf7, 0x92, 0x84, 0x1b)
-                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) |
-                          (0x04 << 21) | (0x1bLL << 28)];
+                    value:(0x3e << 0) | (0x77 << 7) | (0x12 << 14) | (0x04 << 21) | (0x1bLL << 28)];
 }
 
 - (void)testWriteVarint7 {
   // 41256202580718336
   [self assertWriteVarint:bytes(0x80, 0xe6, 0xeb, 0x9c, 0xc3, 0xc9, 0xa4, 0x49)
-                    value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) |
-                          (0x1c << 21) | (0x43LL << 28) | (0x49LL << 35) |
-                          (0x24LL << 42) | (0x49LL << 49)];
+                    value:(0x00 << 0) | (0x66 << 7) | (0x6b << 14) | (0x1c << 21) | (0x43LL << 28) |
+                          (0x49LL << 35) | (0x24LL << 42) | (0x49LL << 49)];
 }
 
 - (void)testWriteVarint8 {
   // 11964378330978735131
-  [self assertWriteVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85,
-                                0xa6, 0x01)
-                    value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) |
-                          (0x42 << 21) | (0x3bLL << 28) | (0x56LL << 35) |
-                          (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) |
+  [self assertWriteVarint:bytes(0x9b, 0xa8, 0xf9, 0xc2, 0xbb, 0xd6, 0x80, 0x85, 0xa6, 0x01)
+                    value:(0x1b << 0) | (0x28 << 7) | (0x79 << 14) | (0x42 << 21) | (0x3bLL << 28) |
+                          (0x56LL << 35) | (0x00LL << 42) | (0x05LL << 49) | (0x26LL << 56) |
                           (0x01ULL << 63)];
 }
 
 - (void)testWriteLittleEndian {
-  [self assertWriteLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12)
-                            value:0x12345678];
-  [self assertWriteLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a)
-                            value:0x9abcdef0];
+  [self assertWriteLittleEndian32:bytes(0x78, 0x56, 0x34, 0x12) value:0x12345678];
+  [self assertWriteLittleEndian32:bytes(0xf0, 0xde, 0xbc, 0x9a) value:0x9abcdef0];
 
-  [self assertWriteLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56,
-                                        0x34, 0x12)
+  [self assertWriteLittleEndian64:bytes(0xf0, 0xde, 0xbc, 0x9a, 0x78, 0x56, 0x34, 0x12)
                             value:0x123456789abcdef0LL];
-  [self assertWriteLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde,
-                                        0xbc, 0x9a)
+  [self assertWriteLittleEndian64:bytes(0x78, 0x56, 0x34, 0x12, 0xf0, 0xde, 0xbc, 0x9a)
                             value:0x9abcdef012345678LL];
 }
 
@@ -305,18 +274,12 @@
   XCTAssertEqual(1ULL, GPBEncodeZigZag64(-1));
   XCTAssertEqual(2ULL, GPBEncodeZigZag64(1));
   XCTAssertEqual(3ULL, GPBEncodeZigZag64(-2));
-  XCTAssertEqual(0x000000007FFFFFFEULL,
-                 GPBEncodeZigZag64(0x000000003FFFFFFFLL));
-  XCTAssertEqual(0x000000007FFFFFFFULL,
-                 GPBEncodeZigZag64(0xFFFFFFFFC0000000LL));
-  XCTAssertEqual(0x00000000FFFFFFFEULL,
-                 GPBEncodeZigZag64(0x000000007FFFFFFFLL));
-  XCTAssertEqual(0x00000000FFFFFFFFULL,
-                 GPBEncodeZigZag64(0xFFFFFFFF80000000LL));
-  XCTAssertEqual(0xFFFFFFFFFFFFFFFEULL,
-                 GPBEncodeZigZag64(0x7FFFFFFFFFFFFFFFLL));
-  XCTAssertEqual(0xFFFFFFFFFFFFFFFFULL,
-                 GPBEncodeZigZag64(0x8000000000000000LL));
+  XCTAssertEqual(0x000000007FFFFFFEULL, GPBEncodeZigZag64(0x000000003FFFFFFFLL));
+  XCTAssertEqual(0x000000007FFFFFFFULL, GPBEncodeZigZag64(0xFFFFFFFFC0000000LL));
+  XCTAssertEqual(0x00000000FFFFFFFEULL, GPBEncodeZigZag64(0x000000007FFFFFFFLL));
+  XCTAssertEqual(0x00000000FFFFFFFFULL, GPBEncodeZigZag64(0xFFFFFFFF80000000LL));
+  XCTAssertEqual(0xFFFFFFFFFFFFFFFEULL, GPBEncodeZigZag64(0x7FFFFFFFFFFFFFFFLL));
+  XCTAssertEqual(0xFFFFFFFFFFFFFFFFULL, GPBEncodeZigZag64(0x8000000000000000LL));
 
   // Some easier-to-verify round-trip tests.  The inputs (other than 0, 1, -1)
   // were chosen semi-randomly via keyboard bashing.
@@ -332,10 +295,8 @@
   XCTAssertEqual(14927ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(14927)));
   XCTAssertEqual(-3612ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-3612)));
 
-  XCTAssertEqual(856912304801416ULL,
-                 GPBEncodeZigZag64(GPBDecodeZigZag64(856912304801416LL)));
-  XCTAssertEqual(-75123905439571256ULL,
-                 GPBEncodeZigZag64(GPBDecodeZigZag64(-75123905439571256LL)));
+  XCTAssertEqual(856912304801416ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(856912304801416LL)));
+  XCTAssertEqual(-75123905439571256ULL, GPBEncodeZigZag64(GPBDecodeZigZag64(-75123905439571256LL)));
 }
 
 - (void)testWriteWholeMessage {
@@ -344,21 +305,18 @@
   TestAllTypes* message = [self allSetRepeatedCount:2];
 
   NSData* rawBytes = message.data;
-  NSData* goldenData =
-      [self getDataFileNamed:@"golden_message" dataToWrite:rawBytes];
+  NSData* goldenData = [self getDataFileNamed:@"golden_message" dataToWrite:rawBytes];
   XCTAssertEqualObjects(rawBytes, goldenData);
 
   // Try different block sizes.
   for (int blockSize = 1; blockSize < 256; blockSize *= 2) {
     NSOutputStream* rawOutput = [NSOutputStream outputStreamToMemory];
-    GPBCodedOutputStream* output =
-        [GPBCodedOutputStream streamWithOutputStream:rawOutput
-                                          bufferSize:blockSize];
+    GPBCodedOutputStream* output = [GPBCodedOutputStream streamWithOutputStream:rawOutput
+                                                                     bufferSize:blockSize];
     [message writeToCodedOutputStream:output];
     [output flush];
 
-    NSData* actual =
-        [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
+    NSData* actual = [rawOutput propertyForKey:NSStreamDataWrittenToMemoryStreamKey];
     XCTAssertEqualObjects(rawBytes, actual);
   }
 
@@ -366,8 +324,7 @@
   // that was generated with 2.
   TestAllExtensions* extensions = [self allExtensionsSetRepeatedCount:2];
   rawBytes = extensions.data;
-  goldenData = [self getDataFileNamed:@"golden_packed_fields_message"
-                          dataToWrite:rawBytes];
+  goldenData = [self getDataFileNamed:@"golden_packed_fields_message" dataToWrite:rawBytes];
   XCTAssertEqualObjects(rawBytes, goldenData);
 }
 
@@ -380,11 +337,10 @@
 
   char zeroTest[] = "\0Test\0String";
   // Note: there is a \0 at the end of this since it is a c-string.
-  NSString *asNSString = [[NSString alloc] initWithBytes:zeroTest
+  NSString* asNSString = [[NSString alloc] initWithBytes:zeroTest
                                                   length:sizeof(zeroTest)
                                                 encoding:NSUTF8StringEncoding];
-  const char *cString =
-      CFStringGetCStringPtr((CFStringRef)asNSString, kCFStringEncodingUTF8);
+  const char* cString = CFStringGetCStringPtr((CFStringRef)asNSString, kCFStringEncodingUTF8);
   XCTAssertTrue(cString != NULL);
   // Again, if the above assert fails, then it means NSString no longer exposes
   // the raw utf8 storage of a string created from utf8 input, so the code using
@@ -392,8 +348,7 @@
   // a different code path); but the optimizations for when
   // CFStringGetCStringPtr does work could possibly go away.
 
-  XCTAssertEqual(sizeof(zeroTest),
-                 [asNSString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertEqual(sizeof(zeroTest), [asNSString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]);
   XCTAssertTrue(0 == memcmp(cString, zeroTest, sizeof(zeroTest)));
   [asNSString release];
 }
@@ -405,25 +360,25 @@
   // strings built via the NSString apis. So this round trips them to ensure
   // they are acting as expected.
 
-  NSArray<NSString *> *strs = @[
+  NSArray<NSString*>* strs = @[
     @"\0at start",
     @"in\0middle",
     @"at end\0",
   ];
   int i = 0;
-  for (NSString *str in strs) {
-    NSData *asUTF8 = [str dataUsingEncoding:NSUTF8StringEncoding];
-    NSMutableData *expected = [NSMutableData data];
+  for (NSString* str in strs) {
+    NSData* asUTF8 = [str dataUsingEncoding:NSUTF8StringEncoding];
+    NSMutableData* expected = [NSMutableData data];
     uint8_t lengthByte = (uint8_t)asUTF8.length;
     [expected appendBytes:&lengthByte length:1];
     [expected appendData:asUTF8];
 
-    NSString *context = [NSString stringWithFormat:@"Loop %d - Literal", i];
+    NSString* context = [NSString stringWithFormat:@"Loop %d - Literal", i];
     [self assertWriteStringNoTag:expected value:str context:context];
 
     // Force a new string to be built which gets a different class from the
     // NSString class cluster than the literal did.
-    NSString *str2 = [NSString stringWithFormat:@"%@", str];
+    NSString* str2 = [NSString stringWithFormat:@"%@", str];
     context = [NSString stringWithFormat:@"Loop %d - Built", i];
     [self assertWriteStringNoTag:expected value:str2 context:context];
 
@@ -432,11 +387,11 @@
 }
 
 - (void)testThatItThrowsWhenWriteRawPtrFails {
-  NSOutputStream *output = [NSOutputStream outputStreamToMemory];
-  GPBCodedOutputStream *codedOutput =
+  NSOutputStream* output = [NSOutputStream outputStreamToMemory];
+  GPBCodedOutputStream* codedOutput =
       [GPBCodedOutputStream streamWithOutputStream:output bufferSize:0];  // Skip buffering.
   [output close];  // Close the output stream to force failure on write.
-  const char *cString = "raw";
+  const char* cString = "raw";
   XCTAssertThrowsSpecificNamed([codedOutput writeRawPtr:cString offset:0 length:strlen(cString)],
                                NSException, GPBCodedOutputStreamException_WriteFailed);
 }
diff --git a/objectivec/Tests/GPBCompileTest01.m b/objectivec/Tests/GPBCompileTest01.m
index c8bc433..c8a6e6b 100644
--- a/objectivec/Tests/GPBCompileTest01.m
+++ b/objectivec/Tests/GPBCompileTest01.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBArray.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_1 = 0;
diff --git a/objectivec/Tests/GPBCompileTest02.m b/objectivec/Tests/GPBCompileTest02.m
index c44e201..77e4589 100644
--- a/objectivec/Tests/GPBCompileTest02.m
+++ b/objectivec/Tests/GPBCompileTest02.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBCodedInputStream.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_2 = 0;
diff --git a/objectivec/Tests/GPBCompileTest03.m b/objectivec/Tests/GPBCompileTest03.m
index 41994f9..f4945a7 100644
--- a/objectivec/Tests/GPBCompileTest03.m
+++ b/objectivec/Tests/GPBCompileTest03.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBCodedOutputStream.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_3 = 0;
diff --git a/objectivec/Tests/GPBCompileTest04.m b/objectivec/Tests/GPBCompileTest04.m
index c31498f..da69c1d 100644
--- a/objectivec/Tests/GPBCompileTest04.m
+++ b/objectivec/Tests/GPBCompileTest04.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBDescriptor.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_4 = 0;
diff --git a/objectivec/Tests/GPBCompileTest05.m b/objectivec/Tests/GPBCompileTest05.m
index adb7225..e4665ea 100644
--- a/objectivec/Tests/GPBCompileTest05.m
+++ b/objectivec/Tests/GPBCompileTest05.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBDictionary.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_5 = 0;
diff --git a/objectivec/Tests/GPBCompileTest06.m b/objectivec/Tests/GPBCompileTest06.m
index b7505b0..c197b56 100644
--- a/objectivec/Tests/GPBCompileTest06.m
+++ b/objectivec/Tests/GPBCompileTest06.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBExtensionRegistry.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_6 = 0;
diff --git a/objectivec/Tests/GPBCompileTest07.m b/objectivec/Tests/GPBCompileTest07.m
index 939bb70..83f7a8f 100644
--- a/objectivec/Tests/GPBCompileTest07.m
+++ b/objectivec/Tests/GPBCompileTest07.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBMessage.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_7 = 0;
diff --git a/objectivec/Tests/GPBCompileTest08.m b/objectivec/Tests/GPBCompileTest08.m
index a84f38c..48246f8 100644
--- a/objectivec/Tests/GPBCompileTest08.m
+++ b/objectivec/Tests/GPBCompileTest08.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBRootObject.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_8 = 0;
diff --git a/objectivec/Tests/GPBCompileTest09.m b/objectivec/Tests/GPBCompileTest09.m
index f8ccb4a..d1d8cdf 100644
--- a/objectivec/Tests/GPBCompileTest09.m
+++ b/objectivec/Tests/GPBCompileTest09.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBUnknownField.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_9 = 0;
diff --git a/objectivec/Tests/GPBCompileTest10.m b/objectivec/Tests/GPBCompileTest10.m
index d831867..31f610d 100644
--- a/objectivec/Tests/GPBCompileTest10.m
+++ b/objectivec/Tests/GPBCompileTest10.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBUnknownFieldSet.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_10 = 0;
diff --git a/objectivec/Tests/GPBCompileTest11.m b/objectivec/Tests/GPBCompileTest11.m
index 9f2c6b1..2f51ec9 100644
--- a/objectivec/Tests/GPBCompileTest11.m
+++ b/objectivec/Tests/GPBCompileTest11.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBUtilities.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_11 = 0;
diff --git a/objectivec/Tests/GPBCompileTest12.m b/objectivec/Tests/GPBCompileTest12.m
index 3aa29b3..9892bcf 100644
--- a/objectivec/Tests/GPBCompileTest12.m
+++ b/objectivec/Tests/GPBCompileTest12.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBWellKnownTypes.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_12 = 0;
diff --git a/objectivec/Tests/GPBCompileTest13.m b/objectivec/Tests/GPBCompileTest13.m
index fef2af5..d5168ae 100644
--- a/objectivec/Tests/GPBCompileTest13.m
+++ b/objectivec/Tests/GPBCompileTest13.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBWireFormat.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_13 = 0;
diff --git a/objectivec/Tests/GPBCompileTest14.m b/objectivec/Tests/GPBCompileTest14.m
index 1e64b71..cd59f6f 100644
--- a/objectivec/Tests/GPBCompileTest14.m
+++ b/objectivec/Tests/GPBCompileTest14.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBAny.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_14 = 0;
diff --git a/objectivec/Tests/GPBCompileTest15.m b/objectivec/Tests/GPBCompileTest15.m
index 2eaedb2..ad9a3f8 100644
--- a/objectivec/Tests/GPBCompileTest15.m
+++ b/objectivec/Tests/GPBCompileTest15.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBApi.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_15 = 0;
diff --git a/objectivec/Tests/GPBCompileTest16.m b/objectivec/Tests/GPBCompileTest16.m
index 25af89e..c5b532e 100644
--- a/objectivec/Tests/GPBCompileTest16.m
+++ b/objectivec/Tests/GPBCompileTest16.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBDuration.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_16 = 0;
diff --git a/objectivec/Tests/GPBCompileTest17.m b/objectivec/Tests/GPBCompileTest17.m
index c719ad3..02988e6 100644
--- a/objectivec/Tests/GPBCompileTest17.m
+++ b/objectivec/Tests/GPBCompileTest17.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBEmpty.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_17 = 0;
diff --git a/objectivec/Tests/GPBCompileTest18.m b/objectivec/Tests/GPBCompileTest18.m
index a02b259..a652c61 100644
--- a/objectivec/Tests/GPBCompileTest18.m
+++ b/objectivec/Tests/GPBCompileTest18.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBFieldMask.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_18 = 0;
diff --git a/objectivec/Tests/GPBCompileTest19.m b/objectivec/Tests/GPBCompileTest19.m
index b447284..7ea31a8 100644
--- a/objectivec/Tests/GPBCompileTest19.m
+++ b/objectivec/Tests/GPBCompileTest19.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBSourceContext.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_19 = 0;
diff --git a/objectivec/Tests/GPBCompileTest20.m b/objectivec/Tests/GPBCompileTest20.m
index 120ef55..d79ceea 100644
--- a/objectivec/Tests/GPBCompileTest20.m
+++ b/objectivec/Tests/GPBCompileTest20.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBStruct.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_20 = 0;
diff --git a/objectivec/Tests/GPBCompileTest21.m b/objectivec/Tests/GPBCompileTest21.m
index 766d890..0a273da 100644
--- a/objectivec/Tests/GPBCompileTest21.m
+++ b/objectivec/Tests/GPBCompileTest21.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBTimestamp.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_21 = 0;
diff --git a/objectivec/Tests/GPBCompileTest22.m b/objectivec/Tests/GPBCompileTest22.m
index 6d0955b..05cd01c 100644
--- a/objectivec/Tests/GPBCompileTest22.m
+++ b/objectivec/Tests/GPBCompileTest22.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBType.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_22 = 0;
diff --git a/objectivec/Tests/GPBCompileTest23.m b/objectivec/Tests/GPBCompileTest23.m
index 22f2db6..ec29f3a 100644
--- a/objectivec/Tests/GPBCompileTest23.m
+++ b/objectivec/Tests/GPBCompileTest23.m
@@ -28,13 +28,11 @@
 // (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 a test including a single public header to ensure things build.
 // It helps test that imports are complete/ordered correctly.
 
 #import "GPBWrappers.pbobjc.h"
 
-
 // Something in the body of this file so the compiler/linker won't complain
 // about an empty .o file.
 __attribute__((visibility("default"))) char dummy_symbol_23 = 0;
diff --git a/objectivec/Tests/GPBCompileTest25.m b/objectivec/Tests/GPBCompileTest25.m
deleted file mode 100644
index 7a482b5..0000000
--- a/objectivec/Tests/GPBCompileTest25.m
+++ /dev/null
@@ -1,42 +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.
-
-
-// This is a test including a single header to ensure things build. This
-// is NOT a public header of the library, but uses a file that defines
-// extensions to proto2 syntax messages, so it can need more things
-// that the proto3 syntax WKTs bundled with the library.
-
-#import "google/protobuf/UnittestCustomOptions.pbobjc.h"
-
-
-// Something in the body of this file so the compiler/linker won't complain
-// about an empty .o file.
-__attribute__((visibility("default"))) char dummy_symbol_25 = 0;
diff --git a/objectivec/Tests/GPBConcurrencyTests.m b/objectivec/Tests/GPBConcurrencyTests.m
index daf75e7..4ea62f9 100644
--- a/objectivec/Tests/GPBConcurrencyTests.m
+++ b/objectivec/Tests/GPBConcurrencyTests.m
@@ -30,8 +30,8 @@
 
 #import "GPBTestUtilities.h"
 
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestObjc.pbobjc.h"
 
 static const int kNumThreads = 100;
 static const int kNumMessages = 100;
@@ -49,8 +49,7 @@
 - (NSArray *)createThreadsWithSelector:(SEL)selector object:(id)object {
   NSMutableArray *array = [NSMutableArray array];
   for (NSUInteger i = 0; i < kNumThreads; i++) {
-    NSThread *thread =
-        [[NSThread alloc] initWithTarget:self selector:selector object:object];
+    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:selector object:object];
     [array addObject:thread];
     [thread release];
   }
@@ -88,9 +87,8 @@
 
 - (void)testConcurrentReadOfUnsetMessageField {
   NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
-  NSArray *threads =
-      [self createThreadsWithSelector:@selector(readForeignMessage:)
-                               object:messages];
+  NSArray *threads = [self createThreadsWithSelector:@selector(readForeignMessage:)
+                                              object:messages];
   [self startThreads:threads];
   [self joinThreads:threads];
   for (TestAllTypes *message in messages) {
@@ -108,9 +106,7 @@
 
 - (void)testConcurrentReadOfUnsetRepeatedIntField {
   NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
-  NSArray *threads =
-      [self createThreadsWithSelector:@selector(readRepeatedInt32:)
-                               object:messages];
+  NSArray *threads = [self createThreadsWithSelector:@selector(readRepeatedInt32:) object:messages];
   [self startThreads:threads];
   [self joinThreads:threads];
   for (TestAllTypes *message in messages) {
@@ -128,9 +124,8 @@
 
 - (void)testConcurrentReadOfUnsetRepeatedStringField {
   NSArray *messages = [self createMessagesWithType:[TestAllTypes class]];
-  NSArray *threads =
-      [self createThreadsWithSelector:@selector(readRepeatedString:)
-                               object:messages];
+  NSArray *threads = [self createThreadsWithSelector:@selector(readRepeatedString:)
+                                              object:messages];
   [self startThreads:threads];
   [self joinThreads:threads];
   for (TestAllTypes *message in messages) {
@@ -147,11 +142,8 @@
 }
 
 - (void)testConcurrentReadOfUnsetInt32Int32MapField {
-  NSArray *messages =
-      [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]];
-  NSArray *threads =
-      [self createThreadsWithSelector:@selector(readInt32Int32Map:)
-                               object:messages];
+  NSArray *messages = [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]];
+  NSArray *threads = [self createThreadsWithSelector:@selector(readInt32Int32Map:) object:messages];
   [self startThreads:threads];
   [self joinThreads:threads];
   for (TestRecursiveMessageWithRepeatedField *message in messages) {
@@ -168,11 +160,9 @@
 }
 
 - (void)testConcurrentReadOfUnsetStringStringMapField {
-  NSArray *messages =
-      [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]];
-  NSArray *threads =
-      [self createThreadsWithSelector:@selector(readStringStringMap:)
-                               object:messages];
+  NSArray *messages = [self createMessagesWithType:[TestRecursiveMessageWithRepeatedField class]];
+  NSArray *threads = [self createThreadsWithSelector:@selector(readStringStringMap:)
+                                              object:messages];
   [self startThreads:threads];
   [self joinThreads:threads];
   for (TestRecursiveMessageWithRepeatedField *message in messages) {
@@ -196,8 +186,7 @@
   NSArray *threads = [self createThreadsWithSelector:sel object:messages];
   [self startThreads:threads];
   [self joinThreads:threads];
-  GPBExtensionDescriptor *extension =
-      [UnittestRoot optionalForeignMessageExtension];
+  GPBExtensionDescriptor *extension = [UnittestRoot optionalForeignMessageExtension];
   for (TestAllExtensions *message in messages) {
     XCTAssertFalse([message hasExtension:extension]);
   }
diff --git a/objectivec/Tests/GPBDescriptorTests.m b/objectivec/Tests/GPBDescriptorTests.m
index b1ff544..e528be4 100644
--- a/objectivec/Tests/GPBDescriptorTests.m
+++ b/objectivec/Tests/GPBDescriptorTests.m
@@ -33,9 +33,9 @@
 #import <objc/runtime.h>
 
 #import "GPBDescriptor_PackagePrivate.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestObjc.pbobjc.h"
-#import "google/protobuf/Descriptor.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestObjc.pbobjc.h"
+#import "objectivec/Tests/UnittestObjcOptions.pbobjc.h"
 
 @interface DescriptorTests : GPBTestCase
 @end
@@ -52,37 +52,36 @@
 
 - (void)testDescriptor_fullName {
   GPBDescriptor *testAllTypesDesc = [TestAllTypes descriptor];
-  XCTAssertEqualObjects(testAllTypesDesc.fullName, @"protobuf_unittest.TestAllTypes");
+  XCTAssertEqualObjects(testAllTypesDesc.fullName, @"objc.protobuf.tests.TestAllTypes");
   GPBDescriptor *nestedMessageDesc = [TestAllTypes_NestedMessage descriptor];
-  XCTAssertEqualObjects(nestedMessageDesc.fullName, @"protobuf_unittest.TestAllTypes.NestedMessage");
+  XCTAssertEqualObjects(nestedMessageDesc.fullName,
+                        @"objc.protobuf.tests.TestAllTypes.NestedMessage");
 
   // Prefixes removed.
-  GPBDescriptor *descDesc = [GPBDescriptorProto descriptor];
-  XCTAssertEqualObjects(descDesc.fullName, @"google.protobuf.DescriptorProto");
-  GPBDescriptor *descExtRngDesc = [GPBDescriptorProto_ExtensionRange descriptor];
-  XCTAssertEqualObjects(descExtRngDesc.fullName, @"google.protobuf.DescriptorProto.ExtensionRange");
+  GPBDescriptor *descDesc = [GPBTESTPrefixedParentMessage descriptor];
+  XCTAssertEqualObjects(descDesc.fullName, @"objc.protobuf.tests.options.PrefixedParentMessage");
+  GPBDescriptor *descExtRngDesc = [GPBTESTPrefixedParentMessage_Child descriptor];
+  XCTAssertEqualObjects(descExtRngDesc.fullName,
+                        @"objc.protobuf.tests.options.PrefixedParentMessage.Child");
 
   // Things that get "_Class" added.
   GPBDescriptor *pointDesc = [Point_Class descriptor];
-  XCTAssertEqualObjects(pointDesc.fullName, @"protobuf_unittest.Point");
+  XCTAssertEqualObjects(pointDesc.fullName, @"objc.protobuf.tests.Point");
   GPBDescriptor *pointRectDesc = [Point_Rect descriptor];
-  XCTAssertEqualObjects(pointRectDesc.fullName, @"protobuf_unittest.Point.Rect");
+  XCTAssertEqualObjects(pointRectDesc.fullName, @"objc.protobuf.tests.Point.Rect");
 }
 
 - (void)testFieldDescriptor {
   GPBDescriptor *descriptor = [TestAllTypes descriptor];
 
   // Nested Enum
-  GPBFieldDescriptor *fieldDescriptorWithName =
-      [descriptor fieldWithName:@"optionalNestedEnum"];
+  GPBFieldDescriptor *fieldDescriptorWithName = [descriptor fieldWithName:@"optionalNestedEnum"];
   XCTAssertNotNil(fieldDescriptorWithName);
-  GPBFieldDescriptor *fieldDescriptorWithNumber =
-      [descriptor fieldWithNumber:21];
+  GPBFieldDescriptor *fieldDescriptorWithNumber = [descriptor fieldWithNumber:21];
   XCTAssertNotNil(fieldDescriptorWithNumber);
   XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
   XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
-  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
-                        @"TestAllTypes_NestedEnum");
+  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"TestAllTypes_NestedEnum");
   XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
   XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
 
@@ -93,8 +92,7 @@
   XCTAssertNotNil(fieldDescriptorWithNumber);
   XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
   XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
-  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
-                        @"ForeignEnum");
+  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"ForeignEnum");
   XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
   XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
 
@@ -105,8 +103,7 @@
   XCTAssertNotNil(fieldDescriptorWithNumber);
   XCTAssertEqual(fieldDescriptorWithName, fieldDescriptorWithNumber);
   XCTAssertNotNil(fieldDescriptorWithNumber.enumDescriptor);
-  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name,
-                        @"ImportEnum");
+  XCTAssertEqualObjects(fieldDescriptorWithNumber.enumDescriptor.name, @"ImportEnum");
   XCTAssertEqual(fieldDescriptorWithName.number, fieldDescriptorWithNumber.number);
   XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeEnum);
 
@@ -121,8 +118,7 @@
   XCTAssertEqual(fieldDescriptorWithName.dataType, GPBDataTypeMessage);
 
   // Foreign Message
-  fieldDescriptorWithName =
-      [descriptor fieldWithName:@"optionalForeignMessage"];
+  fieldDescriptorWithName = [descriptor fieldWithName:@"optionalForeignMessage"];
   XCTAssertNotNil(fieldDescriptorWithName);
   fieldDescriptorWithNumber = [descriptor fieldWithNumber:19];
   XCTAssertNotNil(fieldDescriptorWithNumber);
@@ -152,22 +148,18 @@
   NSString *enumName = [descriptor enumNameForValue:1];
   XCTAssertNotNil(enumName);
   int32_t value;
-  XCTAssertTrue(
-      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
-  XCTAssertTrue(
-      [descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+  XCTAssertTrue([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
+  XCTAssertTrue([descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Foo"]);
   XCTAssertEqual(value, TestAllTypes_NestedEnum_Foo);
 
   enumName = [descriptor enumNameForValue:2];
   XCTAssertNotNil(enumName);
-  XCTAssertTrue(
-      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Bar"]);
+  XCTAssertTrue([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Bar"]);
   XCTAssertEqual(value, TestAllTypes_NestedEnum_Bar);
 
   enumName = [descriptor enumNameForValue:3];
   XCTAssertNotNil(enumName);
-  XCTAssertTrue(
-      [descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Baz"]);
+  XCTAssertTrue([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Baz"]);
   XCTAssertEqual(value, TestAllTypes_NestedEnum_Baz);
 
   // TextFormat
@@ -182,10 +174,8 @@
   XCTAssertNil(enumName);
   XCTAssertFalse([descriptor getValue:&value forEnumName:@"Unknown"]);
   XCTAssertFalse([descriptor getValue:NULL forEnumName:@"Unknown"]);
-  XCTAssertFalse([descriptor getValue:&value
-                          forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
-  XCTAssertFalse([descriptor getValue:NULL
-                          forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+  XCTAssertFalse([descriptor getValue:&value forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
+  XCTAssertFalse([descriptor getValue:NULL forEnumName:@"TestAllTypes_NestedEnum_Unknown"]);
   XCTAssertFalse([descriptor getValue:NULL forEnumTextFormatName:@"Unknown"]);
   XCTAssertFalse([descriptor getValue:&value forEnumTextFormatName:@"Unknown"]);
 }
@@ -194,17 +184,13 @@
   GPBEnumDescriptor *descriptor = TestAllTypes_NestedEnum_EnumDescriptor();
 
   XCTAssertEqual(descriptor.enumNameCount, 4U);
-  XCTAssertEqualObjects([descriptor getEnumNameForIndex:0],
-                        @"TestAllTypes_NestedEnum_Foo");
+  XCTAssertEqualObjects([descriptor getEnumNameForIndex:0], @"TestAllTypes_NestedEnum_Foo");
   XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:0], @"FOO");
-  XCTAssertEqualObjects([descriptor getEnumNameForIndex:1],
-                 @"TestAllTypes_NestedEnum_Bar");
+  XCTAssertEqualObjects([descriptor getEnumNameForIndex:1], @"TestAllTypes_NestedEnum_Bar");
   XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:1], @"BAR");
-  XCTAssertEqualObjects([descriptor getEnumNameForIndex:2],
-                 @"TestAllTypes_NestedEnum_Baz");
+  XCTAssertEqualObjects([descriptor getEnumNameForIndex:2], @"TestAllTypes_NestedEnum_Baz");
   XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:2], @"BAZ");
-  XCTAssertEqualObjects([descriptor getEnumNameForIndex:3],
-                 @"TestAllTypes_NestedEnum_Neg");
+  XCTAssertEqualObjects([descriptor getEnumNameForIndex:3], @"TestAllTypes_NestedEnum_Neg");
   XCTAssertEqualObjects([descriptor getEnumTextFormatNameForIndex:3], @"NEG");
 }
 
@@ -286,8 +272,7 @@
 
 - (void)testEnumValueValidator {
   GPBDescriptor *descriptor = [TestAllTypes descriptor];
-  GPBFieldDescriptor *fieldDescriptor =
-      [descriptor fieldWithName:@"optionalNestedEnum"];
+  GPBFieldDescriptor *fieldDescriptor = [descriptor fieldWithName:@"optionalNestedEnum"];
 
   // Valid values
   XCTAssertTrue([fieldDescriptor isValidEnumValue:1]);
@@ -325,12 +310,10 @@
 
   // Pointer comparisons against lookups from message.
 
-  XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString],
-                 fooStringField);
+  XCTAssertEqual([oneofFoo fieldWithNumber:TestOneof2_FieldNumber_FooString], fooStringField);
   XCTAssertEqual([oneofFoo fieldWithName:@"fooString"], fooStringField);
 
-  XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString],
-                 barStringField);
+  XCTAssertEqual([oneofBar fieldWithNumber:TestOneof2_FieldNumber_BarString], barStringField);
   XCTAssertEqual([oneofBar fieldWithName:@"barString"], barStringField);
 
   // Unknown oneof not found.
@@ -354,8 +337,7 @@
   // (pointer comparisons)
   XCTAssertEqual(fooStringField.containingOneof, oneofFoo);
   XCTAssertEqual(barStringField.containingOneof, oneofBar);
-  GPBFieldDescriptor *bazString =
-      [descriptor fieldWithNumber:TestOneof2_FieldNumber_BazString];
+  GPBFieldDescriptor *bazString = [descriptor fieldWithNumber:TestOneof2_FieldNumber_BazString];
   XCTAssertNotNil(bazString);
   XCTAssertNil(bazString.containingOneof);
 }
diff --git a/objectivec/Tests/GPBDictionaryTests+Bool.m b/objectivec/Tests/GPBDictionaryTests+Bool.m
index 4c02144..37f7eb3 100644
--- a/objectivec/Tests/GPBDictionaryTests+Bool.m
+++ b/objectivec/Tests/GPBDictionaryTests+Bool.m
@@ -34,7 +34,10 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+
+// Disable clang-format for the macros.
+// clang-format off
 
 // Pull in the macros (using an external file because expanding all tests
 // in a single file makes a file that is failing to work with within Xcode.
@@ -42,7 +45,6 @@
 
 //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt32, uint32_t, 100U, 101U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> UInt32
 
@@ -56,8 +58,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt32:NULL forKey:YES]);
-  [dict enumerateKeysAndUInt32sUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused BOOL aKey, __unused uint32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -123,8 +124,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt32sUsingBlock:^(BOOL aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused BOOL aKey, __unused uint32_t aValue, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -346,10 +346,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int32, int32_t, 200, 201)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Int32
 
@@ -363,8 +361,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt32:NULL forKey:YES]);
-  [dict enumerateKeysAndInt32sUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused BOOL aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -430,8 +427,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt32sUsingBlock:^(BOOL aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused BOOL aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -653,10 +649,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(UInt64, uint64_t, 300U, 301U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> UInt64
 
@@ -670,8 +664,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt64:NULL forKey:YES]);
-  [dict enumerateKeysAndUInt64sUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused BOOL aKey, __unused uint64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -737,8 +730,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt64sUsingBlock:^(BOOL aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused BOOL aKey, __unused uint64_t aValue, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -960,10 +952,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Int64, int64_t, 400, 401)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Int64
 
@@ -977,8 +967,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt64:NULL forKey:YES]);
-  [dict enumerateKeysAndInt64sUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused BOOL aKey, __unused int64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1044,8 +1033,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt64sUsingBlock:^(BOOL aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused BOOL aKey, __unused int64_t aValue, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1267,10 +1255,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Bool, BOOL, NO, YES)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Bool
 
@@ -1284,8 +1270,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getBool:NULL forKey:YES]);
-  [dict enumerateKeysAndBoolsUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused BOOL aKey, __unused BOOL aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1351,8 +1336,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndBoolsUsingBlock:^(BOOL aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused BOOL aKey, __unused BOOL aValue, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1574,10 +1558,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Float, float, 500.f, 501.f)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Float
 
@@ -1591,8 +1573,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getFloat:NULL forKey:YES]);
-  [dict enumerateKeysAndFloatsUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused BOOL aKey, __unused float aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1658,8 +1639,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndFloatsUsingBlock:^(BOOL aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused BOOL aKey, __unused float aValue, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1881,10 +1861,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND BOOL_TESTS_FOR_POD_VALUE(Double, double, 600., 601.)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Double
 
@@ -1898,8 +1876,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getDouble:NULL forKey:YES]);
-  [dict enumerateKeysAndDoublesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused BOOL aKey, __unused double aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1965,8 +1942,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndDoublesUsingBlock:^(BOOL aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused BOOL aKey, __unused double aValue, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2188,10 +2164,8 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND TESTS_FOR_BOOL_KEY_OBJECT_VALUE(Object, NSString*, @"abc", @"def")
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 #pragma mark - Bool -> Object
 
@@ -2205,8 +2179,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:YES]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject, stop)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused BOOL aKey, __unused NSString* aObject, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2264,8 +2237,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(BOOL aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused BOOL aKey, __unused NSString* aObject, BOOL *stop) {
     if (idx == 0) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2460,7 +2432,6 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END (8 expansions)
 
 
diff --git a/objectivec/Tests/GPBDictionaryTests+Int32.m b/objectivec/Tests/GPBDictionaryTests+Int32.m
index 8dafaac..f08e213 100644
--- a/objectivec/Tests/GPBDictionaryTests+Int32.m
+++ b/objectivec/Tests/GPBDictionaryTests+Int32.m
@@ -34,7 +34,10 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+
+// Disable clang-format for the macros.
+// clang-format off
 
 // Pull in the macros (using an external file because expanding all tests
 // in a single file makes a file that is failing to work with within Xcode.
@@ -42,7 +45,6 @@
 
 //%PDDM-EXPAND TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // To let the testing macros work, add some extra methods to simplify things.
 @interface GPBInt32EnumDictionary (TestingTweak)
@@ -87,8 +89,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt32:NULL forKey:11]);
-  [dict enumerateKeysAndUInt32sUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused int32_t aKey, __unused uint32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -158,8 +159,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt32sUsingBlock:^(int32_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused int32_t aKey, __unused uint32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -448,8 +448,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt32:NULL forKey:11]);
-  [dict enumerateKeysAndInt32sUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused int32_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -519,8 +518,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt32sUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused int32_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -809,8 +807,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt64:NULL forKey:11]);
-  [dict enumerateKeysAndUInt64sUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused int32_t aKey, __unused uint64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -880,8 +877,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt64sUsingBlock:^(int32_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused int32_t aKey, __unused uint64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1170,8 +1166,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt64:NULL forKey:11]);
-  [dict enumerateKeysAndInt64sUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused int32_t aKey, __unused int64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1241,8 +1236,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt64sUsingBlock:^(int32_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused int32_t aKey, __unused int64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1531,8 +1525,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getBool:NULL forKey:11]);
-  [dict enumerateKeysAndBoolsUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused int32_t aKey, __unused BOOL aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1602,8 +1595,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndBoolsUsingBlock:^(int32_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused int32_t aKey, __unused BOOL aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1892,8 +1884,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getFloat:NULL forKey:11]);
-  [dict enumerateKeysAndFloatsUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused int32_t aKey, __unused float aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1963,8 +1954,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndFloatsUsingBlock:^(int32_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused int32_t aKey, __unused float aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2253,8 +2243,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getDouble:NULL forKey:11]);
-  [dict enumerateKeysAndDoublesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused int32_t aKey, __unused double aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2324,8 +2313,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndDoublesUsingBlock:^(int32_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused int32_t aKey, __unused double aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2614,8 +2602,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getEnum:NULL forKey:11]);
-  [dict enumerateKeysAndEnumsUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused int32_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2685,8 +2672,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndEnumsUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused int32_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3043,8 +3029,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndRawValuesUsingBlock:^(int32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndRawValuesUsingBlock:^(__unused int32_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3393,8 +3378,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:11]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject, stop)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused int32_t aKey, __unused NSString* aObject, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -3454,8 +3438,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(int32_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused int32_t aKey, __unused NSString* aObject, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3673,6 +3656,5 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int32, int32_t, 11, 12, 13, 14)
 
diff --git a/objectivec/Tests/GPBDictionaryTests+Int64.m b/objectivec/Tests/GPBDictionaryTests+Int64.m
index a603356..c052e1c 100644
--- a/objectivec/Tests/GPBDictionaryTests+Int64.m
+++ b/objectivec/Tests/GPBDictionaryTests+Int64.m
@@ -34,7 +34,10 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+
+// Disable clang-format for the macros.
+// clang-format off
 
 // Pull in the macros (using an external file because expanding all tests
 // in a single file makes a file that is failing to work with within Xcode.
@@ -42,7 +45,6 @@
 
 //%PDDM-EXPAND TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // To let the testing macros work, add some extra methods to simplify things.
 @interface GPBInt64EnumDictionary (TestingTweak)
@@ -87,8 +89,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt32:NULL forKey:21LL]);
-  [dict enumerateKeysAndUInt32sUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused int64_t aKey, __unused uint32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -158,8 +159,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt32sUsingBlock:^(int64_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused int64_t aKey, __unused uint32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -448,8 +448,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt32:NULL forKey:21LL]);
-  [dict enumerateKeysAndInt32sUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused int64_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -519,8 +518,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt32sUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused int64_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -809,8 +807,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt64:NULL forKey:21LL]);
-  [dict enumerateKeysAndUInt64sUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused int64_t aKey, __unused uint64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -880,8 +877,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt64sUsingBlock:^(int64_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused int64_t aKey, __unused uint64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1170,8 +1166,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt64:NULL forKey:21LL]);
-  [dict enumerateKeysAndInt64sUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused int64_t aKey, __unused int64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1241,8 +1236,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt64sUsingBlock:^(int64_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused int64_t aKey, __unused int64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1531,8 +1525,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getBool:NULL forKey:21LL]);
-  [dict enumerateKeysAndBoolsUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused int64_t aKey, __unused BOOL aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1602,8 +1595,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndBoolsUsingBlock:^(int64_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused int64_t aKey, __unused BOOL aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1892,8 +1884,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getFloat:NULL forKey:21LL]);
-  [dict enumerateKeysAndFloatsUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused int64_t aKey, __unused float aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1963,8 +1954,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndFloatsUsingBlock:^(int64_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused int64_t aKey, __unused float aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2253,8 +2243,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getDouble:NULL forKey:21LL]);
-  [dict enumerateKeysAndDoublesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused int64_t aKey, __unused double aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2324,8 +2313,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndDoublesUsingBlock:^(int64_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused int64_t aKey, __unused double aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2614,8 +2602,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getEnum:NULL forKey:21LL]);
-  [dict enumerateKeysAndEnumsUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused int64_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2685,8 +2672,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndEnumsUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused int64_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3043,8 +3029,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndRawValuesUsingBlock:^(int64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndRawValuesUsingBlock:^(__unused int64_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3393,8 +3378,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:21LL]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject, stop)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused int64_t aKey, __unused NSString* aObject, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -3454,8 +3438,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(int64_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused int64_t aKey, __unused NSString* aObject, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3673,6 +3656,5 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END TEST_FOR_POD_KEY(Int64, int64_t, 21LL, 22LL, 23LL, 24LL)
 
diff --git a/objectivec/Tests/GPBDictionaryTests+String.m b/objectivec/Tests/GPBDictionaryTests+String.m
index 8ad1cea..6c5d7b3 100644
--- a/objectivec/Tests/GPBDictionaryTests+String.m
+++ b/objectivec/Tests/GPBDictionaryTests+String.m
@@ -34,15 +34,17 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+
+// Disable clang-format for the macros.
+// clang-format off
 
 // Pull in the macros (using an external file because expanding all tests
 // in a single file makes a file that is failing to work with within Xcode.
 //%PDDM-IMPORT-DEFINES GPBDictionaryTests.pddm
 
-//%PDDM-EXPAND TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
+//%PDDM-EXPAND TESTS_FOR_POD_VALUES(String,NSString,*,Objects,@"foo",@"bar",@"baz",@"mumble")
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // To let the testing macros work, add some extra methods to simplify things.
 @interface GPBStringEnumDictionary (TestingTweak)
@@ -87,8 +89,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt32:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndUInt32sUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused NSString *aKey, __unused uint32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -158,8 +159,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt32sUsingBlock:^(NSString *aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused NSString *aKey, __unused uint32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -448,8 +448,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt32:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndInt32sUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused NSString *aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -519,8 +518,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt32sUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused NSString *aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -809,8 +807,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt64:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndUInt64sUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused NSString *aKey, __unused uint64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -880,8 +877,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt64sUsingBlock:^(NSString *aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused NSString *aKey, __unused uint64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1170,8 +1166,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt64:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndInt64sUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused NSString *aKey, __unused int64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1241,8 +1236,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt64sUsingBlock:^(NSString *aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused NSString *aKey, __unused int64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1531,8 +1525,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getBool:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndBoolsUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused NSString *aKey, __unused BOOL aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1602,8 +1595,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndBoolsUsingBlock:^(NSString *aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused NSString *aKey, __unused BOOL aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1892,8 +1884,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getFloat:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndFloatsUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused NSString *aKey, __unused float aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1963,8 +1954,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndFloatsUsingBlock:^(NSString *aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused NSString *aKey, __unused float aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2253,8 +2243,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getDouble:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndDoublesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused NSString *aKey, __unused double aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2324,8 +2313,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndDoublesUsingBlock:^(NSString *aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused NSString *aKey, __unused double aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2614,8 +2602,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getEnum:NULL forKey:@"foo"]);
-  [dict enumerateKeysAndEnumsUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused NSString *aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2685,8 +2672,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndEnumsUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused NSString *aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3043,8 +3029,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndRawValuesUsingBlock:^(NSString *aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndRawValuesUsingBlock:^(__unused NSString *aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3381,6 +3366,4 @@
 
 @end
 
-// clang-format on
-//%PDDM-EXPAND-END TESTS_FOR_POD_VALUES(String, NSString, *, Objects, @"foo", @"bar", @"baz", @"mumble")
-
+//%PDDM-EXPAND-END TESTS_FOR_POD_VALUES(String,NSString,*,Objects,@"foo",@"bar",@"baz",@"mumble")
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt32.m b/objectivec/Tests/GPBDictionaryTests+UInt32.m
index f607538..854d49b 100644
--- a/objectivec/Tests/GPBDictionaryTests+UInt32.m
+++ b/objectivec/Tests/GPBDictionaryTests+UInt32.m
@@ -34,7 +34,10 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+
+// Disable clang-format for the macros.
+// clang-format off
 
 // Pull in the macros (using an external file because expanding all tests
 // in a single file makes a file that is failing to work with within Xcode.
@@ -42,7 +45,6 @@
 
 //%PDDM-EXPAND TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // To let the testing macros work, add some extra methods to simplify things.
 @interface GPBUInt32EnumDictionary (TestingTweak)
@@ -87,8 +89,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt32:NULL forKey:1U]);
-  [dict enumerateKeysAndUInt32sUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused uint32_t aKey, __unused uint32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -158,8 +159,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt32sUsingBlock:^(uint32_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused uint32_t aKey, __unused uint32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -448,8 +448,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt32:NULL forKey:1U]);
-  [dict enumerateKeysAndInt32sUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused uint32_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -519,8 +518,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt32sUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused uint32_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -809,8 +807,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt64:NULL forKey:1U]);
-  [dict enumerateKeysAndUInt64sUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused uint32_t aKey, __unused uint64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -880,8 +877,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt64sUsingBlock:^(uint32_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused uint32_t aKey, __unused uint64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1170,8 +1166,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt64:NULL forKey:1U]);
-  [dict enumerateKeysAndInt64sUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused uint32_t aKey, __unused int64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1241,8 +1236,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt64sUsingBlock:^(uint32_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused uint32_t aKey, __unused int64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1531,8 +1525,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getBool:NULL forKey:1U]);
-  [dict enumerateKeysAndBoolsUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused uint32_t aKey, __unused BOOL aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1602,8 +1595,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndBoolsUsingBlock:^(uint32_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused uint32_t aKey, __unused BOOL aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1892,8 +1884,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getFloat:NULL forKey:1U]);
-  [dict enumerateKeysAndFloatsUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused uint32_t aKey, __unused float aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1963,8 +1954,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndFloatsUsingBlock:^(uint32_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused uint32_t aKey, __unused float aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2253,8 +2243,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getDouble:NULL forKey:1U]);
-  [dict enumerateKeysAndDoublesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused uint32_t aKey, __unused double aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2324,8 +2313,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndDoublesUsingBlock:^(uint32_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused uint32_t aKey, __unused double aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2614,8 +2602,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getEnum:NULL forKey:1U]);
-  [dict enumerateKeysAndEnumsUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused uint32_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2685,8 +2672,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndEnumsUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused uint32_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3043,8 +3029,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndRawValuesUsingBlock:^(uint32_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndRawValuesUsingBlock:^(__unused uint32_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3393,8 +3378,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:1U]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject, stop)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused uint32_t aKey, __unused NSString* aObject, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -3454,8 +3438,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint32_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused uint32_t aKey, __unused NSString* aObject, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3673,6 +3656,5 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt32, uint32_t, 1U, 2U, 3U, 4U)
 
diff --git a/objectivec/Tests/GPBDictionaryTests+UInt64.m b/objectivec/Tests/GPBDictionaryTests+UInt64.m
index b5dd91e..fe7d4fc 100644
--- a/objectivec/Tests/GPBDictionaryTests+UInt64.m
+++ b/objectivec/Tests/GPBDictionaryTests+UInt64.m
@@ -34,7 +34,10 @@
 #import "GPBDictionary.h"
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+
+// Disable clang-format for the macros.
+// clang-format off
 
 // Pull in the macros (using an external file because expanding all tests
 // in a single file makes a file that is failing to work with within Xcode.
@@ -42,7 +45,6 @@
 
 //%PDDM-EXPAND TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 // To let the testing macros work, add some extra methods to simplify things.
 @interface GPBUInt64EnumDictionary (TestingTweak)
@@ -87,8 +89,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt32:NULL forKey:31ULL]);
-  [dict enumerateKeysAndUInt32sUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused uint64_t aKey, __unused uint32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -158,8 +159,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt32sUsingBlock:^(uint64_t aKey, uint32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt32sUsingBlock:^(__unused uint64_t aKey, __unused uint32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -448,8 +448,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt32:NULL forKey:31ULL]);
-  [dict enumerateKeysAndInt32sUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused uint64_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -519,8 +518,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt32sUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt32sUsingBlock:^(__unused uint64_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -809,8 +807,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getUInt64:NULL forKey:31ULL]);
-  [dict enumerateKeysAndUInt64sUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused uint64_t aKey, __unused uint64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -880,8 +877,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndUInt64sUsingBlock:^(uint64_t aKey, uint64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndUInt64sUsingBlock:^(__unused uint64_t aKey, __unused uint64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1170,8 +1166,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getInt64:NULL forKey:31ULL]);
-  [dict enumerateKeysAndInt64sUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused uint64_t aKey, __unused int64_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1241,8 +1236,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndInt64sUsingBlock:^(uint64_t aKey, int64_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndInt64sUsingBlock:^(__unused uint64_t aKey, __unused int64_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1531,8 +1525,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getBool:NULL forKey:31ULL]);
-  [dict enumerateKeysAndBoolsUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused uint64_t aKey, __unused BOOL aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1602,8 +1595,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndBoolsUsingBlock:^(uint64_t aKey, BOOL aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndBoolsUsingBlock:^(__unused uint64_t aKey, __unused BOOL aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -1892,8 +1884,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getFloat:NULL forKey:31ULL]);
-  [dict enumerateKeysAndFloatsUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused uint64_t aKey, __unused float aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -1963,8 +1954,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndFloatsUsingBlock:^(uint64_t aKey, float aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndFloatsUsingBlock:^(__unused uint64_t aKey, __unused float aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2253,8 +2243,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getDouble:NULL forKey:31ULL]);
-  [dict enumerateKeysAndDoublesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused uint64_t aKey, __unused double aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2324,8 +2313,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndDoublesUsingBlock:^(uint64_t aKey, double aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndDoublesUsingBlock:^(__unused uint64_t aKey, __unused double aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -2614,8 +2602,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertFalse([dict getEnum:NULL forKey:31ULL]);
-  [dict enumerateKeysAndEnumsUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue, stop)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused uint64_t aKey, __unused int32_t aValue, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -2685,8 +2672,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndEnumsUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndEnumsUsingBlock:^(__unused uint64_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3043,8 +3029,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndRawValuesUsingBlock:^(uint64_t aKey, int32_t aValue, BOOL *stop) {
-    #pragma unused(aKey, aValue)
+  [dict enumerateKeysAndRawValuesUsingBlock:^(__unused uint64_t aKey, __unused int32_t aValue, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3393,8 +3378,7 @@
   XCTAssertNotNil(dict);
   XCTAssertEqual(dict.count, 0U);
   XCTAssertNil([dict objectForKey:31ULL]);
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject, stop)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused uint64_t aKey, __unused NSString* aObject, __unused BOOL *stop) {
     XCTFail(@"Shouldn't get here!");
   }];
   [dict release];
@@ -3454,8 +3438,7 @@
 
   // Stopping the enumeration.
   idx = 0;
-  [dict enumerateKeysAndObjectsUsingBlock:^(uint64_t aKey, NSString* aObject, BOOL *stop) {
-    #pragma unused(aKey, aObject)
+  [dict enumerateKeysAndObjectsUsingBlock:^(__unused uint64_t aKey, __unused NSString* aObject, BOOL *stop) {
     if (idx == 1) *stop = YES;
     XCTAssertNotEqual(idx, 2U);
     ++idx;
@@ -3673,5 +3656,4 @@
 
 @end
 
-// clang-format on
 //%PDDM-EXPAND-END TEST_FOR_POD_KEY(UInt64, uint64_t, 31ULL, 32ULL, 33ULL, 34ULL)
diff --git a/objectivec/Tests/GPBDictionaryTests.m b/objectivec/Tests/GPBDictionaryTests.m
index 52b4b32..e5670d8 100644
--- a/objectivec/Tests/GPBDictionaryTests.m
+++ b/objectivec/Tests/GPBDictionaryTests.m
@@ -56,17 +56,17 @@
   XCTAssertTrue([dict isEqual:@{}]);
   XCTAssertTrue([dict isEqualToDictionary:@{}]);
 
-  XCTAssertFalse([dict isEqual:@{ @"foo" : @"bar" }]);
-  XCTAssertFalse([dict isEqualToDictionary:@{ @"foo" : @"bar" }]);
+  XCTAssertFalse([dict isEqual:@{@"foo" : @"bar"}]);
+  XCTAssertFalse([dict isEqualToDictionary:@{@"foo" : @"bar"}]);
 
   [dict setObject:@"bar" forKey:@"foo"];
 
   XCTAssertFalse([dict isEqual:@{}]);
   XCTAssertFalse([dict isEqualToDictionary:@{}]);
-  XCTAssertTrue([dict isEqual:@{ @"foo" : @"bar" }]);
-  XCTAssertTrue([dict isEqualToDictionary:@{ @"foo" : @"bar" }]);
-  XCTAssertFalse([dict isEqual:@{ @"bar" : @"baz" }]);
-  XCTAssertFalse([dict isEqualToDictionary:@{ @"bar" : @"baz" }]);
+  XCTAssertTrue([dict isEqual:@{@"foo" : @"bar"}]);
+  XCTAssertTrue([dict isEqualToDictionary:@{@"foo" : @"bar"}]);
+  XCTAssertFalse([dict isEqual:@{@"bar" : @"baz"}]);
+  XCTAssertFalse([dict isEqualToDictionary:@{@"bar" : @"baz"}]);
 
   GPBAutocreatedDictionary *dict2 = [[GPBAutocreatedDictionary alloc] init];
 
@@ -90,14 +90,14 @@
     GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init];
 
     NSDictionary *cpy = [dict copy];
-    XCTAssertTrue(cpy != dict); // Ptr compare
+    XCTAssertTrue(cpy != dict);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSDictionary class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)0);
 
     NSDictionary *cpy2 = [dict copy];
-    XCTAssertTrue(cpy2 != dict); // Ptr compare
-    XCTAssertTrue(cpy2 != cpy); // Ptr compare
+    XCTAssertTrue(cpy2 != dict);  // Ptr compare
+    XCTAssertTrue(cpy2 != cpy);   // Ptr compare
     XCTAssertTrue([cpy2 isKindOfClass:[NSDictionary class]]);
     XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy2.count, (NSUInteger)0);
@@ -111,14 +111,14 @@
     GPBAutocreatedDictionary *dict = [[GPBAutocreatedDictionary alloc] init];
 
     NSMutableDictionary *cpy = [dict mutableCopy];
-    XCTAssertTrue(cpy != dict); // Ptr compare
+    XCTAssertTrue(cpy != dict);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSMutableDictionary class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)0);
 
     NSMutableDictionary *cpy2 = [dict mutableCopy];
-    XCTAssertTrue(cpy2 != dict); // Ptr compare
-    XCTAssertTrue(cpy2 != cpy); // Ptr compare
+    XCTAssertTrue(cpy2 != dict);  // Ptr compare
+    XCTAssertTrue(cpy2 != cpy);   // Ptr compare
     XCTAssertTrue([cpy2 isKindOfClass:[NSMutableDictionary class]]);
     XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy2.count, (NSUInteger)0);
@@ -134,7 +134,7 @@
     dict[@"baz"] = @"mumble";
 
     NSDictionary *cpy = [dict copy];
-    XCTAssertTrue(cpy != dict); // Ptr compare
+    XCTAssertTrue(cpy != dict);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSDictionary class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)2);
@@ -142,8 +142,8 @@
     XCTAssertEqualObjects(cpy[@"baz"], @"mumble");
 
     NSDictionary *cpy2 = [dict copy];
-    XCTAssertTrue(cpy2 != dict); // Ptr compare
-    XCTAssertTrue(cpy2 != cpy); // Ptr compare
+    XCTAssertTrue(cpy2 != dict);  // Ptr compare
+    XCTAssertTrue(cpy2 != cpy);   // Ptr compare
     XCTAssertTrue([cpy2 isKindOfClass:[NSDictionary class]]);
     XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy2.count, (NSUInteger)2);
@@ -161,7 +161,7 @@
     dict[@"baz"] = @"mumble";
 
     NSMutableDictionary *cpy = [dict mutableCopy];
-    XCTAssertTrue(cpy != dict); // Ptr compare
+    XCTAssertTrue(cpy != dict);  // Ptr compare
     XCTAssertTrue([cpy isKindOfClass:[NSMutableDictionary class]]);
     XCTAssertFalse([cpy isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy.count, (NSUInteger)2);
@@ -169,8 +169,8 @@
     XCTAssertEqualObjects(cpy[@"baz"], @"mumble");
 
     NSMutableDictionary *cpy2 = [dict mutableCopy];
-    XCTAssertTrue(cpy2 != dict); // Ptr compare
-    XCTAssertTrue(cpy2 != cpy); // Ptr compare
+    XCTAssertTrue(cpy2 != dict);  // Ptr compare
+    XCTAssertTrue(cpy2 != cpy);   // Ptr compare
     XCTAssertTrue([cpy2 isKindOfClass:[NSMutableDictionary class]]);
     XCTAssertFalse([cpy2 isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(cpy2.count, (NSUInteger)2);
diff --git a/objectivec/Tests/GPBDictionaryTests.pddm b/objectivec/Tests/GPBDictionaryTests.pddm
index 17f12c2..11c08ec 100644
--- a/objectivec/Tests/GPBDictionaryTests.pddm
+++ b/objectivec/Tests/GPBDictionaryTests.pddm
@@ -70,8 +70,7 @@
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertEqual(dict.count, 0U);
 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
-//%  [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
-//%    #pragma unused(aKey, a##VNAME$u, stop)
+//%  [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u, __unused BOOL *stop) {
 //%    XCTFail(@"Shouldn't get here!");
 //%  }];
 //%  [dict release];
@@ -131,8 +130,7 @@
 //%
 //%  // Stopping the enumeration.
 //%  idx = 0;
-//%  [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u, BOOL *stop) {
-//%    #pragma unused(aKey, a##VNAME$u)
+//%  [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u, BOOL *stop) {
 //%    if (idx == 1) *stop = YES;
 //%    XCTAssertNotEqual(idx, 2U);
 //%    ++idx;
@@ -425,8 +423,7 @@
 //%
 //%  // Stopping the enumeration.
 //%  idx = 0;
-//%  [dict enumerateKeysAndRawValuesUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE aValue, BOOL *stop) {
-//%    #pragma unused(aKey, aValue)
+//%  [dict enumerateKeysAndRawValuesUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE aValue, BOOL *stop) {
 //%    if (idx == 1) *stop = YES;
 //%    XCTAssertNotEqual(idx, 2U);
 //%    ++idx;
@@ -790,8 +787,7 @@
 //%  XCTAssertNotNil(dict);
 //%  XCTAssertEqual(dict.count, 0U);
 //%VALUE_NOT_FOUND##VHELPER(VALUE_NAME, dict, KEY1)
-//%  [dict enumerateKeysAnd##VALUE_NAME##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
-//%    #pragma unused(aKey, a##VNAME$u##, stop)
+//%  [dict enumerateKeysAnd##VALUE_NAME##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u##, __unused BOOL *stop) {
 //%    XCTFail(@"Shouldn't get here!");
 //%  }];
 //%  [dict release];
@@ -849,8 +845,7 @@
 //%
 //%  // Stopping the enumeration.
 //%  idx = 0;
-//%  [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(KEY_TYPE KisP##aKey, VALUE_TYPE a##VNAME$u##, BOOL *stop) {
-//%    #pragma unused(aKey, a##VNAME$u)
+//%  [dict enumerateKeysAnd##VALUE_NAME$u##sUsingBlock:^(__unused KEY_TYPE KisP##aKey, __unused VALUE_TYPE a##VNAME$u##, BOOL *stop) {
 //%    if (idx == 0) *stop = YES;
 //%    XCTAssertNotEqual(idx, 2U);
 //%    ++idx;
diff --git a/objectivec/Tests/GPBExtensionRegistryTest.m b/objectivec/Tests/GPBExtensionRegistryTest.m
index b116882..bdd237b 100644
--- a/objectivec/Tests/GPBExtensionRegistryTest.m
+++ b/objectivec/Tests/GPBExtensionRegistryTest.m
@@ -31,7 +31,7 @@
 #import "GPBTestUtilities.h"
 
 #import "GPBExtensionRegistry.h"
-#import "google/protobuf/Unittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
 
 @interface GPBExtensionRegistryTest : GPBTestCase
 @end
@@ -42,20 +42,17 @@
   GPBExtensionRegistry *reg = [[[GPBExtensionRegistry alloc] init] autorelease];
   XCTAssertNotNil(reg);
 
-  XCTAssertNil([reg extensionForDescriptor:[TestAllExtensions descriptor]
-                               fieldNumber:1]);
-  XCTAssertNil([reg extensionForDescriptor:[TestAllTypes descriptor]
-                               fieldNumber:1]);
+  XCTAssertNil([reg extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:1]);
+  XCTAssertNil([reg extensionForDescriptor:[TestAllTypes descriptor] fieldNumber:1]);
 
   [reg addExtension:[UnittestRoot optionalInt32Extension]];
   [reg addExtension:[UnittestRoot packedInt64Extension]];
 
   XCTAssertTrue([reg extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:1] ==
-                [UnittestRoot optionalInt32Extension]); // ptr equality
-  XCTAssertNil([reg extensionForDescriptor:[TestAllTypes descriptor]
-                               fieldNumber:1]);
+                [UnittestRoot optionalInt32Extension]);  // ptr equality
+  XCTAssertNil([reg extensionForDescriptor:[TestAllTypes descriptor] fieldNumber:1]);
   XCTAssertTrue([reg extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:91] ==
-                [UnittestRoot packedInt64Extension]); // ptr equality
+                [UnittestRoot packedInt64Extension]);  // ptr equality
 }
 
 - (void)testCopy {
@@ -66,9 +63,9 @@
   XCTAssertNotNil(reg2);
 
   XCTAssertTrue([reg1 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:1] ==
-                [UnittestRoot optionalInt32Extension]); // ptr equality
+                [UnittestRoot optionalInt32Extension]);  // ptr equality
   XCTAssertTrue([reg2 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:1] ==
-                [UnittestRoot optionalInt32Extension]); // ptr equality
+                [UnittestRoot optionalInt32Extension]);  // ptr equality
 
   // Message class that had registered extension(s) at the -copy time.
 
@@ -76,11 +73,11 @@
   [reg2 addExtension:[UnittestRoot optionalStringExtension]];
 
   XCTAssertTrue([reg1 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:13] ==
-                [UnittestRoot optionalBoolExtension]); // ptr equality
+                [UnittestRoot optionalBoolExtension]);  // ptr equality
   XCTAssertNil([reg1 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:14]);
   XCTAssertNil([reg2 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:13]);
   XCTAssertTrue([reg2 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:14] ==
-                [UnittestRoot optionalStringExtension]); // ptr equality
+                [UnittestRoot optionalStringExtension]);  // ptr equality
 
   // Message class that did not have any registered extensions at the -copy time.
 
@@ -88,12 +85,11 @@
   [reg2 addExtension:[UnittestRoot packedSint32Extension]];
 
   XCTAssertTrue([reg1 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:91] ==
-                [UnittestRoot packedInt64Extension]); // ptr equality
+                [UnittestRoot packedInt64Extension]);  // ptr equality
   XCTAssertNil([reg1 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:94]);
   XCTAssertNil([reg2 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:91]);
   XCTAssertTrue([reg2 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:94] ==
-                [UnittestRoot packedSint32Extension]); // ptr equality
-
+                [UnittestRoot packedSint32Extension]);  // ptr equality
 }
 
 - (void)testAddExtensions {
@@ -102,13 +98,12 @@
 
   GPBExtensionRegistry *reg2 = [[[GPBExtensionRegistry alloc] init] autorelease];
 
-  XCTAssertNil([reg2 extensionForDescriptor:[TestAllExtensions descriptor]
-                                fieldNumber:1]);
+  XCTAssertNil([reg2 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:1]);
 
   [reg2 addExtensions:reg1];
 
   XCTAssertTrue([reg2 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:1] ==
-                [UnittestRoot optionalInt32Extension]); // ptr equality
+                [UnittestRoot optionalInt32Extension]);  // ptr equality
 
   // Confirm adding to the first doesn't add to the second.
 
@@ -116,9 +111,9 @@
   [reg1 addExtension:[UnittestRoot packedInt64Extension]];
 
   XCTAssertTrue([reg1 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:13] ==
-                [UnittestRoot optionalBoolExtension]); // ptr equality
+                [UnittestRoot optionalBoolExtension]);  // ptr equality
   XCTAssertTrue([reg1 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:91] ==
-                [UnittestRoot packedInt64Extension]); // ptr equality
+                [UnittestRoot packedInt64Extension]);  // ptr equality
   XCTAssertNil([reg2 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:13]);
   XCTAssertNil([reg2 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:91]);
 
@@ -130,9 +125,9 @@
   XCTAssertNil([reg1 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:14]);
   XCTAssertNil([reg1 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:94]);
   XCTAssertTrue([reg2 extensionForDescriptor:[TestAllExtensions descriptor] fieldNumber:14] ==
-                [UnittestRoot optionalStringExtension]); // ptr equality
+                [UnittestRoot optionalStringExtension]);  // ptr equality
   XCTAssertTrue([reg2 extensionForDescriptor:[TestPackedExtensions descriptor] fieldNumber:94] ==
-                [UnittestRoot packedSint32Extension]); // ptr equality
+                [UnittestRoot packedSint32Extension]);  // ptr equality
 }
 
 @end
diff --git a/objectivec/Tests/GPBMessageTests+ClassNames.m b/objectivec/Tests/GPBMessageTests+ClassNames.m
index b5a5c51..1b656d0 100644
--- a/objectivec/Tests/GPBMessageTests+ClassNames.m
+++ b/objectivec/Tests/GPBMessageTests+ClassNames.m
@@ -62,15 +62,15 @@
   static GPBDescriptor *descriptor = nil;
   if (!descriptor) {
     static GPBMessageFieldDescription fields[] = {
-      {
-        .name = "foo",
-        .dataTypeSpecific.className = "NSString",
-        .number = 1,
-        .hasIndex = 0,
-        .offset = (uint32_t)offsetof(MessageLackingClazz_storage_, foo),
-        .flags = (GPBFieldFlags)(GPBFieldOptional),
-        .dataType = GPBDataTypeMessage,
-      },
+        {
+            .name = "foo",
+            .dataTypeSpecific.className = "NSString",
+            .number = 1,
+            .hasIndex = 0,
+            .offset = (uint32_t)offsetof(MessageLackingClazz_storage_, foo),
+            .flags = (GPBFieldFlags)(GPBFieldOptional),
+            .dataType = GPBDataTypeMessage,
+        },
     };
     GPBFileDescriptor *desc =
         [[[GPBFileDescriptor alloc] initWithPackage:@"test"
@@ -78,14 +78,14 @@
                                              syntax:GPBFileSyntaxProto3] autorelease];
 
     // GPBDescriptorInitializationFlag_UsesClassRefs intentionally not set here
-    descriptor =
-        [GPBDescriptor allocDescriptorForClass:[MessageLackingClazz class]
-                                     rootClass:[MessageLackingClazzRoot class]
-                                          file:desc
-                                        fields:fields
-                                    fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
-                                   storageSize:sizeof(MessageLackingClazz_storage_)
-                                         flags:GPBDescriptorInitializationFlag_None];
+    descriptor = [GPBDescriptor
+        allocDescriptorForClass:[MessageLackingClazz class]
+                      rootClass:[MessageLackingClazzRoot class]
+                           file:desc
+                         fields:fields
+                     fieldCount:(uint32_t)(sizeof(fields) / sizeof(GPBMessageFieldDescription))
+                    storageSize:sizeof(MessageLackingClazz_storage_)
+                          flags:GPBDescriptorInitializationFlag_None];
     [descriptor setupContainingMessageClassName:"MessageLackingClazz"];
   }
   return descriptor;
@@ -94,24 +94,24 @@
 
 @implementation MessageLackingClazzRoot
 
-+ (GPBExtensionRegistry*)extensionRegistry {
++ (GPBExtensionRegistry *)extensionRegistry {
   // This is called by +initialize so there is no need to worry
   // about thread safety and initialization of registry.
-  static GPBExtensionRegistry* registry = nil;
+  static GPBExtensionRegistry *registry = nil;
   if (!registry) {
     registry = [[GPBExtensionRegistry alloc] init];
     static GPBExtensionDescription descriptions[] = {
-      {
-        .defaultValue.valueMessage = NULL,
-        .singletonName = "MessageLackingClazzRoot_ext1",
-        .extendedClass.name = "MessageLackingClazz",
-        .messageOrGroupClass.name = "MessageLackingClazz",
-        .enumDescriptorFunc = NULL,
-        .fieldNumber = 1,
-        .dataType = GPBDataTypeMessage,
-        // GPBExtensionUsesClazz Intentionally not set
-        .options = 0,
-      },
+        {
+            .defaultValue.valueMessage = NULL,
+            .singletonName = "MessageLackingClazzRoot_ext1",
+            .extendedClass.name = "MessageLackingClazz",
+            .messageOrGroupClass.name = "MessageLackingClazz",
+            .enumDescriptorFunc = NULL,
+            .fieldNumber = 1,
+            .dataType = GPBDataTypeMessage,
+            // GPBExtensionUsesClazz Intentionally not set
+            .options = 0,
+        },
     };
     for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {
       // Intentionall using `-initWithExtensionDescription:` and not `
diff --git a/objectivec/Tests/GPBMessageTests+Merge.m b/objectivec/Tests/GPBMessageTests+Merge.m
index f895542..a853419 100644
--- a/objectivec/Tests/GPBMessageTests+Merge.m
+++ b/objectivec/Tests/GPBMessageTests+Merge.m
@@ -34,11 +34,11 @@
 
 #import "GPBMessage.h"
 
-#import "google/protobuf/MapUnittest.pbobjc.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+#import "objectivec/Tests/MapUnittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto3.pbobjc.h"
 
 @interface MessageMergeTests : GPBTestCase
 @end
@@ -197,9 +197,8 @@
   // Known value.
 
   src.e = UnknownEnumsMyEnum_Bar;
-  src.repeatedEArray =
-      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
-                                       rawValue:UnknownEnumsMyEnum_Bar];
+  src.repeatedEArray = [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+                                                        rawValue:UnknownEnumsMyEnum_Bar];
   src.repeatedPackedEArray =
       [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
                                        rawValue:UnknownEnumsMyEnum_Bar];
@@ -211,8 +210,7 @@
   XCTAssertEqual(dst.repeatedEArray.count, 1U);
   XCTAssertEqual([dst.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
   XCTAssertEqual(dst.repeatedPackedEArray.count, 1U);
-  XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
-                 UnknownEnumsMyEnum_Bar);
+  XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
   XCTAssertEqual(dst.oneofE1, UnknownEnumsMyEnum_Bar);
 
   // Unknown value.
@@ -220,9 +218,8 @@
   const int32_t kUnknownValue = 666;
 
   SetUnknownEnumsMyMessage_E_RawValue(src, kUnknownValue);
-  src.repeatedEArray =
-      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
-                                       rawValue:kUnknownValue];
+  src.repeatedEArray = [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
+                                                        rawValue:kUnknownValue];
   src.repeatedPackedEArray =
       [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnum_IsValidValue
                                        rawValue:kUnknownValue];
@@ -238,13 +235,11 @@
                  UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
   XCTAssertEqual([dst.repeatedEArray rawValueAtIndex:1], kUnknownValue);
   XCTAssertEqual(dst.repeatedPackedEArray.count, 2U);
-  XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0],
-                 UnknownEnumsMyEnum_Bar);
+  XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:0], UnknownEnumsMyEnum_Bar);
   XCTAssertEqual([dst.repeatedPackedEArray valueAtIndex:1],
                  UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
   XCTAssertEqual([dst.repeatedPackedEArray rawValueAtIndex:1], kUnknownValue);
-  XCTAssertEqual(dst.oneofE1,
-                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(dst.oneofE1, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
   XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(dst), kUnknownValue);
 }
 
@@ -258,6 +253,9 @@
 
   dst.oneofEnum = Message2_Enum_Bar;
 
+  // Disable clang-format for the macros.
+  // clang-format off
+
 //%PDDM-DEFINE MERGE2_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
 //%  src.oneof##SET_NAME = SET_VALUE;
 //%  [dst mergeFrom:src];
@@ -267,7 +265,6 @@
 //%
 //%PDDM-EXPAND MERGE2_TEST(Int32, 10, Enum, Message2_Enum_Baz)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofInt32 = 10;
   [dst mergeFrom:src];
@@ -275,10 +272,8 @@
   XCTAssertEqual(dst.oneofInt32, 10);
   XCTAssertEqual(dst.oneofEnum, Message2_Enum_Baz);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Int64, 11, Int32, 100)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofInt64 = 11;
   [dst mergeFrom:src];
@@ -286,10 +281,8 @@
   XCTAssertEqual(dst.oneofInt64, 11);
   XCTAssertEqual(dst.oneofInt32, 100);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Uint32, 12U, Int64, 101)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofUint32 = 12U;
   [dst mergeFrom:src];
@@ -297,10 +290,8 @@
   XCTAssertEqual(dst.oneofUint32, 12U);
   XCTAssertEqual(dst.oneofInt64, 101);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Uint64, 13U, Uint32, 102U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofUint64 = 13U;
   [dst mergeFrom:src];
@@ -308,10 +299,8 @@
   XCTAssertEqual(dst.oneofUint64, 13U);
   XCTAssertEqual(dst.oneofUint32, 102U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Sint32, 14, Uint64, 103U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSint32 = 14;
   [dst mergeFrom:src];
@@ -319,10 +308,8 @@
   XCTAssertEqual(dst.oneofSint32, 14);
   XCTAssertEqual(dst.oneofUint64, 103U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Sint64, 15, Sint32, 104)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSint64 = 15;
   [dst mergeFrom:src];
@@ -330,10 +317,8 @@
   XCTAssertEqual(dst.oneofSint64, 15);
   XCTAssertEqual(dst.oneofSint32, 104);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Fixed32, 16U, Sint64, 105)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofFixed32 = 16U;
   [dst mergeFrom:src];
@@ -341,10 +326,8 @@
   XCTAssertEqual(dst.oneofFixed32, 16U);
   XCTAssertEqual(dst.oneofSint64, 105);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Fixed64, 17U, Fixed32, 106U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofFixed64 = 17U;
   [dst mergeFrom:src];
@@ -352,10 +335,8 @@
   XCTAssertEqual(dst.oneofFixed64, 17U);
   XCTAssertEqual(dst.oneofFixed32, 106U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Sfixed32, 18, Fixed64, 107U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSfixed32 = 18;
   [dst mergeFrom:src];
@@ -363,10 +344,8 @@
   XCTAssertEqual(dst.oneofSfixed32, 18);
   XCTAssertEqual(dst.oneofFixed64, 107U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Sfixed64, 19, Sfixed32, 108)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSfixed64 = 19;
   [dst mergeFrom:src];
@@ -374,10 +353,8 @@
   XCTAssertEqual(dst.oneofSfixed64, 19);
   XCTAssertEqual(dst.oneofSfixed32, 108);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Float, 20.0f, Sfixed64, 109)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofFloat = 20.0f;
   [dst mergeFrom:src];
@@ -385,10 +362,8 @@
   XCTAssertEqual(dst.oneofFloat, 20.0f);
   XCTAssertEqual(dst.oneofSfixed64, 109);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Double, 21.0, Float, 110.0f)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofDouble = 21.0;
   [dst mergeFrom:src];
@@ -396,10 +371,8 @@
   XCTAssertEqual(dst.oneofDouble, 21.0);
   XCTAssertEqual(dst.oneofFloat, 110.0f);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Bool, NO, Double, 111.0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofBool = NO;
   [dst mergeFrom:src];
@@ -407,10 +380,8 @@
   XCTAssertEqual(dst.oneofBool, NO);
   XCTAssertEqual(dst.oneofDouble, 111.0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE2_TEST(Enum, Message2_Enum_Bar, Bool, YES)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofEnum = Message2_Enum_Bar;
   [dst mergeFrom:src];
@@ -418,9 +389,10 @@
   XCTAssertEqual(dst.oneofEnum, Message2_Enum_Bar);
   XCTAssertEqual(dst.oneofBool, YES);
 
-// clang-format on
 //%PDDM-EXPAND-END (14 expansions)
 
+  // clang-format on
+
   NSString *oneofStringDefault = @"string";
   NSData *oneofBytesDefault = [@"data" dataUsingEncoding:NSUTF8StringEncoding];
 
@@ -433,8 +405,7 @@
   src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
   [dst mergeFrom:src];
   XCTAssertEqual(dst.oOneOfCase, Message2_O_OneOfCase_OneofBytes);
-  XCTAssertEqualObjects(dst.oneofBytes,
-                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertEqualObjects(dst.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
   XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
 
   Message2_OneofGroup *group = [Message2_OneofGroup message];
@@ -506,6 +477,9 @@
 
   dst.oneofEnum = Message3_Enum_Bar;
 
+  // Disable clang-format for the macros.
+  // clang-format off
+
 //%PDDM-DEFINE MERGE3_TEST(SET_NAME, SET_VALUE, CLEARED_NAME, CLEARED_DEFAULT)
 //%  src.oneof##SET_NAME = SET_VALUE;
 //%  [dst mergeFrom:src];
@@ -515,7 +489,6 @@
 //%
 //%PDDM-EXPAND MERGE3_TEST(Int32, 10, Enum, Message3_Enum_Foo)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofInt32 = 10;
   [dst mergeFrom:src];
@@ -523,10 +496,8 @@
   XCTAssertEqual(dst.oneofInt32, 10);
   XCTAssertEqual(dst.oneofEnum, Message3_Enum_Foo);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Int64, 11, Int32, 0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofInt64 = 11;
   [dst mergeFrom:src];
@@ -534,10 +505,8 @@
   XCTAssertEqual(dst.oneofInt64, 11);
   XCTAssertEqual(dst.oneofInt32, 0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Uint32, 12U, Int64, 0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofUint32 = 12U;
   [dst mergeFrom:src];
@@ -545,10 +514,8 @@
   XCTAssertEqual(dst.oneofUint32, 12U);
   XCTAssertEqual(dst.oneofInt64, 0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Uint64, 13U, Uint32, 0U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofUint64 = 13U;
   [dst mergeFrom:src];
@@ -556,10 +523,8 @@
   XCTAssertEqual(dst.oneofUint64, 13U);
   XCTAssertEqual(dst.oneofUint32, 0U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Sint32, 14, Uint64, 0U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSint32 = 14;
   [dst mergeFrom:src];
@@ -567,10 +532,8 @@
   XCTAssertEqual(dst.oneofSint32, 14);
   XCTAssertEqual(dst.oneofUint64, 0U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Sint64, 15, Sint32, 0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSint64 = 15;
   [dst mergeFrom:src];
@@ -578,10 +541,8 @@
   XCTAssertEqual(dst.oneofSint64, 15);
   XCTAssertEqual(dst.oneofSint32, 0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Fixed32, 16U, Sint64, 0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofFixed32 = 16U;
   [dst mergeFrom:src];
@@ -589,10 +550,8 @@
   XCTAssertEqual(dst.oneofFixed32, 16U);
   XCTAssertEqual(dst.oneofSint64, 0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Fixed64, 17U, Fixed32, 0U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofFixed64 = 17U;
   [dst mergeFrom:src];
@@ -600,10 +559,8 @@
   XCTAssertEqual(dst.oneofFixed64, 17U);
   XCTAssertEqual(dst.oneofFixed32, 0U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Sfixed32, 18, Fixed64, 0U)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSfixed32 = 18;
   [dst mergeFrom:src];
@@ -611,10 +568,8 @@
   XCTAssertEqual(dst.oneofSfixed32, 18);
   XCTAssertEqual(dst.oneofFixed64, 0U);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Sfixed64, 19, Sfixed32, 0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofSfixed64 = 19;
   [dst mergeFrom:src];
@@ -622,10 +577,8 @@
   XCTAssertEqual(dst.oneofSfixed64, 19);
   XCTAssertEqual(dst.oneofSfixed32, 0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Float, 20.0f, Sfixed64, 0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofFloat = 20.0f;
   [dst mergeFrom:src];
@@ -633,10 +586,8 @@
   XCTAssertEqual(dst.oneofFloat, 20.0f);
   XCTAssertEqual(dst.oneofSfixed64, 0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Double, 21.0, Float, 0.0f)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofDouble = 21.0;
   [dst mergeFrom:src];
@@ -644,10 +595,8 @@
   XCTAssertEqual(dst.oneofDouble, 21.0);
   XCTAssertEqual(dst.oneofFloat, 0.0f);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Bool, YES, Double, 0.0)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofBool = YES;
   [dst mergeFrom:src];
@@ -655,10 +604,8 @@
   XCTAssertEqual(dst.oneofBool, YES);
   XCTAssertEqual(dst.oneofDouble, 0.0);
 
-// clang-format on
 //%PDDM-EXPAND MERGE3_TEST(Enum, Message3_Enum_Bar, Bool, NO)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   src.oneofEnum = Message3_Enum_Bar;
   [dst mergeFrom:src];
@@ -666,9 +613,10 @@
   XCTAssertEqual(dst.oneofEnum, Message3_Enum_Bar);
   XCTAssertEqual(dst.oneofBool, NO);
 
-// clang-format on
 //%PDDM-EXPAND-END (14 expansions)
 
+  // clang-format on
+
   NSString *oneofStringDefault = @"";
   NSData *oneofBytesDefault = [NSData data];
 
@@ -681,11 +629,9 @@
   src.oneofBytes = [@"bar" dataUsingEncoding:NSUTF8StringEncoding];
   [dst mergeFrom:src];
   XCTAssertEqual(dst.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
-  XCTAssertEqualObjects(dst.oneofBytes,
-                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertEqualObjects(dst.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
   XCTAssertEqualObjects(dst.oneofString, oneofStringDefault);
 
-
   Message3 *subMessage = [Message3 message];
   subMessage.optionalInt32 = 777;
   src.oneofMessage = subMessage;
diff --git a/objectivec/Tests/GPBMessageTests+Runtime.m b/objectivec/Tests/GPBMessageTests+Runtime.m
index baad082..3bcfae0 100644
--- a/objectivec/Tests/GPBMessageTests+Runtime.m
+++ b/objectivec/Tests/GPBMessageTests+Runtime.m
@@ -34,12 +34,12 @@
 
 #import "GPBMessage.h"
 
-#import "google/protobuf/MapUnittest.pbobjc.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestCycle.pbobjc.h"
-#import "google/protobuf/UnittestObjcStartup.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+#import "objectivec/Tests/MapUnittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestCycle.pbobjc.h"
+#import "objectivec/Tests/UnittestObjcStartup.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto3.pbobjc.h"
 
 @interface MessageRuntimeTests : GPBTestCase
 @end
@@ -98,14 +98,10 @@
 
   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([Message2 instancesRespondToSelector:hasSel], @"field: %@",
-                  name);
-    XCTAssertTrue([Message2 instancesRespondToSelector:setHasSel], @"field: %@",
-                  name);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasOptional%@", name]);
+    SEL setHasSel = NSSelectorFromString([NSString stringWithFormat:@"setHasOptional%@:", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:hasSel], @"field: %@", name);
+    XCTAssertTrue([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name);
   }
 
   // Repeated fields
@@ -114,33 +110,24 @@
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array:
-    SEL hasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"hasRepeated%@Array", name]);
-    SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
-    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
-                   name);
-    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
-                   @"field: %@", name);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasRepeated%@Array", name]);
+    SEL setHasSel =
+        NSSelectorFromString([NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name);
     // build the selector, i.e. - repeatedInt32Array_Count
-    SEL countSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"repeated%@Array_Count", name]);
-    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
-                   name);
+    SEL countSel = NSSelectorFromString([NSString stringWithFormat:@"repeated%@Array_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", name);
   }
 
   // OneOf fields - no has*/setHas*
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
-    SEL hasSel =
-        NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
-    SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasOneof%@:", name]);
-    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
-                   name);
-    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
-                   @"field: %@", name);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+    SEL setHasSel = NSSelectorFromString([NSString stringWithFormat:@"setHasOneof%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name);
   }
 
   // map<> fields
@@ -148,44 +135,23 @@
   //  - *Count
 
   NSArray *mapNames = @[
-    @"Int32Int32",
-    @"Int64Int64",
-    @"Uint32Uint32",
-    @"Uint64Uint64",
-    @"Sint32Sint32",
-    @"Sint64Sint64",
-    @"Fixed32Fixed32",
-    @"Fixed64Fixed64",
-    @"Sfixed32Sfixed32",
-    @"Sfixed64Sfixed64",
-    @"Int32Float",
-    @"Int32Double",
-    @"BoolBool",
-    @"StringString",
-    @"StringBytes",
-    @"StringMessage",
-    @"Int32Bytes",
-    @"Int32Enum",
-    @"Int32Message",
+    @"Int32Int32",       @"Int64Int64",       @"Uint32Uint32",   @"Uint64Uint64",
+    @"Sint32Sint32",     @"Sint64Sint64",     @"Fixed32Fixed32", @"Fixed64Fixed64",
+    @"Sfixed32Sfixed32", @"Sfixed64Sfixed64", @"Int32Float",     @"Int32Double",
+    @"BoolBool",         @"StringString",     @"StringBytes",    @"StringMessage",
+    @"Int32Bytes",       @"Int32Enum",        @"Int32Message",
   ];
 
   for (NSString *name in mapNames) {
     // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32:
-    SEL hasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"hasMap%@", name]);
-    SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasMap%@:", name]);
-    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@",
-                   name);
-    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel],
-                   @"field: %@", name);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasMap%@", name]);
+    SEL setHasSel = NSSelectorFromString([NSString stringWithFormat:@"setHasMap%@:", name]);
+    XCTAssertFalse([Message2 instancesRespondToSelector:hasSel], @"field: %@", name);
+    XCTAssertFalse([Message2 instancesRespondToSelector:setHasSel], @"field: %@", name);
     // build the selector, i.e. - mapInt32Int32Count
-    SEL countSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"map%@_Count", name]);
-    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@",
-                   name);
+    SEL countSel = NSSelectorFromString([NSString stringWithFormat:@"map%@_Count", name]);
+    XCTAssertTrue([Message2 instancesRespondToSelector:countSel], @"field: %@", name);
   }
-
 }
 
 - (void)testProto3HasMethodSupport {
@@ -217,21 +183,15 @@
 
   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]);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasOptional%@", name]);
+    SEL setHasSel = NSSelectorFromString([NSString stringWithFormat:@"setHasOptional%@:", name]);
     if ([name isEqual:@"Message"]) {
       // Sub messages/groups are the exception.
-      XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@",
-                    name);
-      XCTAssertTrue([Message3 instancesRespondToSelector:setHasSel],
-                    @"field: %@", name);
+      XCTAssertTrue([Message3 instancesRespondToSelector:hasSel], @"field: %@", name);
+      XCTAssertTrue([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name);
     } else {
-      XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
-                     name);
-      XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
-                     @"field: %@", name);
+      XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name);
+      XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name);
     }
   }
 
@@ -241,33 +201,24 @@
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasRepeatedInt32Array/setHasRepeatedInt32Array:
-    SEL hasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"hasRepeated%@Array", name]);
-    SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
-    XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
-                   name);
-    XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
-                   @"field: %@", name);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasRepeated%@Array", name]);
+    SEL setHasSel =
+        NSSelectorFromString([NSString stringWithFormat:@"setHasRepeated%@Array:", name]);
+    XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name);
+    XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name);
     // build the selector, i.e. - repeatedInt32Array_Count
-    SEL countSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"repeated%@Array_Count", name]);
-    XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@",
-                  name);
+    SEL countSel = NSSelectorFromString([NSString stringWithFormat:@"repeated%@Array_Count", name]);
+    XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@", name);
   }
 
   // OneOf fields - no has*/setHas*
 
   for (NSString *name in names) {
     // build the selector, i.e. - hasOneofInt32/setHasOneofInt32:
-    SEL hasSel =
-        NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
-    SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasOneof%@:", name]);
-    XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
-                   name);
-    XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
-                   @"field: %@", name);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasOneof%@", name]);
+    SEL setHasSel = NSSelectorFromString([NSString stringWithFormat:@"setHasOneof%@:", name]);
+    XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name);
+    XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name);
   }
 
   // Single Optional fields
@@ -277,14 +228,10 @@
 
   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);
+    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
@@ -292,42 +239,22 @@
   //  - *Count
 
   NSArray *mapNames = @[
-    @"Int32Int32",
-    @"Int64Int64",
-    @"Uint32Uint32",
-    @"Uint64Uint64",
-    @"Sint32Sint32",
-    @"Sint64Sint64",
-    @"Fixed32Fixed32",
-    @"Fixed64Fixed64",
-    @"Sfixed32Sfixed32",
-    @"Sfixed64Sfixed64",
-    @"Int32Float",
-    @"Int32Double",
-    @"BoolBool",
-    @"StringString",
-    @"StringBytes",
-    @"StringMessage",
-    @"Int32Bytes",
-    @"Int32Enum",
-    @"Int32Message",
+    @"Int32Int32",       @"Int64Int64",       @"Uint32Uint32",   @"Uint64Uint64",
+    @"Sint32Sint32",     @"Sint64Sint64",     @"Fixed32Fixed32", @"Fixed64Fixed64",
+    @"Sfixed32Sfixed32", @"Sfixed64Sfixed64", @"Int32Float",     @"Int32Double",
+    @"BoolBool",         @"StringString",     @"StringBytes",    @"StringMessage",
+    @"Int32Bytes",       @"Int32Enum",        @"Int32Message",
   ];
 
   for (NSString *name in mapNames) {
     // build the selector, i.e. - hasMapInt32Int32/setHasMapInt32Int32:
-    SEL hasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"hasMap%@", name]);
-    SEL setHasSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"setHasMap%@:", name]);
-    XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@",
-                   name);
-    XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel],
-                   @"field: %@", name);
+    SEL hasSel = NSSelectorFromString([NSString stringWithFormat:@"hasMap%@", name]);
+    SEL setHasSel = NSSelectorFromString([NSString stringWithFormat:@"setHasMap%@:", name]);
+    XCTAssertFalse([Message3 instancesRespondToSelector:hasSel], @"field: %@", name);
+    XCTAssertFalse([Message3 instancesRespondToSelector:setHasSel], @"field: %@", name);
     // build the selector, i.e. - mapInt32Int32Count
-    SEL countSel = NSSelectorFromString(
-        [NSString stringWithFormat:@"map%@_Count", name]);
-    XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@",
-                   name);
+    SEL countSel = NSSelectorFromString([NSString stringWithFormat:@"map%@_Count", name]);
+    XCTAssertTrue([Message3 instancesRespondToSelector:countSel], @"field: %@", name);
   }
 }
 
@@ -337,6 +264,9 @@
   // being true.
   //
 
+  // Disable clang-format for the macros.
+  // clang-format off
+
 //%PDDM-DEFINE PROTO2_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
 //%  {  // optional##FIELD :: NON_ZERO_VALUE
 //%    Message2 *msg = [[Message2 alloc] init];
@@ -399,7 +329,6 @@
 //%PROTO2_TEST_CLEAR_FIELD_WITH_NIL(Message, [Message2 message])
 //%PDDM-EXPAND PROTO2_TEST_HAS_FIELDS()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   {  // optionalInt32 :: 1
     Message2 *msg = [[Message2 alloc] init];
@@ -753,8 +682,9 @@
     [msg release];
   }
 
-// clang-format on
 //%PDDM-EXPAND-END PROTO2_TEST_HAS_FIELDS()
+
+  // clang-format on
 }
 
 - (void)testProto3SingleFieldHasBehavior {
@@ -763,6 +693,9 @@
   // being true.  When set to the default, shouldn't be true.
   //
 
+  // Disable clang-format for the macros.
+  // clang-format off
+
 //%PDDM-DEFINE PROTO3_TEST_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
 //%  {  // optional##FIELD
 //%    Message3 *msg = [[Message3 alloc] init];
@@ -815,7 +748,6 @@
 //%PROTO3_TEST_CLEAR_FIELD_WITH_NIL(Message, [Message3 message])
 //%PDDM-EXPAND PROTO3_TEST_HAS_FIELDS()
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
   {  // optionalInt32
     Message3 *msg = [[Message3 alloc] init];
@@ -1015,8 +947,9 @@
     [msg release];
   }
 
-// clang-format on
 //%PDDM-EXPAND-END PROTO3_TEST_HAS_FIELDS()
+
+  // clang-format on
 }
 
 - (void)testProto3SingleOptionalFieldHasBehavior {
@@ -1024,6 +957,9 @@
   // Setting to any value including the default (0) should result in true.
   //
 
+  // Disable clang-format for the macros.
+  // clang-format off
+
 //%PDDM-DEFINE PROTO3_TEST_OPTIONAL_HAS_FIELD(FIELD, NON_ZERO_VALUE, ZERO_VALUE)
 //%  {  // optional##FIELD
 //%    Message3Optional *msg = [[Message3Optional alloc] init];
@@ -1060,7 +996,6 @@
 //%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];
@@ -1258,8 +1193,9 @@
     [msg release];
   }
 
-// clang-format on
 //%PDDM-EXPAND-END PROTO3_TEST_OPTIONAL_HAS_FIELDS()
+
+  // clang-format on
 }
 
 - (void)testAccessingProto2UnknownEnumValues {
@@ -1268,13 +1204,11 @@
   // Set it to something non zero, try and confirm it doesn't change.
 
   msg.optionalEnum = Message2_Enum_Bar;
-  XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
-                               NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException, NSInvalidArgumentException);
   XCTAssertEqual(msg.optionalEnum, Message2_Enum_Bar);
 
   msg.oneofEnum = Message2_Enum_Bar;
-  XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
-                               NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException, NSInvalidArgumentException);
   XCTAssertEqual(msg.oneofEnum, Message2_Enum_Bar);
 
   [msg release];
@@ -1286,20 +1220,17 @@
   // Set it to something non zero, try and confirm it doesn't change.
 
   msg.optionalEnum = Message3_Enum_Bar;
-  XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException,
-                               NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed(msg.optionalEnum = 666, NSException, NSInvalidArgumentException);
   XCTAssertEqual(msg.optionalEnum, Message3_Enum_Bar);
 
   msg.oneofEnum = Message3_Enum_Bar;
-  XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException,
-                               NSInvalidArgumentException);
+  XCTAssertThrowsSpecificNamed(msg.oneofEnum = 666, NSException, NSInvalidArgumentException);
   XCTAssertEqual(msg.oneofEnum, Message3_Enum_Bar);
 
   // Set via raw api to confirm it works.
 
   SetMessage3_OptionalEnum_RawValue(msg, 666);
-  XCTAssertEqual(msg.optionalEnum,
-                 Message3_Enum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(msg.optionalEnum, Message3_Enum_GPBUnrecognizedEnumeratorValue);
   XCTAssertEqual(Message3_OptionalEnum_RawValue(msg), 666);
 
   SetMessage3_OneofEnum_RawValue(msg, 666);
@@ -1663,8 +1594,7 @@
   XCTAssertEqual(msg.oneofDouble, 111.0);
   XCTAssertEqual(msg.oneofBool, YES);
   XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
-  XCTAssertEqualObjects(msg.oneofBytes,
-                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
   XCTAssertNotNil(msg.oneofGroup);
   XCTAssertNotNil(msg.oneofMessage);
   XCTAssertEqual(msg.oneofEnum, Message2_Enum_Baz);
@@ -1747,24 +1677,15 @@
   msg = [[Message2 alloc] init];
 
   int32_t values[] = {
-    Message2_O_OneOfCase_OneofInt32,
-    Message2_O_OneOfCase_OneofInt64,
-    Message2_O_OneOfCase_OneofUint32,
-    Message2_O_OneOfCase_OneofUint64,
-    Message2_O_OneOfCase_OneofSint32,
-    Message2_O_OneOfCase_OneofSint64,
-    Message2_O_OneOfCase_OneofFixed32,
-    Message2_O_OneOfCase_OneofFixed64,
-    Message2_O_OneOfCase_OneofSfixed32,
-    Message2_O_OneOfCase_OneofSfixed64,
-    Message2_O_OneOfCase_OneofFloat,
-    Message2_O_OneOfCase_OneofDouble,
-    Message2_O_OneOfCase_OneofBool,
-    Message2_O_OneOfCase_OneofString,
-    Message2_O_OneOfCase_OneofBytes,
-    Message2_O_OneOfCase_OneofGroup,
-    Message2_O_OneOfCase_OneofMessage,
-    Message2_O_OneOfCase_OneofEnum,
+      Message2_O_OneOfCase_OneofInt32,    Message2_O_OneOfCase_OneofInt64,
+      Message2_O_OneOfCase_OneofUint32,   Message2_O_OneOfCase_OneofUint64,
+      Message2_O_OneOfCase_OneofSint32,   Message2_O_OneOfCase_OneofSint64,
+      Message2_O_OneOfCase_OneofFixed32,  Message2_O_OneOfCase_OneofFixed64,
+      Message2_O_OneOfCase_OneofSfixed32, Message2_O_OneOfCase_OneofSfixed64,
+      Message2_O_OneOfCase_OneofFloat,    Message2_O_OneOfCase_OneofDouble,
+      Message2_O_OneOfCase_OneofBool,     Message2_O_OneOfCase_OneofString,
+      Message2_O_OneOfCase_OneofBytes,    Message2_O_OneOfCase_OneofGroup,
+      Message2_O_OneOfCase_OneofMessage,  Message2_O_OneOfCase_OneofEnum,
   };
 
   for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
@@ -1832,8 +1753,7 @@
     // No need to check the value was set, the above tests did that.
     Message2_ClearOOneOfCase(msg);
     // Nothing in the case.
-    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase,
-                   "Loop: %zd", i);
+    XCTAssertEqual(msg.oOneOfCase, Message2_O_OneOfCase_GPBUnsetOneOfCase, "Loop: %zd", i);
     // Confirm everything is back to defaults after a clear.
     XCTAssertEqual(msg.oneofInt32, 100, "Loop: %zd", i);
     XCTAssertEqual(msg.oneofInt64, 101, "Loop: %zd", i);
@@ -2201,8 +2121,7 @@
   XCTAssertEqual(msg.oneofDouble, 0.0);
   XCTAssertEqual(msg.oneofBool, NO);
   XCTAssertEqualObjects(msg.oneofString, oneofStringDefault);
-  XCTAssertEqualObjects(msg.oneofBytes,
-                        [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
+  XCTAssertEqualObjects(msg.oneofBytes, [@"bar" dataUsingEncoding:NSUTF8StringEncoding]);
   XCTAssertNotNil(msg.oneofMessage);
   XCTAssertEqual(msg.oneofEnum, Message3_Enum_Foo);
   XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_OneofBytes);
@@ -2257,23 +2176,15 @@
   msg = [[Message3 alloc] init];
 
   int32_t values[] = {
-    Message3_O_OneOfCase_OneofInt32,
-    Message3_O_OneOfCase_OneofInt64,
-    Message3_O_OneOfCase_OneofUint32,
-    Message3_O_OneOfCase_OneofUint64,
-    Message3_O_OneOfCase_OneofSint32,
-    Message3_O_OneOfCase_OneofSint64,
-    Message3_O_OneOfCase_OneofFixed32,
-    Message3_O_OneOfCase_OneofFixed64,
-    Message3_O_OneOfCase_OneofSfixed32,
-    Message3_O_OneOfCase_OneofSfixed64,
-    Message3_O_OneOfCase_OneofFloat,
-    Message3_O_OneOfCase_OneofDouble,
-    Message3_O_OneOfCase_OneofBool,
-    Message3_O_OneOfCase_OneofString,
-    Message3_O_OneOfCase_OneofBytes,
-    Message3_O_OneOfCase_OneofMessage,
-    Message3_O_OneOfCase_OneofEnum,
+      Message3_O_OneOfCase_OneofInt32,    Message3_O_OneOfCase_OneofInt64,
+      Message3_O_OneOfCase_OneofUint32,   Message3_O_OneOfCase_OneofUint64,
+      Message3_O_OneOfCase_OneofSint32,   Message3_O_OneOfCase_OneofSint64,
+      Message3_O_OneOfCase_OneofFixed32,  Message3_O_OneOfCase_OneofFixed64,
+      Message3_O_OneOfCase_OneofSfixed32, Message3_O_OneOfCase_OneofSfixed64,
+      Message3_O_OneOfCase_OneofFloat,    Message3_O_OneOfCase_OneofDouble,
+      Message3_O_OneOfCase_OneofBool,     Message3_O_OneOfCase_OneofString,
+      Message3_O_OneOfCase_OneofBytes,    Message3_O_OneOfCase_OneofMessage,
+      Message3_O_OneOfCase_OneofEnum,
   };
 
   for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
@@ -2338,8 +2249,7 @@
     // No need to check the value was set, the above tests did that.
     Message3_ClearOOneOfCase(msg);
     // Nothing in the case.
-    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase,
-                   "Loop: %zd", i);
+    XCTAssertEqual(msg.oOneOfCase, Message3_O_OneOfCase_GPBUnsetOneOfCase, "Loop: %zd", i);
     // Confirm everything is back to defaults after a clear.
     XCTAssertEqual(msg.oneofInt32, 0, "Loop: %zd", i);
     XCTAssertEqual(msg.oneofInt64, 0, "Loop: %zd", i);
@@ -2366,7 +2276,6 @@
 }
 
 - (void)testProto2OneofSetToDefault {
-
   // proto3 doesn't normally write out zero (default) fields, but if they are
   // in a oneof it does.  proto2 doesn't have this special behavior, but we
   // still confirm setting to the explicit default does set the case to be
@@ -2378,24 +2287,24 @@
   Message2 *msg = [[Message2 alloc] init];
 
   int32_t values[] = {
-    Message2_O_OneOfCase_OneofInt32,
-    Message2_O_OneOfCase_OneofInt64,
-    Message2_O_OneOfCase_OneofUint32,
-    Message2_O_OneOfCase_OneofUint64,
-    Message2_O_OneOfCase_OneofSint32,
-    Message2_O_OneOfCase_OneofSint64,
-    Message2_O_OneOfCase_OneofFixed32,
-    Message2_O_OneOfCase_OneofFixed64,
-    Message2_O_OneOfCase_OneofSfixed32,
-    Message2_O_OneOfCase_OneofSfixed64,
-    Message2_O_OneOfCase_OneofFloat,
-    Message2_O_OneOfCase_OneofDouble,
-    Message2_O_OneOfCase_OneofBool,
-    Message2_O_OneOfCase_OneofString,
-    Message2_O_OneOfCase_OneofBytes,
-    // Skip group
-    // Skip message
-    Message2_O_OneOfCase_OneofEnum,
+      Message2_O_OneOfCase_OneofInt32,
+      Message2_O_OneOfCase_OneofInt64,
+      Message2_O_OneOfCase_OneofUint32,
+      Message2_O_OneOfCase_OneofUint64,
+      Message2_O_OneOfCase_OneofSint32,
+      Message2_O_OneOfCase_OneofSint64,
+      Message2_O_OneOfCase_OneofFixed32,
+      Message2_O_OneOfCase_OneofFixed64,
+      Message2_O_OneOfCase_OneofSfixed32,
+      Message2_O_OneOfCase_OneofSfixed64,
+      Message2_O_OneOfCase_OneofFloat,
+      Message2_O_OneOfCase_OneofDouble,
+      Message2_O_OneOfCase_OneofBool,
+      Message2_O_OneOfCase_OneofString,
+      Message2_O_OneOfCase_OneofBytes,
+      // Skip group
+      // Skip message
+      Message2_O_OneOfCase_OneofEnum,
   };
 
   for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
@@ -2496,7 +2405,6 @@
 }
 
 - (void)testProto3OneofSetToZero {
-
   // Normally setting a proto3 field to the zero value should result in it being
   // reset/cleared.  But in a oneof, it still gets recorded so it can go out
   // over the wire and the other side can see what was set in the oneof.
@@ -2507,23 +2415,15 @@
   Message3 *msg = [[Message3 alloc] init];
 
   int32_t values[] = {
-    Message3_O_OneOfCase_OneofInt32,
-    Message3_O_OneOfCase_OneofInt64,
-    Message3_O_OneOfCase_OneofUint32,
-    Message3_O_OneOfCase_OneofUint64,
-    Message3_O_OneOfCase_OneofSint32,
-    Message3_O_OneOfCase_OneofSint64,
-    Message3_O_OneOfCase_OneofFixed32,
-    Message3_O_OneOfCase_OneofFixed64,
-    Message3_O_OneOfCase_OneofSfixed32,
-    Message3_O_OneOfCase_OneofSfixed64,
-    Message3_O_OneOfCase_OneofFloat,
-    Message3_O_OneOfCase_OneofDouble,
-    Message3_O_OneOfCase_OneofBool,
-    Message3_O_OneOfCase_OneofString,
-    Message3_O_OneOfCase_OneofBytes,
-    Message3_O_OneOfCase_OneofMessage,
-    Message3_O_OneOfCase_OneofEnum,
+      Message3_O_OneOfCase_OneofInt32,    Message3_O_OneOfCase_OneofInt64,
+      Message3_O_OneOfCase_OneofUint32,   Message3_O_OneOfCase_OneofUint64,
+      Message3_O_OneOfCase_OneofSint32,   Message3_O_OneOfCase_OneofSint64,
+      Message3_O_OneOfCase_OneofFixed32,  Message3_O_OneOfCase_OneofFixed64,
+      Message3_O_OneOfCase_OneofSfixed32, Message3_O_OneOfCase_OneofSfixed64,
+      Message3_O_OneOfCase_OneofFloat,    Message3_O_OneOfCase_OneofDouble,
+      Message3_O_OneOfCase_OneofBool,     Message3_O_OneOfCase_OneofString,
+      Message3_O_OneOfCase_OneofBytes,    Message3_O_OneOfCase_OneofMessage,
+      Message3_O_OneOfCase_OneofEnum,
   };
 
   for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
@@ -2654,27 +2554,19 @@
   XCTAssertNotEqual(msg1.repeatedStringArray, msg2.repeatedStringArray);
   XCTAssertNotEqual(msg1.repeatedBytesArray, msg2.repeatedBytesArray);
   XCTAssertNotEqual(msg1.repeatedGroupArray, msg2.repeatedGroupArray);
-  XCTAssertNotEqual(msg1.repeatedNestedMessageArray,
-                    msg2.repeatedNestedMessageArray);
-  XCTAssertNotEqual(msg1.repeatedForeignMessageArray,
-                    msg2.repeatedForeignMessageArray);
-  XCTAssertNotEqual(msg1.repeatedImportMessageArray,
-                    msg2.repeatedImportMessageArray);
+  XCTAssertNotEqual(msg1.repeatedNestedMessageArray, msg2.repeatedNestedMessageArray);
+  XCTAssertNotEqual(msg1.repeatedForeignMessageArray, msg2.repeatedForeignMessageArray);
+  XCTAssertNotEqual(msg1.repeatedImportMessageArray, msg2.repeatedImportMessageArray);
   XCTAssertNotEqual(msg1.repeatedNestedEnumArray, msg2.repeatedNestedEnumArray);
-  XCTAssertNotEqual(msg1.repeatedForeignEnumArray,
-                    msg2.repeatedForeignEnumArray);
+  XCTAssertNotEqual(msg1.repeatedForeignEnumArray, msg2.repeatedForeignEnumArray);
   XCTAssertNotEqual(msg1.repeatedImportEnumArray, msg2.repeatedImportEnumArray);
-  XCTAssertNotEqual(msg1.repeatedStringPieceArray,
-                    msg2.repeatedStringPieceArray);
+  XCTAssertNotEqual(msg1.repeatedStringPieceArray, msg2.repeatedStringPieceArray);
   XCTAssertNotEqual(msg1.repeatedCordArray, msg2.repeatedCordArray);
 
   for (int i = 0; i < repeatCount; i++) {
-    XCTAssertNotEqual(msg1.repeatedNestedMessageArray[i],
-                      msg2.repeatedNestedMessageArray[i]);
-    XCTAssertNotEqual(msg1.repeatedForeignMessageArray[i],
-                      msg2.repeatedForeignMessageArray[i]);
-    XCTAssertNotEqual(msg1.repeatedImportMessageArray[i],
-                      msg2.repeatedImportMessageArray[i]);
+    XCTAssertNotEqual(msg1.repeatedNestedMessageArray[i], msg2.repeatedNestedMessageArray[i]);
+    XCTAssertNotEqual(msg1.repeatedForeignMessageArray[i], msg2.repeatedForeignMessageArray[i]);
+    XCTAssertNotEqual(msg1.repeatedImportMessageArray[i], msg2.repeatedImportMessageArray[i]);
   }
 }
 
@@ -2708,8 +2600,7 @@
 
   // Ensure the messages are unique per map.
   [msg1.mapInt32ForeignMessage
-      enumerateKeysAndObjectsUsingBlock:^(int32_t key, id value, BOOL *stop) {
-#pragma unused(stop)
+      enumerateKeysAndObjectsUsingBlock:^(int32_t key, id value, __unused BOOL *stop) {
         ForeignMessage *subMsg2 = [msg2.mapInt32ForeignMessage objectForKey:key];
         XCTAssertNotEqual(value, subMsg2);  // Ptr compare, new object.
       }];
@@ -2720,7 +2611,7 @@
   GPBFieldDescriptor *fieldDescriptor = [[message descriptor] fieldWithName:@"repeatedStringArray"];
   XCTAssertNotNil(fieldDescriptor);
   NSMutableArray *fieldArray = GPBGetMessageRepeatedField(message, fieldDescriptor);
-  XCTAssertNotNil(fieldArray);  // Should have autocreated.
+  XCTAssertNotNil(fieldArray);                               // Should have autocreated.
   XCTAssertTrue(fieldArray == message.repeatedStringArray);  // Same pointer
 }
 
@@ -2740,7 +2631,7 @@
   GPBFieldDescriptor *fieldDescriptor = [[message descriptor] fieldWithName:@"mapStringString"];
   XCTAssertNotNil(fieldDescriptor);
   NSMutableDictionary *fieldMap = GPBGetMessageMapField(message, fieldDescriptor);
-  XCTAssertNotNil(fieldMap);  // Should have autocreated.
+  XCTAssertNotNil(fieldMap);                           // Should have autocreated.
   XCTAssertTrue(fieldMap == message.mapStringString);  // Same pointer
 }
 
diff --git a/objectivec/Tests/GPBMessageTests+Serialization.m b/objectivec/Tests/GPBMessageTests+Serialization.m
index bb63ec3..3c2381c 100644
--- a/objectivec/Tests/GPBMessageTests+Serialization.m
+++ b/objectivec/Tests/GPBMessageTests+Serialization.m
@@ -34,13 +34,12 @@
 
 #import "GPBMessage.h"
 
-#import "google/protobuf/MapProto2Unittest.pbobjc.h"
-#import "google/protobuf/MapUnittest.pbobjc.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestDropUnknownFields.pbobjc.h"
-#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+#import "objectivec/Tests/MapProto2Unittest.pbobjc.h"
+#import "objectivec/Tests/MapUnittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestPreserveUnknownEnum.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto3.pbobjc.h"
 
 @interface MessageSerializationTests : GPBTestCase
 @end
@@ -114,6 +113,9 @@
   // Proto3 optionals should be just like proto2, zero values also get serialized.
   //
 
+  // Disable clang-format for the macros.
+  // clang-format off
+
 //%PDDM-DEFINE PROTO3_TEST_SERIALIZE_OPTIONAL_FIELD(FIELD, ZERO_VALUE, EXPECTED_LEN)
 //%  {  // optional##FIELD
 //%    Message3Optional *msg = [[Message3Optional alloc] init];
@@ -154,7 +156,6 @@
 //%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];
@@ -416,17 +417,17 @@
     [msg release];
   }
 
-// clang-format on
 //%PDDM-EXPAND-END PROTO3_TEST_SERIALIZE_OPTIONAL_FIELDS()
+
+  // clang-format on
 }
 
 - (void)testProto2UnknownEnumToUnknownField {
   Message3 *orig = [[Message3 alloc] init];
 
   orig.optionalEnum = Message3_Enum_Extra3;
-  orig.repeatedEnumArray =
-      [GPBEnumArray arrayWithValidationFunction:Message3_Enum_IsValidValue
-                                       rawValue:Message3_Enum_Extra3];
+  orig.repeatedEnumArray = [GPBEnumArray arrayWithValidationFunction:Message3_Enum_IsValidValue
+                                                            rawValue:Message3_Enum_Extra3];
   orig.oneofEnum = Message3_Enum_Extra3;
 
   NSData *data = [orig data];
@@ -445,15 +446,12 @@
 
   XCTAssertEqual([unknownFields countOfFields], 3U);
   XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OptionalEnum]);
-  XCTAssertTrue(
-      [unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]);
+  XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_RepeatedEnumArray]);
   XCTAssertTrue([unknownFields hasField:Message2_FieldNumber_OneofEnum]);
 
-  GPBUnknownField *field =
-      [unknownFields getField:Message2_FieldNumber_OptionalEnum];
+  GPBUnknownField *field = [unknownFields getField:Message2_FieldNumber_OptionalEnum];
   XCTAssertEqual(field.varintList.count, 1U);
-  XCTAssertEqual([field.varintList valueAtIndex:0],
-                 (uint64_t)Message3_Enum_Extra3);
+  XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3);
 
   field = [unknownFields getField:Message2_FieldNumber_RepeatedEnumArray];
   XCTAssertEqual(field.varintList.count, 1U);
@@ -461,36 +459,32 @@
 
   field = [unknownFields getField:Message2_FieldNumber_OneofEnum];
   XCTAssertEqual(field.varintList.count, 1U);
-  XCTAssertEqual([field.varintList valueAtIndex:0],
-                 (uint64_t)Message3_Enum_Extra3);
+  XCTAssertEqual([field.varintList valueAtIndex:0], (uint64_t)Message3_Enum_Extra3);
 
   [msg release];
   [orig release];
 }
 
 - (void)testProto3UnknownEnumPreserving {
-  UnknownEnumsMyMessagePlusExtra *orig =
-      [UnknownEnumsMyMessagePlusExtra message];
+  UnknownEnumsMyMessagePlusExtra *orig = [UnknownEnumsMyMessagePlusExtra message];
 
   orig.e = UnknownEnumsMyEnumPlusExtra_EExtra;
-  orig.repeatedEArray = [GPBEnumArray
-      arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
-                         rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
-  orig.repeatedPackedEArray = [GPBEnumArray
-      arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
-                         rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+  orig.repeatedEArray =
+      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+                                       rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
+  orig.repeatedPackedEArray =
+      [GPBEnumArray arrayWithValidationFunction:UnknownEnumsMyEnumPlusExtra_IsValidValue
+                                       rawValue:UnknownEnumsMyEnumPlusExtra_EExtra];
   orig.oneofE1 = UnknownEnumsMyEnumPlusExtra_EExtra;
 
   // Everything should be there via raw values.
 
   NSData *data = [orig data];
   XCTAssertNotNil(data);
-  UnknownEnumsMyMessage *msg =
-      [UnknownEnumsMyMessage parseFromData:data error:NULL];
+  UnknownEnumsMyMessage *msg = [UnknownEnumsMyMessage parseFromData:data error:NULL];
 
   XCTAssertEqual(msg.e, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
-  XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(msg),
-                 UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(UnknownEnumsMyMessage_E_RawValue(msg), UnknownEnumsMyEnumPlusExtra_EExtra);
   XCTAssertEqual(msg.repeatedEArray.count, 1U);
   XCTAssertEqual([msg.repeatedEArray valueAtIndex:0],
                  UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
@@ -501,10 +495,8 @@
                  UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
   XCTAssertEqual([msg.repeatedPackedEArray rawValueAtIndex:0],
                  (UnknownEnumsMyEnum)UnknownEnumsMyEnumPlusExtra_EExtra);
-  XCTAssertEqual(msg.oneofE1,
-                 UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
-  XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(msg),
-                 UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual(msg.oneofE1, UnknownEnumsMyEnum_GPBUnrecognizedEnumeratorValue);
+  XCTAssertEqual(UnknownEnumsMyMessage_OneofE1_RawValue(msg), UnknownEnumsMyEnumPlusExtra_EExtra);
 
   // Everything should go out and come back.
 
@@ -513,14 +505,15 @@
 
   XCTAssertEqual(orig.e, UnknownEnumsMyEnumPlusExtra_EExtra);
   XCTAssertEqual(orig.repeatedEArray.count, 1U);
-  XCTAssertEqual([orig.repeatedEArray valueAtIndex:0],
-                 UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual([orig.repeatedEArray valueAtIndex:0], UnknownEnumsMyEnumPlusExtra_EExtra);
   XCTAssertEqual(orig.repeatedPackedEArray.count, 1U);
-  XCTAssertEqual([orig.repeatedPackedEArray valueAtIndex:0],
-                 UnknownEnumsMyEnumPlusExtra_EExtra);
+  XCTAssertEqual([orig.repeatedPackedEArray valueAtIndex:0], UnknownEnumsMyEnumPlusExtra_EExtra);
   XCTAssertEqual(orig.oneofE1, UnknownEnumsMyEnumPlusExtra_EExtra);
 }
 
+// Disable clang-format for the macros.
+// clang-format off
+
 //%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF(MESSAGE, FIELD, VALUE)
 //%TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, )
 //%PDDM-DEFINE TEST_ROUNDTRIP_ONEOF_ADV(MESSAGE, FIELD, VALUE, EQ_SUFFIX)
@@ -584,7 +577,6 @@
 //%
 //%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(2, NO)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)testProto2RoundTripOneof {
 
@@ -815,10 +807,8 @@
   [subMessage release];
 }
 
-// clang-format on
 //%PDDM-EXPAND TEST_ROUNDTRIP_ONEOFS(3, YES)
 // This block of code is generated, do not edit it directly.
-// clang-format off
 
 - (void)testProto3RoundTripOneof {
 
@@ -1035,9 +1025,10 @@
   [subMessage release];
 }
 
-// clang-format on
 //%PDDM-EXPAND-END (2 expansions)
 
+// clang-format on
+
 - (void)testPackedUnpackedMessageParsing {
   // packed is optional, a repeated field should parse when packed or unpacked.
 
@@ -1054,15 +1045,13 @@
                            @"Data should differ (packed vs unpacked) use");
 
   NSError *error = nil;
-  TestPackedTypes *packedParse =
-      [TestPackedTypes parseFromData:unpackedData error:&error];
+  TestPackedTypes *packedParse = [TestPackedTypes parseFromData:unpackedData error:&error];
   XCTAssertNotNil(packedParse);
   XCTAssertNil(error);
   XCTAssertEqualObjects(packedParse, packedOrig);
 
   error = nil;
-  TestUnpackedTypes *unpackedParsed =
-      [TestUnpackedTypes parseFromData:packedData error:&error];
+  TestUnpackedTypes *unpackedParsed = [TestUnpackedTypes parseFromData:packedData error:&error];
   XCTAssertNotNil(unpackedParsed);
   XCTAssertNil(error);
   XCTAssertEqualObjects(unpackedParsed, unpackedOrig);
@@ -1119,8 +1108,7 @@
   XCTAssertEqualObjects(fieldsData, extsData);
 
   NSError *error = nil;
-  TestPackedTypes *fieldsParse =
-      [TestPackedTypes parseFromData:extsData error:&error];
+  TestPackedTypes *fieldsParse = [TestPackedTypes parseFromData:extsData error:&error];
   XCTAssertNotNil(fieldsParse);
   XCTAssertNil(error);
   XCTAssertEqualObjects(fieldsParse, fieldsOrig);
@@ -1150,8 +1138,7 @@
   XCTAssertNotNil(extsData);
   XCTAssertEqualObjects(fieldsData, extsData);
 
-  TestUnpackedTypes *fieldsParse =
-      [TestUnpackedTypes parseFromData:extsData error:NULL];
+  TestUnpackedTypes *fieldsParse = [TestUnpackedTypes parseFromData:extsData error:NULL];
   XCTAssertNotNil(fieldsParse);
   XCTAssertEqualObjects(fieldsParse, fieldsOrig);
 
@@ -1164,11 +1151,9 @@
 }
 
 - (void)testErrorSubsectionInvalidLimit {
-  NSData *data = DataFromCStr(
-      "\x0A\x08\x0A\x07\x12\x04\x72\x02\x4B\x50\x12\x04\x72\x02\x4B\x50");
+  NSData *data = DataFromCStr("\x0A\x08\x0A\x07\x12\x04\x72\x02\x4B\x50\x12\x04\x72\x02\x4B\x50");
   NSError *error = nil;
-  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data
-                                                        error:&error];
+  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data error:&error];
   XCTAssertNil(msg);
   XCTAssertNotNil(error);
   XCTAssertEqualObjects(error.domain, GPBCodedInputStreamErrorDomain);
@@ -1178,8 +1163,7 @@
 - (void)testErrorSubsectionLimitReached {
   NSData *data = DataFromCStr("\x0A\x06\x12\x03\x72\x02\x4B\x50");
   NSError *error = nil;
-  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data
-                                                        error:&error];
+  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data error:&error];
   XCTAssertNil(msg);
   XCTAssertNotNil(error);
   XCTAssertEqualObjects(error.domain, GPBCodedInputStreamErrorDomain);
@@ -1209,8 +1193,7 @@
 - (void)testErrorInvalidSize {
   NSData *data = DataFromCStr("\x72\x03\x4B\x50");
   NSError *error = nil;
-  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data
-                                                        error:&error];
+  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data error:&error];
   XCTAssertNil(msg);
   XCTAssertNotNil(error);
   XCTAssertEqualObjects(error.domain, GPBCodedInputStreamErrorDomain);
@@ -1220,8 +1203,7 @@
 - (void)testErrorInvalidTag {
   NSData *data = DataFromCStr("\x0F");
   NSError *error = nil;
-  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data
-                                                        error:&error];
+  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data error:&error];
   XCTAssertNil(msg);
   XCTAssertNotNil(error);
   XCTAssertEqualObjects(error.domain, GPBCodedInputStreamErrorDomain);
@@ -1231,12 +1213,7 @@
 - (void)testZeroFieldNum {
   // These are ConformanceTestSuite::TestIllegalTags.
 
-  const char *tests[] = {
-    "\1DEADBEEF",
-    "\2\1\1",
-    "\3\4",
-    "\5DEAD"
-  };
+  const char *tests[] = {"\1DEADBEEF", "\2\1\1", "\3\4", "\5DEAD"};
 
   for (size_t i = 0; i < GPBARRAYSIZE(tests); ++i) {
     NSData *data = DataFromCStr(tests[i]);
@@ -1264,27 +1241,25 @@
 }
 
 - (void)testErrorRecursionDepthReached {
-  NSData *data = DataFromCStr(
-      "\x0A\xF2\x01\x0A\xEF\x01\x0A\xEC\x01\x0A\xE9\x01\x0A\xE6\x01"
-      "\x0A\xE3\x01\x0A\xE0\x01\x0A\xDD\x01\x0A\xDA\x01\x0A\xD7\x01"
-      "\x0A\xD4\x01\x0A\xD1\x01\x0A\xCE\x01\x0A\xCB\x01\x0A\xC8\x01"
-      "\x0A\xC5\x01\x0A\xC2\x01\x0A\xBF\x01\x0A\xBC\x01\x0A\xB9\x01"
-      "\x0A\xB6\x01\x0A\xB3\x01\x0A\xB0\x01\x0A\xAD\x01\x0A\xAA\x01"
-      "\x0A\xA7\x01\x0A\xA4\x01\x0A\xA1\x01\x0A\x9E\x01\x0A\x9B\x01"
-      "\x0A\x98\x01\x0A\x95\x01\x0A\x92\x01\x0A\x8F\x01\x0A\x8C\x01"
-      "\x0A\x89\x01\x0A\x86\x01\x0A\x83\x01\x0A\x80\x01\x0A\x7E"
-      "\x0A\x7C\x0A\x7A\x0A\x78\x0A\x76\x0A\x74\x0A\x72\x0A\x70"
-      "\x0A\x6E\x0A\x6C\x0A\x6A\x0A\x68\x0A\x66\x0A\x64\x0A\x62"
-      "\x0A\x60\x0A\x5E\x0A\x5C\x0A\x5A\x0A\x58\x0A\x56\x0A\x54"
-      "\x0A\x52\x0A\x50\x0A\x4E\x0A\x4C\x0A\x4A\x0A\x48\x0A\x46"
-      "\x0A\x44\x0A\x42\x0A\x40\x0A\x3E\x0A\x3C\x0A\x3A\x0A\x38"
-      "\x0A\x36\x0A\x34\x0A\x32\x0A\x30\x0A\x2E\x0A\x2C\x0A\x2A"
-      "\x0A\x28\x0A\x26\x0A\x24\x0A\x22\x0A\x20\x0A\x1E\x0A\x1C"
-      "\x0A\x1A\x0A\x18\x0A\x16\x0A\x14\x0A\x12\x0A\x10\x0A\x0E"
-      "\x0A\x0C\x0A\x0A\x0A\x08\x0A\x06\x12\x04\x72\x02\x4B\x50");
+  NSData *data = DataFromCStr("\x0A\xF2\x01\x0A\xEF\x01\x0A\xEC\x01\x0A\xE9\x01\x0A\xE6\x01"
+                              "\x0A\xE3\x01\x0A\xE0\x01\x0A\xDD\x01\x0A\xDA\x01\x0A\xD7\x01"
+                              "\x0A\xD4\x01\x0A\xD1\x01\x0A\xCE\x01\x0A\xCB\x01\x0A\xC8\x01"
+                              "\x0A\xC5\x01\x0A\xC2\x01\x0A\xBF\x01\x0A\xBC\x01\x0A\xB9\x01"
+                              "\x0A\xB6\x01\x0A\xB3\x01\x0A\xB0\x01\x0A\xAD\x01\x0A\xAA\x01"
+                              "\x0A\xA7\x01\x0A\xA4\x01\x0A\xA1\x01\x0A\x9E\x01\x0A\x9B\x01"
+                              "\x0A\x98\x01\x0A\x95\x01\x0A\x92\x01\x0A\x8F\x01\x0A\x8C\x01"
+                              "\x0A\x89\x01\x0A\x86\x01\x0A\x83\x01\x0A\x80\x01\x0A\x7E"
+                              "\x0A\x7C\x0A\x7A\x0A\x78\x0A\x76\x0A\x74\x0A\x72\x0A\x70"
+                              "\x0A\x6E\x0A\x6C\x0A\x6A\x0A\x68\x0A\x66\x0A\x64\x0A\x62"
+                              "\x0A\x60\x0A\x5E\x0A\x5C\x0A\x5A\x0A\x58\x0A\x56\x0A\x54"
+                              "\x0A\x52\x0A\x50\x0A\x4E\x0A\x4C\x0A\x4A\x0A\x48\x0A\x46"
+                              "\x0A\x44\x0A\x42\x0A\x40\x0A\x3E\x0A\x3C\x0A\x3A\x0A\x38"
+                              "\x0A\x36\x0A\x34\x0A\x32\x0A\x30\x0A\x2E\x0A\x2C\x0A\x2A"
+                              "\x0A\x28\x0A\x26\x0A\x24\x0A\x22\x0A\x20\x0A\x1E\x0A\x1C"
+                              "\x0A\x1A\x0A\x18\x0A\x16\x0A\x14\x0A\x12\x0A\x10\x0A\x0E"
+                              "\x0A\x0C\x0A\x0A\x0A\x08\x0A\x06\x12\x04\x72\x02\x4B\x50");
   NSError *error = nil;
-  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data
-                                                        error:&error];
+  NestedTestAllTypes *msg = [NestedTestAllTypes parseFromData:data error:&error];
   XCTAssertNil(msg);
   XCTAssertNotNil(error);
   XCTAssertEqualObjects(error.domain, GPBCodedInputStreamErrorDomain);
@@ -1295,9 +1270,7 @@
   NSData *data = DataFromCStr("\xFF\xFF\xFF\xFF\x0F");
   GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:data];
   NSError *error;
-  [GPBMessage parseDelimitedFromCodedInputStream:input
-                               extensionRegistry:nil
-                                           error:&error];
+  [GPBMessage parseDelimitedFromCodedInputStream:input extensionRegistry:nil error:&error];
   XCTAssertNil(error);
 }
 
@@ -1433,10 +1406,8 @@
       initWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue] autorelease];
   orig.unknownMapField = [[[GPBInt32EnumDictionary alloc]
       initWithValidationFunction:Proto2MapEnumPlusExtra_IsValidValue] autorelease];
-  [orig.knownMapField setEnum:Proto2MapEnumPlusExtra_EProto2MapEnumFoo
-                       forKey:0];
-  [orig.unknownMapField setEnum:Proto2MapEnumPlusExtra_EProto2MapEnumExtra
-                         forKey:0];
+  [orig.knownMapField setEnum:Proto2MapEnumPlusExtra_EProto2MapEnumFoo forKey:0];
+  [orig.unknownMapField setEnum:Proto2MapEnumPlusExtra_EProto2MapEnumExtra forKey:0];
 
   NSData *data = [orig data];
   XCTAssertNotNil(data);
@@ -1448,8 +1419,7 @@
   XCTAssertEqual(msg1.unknownFields.countOfFields, 1U);
 
   data = [msg1 data];
-  TestEnumMapPlusExtra *msg2 =
-      [TestEnumMapPlusExtra parseFromData:data error:NULL];
+  TestEnumMapPlusExtra *msg2 = [TestEnumMapPlusExtra parseFromData:data error:NULL];
   val = -1;
   XCTAssertEqual(msg2.knownMapField.count, 1U);
   XCTAssertTrue([msg2.knownMapField getEnum:&val forKey:0]);
diff --git a/objectivec/Tests/GPBMessageTests.m b/objectivec/Tests/GPBMessageTests.m
index b2c75ba..6a1d48b 100644
--- a/objectivec/Tests/GPBMessageTests.m
+++ b/objectivec/Tests/GPBMessageTests.m
@@ -36,12 +36,12 @@
 #import "GPBDescriptor.h"
 #import "GPBDictionary_PackagePrivate.h"
 #import "GPBMessage_PackagePrivate.h"
-#import "GPBUnknownField_PackagePrivate.h"
 #import "GPBUnknownFieldSet_PackagePrivate.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestObjc.pbobjc.h"
-#import "google/protobuf/UnittestObjcOptions.pbobjc.h"
-#import "google/protobuf/UnittestImport.pbobjc.h"
+#import "GPBUnknownField_PackagePrivate.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestImport.pbobjc.h"
+#import "objectivec/Tests/UnittestObjc.pbobjc.h"
+#import "objectivec/Tests/UnittestObjcOptions.pbobjc.h"
 
 // Helper class to test KVO.
 @interface GPBKVOTestObserver : NSObject {
@@ -49,7 +49,7 @@
   NSString *keyPath_;
 }
 
-@property (nonatomic) BOOL didObserve;
+@property(nonatomic) BOOL didObserve;
 - (id)initWithObservee:(id)observee keyPath:(NSString *)keyPath;
 @end
 
@@ -74,13 +74,9 @@
 }
 
 - (void)observeValueForKeyPath:(NSString *)keyPath
-                      ofObject:(id)object
-                        change:(NSDictionary *)change
-                       context:(void *)context
-{
-#pragma unused(object)
-#pragma unused(change)
-#pragma unused(context)
+                      ofObject:(__unused id)object
+                        change:(__unused NSDictionary *)change
+                       context:(__unused void *)context {
   if ([keyPath isEqualToString:keyPath_]) {
     self.didObserve = YES;
   }
@@ -156,12 +152,9 @@
   [message setExtension:[UnittestRoot optionalStringExtension] value:@"foo"];
   ForeignMessage *foreignMessage = [ForeignMessage message];
   foreignMessage.c = 4;
-  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
-                  value:foreignMessage];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [TestAllTypes_NestedMessage message];
-  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
-                  value:nestedMessage];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension] value:foreignMessage];
+  TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage];
   return message;
 }
 
@@ -170,13 +163,10 @@
   [message setExtension:[UnittestRoot optionalInt64Extension] value:@6];
   [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
   ForeignMessage *foreignMessage = [ForeignMessage message];
-  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
-                  value:foreignMessage];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [TestAllTypes_NestedMessage message];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension] value:foreignMessage];
+  TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
   nestedMessage.bb = 7;
-  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
-                  value:nestedMessage];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage];
   return message;
 }
 
@@ -187,13 +177,10 @@
   [message setExtension:[UnittestRoot optionalStringExtension] value:@"bar"];
   ForeignMessage *foreignMessage = [ForeignMessage message];
   foreignMessage.c = 4;
-  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
-                  value:foreignMessage];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [TestAllTypes_NestedMessage message];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension] value:foreignMessage];
+  TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
   nestedMessage.bb = 7;
-  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
-                  value:nestedMessage];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage];
   return message;
 }
 
@@ -211,11 +198,9 @@
   result = [[self.mergeDestinationWithoutForeignMessageIvar copy] autorelease];
   [result mergeFrom:self.mergeSource];
   resultData = [result data];
-  mergeResultData =
-      [self.mergeResultForDestinationWithoutForeignMessageIvar data];
+  mergeResultData = [self.mergeResultForDestinationWithoutForeignMessageIvar data];
   XCTAssertEqualObjects(resultData, mergeResultData);
-  XCTAssertEqualObjects(
-      result, self.mergeResultForDestinationWithoutForeignMessageIvar);
+  XCTAssertEqualObjects(result, self.mergeResultForDestinationWithoutForeignMessageIvar);
 
   // Test when destination is empty.
   // The result must is same as the source.
@@ -239,8 +224,7 @@
   result = [self mergeExtensionsDestination];
   NSData *data = [[self mergeExtensionsSource] data];
   XCTAssertNotNil(data);
-  [result mergeFromData:data
-      extensionRegistry:[UnittestRoot extensionRegistry]];
+  [result mergeFromData:data extensionRegistry:[UnittestRoot extensionRegistry]];
   resultData = [result data];
   XCTAssertEqualObjects(resultData, mergeResultData);
   XCTAssertEqualObjects(result, [self mergeExtensionsResult]);
@@ -306,16 +290,13 @@
   [message setExtension:[TestRequired single] value:[TestRequired message]];
   XCTAssertFalse(message.initialized);
 
-  [message setExtension:[TestRequired single]
-                  value:self.testRequiredInitialized];
+  [message setExtension:[TestRequired single] value:self.testRequiredInitialized];
   XCTAssertTrue(message.initialized);
 
   [message addExtension:[TestRequired multi] value:[TestRequired message]];
   XCTAssertFalse(message.initialized);
 
-  [message setExtension:[TestRequired multi]
-                  index:0
-                  value:self.testRequiredInitialized];
+  [message setExtension:[TestRequired multi] index:0 value:self.testRequiredInitialized];
   XCTAssertTrue(message.initialized);
 }
 
@@ -367,8 +348,7 @@
 
 - (void)testParseUninitialized {
   NSError *error = nil;
-  TestRequired *msg =
-      [TestRequired parseFromData:GPBEmptyNSData() error:&error];
+  TestRequired *msg = [TestRequired parseFromData:GPBEmptyNSData() error:&error];
   // In DEBUG, the parse will fail, but in non DEBUG, it passes because
   // the check isn't done (for speed).
 #ifdef DEBUG
@@ -388,8 +368,7 @@
 
 - (void)testCoding {
   GPBMessage *original = [self mergeResult];
-  NSData *data =
-      [NSKeyedArchiver archivedDataWithRootObject:original];
+  NSData *data = [NSKeyedArchiver archivedDataWithRootObject:original];
   id unarchivedObject = [NSKeyedUnarchiver unarchiveObjectWithData:data];
 
   XCTAssertEqualObjects(unarchivedObject, original);
@@ -411,8 +390,7 @@
 
   NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
   [unarchiver setRequiresSecureCoding:YES];
-  id unarchivedObject = [unarchiver decodeObjectOfClass:[GPBMessage class]
-                                                 forKey:key];
+  id unarchivedObject = [unarchiver decodeObjectOfClass:[GPBMessage class] forKey:key];
   [unarchiver finishDecoding];
 
   XCTAssertEqualObjects(unarchivedObject, original);
@@ -485,9 +463,7 @@
 - (void)testKVOBasic {
   TestAllTypes *message = [TestAllTypes message];
   GPBKVOTestObserver *observer =
-      [[[GPBKVOTestObserver alloc] initWithObservee:message
-                                            keyPath:@"optionalString"]
-       autorelease];
+      [[[GPBKVOTestObserver alloc] initWithObservee:message keyPath:@"optionalString"] autorelease];
   XCTAssertFalse(observer.didObserve);
   message.defaultString = @"Hello";
   XCTAssertFalse(observer.didObserve);
@@ -499,12 +475,10 @@
   TestAllTypes *message = [TestAllTypes message];
   GPBKVOTestObserver *autocreateObserver =
       [[[GPBKVOTestObserver alloc] initWithObservee:message
-                                            keyPath:@"optionalImportMessage"]
-       autorelease];
- GPBKVOTestObserver *innerFieldObserver =
-     [[[GPBKVOTestObserver alloc] initWithObservee:message
-                                           keyPath:@"optionalImportMessage.d"]
-      autorelease];
+                                            keyPath:@"optionalImportMessage"] autorelease];
+  GPBKVOTestObserver *innerFieldObserver =
+      [[[GPBKVOTestObserver alloc] initWithObservee:message
+                                            keyPath:@"optionalImportMessage.d"] autorelease];
   XCTAssertFalse(autocreateObserver.didObserve);
   XCTAssertFalse(innerFieldObserver.didObserve);
 
@@ -536,10 +510,8 @@
   TestAllTypes *message = [TestAllTypes message];
   [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
 
-  GPBUnknownFieldSet *unknownFields =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
-  GPBUnknownField *field =
-      [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
+  GPBUnknownFieldSet *unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownField *field = [[[GPBUnknownField alloc] initWithNumber:2] autorelease];
   [field addVarint:2];
   [unknownFields addField:field];
   field = [[[GPBUnknownField alloc] initWithNumber:3] autorelease];
@@ -567,8 +539,7 @@
   TestAllTypes *message = [TestAllTypes message];
   GPBDescriptor *descriptor = [[message class] descriptor];
   XCTAssertNotNil(descriptor);
-  GPBFieldDescriptor *fieldDescriptor =
-      [descriptor fieldWithName:@"defaultInt32"];
+  GPBFieldDescriptor *fieldDescriptor = [descriptor fieldWithName:@"defaultInt32"];
   XCTAssertNotNil(fieldDescriptor);
   GPBGenericValue defaultValue = [fieldDescriptor defaultValue];
   [message setDefaultInt32:defaultValue.valueInt32];
@@ -679,8 +650,7 @@
   TestAllTypes *message = [TestAllTypes message];
   [self setAllFields:message repeatedCount:kGPBDefaultRepeatCount];
   [self modifyRepeatedFields:message];
-  [self assertRepeatedFieldsModified:message
-                       repeatedCount:kGPBDefaultRepeatCount];
+  [self assertRepeatedFieldsModified:message repeatedCount:kGPBDefaultRepeatCount];
 }
 
 - (void)testClear {
@@ -712,19 +682,16 @@
   GPBMessage *message2 = [TestAllExtensions message];
   [message2 addExtension:[UnittestRoot repeatedInt32Extension] value:@1];
 
-  XCTAssertEqual(
-      [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
-      (NSUInteger)1);
+  XCTAssertEqual([[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+                 (NSUInteger)1);
   [message2 clearExtension:[UnittestRoot repeatedInt32Extension]];
-  XCTAssertEqual(
-      [[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
-      (NSUInteger)0);
+  XCTAssertEqual([[message2 getExtension:[UnittestRoot repeatedInt32Extension]] count],
+                 (NSUInteger)0);
 
   // Clearing an unset extension field shouldn't make the target message
   // visible.
   GPBMessage *message3 = [TestAllExtensions message];
-  GPBMessage *extension_msg =
-      [message3 getExtension:[UnittestObjcRoot recursiveExtension]];
+  GPBMessage *extension_msg = [message3 getExtension:[UnittestObjcRoot recursiveExtension]];
   XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
   [extension_msg clearExtension:[UnittestRoot optionalInt32Extension]];
   XCTAssertFalse([message3 hasExtension:[UnittestObjcRoot recursiveExtension]]);
@@ -745,15 +712,11 @@
   // They should auto create something when fetched.
 
   TestAllTypes_OptionalGroup *optionalGroup = [message.optionalGroup retain];
-  TestAllTypes_NestedMessage *optionalNestedMessage =
-      [message.optionalNestedMessage retain];
-  ForeignMessage *optionalForeignMessage =
-      [message.optionalForeignMessage retain];
+  TestAllTypes_NestedMessage *optionalNestedMessage = [message.optionalNestedMessage retain];
+  ForeignMessage *optionalForeignMessage = [message.optionalForeignMessage retain];
   ImportMessage *optionalImportMessage = [message.optionalImportMessage retain];
-  PublicImportMessage *optionalPublicImportMessage =
-      [message.optionalPublicImportMessage retain];
-  TestAllTypes_NestedMessage *optionalLazyMessage =
-      [message.optionalLazyMessage retain];
+  PublicImportMessage *optionalPublicImportMessage = [message.optionalPublicImportMessage retain];
+  TestAllTypes_NestedMessage *optionalLazyMessage = [message.optionalLazyMessage retain];
 
   XCTAssertNotNil(optionalGroup);
   XCTAssertNotNil(optionalNestedMessage);
@@ -779,8 +742,7 @@
   XCTAssertEqual(message.optionalNestedMessage, optionalNestedMessage);
   XCTAssertEqual(message.optionalForeignMessage, optionalForeignMessage);
   XCTAssertEqual(message.optionalImportMessage, optionalImportMessage);
-  XCTAssertEqual(message.optionalPublicImportMessage,
-                 optionalPublicImportMessage);
+  XCTAssertEqual(message.optionalPublicImportMessage, optionalPublicImportMessage);
   XCTAssertEqual(message.optionalLazyMessage, optionalLazyMessage);
 
   // And the default objects for a second message should be distinct (again,
@@ -793,8 +755,7 @@
   XCTAssertNotEqual(message2.optionalNestedMessage, optionalNestedMessage);
   XCTAssertNotEqual(message2.optionalForeignMessage, optionalForeignMessage);
   XCTAssertNotEqual(message2.optionalImportMessage, optionalImportMessage);
-  XCTAssertNotEqual(message2.optionalPublicImportMessage,
-                    optionalPublicImportMessage);
+  XCTAssertNotEqual(message2.optionalPublicImportMessage, optionalPublicImportMessage);
   XCTAssertNotEqual(message2.optionalLazyMessage, optionalLazyMessage);
 
   // Setting the values to nil will clear the has flag, and on next access you
@@ -819,8 +780,7 @@
   XCTAssertNotEqual(message.optionalNestedMessage, optionalNestedMessage);
   XCTAssertNotEqual(message.optionalForeignMessage, optionalForeignMessage);
   XCTAssertNotEqual(message.optionalImportMessage, optionalImportMessage);
-  XCTAssertNotEqual(message.optionalPublicImportMessage,
-                    optionalPublicImportMessage);
+  XCTAssertNotEqual(message.optionalPublicImportMessage, optionalPublicImportMessage);
   XCTAssertNotEqual(message.optionalLazyMessage, optionalLazyMessage);
 
   [optionalGroup release];
@@ -853,8 +813,7 @@
   XCTAssertFalse([message2 hasOptionalNestedMessage]);
 
   // Intentionally doing a pointer comparison.
-  XCTAssertNotEqual(message.optionalNestedMessage,
-                    message2.optionalNestedMessage);
+  XCTAssertNotEqual(message.optionalNestedMessage, message2.optionalNestedMessage);
 }
 
 - (void)testClearAutocreatedSubmessage {
@@ -880,10 +839,9 @@
   ForeignMessage *subMessage;
   @autoreleasepool {
     TestAllTypes *message2 = [TestAllTypes message];
-    subMessage = message2.optionalForeignMessage; // Autocreated
+    subMessage = message2.optionalForeignMessage;  // Autocreated
     message.optionalForeignMessage = subMessage;
-    XCTAssertTrue(GPBWasMessageAutocreatedBy(message.optionalForeignMessage,
-                                             message2));
+    XCTAssertTrue(GPBWasMessageAutocreatedBy(message.optionalForeignMessage, message2));
   }
 
   // Should be the same object, and should still be live.
@@ -1019,8 +977,7 @@
   // Setting autocreated submessage to another value should cause the old one to
   // lose its creator.
   TestAllTypes *message = [TestAllTypes message];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [message.optionalNestedMessage retain];
+  TestAllTypes_NestedMessage *nestedMessage = [message.optionalNestedMessage retain];
 
   message.optionalNestedMessage = [TestAllTypes_NestedMessage message];
   XCTAssertTrue([message hasOptionalNestedMessage]);
@@ -1039,8 +996,7 @@
   XCTAssertNil(message.optionalNestedMessage.unknownFields);
   XCTAssertFalse([message hasOptionalNestedMessage]);
 
-  GPBUnknownFieldSet *unknownFields =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet *unknownFields = [[[GPBUnknownFieldSet alloc] init] autorelease];
   message.optionalNestedMessage.unknownFields = unknownFields;
   XCTAssertTrue([message hasOptionalNestedMessage]);
 
@@ -1089,10 +1045,8 @@
 
 - (void)testDefaultingArrays {
   // Basic tests for default creation of arrays in a message.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
-  TestRecursiveMessageWithRepeatedField *message2 =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message2 = [TestRecursiveMessageWithRepeatedField message];
 
   // Simply accessing the array should not make any fields visible.
   XCTAssertNotNil(message.a.a.iArray);
@@ -1159,11 +1113,9 @@
   XCTAssertNotNil(message.repeatedStringArray);
   TestAllTypes *message4 = [[message3 copy] autorelease];
   XCTAssertNotEqual(message3.repeatedInt32Array, message4.repeatedInt32Array);
-  XCTAssertEqualObjects(message3.repeatedInt32Array,
-                        message4.repeatedInt32Array);
+  XCTAssertEqualObjects(message3.repeatedInt32Array, message4.repeatedInt32Array);
   XCTAssertNotEqual(message3.repeatedStringArray, message4.repeatedStringArray);
-  XCTAssertEqualObjects(message3.repeatedStringArray,
-                        message4.repeatedStringArray);
+  XCTAssertEqualObjects(message3.repeatedStringArray, message4.repeatedStringArray);
 }
 
 - (void)testAutocreatedArrayRetain {
@@ -1176,18 +1128,13 @@
     message.repeatedStringArray = message2.repeatedStringArray;
     // Pointer conparision
     XCTAssertEqual(message.repeatedInt32Array->_autocreator, message2);
-    XCTAssertTrue([message.repeatedStringArray
-        isKindOfClass:[GPBAutocreatedArray class]]);
-    XCTAssertEqual(
-        ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator,
-        message2);
+    XCTAssertTrue([message.repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+    XCTAssertEqual(((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator, message2);
   }
 
   XCTAssertNil(message.repeatedInt32Array->_autocreator);
-  XCTAssertTrue(
-      [message.repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
-  XCTAssertNil(
-      ((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator);
+  XCTAssertTrue([message.repeatedStringArray isKindOfClass:[GPBAutocreatedArray class]]);
+  XCTAssertNil(((GPBAutocreatedArray *)message.repeatedStringArray)->_autocreator);
 }
 
 - (void)testSetNilAutocreatedArray {
@@ -1245,8 +1192,7 @@
     XCTAssertNotNil(message.a);
     XCTAssertNotNil(message.a.strArray);
     XCTAssertFalse([message hasA]);
-    GPBAutocreatedArray *strArray =
-        (GPBAutocreatedArray *)[message.a.strArray retain];
+    GPBAutocreatedArray *strArray = (GPBAutocreatedArray *)[message.a.strArray retain];
     XCTAssertTrue([strArray isKindOfClass:[GPBAutocreatedArray class]]);
     XCTAssertEqual(strArray->_autocreator, message.a);  // Pointer comparison
     message.a.strArray = [NSMutableArray arrayWithObject:@"foo"];
@@ -1286,8 +1232,7 @@
 - (void)testAutocreatedArrayRemoveAllValues {
   // Calling removeAllValues on autocreated array should not cause it to be
   // visible.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
   [message.a.iArray removeAll];
   XCTAssertFalse([message hasA]);
   [message.a.strArray removeAllObjects];
@@ -1296,10 +1241,8 @@
 
 - (void)testDefaultingMaps {
   // Basic tests for default creation of maps in a message.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
-  TestRecursiveMessageWithRepeatedField *message2 =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message2 = [TestRecursiveMessageWithRepeatedField message];
 
   // Simply accessing the map should not make any fields visible.
   XCTAssertNotNil(message.a.a.iToI);
@@ -1349,28 +1292,23 @@
 
 - (void)testAutocreatedMapCopy {
   // Copy should not copy autocreated maps.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
   XCTAssertNotNil(message.strToStr);
   XCTAssertNotNil(message.iToI);
-  TestRecursiveMessageWithRepeatedField *message2 =
-      [[message copy] autorelease];
+  TestRecursiveMessageWithRepeatedField *message2 = [[message copy] autorelease];
   // Pointer conparisions.
   XCTAssertNotEqual(message.strToStr, message2.strToStr);
   XCTAssertNotEqual(message.iToI, message2.iToI);
 
   // Mutable copy should copy empty arrays that were explicitly set (end up
   // with different objects that are equal).
-  TestRecursiveMessageWithRepeatedField *message3 =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message3 = [TestRecursiveMessageWithRepeatedField message];
   message3.iToI = [[[GPBInt32Int32Dictionary alloc] init] autorelease];
   [message3.iToI setInt32:10 forKey:20];
-  message3.strToStr =
-      [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"123"];
+  message3.strToStr = [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"123"];
   XCTAssertNotNil(message.iToI);
   XCTAssertNotNil(message.iToI);
-  TestRecursiveMessageWithRepeatedField *message4 =
-      [[message3 copy] autorelease];
+  TestRecursiveMessageWithRepeatedField *message4 = [[message3 copy] autorelease];
   XCTAssertNotEqual(message3.iToI, message4.iToI);
   XCTAssertEqualObjects(message3.iToI, message4.iToI);
   XCTAssertNotEqual(message3.strToStr, message4.strToStr);
@@ -1379,8 +1317,7 @@
 
 - (void)testAutocreatedMapRetain {
   // Should be able to retain autocreated map while the creator is dealloced.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
 
   @autoreleasepool {
     TestRecursiveMessageWithRepeatedField *message2 =
@@ -1389,27 +1326,20 @@
     message.strToStr = message2.strToStr;
     // Pointer conparision
     XCTAssertEqual(message.iToI->_autocreator, message2);
-    XCTAssertTrue([message.strToStr
-        isKindOfClass:[GPBAutocreatedDictionary class]]);
-    XCTAssertEqual(
-        ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator,
-        message2);
+    XCTAssertTrue([message.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
+    XCTAssertEqual(((GPBAutocreatedDictionary *)message.strToStr)->_autocreator, message2);
   }
 
   XCTAssertNil(message.iToI->_autocreator);
-  XCTAssertTrue(
-      [message.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
-  XCTAssertNil(
-      ((GPBAutocreatedDictionary *)message.strToStr)->_autocreator);
+  XCTAssertTrue([message.strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
+  XCTAssertNil(((GPBAutocreatedDictionary *)message.strToStr)->_autocreator);
 }
 
 - (void)testSetNilAutocreatedMap {
   // Setting map to nil should cause it to lose its delegate.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
   GPBInt32Int32Dictionary *iToI = [message.iToI retain];
-  GPBAutocreatedDictionary *strToStr =
-      (GPBAutocreatedDictionary *)[message.strToStr retain];
+  GPBAutocreatedDictionary *strToStr = (GPBAutocreatedDictionary *)[message.strToStr retain];
   XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
   XCTAssertEqual(iToI->_autocreator, message);
   XCTAssertEqual(strToStr->_autocreator, message);
@@ -1426,15 +1356,13 @@
   // an autocreated one or a straight NSDictionary.
 
   // The real test here is that nothing crashes while doing the work.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
   message.strToStr[@"foo"] = @"bar";
   XCTAssertEqual(message.strToStr_Count, (NSUInteger)1);
   message.strToStr =
       [NSMutableDictionary dictionaryWithObjectsAndKeys:@"bar", @"key1", @"baz", @"key2", nil];
   XCTAssertEqual(message.strToStr_Count, (NSUInteger)2);
-  message.strToStr =
-      [NSMutableDictionary dictionaryWithObject:@"baz" forKey:@"mumble"];
+  message.strToStr = [NSMutableDictionary dictionaryWithObject:@"baz" forKey:@"mumble"];
   XCTAssertEqual(message.strToStr_Count, (NSUInteger)1);
 }
 
@@ -1463,12 +1391,10 @@
     XCTAssertNotNil(message.a);
     XCTAssertNotNil(message.a.strToStr);
     XCTAssertFalse([message hasA]);
-    GPBAutocreatedDictionary *strToStr =
-        (GPBAutocreatedDictionary *)[message.a.strToStr retain];
+    GPBAutocreatedDictionary *strToStr = (GPBAutocreatedDictionary *)[message.a.strToStr retain];
     XCTAssertTrue([strToStr isKindOfClass:[GPBAutocreatedDictionary class]]);
     XCTAssertEqual(strToStr->_autocreator, message.a);  // Pointer comparison
-    message.a.strToStr =
-        [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"def"];
+    message.a.strToStr = [NSMutableDictionary dictionaryWithObject:@"abc" forKey:@"def"];
     XCTAssertTrue([message hasA]);
     XCTAssertNotEqual(message.a.strToStr, strToStr);  // Pointer comparison
     XCTAssertNil(strToStr->_autocreator);
@@ -1504,8 +1430,7 @@
 
 - (void)testAutocreatedMapRemoveAllValues {
   // Calling removeAll on autocreated map should not cause it to be visible.
-  TestRecursiveMessageWithRepeatedField *message =
-      [TestRecursiveMessageWithRepeatedField message];
+  TestRecursiveMessageWithRepeatedField *message = [TestRecursiveMessageWithRepeatedField message];
   [message.a.iToI removeAll];
   XCTAssertFalse([message hasA]);
   [message.a.strToStr removeAllObjects];
@@ -1522,8 +1447,7 @@
   TestAllExtensions *message = [TestAllExtensions message];
   [self setAllExtensions:message repeatedCount:kGPBDefaultRepeatCount];
   [self modifyRepeatedExtensions:message];
-  [self assertRepeatedExtensionsModified:message
-                           repeatedCount:kGPBDefaultRepeatCount];
+  [self assertRepeatedExtensionsModified:message repeatedCount:kGPBDefaultRepeatCount];
 }
 
 - (void)testExtensionDefaults {
@@ -1557,6 +1481,82 @@
   XCTAssertEqualObjects(message, message2);
 }
 
+- (void)testClosedEnumsInExtensions {
+  // Only unknown values.
+
+  NSData *data =
+      DataFromCStr("\xA8\x01\x0A"      // optional_nested_enum_extension set to 10
+                   "\x98\x03\x0B"      // repeated_nested_enum_extension set to 11
+                   "\xA2\x03\x01\x0C"  // repeated_foreign_enum_extension set to 12 (packed)
+      );
+  NSError *error = nil;
+
+  TestAllExtensions *msg = [TestAllExtensions parseFromData:data
+                                          extensionRegistry:[self extensionRegistry]
+                                                      error:&error];
+  XCTAssertNil(error);
+
+  XCTAssertFalse([msg hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+  XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedNestedEnumExtension]]);
+  XCTAssertFalse([msg hasExtension:[UnittestRoot repeatedForeignEnumExtension]]);
+
+  GPBUnknownFieldSet *unknownFields = msg.unknownFields;
+  GPBUnknownField *field =
+      [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber];
+  XCTAssertNotNil(field);
+  XCTAssertEqual(field.varintList.count, 1);
+  XCTAssertEqual([field.varintList valueAtIndex:0], 10);
+  field = [unknownFields getField:[UnittestRoot repeatedNestedEnumExtension].fieldNumber];
+  XCTAssertNotNil(field);
+  XCTAssertEqual(field.varintList.count, 1);
+  XCTAssertEqual([field.varintList valueAtIndex:0], 11);
+  field = [unknownFields getField:[UnittestRoot repeatedForeignEnumExtension].fieldNumber];
+  XCTAssertNotNil(field);
+  XCTAssertEqual(field.varintList.count, 1);
+  XCTAssertEqual([field.varintList valueAtIndex:0], 12);
+
+  // Unknown and known, the known come though an unknown go to unknown fields.
+
+  data = DataFromCStr(
+      "\xA8\x01\x01"              // optional_nested_enum_extension set to 1
+      "\xA8\x01\x0A"              // optional_nested_enum_extension set to 10
+      "\xA8\x01\x02"              // optional_nested_enum_extension set to 2
+      "\x98\x03\x02"              // repeated_nested_enum_extension set to 2
+      "\x98\x03\x0B"              // repeated_nested_enum_extension set to 11
+      "\x98\x03\x03"              // repeated_nested_enum_extension set to 3
+      "\xA2\x03\x03\x04\x0C\x06"  // repeated_foreign_enum_extension set to 4, 12, 6 (packed)
+  );
+  error = nil;
+
+  msg = [TestAllExtensions parseFromData:data
+                       extensionRegistry:[self extensionRegistry]
+                                   error:&error];
+  XCTAssertNil(error);
+
+  XCTAssertTrue([msg hasExtension:[UnittestRoot optionalNestedEnumExtension]]);
+  XCTAssertEqualObjects([msg getExtension:[UnittestRoot optionalNestedEnumExtension]], @2);
+  XCTAssertTrue([msg hasExtension:[UnittestRoot repeatedNestedEnumExtension]]);
+  id expected = @[ @2, @3 ];
+  XCTAssertEqualObjects([msg getExtension:[UnittestRoot repeatedNestedEnumExtension]], expected);
+  XCTAssertTrue([msg hasExtension:[UnittestRoot repeatedForeignEnumExtension]]);
+  expected = @[ @4, @6 ];
+  XCTAssertEqualObjects([msg getExtension:[UnittestRoot repeatedForeignEnumExtension]], expected);
+
+  unknownFields = msg.unknownFields;
+  field = [unknownFields getField:[UnittestRoot optionalNestedEnumExtension].fieldNumber];
+  XCTAssertNotNil(field);
+  XCTAssertEqual(field.varintList.count, 1);
+  XCTAssertEqual([field.varintList valueAtIndex:0], 10);
+  field = [unknownFields getField:[UnittestRoot repeatedNestedEnumExtension].fieldNumber];
+  XCTAssertNotNil(field);
+  XCTAssertEqual(field.varintList.count, 1);
+  XCTAssertEqual([field.varintList valueAtIndex:0], 11);
+  field = [unknownFields getField:[UnittestRoot repeatedForeignEnumExtension].fieldNumber];
+  XCTAssertNotNil(field);
+  XCTAssertEqual(field.varintList.count, 1);
+  XCTAssertEqual([field.varintList valueAtIndex:0], 12);
+}
+
 - (void)testDefaultingExtensionMessages {
   TestAllExtensions *message = [TestAllExtensions message];
 
@@ -1564,16 +1564,11 @@
 
   XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
   XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
-  XCTAssertFalse([message
-      hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
 
   // They should auto create something when fetched.
 
@@ -1585,8 +1580,8 @@
       [message getExtension:[UnittestRoot optionalForeignMessageExtension]];
   ImportMessage *optionalImportMessage =
       [message getExtension:[UnittestRoot optionalImportMessageExtension]];
-  PublicImportMessage *optionalPublicImportMessage = [message
-      getExtension:[UnittestRoot optionalPublicImportMessageExtension]];
+  PublicImportMessage *optionalPublicImportMessage =
+      [message getExtension:[UnittestRoot optionalPublicImportMessageExtension]];
   TestAllTypes_NestedMessage *optionalLazyMessage =
       [message getExtension:[UnittestRoot optionalLazyMessageExtension]];
 
@@ -1611,23 +1606,17 @@
   // And they set that value back in to the message since the value created was
   // mutable (so a second fetch should give the same object).
 
-  XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
-                 optionalGroup);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
-      optionalNestedMessage);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
-      optionalForeignMessage);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalImportMessageExtension]],
-      optionalImportMessage);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
-      optionalPublicImportMessage);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
-      optionalLazyMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]], optionalGroup);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+                 optionalNestedMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+                 optionalForeignMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalImportMessageExtension]],
+                 optionalImportMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+                 optionalPublicImportMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+                 optionalLazyMessage);
 
   // And the default objects for a second message should be distinct (again,
   // since they are mutable, each needs their own copy).
@@ -1635,70 +1624,47 @@
   TestAllExtensions *message2 = [TestAllExtensions message];
 
   // Intentionally doing a pointer comparison.
-  XCTAssertNotEqual(
-      [message2 getExtension:[UnittestRoot optionalGroupExtension]],
-      optionalGroup);
-  XCTAssertNotEqual(
-      [message2 getExtension:[UnittestRoot optionalNestedMessageExtension]],
-      optionalNestedMessage);
-  XCTAssertNotEqual(
-      [message2 getExtension:[UnittestRoot optionalForeignMessageExtension]],
-      optionalForeignMessage);
-  XCTAssertNotEqual(
-      [message2 getExtension:[UnittestRoot optionalImportMessageExtension]],
-      optionalImportMessage);
-  XCTAssertNotEqual(
-      [message2 getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
-      optionalPublicImportMessage);
-  XCTAssertNotEqual(
-      [message2 getExtension:[UnittestRoot optionalLazyMessageExtension]],
-      optionalLazyMessage);
+  XCTAssertNotEqual([message2 getExtension:[UnittestRoot optionalGroupExtension]], optionalGroup);
+  XCTAssertNotEqual([message2 getExtension:[UnittestRoot optionalNestedMessageExtension]],
+                    optionalNestedMessage);
+  XCTAssertNotEqual([message2 getExtension:[UnittestRoot optionalForeignMessageExtension]],
+                    optionalForeignMessage);
+  XCTAssertNotEqual([message2 getExtension:[UnittestRoot optionalImportMessageExtension]],
+                    optionalImportMessage);
+  XCTAssertNotEqual([message2 getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+                    optionalPublicImportMessage);
+  XCTAssertNotEqual([message2 getExtension:[UnittestRoot optionalLazyMessageExtension]],
+                    optionalLazyMessage);
 
   // Clear values, and on next access you get back new submessages.
 
   [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
   [message setExtension:[UnittestRoot optionalGroupExtension] value:nil];
-  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
-                  value:nil];
-  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
-                  value:nil];
-  [message setExtension:[UnittestRoot optionalImportMessageExtension]
-                  value:nil];
-  [message setExtension:[UnittestRoot optionalPublicImportMessageExtension]
-                  value:nil];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nil];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension] value:nil];
+  [message setExtension:[UnittestRoot optionalImportMessageExtension] value:nil];
+  [message setExtension:[UnittestRoot optionalPublicImportMessageExtension] value:nil];
   [message setExtension:[UnittestRoot optionalLazyMessageExtension] value:nil];
 
   XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
   XCTAssertFalse([message hasExtension:[UnittestRoot optionalGroupExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
-  XCTAssertFalse([message
-      hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
-  XCTAssertFalse(
-      [message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalNestedMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalForeignMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalImportMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalPublicImportMessageExtension]]);
+  XCTAssertFalse([message hasExtension:[UnittestRoot optionalLazyMessageExtension]]);
 
-  XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]],
-                 optionalGroup);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalNestedMessageExtension]],
-      optionalNestedMessage);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalForeignMessageExtension]],
-      optionalForeignMessage);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalImportMessageExtension]],
-      optionalImportMessage);
-  XCTAssertEqual(
-      [message
-          getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
-      optionalPublicImportMessage);
-  XCTAssertEqual(
-      [message getExtension:[UnittestRoot optionalLazyMessageExtension]],
-      optionalLazyMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalGroupExtension]], optionalGroup);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalNestedMessageExtension]],
+                 optionalNestedMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalForeignMessageExtension]],
+                 optionalForeignMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalImportMessageExtension]],
+                 optionalImportMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalPublicImportMessageExtension]],
+                 optionalPublicImportMessage);
+  XCTAssertEqual([message getExtension:[UnittestRoot optionalLazyMessageExtension]],
+                 optionalLazyMessage);
 }
 
 - (void)testMultiplePointersToAutocreatedExtension {
@@ -1708,13 +1674,11 @@
   TestAllExtensions *message2 = [TestAllExtensions message];
   GPBExtensionDescriptor *extension = [UnittestRoot optionalGroupExtension];
   [message setExtension:extension value:[message2 getExtension:extension]];
-  XCTAssertEqual([message getExtension:extension],
-                 [message2 getExtension:extension]);
+  XCTAssertEqual([message getExtension:extension], [message2 getExtension:extension]);
   XCTAssertFalse([message2 hasExtension:extension]);
   XCTAssertTrue([message hasExtension:extension]);
 
-  TestAllTypes_OptionalGroup *extensionValue =
-      [message2 getExtension:extension];
+  TestAllTypes_OptionalGroup *extensionValue = [message2 getExtension:extension];
   extensionValue.a = 1;
   XCTAssertTrue([message2 hasExtension:extension]);
   XCTAssertTrue([message hasExtension:extension]);
@@ -1723,12 +1687,10 @@
 - (void)testCopyWithAutocreatedExtension {
   // Mutable copy shouldn't copy autocreated extensions.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionDescriptor *optionalGroupExtension =
-      [UnittestRoot optionalGroupExtension];
+  GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension];
   GPBExtensionDescriptor *optionalNestedMessageExtesion =
       [UnittestRoot optionalNestedMessageExtension];
-  TestAllTypes_OptionalGroup *optionalGroup =
-      [message getExtension:optionalGroupExtension];
+  TestAllTypes_OptionalGroup *optionalGroup = [message getExtension:optionalGroupExtension];
   optionalGroup.a = 42;
   XCTAssertNotNil(optionalGroup);
   XCTAssertNotNil([message getExtension:optionalNestedMessageExtesion]);
@@ -1755,13 +1717,11 @@
 - (void)testClearMessageAutocreatedExtension {
   // Call clear should cause it to recreate its autocreated extensions.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionDescriptor *optionalGroupExtension =
-      [UnittestRoot optionalGroupExtension];
+  GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension];
   TestAllTypes_OptionalGroup *optionalGroup =
       [[message getExtension:optionalGroupExtension] retain];
   [message clear];
-  TestAllTypes_OptionalGroup *optionalGroupNew =
-      [message getExtension:optionalGroupExtension];
+  TestAllTypes_OptionalGroup *optionalGroupNew = [message getExtension:optionalGroupExtension];
 
   // Intentionally doing a pointer comparison.
   XCTAssertNotEqual(optionalGroup, optionalGroupNew);
@@ -1772,42 +1732,37 @@
   // Should be able to retain autocreated extension while the creator is
   // dealloced.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionDescriptor *optionalGroupExtension =
-      [UnittestRoot optionalGroupExtension];
+  GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension];
 
   @autoreleasepool {
     TestAllExtensions *message2 = [TestAllExtensions message];
     [message setExtension:optionalGroupExtension
                     value:[message2 getExtension:optionalGroupExtension]];
-    XCTAssertTrue(GPBWasMessageAutocreatedBy(
-        [message getExtension:optionalGroupExtension], message2));
+    XCTAssertTrue(
+        GPBWasMessageAutocreatedBy([message getExtension:optionalGroupExtension], message2));
   }
 
-  XCTAssertFalse(GPBWasMessageAutocreatedBy(
-      [message getExtension:optionalGroupExtension], message));
+  XCTAssertFalse(
+      GPBWasMessageAutocreatedBy([message getExtension:optionalGroupExtension], message));
 }
 
 - (void)testClearAutocreatedExtension {
   // Clearing autocreated extension should NOT cause it to lose its creator.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionDescriptor *optionalGroupExtension =
-      [UnittestRoot optionalGroupExtension];
+  GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension];
   TestAllTypes_OptionalGroup *optionalGroup =
       [[message getExtension:optionalGroupExtension] retain];
   [message clearExtension:optionalGroupExtension];
-  TestAllTypes_OptionalGroup *optionalGroupNew =
-      [message getExtension:optionalGroupExtension];
+  TestAllTypes_OptionalGroup *optionalGroupNew = [message getExtension:optionalGroupExtension];
   XCTAssertEqual(optionalGroup, optionalGroupNew);
   XCTAssertFalse([message hasExtension:optionalGroupExtension]);
   [optionalGroup release];
 
   // Clearing autocreated extension should not cause its creator to become
   // visible
-  GPBExtensionDescriptor *recursiveExtension =
-      [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension = [UnittestObjcRoot recursiveExtension];
   TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
-  TestAllExtensions *message_lvl3 =
-      [message_lvl2 getExtension:recursiveExtension];
+  TestAllExtensions *message_lvl3 = [message_lvl2 getExtension:recursiveExtension];
   [message_lvl3 clearExtension:recursiveExtension];
   XCTAssertFalse([message hasExtension:recursiveExtension]);
 }
@@ -1816,13 +1771,10 @@
   // Setting an extension should cause the extension to appear to its creator.
   // Test this several levels deep.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionDescriptor *recursiveExtension =
-      [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension = [UnittestObjcRoot recursiveExtension];
   TestAllExtensions *message_lvl2 = [message getExtension:recursiveExtension];
-  TestAllExtensions *message_lvl3 =
-      [message_lvl2 getExtension:recursiveExtension];
-  TestAllExtensions *message_lvl4 =
-      [message_lvl3 getExtension:recursiveExtension];
+  TestAllExtensions *message_lvl3 = [message_lvl2 getExtension:recursiveExtension];
+  TestAllExtensions *message_lvl4 = [message_lvl3 getExtension:recursiveExtension];
   XCTAssertFalse([message hasExtension:recursiveExtension]);
   XCTAssertFalse([message_lvl2 hasExtension:recursiveExtension]);
   XCTAssertFalse([message_lvl3 hasExtension:recursiveExtension]);
@@ -1840,18 +1792,15 @@
 - (void)testSetAutocreatedExtensionToSelf {
   // Setting extension to itself should cause it to become visible.
   TestAllExtensions *message = [TestAllExtensions message];
-  GPBExtensionDescriptor *optionalGroupExtension =
-      [UnittestRoot optionalGroupExtension];
+  GPBExtensionDescriptor *optionalGroupExtension = [UnittestRoot optionalGroupExtension];
   XCTAssertNotNil([message getExtension:optionalGroupExtension]);
   XCTAssertFalse([message hasExtension:optionalGroupExtension]);
-  [message setExtension:optionalGroupExtension
-                  value:[message getExtension:optionalGroupExtension]];
+  [message setExtension:optionalGroupExtension value:[message getExtension:optionalGroupExtension]];
   XCTAssertTrue([message hasExtension:optionalGroupExtension]);
 }
 
 - (void)testAutocreatedExtensionMemoryLeaks {
-  GPBExtensionDescriptor *recursiveExtension =
-      [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension = [UnittestObjcRoot recursiveExtension];
 
   // Test for memory leaks with autocreated extensions.
   TestAllExtensions *message;
@@ -1863,8 +1812,7 @@
     message_lvl2 = [[message getExtension:recursiveExtension] retain];
     message_lvl3 = [[message_lvl2 getExtension:recursiveExtension] retain];
     message_lvl4 = [[message_lvl3 getExtension:recursiveExtension] retain];
-    [message_lvl2 setExtension:[UnittestRoot optionalInt32Extension]
-                         value:@(1)];
+    [message_lvl2 setExtension:[UnittestRoot optionalInt32Extension] value:@(1)];
   }
 
   XCTAssertEqual(message.retainCount, (NSUInteger)1);
@@ -1884,8 +1832,7 @@
 }
 
 - (void)testSetExtensionWithAutocreatedValue {
-  GPBExtensionDescriptor *recursiveExtension =
-      [UnittestObjcRoot recursiveExtension];
+  GPBExtensionDescriptor *recursiveExtension = [UnittestObjcRoot recursiveExtension];
 
   TestAllExtensions *message;
   @autoreleasepool {
@@ -1895,8 +1842,7 @@
 
   // This statements checks that the extension value isn't accidentally
   // dealloced when removing it from the autocreated map.
-  [message setExtension:recursiveExtension
-                  value:[message getExtension:recursiveExtension]];
+  [message setExtension:recursiveExtension value:[message getExtension:recursiveExtension]];
   XCTAssertTrue([message hasExtension:recursiveExtension]);
   [message release];
 }
@@ -1909,26 +1855,22 @@
 }
 
 - (void)testGenerateAndParseUnknownMessage {
-  GPBUnknownFieldSet *unknowns =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet *unknowns = [[[GPBUnknownFieldSet alloc] init] autorelease];
   [unknowns mergeVarintField:123 value:456];
   GPBMessage *message = [GPBMessage message];
   [message setUnknownFields:unknowns];
   NSData *data = [message data];
-  GPBMessage *message2 =
-      [GPBMessage parseFromData:data extensionRegistry:nil error:NULL];
+  GPBMessage *message2 = [GPBMessage parseFromData:data extensionRegistry:nil error:NULL];
   XCTAssertEqualObjects(message, message2);
 }
 
 - (void)testDelimitedWriteAndParseMultipleMessages {
-  GPBUnknownFieldSet *unknowns1 =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet *unknowns1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   [unknowns1 mergeVarintField:123 value:456];
   GPBMessage *message1 = [GPBMessage message];
   [message1 setUnknownFields:unknowns1];
 
-  GPBUnknownFieldSet *unknowns2 =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet *unknowns2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   [unknowns2 mergeVarintField:789 value:987];
   [unknowns2 mergeVarintField:654 value:321];
   GPBMessage *message2 = [GPBMessage message];
@@ -1937,8 +1879,7 @@
   NSMutableData *delimitedData = [NSMutableData data];
   [delimitedData appendData:[message1 delimitedData]];
   [delimitedData appendData:[message2 delimitedData]];
-  GPBCodedInputStream *input =
-      [GPBCodedInputStream streamWithData:delimitedData];
+  GPBCodedInputStream *input = [GPBCodedInputStream streamWithData:delimitedData];
   GPBMessage *message3 = [GPBMessage parseDelimitedFromCodedInputStream:input
                                                       extensionRegistry:nil
                                                                   error:NULL];
@@ -1970,8 +1911,7 @@
 }
 
 - (void)testEnumDescriptorFromExtensionDescriptor {
-  GPBExtensionDescriptor *extDescriptor =
-      [UnittestRoot optionalForeignEnumExtension];
+  GPBExtensionDescriptor *extDescriptor = [UnittestRoot optionalForeignEnumExtension];
   XCTAssertEqual(extDescriptor.dataType, GPBDataTypeEnum);
   GPBEnumDescriptor *enumDescriptor = extDescriptor.enumDescriptor;
   GPBEnumDescriptor *expectedDescriptor = ForeignEnum_EnumDescriptor();
@@ -1979,8 +1919,8 @@
 }
 
 - (void)testPropertyNaming {
-  // objectivec_helpers.cc has some special handing to get proper all caps
-  // for a few cases to meet objc developer expectations.
+  // names.cc has some special handing to get proper all caps for a few cases to
+  // meet objc developer expectations.
   //
   // This "test" confirms that the expected names are generated, otherwise the
   // test itself will fail to compile.
@@ -1997,7 +1937,7 @@
 }
 
 - (void)testEnumNaming {
-  // objectivec_helpers.cc has some interesting cases to deal with in
+  // names.cc has some interesting cases to deal with in
   // EnumValueName/EnumValueShortName.  Confirm that things generated as
   // expected.
 
@@ -2078,8 +2018,7 @@
 
   // Repeated field (shouldn't ever be an issue since developer has to use the
   // right GPBArray methods themselves).
-  msg.mumbleArray = [GPBEnumArray
-      arrayWithValidationFunction:EnumTestMsg_MyEnum_IsValidValue];
+  msg.mumbleArray = [GPBEnumArray arrayWithValidationFunction:EnumTestMsg_MyEnum_IsValidValue];
   [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Zero];
   [msg.mumbleArray addValue:EnumTestMsg_MyEnum_One];
   [msg.mumbleArray addValue:EnumTestMsg_MyEnum_Two];
@@ -2095,20 +2034,16 @@
   XCTAssertNotNil(data);
   msgPrime = [EnumTestMsg parseFromData:data error:NULL];
   XCTAssertEqualObjects(msgPrime, msg);
-  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0],
-                 EnumTestMsg_MyEnum_Zero);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:0], EnumTestMsg_MyEnum_Zero);
   XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:1], EnumTestMsg_MyEnum_One);
   XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:2], EnumTestMsg_MyEnum_Two);
-  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:3],
-                 EnumTestMsg_MyEnum_NegOne);
-  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4],
-                 EnumTestMsg_MyEnum_NegTwo);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:3], EnumTestMsg_MyEnum_NegOne);
+  XCTAssertEqual([msgPrime.mumbleArray valueAtIndex:4], EnumTestMsg_MyEnum_NegTwo);
 }
 
 - (void)testReservedWordNaming {
-  // objectivec_helpers.cc has some special handing to make sure that
-  // some "reserved" objc names get renamed in a way so they
-  // don't conflict.
+  // names.cc has some special handing to make sure that some "reserved" objc
+  // names get renamed in a way so they don't conflict.
   //
   // This "test" confirms that the expected names are generated,
   // otherwise the test itself will fail to compile.
@@ -2200,12 +2135,12 @@
   msg1.boolField32 = YES;
   msg2.boolField32 = YES;
 
-  XCTAssertTrue(msg1 != msg2); // Different pointers.
+  XCTAssertTrue(msg1 != msg2);  // Different pointers.
   XCTAssertEqual([msg1 hash], [msg2 hash]);
   XCTAssertEqualObjects(msg1, msg2);
 
   BoolOnlyMessage *msg1Prime = [[msg1 copy] autorelease];
-  XCTAssertTrue(msg1Prime != msg1); // Different pointers.
+  XCTAssertTrue(msg1Prime != msg1);  // Different pointers.
   XCTAssertEqual([msg1 hash], [msg1Prime hash]);
   XCTAssertEqualObjects(msg1, msg1Prime);
 
@@ -2252,24 +2187,26 @@
   TestMessageOfMaps *msg2 = [[msg copy] autorelease];
   XCTAssertNotNil(msg2);
   XCTAssertEqualObjects(msg2, msg);
-  XCTAssertTrue(msg2 != msg);  // ptr compare
-  XCTAssertTrue(msg.strToStr != msg2.strToStr);  // ptr compare
-  XCTAssertTrue(msg.intToStr != msg2.intToStr);  // ptr compare
-  XCTAssertTrue(msg.intToInt != msg2.intToInt);  // ptr compare
-  XCTAssertTrue(msg.strToBool != msg2.strToBool);  // ptr compare
-  XCTAssertTrue(msg.boolToStr != msg2.boolToStr);  // ptr compare
+  XCTAssertTrue(msg2 != msg);                        // ptr compare
+  XCTAssertTrue(msg.strToStr != msg2.strToStr);      // ptr compare
+  XCTAssertTrue(msg.intToStr != msg2.intToStr);      // ptr compare
+  XCTAssertTrue(msg.intToInt != msg2.intToInt);      // ptr compare
+  XCTAssertTrue(msg.strToBool != msg2.strToBool);    // ptr compare
+  XCTAssertTrue(msg.boolToStr != msg2.boolToStr);    // ptr compare
   XCTAssertTrue(msg.boolToBool != msg2.boolToBool);  // ptr compare
-  XCTAssertTrue(msg.intToBool != msg2.intToBool);  // ptr compare
-  XCTAssertTrue(msg.boolToInt != msg2.boolToInt);  // ptr compare
-  XCTAssertTrue(msg.strToMsg != msg2.strToMsg);  // ptr compare
-  XCTAssertTrue(msg.intToMsg != msg2.intToMsg);  // ptr compare
-  XCTAssertTrue(msg.boolToMsg != msg2.boolToMsg);  // ptr compare
+  XCTAssertTrue(msg.intToBool != msg2.intToBool);    // ptr compare
+  XCTAssertTrue(msg.boolToInt != msg2.boolToInt);    // ptr compare
+  XCTAssertTrue(msg.strToMsg != msg2.strToMsg);      // ptr compare
+  XCTAssertTrue(msg.intToMsg != msg2.intToMsg);      // ptr compare
+  XCTAssertTrue(msg.boolToMsg != msg2.boolToMsg);    // ptr compare
 
   XCTAssertTrue(msg.strToMsg[@"baz"] != msg2.strToMsg[@"baz"]);  // ptr compare
   XCTAssertEqualObjects(msg.strToMsg[@"baz"], msg2.strToMsg[@"baz"]);
-  XCTAssertTrue([msg.intToMsg objectForKey:222] != [msg2.intToMsg objectForKey:222]);  // ptr compare
+  XCTAssertTrue([msg.intToMsg objectForKey:222] !=
+                [msg2.intToMsg objectForKey:222]);  // ptr compare
   XCTAssertEqualObjects([msg.intToMsg objectForKey:222], [msg2.intToMsg objectForKey:222]);
-  XCTAssertTrue([msg.boolToMsg objectForKey:YES] != [msg2.boolToMsg objectForKey:YES]);  // ptr compare
+  XCTAssertTrue([msg.boolToMsg objectForKey:YES] !=
+                [msg2.boolToMsg objectForKey:YES]);  // ptr compare
   XCTAssertEqualObjects([msg.boolToMsg objectForKey:YES], [msg2.boolToMsg objectForKey:YES]);
 }
 
diff --git a/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm b/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
index fb67495..a89bb47 100644
--- a/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
+++ b/objectivec/Tests/GPBObjectiveCPlusPlusTest.mm
@@ -28,10 +28,8 @@
 // (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 "GPBTestUtilities.h"
 
-
 //
 // This is just a compile test (here to make sure things never regress).
 //
@@ -43,20 +41,19 @@
 // The "well know types" should have cross file enums needing imports.
 #import "GPBProtocolBuffers.h"
 // Some of the tests explicitly use cross file enums also.
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestImport.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestImport.pbobjc.h"
 
 // Sanity check the conditions of the test within the Xcode project.
 #if !__cplusplus
-  #error This isn't compiled as Objective C++?
+#error This isn't compiled as Objective C++?
 #elif __cplusplus >= 201103L
-  // If this trips, it means the Xcode default might have change (or someone
-  // edited the testing project) and it might be time to revisit the GPB_ENUM
-  // define in GPBBootstrap.h.
-  #warning Did the Xcode default for C++ spec change?
+// If this trips, it means the Xcode default might have change (or someone
+// edited the testing project) and it might be time to revisit the GPB_ENUM
+// define in GPBBootstrap.h.
+#warning Did the Xcode default for C++ spec change?
 #endif
 
-
 // Dummy XCTest.
 @interface GPBObjectiveCPlusPlusTests : GPBTestCase
 @end
diff --git a/objectivec/Tests/GPBPerfTests.m b/objectivec/Tests/GPBPerfTests.m
index 8dd0ffc..7c1cbc5 100644
--- a/objectivec/Tests/GPBPerfTests.m
+++ b/objectivec/Tests/GPBPerfTests.m
@@ -29,9 +29,9 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestImport.pbobjc.h"
-#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestImport.pbobjc.h"
+#import "objectivec/Tests/UnittestObjc.pbobjc.h"
 
 //
 // This file really just uses the unittests framework as a testbed to
@@ -69,9 +69,9 @@
   // lock across threads when parsing different instances. The Serial version of the test should run
   // around ~2 times slower than the Parallel version since it's parsing the protos in the same
   // thread.
-  TestAllTypes *allTypesMessage = [TestAllTypes message];
+  TestAllTypes* allTypesMessage = [TestAllTypes message];
   [self setAllFields:allTypesMessage repeatedCount:2];
-  NSData *allTypesData = allTypesMessage.data;
+  NSData* allTypesData = allTypesMessage.data;
 
   [self measureBlock:^{
     for (int i = 0; i < 500; ++i) {
@@ -86,9 +86,9 @@
   // not lock across threads when parsing different instances. The Serial version of the test should
   // run around ~2 times slower than the Parallel version since it's parsing the protos in the same
   // thread.
-  TestAllTypes *allTypesMessage = [TestAllTypes message];
+  TestAllTypes* allTypesMessage = [TestAllTypes message];
   [self setAllFields:allTypesMessage repeatedCount:2];
-  NSData *allTypesData = allTypesMessage.data;
+  NSData* allTypesData = allTypesMessage.data;
 
   dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT);
 
@@ -104,7 +104,9 @@
         [TestAllTypes parseFromData:allTypesData error:NULL];
       });
 
-      dispatch_group_notify(group, concurrentQueue, ^{});
+      dispatch_group_notify(group, concurrentQueue,
+                            ^{
+                            });
 
       dispatch_release(group);
     }
@@ -118,9 +120,9 @@
   // lock across threads when parsing different instances when using extensions. The Serial version
   // of the test should run around ~2 times slower than the Parallel version since it's parsing the
   // protos in the same thread.
-  TestAllExtensions *allExtensionsMessage = [TestAllExtensions message];
+  TestAllExtensions* allExtensionsMessage = [TestAllExtensions message];
   [self setAllExtensions:allExtensionsMessage repeatedCount:2];
-  NSData *allExtensionsData = allExtensionsMessage.data;
+  NSData* allExtensionsData = allExtensionsMessage.data;
 
   [self measureBlock:^{
     for (int i = 0; i < 500; ++i) {
@@ -139,9 +141,9 @@
   // not lock across threads when parsing different instances when using extensions. The Serial
   // version of the test should run around ~2 times slower than the Parallel version since it's
   // parsing the protos in the same thread.
-  TestAllExtensions *allExtensionsMessage = [TestAllExtensions message];
+  TestAllExtensions* allExtensionsMessage = [TestAllExtensions message];
   [self setAllExtensions:allExtensionsMessage repeatedCount:2];
-  NSData *allExtensionsData = allExtensionsMessage.data;
+  NSData* allExtensionsData = allExtensionsMessage.data;
 
   dispatch_queue_t concurrentQueue = dispatch_queue_create("perfQueue", DISPATCH_QUEUE_CONCURRENT);
 
@@ -161,7 +163,9 @@
                                    error:NULL];
       });
 
-      dispatch_group_notify(group, concurrentQueue, ^{});
+      dispatch_group_notify(group, concurrentQueue,
+                            ^{
+                            });
 
       dispatch_release(group);
     }
@@ -177,8 +181,7 @@
       [self setAllExtensions:message repeatedCount:kRepeatedCount];
       NSData* rawBytes = [message data];
       [message release];
-      TestAllExtensions* message2 =
-          [[TestAllExtensions alloc] initWithData:rawBytes error:NULL];
+      TestAllExtensions* message2 = [[TestAllExtensions alloc] initWithData:rawBytes error:NULL];
       [message2 release];
     }
   }];
@@ -204,8 +207,8 @@
       [self setPackedExtensions:message repeatedCount:kRepeatedCount];
       NSData* rawBytes = [message data];
       [message release];
-      TestPackedExtensions* message2 =
-          [[TestPackedExtensions alloc] initWithData:rawBytes error:NULL];
+      TestPackedExtensions* message2 = [[TestPackedExtensions alloc] initWithData:rawBytes
+                                                                            error:NULL];
       [message2 release];
     }
   }];
diff --git a/objectivec/Tests/GPBTestUtilities.h b/objectivec/Tests/GPBTestUtilities.h
index 780184b..bebd557 100644
--- a/objectivec/Tests/GPBTestUtilities.h
+++ b/objectivec/Tests/GPBTestUtilities.h
@@ -48,7 +48,6 @@
 #define GPBARRAYSIZE(a) ((sizeof(a) / sizeof((a[0]))))
 #endif  // GPBARRAYSIZE
 
-
 // The number of repetitions of any repeated objects inside of test messages.
 extern const uint32_t kGPBDefaultRepeatCount;
 
@@ -56,16 +55,11 @@
 
 - (void)setAllFields:(TestAllTypes *)message repeatedCount:(uint32_t)count;
 - (void)clearAllFields:(TestAllTypes *)message;
-- (void)setAllExtensions:(TestAllExtensions *)message
-           repeatedCount:(uint32_t)count;
-- (void)setPackedFields:(TestPackedTypes *)message
-          repeatedCount:(uint32_t)count;
-- (void)setUnpackedFields:(TestUnpackedTypes *)message
-            repeatedCount:(uint32_t)count;
-- (void)setPackedExtensions:(TestPackedExtensions *)message
-              repeatedCount:(uint32_t)count;
-- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message
-              repeatedCount:(uint32_t)count;
+- (void)setAllExtensions:(TestAllExtensions *)message repeatedCount:(uint32_t)count;
+- (void)setPackedFields:(TestPackedTypes *)message repeatedCount:(uint32_t)count;
+- (void)setUnpackedFields:(TestUnpackedTypes *)message repeatedCount:(uint32_t)count;
+- (void)setPackedExtensions:(TestPackedExtensions *)message repeatedCount:(uint32_t)count;
+- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message repeatedCount:(uint32_t)count;
 - (void)setAllMapFields:(TestMap *)message numEntries:(uint32_t)count;
 
 - (TestAllTypes *)allSetRepeatedCount:(uint32_t)count;
@@ -73,20 +67,14 @@
 - (TestPackedTypes *)packedSetRepeatedCount:(uint32_t)count;
 - (TestPackedExtensions *)packedExtensionsSetRepeatedCount:(uint32_t)count;
 
-- (void)assertAllFieldsSet:(TestAllTypes *)message
-             repeatedCount:(uint32_t)count;
-- (void)assertAllExtensionsSet:(TestAllExtensions *)message
-                 repeatedCount:(uint32_t)count;
-- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
-                       repeatedCount:(uint32_t)count;
-- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message
-                           repeatedCount:(uint32_t)count;
+- (void)assertAllFieldsSet:(TestAllTypes *)message repeatedCount:(uint32_t)count;
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message repeatedCount:(uint32_t)count;
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message repeatedCount:(uint32_t)count;
+- (void)assertRepeatedExtensionsModified:(TestAllExtensions *)message repeatedCount:(uint32_t)count;
 - (void)assertExtensionsClear:(TestAllExtensions *)message;
 - (void)assertClear:(TestAllTypes *)message;
-- (void)assertPackedFieldsSet:(TestPackedTypes *)message
-                repeatedCount:(uint32_t)count;
-- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
-                    repeatedCount:(uint32_t)count;
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message repeatedCount:(uint32_t)count;
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message repeatedCount:(uint32_t)count;
 
 - (void)modifyRepeatedExtensions:(TestAllExtensions *)message;
 - (void)modifyRepeatedFields:(TestAllTypes *)message;
@@ -96,8 +84,7 @@
 - (NSData *)getDataFileNamed:(NSString *)name dataToWrite:(NSData *)dataToWrite;
 
 - (void)assertAllFieldsKVCMatch:(TestAllTypes *)message;
-- (void)setAllFieldsViaKVC:(TestAllTypes *)message
-             repeatedCount:(uint32_t)count;
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message repeatedCount:(uint32_t)count;
 - (void)assertClearKVC:(TestAllTypes *)message;
 
 @end
diff --git a/objectivec/Tests/GPBTestUtilities.m b/objectivec/Tests/GPBTestUtilities.m
index 48d75e7..37bd5d7 100644
--- a/objectivec/Tests/GPBTestUtilities.m
+++ b/objectivec/Tests/GPBTestUtilities.m
@@ -30,9 +30,9 @@
 
 #import "GPBTestUtilities.h"
 
-#import "google/protobuf/MapUnittest.pbobjc.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestImport.pbobjc.h"
+#import "objectivec/Tests/MapUnittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestImport.pbobjc.h"
 
 const uint32_t kGPBDefaultRepeatCount = 2;
 
@@ -66,8 +66,7 @@
 
 // Return data for name. Optionally (based on #if setting) write out dataToWrite
 // to replace that data. Useful for setting golden masters.
-- (NSData *)getDataFileNamed:(NSString *)name
-                 dataToWrite:(NSData *)dataToWrite {
+- (NSData *)getDataFileNamed:(NSString *)name dataToWrite:(NSData *)dataToWrite {
   NSBundle *bundle = [NSBundle bundleForClass:[self class]];
   NSString *path = [bundle pathForResource:[name stringByDeletingPathExtension]
                                     ofType:[name pathExtension]];
@@ -93,63 +92,30 @@
 // -------------------------------------------------------------------
 
 - (void)modifyRepeatedExtensions:(TestAllExtensions *)message {
-  [message setExtension:[UnittestRoot repeatedInt32Extension]
-                  index:1
-                  value:@501];
-  [message setExtension:[UnittestRoot repeatedInt64Extension]
-                  index:1
-                  value:@502];
-  [message setExtension:[UnittestRoot repeatedUint32Extension]
-                  index:1
-                  value:@503];
-  [message setExtension:[UnittestRoot repeatedUint64Extension]
-                  index:1
-                  value:@504];
-  [message setExtension:[UnittestRoot repeatedSint32Extension]
-                  index:1
-                  value:@505];
-  [message setExtension:[UnittestRoot repeatedSint64Extension]
-                  index:1
-                  value:@506];
-  [message setExtension:[UnittestRoot repeatedFixed32Extension]
-                  index:1
-                  value:@507];
-  [message setExtension:[UnittestRoot repeatedFixed64Extension]
-                  index:1
-                  value:@508];
-  [message setExtension:[UnittestRoot repeatedSfixed32Extension]
-                  index:1
-                  value:@509];
-  [message setExtension:[UnittestRoot repeatedSfixed64Extension]
-                  index:1
-                  value:@510];
-  [message setExtension:[UnittestRoot repeatedFloatExtension]
-                  index:1
-                  value:@511.0f];
-  [message setExtension:[UnittestRoot repeatedDoubleExtension]
-                  index:1
-                  value:@512.0];
-  [message setExtension:[UnittestRoot repeatedBoolExtension]
-                  index:1
-                  value:@YES];
-  [message setExtension:[UnittestRoot repeatedStringExtension]
-                  index:1
-                  value:@"515"];
+  [message setExtension:[UnittestRoot repeatedInt32Extension] index:1 value:@501];
+  [message setExtension:[UnittestRoot repeatedInt64Extension] index:1 value:@502];
+  [message setExtension:[UnittestRoot repeatedUint32Extension] index:1 value:@503];
+  [message setExtension:[UnittestRoot repeatedUint64Extension] index:1 value:@504];
+  [message setExtension:[UnittestRoot repeatedSint32Extension] index:1 value:@505];
+  [message setExtension:[UnittestRoot repeatedSint64Extension] index:1 value:@506];
+  [message setExtension:[UnittestRoot repeatedFixed32Extension] index:1 value:@507];
+  [message setExtension:[UnittestRoot repeatedFixed64Extension] index:1 value:@508];
+  [message setExtension:[UnittestRoot repeatedSfixed32Extension] index:1 value:@509];
+  [message setExtension:[UnittestRoot repeatedSfixed64Extension] index:1 value:@510];
+  [message setExtension:[UnittestRoot repeatedFloatExtension] index:1 value:@511.0f];
+  [message setExtension:[UnittestRoot repeatedDoubleExtension] index:1 value:@512.0];
+  [message setExtension:[UnittestRoot repeatedBoolExtension] index:1 value:@YES];
+  [message setExtension:[UnittestRoot repeatedStringExtension] index:1 value:@"515"];
   [message setExtension:[UnittestRoot repeatedBytesExtension]
                   index:1
                   value:[NSData gpbtu_dataWithUint32:516]];
 
   RepeatedGroup_extension *repeatedGroup = [RepeatedGroup_extension message];
   [repeatedGroup setA:517];
-  [message setExtension:[UnittestRoot repeatedGroupExtension]
-                  index:1
-                  value:repeatedGroup];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [TestAllTypes_NestedMessage message];
+  [message setExtension:[UnittestRoot repeatedGroupExtension] index:1 value:repeatedGroup];
+  TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
   [nestedMessage setBb:518];
-  [message setExtension:[UnittestRoot repeatedNestedMessageExtension]
-                  index:1
-                  value:nestedMessage];
+  [message setExtension:[UnittestRoot repeatedNestedMessageExtension] index:1 value:nestedMessage];
   ForeignMessage *foreignMessage = [ForeignMessage message];
   [foreignMessage setC:519];
   [message setExtension:[UnittestRoot repeatedForeignMessageExtension]
@@ -157,9 +123,7 @@
                   value:foreignMessage];
   ImportMessage *importMessage = [ImportMessage message];
   [importMessage setD:520];
-  [message setExtension:[UnittestRoot repeatedImportMessageExtension]
-                  index:1
-                  value:importMessage];
+  [message setExtension:[UnittestRoot repeatedImportMessageExtension] index:1 value:importMessage];
 
   [message setExtension:[UnittestRoot repeatedNestedEnumExtension]
                   index:1
@@ -171,16 +135,11 @@
                   index:1
                   value:@(ImportEnum_ImportFoo)];
 
-  [message setExtension:[UnittestRoot repeatedStringPieceExtension]
-                  index:1
-                  value:@"524"];
-  [message setExtension:[UnittestRoot repeatedCordExtension]
-                  index:1
-                  value:@"525"];
+  [message setExtension:[UnittestRoot repeatedStringPieceExtension] index:1 value:@"524"];
+  [message setExtension:[UnittestRoot repeatedCordExtension] index:1 value:@"525"];
 }
 
-- (void)assertAllExtensionsSet:(TestAllExtensions *)message
-                 repeatedCount:(uint32_t)count {
+- (void)assertAllExtensionsSet:(TestAllExtensions *)message repeatedCount:(uint32_t)count {
   XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt32Extension]]);
   XCTAssertTrue([message hasExtension:[UnittestRoot optionalInt64Extension]]);
   XCTAssertTrue([message hasExtension:[UnittestRoot optionalUint32Extension]]);
@@ -238,29 +197,44 @@
   XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
 
   XCTAssertEqual(101, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
-  XCTAssertEqual(102LL, [[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
-  XCTAssertEqual(103U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
-  XCTAssertEqual(104ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(102LL,
+                 [[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+  XCTAssertEqual(103U,
+                 [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual(104ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]]
+                             unsignedLongLongValue]);
   XCTAssertEqual(105, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
-  XCTAssertEqual(106LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
-  XCTAssertEqual(107U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
-  XCTAssertEqual(108ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(106LL,
+                 [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+  XCTAssertEqual(107U,
+                 [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+  XCTAssertEqual(108ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]]
+                             unsignedLongLongValue]);
   XCTAssertEqual(109, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
-  XCTAssertEqual(110LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
-  XCTAssertEqualWithAccuracy(111.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
-  XCTAssertEqualWithAccuracy(112.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+  XCTAssertEqual(110LL,
+                 [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy(
+      111.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(
+      112.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
   XCTAssertTrue([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
   XCTAssertEqualObjects(@"115", [message getExtension:[UnittestRoot optionalStringExtension]]);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls], [message getExtension:[UnittestRoot optionalBytesExtension]]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls],
+                        [message getExtension:[UnittestRoot optionalBytesExtension]]);
 
-  XCTAssertEqual(117, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
-  XCTAssertEqual(118, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+  XCTAssertEqual(117, [(TestAllTypes_OptionalGroup *)[message
+                          getExtension:[UnittestRoot optionalGroupExtension]] a]);
+  XCTAssertEqual(118, [(TestAllTypes_NestedMessage *)[message
+                          getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
   XCTAssertEqual(119, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
   XCTAssertEqual(120, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
 
-  XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
-  XCTAssertEqual(ForeignEnum_ForeignBaz, [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
-  XCTAssertEqual(ImportEnum_ImportBaz, [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+  XCTAssertEqual(TestAllTypes_NestedEnum_Baz,
+                 [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignBaz,
+                 [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+  XCTAssertEqual(ImportEnum_ImportBaz,
+                 [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
 
   XCTAssertEqualObjects(@"124", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
   XCTAssertEqualObjects(@"125", [message getExtension:[UnittestRoot optionalCordExtension]]);
@@ -284,9 +258,12 @@
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
 
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
-  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
-  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
-  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+  XCTAssertEqual(count,
+                 [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+  XCTAssertEqual(count,
+                 [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+  XCTAssertEqual(count,
+                 [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
@@ -333,18 +310,20 @@
     [data release];
 
     extension = [message getExtension:[UnittestRoot repeatedGroupExtension]];
-    XCTAssertEqual((int)(217 + i * 100), [(TestAllTypes_OptionalGroup*)extension[i] a]);
+    XCTAssertEqual((int)(217 + i * 100), [(TestAllTypes_OptionalGroup *)extension[i] a]);
     extension = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
-    XCTAssertEqual((int)(218 + i * 100), [(TestAllTypes_NestedMessage*)extension[i] bb]);
+    XCTAssertEqual((int)(218 + i * 100), [(TestAllTypes_NestedMessage *)extension[i] bb]);
     extension = [message getExtension:[UnittestRoot repeatedForeignMessageExtension]];
     XCTAssertEqual((int)(219 + i * 100), [extension[i] c]);
     extension = [message getExtension:[UnittestRoot repeatedImportMessageExtension]];
     XCTAssertEqual((int)(220 + i * 100), [extension[i] d]);
 
     extension = [message getExtension:[UnittestRoot repeatedNestedEnumExtension]];
-    XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [extension[i] intValue]);
+    XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz,
+                   [extension[i] intValue]);
     extension = [message getExtension:[UnittestRoot repeatedForeignEnumExtension]];
-    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [extension[i] intValue]);
+    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+                   [extension[i] intValue]);
     extension = [message getExtension:[UnittestRoot repeatedImportEnumExtension]];
     XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [extension[i] intValue]);
 
@@ -385,24 +364,37 @@
   XCTAssertTrue([message hasExtension:[UnittestRoot defaultCordExtension]]);
 
   XCTAssertEqual(401, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
-  XCTAssertEqual(402LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
-  XCTAssertEqual(403U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
-  XCTAssertEqual(404ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(402LL,
+                 [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+  XCTAssertEqual(403U,
+                 [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual(
+      404ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
   XCTAssertEqual(405, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
-  XCTAssertEqual(406LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
-  XCTAssertEqual(407U, [[message getExtension:[UnittestRoot defaultFixed32Extension]] unsignedIntValue]);
-  XCTAssertEqual(408ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(406LL,
+                 [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+  XCTAssertEqual(407U,
+                 [[message getExtension:[UnittestRoot defaultFixed32Extension]] unsignedIntValue]);
+  XCTAssertEqual(408ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]]
+                             unsignedLongLongValue]);
   XCTAssertEqual(409, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
-  XCTAssertEqual(410LL,[[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
-  XCTAssertEqualWithAccuracy(411.0f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
-  XCTAssertEqualWithAccuracy(412.0, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+  XCTAssertEqual(410LL,
+                 [[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy(
+      411.0f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(
+      412.0, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
   XCTAssertFalse([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
   XCTAssertEqualObjects(@"415", [message getExtension:[UnittestRoot defaultStringExtension]]);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416],
+                        [message getExtension:[UnittestRoot defaultBytesExtension]]);
 
-  XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
-  XCTAssertEqual(ForeignEnum_ForeignFoo, [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
-  XCTAssertEqual(ImportEnum_ImportFoo, [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+  XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
+                 [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+  XCTAssertEqual(ForeignEnum_ForeignFoo,
+                 [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+  XCTAssertEqual(ImportEnum_ImportFoo,
+                 [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
 
   XCTAssertEqualObjects(@"424", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
   XCTAssertEqualObjects(@"425", [message getExtension:[UnittestRoot defaultCordExtension]]);
@@ -430,9 +422,12 @@
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedBytesExtension]] count]);
 
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedGroupExtension]] count]);
-  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
-  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
-  XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
+  XCTAssertEqual(count,
+                 [[message getExtension:[UnittestRoot repeatedNestedMessageExtension]] count]);
+  XCTAssertEqual(count,
+                 [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]] count]);
+  XCTAssertEqual(count,
+                 [[message getExtension:[UnittestRoot repeatedImportMessageExtension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedNestedEnumExtension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedForeignEnumExtension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedImportEnumExtension]] count]);
@@ -440,24 +435,37 @@
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedStringPieceExtension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot repeatedCordExtension]] count]);
 
-  XCTAssertEqual(201,[[message getExtension:[UnittestRoot repeatedInt32Extension]][0] intValue]);
-  XCTAssertEqual(202LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][0] longLongValue]);
-  XCTAssertEqual(203U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][0] unsignedIntValue]);
-  XCTAssertEqual(204ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][0] unsignedLongLongValue]);
+  XCTAssertEqual(201, [[message getExtension:[UnittestRoot repeatedInt32Extension]][0] intValue]);
+  XCTAssertEqual(202LL,
+                 [[message getExtension:[UnittestRoot repeatedInt64Extension]][0] longLongValue]);
+  XCTAssertEqual(
+      203U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][0] unsignedIntValue]);
+  XCTAssertEqual(204ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][0]
+                             unsignedLongLongValue]);
   XCTAssertEqual(205, [[message getExtension:[UnittestRoot repeatedSint32Extension]][0] intValue]);
-  XCTAssertEqual(206LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][0] longLongValue]);
-  XCTAssertEqual(207U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][0] unsignedIntValue]);
-  XCTAssertEqual(208ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][0] unsignedLongLongValue]);
-  XCTAssertEqual(209, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][0] intValue]);
-  XCTAssertEqual(210LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][0] longLongValue]);
-  XCTAssertEqualWithAccuracy(211.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][0] floatValue], 0.01);
-  XCTAssertEqualWithAccuracy(212.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][0] doubleValue], 0.01);
+  XCTAssertEqual(206LL,
+                 [[message getExtension:[UnittestRoot repeatedSint64Extension]][0] longLongValue]);
+  XCTAssertEqual(
+      207U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][0] unsignedIntValue]);
+  XCTAssertEqual(208ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][0]
+                             unsignedLongLongValue]);
+  XCTAssertEqual(209,
+                 [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][0] intValue]);
+  XCTAssertEqual(
+      210LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][0] longLongValue]);
+  XCTAssertEqualWithAccuracy(
+      211.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][0] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(
+      212.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][0] doubleValue], 0.01);
   XCTAssertFalse([[message getExtension:[UnittestRoot repeatedBoolExtension]][0] boolValue]);
   XCTAssertEqualObjects(@"215", [message getExtension:[UnittestRoot repeatedStringExtension]][0]);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216], [message getExtension:[UnittestRoot repeatedBytesExtension]][0]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216],
+                        [message getExtension:[UnittestRoot repeatedBytesExtension]][0]);
 
-  XCTAssertEqual(217, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][0] a]);
-  XCTAssertEqual(218, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][0] bb]);
+  XCTAssertEqual(217, [(TestAllTypes_OptionalGroup *)[message
+                          getExtension:[UnittestRoot repeatedGroupExtension]][0] a]);
+  XCTAssertEqual(218, [(TestAllTypes_NestedMessage *)[message
+                          getExtension:[UnittestRoot repeatedNestedMessageExtension]][0] bb]);
   XCTAssertEqual(219, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][0] c]);
   XCTAssertEqual(220, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][0] d]);
 
@@ -468,28 +476,42 @@
   XCTAssertEqual(ImportEnum_ImportBaz,
                  [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][0] intValue]);
 
-  XCTAssertEqualObjects(@"224", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][0]);
+  XCTAssertEqualObjects(@"224",
+                        [message getExtension:[UnittestRoot repeatedStringPieceExtension]][0]);
   XCTAssertEqualObjects(@"225", [message getExtension:[UnittestRoot repeatedCordExtension]][0]);
 
   // Actually verify the second (modified) elements now.
   XCTAssertEqual(501, [[message getExtension:[UnittestRoot repeatedInt32Extension]][1] intValue]);
-  XCTAssertEqual(502LL, [[message getExtension:[UnittestRoot repeatedInt64Extension]][1] longLongValue]);
-  XCTAssertEqual(503U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][1] unsignedIntValue]);
-  XCTAssertEqual(504ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][1] unsignedLongLongValue]);
+  XCTAssertEqual(502LL,
+                 [[message getExtension:[UnittestRoot repeatedInt64Extension]][1] longLongValue]);
+  XCTAssertEqual(
+      503U, [[message getExtension:[UnittestRoot repeatedUint32Extension]][1] unsignedIntValue]);
+  XCTAssertEqual(504ULL, [[message getExtension:[UnittestRoot repeatedUint64Extension]][1]
+                             unsignedLongLongValue]);
   XCTAssertEqual(505, [[message getExtension:[UnittestRoot repeatedSint32Extension]][1] intValue]);
-  XCTAssertEqual(506LL, [[message getExtension:[UnittestRoot repeatedSint64Extension]][1] longLongValue]);
-  XCTAssertEqual(507U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][1] unsignedIntValue]);
-  XCTAssertEqual(508ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][1] unsignedLongLongValue]);
-  XCTAssertEqual(509, [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][1] intValue]);
-  XCTAssertEqual(510LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][1] longLongValue]);
-  XCTAssertEqualWithAccuracy(511.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][1] floatValue], 0.01);
-  XCTAssertEqualWithAccuracy(512.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][1] doubleValue], 0.01);
+  XCTAssertEqual(506LL,
+                 [[message getExtension:[UnittestRoot repeatedSint64Extension]][1] longLongValue]);
+  XCTAssertEqual(
+      507U, [[message getExtension:[UnittestRoot repeatedFixed32Extension]][1] unsignedIntValue]);
+  XCTAssertEqual(508ULL, [[message getExtension:[UnittestRoot repeatedFixed64Extension]][1]
+                             unsignedLongLongValue]);
+  XCTAssertEqual(509,
+                 [[message getExtension:[UnittestRoot repeatedSfixed32Extension]][1] intValue]);
+  XCTAssertEqual(
+      510LL, [[message getExtension:[UnittestRoot repeatedSfixed64Extension]][1] longLongValue]);
+  XCTAssertEqualWithAccuracy(
+      511.0f, [[message getExtension:[UnittestRoot repeatedFloatExtension]][1] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(
+      512.0, [[message getExtension:[UnittestRoot repeatedDoubleExtension]][1] doubleValue], 0.01);
   XCTAssertTrue([[message getExtension:[UnittestRoot repeatedBoolExtension]][1] boolValue]);
   XCTAssertEqualObjects(@"515", [message getExtension:[UnittestRoot repeatedStringExtension]][1]);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516], [message getExtension:[UnittestRoot repeatedBytesExtension]][1]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516],
+                        [message getExtension:[UnittestRoot repeatedBytesExtension]][1]);
 
-  XCTAssertEqual(517, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot repeatedGroupExtension]][1] a]);
-  XCTAssertEqual(518, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot repeatedNestedMessageExtension]][1] bb]);
+  XCTAssertEqual(517, [(TestAllTypes_OptionalGroup *)[message
+                          getExtension:[UnittestRoot repeatedGroupExtension]][1] a]);
+  XCTAssertEqual(518, [(TestAllTypes_NestedMessage *)[message
+                          getExtension:[UnittestRoot repeatedNestedMessageExtension]][1] bb]);
   XCTAssertEqual(519, [[message getExtension:[UnittestRoot repeatedForeignMessageExtension]][1] c]);
   XCTAssertEqual(520, [[message getExtension:[UnittestRoot repeatedImportMessageExtension]][1] d]);
 
@@ -500,14 +522,14 @@
   XCTAssertEqual(ImportEnum_ImportFoo,
                  [[message getExtension:[UnittestRoot repeatedImportEnumExtension]][1] intValue]);
 
-  XCTAssertEqualObjects(@"524", [message getExtension:[UnittestRoot repeatedStringPieceExtension]][1]);
+  XCTAssertEqualObjects(@"524",
+                        [message getExtension:[UnittestRoot repeatedStringPieceExtension]][1]);
   XCTAssertEqualObjects(@"525", [message getExtension:[UnittestRoot repeatedCordExtension]][1]);
 }
 
 // -------------------------------------------------------------------
 
-- (void)assertAllFieldsSet:(TestAllTypes *)message
-             repeatedCount:(uint32_t)count {
+- (void)assertAllFieldsSet:(TestAllTypes *)message repeatedCount:(uint32_t)count {
   XCTAssertTrue(message.hasOptionalInt32);
   XCTAssertTrue(message.hasOptionalInt64);
   XCTAssertTrue(message.hasOptionalUint32);
@@ -555,8 +577,7 @@
   XCTAssertEqualWithAccuracy(112.0, message.optionalDouble, 0.1);
   XCTAssertTrue(message.optionalBool);
   XCTAssertEqualObjects(@"115", message.optionalString);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls],
-                        message.optionalBytes);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithEmbeddedNulls], message.optionalBytes);
 
   XCTAssertEqual(117, message.optionalGroup.a);
   XCTAssertEqual(118, message.optionalNestedMessage.bb);
@@ -627,28 +648,19 @@
   XCTAssertEqual(count, message.repeatedCordArray_Count);
 
   for (uint32_t i = 0; i < count; ++i) {
-    XCTAssertEqual((int)(201 + i * 100),
-                   [message.repeatedInt32Array valueAtIndex:i]);
+    XCTAssertEqual((int)(201 + i * 100), [message.repeatedInt32Array valueAtIndex:i]);
     XCTAssertEqual(202 + i * 100, [message.repeatedInt64Array valueAtIndex:i]);
     XCTAssertEqual(203 + i * 100, [message.repeatedUint32Array valueAtIndex:i]);
     XCTAssertEqual(204 + i * 100, [message.repeatedUint64Array valueAtIndex:i]);
-    XCTAssertEqual((int)(205 + i * 100),
-                   [message.repeatedSint32Array valueAtIndex:i]);
+    XCTAssertEqual((int)(205 + i * 100), [message.repeatedSint32Array valueAtIndex:i]);
     XCTAssertEqual(206 + i * 100, [message.repeatedSint64Array valueAtIndex:i]);
-    XCTAssertEqual(207 + i * 100,
-                   [message.repeatedFixed32Array valueAtIndex:i]);
-    XCTAssertEqual(208 + i * 100,
-                   [message.repeatedFixed64Array valueAtIndex:i]);
-    XCTAssertEqual((int)(209 + i * 100),
-                   [message.repeatedSfixed32Array valueAtIndex:i]);
-    XCTAssertEqual(210 + i * 100,
-                   [message.repeatedSfixed64Array valueAtIndex:i]);
-    XCTAssertEqualWithAccuracy(
-        211 + i * 100, [message.repeatedFloatArray valueAtIndex:i], 0.1);
-    XCTAssertEqualWithAccuracy(
-        212 + i * 100, [message.repeatedDoubleArray valueAtIndex:i], 0.1);
-    XCTAssertEqual((i % 2) ? YES : NO,
-                   [message.repeatedBoolArray valueAtIndex:i]);
+    XCTAssertEqual(207 + i * 100, [message.repeatedFixed32Array valueAtIndex:i]);
+    XCTAssertEqual(208 + i * 100, [message.repeatedFixed64Array valueAtIndex:i]);
+    XCTAssertEqual((int)(209 + i * 100), [message.repeatedSfixed32Array valueAtIndex:i]);
+    XCTAssertEqual(210 + i * 100, [message.repeatedSfixed64Array valueAtIndex:i]);
+    XCTAssertEqualWithAccuracy(211 + i * 100, [message.repeatedFloatArray valueAtIndex:i], 0.1);
+    XCTAssertEqualWithAccuracy(212 + i * 100, [message.repeatedDoubleArray valueAtIndex:i], 0.1);
+    XCTAssertEqual((i % 2) ? YES : NO, [message.repeatedBoolArray valueAtIndex:i]);
 
     NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
     XCTAssertEqualObjects(string, message.repeatedStringArray[i]);
@@ -658,14 +670,21 @@
     XCTAssertEqualObjects(data, message.repeatedBytesArray[i]);
     [data release];
 
-    XCTAssertEqual((int)(217 + i * 100), ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[i]).a);
-    XCTAssertEqual((int)(218 + i * 100), ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[i]).bb);
-    XCTAssertEqual((int)(219 + i * 100), ((ForeignMessage*)message.repeatedForeignMessageArray[i]).c);
-    XCTAssertEqual((int)(220 + i * 100), ((ImportMessage*)message.repeatedImportMessageArray[i]).d);
+    XCTAssertEqual((int)(217 + i * 100),
+                   ((TestAllTypes_RepeatedGroup *)message.repeatedGroupArray[i]).a);
+    XCTAssertEqual((int)(218 + i * 100),
+                   ((TestAllTypes_NestedMessage *)message.repeatedNestedMessageArray[i]).bb);
+    XCTAssertEqual((int)(219 + i * 100),
+                   ((ForeignMessage *)message.repeatedForeignMessageArray[i]).c);
+    XCTAssertEqual((int)(220 + i * 100),
+                   ((ImportMessage *)message.repeatedImportMessageArray[i]).d);
 
-    XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:i]);
-    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:i]);
-    XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz, [message.repeatedImportEnumArray valueAtIndex:i]);
+    XCTAssertEqual((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz,
+                   [message.repeatedNestedEnumArray valueAtIndex:i]);
+    XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
+                   [message.repeatedForeignEnumArray valueAtIndex:i]);
+    XCTAssertEqual((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz,
+                   [message.repeatedImportEnumArray valueAtIndex:i]);
 
     string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
     XCTAssertEqualObjects(string, message.repeatedStringPieceArray[i]);
@@ -715,8 +734,7 @@
   XCTAssertEqualWithAccuracy(412.0, message.defaultDouble, 0.1);
   XCTAssertFalse(message.defaultBool);
   XCTAssertEqualObjects(@"415", message.defaultString);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416],
-                        message.defaultBytes);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:416], message.defaultBytes);
 
   XCTAssertEqual(TestAllTypes_NestedEnum_Foo, message.defaultNestedEnum);
   XCTAssertEqual(ForeignEnum_ForeignFoo, message.defaultForeignEnum);
@@ -746,8 +764,7 @@
   TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
   [allTypes setA:117];
   [message setOptionalGroup:allTypes];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [TestAllTypes_NestedMessage message];
+  TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
   [nestedMessage setBb:118];
   [message setOptionalNestedMessage:nestedMessage];
   ForeignMessage *foreignMessage = [ForeignMessage message];
@@ -788,8 +805,7 @@
     [message.repeatedBytesArray addObject:data];
     [data release];
 
-    TestAllTypes_RepeatedGroup *testAll =
-        [[TestAllTypes_RepeatedGroup alloc] init];
+    TestAllTypes_RepeatedGroup *testAll = [[TestAllTypes_RepeatedGroup alloc] init];
     [testAll setA:217 + i * 100];
     [message.repeatedGroupArray addObject:testAll];
     [testAll release];
@@ -809,10 +825,13 @@
     [message.repeatedImportMessageArray addObject:importMessage];
     [importMessage release];
 
-    [message.repeatedNestedEnumArray addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz];
+    [message.repeatedNestedEnumArray
+        addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz];
 
-    [message.repeatedForeignEnumArray addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
-    [message.repeatedImportEnumArray addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
+    [message.repeatedForeignEnumArray
+        addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+    [message.repeatedImportEnumArray
+        addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
 
     string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
     [message.repeatedStringPieceArray addObject:string];
@@ -933,8 +952,7 @@
   message.hasDefaultCord = NO;
 }
 
-- (void)setAllExtensions:(TestAllExtensions *)message
-           repeatedCount:(uint32_t)count {
+- (void)setAllExtensions:(TestAllExtensions *)message repeatedCount:(uint32_t)count {
   [message setExtension:[UnittestRoot optionalInt32Extension] value:@101];
   [message setExtension:[UnittestRoot optionalInt64Extension] value:@102L];
   [message setExtension:[UnittestRoot optionalUint32Extension] value:@103];
@@ -954,60 +972,40 @@
 
   OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
   [optionalGroup setA:117];
-  [message setExtension:[UnittestRoot optionalGroupExtension]
-                  value:optionalGroup];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [TestAllTypes_NestedMessage message];
+  [message setExtension:[UnittestRoot optionalGroupExtension] value:optionalGroup];
+  TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
   [nestedMessage setBb:118];
-  [message setExtension:[UnittestRoot optionalNestedMessageExtension]
-                  value:nestedMessage];
+  [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage];
   ForeignMessage *foreignMessage = [ForeignMessage message];
   [foreignMessage setC:119];
-  [message setExtension:[UnittestRoot optionalForeignMessageExtension]
-                  value:foreignMessage];
+  [message setExtension:[UnittestRoot optionalForeignMessageExtension] value:foreignMessage];
   ImportMessage *importMessage = [ImportMessage message];
   [importMessage setD:120];
-  [message setExtension:[UnittestRoot optionalImportMessageExtension]
-                  value:importMessage];
+  [message setExtension:[UnittestRoot optionalImportMessageExtension] value:importMessage];
 
   [message setExtension:[UnittestRoot optionalNestedEnumExtension]
                   value:@(TestAllTypes_NestedEnum_Baz)];
   [message setExtension:[UnittestRoot optionalForeignEnumExtension]
                   value:@(ForeignEnum_ForeignBaz)];
-  [message setExtension:[UnittestRoot optionalImportEnumExtension]
-                  value:@(ImportEnum_ImportBaz)];
+  [message setExtension:[UnittestRoot optionalImportEnumExtension] value:@(ImportEnum_ImportBaz)];
 
-  [message setExtension:[UnittestRoot optionalStringPieceExtension]
-                  value:@"124"];
+  [message setExtension:[UnittestRoot optionalStringPieceExtension] value:@"124"];
   [message setExtension:[UnittestRoot optionalCordExtension] value:@"125"];
 
   for (uint32_t i = 0; i < count; ++i) {
-    [message addExtension:[UnittestRoot repeatedInt32Extension]
-                    value:@(201 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedInt64Extension]
-                    value:@(202 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedUint32Extension]
-                    value:@(203 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedUint64Extension]
-                    value:@(204 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedSint32Extension]
-                    value:@(205 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedSint64Extension]
-                    value:@(206 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedFixed32Extension]
-                    value:@(207 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedFixed64Extension]
-                    value:@(208 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedSfixed32Extension]
-                    value:@(209 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedSfixed64Extension]
-                    value:@(210 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedFloatExtension]
-                    value:@(211 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedDoubleExtension]
-                    value:@(212 + i * 100)];
-    [message addExtension:[UnittestRoot repeatedBoolExtension]
-                    value:@((i % 2) ? YES : NO)];
+    [message addExtension:[UnittestRoot repeatedInt32Extension] value:@(201 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedInt64Extension] value:@(202 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedUint32Extension] value:@(203 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedUint64Extension] value:@(204 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSint32Extension] value:@(205 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSint64Extension] value:@(206 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedFixed32Extension] value:@(207 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedFixed64Extension] value:@(208 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSfixed32Extension] value:@(209 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedSfixed64Extension] value:@(210 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedFloatExtension] value:@(211 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedDoubleExtension] value:@(212 + i * 100)];
+    [message addExtension:[UnittestRoot repeatedBoolExtension] value:@((i % 2) ? YES : NO)];
     NSString *string = [[NSString alloc] initWithFormat:@"%d", 215 + i * 100];
     [message addExtension:[UnittestRoot repeatedStringExtension] value:string];
     [string release];
@@ -1015,40 +1013,31 @@
     [message addExtension:[UnittestRoot repeatedBytesExtension] value:data];
     [data release];
 
-    RepeatedGroup_extension *repeatedGroup =
-        [[RepeatedGroup_extension alloc] init];
+    RepeatedGroup_extension *repeatedGroup = [[RepeatedGroup_extension alloc] init];
     [repeatedGroup setA:217 + i * 100];
-    [message addExtension:[UnittestRoot repeatedGroupExtension]
-                    value:repeatedGroup];
+    [message addExtension:[UnittestRoot repeatedGroupExtension] value:repeatedGroup];
     [repeatedGroup release];
     nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
     [nestedMessage setBb:218 + i * 100];
-    [message addExtension:[UnittestRoot repeatedNestedMessageExtension]
-                    value:nestedMessage];
+    [message addExtension:[UnittestRoot repeatedNestedMessageExtension] value:nestedMessage];
     [nestedMessage release];
     foreignMessage = [[ForeignMessage alloc] init];
     [foreignMessage setC:219 + i * 100];
-    [message addExtension:[UnittestRoot repeatedForeignMessageExtension]
-                    value:foreignMessage];
+    [message addExtension:[UnittestRoot repeatedForeignMessageExtension] value:foreignMessage];
     [foreignMessage release];
     importMessage = [[ImportMessage alloc] init];
     [importMessage setD:220 + i * 100];
-    [message addExtension:[UnittestRoot repeatedImportMessageExtension]
-                    value:importMessage];
+    [message addExtension:[UnittestRoot repeatedImportMessageExtension] value:importMessage];
     [importMessage release];
     [message addExtension:[UnittestRoot repeatedNestedEnumExtension]
-                    value:@((i % 2) ? TestAllTypes_NestedEnum_Bar
-                                    : TestAllTypes_NestedEnum_Baz)];
+                    value:@((i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz)];
     [message addExtension:[UnittestRoot repeatedForeignEnumExtension]
-                    value:@((i % 2) ? ForeignEnum_ForeignBar
-                                    : ForeignEnum_ForeignBaz)];
-    [message
-        addExtension:[UnittestRoot repeatedImportEnumExtension]
-               value:@((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz)];
+                    value:@((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz)];
+    [message addExtension:[UnittestRoot repeatedImportEnumExtension]
+                    value:@((i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz)];
 
     string = [[NSString alloc] initWithFormat:@"%d", 224 + i * 100];
-    [message addExtension:[UnittestRoot repeatedStringPieceExtension]
-                    value:string];
+    [message addExtension:[UnittestRoot repeatedStringPieceExtension] value:string];
     [string release];
 
     string = [[NSString alloc] initWithFormat:@"%d", 225 + i * 100];
@@ -1077,13 +1066,10 @@
 
   [message setExtension:[UnittestRoot defaultNestedEnumExtension]
                   value:@(TestAllTypes_NestedEnum_Foo)];
-  [message setExtension:[UnittestRoot defaultForeignEnumExtension]
-                  value:@(ForeignEnum_ForeignFoo)];
-  [message setExtension:[UnittestRoot defaultImportEnumExtension]
-                  value:@(ImportEnum_ImportFoo)];
+  [message setExtension:[UnittestRoot defaultForeignEnumExtension] value:@(ForeignEnum_ForeignFoo)];
+  [message setExtension:[UnittestRoot defaultImportEnumExtension] value:@(ImportEnum_ImportFoo)];
 
-  [message setExtension:[UnittestRoot defaultStringPieceExtension]
-                  value:@"424"];
+  [message setExtension:[UnittestRoot defaultStringPieceExtension] value:@"424"];
   [message setExtension:[UnittestRoot defaultCordExtension] value:@"425"];
 }
 
@@ -1113,9 +1099,8 @@
     [message.mapInt32Bytes setObject:data forKey:113 + i * 100];
     [data release];
 
-    [message.mapInt32Enum
-        setEnum:(i % 2) ? MapEnum_MapEnumBar : MapEnum_MapEnumBaz
-         forKey:114 + i * 100];
+    [message.mapInt32Enum setEnum:(i % 2) ? MapEnum_MapEnumBar : MapEnum_MapEnumBaz
+                           forKey:114 + i * 100];
 
     ForeignMessage *subMsg = [[ForeignMessage alloc] init];
     subMsg.c = i + 1;
@@ -1376,8 +1361,7 @@
   XCTAssertEqualWithAccuracy(52e3, message.defaultDouble, 0.1);
   XCTAssertTrue(message.defaultBool);
   XCTAssertEqualObjects(@"hello", message.defaultString);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"],
-                        message.defaultBytes);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"], message.defaultBytes);
 
   XCTAssertEqual(TestAllTypes_NestedEnum_Bar, message.defaultNestedEnum);
   XCTAssertEqual(ForeignEnum_ForeignBar, message.defaultForeignEnum);
@@ -1419,20 +1403,29 @@
 
   // Optional fields without defaults are set to zero or something like it.
   XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalInt32Extension]] intValue]);
-  XCTAssertEqual(0LL,[[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
-  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
-  XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalInt64Extension]] longLongValue]);
+  XCTAssertEqual(0U,
+                 [[message getExtension:[UnittestRoot optionalUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual(
+      0ULL, [[message getExtension:[UnittestRoot optionalUint64Extension]] unsignedLongLongValue]);
   XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSint32Extension]] intValue]);
-  XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
-  XCTAssertEqual(0U, [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
-  XCTAssertEqual(0ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(0LL,
+                 [[message getExtension:[UnittestRoot optionalSint64Extension]] longLongValue]);
+  XCTAssertEqual(0U,
+                 [[message getExtension:[UnittestRoot optionalFixed32Extension]] unsignedIntValue]);
+  XCTAssertEqual(
+      0ULL, [[message getExtension:[UnittestRoot optionalFixed64Extension]] unsignedLongLongValue]);
   XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalSfixed32Extension]] intValue]);
-  XCTAssertEqual(0LL, [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
-  XCTAssertEqualWithAccuracy(0.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
-  XCTAssertEqualWithAccuracy(0.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
+  XCTAssertEqual(0LL,
+                 [[message getExtension:[UnittestRoot optionalSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy(
+      0.0f, [[message getExtension:[UnittestRoot optionalFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(
+      0.0, [[message getExtension:[UnittestRoot optionalDoubleExtension]] doubleValue], 0.01);
   XCTAssertFalse([[message getExtension:[UnittestRoot optionalBoolExtension]] boolValue]);
   XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringExtension]]);
-  XCTAssertEqualObjects(GPBEmptyNSData(), [message getExtension:[UnittestRoot optionalBytesExtension]]);
+  XCTAssertEqualObjects(GPBEmptyNSData(),
+                        [message getExtension:[UnittestRoot optionalBytesExtension]]);
 
   // Embedded messages should also be clear.
 
@@ -1441,18 +1434,20 @@
   XCTAssertFalse([[message getExtension:[UnittestRoot optionalForeignMessageExtension]] hasC]);
   XCTAssertFalse([[message getExtension:[UnittestRoot optionalImportMessageExtension]] hasD]);
 
-  XCTAssertEqual(0, [(TestAllTypes_OptionalGroup*)[message getExtension:[UnittestRoot optionalGroupExtension]] a]);
-  XCTAssertEqual(0, [(TestAllTypes_NestedMessage*)[message getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
+  XCTAssertEqual(0, [(TestAllTypes_OptionalGroup *)[message
+                        getExtension:[UnittestRoot optionalGroupExtension]] a]);
+  XCTAssertEqual(0, [(TestAllTypes_NestedMessage *)[message
+                        getExtension:[UnittestRoot optionalNestedMessageExtension]] bb]);
   XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalForeignMessageExtension]] c]);
   XCTAssertEqual(0, [[message getExtension:[UnittestRoot optionalImportMessageExtension]] d]);
 
   // Enums without defaults are set to the first value in the enum.
   XCTAssertEqual(TestAllTypes_NestedEnum_Foo,
-               [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
+                 [[message getExtension:[UnittestRoot optionalNestedEnumExtension]] intValue]);
   XCTAssertEqual(ForeignEnum_ForeignFoo,
-               [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
+                 [[message getExtension:[UnittestRoot optionalForeignEnumExtension]] intValue]);
   XCTAssertEqual(ImportEnum_ImportFoo,
-               [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
+                 [[message getExtension:[UnittestRoot optionalImportEnumExtension]] intValue]);
 
   XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalStringPieceExtension]]);
   XCTAssertEqualObjects(@"", [message getExtension:[UnittestRoot optionalCordExtension]]);
@@ -1510,28 +1505,36 @@
   XCTAssertFalse([message hasExtension:[UnittestRoot defaultCordExtension]]);
 
   // Fields with defaults have their default values (duh).
-  XCTAssertEqual( 41, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
-  XCTAssertEqual( 42LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
-  XCTAssertEqual( 43U, [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
-  XCTAssertEqual( 44ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(41, [[message getExtension:[UnittestRoot defaultInt32Extension]] intValue]);
+  XCTAssertEqual(42LL, [[message getExtension:[UnittestRoot defaultInt64Extension]] longLongValue]);
+  XCTAssertEqual(43U,
+                 [[message getExtension:[UnittestRoot defaultUint32Extension]] unsignedIntValue]);
+  XCTAssertEqual(
+      44ULL, [[message getExtension:[UnittestRoot defaultUint64Extension]] unsignedLongLongValue]);
   XCTAssertEqual(-45, [[message getExtension:[UnittestRoot defaultSint32Extension]] intValue]);
-  XCTAssertEqual( 46LL, [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
-  XCTAssertEqual( 47, [[message getExtension:[UnittestRoot defaultFixed32Extension]] intValue]);
-  XCTAssertEqual( 48ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
-  XCTAssertEqual( 49, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
-  XCTAssertEqual(-50LL, [[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
-  XCTAssertEqualWithAccuracy( 51.5f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
-  XCTAssertEqualWithAccuracy( 52e3, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
+  XCTAssertEqual(46LL,
+                 [[message getExtension:[UnittestRoot defaultSint64Extension]] longLongValue]);
+  XCTAssertEqual(47, [[message getExtension:[UnittestRoot defaultFixed32Extension]] intValue]);
+  XCTAssertEqual(
+      48ULL, [[message getExtension:[UnittestRoot defaultFixed64Extension]] unsignedLongLongValue]);
+  XCTAssertEqual(49, [[message getExtension:[UnittestRoot defaultSfixed32Extension]] intValue]);
+  XCTAssertEqual(-50LL,
+                 [[message getExtension:[UnittestRoot defaultSfixed64Extension]] longLongValue]);
+  XCTAssertEqualWithAccuracy(
+      51.5f, [[message getExtension:[UnittestRoot defaultFloatExtension]] floatValue], 0.01);
+  XCTAssertEqualWithAccuracy(
+      52e3, [[message getExtension:[UnittestRoot defaultDoubleExtension]] doubleValue], 0.01);
   XCTAssertTrue([[message getExtension:[UnittestRoot defaultBoolExtension]] boolValue]);
   XCTAssertEqualObjects(@"hello", [message getExtension:[UnittestRoot defaultStringExtension]]);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"], [message getExtension:[UnittestRoot defaultBytesExtension]]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithCString:"world"],
+                        [message getExtension:[UnittestRoot defaultBytesExtension]]);
 
   XCTAssertEqual(TestAllTypes_NestedEnum_Bar,
-               [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
+                 [[message getExtension:[UnittestRoot defaultNestedEnumExtension]] intValue]);
   XCTAssertEqual(ForeignEnum_ForeignBar,
-               [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
+                 [[message getExtension:[UnittestRoot defaultForeignEnumExtension]] intValue]);
   XCTAssertEqual(ImportEnum_ImportBar,
-               [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
+                 [[message getExtension:[UnittestRoot defaultImportEnumExtension]] intValue]);
 
   XCTAssertEqualObjects(@"abc", [message getExtension:[UnittestRoot defaultStringPieceExtension]]);
   XCTAssertEqualObjects(@"123", [message getExtension:[UnittestRoot defaultCordExtension]]);
@@ -1557,29 +1560,24 @@
   [message.repeatedBytesArray replaceObjectAtIndex:1 withObject:data];
   [data release];
 
-  TestAllTypes_RepeatedGroup *testAll =
-      [[TestAllTypes_RepeatedGroup alloc] init];
+  TestAllTypes_RepeatedGroup *testAll = [[TestAllTypes_RepeatedGroup alloc] init];
   [testAll setA:517];
   [message.repeatedGroupArray replaceObjectAtIndex:1 withObject:testAll];
   [testAll release];
 
-  TestAllTypes_NestedMessage *nestedMessage =
-      [[TestAllTypes_NestedMessage alloc] init];
+  TestAllTypes_NestedMessage *nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
   [nestedMessage setBb:518];
-  [message.repeatedNestedMessageArray replaceObjectAtIndex:1
-                                                withObject:nestedMessage];
+  [message.repeatedNestedMessageArray replaceObjectAtIndex:1 withObject:nestedMessage];
   [nestedMessage release];
 
   ForeignMessage *foreignMessage = [[ForeignMessage alloc] init];
   [foreignMessage setC:519];
-  [message.repeatedForeignMessageArray replaceObjectAtIndex:1
-                                                 withObject:foreignMessage];
+  [message.repeatedForeignMessageArray replaceObjectAtIndex:1 withObject:foreignMessage];
   [foreignMessage release];
 
   ImportMessage *importMessage = [[ImportMessage alloc] init];
   [importMessage setD:520];
-  [message.repeatedImportMessageArray replaceObjectAtIndex:1
-                                                withObject:importMessage];
+  [message.repeatedImportMessageArray replaceObjectAtIndex:1 withObject:importMessage];
   [importMessage release];
 
   [message.repeatedNestedEnumArray replaceValueAtIndex:1 withValue:TestAllTypes_NestedEnum_Foo];
@@ -1590,8 +1588,7 @@
   [message.repeatedCordArray replaceObjectAtIndex:1 withObject:@"525"];
 }
 
-- (void)assertRepeatedFieldsModified:(TestAllTypes *)message
-                       repeatedCount:(uint32_t)count {
+- (void)assertRepeatedFieldsModified:(TestAllTypes *)message repeatedCount:(uint32_t)count {
   // 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.
@@ -1664,13 +1661,12 @@
   XCTAssertEqualWithAccuracy(212.0, [message.repeatedDoubleArray valueAtIndex:0], 0.01);
   XCTAssertFalse([message.repeatedBoolArray valueAtIndex:0]);
   XCTAssertEqualObjects(@"215", message.repeatedStringArray[0]);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216],
-                        message.repeatedBytesArray[0]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:216], message.repeatedBytesArray[0]);
 
-  XCTAssertEqual(217, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[0]).a);
-  XCTAssertEqual(218, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[0]).bb);
-  XCTAssertEqual(219, ((ForeignMessage*)message.repeatedForeignMessageArray[0]).c);
-  XCTAssertEqual(220, ((ImportMessage*)message.repeatedImportMessageArray[0]).d);
+  XCTAssertEqual(217, ((TestAllTypes_RepeatedGroup *)message.repeatedGroupArray[0]).a);
+  XCTAssertEqual(218, ((TestAllTypes_NestedMessage *)message.repeatedNestedMessageArray[0]).bb);
+  XCTAssertEqual(219, ((ForeignMessage *)message.repeatedForeignMessageArray[0]).c);
+  XCTAssertEqual(220, ((ImportMessage *)message.repeatedImportMessageArray[0]).d);
 
   XCTAssertEqual(TestAllTypes_NestedEnum_Baz, [message.repeatedNestedEnumArray valueAtIndex:0]);
   XCTAssertEqual(ForeignEnum_ForeignBaz, [message.repeatedForeignEnumArray valueAtIndex:0]);
@@ -1694,13 +1690,12 @@
   XCTAssertEqualWithAccuracy(512.0, [message.repeatedDoubleArray valueAtIndex:1], 0.01);
   XCTAssertTrue([message.repeatedBoolArray valueAtIndex:1]);
   XCTAssertEqualObjects(@"515", message.repeatedStringArray[1]);
-  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516],
-                        message.repeatedBytesArray[1]);
+  XCTAssertEqualObjects([NSData gpbtu_dataWithUint32:516], message.repeatedBytesArray[1]);
 
-  XCTAssertEqual(517, ((TestAllTypes_RepeatedGroup*)message.repeatedGroupArray[1]).a);
-  XCTAssertEqual(518, ((TestAllTypes_NestedMessage*)message.repeatedNestedMessageArray[1]).bb);
-  XCTAssertEqual(519, ((ForeignMessage*)message.repeatedForeignMessageArray[1]).c);
-  XCTAssertEqual(520, ((ImportMessage*)message.repeatedImportMessageArray[1]).d);
+  XCTAssertEqual(517, ((TestAllTypes_RepeatedGroup *)message.repeatedGroupArray[1]).a);
+  XCTAssertEqual(518, ((TestAllTypes_NestedMessage *)message.repeatedNestedMessageArray[1]).bb);
+  XCTAssertEqual(519, ((ForeignMessage *)message.repeatedForeignMessageArray[1]).c);
+  XCTAssertEqual(520, ((ImportMessage *)message.repeatedImportMessageArray[1]).d);
 
   XCTAssertEqual(TestAllTypes_NestedEnum_Foo, [message.repeatedNestedEnumArray valueAtIndex:1]);
   XCTAssertEqual(ForeignEnum_ForeignFoo, [message.repeatedForeignEnumArray valueAtIndex:1]);
@@ -1710,8 +1705,7 @@
   XCTAssertEqualObjects(@"525", message.repeatedCordArray[1]);
 }
 
-- (void)setPackedFields:(TestPackedTypes *)message
-          repeatedCount:(uint32_t)count {
+- (void)setPackedFields:(TestPackedTypes *)message repeatedCount:(uint32_t)count {
   // Must match -setUnpackedFields:repeatedCount:
   // Must match -setPackedExtensions:repeatedCount:
   // Must match -setUnpackedExtensions:repeatedCount:
@@ -1755,13 +1749,11 @@
     [message.packedBoolArray addValue:(i % 2) ? YES : NO];
   }
   for (uint32_t i = 0; i < count; ++i) {
-    [message.packedEnumArray
-        addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+    [message.packedEnumArray addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
   }
 }
 
-- (void)setUnpackedFields:(TestUnpackedTypes *)message
-            repeatedCount:(uint32_t)count {
+- (void)setUnpackedFields:(TestUnpackedTypes *)message repeatedCount:(uint32_t)count {
   // Must match -setPackedFields:repeatedCount:
   // Must match -setPackedExtensions:repeatedCount:
   // Must match -setUnpackedExtensions:repeatedCount:
@@ -1805,13 +1797,11 @@
     [message.unpackedBoolArray addValue:(i % 2) ? YES : NO];
   }
   for (uint32_t i = 0; i < count; ++i) {
-    [message.unpackedEnumArray
-        addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+    [message.unpackedEnumArray addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
   }
 }
 
-- (void)assertPackedFieldsSet:(TestPackedTypes *)message
-                repeatedCount:(uint32_t)count {
+- (void)assertPackedFieldsSet:(TestPackedTypes *)message repeatedCount:(uint32_t)count {
   XCTAssertEqual(count, message.packedInt32Array.count);
   XCTAssertEqual(count, message.packedInt64Array.count);
   XCTAssertEqual(count, message.packedUint32Array.count);
@@ -1827,108 +1817,71 @@
   XCTAssertEqual(count, message.packedBoolArray.count);
   XCTAssertEqual(count, message.packedEnumArray.count);
   for (uint32_t i = 0; i < count; ++i) {
-    XCTAssertEqual((int)(601 + i * 100),
-                   [message.packedInt32Array valueAtIndex:i]);
+    XCTAssertEqual((int)(601 + i * 100), [message.packedInt32Array valueAtIndex:i]);
     XCTAssertEqual(602 + i * 100, [message.packedInt64Array valueAtIndex:i]);
     XCTAssertEqual(603 + i * 100, [message.packedUint32Array valueAtIndex:i]);
     XCTAssertEqual(604 + i * 100, [message.packedUint64Array valueAtIndex:i]);
-    XCTAssertEqual((int)(605 + i * 100),
-                   [message.packedSint32Array valueAtIndex:i]);
+    XCTAssertEqual((int)(605 + i * 100), [message.packedSint32Array valueAtIndex:i]);
     XCTAssertEqual(606 + i * 100, [message.packedSint64Array valueAtIndex:i]);
     XCTAssertEqual(607 + i * 100, [message.packedFixed32Array valueAtIndex:i]);
     XCTAssertEqual(608 + i * 100, [message.packedFixed64Array valueAtIndex:i]);
-    XCTAssertEqual((int)(609 + i * 100),
-                   [message.packedSfixed32Array valueAtIndex:i]);
+    XCTAssertEqual((int)(609 + i * 100), [message.packedSfixed32Array valueAtIndex:i]);
     XCTAssertEqual(610 + i * 100, [message.packedSfixed64Array valueAtIndex:i]);
-    XCTAssertEqualWithAccuracy(611 + i * 100,
-                               [message.packedFloatArray valueAtIndex:i], 0.01);
-    XCTAssertEqualWithAccuracy(
-        612 + i * 100, [message.packedDoubleArray valueAtIndex:i], 0.01);
-    XCTAssertEqual((i % 2) ? YES : NO,
-                   [message.packedBoolArray valueAtIndex:i]);
+    XCTAssertEqualWithAccuracy(611 + i * 100, [message.packedFloatArray valueAtIndex:i], 0.01);
+    XCTAssertEqualWithAccuracy(612 + i * 100, [message.packedDoubleArray valueAtIndex:i], 0.01);
+    XCTAssertEqual((i % 2) ? YES : NO, [message.packedBoolArray valueAtIndex:i]);
     XCTAssertEqual((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz,
                    [message.packedEnumArray valueAtIndex:i]);
   }
 }
 
-- (void)setPackedExtensions:(TestPackedExtensions *)message
-              repeatedCount:(uint32_t)count {
+- (void)setPackedExtensions:(TestPackedExtensions *)message repeatedCount:(uint32_t)count {
   // Must match -setPackedFields:repeatedCount:
   // Must match -setUnpackedFields:repeatedCount:
   // Must match -setUnpackedExtensions:repeatedCount:
   for (uint32_t i = 0; i < count; i++) {
-    [message addExtension:[UnittestRoot packedInt32Extension]
-                    value:@(601 + i * 100)];
-    [message addExtension:[UnittestRoot packedInt64Extension]
-                    value:@(602 + i * 100)];
-    [message addExtension:[UnittestRoot packedUint32Extension]
-                    value:@(603 + i * 100)];
-    [message addExtension:[UnittestRoot packedUint64Extension]
-                    value:@(604 + i * 100)];
-    [message addExtension:[UnittestRoot packedSint32Extension]
-                    value:@(605 + i * 100)];
-    [message addExtension:[UnittestRoot packedSint64Extension]
-                    value:@(606 + i * 100)];
-    [message addExtension:[UnittestRoot packedFixed32Extension]
-                    value:@(607 + i * 100)];
-    [message addExtension:[UnittestRoot packedFixed64Extension]
-                    value:@(608 + i * 100)];
-    [message addExtension:[UnittestRoot packedSfixed32Extension]
-                    value:@(609 + i * 100)];
-    [message addExtension:[UnittestRoot packedSfixed64Extension]
-                    value:@(610 + i * 100)];
-    [message addExtension:[UnittestRoot packedFloatExtension]
-                    value:@(611 + i * 100)];
-    [message addExtension:[UnittestRoot packedDoubleExtension]
-                    value:@(612 + i * 100)];
-    [message addExtension:[UnittestRoot packedBoolExtension]
-                    value:@((i % 2) ? YES : NO)];
+    [message addExtension:[UnittestRoot packedInt32Extension] value:@(601 + i * 100)];
+    [message addExtension:[UnittestRoot packedInt64Extension] value:@(602 + i * 100)];
+    [message addExtension:[UnittestRoot packedUint32Extension] value:@(603 + i * 100)];
+    [message addExtension:[UnittestRoot packedUint64Extension] value:@(604 + i * 100)];
+    [message addExtension:[UnittestRoot packedSint32Extension] value:@(605 + i * 100)];
+    [message addExtension:[UnittestRoot packedSint64Extension] value:@(606 + i * 100)];
+    [message addExtension:[UnittestRoot packedFixed32Extension] value:@(607 + i * 100)];
+    [message addExtension:[UnittestRoot packedFixed64Extension] value:@(608 + i * 100)];
+    [message addExtension:[UnittestRoot packedSfixed32Extension] value:@(609 + i * 100)];
+    [message addExtension:[UnittestRoot packedSfixed64Extension] value:@(610 + i * 100)];
+    [message addExtension:[UnittestRoot packedFloatExtension] value:@(611 + i * 100)];
+    [message addExtension:[UnittestRoot packedDoubleExtension] value:@(612 + i * 100)];
+    [message addExtension:[UnittestRoot packedBoolExtension] value:@((i % 2) ? YES : NO)];
     [message addExtension:[UnittestRoot packedEnumExtension]
-                    value:@((i % 2) ? ForeignEnum_ForeignBar
-                                    : ForeignEnum_ForeignBaz)];
+                    value:@((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz)];
   }
 }
 
-- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message
-                repeatedCount:(uint32_t)count {
+- (void)setUnpackedExtensions:(TestUnpackedExtensions *)message repeatedCount:(uint32_t)count {
   // Must match -setPackedFields:repeatedCount:
   // Must match -setUnpackedFields:repeatedCount:
   // Must match -setPackedExtensions:repeatedCount:
   for (uint32_t i = 0; i < count; i++) {
-    [message addExtension:[UnittestRoot unpackedInt32Extension]
-                    value:@(601 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedInt64Extension]
-                    value:@(602 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedUint32Extension]
-                    value:@(603 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedUint64Extension]
-                    value:@(604 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedSint32Extension]
-                    value:@(605 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedSint64Extension]
-                    value:@(606 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedFixed32Extension]
-                    value:@(607 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedFixed64Extension]
-                    value:@(608 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedSfixed32Extension]
-                    value:@(609 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedSfixed64Extension]
-                    value:@(610 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedFloatExtension]
-                    value:@(611 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedDoubleExtension]
-                    value:@(612 + i * 100)];
-    [message addExtension:[UnittestRoot unpackedBoolExtension]
-                    value:@((i % 2) ? YES : NO)];
+    [message addExtension:[UnittestRoot unpackedInt32Extension] value:@(601 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedInt64Extension] value:@(602 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedUint32Extension] value:@(603 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedUint64Extension] value:@(604 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSint32Extension] value:@(605 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSint64Extension] value:@(606 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFixed32Extension] value:@(607 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFixed64Extension] value:@(608 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSfixed32Extension] value:@(609 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedSfixed64Extension] value:@(610 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedFloatExtension] value:@(611 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedDoubleExtension] value:@(612 + i * 100)];
+    [message addExtension:[UnittestRoot unpackedBoolExtension] value:@((i % 2) ? YES : NO)];
     [message addExtension:[UnittestRoot unpackedEnumExtension]
-                    value:@((i % 2) ? ForeignEnum_ForeignBar
-                         : ForeignEnum_ForeignBaz)];
+                    value:@((i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz)];
   }
 }
 
-- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message
-                    repeatedCount:(uint32_t)count{
+- (void)assertPackedExtensionsSet:(TestPackedExtensions *)message repeatedCount:(uint32_t)count {
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt32Extension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedInt64Extension]] count]);
   XCTAssertEqual(count, [[message getExtension:[UnittestRoot packedUint32Extension]] count]);
@@ -2016,20 +1969,24 @@
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @YES);
   XCTAssertNotNil(message.optionalNestedMessage);
   XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.hasBb"], @YES);
-  XCTAssertEqualObjects(@(message.optionalNestedMessage.bb), [message valueForKeyPath:@"optionalNestedMessage.bb"]);
+  XCTAssertEqualObjects(@(message.optionalNestedMessage.bb),
+                        [message valueForKeyPath:@"optionalNestedMessage.bb"]);
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"], @YES);
   XCTAssertNotNil(message.optionalForeignMessage);
   XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.hasC"], @YES);
-  XCTAssertEqualObjects(@(message.optionalForeignMessage.c), [message valueForKeyPath:@"optionalForeignMessage.c"]);
+  XCTAssertEqualObjects(@(message.optionalForeignMessage.c),
+                        [message valueForKeyPath:@"optionalForeignMessage.c"]);
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @YES);
   XCTAssertNotNil(message.optionalForeignMessage);
   XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"], @YES);
-  XCTAssertEqualObjects(@(message.optionalImportMessage.d), [message valueForKeyPath:@"optionalImportMessage.d"]);
+  XCTAssertEqualObjects(@(message.optionalImportMessage.d),
+                        [message valueForKeyPath:@"optionalImportMessage.d"]);
 
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @YES);
   XCTAssertEqualObjects(@(message.optionalNestedEnum), [message valueForKey:@"optionalNestedEnum"]);
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignEnum"], @YES);
-  XCTAssertEqualObjects(@(message.optionalForeignEnum), [message valueForKey:@"optionalForeignEnum"]);
+  XCTAssertEqualObjects(@(message.optionalForeignEnum),
+                        [message valueForKey:@"optionalForeignEnum"]);
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportEnum"], @YES);
   XCTAssertEqualObjects(@(message.optionalImportEnum), [message valueForKey:@"optionalImportEnum"]);
 
@@ -2048,10 +2005,14 @@
   XCTAssertEqualObjects(message.repeatedUint64Array, [message valueForKey:@"repeatedUint64Array"]);
   XCTAssertEqualObjects(message.repeatedSint32Array, [message valueForKey:@"repeatedSint32Array"]);
   XCTAssertEqualObjects(message.repeatedSint64Array, [message valueForKey:@"repeatedSint64Array"]);
-  XCTAssertEqualObjects(message.repeatedFixed32Array, [message valueForKey:@"repeatedFixed32Array"]);
-  XCTAssertEqualObjects(message.repeatedFixed64Array, [message valueForKey:@"repeatedFixed64Array"]);
-  XCTAssertEqualObjects(message.repeatedSfixed32Array, [message valueForKey:@"repeatedSfixed32Array"]);
-  XCTAssertEqualObjects(message.repeatedSfixed64Array, [message valueForKey:@"repeatedSfixed64Array"]);
+  XCTAssertEqualObjects(message.repeatedFixed32Array,
+                        [message valueForKey:@"repeatedFixed32Array"]);
+  XCTAssertEqualObjects(message.repeatedFixed64Array,
+                        [message valueForKey:@"repeatedFixed64Array"]);
+  XCTAssertEqualObjects(message.repeatedSfixed32Array,
+                        [message valueForKey:@"repeatedSfixed32Array"]);
+  XCTAssertEqualObjects(message.repeatedSfixed64Array,
+                        [message valueForKey:@"repeatedSfixed64Array"]);
   XCTAssertEqualObjects(message.repeatedFloatArray, [message valueForKey:@"repeatedFloatArray"]);
   XCTAssertEqualObjects(message.repeatedDoubleArray, [message valueForKey:@"repeatedDoubleArray"]);
   XCTAssertEqualObjects(message.repeatedBoolArray, [message valueForKey:@"repeatedBoolArray"]);
@@ -2059,44 +2020,75 @@
   XCTAssertEqualObjects(message.repeatedBytesArray, [message valueForKey:@"repeatedBytesArray"]);
 
   XCTAssertEqualObjects(message.repeatedGroupArray, [message valueForKey:@"repeatedGroupArray"]);
-  XCTAssertEqualObjects(message.repeatedNestedMessageArray, [message valueForKey:@"repeatedNestedMessageArray"]);
-  XCTAssertEqualObjects(message.repeatedForeignMessageArray, [message valueForKey:@"repeatedForeignMessageArray"]);
-  XCTAssertEqualObjects(message.repeatedImportMessageArray, [message valueForKey:@"repeatedImportMessageArray"]);
+  XCTAssertEqualObjects(message.repeatedNestedMessageArray,
+                        [message valueForKey:@"repeatedNestedMessageArray"]);
+  XCTAssertEqualObjects(message.repeatedForeignMessageArray,
+                        [message valueForKey:@"repeatedForeignMessageArray"]);
+  XCTAssertEqualObjects(message.repeatedImportMessageArray,
+                        [message valueForKey:@"repeatedImportMessageArray"]);
 
-  XCTAssertEqualObjects(message.repeatedNestedEnumArray, [message valueForKey:@"repeatedNestedEnumArray"]);
-  XCTAssertEqualObjects(message.repeatedForeignEnumArray, [message valueForKey:@"repeatedForeignEnumArray"]);
-  XCTAssertEqualObjects(message.repeatedImportEnumArray, [message valueForKey:@"repeatedImportEnumArray"]);
+  XCTAssertEqualObjects(message.repeatedNestedEnumArray,
+                        [message valueForKey:@"repeatedNestedEnumArray"]);
+  XCTAssertEqualObjects(message.repeatedForeignEnumArray,
+                        [message valueForKey:@"repeatedForeignEnumArray"]);
+  XCTAssertEqualObjects(message.repeatedImportEnumArray,
+                        [message valueForKey:@"repeatedImportEnumArray"]);
 
-  XCTAssertEqualObjects(message.repeatedStringPieceArray, [message valueForKey:@"repeatedStringPieceArray"]);
+  XCTAssertEqualObjects(message.repeatedStringPieceArray,
+                        [message valueForKey:@"repeatedStringPieceArray"]);
   XCTAssertEqualObjects(message.repeatedCordArray, [message valueForKey:@"repeatedCordArray"]);
 
-  XCTAssertEqualObjects(@(message.repeatedInt32Array_Count), [message valueForKey:@"repeatedInt32Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedInt64Array_Count), [message valueForKey:@"repeatedInt64Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedUint32Array_Count), [message valueForKey:@"repeatedUint32Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedUint64Array_Count), [message valueForKey:@"repeatedUint64Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedSint32Array_Count), [message valueForKey:@"repeatedSint32Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedSint64Array_Count), [message valueForKey:@"repeatedSint64Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedFixed32Array_Count), [message valueForKey:@"repeatedFixed32Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedFixed64Array_Count), [message valueForKey:@"repeatedFixed64Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedSfixed32Array_Count), [message valueForKey:@"repeatedSfixed32Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedSfixed64Array_Count), [message valueForKey:@"repeatedSfixed64Array_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedFloatArray_Count), [message valueForKey:@"repeatedFloatArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedDoubleArray_Count), [message valueForKey:@"repeatedDoubleArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedBoolArray_Count), [message valueForKey:@"repeatedBoolArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedStringArray_Count), [message valueForKey:@"repeatedStringArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedBytesArray_Count), [message valueForKey:@"repeatedBytesArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedInt32Array_Count),
+                        [message valueForKey:@"repeatedInt32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedInt64Array_Count),
+                        [message valueForKey:@"repeatedInt64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedUint32Array_Count),
+                        [message valueForKey:@"repeatedUint32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedUint64Array_Count),
+                        [message valueForKey:@"repeatedUint64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSint32Array_Count),
+                        [message valueForKey:@"repeatedSint32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSint64Array_Count),
+                        [message valueForKey:@"repeatedSint64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFixed32Array_Count),
+                        [message valueForKey:@"repeatedFixed32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFixed64Array_Count),
+                        [message valueForKey:@"repeatedFixed64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSfixed32Array_Count),
+                        [message valueForKey:@"repeatedSfixed32Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedSfixed64Array_Count),
+                        [message valueForKey:@"repeatedSfixed64Array_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedFloatArray_Count),
+                        [message valueForKey:@"repeatedFloatArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedDoubleArray_Count),
+                        [message valueForKey:@"repeatedDoubleArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedBoolArray_Count),
+                        [message valueForKey:@"repeatedBoolArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedStringArray_Count),
+                        [message valueForKey:@"repeatedStringArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedBytesArray_Count),
+                        [message valueForKey:@"repeatedBytesArray_Count"]);
 
-  XCTAssertEqualObjects(@(message.repeatedGroupArray_Count), [message valueForKey:@"repeatedGroupArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedNestedMessageArray_Count), [message valueForKey:@"repeatedNestedMessageArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedForeignMessageArray_Count), [message valueForKey:@"repeatedForeignMessageArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedImportMessageArray_Count), [message valueForKey:@"repeatedImportMessageArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedGroupArray_Count),
+                        [message valueForKey:@"repeatedGroupArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedNestedMessageArray_Count),
+                        [message valueForKey:@"repeatedNestedMessageArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedForeignMessageArray_Count),
+                        [message valueForKey:@"repeatedForeignMessageArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedImportMessageArray_Count),
+                        [message valueForKey:@"repeatedImportMessageArray_Count"]);
 
-  XCTAssertEqualObjects(@(message.repeatedNestedEnumArray_Count), [message valueForKey:@"repeatedNestedEnumArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedForeignEnumArray_Count), [message valueForKey:@"repeatedForeignEnumArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedImportEnumArray_Count), [message valueForKey:@"repeatedImportEnumArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedNestedEnumArray_Count),
+                        [message valueForKey:@"repeatedNestedEnumArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedForeignEnumArray_Count),
+                        [message valueForKey:@"repeatedForeignEnumArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedImportEnumArray_Count),
+                        [message valueForKey:@"repeatedImportEnumArray_Count"]);
 
-  XCTAssertEqualObjects(@(message.repeatedStringPieceArray_Count), [message valueForKey:@"repeatedStringPieceArray_Count"]);
-  XCTAssertEqualObjects(@(message.repeatedCordArray_Count), [message valueForKey:@"repeatedCordArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedStringPieceArray_Count),
+                        [message valueForKey:@"repeatedStringPieceArray_Count"]);
+  XCTAssertEqualObjects(@(message.repeatedCordArray_Count),
+                        [message valueForKey:@"repeatedCordArray_Count"]);
 
   // -----------------------------------------------------------------
 
@@ -2144,8 +2136,7 @@
   XCTAssertEqualObjects(message.defaultCord, [message valueForKey:@"defaultCord"]);
 }
 
-- (void)setAllFieldsViaKVC:(TestAllTypes *)message
-             repeatedCount:(uint32_t)count {
+- (void)setAllFieldsViaKVC:(TestAllTypes *)message repeatedCount:(uint32_t)count {
   [message setValue:@101 forKey:@"optionalInt32"];
   [message setValue:@102 forKey:@"optionalInt64"];
   [message setValue:@103 forKey:@"optionalUint32"];
@@ -2160,14 +2151,12 @@
   [message setValue:@112 forKey:@"optionalDouble"];
   [message setValue:@YES forKey:@"optionalBool"];
   [message setValue:@"115" forKey:@"optionalString"];
-  [message setValue:[NSData gpbtu_dataWithEmbeddedNulls]
-             forKey:@"optionalBytes"];
+  [message setValue:[NSData gpbtu_dataWithEmbeddedNulls] forKey:@"optionalBytes"];
 
   TestAllTypes_OptionalGroup *allTypes = [TestAllTypes_OptionalGroup message];
   [allTypes setValue:@117 forKey:@"a"];
   [message setValue:allTypes forKey:@"optionalGroup"];
-  TestAllTypes_NestedMessage *nestedMessage =
-      [TestAllTypes_NestedMessage message];
+  TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
   [nestedMessage setValue:@118 forKey:@"bb"];
   [message setValue:nestedMessage forKey:@"optionalNestedMessage"];
   ForeignMessage *foreignMessage = [ForeignMessage message];
@@ -2177,8 +2166,7 @@
   [importMessage setValue:@120 forKey:@"d"];
   [message setValue:importMessage forKey:@"optionalImportMessage"];
 
-  [message setValue:@(TestAllTypes_NestedEnum_Baz)
-             forKey:@"optionalNestedEnum"];
+  [message setValue:@(TestAllTypes_NestedEnum_Baz) forKey:@"optionalNestedEnum"];
   [message setValue:@(ForeignEnum_ForeignBaz) forKey:@"optionalForeignEnum"];
   [message setValue:@(ImportEnum_ImportBaz) forKey:@"optionalImportEnum"];
 
@@ -2299,8 +2287,7 @@
 
   array = [[NSMutableArray alloc] initWithCapacity:count];
   for (uint32_t i = 0; i < count; ++i) {
-    TestAllTypes_RepeatedGroup *testAll =
-        [[TestAllTypes_RepeatedGroup alloc] init];
+    TestAllTypes_RepeatedGroup *testAll = [[TestAllTypes_RepeatedGroup alloc] init];
     [testAll setA:217 + i * 100];
     [array addObject:testAll];
     [testAll release];
@@ -2339,26 +2326,22 @@
   [array release];
 
   {
-    GPBEnumArray *scratch = [GPBEnumArray
-        arrayWithValidationFunction:TestAllTypes_NestedEnum_IsValidValue];
+    GPBEnumArray *scratch =
+        [GPBEnumArray arrayWithValidationFunction:TestAllTypes_NestedEnum_IsValidValue];
     for (uint32_t i = 0; i < count; ++i) {
-      [scratch addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar
-                                : TestAllTypes_NestedEnum_Baz];
+      [scratch addValue:(i % 2) ? TestAllTypes_NestedEnum_Bar : TestAllTypes_NestedEnum_Baz];
     }
     [message setValue:scratch forKey:@"repeatedNestedEnumArray"];
   }
   {
-    GPBEnumArray *scratch =
-        [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
+    GPBEnumArray *scratch = [GPBEnumArray arrayWithValidationFunction:ForeignEnum_IsValidValue];
     for (uint32_t i = 0; i < count; ++i) {
-      [scratch
-          addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
+      [scratch addValue:(i % 2) ? ForeignEnum_ForeignBar : ForeignEnum_ForeignBaz];
     }
     [message setValue:scratch forKey:@"repeatedForeignEnumArray"];
   }
   {
-    GPBEnumArray *scratch =
-        [GPBEnumArray arrayWithValidationFunction:ImportEnum_IsValidValue];
+    GPBEnumArray *scratch = [GPBEnumArray arrayWithValidationFunction:ImportEnum_IsValidValue];
     for (uint32_t i = 0; i < count; ++i) {
       [scratch addValue:(i % 2) ? ImportEnum_ImportBar : ImportEnum_ImportBaz];
     }
@@ -2428,8 +2411,7 @@
 
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalGroup"], @NO);
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedMessage"], @NO);
-  XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"],
-                        @NO);
+  XCTAssertEqualObjects([message valueForKey:@"hasOptionalForeignMessage"], @NO);
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalImportMessage"], @NO);
 
   XCTAssertEqualObjects([message valueForKey:@"hasOptionalNestedEnum"], @NO);
@@ -2454,8 +2436,7 @@
   XCTAssertEqualObjects([message valueForKey:@"optionalDouble"], @0);
   XCTAssertEqualObjects([message valueForKey:@"optionalBool"], @NO);
   XCTAssertEqualObjects([message valueForKey:@"optionalString"], @"");
-  XCTAssertEqualObjects([message valueForKey:@"optionalBytes"],
-                        GPBEmptyNSData());
+  XCTAssertEqualObjects([message valueForKey:@"optionalBytes"], GPBEmptyNSData());
 
   // Embedded messages should also be exist, but be clear.
   XCTAssertNotNil([message valueForKeyPath:@"optionalGroup"]);
@@ -2463,28 +2444,20 @@
   XCTAssertNotNil([message valueForKeyPath:@"optionalForeignMessage"]);
   XCTAssertNotNil([message valueForKeyPath:@"optionalImportMessage"]);
   XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.hasA"], @NO);
-  XCTAssertEqualObjects(
-      [message valueForKeyPath:@"optionalNestedMessage.hasBb"], @NO);
-  XCTAssertEqualObjects(
-      [message valueForKeyPath:@"optionalForeignMessage.hasC"], @NO);
-  XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"],
-                        @NO);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.hasBb"], @NO);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.hasC"], @NO);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.hasD"], @NO);
 
   XCTAssertEqualObjects([message valueForKeyPath:@"optionalGroup.a"], @0);
-  XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.bb"],
-                        @0);
-  XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.c"],
-                        @0);
-  XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.d"],
-                        @0);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalNestedMessage.bb"], @0);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalForeignMessage.c"], @0);
+  XCTAssertEqualObjects([message valueForKeyPath:@"optionalImportMessage.d"], @0);
 
   // Enums without defaults are set to the first value in the enum.
   XCTAssertEqualObjects([message valueForKey:@"optionalNestedEnum"],
                         @(TestAllTypes_NestedEnum_Foo));
-  XCTAssertEqualObjects([message valueForKey:@"optionalForeignEnum"],
-                        @(ForeignEnum_ForeignFoo));
-  XCTAssertEqualObjects([message valueForKey:@"optionalImportEnum"],
-                        @(ImportEnum_ImportFoo));
+  XCTAssertEqualObjects([message valueForKey:@"optionalForeignEnum"], @(ForeignEnum_ForeignFoo));
+  XCTAssertEqualObjects([message valueForKey:@"optionalImportEnum"], @(ImportEnum_ImportFoo));
 
   XCTAssertEqualObjects([message valueForKey:@"optionalStringPiece"], @"");
   XCTAssertEqualObjects([message valueForKey:@"optionalCord"], @"");
@@ -2532,12 +2505,9 @@
   XCTAssertEqualObjects([message valueForKey:@"defaultBytes"],
                         [NSData gpbtu_dataWithCString:"world"]);
 
-  XCTAssertEqualObjects([message valueForKey:@"defaultNestedEnum"],
-                        @(TestAllTypes_NestedEnum_Bar));
-  XCTAssertEqualObjects([message valueForKey:@"defaultForeignEnum"],
-                        @(ForeignEnum_ForeignBar));
-  XCTAssertEqualObjects([message valueForKey:@"defaultImportEnum"],
-                        @(ImportEnum_ImportBar));
+  XCTAssertEqualObjects([message valueForKey:@"defaultNestedEnum"], @(TestAllTypes_NestedEnum_Bar));
+  XCTAssertEqualObjects([message valueForKey:@"defaultForeignEnum"], @(ForeignEnum_ForeignBar));
+  XCTAssertEqualObjects([message valueForKey:@"defaultImportEnum"], @(ImportEnum_ImportBar));
 
   XCTAssertEqualObjects([message valueForKey:@"defaultStringPiece"], @"abc");
   XCTAssertEqualObjects([message valueForKey:@"defaultCord"], @"123");
diff --git a/objectivec/Tests/GPBUnittestProtos.m b/objectivec/Tests/GPBUnittestProtos.m
index 1c6eddf..6208e12 100644
--- a/objectivec/Tests/GPBUnittestProtos.m
+++ b/objectivec/Tests/GPBUnittestProtos.m
@@ -31,43 +31,27 @@
 // Collects all the compiled protos into one file and compiles them to make sure
 // the compiler is generating valid code.
 
-// The unittest_custom_options.proto extends the messages in descriptor.proto
-// so we build it in to test extending in general. The library doesn't provide
-// a descriptor as it doesn't use the classes/enums.
-#import "google/protobuf/Descriptor.pbobjc.m"
+#import "objectivec/Tests/AnyTest.pbobjc.m"
+#import "objectivec/Tests/MapProto2Unittest.pbobjc.m"
+#import "objectivec/Tests/MapUnittest.pbobjc.m"
+#import "objectivec/Tests/Unittest.pbobjc.m"
+#import "objectivec/Tests/UnittestCycle.pbobjc.m"
+#import "objectivec/Tests/UnittestDeprecated.pbobjc.m"
+#import "objectivec/Tests/UnittestDeprecatedFile.pbobjc.m"
+#import "objectivec/Tests/UnittestImport.pbobjc.m"
+#import "objectivec/Tests/UnittestImportPublic.pbobjc.m"
+#import "objectivec/Tests/UnittestMset.pbobjc.m"
+#import "objectivec/Tests/UnittestObjc.pbobjc.m"
+#import "objectivec/Tests/UnittestObjcOptions.pbobjc.m"
+#import "objectivec/Tests/UnittestObjcStartup.pbobjc.m"
+#import "objectivec/Tests/UnittestPreserveUnknownEnum.pbobjc.m"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.m"
+#import "objectivec/Tests/UnittestRuntimeProto3.pbobjc.m"
 
-#import "google/protobuf/AnyTest.pbobjc.m"
-#import "google/protobuf/MapProto2Unittest.pbobjc.m"
-#import "google/protobuf/MapUnittest.pbobjc.m"
-#import "google/protobuf/Unittest.pbobjc.m"
-#import "google/protobuf/UnittestArena.pbobjc.m"
-#import "google/protobuf/UnittestCustomOptions.pbobjc.m"
-#import "google/protobuf/UnittestCycle.pbobjc.m"
-#import "google/protobuf/UnittestDeprecated.pbobjc.m"
-#import "google/protobuf/UnittestDeprecatedFile.pbobjc.m"
-#import "google/protobuf/UnittestDropUnknownFields.pbobjc.m"
-#import "google/protobuf/UnittestEmbedOptimizeFor.pbobjc.m"
-#import "google/protobuf/UnittestEmpty.pbobjc.m"
-#import "google/protobuf/UnittestEnormousDescriptor.pbobjc.m"
-#import "google/protobuf/UnittestImport.pbobjc.m"
-#import "google/protobuf/UnittestImportLite.pbobjc.m"
-#import "google/protobuf/UnittestImportPublic.pbobjc.m"
-#import "google/protobuf/UnittestImportPublicLite.pbobjc.m"
-#import "google/protobuf/UnittestLite.pbobjc.m"
-#import "google/protobuf/UnittestMset.pbobjc.m"
-#import "google/protobuf/UnittestMsetWireFormat.pbobjc.m"
-#import "google/protobuf/UnittestNoGenericServices.pbobjc.m"
-#import "google/protobuf/UnittestObjc.pbobjc.m"
-#import "google/protobuf/UnittestObjcStartup.pbobjc.m"
-#import "google/protobuf/UnittestOptimizeFor.pbobjc.m"
-#import "google/protobuf/UnittestPreserveUnknownEnum.pbobjc.m"
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.m"
-#import "google/protobuf/UnittestRuntimeProto3.pbobjc.m"
-
-#import "google/protobuf/UnittestExtensionChainA.pbobjc.m"
-#import "google/protobuf/UnittestExtensionChainB.pbobjc.m"
-#import "google/protobuf/UnittestExtensionChainC.pbobjc.m"
-#import "google/protobuf/UnittestExtensionChainD.pbobjc.m"
-#import "google/protobuf/UnittestExtensionChainE.pbobjc.m"
+#import "objectivec/Tests/UnittestExtensionChainA.pbobjc.m"
+#import "objectivec/Tests/UnittestExtensionChainB.pbobjc.m"
+#import "objectivec/Tests/UnittestExtensionChainC.pbobjc.m"
+#import "objectivec/Tests/UnittestExtensionChainD.pbobjc.m"
+#import "objectivec/Tests/UnittestExtensionChainE.pbobjc.m"
 // See GPBUnittestProtos2.m for for "UnittestExtensionChainF.pbobjc.m"
-#import "google/protobuf/UnittestExtensionChainG.pbobjc.m"
+#import "objectivec/Tests/UnittestExtensionChainG.pbobjc.m"
diff --git a/objectivec/Tests/GPBUnittestProtos2.m b/objectivec/Tests/GPBUnittestProtos2.m
index ef9f070..498d85a 100644
--- a/objectivec/Tests/GPBUnittestProtos2.m
+++ b/objectivec/Tests/GPBUnittestProtos2.m
@@ -31,4 +31,4 @@
 // This one file in the chain tests is compiled by itself to ensure if was
 // generated with the extra #imports needed to pull in the indirect Root class
 // used in its Root registry.
-#import "google/protobuf/UnittestExtensionChainF.pbobjc.m"
+#import "objectivec/Tests/UnittestExtensionChainF.pbobjc.m"
diff --git a/objectivec/Tests/GPBUnknownFieldSetTest.m b/objectivec/Tests/GPBUnknownFieldSetTest.m
index 5fa60b2..b98f52e 100644
--- a/objectivec/Tests/GPBUnknownFieldSetTest.m
+++ b/objectivec/Tests/GPBUnknownFieldSetTest.m
@@ -30,9 +30,9 @@
 
 #import "GPBTestUtilities.h"
 
-#import "GPBUnknownField_PackagePrivate.h"
 #import "GPBUnknownFieldSet_PackagePrivate.h"
-#import "google/protobuf/Unittest.pbobjc.h"
+#import "GPBUnknownField_PackagePrivate.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
 
 @interface GPBUnknownFieldSet (GPBUnknownFieldSetTest)
 - (void)getTags:(int32_t*)tags;
@@ -61,7 +61,7 @@
 }
 
 - (void)testInvalidFieldNumber {
-  GPBUnknownFieldSet *set = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* set = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:0] autorelease];
   XCTAssertThrowsSpecificNamed([set addField:field], NSException, NSInvalidArgumentException);
 }
@@ -69,10 +69,10 @@
 - (void)testEqualityAndHash {
   // Empty
 
-  GPBUnknownFieldSet *set1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* set1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   XCTAssertTrue([set1 isEqual:set1]);
   XCTAssertFalse([set1 isEqual:@"foo"]);
-  GPBUnknownFieldSet *set2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* set2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   XCTAssertEqualObjects(set1, set2);
   XCTAssertEqual([set1 hash], [set2 hash]);
 
@@ -126,11 +126,11 @@
 
   // Group
 
-  GPBUnknownFieldSet *group1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* group1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* fieldGroup1 = [[[GPBUnknownField alloc] initWithNumber:10] autorelease];
   [fieldGroup1 addVarint:1];
   [group1 addField:fieldGroup1];
-  GPBUnknownFieldSet *group2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* group2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* fieldGroup2 = [[[GPBUnknownField alloc] initWithNumber:10] autorelease];
   [fieldGroup2 addVarint:1];
   [group2 addField:fieldGroup2];
@@ -153,10 +153,9 @@
 // numbers as allFieldsData except that each field is some other wire
 // type.
 - (NSData*)getBizarroData {
-  GPBUnknownFieldSet* bizarroFields =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* bizarroFields = [[[GPBUnknownFieldSet alloc] init] autorelease];
   NSUInteger count = [unknownFields_ countOfFields];
-  int32_t *tags = malloc(count * sizeof(int32_t));
+  int32_t* tags = malloc(count * sizeof(int32_t));
   if (!tags) {
     XCTFail(@"Failed to make scratch buffer for testing");
     return [NSData data];
@@ -168,20 +167,17 @@
       GPBUnknownField* field = [unknownFields_ getField:tag];
       if (field.varintList.count == 0) {
         // Original field is not a varint, so use a varint.
-        GPBUnknownField* varintField =
-            [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
+        GPBUnknownField* varintField = [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
         [varintField addVarint:1];
         [bizarroFields addField:varintField];
       } else {
         // Original field *is* a varint, so use something else.
-        GPBUnknownField* fixed32Field =
-            [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
+        GPBUnknownField* fixed32Field = [[[GPBUnknownField alloc] initWithNumber:tag] autorelease];
         [fixed32Field addFixed32:1];
         [bizarroFields addField:fixed32Field];
       }
     }
-  }
-  @finally {
+  } @finally {
     free(tags);
   }
 
@@ -220,7 +216,7 @@
   [field addLengthDelimited:DataFromCStr("data1")];
   [set1 addField:field];
 
-  GPBUnknownFieldSet *group1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* group1 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* fieldGroup1 = [[[GPBUnknownField alloc] initWithNumber:200] autorelease];
   [fieldGroup1 addVarint:100];
   [group1 addField:fieldGroup1];
@@ -246,7 +242,7 @@
   [field addLengthDelimited:DataFromCStr("data2")];
   [set2 addField:field];
 
-  GPBUnknownFieldSet *group2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* group2 = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* fieldGroup2 = [[[GPBUnknownField alloc] initWithNumber:201] autorelease];
   [fieldGroup2 addVarint:99];
   [group2 addField:fieldGroup2];
@@ -280,11 +276,11 @@
   [field addLengthDelimited:DataFromCStr("data2")];
   [set3 addField:field];
 
-  GPBUnknownFieldSet *group3a = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* group3a = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* fieldGroup3a1 = [[[GPBUnknownField alloc] initWithNumber:200] autorelease];
   [fieldGroup3a1 addVarint:100];
   [group3a addField:fieldGroup3a1];
-  GPBUnknownFieldSet *group3b = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* group3b = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* fieldGroup3b2 = [[[GPBUnknownField alloc] initWithNumber:201] autorelease];
   [fieldGroup3b2 addVarint:99];
   [group3b addField:fieldGroup3b2];
@@ -314,7 +310,7 @@
 }
 
 - (void)testClearMessage {
-  TestEmptyMessage *message = [TestEmptyMessage message];
+  TestEmptyMessage* message = [TestEmptyMessage message];
   [message mergeFrom:emptyMessage_];
   [message clear];
   XCTAssertEqual(message.serializedSize, (size_t)0);
@@ -322,9 +318,8 @@
 
 - (void)testParseKnownAndUnknown {
   // Test mixing known and unknown fields when parsing.
-  GPBUnknownFieldSet *fields = [[unknownFields_ copy] autorelease];
-  GPBUnknownField *field =
-    [[[GPBUnknownField alloc] initWithNumber:123456] autorelease];
+  GPBUnknownFieldSet* fields = [[unknownFields_ copy] autorelease];
+  GPBUnknownField* field = [[[GPBUnknownField alloc] initWithNumber:123456] autorelease];
   [field addVarint:654321];
   [fields addField:field];
 
@@ -344,10 +339,8 @@
   // when parsing.
 
   NSData* bizarroData = [self getBizarroData];
-  TestAllTypes* allTypesMessage =
-      [TestAllTypes parseFromData:bizarroData error:NULL];
-  TestEmptyMessage* emptyMessage =
-      [TestEmptyMessage parseFromData:bizarroData error:NULL];
+  TestAllTypes* allTypesMessage = [TestAllTypes parseFromData:bizarroData error:NULL];
+  TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData error:NULL];
 
   // All fields should have been interpreted as unknown, so the debug strings
   // should be the same.
@@ -361,8 +354,7 @@
   TestEmptyMessageWithExtensions* message =
       [TestEmptyMessageWithExtensions parseFromData:allFieldsData_ error:NULL];
 
-  XCTAssertEqual(unknownFields_.countOfFields,
-                 message.unknownFields.countOfFields);
+  XCTAssertEqual(unknownFields_.countOfFields, message.unknownFields.countOfFields);
   XCTAssertEqualObjects(allFieldsData_, message.data);
 }
 
@@ -371,10 +363,9 @@
   // when parsing extensions.
 
   NSData* bizarroData = [self getBizarroData];
-  TestAllExtensions* allExtensionsMessage =
-      [TestAllExtensions parseFromData:bizarroData error:NULL];
-  TestEmptyMessage* emptyMessage =
-      [TestEmptyMessage parseFromData:bizarroData error:NULL];
+  TestAllExtensions* allExtensionsMessage = [TestAllExtensions parseFromData:bizarroData
+                                                                       error:NULL];
+  TestEmptyMessage* emptyMessage = [TestEmptyMessage parseFromData:bizarroData error:NULL];
 
   // All fields should have been interpreted as unknown, so the debug strings
   // should be the same.
@@ -465,7 +456,7 @@
 
   // Group
 
-  GPBUnknownFieldSet *group = [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* group = [[[GPBUnknownFieldSet alloc] init] autorelease];
   GPBUnknownField* fieldGroup = [[[GPBUnknownField alloc] initWithNumber:100] autorelease];
   [fieldGroup addVarint:100];
   [group addField:fieldGroup];
diff --git a/objectivec/Tests/GPBUtilitiesTests.m b/objectivec/Tests/GPBUtilitiesTests.m
index f4a09de..b4d52ad 100644
--- a/objectivec/Tests/GPBUtilitiesTests.m
+++ b/objectivec/Tests/GPBUtilitiesTests.m
@@ -41,9 +41,9 @@
 #import "GPBMessage.h"
 #import "GPBUnknownField_PackagePrivate.h"
 
-#import "google/protobuf/MapUnittest.pbobjc.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestObjc.pbobjc.h"
+#import "objectivec/Tests/MapUnittest.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestObjc.pbobjc.h"
 
 @interface UtilitiesTests : GPBTestCase
 @end
@@ -62,6 +62,7 @@
 
 - (void)testGPBDecodeTextFormatName {
   uint8_t decodeData[] = {
+      // clang-format off
     0x6,
     // An inlined string (first to make sure the leading null is handled
     // correctly, and with a key of zero to check that).
@@ -80,6 +81,7 @@
     //   underscore, lower + 30 (01 op), as is + 30 (00 op), as is + 13 (00 op),
     //   underscore, as is + 3 (00 op)
     0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
+      // clang-format on
   };
   NSString *inputStr = @"abcdefghIJ";
 
@@ -104,10 +106,12 @@
   // An inlined string (and key of zero).
   XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 0, inputStr), @"zbcdefghIJ");
 
+  // clang-format off
   // Long name so multiple decode ops are needed.
   inputStr = @"longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
   XCTAssertEqualObjects(GPBDecodeTextFormatName(decodeData, 1000, inputStr),
                         @"long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+  // clang-format on
 }
 
 - (void)testTextFormat {
@@ -121,10 +125,8 @@
 
   NSString *fileName = @"text_format_unittest_data.txt";
   NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
-  NSData *expectedData =
-      [self getDataFileNamed:fileName dataToWrite:resultData];
-  NSString *expected = [[NSString alloc] initWithData:expectedData
-                                             encoding:NSUTF8StringEncoding];
+  NSData *expectedData = [self getDataFileNamed:fileName dataToWrite:resultData];
+  NSString *expected = [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding];
   XCTAssertEqualObjects(expected, result);
   [expected release];
 }
@@ -141,12 +143,14 @@
   message.subEnum = self_autorelease_RetainCount;
   message.new_p.copy_p = @"foo";
 
+  // clang-format off
   NSString *expected = @"_cmd: true\n"
                        @"isProxy: true\n"
                        @"SubEnum: retainCount\n"
                        @"New {\n"
                        @"  copy: \"foo\"\n"
                        @"}\n";
+  // clang-format on
   NSString *result = GPBTextFormatForMessage(message, nil);
   XCTAssertEqualObjects(expected, result);
 }
@@ -161,10 +165,8 @@
 
   NSString *fileName = @"text_format_map_unittest_data.txt";
   NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
-  NSData *expectedData =
-      [self getDataFileNamed:fileName dataToWrite:resultData];
-  NSString *expected = [[NSString alloc] initWithData:expectedData
-                                             encoding:NSUTF8StringEncoding];
+  NSData *expectedData = [self getDataFileNamed:fileName dataToWrite:resultData];
+  NSString *expected = [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding];
   XCTAssertEqualObjects(expected, result);
   [expected release];
 }
@@ -183,10 +185,8 @@
   // of the bracketed extension name.
   NSString *fileName = @"text_format_extensions_unittest_data.txt";
   NSData *resultData = [result dataUsingEncoding:NSUTF8StringEncoding];
-  NSData *expectedData =
-      [self getDataFileNamed:fileName dataToWrite:resultData];
-  NSString *expected = [[NSString alloc] initWithData:expectedData
-                                             encoding:NSUTF8StringEncoding];
+  NSData *expectedData = [self getDataFileNamed:fileName dataToWrite:resultData];
+  NSString *expected = [[NSString alloc] initWithData:expectedData encoding:NSUTF8StringEncoding];
   XCTAssertEqualObjects(expected, result);
   [expected release];
 }
@@ -195,7 +195,7 @@
   TestAllTypes *message = [TestAllTypes message];
 
   NSDictionary *repeatedFieldValues = @{
-    @"repeatedStringArray" : [@[@"foo", @"bar"] mutableCopy],
+    @"repeatedStringArray" : [@[ @"foo", @"bar" ] mutableCopy],
     @"repeatedBoolArray" : [GPBBoolArray arrayWithValue:YES],
     @"repeatedInt32Array" : [GPBInt32Array arrayWithValue:14],
     @"repeatedInt64Array" : [GPBInt64Array arrayWithValue:15],
@@ -208,23 +208,19 @@
                                          rawValue:TestAllTypes_NestedEnum_Foo],
   };
   for (NSString *fieldName in repeatedFieldValues) {
-    GPBFieldDescriptor *field =
-        [message.descriptor fieldWithName:fieldName];
+    GPBFieldDescriptor *field = [message.descriptor fieldWithName:fieldName];
     XCTAssertNotNil(field, @"No field with name: %@", fieldName);
     id expectedValues = repeatedFieldValues[fieldName];
     GPBSetMessageRepeatedField(message, field, expectedValues);
-    XCTAssertEqualObjects(expectedValues,
-                          [message valueForKeyPath:fieldName]);
+    XCTAssertEqualObjects(expectedValues, [message valueForKeyPath:fieldName]);
   }
 }
 
 // Helper to make an unknown field set with something in it.
 static GPBUnknownFieldSet *UnknownFieldsSetHelper(int num) {
-  GPBUnknownFieldSet *result =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet *result = [[[GPBUnknownFieldSet alloc] init] autorelease];
 
-  GPBUnknownField *field =
-      [[[GPBUnknownField alloc] initWithNumber:num] autorelease];
+  GPBUnknownField *field = [[[GPBUnknownField alloc] initWithNumber:num] autorelease];
   [field addVarint:num];
   [result addField:field];
 
@@ -246,32 +242,26 @@
     OptionalGroup_extension *optionalGroup = [OptionalGroup_extension message];
     optionalGroup.a = 123;
     optionalGroup.unknownFields = UnknownFieldsSetHelper(779);
-    [message setExtension:[UnittestRoot optionalGroupExtension]
-                    value:optionalGroup];
+    [message setExtension:[UnittestRoot optionalGroupExtension] value:optionalGroup];
 
     // Message
-    TestAllTypes_NestedMessage *nestedMessage =
-        [TestAllTypes_NestedMessage message];
+    TestAllTypes_NestedMessage *nestedMessage = [TestAllTypes_NestedMessage message];
     nestedMessage.bb = 456;
     nestedMessage.unknownFields = UnknownFieldsSetHelper(778);
-    [message setExtension:[UnittestRoot optionalNestedMessageExtension]
-                    value:nestedMessage];
+    [message setExtension:[UnittestRoot optionalNestedMessageExtension] value:nestedMessage];
 
     // Repeated Group
-    RepeatedGroup_extension *repeatedGroup =
-      [[RepeatedGroup_extension alloc] init];
+    RepeatedGroup_extension *repeatedGroup = [[RepeatedGroup_extension alloc] init];
     repeatedGroup.a = 567;
     repeatedGroup.unknownFields = UnknownFieldsSetHelper(780);
-    [message addExtension:[UnittestRoot repeatedGroupExtension]
-                    value:repeatedGroup];
+    [message addExtension:[UnittestRoot repeatedGroupExtension] value:repeatedGroup];
     [repeatedGroup release];
 
     // Repeated Message
     nestedMessage = [[TestAllTypes_NestedMessage alloc] init];
     nestedMessage.bb = 678;
     nestedMessage.unknownFields = UnknownFieldsSetHelper(781);
-    [message addExtension:[UnittestRoot repeatedNestedMessageExtension]
-                    value:nestedMessage];
+    [message addExtension:[UnittestRoot repeatedNestedMessageExtension] value:nestedMessage];
     [nestedMessage release];
   }
 
@@ -311,7 +301,8 @@
 
   {
     XCTAssertTrue([message hasExtension:[UnittestRoot repeatedNestedMessageExtension]]);
-    NSArray *repeatedNestedMessages = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
+    NSArray *repeatedNestedMessages =
+        [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
     XCTAssertEqual(repeatedNestedMessages.count, (NSUInteger)1);
     TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
     XCTAssertNotNil(repeatedNestedMessage);
@@ -358,14 +349,14 @@
 
   {
     XCTAssertTrue([message hasExtension:[UnittestRoot repeatedNestedMessageExtension]]);
-    NSArray *repeatedNestedMessages = [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
+    NSArray *repeatedNestedMessages =
+        [message getExtension:[UnittestRoot repeatedNestedMessageExtension]];
     XCTAssertEqual(repeatedNestedMessages.count, (NSUInteger)1);
     TestAllTypes_NestedMessage *repeatedNestedMessage = repeatedNestedMessages.firstObject;
     XCTAssertNotNil(repeatedNestedMessage);
     XCTAssertEqual(repeatedNestedMessage.bb, 678);
     XCTAssertNil(repeatedNestedMessage.unknownFields);
   }
-
 }
 
 - (void)testDropMessageUnknownFieldsRecursively_Maps {
@@ -414,7 +405,6 @@
     XCTAssertNotNil(foreignMessage);
     XCTAssertNil(foreignMessage.unknownFields);
   }
-
 }
 
 @end
diff --git a/objectivec/Tests/GPBWellKnownTypesTest.m b/objectivec/Tests/GPBWellKnownTypesTest.m
index 592d5af..e6ee20a 100644
--- a/objectivec/Tests/GPBWellKnownTypesTest.m
+++ b/objectivec/Tests/GPBWellKnownTypesTest.m
@@ -33,7 +33,7 @@
 #import <XCTest/XCTest.h>
 
 #import "GPBTestUtilities.h"
-#import "google/protobuf/AnyTest.pbobjc.h"
+#import "objectivec/Tests/AnyTest.pbobjc.h"
 
 // Nanosecond time accuracy
 static const NSTimeInterval kTimeAccuracy = 1e-9;
@@ -46,8 +46,7 @@
 - (void)testTimeStamp {
   // Test negative and positive values.
   NSTimeInterval values[] = {
-      -428027599.483999967, -1234567.0, -0.5, 0, 0.75, 54321.0, 2468086,483999967
-  };
+      -428027599.483999967, -1234567.0, -0.5, 0, 0.75, 54321.0, 2468086, 483999967};
   for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
     NSTimeInterval value = values[i];
 
@@ -55,30 +54,24 @@
     NSDate *date = [NSDate dateWithTimeIntervalSince1970:value];
     GPBTimestamp *timeStamp = [[GPBTimestamp alloc] initWithDate:date];
 
-    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0,
-                                @"Offset %f - Date: %@", (double)value, date);
-    XCTAssertLessThan(timeStamp.nanos, 1e9,
-                      @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0, @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertLessThan(timeStamp.nanos, 1e9, @"Offset %f - Date: %@", (double)value, date);
 
     // Comparing timeIntervals instead of directly comparing dates because date
     // equality requires the time intervals to be exactly the same, and the
     // timeintervals go through a bit of floating point error as they are
     // converted back and forth from the internal representation.
-    XCTAssertEqualWithAccuracy(value, timeStamp.date.timeIntervalSince1970,
-                               kTimeAccuracy,
+    XCTAssertEqualWithAccuracy(value, timeStamp.date.timeIntervalSince1970, kTimeAccuracy,
                                @"Offset %f - Date: %@", (double)value, date);
     [timeStamp release];
 
     // Test Creation - timeIntervalSince1970.
     timeStamp = [[GPBTimestamp alloc] initWithTimeIntervalSince1970:value];
 
-    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0,
-                                @"Offset %f - Date: %@", (double)value, date);
-    XCTAssertLessThan(timeStamp.nanos, 1e9,
-                      @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0, @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertLessThan(timeStamp.nanos, 1e9, @"Offset %f - Date: %@", (double)value, date);
 
-    XCTAssertEqualWithAccuracy(value, timeStamp.timeIntervalSince1970,
-                               kTimeAccuracy,
+    XCTAssertEqualWithAccuracy(value, timeStamp.timeIntervalSince1970, kTimeAccuracy,
                                @"Offset %f - Date: %@", (double)value, date);
     [timeStamp release];
 
@@ -86,13 +79,10 @@
     timeStamp = [[GPBTimestamp alloc] init];
     timeStamp.date = date;
 
-    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0,
-                                @"Offset %f - Date: %@", (double)value, date);
-    XCTAssertLessThan(timeStamp.nanos, 1e9,
-                      @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0, @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertLessThan(timeStamp.nanos, 1e9, @"Offset %f - Date: %@", (double)value, date);
 
-    XCTAssertEqualWithAccuracy(value, timeStamp.date.timeIntervalSince1970,
-                               kTimeAccuracy,
+    XCTAssertEqualWithAccuracy(value, timeStamp.date.timeIntervalSince1970, kTimeAccuracy,
                                @"Offset %f - Date: %@", (double)value, date);
     [timeStamp release];
 
@@ -100,13 +90,10 @@
     timeStamp = [[GPBTimestamp alloc] init];
     timeStamp.timeIntervalSince1970 = value;
 
-    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0,
-                                @"Offset %f - Date: %@", (double)value, date);
-    XCTAssertLessThan(timeStamp.nanos, 1e9,
-                      @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertGreaterThanOrEqual(timeStamp.nanos, 0, @"Offset %f - Date: %@", (double)value, date);
+    XCTAssertLessThan(timeStamp.nanos, 1e9, @"Offset %f - Date: %@", (double)value, date);
 
-    XCTAssertEqualWithAccuracy(value, timeStamp.date.timeIntervalSince1970,
-                               kTimeAccuracy,
+    XCTAssertEqualWithAccuracy(value, timeStamp.date.timeIntervalSince1970, kTimeAccuracy,
                                @"Offset %f - Date: %@", (double)value, date);
 
     [timeStamp release];
@@ -115,55 +102,45 @@
 
 - (void)testDuration {
   // Test negative and positive values.
-  NSTimeInterval values[] = { -1000.0001, -500.0, -0.5, 0, 0.75, 1000.0, 2000.0002 };
+  NSTimeInterval values[] = {-1000.0001, -500.0, -0.5, 0, 0.75, 1000.0, 2000.0002};
   for (size_t i = 0; i < GPBARRAYSIZE(values); ++i) {
     NSTimeInterval value = values[i];
 
     // Test Creation.
-    GPBDuration *duration =
-        [[GPBDuration alloc] initWithTimeInterval:value];
-    XCTAssertEqualWithAccuracy(value, duration.timeInterval, kTimeAccuracy,
-                               @"For interval %f", (double)value);
+    GPBDuration *duration = [[GPBDuration alloc] initWithTimeInterval:value];
+    XCTAssertEqualWithAccuracy(value, duration.timeInterval, kTimeAccuracy, @"For interval %f",
+                               (double)value);
     if (value > 0) {
-      XCTAssertGreaterThanOrEqual(duration.seconds, 0,
-                                  @"For interval %f", (double)value);
-      XCTAssertGreaterThanOrEqual(duration.nanos, 0,
-                                  @"For interval %f", (double)value);
+      XCTAssertGreaterThanOrEqual(duration.seconds, 0, @"For interval %f", (double)value);
+      XCTAssertGreaterThanOrEqual(duration.nanos, 0, @"For interval %f", (double)value);
     } else {
-      XCTAssertLessThanOrEqual(duration.seconds, 0,
-                               @"For interval %f", (double)value);
-      XCTAssertLessThanOrEqual(duration.nanos, 0,
-                               @"For interval %f", (double)value);
+      XCTAssertLessThanOrEqual(duration.seconds, 0, @"For interval %f", (double)value);
+      XCTAssertLessThanOrEqual(duration.nanos, 0, @"For interval %f", (double)value);
     }
     [duration release];
 
     // Test Mutation.
     duration = [[GPBDuration alloc] init];
     duration.timeInterval = value;
-    XCTAssertEqualWithAccuracy(value, duration.timeInterval, kTimeAccuracy,
-                               @"For interval %f", (double)value);
+    XCTAssertEqualWithAccuracy(value, duration.timeInterval, kTimeAccuracy, @"For interval %f",
+                               (double)value);
     if (value > 0) {
-      XCTAssertGreaterThanOrEqual(duration.seconds, 0,
-                                  @"For interval %f", (double)value);
-      XCTAssertGreaterThanOrEqual(duration.nanos, 0,
-                                  @"For interval %f", (double)value);
+      XCTAssertGreaterThanOrEqual(duration.seconds, 0, @"For interval %f", (double)value);
+      XCTAssertGreaterThanOrEqual(duration.nanos, 0, @"For interval %f", (double)value);
     } else {
-      XCTAssertLessThanOrEqual(duration.seconds, 0,
-                               @"For interval %f", (double)value);
-      XCTAssertLessThanOrEqual(duration.nanos, 0,
-                               @"For interval %f", (double)value);
+      XCTAssertLessThanOrEqual(duration.seconds, 0, @"For interval %f", (double)value);
+      XCTAssertLessThanOrEqual(duration.nanos, 0, @"For interval %f", (double)value);
     }
     [duration release];
   }
 }
 
 - (void)testAnyHelpers {
-
   // Set and extract covers most of the code.
 
-  TestAny *subMessage = [TestAny message];
+  AnyTestMessage *subMessage = [AnyTestMessage message];
   subMessage.int32Value = 12345;
-  TestAny *message = [TestAny message];
+  AnyTestMessage *message = [AnyTestMessage message];
   NSError *err = nil;
   message.anyValue = [GPBAny anyWithMessage:subMessage error:&err];
   XCTAssertNil(err);
@@ -171,14 +148,13 @@
   NSData *data = message.data;
   XCTAssertNotNil(data);
 
-  TestAny *message2 = [TestAny parseFromData:data error:&err];
+  AnyTestMessage *message2 = [AnyTestMessage parseFromData:data error:&err];
   XCTAssertNil(err);
   XCTAssertNotNil(message2);
   XCTAssertTrue(message2.hasAnyValue);
 
-  TestAny *subMessage2 =
-      (TestAny *)[message.anyValue unpackMessageClass:[TestAny class]
-                                                error:&err];
+  AnyTestMessage *subMessage2 =
+      (AnyTestMessage *)[message.anyValue unpackMessageClass:[AnyTestMessage class] error:&err];
   XCTAssertNil(err);
   XCTAssertNotNil(subMessage2);
   XCTAssertEqual(subMessage2.int32Value, 12345);
@@ -189,25 +165,22 @@
   NSData *data2 = message.data;
   XCTAssertEqualObjects(data2, data);
 
-  TestAny *subMessage3 =
-      (TestAny *)[message.anyValue unpackMessageClass:[TestAny class]
-                                                error:NULL];
+  AnyTestMessage *subMessage3 =
+      (AnyTestMessage *)[message.anyValue unpackMessageClass:[AnyTestMessage class] error:NULL];
   XCTAssertNotNil(subMessage3);
   XCTAssertEqualObjects(subMessage2, subMessage3);
 
   // Try to extract wrong type.
 
   GPBTimestamp *wrongMessage =
-      (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class]
-                                                     error:&err];
+      (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class] error:&err];
   XCTAssertNotNil(err);
   XCTAssertNil(wrongMessage);
   XCTAssertEqualObjects(err.domain, GPBWellKnownTypesErrorDomain);
   XCTAssertEqual(err.code, GPBWellKnownTypesErrorCodeTypeURLMismatch);
 
-  wrongMessage =
-      (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class]
-                                                     error:NULL];
+  wrongMessage = (GPBTimestamp *)[message.anyValue unpackMessageClass:[GPBTimestamp class]
+                                                                error:NULL];
   XCTAssertNil(wrongMessage);
 }
 
diff --git a/objectivec/Tests/GPBWireFormatTests.m b/objectivec/Tests/GPBWireFormatTests.m
index dbeab21..64456bc 100644
--- a/objectivec/Tests/GPBWireFormatTests.m
+++ b/objectivec/Tests/GPBWireFormatTests.m
@@ -33,9 +33,8 @@
 #import "GPBCodedInputStream.h"
 #import "GPBMessage_PackagePrivate.h"
 #import "GPBUnknownField_PackagePrivate.h"
-#import "google/protobuf/Unittest.pbobjc.h"
-#import "google/protobuf/UnittestMset.pbobjc.h"
-#import "google/protobuf/UnittestMsetWireFormat.pbobjc.h"
+#import "objectivec/Tests/Unittest.pbobjc.h"
+#import "objectivec/Tests/UnittestMset.pbobjc.h"
 
 @interface WireFormatTests : GPBTestCase
 @end
@@ -55,15 +54,13 @@
 }
 
 - (void)testSerializationPacked {
-  TestPackedTypes* message =
-      [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+  TestPackedTypes* message = [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
 
   NSData* rawBytes = message.data;
   [self assertFieldsInOrder:rawBytes];
   XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
 
-  TestPackedTypes* message2 =
-      [TestPackedTypes parseFromData:rawBytes error:NULL];
+  TestPackedTypes* message2 = [TestPackedTypes parseFromData:rawBytes error:NULL];
 
   [self assertPackedFieldsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
 }
@@ -73,8 +70,7 @@
   // so if we serealize a TestAllExtensions then parse it as TestAllTypes
   // it should work.
 
-  TestAllExtensions* message =
-      [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+  TestAllExtensions* message = [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
   NSData* rawBytes = message.data;
   [self assertFieldsInOrder:rawBytes];
   XCTAssertEqual(message.serializedSize, (size_t)rawBytes.length);
@@ -87,13 +83,11 @@
 - (void)testSerializePackedExtensions {
   // TestPackedTypes and TestPackedExtensions should have compatible wire
   // formats; check that they serialize to the same string.
-  TestPackedExtensions* message =
-      [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+  TestPackedExtensions* message = [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
   NSData* rawBytes = message.data;
   [self assertFieldsInOrder:rawBytes];
 
-  TestPackedTypes* message2 =
-      [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
+  TestPackedTypes* message2 = [self packedSetRepeatedCount:kGPBDefaultRepeatCount];
   NSData* rawBytes2 = message2.data;
 
   XCTAssertEqualObjects(rawBytes, rawBytes2);
@@ -117,7 +111,6 @@
   [self assertAllExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
 }
 
-
 - (void)testExtensionsSerializedSize {
   size_t allSet = [self allSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
   size_t extensionSet = [self allExtensionsSetRepeatedCount:kGPBDefaultRepeatCount].serializedSize;
@@ -126,8 +119,7 @@
 
 - (void)testParsePackedExtensions {
   // Ensure that packed extensions can be properly parsed.
-  TestPackedExtensions* message =
-      [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
+  TestPackedExtensions* message = [self packedExtensionsSetRepeatedCount:kGPBDefaultRepeatCount];
   NSData* rawBytes = message.data;
   [self assertFieldsInOrder:rawBytes];
 
@@ -137,79 +129,74 @@
                                                      extensionRegistry:registry
                                                                  error:NULL];
 
-  [self assertPackedExtensionsSet:message2
-                    repeatedCount:kGPBDefaultRepeatCount];
+  [self assertPackedExtensionsSet:message2 repeatedCount:kGPBDefaultRepeatCount];
 }
 
 const int kUnknownTypeId = 1550055;
 
 - (void)testSerializeMessageSet {
-  // Set up a TestMessageSet with two known messages and an unknown one.
-  TestMessageSet* message_set = [TestMessageSet message];
-  [[message_set getExtension:[TestMessageSetExtension1 messageSetExtension]]
-      setI:123];
-  [[message_set getExtension:[TestMessageSetExtension2 messageSetExtension]]
-      setStr:@"foo"];
+  // Set up a MSetMessage with two known messages and an unknown one.
+  MSetMessage* message_set = [MSetMessage message];
+  [[message_set getExtension:[MSetMessageExtension1 messageSetExtension]] setI:123];
+  [[message_set getExtension:[MSetMessageExtension2 messageSetExtension]] setStr:@"foo"];
   GPBUnknownField* unknownField =
       [[[GPBUnknownField alloc] initWithNumber:kUnknownTypeId] autorelease];
   [unknownField addLengthDelimited:[NSData dataWithBytes:"bar" length:3]];
-  GPBUnknownFieldSet* unknownFieldSet =
-      [[[GPBUnknownFieldSet alloc] init] autorelease];
+  GPBUnknownFieldSet* unknownFieldSet = [[[GPBUnknownFieldSet alloc] init] autorelease];
   [unknownFieldSet addField:unknownField];
   [message_set setUnknownFields:unknownFieldSet];
 
   NSData* data = [message_set data];
 
-  // Parse back using RawMessageSet and check the contents.
-  RawMessageSet* raw = [RawMessageSet parseFromData:data error:NULL];
+  // Parse back using MSetRawMessageSet and check the contents.
+  MSetRawMessageSet* raw = [MSetRawMessageSet parseFromData:data error:NULL];
 
   XCTAssertEqual([raw.unknownFields countOfFields], (NSUInteger)0);
 
   XCTAssertEqual(raw.itemArray.count, (NSUInteger)3);
   XCTAssertEqual((uint32_t)[raw.itemArray[0] typeId],
-                 [TestMessageSetExtension1 messageSetExtension].fieldNumber);
+                 [MSetMessageExtension1 messageSetExtension].fieldNumber);
   XCTAssertEqual((uint32_t)[raw.itemArray[1] typeId],
-                 [TestMessageSetExtension2 messageSetExtension].fieldNumber);
+                 [MSetMessageExtension2 messageSetExtension].fieldNumber);
   XCTAssertEqual([raw.itemArray[2] typeId], kUnknownTypeId);
 
-  TestMessageSetExtension1* message1 =
-      [TestMessageSetExtension1 parseFromData:[((RawMessageSet_Item*)raw.itemArray[0]) message]
-                                        error:NULL];
+  MSetMessageExtension1* message1 =
+      [MSetMessageExtension1 parseFromData:[((MSetRawMessageSet_Item*)raw.itemArray[0]) message]
+                                     error:NULL];
   XCTAssertEqual(message1.i, 123);
 
-  TestMessageSetExtension2* message2 =
-      [TestMessageSetExtension2 parseFromData:[((RawMessageSet_Item*)raw.itemArray[1]) message]
-                                        error:NULL];
+  MSetMessageExtension2* message2 =
+      [MSetMessageExtension2 parseFromData:[((MSetRawMessageSet_Item*)raw.itemArray[1]) message]
+                                     error:NULL];
   XCTAssertEqualObjects(message2.str, @"foo");
 
-  XCTAssertEqualObjects([raw.itemArray[2] message],
-                        [NSData dataWithBytes:"bar" length:3]);
+  XCTAssertEqualObjects([raw.itemArray[2] message], [NSData dataWithBytes:"bar" length:3]);
 }
 
 - (void)testParseMessageSet {
-  // Set up a RawMessageSet with two known messages and an unknown one.
-  RawMessageSet* raw = [RawMessageSet message];
+  // Set up a MSetRawMessageSet with two known messages and an unknown one.
+  MSetRawMessageSet* raw = [MSetRawMessageSet message];
 
   {
-    RawMessageSet_Item* item = [RawMessageSet_Item message];
-    item.typeId = [TestMessageSetExtension1 messageSetExtension].fieldNumber;
-    TestMessageSetExtension1* message = [TestMessageSetExtension1 message];
+    MSetRawMessageSet_Item* item = [MSetRawMessageSet_Item message];
+    item.typeId = [MSetMessageExtension1 messageSetExtension].fieldNumber;
+    MSetMessageExtension1* message = [MSetMessageExtension1 message];
     message.i = 123;
     item.message = [message data];
     [raw.itemArray addObject:item];
   }
 
   {
-    RawMessageSet_Item* item = [RawMessageSet_Item message];
-    item.typeId = [TestMessageSetExtension2 messageSetExtension].fieldNumber;
-    TestMessageSetExtension2* message = [TestMessageSetExtension2 message];
+    MSetRawMessageSet_Item* item = [MSetRawMessageSet_Item message];
+    item.typeId = [MSetMessageExtension2 messageSetExtension].fieldNumber;
+    MSetMessageExtension2* message = [MSetMessageExtension2 message];
     message.str = @"foo";
     item.message = [message data];
     [raw.itemArray addObject:item];
   }
 
   {
-    RawMessageSet_Item* item = [RawMessageSet_Item message];
+    MSetRawMessageSet_Item* item = [MSetRawMessageSet_Item message];
     item.typeId = kUnknownTypeId;
     item.message = [NSData dataWithBytes:"bar" length:3];
     [raw.itemArray addObject:item];
@@ -217,27 +204,20 @@
 
   NSData* data = [raw data];
 
-  // Parse as a TestMessageSet and check the contents.
-  TestMessageSet* messageSet =
-      [TestMessageSet parseFromData:data
-                  extensionRegistry:[UnittestMsetRoot extensionRegistry]
-                              error:NULL];
+  // Parse as a MSetMessage and check the contents.
+  MSetMessage* messageSet = [MSetMessage parseFromData:data
+                                     extensionRegistry:[MSetUnittestMsetRoot extensionRegistry]
+                                                 error:NULL];
 
-  XCTAssertEqual(
-      [[messageSet
-          getExtension:[TestMessageSetExtension1 messageSetExtension]] i],
-      123);
-  XCTAssertEqualObjects(
-      [[messageSet
-          getExtension:[TestMessageSetExtension2 messageSetExtension]] str],
-      @"foo");
+  XCTAssertEqual([[messageSet getExtension:[MSetMessageExtension1 messageSetExtension]] i], 123);
+  XCTAssertEqualObjects([[messageSet getExtension:[MSetMessageExtension2 messageSetExtension]] str],
+                        @"foo");
 
   XCTAssertEqual([messageSet.unknownFields countOfFields], (NSUInteger)1);
   GPBUnknownField* unknownField = [messageSet.unknownFields getField:kUnknownTypeId];
   XCTAssertNotNil(unknownField);
   XCTAssertEqual(unknownField.lengthDelimitedList.count, (NSUInteger)1);
-  XCTAssertEqualObjects(unknownField.lengthDelimitedList[0],
-                        [NSData dataWithBytes:"bar" length:3]);
+  XCTAssertEqualObjects(unknownField.lengthDelimitedList[0], [NSData dataWithBytes:"bar" length:3]);
 }
 
 - (void)assertFieldsInOrder:(NSData*)data {
diff --git a/objectivec/Tests/UnitTests-Bridging-Header.h b/objectivec/Tests/UnitTests-Bridging-Header.h
index 46292fc..c5b651c 100644
--- a/objectivec/Tests/UnitTests-Bridging-Header.h
+++ b/objectivec/Tests/UnitTests-Bridging-Header.h
@@ -1,6 +1,37 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2008 Google Inc.  All rights reserved.
+// https://developers.google.com/protocol-buffers/
 //
-//  Use this file to import your target's public headers that you would like to expose to Swift.
+// 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.
+
+//
+//  Use this file to import your target's public headers that you would like to
+//  expose to Swift.
 //
 
-#import "google/protobuf/UnittestRuntimeProto2.pbobjc.h"
-#import "google/protobuf/UnittestRuntimeProto3.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto2.pbobjc.h"
+#import "objectivec/Tests/UnittestRuntimeProto3.pbobjc.h"
diff --git a/src/google/protobuf/util/internal/testdata/proto3.proto b/objectivec/Tests/any_test.proto
similarity index 85%
copy from src/google/protobuf/util/internal/testdata/proto3.proto
copy to objectivec/Tests/any_test.proto
index 01434b0..f2461bf 100644
--- a/src/google/protobuf/util/internal/testdata/proto3.proto
+++ b/objectivec/Tests/any_test.proto
@@ -30,13 +30,15 @@
 
 syntax = "proto3";
 
-package proto_util_converter.testing;
+package objc.protobuf.tests.any;
 
-message Proto3Message {
-  enum NestedEnum {
-    FOO = 0;
-    BAR = 1;
-    BAZ = 2;
-  }
-  NestedEnum enum_value = 1;
+import "google/protobuf/any.proto";
+
+option objc_class_prefix = "Any";
+
+message TestMessage {
+  int32 int32_value = 1;
+  google.protobuf.Any any_value = 2;
+  repeated google.protobuf.Any repeated_any_value = 3;
+  string text = 4;
 }
diff --git a/objectivec/Tests/expected_prefixes.txt b/objectivec/Tests/expected_prefixes.txt
new file mode 100644
index 0000000..1665ab1
--- /dev/null
+++ b/objectivec/Tests/expected_prefixes.txt
@@ -0,0 +1,12 @@
+objc.protobuf.tests = ""  # Explicit empty prefix
+objc.protobuf.tests.any = Any
+objc.protobuf.tests.chain = Chain
+objc.protobuf.tests.cycle = Cycle
+objc.protobuf.tests.deprecated = Dep
+objc.protobuf.tests.deprecated_file = FileDep
+objc.protobuf.tests.import = Import
+objc.protobuf.tests.mset = MSet
+objc.protobuf.tests.options = GPBTEST
+objc.protobuf.tests.proto3_preserve_unknown_enum = UnknownEnums
+objc.protobuf.tests.public_import = PublicImport
+objc.protobuf.tests.startup = TestObjCStartup
diff --git a/objectivec/Tests/map_proto2_unittest.proto b/objectivec/Tests/map_proto2_unittest.proto
new file mode 100644
index 0000000..d7b494c
--- /dev/null
+++ b/objectivec/Tests/map_proto2_unittest.proto
@@ -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.
+
+syntax = "proto2";
+
+import "objectivec/Tests/unittest_import.proto";
+
+package objc.protobuf.tests;
+
+// Explicit empty prefix, tests some validations code paths also.
+option objc_class_prefix = "";
+
+enum Proto2MapEnum {
+  PROTO2_MAP_ENUM_FOO   = 0;
+  PROTO2_MAP_ENUM_BAR   = 1;
+  PROTO2_MAP_ENUM_BAZ   = 2;
+}
+
+enum Proto2MapEnumPlusExtra {
+  E_PROTO2_MAP_ENUM_FOO   = 0;
+  E_PROTO2_MAP_ENUM_BAR   = 1;
+  E_PROTO2_MAP_ENUM_BAZ   = 2;
+  E_PROTO2_MAP_ENUM_EXTRA = 3;
+}
+
+message TestEnumMap {
+  map<int32, Proto2MapEnum> known_map_field = 101;
+  map<int32, Proto2MapEnum> unknown_map_field = 102;
+}
+
+message TestEnumMapPlusExtra {
+  map<int32, Proto2MapEnumPlusExtra> known_map_field = 101;
+  map<int32, Proto2MapEnumPlusExtra> unknown_map_field = 102;
+}
+
+message TestImportEnumMap {
+  map<int32, objc.protobuf.tests.import.EnumForMap> import_enum_amp = 1;
+}
+
+message TestIntIntMap {
+  map<int32, int32> m = 1;
+}
+
+// Test all key types: string, plus the non-floating-point scalars.
+message TestMaps {
+  map<int32, TestIntIntMap> m_int32 = 1;
+  map<int64, TestIntIntMap> m_int64 = 2;
+  map<uint32, TestIntIntMap> m_uint32 = 3;
+  map<uint64, TestIntIntMap> m_uint64 = 4;
+  map<sint32, TestIntIntMap> m_sint32 = 5;
+  map<sint64, TestIntIntMap> m_sint64 = 6;
+  map<fixed32, TestIntIntMap> m_fixed32 = 7;
+  map<fixed64, TestIntIntMap> m_fixed64 = 8;
+  map<sfixed32, TestIntIntMap> m_sfixed32 = 9;
+  map<sfixed64, TestIntIntMap> m_sfixed64 = 10;
+  map<bool, TestIntIntMap> m_bool = 11;
+  map<string, TestIntIntMap> m_string = 12;
+}
+
+// Test maps in submessages.
+message TestSubmessageMaps {
+  optional TestMaps m = 1;
+}
diff --git a/objectivec/Tests/map_unittest.proto b/objectivec/Tests/map_unittest.proto
new file mode 100644
index 0000000..ba41439
--- /dev/null
+++ b/objectivec/Tests/map_unittest.proto
@@ -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.
+
+syntax = "proto3";
+
+import "objectivec/Tests/unittest.proto";
+
+package objc.protobuf.tests;
+
+// Explicit empty prefix, tests some validations code paths also.
+option objc_class_prefix = "";
+
+// 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<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;
+}
+
+message TestMapSubmessage {
+  TestMap test_map = 1;
+}
+
+message TestMessageMap {
+  map<int32, TestAllTypes> map_int32_message = 1;
+}
+
+// Two map fields share the same entry default instance.
+message TestSameTypeMap {
+  map<int32, int32> map1 = 1;
+  map<int32, int32> map2 = 2;
+}
+
+
+enum MapEnum {
+  MAP_ENUM_FOO = 0;
+  MAP_ENUM_BAR = 1;
+  MAP_ENUM_BAZ = 2;
+}
+
+// Test embedded message with required fields
+message TestRequiredMessageMap {
+  map<int32, TestRequired> map_field = 1;
+}
+
+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<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;
+}
+
+// Previously, message containing enum called Type cannot be used as value of
+// map field.
+message MessageContainingEnumCalledType {
+  enum Type { TYPE_FOO = 0; }
+  map<string, MessageContainingEnumCalledType> type = 1;
+}
+
+// Previously, message cannot contain map field called "entry".
+message MessageContainingMapCalledEntry {
+  map<int32, int32> entry = 1;
+}
+
+message TestRecursiveMapMessage {
+  map<string, TestRecursiveMapMessage> a = 1;
+}
diff --git a/objectivec/Tests/unittest.proto b/objectivec/Tests/unittest.proto
new file mode 100644
index 0000000..31353b4
--- /dev/null
+++ b/objectivec/Tests/unittest.proto
@@ -0,0 +1,1536 @@
+// 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: ALLOW_GROUPS, LEGACY_NAMES
+
+syntax = "proto2";
+
+import "objectivec/Tests/unittest_import.proto";
+
+// Explicit empty prefix, tests some validations code paths also.
+option objc_class_prefix = "";
+
+package objc.protobuf.tests;
+
+// 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 objc.protobuf.tests.import.Message   optional_import_message  = 20;
+
+  optional NestedEnum                           optional_nested_enum     = 21;
+  optional ForeignEnum                          optional_foreign_enum    = 22;
+  optional objc.protobuf.tests.import.Enum      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 objc.protobuf.tests.public_import.Message
+      optional_public_import_message = 26;
+
+  optional NestedMessage optional_lazy_message = 27 [lazy=true];
+  optional NestedMessage optional_unverified_lazy_message = 28 [unverified_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 objc.protobuf.tests.import.Message   repeated_import_message  = 50;
+
+  repeated NestedEnum                           repeated_nested_enum     = 51;
+  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+  repeated objc.protobuf.tests.import.Enum      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 objc.protobuf.tests.import.Enum
+      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;
+  }
+}
+
+// This proto includes a recursively nested message.
+message NestedTestAllTypes {
+  optional NestedTestAllTypes child = 1;
+  optional TestAllTypes payload = 2;
+  repeated NestedTestAllTypes repeated_child = 3;
+  optional NestedTestAllTypes lazy_child = 4 [lazy=true];
+  optional TestAllTypes eager_child = 5 [lazy=false];
+}
+
+message TestDeprecatedFields {
+  optional int32 deprecated_int32 = 1 [deprecated=true];
+  oneof oneof_fields {
+    int32 deprecated_int32_in_oneof = 2 [deprecated=true];
+  }
+}
+
+message TestDeprecatedMessage {
+  option deprecated = true;
+}
+
+// Define these after TestAllTypes to make sure the compiler can handle
+// that.
+message ForeignMessage {
+  optional int32 c = 1;
+  optional int32 d = 2;
+}
+
+enum ForeignEnum {
+  FOREIGN_FOO = 4;
+  FOREIGN_BAR = 5;
+  FOREIGN_BAZ = 6;
+}
+
+message TestReservedFields {
+  reserved 2, 15, 9 to 11;
+  reserved "bar", "baz";
+}
+
+enum TestReservedEnumFields {
+  UNKNOWN = 0;
+  reserved 2, 15, 9 to 11;
+  reserved "bar", "baz";
+}
+
+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 objc.protobuf.tests.import.Message
+    optional_import_message_extension = 20;
+
+  optional TestAllTypes.NestedEnum optional_nested_enum_extension = 21;
+  optional ForeignEnum optional_foreign_enum_extension = 22;
+  optional objc.protobuf.tests.import.Enum
+    optional_import_enum_extension = 23;
+
+  optional string optional_string_piece_extension = 24 [ctype=STRING_PIECE];
+  optional string optional_cord_extension = 25 [ctype=CORD];
+
+  optional objc.protobuf.tests.public_import.Message
+    optional_public_import_message_extension = 26;
+
+  optional TestAllTypes.NestedMessage
+    optional_lazy_message_extension = 27 [lazy=true];
+  optional TestAllTypes.NestedMessage
+    optional_unverified_lazy_message_extension = 28 [unverified_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 objc.protobuf.tests.import.Message
+    repeated_import_message_extension = 50;
+
+  repeated TestAllTypes.NestedEnum repeated_nested_enum_extension = 51;
+  repeated ForeignEnum repeated_foreign_enum_extension = 52;
+  repeated objc.protobuf.tests.import.Enum
+    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 objc.protobuf.tests.import.Enum
+    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"];
+
+  // For oneof test
+  optional uint32 oneof_uint32_extension = 111;
+  optional TestAllTypes.NestedMessage oneof_nested_message_extension = 112;
+  optional string oneof_string_extension = 113;
+  optional bytes oneof_bytes_extension = 114;
+}
+
+message TestMixedFieldsAndExtensions {
+  optional int32 a = 1;
+  repeated fixed32 b = 3;
+  extensions 2, 4;
+  extend TestMixedFieldsAndExtensions {
+    optional int32 c = 2;
+    repeated fixed32 d = 4;
+  }
+}
+
+message TestGroup {
+  optional group OptionalGroup = 16 {
+    optional int32 a = 17;
+  }
+  optional ForeignEnum optional_foreign_enum = 22;
+}
+
+message TestGroupExtension {
+  extensions 1 to max;
+}
+
+message TestNestedExtension {
+  extend TestAllExtensions {
+    // Check for bug where string extensions declared in tested scope did not
+    // compile.
+    optional string test = 1002 [default="test"];
+    // Used to test if generated extension name is correct when there are
+    // underscores.
+    optional string nested_string_extension = 1003;
+  }
+
+  extend TestGroupExtension {
+    optional group OptionalGroup_extension = 16 {
+      optional int32 a = 17;
+    }
+    optional ForeignEnum optional_foreign_enum_extension = 22;
+  }
+}
+
+message TestChildExtension {
+  optional string a = 1;
+  optional string b = 2;
+  optional TestAllExtensions optional_extension = 3;
+}
+
+// Emulates wireformat data of TestChildExtension with dynamic extension
+// (DynamicExtension).
+message TestChildExtensionData {
+  message NestedTestAllExtensionsData {
+    message NestedDynamicExtensions {
+      optional int32 a = 1;
+      optional int32 b = 2;
+    }
+    optional NestedDynamicExtensions dynamic = 409707008;
+  }
+  optional string a = 1;
+  optional string b = 2;
+  optional NestedTestAllExtensionsData optional_extension = 3;
+}
+
+message TestNestedChildExtension {
+  optional int32 a = 1;
+  optional TestChildExtension child = 2;
+}
+
+// Emulates wireformat data of TestNestedChildExtension with dynamic extension
+// (DynamicExtension).
+message TestNestedChildExtensionData {
+  optional int32 a = 1;
+  optional TestChildExtensionData child = 2;
+}
+
+// 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;
+
+  // Add an optional child message to make this non-trivial for go/pdlazy.
+  optional ForeignMessage optional_foreign = 34;
+}
+
+message TestRequiredForeign {
+  optional TestRequired optional_message = 1;
+  repeated TestRequired repeated_message = 2;
+  optional int32 dummy = 3;
+
+  // Missing required fields must not affect verification of child messages.
+  optional NestedTestAllTypes optional_lazy_message = 4 [lazy = true];
+}
+
+message TestRequiredMessage {
+  optional TestRequired optional_message = 1;
+  repeated TestRequired repeated_message = 2;
+  required TestRequired required_message = 3;
+}
+
+message TestNestedRequiredForeign {
+  optional TestNestedRequiredForeign child = 1;
+  optional TestRequiredForeign payload = 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;
+}
+
+// Needed for a Python test.
+message TestPickleNestedMessage {
+  message NestedMessage {
+    optional int32 bb = 1;
+    message NestedNestedMessage {
+      optional int32 cc = 1;
+    }
+  }
+}
+
+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 {
+  message SubMessage {
+    optional TestMutualRecursionB b = 1;
+  }
+  optional TestMutualRecursionB bb = 1;
+  optional group SubGroup = 2 {
+    optional SubMessage sub_message = 3;  // Needed because of bug in javatest
+    optional TestAllTypes not_in_this_scc = 4;
+  }
+}
+
+message TestMutualRecursionB {
+  optional TestMutualRecursionA a = 1;
+  optional int32 optional_int32 = 2;
+}
+
+message TestIsInitialized {
+  message SubMessage {
+    optional group SubGroup = 1 {
+      required int32 i = 2;
+    }
+  }
+  optional SubMessage sub_message = 1;
+}
+
+// Test that groups have disjoint field numbers from their siblings and
+// parents.  This is NOT possible in proto1; only google.protobuf.  When attempting
+// to compile with proto1, this will emit an error; so we only include it
+// in objc.protobuf.tests_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];
+}
+message TestEagerMaybeLazy {
+  message NestedMessage {
+    optional TestPackedTypes packed = 1;
+  }
+  optional TestAllTypes message_foo = 1;
+  optional TestAllTypes message_bar = 2;
+  optional NestedMessage message_baz = 3;
+}
+// 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;
+  message NestedMessage {
+    optional int64 oo = 2;
+    // 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;
+  }
+
+  optional NestedMessage optional_nested_message  = 200;
+}
+
+extend TestFieldOrderings {
+  optional string my_extension_string = 50;
+  optional int32 my_extension_int = 5;
+}
+
+message TestExtensionOrderings1 {
+  extend TestFieldOrderings {
+    optional TestExtensionOrderings1 test_ext_orderings1 = 13;
+  }
+  optional string my_string = 1;
+}
+
+message TestExtensionOrderings2 {
+  extend TestFieldOrderings {
+    optional TestExtensionOrderings2 test_ext_orderings2 = 12;
+  }
+  message TestExtensionOrderings3 {
+    extend TestFieldOrderings {
+      optional TestExtensionOrderings3 test_ext_orderings3 = 14;
+    }
+    optional string my_string = 1;
+  }
+  optional string my_string = 1;
+}
+
+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"];
+  optional string replacement_string     = 27 [default="${unknown}"];
+}
+
+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;
+}
+
+message ManyOptionalString {
+  optional string str1 = 1;
+  optional string str2 = 2;
+  optional string str3 = 3;
+  optional string str4 = 4;
+  optional string str5 = 5;
+  optional string str6 = 6;
+  optional string str7 = 7;
+  optional string str8 = 8;
+  optional string str9 = 9;
+  optional string str10 = 10;
+  optional string str11 = 11;
+  optional string str12 = 12;
+  optional string str13 = 13;
+  optional string str14 = 14;
+  optional string str15 = 15;
+  optional string str16 = 16;
+  optional string str17 = 17;
+  optional string str18 = 18;
+  optional string str19 = 19;
+  optional string str20 = 20;
+  optional string str21 = 21;
+  optional string str22 = 22;
+  optional string str23 = 23;
+  optional string str24 = 24;
+  optional string str25 = 25;
+  optional string str26 = 26;
+  optional string str27 = 27;
+  optional string str28 = 28;
+  optional string str29 = 29;
+  optional string str30 = 30;
+  optional string str31 = 31;
+  optional string str32 = 32;
+}
+
+// Test int32, uint32, int64, uint64, and bool are all compatible
+message Int32Message {
+  optional int32 data = 1;
+}
+
+message Uint32Message {
+  optional uint32 data = 1;
+}
+
+message Int64Message {
+  optional int64 data = 1;
+}
+
+message Uint64Message {
+  optional uint64 data = 1;
+}
+
+message BoolMessage {
+  optional bool data = 1;
+}
+
+// Test oneofs.
+message TestOneof {
+  oneof foo {
+    int32 foo_int = 1;
+    string foo_string = 2;
+    TestAllTypes foo_message = 3;
+    group FooGroup = 4 {
+      optional int32 a = 5;
+      optional string b = 6;
+    }
+  }
+}
+
+message TestOneofBackwardsCompatible {
+  optional int32 foo_int = 1;
+  optional string foo_string = 2;
+  optional TestAllTypes foo_message = 3;
+  optional group FooGroup = 4 {
+    optional int32 a = 5;
+    optional string b = 6;
+  }
+}
+
+message TestOneof2 {
+  oneof foo {
+    int32 foo_int = 1;
+    string foo_string = 2;
+    string foo_cord = 3 [ctype=CORD];
+    string foo_string_piece = 4 [ctype=STRING_PIECE];
+    bytes foo_bytes = 5;
+    NestedEnum foo_enum = 6;
+    NestedMessage foo_message = 7;
+    group FooGroup = 8 {
+      optional int32 a = 9;
+      optional string b = 10;
+    }
+    NestedMessage foo_lazy_message = 11 [lazy=true];
+  }
+
+  oneof bar {
+    int32 bar_int = 12 [default = 5];
+    string bar_string = 13 [default = "STRING"];
+    string bar_cord = 14 [ctype=CORD, default = "CORD"];
+    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;
+  optional string baz_string = 19 [default = "BAZ"];
+
+  message NestedMessage {
+    optional int64 moo_int = 1;
+    repeated int32 corge_int = 2;
+  }
+
+  enum NestedEnum {
+    FOO = 1;
+    BAR = 2;
+    BAZ = 3;
+  }
+}
+
+message TestRequiredOneof {
+  oneof foo {
+    int32 foo_int = 1;
+    string foo_string = 2;
+    NestedMessage foo_message = 3;
+  }
+  message NestedMessage {
+    required double required_double = 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];
+}
+
+message TestUnpackedExtensions {
+  extensions 1 to max;
+}
+
+extend TestUnpackedExtensions {
+  repeated    int32 unpacked_int32_extension    =  90 [packed = false];
+  repeated    int64 unpacked_int64_extension    =  91 [packed = false];
+  repeated   uint32 unpacked_uint32_extension   =  92 [packed = false];
+  repeated   uint64 unpacked_uint64_extension   =  93 [packed = false];
+  repeated   sint32 unpacked_sint32_extension   =  94 [packed = false];
+  repeated   sint64 unpacked_sint64_extension   =  95 [packed = false];
+  repeated  fixed32 unpacked_fixed32_extension  =  96 [packed = false];
+  repeated  fixed64 unpacked_fixed64_extension  =  97 [packed = false];
+  repeated sfixed32 unpacked_sfixed32_extension =  98 [packed = false];
+  repeated sfixed64 unpacked_sfixed64_extension =  99 [packed = false];
+  repeated    float unpacked_float_extension    = 100 [packed = false];
+  repeated   double unpacked_double_extension   = 101 [packed = false];
+  repeated     bool unpacked_bool_extension     = 102 [packed = false];
+  repeated ForeignEnum unpacked_enum_extension  = 103 [packed = false];
+}
+
+// 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;
+  }
+}
+
+// Test that the correct exception is thrown by parseFrom in a corner case
+// involving merging, extensions, and required fields.
+message TestMergeException {
+  optional TestAllExtensions all_extensions = 1;
+}
+
+message TestCommentInjectionMessage {
+  // */ <- This should not close the generated doc comment
+  optional string a = 1 [default="*/ <- Neither should this."];
+}
+
+// Used to check that the c++ code generator re-orders messages to reduce
+// padding.
+message TestMessageSize {
+  optional bool m1 = 1;
+  optional int64 m2 = 2;
+  optional bool m3 = 3;
+  optional string m4 = 4;
+  optional int32 m5 = 5;
+  optional int64 m6 = 6;
+}
+
+
+// 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 {}
+
+message TestJsonName {
+  optional int32 field_name1 = 1;
+  optional int32 fieldName2 = 2;
+  optional int32 FieldName3 = 3;
+  optional int32 _field_name4 = 4;
+  optional int32 FIELD_NAME5 = 5;
+  optional int32 field_name6 = 6 [json_name = "@type"];
+  optional int32 fieldname7 = 7;
+}
+
+message TestHugeFieldNumbers {
+  optional int32 optional_int32 = 536870000;
+  optional int32 fixed_32 = 536870001;
+  repeated int32 repeated_int32 = 536870002 [packed = false];
+  repeated int32 packed_int32 = 536870003 [packed = true];
+
+  optional ForeignEnum optional_enum = 536870004;
+  optional string optional_string = 536870005;
+  optional bytes optional_bytes = 536870006;
+  optional ForeignMessage optional_message = 536870007;
+
+  optional group OptionalGroup = 536870008 {
+    optional int32 group_a = 536870009;
+  }
+
+  map<string, string> string_string_map = 536870010;
+
+  oneof oneof_field {
+    uint32 oneof_uint32 = 536870011;
+    TestAllTypes oneof_test_all_types = 536870012;
+    string oneof_string = 536870013;
+    bytes oneof_bytes = 536870014;
+  }
+
+  extensions  536860000 to 536869999;
+}
+
+extend TestHugeFieldNumbers {
+  optional TestAllTypes test_all_types = 536860000;
+}
+
+message TestExtensionInsideTable {
+  optional int32 field1 = 1;
+  optional int32 field2 = 2;
+  optional int32 field3 = 3;
+  optional int32 field4 = 4;
+  extensions 5 to 5;
+  optional int32 field6 = 6;
+  optional int32 field7 = 7;
+  optional int32 field8 = 8;
+  optional int32 field9 = 9;
+  optional int32 field10 = 10;
+}
+
+extend TestExtensionInsideTable {
+  optional int32 test_extension_inside_table_extension = 5;
+}
+
+// NOTE(b/202996544): Intentionally nested to mirror go/glep.
+message TestNestedGroupExtensionOuter {
+  optional group Layer1OptionalGroup = 1 {
+    repeated group Layer2RepeatedGroup = 2 {
+      extensions 3
+        // NOTE: extension metadata is not supported due to targets such as
+        // `//third_party/protobuf_legacy_opensource/src:shell_scripts_test`,
+        // eee https://screenshot.googleplex.com/Axz2QD8nxjdpyFF
+        //[metadata = {
+        // NOTE: can't write type there due to some clever build gen code at
+        // http://google3/net/proto2/internal/BUILD;l=1247;rcl=411090862
+        // type: "objc.protobuf.tests.TestNestedGroupExtensionInnerExtension",
+        // name: "inner",
+        // }]
+        ;
+      optional string another_field = 6;
+    }
+    repeated group Layer2AnotherOptionalRepeatedGroup = 4 {
+      optional string but_why_tho = 5;
+    }
+  }
+}
+
+message TestNestedGroupExtensionInnerExtension {
+  optional string inner_name= 1;
+}
+
+extend TestNestedGroupExtensionOuter.Layer1OptionalGroup.Layer2RepeatedGroup {
+  optional TestNestedGroupExtensionInnerExtension inner = 3;
+}
+
+enum VeryLargeEnum {
+  ENUM_LABEL_DEFAULT = 0;
+  ENUM_LABEL_1 = 1;
+  ENUM_LABEL_2 = 2;
+  ENUM_LABEL_3 = 3;
+  ENUM_LABEL_4 = 4;
+  ENUM_LABEL_5 = 5;
+  ENUM_LABEL_6 = 6;
+  ENUM_LABEL_7 = 7;
+  ENUM_LABEL_8 = 8;
+  ENUM_LABEL_9 = 9;
+  ENUM_LABEL_10 = 10;
+  ENUM_LABEL_11 = 11;
+  ENUM_LABEL_12 = 12;
+  ENUM_LABEL_13 = 13;
+  ENUM_LABEL_14 = 14;
+  ENUM_LABEL_15 = 15;
+  ENUM_LABEL_16 = 16;
+  ENUM_LABEL_17 = 17;
+  ENUM_LABEL_18 = 18;
+  ENUM_LABEL_19 = 19;
+  ENUM_LABEL_20 = 20;
+  ENUM_LABEL_21 = 21;
+  ENUM_LABEL_22 = 22;
+  ENUM_LABEL_23 = 23;
+  ENUM_LABEL_24 = 24;
+  ENUM_LABEL_25 = 25;
+  ENUM_LABEL_26 = 26;
+  ENUM_LABEL_27 = 27;
+  ENUM_LABEL_28 = 28;
+  ENUM_LABEL_29 = 29;
+  ENUM_LABEL_30 = 30;
+  ENUM_LABEL_31 = 31;
+  ENUM_LABEL_32 = 32;
+  ENUM_LABEL_33 = 33;
+  ENUM_LABEL_34 = 34;
+  ENUM_LABEL_35 = 35;
+  ENUM_LABEL_36 = 36;
+  ENUM_LABEL_37 = 37;
+  ENUM_LABEL_38 = 38;
+  ENUM_LABEL_39 = 39;
+  ENUM_LABEL_40 = 40;
+  ENUM_LABEL_41 = 41;
+  ENUM_LABEL_42 = 42;
+  ENUM_LABEL_43 = 43;
+  ENUM_LABEL_44 = 44;
+  ENUM_LABEL_45 = 45;
+  ENUM_LABEL_46 = 46;
+  ENUM_LABEL_47 = 47;
+  ENUM_LABEL_48 = 48;
+  ENUM_LABEL_49 = 49;
+  ENUM_LABEL_50 = 50;
+  ENUM_LABEL_51 = 51;
+  ENUM_LABEL_52 = 52;
+  ENUM_LABEL_53 = 53;
+  ENUM_LABEL_54 = 54;
+  ENUM_LABEL_55 = 55;
+  ENUM_LABEL_56 = 56;
+  ENUM_LABEL_57 = 57;
+  ENUM_LABEL_58 = 58;
+  ENUM_LABEL_59 = 59;
+  ENUM_LABEL_60 = 60;
+  ENUM_LABEL_61 = 61;
+  ENUM_LABEL_62 = 62;
+  ENUM_LABEL_63 = 63;
+  ENUM_LABEL_64 = 64;
+  ENUM_LABEL_65 = 65;
+  ENUM_LABEL_66 = 66;
+  ENUM_LABEL_67 = 67;
+  ENUM_LABEL_68 = 68;
+  ENUM_LABEL_69 = 69;
+  ENUM_LABEL_70 = 70;
+  ENUM_LABEL_71 = 71;
+  ENUM_LABEL_72 = 72;
+  ENUM_LABEL_73 = 73;
+  ENUM_LABEL_74 = 74;
+  ENUM_LABEL_75 = 75;
+  ENUM_LABEL_76 = 76;
+  ENUM_LABEL_77 = 77;
+  ENUM_LABEL_78 = 78;
+  ENUM_LABEL_79 = 79;
+  ENUM_LABEL_80 = 80;
+  ENUM_LABEL_81 = 81;
+  ENUM_LABEL_82 = 82;
+  ENUM_LABEL_83 = 83;
+  ENUM_LABEL_84 = 84;
+  ENUM_LABEL_85 = 85;
+  ENUM_LABEL_86 = 86;
+  ENUM_LABEL_87 = 87;
+  ENUM_LABEL_88 = 88;
+  ENUM_LABEL_89 = 89;
+  ENUM_LABEL_90 = 90;
+  ENUM_LABEL_91 = 91;
+  ENUM_LABEL_92 = 92;
+  ENUM_LABEL_93 = 93;
+  ENUM_LABEL_94 = 94;
+  ENUM_LABEL_95 = 95;
+  ENUM_LABEL_96 = 96;
+  ENUM_LABEL_97 = 97;
+  ENUM_LABEL_98 = 98;
+  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;
+  }
+}
+
+message TestVerifyInt32Simple {
+    optional int32 optional_int32_1 = 1;
+    optional int32 optional_int32_2 = 2;
+    optional int32 optional_int32_63 = 63;
+    optional int32 optional_int32_64 = 64;
+}
+
+message TestVerifyInt32 {
+    optional int32 optional_int32_1 = 1;
+    optional int32 optional_int32_2 = 2;
+    optional int32 optional_int32_63 = 63;
+    optional int32 optional_int32_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyMostlyInt32 {
+    optional int64 optional_int64_30 = 30;
+
+    optional int32 optional_int32_1 = 1;
+    optional int32 optional_int32_2 = 2;
+    optional int32 optional_int32_3 = 3;
+    optional int32 optional_int32_4 = 4;
+    optional int32 optional_int32_63 = 63;
+    optional int32 optional_int32_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyMostlyInt32BigFieldNumber {
+    optional int64 optional_int64_30 = 30;
+    optional int32 optional_int32_300 = 300;
+
+    optional int32 optional_int32_1 = 1;
+    optional int32 optional_int32_2 = 2;
+    optional int32 optional_int32_3 = 3;
+    optional int32 optional_int32_4 = 4;
+    optional int32 optional_int32_63 = 63;
+    optional int32 optional_int32_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyUint32Simple {
+    optional uint32 optional_uint32_1 = 1;
+    optional uint32 optional_uint32_2 = 2;
+    optional uint32 optional_uint32_63 = 63;
+    optional uint32 optional_uint32_64 = 64;
+}
+
+message TestVerifyUint32 {
+    optional uint32 optional_uint32_1 = 1;
+    optional uint32 optional_uint32_2 = 2;
+    optional uint32 optional_uint32_63 = 63;
+    optional uint32 optional_uint32_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyOneUint32 {
+    optional uint32 optional_uint32_1 = 1;
+    optional int32 optional_int32_2 = 2;
+    optional int32 optional_int32_63 = 63;
+    optional int32 optional_int32_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyOneInt32BigFieldNumber {
+    optional int32 optional_int32_65 = 65;
+
+    optional int64 optional_int64_1 = 1;
+    optional int64 optional_int64_2 = 2;
+    optional int64 optional_int64_63 = 63;
+    optional int64 optional_int64_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyInt32BigFieldNumber {
+    optional int32 optional_int32_1000 = 1000;
+    optional int32 optional_int32_65 = 65;
+
+    optional int32 optional_int32_1 = 1;
+    optional int32 optional_int32_2 = 2;
+    optional int32 optional_int32_63 = 63;
+    optional int32 optional_int32_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyUint32BigFieldNumber {
+    optional uint32 optional_uint32_1000 = 1000;
+    optional uint32 optional_uint32_65 = 65;
+
+    optional uint32 optional_uint32_1 = 1;
+    optional uint32 optional_uint32_2 = 2;
+    optional uint32 optional_uint32_63 = 63;
+    optional uint32 optional_uint32_64 = 64;
+
+    optional TestAllTypes optional_all_types = 9;
+    repeated TestAllTypes repeated_all_types = 10;
+}
+
+message TestVerifyBigFieldNumberUint32 {
+  message Nested {
+    optional uint32 optional_uint32_5000 = 5000;
+    optional uint32 optional_uint32_1000 = 1000;
+    optional uint32 optional_uint32_66 = 66;
+    optional uint32 optional_uint32_65 = 65;
+
+    optional uint32 optional_uint32_1 = 1;
+    optional uint32 optional_uint32_2 = 2;
+    optional uint32 optional_uint32_63 = 63;
+    optional uint32 optional_uint32_64 = 64;
+
+    optional Nested optional_nested = 9;
+    repeated Nested repeated_nested = 10;
+  }
+  optional Nested optional_nested = 1;
+}
+
+
+// This message contains different kind of enums to exercise the different
+// parsers in table-driven.
+message EnumParseTester {
+  enum SeqSmall0 {
+    SEQ_SMALL_0_DEFAULT = 0;
+    SEQ_SMALL_0_1 = 1;
+    SEQ_SMALL_0_2 = 2;
+  };
+  optional SeqSmall0 optional_seq_small_0_lowfield = 1;
+  optional SeqSmall0 optional_seq_small_0_midfield = 1001;
+  optional SeqSmall0 optional_seq_small_0_hifield = 1000001;
+  repeated SeqSmall0 repeated_seq_small_0_lowfield = 2;
+  repeated SeqSmall0 repeated_seq_small_0_midfield = 1002;
+  repeated SeqSmall0 repeated_seq_small_0_hifield = 1000002;
+  repeated SeqSmall0 packed_seq_small_0_lowfield = 3 [packed = true];
+  repeated SeqSmall0 packed_seq_small_0_midfield = 1003 [packed = true];
+  repeated SeqSmall0 packed_seq_small_0_hifield = 1000003 [packed = true];
+
+  enum SeqSmall1 {
+    SEQ_SMALL_1_DEFAULT = 1;
+    SEQ_SMALL_1_2 = 2;
+    SEQ_SMALL_1_3 = 3;
+  };
+  optional SeqSmall1 optional_seq_small_1_lowfield = 4;
+  optional SeqSmall1 optional_seq_small_1_midfield = 1004;
+  optional SeqSmall1 optional_seq_small_1_hifield = 1000004;
+  repeated SeqSmall1 repeated_seq_small_1_lowfield = 5;
+  repeated SeqSmall1 repeated_seq_small_1_midfield = 1005;
+  repeated SeqSmall1 repeated_seq_small_1_hifield = 1000005;
+  repeated SeqSmall1 packed_seq_small_1_lowfield = 6 [packed = true];
+  repeated SeqSmall1 packed_seq_small_1_midfield = 1006 [packed = true];
+  repeated SeqSmall1 packed_seq_small_1_hifield = 1000006 [packed = true];
+
+  enum SeqLarge {
+    SEQ_LARGE_DEFAULT = -1;
+    SEQ_LARGE_0 = 0;
+    SEQ_LARGE_1 = 1;
+    SEQ_LARGE_2 = 2;
+    SEQ_LARGE_3 = 3;
+    SEQ_LARGE_4 = 4;
+    SEQ_LARGE_5 = 5;
+    SEQ_LARGE_6 = 6;
+    SEQ_LARGE_7 = 7;
+    SEQ_LARGE_8 = 8;
+    SEQ_LARGE_9 = 9;
+    SEQ_LARGE_10 = 10;
+    SEQ_LARGE_11 = 11;
+    SEQ_LARGE_12 = 12;
+    SEQ_LARGE_13 = 13;
+    SEQ_LARGE_14 = 14;
+    SEQ_LARGE_15 = 15;
+    SEQ_LARGE_16 = 16;
+    SEQ_LARGE_17 = 17;
+    SEQ_LARGE_18 = 18;
+    SEQ_LARGE_19 = 19;
+    SEQ_LARGE_20 = 20;
+    SEQ_LARGE_21 = 21;
+    SEQ_LARGE_22 = 22;
+    SEQ_LARGE_23 = 23;
+    SEQ_LARGE_24 = 24;
+    SEQ_LARGE_25 = 25;
+    SEQ_LARGE_26 = 26;
+    SEQ_LARGE_27 = 27;
+    SEQ_LARGE_28 = 28;
+    SEQ_LARGE_29 = 29;
+    SEQ_LARGE_30 = 30;
+    SEQ_LARGE_31 = 31;
+    SEQ_LARGE_32 = 32;
+    SEQ_LARGE_33 = 33;
+  };
+  optional SeqLarge optional_seq_large_lowfield = 7;
+  optional SeqLarge optional_seq_large_midfield = 1007;
+  optional SeqLarge optional_seq_large_hifield = 1000007;
+  repeated SeqLarge repeated_seq_large_lowfield = 8;
+  repeated SeqLarge repeated_seq_large_midfield = 1008;
+  repeated SeqLarge repeated_seq_large_hifield = 1000008;
+  repeated SeqLarge packed_seq_large_lowfield = 9 [packed = true];
+  repeated SeqLarge packed_seq_large_midfield = 1009 [packed = true];
+  repeated SeqLarge packed_seq_large_hifield = 1000009 [packed = true];
+
+  enum Arbitrary {
+    ARBITRARY_DEFAULT = -123123;
+    ARBITRARY_1 = -123;
+    ARBITRARY_2 = 213;
+    ARBITRARY_3 = 213213;
+    ARBITRARY_MIN = -2147483648;
+    ARBITRARY_MAX = 2147483647;
+  };
+  optional Arbitrary optional_arbitrary_lowfield = 10;
+  optional Arbitrary optional_arbitrary_midfield = 1010;
+  optional Arbitrary optional_arbitrary_hifield = 1000010;
+  repeated Arbitrary repeated_arbitrary_lowfield = 11;
+  repeated Arbitrary repeated_arbitrary_midfield = 1011;
+  repeated Arbitrary repeated_arbitrary_hifield = 1000011;
+  repeated Arbitrary packed_arbitrary_lowfield = 12 [packed = true];
+  repeated Arbitrary packed_arbitrary_midfield = 1012 [packed = true];
+  repeated Arbitrary packed_arbitrary_hifield = 1000012 [packed = true];
+
+  // An arbitrary field we can append to to break the runs of repeated fields.
+  optional int32 other_field = 99;
+};
+
+// This message contains different kind of bool fields to exercise the different
+// parsers in table-drived.
+message BoolParseTester {
+  optional bool optional_bool_lowfield = 1;
+  optional bool optional_bool_midfield = 1001;
+  optional bool optional_bool_hifield = 1000001;
+  repeated bool repeated_bool_lowfield = 2;
+  repeated bool repeated_bool_midfield = 1002;
+  repeated bool repeated_bool_hifield = 1000002;
+  repeated bool packed_bool_lowfield = 3 [packed = true];
+  repeated bool packed_bool_midfield = 1003 [packed = true];
+  repeated bool packed_bool_hifield = 1000003 [packed = true];
+
+  // An arbitrary field we can append to to break the runs of repeated fields.
+  optional int32 other_field = 99;
+};
+
diff --git a/objectivec/Tests/unittest_cycle.proto b/objectivec/Tests/unittest_cycle.proto
index afc1b0f..850fdba 100644
--- a/objectivec/Tests/unittest_cycle.proto
+++ b/objectivec/Tests/unittest_cycle.proto
@@ -1,5 +1,6 @@
 // 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
@@ -29,7 +30,9 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.cycle;
+
+option objc_class_prefix = "Cycle";
 
 // Cycles in the Message graph can cause problems for message class
 // initialization order.
@@ -37,20 +40,20 @@
 // You can't make a object graph that spans files, so this can only be done
 // within a single proto file.
 
-message CycleFoo {
-  optional CycleFoo a_foo = 1;
-  optional CycleBar a_bar = 2;
-  optional CycleBaz a_baz = 3;
+message Foo {
+  optional Foo a_foo = 1;
+  optional Bar a_bar = 2;
+  optional Baz a_baz = 3;
 }
 
-message CycleBar {
-  optional CycleBar a_bar = 1;
-  optional CycleBaz a_baz = 2;
-  optional CycleFoo a_foo = 3;
+message Bar {
+  optional Bar a_bar = 1;
+  optional Baz a_baz = 2;
+  optional Foo a_foo = 3;
 }
 
-message CycleBaz {
-  optional CycleBaz a_baz = 1;
-  optional CycleFoo a_foo = 2;
-  optional CycleBar a_bar = 3;
+message Baz {
+  optional Baz a_baz = 1;
+  optional Foo a_foo = 2;
+  optional Bar a_bar = 3;
 }
diff --git a/objectivec/Tests/unittest_deprecated.proto b/objectivec/Tests/unittest_deprecated.proto
index 96a52bb..9d09a9a 100644
--- a/objectivec/Tests/unittest_deprecated.proto
+++ b/objectivec/Tests/unittest_deprecated.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,7 +30,7 @@
 
 syntax = "proto2";
 
-package protobuf_deprecated;
+package objc.protobuf.tests.deprecated;
 option objc_class_prefix = "Dep";
 
 //
diff --git a/objectivec/Tests/unittest_deprecated_file.proto b/objectivec/Tests/unittest_deprecated_file.proto
index ef92e7d..5481032 100644
--- a/objectivec/Tests/unittest_deprecated_file.proto
+++ b/objectivec/Tests/unittest_deprecated_file.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,7 +30,7 @@
 
 syntax = "proto2";
 
-package protobuf_deprecated_file;
+package objc.protobuf.tests.deprecated_file;
 option objc_class_prefix = "FileDep";
 
 //
diff --git a/objectivec/Tests/unittest_extension_chain_a.proto b/objectivec/Tests/unittest_extension_chain_a.proto
index 6a227eb..aceeed3 100644
--- a/objectivec/Tests/unittest_extension_chain_a.proto
+++ b/objectivec/Tests/unittest_extension_chain_a.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,23 +30,25 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.chain;
 
-import "google/protobuf/unittest.proto";
+import "objectivec/Tests/unittest.proto";
 
-import "unittest_extension_chain_b.proto";
-import "unittest_extension_chain_c.proto";
-import "unittest_extension_chain_d.proto";
+import "objectivec/Tests/unittest_extension_chain_b.proto";
+import "objectivec/Tests/unittest_extension_chain_c.proto";
+import "objectivec/Tests/unittest_extension_chain_d.proto";
+
+option objc_class_prefix = "Chain";
 
 // The Root for this file should end up adding the local extension and merging
 // in the extensions from D's Root (unittest and C will come via D's).
 
-message ChainAMessage {
-  optional ChainBMessage b = 1;
-  optional ChainCMessage c = 2;
-  optional ChainDMessage d = 3;
+message AMessage {
+  optional BMessage b = 1;
+  optional CMessage c = 2;
+  optional DMessage d = 3;
 }
 
-extend TestAllExtensions {
+extend objc.protobuf.tests.TestAllExtensions {
   optional int32 chain_a_extension = 10001;
 }
diff --git a/objectivec/Tests/unittest_extension_chain_b.proto b/objectivec/Tests/unittest_extension_chain_b.proto
index 0da7ed3..a9f3947 100644
--- a/objectivec/Tests/unittest_extension_chain_b.proto
+++ b/objectivec/Tests/unittest_extension_chain_b.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,19 +30,21 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.chain;
 
-import "google/protobuf/unittest.proto";
+import "objectivec/Tests/unittest.proto";
 
-import "unittest_extension_chain_c.proto";
+import "objectivec/Tests/unittest_extension_chain_c.proto";
+
+option objc_class_prefix = "Chain";
 
 // The Root for this file should end up adding the local extension and merging
 // in the extensions from C's Root (unittest will come via C's).
 
-message ChainBMessage {
-  optional ChainCMessage c = 1;
+message BMessage {
+  optional CMessage c = 1;
 }
 
-extend TestAllExtensions {
+extend objc.protobuf.tests.TestAllExtensions {
   optional int32 chain_b_extension = 10002;
 }
diff --git a/objectivec/Tests/unittest_extension_chain_c.proto b/objectivec/Tests/unittest_extension_chain_c.proto
index c702900..a8d4862 100644
--- a/objectivec/Tests/unittest_extension_chain_c.proto
+++ b/objectivec/Tests/unittest_extension_chain_c.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,17 +30,19 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.chain;
 
-import "google/protobuf/unittest.proto";
+import "objectivec/Tests/unittest.proto";
+
+option objc_class_prefix = "Chain";
 
 // The Root for this file should end up adding the local extension and merging
 // in the extensions from unittest.proto's Root.
 
-message ChainCMessage {
+message CMessage {
   optional int32 my_field = 1;
 }
 
-extend TestAllExtensions {
+extend objc.protobuf.tests.TestAllExtensions {
   optional int32 chain_c_extension = 10003;
 }
diff --git a/objectivec/Tests/unittest_extension_chain_d.proto b/objectivec/Tests/unittest_extension_chain_d.proto
index f9abe3b..5c91a1b 100644
--- a/objectivec/Tests/unittest_extension_chain_d.proto
+++ b/objectivec/Tests/unittest_extension_chain_d.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,21 +30,23 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.chain;
 
-import "google/protobuf/unittest.proto";
+import "objectivec/Tests/unittest.proto";
 
-import "unittest_extension_chain_b.proto";
-import "unittest_extension_chain_c.proto";
+import "objectivec/Tests/unittest_extension_chain_b.proto";
+import "objectivec/Tests/unittest_extension_chain_c.proto";
+
+option objc_class_prefix = "Chain";
 
 // The root should end up needing to merge B (C will be merged into B, so it
 // doesn't need to be directly merged).
 
-message ChainDMessage {
-  optional ChainBMessage b = 1;
-  optional ChainCMessage c = 2;
+message DMessage {
+  optional BMessage b = 1;
+  optional CMessage c = 2;
 }
 
-extend TestAllExtensions {
+extend objc.protobuf.tests.TestAllExtensions {
   optional int32 chain_d_extension = 10004;
 }
diff --git a/objectivec/Tests/unittest_extension_chain_e.proto b/objectivec/Tests/unittest_extension_chain_e.proto
index fe11663..bf63e8a 100644
--- a/objectivec/Tests/unittest_extension_chain_e.proto
+++ b/objectivec/Tests/unittest_extension_chain_e.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,12 +30,14 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.chain;
 
-import "google/protobuf/unittest.proto";
+import "objectivec/Tests/unittest.proto";
+
+option objc_class_prefix = "Chain";
 
 // The Root for this file should end up just merging in unittest's Root.
 
-message ChainEMessage {
+message EMessage {
   optional TestAllTypes my_field = 1;
 }
diff --git a/objectivec/Tests/unittest_extension_chain_f.proto b/objectivec/Tests/unittest_extension_chain_f.proto
index 096598d..5f9196b 100644
--- a/objectivec/Tests/unittest_extension_chain_f.proto
+++ b/objectivec/Tests/unittest_extension_chain_f.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,9 +30,11 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.chain;
 
-import "unittest_extension_chain_g.proto";
+import "objectivec/Tests/unittest_extension_chain_g.proto";
+
+option objc_class_prefix = "Chain";
 
 // The Root for this file should just be merging in the extensions from C's
 // Root (because G doesn't define anything itself).
@@ -39,6 +42,6 @@
 // The generated source will also have to directly import C's .h file so it can
 // compile the reference to C's Root class.
 
-message ChainFMessage {
-  optional ChainGMessage g = 1;
+message FMessage {
+  optional GMessage g = 1;
 }
diff --git a/objectivec/Tests/unittest_extension_chain_g.proto b/objectivec/Tests/unittest_extension_chain_g.proto
index aee827b..7b228ae 100644
--- a/objectivec/Tests/unittest_extension_chain_g.proto
+++ b/objectivec/Tests/unittest_extension_chain_g.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2016 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
@@ -29,13 +30,15 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+package objc.protobuf.tests.chain;
 
-import "unittest_extension_chain_c.proto";
+import "objectivec/Tests/unittest_extension_chain_c.proto";
+
+option objc_class_prefix = "Chain";
 
 // The Root for this file should just be merging in the extensions from C's
 // Root.
 
-message ChainGMessage {
-  optional ChainCMessage c = 1;
+message GMessage {
+  optional CMessage c = 1;
 }
diff --git a/objectivec/Tests/GPBCompileTest24.m b/objectivec/Tests/unittest_import.proto
similarity index 77%
rename from objectivec/Tests/GPBCompileTest24.m
rename to objectivec/Tests/unittest_import.proto
index c81ea73..8b8996f 100644
--- a/objectivec/Tests/GPBCompileTest24.m
+++ b/objectivec/Tests/unittest_import.proto
@@ -28,15 +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.
 
+// A proto file which is imported by unittest.proto to test importing.
 
-// This is a test including a single header to ensure things build. This
-// is NOT a public header of the library, but uses a file that defines
-// proto2 syntax messages that are extendable, so it can need more things
-// that the proto3 syntax WKTs bundled with the library.
+syntax = "proto2";
 
-#import "google/protobuf/Descriptor.pbobjc.h"
+package objc.protobuf.tests.import;
+
+// Test public import
+import public "objectivec/Tests/unittest_import_public.proto";
+
+option objc_class_prefix = "Import";
+
+message Message {
+  optional int32 d = 1;
+}
+
+enum Enum {
+  IMPORT_FOO = 7;
+  IMPORT_BAR = 8;
+  IMPORT_BAZ = 9;
+}
 
 
-// Something in the body of this file so the compiler/linker won't complain
-// about an empty .o file.
-__attribute__((visibility("default"))) char dummy_symbol_24 = 0;
+// To use an enum in a map, it must has the first value as 0.
+enum EnumForMap {
+  UNKNOWN = 0;
+  FOO = 1;
+  BAR = 2;
+}
diff --git a/src/google/protobuf/util/internal/testdata/proto3.proto b/objectivec/Tests/unittest_import_public.proto
similarity index 88%
rename from src/google/protobuf/util/internal/testdata/proto3.proto
rename to objectivec/Tests/unittest_import_public.proto
index 01434b0..05969b6 100644
--- a/src/google/protobuf/util/internal/testdata/proto3.proto
+++ b/objectivec/Tests/unittest_import_public.proto
@@ -28,15 +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 = "proto3";
+// Author: liujisi@google.com (Pherl Liu)
 
-package proto_util_converter.testing;
+syntax = "proto2";
 
-message Proto3Message {
-  enum NestedEnum {
-    FOO = 0;
-    BAR = 1;
-    BAZ = 2;
-  }
-  NestedEnum enum_value = 1;
+package objc.protobuf.tests.public_import;
+
+option objc_class_prefix = "PublicImport";
+
+message Message {
+  optional int32 e = 1;
 }
diff --git a/src/google/protobuf/util/internal/testdata/default_value_test.proto b/objectivec/Tests/unittest_mset.proto
similarity index 68%
rename from src/google/protobuf/util/internal/testdata/default_value_test.proto
rename to objectivec/Tests/unittest_mset.proto
index af755d3..9ff070f 100644
--- a/src/google/protobuf/util/internal/testdata/default_value_test.proto
+++ b/objectivec/Tests/unittest_mset.proto
@@ -28,26 +28,38 @@
 // (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 = "proto3";
+syntax = "proto2";
 
-package proto_util_converter.testing;
+package objc.protobuf.tests.mset;
 
-message DefaultValueTest {
-  double double_value = 1;
-  repeated double repeated_double = 2;
-  float float_value = 3;
-  int64 int64_value = 5;
-  uint64 uint64_value = 7;
-  int32 int32_value = 9;
-  uint32 uint32_value = 11;
-  bool bool_value = 13;
-  string string_value = 15;
-  bytes bytes_value = 17 [ctype = CORD];
+option objc_class_prefix = "MSet";
 
-  enum EnumDefault {
-    ENUM_FIRST = 0;
-    ENUM_SECOND = 1;
-    ENUM_THIRD = 2;
+// A message with message_set_wire_format.
+message Message {
+  option message_set_wire_format = true;
+  extensions 4 to max;
+}
+
+message MessageExtension1 {
+  extend Message {
+    optional MessageExtension1 message_set_extension = 1545008;
   }
-  EnumDefault enum_value = 18;
+  optional int32 i = 15;
+  optional Message recursive = 16;
+  optional string test_aliasing = 17 [ctype = STRING_PIECE];
+}
+
+message MessageExtension2 {
+  extend Message {
+    optional MessageExtension2 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/objectivec/Tests/unittest_objc.proto b/objectivec/Tests/unittest_objc.proto
index 91c2139..48db856 100644
--- a/objectivec/Tests/unittest_objc.proto
+++ b/objectivec/Tests/unittest_objc.proto
@@ -1,5 +1,6 @@
 // Protocol Buffers - Google's data interchange format
 // Copyright 2011 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
@@ -30,9 +31,12 @@
 syntax = "proto2";
 
 import "google/protobuf/any.proto";
-import "google/protobuf/unittest.proto";
+import "objectivec/Tests/unittest.proto";
 
-package protobuf_unittest;
+package objc.protobuf.tests;
+
+// Explicit empty prefix, tests some validations code paths also.
+option objc_class_prefix = "";
 
 // Used to check that Headerdocs and appledoc work correctly. If these comments
 // are not handled correctly, Xcode will fail to build the tests.
@@ -236,8 +240,7 @@
   repeated   sint32 byref               =  3004 [packed = true];
 }
 
-// Test handing of fields that start with init* since Xcode 5's ARC support
-// doesn't like messages that look like initializers but aren't.
+// Test handing of fields that start with init*.
 message ObjCInitFoo {
   optional string init_val = 11;
   optional int32 init_size = 12;
diff --git a/objectivec/Tests/unittest_objc_options.proto b/objectivec/Tests/unittest_objc_options.proto
index 6129b85..7d3f677 100644
--- a/objectivec/Tests/unittest_objc_options.proto
+++ b/objectivec/Tests/unittest_objc_options.proto
@@ -30,7 +30,8 @@
 
 syntax = "proto2";
 
-package protobuf_objc_unittest;
+package objc.protobuf.tests.options;
+
 option objc_class_prefix = "GPBTEST";
 
 // Verify that enum types and values get the prefix.
@@ -59,3 +60,9 @@
 // Verify that classes named the same as prefixes are prefixed.
 message GPBTEST {
 }
+
+// Tests that lookup deals with prefix.
+message PrefixedParentMessage {
+  message Child {
+  }
+}
diff --git a/objectivec/Tests/unittest_objc_startup.proto b/objectivec/Tests/unittest_objc_startup.proto
index aee7bd5..f2bf9d5 100644
--- a/objectivec/Tests/unittest_objc_startup.proto
+++ b/objectivec/Tests/unittest_objc_startup.proto
@@ -30,20 +30,21 @@
 
 syntax = "proto2";
 
-package protobuf_objc_unittest;
+package objc.protobuf.tests.startup;
+option objc_class_prefix = "TestObjCStartup";
 
-message TestObjCStartupMessage {
+message Message {
   extensions 1 to max;
 }
 
-extend TestObjCStartupMessage {
+extend Message {
   // Singular
   optional    int32 optional_int32_extension    = 1;
   repeated    int32 repeated_int32_extension    = 2;
 }
 
-message TestObjCStartupNested {
-  extend TestObjCStartupMessage {
+message Nested {
+  extend Message {
     optional string nested_string_extension = 3;
   }
 }
diff --git a/src/google/protobuf/util/internal/testdata/proto3.proto b/objectivec/Tests/unittest_preserve_unknown_enum.proto
similarity index 66%
copy from src/google/protobuf/util/internal/testdata/proto3.proto
copy to objectivec/Tests/unittest_preserve_unknown_enum.proto
index 01434b0..8cdd58d 100644
--- a/src/google/protobuf/util/internal/testdata/proto3.proto
+++ b/objectivec/Tests/unittest_preserve_unknown_enum.proto
@@ -30,13 +30,40 @@
 
 syntax = "proto3";
 
-package proto_util_converter.testing;
+package objc.protobuf.tests.proto3_preserve_unknown_enum;
+option objc_class_prefix = "UnknownEnums";
 
-message Proto3Message {
-  enum NestedEnum {
-    FOO = 0;
-    BAR = 1;
-    BAZ = 2;
+enum MyEnum {
+  FOO = 0;
+  BAR = 1;
+  BAZ = 2;
+}
+
+enum MyEnumPlusExtra {
+  E_FOO = 0;
+  E_BAR = 1;
+  E_BAZ = 2;
+  E_EXTRA = 3;
+}
+
+message MyMessage {
+  MyEnum e = 1;
+  repeated MyEnum repeated_e = 2;
+  repeated MyEnum repeated_packed_e = 3 [packed=true];
+  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4;  // not packed
+  oneof o {
+    MyEnum oneof_e_1 = 5;
+    MyEnum oneof_e_2 = 6;
   }
-  NestedEnum enum_value = 1;
+}
+
+message MyMessagePlusExtra {
+  MyEnumPlusExtra e = 1;
+  repeated MyEnumPlusExtra repeated_e = 2;
+  repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true];
+  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true];
+  oneof o {
+    MyEnumPlusExtra oneof_e_1 = 5;
+    MyEnumPlusExtra oneof_e_2 = 6;
+  }
 }
diff --git a/objectivec/Tests/unittest_runtime_proto2.proto b/objectivec/Tests/unittest_runtime_proto2.proto
index ed83502..b2f0ceb 100644
--- a/objectivec/Tests/unittest_runtime_proto2.proto
+++ b/objectivec/Tests/unittest_runtime_proto2.proto
@@ -1,5 +1,6 @@
 // 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
@@ -29,7 +30,10 @@
 
 syntax = "proto2";
 
-package protobuf_unittest;
+// Explicit empty prefix, tests some validations code paths also.
+package objc.protobuf.tests;
+
+option objc_class_prefix = "";
 
 message Message2 {
   enum Enum {
diff --git a/objectivec/Tests/unittest_runtime_proto3.proto b/objectivec/Tests/unittest_runtime_proto3.proto
index c2ee5fb..2a2fb66 100644
--- a/objectivec/Tests/unittest_runtime_proto3.proto
+++ b/objectivec/Tests/unittest_runtime_proto3.proto
@@ -1,5 +1,6 @@
 // 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
@@ -29,7 +30,10 @@
 
 syntax = "proto3";
 
-package protobuf_unittest;
+// Explicit empty prefix, tests some validations code paths also.
+package objc.protobuf.tests;
+
+option objc_class_prefix = "";
 
 message Message3 {
   enum Enum {
diff --git a/objectivec/generate_well_known_types.sh b/objectivec/generate_well_known_types.sh
index 1b9de6e..83a341e 100755
--- a/objectivec/generate_well_known_types.sh
+++ b/objectivec/generate_well_known_types.sh
@@ -3,16 +3,15 @@
 # Run this script to regenerate *.pbobjc.{h,m} for the well known types after
 # the protocol compiler changes.
 
-# HINT:  Flags passed to generate_well_known_types.sh will be passed directly
-#   to make when building protoc.  This is particularly useful for passing
-#   -j4 to run 4 jobs simultaneously.
-
 set -eu
 
 readonly ScriptDir=$(dirname "$(echo $0 | sed -e "s,^\([^/]\),$(pwd)/\1,")")
 readonly ObjCDir="${ScriptDir}"
 readonly ProtoRootDir="${ObjCDir}/.."
 
+# Invoke with BAZEL=bazelisk to use that instead.
+readonly BazelBin="${BAZEL:=bazel}"
+
 # Flag for continuous integration to check that everything is current.
 CHECK_ONLY=0
 if [[ $# -ge 1 && ( "$1" == "--check-only" ) ]] ; then
@@ -30,18 +29,10 @@
   exit 1
 fi
 
-if [[ ! -e src/Makefile ]]; then
-  cat >&2 << __EOF__
-Could not find src/Makefile.  You must run ./configure (and perhaps
-./autogen.sh) first.
-__EOF__
-  exit 1
-fi
-
 # Make sure the compiler is current.
-cd src
-make $@ protoc
+"${BazelBin}" build //:protoc $@
 
+cd src
 declare -a RUNTIME_PROTO_FILES=( \
   google/protobuf/any.proto \
   google/protobuf/api.proto \
@@ -59,7 +50,7 @@
 # Generate to a temp directory to see if they match.
 TMP_DIR=$(mktemp -d)
 trap "rm -rf ${TMP_DIR}" EXIT
-./protoc --objc_out="${TMP_DIR}" ${RUNTIME_PROTO_FILES[@]}
+${ProtoRootDir}/bazel-bin/protoc --objc_out="${TMP_DIR}" ${RUNTIME_PROTO_FILES[@]}
 
 DID_COPY=0
 for PROTO_FILE in "${RUNTIME_PROTO_FILES[@]}"; do
@@ -73,6 +64,7 @@
     if ! diff "${ObjCDir}/GPB${OBJC_NAME}${EXT}" "${TMP_DIR}/${DIR}/${OBJC_NAME}${EXT}" > /dev/null 2>&1 ; then
       if [[ "${CHECK_ONLY}" == 1 ]] ; then
         echo "ERROR: The WKTs need to be regenerated! Run $0"
+        diff -u "${ObjCDir}/GPB${OBJC_NAME}${EXT}" "${TMP_DIR}/${DIR}/${OBJC_NAME}${EXT}"
         exit 1
       fi
 
diff --git a/php/BUILD.bazel b/php/BUILD.bazel
index 7fededa..e3be222 100644
--- a/php/BUILD.bazel
+++ b/php/BUILD.bazel
@@ -2,22 +2,125 @@
 #
 # See also code generation logic under /src/google/protobuf/compiler/php.
 
-load("@rules_pkg//:pkg.bzl", "pkg_tar")
 load("@rules_pkg//:mappings.bzl", "pkg_files", "pkg_filegroup", "strip_prefix")
-load("//:protobuf_version.bzl", "PROTOBUF_PHP_VERSION")
+load("@rules_pkg//:pkg.bzl", "pkg_tar")
+load("@upb//cmake:build_defs.bzl", "staleness_test")
+load("//build_defs:internal_shell.bzl", "inline_sh_binary")
+load("//conformance:defs.bzl", "conformance_test")
+load("//:protobuf_version.bzl", "PROTOBUF_PHP_VERSION", "PROTOC_VERSION")
+
+filegroup(
+    name = "source_files",
+    visibility = [
+        "//conformance:__pkg__",
+        "//php:__pkg__",
+    ],
+    srcs = glob([
+        "src/GPBMetadata/Google/Protobuf/**/*.php",
+        "src/Google/Protobuf/**/*.php",
+    ]) + [
+        "composer.json",
+        ":php_ext_source_files",
+    ],
+)
+
+################################################################################
+# PHP Extension
+################################################################################
+
+inline_sh_binary(
+    name = "build_extension",
+    cmd = """
+        mkdir -p php/ext/google/protobuf/third_party/utf8_range
+        cp external/utf8_range/* php/ext/google/protobuf/third_party/utf8_range
+
+        pushd  php/ext/google/protobuf
+        phpize
+        ./configure --with-php-config=$$(which php-config)
+        make
+        popd
+    """,
+)
+
+genrule(
+    name = "extension",
+    srcs = [
+        ":source_files",
+        "@utf8_range//:utf8_range_srcs",
+    ],
+    tools = [":build_extension"],
+    outs = ["protobuf.so"],
+    cmd = """
+        ./$(execpath :build_extension) $@
+        cp php/ext/google/protobuf/modules/protobuf.so $(OUTS)
+    """,
+    visibility = ["//visibility:public"],
+)
+
+################################################################################
+# Tests
+################################################################################
+
+conformance_test(
+    name = "conformance_test",
+    failure_list = "//conformance:failure_list_php.txt",
+    testee = "//conformance:conformance_php",
+    text_format_failure_list = "//conformance:text_format_failure_list_php.txt",
+    target_compatible_with = select({
+        "@platforms//os:osx": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    }),
+)
+
+conformance_test(
+    name = "conformance_test_c",
+    failure_list = "//conformance:failure_list_php_c.txt",
+    testee = "//conformance:conformance_php_c",
+    text_format_failure_list = "//conformance:text_format_failure_list_php.txt",
+    target_compatible_with = select({
+        "@platforms//os:osx": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+)
+
+genrule(
+    name = "copy_php_amalgamation_h",
+    srcs = ["@upb//:php-upb.h"],
+    outs = ["generated-in/ext/google/protobuf/php-upb.h"],
+    cmd = "cp $< $@",
+)
+
+genrule(
+    name = "copy_php_amalgamation_c",
+    srcs = ["@upb//:php-upb.c"],
+    outs = ["generated-in/ext/google/protobuf/php-upb.c"],
+    cmd = "cp $< $@",
+)
+
+staleness_test(
+    name = "test_amalgamation_staleness",
+    outs = [
+        "ext/google/protobuf/php-upb.h",
+        "ext/google/protobuf/php-upb.c",
+    ],
+    generated_pattern = "generated-in/%s",
+)
+
+################################################################################
+# Distribution files
+################################################################################
 
 pkg_files(
     name = "dist_files",
     srcs = glob([
         "ext/google/protobuf/**/*",
-        "src/GPBMetadata/Google/Protobuf/**/*.php",
-        "src/Google/Protobuf/**/*.php",
         "tests/*.php",
         "tests/*.sh",
         "tests/generated_previous/**/*.php",
         "tests/proto/**/*.proto",
         "tests/proto_previous/*.proto",
     ]) + [
+        ":source_files",
         "BUILD.bazel",
         "README.md",
         "REFCOUNTING.md",
@@ -52,9 +155,8 @@
 pkg_files(
   name = "utf8_range_files",
   srcs = [
-    "//third_party/utf8_range:utf8_range_srcs",
-     "//third_party/utf8_range:LICENSE",
-
+    "@utf8_range//:utf8_range_srcs",
+    "@utf8_range//:LICENSE",
   ],
   prefix = "third_party/utf8_range",
 )
@@ -90,6 +192,7 @@
       "$(location ext/google/protobuf/generate_package_xml.sh)",
       "$(location ext/google/protobuf/template_package.xml)",
       PROTOBUF_PHP_VERSION,
+      PROTOC_VERSION,
       "$$(tar -tf $(location :release_without_package) | sed -z -e 's;\\n;,;g')",
       "$(location package.xml)"
     ]),
@@ -104,4 +207,4 @@
     ":generate_package_xml",
   ],
   out = "protobuf-%s.tgz" % PROTOBUF_PHP_VERSION,
-)
\ No newline at end of file
+)
diff --git a/php/README.md b/php/README.md
index c4292cf..f4e420e 100644
--- a/php/README.md
+++ b/php/README.md
@@ -26,8 +26,6 @@
 #### Prerequirements
 
 To install the c extension, the following tools are needed:
-* autoconf
-* automake
 * libtool
 * make
 * gcc
@@ -36,7 +34,7 @@
 
 On Ubuntu, you can install them with:
 ```
-sudo apt-get install -y php-pear php5-dev autoconf automake libtool make gcc
+sudo apt-get install -y php-pear php-dev libtool make gcc
 ```
 On other platforms, please use the corresponding package managing tool to
 install them before proceeding.
@@ -67,6 +65,8 @@
 Simply add "google/protobuf" to the 'require' section of composer.json in your
 project.
 
+To use the pure PHP implementation, you need to install bcmath.
+
 ### Protoc
 
 Once the extension or package is installed, if you wish to generate PHP code
@@ -98,24 +98,18 @@
 
 ## Development
 
-### Docker Image
-
-We provide a docker image for php development, which is also used in our automatic tests:
-```
-docker run --security-opt seccomp=unconfined -it protobuftesting/php_8dbe419c6df1a8b3af0ae3a267c112efb436b45c
-```
-
 ### Test Native PHP
 
 ```
+# Install Dependencies (Linux)
+apt-get install bazel composer php-dev
+
 # Download protobuf
 git clone https://github.com/protocolbuffers/protobuf.git
 cd protobuf
 
 # Build protoc
-./autogen.sh
-./configure
-make -j4
+bazel build :protoc
 
 # Test native php
 cd php
diff --git a/php/composer.json b/php/composer.json
index 436142f..0e498fc 100644
--- a/php/composer.json
+++ b/php/composer.json
@@ -30,5 +30,8 @@
     "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"
+  },
+  "config": {
+    "process-timeout": 1200
   }
 }
diff --git a/php/ext/google/protobuf/convert.c b/php/ext/google/protobuf/convert.c
index bedbcca..6a8cca9 100644
--- a/php/ext/google/protobuf/convert.c
+++ b/php/ext/google/protobuf/convert.c
@@ -505,7 +505,8 @@
     // 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_Message *wrapper = upb_Message_New(subm, arena);
+    upb_MiniTable *t = upb_MessageDef_MiniTable(subm);
+    upb_Message *wrapper = upb_Message_New(t, arena);
     const upb_FieldDef *val_f = upb_MessageDef_FindFieldByNumber(subm, 1);
     upb_MessageValue msgval;
     if (!Convert_PhpToUpb(val, &msgval, TypeInfo_Get(val_f), arena)) return false;
diff --git a/php/ext/google/protobuf/generate_package_xml.sh b/php/ext/google/protobuf/generate_package_xml.sh
index 3228785..7d4aa94 100755
--- a/php/ext/google/protobuf/generate_package_xml.sh
+++ b/php/ext/google/protobuf/generate_package_xml.sh
@@ -2,8 +2,9 @@
 
 template_package_xml=$1
 release_version=$2
-release_files=$3
-out=$4
+protoc_version=$3
+release_files=$4
+out=$5
 
 date=$(date +%Y-%m-%d)
 time=$(date +%H:%M:%S)
@@ -36,4 +37,5 @@
 sed -e "s;TEMPLATE_PHP_RELEASE;${release_version};" |
 sed -e "s;TEMPLATE_PHP_API;${api_version};" |
 sed -e "s;TEMPLATE_PHP_STABILITY;${stability};g" |
-sed -e "s;TEMPLATE_FILES;${files};" > $out
\ No newline at end of file
+sed -e "s;TEMPLATE_PROTOC_VERSION;${protoc_version};" |
+sed -e "s;TEMPLATE_FILES;${files};" > $out
diff --git a/php/ext/google/protobuf/message.c b/php/ext/google/protobuf/message.c
index 55f4f4d..0829653 100644
--- a/php/ext/google/protobuf/message.c
+++ b/php/ext/google/protobuf/message.c
@@ -426,11 +426,12 @@
  */
 static zend_object *Message_clone_obj(PROTO_VAL *object) {
   Message* intern = PROTO_VAL_P(object);
-  upb_Message *clone = upb_Message_New(intern->desc->msgdef, Arena_Get(&intern->arena));
+  upb_MiniTable *t = upb_MessageDef_MiniTable(intern->desc->msgdef);
+  upb_Message *clone = upb_Message_New(t, Arena_Get(&intern->arena));
 
   // TODO: copy unknown fields?
   // TODO: use official upb msg copy function
-  memcpy(clone, intern->msg, upb_MessageDef_MiniTable(intern->desc->msgdef)->size);
+  memcpy(clone, intern->msg, t->size);
   zval ret;
   Message_GetPhpWrapper(&ret, intern->desc, clone, &intern->arena);
   return Z_OBJ_P(&ret);
@@ -579,7 +580,8 @@
 
 static void Message_Initialize(Message *intern, const Descriptor *desc) {
   intern->desc = desc;
-  intern->msg = upb_Message_New(desc->msgdef, Arena_Get(&intern->arena));
+  upb_MiniTable *t = upb_MessageDef_MiniTable(desc->msgdef);
+  intern->msg = upb_Message_New(t, Arena_Get(&intern->arena));
   ObjCache_Add(intern->msg, &intern->std);
 }
 
@@ -601,7 +603,7 @@
   //
   // 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
+  // store this `ce` in a global variable to break the cycle (see the check in
   // NameMap_GetMessage()).
   NameMap_EnterConstructor(ce);
   desc = Descriptor_GetFromClassEntry(ce);
@@ -646,6 +648,25 @@
   upb_Message_Clear(intern->msg, intern->desc->msgdef);
 }
 
+static bool Message_checkEncodeStatus(upb_EncodeStatus status) {
+  switch (status) {
+    case kUpb_EncodeStatus_Ok:
+      return true;
+    case kUpb_EncodeStatus_OutOfMemory:
+      zend_throw_exception_ex(NULL, 0, "Out of memory");
+      return false;
+    case kUpb_EncodeStatus_MaxDepthExceeded:
+      zend_throw_exception_ex(NULL, 0, "Max nesting exceeded");
+      return false;
+    case kUpb_EncodeStatus_MissingRequired:
+      zend_throw_exception_ex(NULL, 0, "Missing required field");
+      return false;
+    default:
+      zend_throw_exception_ex(NULL, 0, "Unknown error encoding");
+      return false;
+  }
+}
+
 /**
  * Message::mergeFrom()
  *
@@ -673,14 +694,9 @@
   // 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, 0, arena, &size);
-
-  if (!pb) {
-    zend_throw_exception_ex(NULL, 0, "Max nesting exceeded");
-    return;
-  }
+  // TODO(haberman): use a temp arena for this.
+  upb_EncodeStatus status = upb_Encode(from->msg, l, 0, arena, &pb, &size);
+  if (!Message_checkEncodeStatus(status)) return;
 
   ok = upb_Decode(pb, size, intern->msg, l, NULL, 0, arena) ==
        kUpb_DecodeStatus_Ok;
@@ -730,7 +746,9 @@
   char *data;
   size_t size;
 
-  data = upb_Encode(intern->msg, l, 0, tmp_arena, &size);
+  upb_EncodeStatus status =
+      upb_Encode(intern->msg, l, 0, tmp_arena, &data, &size);
+  if (!Message_checkEncodeStatus(status)) return;
 
   if (!data) {
     zend_throw_exception_ex(NULL, 0, "Error occurred during serialization");
@@ -1232,8 +1250,12 @@
   msg = (Message*)Z_OBJ_P(val);
 
   // Serialize and set value.
-  value.data = upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->desc->msgdef),
-                          0, arena, &value.size);
+  char* pb;
+  upb_EncodeStatus status =
+      upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->desc->msgdef), 0,
+                 arena, &pb, &value.size);
+  if (!Message_checkEncodeStatus(status)) return;
+  value.data = pb;
   Message_setval(intern, "value", StringVal(value));
 
   // Set type url: type_url_prefix + fully_qualified_name
diff --git a/php/ext/google/protobuf/php-upb.c b/php/ext/google/protobuf/php-upb.c
index 1179ac3..376b202 100644
--- a/php/ext/google/protobuf/php-upb.c
+++ b/php/ext/google/protobuf/php-upb.c
@@ -1,37 +1,10 @@
 /* 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.
+ * This is where we define internal portability macros used across upb.
  *
- * All of these macros are undef'd in port_undef.inc to avoid leaking them to
- * users.
+ * All of these macros are undef'd in undef.inc to avoid leaking them to users.
  *
  * The correct usage is:
  *
@@ -39,25 +12,38 @@
  *   #include "upb/baz.h"
  *
  *   // MUST be last included header.
- *   #include "upb/port_def.inc"
+ *   #include "upb/port/def.inc"
  *
  *   // Code for this file.
  *   // <...>
  *
  *   // Can be omitted for .c files, required for .h.
- *   #include "upb/port_undef.inc"
+ *   #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(__cplusplus) && __cplusplus >= 201402L) ||           \
       (defined(_MSC_VER) && _MSC_VER >= 1900))
-#error upb requires C99 or C++11 or MSVC >= 2015.
+#error upb requires C99 or C++14 or MSVC >= 2015.
 #endif
 
-#include <stdint.h>
+// 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 UPB_GNUC_MIN(x, y) \
+  (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
+#else
+#define UPB_GNUC_MIN(x, y) 0
+#endif
+
+#include <assert.h>
+#include <setjmp.h>
+#include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
 
 #if UINTPTR_MAX == 0xffffffff
 #define UPB_SIZE(size32, size64) size32
@@ -70,11 +56,6 @@
  */
 #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;
@@ -90,21 +71,22 @@
 #define UPB_INLINE static
 #endif
 
+#define UPB_MALLOC_ALIGN 8
 #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_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN)
 #define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
 
-/* Hints to the compiler about likely/unlikely branches. */
+// 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)
+#define UPB_LIKELY(x) __builtin_expect((bool)(x), 1)
+#define UPB_UNLIKELY(x) __builtin_expect((bool)(x), 0)
 #else
 #define UPB_LIKELY(x) (x)
 #define UPB_UNLIKELY(x) (x)
 #endif
 
-/* Macros for function attributes on compilers that support them. */
+// Macros for function attributes on compilers that support them.
 #ifdef __GNUC__
 #define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
 #define UPB_NOINLINE __attribute__((noinline))
@@ -127,8 +109,7 @@
 
 #define UPB_UNUSED(var) (void)var
 
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
+// 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()
@@ -230,7 +211,11 @@
 
 #undef UPB_FASTTABLE_SUPPORTED
 
-/* ASAN poisoning (for arena) *************************************************/
+/* ASAN poisoning (for arena).
+ * If using UPB from an interpreted language like Ruby, a build of the
+ * interpreter compiled with ASAN enabled must be used in order to get sane and
+ * expected behavior.
+ */
 
 #if defined(__SANITIZE_ADDRESS__)
 #define UPB_ASAN 1
@@ -254,1813 +239,180 @@
   ((void)(addr), (void)(size))
 #endif
 
-/** upb/decode.c ************************************************************/
+/* Disable proto2 arena behavior (TEMPORARY) **********************************/
 
-#include <setjmp.h>
+#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING
+#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1
+#else
+#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0
+#endif
+
+#if defined(__cplusplus)
+#if defined(__clang__) || UPB_GNUC_MIN(6, 0)
+// https://gcc.gnu.org/gcc-6/changes.html
+#if __cplusplus >= 201402L
+#define UPB_DEPRECATED [[deprecated]]
+#else
+#define UPB_DEPRECATED __attribute__((deprecated))
+#endif
+#else
+#define UPB_DEPRECATED
+#endif
+#else
+#define UPB_DEPRECATED
+#endif
+
+
+#include <errno.h>
+#include <float.h>
+#include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
 
+// Must be last.
 
-/* 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_MASK = (1 << kUpb_FieldType_Float) |
-                                        (1 << kUpb_FieldType_Fixed32) |
-                                        (1 << kUpb_FieldType_SFixed32);
-
-static const unsigned FIXED64_OK_MASK = (1 << kUpb_FieldType_Double) |
-                                        (1 << kUpb_FieldType_Fixed64) |
-                                        (1 << kUpb_FieldType_SFixed64);
-
-/* Three fake field types for MessageSet. */
-#define TYPE_MSGSET_ITEM 19
-#define TYPE_MSGSET_TYPE_ID 20
-#define TYPE_COUNT 20
-
-/* Op: an action to be performed for a wire-type/field-type combination. */
-#define OP_UNKNOWN -1 /* Unknown field. */
-#define OP_MSGSET_ITEM -2
-#define OP_MSGSET_TYPEID -3
-#define OP_SCALAR_LG2(n) (n) /* n in [0, 2, 3] => op in [0, 2, 3] */
-#define OP_ENUM 1
-#define OP_STRING 4
-#define OP_BYTES 5
-#define OP_SUBMSG 6
-/* Scalar fields use only ops above. 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] */
-#define OP_PACKED_ENUM 13
-
-static const int8_t varint_ops[] = {
-    OP_UNKNOWN,       /* field not found */
-    OP_UNKNOWN,       /* DOUBLE */
-    OP_UNKNOWN,       /* FLOAT */
-    OP_SCALAR_LG2(3), /* INT64 */
-    OP_SCALAR_LG2(3), /* UINT64 */
-    OP_SCALAR_LG2(2), /* INT32 */
-    OP_UNKNOWN,       /* FIXED64 */
-    OP_UNKNOWN,       /* FIXED32 */
-    OP_SCALAR_LG2(0), /* BOOL */
-    OP_UNKNOWN,       /* STRING */
-    OP_UNKNOWN,       /* GROUP */
-    OP_UNKNOWN,       /* MESSAGE */
-    OP_UNKNOWN,       /* BYTES */
-    OP_SCALAR_LG2(2), /* UINT32 */
-    OP_ENUM,          /* ENUM */
-    OP_UNKNOWN,       /* SFIXED32 */
-    OP_UNKNOWN,       /* SFIXED64 */
-    OP_SCALAR_LG2(2), /* SINT32 */
-    OP_SCALAR_LG2(3), /* SINT64 */
-    OP_UNKNOWN,       /* MSGSET_ITEM */
-    OP_MSGSET_TYPEID, /* MSGSET TYPEID */
-};
-
-static const int8_t delim_ops[] = {
-    /* For non-repeated field type. */
-    OP_UNKNOWN, /* field not found */
-    OP_UNKNOWN, /* DOUBLE */
-    OP_UNKNOWN, /* FLOAT */
-    OP_UNKNOWN, /* INT64 */
-    OP_UNKNOWN, /* UINT64 */
-    OP_UNKNOWN, /* INT32 */
-    OP_UNKNOWN, /* FIXED64 */
-    OP_UNKNOWN, /* FIXED32 */
-    OP_UNKNOWN, /* BOOL */
-    OP_STRING,  /* STRING */
-    OP_UNKNOWN, /* GROUP */
-    OP_SUBMSG,  /* MESSAGE */
-    OP_BYTES,   /* BYTES */
-    OP_UNKNOWN, /* UINT32 */
-    OP_UNKNOWN, /* ENUM */
-    OP_UNKNOWN, /* SFIXED32 */
-    OP_UNKNOWN, /* SFIXED64 */
-    OP_UNKNOWN, /* SINT32 */
-    OP_UNKNOWN, /* SINT64 */
-    OP_UNKNOWN, /* MSGSET_ITEM */
-    OP_UNKNOWN, /* MSGSET TYPEID */
-    /* 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_PACKED_ENUM,   /* 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 */
-    /* Omitting MSGSET_*, because we never emit a repeated msgset type */
-};
-
-typedef union {
-  bool bool_val;
-  uint32_t uint32_val;
-  uint64_t uint64_val;
-  uint32_t size;
-} wireval;
-
-static const char* decode_msg(upb_Decoder* d, const char* ptr, upb_Message* msg,
-                              const upb_MiniTable* layout);
-
-UPB_NORETURN static void* decode_err(upb_Decoder* d, upb_DecodeStatus status) {
-  assert(status != kUpb_DecodeStatus_Ok);
-  UPB_LONGJMP(d->err, status);
+void upb_Status_Clear(upb_Status* status) {
+  if (!status) return;
+  status->ok = true;
+  status->msg[0] = '\0';
 }
 
-const char* fastdecode_err(upb_Decoder* d, int status) {
-  assert(status != kUpb_DecodeStatus_Ok);
-  UPB_LONGJMP(d->err, status);
-  return NULL;
-}
-static void decode_verifyutf8(upb_Decoder* d, const char* buf, int len) {
-  if (!decode_verifyutf8_inl(buf, len))
-    decode_err(d, kUpb_DecodeStatus_BadUtf8);
+bool upb_Status_IsOk(const upb_Status* status) { return status->ok; }
+
+const char* upb_Status_ErrorMessage(const upb_Status* status) {
+  return status->msg;
 }
 
-static bool decode_reserve(upb_Decoder* 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, kUpb_DecodeStatus_OutOfMemory);
-  }
-  return need_realloc;
+void upb_Status_SetErrorMessage(upb_Status* status, const char* msg) {
+  if (!status) return;
+  status->ok = false;
+  strncpy(status->msg, msg, _kUpb_Status_MaxMessage - 1);
+  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
 }
 
-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;
+void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_Status_VSetErrorFormat(status, fmt, args);
+  va_end(args);
 }
 
-UPB_FORCEINLINE
-static const char* decode_varint64(upb_Decoder* 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) return decode_err(d, kUpb_DecodeStatus_Malformed);
-    *val = res.val;
-    return res.ptr;
-  }
+void upb_Status_VSetErrorFormat(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[_kUpb_Status_MaxMessage - 1] = '\0';
 }
 
-UPB_FORCEINLINE
-static const char* decode_tag(upb_Decoder* 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);
-    if (!res.ptr || res.ptr - start > 5 || res.val > UINT32_MAX) {
-      return decode_err(d, kUpb_DecodeStatus_Malformed);
-    }
-    *val = res.val;
-    return res.ptr;
-  }
-}
-
-static void decode_munge_int32(wireval* val) {
-  if (!_upb_IsLittleEndian()) {
-    /* The next stage will memcpy(dst, &val, 4) */
-    val->uint32_val = val->uint64_val;
-  }
-}
-
-static void decode_munge(int type, wireval* val) {
-  switch (type) {
-    case kUpb_FieldType_Bool:
-      val->bool_val = val->uint64_val != 0;
-      break;
-    case kUpb_FieldType_SInt32: {
-      uint32_t n = val->uint64_val;
-      val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
-      break;
-    }
-    case kUpb_FieldType_SInt64: {
-      uint64_t n = val->uint64_val;
-      val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
-      break;
-    }
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_UInt32:
-    case kUpb_FieldType_Enum:
-      decode_munge_int32(val);
-      break;
-  }
-}
-
-static upb_Message* decode_newsubmsg(upb_Decoder* d,
-                                     const upb_MiniTable_Sub* subs,
-                                     const upb_MiniTable_Field* field) {
-  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
-  return _upb_Message_New_inl(subl, &d->arena);
-}
-
-UPB_NOINLINE
-const char* decode_isdonefallback(upb_Decoder* d, const char* ptr,
-                                  int overrun) {
-  int status;
-  ptr = decode_isdonefallback_inl(d, ptr, overrun, &status);
-  if (ptr == NULL) {
-    return decode_err(d, status);
-  }
-  return ptr;
-}
-
-static const char* decode_readstr(upb_Decoder* d, const char* ptr, int size,
-                                  upb_StringView* str) {
-  if (d->options & kUpb_DecodeOption_AliasString) {
-    str->data = ptr;
-  } else {
-    char* data = upb_Arena_Malloc(&d->arena, size);
-    if (!data) return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    memcpy(data, ptr, size);
-    str->data = data;
-  }
-  str->size = size;
-  return ptr + size;
-}
-
-UPB_FORCEINLINE
-static const char* decode_tosubmsg2(upb_Decoder* d, const char* ptr,
-                                    upb_Message* submsg,
-                                    const upb_MiniTable* subl, int size) {
-  int saved_delta = decode_pushlimit(d, ptr, size);
-  if (--d->depth < 0) return decode_err(d, kUpb_DecodeStatus_MaxDepthExceeded);
-  ptr = decode_msg(d, ptr, submsg, subl);
-  if (d->end_group != DECODE_NOGROUP)
-    return decode_err(d, kUpb_DecodeStatus_Malformed);
-  decode_poplimit(d, ptr, saved_delta);
-  d->depth++;
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_tosubmsg(upb_Decoder* d, const char* ptr,
-                                   upb_Message* submsg,
-                                   const upb_MiniTable_Sub* subs,
-                                   const upb_MiniTable_Field* field, int size) {
-  return decode_tosubmsg2(d, ptr, submsg, subs[field->submsg_index].submsg,
-                          size);
-}
-
-UPB_FORCEINLINE
-static const char* decode_group(upb_Decoder* d, const char* ptr,
-                                upb_Message* submsg, const upb_MiniTable* subl,
-                                uint32_t number) {
-  if (--d->depth < 0) return decode_err(d, kUpb_DecodeStatus_MaxDepthExceeded);
-  if (decode_isdone(d, &ptr)) {
-    return decode_err(d, kUpb_DecodeStatus_Malformed);
-  }
-  ptr = decode_msg(d, ptr, submsg, subl);
-  if (d->end_group != number) return decode_err(d, kUpb_DecodeStatus_Malformed);
-  d->end_group = DECODE_NOGROUP;
-  d->depth++;
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_togroup(upb_Decoder* d, const char* ptr,
-                                  upb_Message* submsg,
-                                  const upb_MiniTable_Sub* subs,
-                                  const upb_MiniTable_Field* field) {
-  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
-  return decode_group(d, ptr, submsg, subl, field->number);
-}
-
-static char* encode_varint32(uint32_t val, char* ptr) {
-  do {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    *(ptr++) = byte;
-  } while (val);
-  return ptr;
-}
-
-UPB_NOINLINE
-static bool decode_checkenum_slow(upb_Decoder* d, const char* ptr,
-                                  upb_Message* msg, const upb_MiniTable_Enum* e,
-                                  const upb_MiniTable_Field* field,
-                                  uint32_t v) {
-  // OPT: binary search long lists?
-  int n = e->value_count;
-  for (int i = 0; i < n; i++) {
-    if ((uint32_t)e->values[i] == v) return true;
-  }
-
-  // Unrecognized enum goes into unknown fields.
-  // For packed fields the tag could be arbitrarily far in the past, so we
-  // just re-encode the tag here.
-  char buf[20];
-  char* end = buf;
-  uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Varint;
-  end = encode_varint32(tag, end);
-  end = encode_varint32(v, end);
-
-  if (!_upb_Message_AddUnknown(msg, buf, end - buf, &d->arena)) {
-    decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-  }
-
-  return false;
-}
-
-UPB_FORCEINLINE
-static bool decode_checkenum(upb_Decoder* d, const char* ptr, upb_Message* msg,
-                             const upb_MiniTable_Enum* e,
-                             const upb_MiniTable_Field* field, wireval* val) {
-  uint32_t v = val->uint32_val;
-
-  if (UPB_LIKELY(v < 64) && UPB_LIKELY(((1ULL << v) & e->mask))) return true;
-
-  return decode_checkenum_slow(d, ptr, msg, e, field, v);
-}
-
-UPB_NOINLINE
-static const char* decode_enum_toarray(upb_Decoder* d, const char* ptr,
-                                       upb_Message* msg, upb_Array* arr,
-                                       const upb_MiniTable_Sub* subs,
-                                       const upb_MiniTable_Field* field,
-                                       wireval* val) {
-  const upb_MiniTable_Enum* e = subs[field->submsg_index].subenum;
-  if (!decode_checkenum(d, ptr, msg, e, field, val)) return ptr;
-  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len * 4, void);
-  arr->len++;
-  memcpy(mem, val, 4);
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_fixed_packed(upb_Decoder* d, const char* ptr,
-                                       upb_Array* arr, wireval* val,
-                                       const upb_MiniTable_Field* field,
-                                       int lg2) {
-  int mask = (1 << lg2) - 1;
-  size_t count = val->size >> lg2;
-  if ((val->size & mask) != 0) {
-    // Length isn't a round multiple of elem size.
-    return decode_err(d, kUpb_DecodeStatus_Malformed);
-  }
-  decode_reserve(d, arr, count);
-  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-  arr->len += count;
-  // Note: if/when the decoder supports multi-buffer input, we will need to
-  // handle buffer seams here.
-  if (_upb_IsLittleEndian()) {
-    memcpy(mem, ptr, val->size);
-    ptr += val->size;
-  } else {
-    const char* end = ptr + val->size;
-    char* dst = mem;
-    while (ptr < end) {
-      if (lg2 == 2) {
-        uint32_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap32(val);
-        memcpy(dst, &val, sizeof(val));
-      } else {
-        UPB_ASSERT(lg2 == 3);
-        uint64_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap64(val);
-        memcpy(dst, &val, sizeof(val));
-      }
-      ptr += 1 << lg2;
-      dst += 1 << lg2;
-    }
-  }
-
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_varint_packed(upb_Decoder* d, const char* ptr,
-                                        upb_Array* arr, wireval* val,
-                                        const upb_MiniTable_Field* field,
-                                        int lg2) {
-  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;
-}
-
-UPB_NOINLINE
-static const char* decode_enum_packed(upb_Decoder* d, const char* ptr,
-                                      upb_Message* msg, upb_Array* arr,
-                                      const upb_MiniTable_Sub* subs,
-                                      const upb_MiniTable_Field* field,
-                                      wireval* val) {
-  const upb_MiniTable_Enum* e = subs[field->submsg_index].subenum;
-  int saved_limit = decode_pushlimit(d, ptr, val->size);
-  char* out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len * 4, void);
-  while (!decode_isdone(d, &ptr)) {
-    wireval elem;
-    ptr = decode_varint64(d, ptr, &elem.uint64_val);
-    decode_munge_int32(&elem);
-    if (!decode_checkenum(d, ptr, msg, e, field, &elem)) {
-      continue;
-    }
-    if (decode_reserve(d, arr, 1)) {
-      out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len * 4, void);
-    }
-    arr->len++;
-    memcpy(out, &elem, 4);
-    out += 4;
-  }
-  decode_poplimit(d, ptr, saved_limit);
-  return ptr;
-}
-
-static const char* decode_toarray(upb_Decoder* d, const char* ptr,
-                                  upb_Message* msg,
-                                  const upb_MiniTable_Sub* subs,
-                                  const upb_MiniTable_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) return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    *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_StringView* str = (upb_StringView*)_upb_array_ptr(arr) + arr->len;
-      arr->len++;
-      return decode_readstr(d, ptr, val->size, str);
-    }
-    case OP_SUBMSG: {
-      /* Append submessage / group. */
-      upb_Message* submsg = decode_newsubmsg(d, subs, field);
-      *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void*), upb_Message*) =
-          submsg;
-      arr->len++;
-      if (UPB_UNLIKELY(field->descriptortype == kUpb_FieldType_Group)) {
-        return decode_togroup(d, ptr, submsg, subs, field);
-      } else {
-        return decode_tosubmsg(d, ptr, submsg, subs, field, val->size);
-      }
-    }
-    case OP_FIXPCK_LG2(2):
-    case OP_FIXPCK_LG2(3):
-      return decode_fixed_packed(d, ptr, arr, val, field,
-                                 op - OP_FIXPCK_LG2(0));
-    case OP_VARPCK_LG2(0):
-    case OP_VARPCK_LG2(2):
-    case OP_VARPCK_LG2(3):
-      return decode_varint_packed(d, ptr, arr, val, field,
-                                  op - OP_VARPCK_LG2(0));
-    case OP_ENUM:
-      return decode_enum_toarray(d, ptr, msg, arr, subs, field, val);
-    case OP_PACKED_ENUM:
-      return decode_enum_packed(d, ptr, msg, arr, subs, field, val);
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-static const char* decode_tomap(upb_Decoder* d, const char* ptr,
-                                upb_Message* msg, const upb_MiniTable_Sub* subs,
-                                const upb_MiniTable_Field* field,
-                                wireval* val) {
-  upb_Map** map_p = UPB_PTR_AT(msg, field->offset, upb_Map*);
-  upb_Map* map = *map_p;
-  upb_MapEntry ent;
-  const upb_MiniTable* entry = subs[field->submsg_index].submsg;
-
-  if (!map) {
-    /* Lazily create map. */
-    const upb_MiniTable_Field* key_field = &entry->fields[0];
-    const upb_MiniTable_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_StringView));
-    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 == kUpb_FieldType_Message ||
-      entry->fields[1].descriptortype == kUpb_FieldType_Group) {
-    /* Create proactively to handle the case where it doesn't appear. */
-    ent.v.val =
-        upb_value_ptr(_upb_Message_New(entry->subs[0].submsg, &d->arena));
-  }
-
-  ptr = decode_tosubmsg(d, ptr, &ent.k, subs, 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_Decoder* d, const char* ptr,
-                                upb_Message* msg, const upb_MiniTable_Sub* subs,
-                                const upb_MiniTable_Field* field, wireval* val,
-                                int op) {
-  void* mem = UPB_PTR_AT(msg, field->offset, void);
-  int type = field->descriptortype;
-
-  if (UPB_UNLIKELY(op == OP_ENUM) &&
-      !decode_checkenum(d, ptr, msg, subs[field->submsg_index].subenum, field,
-                        val)) {
-    return ptr;
-  }
-
-  /* Set presence if necessary. */
-  if (field->presence > 0) {
-    _upb_sethas_field(msg, field);
-  } else 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;
-  }
-
-  /* Store into message. */
-  switch (op) {
-    case OP_SUBMSG: {
-      upb_Message** submsgp = mem;
-      upb_Message* submsg = *submsgp;
-      if (!submsg) {
-        submsg = decode_newsubmsg(d, subs, field);
-        *submsgp = submsg;
-      }
-      if (UPB_UNLIKELY(type == kUpb_FieldType_Group)) {
-        ptr = decode_togroup(d, ptr, submsg, subs, field);
-      } else {
-        ptr = decode_tosubmsg(d, ptr, submsg, subs, 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_ENUM:
-    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_NOINLINE
-const char* decode_checkrequired(upb_Decoder* d, const char* ptr,
-                                 const upb_Message* msg,
-                                 const upb_MiniTable* l) {
-  assert(l->required_count);
-  if (UPB_LIKELY((d->options & kUpb_DecodeOption_CheckRequired) == 0)) {
-    return ptr;
-  }
-  uint64_t msg_head;
-  memcpy(&msg_head, msg, 8);
-  msg_head = _upb_BigEndian_Swap64(msg_head);
-  if (upb_MiniTable_requiredmask(l) & ~msg_head) {
-    d->missing_required = true;
-  }
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static bool decode_tryfastdispatch(upb_Decoder* d, const char** ptr,
-                                   upb_Message* msg,
-                                   const upb_MiniTable* 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;
-}
-
-static const char* decode_msgset(upb_Decoder* d, const char* ptr,
-                                 upb_Message* msg,
-                                 const upb_MiniTable* layout) {
-  // We create a temporary upb_MiniTable here and abuse its fields as temporary
-  // storage, to avoid creating lots of MessageSet-specific parsing code-paths:
-  //   1. We store 'layout' in item_layout.subs.  We will need this later as
-  //      a key to look up extensions for this MessageSet.
-  //   2. We use item_layout.fields as temporary storage to store the extension
-  //   we
-  //      found when parsing the type id.
-  upb_MiniTable item_layout = {
-      .subs = (const upb_MiniTable_Sub[]){{.submsg = layout}},
-      .fields = NULL,
-      .size = 0,
-      .field_count = 0,
-      .ext = upb_ExtMode_IsMessageSet_ITEM,
-      .dense_below = 0,
-      .table_mask = -1};
-  return decode_group(d, ptr, msg, &item_layout, 1);
-}
-
-static const upb_MiniTable_Field* decode_findfield(upb_Decoder* d,
-                                                   const upb_MiniTable* l,
-                                                   uint32_t field_number,
-                                                   int* last_field_index) {
-  static upb_MiniTable_Field none = {0, 0, 0, 0, 0, 0};
-  if (l == NULL) return &none;
-
-  size_t idx = ((size_t)field_number) - 1;  // 0 wraps to SIZE_MAX
-  if (idx < l->dense_below) {
-    /* Fastest case: index into dense fields. */
-    goto found;
-  }
-
-  if (l->dense_below < l->field_count) {
-    /* Linear search non-dense fields. Resume scanning from last_field_index
-     * since fields are usually in order. */
-    int last = *last_field_index;
-    for (idx = last; idx < l->field_count; idx++) {
-      if (l->fields[idx].number == field_number) {
-        goto found;
-      }
-    }
-
-    for (idx = l->dense_below; idx < last; idx++) {
-      if (l->fields[idx].number == field_number) {
-        goto found;
-      }
-    }
-  }
-
-  if (d->extreg) {
-    switch (l->ext) {
-      case upb_ExtMode_Extendable: {
-        const upb_MiniTable_Extension* ext =
-            _upb_extreg_get(d->extreg, l, field_number);
-        if (ext) return &ext->field;
-        break;
-      }
-      case upb_ExtMode_IsMessageSet:
-        if (field_number == _UPB_MSGSET_ITEM) {
-          static upb_MiniTable_Field item = {0, 0, 0, 0, TYPE_MSGSET_ITEM, 0};
-          return &item;
-        }
-        break;
-      case upb_ExtMode_IsMessageSet_ITEM:
-        switch (field_number) {
-          case _UPB_MSGSET_TYPEID: {
-            static upb_MiniTable_Field type_id = {
-                0, 0, 0, 0, TYPE_MSGSET_TYPE_ID, 0};
-            return &type_id;
-          }
-          case _UPB_MSGSET_MESSAGE:
-            if (l->fields) {
-              // We saw type_id previously and succeeded in looking up msg.
-              return l->fields;
-            } else {
-              // TODO: out of order MessageSet.
-              // This is a very rare case: all serializers will emit in-order
-              // MessageSets.  To hit this case there has to be some kind of
-              // re-ordering proxy.  We should eventually handle this case, but
-              // not today.
-            }
-            break;
-        }
-    }
-  }
-
-  return &none; /* Unknown field. */
-
-found:
-  UPB_ASSERT(l->fields[idx].number == field_number);
-  *last_field_index = idx;
-  return &l->fields[idx];
-}
-
-UPB_FORCEINLINE
-static const char* decode_wireval(upb_Decoder* d, const char* ptr,
-                                  const upb_MiniTable_Field* field,
-                                  int wire_type, wireval* val, int* op) {
-  switch (wire_type) {
-    case kUpb_WireType_Varint:
-      ptr = decode_varint64(d, ptr, &val->uint64_val);
-      *op = varint_ops[field->descriptortype];
-      decode_munge(field->descriptortype, val);
-      return ptr;
-    case kUpb_WireType_32Bit:
-      memcpy(&val->uint32_val, ptr, 4);
-      val->uint32_val = _upb_BigEndian_Swap32(val->uint32_val);
-      *op = OP_SCALAR_LG2(2);
-      if (((1 << field->descriptortype) & FIXED32_OK_MASK) == 0) {
-        *op = OP_UNKNOWN;
-      }
-      return ptr + 4;
-    case kUpb_WireType_64Bit:
-      memcpy(&val->uint64_val, ptr, 8);
-      val->uint64_val = _upb_BigEndian_Swap64(val->uint64_val);
-      *op = OP_SCALAR_LG2(3);
-      if (((1 << field->descriptortype) & FIXED64_OK_MASK) == 0) {
-        *op = OP_UNKNOWN;
-      }
-      return ptr + 8;
-    case kUpb_WireType_Delimited: {
-      int ndx = field->descriptortype;
-      uint64_t size;
-      if (upb_FieldMode_Get(field) == kUpb_FieldMode_Array) ndx += TYPE_COUNT;
-      ptr = decode_varint64(d, ptr, &size);
-      if (size >= INT32_MAX || ptr - d->end + (int32_t)size > d->limit) {
-        break; /* Length overflow. */
-      }
-      *op = delim_ops[ndx];
-      val->size = size;
-      return ptr;
-    }
-    case kUpb_WireType_StartGroup:
-      val->uint32_val = field->number;
-      if (field->descriptortype == kUpb_FieldType_Group) {
-        *op = OP_SUBMSG;
-      } else if (field->descriptortype == TYPE_MSGSET_ITEM) {
-        *op = OP_MSGSET_ITEM;
-      } else {
-        *op = OP_UNKNOWN;
-      }
-      return ptr;
-    default:
-      break;
-  }
-  return decode_err(d, kUpb_DecodeStatus_Malformed);
-}
-
-UPB_FORCEINLINE
-static const char* decode_known(upb_Decoder* d, const char* ptr,
-                                upb_Message* msg, const upb_MiniTable* layout,
-                                const upb_MiniTable_Field* field, int op,
-                                wireval* val) {
-  const upb_MiniTable_Sub* subs = layout->subs;
-  uint8_t mode = field->mode;
-
-  if (UPB_UNLIKELY(mode & upb_LabelFlags_IsExtension)) {
-    const upb_MiniTable_Extension* ext_layout =
-        (const upb_MiniTable_Extension*)field;
-    upb_Message_Extension* ext =
-        _upb_Message_Getorcreateext(msg, ext_layout, &d->arena);
-    if (UPB_UNLIKELY(!ext)) return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    msg = &ext->data;
-    subs = &ext->ext->sub;
-  }
-
-  switch (mode & kUpb_FieldMode_Mask) {
-    case kUpb_FieldMode_Array:
-      return decode_toarray(d, ptr, msg, subs, field, val, op);
-    case kUpb_FieldMode_Map:
-      return decode_tomap(d, ptr, msg, subs, field, val);
-    case kUpb_FieldMode_Scalar:
-      return decode_tomsg(d, ptr, msg, subs, field, val, op);
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-static const char* decode_reverse_skip_varint(const char* ptr, uint32_t val) {
-  uint32_t seen = 0;
-  do {
-    ptr--;
-    seen <<= 7;
-    seen |= *ptr & 0x7f;
-  } while (seen != val);
-  return ptr;
-}
-
-static const char* decode_unknown(upb_Decoder* d, const char* ptr,
-                                  upb_Message* msg, int field_number,
-                                  int wire_type, wireval val) {
-  if (field_number == 0) return decode_err(d, kUpb_DecodeStatus_Malformed);
-
-  // Since unknown fields are the uncommon case, we do a little extra work here
-  // to walk backwards through the buffer to find the field start.  This frees
-  // up a register in the fast paths (when the field is known), which leads to
-  // significant speedups in benchmarks.
-  const char* start = ptr;
-
-  if (wire_type == kUpb_WireType_Delimited) ptr += val.size;
-  if (msg) {
-    switch (wire_type) {
-      case kUpb_WireType_Varint:
-      case kUpb_WireType_Delimited:
-        start--;
-        while (start[-1] & 0x80) start--;
-        break;
-      case kUpb_WireType_32Bit:
-        start -= 4;
-        break;
-      case kUpb_WireType_64Bit:
-        start -= 8;
-        break;
-      default:
-        break;
-    }
-
-    assert(start == d->debug_valstart);
-    uint32_t tag = ((uint32_t)field_number << 3) | wire_type;
-    start = decode_reverse_skip_varint(start, tag);
-    assert(start == d->debug_tagstart);
-
-    if (wire_type == kUpb_WireType_StartGroup) {
-      d->unknown = start;
-      d->unknown_msg = msg;
-      ptr = decode_group(d, ptr, NULL, NULL, field_number);
-      start = d->unknown;
-      d->unknown_msg = NULL;
-      d->unknown = NULL;
-    }
-    if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
-      return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    }
-  } else if (wire_type == kUpb_WireType_StartGroup) {
-    ptr = decode_group(d, ptr, NULL, NULL, field_number);
-  }
-  return ptr;
-}
-
-UPB_NOINLINE
-static const char* decode_msg(upb_Decoder* d, const char* ptr, upb_Message* msg,
-                              const upb_MiniTable* layout) {
-  int last_field_index = 0;
-
-#if UPB_FASTTABLE
-  // The first time we want to skip fast dispatch, because we may have just been
-  // invoked by the fast parser to handle a case that it bailed on.
-  if (!decode_isdone(d, &ptr)) goto nofast;
-#endif
-
-  while (!decode_isdone(d, &ptr)) {
-    uint32_t tag;
-    const upb_MiniTable_Field* field;
-    int field_number;
-    int wire_type;
-    wireval val;
-    int op;
-
-    if (decode_tryfastdispatch(d, &ptr, msg, layout)) break;
-
-#if UPB_FASTTABLE
-  nofast:
-#endif
-
-#ifndef NDEBUG
-    d->debug_tagstart = ptr;
-#endif
-
-    UPB_ASSERT(ptr < d->limit_ptr);
-    ptr = decode_tag(d, ptr, &tag);
-    field_number = tag >> 3;
-    wire_type = tag & 7;
-
-#ifndef NDEBUG
-    d->debug_valstart = ptr;
-#endif
-
-    if (wire_type == kUpb_WireType_EndGroup) {
-      d->end_group = field_number;
-      return ptr;
-    }
-
-    field = decode_findfield(d, layout, field_number, &last_field_index);
-    ptr = decode_wireval(d, ptr, field, wire_type, &val, &op);
-
-    if (op >= 0) {
-      ptr = decode_known(d, ptr, msg, layout, field, op, &val);
-    } else {
-      switch (op) {
-        case OP_UNKNOWN:
-          ptr = decode_unknown(d, ptr, msg, field_number, wire_type, val);
-          break;
-        case OP_MSGSET_ITEM:
-          ptr = decode_msgset(d, ptr, msg, layout);
-          break;
-        case OP_MSGSET_TYPEID: {
-          const upb_MiniTable_Extension* ext = _upb_extreg_get(
-              d->extreg, layout->subs[0].submsg, val.uint64_val);
-          if (ext) ((upb_MiniTable*)layout)->fields = &ext->field;
-          break;
-        }
-      }
-    }
-  }
-
-  return UPB_UNLIKELY(layout && layout->required_count)
-             ? decode_checkrequired(d, ptr, msg, layout)
-             : ptr;
-}
-
-const char* fastdecode_generic(struct upb_Decoder* d, const char* ptr,
-                               upb_Message* 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 upb_DecodeStatus decode_top(struct upb_Decoder* d, const char* buf,
-                                   void* msg, const upb_MiniTable* l) {
-  if (!decode_tryfastdispatch(d, &buf, msg, l)) {
-    decode_msg(d, buf, msg, l);
-  }
-  if (d->end_group != DECODE_NOGROUP) return kUpb_DecodeStatus_Malformed;
-  if (d->missing_required) return kUpb_DecodeStatus_MissingRequired;
-  return kUpb_DecodeStatus_Ok;
-}
-
-upb_DecodeStatus upb_Decode(const char* buf, size_t size, void* msg,
-                            const upb_MiniTable* l,
-                            const upb_ExtensionRegistry* extreg, int options,
-                            upb_Arena* arena) {
-  upb_Decoder state;
-  unsigned depth = (unsigned)options >> 16;
-
-  if (size <= 16) {
-    memset(&state.patch, 0, 32);
-    if (size) memcpy(&state.patch, buf, size);
-    buf = state.patch;
-    state.end = buf + size;
-    state.limit = 0;
-    options &= ~kUpb_DecodeOption_AliasString;  // Can't alias patch buf.
-  } else {
-    state.end = buf + size - 16;
-    state.limit = 16;
-  }
-
-  state.extreg = extreg;
-  state.limit_ptr = state.end;
-  state.unknown_msg = NULL;
-  state.depth = depth ? depth : 64;
-  state.end_group = DECODE_NOGROUP;
-  state.options = (uint16_t)options;
-  state.missing_required = false;
-  state.arena.head = arena->head;
-  state.arena.last_size = arena->last_size;
-  state.arena.cleanup_metadata = arena->cleanup_metadata;
-  state.arena.parent = arena;
-
-  upb_DecodeStatus status = UPB_SETJMP(state.err);
-  if (UPB_LIKELY(status == kUpb_DecodeStatus_Ok)) {
-    status = 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 status;
-}
-
-#undef OP_UNKNOWN
-#undef OP_SKIP
-#undef OP_SCALAR_LG2
-#undef OP_FIXPCK_LG2
-#undef OP_VARPCK_LG2
-#undef OP_STRING
-#undef OP_BYTES
-#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_BigEndian_Swap64(val);
-  encode_bytes(e, &val, sizeof(uint64_t));
-}
-
-static void encode_fixed32(upb_encstate* e, uint32_t val) {
-  val = _upb_BigEndian_Swap32(val);
-  encode_bytes(e, &val, sizeof(uint32_t));
-}
-
-UPB_NOINLINE
-static void encode_longvarint(upb_encstate* e, uint64_t val) {
+void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
+                                   va_list args) {
   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;
+  if (!status) return;
+  status->ok = false;
+  len = strlen(status->msg);
+  vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
+  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
 }
 
-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);
-  }
+#include <string.h>
+
+
+// Must be last.
+
+static const char _upb_CTypeo_sizelg2[12] = {
+    0,
+    0,              /* kUpb_CType_Bool */
+    2,              /* kUpb_CType_Float */
+    2,              /* kUpb_CType_Int32 */
+    2,              /* kUpb_CType_UInt32 */
+    2,              /* kUpb_CType_Enum */
+    UPB_SIZE(2, 3), /* kUpb_CType_Message */
+    3,              /* kUpb_CType_Double */
+    3,              /* kUpb_CType_Int64 */
+    3,              /* kUpb_CType_UInt64 */
+    UPB_SIZE(3, 4), /* kUpb_CType_String */
+    UPB_SIZE(3, 4), /* kUpb_CType_Bytes */
+};
+
+upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) {
+  return _upb_Array_New(a, 4, _upb_CTypeo_sizelg2[type]);
 }
 
-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);
-}
+size_t upb_Array_Size(const upb_Array* arr) { return arr->size; }
 
-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;
+upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) {
+  upb_MessageValue ret;
   const char* data = _upb_array_constptr(arr);
-  const char* ptr = data + bytes - elem_size;
-
-  if (tag || !_upb_IsLittleEndian()) {
-    while (true) {
-      if (elem_size == 4) {
-        uint32_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap32(val);
-        encode_bytes(e, &val, elem_size);
-      } else {
-        UPB_ASSERT(elem_size == 8);
-        uint64_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap64(val);
-        encode_bytes(e, &val, elem_size);
-      }
-
-      if (tag) 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 upb_Message* msg,
-                           const upb_MiniTable* m, size_t* size);
-
-static void encode_scalar(upb_encstate* e, const void* _field_mem,
-                          const upb_MiniTable_Sub* subs,
-                          const upb_MiniTable_Field* f) {
-  const char* field_mem = _field_mem;
-  int wire_type;
-
-#define CASE(ctype, type, wtype, encodeval) \
-  {                                         \
-    ctype val = *(ctype*)field_mem;         \
-    encode_##type(e, encodeval);            \
-    wire_type = wtype;                      \
-    break;                                  \
-  }
-
-  switch (f->descriptortype) {
-    case kUpb_FieldType_Double:
-      CASE(double, double, kUpb_WireType_64Bit, val);
-    case kUpb_FieldType_Float:
-      CASE(float, float, kUpb_WireType_32Bit, val);
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_UInt64:
-      CASE(uint64_t, varint, kUpb_WireType_Varint, val);
-    case kUpb_FieldType_UInt32:
-      CASE(uint32_t, varint, kUpb_WireType_Varint, val);
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_Enum:
-      CASE(int32_t, varint, kUpb_WireType_Varint, (int64_t)val);
-    case kUpb_FieldType_SFixed64:
-    case kUpb_FieldType_Fixed64:
-      CASE(uint64_t, fixed64, kUpb_WireType_64Bit, val);
-    case kUpb_FieldType_Fixed32:
-    case kUpb_FieldType_SFixed32:
-      CASE(uint32_t, fixed32, kUpb_WireType_32Bit, val);
-    case kUpb_FieldType_Bool:
-      CASE(bool, varint, kUpb_WireType_Varint, val);
-    case kUpb_FieldType_SInt32:
-      CASE(int32_t, varint, kUpb_WireType_Varint, encode_zz32(val));
-    case kUpb_FieldType_SInt64:
-      CASE(int64_t, varint, kUpb_WireType_Varint, encode_zz64(val));
-    case kUpb_FieldType_String:
-    case kUpb_FieldType_Bytes: {
-      upb_StringView view = *(upb_StringView*)field_mem;
-      encode_bytes(e, view.data, view.size);
-      encode_varint(e, view.size);
-      wire_type = kUpb_WireType_Delimited;
-      break;
-    }
-    case kUpb_FieldType_Group: {
-      size_t size;
-      void* submsg = *(void**)field_mem;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      if (submsg == NULL) {
-        return;
-      }
-      if (--e->depth == 0) encode_err(e);
-      encode_tag(e, f->number, kUpb_WireType_EndGroup);
-      encode_message(e, submsg, subm, &size);
-      wire_type = kUpb_WireType_StartGroup;
-      e->depth++;
-      break;
-    }
-    case kUpb_FieldType_Message: {
-      size_t size;
-      void* submsg = *(void**)field_mem;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      if (submsg == NULL) {
-        return;
-      }
-      if (--e->depth == 0) encode_err(e);
-      encode_message(e, submsg, subm, &size);
-      encode_varint(e, size);
-      wire_type = kUpb_WireType_Delimited;
-      e->depth++;
-      break;
-    }
-    default:
-      UPB_UNREACHABLE();
-  }
-#undef CASE
-
-  encode_tag(e, f->number, wire_type);
-}
-
-static void encode_array(upb_encstate* e, const upb_Message* msg,
-                         const upb_MiniTable_Sub* subs,
-                         const upb_MiniTable_Field* f) {
-  const upb_Array* arr = *UPB_PTR_AT(msg, f->offset, upb_Array*);
-  bool packed = f->mode & upb_LabelFlags_IsPacked;
-  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) | kUpb_WireType_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 kUpb_FieldType_Double:
-      encode_fixedarray(e, arr, sizeof(double), TAG(kUpb_WireType_64Bit));
-      break;
-    case kUpb_FieldType_Float:
-      encode_fixedarray(e, arr, sizeof(float), TAG(kUpb_WireType_32Bit));
-      break;
-    case kUpb_FieldType_SFixed64:
-    case kUpb_FieldType_Fixed64:
-      encode_fixedarray(e, arr, sizeof(uint64_t), TAG(kUpb_WireType_64Bit));
-      break;
-    case kUpb_FieldType_Fixed32:
-    case kUpb_FieldType_SFixed32:
-      encode_fixedarray(e, arr, sizeof(uint32_t), TAG(kUpb_WireType_32Bit));
-      break;
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_UInt64:
-      VARINT_CASE(uint64_t, *ptr);
-    case kUpb_FieldType_UInt32:
-      VARINT_CASE(uint32_t, *ptr);
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_Enum:
-      VARINT_CASE(int32_t, (int64_t)*ptr);
-    case kUpb_FieldType_Bool:
-      VARINT_CASE(bool, *ptr);
-    case kUpb_FieldType_SInt32:
-      VARINT_CASE(int32_t, encode_zz32(*ptr));
-    case kUpb_FieldType_SInt64:
-      VARINT_CASE(int64_t, encode_zz64(*ptr));
-    case kUpb_FieldType_String:
-    case kUpb_FieldType_Bytes: {
-      const upb_StringView* start = _upb_array_constptr(arr);
-      const upb_StringView* ptr = start + arr->len;
-      do {
-        ptr--;
-        encode_bytes(e, ptr->data, ptr->size);
-        encode_varint(e, ptr->size);
-        encode_tag(e, f->number, kUpb_WireType_Delimited);
-      } while (ptr != start);
-      return;
-    }
-    case kUpb_FieldType_Group: {
-      const void* const* start = _upb_array_constptr(arr);
-      const void* const* ptr = start + arr->len;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      if (--e->depth == 0) encode_err(e);
-      do {
-        size_t size;
-        ptr--;
-        encode_tag(e, f->number, kUpb_WireType_EndGroup);
-        encode_message(e, *ptr, subm, &size);
-        encode_tag(e, f->number, kUpb_WireType_StartGroup);
-      } while (ptr != start);
-      e->depth++;
-      return;
-    }
-    case kUpb_FieldType_Message: {
-      const void* const* start = _upb_array_constptr(arr);
-      const void* const* ptr = start + arr->len;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      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, kUpb_WireType_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, kUpb_WireType_Delimited);
-  }
-}
-
-static void encode_mapentry(upb_encstate* e, uint32_t number,
-                            const upb_MiniTable* layout,
-                            const upb_MapEntry* ent) {
-  const upb_MiniTable_Field* key_field = &layout->fields[0];
-  const upb_MiniTable_Field* val_field = &layout->fields[1];
-  size_t pre_len = e->limit - e->ptr;
-  size_t size;
-  encode_scalar(e, &ent->v, layout->subs, val_field);
-  encode_scalar(e, &ent->k, layout->subs, key_field);
-  size = (e->limit - e->ptr) - pre_len;
-  encode_varint(e, size);
-  encode_tag(e, number, kUpb_WireType_Delimited);
-}
-
-static void encode_map(upb_encstate* e, const upb_Message* msg,
-                       const upb_MiniTable_Sub* subs,
-                       const upb_MiniTable_Field* f) {
-  const upb_Map* map = *UPB_PTR_AT(msg, f->offset, const upb_Map*);
-  const upb_MiniTable* layout = subs[f->submsg_index].submsg;
-  UPB_ASSERT(layout->field_count == 2);
-
-  if (map == NULL) return;
-
-  if (e->options & kUpb_Encode_Deterministic) {
-    _upb_sortedmap sorted;
-    _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
-                           &sorted);
-    upb_MapEntry 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_StringView key = upb_strtable_iter_key(&i);
-      const upb_value val = upb_strtable_iter_value(&i);
-      upb_MapEntry 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 bool encode_shouldencode(upb_encstate* e, const upb_Message* msg,
-                                const upb_MiniTable_Sub* subs,
-                                const upb_MiniTable_Field* f) {
-  if (f->presence == 0) {
-    /* Proto3 presence or map/array. */
-    const void* mem = UPB_PTR_AT(msg, f->offset, void);
-    switch (f->mode >> upb_FieldRep_Shift) {
-      case upb_FieldRep_1Byte: {
-        char ch;
-        memcpy(&ch, mem, 1);
-        return ch != 0;
-      }
-      case upb_FieldRep_4Byte: {
-        uint32_t u32;
-        memcpy(&u32, mem, 4);
-        return u32 != 0;
-      }
-      case upb_FieldRep_8Byte: {
-        uint64_t u64;
-        memcpy(&u64, mem, 8);
-        return u64 != 0;
-      }
-      case upb_FieldRep_StringView: {
-        const upb_StringView* str = (const upb_StringView*)mem;
-        return str->size != 0;
-      }
-      default:
-        UPB_UNREACHABLE();
-    }
-  } else if (f->presence > 0) {
-    /* Proto2 presence: hasbit. */
-    return _upb_hasbit_field(msg, f);
-  } else {
-    /* Field is in a oneof. */
-    return _upb_getoneofcase_field(msg, f) == f->number;
-  }
-}
-
-static void encode_field(upb_encstate* e, const upb_Message* msg,
-                         const upb_MiniTable_Sub* subs,
-                         const upb_MiniTable_Field* field) {
-  switch (upb_FieldMode_Get(field)) {
-    case kUpb_FieldMode_Array:
-      encode_array(e, msg, subs, field);
-      break;
-    case kUpb_FieldMode_Map:
-      encode_map(e, msg, subs, field);
-      break;
-    case kUpb_FieldMode_Scalar:
-      encode_scalar(e, UPB_PTR_AT(msg, field->offset, void), subs, field);
-      break;
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-/* message MessageSet {
- *   repeated group Item = 1 {
- *     required int32 type_id = 2;
- *     required string message = 3;
- *   }
- * } */
-static void encode_msgset_item(upb_encstate* e,
-                               const upb_Message_Extension* ext) {
-  size_t size;
-  encode_tag(e, 1, kUpb_WireType_EndGroup);
-  encode_message(e, ext->data.ptr, ext->ext->sub.submsg, &size);
-  encode_varint(e, size);
-  encode_tag(e, 3, kUpb_WireType_Delimited);
-  encode_varint(e, ext->ext->field.number);
-  encode_tag(e, 2, kUpb_WireType_Varint);
-  encode_tag(e, 1, kUpb_WireType_StartGroup);
-}
-
-static void encode_message(upb_encstate* e, const upb_Message* msg,
-                           const upb_MiniTable* m, size_t* size) {
-  size_t pre_len = e->limit - e->ptr;
-
-  if ((e->options & kUpb_Encode_CheckRequired) && m->required_count) {
-    uint64_t msg_head;
-    memcpy(&msg_head, msg, 8);
-    msg_head = _upb_BigEndian_Swap64(msg_head);
-    if (upb_MiniTable_requiredmask(m) & ~msg_head) {
-      encode_err(e);
-    }
-  }
-
-  if ((e->options & kUpb_Encode_SkipUnknown) == 0) {
-    size_t unknown_size;
-    const char* unknown = upb_Message_GetUnknown(msg, &unknown_size);
-
-    if (unknown) {
-      encode_bytes(e, unknown, unknown_size);
-    }
-  }
-
-  if (m->ext != upb_ExtMode_NonExtendable) {
-    /* Encode all extensions together. Unlike C++, we do not attempt to keep
-     * these in field number order relative to normal fields or even to each
-     * other. */
-    size_t ext_count;
-    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &ext_count);
-    if (ext_count) {
-      const upb_Message_Extension* end = ext + ext_count;
-      for (; ext != end; ext++) {
-        if (UPB_UNLIKELY(m->ext == upb_ExtMode_IsMessageSet)) {
-          encode_msgset_item(e, ext);
-        } else {
-          encode_field(e, &ext->data, &ext->ext->sub, &ext->ext->field);
-        }
-      }
-    }
-  }
-
-  if (m->field_count) {
-    const upb_MiniTable_Field* f = &m->fields[m->field_count];
-    const upb_MiniTable_Field* first = &m->fields[0];
-    while (f != first) {
-      f--;
-      if (encode_shouldencode(e, msg, m->subs, f)) {
-        encode_field(e, msg, m->subs, f);
-      }
-    }
-  }
-
-  *size = (e->limit - e->ptr) - pre_len;
-}
-
-char* upb_Encode(const void* msg, const upb_MiniTable* 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);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->size);
+  memcpy(&ret, data + (i << lg2), 1 << lg2);
   return ret;
 }
 
-/** upb/msg.c ************************************************************/
-
-
-/** upb_Message
- * *******************************************************************/
-
-static const size_t overhead = sizeof(upb_Message_InternalData);
-
-static const upb_Message_Internal* upb_Message_Getinternal_const(
-    const upb_Message* msg) {
-  ptrdiff_t size = sizeof(upb_Message_Internal);
-  return (upb_Message_Internal*)((char*)msg - size);
+void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
+  char* data = _upb_array_ptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->size);
+  memcpy(data + (i << lg2), &val, 1 << lg2);
 }
 
-upb_Message* _upb_Message_New(const upb_MiniTable* l, upb_Arena* a) {
-  return _upb_Message_New_inl(l, a);
-}
-
-void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l) {
-  void* mem = UPB_PTR_AT(msg, -sizeof(upb_Message_Internal), char);
-  memset(mem, 0, upb_msg_sizeof(l));
-}
-
-static bool realloc_internal(upb_Message* msg, size_t need, upb_Arena* arena) {
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  if (!in->internal) {
-    /* No internal data, allocate from scratch. */
-    size_t size = UPB_MAX(128, _upb_Log2Ceilingsize(need + overhead));
-    upb_Message_InternalData* internal = upb_Arena_Malloc(arena, size);
-    if (!internal) return false;
-    internal->size = size;
-    internal->unknown_end = overhead;
-    internal->ext_begin = size;
-    in->internal = internal;
-  } else if (in->internal->ext_begin - in->internal->unknown_end < need) {
-    /* Internal data is too small, reallocate. */
-    size_t new_size = _upb_Log2Ceilingsize(in->internal->size + need);
-    size_t ext_bytes = in->internal->size - in->internal->ext_begin;
-    size_t new_ext_begin = new_size - ext_bytes;
-    upb_Message_InternalData* internal =
-        upb_Arena_Realloc(arena, in->internal, in->internal->size, new_size);
-    if (!internal) return false;
-    if (ext_bytes) {
-      /* Need to move extension data to the end. */
-      char* ptr = (char*)internal;
-      memmove(ptr + new_ext_begin, ptr + internal->ext_begin, ext_bytes);
-    }
-    internal->ext_begin = new_ext_begin;
-    internal->size = new_size;
-    in->internal = internal;
+bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
+  if (!upb_Array_Resize(arr, arr->size + 1, arena)) {
+    return false;
   }
-  UPB_ASSERT(in->internal->ext_begin - in->internal->unknown_end >= need);
+  upb_Array_Set(arr, arr->size - 1, val);
   return true;
 }
 
-bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
-                             upb_Arena* arena) {
-  if (!realloc_internal(msg, len, arena)) return false;
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  memcpy(UPB_PTR_AT(in->internal, in->internal->unknown_end, char), data, len);
-  in->internal->unknown_end += len;
+void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
+                    size_t count) {
+  char* data = _upb_array_ptr(arr);
+  int lg2 = arr->data & 7;
+  memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
+}
+
+bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
+                      upb_Arena* arena) {
+  UPB_ASSERT(i <= arr->size);
+  UPB_ASSERT(count + arr->size >= count);
+  size_t oldsize = arr->size;
+  if (!upb_Array_Resize(arr, arr->size + count, arena)) {
+    return false;
+  }
+  upb_Array_Move(arr, i + count, i, oldsize - i);
   return true;
 }
 
-void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  if (in->internal) {
-    in->internal->unknown_end = overhead;
-  }
+/*
+ *              i        end      arr->size
+ * |------------|XXXXXXXX|--------|
+ */
+void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
+  size_t end = i + count;
+  UPB_ASSERT(i <= end);
+  UPB_ASSERT(end <= arr->size);
+  upb_Array_Move(arr, i, end, arr->size - end);
+  arr->size -= count;
 }
 
-const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
-  const upb_Message_Internal* in = upb_Message_Getinternal_const(msg);
-  if (in->internal) {
-    *len = in->internal->unknown_end - overhead;
-    return (char*)(in->internal + 1);
-  } else {
-    *len = 0;
-    return NULL;
-  }
+bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) {
+  return _upb_Array_Resize(arr, size, arena);
 }
 
-const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
-                                                  size_t* count) {
-  const upb_Message_Internal* in = upb_Message_Getinternal_const(msg);
-  if (in->internal) {
-    *count = (in->internal->size - in->internal->ext_begin) /
-             sizeof(upb_Message_Extension);
-    return UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
-  } else {
-    *count = 0;
-    return NULL;
-  }
-}
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
 
-const upb_Message_Extension* _upb_Message_Getext(
-    const upb_Message* msg, const upb_MiniTable_Extension* e) {
-  size_t n;
-  const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &n);
-
-  /* For now we use linear search exclusively to find extensions. If this
-   * becomes an issue due to messages with lots of extensions, we can introduce
-   * a table of some sort. */
-  for (size_t i = 0; i < n; i++) {
-    if (ext[i].ext == e) {
-      return &ext[i];
-    }
-  }
-
-  return NULL;
-}
-
-void _upb_Message_Clearext(upb_Message* msg,
-                           const upb_MiniTable_Extension* ext_l) {
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  if (!in->internal) return;
-  const upb_Message_Extension* base =
-      UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
-  upb_Message_Extension* ext =
-      (upb_Message_Extension*)_upb_Message_Getext(msg, ext_l);
-  if (ext) {
-    *ext = *base;
-    in->internal->ext_begin += sizeof(upb_Message_Extension);
-  }
-}
-
-upb_Message_Extension* _upb_Message_Getorcreateext(
-    upb_Message* msg, const upb_MiniTable_Extension* e, upb_Arena* arena) {
-  upb_Message_Extension* ext =
-      (upb_Message_Extension*)_upb_Message_Getext(msg, e);
-  if (ext) return ext;
-  if (!realloc_internal(msg, sizeof(upb_Message_Extension), arena)) return NULL;
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  in->internal->ext_begin -= sizeof(upb_Message_Extension);
-  ext = UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
-  memset(ext, 0, sizeof(upb_Message_Extension));
-  ext->ext = e;
-  return ext;
-}
-
-size_t upb_Message_ExtensionCount(const upb_Message* msg) {
-  size_t count;
-  _upb_Message_Getexts(msg, &count);
-  return count;
-}
-
-/** 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);
+bool _upb_array_realloc(upb_Array* arr, size_t min_capacity, upb_Arena* arena) {
+  size_t new_capacity = UPB_MAX(arr->capacity, 4);
   int elem_size_lg2 = arr->data & 7;
-  size_t old_bytes = arr->size << elem_size_lg2;
+  size_t old_bytes = arr->capacity << 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;
+  // Log2 ceiling of size.
+  while (new_capacity < min_capacity) new_capacity *= 2;
 
-  new_bytes = new_size << elem_size_lg2;
+  new_bytes = new_capacity << elem_size_lg2;
   ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes);
 
   if (!ptr) {
@@ -2068,7 +420,7 @@
   }
 
   arr->data = _upb_tag_arrptr(ptr, elem_size_lg2);
-  arr->size = new_size;
+  arr->capacity = new_capacity;
   return true;
 }
 
@@ -2095,7 +447,7 @@
   upb_Array* arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
   if (!arr) return false;
 
-  size_t elems = arr->len;
+  size_t elems = arr->size;
 
   if (!_upb_Array_Resize(arr, elems + 1, arena)) {
     return false;
@@ -2106,14 +458,100 @@
   return true;
 }
 
-/** upb_Map *******************************************************************/
+
+#include <string.h>
+
+
+// Must be last.
+
+/* Strings/bytes are special-cased in maps. */
+static char _upb_CTypeo_mapsize[12] = {
+    0,
+    1,             /* kUpb_CType_Bool */
+    4,             /* kUpb_CType_Float */
+    4,             /* kUpb_CType_Int32 */
+    4,             /* kUpb_CType_UInt32 */
+    4,             /* kUpb_CType_Enum */
+    sizeof(void*), /* kUpb_CType_Message */
+    8,             /* kUpb_CType_Double */
+    8,             /* kUpb_CType_Int64 */
+    8,             /* kUpb_CType_UInt64 */
+    0,             /* kUpb_CType_String */
+    0,             /* kUpb_CType_Bytes */
+};
+
+upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) {
+  return _upb_Map_New(a, _upb_CTypeo_mapsize[key_type],
+                      _upb_CTypeo_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_MessageValue key,
+                 upb_MessageValue* 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); }
+
+upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
+                                   upb_MessageValue val, upb_Arena* arena) {
+  return (upb_MapInsertStatus)_upb_Map_Insert(map, &key, map->key_size, &val,
+                                              map->val_size, arena);
+}
+
+bool upb_Map_Delete(upb_Map* map, upb_MessageValue key) {
+  return _upb_Map_Delete(map, &key, map->key_size);
+}
+
+bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
+                  upb_MessageValue* val, size_t* iter) {
+  upb_StringView k;
+  upb_value v;
+  const bool ok = upb_strtable_next2(&map->table, &k, &v, (intptr_t*)iter);
+  if (ok) {
+    _upb_map_fromkey(k, key, map->key_size);
+    _upb_map_fromvalue(v, val, map->val_size);
+  }
+  return ok;
+}
+
+bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) {
+  return _upb_map_next(map, iter);
+}
+
+bool upb_MapIterator_Done(const upb_Map* map, size_t iter) {
+  upb_strtable_iter i;
+  UPB_ASSERT(iter != kUpb_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_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
+  upb_strtable_iter i;
+  upb_MessageValue ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
+  return ret;
+}
+
+upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
+  upb_strtable_iter i;
+  upb_MessageValue ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
+  return ret;
+}
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
 
 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;
-  }
+  if (!map) return NULL;
 
   upb_strtable_init(&map->table, 4, a);
   map->key_size = key_size;
@@ -2122,6 +560,9 @@
   return map;
 }
 
+
+// Must be last.
+
 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;
@@ -2132,36 +573,34 @@
   _upb_map_fromkey(b_tabkey, b_key, size);
 }
 
-#define UPB_COMPARE_INTEGERS(a, b) ((a) < (b) ? -1 : ((a) == (b) ? 0 : 1))
-
 static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) {
   int64_t a, b;
   _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
-  return UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : a > b;
 }
 
 static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) {
@@ -2170,10 +609,30 @@
   size_t common_size = UPB_MIN(a.size, b.size);
   int cmp = memcmp(a.data, b.data, common_size);
   if (cmp) return -cmp;
-  return UPB_COMPARE_INTEGERS(a.size, b.size);
+  return a.size < b.size ? -1 : a.size > b.size;
 }
 
-#undef UPB_COMPARE_INTEGERS
+static int (*const compar[kUpb_FieldType_SizeOf])(const void*, const void*) = {
+    [kUpb_FieldType_Int64] = _upb_mapsorter_cmpi64,
+    [kUpb_FieldType_SFixed64] = _upb_mapsorter_cmpi64,
+    [kUpb_FieldType_SInt64] = _upb_mapsorter_cmpi64,
+
+    [kUpb_FieldType_UInt64] = _upb_mapsorter_cmpu64,
+    [kUpb_FieldType_Fixed64] = _upb_mapsorter_cmpu64,
+
+    [kUpb_FieldType_Int32] = _upb_mapsorter_cmpi32,
+    [kUpb_FieldType_SInt32] = _upb_mapsorter_cmpi32,
+    [kUpb_FieldType_SFixed32] = _upb_mapsorter_cmpi32,
+    [kUpb_FieldType_Enum] = _upb_mapsorter_cmpi32,
+
+    [kUpb_FieldType_UInt32] = _upb_mapsorter_cmpu32,
+    [kUpb_FieldType_Fixed32] = _upb_mapsorter_cmpu32,
+
+    [kUpb_FieldType_Bool] = _upb_mapsorter_cmpbool,
+
+    [kUpb_FieldType_String] = _upb_mapsorter_cmpstr,
+    [kUpb_FieldType_Bytes] = _upb_mapsorter_cmpstr,
+};
 
 bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
                             const upb_Map* map, _upb_sortedmap* sorted) {
@@ -2182,16 +641,16 @@
   sorted->pos = sorted->start;
   sorted->end = sorted->start + map_size;
 
-  /* Grow s->entries if necessary. */
+  // Grow s->entries if necessary.
   if (sorted->end > s->cap) {
-    s->cap = _upb_Log2Ceilingsize(sorted->end);
+    s->cap = upb_Log2CeilingSize(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. */
+  // 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);
@@ -2203,107 +662,954 @@
   }
   UPB_ASSERT(dst == &s->entries[sorted->end]);
 
-  /* Sort entries according to the key type. */
-
-  int (*compar)(const void*, const void*);
-
-  switch (key_type) {
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_SFixed64:
-    case kUpb_FieldType_SInt64:
-      compar = _upb_mapsorter_cmpi64;
-      break;
-    case kUpb_FieldType_UInt64:
-    case kUpb_FieldType_Fixed64:
-      compar = _upb_mapsorter_cmpu64;
-      break;
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_SInt32:
-    case kUpb_FieldType_SFixed32:
-    case kUpb_FieldType_Enum:
-      compar = _upb_mapsorter_cmpi32;
-      break;
-    case kUpb_FieldType_UInt32:
-    case kUpb_FieldType_Fixed32:
-      compar = _upb_mapsorter_cmpu32;
-      break;
-    case kUpb_FieldType_Bool:
-      compar = _upb_mapsorter_cmpbool;
-      break;
-    case kUpb_FieldType_String:
-    case kUpb_FieldType_Bytes:
-      compar = _upb_mapsorter_cmpstr;
-      break;
-    default:
-      UPB_UNREACHABLE();
-  }
-
-  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
+  // Sort entries according to the key type.
+  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries),
+        compar[key_type]);
   return true;
 }
+/* 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. */
 
-/** upb_ExtensionRegistry
- * ****************************************************************/
+#include <stddef.h>
 
-struct upb_ExtensionRegistry {
-  upb_Arena* arena;
-  upb_strtable exts; /* Key is upb_MiniTable* concatenated with fieldnum. */
+
+static const upb_MiniTableSub google_protobuf_FileDescriptorSet_submsgs[1] = {
+  {.submsg = &google_protobuf_FileDescriptorProto_msg_init},
 };
 
-#define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
+static const upb_MiniTableField google_protobuf_FileDescriptorSet__fields[1] = {
+  {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
 
-static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
-  memcpy(buf, &l, sizeof(l));
-  memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
-}
+const upb_MiniTable google_protobuf_FileDescriptorSet_msg_init = {
+  &google_protobuf_FileDescriptorSet_submsgs[0],
+  &google_protobuf_FileDescriptorSet__fields[0],
+  8, 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+};
 
-upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
-  upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
-  if (!r) return NULL;
-  r->arena = arena;
-  if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
-  return r;
-}
+static const upb_MiniTableSub google_protobuf_FileDescriptorProto_submsgs[6] = {
+  {.submsg = &google_protobuf_DescriptorProto_msg_init},
+  {.submsg = &google_protobuf_EnumDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_ServiceDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_FieldDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_FileOptions_msg_init},
+  {.submsg = &google_protobuf_SourceCodeInfo_msg_init},
+};
 
-bool _upb_extreg_add(upb_ExtensionRegistry* r,
-                     const upb_MiniTable_Extension** e, size_t count) {
-  char buf[EXTREG_KEY_SIZE];
-  const upb_MiniTable_Extension** start = e;
-  const upb_MiniTable_Extension** end = UPB_PTRADD(e, count);
-  for (; e < end; e++) {
-    const upb_MiniTable_Extension* ext = *e;
-    extreg_key(buf, ext->extendee, ext->field.number);
-    if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
-                             upb_value_constptr(ext), r->arena)) {
-      goto failure;
-    }
-  }
-  return true;
+static const upb_MiniTableField google_protobuf_FileDescriptorProto__fields[13] = {
+  {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(4, 40), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(8, 48), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(12, 56), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(16, 64), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(20, 72), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {10, UPB_SIZE(32, 96), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {11, UPB_SIZE(36, 104), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+};
 
-failure:
-  /* Back out the entries previously added. */
-  for (end = e, e = start; e < end; e++) {
-    const upb_MiniTable_Extension* ext = *e;
-    extreg_key(buf, ext->extendee, ext->field.number);
-    upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
-  }
-  return false;
-}
+const upb_MiniTable google_protobuf_FileDescriptorProto_msg_init = {
+  &google_protobuf_FileDescriptorProto_submsgs[0],
+  &google_protobuf_FileDescriptorProto__fields[0],
+  UPB_SIZE(72, 144), 13, kUpb_ExtMode_NonExtendable, 13, 255, 0,
+};
 
-const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
-                                               const upb_MiniTable* l,
-                                               uint32_t num) {
-  char buf[EXTREG_KEY_SIZE];
-  upb_value v;
-  extreg_key(buf, l, num);
-  if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
-    return upb_value_getconstptr(v);
-  } else {
-    return NULL;
-  }
-}
+static const upb_MiniTableSub google_protobuf_DescriptorProto_submsgs[8] = {
+  {.submsg = &google_protobuf_FieldDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_DescriptorProto_msg_init},
+  {.submsg = &google_protobuf_EnumDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_DescriptorProto_ExtensionRange_msg_init},
+  {.submsg = &google_protobuf_FieldDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_MessageOptions_msg_init},
+  {.submsg = &google_protobuf_OneofDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_DescriptorProto_ReservedRange_msg_init},
+};
 
-/** upb/table.c ************************************************************/
+static const upb_MiniTableField google_protobuf_DescriptorProto__fields[10] = {
+  {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 32), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(16, 48), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(20, 56), 0, 4, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(28, 72), 0, 6, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {9, UPB_SIZE(32, 80), 0, 7, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {10, UPB_SIZE(36, 88), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_DescriptorProto_msg_init = {
+  &google_protobuf_DescriptorProto_submsgs[0],
+  &google_protobuf_DescriptorProto__fields[0],
+  UPB_SIZE(48, 96), 10, kUpb_ExtMode_NonExtendable, 10, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
+  {.submsg = &google_protobuf_ExtensionRangeOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
+  {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msg_init = {
+  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
+  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
+  UPB_SIZE(16, 24), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
+  {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msg_init = {
+  NULL,
+  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
+  16, 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_ExtensionRangeOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_ExtensionRangeOptions__fields[1] = {
+  {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_ExtensionRangeOptions_msg_init = {
+  &google_protobuf_ExtensionRangeOptions_submsgs[0],
+  &google_protobuf_ExtensionRangeOptions__fields[0],
+  8, 1, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_FieldDescriptorProto_submsgs[3] = {
+  {.subenum = &google_protobuf_FieldDescriptorProto_Label_enum_init},
+  {.subenum = &google_protobuf_FieldDescriptorProto_Type_enum_init},
+  {.submsg = &google_protobuf_FieldOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_FieldDescriptorProto__fields[11] = {
+  {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_FieldDescriptorProto_msg_init = {
+  &google_protobuf_FieldDescriptorProto_submsgs[0],
+  &google_protobuf_FieldDescriptorProto__fields[0],
+  UPB_SIZE(72, 112), 11, kUpb_ExtMode_NonExtendable, 10, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_OneofDescriptorProto_submsgs[1] = {
+  {.submsg = &google_protobuf_OneofOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_OneofDescriptorProto__fields[2] = {
+  {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_OneofDescriptorProto_msg_init = {
+  &google_protobuf_OneofDescriptorProto_submsgs[0],
+  &google_protobuf_OneofDescriptorProto__fields[0],
+  UPB_SIZE(16, 32), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumDescriptorProto_submsgs[3] = {
+  {.submsg = &google_protobuf_EnumValueDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_EnumOptions_msg_init},
+  {.submsg = &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumDescriptorProto__fields[5] = {
+  {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(16, 48), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumDescriptorProto_msg_init = {
+  &google_protobuf_EnumDescriptorProto_submsgs[0],
+  &google_protobuf_EnumDescriptorProto__fields[0],
+  UPB_SIZE(32, 56), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
+  {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init = {
+  NULL,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
+  16, 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
+  {.submsg = &google_protobuf_EnumValueOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumValueDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msg_init = {
+  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
+  &google_protobuf_EnumValueDescriptorProto__fields[0],
+  UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_ServiceDescriptorProto_submsgs[2] = {
+  {.submsg = &google_protobuf_MethodDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_ServiceOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_ServiceDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_ServiceDescriptorProto_msg_init = {
+  &google_protobuf_ServiceDescriptorProto_submsgs[0],
+  &google_protobuf_ServiceDescriptorProto__fields[0],
+  UPB_SIZE(24, 40), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_MethodDescriptorProto_submsgs[1] = {
+  {.submsg = &google_protobuf_MethodOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_MethodDescriptorProto__fields[6] = {
+  {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_MethodDescriptorProto_msg_init = {
+  &google_protobuf_MethodDescriptorProto_submsgs[0],
+  &google_protobuf_MethodDescriptorProto__fields[0],
+  UPB_SIZE(40, 64), 6, kUpb_ExtMode_NonExtendable, 6, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_FileOptions_submsgs[2] = {
+  {.subenum = &google_protobuf_FileOptions_OptimizeMode_enum_init},
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_FileOptions__fields[21] = {
+  {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(20, 184), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_FileOptions_msg_init = {
+  &google_protobuf_FileOptions_submsgs[0],
+  &google_protobuf_FileOptions__fields[0],
+  UPB_SIZE(104, 192), 21, kUpb_ExtMode_Extendable, 1, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_MessageOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_MessageOptions__fields[5] = {
+  {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, 8, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_MessageOptions_msg_init = {
+  &google_protobuf_MessageOptions_submsgs[0],
+  &google_protobuf_MessageOptions__fields[0],
+  16, 5, kUpb_ExtMode_Extendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_FieldOptions_submsgs[3] = {
+  {.subenum = &google_protobuf_FieldOptions_CType_enum_init},
+  {.subenum = &google_protobuf_FieldOptions_JSType_enum_init},
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_FieldOptions__fields[8] = {
+  {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(20, 24), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_FieldOptions_msg_init = {
+  &google_protobuf_FieldOptions_submsgs[0],
+  &google_protobuf_FieldOptions__fields[0],
+  UPB_SIZE(24, 32), 8, kUpb_ExtMode_Extendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_OneofOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_OneofOptions__fields[1] = {
+  {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_OneofOptions_msg_init = {
+  &google_protobuf_OneofOptions_submsgs[0],
+  &google_protobuf_OneofOptions__fields[0],
+  8, 1, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumOptions__fields[3] = {
+  {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumOptions_msg_init = {
+  &google_protobuf_EnumOptions_submsgs[0],
+  &google_protobuf_EnumOptions__fields[0],
+  UPB_SIZE(8, 16), 3, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumValueOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumValueOptions__fields[2] = {
+  {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumValueOptions_msg_init = {
+  &google_protobuf_EnumValueOptions_submsgs[0],
+  &google_protobuf_EnumValueOptions__fields[0],
+  UPB_SIZE(8, 16), 2, kUpb_ExtMode_Extendable, 1, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_ServiceOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_ServiceOptions__fields[2] = {
+  {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_ServiceOptions_msg_init = {
+  &google_protobuf_ServiceOptions_submsgs[0],
+  &google_protobuf_ServiceOptions__fields[0],
+  UPB_SIZE(8, 16), 2, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_MethodOptions_submsgs[2] = {
+  {.subenum = &google_protobuf_MethodOptions_IdempotencyLevel_enum_init},
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_MethodOptions__fields[3] = {
+  {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {999, 8, 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_MethodOptions_msg_init = {
+  &google_protobuf_MethodOptions_submsgs[0],
+  &google_protobuf_MethodOptions__fields[0],
+  16, 3, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_UninterpretedOption_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_NamePart_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_UninterpretedOption__fields[7] = {
+  {2, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_UninterpretedOption_msg_init = {
+  &google_protobuf_UninterpretedOption_submsgs[0],
+  &google_protobuf_UninterpretedOption__fields[0],
+  UPB_SIZE(56, 88), 7, kUpb_ExtMode_NonExtendable, 0, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_UninterpretedOption_NamePart__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msg_init = {
+  NULL,
+  &google_protobuf_UninterpretedOption_NamePart__fields[0],
+  UPB_SIZE(16, 24), 2, kUpb_ExtMode_NonExtendable, 2, 255, 2,
+};
+
+static const upb_MiniTableSub google_protobuf_SourceCodeInfo_submsgs[1] = {
+  {.submsg = &google_protobuf_SourceCodeInfo_Location_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_SourceCodeInfo__fields[1] = {
+  {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_SourceCodeInfo_msg_init = {
+  &google_protobuf_SourceCodeInfo_submsgs[0],
+  &google_protobuf_SourceCodeInfo__fields[0],
+  8, 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_SourceCodeInfo_Location__fields[5] = {
+  {1, UPB_SIZE(4, 8), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(8, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(12, 56), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msg_init = {
+  NULL,
+  &google_protobuf_SourceCodeInfo_Location__fields[0],
+  UPB_SIZE(32, 64), 5, kUpb_ExtMode_NonExtendable, 4, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_submsgs[1] = {
+  {.submsg = &google_protobuf_GeneratedCodeInfo_Annotation_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_GeneratedCodeInfo__fields[1] = {
+  {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_GeneratedCodeInfo_msg_init = {
+  &google_protobuf_GeneratedCodeInfo_submsgs[0],
+  &google_protobuf_GeneratedCodeInfo__fields[0],
+  8, 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_Annotation_submsgs[1] = {
+  {.subenum = &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init},
+};
+
+static const upb_MiniTableField google_protobuf_GeneratedCodeInfo_Annotation__fields[5] = {
+  {1, UPB_SIZE(4, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msg_init = {
+  &google_protobuf_GeneratedCodeInfo_Annotation_submsgs[0],
+  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
+  UPB_SIZE(32, 40), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0,
+};
+
+static const upb_MiniTable *messages_layout[27] = {
+  &google_protobuf_FileDescriptorSet_msg_init,
+  &google_protobuf_FileDescriptorProto_msg_init,
+  &google_protobuf_DescriptorProto_msg_init,
+  &google_protobuf_DescriptorProto_ExtensionRange_msg_init,
+  &google_protobuf_DescriptorProto_ReservedRange_msg_init,
+  &google_protobuf_ExtensionRangeOptions_msg_init,
+  &google_protobuf_FieldDescriptorProto_msg_init,
+  &google_protobuf_OneofDescriptorProto_msg_init,
+  &google_protobuf_EnumDescriptorProto_msg_init,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init,
+  &google_protobuf_EnumValueDescriptorProto_msg_init,
+  &google_protobuf_ServiceDescriptorProto_msg_init,
+  &google_protobuf_MethodDescriptorProto_msg_init,
+  &google_protobuf_FileOptions_msg_init,
+  &google_protobuf_MessageOptions_msg_init,
+  &google_protobuf_FieldOptions_msg_init,
+  &google_protobuf_OneofOptions_msg_init,
+  &google_protobuf_EnumOptions_msg_init,
+  &google_protobuf_EnumValueOptions_msg_init,
+  &google_protobuf_ServiceOptions_msg_init,
+  &google_protobuf_MethodOptions_msg_init,
+  &google_protobuf_UninterpretedOption_msg_init,
+  &google_protobuf_UninterpretedOption_NamePart_msg_init,
+  &google_protobuf_SourceCodeInfo_msg_init,
+  &google_protobuf_SourceCodeInfo_Location_msg_init,
+  &google_protobuf_GeneratedCodeInfo_msg_init,
+  &google_protobuf_GeneratedCodeInfo_Annotation_msg_init,
+};
+
+const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init = {
+    64,
+    0,
+    {
+        0x7fffe,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init = {
+    64,
+    0,
+    {
+        0xe,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init = {
+    64,
+    0,
+    {
+        0xe,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+static const upb_MiniTableEnum *enums_layout[7] = {
+  &google_protobuf_FieldDescriptorProto_Type_enum_init,
+  &google_protobuf_FieldDescriptorProto_Label_enum_init,
+  &google_protobuf_FileOptions_OptimizeMode_enum_init,
+  &google_protobuf_FieldOptions_CType_enum_init,
+  &google_protobuf_FieldOptions_JSType_enum_init,
+  &google_protobuf_MethodOptions_IdempotencyLevel_enum_init,
+  &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init,
+};
+
+const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = {
+  messages_layout,
+  enums_layout,
+  NULL,
+  27,
+  7,
+  0,
+};
+
+
+/* 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. */
+
+
+static const char descriptor[7820] = {'\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', '\"', '\376', '\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', '\022', '\030', '\n', '\007', 'e', 
+'d', 'i', 't', 'i', 'o', 'n', '\030', '\r', ' ', '\001', '(', '\t', 'R', '\007', 'e', 'd', 'i', 't', 'i', 'o', 'n', '\"', '\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', '\'', '\"', '\343', '\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', '\004', '\020', '\005', 'J', '\004', 
+'\010', '\005', '\020', '\006', 'J', '\004', '\010', '\006', '\020', '\007', 'J', '\004', '\010', '\010', '\020', '\t', 'J', '\004', '\010', '\t', '\020', '\n', '\"', '\222', '\004', 
+'\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', '\017', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', '_', 'l', 'a', 'z', 'y', '\030', 
+'\017', ' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\016', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', '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', '\"', '\320', '\002', '\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', '\353', '\001', '\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', '\022', 'R', '\n', '\010', 's', 'e', 'm', 'a', 'n', 
+'t', 'i', 'c', '\030', '\005', ' ', '\001', '(', '\016', '2', '6', '.', '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', '.', 'S', 'e', 'm', 'a', 'n', 't', 'i', 'c', 'R', '\010', 's', 'e', 'm', 'a', 'n', 't', 'i', 'c', 
+'\"', '(', '\n', '\010', 'S', 'e', 'm', 'a', 'n', 't', 'i', 'c', '\022', '\010', '\n', '\004', 'N', 'O', 'N', 'E', '\020', '\000', '\022', '\007', '\n', 
+'\003', 'S', 'E', 'T', '\020', '\001', '\022', '\t', '\n', '\005', 'A', 'L', 'I', 'A', 'S', '\020', '\002', '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_DefPool_Init *deps[1] = {
+  NULL
+};
+
+_upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit = {
+  deps,
+  &google_protobuf_descriptor_proto_upb_file_layout,
+  "google/protobuf/descriptor.proto",
+  UPB_STRINGVIEW_INIT(descriptor, 7820)
+};
+
 /*
  * upb_table Implementation
  *
@@ -2313,11 +1619,11 @@
 #include <string.h>
 
 
-/* Must be last. */
+// Must be last.
 
-#define UPB_MAXARRSIZE 16 /* 64k. */
+#define UPB_MAXARRSIZE 16  // 2**16 = 64k.
 
-/* From Chromium. */
+// From Chromium.
 #define ARRAY_SIZE(x) \
   ((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x])))))
 
@@ -2340,7 +1646,7 @@
   int ret = 0;
   bool pow2 = is_pow2(v);
   while (v >>= 1) ret++;
-  ret = pow2 ? ret : ret + 1; /* Ceiling. */
+  ret = pow2 ? ret : ret + 1;  // Ceiling.
   return UPB_MIN(UPB_MAXARRSIZE, ret);
 }
 
@@ -2710,14 +2016,18 @@
     0x082EFA98EC4E6C89ULL, 0x452821E638D01377ULL,
 };
 
-static uint32_t table_hash(const char* p, size_t n) {
-  return Wyhash(p, n, 0, kWyhashSalt);
+uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed) {
+  return Wyhash(p, n, seed, kWyhashSalt);
+}
+
+static uint32_t _upb_Hash_NoSeed(const char* p, size_t n) {
+  return _upb_Hash(p, n, 0);
 }
 
 static uint32_t strhash(upb_tabkey key) {
   uint32_t len;
   char* str = upb_tabstr(key, &len);
-  return table_hash(str, len);
+  return _upb_Hash_NoSeed(str, len);
 }
 
 static bool streql(upb_tabkey k1, lookupkey_t k2) {
@@ -2731,7 +2041,7 @@
   // denominator.
   size_t need_entries = (expected_size + 1) * 1204 / 1024;
   UPB_ASSERT(need_entries >= expected_size * 0.85);
-  int size_lg2 = _upb_Log2Ceiling(need_entries);
+  int size_lg2 = upb_Log2Ceiling(need_entries);
   return init(&t->t, size_lg2, a);
 }
 
@@ -2743,14 +2053,13 @@
 
 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_StringView key = upb_strtable_iter_key(&i);
-    upb_strtable_insert(&new_table, key.data, key.size,
-                        upb_strtable_iter_value(&i), a);
+
+  intptr_t iter = UPB_STRTABLE_BEGIN;
+  upb_StringView key;
+  upb_value val;
+  while (upb_strtable_next2(t, &key, &val, &iter)) {
+    upb_strtable_insert(&new_table, key.data, key.size, val, a);
   }
   *t = new_table;
   return true;
@@ -2773,20 +2082,20 @@
   tabkey = strcopy(key, a);
   if (tabkey == 0) return false;
 
-  hash = table_hash(key.str.str, key.str.len);
+  hash = _upb_Hash_NoSeed(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);
+  uint32_t hash = _upb_Hash_NoSeed(key, len);
   return lookup(&t->t, strkey2(key, len), v, hash, &streql);
 }
 
 bool upb_strtable_remove2(upb_strtable* t, const char* key, size_t len,
                           upb_value* val) {
-  uint32_t hash = table_hash(key, len);
+  uint32_t hash = _upb_Hash_NoSeed(key, len);
   upb_tabkey tabkey;
   return rm(&t->t, strkey2(key, len), val, &tabkey, hash, &streql);
 }
@@ -2869,12 +2178,13 @@
   UPB_UNUSED(t);
 #if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
   {
-    /* This check is very expensive (makes inserts/deletes O(N)). */
+    // 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));
+    intptr_t iter = UPB_INTTABLE_BEGIN;
+    uintptr_t key;
+    upb_value val;
+    while (upb_inttable_next(t, &key, &val, &iter)) {
+      UPB_ASSERT(upb_inttable_lookup(t, key, NULL));
     }
     UPB_ASSERT(count == upb_inttable_count(t));
   }
@@ -2987,22 +2297,22 @@
   /* 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]++;
+  {
+    intptr_t iter = UPB_INTTABLE_BEGIN;
+    uintptr_t key;
+    upb_value val;
+    while (upb_inttable_next(t, &key, &val, &iter)) {
+      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);
+  size_t arr_count = upb_inttable_count(t);
+  int size_lg2;
+  upb_inttable new_t;
 
   for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
     if (counts[size_lg2] == 0) {
@@ -3025,55 +2335,28 @@
     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);
+
+    {
+      intptr_t iter = UPB_INTTABLE_BEGIN;
+      uintptr_t key;
+      upb_value val;
+      while (upb_inttable_next(t, &key, &val, &iter)) {
+        upb_inttable_insert(&new_t, key, val, a);
+      }
     }
+
     UPB_ASSERT(new_t.array_size == arr_size);
     UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
   }
   *t = new_t;
 }
 
-/* Iteration. */
+// 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_next2(const upb_inttable* t, uintptr_t* key, upb_value* val,
-                        intptr_t* iter) {
+bool upb_inttable_next(const upb_inttable* t, uintptr_t* key, upb_value* val,
+                       intptr_t* iter) {
   intptr_t i = *iter;
-  if (i < t->array_size) {
+  if ((size_t)(i + 1) <= t->array_size) {
     while (++i < t->array_size) {
       upb_tabval ent = t->array[i];
       if (upb_arrhas(ent)) {
@@ -3083,9 +2366,10 @@
         return true;
       }
     }
+    i--;  // Back up to exactly one position before the start of the table.
   }
 
-  size_t tab_idx = next(&t->t, i == -1 ? -1 : i - t->array_size);
+  size_t tab_idx = next(&t->t, i - t->array_size);
   if (tab_idx < upb_table_size(&t->t)) {
     upb_tabent* ent = &t->t.entries[tab_idx];
     *key = ent->key;
@@ -3164,5996 +2448,17 @@
   ent->next = NULL;
 }
 
-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 <float.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-// Must be last.
-
-/* upb_Status *****************************************************************/
-
-void upb_Status_Clear(upb_Status* status) {
-  if (!status) return;
-  status->ok = true;
-  status->msg[0] = '\0';
-}
-
-bool upb_Status_IsOk(const upb_Status* status) { return status->ok; }
-
-const char* upb_Status_ErrorMessage(const upb_Status* status) {
-  return status->msg;
-}
-
-void upb_Status_SetErrorMessage(upb_Status* status, const char* msg) {
-  if (!status) return;
-  status->ok = false;
-  strncpy(status->msg, msg, _kUpb_Status_MaxMessage - 1);
-  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
-void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  upb_Status_VSetErrorFormat(status, fmt, args);
-  va_end(args);
-}
-
-void upb_Status_VSetErrorFormat(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[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
-void upb_Status_VAppendErrorFormat(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[_kUpb_Status_MaxMessage - 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_CleanupFunc* 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;
-
-  if (n) {
-    /* Align initial pointer up so that we return properly-aligned pointers. */
-    void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, 16);
-    size_t delta = (uintptr_t)aligned - (uintptr_t)mem;
-    n = delta <= n ? n - delta : 0;
-    mem = aligned;
-  }
-
-  /* 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_CleanupFunc* 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;
-}
-
-/* Miscellaneous utilities ****************************************************/
-
-static void upb_FixLocale(char* p) {
-  /* printf() is dependent on locales; sadly there is no easy and portable way
-   * to avoid this. This little post-processing step will translate 1,2 -> 1.2
-   * since JSON needs the latter. Arguably a hack, but it is simple and the
-   * alternatives are far more complicated, platform-dependent, and/or larger
-   * in code size. */
-  for (; *p; p++) {
-    if (*p == ',') *p = '.';
-  }
-}
-
-void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) {
-  assert(size >= kUpb_RoundTripBufferSize);
-  snprintf(buf, size, "%.*g", DBL_DIG, val);
-  if (strtod(buf, NULL) != val) {
-    snprintf(buf, size, "%.*g", DBL_DIG + 2, val);
-    assert(strtod(buf, NULL) == val);
-  }
-  upb_FixLocale(buf);
-}
-
-void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) {
-  assert(size >= kUpb_RoundTripBufferSize);
-  snprintf(buf, size, "%.*g", FLT_DIG, val);
-  if (strtof(buf, NULL) != val) {
-    snprintf(buf, size, "%.*g", FLT_DIG + 3, val);
-    assert(strtof(buf, NULL) == val);
-  }
-  upb_FixLocale(buf);
-}
-
-/** 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_Decoder *d, const char *ptr, upb_Message *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;
-  int status;
-  ptr = decode_isdonefallback_inl(d, ptr, overrun, &status);
-  if (ptr == NULL) {
-    return fastdecode_err(d, status);
-  }
-  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.
-      const upb_MiniTable* l = decode_totablep(table);
-      return UPB_UNLIKELY(l->required_count)
-                 ? decode_checkrequired(d, ptr, msg, l)
-                 : 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_Decoder* d, const char* ptr,
-                                         void* ctx);
-
-UPB_FORCEINLINE
-static const char* fastdecode_delimited(upb_Decoder* 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_Decoder* 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_Decoder* 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_Message* msg, uint64_t data) {
-  size_t ofs = data >> 48;
-  return (char*)msg + ofs;
-}
-
-UPB_FORCEINLINE
-static void* fastdecode_getfield(upb_Decoder* d, const char* ptr,
-                                 upb_Message* 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, kUpb_DecodeStatus_Malformed);      \
-  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_Decoder* 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, kUpb_DecodeStatus_Malformed);                   \
-  }                                                                          \
-                                                                             \
-  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, kUpb_DecodeStatus_Malformed);                  \
-  }                                                                         \
-                                                                            \
-  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, kUpb_DecodeStatus_Malformed);                \
-    }                                                                       \
-  } 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_Decoder* d,
-                                            const char* ptr, upb_Message* msg,
-                                            const upb_MiniTable* table,
-                                            uint64_t hasbits,
-                                            upb_StringView* dst);
-
-UPB_NOINLINE
-static const char* fastdecode_verifyutf8(upb_Decoder* d, const char* ptr,
-                                         upb_Message* msg, intptr_t table,
-                                         uint64_t hasbits, uint64_t data) {
-  upb_StringView* dst = (upb_StringView*)data;
-  if (!decode_verifyutf8_inl(dst->data, dst->size)) {
-    return fastdecode_err(d, kUpb_DecodeStatus_BadUtf8);
-  }
-  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, kUpb_DecodeStatus_Malformed);                     \
-  }                                                                            \
-                                                                               \
-  if (d->options & kUpb_DecodeOption_AliasString) {                            \
-    dst->data = ptr;                                                           \
-    dst->size = size;                                                          \
-  } else {                                                                     \
-    char* data = upb_Arena_Malloc(&d->arena, size);                            \
-    if (!data) {                                                               \
-      return fastdecode_err(d, kUpb_DecodeStatus_OutOfMemory);                 \
-    }                                                                          \
-    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_Decoder* d,
-                                              const char* ptr, upb_Message* msg,
-                                              intptr_t table, uint64_t hasbits,
-                                              uint64_t data) {
-  upb_StringView* dst = (upb_StringView*)data;
-  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
-}
-
-UPB_NOINLINE
-static const char* fastdecode_longstring_noutf8(
-    struct upb_Decoder* d, const char* ptr, upb_Message* msg, intptr_t table,
-    uint64_t hasbits, uint64_t data) {
-  upb_StringView* dst = (upb_StringView*)data;
-  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
-}
-
-UPB_FORCEINLINE
-static void fastdecode_docopy(upb_Decoder* d, const char* ptr, uint32_t size,
-                              int copy, char* data, upb_StringView* 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_StringView* dst;                                                        \
-  fastdecode_arr farr;                                                        \
-  int64_t size;                                                               \
-  size_t arena_has;                                                           \
-  size_t common_has;                                                          \
-  char* buf;                                                                  \
-                                                                              \
-  UPB_ASSERT((d->options & kUpb_DecodeOption_AliasString) == 0);              \
-  UPB_ASSERT(fastdecode_checktag(data, tagbytes));                            \
-                                                                              \
-  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,              \
-                            sizeof(upb_StringView), card);                    \
-                                                                              \
-  again:                                                                      \
-  if (card == CARD_r) {                                                       \
-    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));        \
-  }                                                                           \
-                                                                              \
-  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, kUpb_DecodeStatus_BadUtf8);                    \
-    }                                                                         \
-    fastdecode_nextret ret = fastdecode_nextrepeated(                         \
-        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));         \
-    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:                                                                    \
-  if (card == CARD_r) {                                                       \
-    fastdecode_commitarr(dst + 1, &farr, sizeof(upb_StringView));             \
-  }                                                                           \
-  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_StringView* 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->options & kUpb_DecodeOption_AliasString) == 0)) {       \
-    UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS);                              \
-  }                                                                            \
-                                                                               \
-  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
-                            sizeof(upb_StringView), card);                     \
-                                                                               \
-  again:                                                                       \
-  if (card == CARD_r) {                                                        \
-    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));         \
-  }                                                                            \
-                                                                               \
-  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, kUpb_DecodeStatus_BadUtf8);                     \
-    }                                                                          \
-    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
-        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));          \
-    switch (ret.next) {                                                        \
-      case FD_NEXT_SAMEFIELD:                                                  \
-        dst = ret.dst;                                                         \
-        if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
-          /* 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_StringView));            \
-          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_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* l,
-                                int msg_ceil_bytes) {
-  size_t size = l->size + sizeof(upb_Message_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_Message_Internal);
-}
-
-typedef struct {
-  intptr_t table;
-  upb_Message* msg;
-} fastdecode_submsgdata;
-
-UPB_FORCEINLINE
-static const char* fastdecode_tosubmsg(upb_Decoder* 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, kUpb_DecodeStatus_MaxDepthExceeded);         \
-  }                                                                       \
-                                                                          \
-  upb_Message** dst;                                                      \
-  uint32_t submsg_idx = (data >> 16) & 0xff;                              \
-  const upb_MiniTable* tablep = decode_totablep(table);                   \
-  const upb_MiniTable* subtablep = tablep->subs[submsg_idx].submsg;       \
-  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_Message*), card);                  \
-                                                                          \
-  if (card == CARD_s) {                                                   \
-    *(uint32_t*)msg |= hasbits;                                           \
-    hasbits = 0;                                                          \
-  }                                                                       \
-                                                                          \
-  again:                                                                  \
-  if (card == CARD_r) {                                                   \
-    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*));      \
-  }                                                                       \
-                                                                          \
-  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, kUpb_DecodeStatus_Malformed);                \
-  }                                                                       \
-                                                                          \
-  if (card == CARD_r) {                                                   \
-    fastdecode_nextret ret = fastdecode_nextrepeated(                     \
-        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*));       \
-    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_MiniTable_Sub google_protobuf_FileDescriptorSet_submsgs[1] = {
-  {.submsg = &google_protobuf_FileDescriptorProto_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FileDescriptorSet__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FileDescriptorSet_msginit = {
-  &google_protobuf_FileDescriptorSet_submsgs[0],
-  &google_protobuf_FileDescriptorSet__fields[0],
-  UPB_SIZE(8, 8), 1, upb_ExtMode_NonExtendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FileDescriptorProto_submsgs[6] = {
-  {.submsg = &google_protobuf_DescriptorProto_msginit},
-  {.submsg = &google_protobuf_EnumDescriptorProto_msginit},
-  {.submsg = &google_protobuf_FieldDescriptorProto_msginit},
-  {.submsg = &google_protobuf_FileOptions_msginit},
-  {.submsg = &google_protobuf_ServiceDescriptorProto_msginit},
-  {.submsg = &google_protobuf_SourceCodeInfo_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FileDescriptorProto__fields[12] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 24), 2, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(36, 72), 0, 0, 12, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(40, 80), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {5, UPB_SIZE(44, 88), 0, 1, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {6, UPB_SIZE(48, 96), 0, 4, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {7, UPB_SIZE(52, 104), 0, 2, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {8, UPB_SIZE(28, 56), 3, 3, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {9, UPB_SIZE(32, 64), 4, 5, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {10, UPB_SIZE(56, 112), 0, 0, 5, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {11, UPB_SIZE(60, 120), 0, 0, 5, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {12, UPB_SIZE(20, 40), 5, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FileDescriptorProto_msginit = {
-  &google_protobuf_FileDescriptorProto_submsgs[0],
-  &google_protobuf_FileDescriptorProto__fields[0],
-  UPB_SIZE(64, 128), 12, upb_ExtMode_NonExtendable, 12, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_DescriptorProto_submsgs[7] = {
-  {.submsg = &google_protobuf_DescriptorProto_msginit},
-  {.submsg = &google_protobuf_DescriptorProto_ExtensionRange_msginit},
-  {.submsg = &google_protobuf_DescriptorProto_ReservedRange_msginit},
-  {.submsg = &google_protobuf_EnumDescriptorProto_msginit},
-  {.submsg = &google_protobuf_FieldDescriptorProto_msginit},
-  {.submsg = &google_protobuf_MessageOptions_msginit},
-  {.submsg = &google_protobuf_OneofDescriptorProto_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_DescriptorProto__fields[10] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(16, 32), 0, 4, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(20, 40), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(24, 48), 0, 3, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {5, UPB_SIZE(28, 56), 0, 1, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {6, UPB_SIZE(32, 64), 0, 4, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {7, UPB_SIZE(12, 24), 2, 5, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {8, UPB_SIZE(36, 72), 0, 6, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {9, UPB_SIZE(40, 80), 0, 2, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {10, UPB_SIZE(44, 88), 0, 0, 12, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_DescriptorProto_msginit = {
-  &google_protobuf_DescriptorProto_submsgs[0],
-  &google_protobuf_DescriptorProto__fields[0],
-  UPB_SIZE(48, 96), 10, upb_ExtMode_NonExtendable, 10, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
-  {.submsg = &google_protobuf_ExtensionRangeOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msginit = {
-  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
-  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
-  UPB_SIZE(16, 24), 3, upb_ExtMode_NonExtendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msginit = {
-  NULL,
-  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
-  UPB_SIZE(16, 16), 2, upb_ExtMode_NonExtendable, 2, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_ExtensionRangeOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_ExtensionRangeOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_ExtensionRangeOptions_msginit = {
-  &google_protobuf_ExtensionRangeOptions_submsgs[0],
-  &google_protobuf_ExtensionRangeOptions__fields[0],
-  UPB_SIZE(8, 8), 1, upb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FieldDescriptorProto_submsgs[3] = {
-  {.submsg = &google_protobuf_FieldOptions_msginit},
-  {.subenum = &google_protobuf_FieldDescriptorProto_Label_enuminit},
-  {.subenum = &google_protobuf_FieldDescriptorProto_Type_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FieldDescriptorProto__fields[11] = {
-  {1, UPB_SIZE(24, 24), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(32, 40), 2, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 12), 3, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(4, 4), 4, 1, 14, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {5, UPB_SIZE(8, 8), 5, 2, 14, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {6, UPB_SIZE(40, 56), 6, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {7, UPB_SIZE(48, 72), 7, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {8, UPB_SIZE(64, 104), 8, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {9, UPB_SIZE(16, 16), 9, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {10, UPB_SIZE(56, 88), 10, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {17, UPB_SIZE(20, 20), 11, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FieldDescriptorProto_msginit = {
-  &google_protobuf_FieldDescriptorProto_submsgs[0],
-  &google_protobuf_FieldDescriptorProto__fields[0],
-  UPB_SIZE(72, 112), 11, upb_ExtMode_NonExtendable, 10, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_OneofDescriptorProto_submsgs[1] = {
-  {.submsg = &google_protobuf_OneofOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_OneofDescriptorProto__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_OneofDescriptorProto_msginit = {
-  &google_protobuf_OneofDescriptorProto_submsgs[0],
-  &google_protobuf_OneofDescriptorProto__fields[0],
-  UPB_SIZE(16, 32), 2, upb_ExtMode_NonExtendable, 2, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumDescriptorProto_submsgs[3] = {
-  {.submsg = &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit},
-  {.submsg = &google_protobuf_EnumOptions_msginit},
-  {.submsg = &google_protobuf_EnumValueDescriptorProto_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumDescriptorProto__fields[5] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(16, 32), 0, 2, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(20, 40), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {5, UPB_SIZE(24, 48), 0, 0, 12, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumDescriptorProto_msginit = {
-  &google_protobuf_EnumDescriptorProto_submsgs[0],
-  &google_protobuf_EnumDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 5, upb_ExtMode_NonExtendable, 5, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
-  NULL,
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
-  UPB_SIZE(16, 16), 2, upb_ExtMode_NonExtendable, 2, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
-  {.submsg = &google_protobuf_EnumValueOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumValueDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(8, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(4, 4), 2, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(16, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msginit = {
-  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
-  &google_protobuf_EnumValueDescriptorProto__fields[0],
-  UPB_SIZE(24, 32), 3, upb_ExtMode_NonExtendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_ServiceDescriptorProto_submsgs[2] = {
-  {.submsg = &google_protobuf_MethodDescriptorProto_msginit},
-  {.submsg = &google_protobuf_ServiceOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_ServiceDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(16, 32), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_ServiceDescriptorProto_msginit = {
-  &google_protobuf_ServiceDescriptorProto_submsgs[0],
-  &google_protobuf_ServiceDescriptorProto__fields[0],
-  UPB_SIZE(24, 48), 3, upb_ExtMode_NonExtendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_MethodDescriptorProto_submsgs[1] = {
-  {.submsg = &google_protobuf_MethodOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_MethodDescriptorProto__fields[6] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 24), 2, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(20, 40), 3, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(28, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {5, UPB_SIZE(1, 1), 5, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {6, UPB_SIZE(2, 2), 6, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_MethodDescriptorProto_msginit = {
-  &google_protobuf_MethodDescriptorProto_submsgs[0],
-  &google_protobuf_MethodDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 6, upb_ExtMode_NonExtendable, 6, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FileOptions_submsgs[2] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-  {.subenum = &google_protobuf_FileOptions_OptimizeMode_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FileOptions__fields[21] = {
-  {1, UPB_SIZE(20, 24), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {8, UPB_SIZE(28, 40), 2, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {9, UPB_SIZE(4, 4), 3, 1, 14, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {10, UPB_SIZE(8, 8), 4, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {11, UPB_SIZE(36, 56), 5, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {16, UPB_SIZE(9, 9), 6, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {17, UPB_SIZE(10, 10), 7, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {18, UPB_SIZE(11, 11), 8, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {20, UPB_SIZE(12, 12), 9, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {23, UPB_SIZE(13, 13), 10, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {27, UPB_SIZE(14, 14), 11, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {31, UPB_SIZE(15, 15), 12, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {36, UPB_SIZE(44, 72), 13, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {37, UPB_SIZE(52, 88), 14, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {39, UPB_SIZE(60, 104), 15, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {40, UPB_SIZE(68, 120), 16, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {41, UPB_SIZE(76, 136), 17, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {42, UPB_SIZE(16, 16), 18, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {44, UPB_SIZE(84, 152), 19, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {45, UPB_SIZE(92, 168), 20, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {999, UPB_SIZE(100, 184), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FileOptions_msginit = {
-  &google_protobuf_FileOptions_submsgs[0],
-  &google_protobuf_FileOptions__fields[0],
-  UPB_SIZE(104, 192), 21, upb_ExtMode_Extendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_MessageOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_MessageOptions__fields[5] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(2, 2), 2, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(3, 3), 3, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {7, UPB_SIZE(4, 4), 4, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {999, UPB_SIZE(8, 8), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_MessageOptions_msginit = {
-  &google_protobuf_MessageOptions_submsgs[0],
-  &google_protobuf_MessageOptions__fields[0],
-  UPB_SIZE(16, 16), 5, upb_ExtMode_Extendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FieldOptions_submsgs[3] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-  {.subenum = &google_protobuf_FieldOptions_CType_enuminit},
-  {.subenum = &google_protobuf_FieldOptions_JSType_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FieldOptions__fields[8] = {
-  {1, UPB_SIZE(4, 4), 1, 1, 14, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 12), 2, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(13, 13), 3, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {5, UPB_SIZE(14, 14), 4, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {6, UPB_SIZE(8, 8), 5, 2, 14, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {10, UPB_SIZE(15, 15), 6, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {15, UPB_SIZE(16, 16), 7, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {999, UPB_SIZE(20, 24), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FieldOptions_msginit = {
-  &google_protobuf_FieldOptions_submsgs[0],
-  &google_protobuf_FieldOptions__fields[0],
-  UPB_SIZE(24, 32), 8, upb_ExtMode_Extendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_OneofOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_OneofOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_OneofOptions_msginit = {
-  &google_protobuf_OneofOptions_submsgs[0],
-  &google_protobuf_OneofOptions__fields[0],
-  UPB_SIZE(8, 8), 1, upb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumOptions__fields[3] = {
-  {2, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(2, 2), 2, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumOptions_msginit = {
-  &google_protobuf_EnumOptions_submsgs[0],
-  &google_protobuf_EnumOptions__fields[0],
-  UPB_SIZE(8, 16), 3, upb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumValueOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumValueOptions__fields[2] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumValueOptions_msginit = {
-  &google_protobuf_EnumValueOptions_submsgs[0],
-  &google_protobuf_EnumValueOptions__fields[0],
-  UPB_SIZE(8, 16), 2, upb_ExtMode_Extendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_ServiceOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_ServiceOptions__fields[2] = {
-  {33, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_ServiceOptions_msginit = {
-  &google_protobuf_ServiceOptions_submsgs[0],
-  &google_protobuf_ServiceOptions__fields[0],
-  UPB_SIZE(8, 16), 2, upb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_MethodOptions_submsgs[2] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-  {.subenum = &google_protobuf_MethodOptions_IdempotencyLevel_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_MethodOptions__fields[3] = {
-  {33, UPB_SIZE(8, 8), 1, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-  {34, UPB_SIZE(4, 4), 2, 1, 14, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {999, UPB_SIZE(12, 16), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_MethodOptions_msginit = {
-  &google_protobuf_MethodOptions_submsgs[0],
-  &google_protobuf_MethodOptions__fields[0],
-  UPB_SIZE(16, 24), 3, upb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_UninterpretedOption_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_NamePart_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_UninterpretedOption__fields[7] = {
-  {2, UPB_SIZE(56, 80), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(32, 32), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(8, 8), 2, 0, 4, kUpb_FieldMode_Scalar | (upb_FieldRep_8Byte << upb_FieldRep_Shift)},
-  {5, UPB_SIZE(16, 16), 3, 0, 3, kUpb_FieldMode_Scalar | (upb_FieldRep_8Byte << upb_FieldRep_Shift)},
-  {6, UPB_SIZE(24, 24), 4, 0, 1, kUpb_FieldMode_Scalar | (upb_FieldRep_8Byte << upb_FieldRep_Shift)},
-  {7, UPB_SIZE(40, 48), 5, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {8, UPB_SIZE(48, 64), 6, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_UninterpretedOption_msginit = {
-  &google_protobuf_UninterpretedOption_submsgs[0],
-  &google_protobuf_UninterpretedOption__fields[0],
-  UPB_SIZE(64, 96), 7, upb_ExtMode_NonExtendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(1, 1), 2, 0, 8, kUpb_FieldMode_Scalar | (upb_FieldRep_1Byte << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msginit = {
-  NULL,
-  &google_protobuf_UninterpretedOption_NamePart__fields[0],
-  UPB_SIZE(16, 32), 2, upb_ExtMode_NonExtendable, 2, 255, 2,
-};
-
-static const upb_MiniTable_Sub google_protobuf_SourceCodeInfo_submsgs[1] = {
-  {.submsg = &google_protobuf_SourceCodeInfo_Location_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_SourceCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_SourceCodeInfo_msginit = {
-  &google_protobuf_SourceCodeInfo_submsgs[0],
-  &google_protobuf_SourceCodeInfo__fields[0],
-  UPB_SIZE(8, 8), 1, upb_ExtMode_NonExtendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_SourceCodeInfo_Location__fields[5] = {
-  {1, UPB_SIZE(20, 40), 0, 0, 5, kUpb_FieldMode_Array | upb_LabelFlags_IsPacked | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(24, 48), 0, 0, 5, kUpb_FieldMode_Array | upb_LabelFlags_IsPacked | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(12, 24), 2, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {6, UPB_SIZE(28, 56), 0, 0, 12, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msginit = {
-  NULL,
-  &google_protobuf_SourceCodeInfo_Location__fields[0],
-  UPB_SIZE(32, 64), 5, upb_ExtMode_NonExtendable, 4, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_GeneratedCodeInfo_submsgs[1] = {
-  {.submsg = &google_protobuf_GeneratedCodeInfo_Annotation_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_GeneratedCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_GeneratedCodeInfo_msginit = {
-  &google_protobuf_GeneratedCodeInfo_submsgs[0],
-  &google_protobuf_GeneratedCodeInfo__fields[0],
-  UPB_SIZE(8, 8), 1, upb_ExtMode_NonExtendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
-  {1, UPB_SIZE(20, 32), 0, 0, 5, kUpb_FieldMode_Array | upb_LabelFlags_IsPacked | (upb_FieldRep_Pointer << upb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 16), 1, 0, 12, kUpb_FieldMode_Scalar | (upb_FieldRep_StringView << upb_FieldRep_Shift)},
-  {3, UPB_SIZE(4, 4), 2, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-  {4, UPB_SIZE(8, 8), 3, 0, 5, kUpb_FieldMode_Scalar | (upb_FieldRep_4Byte << upb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
-  NULL,
-  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
-  UPB_SIZE(24, 48), 4, upb_ExtMode_NonExtendable, 4, 255, 0,
-};
-
-static const upb_MiniTable *messages_layout[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,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Type_enuminit = {
-  NULL,
-  0x7fffeULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Label_enuminit = {
-  NULL,
-  0xeULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FileOptions_OptimizeMode_enuminit = {
-  NULL,
-  0xeULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldOptions_CType_enuminit = {
-  NULL,
-  0x7ULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldOptions_JSType_enuminit = {
-  NULL,
-  0x7ULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_MethodOptions_IdempotencyLevel_enuminit = {
-  NULL,
-  0x7ULL,
-  0,
-};
-
-static const upb_MiniTable_Enum *enums_layout[6] = {
-  &google_protobuf_FieldDescriptorProto_Type_enuminit,
-  &google_protobuf_FieldDescriptorProto_Label_enuminit,
-  &google_protobuf_FileOptions_OptimizeMode_enuminit,
-  &google_protobuf_FieldOptions_CType_enuminit,
-  &google_protobuf_FieldOptions_JSType_enuminit,
-  &google_protobuf_MethodOptions_IdempotencyLevel_enuminit,
-};
-
-const upb_MiniTable_File google_protobuf_descriptor_proto_upb_file_layout = {
-  messages_layout,
-  enums_layout,
-  NULL,
-  27,
-  6,
-  0,
-};
-
-
-
-/** 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. */
-
-
-static const char descriptor[7667] = {'\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', '\'', '\"', '\343', '\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', '\004', '\020', '\005', 'J', '\004', '\010', 
-'\005', '\020', '\006', 'J', '\004', '\010', '\006', '\020', '\007', 'J', '\004', '\010', '\010', '\020', '\t', 'J', '\004', '\010', '\t', '\020', '\n', '\"', '\222', '\004', '\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', '\017', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', '_', 'l', 'a', 'z', 'y', '\030', '\017', 
-' ', '\001', '(', '\010', ':', '\005', 'f', 'a', 'l', 's', 'e', 'R', '\016', 'u', 'n', 'v', 'e', 'r', 'i', 'f', 'i', 'e', 'd', '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_DefPool_Init *deps[1] = {
-  NULL
-};
-
-_upb_DefPool_Init google_protobuf_descriptor_proto_upbdefinit = {
-  deps,
-  &google_protobuf_descriptor_proto_upb_file_layout,
-  "google/protobuf/descriptor.proto",
-  UPB_STRINGVIEW_INIT(descriptor, 7667)
-};
-
-/** 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;
-
-/* The upb core does not generally have a concept of default instances. However
- * for descriptor options we make an exception since the max size is known and
- * modest (<200 bytes). All types can share a default instance since it is
- * initialized to zeroes.
- *
- * We have to allocate an extra pointer for upb's internal metadata. */
-static const char opt_default_buf[_UPB_MAXOPT_SIZE + sizeof(void*)] = {0};
-static const char* opt_default = &opt_default_buf[sizeof(void*)];
-
-struct upb_FieldDef {
-  const google_protobuf_FieldOptions* opts;
-  const upb_FileDef* file;
-  const upb_MessageDef* 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;
-  union {
-    const upb_OneofDef* oneof;
-    const upb_MessageDef* extension_scope;
-  } scope;
-  union {
-    const upb_MessageDef* msgdef;
-    const upb_EnumDef* enumdef;
-    const google_protobuf_FieldDescriptorProto* unresolved;
-  } sub;
-  uint32_t number_;
-  uint16_t index_;
-  uint16_t layout_index; /* Index into msgdef->layout->fields or file->exts */
-  bool has_default;
-  bool is_extension_;
-  bool packed_;
-  bool proto3_optional_;
-  bool has_json_name_;
-  upb_FieldType type_;
-  upb_Label label_;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_ExtensionRange {
-  const google_protobuf_ExtensionRangeOptions* opts;
-  int32_t start;
-  int32_t end;
-};
-
-struct upb_MessageDef {
-  const google_protobuf_MessageOptions* opts;
-  const upb_MiniTable* layout;
-  const upb_FileDef* file;
-  const upb_MessageDef* containing_type;
-  const char* full_name;
-
-  /* Tables for looking up fields by number and name. */
-  upb_inttable itof;
-  upb_strtable ntof;
-
-  /* All nested defs.
-   * MEM: We could save some space here by putting nested defs in a contiguous
-   * region and calculating counts from offsets or vice-versa. */
-  const upb_FieldDef* fields;
-  const upb_OneofDef* oneofs;
-  const upb_ExtensionRange* ext_ranges;
-  const upb_MessageDef* nested_msgs;
-  const upb_EnumDef* nested_enums;
-  const upb_FieldDef* nested_exts;
-  int field_count;
-  int real_oneof_count;
-  int oneof_count;
-  int ext_range_count;
-  int nested_msg_count;
-  int nested_enum_count;
-  int nested_ext_count;
-  bool in_message_set;
-  upb_WellKnown well_known_type;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_EnumDef {
-  const google_protobuf_EnumOptions* opts;
-  const upb_MiniTable_Enum* layout;  // Only for proto2.
-  const upb_FileDef* file;
-  const upb_MessageDef* containing_type;  // Could be merged with "file".
-  const char* full_name;
-  upb_strtable ntoi;
-  upb_inttable iton;
-  const upb_EnumValueDef* values;
-  int value_count;
-  int32_t defaultval;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_EnumValueDef {
-  const google_protobuf_EnumValueOptions* opts;
-  const upb_EnumDef* parent;
-  const char* full_name;
-  int32_t number;
-};
-
-struct upb_OneofDef {
-  const google_protobuf_OneofOptions* opts;
-  const upb_MessageDef* parent;
-  const char* full_name;
-  int field_count;
-  bool synthetic;
-  const upb_FieldDef** fields;
-  upb_strtable ntof;
-  upb_inttable itof;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_FileDef {
-  const google_protobuf_FileOptions* opts;
-  const char* name;
-  const char* package;
-
-  const upb_FileDef** deps;
-  const int32_t* public_deps;
-  const int32_t* weak_deps;
-  const upb_MessageDef* top_lvl_msgs;
-  const upb_EnumDef* top_lvl_enums;
-  const upb_FieldDef* top_lvl_exts;
-  const upb_ServiceDef* services;
-  const upb_MiniTable_Extension** ext_layouts;
-  const upb_DefPool* symtab;
-
-  int dep_count;
-  int public_dep_count;
-  int weak_dep_count;
-  int top_lvl_msg_count;
-  int top_lvl_enum_count;
-  int top_lvl_ext_count;
-  int service_count;
-  int ext_count; /* All exts in the file. */
-  upb_Syntax syntax;
-};
-
-struct upb_MethodDef {
-  const google_protobuf_MethodOptions* opts;
-  upb_ServiceDef* service;
-  const char* full_name;
-  const upb_MessageDef* input_type;
-  const upb_MessageDef* output_type;
-  int index;
-  bool client_streaming;
-  bool server_streaming;
-};
-
-struct upb_ServiceDef {
-  const google_protobuf_ServiceOptions* opts;
-  const upb_FileDef* file;
-  const char* full_name;
-  upb_MethodDef* methods;
-  int method_count;
-  int index;
-};
-
-struct upb_DefPool {
-  upb_Arena* arena;
-  upb_strtable syms;  /* full_name -> packed def ptr */
-  upb_strtable files; /* file_name -> upb_FileDef* */
-  upb_inttable exts;  /* upb_MiniTable_Extension* -> upb_FieldDef* */
-  upb_ExtensionRegistry* extreg;
-  size_t bytes_loaded;
-};
-
-/* Inside a symtab we store tagged pointers to specific def types. */
-typedef enum {
-  UPB_DEFTYPE_MASK = 7,
-
-  /* Only inside symtab table. */
-  UPB_DEFTYPE_EXT = 0,
-  UPB_DEFTYPE_MSG = 1,
-  UPB_DEFTYPE_ENUM = 2,
-  UPB_DEFTYPE_ENUMVAL = 3,
-  UPB_DEFTYPE_SERVICE = 4,
-
-  /* Only inside message table. */
-  UPB_DEFTYPE_FIELD = 0,
-  UPB_DEFTYPE_ONEOF = 1,
-  UPB_DEFTYPE_FIELD_JSONNAME = 2,
-
-  /* Only inside file table. */
-  UPB_DEFTYPE_FILE = 0,
-  UPB_DEFTYPE_LAYOUT = 1
-} upb_deftype_t;
-
-#define FIELD_TYPE_UNSPECIFIED 0
-
-static upb_deftype_t deftype(upb_value v) {
-  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
-  return num & UPB_DEFTYPE_MASK;
-}
-
-static const void* unpack_def(upb_value v, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
-  return (num & UPB_DEFTYPE_MASK) == type
-             ? (const void*)(num & ~UPB_DEFTYPE_MASK)
-             : NULL;
-}
-
-static upb_value pack_def(const void* ptr, upb_deftype_t type) {
-  // Our 3-bit pointer tagging requires all pointers to be multiples of 8.
-  // The arena will always yield 8-byte-aligned addresses, however we put
-  // the defs into arrays.  For each element in the array to be 8-byte-aligned,
-  // the sizes of each def type must also be a multiple of 8.
-  //
-  // If any of these asserts fail, we need to add or remove padding on 32-bit
-  // machines (64-bit machines will have 8-byte alignment already due to
-  // pointers, which all of these structs have).
-  UPB_ASSERT((sizeof(upb_FieldDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_MessageDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_EnumDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_EnumValueDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_ServiceDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_OneofDef) & UPB_DEFTYPE_MASK) == 0);
-  uintptr_t num = (uintptr_t)ptr;
-  UPB_ASSERT((num & UPB_DEFTYPE_MASK) == 0);
-  num |= 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(uint8_t c, uint8_t low, uint8_t high) {
-  return c >= low && c <= high;
-}
-
-static char upb_ascii_lower(char ch) {
-  // Per ASCII this will lower-case a letter.  If the result is a letter, the
-  // input was definitely a letter.  If the output is not a letter, this may
-  // have transformed the character unpredictably.
-  return ch | 0x20;
-}
-
-static bool upb_isletter(char c) {
-  char lower = upb_ascii_lower(c);
-  return upb_isbetween(lower, '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_IsSubMessage(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_SetErrorMessage(status, "out of memory");
-}
-
-static void assign_msg_wellknowntype(upb_MessageDef* m) {
-  const char* name = upb_MessageDef_FullName(m);
-  if (name == NULL) {
-    m->well_known_type = kUpb_WellKnown_Unspecified;
-    return;
-  }
-  if (!strcmp(name, "google.protobuf.Any")) {
-    m->well_known_type = kUpb_WellKnown_Any;
-  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
-    m->well_known_type = kUpb_WellKnown_FieldMask;
-  } else if (!strcmp(name, "google.protobuf.Duration")) {
-    m->well_known_type = kUpb_WellKnown_Duration;
-  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
-    m->well_known_type = kUpb_WellKnown_Timestamp;
-  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
-    m->well_known_type = kUpb_WellKnown_DoubleValue;
-  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
-    m->well_known_type = kUpb_WellKnown_FloatValue;
-  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
-    m->well_known_type = kUpb_WellKnown_Int64Value;
-  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
-    m->well_known_type = kUpb_WellKnown_UInt64Value;
-  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
-    m->well_known_type = kUpb_WellKnown_Int32Value;
-  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
-    m->well_known_type = kUpb_WellKnown_UInt32Value;
-  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
-    m->well_known_type = kUpb_WellKnown_BoolValue;
-  } else if (!strcmp(name, "google.protobuf.StringValue")) {
-    m->well_known_type = kUpb_WellKnown_StringValue;
-  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
-    m->well_known_type = kUpb_WellKnown_BytesValue;
-  } else if (!strcmp(name, "google.protobuf.Value")) {
-    m->well_known_type = kUpb_WellKnown_Value;
-  } else if (!strcmp(name, "google.protobuf.ListValue")) {
-    m->well_known_type = kUpb_WellKnown_ListValue;
-  } else if (!strcmp(name, "google.protobuf.Struct")) {
-    m->well_known_type = kUpb_WellKnown_Struct;
-  } else {
-    m->well_known_type = kUpb_WellKnown_Unspecified;
-  }
-}
-
-/* upb_EnumDef ****************************************************************/
-
-const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) {
-  return e->opts;
-}
-
-bool upb_EnumDef_HasOptions(const upb_EnumDef* e) {
-  return e->opts != (void*)opt_default;
-}
-
-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; }
-
-const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e) {
-  return e->containing_type;
-}
-
-int32_t upb_EnumDef_Default(const upb_EnumDef* e) {
-  UPB_ASSERT(upb_EnumDef_FindValueByNumber(e, e->defaultval));
-  return e->defaultval;
-}
-
-int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; }
-
-const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
-    const upb_EnumDef* def, const char* name, size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&def->ntoi, name, len, &v)
-             ? upb_value_getconstptr(v)
-             : NULL;
-}
-
-const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* def,
-                                                      int32_t num) {
-  upb_value v;
-  return upb_inttable_lookup(&def->iton, num, &v) ? upb_value_getconstptr(v)
-                                                  : NULL;
-}
-
-bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num) {
-  // We could use upb_EnumDef_FindValueByNumber(e, num) != NULL, but we expect
-  // this to be faster (especially for small numbers).
-  return upb_MiniTable_Enum_CheckValue(e->layout, num);
-}
-
-const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) {
-  UPB_ASSERT(0 <= i && i < e->value_count);
-  return &e->values[i];
-}
-
-/* upb_EnumValueDef ***********************************************************/
-
-const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
-    const upb_EnumValueDef* e) {
-  return e->opts;
-}
-
-bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* e) {
-  return e->opts != (void*)opt_default;
-}
-
-const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* ev) {
-  return ev->parent;
-}
-
-const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* ev) {
-  return ev->full_name;
-}
-
-const char* upb_EnumValueDef_Name(const upb_EnumValueDef* ev) {
-  return shortdefname(ev->full_name);
-}
-
-int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* ev) {
-  return ev->number;
-}
-
-uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* ev) {
-  // Compute index in our parent's array.
-  return ev - ev->parent->values;
-}
-
-/* upb_ExtensionRange
- * ***************************************************************/
-
-const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
-    const upb_ExtensionRange* r) {
-  return r->opts;
-}
-
-bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r) {
-  return r->opts != (void*)opt_default;
-}
-
-int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* e) {
-  return e->start;
-}
-
-int32_t upb_ExtensionRange_End(const upb_ExtensionRange* e) { return e->end; }
-
-/* upb_FieldDef ***************************************************************/
-
-const google_protobuf_FieldOptions* upb_FieldDef_Options(
-    const upb_FieldDef* f) {
-  return f->opts;
-}
-
-bool upb_FieldDef_HasOptions(const upb_FieldDef* f) {
-  return f->opts != (void*)opt_default;
-}
-
-const char* upb_FieldDef_FullName(const upb_FieldDef* f) {
-  return f->full_name;
-}
-
-upb_CType upb_FieldDef_CType(const upb_FieldDef* f) {
-  switch (f->type_) {
-    case kUpb_FieldType_Double:
-      return kUpb_CType_Double;
-    case kUpb_FieldType_Float:
-      return kUpb_CType_Float;
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_SInt64:
-    case kUpb_FieldType_SFixed64:
-      return kUpb_CType_Int64;
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_SFixed32:
-    case kUpb_FieldType_SInt32:
-      return kUpb_CType_Int32;
-    case kUpb_FieldType_UInt64:
-    case kUpb_FieldType_Fixed64:
-      return kUpb_CType_UInt64;
-    case kUpb_FieldType_UInt32:
-    case kUpb_FieldType_Fixed32:
-      return kUpb_CType_UInt32;
-    case kUpb_FieldType_Enum:
-      return kUpb_CType_Enum;
-    case kUpb_FieldType_Bool:
-      return kUpb_CType_Bool;
-    case kUpb_FieldType_String:
-      return kUpb_CType_String;
-    case kUpb_FieldType_Bytes:
-      return kUpb_CType_Bytes;
-    case kUpb_FieldType_Group:
-    case kUpb_FieldType_Message:
-      return kUpb_CType_Message;
-  }
-  UPB_UNREACHABLE();
-}
-
-upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { return f->type_; }
-
-uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; }
-
-upb_Label 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_IsPacked(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;
-}
-
-bool upb_FieldDef_HasJsonName(const upb_FieldDef* f) {
-  return f->has_json_name_;
-}
-
-const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f) { return f->file; }
-
-const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f) {
-  return f->msgdef;
-}
-
-const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f) {
-  return f->is_extension_ ? f->scope.extension_scope : NULL;
-}
-
-const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f) {
-  return f->is_extension_ ? NULL : f->scope.oneof;
-}
-
-const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f) {
-  const upb_OneofDef* oneof = upb_FieldDef_ContainingOneof(f);
-  if (!oneof || upb_OneofDef_IsSynthetic(oneof)) return NULL;
-  return oneof;
-}
-
-upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f) {
-  UPB_ASSERT(!upb_FieldDef_IsSubMessage(f));
-  upb_MessageValue ret;
-
-  switch (upb_FieldDef_CType(f)) {
-    case kUpb_CType_Bool:
-      return (upb_MessageValue){.bool_val = f->defaultval.boolean};
-    case kUpb_CType_Int64:
-      return (upb_MessageValue){.int64_val = f->defaultval.sint};
-    case kUpb_CType_UInt64:
-      return (upb_MessageValue){.uint64_val = f->defaultval.uint};
-    case kUpb_CType_Enum:
-    case kUpb_CType_Int32:
-      return (upb_MessageValue){.int32_val = (int32_t)f->defaultval.sint};
-    case kUpb_CType_UInt32:
-      return (upb_MessageValue){.uint32_val = (uint32_t)f->defaultval.uint};
-    case kUpb_CType_Float:
-      return (upb_MessageValue){.float_val = f->defaultval.flt};
-    case kUpb_CType_Double:
-      return (upb_MessageValue){.double_val = f->defaultval.dbl};
-    case kUpb_CType_String:
-    case kUpb_CType_Bytes: {
-      str_t* str = f->defaultval.str;
-      if (str) {
-        return (upb_MessageValue){
-            .str_val = (upb_StringView){.data = str->str, .size = str->len}};
-      } else {
-        return (upb_MessageValue){
-            .str_val = (upb_StringView){.data = NULL, .size = 0}};
-      }
-    }
-    default:
-      UPB_UNREACHABLE();
-  }
-
-  return ret;
-}
-
-const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_Message ? f->sub.msgdef : NULL;
-}
-
-const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_Enum ? f->sub.enumdef : NULL;
-}
-
-const upb_MiniTable_Field* upb_FieldDef_MiniTable(const upb_FieldDef* f) {
-  UPB_ASSERT(!upb_FieldDef_IsExtension(f));
-  return &f->msgdef->layout->fields[f->layout_index];
-}
-
-const upb_MiniTable_Extension* _upb_FieldDef_ExtensionMiniTable(
-    const upb_FieldDef* f) {
-  UPB_ASSERT(upb_FieldDef_IsExtension(f));
-  return f->file->ext_layouts[f->layout_index];
-}
-
-bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f) {
-  return f->proto3_optional_;
-}
-
-bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_Message;
-}
-
-bool upb_FieldDef_IsString(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_String ||
-         upb_FieldDef_CType(f) == kUpb_CType_Bytes;
-}
-
-bool upb_FieldDef_IsRepeated(const upb_FieldDef* f) {
-  return upb_FieldDef_Label(f) == kUpb_Label_Repeated;
-}
-
-bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f) {
-  return !upb_FieldDef_IsString(f) && !upb_FieldDef_IsSubMessage(f);
-}
-
-bool upb_FieldDef_IsMap(const upb_FieldDef* f) {
-  return upb_FieldDef_IsRepeated(f) && upb_FieldDef_IsSubMessage(f) &&
-         upb_MessageDef_IsMapEntry(upb_FieldDef_MessageSubDef(f));
-}
-
-bool upb_FieldDef_HasDefault(const upb_FieldDef* f) { return f->has_default; }
-
-bool upb_FieldDef_HasSubDef(const upb_FieldDef* f) {
-  return upb_FieldDef_IsSubMessage(f) ||
-         upb_FieldDef_CType(f) == kUpb_CType_Enum;
-}
-
-bool upb_FieldDef_HasPresence(const upb_FieldDef* f) {
-  if (upb_FieldDef_IsRepeated(f)) return false;
-  return upb_FieldDef_IsSubMessage(f) || upb_FieldDef_ContainingOneof(f) ||
-         f->file->syntax == kUpb_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_MessageDef
- * *****************************************************************/
-
-const google_protobuf_MessageOptions* upb_MessageDef_Options(
-    const upb_MessageDef* m) {
-  return m->opts;
-}
-
-bool upb_MessageDef_HasOptions(const upb_MessageDef* m) {
-  return m->opts != (void*)opt_default;
-}
-
-const char* upb_MessageDef_FullName(const upb_MessageDef* m) {
-  return m->full_name;
-}
-
-const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m) {
-  return m->file;
-}
-
-const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m) {
-  return m->containing_type;
-}
-
-const char* upb_MessageDef_Name(const upb_MessageDef* m) {
-  return shortdefname(m->full_name);
-}
-
-upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m) {
-  return m->file->syntax;
-}
-
-const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
-                                                     uint32_t i) {
-  upb_value val;
-  return upb_inttable_lookup(&m->itof, i, &val) ? upb_value_getconstptr(val)
-                                                : NULL;
-}
-
-const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
-    const upb_MessageDef* 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_MessageDef_FindOneofByNameWithSize(
-    const upb_MessageDef* 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_MessageDef_FindByNameWithSize(const upb_MessageDef* m,
-                                       const char* name, size_t len,
-                                       const upb_FieldDef** out_f,
-                                       const upb_OneofDef** out_o) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return false;
-  }
-
-  const upb_FieldDef* f = unpack_def(val, UPB_DEFTYPE_FIELD);
-  const upb_OneofDef* o = unpack_def(val, UPB_DEFTYPE_ONEOF);
-  if (out_f) *out_f = f;
-  if (out_o) *out_o = o;
-  return f || o; /* False if this was a JSON name. */
-}
-
-const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
-    const upb_MessageDef* 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_MessageDef_numfields(const upb_MessageDef* m) { return m->field_count; }
-
-int upb_MessageDef_numoneofs(const upb_MessageDef* m) { return m->oneof_count; }
-
-int upb_MessageDef_numrealoneofs(const upb_MessageDef* m) {
-  return m->real_oneof_count;
-}
-
-int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m) {
-  return m->ext_range_count;
-}
-
-int upb_MessageDef_FieldCount(const upb_MessageDef* m) {
-  return m->field_count;
-}
-
-int upb_MessageDef_OneofCount(const upb_MessageDef* m) {
-  return m->oneof_count;
-}
-
-int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m) {
-  return m->nested_msg_count;
-}
-
-int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m) {
-  return m->nested_enum_count;
-}
-
-int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m) {
-  return m->nested_ext_count;
-}
-
-int upb_MessageDef_realoneofcount(const upb_MessageDef* m) {
-  return m->real_oneof_count;
-}
-
-const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m) {
-  return m->layout;
-}
-
-const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m,
-                                                        int i) {
-  UPB_ASSERT(0 <= i && i < m->ext_range_count);
-  return &m->ext_ranges[i];
-}
-
-const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, int i) {
-  UPB_ASSERT(0 <= i && i < m->field_count);
-  return &m->fields[i];
-}
-
-const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i) {
-  UPB_ASSERT(0 <= i && i < m->oneof_count);
-  return &m->oneofs[i];
-}
-
-const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
-                                                   int i) {
-  UPB_ASSERT(0 <= i && i < m->nested_msg_count);
-  return &m->nested_msgs[i];
-}
-
-const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i) {
-  UPB_ASSERT(0 <= i && i < m->nested_enum_count);
-  return &m->nested_enums[i];
-}
-
-const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
-                                                   int i) {
-  UPB_ASSERT(0 <= i && i < m->nested_ext_count);
-  return &m->nested_exts[i];
-}
-
-upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m) {
-  return m->well_known_type;
-}
-
-/* upb_OneofDef ***************************************************************/
-
-const google_protobuf_OneofOptions* upb_OneofDef_Options(
-    const upb_OneofDef* o) {
-  return o->opts;
-}
-
-bool upb_OneofDef_HasOptions(const upb_OneofDef* o) {
-  return o->opts != (void*)opt_default;
-}
-
-const char* upb_OneofDef_Name(const upb_OneofDef* o) {
-  return shortdefname(o->full_name);
-}
-
-const upb_MessageDef* 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) {
-  // Compute index in our parent's array.
-  return o - o->parent->oneofs;
-}
-
-bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o) { return o->synthetic; }
-
-const upb_FieldDef* upb_OneofDef_LookupNameWithSize(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_LookupNumber(const upb_OneofDef* o,
-                                              uint32_t num) {
-  upb_value val;
-  return upb_inttable_lookup(&o->itof, num, &val) ? upb_value_getptr(val)
-                                                  : NULL;
-}
-
-/* upb_FileDef ****************************************************************/
-
-const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f) {
-  return f->opts;
-}
-
-bool upb_FileDef_HasOptions(const upb_FileDef* f) {
-  return f->opts != (void*)opt_default;
-}
-
-const char* upb_FileDef_Name(const upb_FileDef* f) { return f->name; }
-
-const char* upb_FileDef_Package(const upb_FileDef* f) { return f->package; }
-
-upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f) { return f->syntax; }
-
-int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f) {
-  return f->top_lvl_msg_count;
-}
-
-int upb_FileDef_DependencyCount(const upb_FileDef* f) { return f->dep_count; }
-
-int upb_FileDef_PublicDependencyCount(const upb_FileDef* f) {
-  return f->public_dep_count;
-}
-
-int upb_FileDef_WeakDependencyCount(const upb_FileDef* f) {
-  return f->weak_dep_count;
-}
-
-const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f) {
-  return f->public_deps;
-}
-
-const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f) {
-  return f->weak_deps;
-}
-
-int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f) {
-  return f->top_lvl_enum_count;
-}
-
-int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f) {
-  return f->top_lvl_ext_count;
-}
-
-int upb_FileDef_ServiceCount(const upb_FileDef* f) { return f->service_count; }
-
-const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->dep_count);
-  return f->deps[i];
-}
-
-const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->public_dep_count);
-  return f->deps[f->public_deps[i]];
-}
-
-const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->public_dep_count);
-  return f->deps[f->weak_deps[i]];
-}
-
-const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->top_lvl_msg_count);
-  return &f->top_lvl_msgs[i];
-}
-
-const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->top_lvl_enum_count);
-  return &f->top_lvl_enums[i];
-}
-
-const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->top_lvl_ext_count);
-  return &f->top_lvl_exts[i];
-}
-
-const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->service_count);
-  return &f->services[i];
-}
-
-const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f) { return f->symtab; }
-
-/* upb_MethodDef **************************************************************/
-
-const google_protobuf_MethodOptions* upb_MethodDef_Options(
-    const upb_MethodDef* m) {
-  return m->opts;
-}
-
-bool upb_MethodDef_HasOptions(const upb_MethodDef* m) {
-  return m->opts != (void*)opt_default;
-}
-
-const char* upb_MethodDef_FullName(const upb_MethodDef* m) {
-  return m->full_name;
-}
-
-int upb_MethodDef_Index(const upb_MethodDef* m) { return m->index; }
-
-const char* upb_MethodDef_Name(const upb_MethodDef* m) {
-  return shortdefname(m->full_name);
-}
-
-const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m) {
-  return m->service;
-}
-
-const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m) {
-  return m->input_type;
-}
-
-const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m) {
-  return m->output_type;
-}
-
-bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m) {
-  return m->client_streaming;
-}
-
-bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m) {
-  return m->server_streaming;
-}
-
-/* upb_ServiceDef *************************************************************/
-
-const google_protobuf_ServiceOptions* upb_ServiceDef_Options(
-    const upb_ServiceDef* s) {
-  return s->opts;
-}
-
-bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s) {
-  return s->opts != (void*)opt_default;
-}
-
-const char* upb_ServiceDef_FullName(const upb_ServiceDef* s) {
-  return s->full_name;
-}
-
-const char* upb_ServiceDef_Name(const upb_ServiceDef* s) {
-  return shortdefname(s->full_name);
-}
-
-int upb_ServiceDef_Index(const upb_ServiceDef* s) { return s->index; }
-
-const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s) {
-  return s->file;
-}
-
-int upb_ServiceDef_MethodCount(const upb_ServiceDef* s) {
-  return s->method_count;
-}
-
-const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i) {
-  return i < 0 || i >= s->method_count ? NULL : &s->methods[i];
-}
-
-const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
-                                                     const char* name) {
-  for (int i = 0; i < s->method_count; i++) {
-    if (strcmp(name, upb_MethodDef_Name(&s->methods[i])) == 0) {
-      return &s->methods[i];
-    }
-  }
-  return NULL;
-}
-
-/* upb_DefPool ****************************************************************/
-
-void upb_DefPool_Free(upb_DefPool* s) {
-  upb_Arena_Free(s->arena);
-  upb_gfree(s);
-}
-
-upb_DefPool* upb_DefPool_New(void) {
-  upb_DefPool* 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_inttable_init(&s->exts, s->arena)) {
-    goto err;
-  }
-
-  s->extreg = upb_ExtensionRegistry_New(s->arena);
-  if (!s->extreg) goto err;
-  return s;
-
-err:
-  upb_Arena_Free(s->arena);
-  upb_gfree(s);
-  return NULL;
-}
-
-static const void* symtab_lookup(const upb_DefPool* s, const char* sym,
-                                 upb_deftype_t type) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ? unpack_def(v, type) : NULL;
-}
-
-static const void* symtab_lookup2(const upb_DefPool* s, const char* sym,
-                                  size_t size, upb_deftype_t type) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->syms, sym, size, &v) ? unpack_def(v, type)
-                                                       : NULL;
-}
-
-const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
-                                                    const char* sym) {
-  return symtab_lookup(s, sym, UPB_DEFTYPE_MSG);
-}
-
-const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
-    const upb_DefPool* s, const char* sym, size_t len) {
-  return symtab_lookup2(s, sym, len, UPB_DEFTYPE_MSG);
-}
-
-const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
-                                              const char* sym) {
-  return symtab_lookup(s, sym, UPB_DEFTYPE_ENUM);
-}
-
-const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
-                                                      const char* sym) {
-  return symtab_lookup(s, sym, UPB_DEFTYPE_ENUMVAL);
-}
-
-const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
-                                              const char* name) {
-  upb_value v;
-  return upb_strtable_lookup(&s->files, name, &v)
-             ? unpack_def(v, UPB_DEFTYPE_FILE)
-             : NULL;
-}
-
-const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s,
-                                                      const char* name,
-                                                      size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->files, name, len, &v)
-             ? unpack_def(v, UPB_DEFTYPE_FILE)
-             : NULL;
-}
-
-const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
-    const upb_DefPool* s, const char* name, size_t size) {
-  upb_value v;
-  if (!upb_strtable_lookup2(&s->syms, name, size, &v)) return NULL;
-
-  switch (deftype(v)) {
-    case UPB_DEFTYPE_FIELD:
-      return unpack_def(v, UPB_DEFTYPE_FIELD);
-    case UPB_DEFTYPE_MSG: {
-      const upb_MessageDef* m = unpack_def(v, UPB_DEFTYPE_MSG);
-      return m->in_message_set ? &m->nested_exts[0] : NULL;
-    }
-    default:
-      break;
-  }
-
-  return NULL;
-}
-
-const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
-                                                    const char* sym) {
-  return upb_DefPool_FindExtensionByNameWithSize(s, sym, strlen(sym));
-}
-
-const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
-                                                    const char* name) {
-  return symtab_lookup(s, name, UPB_DEFTYPE_SERVICE);
-}
-
-const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
-    const upb_DefPool* s, const char* name, size_t size) {
-  return symtab_lookup2(s, name, size, UPB_DEFTYPE_SERVICE);
-}
-
-const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
-                                                        const char* name) {
-  upb_value v;
-  // TODO(haberman): non-extension fields and oneofs.
-  if (upb_strtable_lookup(&s->syms, name, &v)) {
-    switch (deftype(v)) {
-      case UPB_DEFTYPE_EXT: {
-        const upb_FieldDef* f = unpack_def(v, UPB_DEFTYPE_EXT);
-        return upb_FieldDef_File(f);
-      }
-      case UPB_DEFTYPE_MSG: {
-        const upb_MessageDef* m = unpack_def(v, UPB_DEFTYPE_MSG);
-        return upb_MessageDef_File(m);
-      }
-      case UPB_DEFTYPE_ENUM: {
-        const upb_EnumDef* e = unpack_def(v, UPB_DEFTYPE_ENUM);
-        return upb_EnumDef_File(e);
-      }
-      case UPB_DEFTYPE_ENUMVAL: {
-        const upb_EnumValueDef* ev = unpack_def(v, UPB_DEFTYPE_ENUMVAL);
-        return upb_EnumDef_File(upb_EnumValueDef_Enum(ev));
-      }
-      case UPB_DEFTYPE_SERVICE: {
-        const upb_ServiceDef* service = unpack_def(v, UPB_DEFTYPE_SERVICE);
-        return upb_ServiceDef_File(service);
-      }
-      default:
-        UPB_UNREACHABLE();
-    }
-  }
-
-  const char* last_dot = strrchr(name, '.');
-  if (last_dot) {
-    const upb_MessageDef* parent =
-        upb_DefPool_FindMessageByNameWithSize(s, name, last_dot - name);
-    if (parent) {
-      const char* shortname = last_dot + 1;
-      if (upb_MessageDef_FindByNameWithSize(parent, shortname,
-                                            strlen(shortname), NULL, NULL)) {
-        return upb_MessageDef_File(parent);
-      }
-    }
-  }
-
-  return NULL;
-}
-
-/* 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_DefPool* symtab;
-  upb_FileDef* file;                /* File we are building. */
-  upb_Arena* arena;                 /* Allocate defs here. */
-  upb_Arena* tmp_arena;             /* For temporary allocations. */
-  const upb_MiniTable_File* layout; /* NULL if we should build layouts. */
-  int enum_count;                   /* Count of enums built so far. */
-  int msg_count;                    /* Count of messages built so far. */
-  int ext_count;                    /* Count of extensions built so far. */
-  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_VSetErrorFormat(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) {
-  if (bytes == 0) return NULL;
-  void* ret = upb_Arena_Malloc(ctx->arena, bytes);
-  if (!ret) symtab_oomerr(ctx);
-  return ret;
-}
-
-// We want to copy the options verbatim into the destination options proto.
-// We use serialize+parse as our deep copy.
-#define SET_OPTIONS(target, desc_type, options_type, proto)                   \
-  if (google_protobuf_##desc_type##_has_options(proto)) {                     \
-    size_t size;                                                              \
-    char* pb = google_protobuf_##options_type##_serialize(                    \
-        google_protobuf_##desc_type##_options(proto), ctx->tmp_arena, &size); \
-    CHK_OOM(pb);                                                              \
-    target = google_protobuf_##options_type##_parse(pb, size, ctx->arena);    \
-    CHK_OOM(target);                                                          \
-  } else {                                                                    \
-    target = (const google_protobuf_##options_type*)opt_default;              \
-  }
-
-static void check_ident(symtab_addctx* ctx, upb_StringView 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_MessageValue_sizeof(upb_CType type) {
-  switch (type) {
-    case kUpb_CType_Double:
-    case kUpb_CType_Int64:
-    case kUpb_CType_UInt64:
-      return 8;
-    case kUpb_CType_Enum:
-    case kUpb_CType_Int32:
-    case kUpb_CType_UInt32:
-    case kUpb_CType_Float:
-      return 4;
-    case kUpb_CType_Bool:
-      return 1;
-    case kUpb_CType_Message:
-      return sizeof(void*);
-    case kUpb_CType_Bytes:
-    case kUpb_CType_String:
-      return sizeof(upb_StringView);
-  }
-  UPB_UNREACHABLE();
-}
-
-static uint8_t upb_msg_fielddefsize(const upb_FieldDef* f) {
-  if (upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f))) {
-    upb_MapEntry ent;
-    UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
-    return sizeof(ent.k);
-  } else if (upb_FieldDef_IsRepeated(f)) {
-    return sizeof(void*);
-  } else {
-    return upb_MessageValue_sizeof(upb_FieldDef_CType(f));
-  }
-}
-
-static uint32_t upb_MiniTable_place(symtab_addctx* ctx, upb_MiniTable* l,
-                                    size_t size, const upb_MessageDef* m) {
-  size_t ofs = UPB_ALIGN_UP(l->size, size);
-  size_t next = ofs + size;
-
-  if (next > UINT16_MAX) {
-    symtab_errf(ctx, "size of message %s exceeded max size of %zu bytes",
-                upb_MessageDef_FullName(m), (size_t)UINT16_MAX);
-  }
-
-  l->size = next;
-  return ofs;
-}
-
-static int field_number_cmp(const void* p1, const void* p2) {
-  const upb_MiniTable_Field* f1 = p1;
-  const upb_MiniTable_Field* f2 = p2;
-  return f1->number - f2->number;
-}
-
-static void assign_layout_indices(const upb_MessageDef* m, upb_MiniTable* l,
-                                  upb_MiniTable_Field* fields) {
-  int i;
-  int n = upb_MessageDef_numfields(m);
-  int dense_below = 0;
-  for (i = 0; i < n; i++) {
-    upb_FieldDef* f =
-        (upb_FieldDef*)upb_MessageDef_FindFieldByNumber(m, fields[i].number);
-    UPB_ASSERT(f);
-    f->layout_index = i;
-    if (i < UINT8_MAX && fields[i].number == i + 1 &&
-        (i == 0 || fields[i - 1].number == i)) {
-      dense_below = i + 1;
-    }
-  }
-  l->dense_below = dense_below;
-}
-
-static uint8_t map_descriptortype(const upb_FieldDef* f) {
-  uint8_t type = upb_FieldDef_Type(f);
-  /* See TableDescriptorType() in upbc/generator.cc for details and
-   * rationale of these exceptions. */
-  if (type == kUpb_FieldType_String && f->file->syntax == kUpb_Syntax_Proto2) {
-    return kUpb_FieldType_Bytes;
-  } else if (type == kUpb_FieldType_Enum &&
-             f->sub.enumdef->file->syntax == kUpb_Syntax_Proto3) {
-    return kUpb_FieldType_Int32;
-  }
-  return type;
-}
-
-static void fill_fieldlayout(upb_MiniTable_Field* field,
-                             const upb_FieldDef* f) {
-  field->number = upb_FieldDef_Number(f);
-  field->descriptortype = map_descriptortype(f);
-
-  if (upb_FieldDef_IsMap(f)) {
-    field->mode =
-        kUpb_FieldMode_Map | (upb_FieldRep_Pointer << upb_FieldRep_Shift);
-  } else if (upb_FieldDef_IsRepeated(f)) {
-    field->mode =
-        kUpb_FieldMode_Array | (upb_FieldRep_Pointer << upb_FieldRep_Shift);
-  } else {
-    /* Maps descriptor type -> elem_size_lg2.  */
-    static const uint8_t sizes[] = {
-        -1,                      /* invalid descriptor type */
-        upb_FieldRep_8Byte,      /* DOUBLE */
-        upb_FieldRep_4Byte,      /* FLOAT */
-        upb_FieldRep_8Byte,      /* INT64 */
-        upb_FieldRep_8Byte,      /* UINT64 */
-        upb_FieldRep_4Byte,      /* INT32 */
-        upb_FieldRep_8Byte,      /* FIXED64 */
-        upb_FieldRep_4Byte,      /* FIXED32 */
-        upb_FieldRep_1Byte,      /* BOOL */
-        upb_FieldRep_StringView, /* STRING */
-        upb_FieldRep_Pointer,    /* GROUP */
-        upb_FieldRep_Pointer,    /* MESSAGE */
-        upb_FieldRep_StringView, /* BYTES */
-        upb_FieldRep_4Byte,      /* UINT32 */
-        upb_FieldRep_4Byte,      /* ENUM */
-        upb_FieldRep_4Byte,      /* SFIXED32 */
-        upb_FieldRep_8Byte,      /* SFIXED64 */
-        upb_FieldRep_4Byte,      /* SINT32 */
-        upb_FieldRep_8Byte,      /* SINT64 */
-    };
-    field->mode = kUpb_FieldMode_Scalar |
-                  (sizes[field->descriptortype] << upb_FieldRep_Shift);
-  }
-
-  if (upb_FieldDef_IsPacked(f)) {
-    field->mode |= upb_LabelFlags_IsPacked;
-  }
-
-  if (upb_FieldDef_IsExtension(f)) {
-    field->mode |= upb_LabelFlags_IsExtension;
-  }
-}
-
-/* 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_MessageDef* m) {
-  upb_MiniTable* l = (upb_MiniTable*)m->layout;
-  size_t field_count = upb_MessageDef_numfields(m);
-  size_t sublayout_count = 0;
-  upb_MiniTable_Sub* subs;
-  upb_MiniTable_Field* fields;
-
-  memset(l, 0, sizeof(*l) + sizeof(_upb_FastTable_Entry));
-
-  /* Count sub-messages. */
-  for (size_t i = 0; i < field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    if (upb_FieldDef_IsSubMessage(f)) {
-      sublayout_count++;
-    }
-    if (upb_FieldDef_CType(f) == kUpb_CType_Enum &&
-        f->sub.enumdef->file->syntax == kUpb_Syntax_Proto2) {
-      sublayout_count++;
-    }
-  }
-
-  fields = symtab_alloc(ctx, field_count * sizeof(*fields));
-  subs = symtab_alloc(ctx, sublayout_count * sizeof(*subs));
-
-  l->field_count = upb_MessageDef_numfields(m);
-  l->fields = fields;
-  l->subs = subs;
-  l->table_mask = 0;
-  l->required_count = 0;
-
-  if (upb_MessageDef_ExtensionRangeCount(m) > 0) {
-    if (google_protobuf_MessageOptions_message_set_wire_format(m->opts)) {
-      l->ext = upb_ExtMode_IsMessageSet;
-    } else {
-      l->ext = upb_ExtMode_Extendable;
-    }
-  } else {
-    l->ext = upb_ExtMode_NonExtendable;
-  }
-
-  /* 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_MessageDef_IsMapEntry(m)) {
-    /* TODO(haberman): refactor this method so this special case is more
-     * elegant. */
-    const upb_FieldDef* key = upb_MessageDef_FindFieldByNumber(m, 1);
-    const upb_FieldDef* val = upb_MessageDef_FindFieldByNumber(m, 2);
-    fields[0].number = 1;
-    fields[1].number = 2;
-    fields[0].mode = kUpb_FieldMode_Scalar;
-    fields[1].mode = kUpb_FieldMode_Scalar;
-    fields[0].presence = 0;
-    fields[1].presence = 0;
-    fields[0].descriptortype = map_descriptortype(key);
-    fields[1].descriptortype = map_descriptortype(val);
-    fields[0].offset = 0;
-    fields[1].offset = sizeof(upb_StringView);
-    fields[1].submsg_index = 0;
-
-    if (upb_FieldDef_CType(val) == kUpb_CType_Message) {
-      subs[0].submsg = upb_FieldDef_MessageSubDef(val)->layout;
-    }
-
-    upb_FieldDef* fielddefs = (upb_FieldDef*)&m->fields[0];
-    UPB_ASSERT(fielddefs[0].number_ == 1);
-    UPB_ASSERT(fielddefs[1].number_ == 2);
-    fielddefs[0].layout_index = 0;
-    fielddefs[1].layout_index = 1;
-
-    l->field_count = 2;
-    l->size = 2 * sizeof(upb_StringView);
-    l->size = UPB_ALIGN_UP(l->size, 8);
-    l->dense_below = 2;
-    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.
-   */
-
-  /* Assign hasbits for required fields first. */
-  size_t hasbit = 0;
-
-  for (int i = 0; i < m->field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    upb_MiniTable_Field* field = &fields[upb_FieldDef_Index(f)];
-    if (upb_FieldDef_Label(f) == kUpb_Label_Required) {
-      field->presence = ++hasbit;
-      if (hasbit >= 63) {
-        symtab_errf(ctx, "Message with >=63 required fields: %s",
-                    upb_MessageDef_FullName(m));
-      }
-      l->required_count++;
-    }
-  }
-
-  /* Allocate hasbits and set basic field attributes. */
-  sublayout_count = 0;
-  for (int i = 0; i < m->field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    upb_MiniTable_Field* field = &fields[upb_FieldDef_Index(f)];
-
-    fill_fieldlayout(field, f);
-
-    if (upb_FieldDef_IsSubMessage(f)) {
-      field->submsg_index = sublayout_count++;
-      subs[field->submsg_index].submsg = upb_FieldDef_MessageSubDef(f)->layout;
-    } else if (upb_FieldDef_CType(f) == kUpb_CType_Enum &&
-               f->sub.enumdef->file->syntax == kUpb_Syntax_Proto2) {
-      field->submsg_index = sublayout_count++;
-      subs[field->submsg_index].subenum = upb_FieldDef_EnumSubDef(f)->layout;
-      UPB_ASSERT(subs[field->submsg_index].subenum);
-    }
-
-    if (upb_FieldDef_Label(f) == kUpb_Label_Required) {
-      /* Hasbit was already assigned. */
-    } else 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 = hasbit ? div_round_up(hasbit + 1, 8) : 0;
-
-  /* Allocate non-oneof fields. */
-  for (int i = 0; i < m->field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    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_MiniTable_place(ctx, l, field_size, m);
-  }
-
-  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
-   * and space for the actual data. */
-  for (int i = 0; i < m->oneof_count; i++) {
-    const upb_OneofDef* o = &m->oneofs[i];
-    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;
-
-    if (o->field_count == 0) {
-      symtab_errf(ctx, "Oneof must have at least one field (%s)", o->full_name);
-    }
-
-    /* Calculate field size: the max of all field sizes. */
-    for (int j = 0; j < o->field_count; j++) {
-      const upb_FieldDef* f = o->fields[j];
-      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
-    }
-
-    /* Align and allocate case offset. */
-    case_offset = upb_MiniTable_place(ctx, l, case_size, m);
-    data_offset = upb_MiniTable_place(ctx, l, field_size, m);
-
-    for (int i = 0; i < o->field_count; i++) {
-      const upb_FieldDef* f = o->fields[i];
-      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. */
-  if (fields) {
-    qsort(fields, upb_MessageDef_numfields(m), sizeof(*fields),
-          field_number_cmp);
-  }
-  assign_layout_indices(m, l, fields);
-}
-
-static char* strviewdup(symtab_addctx* ctx, upb_StringView view) {
-  char* ret = upb_strdup2(view.data, view.size, ctx->arena);
-  CHK_OOM(ret);
-  return ret;
-}
-
-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_StringView view, const char* b) {
-  return streql2(view.data, view.size, b);
-}
-
-static const char* makefullname(symtab_addctx* ctx, const char* prefix,
-                                upb_StringView 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_MessageDef* 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*)upb_FieldDef_ContainingOneof(f);
-    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;
-}
-
-/* Adds a symbol |v| to the symtab, which must be a def pointer previously
- * packed with pack_def().  The def's pointer to upb_FileDef* must be set before
- * adding, so we know which entries to remove if building this file fails. */
-static void symtab_add(symtab_addctx* ctx, const char* name, upb_value v) {
-  // TODO: table should support an operation "tryinsert" to avoid the double
-  // lookup.
-  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));
-}
-
-static bool remove_component(char* base, size_t* len) {
-  if (*len == 0) return false;
-
-  for (size_t i = *len - 1; i > 0; i--) {
-    if (base[i] == '.') {
-      *len = i;
-      return true;
-    }
-  }
-
-  *len = 0;
-  return true;
-}
-
-/* Given a symbol and the base symbol inside which it is defined, find the
- * symbol's definition in t. */
-static const void* symtab_resolveany(symtab_addctx* ctx,
-                                     const char* from_name_dbg,
-                                     const char* base, upb_StringView sym,
-                                     upb_deftype_t* type) {
-  const upb_strtable* t = &ctx->symtab->syms;
-  if (sym.size == 0) goto notfound;
-  upb_value v;
-  if (sym.data[0] == '.') {
-    /* Symbols starting with '.' are absolute, so we do a single lookup.
-     * Slice to omit the leading '.' */
-    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
-      goto notfound;
-    }
-  } else {
-    /* Remove components from base until we find an entry or run out. */
-    size_t baselen = base ? strlen(base) : 0;
-    char* tmp = malloc(sym.size + baselen + 1);
-    while (1) {
-      char* p = tmp;
-      if (baselen) {
-        memcpy(p, base, baselen);
-        p[baselen] = '.';
-        p += baselen + 1;
-      }
-      memcpy(p, sym.data, sym.size);
-      p += sym.size;
-      if (upb_strtable_lookup2(t, tmp, p - tmp, &v)) {
-        break;
-      }
-      if (!remove_component(tmp, &baselen)) {
-        free(tmp);
-        goto notfound;
-      }
-    }
-    free(tmp);
-  }
-
-  *type = deftype(v);
-  return unpack_def(v, *type);
-
-notfound:
-  symtab_errf(ctx, "couldn't resolve name '" UPB_STRINGVIEW_FORMAT "'",
-              UPB_STRINGVIEW_ARGS(sym));
-}
-
-static const void* symtab_resolve(symtab_addctx* ctx, const char* from_name_dbg,
-                                  const char* base, upb_StringView sym,
-                                  upb_deftype_t type) {
-  upb_deftype_t found_type;
-  const void* ret =
-      symtab_resolveany(ctx, from_name_dbg, base, sym, &found_type);
-  if (ret && found_type != type) {
-    symtab_errf(ctx,
-                "type mismatch when resolving %s: couldn't find "
-                "name " UPB_STRINGVIEW_FORMAT " with type=%d",
-                from_name_dbg, UPB_STRINGVIEW_ARGS(sym), (int)type);
-  }
-  return ret;
-}
-
-static void create_oneofdef(
-    symtab_addctx* ctx, upb_MessageDef* m,
-    const google_protobuf_OneofDescriptorProto* oneof_proto,
-    const upb_OneofDef* _o) {
-  upb_OneofDef* o = (upb_OneofDef*)_o;
-  upb_StringView name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
-  upb_value v;
-
-  o->parent = m;
-  o->full_name = makefullname(ctx, m->full_name, name);
-  o->field_count = 0;
-  o->synthetic = false;
-
-  SET_OPTIONS(o->opts, OneofDescriptorProto, OneofOptions, oneof_proto);
-
-  upb_value existing_v;
-  if (upb_strtable_lookup2(&m->ntof, name.data, name.size, &existing_v)) {
-    symtab_errf(ctx, "duplicate oneof name (%s)", o->full_name);
-  }
-
-  v = pack_def(o, UPB_DEFTYPE_ONEOF);
-  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);
-  CHK_OOM(ret);
-  ret->len = len;
-  if (len) memcpy(ret->str, data, len);
-  ret->str[len] = '\0';
-  return ret;
-}
-
-static bool upb_DefPool_TryGetChar(const char** src, const char* end,
-                                   char* ch) {
-  if (*src == end) return false;
-  *ch = **src;
-  *src += 1;
-  return true;
-}
-
-static char upb_DefPool_TryGetHexDigit(symtab_addctx* ctx,
-                                       const upb_FieldDef* f, const char** src,
-                                       const char* end) {
-  char ch;
-  if (!upb_DefPool_TryGetChar(src, end, &ch)) return -1;
-  if ('0' <= ch && ch <= '9') {
-    return ch - '0';
-  }
-  ch = upb_ascii_lower(ch);
-  if ('a' <= ch && ch <= 'f') {
-    return ch - 'a' + 0xa;
-  }
-  *src -= 1;  // Char wasn't actually a hex digit.
-  return -1;
-}
-
-static char upb_DefPool_ParseHexEscape(symtab_addctx* ctx,
-                                       const upb_FieldDef* f, const char** src,
-                                       const char* end) {
-  char hex_digit = upb_DefPool_TryGetHexDigit(ctx, f, src, end);
-  if (hex_digit < 0) {
-    symtab_errf(ctx,
-                "\\x cannot be followed by non-hex digit in field '%s' default",
-                upb_FieldDef_FullName(f));
-    return 0;
-  }
-  unsigned int ret = hex_digit;
-  while ((hex_digit = upb_DefPool_TryGetHexDigit(ctx, f, src, end)) >= 0) {
-    ret = (ret << 4) | hex_digit;
-  }
-  if (ret > 0xff) {
-    symtab_errf(ctx, "Value of hex escape in field %s exceeds 8 bits",
-                upb_FieldDef_FullName(f));
-    return 0;
-  }
-  return ret;
-}
-
-char upb_DefPool_TryGetOctalDigit(const char** src, const char* end) {
-  char ch;
-  if (!upb_DefPool_TryGetChar(src, end, &ch)) return -1;
-  if ('0' <= ch && ch <= '7') {
-    return ch - '0';
-  }
-  *src -= 1;  // Char wasn't actually an octal digit.
-  return -1;
-}
-
-static char upb_DefPool_ParseOctalEscape(symtab_addctx* ctx,
-                                         const upb_FieldDef* f,
-                                         const char** src, const char* end) {
-  char ch = 0;
-  for (int i = 0; i < 3; i++) {
-    char digit;
-    if ((digit = upb_DefPool_TryGetOctalDigit(src, end)) >= 0) {
-      ch = (ch << 3) | digit;
-    }
-  }
-  return ch;
-}
-
-static char upb_DefPool_ParseEscape(symtab_addctx* ctx, const upb_FieldDef* f,
-                                    const char** src, const char* end) {
-  char ch;
-  if (!upb_DefPool_TryGetChar(src, end, &ch)) {
-    symtab_errf(ctx, "unterminated escape sequence in field %s",
-                upb_FieldDef_FullName(f));
-    return 0;
-  }
-  switch (ch) {
-    case 'a':
-      return '\a';
-    case 'b':
-      return '\b';
-    case 'f':
-      return '\f';
-    case 'n':
-      return '\n';
-    case 'r':
-      return '\r';
-    case 't':
-      return '\t';
-    case 'v':
-      return '\v';
-    case '\\':
-      return '\\';
-    case '\'':
-      return '\'';
-    case '\"':
-      return '\"';
-    case '?':
-      return '\?';
-    case 'x':
-    case 'X':
-      return upb_DefPool_ParseHexEscape(ctx, f, src, end);
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-      *src -= 1;
-      return upb_DefPool_ParseOctalEscape(ctx, f, src, end);
-  }
-  symtab_errf(ctx, "Unknown escape sequence: \\%c", ch);
-}
-
-static str_t* unescape(symtab_addctx* ctx, const upb_FieldDef* f,
-                       const char* data, size_t len) {
-  // Size here is an upper bound; escape sequences could ultimately shrink it.
-  str_t* ret = symtab_alloc(ctx, sizeof(*ret) + len);
-  char* dst = &ret->str[0];
-  const char* src = data;
-  const char* end = data + len;
-
-  while (src < end) {
-    if (*src == '\\') {
-      src++;
-      *dst++ = upb_DefPool_ParseEscape(ctx, f, &src, end);
-    } else {
-      *dst++ = *src++;
-    }
-  }
-
-  ret->len = dst - &ret->str[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_CType(f)) {
-    case kUpb_CType_Int32:
-    case kUpb_CType_Int64:
-    case kUpb_CType_UInt32:
-    case kUpb_CType_UInt64:
-    case kUpb_CType_Double:
-    case kUpb_CType_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_CType(f)) {
-    case kUpb_CType_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 kUpb_CType_Enum: {
-      const upb_EnumDef* e = f->sub.enumdef;
-      const upb_EnumValueDef* ev =
-          upb_EnumDef_FindValueByNameWithSize(e, str, len);
-      if (!ev) {
-        goto invalid;
-      }
-      f->defaultval.sint = ev->number;
-      break;
-    }
-    case kUpb_CType_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 kUpb_CType_UInt32: {
-      unsigned long val = strtoul(str, &end, 0);
-      if (val > UINT32_MAX || errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.uint = val;
-      break;
-    }
-    case kUpb_CType_UInt64: {
-      unsigned long long val = strtoull(str, &end, 0);
-      if (val > UINT64_MAX || errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.uint = val;
-      break;
-    }
-    case kUpb_CType_Double: {
-      double val = strtod(str, &end);
-      if (errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.dbl = val;
-      break;
-    }
-    case kUpb_CType_Float: {
-      float val = strtof(str, &end);
-      if (errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.flt = val;
-      break;
-    }
-    case kUpb_CType_Bool: {
-      if (streql2(str, len, "false")) {
-        f->defaultval.boolean = false;
-      } else if (streql2(str, len, "true")) {
-        f->defaultval.boolean = true;
-      } else {
-        goto invalid;
-      }
-      break;
-    }
-    case kUpb_CType_String:
-      f->defaultval.str = newstr(ctx, str, len);
-      break;
-    case kUpb_CType_Bytes:
-      f->defaultval.str = unescape(ctx, f, str, len);
-      break;
-    case kUpb_CType_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 of type %d", (int)len,
-              str, upb_FieldDef_FullName(f), (int)upb_FieldDef_Type(f));
-}
-
-static void set_default_default(symtab_addctx* ctx, upb_FieldDef* f) {
-  switch (upb_FieldDef_CType(f)) {
-    case kUpb_CType_Int32:
-    case kUpb_CType_Int64:
-      f->defaultval.sint = 0;
-      break;
-    case kUpb_CType_UInt64:
-    case kUpb_CType_UInt32:
-      f->defaultval.uint = 0;
-      break;
-    case kUpb_CType_Double:
-    case kUpb_CType_Float:
-      f->defaultval.dbl = 0;
-      break;
-    case kUpb_CType_String:
-    case kUpb_CType_Bytes:
-      f->defaultval.str = newstr(ctx, NULL, 0);
-      break;
-    case kUpb_CType_Bool:
-      f->defaultval.boolean = false;
-      break;
-    case kUpb_CType_Enum:
-      f->defaultval.sint = f->sub.enumdef->values[0].number;
-    case kUpb_CType_Message:
-      break;
-  }
-}
-
-static void create_fielddef(
-    symtab_addctx* ctx, const char* prefix, upb_MessageDef* m,
-    const google_protobuf_FieldDescriptorProto* field_proto,
-    const upb_FieldDef* _f, bool is_extension) {
-  upb_FieldDef* f = (upb_FieldDef*)_f;
-  upb_StringView name;
-  const char* full_name;
-  const char* json_name;
-  const char* shortname;
-  int32_t field_number;
-
-  f->file = ctx->file; /* Must happen prior to symtab_add(). */
-
-  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
-    symtab_errf(ctx, "field has no name");
-  }
-
-  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));
-    f->has_json_name_ = true;
-  } else {
-    json_name = makejsonname(ctx, shortname);
-    f->has_json_name_ = false;
-  }
-
-  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
-
-  f->full_name = full_name;
-  f->json_name = json_name;
-  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
-  f->number_ = field_number;
-  f->scope.oneof = NULL;
-  f->proto3_optional_ =
-      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
-
-  bool has_type = google_protobuf_FieldDescriptorProto_has_type(field_proto);
-  bool has_type_name =
-      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
-
-  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
-
-  if (has_type) {
-    switch (f->type_) {
-      case kUpb_FieldType_Message:
-      case kUpb_FieldType_Group:
-      case kUpb_FieldType_Enum:
-        if (!has_type_name) {
-          symtab_errf(ctx, "field of type %d requires type name (%s)",
-                      (int)f->type_, full_name);
-        }
-        break;
-      default:
-        if (has_type_name) {
-          symtab_errf(ctx, "invalid type for field with type_name set (%s, %d)",
-                      full_name, (int)f->type_);
-        }
-    }
-  } else if (has_type_name) {
-    f->type_ =
-        FIELD_TYPE_UNSPECIFIED;  // We'll fill this in in resolve_fielddef().
-  }
-
-  if (!is_extension) {
-    /* direct message field. */
-    upb_value v, field_v, json_v, existing_v;
-    size_t json_size;
-
-    if (field_number <= 0 || field_number > kUpb_MaxFieldNumber) {
-      symtab_errf(ctx, "invalid field number (%u)", field_number);
-    }
-
-    f->index_ = f - m->fields;
-    f->msgdef = m;
-    f->is_extension_ = 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);
-
-    if (upb_strtable_lookup(&m->ntof, shortname, &existing_v)) {
-      symtab_errf(ctx, "duplicate field name (%s)", shortname);
-    }
-
-    CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, field_v,
-                                ctx->arena));
-
-    if (strcmp(shortname, json_name) != 0) {
-      if (upb_strtable_lookup(&m->ntof, json_name, &v)) {
-        symtab_errf(ctx, "duplicate json_name (%s)", json_name);
-      } else {
-        CHK_OOM(upb_strtable_insert(&m->ntof, json_name, json_size, json_v,
-                                    ctx->arena));
-      }
-    }
-
-    if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
-      symtab_errf(ctx, "duplicate field number (%u)", field_number);
-    }
-
-    CHK_OOM(upb_inttable_insert(&m->itof, field_number, v, ctx->arena));
-
-    if (ctx->layout) {
-      const upb_MiniTable_Field* fields = m->layout->fields;
-      int count = m->layout->field_count;
-      bool found = false;
-      for (int 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->is_extension_ = true;
-    f->scope.extension_scope = m;
-    symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_EXT));
-    f->layout_index = ctx->ext_count++;
-    if (ctx->layout) {
-      UPB_ASSERT(ctx->file->ext_layouts[f->layout_index]->field.number ==
-                 field_number);
-    }
-  }
-
-  if (f->type_ < kUpb_FieldType_Double || f->type_ > kUpb_FieldType_SInt64) {
-    symtab_errf(ctx, "invalid type for field %s (%d)", f->full_name, f->type_);
-  }
-
-  if (f->label_ < kUpb_Label_Optional || f->label_ > kUpb_Label_Repeated) {
-    symtab_errf(ctx, "invalid label for field %s (%d)", f->full_name,
-                f->label_);
-  }
-
-  /* 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_ == kUpb_Label_Required &&
-      f->file->syntax == kUpb_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) != kUpb_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->scope.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 {
-    if (f->proto3_optional_) {
-      symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)",
-                  f->full_name);
-    }
-  }
-
-  SET_OPTIONS(f->opts, FieldDescriptorProto, FieldOptions, field_proto);
-
-  if (google_protobuf_FieldOptions_has_packed(f->opts)) {
-    f->packed_ = google_protobuf_FieldOptions_packed(f->opts);
-  } else {
-    /* Repeated fields default to packed for proto3 only. */
-    f->packed_ = upb_FieldDef_IsPrimitive(f) &&
-                 f->label_ == kUpb_Label_Repeated &&
-                 f->file->syntax == kUpb_Syntax_Proto3;
-  }
-}
-
-static void create_service(
-    symtab_addctx* ctx, const google_protobuf_ServiceDescriptorProto* svc_proto,
-    const upb_ServiceDef* _s) {
-  upb_ServiceDef* s = (upb_ServiceDef*)_s;
-  upb_StringView name;
-  const google_protobuf_MethodDescriptorProto* const* methods;
-  size_t i, n;
-
-  s->file = ctx->file; /* Must happen prior to symtab_add. */
-
-  name = google_protobuf_ServiceDescriptorProto_name(svc_proto);
-  check_ident(ctx, name, false);
-  s->full_name = makefullname(ctx, ctx->file->package, name);
-  symtab_add(ctx, s->full_name, pack_def(s, UPB_DEFTYPE_SERVICE));
-
-  methods = google_protobuf_ServiceDescriptorProto_method(svc_proto, &n);
-
-  s->method_count = n;
-  s->methods = symtab_alloc(ctx, sizeof(*s->methods) * n);
-
-  SET_OPTIONS(s->opts, ServiceDescriptorProto, ServiceOptions, svc_proto);
-
-  for (i = 0; i < n; i++) {
-    const google_protobuf_MethodDescriptorProto* method_proto = methods[i];
-    upb_MethodDef* m = (upb_MethodDef*)&s->methods[i];
-    upb_StringView name =
-        google_protobuf_MethodDescriptorProto_name(method_proto);
-
-    m->service = s;
-    m->full_name = makefullname(ctx, s->full_name, name);
-    m->index = i;
-    m->client_streaming =
-        google_protobuf_MethodDescriptorProto_client_streaming(method_proto);
-    m->server_streaming =
-        google_protobuf_MethodDescriptorProto_server_streaming(method_proto);
-    m->input_type = symtab_resolve(
-        ctx, m->full_name, m->full_name,
-        google_protobuf_MethodDescriptorProto_input_type(method_proto),
-        UPB_DEFTYPE_MSG);
-    m->output_type = symtab_resolve(
-        ctx, m->full_name, m->full_name,
-        google_protobuf_MethodDescriptorProto_output_type(method_proto),
-        UPB_DEFTYPE_MSG);
-
-    SET_OPTIONS(m->opts, MethodDescriptorProto, MethodOptions, method_proto);
-  }
-}
-
-static int count_bits_debug(uint64_t x) {
-  // For assertions only, speed does not matter.
-  int n = 0;
-  while (x) {
-    if (x & 1) n++;
-    x >>= 1;
-  }
-  return n;
-}
-
-static int compare_int32(const void* a_ptr, const void* b_ptr) {
-  int32_t a = *(int32_t*)a_ptr;
-  int32_t b = *(int32_t*)b_ptr;
-  return a < b ? -1 : (a == b ? 0 : 1);
-}
-
-upb_MiniTable_Enum* create_enumlayout(symtab_addctx* ctx,
-                                      const upb_EnumDef* e) {
-  int n = 0;
-  uint64_t mask = 0;
-
-  for (int i = 0; i < e->value_count; i++) {
-    uint32_t val = (uint32_t)e->values[i].number;
-    if (val < 64) {
-      mask |= 1ULL << val;
-    } else {
-      n++;
-    }
-  }
-
-  int32_t* values = symtab_alloc(ctx, sizeof(*values) * n);
-
-  if (n) {
-    int32_t* p = values;
-
-    // Add values outside the bitmask range to the list, as described in the
-    // comments for upb_MiniTable_Enum.
-    for (int i = 0; i < e->value_count; i++) {
-      int32_t val = e->values[i].number;
-      if ((uint32_t)val >= 64) {
-        *p++ = val;
-      }
-    }
-    UPB_ASSERT(p == values + n);
-  }
-
-  // Enums can have duplicate values; we must sort+uniq them.
-  if (values) qsort(values, n, sizeof(*values), &compare_int32);
-
-  int dst = 0;
-  for (int i = 0; i < n; dst++) {
-    int32_t val = values[i];
-    while (i < n && values[i] == val) i++;  // Skip duplicates.
-    values[dst] = val;
-  }
-  n = dst;
-
-  UPB_ASSERT(upb_inttable_count(&e->iton) == n + count_bits_debug(mask));
-
-  upb_MiniTable_Enum* layout = symtab_alloc(ctx, sizeof(*layout));
-  layout->value_count = n;
-  layout->mask = mask;
-  layout->values = values;
-
-  return layout;
-}
-
-static void create_enumvaldef(
-    symtab_addctx* ctx, const char* prefix,
-    const google_protobuf_EnumValueDescriptorProto* val_proto, upb_EnumDef* e,
-    int i) {
-  upb_EnumValueDef* val = (upb_EnumValueDef*)&e->values[i];
-  upb_StringView name =
-      google_protobuf_EnumValueDescriptorProto_name(val_proto);
-  upb_value v = upb_value_constptr(val);
-
-  val->parent = e; /* Must happen prior to symtab_add(). */
-  val->full_name = makefullname(ctx, prefix, name);
-  val->number = google_protobuf_EnumValueDescriptorProto_number(val_proto);
-  symtab_add(ctx, val->full_name, pack_def(val, UPB_DEFTYPE_ENUMVAL));
-
-  SET_OPTIONS(val->opts, EnumValueDescriptorProto, EnumValueOptions, val_proto);
-
-  if (i == 0 && e->file->syntax == kUpb_Syntax_Proto3 && val->number != 0) {
-    symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)",
-                e->full_name);
-  }
-
-  CHK_OOM(upb_strtable_insert(&e->ntoi, name.data, name.size, v, ctx->arena));
-
-  // Multiple enumerators can have the same number, first one wins.
-  if (!upb_inttable_lookup(&e->iton, val->number, NULL)) {
-    CHK_OOM(upb_inttable_insert(&e->iton, val->number, v, ctx->arena));
-  }
-}
-
-static void create_enumdef(
-    symtab_addctx* ctx, const char* prefix,
-    const google_protobuf_EnumDescriptorProto* enum_proto,
-    const upb_MessageDef* containing_type, const upb_EnumDef* _e) {
-  upb_EnumDef* e = (upb_EnumDef*)_e;
-  ;
-  const google_protobuf_EnumValueDescriptorProto* const* values;
-  upb_StringView name;
-  size_t i, n;
-
-  e->file = ctx->file; /* Must happen prior to symtab_add() */
-  e->containing_type = containing_type;
-
-  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
-  check_ident(ctx, name, false);
-
-  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->defaultval = 0;
-  e->value_count = n;
-  e->values = symtab_alloc(ctx, sizeof(*e->values) * n);
-
-  if (n == 0) {
-    symtab_errf(ctx, "enums must contain at least one value (%s)",
-                e->full_name);
-  }
-
-  SET_OPTIONS(e->opts, EnumDescriptorProto, EnumOptions, enum_proto);
-
-  for (i = 0; i < n; i++) {
-    create_enumvaldef(ctx, prefix, values[i], e, i);
-  }
-
-  upb_inttable_compact(&e->iton, ctx->arena);
-
-  if (e->file->syntax == kUpb_Syntax_Proto2) {
-    if (ctx->layout) {
-      UPB_ASSERT(ctx->enum_count < ctx->layout->enum_count);
-      e->layout = ctx->layout->enums[ctx->enum_count++];
-      UPB_ASSERT(upb_inttable_count(&e->iton) ==
-                 e->layout->value_count + count_bits_debug(e->layout->mask));
-    } else {
-      e->layout = create_enumlayout(ctx, e);
-    }
-  } else {
-    e->layout = NULL;
-  }
-}
-
-static void msgdef_create_nested(
-    symtab_addctx* ctx, const google_protobuf_DescriptorProto* msg_proto,
-    upb_MessageDef* m);
-
-static void create_msgdef(symtab_addctx* ctx, const char* prefix,
-                          const google_protobuf_DescriptorProto* msg_proto,
-                          const upb_MessageDef* containing_type,
-                          const upb_MessageDef* _m) {
-  upb_MessageDef* m = (upb_MessageDef*)_m;
-  const google_protobuf_OneofDescriptorProto* const* oneofs;
-  const google_protobuf_FieldDescriptorProto* const* fields;
-  const google_protobuf_DescriptorProto_ExtensionRange* const* ext_ranges;
-  size_t i, n_oneof, n_field, n_ext_range;
-  upb_StringView name;
-
-  m->file = ctx->file; /* Must happen prior to symtab_add(). */
-  m->containing_type = containing_type;
-
-  name = google_protobuf_DescriptorProto_name(msg_proto);
-  check_ident(ctx, name, false);
-
-  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);
-  ext_ranges =
-      google_protobuf_DescriptorProto_extension_range(msg_proto, &n_ext_range);
-
-  CHK_OOM(upb_inttable_init(&m->itof, ctx->arena));
-  CHK_OOM(upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena));
-
-  if (ctx->layout) {
-    /* create_fielddef() below depends on this being set. */
-    UPB_ASSERT(ctx->msg_count < ctx->layout->msg_count);
-    m->layout = ctx->layout->msgs[ctx->msg_count++];
-    UPB_ASSERT(n_field == m->layout->field_count);
-  } else {
-    /* Allocate now (to allow cross-linking), populate later. */
-    m->layout =
-        symtab_alloc(ctx, sizeof(*m->layout) + sizeof(_upb_FastTable_Entry));
-  }
-
-  SET_OPTIONS(m->opts, DescriptorProto, MessageOptions, msg_proto);
-
-  m->oneof_count = n_oneof;
-  m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof);
-  for (i = 0; i < n_oneof; i++) {
-    create_oneofdef(ctx, m, oneofs[i], &m->oneofs[i]);
-  }
-
-  m->field_count = n_field;
-  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], &m->fields[i],
-                    /* is_extension= */ false);
-  }
-
-  m->ext_range_count = n_ext_range;
-  m->ext_ranges = symtab_alloc(ctx, sizeof(*m->ext_ranges) * n_ext_range);
-  for (i = 0; i < n_ext_range; i++) {
-    const google_protobuf_DescriptorProto_ExtensionRange* r = ext_ranges[i];
-    upb_ExtensionRange* r_def = (upb_ExtensionRange*)&m->ext_ranges[i];
-    int32_t start = google_protobuf_DescriptorProto_ExtensionRange_start(r);
-    int32_t end = google_protobuf_DescriptorProto_ExtensionRange_end(r);
-    int32_t max =
-        google_protobuf_MessageOptions_message_set_wire_format(m->opts)
-            ? INT32_MAX
-            : kUpb_MaxFieldNumber + 1;
-
-    // A full validation would also check that each range is disjoint, and that
-    // none of the fields overlap with the extension ranges, but we are just
-    // sanity checking here.
-    if (start < 1 || end <= start || end > max) {
-      symtab_errf(ctx, "Extension range (%d, %d) is invalid, message=%s\n",
-                  (int)start, (int)end, m->full_name);
-    }
-
-    r_def->start = start;
-    r_def->end = end;
-    SET_OPTIONS(r_def->opts, DescriptorProto_ExtensionRange,
-                ExtensionRangeOptions, r);
-  }
-
-  finalize_oneofs(ctx, m);
-  assign_msg_wellknowntype(m);
-  upb_inttable_compact(&m->itof, ctx->arena);
-  msgdef_create_nested(ctx, msg_proto, m);
-}
-
-static void msgdef_create_nested(
-    symtab_addctx* ctx, const google_protobuf_DescriptorProto* msg_proto,
-    upb_MessageDef* m) {
-  size_t n;
-
-  const google_protobuf_EnumDescriptorProto* const* enums =
-      google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  m->nested_enum_count = n;
-  m->nested_enums = symtab_alloc(ctx, sizeof(*m->nested_enums) * n);
-  for (size_t i = 0; i < n; i++) {
-    m->nested_enum_count = i + 1;
-    create_enumdef(ctx, m->full_name, enums[i], m, &m->nested_enums[i]);
-  }
-
-  const google_protobuf_FieldDescriptorProto* const* exts =
-      google_protobuf_DescriptorProto_extension(msg_proto, &n);
-  m->nested_ext_count = n;
-  m->nested_exts = symtab_alloc(ctx, sizeof(*m->nested_exts) * n);
-  for (size_t i = 0; i < n; i++) {
-    create_fielddef(ctx, m->full_name, m, exts[i], &m->nested_exts[i],
-                    /* is_extension= */ true);
-    ((upb_FieldDef*)&m->nested_exts[i])->index_ = i;
-  }
-
-  const google_protobuf_DescriptorProto* const* msgs =
-      google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  m->nested_msg_count = n;
-  m->nested_msgs = symtab_alloc(ctx, sizeof(*m->nested_msgs) * n);
-  for (size_t i = 0; i < n; i++) {
-    create_msgdef(ctx, m->full_name, msgs[i], m, &m->nested_msgs[i]);
-  }
-}
-
-static void resolve_subdef(symtab_addctx* ctx, const char* prefix,
-                           upb_FieldDef* f) {
-  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
-  upb_StringView name =
-      google_protobuf_FieldDescriptorProto_type_name(field_proto);
-  bool has_name =
-      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
-  switch ((int)f->type_) {
-    case FIELD_TYPE_UNSPECIFIED: {
-      // Type was not specified and must be inferred.
-      UPB_ASSERT(has_name);
-      upb_deftype_t type;
-      const void* def =
-          symtab_resolveany(ctx, f->full_name, prefix, name, &type);
-      switch (type) {
-        case UPB_DEFTYPE_ENUM:
-          f->sub.enumdef = def;
-          f->type_ = kUpb_FieldType_Enum;
-          break;
-        case UPB_DEFTYPE_MSG:
-          f->sub.msgdef = def;
-          f->type_ = kUpb_FieldType_Message;  // It appears there is no way of
-                                              // this being a group.
-          break;
-        default:
-          symtab_errf(ctx, "Couldn't resolve type name for field %s",
-                      f->full_name);
-      }
-    }
-    case kUpb_FieldType_Message:
-    case kUpb_FieldType_Group:
-      UPB_ASSERT(has_name);
-      f->sub.msgdef =
-          symtab_resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_MSG);
-      break;
-    case kUpb_FieldType_Enum:
-      UPB_ASSERT(has_name);
-      f->sub.enumdef =
-          symtab_resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_ENUM);
-      break;
-    default:
-      // No resolution necessary.
-      break;
-  }
-}
-
-static void resolve_extension(
-    symtab_addctx* ctx, const char* prefix, upb_FieldDef* f,
-    const google_protobuf_FieldDescriptorProto* field_proto) {
-  if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
-    symtab_errf(ctx, "extension for field '%s' had no extendee", f->full_name);
-  }
-
-  upb_StringView name =
-      google_protobuf_FieldDescriptorProto_extendee(field_proto);
-  const upb_MessageDef* m =
-      symtab_resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_MSG);
-  f->msgdef = m;
-
-  bool found = false;
-
-  for (int i = 0, n = m->ext_range_count; i < n; i++) {
-    const upb_ExtensionRange* r = &m->ext_ranges[i];
-    if (r->start <= f->number_ && f->number_ < r->end) {
-      found = true;
-      break;
-    }
-  }
-
-  if (!found) {
-    symtab_errf(ctx,
-                "field number %u in extension %s has no extension range in "
-                "message %s",
-                (unsigned)f->number_, f->full_name, f->msgdef->full_name);
-  }
-
-  const upb_MiniTable_Extension* ext = ctx->file->ext_layouts[f->layout_index];
-  if (ctx->layout) {
-    UPB_ASSERT(upb_FieldDef_Number(f) == ext->field.number);
-  } else {
-    upb_MiniTable_Extension* mut_ext = (upb_MiniTable_Extension*)ext;
-    fill_fieldlayout(&mut_ext->field, f);
-    mut_ext->field.presence = 0;
-    mut_ext->field.offset = 0;
-    mut_ext->field.submsg_index = 0;
-    mut_ext->extendee = f->msgdef->layout;
-    mut_ext->sub.submsg = f->sub.msgdef->layout;
-  }
-
-  CHK_OOM(upb_inttable_insert(&ctx->symtab->exts, (uintptr_t)ext,
-                              upb_value_constptr(f), ctx->arena));
-}
-
-static void resolve_default(
-    symtab_addctx* ctx, upb_FieldDef* f,
-    const google_protobuf_FieldDescriptorProto* field_proto) {
-  // 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_StringView defaultval =
-        google_protobuf_FieldDescriptorProto_default_value(field_proto);
-
-    if (f->file->syntax == kUpb_Syntax_Proto3) {
-      symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)",
-                  f->full_name);
-    }
-
-    if (upb_FieldDef_IsSubMessage(f)) {
-      symtab_errf(ctx, "message fields cannot have explicit defaults (%s)",
-                  f->full_name);
-    }
-
-    parse_default(ctx, defaultval.data, defaultval.size, f);
-    f->has_default = true;
-  } else {
-    set_default_default(ctx, f);
-    f->has_default = false;
-  }
-}
-
-static void resolve_fielddef(symtab_addctx* ctx, const char* prefix,
-                             upb_FieldDef* f) {
-  // We have to stash this away since resolve_subdef() may overwrite it.
-  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
-
-  resolve_subdef(ctx, prefix, f);
-  resolve_default(ctx, f, field_proto);
-
-  if (f->is_extension_) {
-    resolve_extension(ctx, prefix, f, field_proto);
-  }
-}
-
-static void resolve_msgdef(symtab_addctx* ctx, upb_MessageDef* m) {
-  for (int i = 0; i < m->field_count; i++) {
-    resolve_fielddef(ctx, m->full_name, (upb_FieldDef*)&m->fields[i]);
-  }
-
-  m->in_message_set = false;
-  for (int i = 0; i < m->nested_ext_count; i++) {
-    upb_FieldDef* ext = (upb_FieldDef*)&m->nested_exts[i];
-    resolve_fielddef(ctx, m->full_name, ext);
-    if (ext->type_ == kUpb_FieldType_Message &&
-        ext->label_ == kUpb_Label_Optional && ext->sub.msgdef == m &&
-        google_protobuf_MessageOptions_message_set_wire_format(
-            ext->msgdef->opts)) {
-      m->in_message_set = true;
-    }
-  }
-
-  if (!ctx->layout) make_layout(ctx, m);
-
-  for (int i = 0; i < m->nested_msg_count; i++) {
-    resolve_msgdef(ctx, (upb_MessageDef*)&m->nested_msgs[i]);
-  }
-}
-
-static int count_exts_in_msg(const google_protobuf_DescriptorProto* msg_proto) {
-  size_t n;
-  google_protobuf_DescriptorProto_extension(msg_proto, &n);
-  int ext_count = n;
-
-  const google_protobuf_DescriptorProto* const* nested_msgs =
-      google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (size_t i = 0; i < n; i++) {
-    ext_count += count_exts_in_msg(nested_msgs[i]);
-  }
-
-  return ext_count;
-}
-
-static void build_filedef(
-    symtab_addctx* ctx, upb_FileDef* file,
-    const google_protobuf_FileDescriptorProto* file_proto) {
-  const google_protobuf_DescriptorProto* const* msgs;
-  const google_protobuf_EnumDescriptorProto* const* enums;
-  const google_protobuf_FieldDescriptorProto* const* exts;
-  const google_protobuf_ServiceDescriptorProto* const* services;
-  const upb_StringView* strs;
-  const int32_t* public_deps;
-  const int32_t* weak_deps;
-  size_t i, n;
-
-  file->symtab = ctx->symtab;
-
-  /* Count all extensions in the file, to build a flat array of layouts. */
-  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  int ext_count = n;
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (int i = 0; i < n; i++) {
-    ext_count += count_exts_in_msg(msgs[i]);
-  }
-  file->ext_count = ext_count;
-
-  if (ctx->layout) {
-    /* We are using the ext layouts that were passed in. */
-    file->ext_layouts = ctx->layout->exts;
-    if (ctx->layout->ext_count != file->ext_count) {
-      symtab_errf(ctx, "Extension count did not match layout (%d vs %d)",
-                  ctx->layout->ext_count, file->ext_count);
-    }
-  } else {
-    /* We are building ext layouts from scratch. */
-    file->ext_layouts =
-        symtab_alloc(ctx, sizeof(*file->ext_layouts) * file->ext_count);
-    upb_MiniTable_Extension* ext =
-        symtab_alloc(ctx, sizeof(*ext) * file->ext_count);
-    for (int i = 0; i < file->ext_count; i++) {
-      file->ext_layouts[i] = &ext[i];
-    }
-  }
-
-  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));
-
-  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
-    upb_StringView 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_StringView syntax =
-        google_protobuf_FileDescriptorProto_syntax(file_proto);
-
-    if (streql_view(syntax, "proto2")) {
-      file->syntax = kUpb_Syntax_Proto2;
-    } else if (streql_view(syntax, "proto3")) {
-      file->syntax = kUpb_Syntax_Proto3;
-    } else {
-      symtab_errf(ctx, "Invalid syntax '" UPB_STRINGVIEW_FORMAT "'",
-                  UPB_STRINGVIEW_ARGS(syntax));
-    }
-  } else {
-    file->syntax = kUpb_Syntax_Proto2;
-  }
-
-  /* Read options. */
-  SET_OPTIONS(file->opts, FileDescriptorProto, FileOptions, file_proto);
-
-  /* Verify dependencies. */
-  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
-  file->dep_count = n;
-  file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n);
-
-  for (i = 0; i < n; i++) {
-    upb_StringView str = strs[i];
-    file->deps[i] =
-        upb_DefPool_FindFileByNameWithSize(ctx->symtab, str.data, str.size);
-    if (!file->deps[i]) {
-      symtab_errf(ctx,
-                  "Depends on file '" UPB_STRINGVIEW_FORMAT
-                  "', but it has not been loaded",
-                  UPB_STRINGVIEW_ARGS(str));
-    }
-  }
-
-  public_deps =
-      google_protobuf_FileDescriptorProto_public_dependency(file_proto, &n);
-  file->public_dep_count = n;
-  file->public_deps = symtab_alloc(ctx, sizeof(*file->public_deps) * n);
-  int32_t* mutable_public_deps = (int32_t*)file->public_deps;
-  for (i = 0; i < n; i++) {
-    if (public_deps[i] >= file->dep_count) {
-      symtab_errf(ctx, "public_dep %d is out of range", (int)public_deps[i]);
-    }
-    mutable_public_deps[i] = public_deps[i];
-  }
-
-  weak_deps =
-      google_protobuf_FileDescriptorProto_weak_dependency(file_proto, &n);
-  file->weak_dep_count = n;
-  file->weak_deps = symtab_alloc(ctx, sizeof(*file->weak_deps) * n);
-  int32_t* mutable_weak_deps = (int32_t*)file->weak_deps;
-  for (i = 0; i < n; i++) {
-    if (weak_deps[i] >= file->dep_count) {
-      symtab_errf(ctx, "weak_dep %d is out of range", (int)weak_deps[i]);
-    }
-    mutable_weak_deps[i] = weak_deps[i];
-  }
-
-  /* Create enums. */
-  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  file->top_lvl_enum_count = n;
-  file->top_lvl_enums = symtab_alloc(ctx, sizeof(*file->top_lvl_enums) * n);
-  for (i = 0; i < n; i++) {
-    create_enumdef(ctx, file->package, enums[i], NULL, &file->top_lvl_enums[i]);
-  }
-
-  /* Create extensions. */
-  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  file->top_lvl_ext_count = n;
-  file->top_lvl_exts = symtab_alloc(ctx, sizeof(*file->top_lvl_exts) * n);
-  for (i = 0; i < n; i++) {
-    create_fielddef(ctx, file->package, NULL, exts[i], &file->top_lvl_exts[i],
-                    /* is_extension= */ true);
-    ((upb_FieldDef*)&file->top_lvl_exts[i])->index_ = i;
-  }
-
-  /* Create messages. */
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  file->top_lvl_msg_count = n;
-  file->top_lvl_msgs = symtab_alloc(ctx, sizeof(*file->top_lvl_msgs) * n);
-  for (i = 0; i < n; i++) {
-    create_msgdef(ctx, file->package, msgs[i], NULL, &file->top_lvl_msgs[i]);
-  }
-
-  /* Create services. */
-  services = google_protobuf_FileDescriptorProto_service(file_proto, &n);
-  file->service_count = n;
-  file->services = symtab_alloc(ctx, sizeof(*file->services) * n);
-  for (i = 0; i < n; i++) {
-    create_service(ctx, services[i], &file->services[i]);
-    ((upb_ServiceDef*)&file->services[i])->index = i;
-  }
-
-  /* Now that all names are in the table, build layouts and resolve refs. */
-  for (i = 0; i < (size_t)file->top_lvl_ext_count; i++) {
-    resolve_fielddef(ctx, file->package, (upb_FieldDef*)&file->top_lvl_exts[i]);
-  }
-
-  for (i = 0; i < (size_t)file->top_lvl_msg_count; i++) {
-    resolve_msgdef(ctx, (upb_MessageDef*)&file->top_lvl_msgs[i]);
-  }
-
-  if (file->ext_count) {
-    CHK_OOM(_upb_extreg_add(ctx->symtab->extreg, file->ext_layouts,
-                            file->ext_count));
-  }
-}
-
-static void remove_filedef(upb_DefPool* s, upb_FileDef* file) {
-  intptr_t iter = UPB_INTTABLE_BEGIN;
-  upb_StringView key;
-  upb_value val;
-  while (upb_strtable_next2(&s->syms, &key, &val, &iter)) {
-    const upb_FileDef* f;
-    switch (deftype(val)) {
-      case UPB_DEFTYPE_EXT:
-        f = upb_FieldDef_File(unpack_def(val, UPB_DEFTYPE_EXT));
-        break;
-      case UPB_DEFTYPE_MSG:
-        f = upb_MessageDef_File(unpack_def(val, UPB_DEFTYPE_MSG));
-        break;
-      case UPB_DEFTYPE_ENUM:
-        f = upb_EnumDef_File(unpack_def(val, UPB_DEFTYPE_ENUM));
-        break;
-      case UPB_DEFTYPE_ENUMVAL:
-        f = upb_EnumDef_File(
-            upb_EnumValueDef_Enum(unpack_def(val, UPB_DEFTYPE_ENUMVAL)));
-        break;
-      case UPB_DEFTYPE_SERVICE:
-        f = upb_ServiceDef_File(unpack_def(val, UPB_DEFTYPE_SERVICE));
-        break;
-      default:
-        UPB_UNREACHABLE();
-    }
-
-    if (f == file) upb_strtable_removeiter(&s->syms, &iter);
-  }
-}
-
-static const upb_FileDef* _upb_DefPool_AddFile(
-    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
-    const upb_MiniTable_File* layout, upb_Status* status) {
-  symtab_addctx ctx;
-  upb_StringView name = google_protobuf_FileDescriptorProto_name(file_proto);
-  upb_value v;
-
-  if (upb_strtable_lookup2(&s->files, name.data, name.size, &v)) {
-    if (unpack_def(v, UPB_DEFTYPE_FILE)) {
-      upb_Status_SetErrorFormat(status, "duplicate file name (%.*s)",
-                                UPB_STRINGVIEW_ARGS(name));
-      return NULL;
-    }
-    const upb_MiniTable_File* registered = unpack_def(v, UPB_DEFTYPE_LAYOUT);
-    UPB_ASSERT(registered);
-    if (layout && layout != registered) {
-      upb_Status_SetErrorFormat(
-          status, "tried to build with a different layout (filename=%.*s)",
-          UPB_STRINGVIEW_ARGS(name));
-      return NULL;
-    }
-    layout = registered;
-  }
-
-  ctx.symtab = s;
-  ctx.layout = layout;
-  ctx.msg_count = 0;
-  ctx.enum_count = 0;
-  ctx.ext_count = 0;
-  ctx.status = status;
-  ctx.file = NULL;
-  ctx.arena = upb_Arena_New();
-  ctx.tmp_arena = upb_Arena_New();
-
-  if (!ctx.arena || !ctx.tmp_arena) {
-    if (ctx.arena) upb_Arena_Free(ctx.arena);
-    if (ctx.tmp_arena) upb_Arena_Free(ctx.tmp_arena);
-    upb_Status_setoom(status);
-    return NULL;
-  }
-
-  if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) {
-    UPB_ASSERT(!upb_Status_IsOk(status));
-    if (ctx.file) {
-      remove_filedef(s, ctx.file);
-      ctx.file = NULL;
-    }
-  } else {
-    ctx.file = symtab_alloc(&ctx, sizeof(*ctx.file));
-    build_filedef(&ctx, ctx.file, file_proto);
-    upb_strtable_insert(&s->files, name.data, name.size,
-                        pack_def(ctx.file, UPB_DEFTYPE_FILE), ctx.arena);
-    UPB_ASSERT(upb_Status_IsOk(status));
-    upb_Arena_Fuse(s->arena, ctx.arena);
-  }
-
-  upb_Arena_Free(ctx.arena);
-  upb_Arena_Free(ctx.tmp_arena);
-  return ctx.file;
-}
-
-const upb_FileDef* upb_DefPool_AddFile(
-    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
-    upb_Status* status) {
-  return _upb_DefPool_AddFile(s, file_proto, NULL, status);
-}
-
-/* Include here since we want most of this file to be stdio-free. */
-#include <stdio.h>
-
-bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
-                                bool rebuild_minitable) {
-  /* 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_DefPool_Init** deps = init->deps;
-  google_protobuf_FileDescriptorProto* file;
-  upb_Arena* arena;
-  upb_Status status;
-
-  upb_Status_Clear(&status);
-
-  if (upb_DefPool_FindFileByName(s, init->filename)) {
-    return true;
-  }
-
-  arena = upb_Arena_New();
-
-  for (; *deps; deps++) {
-    if (!_upb_DefPool_LoadDefInitEx(s, *deps, rebuild_minitable)) goto err;
-  }
-
-  file = google_protobuf_FileDescriptorProto_parse_ex(
-      init->descriptor.data, init->descriptor.size, NULL,
-      kUpb_DecodeOption_AliasString, arena);
-  s->bytes_loaded += init->descriptor.size;
-
-  if (!file) {
-    upb_Status_SetErrorFormat(
-        &status,
-        "Failed to parse compiled-in descriptor for file '%s'. This should "
-        "never happen.",
-        init->filename);
-    goto err;
-  }
-
-  const upb_MiniTable_File* mt = rebuild_minitable ? NULL : init->layout;
-  if (!_upb_DefPool_AddFile(s, file, mt, &status)) {
-    goto err;
-  }
-
-  upb_Arena_Free(arena);
-  return true;
-
-err:
-  fprintf(stderr,
-          "Error loading compiled-in descriptor for file '%s' (this should "
-          "never happen): %s\n",
-          init->filename, upb_Status_ErrorMessage(&status));
-  upb_Arena_Free(arena);
-  return false;
-}
-
-size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s) {
-  return s->bytes_loaded;
-}
-
-upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s) { return s->arena; }
-
-const upb_FieldDef* _upb_DefPool_FindExtensionByMiniTable(
-    const upb_DefPool* s, const upb_MiniTable_Extension* ext) {
-  upb_value v;
-  bool ok = upb_inttable_lookup(&s->exts, (uintptr_t)ext, &v);
-  UPB_ASSERT(ok);
-  return upb_value_getconstptr(v);
-}
-
-const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
-                                                      const upb_MessageDef* m,
-                                                      int32_t fieldnum) {
-  const upb_MiniTable* l = upb_MessageDef_MiniTable(m);
-  const upb_MiniTable_Extension* ext = _upb_extreg_get(s->extreg, l, fieldnum);
-  return ext ? _upb_DefPool_FindExtensionByMiniTable(s, ext) : NULL;
-}
-
-bool _upb_DefPool_registerlayout(upb_DefPool* s, const char* filename,
-                                 const upb_MiniTable_File* file) {
-  if (upb_DefPool_FindFileByName(s, filename)) return false;
-  upb_value v = pack_def(file, UPB_DEFTYPE_LAYOUT);
-  return upb_strtable_insert(&s->files, filename, strlen(filename), v,
-                             s->arena);
-}
-
-const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
-    const upb_DefPool* s) {
-  return s->extreg;
-}
-
-const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
-                                                  const upb_MessageDef* m,
-                                                  size_t* count) {
-  size_t n = 0;
-  intptr_t iter = UPB_INTTABLE_BEGIN;
-  uintptr_t key;
-  upb_value val;
-  // This is O(all exts) instead of O(exts for m).  If we need this to be
-  // efficient we may need to make extreg into a two-level table, or have a
-  // second per-message index.
-  while (upb_inttable_next2(&s->exts, &key, &val, &iter)) {
-    const upb_FieldDef* f = upb_value_getconstptr(val);
-    if (upb_FieldDef_ContainingType(f) == m) n++;
-  }
-  const upb_FieldDef** exts = malloc(n * sizeof(*exts));
-  iter = UPB_INTTABLE_BEGIN;
-  size_t i = 0;
-  while (upb_inttable_next2(&s->exts, &key, &val, &iter)) {
-    const upb_FieldDef* f = upb_value_getconstptr(val);
-    if (upb_FieldDef_ContainingType(f) == m) exts[i++] = f;
-  }
-  *count = n;
-  return exts;
-}
-
-#undef CHK_OOM
-
-/** upb/reflection.c ************************************************************/
-
-#include <string.h>
-
-
-static size_t get_field_size(const upb_MiniTable_Field* f) {
-  static unsigned char sizes[] = {
-      0,                      /* 0 */
-      8,                      /* kUpb_FieldType_Double */
-      4,                      /* kUpb_FieldType_Float */
-      8,                      /* kUpb_FieldType_Int64 */
-      8,                      /* kUpb_FieldType_UInt64 */
-      4,                      /* kUpb_FieldType_Int32 */
-      8,                      /* kUpb_FieldType_Fixed64 */
-      4,                      /* kUpb_FieldType_Fixed32 */
-      1,                      /* kUpb_FieldType_Bool */
-      sizeof(upb_StringView), /* kUpb_FieldType_String */
-      sizeof(void*),          /* kUpb_FieldType_Group */
-      sizeof(void*),          /* kUpb_FieldType_Message */
-      sizeof(upb_StringView), /* kUpb_FieldType_Bytes */
-      4,                      /* kUpb_FieldType_UInt32 */
-      4,                      /* kUpb_FieldType_Enum */
-      4,                      /* kUpb_FieldType_SFixed32 */
-      8,                      /* kUpb_FieldType_SFixed64 */
-      4,                      /* kUpb_FieldType_SInt32 */
-      8,                      /* kUpb_FieldType_SInt64 */
-  };
-  return upb_IsRepeatedOrMap(f) ? sizeof(void*) : sizes[f->descriptortype];
-}
-
-/* Strings/bytes are special-cased in maps. */
-static char _upb_CTypeo_mapsize[12] = {
-    0,
-    1,             /* kUpb_CType_Bool */
-    4,             /* kUpb_CType_Float */
-    4,             /* kUpb_CType_Int32 */
-    4,             /* kUpb_CType_UInt32 */
-    4,             /* kUpb_CType_Enum */
-    sizeof(void*), /* kUpb_CType_Message */
-    8,             /* kUpb_CType_Double */
-    8,             /* kUpb_CType_Int64 */
-    8,             /* kUpb_CType_UInt64 */
-    0,             /* kUpb_CType_String */
-    0,             /* kUpb_CType_Bytes */
-};
-
-static const char _upb_CTypeo_sizelg2[12] = {
-    0,
-    0,              /* kUpb_CType_Bool */
-    2,              /* kUpb_CType_Float */
-    2,              /* kUpb_CType_Int32 */
-    2,              /* kUpb_CType_UInt32 */
-    2,              /* kUpb_CType_Enum */
-    UPB_SIZE(2, 3), /* kUpb_CType_Message */
-    3,              /* kUpb_CType_Double */
-    3,              /* kUpb_CType_Int64 */
-    3,              /* kUpb_CType_UInt64 */
-    UPB_SIZE(3, 4), /* kUpb_CType_String */
-    UPB_SIZE(3, 4), /* kUpb_CType_Bytes */
-};
-
-/** upb_Message
- * *******************************************************************/
-
-upb_Message* upb_Message_New(const upb_MessageDef* m, upb_Arena* a) {
-  return _upb_Message_New(upb_MessageDef_MiniTable(m), a);
-}
-
-static bool in_oneof(const upb_MiniTable_Field* field) {
-  return field->presence < 0;
-}
-
-static upb_MessageValue _upb_Message_Getraw(const upb_Message* msg,
-                                            const upb_FieldDef* f) {
-  const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(f);
-  const char* mem = UPB_PTR_AT(msg, field->offset, char);
-  upb_MessageValue val = {0};
-  memcpy(&val, mem, get_field_size(field));
-  return val;
-}
-
-bool upb_Message_Has(const upb_Message* msg, const upb_FieldDef* f) {
-  assert(upb_FieldDef_HasPresence(f));
-  if (upb_FieldDef_IsExtension(f)) {
-    const upb_MiniTable_Extension* ext = _upb_FieldDef_ExtensionMiniTable(f);
-    return _upb_Message_Getext(msg, ext) != NULL;
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(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 == kUpb_FieldType_Message ||
-                 field->descriptortype == kUpb_FieldType_Group);
-      return _upb_Message_Getraw(msg, f).msg_val != NULL;
-    }
-  }
-}
-
-const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* 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_Message_Has(msg, f) ? f : NULL;
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(f);
-    uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
-    f = oneof_case ? upb_OneofDef_LookupNumber(o, oneof_case) : NULL;
-    UPB_ASSERT((f != NULL) == (oneof_case != 0));
-    return f;
-  }
-}
-
-upb_MessageValue upb_Message_Get(const upb_Message* msg,
-                                 const upb_FieldDef* f) {
-  if (upb_FieldDef_IsExtension(f)) {
-    const upb_Message_Extension* ext =
-        _upb_Message_Getext(msg, _upb_FieldDef_ExtensionMiniTable(f));
-    if (ext) {
-      upb_MessageValue val;
-      memcpy(&val, &ext->data, sizeof(val));
-      return val;
-    } else if (upb_FieldDef_IsRepeated(f)) {
-      return (upb_MessageValue){.array_val = NULL};
-    }
-  } else if (!upb_FieldDef_HasPresence(f) || upb_Message_Has(msg, f)) {
-    return _upb_Message_Getraw(msg, f);
-  }
-  return upb_FieldDef_Default(f);
-}
-
-upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg,
-                                            const upb_FieldDef* f,
-                                            upb_Arena* a) {
-  UPB_ASSERT(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_IsRepeated(f));
-  if (upb_FieldDef_HasPresence(f) && !upb_Message_Has(msg, f)) {
-    // We need to skip the upb_Message_Get() call in this case.
-    goto make;
-  }
-
-  upb_MessageValue val = upb_Message_Get(msg, f);
-  if (val.array_val) {
-    return (upb_MutableMessageValue){.array = (upb_Array*)val.array_val};
-  }
-
-  upb_MutableMessageValue ret;
-make:
-  if (!a) return (upb_MutableMessageValue){.array = NULL};
-  if (upb_FieldDef_IsMap(f)) {
-    const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
-    const upb_FieldDef* key =
-        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
-    const upb_FieldDef* value =
-        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
-    ret.map =
-        upb_Map_New(a, upb_FieldDef_CType(key), upb_FieldDef_CType(value));
-  } else if (upb_FieldDef_IsRepeated(f)) {
-    ret.array = upb_Array_New(a, upb_FieldDef_CType(f));
-  } else {
-    UPB_ASSERT(upb_FieldDef_IsSubMessage(f));
-    ret.msg = upb_Message_New(upb_FieldDef_MessageSubDef(f), a);
-  }
-
-  val.array_val = ret.array;
-  upb_Message_Set(msg, f, val, a);
-
-  return ret;
-}
-
-bool upb_Message_Set(upb_Message* msg, const upb_FieldDef* f,
-                     upb_MessageValue val, upb_Arena* a) {
-  if (upb_FieldDef_IsExtension(f)) {
-    upb_Message_Extension* ext = _upb_Message_Getorcreateext(
-        msg, _upb_FieldDef_ExtensionMiniTable(f), a);
-    if (!ext) return false;
-    memcpy(&ext->data, &val, sizeof(val));
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(f);
-    char* mem = UPB_PTR_AT(msg, field->offset, char);
-    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;
-    }
-  }
-  return true;
-}
-
-void upb_Message_ClearField(upb_Message* msg, const upb_FieldDef* f) {
-  if (upb_FieldDef_IsExtension(f)) {
-    _upb_Message_Clearext(msg, _upb_FieldDef_ExtensionMiniTable(f));
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(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_Message_Clear(upb_Message* msg, const upb_MessageDef* m) {
-  _upb_Message_Clear(msg, upb_MessageDef_MiniTable(m));
-}
-
-bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
-                      const upb_DefPool* ext_pool, const upb_FieldDef** out_f,
-                      upb_MessageValue* out_val, size_t* iter) {
-  size_t i = *iter;
-  size_t n = upb_MessageDef_FieldCount(m);
-  const upb_MessageValue zero = {0};
-  UPB_UNUSED(ext_pool);
-
-  /* Iterate over normal fields, returning the first one that is set. */
-  while (++i < n) {
-    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
-    upb_MessageValue val = _upb_Message_Getraw(msg, f);
-
-    /* Skip field if unset or empty. */
-    if (upb_FieldDef_HasPresence(f)) {
-      if (!upb_Message_Has(msg, f)) continue;
-    } else {
-      upb_MessageValue test = val;
-      if (upb_FieldDef_IsString(f) && !upb_FieldDef_IsRepeated(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_IsRepeated(f)) {
-        if (upb_Array_Size(test.array_val) == 0) continue;
-      }
-    }
-
-    *out_val = val;
-    *out_f = f;
-    *iter = i;
-    return true;
-  }
-
-  if (ext_pool) {
-    /* Return any extensions that are set. */
-    size_t count;
-    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &count);
-    if (i - n < count) {
-      ext += count - 1 - (i - n);
-      memcpy(out_val, &ext->data, sizeof(*out_val));
-      *out_f = _upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
-      *iter = i;
-      return true;
-    }
-  }
-
-  *iter = i;
-  return false;
-}
-
-bool _upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
-                                 int depth) {
-  size_t iter = kUpb_Message_Begin;
-  const upb_FieldDef* f;
-  upb_MessageValue val;
-  bool ret = true;
-
-  if (--depth == 0) return false;
-
-  _upb_Message_DiscardUnknown_shallow(msg);
-
-  while (upb_Message_Next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
-    const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
-    if (!subm) continue;
-    if (upb_FieldDef_IsMap(f)) {
-      const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(subm, 2);
-      const upb_MessageDef* val_m = upb_FieldDef_MessageSubDef(val_f);
-      upb_Map* map = (upb_Map*)val.map_val;
-      size_t iter = kUpb_Map_Begin;
-
-      if (!val_m) continue;
-
-      while (upb_MapIterator_Next(map, &iter)) {
-        upb_MessageValue map_val = upb_MapIterator_Value(map, iter);
-        if (!_upb_Message_DiscardUnknown((upb_Message*)map_val.msg_val, val_m,
-                                         depth)) {
-          ret = false;
-        }
-      }
-    } else if (upb_FieldDef_IsRepeated(f)) {
-      const upb_Array* arr = val.array_val;
-      size_t i, n = upb_Array_Size(arr);
-      for (i = 0; i < n; i++) {
-        upb_MessageValue elem = upb_Array_Get(arr, i);
-        if (!_upb_Message_DiscardUnknown((upb_Message*)elem.msg_val, subm,
-                                         depth)) {
-          ret = false;
-        }
-      }
-    } else {
-      if (!_upb_Message_DiscardUnknown((upb_Message*)val.msg_val, subm,
-                                       depth)) {
-        ret = false;
-      }
-    }
-  }
-
-  return ret;
-}
-
-bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
-                                int maxdepth) {
-  return _upb_Message_DiscardUnknown(msg, m, maxdepth);
-}
-
-/** upb_Array *****************************************************************/
-
-upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) {
-  return _upb_Array_New(a, 4, _upb_CTypeo_sizelg2[type]);
-}
-
-size_t upb_Array_Size(const upb_Array* arr) { return arr->len; }
-
-upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) {
-  upb_MessageValue 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_MessageValue 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_MessageValue 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;
-}
-
-void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
-                    size_t count) {
-  char* data = _upb_array_ptr(arr);
-  int lg2 = arr->data & 7;
-  memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
-}
-
-bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
-                      upb_Arena* arena) {
-  UPB_ASSERT(i <= arr->len);
-  UPB_ASSERT(count + arr->len >= count);
-  size_t oldsize = arr->len;
-  if (!upb_Array_Resize(arr, arr->len + count, arena)) {
-    return false;
-  }
-  upb_Array_Move(arr, i + count, i, oldsize - i);
-  return true;
-}
-
-/*
- *              i        end      arr->len
- * |------------|XXXXXXXX|--------|
- */
-void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
-  size_t end = i + count;
-  UPB_ASSERT(i <= end);
-  UPB_ASSERT(end <= arr->len);
-  upb_Array_Move(arr, i, end, arr->len - end);
-  arr->len -= count;
-}
-
-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_CType key_type, upb_CType value_type) {
-  return _upb_Map_New(a, _upb_CTypeo_mapsize[key_type],
-                      _upb_CTypeo_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_MessageValue key,
-                 upb_MessageValue* 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_MessageValue key, upb_MessageValue 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_MessageValue key) {
-  return _upb_Map_Delete(map, &key, map->key_size);
-}
-
-bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) {
-  return _upb_map_next(map, iter);
-}
-
-bool upb_MapIterator_Done(const upb_Map* map, size_t iter) {
-  upb_strtable_iter i;
-  UPB_ASSERT(iter != kUpb_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_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
-  upb_strtable_iter i;
-  upb_MessageValue ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
-  return ret;
-}
-
-upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
-  upb_strtable_iter i;
-  upb_MessageValue ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
-  return ret;
-}
-
-/* void upb_MapIterator_SetValue(upb_Map *map, size_t iter, upb_MessageValue
- * 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. */
+// Must be last.
 
 typedef struct {
   const char *ptr, *end;
@@ -9490,44 +2795,20 @@
 /* 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) {
+  if (upb_Unicode_IsHigh(cp)) {
     /* 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) {
+    uint32_t low = jsondec_codepoint(d);
+    if (!upb_Unicode_IsLow(low)) jsondec_err(d, "Invalid low surrogate");
+    cp = upb_Unicode_FromPair(cp, low);
+  } else if (upb_Unicode_IsLow(cp)) {
     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");
-  }
+  int bytes = upb_Unicode_ToUTF8(cp, out);
+  if (bytes == 0) jsondec_err(d, "Invalid codepoint");
+  return bytes;
 }
 
 static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) {
@@ -9573,7 +2854,7 @@
         if (*d->ptr == 'u') {
           d->ptr++;
           if (buf_end - end < 4) {
-            /* Allow space for maximum-sized code point (4 bytes). */
+            /* Allow space for maximum-sized codepoint (4 bytes). */
             jsondec_resize(d, &buf, &end, &buf_end);
           }
           end += jsondec_unicode(d, end);
@@ -9746,44 +3027,19 @@
 
 /* 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;
+  const char* out = upb_BufToUint64(ptr, end, val);
+  if (!out) jsondec_err(d, "Integer overflow");
+  return out;
 }
 
 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;
+                                      const char* end, int64_t* val,
+                                      bool* is_neg) {
+  const char* out = upb_BufToInt64(ptr, end, val, is_neg);
+  if (!out) jsondec_err(d, "Integer overflow");
+  return out;
 }
 
 static uint64_t jsondec_strtouint64(jsondec* d, upb_StringView str) {
@@ -9798,7 +3054,7 @@
 static int64_t jsondec_strtoint64(jsondec* d, upb_StringView str) {
   const char* end = str.data + str.size;
   int64_t ret;
-  if (jsondec_buftoint64(d, str.data, end, &ret) != end) {
+  if (jsondec_buftoint64(d, str.data, end, &ret, NULL) != end) {
     jsondec_err(d, "Non-number characters in quoted integer");
   }
   return ret;
@@ -9905,11 +3161,11 @@
   }
 
   if (upb_FieldDef_CType(f) == kUpb_CType_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");
+    float f = val.double_val;
+    if (val.double_val != INFINITY && val.double_val != -INFINITY) {
+      if (f == INFINITY || f == -INFINITY) jsondec_err(d, "Float out of range");
     }
-    val.float_val = val.double_val;
+    val.float_val = f;
   }
 
   return val;
@@ -10032,7 +3288,8 @@
 
 static upb_MessageValue jsondec_msg(jsondec* d, const upb_FieldDef* f) {
   const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
-  upb_Message* msg = upb_Message_New(m, d->arena);
+  const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
+  upb_Message* msg = upb_Message_New(layout, d->arena);
   upb_MessageValue val;
 
   jsondec_tomsg(d, msg, m);
@@ -10267,9 +3524,10 @@
   const char* ptr = str.data;
   const char* end = ptr + str.size;
   const int64_t max = (uint64_t)3652500 * 86400;
+  bool neg = false;
 
   /* "3.000000001s", "3s", etc. */
-  ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val);
+  ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val, &neg);
   nanos.int32_val = jsondec_nanos(d, &ptr, end);
 
   if (end - ptr != 1 || *ptr != 's') {
@@ -10280,7 +3538,7 @@
     jsondec_err(d, "Duration out of range");
   }
 
-  if (seconds.int64_val < 0) {
+  if (neg) {
     nanos.int32_val = -nanos.int32_val;
   }
 
@@ -10293,11 +3551,12 @@
                               const upb_MessageDef* m) {
   const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1);
   const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(values_f);
+  const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m);
   upb_Array* values = upb_Message_Mutable(msg, values_f, d->arena).array;
 
   jsondec_arrstart(d);
   while (jsondec_arrnext(d)) {
-    upb_Message* value_msg = upb_Message_New(value_m, d->arena);
+    upb_Message* value_msg = upb_Message_New(value_layout, d->arena);
     upb_MessageValue value;
     value.msg_val = value_msg;
     upb_Array_Append(values, value, d->arena);
@@ -10312,12 +3571,13 @@
   const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
   const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
   const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(value_f);
+  const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m);
   upb_Map* fields = upb_Message_Mutable(msg, fields_f, d->arena).map;
 
   jsondec_objstart(d);
   while (jsondec_objnext(d)) {
     upb_MessageValue key, value;
-    upb_Message* value_msg = upb_Message_New(value_m, d->arena);
+    upb_Message* value_msg = upb_Message_New(value_layout, d->arena);
     key.str_val = jsondec_string(d);
     value.msg_val = value_msg;
     upb_Map_Set(fields, key, value, d->arena);
@@ -10519,7 +3779,8 @@
     jsondec_err(d, "Any object didn't contain a '@type' field");
   }
 
-  any_msg = upb_Message_New(any_m, d->arena);
+  const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m);
+  any_msg = upb_Message_New(any_layout, d->arena);
 
   if (pre_type_data) {
     size_t len = pre_type_end - pre_type_data + 1;
@@ -10544,8 +3805,11 @@
 
   jsondec_objend(d);
 
-  encoded.str_val.data = upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0,
-                                    d->arena, &encoded.str_val.size);
+  upb_EncodeStatus status =
+      upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0, d->arena,
+                 (char**)&encoded.str_val.data, &encoded.str_val.size);
+  // TODO(b/235839510): We should fail gracefully here on a bad return status.
+  UPB_ASSERT(status == kUpb_EncodeStatus_Ok);
   upb_Message_Set(msg, value_f, encoded, d->arena);
 }
 
@@ -10621,19 +3885,16 @@
   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. */
+// Must be last.
 
 typedef struct {
   char *buf, *ptr, *end;
@@ -10704,7 +3965,7 @@
   va_list args;
 
   va_start(args, fmt);
-  n = vsnprintf(e->ptr, have, fmt, args);
+  n = _upb_vsnprintf(e->ptr, have, fmt, args);
   va_end(args);
 
   if (UPB_LIKELY(have > n)) {
@@ -10780,17 +4041,27 @@
   const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2);
   int64_t seconds = upb_Message_Get(msg, seconds_f).int64_val;
   int32_t nanos = upb_Message_Get(msg, nanos_f).int32_val;
+  bool negative = false;
 
   if (seconds > 315576000000 || seconds < -315576000000 ||
-      (seconds < 0) != (nanos < 0)) {
+      (seconds != 0 && nanos != 0 && (seconds < 0) != (nanos < 0))) {
     jsonenc_err(e, "bad duration");
   }
 
+  if (seconds < 0) {
+    negative = true;
+    seconds = -seconds;
+  }
   if (nanos < 0) {
+    negative = true;
     nanos = -nanos;
   }
 
-  jsonenc_printf(e, "\"%" PRId64, seconds);
+  jsonenc_putstr(e, "\"");
+  if (negative) {
+    jsonenc_putstr(e, "-");
+  }
+  jsonenc_printf(e, "%" PRId64, seconds);
   jsonenc_nanos(e, nanos);
   jsonenc_putstr(e, "s\"");
 }
@@ -10801,7 +4072,10 @@
   if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) {
     jsonenc_putstr(e, "null");
   } else {
-    const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e_def, val);
+    const upb_EnumValueDef* ev =
+        (e->options & upb_JsonEncode_FormatEnumsAsIntegers)
+            ? NULL
+            : upb_EnumDef_FindValueByNumber(e_def, val);
 
     if (ev) {
       jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev));
@@ -10977,7 +4251,7 @@
   const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url);
   const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m);
   upb_Arena* arena = jsonenc_arena(e);
-  upb_Message* any = upb_Message_New(any_m, arena);
+  upb_Message* any = upb_Message_New(any_layout, arena);
 
   if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) !=
       kUpb_DecodeStatus_Ok) {
@@ -11049,20 +4323,20 @@
 
 static void jsonenc_struct(jsonenc* e, const upb_Message* msg,
                            const upb_MessageDef* m) {
-  const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1);
-  const upb_Map* fields = upb_Message_Get(msg, fields_f).map_val;
-  const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
-  const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
-  size_t iter = kUpb_Map_Begin;
-  bool first = true;
-
   jsonenc_putstr(e, "{");
 
-  if (fields) {
-    while (upb_MapIterator_Next(fields, &iter)) {
-      upb_MessageValue key = upb_MapIterator_Key(fields, iter);
-      upb_MessageValue val = upb_MapIterator_Value(fields, iter);
+  const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1);
+  const upb_Map* fields = upb_Message_Get(msg, fields_f).map_val;
 
+  if (fields) {
+    const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
+    const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
+
+    size_t iter = kUpb_Map_Begin;
+    bool first = true;
+
+    upb_MessageValue key, val;
+    while (upb_Map_Next(fields, &key, &val, &iter)) {
       jsonenc_putsep(e, ",", &first);
       jsonenc_string(e, key.str_val);
       jsonenc_putstr(e, ":");
@@ -11256,19 +4530,21 @@
 }
 
 static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) {
+  jsonenc_putstr(e, "{");
+
   const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
   const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1);
   const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2);
-  size_t iter = kUpb_Map_Begin;
-  bool first = true;
-
-  jsonenc_putstr(e, "{");
 
   if (map) {
-    while (upb_MapIterator_Next(map, &iter)) {
+    size_t iter = kUpb_Map_Begin;
+    bool first = true;
+
+    upb_MessageValue key, val;
+    while (upb_Map_Next(map, &key, &val, &iter)) {
       jsonenc_putsep(e, ",", &first);
-      jsonenc_mapkey(e, upb_MapIterator_Key(map, iter), key_f);
-      jsonenc_scalar(e, upb_MapIterator_Value(map, iter), val_f);
+      jsonenc_mapkey(e, key, key_f);
+      jsonenc_scalar(e, val, val_f);
     }
   }
 
@@ -11360,15 +4636,8945 @@
   e.status = status;
   e.arena = NULL;
 
-  if (setjmp(e.err)) return -1;
+  if (UPB_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. */
+
+// Must be last.
+
+const char* upb_BufToUint64(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) {
+      return NULL;  // integer overflow
+    }
+    u64 *= 10;
+    u64 += ch;
+    ptr++;
+  }
+
+  *val = u64;
+  return ptr;
+}
+
+const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val,
+                           bool* is_neg) {
+  bool neg = false;
+  uint64_t u64;
+
+  if (ptr != end && *ptr == '-') {
+    ptr++;
+    neg = true;
+  }
+
+  ptr = upb_BufToUint64(ptr, end, &u64);
+  if (!ptr || u64 > (uint64_t)INT64_MAX + neg) {
+    return NULL;  // integer overflow
+  }
+
+  *val = neg ? -u64 : u64;
+  if (is_neg) *is_neg = neg;
+  return ptr;
+}
+
+
+#include <float.h>
+#include <stdlib.h>
+
+// Must be last.
+
+/* Miscellaneous utilities ****************************************************/
+
+static void upb_FixLocale(char* p) {
+  /* printf() is dependent on locales; sadly there is no easy and portable way
+   * to avoid this. This little post-processing step will translate 1,2 -> 1.2
+   * since JSON needs the latter. Arguably a hack, but it is simple and the
+   * alternatives are far more complicated, platform-dependent, and/or larger
+   * in code size. */
+  for (; *p; p++) {
+    if (*p == ',') *p = '.';
+  }
+}
+
+void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) {
+  assert(size >= kUpb_RoundTripBufferSize);
+  snprintf(buf, size, "%.*g", DBL_DIG, val);
+  if (strtod(buf, NULL) != val) {
+    snprintf(buf, size, "%.*g", DBL_DIG + 2, val);
+    assert(strtod(buf, NULL) == val);
+  }
+  upb_FixLocale(buf);
+}
+
+void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) {
+  assert(size >= kUpb_RoundTripBufferSize);
+  snprintf(buf, size, "%.*g", FLT_DIG, val);
+  if (strtof(buf, NULL) != val) {
+    snprintf(buf, size, "%.*g", FLT_DIG + 3, val);
+    assert(strtof(buf, NULL) == val);
+  }
+  upb_FixLocale(buf);
+}
+
+
+#include <stdlib.h>
+#include <string.h>
+
+// Must be last.
+
+// Determine the locale-specific radix character by calling sprintf() to print
+// the number 1.5, then stripping off the digits.  As far as I can tell, this
+// is the only portable, thread-safe way to get the C library to divulge the
+// locale's radix character.  No, localeconv() is NOT thread-safe.
+
+static int GetLocaleRadix(char *data, size_t capacity) {
+  char temp[16];
+  const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5);
+  UPB_ASSERT(temp[0] == '1');
+  UPB_ASSERT(temp[size - 1] == '5');
+  UPB_ASSERT(size < capacity);
+  temp[size - 1] = '\0';
+  strcpy(data, temp + 1);
+  return size - 2;
+}
+
+// Populates a string identical to *input except that the character pointed to
+// by pos (which should be '.') is replaced with the locale-specific radix.
+
+static void LocalizeRadix(const char *input, const char *pos, char *output) {
+  const int len1 = pos - input;
+
+  char radix[8];
+  const int len2 = GetLocaleRadix(radix, sizeof(radix));
+
+  memcpy(output, input, len1);
+  memcpy(output + len1, radix, len2);
+  strcpy(output + len1 + len2, input + len1 + 1);
+}
+
+double _upb_NoLocaleStrtod(const char *str, char **endptr) {
+  // We cannot simply set the locale to "C" temporarily with setlocale()
+  // as this is not thread-safe.  Instead, we try to parse in the current
+  // locale first.  If parsing stops at a '.' character, then this is a
+  // pretty good hint that we're actually in some other locale in which
+  // '.' is not the radix character.
+
+  char *temp_endptr;
+  double result = strtod(str, &temp_endptr);
+  if (endptr != NULL) *endptr = temp_endptr;
+  if (*temp_endptr != '.') return result;
+
+  // Parsing halted on a '.'.  Perhaps we're in a different locale?  Let's
+  // try to replace the '.' with a locale-specific radix character and
+  // try again.
+
+  char localized[80];
+  LocalizeRadix(str, temp_endptr, localized);
+  char *localized_endptr;
+  result = strtod(localized, &localized_endptr);
+  if ((localized_endptr - &localized[0]) > (temp_endptr - str)) {
+    // This attempt got further, so replacing the decimal must have helped.
+    // Update endptr to point at the right location.
+    if (endptr != NULL) {
+      // size_diff is non-zero if the localized radix has multiple bytes.
+      int size_diff = strlen(localized) - strlen(str);
+      *endptr = (char *)str + (localized_endptr - &localized[0] - size_diff);
+    }
+  }
+
+  return result;
+}
+
+
+// Must be last.
+
+int upb_Unicode_ToUTF8(uint32_t cp, char* out) {
+  if (cp <= 0x7f) {
+    out[0] = cp;
+    return 1;
+  }
+  if (cp <= 0x07ff) {
+    out[0] = (cp >> 6) | 0xc0;
+    out[1] = (cp & 0x3f) | 0x80;
+    return 2;
+  }
+  if (cp <= 0xffff) {
+    out[0] = (cp >> 12) | 0xe0;
+    out[1] = ((cp >> 6) & 0x3f) | 0x80;
+    out[2] = (cp & 0x3f) | 0x80;
+    return 3;
+  }
+  if (cp <= 0x10ffff) {
+    out[0] = (cp >> 18) | 0xf0;
+    out[1] = ((cp >> 12) & 0x3f) | 0x80;
+    out[2] = ((cp >> 6) & 0x3f) | 0x80;
+    out[3] = (cp & 0x3f) | 0x80;
+    return 4;
+  }
+  return 0;
+}
+
+
+#include <stdlib.h>
+
+// Must be last.
+
+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};
+
+
+// Must be last.
+
+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;
+}
+
+struct _upb_MemBlock {
+  struct _upb_MemBlock* next;
+  uint32_t size;
+  uint32_t cleanups;
+  // Data follows.
+};
+
+typedef struct cleanup_ent {
+  upb_CleanupFunc* cleanup;
+  void* ud;
+} cleanup_ent;
+
+static const size_t memblock_reserve =
+    UPB_ALIGN_UP(sizeof(_upb_MemBlock), UPB_MALLOC_ALIGN);
+
+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;
+}
+
+size_t upb_Arena_SpaceAllocated(upb_Arena* arena) {
+  arena = arena_findroot(arena);
+  size_t memsize = 0;
+
+  _upb_MemBlock* block = arena->freelist;
+
+  while (block) {
+    memsize += sizeof(_upb_MemBlock) + block->size;
+    block = block->next;
+  }
+
+  return memsize;
+}
+
+uint32_t upb_Arena_DebugRefCount(upb_Arena* arena) {
+  return arena_findroot(arena)->refcount;
+}
+
+static void upb_Arena_addblock(upb_Arena* a, upb_Arena* root, void* ptr,
+                               size_t size) {
+  _upb_MemBlock* 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;
+  _upb_MemBlock* 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);
+}
+
+/* Public Arena API ***********************************************************/
+
+static 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->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;
+
+  if (n) {
+    /* Align initial pointer up so that we return properly-aligned pointers. */
+    void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, UPB_MALLOC_ALIGN);
+    size_t delta = (uintptr_t)aligned - (uintptr_t)mem;
+    n = delta <= n ? n - delta : 0;
+    mem = aligned;
+  }
+
+  /* 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->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->freelist_tail = NULL;
+  a->cleanup_metadata = upb_cleanup_metadata(NULL, true);
+
+  return a;
+}
+
+static void arena_dofree(upb_Arena* a) {
+  _upb_MemBlock* block = a->freelist;
+  UPB_ASSERT(a->parent == a);
+  UPB_ASSERT(a->refcount == 0);
+
+  while (block) {
+    /* Load first since we are deleting block. */
+    _upb_MemBlock* 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_CleanupFunc* 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;
+}
+
+
+
+// Must be last.
+
+static size_t _upb_MiniTableField_Size(const upb_MiniTableField* f) {
+  static unsigned char sizes[] = {
+      0,                      /* 0 */
+      8,                      /* kUpb_FieldType_Double */
+      4,                      /* kUpb_FieldType_Float */
+      8,                      /* kUpb_FieldType_Int64 */
+      8,                      /* kUpb_FieldType_UInt64 */
+      4,                      /* kUpb_FieldType_Int32 */
+      8,                      /* kUpb_FieldType_Fixed64 */
+      4,                      /* kUpb_FieldType_Fixed32 */
+      1,                      /* kUpb_FieldType_Bool */
+      sizeof(upb_StringView), /* kUpb_FieldType_String */
+      sizeof(void*),          /* kUpb_FieldType_Group */
+      sizeof(void*),          /* kUpb_FieldType_Message */
+      sizeof(upb_StringView), /* kUpb_FieldType_Bytes */
+      4,                      /* kUpb_FieldType_UInt32 */
+      4,                      /* kUpb_FieldType_Enum */
+      4,                      /* kUpb_FieldType_SFixed32 */
+      8,                      /* kUpb_FieldType_SFixed64 */
+      4,                      /* kUpb_FieldType_SInt32 */
+      8,                      /* kUpb_FieldType_SInt64 */
+  };
+  return upb_IsRepeatedOrMap(f) ? sizeof(void*) : sizes[f->descriptortype];
+}
+
+// Maps descriptor type to elem_size_lg2.
+static int _upb_MiniTableField_CTypeLg2Size(const upb_MiniTableField* f) {
+  static const uint8_t sizes[] = {
+      -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 */
+  };
+  return sizes[f->descriptortype];
+}
+
+void* upb_MiniTable_ResizeArray(upb_Message* msg,
+                                const upb_MiniTableField* field, size_t len,
+                                upb_Arena* arena) {
+  return _upb_Array_Resize_accessor2(
+      msg, field->offset, len, _upb_MiniTableField_CTypeLg2Size(field), arena);
+}
+
+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(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) return NULL;
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char* decode_tag(const char* ptr, uint32_t* val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = (uint32_t)byte;
+    return ptr + 1;
+  } else {
+    const char* start = ptr;
+    decode_vret res = decode_longvarint64(ptr, byte);
+    if (!res.ptr || res.ptr - start > 5 || res.val > UINT32_MAX) {
+      return NULL;  // Malformed.
+    }
+    *val = (uint32_t)res.val;
+    return res.ptr;
+  }
+}
+
+// Parses unknown data by merging into existing base_message or creating a
+// new message usingg mini_table.
+static upb_UnknownToMessageRet upb_MiniTable_ParseUnknownMessage(
+    const char* unknown_data, size_t unknown_size,
+    const upb_MiniTable* mini_table, upb_Message* base_message,
+    int decode_options, upb_Arena* arena) {
+  upb_UnknownToMessageRet ret;
+  ret.message =
+      base_message ? base_message : _upb_Message_New(mini_table, arena);
+  if (!ret.message) {
+    ret.status = kUpb_UnknownToMessage_OutOfMemory;
+    return ret;
+  }
+  // Decode sub message using unknown field contents.
+  const char* data = unknown_data;
+  uint32_t tag;
+  uint64_t message_len = 0;
+  data = decode_tag(data, &tag);
+  data = decode_varint64(data, &message_len);
+  upb_DecodeStatus status = upb_Decode(data, message_len, ret.message,
+                                       mini_table, NULL, decode_options, arena);
+  if (status == kUpb_DecodeStatus_OutOfMemory) {
+    ret.status = kUpb_UnknownToMessage_OutOfMemory;
+  } else if (status == kUpb_DecodeStatus_Ok) {
+    ret.status = kUpb_UnknownToMessage_Ok;
+  } else {
+    ret.status = kUpb_UnknownToMessage_ParseError;
+  }
+  return ret;
+}
+
+upb_GetExtension_Status upb_MiniTable_GetOrPromoteExtension(
+    upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int decode_options, upb_Arena* arena,
+    const upb_Message_Extension** extension) {
+  UPB_ASSERT(ext_table->field.descriptortype == kUpb_FieldType_Message);
+  *extension = _upb_Message_Getext(msg, ext_table);
+  if (*extension) {
+    return kUpb_GetExtension_Ok;
+  }
+
+  // Check unknown fields, if available promote.
+  int field_number = ext_table->field.number;
+  upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number);
+  if (result.status != kUpb_FindUnknown_Ok) {
+    return kUpb_GetExtension_NotPresent;
+  }
+  size_t len;
+  size_t ofs = result.ptr - upb_Message_GetUnknown(msg, &len);
+  // Decode and promote from unknown.
+  const upb_MiniTable* extension_table = ext_table->sub.submsg;
+  upb_UnknownToMessageRet parse_result = upb_MiniTable_ParseUnknownMessage(
+      result.ptr, result.len, extension_table,
+      /* base_message= */ NULL, decode_options, arena);
+  switch (parse_result.status) {
+    case kUpb_UnknownToMessage_OutOfMemory:
+      return kUpb_GetExtension_OutOfMemory;
+    case kUpb_UnknownToMessage_ParseError:
+      return kUpb_GetExtension_ParseError;
+    case kUpb_UnknownToMessage_NotFound:
+      return kUpb_GetExtension_NotPresent;
+    case kUpb_UnknownToMessage_Ok:
+      break;
+  }
+  upb_Message* extension_msg = parse_result.message;
+  // Add to extensions.
+  upb_Message_Extension* ext =
+      _upb_Message_GetOrCreateExtension(msg, ext_table, arena);
+  if (!ext) {
+    return kUpb_GetExtension_OutOfMemory;
+  }
+  memcpy(&ext->data, &extension_msg, sizeof(extension_msg));
+  *extension = ext;
+  const char* delete_ptr = upb_Message_GetUnknown(msg, &len) + ofs;
+  upb_Message_DeleteUnknown(msg, delete_ptr, result.len);
+  return kUpb_GetExtension_Ok;
+}
+
+upb_GetExtensionAsBytes_Status upb_MiniTable_GetExtensionAsBytes(
+    const upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int encode_options, upb_Arena* arena, const char** extension_data,
+    size_t* len) {
+  const upb_Message_Extension* msg_ext = _upb_Message_Getext(msg, ext_table);
+  UPB_ASSERT(ext_table->field.descriptortype == kUpb_FieldType_Message);
+  if (msg_ext) {
+    upb_EncodeStatus status =
+        upb_Encode(msg_ext->data.ptr, msg_ext->ext->sub.submsg, encode_options,
+                   arena, (char**)extension_data, len);
+    if (status != kUpb_EncodeStatus_Ok) {
+      return kUpb_GetExtensionAsBytes_EncodeError;
+    }
+    return kUpb_GetExtensionAsBytes_Ok;
+  }
+  int field_number = ext_table->field.number;
+  upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number);
+  if (result.status != kUpb_FindUnknown_Ok) {
+    return kUpb_GetExtensionAsBytes_NotPresent;
+  }
+  const char* data = result.ptr;
+  uint32_t tag;
+  uint64_t message_len = 0;
+  data = decode_tag(data, &tag);
+  data = decode_varint64(data, &message_len);
+  *extension_data = data;
+  *len = message_len;
+  return kUpb_GetExtensionAsBytes_Ok;
+}
+
+static const char* UnknownFieldSet_SkipGroup(const char* ptr, const char* end,
+                                             int group_number);
+
+static const char* UnknownFieldSet_SkipField(const char* ptr, const char* end,
+                                             uint32_t tag) {
+  int field_number = tag >> 3;
+  int wire_type = tag & 7;
+  switch (wire_type) {
+    case kUpb_WireType_Varint: {
+      uint64_t val;
+      return decode_varint64(ptr, &val);
+    }
+    case kUpb_WireType_64Bit:
+      if (end - ptr < 8) return NULL;
+      return ptr + 8;
+    case kUpb_WireType_32Bit:
+      if (end - ptr < 4) return NULL;
+      return ptr + 4;
+    case kUpb_WireType_Delimited: {
+      uint64_t size;
+      ptr = decode_varint64(ptr, &size);
+      if (!ptr || end - ptr < size) return NULL;
+      return ptr + size;
+    }
+    case kUpb_WireType_StartGroup:
+      return UnknownFieldSet_SkipGroup(ptr, end, field_number);
+    case kUpb_WireType_EndGroup:
+      return NULL;
+    default:
+      assert(0);
+      return NULL;
+  }
+}
+
+static const char* UnknownFieldSet_SkipGroup(const char* ptr, const char* end,
+                                             int group_number) {
+  uint32_t end_tag = (group_number << 3) | kUpb_WireType_EndGroup;
+  while (true) {
+    if (ptr == end) return NULL;
+    uint64_t tag;
+    ptr = decode_varint64(ptr, &tag);
+    if (!ptr) return NULL;
+    if (tag == end_tag) return ptr;
+    ptr = UnknownFieldSet_SkipField(ptr, end, (uint32_t)tag);
+    if (!ptr) return NULL;
+  }
+  return ptr;
+}
+
+enum {
+  kUpb_MessageSet_StartItemTag = (1 << 3) | kUpb_WireType_StartGroup,
+  kUpb_MessageSet_EndItemTag = (1 << 3) | kUpb_WireType_EndGroup,
+  kUpb_MessageSet_TypeIdTag = (2 << 3) | kUpb_WireType_Varint,
+  kUpb_MessageSet_MessageTag = (3 << 3) | kUpb_WireType_Delimited,
+};
+
+upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg,
+                                             uint32_t field_number) {
+  size_t size;
+  upb_FindUnknownRet ret;
+
+  const char* ptr = upb_Message_GetUnknown(msg, &size);
+  if (size == 0) {
+    ret.status = kUpb_FindUnknown_NotPresent;
+    ret.ptr = NULL;
+    ret.len = 0;
+    return ret;
+  }
+  const char* end = ptr + size;
+  uint64_t uint64_val;
+
+  while (ptr < end) {
+    uint32_t tag = 0;
+    int field;
+    int wire_type;
+    const char* unknown_begin = ptr;
+    ptr = decode_tag(ptr, &tag);
+    field = tag >> 3;
+    wire_type = tag & 7;
+    switch (wire_type) {
+      case kUpb_WireType_EndGroup:
+        ret.status = kUpb_FindUnknown_ParseError;
+        return ret;
+      case kUpb_WireType_Varint:
+        ptr = decode_varint64(ptr, &uint64_val);
+        if (!ptr) {
+          ret.status = kUpb_FindUnknown_ParseError;
+          return ret;
+        }
+        break;
+      case kUpb_WireType_32Bit:
+        ptr += 4;
+        break;
+      case kUpb_WireType_64Bit:
+        ptr += 8;
+        break;
+      case kUpb_WireType_Delimited:
+        // Read size.
+        ptr = decode_varint64(ptr, &uint64_val);
+        if (uint64_val >= INT32_MAX || !ptr) {
+          ret.status = kUpb_FindUnknown_ParseError;
+          return ret;
+        }
+        ptr += uint64_val;
+        break;
+      case kUpb_WireType_StartGroup:
+        // tag >> 3 specifies the group number, recurse and skip
+        // until we see group end tag.
+        ptr = UnknownFieldSet_SkipGroup(ptr, end, field_number);
+        break;
+      default:
+        ret.status = kUpb_FindUnknown_ParseError;
+        return ret;
+    }
+    if (field_number == field) {
+      ret.status = kUpb_FindUnknown_Ok;
+      ret.ptr = unknown_begin;
+      ret.len = ptr - unknown_begin;
+      return ret;
+    }
+  }
+  ret.status = kUpb_FindUnknown_NotPresent;
+  ret.ptr = NULL;
+  ret.len = 0;
+  return ret;
+}
+
+upb_UnknownToMessageRet upb_MiniTable_PromoteUnknownToMessage(
+    upb_Message* msg, const upb_MiniTable* mini_table,
+    const upb_MiniTableField* field, const upb_MiniTable* sub_mini_table,
+    int decode_options, upb_Arena* arena) {
+  upb_FindUnknownRet unknown;
+  // We need to loop and merge unknowns that have matching tag field->number.
+  upb_Message* message = NULL;
+  // Callers should check that message is not set first before calling
+  // PromotoUnknownToMessage.
+  UPB_ASSERT(upb_MiniTable_GetMessage(msg, field, NULL) == NULL);
+  upb_UnknownToMessageRet ret;
+  ret.status = kUpb_UnknownToMessage_Ok;
+  do {
+    unknown = upb_MiniTable_FindUnknown(msg, field->number);
+    switch (unknown.status) {
+      case kUpb_FindUnknown_Ok: {
+        const char* unknown_data = unknown.ptr;
+        size_t unknown_size = unknown.len;
+        ret = upb_MiniTable_ParseUnknownMessage(unknown_data, unknown_size,
+                                                sub_mini_table, message,
+                                                decode_options, arena);
+        if (ret.status == kUpb_UnknownToMessage_Ok) {
+          message = ret.message;
+          upb_Message_DeleteUnknown(msg, unknown_data, unknown_size);
+        }
+      } break;
+      case kUpb_FindUnknown_ParseError:
+        ret.status = kUpb_UnknownToMessage_ParseError;
+        break;
+      case kUpb_FindUnknown_NotPresent:
+        // If we parsed at least one unknown, we are done.
+        ret.status =
+            message ? kUpb_UnknownToMessage_Ok : kUpb_UnknownToMessage_NotFound;
+        break;
+    }
+  } while (unknown.status == kUpb_FindUnknown_Ok);
+  if (message) {
+    upb_MiniTable_SetMessage(msg, mini_table, field, message);
+    ret.message = message;
+  }
+  return ret;
+}
+
+// Moves repeated messages in unknowns to a upb_Array.
+//
+// Since the repeated field is not a scalar type we don't check for
+// kUpb_LabelFlags_IsPacked.
+// TODO(b/251007554): Optimize. Instead of converting messages one at a time,
+// scan all unknown data once and compact.
+upb_UnknownToMessage_Status upb_MiniTable_PromoteUnknownToMessageArray(
+    upb_Message* msg, const upb_MiniTableField* field,
+    const upb_MiniTable* mini_table, int decode_options, upb_Arena* arena) {
+  upb_Array* repeated_messages = upb_MiniTable_GetMutableArray(msg, field);
+  // Find all unknowns with given field number and parse.
+  upb_FindUnknownRet unknown;
+  do {
+    unknown = upb_MiniTable_FindUnknown(msg, field->number);
+    if (unknown.status == kUpb_FindUnknown_Ok) {
+      upb_UnknownToMessageRet ret = upb_MiniTable_ParseUnknownMessage(
+          unknown.ptr, unknown.len, mini_table,
+          /* base_message= */ NULL, decode_options, arena);
+      if (ret.status == kUpb_UnknownToMessage_Ok) {
+        upb_MessageValue value;
+        value.msg_val = ret.message;
+        if (!upb_Array_Append(repeated_messages, value, arena)) {
+          return kUpb_UnknownToMessage_OutOfMemory;
+        }
+        upb_Message_DeleteUnknown(msg, unknown.ptr, unknown.len);
+      } else {
+        return ret.status;
+      }
+    }
+  } while (unknown.status == kUpb_FindUnknown_Ok);
+  return kUpb_UnknownToMessage_Ok;
+}
+
+
+#include <math.h>
+
+
+// Must be last.
+
+const float kUpb_FltInfinity = INFINITY;
+const double kUpb_Infinity = INFINITY;
+const double kUpb_NaN = NAN;
+
+static const size_t overhead = sizeof(upb_Message_InternalData);
+
+upb_Message* upb_Message_New(const upb_MiniTable* mini_table,
+                             upb_Arena* arena) {
+  return _upb_Message_New(mini_table, arena);
+}
+
+void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l) {
+  // Note: Can't use UPB_PTR_AT() here because we are doing pointer subtraction.
+  char* mem = (char*)msg - sizeof(upb_Message_Internal);
+  memset(mem, 0, upb_msg_sizeof(l));
+}
+
+static bool realloc_internal(upb_Message* msg, size_t need, upb_Arena* arena) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (!in->internal) {
+    /* No internal data, allocate from scratch. */
+    size_t size = UPB_MAX(128, upb_Log2CeilingSize(need + overhead));
+    upb_Message_InternalData* internal = upb_Arena_Malloc(arena, size);
+    if (!internal) return false;
+    internal->size = size;
+    internal->unknown_end = overhead;
+    internal->ext_begin = size;
+    in->internal = internal;
+  } else if (in->internal->ext_begin - in->internal->unknown_end < need) {
+    /* Internal data is too small, reallocate. */
+    size_t new_size = upb_Log2CeilingSize(in->internal->size + need);
+    size_t ext_bytes = in->internal->size - in->internal->ext_begin;
+    size_t new_ext_begin = new_size - ext_bytes;
+    upb_Message_InternalData* internal =
+        upb_Arena_Realloc(arena, in->internal, in->internal->size, new_size);
+    if (!internal) return false;
+    if (ext_bytes) {
+      /* Need to move extension data to the end. */
+      char* ptr = (char*)internal;
+      memmove(ptr + new_ext_begin, ptr + internal->ext_begin, ext_bytes);
+    }
+    internal->ext_begin = new_ext_begin;
+    internal->size = new_size;
+    in->internal = internal;
+  }
+  UPB_ASSERT(in->internal->ext_begin - in->internal->unknown_end >= need);
+  return true;
+}
+
+bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
+                             upb_Arena* arena) {
+  if (!realloc_internal(msg, len, arena)) return false;
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  memcpy(UPB_PTR_AT(in->internal, in->internal->unknown_end, char), data, len);
+  in->internal->unknown_end += len;
+  return true;
+}
+
+void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (in->internal) {
+    in->internal->unknown_end = overhead;
+  }
+}
+
+const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
+  const upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (in->internal) {
+    *len = in->internal->unknown_end - overhead;
+    return (char*)(in->internal + 1);
+  } else {
+    *len = 0;
+    return NULL;
+  }
+}
+
+void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  const char* internal_unknown_end =
+      UPB_PTR_AT(in->internal, in->internal->unknown_end, char);
+#ifndef NDEBUG
+  size_t full_unknown_size;
+  const char* full_unknown = upb_Message_GetUnknown(msg, &full_unknown_size);
+  UPB_ASSERT((uintptr_t)data >= (uintptr_t)full_unknown);
+  UPB_ASSERT((uintptr_t)data < (uintptr_t)(full_unknown + full_unknown_size));
+  UPB_ASSERT((uintptr_t)(data + len) > (uintptr_t)data);
+  UPB_ASSERT((uintptr_t)(data + len) <= (uintptr_t)internal_unknown_end);
+#endif
+  if ((data + len) != internal_unknown_end) {
+    memmove((char*)data, data + len, internal_unknown_end - data - len);
+  }
+  in->internal->unknown_end -= len;
+}
+
+const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
+                                                  size_t* count) {
+  const upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (in->internal) {
+    *count = (in->internal->size - in->internal->ext_begin) /
+             sizeof(upb_Message_Extension);
+    return UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
+  } else {
+    *count = 0;
+    return NULL;
+  }
+}
+
+const upb_Message_Extension* _upb_Message_Getext(
+    const upb_Message* msg, const upb_MiniTableExtension* e) {
+  size_t n;
+  const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &n);
+
+  /* For now we use linear search exclusively to find extensions. If this
+   * becomes an issue due to messages with lots of extensions, we can introduce
+   * a table of some sort. */
+  for (size_t i = 0; i < n; i++) {
+    if (ext[i].ext == e) {
+      return &ext[i];
+    }
+  }
+
+  return NULL;
+}
+
+void _upb_Message_Clearext(upb_Message* msg,
+                           const upb_MiniTableExtension* ext_l) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (!in->internal) return;
+  const upb_Message_Extension* base =
+      UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
+  upb_Message_Extension* ext =
+      (upb_Message_Extension*)_upb_Message_Getext(msg, ext_l);
+  if (ext) {
+    *ext = *base;
+    in->internal->ext_begin += sizeof(upb_Message_Extension);
+  }
+}
+
+upb_Message_Extension* _upb_Message_GetOrCreateExtension(
+    upb_Message* msg, const upb_MiniTableExtension* e, upb_Arena* arena) {
+  upb_Message_Extension* ext =
+      (upb_Message_Extension*)_upb_Message_Getext(msg, e);
+  if (ext) return ext;
+  if (!realloc_internal(msg, sizeof(upb_Message_Extension), arena)) return NULL;
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  in->internal->ext_begin -= sizeof(upb_Message_Extension);
+  ext = UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
+  memset(ext, 0, sizeof(upb_Message_Extension));
+  ext->ext = e;
+  return ext;
+}
+
+size_t upb_Message_ExtensionCount(const upb_Message* msg) {
+  size_t count;
+  _upb_Message_Getexts(msg, &count);
+  return count;
+}
+
+
+#include <inttypes.h>
+
+
+// Must be last.
+
+const char _kUpb_ToBase92[] = {
+    ' ', '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/',
+    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
+    '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
+    'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+    'Z', '[', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+    'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', '{', '|', '}', '~',
+};
+
+const int8_t _kUpb_FromBase92[] = {
+    0,  1,  -1, 2,  3,  4,  5,  -1, 6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16,
+    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+    36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+    55, 56, 57, -1, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+    73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+};
+
+const upb_MiniTableField* upb_MiniTable_FindFieldByNumber(
+    const upb_MiniTable* table, uint32_t number) {
+  int n = table->field_count;
+  for (int i = 0; i < n; i++) {
+    if (table->fields[i].number == number) {
+      return &table->fields[i];
+    }
+  }
+  return NULL;
+}
+
+upb_FieldType upb_MiniTableField_Type(const upb_MiniTableField* field) {
+  if (field->mode & kUpb_LabelFlags_IsAlternate) {
+    if (field->descriptortype == kUpb_FieldType_Int32) {
+      return kUpb_FieldType_Enum;
+    } else if (field->descriptortype == kUpb_FieldType_Bytes) {
+      return kUpb_FieldType_String;
+    } else {
+      UPB_ASSERT(false);
+    }
+  }
+  return field->descriptortype;
+}
+
+
+#include <inttypes.h>
+#include <stdlib.h>
+
+
+// Must be last.
+
+// Note: we sort by this number when calculating layout order.
+typedef enum {
+  kUpb_LayoutItemType_OneofCase,   // Oneof case.
+  kUpb_LayoutItemType_OneofField,  // Oneof field data.
+  kUpb_LayoutItemType_Field,       // Non-oneof field data.
+
+  kUpb_LayoutItemType_Max = kUpb_LayoutItemType_Field,
+} upb_LayoutItemType;
+
+#define kUpb_LayoutItem_IndexSentinel ((uint16_t)-1)
+
+typedef struct {
+  // Index of the corresponding field.  When this is a oneof field, the field's
+  // offset will be the index of the next field in a linked list.
+  uint16_t field_index;
+  uint16_t offset;
+  upb_FieldRep rep;
+  upb_LayoutItemType type;
+} upb_LayoutItem;
+
+typedef struct {
+  upb_LayoutItem* data;
+  size_t size;
+  size_t capacity;
+} upb_LayoutItemVector;
+
+typedef struct {
+  const char* end;
+  upb_MiniTable* table;
+  upb_MiniTableField* fields;
+  upb_MiniTablePlatform platform;
+  upb_LayoutItemVector vec;
+  upb_Arena* arena;
+  upb_Status* status;
+
+  // When building enums.
+  upb_MiniTableEnum* enum_table;
+  uint32_t enum_value_count;
+  uint32_t enum_data_count;
+  uint32_t enum_data_capacity;
+
+  jmp_buf err;
+} upb_MtDecoder;
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void upb_MtDecoder_ErrorFormat(upb_MtDecoder* d,
+                                                   const char* fmt, ...) {
+  if (d->status) {
+    va_list argp;
+    upb_Status_SetErrorMessage(d->status, "Error building mini table: ");
+    va_start(argp, fmt);
+    upb_Status_VAppendErrorFormat(d->status, fmt, argp);
+    va_end(argp);
+  }
+  UPB_LONGJMP(d->err, 1);
+}
+
+static void upb_MtDecoder_CheckOutOfMemory(upb_MtDecoder* d, const void* ptr) {
+  if (!ptr) upb_MtDecoder_ErrorFormat(d, "Out of memory");
+}
+
+// In each field's offset, we temporarily store a presence classifier:
+enum PresenceClass {
+  kNoPresence = 0,
+  kHasbitPresence = 1,
+  kRequiredPresence = 2,
+  kOneofBase = 3,
+  // Negative values refer to a specific oneof with that number.  Positive
+  // values >= kOneofBase indicate that this field is in a oneof, and specify
+  // the next field in this oneof's linked list.
+};
+
+static const char* upb_MiniTable_DecodeBase92Varint(upb_MtDecoder* d,
+                                                    const char* ptr,
+                                                    char first_ch, uint8_t min,
+                                                    uint8_t max,
+                                                    uint32_t* out_val) {
+  uint32_t val = 0;
+  uint32_t shift = 0;
+  const int bits_per_char =
+      upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min));
+  char ch = first_ch;
+  while (1) {
+    uint32_t bits = _upb_FromBase92(ch) - _upb_FromBase92(min);
+    val |= bits << shift;
+    if (ptr == d->end || *ptr < min || max < *ptr) {
+      *out_val = val;
+      return ptr;
+    }
+    ch = *ptr++;
+    shift += bits_per_char;
+    if (shift >= 32) upb_MtDecoder_ErrorFormat(d, "Overlong varint");
+  }
+}
+
+static bool upb_MiniTable_HasSub(upb_MiniTableField* field,
+                                 uint64_t msg_modifiers) {
+  switch (field->descriptortype) {
+    case kUpb_FieldType_Message:
+    case kUpb_FieldType_Group:
+    case kUpb_FieldType_Enum:
+      return true;
+    case kUpb_FieldType_String:
+      if (!(msg_modifiers & kUpb_MessageModifier_ValidateUtf8)) {
+        field->descriptortype = kUpb_FieldType_Bytes;
+        field->mode |= kUpb_LabelFlags_IsAlternate;
+      }
+      return false;
+    default:
+      return false;
+  }
+}
+
+static bool upb_MtDecoder_FieldIsPackable(upb_MiniTableField* field) {
+  return (field->mode & kUpb_FieldMode_Array) &&
+         _upb_FieldType_IsPackable(field->descriptortype);
+}
+
+static void upb_MiniTable_SetTypeAndSub(upb_MiniTableField* field,
+                                        upb_FieldType type, uint32_t* sub_count,
+                                        uint64_t msg_modifiers,
+                                        bool is_proto3_enum) {
+  field->descriptortype = type;
+
+  if (is_proto3_enum) {
+    UPB_ASSERT(field->descriptortype == kUpb_FieldType_Enum);
+    field->descriptortype = kUpb_FieldType_Int32;
+    field->mode |= kUpb_LabelFlags_IsAlternate;
+  }
+
+  if (upb_MiniTable_HasSub(field, msg_modifiers)) {
+    field->submsg_index = sub_count ? (*sub_count)++ : 0;
+  } else {
+    field->submsg_index = kUpb_NoSub;
+  }
+
+  if (upb_MtDecoder_FieldIsPackable(field) &&
+      (msg_modifiers & kUpb_MessageModifier_DefaultIsPacked)) {
+    field->mode |= kUpb_LabelFlags_IsPacked;
+  }
+}
+
+static const char kUpb_EncodedToType[] = {
+    [kUpb_EncodedType_Double] = kUpb_FieldType_Double,
+    [kUpb_EncodedType_Float] = kUpb_FieldType_Float,
+    [kUpb_EncodedType_Int64] = kUpb_FieldType_Int64,
+    [kUpb_EncodedType_UInt64] = kUpb_FieldType_UInt64,
+    [kUpb_EncodedType_Int32] = kUpb_FieldType_Int32,
+    [kUpb_EncodedType_Fixed64] = kUpb_FieldType_Fixed64,
+    [kUpb_EncodedType_Fixed32] = kUpb_FieldType_Fixed32,
+    [kUpb_EncodedType_Bool] = kUpb_FieldType_Bool,
+    [kUpb_EncodedType_String] = kUpb_FieldType_String,
+    [kUpb_EncodedType_Group] = kUpb_FieldType_Group,
+    [kUpb_EncodedType_Message] = kUpb_FieldType_Message,
+    [kUpb_EncodedType_Bytes] = kUpb_FieldType_Bytes,
+    [kUpb_EncodedType_UInt32] = kUpb_FieldType_UInt32,
+    [kUpb_EncodedType_OpenEnum] = kUpb_FieldType_Enum,
+    [kUpb_EncodedType_SFixed32] = kUpb_FieldType_SFixed32,
+    [kUpb_EncodedType_SFixed64] = kUpb_FieldType_SFixed64,
+    [kUpb_EncodedType_SInt32] = kUpb_FieldType_SInt32,
+    [kUpb_EncodedType_SInt64] = kUpb_FieldType_SInt64,
+    [kUpb_EncodedType_ClosedEnum] = kUpb_FieldType_Enum,
+};
+
+static void upb_MiniTable_SetField(upb_MtDecoder* d, uint8_t ch,
+                                   upb_MiniTableField* field,
+                                   uint64_t msg_modifiers,
+                                   uint32_t* sub_count) {
+  static const char kUpb_EncodedToFieldRep[] = {
+      [kUpb_EncodedType_Double] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_Float] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_Int64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_UInt64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_Int32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_Fixed64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_Fixed32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_Bool] = kUpb_FieldRep_1Byte,
+      [kUpb_EncodedType_String] = kUpb_FieldRep_StringView,
+      [kUpb_EncodedType_Bytes] = kUpb_FieldRep_StringView,
+      [kUpb_EncodedType_UInt32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_OpenEnum] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_SFixed32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_SFixed64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_SInt32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_SInt64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_ClosedEnum] = kUpb_FieldRep_4Byte,
+  };
+
+  char pointer_rep = d->platform == kUpb_MiniTablePlatform_32Bit
+                         ? kUpb_FieldRep_4Byte
+                         : kUpb_FieldRep_8Byte;
+
+  int8_t type = _upb_FromBase92(ch);
+  if (ch >= _upb_ToBase92(kUpb_EncodedType_RepeatedBase)) {
+    type -= kUpb_EncodedType_RepeatedBase;
+    field->mode = kUpb_FieldMode_Array;
+    field->mode |= pointer_rep << kUpb_FieldRep_Shift;
+    field->offset = kNoPresence;
+  } else {
+    field->mode = kUpb_FieldMode_Scalar;
+    field->offset = kHasbitPresence;
+    if (type == kUpb_EncodedType_Group || type == kUpb_EncodedType_Message) {
+      field->mode |= pointer_rep << kUpb_FieldRep_Shift;
+    } else if (type >= sizeof(kUpb_EncodedToFieldRep)) {
+      upb_MtDecoder_ErrorFormat(d, "Invalid field type: %d", (int)type);
+      UPB_UNREACHABLE();
+    } else {
+      field->mode |= kUpb_EncodedToFieldRep[type] << kUpb_FieldRep_Shift;
+    }
+  }
+  if (type >= sizeof(kUpb_EncodedToType)) {
+    upb_MtDecoder_ErrorFormat(d, "Invalid field type: %d", (int)type);
+    UPB_UNREACHABLE();
+  }
+  upb_MiniTable_SetTypeAndSub(field, kUpb_EncodedToType[type], sub_count,
+                              msg_modifiers, type == kUpb_EncodedType_OpenEnum);
+}
+
+static void upb_MtDecoder_ModifyField(upb_MtDecoder* d,
+                                      uint32_t message_modifiers,
+                                      uint32_t field_modifiers,
+                                      upb_MiniTableField* field) {
+  if (field_modifiers & kUpb_EncodedFieldModifier_FlipPacked) {
+    if (!upb_MtDecoder_FieldIsPackable(field)) {
+      upb_MtDecoder_ErrorFormat(
+          d, "Cannot flip packed on unpackable field %" PRIu32, field->number);
+      UPB_UNREACHABLE();
+    }
+    field->mode ^= kUpb_LabelFlags_IsPacked;
+  }
+
+  bool singular = field_modifiers & kUpb_EncodedFieldModifier_IsProto3Singular;
+  bool required = field_modifiers & kUpb_EncodedFieldModifier_IsRequired;
+
+  // Validate.
+  if ((singular || required) && field->offset != kHasbitPresence) {
+    upb_MtDecoder_ErrorFormat(
+        d, "Invalid modifier(s) for repeated field %" PRIu32, field->number);
+    UPB_UNREACHABLE();
+  }
+  if (singular && required) {
+    upb_MtDecoder_ErrorFormat(
+        d, "Field %" PRIu32 " cannot be both singular and required",
+        field->number);
+    UPB_UNREACHABLE();
+  }
+
+  if (singular) field->offset = kNoPresence;
+  if (required) {
+    field->offset = kRequiredPresence;
+  }
+}
+
+static void upb_MtDecoder_PushItem(upb_MtDecoder* d, upb_LayoutItem item) {
+  if (d->vec.size == d->vec.capacity) {
+    size_t new_cap = UPB_MAX(8, d->vec.size * 2);
+    d->vec.data = realloc(d->vec.data, new_cap * sizeof(*d->vec.data));
+    upb_MtDecoder_CheckOutOfMemory(d, d->vec.data);
+    d->vec.capacity = new_cap;
+  }
+  d->vec.data[d->vec.size++] = item;
+}
+
+static void upb_MtDecoder_PushOneof(upb_MtDecoder* d, upb_LayoutItem item) {
+  if (item.field_index == kUpb_LayoutItem_IndexSentinel) {
+    upb_MtDecoder_ErrorFormat(d, "Empty oneof");
+    UPB_UNREACHABLE();
+  }
+  item.field_index -= kOneofBase;
+
+  // Push oneof data.
+  item.type = kUpb_LayoutItemType_OneofField;
+  upb_MtDecoder_PushItem(d, item);
+
+  // Push oneof case.
+  item.rep = kUpb_FieldRep_4Byte;  // Field Number.
+  item.type = kUpb_LayoutItemType_OneofCase;
+  upb_MtDecoder_PushItem(d, item);
+}
+
+size_t upb_MtDecoder_SizeOfRep(upb_FieldRep rep,
+                               upb_MiniTablePlatform platform) {
+  static const uint8_t kRepToSize32[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 8,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  static const uint8_t kRepToSize64[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 16,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  UPB_ASSERT(sizeof(upb_StringView) ==
+             UPB_SIZE(kRepToSize32, kRepToSize64)[kUpb_FieldRep_StringView]);
+  return platform == kUpb_MiniTablePlatform_32Bit ? kRepToSize32[rep]
+                                                  : kRepToSize64[rep];
+}
+
+size_t upb_MtDecoder_AlignOfRep(upb_FieldRep rep,
+                                upb_MiniTablePlatform platform) {
+  static const uint8_t kRepToAlign32[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 4,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  static const uint8_t kRepToAlign64[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 8,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  UPB_ASSERT(UPB_ALIGN_OF(upb_StringView) ==
+             UPB_SIZE(kRepToAlign32, kRepToAlign64)[kUpb_FieldRep_StringView]);
+  return platform == kUpb_MiniTablePlatform_32Bit ? kRepToAlign32[rep]
+                                                  : kRepToAlign64[rep];
+}
+
+static const char* upb_MtDecoder_DecodeOneofField(upb_MtDecoder* d,
+                                                  const char* ptr,
+                                                  char first_ch,
+                                                  upb_LayoutItem* item) {
+  uint32_t field_num;
+  ptr = upb_MiniTable_DecodeBase92Varint(
+      d, ptr, first_ch, kUpb_EncodedValue_MinOneofField,
+      kUpb_EncodedValue_MaxOneofField, &field_num);
+  upb_MiniTableField* f =
+      (void*)upb_MiniTable_FindFieldByNumber(d->table, field_num);
+
+  if (!f) {
+    upb_MtDecoder_ErrorFormat(d,
+                              "Couldn't add field number %" PRIu32
+                              " to oneof, no such field number.",
+                              field_num);
+    UPB_UNREACHABLE();
+  }
+  if (f->offset != kHasbitPresence) {
+    upb_MtDecoder_ErrorFormat(
+        d,
+        "Cannot add repeated, required, or singular field %" PRIu32
+        " to oneof.",
+        field_num);
+    UPB_UNREACHABLE();
+  }
+
+  // Oneof storage must be large enough to accommodate the largest member.
+  int rep = f->mode >> kUpb_FieldRep_Shift;
+  if (upb_MtDecoder_SizeOfRep(rep, d->platform) >
+      upb_MtDecoder_SizeOfRep(item->rep, d->platform)) {
+    item->rep = rep;
+  }
+  // Prepend this field to the linked list.
+  f->offset = item->field_index;
+  item->field_index = (f - d->fields) + kOneofBase;
+  return ptr;
+}
+
+static const char* upb_MtDecoder_DecodeOneofs(upb_MtDecoder* d,
+                                              const char* ptr) {
+  upb_LayoutItem item = {.rep = 0,
+                         .field_index = kUpb_LayoutItem_IndexSentinel};
+  while (ptr < d->end) {
+    char ch = *ptr++;
+    if (ch == kUpb_EncodedValue_FieldSeparator) {
+      // Field separator, no action needed.
+    } else if (ch == kUpb_EncodedValue_OneofSeparator) {
+      // End of oneof.
+      upb_MtDecoder_PushOneof(d, item);
+      item.field_index = kUpb_LayoutItem_IndexSentinel;  // Move to next oneof.
+    } else {
+      ptr = upb_MtDecoder_DecodeOneofField(d, ptr, ch, &item);
+    }
+  }
+
+  // Push final oneof.
+  upb_MtDecoder_PushOneof(d, item);
+  return ptr;
+}
+
+static const char* upb_MtDecoder_ParseModifier(upb_MtDecoder* d,
+                                               const char* ptr, char first_ch,
+                                               upb_MiniTableField* last_field,
+                                               uint64_t* msg_modifiers) {
+  uint32_t mod;
+  ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, first_ch,
+                                         kUpb_EncodedValue_MinModifier,
+                                         kUpb_EncodedValue_MaxModifier, &mod);
+  if (last_field) {
+    upb_MtDecoder_ModifyField(d, *msg_modifiers, mod, last_field);
+  } else {
+    if (!d->table) {
+      upb_MtDecoder_ErrorFormat(d, "Extensions cannot have message modifiers");
+      UPB_UNREACHABLE();
+    }
+    *msg_modifiers = mod;
+  }
+
+  return ptr;
+}
+
+static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, uint32_t sub_count) {
+  size_t subs_bytes = sizeof(*d->table->subs) * sub_count;
+  void* subs = upb_Arena_Malloc(d->arena, subs_bytes);
+  memset(subs, 0, subs_bytes);
+  d->table->subs = subs;
+  upb_MtDecoder_CheckOutOfMemory(d, d->table->subs);
+}
+
+static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr,
+                                       size_t len, void* fields,
+                                       size_t field_size, uint16_t* field_count,
+                                       uint32_t* sub_count) {
+  uint64_t msg_modifiers = 0;
+  uint32_t last_field_number = 0;
+  upb_MiniTableField* last_field = NULL;
+  bool need_dense_below = d->table != NULL;
+
+  d->end = UPB_PTRADD(ptr, len);
+
+  while (ptr < d->end) {
+    char ch = *ptr++;
+    if (ch <= kUpb_EncodedValue_MaxField) {
+      if (!d->table && last_field) {
+        // For extensions, consume only a single field and then return.
+        return --ptr;
+      }
+      upb_MiniTableField* field = fields;
+      *field_count += 1;
+      fields = (char*)fields + field_size;
+      field->number = ++last_field_number;
+      last_field = field;
+      upb_MiniTable_SetField(d, ch, field, msg_modifiers, sub_count);
+    } else if (kUpb_EncodedValue_MinModifier <= ch &&
+               ch <= kUpb_EncodedValue_MaxModifier) {
+      ptr = upb_MtDecoder_ParseModifier(d, ptr, ch, last_field, &msg_modifiers);
+      if (msg_modifiers & kUpb_MessageModifier_IsExtendable) {
+        d->table->ext |= kUpb_ExtMode_Extendable;
+      }
+    } else if (ch == kUpb_EncodedValue_End) {
+      if (!d->table) {
+        upb_MtDecoder_ErrorFormat(d, "Extensions cannot have oneofs.");
+        UPB_UNREACHABLE();
+      }
+      ptr = upb_MtDecoder_DecodeOneofs(d, ptr);
+    } else if (kUpb_EncodedValue_MinSkip <= ch &&
+               ch <= kUpb_EncodedValue_MaxSkip) {
+      if (need_dense_below) {
+        d->table->dense_below = d->table->field_count;
+        need_dense_below = false;
+      }
+      uint32_t skip;
+      ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, ch,
+                                             kUpb_EncodedValue_MinSkip,
+                                             kUpb_EncodedValue_MaxSkip, &skip);
+      last_field_number += skip;
+      last_field_number--;  // Next field seen will increment.
+    } else {
+      upb_MtDecoder_ErrorFormat(d, "Invalid char: %c", ch);
+      UPB_UNREACHABLE();
+    }
+  }
+
+  if (need_dense_below) {
+    d->table->dense_below = d->table->field_count;
+  }
+
+  return ptr;
+}
+
+static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data,
+                                       size_t len) {
+  // Buffer length is an upper bound on the number of fields. We will return
+  // what we don't use.
+  d->fields = upb_Arena_Malloc(d->arena, sizeof(*d->fields) * len);
+  upb_MtDecoder_CheckOutOfMemory(d, d->fields);
+
+  uint32_t sub_count = 0;
+  d->table->field_count = 0;
+  d->table->fields = d->fields;
+  upb_MtDecoder_Parse(d, data, len, d->fields, sizeof(*d->fields),
+                      &d->table->field_count, &sub_count);
+
+  upb_Arena_ShrinkLast(d->arena, d->fields, sizeof(*d->fields) * len,
+                       sizeof(*d->fields) * d->table->field_count);
+  d->table->fields = d->fields;
+  upb_MtDecoder_AllocateSubs(d, sub_count);
+}
+
+int upb_MtDecoder_CompareFields(const void* _a, const void* _b) {
+  const upb_LayoutItem* a = _a;
+  const upb_LayoutItem* b = _b;
+  // Currently we just sort by:
+  //  1. rep (smallest fields first)
+  //  2. type (oneof cases first)
+  //  2. field_index (smallest numbers first)
+  // The main goal of this is to reduce space lost to padding.
+  // Later we may have more subtle reasons to prefer a different ordering.
+  const int rep_bits = upb_Log2Ceiling(kUpb_FieldRep_Max);
+  const int type_bits = upb_Log2Ceiling(kUpb_LayoutItemType_Max);
+  const int idx_bits = (sizeof(a->field_index) * 8);
+  UPB_ASSERT(idx_bits + rep_bits + type_bits < 32);
+#define UPB_COMBINE(rep, ty, idx) (((rep << type_bits) | ty) << idx_bits) | idx
+  uint32_t a_packed = UPB_COMBINE(a->rep, a->type, a->field_index);
+  uint32_t b_packed = UPB_COMBINE(b->rep, b->type, b->field_index);
+  assert(a_packed != b_packed);
+#undef UPB_COMBINE
+  return a_packed < b_packed ? -1 : 1;
+}
+
+static bool upb_MtDecoder_SortLayoutItems(upb_MtDecoder* d) {
+  // Add items for all non-oneof fields (oneofs were already added).
+  int n = d->table->field_count;
+  for (int i = 0; i < n; i++) {
+    upb_MiniTableField* f = &d->fields[i];
+    if (f->offset >= kOneofBase) continue;
+    upb_LayoutItem item = {.field_index = i,
+                           .rep = f->mode >> kUpb_FieldRep_Shift,
+                           .type = kUpb_LayoutItemType_Field};
+    upb_MtDecoder_PushItem(d, item);
+  }
+
+  if (d->vec.size) {
+    qsort(d->vec.data, d->vec.size, sizeof(*d->vec.data),
+          upb_MtDecoder_CompareFields);
+  }
+
+  return true;
+}
+
+static size_t upb_MiniTable_DivideRoundUp(size_t n, size_t d) {
+  return (n + d - 1) / d;
+}
+
+static void upb_MtDecoder_AssignHasbits(upb_MiniTable* ret) {
+  int n = ret->field_count;
+  int last_hasbit = 0;  // 0 cannot be used.
+
+  // First assign required fields, which must have the lowest hasbits.
+  for (int i = 0; i < n; i++) {
+    upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i];
+    if (field->offset == kRequiredPresence) {
+      field->presence = ++last_hasbit;
+    } else if (field->offset == kNoPresence) {
+      field->presence = 0;
+    }
+  }
+  ret->required_count = last_hasbit;
+
+  // Next assign non-required hasbit fields.
+  for (int i = 0; i < n; i++) {
+    upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i];
+    if (field->offset == kHasbitPresence) {
+      field->presence = ++last_hasbit;
+    }
+  }
+
+  ret->size = last_hasbit ? upb_MiniTable_DivideRoundUp(last_hasbit + 1, 8) : 0;
+}
+
+size_t upb_MtDecoder_Place(upb_MtDecoder* d, upb_FieldRep rep) {
+  size_t size = upb_MtDecoder_SizeOfRep(rep, d->platform);
+  size_t align = upb_MtDecoder_AlignOfRep(rep, d->platform);
+  size_t ret = UPB_ALIGN_UP(d->table->size, align);
+  static const size_t max = UINT16_MAX;
+  size_t new_size = ret + size;
+  if (new_size > max) {
+    upb_MtDecoder_ErrorFormat(
+        d, "Message size exceeded maximum size of %zu bytes", max);
+  }
+  d->table->size = new_size;
+  return ret;
+}
+
+static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) {
+  upb_LayoutItem* end = UPB_PTRADD(d->vec.data, d->vec.size);
+
+  // Compute offsets.
+  for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+    item->offset = upb_MtDecoder_Place(d, item->rep);
+  }
+
+  // Assign oneof case offsets.  We must do these first, since assigning
+  // actual offsets will overwrite the links of the linked list.
+  for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+    if (item->type != kUpb_LayoutItemType_OneofCase) continue;
+    upb_MiniTableField* f = &d->fields[item->field_index];
+    while (true) {
+      f->presence = ~item->offset;
+      if (f->offset == kUpb_LayoutItem_IndexSentinel) break;
+      UPB_ASSERT(f->offset - kOneofBase < d->table->field_count);
+      f = &d->fields[f->offset - kOneofBase];
+    }
+  }
+
+  // Assign offsets.
+  for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+    upb_MiniTableField* f = &d->fields[item->field_index];
+    switch (item->type) {
+      case kUpb_LayoutItemType_OneofField:
+        while (true) {
+          uint16_t next_offset = f->offset;
+          f->offset = item->offset;
+          if (next_offset == kUpb_LayoutItem_IndexSentinel) break;
+          f = &d->fields[next_offset - kOneofBase];
+        }
+        break;
+      case kUpb_LayoutItemType_Field:
+        f->offset = item->offset;
+        break;
+      default:
+        break;
+    }
+  }
+
+  // The fasttable parser (supported on 64-bit only) depends on this being a
+  // multiple of 8 in order to satisfy UPB_MALLOC_ALIGN, which is also 8.
+  //
+  // On 32-bit we could potentially make this smaller, but there is no
+  // compelling reason to optimize this right now.
+  d->table->size = UPB_ALIGN_UP(d->table->size, 8);
+}
+
+static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data,
+                                   size_t len) {
+  if (len < 2) {
+    upb_MtDecoder_ErrorFormat(d, "Invalid map encode length: %zu", len);
+    UPB_UNREACHABLE();
+  }
+  const upb_EncodedType key_type = _upb_FromBase92(data[0]);
+  switch (key_type) {
+    case kUpb_EncodedType_Fixed32:
+    case kUpb_EncodedType_Fixed64:
+    case kUpb_EncodedType_SFixed32:
+    case kUpb_EncodedType_SFixed64:
+    case kUpb_EncodedType_Int32:
+    case kUpb_EncodedType_UInt32:
+    case kUpb_EncodedType_SInt32:
+    case kUpb_EncodedType_Int64:
+    case kUpb_EncodedType_UInt64:
+    case kUpb_EncodedType_SInt64:
+    case kUpb_EncodedType_Bool:
+    case kUpb_EncodedType_String:
+      break;
+
+    default:
+      upb_MtDecoder_ErrorFormat(d, "Invalid map key field type: %d", key_type);
+      UPB_UNREACHABLE();
+  }
+
+  upb_MtDecoder_ParseMessage(d, data, len);
+  upb_MtDecoder_AssignHasbits(d->table);
+
+  // Map entries have a pre-determined layout, regardless of types.
+  // NOTE: sync with mini_table/message_internal.h.
+  const size_t kv_size = d->platform == kUpb_MiniTablePlatform_32Bit ? 8 : 16;
+  const size_t hasbit_size = 8;
+  d->fields[0].offset = hasbit_size;
+  d->fields[1].offset = hasbit_size + kv_size;
+  d->table->size = UPB_ALIGN_UP(hasbit_size + kv_size + kv_size, 8);
+
+  // Map entries have a special bit set to signal it's a map entry, used in
+  // upb_MiniTable_SetSubMessage() below.
+  d->table->ext |= kUpb_ExtMode_IsMapEntry;
+}
+
+static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data,
+                                          size_t len) {
+  if (len > 0) {
+    upb_MtDecoder_ErrorFormat(d, "Invalid message set encode length: %zu", len);
+    UPB_UNREACHABLE();
+  }
+
+  upb_MiniTable* ret = d->table;
+  ret->size = 0;
+  ret->field_count = 0;
+  ret->ext = kUpb_ExtMode_IsMessageSet;
+  ret->dense_below = 0;
+  ret->table_mask = -1;
+  ret->required_count = 0;
+}
+
+upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Arena* arena, void** buf,
+                                          size_t* buf_size,
+                                          upb_Status* status) {
+  upb_MtDecoder decoder = {
+      .platform = platform,
+      .vec =
+          {
+              .data = *buf,
+              .capacity = *buf_size / sizeof(*decoder.vec.data),
+              .size = 0,
+          },
+      .arena = arena,
+      .status = status,
+      .table = upb_Arena_Malloc(arena, sizeof(*decoder.table)),
+  };
+
+  if (UPB_SETJMP(decoder.err)) {
+    decoder.table = NULL;
+    goto done;
+  }
+
+  upb_MtDecoder_CheckOutOfMemory(&decoder, decoder.table);
+
+  decoder.table->size = 0;
+  decoder.table->field_count = 0;
+  decoder.table->ext = kUpb_ExtMode_NonExtendable;
+  decoder.table->dense_below = 0;
+  decoder.table->table_mask = -1;
+  decoder.table->required_count = 0;
+
+  // Strip off and verify the version tag.
+  if (!len--) goto done;
+  const char vers = *data++;
+
+  switch (vers) {
+    case kUpb_EncodedVersion_MapV1:
+      upb_MtDecoder_ParseMap(&decoder, data, len);
+      break;
+
+    case kUpb_EncodedVersion_MessageV1:
+      upb_MtDecoder_ParseMessage(&decoder, data, len);
+      upb_MtDecoder_AssignHasbits(decoder.table);
+      upb_MtDecoder_SortLayoutItems(&decoder);
+      upb_MtDecoder_AssignOffsets(&decoder);
+      break;
+
+    case kUpb_EncodedVersion_MessageSetV1:
+      upb_MtDecoder_ParseMessageSet(&decoder, data, len);
+      break;
+
+    default:
+      upb_MtDecoder_ErrorFormat(&decoder, "Invalid message version: %c", vers);
+      UPB_UNREACHABLE();
+  }
+
+done:
+  *buf = decoder.vec.data;
+  *buf_size = decoder.vec.capacity * sizeof(*decoder.vec.data);
+  return decoder.table;
+}
+
+static size_t upb_MiniTableEnum_Size(size_t count) {
+  return sizeof(upb_MiniTableEnum) + count * sizeof(uint32_t);
+}
+
+static upb_MiniTableEnum* _upb_MiniTable_AddEnumDataMember(upb_MtDecoder* d,
+                                                           uint32_t val) {
+  if (d->enum_data_count == d->enum_data_capacity) {
+    size_t old_sz = upb_MiniTableEnum_Size(d->enum_data_capacity);
+    d->enum_data_capacity = UPB_MAX(2, d->enum_data_capacity * 2);
+    size_t new_sz = upb_MiniTableEnum_Size(d->enum_data_capacity);
+    d->enum_table = upb_Arena_Realloc(d->arena, d->enum_table, old_sz, new_sz);
+    upb_MtDecoder_CheckOutOfMemory(d, d->enum_table);
+  }
+  d->enum_table->data[d->enum_data_count++] = val;
+  return d->enum_table;
+}
+
+static void upb_MiniTableEnum_BuildValue(upb_MtDecoder* d, uint32_t val) {
+  upb_MiniTableEnum* table = d->enum_table;
+  d->enum_value_count++;
+  if (table->value_count || (val > 512 && d->enum_value_count < val / 32)) {
+    if (table->value_count == 0) {
+      assert(d->enum_data_count == table->mask_limit / 32);
+    }
+    table = _upb_MiniTable_AddEnumDataMember(d, val);
+    table->value_count++;
+  } else {
+    uint32_t new_mask_limit = ((val / 32) + 1) * 32;
+    while (table->mask_limit < new_mask_limit) {
+      table = _upb_MiniTable_AddEnumDataMember(d, 0);
+      table->mask_limit += 32;
+    }
+    table->data[val / 32] |= 1ULL << (val % 32);
+  }
+}
+
+upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len,
+                                           upb_Arena* arena,
+                                           upb_Status* status) {
+  upb_MtDecoder decoder = {
+      .enum_table = upb_Arena_Malloc(arena, upb_MiniTableEnum_Size(2)),
+      .enum_value_count = 0,
+      .enum_data_count = 0,
+      .enum_data_capacity = 1,
+      .status = status,
+      .end = UPB_PTRADD(data, len),
+      .arena = arena,
+  };
+
+  if (UPB_SETJMP(decoder.err)) return NULL;
+
+  // If the string is non-empty then it must begin with a version tag.
+  if (len) {
+    if (*data != kUpb_EncodedVersion_EnumV1) {
+      upb_MtDecoder_ErrorFormat(&decoder, "Invalid enum version: %c", *data);
+      UPB_UNREACHABLE();
+    }
+    data++;
+    len--;
+  }
+
+  upb_MtDecoder_CheckOutOfMemory(&decoder, decoder.enum_table);
+
+  // Guarantee at least 64 bits of mask without checking mask size.
+  decoder.enum_table->mask_limit = 64;
+  decoder.enum_table = _upb_MiniTable_AddEnumDataMember(&decoder, 0);
+  decoder.enum_table = _upb_MiniTable_AddEnumDataMember(&decoder, 0);
+
+  decoder.enum_table->value_count = 0;
+
+  const char* ptr = data;
+  uint32_t base = 0;
+
+  while (ptr < decoder.end) {
+    char ch = *ptr++;
+    if (ch <= kUpb_EncodedValue_MaxEnumMask) {
+      uint32_t mask = _upb_FromBase92(ch);
+      for (int i = 0; i < 5; i++, base++, mask >>= 1) {
+        if (mask & 1) upb_MiniTableEnum_BuildValue(&decoder, base);
+      }
+    } else if (kUpb_EncodedValue_MinSkip <= ch &&
+               ch <= kUpb_EncodedValue_MaxSkip) {
+      uint32_t skip;
+      ptr = upb_MiniTable_DecodeBase92Varint(&decoder, ptr, ch,
+                                             kUpb_EncodedValue_MinSkip,
+                                             kUpb_EncodedValue_MaxSkip, &skip);
+      base += skip;
+    } else {
+      upb_MtDecoder_ErrorFormat(&decoder, "Unexpected character: %c", ch);
+      return NULL;
+    }
+  }
+
+  return decoder.enum_table;
+}
+
+const char* _upb_MiniTableExtension_Build(const char* data, size_t len,
+                                          upb_MiniTableExtension* ext,
+                                          const upb_MiniTable* extendee,
+                                          upb_MiniTableSub sub,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Status* status) {
+  upb_MtDecoder decoder = {
+      .arena = NULL,
+      .status = status,
+      .table = NULL,
+      .platform = platform,
+  };
+
+  if (UPB_SETJMP(decoder.err)) return NULL;
+
+  // If the string is non-empty then it must begin with a version tag.
+  if (len) {
+    if (*data != kUpb_EncodedVersion_ExtensionV1) {
+      upb_MtDecoder_ErrorFormat(&decoder, "Invalid ext version: %c", *data);
+      UPB_UNREACHABLE();
+    }
+    data++;
+    len--;
+  }
+
+  uint16_t count = 0;
+  const char* ret =
+      upb_MtDecoder_Parse(&decoder, data, len, ext, sizeof(*ext), &count, NULL);
+  if (!ret || count != 1) return NULL;
+
+  upb_MiniTableField* f = &ext->field;
+
+  f->mode |= kUpb_LabelFlags_IsExtension;
+  f->offset = 0;
+  f->presence = 0;
+
+  if (extendee->ext & kUpb_ExtMode_IsMessageSet) {
+    // Extensions of MessageSet must be messages.
+    if (!upb_IsSubMessage(f)) return NULL;
+
+    // Extensions of MessageSet must be non-repeating.
+    if ((f->mode & kUpb_FieldMode_Mask) == kUpb_FieldMode_Array) return NULL;
+  }
+
+  ext->extendee = extendee;
+  ext->sub = sub;
+
+  return ret;
+}
+
+upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len,
+                                    upb_MiniTablePlatform platform,
+                                    upb_Arena* arena, upb_Status* status) {
+  void* buf = NULL;
+  size_t size = 0;
+  upb_MiniTable* ret = upb_MiniTable_BuildWithBuf(data, len, platform, arena,
+                                                  &buf, &size, status);
+  free(buf);
+  return ret;
+}
+
+void upb_MiniTable_SetSubMessage(upb_MiniTable* table,
+                                 upb_MiniTableField* field,
+                                 const upb_MiniTable* sub) {
+  UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
+             (uintptr_t)field <
+                 (uintptr_t)(table->fields + table->field_count));
+  if (sub->ext & kUpb_ExtMode_IsMapEntry) {
+    field->mode = (field->mode & ~kUpb_FieldMode_Mask) | kUpb_FieldMode_Map;
+  }
+  upb_MiniTableSub* table_sub = (void*)&table->subs[field->submsg_index];
+  table_sub->submsg = sub;
+}
+
+void upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTableField* field,
+                              const upb_MiniTableEnum* sub) {
+  UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
+             (uintptr_t)field <
+                 (uintptr_t)(table->fields + table->field_count));
+  upb_MiniTableSub* table_sub = (void*)&table->subs[field->submsg_index];
+  table_sub->subenum = sub;
+}
+
+#include <inttypes.h>
+
+
+// Must be last.
+
+typedef struct {
+  uint64_t present_values_mask;
+  uint32_t last_written_value;
+} upb_MtDataEncoderInternal_EnumState;
+
+typedef struct {
+  uint64_t msg_modifiers;
+  uint32_t last_field_num;
+  enum {
+    kUpb_OneofState_NotStarted,
+    kUpb_OneofState_StartedOneof,
+    kUpb_OneofState_EmittedOneofField,
+  } oneof_state;
+} upb_MtDataEncoderInternal_MsgState;
+
+typedef struct {
+  char* buf_start;  // Only for checking kUpb_MtDataEncoder_MinSize.
+  union {
+    upb_MtDataEncoderInternal_EnumState enum_state;
+    upb_MtDataEncoderInternal_MsgState msg_state;
+  } state;
+} upb_MtDataEncoderInternal;
+
+static upb_MtDataEncoderInternal* upb_MtDataEncoder_GetInternal(
+    upb_MtDataEncoder* e, char* buf_start) {
+  UPB_ASSERT(sizeof(upb_MtDataEncoderInternal) <= sizeof(e->internal));
+  upb_MtDataEncoderInternal* ret = (upb_MtDataEncoderInternal*)e->internal;
+  ret->buf_start = buf_start;
+  return ret;
+}
+
+static char* upb_MtDataEncoder_PutRaw(upb_MtDataEncoder* e, char* ptr,
+                                      char ch) {
+  upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal;
+  UPB_ASSERT(ptr - in->buf_start < kUpb_MtDataEncoder_MinSize);
+  if (ptr == e->end) return NULL;
+  *ptr++ = ch;
+  return ptr;
+}
+
+static char* upb_MtDataEncoder_Put(upb_MtDataEncoder* e, char* ptr, char ch) {
+  return upb_MtDataEncoder_PutRaw(e, ptr, _upb_ToBase92(ch));
+}
+
+static char* upb_MtDataEncoder_PutBase92Varint(upb_MtDataEncoder* e, char* ptr,
+                                               uint32_t val, int min, int max) {
+  int shift = upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min) + 1);
+  UPB_ASSERT(shift <= 6);
+  uint32_t mask = (1 << shift) - 1;
+  do {
+    uint32_t bits = val & mask;
+    ptr = upb_MtDataEncoder_Put(e, ptr, bits + _upb_FromBase92(min));
+    if (!ptr) return NULL;
+    val >>= shift;
+  } while (val);
+  return ptr;
+}
+
+char* upb_MtDataEncoder_PutModifier(upb_MtDataEncoder* e, char* ptr,
+                                    uint64_t mod) {
+  if (mod) {
+    ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, mod,
+                                            kUpb_EncodedValue_MinModifier,
+                                            kUpb_EncodedValue_MaxModifier);
+  }
+  return ptr;
+}
+
+char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr,
+                                        upb_FieldType type, uint32_t field_num,
+                                        uint64_t field_mod) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.msg_state.msg_modifiers = 0;
+  in->state.msg_state.last_field_num = 0;
+  in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted;
+
+  ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_ExtensionV1);
+  if (!ptr) return NULL;
+
+  return upb_MtDataEncoder_PutField(e, ptr, type, field_num, field_mod);
+}
+
+char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr,
+                                  upb_FieldType key_type,
+                                  upb_FieldType value_type, uint64_t key_mod,
+                                  uint64_t value_mod) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.msg_state.msg_modifiers = 0;
+  in->state.msg_state.last_field_num = 0;
+  in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted;
+
+  ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MapV1);
+  if (!ptr) return NULL;
+
+  ptr = upb_MtDataEncoder_PutField(e, ptr, key_type, 1, key_mod);
+  if (!ptr) return NULL;
+
+  return upb_MtDataEncoder_PutField(e, ptr, value_type, 2, value_mod);
+}
+
+char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr) {
+  (void)upb_MtDataEncoder_GetInternal(e, ptr);
+  return upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MessageSetV1);
+}
+
+char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr,
+                                     uint64_t msg_mod) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.msg_state.msg_modifiers = msg_mod;
+  in->state.msg_state.last_field_num = 0;
+  in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted;
+
+  ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MessageV1);
+  if (!ptr) return NULL;
+
+  return upb_MtDataEncoder_PutModifier(e, ptr, msg_mod);
+}
+
+char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr,
+                                 upb_FieldType type, uint32_t field_num,
+                                 uint64_t field_mod) {
+  static const char kUpb_TypeToEncoded[] = {
+      [kUpb_FieldType_Double] = kUpb_EncodedType_Double,
+      [kUpb_FieldType_Float] = kUpb_EncodedType_Float,
+      [kUpb_FieldType_Int64] = kUpb_EncodedType_Int64,
+      [kUpb_FieldType_UInt64] = kUpb_EncodedType_UInt64,
+      [kUpb_FieldType_Int32] = kUpb_EncodedType_Int32,
+      [kUpb_FieldType_Fixed64] = kUpb_EncodedType_Fixed64,
+      [kUpb_FieldType_Fixed32] = kUpb_EncodedType_Fixed32,
+      [kUpb_FieldType_Bool] = kUpb_EncodedType_Bool,
+      [kUpb_FieldType_String] = kUpb_EncodedType_String,
+      [kUpb_FieldType_Group] = kUpb_EncodedType_Group,
+      [kUpb_FieldType_Message] = kUpb_EncodedType_Message,
+      [kUpb_FieldType_Bytes] = kUpb_EncodedType_Bytes,
+      [kUpb_FieldType_UInt32] = kUpb_EncodedType_UInt32,
+      [kUpb_FieldType_Enum] = kUpb_EncodedType_OpenEnum,
+      [kUpb_FieldType_SFixed32] = kUpb_EncodedType_SFixed32,
+      [kUpb_FieldType_SFixed64] = kUpb_EncodedType_SFixed64,
+      [kUpb_FieldType_SInt32] = kUpb_EncodedType_SInt32,
+      [kUpb_FieldType_SInt64] = kUpb_EncodedType_SInt64,
+  };
+
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (field_num <= in->state.msg_state.last_field_num) return NULL;
+  if (in->state.msg_state.last_field_num + 1 != field_num) {
+    // Put skip.
+    UPB_ASSERT(field_num > in->state.msg_state.last_field_num);
+    uint32_t skip = field_num - in->state.msg_state.last_field_num;
+    ptr = upb_MtDataEncoder_PutBase92Varint(
+        e, ptr, skip, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip);
+    if (!ptr) return NULL;
+  }
+  in->state.msg_state.last_field_num = field_num;
+
+  uint32_t encoded_modifiers = 0;
+
+  // Put field type.
+  int encoded_type = kUpb_TypeToEncoded[type];
+  if (field_mod & kUpb_FieldModifier_IsClosedEnum) {
+    UPB_ASSERT(type == kUpb_FieldType_Enum);
+    encoded_type = kUpb_EncodedType_ClosedEnum;
+  }
+  if (field_mod & kUpb_FieldModifier_IsRepeated) {
+    // Repeated fields shift the type number up (unlike other modifiers which
+    // are bit flags).
+    encoded_type += kUpb_EncodedType_RepeatedBase;
+
+    if (_upb_FieldType_IsPackable(type)) {
+      bool field_is_packed = field_mod & kUpb_FieldModifier_IsPacked;
+      bool default_is_packed = in->state.msg_state.msg_modifiers &
+                               kUpb_MessageModifier_DefaultIsPacked;
+      if (field_is_packed != default_is_packed) {
+        encoded_modifiers |= kUpb_EncodedFieldModifier_FlipPacked;
+      }
+    }
+  }
+  ptr = upb_MtDataEncoder_Put(e, ptr, encoded_type);
+  if (!ptr) return NULL;
+
+  if (field_mod & kUpb_FieldModifier_IsProto3Singular) {
+    encoded_modifiers |= kUpb_EncodedFieldModifier_IsProto3Singular;
+  }
+  if (field_mod & kUpb_FieldModifier_IsRequired) {
+    encoded_modifiers |= kUpb_EncodedFieldModifier_IsRequired;
+  }
+  return upb_MtDataEncoder_PutModifier(e, ptr, encoded_modifiers);
+}
+
+char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (in->state.msg_state.oneof_state == kUpb_OneofState_NotStarted) {
+    ptr = upb_MtDataEncoder_Put(e, ptr, _upb_FromBase92(kUpb_EncodedValue_End));
+  } else {
+    ptr = upb_MtDataEncoder_Put(
+        e, ptr, _upb_FromBase92(kUpb_EncodedValue_OneofSeparator));
+  }
+  in->state.msg_state.oneof_state = kUpb_OneofState_StartedOneof;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr,
+                                      uint32_t field_num) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (in->state.msg_state.oneof_state == kUpb_OneofState_EmittedOneofField) {
+    ptr = upb_MtDataEncoder_Put(
+        e, ptr, _upb_FromBase92(kUpb_EncodedValue_FieldSeparator));
+    if (!ptr) return NULL;
+  }
+  ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, field_num, _upb_ToBase92(0),
+                                          _upb_ToBase92(63));
+  in->state.msg_state.oneof_state = kUpb_OneofState_EmittedOneofField;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e, char* ptr) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.enum_state.present_values_mask = 0;
+  in->state.enum_state.last_written_value = 0;
+
+  return upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_EnumV1);
+}
+
+static char* upb_MtDataEncoder_FlushDenseEnumMask(upb_MtDataEncoder* e,
+                                                  char* ptr) {
+  upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal;
+  ptr = upb_MtDataEncoder_Put(e, ptr, in->state.enum_state.present_values_mask);
+  in->state.enum_state.present_values_mask = 0;
+  in->state.enum_state.last_written_value += 5;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr,
+                                     uint32_t val) {
+  // TODO(b/229641772): optimize this encoding.
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  UPB_ASSERT(val >= in->state.enum_state.last_written_value);
+  uint32_t delta = val - in->state.enum_state.last_written_value;
+  if (delta >= 5 && in->state.enum_state.present_values_mask) {
+    ptr = upb_MtDataEncoder_FlushDenseEnumMask(e, ptr);
+    if (!ptr) {
+      return NULL;
+    }
+    delta -= 5;
+  }
+
+  if (delta >= 5) {
+    ptr = upb_MtDataEncoder_PutBase92Varint(
+        e, ptr, delta, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip);
+    in->state.enum_state.last_written_value += delta;
+    delta = 0;
+  }
+
+  UPB_ASSERT((in->state.enum_state.present_values_mask >> delta) == 0);
+  in->state.enum_state.present_values_mask |= 1ULL << delta;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (!in->state.enum_state.present_values_mask) return ptr;
+  return upb_MtDataEncoder_FlushDenseEnumMask(e, ptr);
+}
+
+
+
+// Must be last.
+
+#define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
+
+struct upb_ExtensionRegistry {
+  upb_Arena* arena;
+  upb_strtable exts;  // Key is upb_MiniTable* concatenated with fieldnum.
+};
+
+static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
+  memcpy(buf, &l, sizeof(l));
+  memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
+}
+
+upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
+  upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
+  if (!r) return NULL;
+  r->arena = arena;
+  if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
+  return r;
+}
+
+bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r,
+                                    const upb_MiniTableExtension** e,
+                                    size_t count) {
+  char buf[EXTREG_KEY_SIZE];
+  const upb_MiniTableExtension** start = e;
+  const upb_MiniTableExtension** end = UPB_PTRADD(e, count);
+  for (; e < end; e++) {
+    const upb_MiniTableExtension* ext = *e;
+    extreg_key(buf, ext->extendee, ext->field.number);
+    upb_value v;
+    if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
+      goto failure;
+    }
+    if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
+                             upb_value_constptr(ext), r->arena)) {
+      goto failure;
+    }
+  }
+  return true;
+
+failure:
+  // Back out the entries previously added.
+  for (end = e, e = start; e < end; e++) {
+    const upb_MiniTableExtension* ext = *e;
+    extreg_key(buf, ext->extendee, ext->field.number);
+    upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
+  }
+  return false;
+}
+
+const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup(
+    const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num) {
+  char buf[EXTREG_KEY_SIZE];
+  upb_value v;
+  extreg_key(buf, t, num);
+  if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
+    return upb_value_getconstptr(v);
+  } else {
+    return NULL;
+  }
+}
+
+#include <string.h>
+
+
+// Must be last.
+
+/* The upb core does not generally have a concept of default instances. However
+ * for descriptor options we make an exception since the max size is known and
+ * modest (<200 bytes). All types can share a default instance since it is
+ * initialized to zeroes.
+ *
+ * We have to allocate an extra pointer for upb's internal metadata. */
+static const char opt_default_buf[_UPB_MAXOPT_SIZE + sizeof(void*)] = {0};
+const char* kUpbDefOptDefault = &opt_default_buf[sizeof(void*)];
+
+const char* _upb_DefBuilder_FullToShort(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;
+  }
+}
+
+void _upb_DefBuilder_FailJmp(upb_DefBuilder* ctx) { UPB_LONGJMP(ctx->err, 1); }
+
+void _upb_DefBuilder_Errf(upb_DefBuilder* ctx, const char* fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_Status_VSetErrorFormat(ctx->status, fmt, argp);
+  va_end(argp);
+  _upb_DefBuilder_FailJmp(ctx);
+}
+
+void _upb_DefBuilder_OomErr(upb_DefBuilder* ctx) {
+  upb_Status_SetErrorMessage(ctx->status, "out of memory");
+  _upb_DefBuilder_FailJmp(ctx);
+}
+
+const char* _upb_DefBuilder_MakeFullName(upb_DefBuilder* ctx,
+                                         const char* prefix,
+                                         upb_StringView name) {
+  if (prefix) {
+    // ret = prefix + '.' + name;
+    size_t n = strlen(prefix);
+    char* ret = _upb_DefBuilder_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 {
+    char* ret = upb_strdup2(name.data, name.size, ctx->arena);
+    if (!ret) _upb_DefBuilder_OomErr(ctx);
+    return ret;
+  }
+}
+
+static bool remove_component(char* base, size_t* len) {
+  if (*len == 0) return false;
+
+  for (size_t i = *len - 1; i > 0; i--) {
+    if (base[i] == '.') {
+      *len = i;
+      return true;
+    }
+  }
+
+  *len = 0;
+  return true;
+}
+
+const void* _upb_DefBuilder_ResolveAny(upb_DefBuilder* ctx,
+                                       const char* from_name_dbg,
+                                       const char* base, upb_StringView sym,
+                                       upb_deftype_t* type) {
+  if (sym.size == 0) goto notfound;
+  upb_value v;
+  if (sym.data[0] == '.') {
+    /* Symbols starting with '.' are absolute, so we do a single lookup.
+     * Slice to omit the leading '.' */
+    if (!_upb_DefPool_LookupSym(ctx->symtab, sym.data + 1, sym.size - 1, &v)) {
+      goto notfound;
+    }
+  } else {
+    /* Remove components from base until we find an entry or run out. */
+    size_t baselen = base ? strlen(base) : 0;
+    char* tmp = malloc(sym.size + baselen + 1);
+    while (1) {
+      char* p = tmp;
+      if (baselen) {
+        memcpy(p, base, baselen);
+        p[baselen] = '.';
+        p += baselen + 1;
+      }
+      memcpy(p, sym.data, sym.size);
+      p += sym.size;
+      if (_upb_DefPool_LookupSym(ctx->symtab, tmp, p - tmp, &v)) {
+        break;
+      }
+      if (!remove_component(tmp, &baselen)) {
+        free(tmp);
+        goto notfound;
+      }
+    }
+    free(tmp);
+  }
+
+  *type = _upb_DefType_Type(v);
+  return _upb_DefType_Unpack(v, *type);
+
+notfound:
+  _upb_DefBuilder_Errf(ctx, "couldn't resolve name '" UPB_STRINGVIEW_FORMAT "'",
+                       UPB_STRINGVIEW_ARGS(sym));
+}
+
+const void* _upb_DefBuilder_Resolve(upb_DefBuilder* ctx,
+                                    const char* from_name_dbg, const char* base,
+                                    upb_StringView sym, upb_deftype_t type) {
+  upb_deftype_t found_type;
+  const void* ret =
+      _upb_DefBuilder_ResolveAny(ctx, from_name_dbg, base, sym, &found_type);
+  if (ret && found_type != type) {
+    _upb_DefBuilder_Errf(ctx,
+                         "type mismatch when resolving %s: couldn't find "
+                         "name " UPB_STRINGVIEW_FORMAT " with type=%d",
+                         from_name_dbg, UPB_STRINGVIEW_ARGS(sym), (int)type);
+  }
+  return ret;
+}
+
+// Per ASCII this will lower-case a letter. If the result is a letter, the
+// input was definitely a letter. If the output is not a letter, this may
+// have transformed the character unpredictably.
+static char upb_ascii_lower(char ch) { return ch | 0x20; }
+
+// isalpha() etc. from <ctype.h> are locale-dependent, which we don't want.
+static bool upb_isbetween(uint8_t c, uint8_t low, uint8_t high) {
+  return low <= c && c <= high;
+}
+
+static bool upb_isletter(char c) {
+  char lower = upb_ascii_lower(c);
+  return upb_isbetween(lower, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+  return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static bool TryGetChar(const char** src, const char* end, char* ch) {
+  if (*src == end) return false;
+  *ch = **src;
+  *src += 1;
+  return true;
+}
+
+static char TryGetHexDigit(const char** src, const char* end) {
+  char ch;
+  if (!TryGetChar(src, end, &ch)) return -1;
+  if ('0' <= ch && ch <= '9') {
+    return ch - '0';
+  }
+  ch = upb_ascii_lower(ch);
+  if ('a' <= ch && ch <= 'f') {
+    return ch - 'a' + 0xa;
+  }
+  *src -= 1;  // Char wasn't actually a hex digit.
+  return -1;
+}
+
+static char upb_DefBuilder_ParseHexEscape(upb_DefBuilder* ctx,
+                                          const upb_FieldDef* f,
+                                          const char** src, const char* end) {
+  char hex_digit = TryGetHexDigit(src, end);
+  if (hex_digit < 0) {
+    _upb_DefBuilder_Errf(
+        ctx, "\\x cannot be followed by non-hex digit in field '%s' default",
+        upb_FieldDef_FullName(f));
+    return 0;
+  }
+  unsigned int ret = hex_digit;
+  while ((hex_digit = TryGetHexDigit(src, end)) >= 0) {
+    ret = (ret << 4) | hex_digit;
+  }
+  if (ret > 0xff) {
+    _upb_DefBuilder_Errf(ctx, "Value of hex escape in field %s exceeds 8 bits",
+                         upb_FieldDef_FullName(f));
+    return 0;
+  }
+  return ret;
+}
+
+static char TryGetOctalDigit(const char** src, const char* end) {
+  char ch;
+  if (!TryGetChar(src, end, &ch)) return -1;
+  if ('0' <= ch && ch <= '7') {
+    return ch - '0';
+  }
+  *src -= 1;  // Char wasn't actually an octal digit.
+  return -1;
+}
+
+static char upb_DefBuilder_ParseOctalEscape(upb_DefBuilder* ctx,
+                                            const upb_FieldDef* f,
+                                            const char** src, const char* end) {
+  char ch = 0;
+  for (int i = 0; i < 3; i++) {
+    char digit;
+    if ((digit = TryGetOctalDigit(src, end)) >= 0) {
+      ch = (ch << 3) | digit;
+    }
+  }
+  return ch;
+}
+
+char _upb_DefBuilder_ParseEscape(upb_DefBuilder* ctx, const upb_FieldDef* f,
+                                 const char** src, const char* end) {
+  char ch;
+  if (!TryGetChar(src, end, &ch)) {
+    _upb_DefBuilder_Errf(ctx, "unterminated escape sequence in field %s",
+                         upb_FieldDef_FullName(f));
+    return 0;
+  }
+  switch (ch) {
+    case 'a':
+      return '\a';
+    case 'b':
+      return '\b';
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    case 'v':
+      return '\v';
+    case '\\':
+      return '\\';
+    case '\'':
+      return '\'';
+    case '\"':
+      return '\"';
+    case '?':
+      return '\?';
+    case 'x':
+    case 'X':
+      return upb_DefBuilder_ParseHexEscape(ctx, f, src, end);
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+      *src -= 1;
+      return upb_DefBuilder_ParseOctalEscape(ctx, f, src, end);
+  }
+  _upb_DefBuilder_Errf(ctx, "Unknown escape sequence: \\%c", ch);
+}
+
+void _upb_DefBuilder_CheckIdentSlow(upb_DefBuilder* ctx, upb_StringView name,
+                                    bool full) {
+  const char* str = name.data;
+  const size_t len = name.size;
+  bool start = true;
+  for (size_t i = 0; i < len; i++) {
+    const char c = str[i];
+    if (c == '.') {
+      if (start || !full) {
+        _upb_DefBuilder_Errf(
+            ctx, "invalid name: unexpected '.' (" UPB_STRINGVIEW_FORMAT ")",
+            UPB_STRINGVIEW_ARGS(name));
+      }
+      start = true;
+    } else if (start) {
+      if (!upb_isletter(c)) {
+        _upb_DefBuilder_Errf(ctx,
+                             "invalid name: path components must start with a "
+                             "letter (" UPB_STRINGVIEW_FORMAT ")",
+                             UPB_STRINGVIEW_ARGS(name));
+      }
+      start = false;
+    } else if (!upb_isalphanum(c)) {
+      _upb_DefBuilder_Errf(
+          ctx,
+          "invalid name: non-alphanumeric character (" UPB_STRINGVIEW_FORMAT
+          ")",
+          UPB_STRINGVIEW_ARGS(name));
+    }
+  }
+  if (start) {
+    _upb_DefBuilder_Errf(ctx,
+                         "invalid name: empty part (" UPB_STRINGVIEW_FORMAT ")",
+                         UPB_STRINGVIEW_ARGS(name));
+  }
+
+  // We should never reach this point.
+  UPB_ASSERT(false);
+}
+
+
+// Must be last.
+
+struct upb_DefPool {
+  upb_Arena* arena;
+  upb_strtable syms;   // full_name -> packed def ptr
+  upb_strtable files;  // file_name -> (upb_FileDef*)
+  upb_inttable exts;   // (upb_MiniTableExtension*) -> (upb_FieldDef*)
+  upb_ExtensionRegistry* extreg;
+  void* scratch_data;
+  size_t scratch_size;
+  size_t bytes_loaded;
+};
+
+void upb_DefPool_Free(upb_DefPool* s) {
+  upb_Arena_Free(s->arena);
+  upb_gfree(s->scratch_data);
+  upb_gfree(s);
+}
+
+upb_DefPool* upb_DefPool_New(void) {
+  upb_DefPool* s = upb_gmalloc(sizeof(*s));
+  if (!s) return NULL;
+
+  s->arena = upb_Arena_New();
+  s->bytes_loaded = 0;
+
+  s->scratch_size = 240;
+  s->scratch_data = upb_gmalloc(s->scratch_size);
+  if (!s->scratch_data) goto err;
+
+  if (!upb_strtable_init(&s->syms, 32, s->arena)) goto err;
+  if (!upb_strtable_init(&s->files, 4, s->arena)) goto err;
+  if (!upb_inttable_init(&s->exts, s->arena)) goto err;
+
+  s->extreg = upb_ExtensionRegistry_New(s->arena);
+  if (!s->extreg) goto err;
+
+  return s;
+
+err:
+  upb_DefPool_Free(s);
+  return NULL;
+}
+
+bool _upb_DefPool_InsertExt(upb_DefPool* s, const upb_MiniTableExtension* ext,
+                            upb_FieldDef* f) {
+  return upb_inttable_insert(&s->exts, (uintptr_t)ext, upb_value_constptr(f),
+                             s->arena);
+}
+
+bool _upb_DefPool_InsertSym(upb_DefPool* s, upb_StringView sym, upb_value v,
+                            upb_Status* status) {
+  // TODO: table should support an operation "tryinsert" to avoid the double
+  // lookup.
+  if (upb_strtable_lookup2(&s->syms, sym.data, sym.size, NULL)) {
+    upb_Status_SetErrorFormat(status, "duplicate symbol '%s'", sym.data);
+    return false;
+  }
+  if (!upb_strtable_insert(&s->syms, sym.data, sym.size, v, s->arena)) {
+    upb_Status_SetErrorMessage(status, "out of memory");
+    return false;
+  }
+  return true;
+}
+
+static const void* _upb_DefPool_Unpack(const upb_DefPool* s, const char* sym,
+                                       size_t size, upb_deftype_t type) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->syms, sym, size, &v)
+             ? _upb_DefType_Unpack(v, type)
+             : NULL;
+}
+
+bool _upb_DefPool_LookupSym(const upb_DefPool* s, const char* sym, size_t size,
+                            upb_value* v) {
+  return upb_strtable_lookup2(&s->syms, sym, size, v);
+}
+
+upb_ExtensionRegistry* _upb_DefPool_ExtReg(const upb_DefPool* s) {
+  return s->extreg;
+}
+
+void** _upb_DefPool_ScratchData(const upb_DefPool* s) {
+  return (void**)&s->scratch_data;
+}
+
+size_t* _upb_DefPool_ScratchSize(const upb_DefPool* s) {
+  return (size_t*)&s->scratch_size;
+}
+
+const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
+                                                    const char* sym) {
+  return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_MSG);
+}
+
+const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
+    const upb_DefPool* s, const char* sym, size_t len) {
+  return _upb_DefPool_Unpack(s, sym, len, UPB_DEFTYPE_MSG);
+}
+
+const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
+                                              const char* sym) {
+  return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUM);
+}
+
+const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
+                                                      const char* sym) {
+  return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUMVAL);
+}
+
+const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
+                                              const char* name) {
+  upb_value v;
+  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
+                                                  : NULL;
+}
+
+const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* 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_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size) {
+  upb_value v;
+  if (!upb_strtable_lookup2(&s->syms, name, size, &v)) return NULL;
+
+  switch (_upb_DefType_Type(v)) {
+    case UPB_DEFTYPE_FIELD:
+      return _upb_DefType_Unpack(v, UPB_DEFTYPE_FIELD);
+    case UPB_DEFTYPE_MSG: {
+      const upb_MessageDef* m = _upb_DefType_Unpack(v, UPB_DEFTYPE_MSG);
+      return _upb_MessageDef_InMessageSet(m)
+                 ? upb_MessageDef_NestedExtension(m, 0)
+                 : NULL;
+    }
+    default:
+      break;
+  }
+
+  return NULL;
+}
+
+const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
+                                                    const char* sym) {
+  return upb_DefPool_FindExtensionByNameWithSize(s, sym, strlen(sym));
+}
+
+const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
+                                                    const char* name) {
+  return _upb_DefPool_Unpack(s, name, strlen(name), UPB_DEFTYPE_SERVICE);
+}
+
+const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size) {
+  return _upb_DefPool_Unpack(s, name, size, UPB_DEFTYPE_SERVICE);
+}
+
+const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
+                                                        const char* name) {
+  upb_value v;
+  // TODO(haberman): non-extension fields and oneofs.
+  if (upb_strtable_lookup(&s->syms, name, &v)) {
+    switch (_upb_DefType_Type(v)) {
+      case UPB_DEFTYPE_EXT: {
+        const upb_FieldDef* f = _upb_DefType_Unpack(v, UPB_DEFTYPE_EXT);
+        return upb_FieldDef_File(f);
+      }
+      case UPB_DEFTYPE_MSG: {
+        const upb_MessageDef* m = _upb_DefType_Unpack(v, UPB_DEFTYPE_MSG);
+        return upb_MessageDef_File(m);
+      }
+      case UPB_DEFTYPE_ENUM: {
+        const upb_EnumDef* e = _upb_DefType_Unpack(v, UPB_DEFTYPE_ENUM);
+        return upb_EnumDef_File(e);
+      }
+      case UPB_DEFTYPE_ENUMVAL: {
+        const upb_EnumValueDef* ev =
+            _upb_DefType_Unpack(v, UPB_DEFTYPE_ENUMVAL);
+        return upb_EnumDef_File(upb_EnumValueDef_Enum(ev));
+      }
+      case UPB_DEFTYPE_SERVICE: {
+        const upb_ServiceDef* service =
+            _upb_DefType_Unpack(v, UPB_DEFTYPE_SERVICE);
+        return upb_ServiceDef_File(service);
+      }
+      default:
+        UPB_UNREACHABLE();
+    }
+  }
+
+  const char* last_dot = strrchr(name, '.');
+  if (last_dot) {
+    const upb_MessageDef* parent =
+        upb_DefPool_FindMessageByNameWithSize(s, name, last_dot - name);
+    if (parent) {
+      const char* shortname = last_dot + 1;
+      if (upb_MessageDef_FindByNameWithSize(parent, shortname,
+                                            strlen(shortname), NULL, NULL)) {
+        return upb_MessageDef_File(parent);
+      }
+    }
+  }
+
+  return NULL;
+}
+
+static void remove_filedef(upb_DefPool* s, upb_FileDef* file) {
+  intptr_t iter = UPB_INTTABLE_BEGIN;
+  upb_StringView key;
+  upb_value val;
+  while (upb_strtable_next2(&s->syms, &key, &val, &iter)) {
+    const upb_FileDef* f;
+    switch (_upb_DefType_Type(val)) {
+      case UPB_DEFTYPE_EXT:
+        f = upb_FieldDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_EXT));
+        break;
+      case UPB_DEFTYPE_MSG:
+        f = upb_MessageDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_MSG));
+        break;
+      case UPB_DEFTYPE_ENUM:
+        f = upb_EnumDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_ENUM));
+        break;
+      case UPB_DEFTYPE_ENUMVAL:
+        f = upb_EnumDef_File(upb_EnumValueDef_Enum(
+            _upb_DefType_Unpack(val, UPB_DEFTYPE_ENUMVAL)));
+        break;
+      case UPB_DEFTYPE_SERVICE:
+        f = upb_ServiceDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_SERVICE));
+        break;
+      default:
+        UPB_UNREACHABLE();
+    }
+
+    if (f == file) upb_strtable_removeiter(&s->syms, &iter);
+  }
+}
+
+static const upb_FileDef* _upb_DefPool_AddFile(
+    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
+    const upb_MiniTableFile* layout, upb_Status* status) {
+  const upb_StringView name = google_protobuf_FileDescriptorProto_name(file_proto);
+
+  if (name.size == 0) {
+    upb_Status_SetErrorFormat(status,
+                              "missing name in google_protobuf_FileDescriptorProto");
+    return NULL;
+  }
+
+  // Determine whether we already know about this file.
+  {
+    upb_value v;
+    if (upb_strtable_lookup2(&s->files, name.data, name.size, &v)) {
+      upb_Status_SetErrorFormat(status,
+                                "duplicate file name " UPB_STRINGVIEW_FORMAT,
+                                UPB_STRINGVIEW_ARGS(name));
+      return NULL;
+    }
+  }
+
+  upb_DefBuilder ctx = {
+      .symtab = s,
+      .layout = layout,
+      .msg_count = 0,
+      .enum_count = 0,
+      .ext_count = 0,
+      .status = status,
+      .file = NULL,
+      .arena = upb_Arena_New(),
+      .tmp_arena = upb_Arena_New(),
+  };
+
+  if (UPB_SETJMP(ctx.err)) {
+    UPB_ASSERT(!upb_Status_IsOk(status));
+    if (ctx.file) {
+      remove_filedef(s, ctx.file);
+      ctx.file = NULL;
+    }
+  } else if (!ctx.arena || !ctx.tmp_arena) {
+    _upb_DefBuilder_OomErr(&ctx);
+  } else {
+    _upb_FileDef_Create(&ctx, file_proto);
+    upb_strtable_insert(&s->files, name.data, name.size,
+                        upb_value_constptr(ctx.file), ctx.arena);
+    UPB_ASSERT(upb_Status_IsOk(status));
+    upb_Arena_Fuse(s->arena, ctx.arena);
+  }
+
+  if (ctx.arena) upb_Arena_Free(ctx.arena);
+  if (ctx.tmp_arena) upb_Arena_Free(ctx.tmp_arena);
+  return ctx.file;
+}
+
+const upb_FileDef* upb_DefPool_AddFile(
+    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
+    upb_Status* status) {
+  return _upb_DefPool_AddFile(s, file_proto, NULL, status);
+}
+
+bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
+                                bool rebuild_minitable) {
+  /* 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_DefPool_Init** deps = init->deps;
+  google_protobuf_FileDescriptorProto* file;
+  upb_Arena* arena;
+  upb_Status status;
+
+  upb_Status_Clear(&status);
+
+  if (upb_DefPool_FindFileByName(s, init->filename)) {
+    return true;
+  }
+
+  arena = upb_Arena_New();
+
+  for (; *deps; deps++) {
+    if (!_upb_DefPool_LoadDefInitEx(s, *deps, rebuild_minitable)) goto err;
+  }
+
+  file = google_protobuf_FileDescriptorProto_parse_ex(
+      init->descriptor.data, init->descriptor.size, NULL,
+      kUpb_DecodeOption_AliasString, arena);
+  s->bytes_loaded += init->descriptor.size;
+
+  if (!file) {
+    upb_Status_SetErrorFormat(
+        &status,
+        "Failed to parse compiled-in descriptor for file '%s'. This should "
+        "never happen.",
+        init->filename);
+    goto err;
+  }
+
+  const upb_MiniTableFile* mt = rebuild_minitable ? NULL : init->layout;
+  if (!_upb_DefPool_AddFile(s, file, mt, &status)) {
+    goto err;
+  }
+
+  upb_Arena_Free(arena);
+  return true;
+
+err:
+  fprintf(stderr,
+          "Error loading compiled-in descriptor for file '%s' (this should "
+          "never happen): %s\n",
+          init->filename, upb_Status_ErrorMessage(&status));
+  upb_Arena_Free(arena);
+  return false;
+}
+
+size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s) {
+  return s->bytes_loaded;
+}
+
+upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s) { return s->arena; }
+
+const upb_FieldDef* upb_DefPool_FindExtensionByMiniTable(
+    const upb_DefPool* s, const upb_MiniTableExtension* ext) {
+  upb_value v;
+  bool ok = upb_inttable_lookup(&s->exts, (uintptr_t)ext, &v);
+  UPB_ASSERT(ok);
+  return upb_value_getconstptr(v);
+}
+
+const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
+                                                      const upb_MessageDef* m,
+                                                      int32_t fieldnum) {
+  const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
+  const upb_MiniTableExtension* ext =
+      upb_ExtensionRegistry_Lookup(s->extreg, t, fieldnum);
+  return ext ? upb_DefPool_FindExtensionByMiniTable(s, ext) : NULL;
+}
+
+const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
+    const upb_DefPool* s) {
+  return s->extreg;
+}
+
+const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
+                                                  const upb_MessageDef* m,
+                                                  size_t* count) {
+  size_t n = 0;
+  intptr_t iter = UPB_INTTABLE_BEGIN;
+  uintptr_t key;
+  upb_value val;
+  // This is O(all exts) instead of O(exts for m).  If we need this to be
+  // efficient we may need to make extreg into a two-level table, or have a
+  // second per-message index.
+  while (upb_inttable_next(&s->exts, &key, &val, &iter)) {
+    const upb_FieldDef* f = upb_value_getconstptr(val);
+    if (upb_FieldDef_ContainingType(f) == m) n++;
+  }
+  const upb_FieldDef** exts = malloc(n * sizeof(*exts));
+  iter = UPB_INTTABLE_BEGIN;
+  size_t i = 0;
+  while (upb_inttable_next(&s->exts, &key, &val, &iter)) {
+    const upb_FieldDef* f = upb_value_getconstptr(val);
+    if (upb_FieldDef_ContainingType(f) == m) exts[i++] = f;
+  }
+  *count = n;
+  return exts;
+}
+
+bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init) {
+  return _upb_DefPool_LoadDefInitEx(s, init, false);
+}
+
+
+// Must be last.
+
+upb_deftype_t _upb_DefType_Type(upb_value v) {
+  const uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+  return num & UPB_DEFTYPE_MASK;
+}
+
+upb_value _upb_DefType_Pack(const void* ptr, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)ptr;
+  UPB_ASSERT((num & UPB_DEFTYPE_MASK) == 0);
+  num |= type;
+  return upb_value_constptr((const void*)num);
+}
+
+const void* _upb_DefType_Unpack(upb_value v, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+  return (num & UPB_DEFTYPE_MASK) == type
+             ? (const void*)(num & ~UPB_DEFTYPE_MASK)
+             : NULL;
+}
+
+
+// Must be last.
+
+bool _upb_DescState_Grow(upb_DescState* d, upb_Arena* a) {
+  const size_t oldbufsize = d->bufsize;
+  const int used = d->ptr - d->buf;
+
+  if (!d->buf) {
+    d->buf = upb_Arena_Malloc(a, d->bufsize);
+    if (!d->buf) return false;
+    d->ptr = d->buf;
+    d->e.end = d->buf + d->bufsize;
+  }
+
+  if (oldbufsize - used < kUpb_MtDataEncoder_MinSize) {
+    d->bufsize *= 2;
+    d->buf = upb_Arena_Realloc(a, d->buf, oldbufsize, d->bufsize);
+    if (!d->buf) return false;
+    d->ptr = d->buf + used;
+    d->e.end = d->buf + d->bufsize;
+  }
+
+  return true;
+}
+
+
+// Must be last.
+
+struct upb_EnumDef {
+  const google_protobuf_EnumOptions* opts;
+  const upb_MiniTableEnum* layout;  // Only for proto2.
+  const upb_FileDef* file;
+  const upb_MessageDef* containing_type;  // Could be merged with "file".
+  const char* full_name;
+  upb_strtable ntoi;
+  upb_inttable iton;
+  const upb_EnumValueDef* values;
+  const upb_EnumReservedRange* res_ranges;
+  const upb_StringView* res_names;
+  int value_count;
+  int res_range_count;
+  int res_name_count;
+  int32_t defaultval;
+  bool is_sorted;  // Whether all of the values are defined in ascending order.
+};
+
+upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i) {
+  return (upb_EnumDef*)&e[i];
+}
+
+// TODO: Maybe implement this on top of a ZCOS instead?
+void _upb_EnumDef_Debug(const upb_EnumDef* e) {
+  fprintf(stderr, "enum %s (%p) {\n", e->full_name, e);
+  fprintf(stderr, " value_count: %d\n", e->value_count);
+  fprintf(stderr, " default:     %d\n", e->defaultval);
+  fprintf(stderr, " is_sorted:   %d\n", e->is_sorted);
+  fprintf(stderr, "}\n");
+}
+
+const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e) {
+  return e->layout;
+}
+
+bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a) {
+  const char* name = upb_EnumValueDef_Name(v);
+  const upb_value val = upb_value_constptr(v);
+  bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, a);
+  if (!ok) return false;
+
+  // Multiple enumerators can have the same number, first one wins.
+  const int number = upb_EnumValueDef_Number(v);
+  if (!upb_inttable_lookup(&e->iton, number, NULL)) {
+    return upb_inttable_insert(&e->iton, number, val, a);
+  }
+  return true;
+}
+
+const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) {
+  return e->opts;
+}
+
+bool upb_EnumDef_HasOptions(const upb_EnumDef* e) {
+  return e->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_EnumDef_FullName(const upb_EnumDef* e) { return e->full_name; }
+
+const char* upb_EnumDef_Name(const upb_EnumDef* e) {
+  return _upb_DefBuilder_FullToShort(e->full_name);
+}
+
+const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e) { return e->file; }
+
+const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e) {
+  return e->containing_type;
+}
+
+int32_t upb_EnumDef_Default(const upb_EnumDef* e) {
+  UPB_ASSERT(upb_EnumDef_FindValueByNumber(e, e->defaultval));
+  return e->defaultval;
+}
+
+int upb_EnumDef_ReservedRangeCount(const upb_EnumDef* e) {
+  return e->res_range_count;
+}
+
+const upb_EnumReservedRange* upb_EnumDef_ReservedRange(const upb_EnumDef* e,
+                                                       int i) {
+  UPB_ASSERT(0 <= i && i < e->res_range_count);
+  return _upb_EnumReservedRange_At(e->res_ranges, i);
+}
+
+int upb_EnumDef_ReservedNameCount(const upb_EnumDef* e) {
+  return e->res_name_count;
+}
+
+upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i) {
+  UPB_ASSERT(0 <= i && i < e->res_name_count);
+  return e->res_names[i];
+}
+
+int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; }
+
+const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e,
+                                                    const char* name) {
+  return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name));
+}
+
+const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
+    const upb_EnumDef* e, const char* name, size_t size) {
+  upb_value v;
+  return upb_strtable_lookup2(&e->ntoi, name, size, &v)
+             ? upb_value_getconstptr(v)
+             : NULL;
+}
+
+const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e,
+                                                      int32_t num) {
+  upb_value v;
+  return upb_inttable_lookup(&e->iton, num, &v) ? upb_value_getconstptr(v)
+                                                : NULL;
+}
+
+bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num) {
+  // We could use upb_EnumDef_FindValueByNumber(e, num) != NULL, but we expect
+  // this to be faster (especially for small numbers).
+  return upb_MiniTableEnum_CheckValue(e->layout, num);
+}
+
+const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) {
+  UPB_ASSERT(0 <= i && i < e->value_count);
+  return _upb_EnumValueDef_At(e->values, i);
+}
+
+bool upb_EnumDef_IsClosed(const upb_EnumDef* e) {
+  if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3) return false;
+  return upb_FileDef_Syntax(e->file) == kUpb_Syntax_Proto2;
+}
+
+bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a,
+                                      upb_StringView* out) {
+  upb_DescState s;
+  _upb_DescState_Init(&s);
+
+  const upb_EnumValueDef** sorted = NULL;
+  if (!e->is_sorted) {
+    sorted = _upb_EnumValueDefs_Sorted(e->values, e->value_count, a);
+    if (!sorted) return false;
+  }
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  s.ptr = upb_MtDataEncoder_StartEnum(&s.e, s.ptr);
+
+  // Duplicate values are allowed but we only encode each value once.
+  uint32_t previous = 0;
+
+  for (size_t i = 0; i < e->value_count; i++) {
+    const uint32_t current =
+        upb_EnumValueDef_Number(sorted ? sorted[i] : upb_EnumDef_Value(e, i));
+    if (i != 0 && previous == current) continue;
+
+    if (!_upb_DescState_Grow(&s, a)) return false;
+    s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, current);
+    previous = current;
+  }
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  s.ptr = upb_MtDataEncoder_EndEnum(&s.e, s.ptr);
+
+  // There will always be room for this '\0' in the encoder buffer because
+  // kUpb_MtDataEncoder_MinSize is overkill for upb_MtDataEncoder_EndEnum().
+  UPB_ASSERT(s.ptr < s.buf + s.bufsize);
+  *s.ptr = '\0';
+
+  out->data = s.buf;
+  out->size = s.ptr - s.buf;
+  return true;
+}
+
+static upb_MiniTableEnum* create_enumlayout(upb_DefBuilder* ctx,
+                                            const upb_EnumDef* e) {
+  upb_StringView sv;
+  bool ok = upb_EnumDef_MiniDescriptorEncode(e, ctx->tmp_arena, &sv);
+  if (!ok) _upb_DefBuilder_Errf(ctx, "OOM while building enum MiniDescriptor");
+
+  upb_Status status;
+  upb_MiniTableEnum* layout =
+      upb_MiniTableEnum_Build(sv.data, sv.size, ctx->arena, &status);
+  if (!layout)
+    _upb_DefBuilder_Errf(ctx, "Error building enum MiniTable: %s", status.msg);
+  return layout;
+}
+
+static upb_StringView* _upb_EnumReservedNames_New(
+    upb_DefBuilder* ctx, int n, const upb_StringView* protos) {
+  upb_StringView* sv = _upb_DefBuilder_Alloc(ctx, sizeof(upb_StringView) * n);
+  for (size_t i = 0; i < n; i++) {
+    sv[i].data =
+        upb_strdup2(protos[i].data, protos[i].size, _upb_DefBuilder_Arena(ctx));
+    sv[i].size = protos[i].size;
+  }
+  return sv;
+}
+
+static void create_enumdef(upb_DefBuilder* ctx, const char* prefix,
+                           const google_protobuf_EnumDescriptorProto* enum_proto,
+                           upb_EnumDef* e) {
+  const google_protobuf_EnumValueDescriptorProto* const* values;
+  const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* res_ranges;
+  const upb_StringView* res_names;
+  upb_StringView name;
+  size_t n_value, n_res_range, n_res_name;
+
+  // Must happen before _upb_DefBuilder_Add()
+  e->file = _upb_DefBuilder_File(ctx);
+
+  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+
+  e->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  _upb_DefBuilder_Add(ctx, e->full_name,
+                      _upb_DefType_Pack(e, UPB_DEFTYPE_ENUM));
+
+  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n_value);
+
+  bool ok = upb_strtable_init(&e->ntoi, n_value, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_inttable_init(&e->iton, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  e->defaultval = 0;
+  e->value_count = n_value;
+  e->values =
+      _upb_EnumValueDefs_New(ctx, prefix, n_value, values, e, &e->is_sorted);
+
+  if (n_value == 0) {
+    _upb_DefBuilder_Errf(ctx, "enums must contain at least one value (%s)",
+                         e->full_name);
+  }
+
+  res_ranges =
+      google_protobuf_EnumDescriptorProto_reserved_range(enum_proto, &n_res_range);
+  e->res_range_count = n_res_range;
+  e->res_ranges = _upb_EnumReservedRanges_New(ctx, n_res_range, res_ranges, e);
+
+  res_names = google_protobuf_EnumDescriptorProto_reserved_name(enum_proto, &n_res_name);
+  e->res_name_count = n_res_name;
+  e->res_names = _upb_EnumReservedNames_New(ctx, n_res_name, res_names);
+
+  UPB_DEF_SET_OPTIONS(e->opts, EnumDescriptorProto, EnumOptions, enum_proto);
+
+  upb_inttable_compact(&e->iton, ctx->arena);
+
+  if (upb_FileDef_Syntax(e->file) == kUpb_Syntax_Proto2) {
+    if (ctx->layout) {
+      UPB_ASSERT(ctx->enum_count < ctx->layout->enum_count);
+      e->layout = ctx->layout->enums[ctx->enum_count++];
+    } else {
+      e->layout = create_enumlayout(ctx, e);
+    }
+  } else {
+    e->layout = NULL;
+  }
+}
+
+upb_EnumDef* _upb_EnumDefs_New(upb_DefBuilder* ctx, int n,
+                               const google_protobuf_EnumDescriptorProto* const* protos,
+                               const upb_MessageDef* containing_type) {
+  _upb_DefType_CheckPadding(sizeof(upb_EnumDef));
+
+  // If a containing type is defined then get the full name from that.
+  // Otherwise use the package name from the file def.
+  const char* name = containing_type ? upb_MessageDef_FullName(containing_type)
+                                     : _upb_FileDef_RawPackage(ctx->file);
+
+  upb_EnumDef* e = _upb_DefBuilder_Alloc(ctx, sizeof(upb_EnumDef) * n);
+  for (size_t i = 0; i < n; i++) {
+    create_enumdef(ctx, name, protos[i], &e[i]);
+    e[i].containing_type = containing_type;
+  }
+  return e;
+}
+
+// #include "upb/reflection/extension_range_internal.h"
+// #include "upb/reflection/message_def.h"
+
+// Must be last.
+
+struct upb_EnumReservedRange {
+  int32_t start;
+  int32_t end;
+};
+
+upb_EnumReservedRange* _upb_EnumReservedRange_At(const upb_EnumReservedRange* r,
+                                                 int i) {
+  return (upb_EnumReservedRange*)&r[i];
+}
+
+int32_t upb_EnumReservedRange_Start(const upb_EnumReservedRange* r) {
+  return r->start;
+}
+int32_t upb_EnumReservedRange_End(const upb_EnumReservedRange* r) {
+  return r->end;
+}
+
+upb_EnumReservedRange* _upb_EnumReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* protos,
+    const upb_EnumDef* e) {
+  upb_EnumReservedRange* r =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_EnumReservedRange) * n);
+
+  for (int i = 0; i < n; i++) {
+    const int32_t start =
+        google_protobuf_EnumDescriptorProto_EnumReservedRange_start(protos[i]);
+    const int32_t end =
+        google_protobuf_EnumDescriptorProto_EnumReservedRange_end(protos[i]);
+    const int32_t max = kUpb_MaxFieldNumber + 1;
+
+    // A full validation would also check that each range is disjoint, and that
+    // none of the fields overlap with the extension ranges, but we are just
+    // sanity checking here.
+
+    // Note: Not a typo! Unlike extension ranges and message reserved ranges,
+    // the end value of an enum reserved range is *inclusive*!
+    if (start < 1 || end < start || end > max) {
+      _upb_DefBuilder_Errf(ctx, "Reserved range (%d, %d) is invalid, enum=%s\n",
+                           (int)start, (int)end, upb_EnumDef_FullName(e));
+    }
+
+    r[i].start = start;
+    r[i].end = end;
+  }
+
+  return r;
+}
+
+
+// Must be last.
+
+struct upb_EnumValueDef {
+  const google_protobuf_EnumValueOptions* opts;
+  const upb_EnumDef* parent;
+  const char* full_name;
+  int32_t number;
+};
+
+upb_EnumValueDef* _upb_EnumValueDef_At(const upb_EnumValueDef* v, int i) {
+  return (upb_EnumValueDef*)&v[i];
+}
+
+static int _upb_EnumValueDef_Compare(const void* p1, const void* p2) {
+  const uint32_t v1 = (*(const upb_EnumValueDef**)p1)->number;
+  const uint32_t v2 = (*(const upb_EnumValueDef**)p2)->number;
+  return (v1 < v2) ? -1 : (v1 > v2);
+}
+
+const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v,
+                                                   int n, upb_Arena* a) {
+  // TODO: Try to replace this arena alloc with a persistent scratch buffer.
+  upb_EnumValueDef** out =
+      (upb_EnumValueDef**)upb_Arena_Malloc(a, n * sizeof(void*));
+  if (!out) return NULL;
+
+  for (int i = 0; i < n; i++) {
+    out[i] = (upb_EnumValueDef*)&v[i];
+  }
+  qsort(out, n, sizeof(void*), _upb_EnumValueDef_Compare);
+
+  return (const upb_EnumValueDef**)out;
+}
+
+const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
+    const upb_EnumValueDef* v) {
+  return v->opts;
+}
+
+bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v) {
+  return v->opts != (void*)kUpbDefOptDefault;
+}
+
+const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v) {
+  return v->parent;
+}
+
+const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v) {
+  return v->full_name;
+}
+
+const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v) {
+  return _upb_DefBuilder_FullToShort(v->full_name);
+}
+
+int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v) { return v->number; }
+
+uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v) {
+  // Compute index in our parent's array.
+  return v - upb_EnumDef_Value(v->parent, 0);
+}
+
+static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix,
+                              const google_protobuf_EnumValueDescriptorProto* val_proto,
+                              upb_EnumDef* e, upb_EnumValueDef* v) {
+  upb_StringView name = google_protobuf_EnumValueDescriptorProto_name(val_proto);
+
+  v->parent = e;  // Must happen prior to _upb_DefBuilder_Add()
+  v->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  v->number = google_protobuf_EnumValueDescriptorProto_number(val_proto);
+  _upb_DefBuilder_Add(ctx, v->full_name,
+                      _upb_DefType_Pack(v, UPB_DEFTYPE_ENUMVAL));
+
+  UPB_DEF_SET_OPTIONS(v->opts, EnumValueDescriptorProto, EnumValueOptions,
+                      val_proto);
+
+  bool ok = _upb_EnumDef_Insert(e, v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+// Allocate and initialize an array of |n| enum value defs owned by |e|.
+upb_EnumValueDef* _upb_EnumValueDefs_New(
+    upb_DefBuilder* ctx, const char* prefix, int n,
+    const google_protobuf_EnumValueDescriptorProto* const* protos, upb_EnumDef* e,
+    bool* is_sorted) {
+  _upb_DefType_CheckPadding(sizeof(upb_EnumValueDef));
+
+  upb_EnumValueDef* v =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_EnumValueDef) * n);
+
+  *is_sorted = true;
+  uint32_t previous = 0;
+  for (size_t i = 0; i < n; i++) {
+    create_enumvaldef(ctx, prefix, protos[i], e, &v[i]);
+
+    const uint32_t current = v[i].number;
+    if (previous > current) *is_sorted = false;
+    previous = current;
+  }
+
+  if (upb_FileDef_Syntax(ctx->file) == kUpb_Syntax_Proto3 && n > 0 &&
+      v[0].number != 0) {
+    _upb_DefBuilder_Errf(ctx,
+                         "for proto3, the first enum value must be zero (%s)",
+                         upb_EnumDef_FullName(e));
+  }
+
+  return v;
+}
+
+
+// Must be last.
+
+struct upb_ExtensionRange {
+  const google_protobuf_ExtensionRangeOptions* opts;
+  int32_t start;
+  int32_t end;
+};
+
+upb_ExtensionRange* _upb_ExtensionRange_At(const upb_ExtensionRange* r, int i) {
+  return (upb_ExtensionRange*)&r[i];
+}
+
+const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
+    const upb_ExtensionRange* r) {
+  return r->opts;
+}
+
+bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r) {
+  return r->opts != (void*)kUpbDefOptDefault;
+}
+
+int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r) {
+  return r->start;
+}
+
+int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r) { return r->end; }
+
+upb_ExtensionRange* _upb_ExtensionRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ExtensionRange* const* protos,
+    const upb_MessageDef* m) {
+  upb_ExtensionRange* r =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_ExtensionRange) * n);
+
+  for (int i = 0; i < n; i++) {
+    const int32_t start =
+        google_protobuf_DescriptorProto_ExtensionRange_start(protos[i]);
+    const int32_t end = google_protobuf_DescriptorProto_ExtensionRange_end(protos[i]);
+    const int32_t max =
+        google_protobuf_MessageOptions_message_set_wire_format(upb_MessageDef_Options(m))
+            ? INT32_MAX
+            : kUpb_MaxFieldNumber + 1;
+
+    // A full validation would also check that each range is disjoint, and that
+    // none of the fields overlap with the extension ranges, but we are just
+    // sanity checking here.
+    if (start < 1 || end <= start || end > max) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Extension range (%d, %d) is invalid, message=%s\n",
+                           (int)start, (int)end, upb_MessageDef_FullName(m));
+    }
+
+    r[i].start = start;
+    r[i].end = end;
+    UPB_DEF_SET_OPTIONS(r[i].opts, DescriptorProto_ExtensionRange,
+                        ExtensionRangeOptions, protos[i]);
+  }
+
+  return r;
+}
+
+#include <ctype.h>
+#include <errno.h>
+
+
+// Must be last.
+
+#define UPB_FIELD_TYPE_UNSPECIFIED 0
+
+typedef struct {
+  size_t len;
+  char str[1];  // Null-terminated string data follows.
+} str_t;
+
+struct upb_FieldDef {
+  const google_protobuf_FieldOptions* opts;
+  const upb_FileDef* file;
+  const upb_MessageDef* 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;
+    void* msg;  // Always NULL.
+  } defaultval;
+  union {
+    const upb_OneofDef* oneof;
+    const upb_MessageDef* extension_scope;
+  } scope;
+  union {
+    const upb_MessageDef* msgdef;
+    const upb_EnumDef* enumdef;
+    const google_protobuf_FieldDescriptorProto* unresolved;
+  } sub;
+  uint32_t number_;
+  uint16_t index_;
+  uint16_t layout_index;  // Index into msgdef->layout->fields or file->exts
+  bool has_default;
+  bool is_extension_;
+  bool is_packed_;
+  bool proto3_optional_;
+  bool has_json_name_;
+  upb_FieldType type_;
+  upb_Label label_;
+#if UINTPTR_MAX == 0xffffffff
+  uint32_t padding;  // Increase size to a multiple of 8.
+#endif
+};
+
+upb_FieldDef* _upb_FieldDef_At(const upb_FieldDef* f, int i) {
+  return (upb_FieldDef*)&f[i];
+}
+
+const google_protobuf_FieldOptions* upb_FieldDef_Options(const upb_FieldDef* f) {
+  return f->opts;
+}
+
+bool upb_FieldDef_HasOptions(const upb_FieldDef* f) {
+  return f->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_FieldDef_FullName(const upb_FieldDef* f) {
+  return f->full_name;
+}
+
+upb_CType upb_FieldDef_CType(const upb_FieldDef* f) {
+  switch (f->type_) {
+    case kUpb_FieldType_Double:
+      return kUpb_CType_Double;
+    case kUpb_FieldType_Float:
+      return kUpb_CType_Float;
+    case kUpb_FieldType_Int64:
+    case kUpb_FieldType_SInt64:
+    case kUpb_FieldType_SFixed64:
+      return kUpb_CType_Int64;
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_SFixed32:
+    case kUpb_FieldType_SInt32:
+      return kUpb_CType_Int32;
+    case kUpb_FieldType_UInt64:
+    case kUpb_FieldType_Fixed64:
+      return kUpb_CType_UInt64;
+    case kUpb_FieldType_UInt32:
+    case kUpb_FieldType_Fixed32:
+      return kUpb_CType_UInt32;
+    case kUpb_FieldType_Enum:
+      return kUpb_CType_Enum;
+    case kUpb_FieldType_Bool:
+      return kUpb_CType_Bool;
+    case kUpb_FieldType_String:
+      return kUpb_CType_String;
+    case kUpb_FieldType_Bytes:
+      return kUpb_CType_Bytes;
+    case kUpb_FieldType_Group:
+    case kUpb_FieldType_Message:
+      return kUpb_CType_Message;
+  }
+  UPB_UNREACHABLE();
+}
+
+upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { return f->type_; }
+
+uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; }
+
+upb_Label 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_IsPacked(const upb_FieldDef* f) { return f->is_packed_; }
+
+const char* upb_FieldDef_Name(const upb_FieldDef* f) {
+  return _upb_DefBuilder_FullToShort(f->full_name);
+}
+
+const char* upb_FieldDef_JsonName(const upb_FieldDef* f) {
+  return f->json_name;
+}
+
+bool upb_FieldDef_HasJsonName(const upb_FieldDef* f) {
+  return f->has_json_name_;
+}
+
+const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f) { return f->file; }
+
+const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f) {
+  return f->msgdef;
+}
+
+const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f) {
+  return f->is_extension_ ? f->scope.extension_scope : NULL;
+}
+
+const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f) {
+  return f->is_extension_ ? NULL : f->scope.oneof;
+}
+
+const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f) {
+  const upb_OneofDef* oneof = upb_FieldDef_ContainingOneof(f);
+  if (!oneof || upb_OneofDef_IsSynthetic(oneof)) return NULL;
+  return oneof;
+}
+
+upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f) {
+  upb_MessageValue ret;
+
+  if (upb_FieldDef_IsRepeated(f) || upb_FieldDef_IsSubMessage(f)) {
+    return (upb_MessageValue){.msg_val = NULL};
+  }
+
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_Bool:
+      return (upb_MessageValue){.bool_val = f->defaultval.boolean};
+    case kUpb_CType_Int64:
+      return (upb_MessageValue){.int64_val = f->defaultval.sint};
+    case kUpb_CType_UInt64:
+      return (upb_MessageValue){.uint64_val = f->defaultval.uint};
+    case kUpb_CType_Enum:
+    case kUpb_CType_Int32:
+      return (upb_MessageValue){.int32_val = (int32_t)f->defaultval.sint};
+    case kUpb_CType_UInt32:
+      return (upb_MessageValue){.uint32_val = (uint32_t)f->defaultval.uint};
+    case kUpb_CType_Float:
+      return (upb_MessageValue){.float_val = f->defaultval.flt};
+    case kUpb_CType_Double:
+      return (upb_MessageValue){.double_val = f->defaultval.dbl};
+    case kUpb_CType_String:
+    case kUpb_CType_Bytes: {
+      str_t* str = f->defaultval.str;
+      if (str) {
+        return (upb_MessageValue){
+            .str_val = (upb_StringView){.data = str->str, .size = str->len}};
+      } else {
+        return (upb_MessageValue){
+            .str_val = (upb_StringView){.data = NULL, .size = 0}};
+      }
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  return ret;
+}
+
+const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_Message ? f->sub.msgdef : NULL;
+}
+
+const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_Enum ? f->sub.enumdef : NULL;
+}
+
+const upb_MiniTableField* upb_FieldDef_MiniTable(const upb_FieldDef* f) {
+  if (upb_FieldDef_IsExtension(f)) {
+    const upb_FileDef* file = upb_FieldDef_File(f);
+    return (upb_MiniTableField*)_upb_FileDef_ExtensionMiniTable(
+        file, f->layout_index);
+  } else {
+    const upb_MiniTable* layout = upb_MessageDef_MiniTable(f->msgdef);
+    return &layout->fields[f->layout_index];
+  }
+}
+
+const upb_MiniTableExtension* _upb_FieldDef_ExtensionMiniTable(
+    const upb_FieldDef* f) {
+  UPB_ASSERT(upb_FieldDef_IsExtension(f));
+  const upb_FileDef* file = upb_FieldDef_File(f);
+  return _upb_FileDef_ExtensionMiniTable(file, f->layout_index);
+}
+
+bool _upb_FieldDef_IsClosedEnum(const upb_FieldDef* f) {
+  if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3) return false;
+  if (f->type_ != kUpb_FieldType_Enum) return false;
+
+  // TODO: Maybe make is_proto2 a bool at creation?
+  const upb_FileDef* file = upb_EnumDef_File(f->sub.enumdef);
+  return upb_FileDef_Syntax(file) == kUpb_Syntax_Proto2;
+}
+
+bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f) {
+  return f->proto3_optional_;
+}
+
+int _upb_FieldDef_LayoutIndex(const upb_FieldDef* f) { return f->layout_index; }
+
+uint64_t _upb_FieldDef_Modifiers(const upb_FieldDef* f) {
+  uint64_t out = f->is_packed_ ? kUpb_FieldModifier_IsPacked : 0;
+
+  switch (f->label_) {
+    case kUpb_Label_Optional:
+      if (!upb_FieldDef_HasPresence(f)) {
+        out |= kUpb_FieldModifier_IsProto3Singular;
+      }
+      break;
+    case kUpb_Label_Repeated:
+      out |= kUpb_FieldModifier_IsRepeated;
+      break;
+    case kUpb_Label_Required:
+      out |= kUpb_FieldModifier_IsRequired;
+      break;
+  }
+
+  if (_upb_FieldDef_IsClosedEnum(f)) {
+    out |= kUpb_FieldModifier_IsClosedEnum;
+  }
+  return out;
+}
+
+bool upb_FieldDef_HasDefault(const upb_FieldDef* f) { return f->has_default; }
+
+bool upb_FieldDef_HasPresence(const upb_FieldDef* f) {
+  if (upb_FieldDef_IsRepeated(f)) return false;
+  const upb_FileDef* file = upb_FieldDef_File(f);
+  return upb_FieldDef_IsSubMessage(f) || upb_FieldDef_ContainingOneof(f) ||
+         upb_FileDef_Syntax(file) == kUpb_Syntax_Proto2;
+}
+
+bool upb_FieldDef_HasSubDef(const upb_FieldDef* f) {
+  return upb_FieldDef_IsSubMessage(f) ||
+         upb_FieldDef_CType(f) == kUpb_CType_Enum;
+}
+
+bool upb_FieldDef_IsMap(const upb_FieldDef* f) {
+  return upb_FieldDef_IsRepeated(f) && upb_FieldDef_IsSubMessage(f) &&
+         upb_MessageDef_IsMapEntry(upb_FieldDef_MessageSubDef(f));
+}
+
+bool upb_FieldDef_IsOptional(const upb_FieldDef* f) {
+  return upb_FieldDef_Label(f) == kUpb_Label_Optional;
+}
+
+bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f) {
+  return !upb_FieldDef_IsString(f) && !upb_FieldDef_IsSubMessage(f);
+}
+
+bool upb_FieldDef_IsRepeated(const upb_FieldDef* f) {
+  return upb_FieldDef_Label(f) == kUpb_Label_Repeated;
+}
+
+bool upb_FieldDef_IsRequired(const upb_FieldDef* f) {
+  return upb_FieldDef_Label(f) == kUpb_Label_Required;
+}
+
+bool upb_FieldDef_IsString(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_String ||
+         upb_FieldDef_CType(f) == kUpb_CType_Bytes;
+}
+
+bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_Message;
+}
+
+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);
+}
+
+static bool streql2(const char* a, size_t n, const char* b) {
+  return n == strlen(b) && memcmp(a, b, n) == 0;
+}
+
+// Implement the transformation as described in the spec:
+//   1. upper case all letters after an underscore.
+//   2. remove all underscores.
+static char* make_json_name(const char* name, size_t size, upb_Arena* a) {
+  char* out = upb_Arena_Malloc(a, size + 1);  // +1 is to add a trailing '\0'
+  if (out == NULL) return NULL;
+
+  bool ucase_next = false;
+  char* des = out;
+  for (size_t i = 0; i < size; i++) {
+    if (name[i] == '_') {
+      ucase_next = true;
+    } else {
+      *des++ = ucase_next ? toupper(name[i]) : name[i];
+      ucase_next = false;
+    }
+  }
+  *des++ = '\0';
+  return out;
+}
+
+static str_t* newstr(upb_DefBuilder* ctx, const char* data, size_t len) {
+  str_t* ret = _upb_DefBuilder_Alloc(ctx, sizeof(*ret) + len);
+  if (!ret) _upb_DefBuilder_OomErr(ctx);
+  ret->len = len;
+  if (len) memcpy(ret->str, data, len);
+  ret->str[len] = '\0';
+  return ret;
+}
+
+static str_t* unescape(upb_DefBuilder* ctx, const upb_FieldDef* f,
+                       const char* data, size_t len) {
+  // Size here is an upper bound; escape sequences could ultimately shrink it.
+  str_t* ret = _upb_DefBuilder_Alloc(ctx, sizeof(*ret) + len);
+  char* dst = &ret->str[0];
+  const char* src = data;
+  const char* end = data + len;
+
+  while (src < end) {
+    if (*src == '\\') {
+      src++;
+      *dst++ = _upb_DefBuilder_ParseEscape(ctx, f, &src, end);
+    } else {
+      *dst++ = *src++;
+    }
+  }
+
+  ret->len = dst - &ret->str[0];
+  return ret;
+}
+
+static void parse_default(upb_DefBuilder* ctx, const char* str, size_t len,
+                          upb_FieldDef* f) {
+  char* end;
+  char nullz[64];
+  errno = 0;
+
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_Int32:
+    case kUpb_CType_Int64:
+    case kUpb_CType_UInt32:
+    case kUpb_CType_UInt64:
+    case kUpb_CType_Double:
+    case kUpb_CType_Float:
+      // Standard C number parsing functions expect null-terminated strings.
+      if (len >= sizeof(nullz) - 1) {
+        _upb_DefBuilder_Errf(ctx, "Default too long: %.*s", (int)len, str);
+      }
+      memcpy(nullz, str, len);
+      nullz[len] = '\0';
+      str = nullz;
+      break;
+    default:
+      break;
+  }
+
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_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 kUpb_CType_Enum: {
+      const upb_EnumDef* e = f->sub.enumdef;
+      const upb_EnumValueDef* ev =
+          upb_EnumDef_FindValueByNameWithSize(e, str, len);
+      if (!ev) {
+        goto invalid;
+      }
+      f->defaultval.sint = upb_EnumValueDef_Number(ev);
+      break;
+    }
+    case kUpb_CType_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 kUpb_CType_UInt32: {
+      unsigned long val = strtoul(str, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case kUpb_CType_UInt64: {
+      unsigned long long val = strtoull(str, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case kUpb_CType_Double: {
+      double val = strtod(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.dbl = val;
+      break;
+    }
+    case kUpb_CType_Float: {
+      float val = strtof(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.flt = val;
+      break;
+    }
+    case kUpb_CType_Bool: {
+      if (streql2(str, len, "false")) {
+        f->defaultval.boolean = false;
+      } else if (streql2(str, len, "true")) {
+        f->defaultval.boolean = true;
+      } else {
+        goto invalid;
+      }
+      break;
+    }
+    case kUpb_CType_String:
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case kUpb_CType_Bytes:
+      f->defaultval.str = unescape(ctx, f, str, len);
+      break;
+    case kUpb_CType_Message:
+      /* Should not have a default value. */
+      _upb_DefBuilder_Errf(ctx, "Message should not have a default (%s)",
+                           upb_FieldDef_FullName(f));
+  }
+
+  return;
+
+invalid:
+  _upb_DefBuilder_Errf(ctx, "Invalid default '%.*s' for field %s of type %d",
+                       (int)len, str, upb_FieldDef_FullName(f),
+                       (int)upb_FieldDef_Type(f));
+}
+
+static void set_default_default(upb_DefBuilder* ctx, upb_FieldDef* f) {
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_Int32:
+    case kUpb_CType_Int64:
+      f->defaultval.sint = 0;
+      break;
+    case kUpb_CType_UInt64:
+    case kUpb_CType_UInt32:
+      f->defaultval.uint = 0;
+      break;
+    case kUpb_CType_Double:
+    case kUpb_CType_Float:
+      f->defaultval.dbl = 0;
+      break;
+    case kUpb_CType_String:
+    case kUpb_CType_Bytes:
+      f->defaultval.str = newstr(ctx, NULL, 0);
+      break;
+    case kUpb_CType_Bool:
+      f->defaultval.boolean = false;
+      break;
+    case kUpb_CType_Enum: {
+      const upb_EnumValueDef* v = upb_EnumDef_Value(f->sub.enumdef, 0);
+      f->defaultval.sint = upb_EnumValueDef_Number(v);
+      break;
+    }
+    case kUpb_CType_Message:
+      break;
+  }
+}
+
+static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix,
+                                 const google_protobuf_FieldDescriptorProto* field_proto,
+                                 upb_MessageDef* m, upb_FieldDef* f) {
+  // Must happen before _upb_DefBuilder_Add()
+  f->file = _upb_DefBuilder_File(ctx);
+
+  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
+    _upb_DefBuilder_Errf(ctx, "field has no name");
+  }
+
+  const upb_StringView name = google_protobuf_FieldDescriptorProto_name(field_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+
+  f->has_json_name_ = google_protobuf_FieldDescriptorProto_has_json_name(field_proto);
+  if (f->has_json_name_) {
+    const upb_StringView sv =
+        google_protobuf_FieldDescriptorProto_json_name(field_proto);
+    f->json_name = upb_strdup2(sv.data, sv.size, ctx->arena);
+  } else {
+    f->json_name = make_json_name(name.data, name.size, ctx->arena);
+  }
+  if (!f->json_name) _upb_DefBuilder_OomErr(ctx);
+
+  f->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
+  f->number_ = google_protobuf_FieldDescriptorProto_number(field_proto);
+  f->proto3_optional_ =
+      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
+  f->msgdef = m;
+  f->scope.oneof = NULL;
+
+  const bool has_type = google_protobuf_FieldDescriptorProto_has_type(field_proto);
+  const bool has_type_name =
+      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
+
+  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
+
+  if (has_type) {
+    switch (f->type_) {
+      case kUpb_FieldType_Message:
+      case kUpb_FieldType_Group:
+      case kUpb_FieldType_Enum:
+        if (!has_type_name) {
+          _upb_DefBuilder_Errf(ctx, "field of type %d requires type name (%s)",
+                               (int)f->type_, f->full_name);
+        }
+        break;
+      default:
+        if (has_type_name) {
+          _upb_DefBuilder_Errf(
+              ctx, "invalid type for field with type_name set (%s, %d)",
+              f->full_name, (int)f->type_);
+        }
+    }
+  } else if (has_type_name) {
+    f->type_ =
+        UPB_FIELD_TYPE_UNSPECIFIED;  // We'll fill this in in resolve_fielddef()
+  }
+
+  if (f->type_ < kUpb_FieldType_Double || f->type_ > kUpb_FieldType_SInt64) {
+    _upb_DefBuilder_Errf(ctx, "invalid type for field %s (%d)", f->full_name,
+                         f->type_);
+  }
+
+  if (f->label_ < kUpb_Label_Optional || f->label_ > kUpb_Label_Repeated) {
+    _upb_DefBuilder_Errf(ctx, "invalid label for field %s (%d)", f->full_name,
+                         f->label_);
+  }
+
+  /* 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_ == kUpb_Label_Required &&
+      upb_FileDef_Syntax(f->file) == kUpb_Syntax_Proto3) {
+    _upb_DefBuilder_Errf(ctx, "proto3 fields cannot be required (%s)",
+                         f->full_name);
+  }
+
+  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    uint32_t oneof_index = google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
+
+    if (upb_FieldDef_Label(f) != kUpb_Label_Optional) {
+      _upb_DefBuilder_Errf(ctx, "fields in oneof must have OPTIONAL label (%s)",
+                           f->full_name);
+    }
+
+    if (!m) {
+      _upb_DefBuilder_Errf(ctx, "oneof field (%s) has no containing msg",
+                           f->full_name);
+    }
+
+    if (oneof_index >= upb_MessageDef_OneofCount(m)) {
+      _upb_DefBuilder_Errf(ctx, "oneof_index out of range (%s)", f->full_name);
+    }
+
+    upb_OneofDef* oneof = (upb_OneofDef*)upb_MessageDef_Oneof(m, oneof_index);
+    f->scope.oneof = oneof;
+
+    bool ok = _upb_OneofDef_Insert(oneof, f, name.data, name.size, ctx->arena);
+    if (!ok) _upb_DefBuilder_OomErr(ctx);
+  }
+
+  UPB_DEF_SET_OPTIONS(f->opts, FieldDescriptorProto, FieldOptions, field_proto);
+
+  if (google_protobuf_FieldOptions_has_packed(f->opts)) {
+    f->is_packed_ = google_protobuf_FieldOptions_packed(f->opts);
+  } else {
+    // Repeated fields default to packed for proto3 only.
+    f->is_packed_ = upb_FieldDef_IsPrimitive(f) &&
+                    f->label_ == kUpb_Label_Repeated &&
+                    upb_FileDef_Syntax(f->file) == kUpb_Syntax_Proto3;
+  }
+}
+
+static void _upb_FieldDef_CreateExt(
+    upb_DefBuilder* ctx, const char* prefix,
+    const google_protobuf_FieldDescriptorProto* field_proto, upb_MessageDef* m,
+    upb_FieldDef* f) {
+  _upb_FieldDef_Create(ctx, prefix, field_proto, m, f);
+  f->is_extension_ = true;
+
+  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    _upb_DefBuilder_Errf(ctx, "oneof_index provided for extension field (%s)",
+                         f->full_name);
+  }
+
+  f->scope.extension_scope = m;
+  _upb_DefBuilder_Add(ctx, f->full_name, _upb_DefType_Pack(f, UPB_DEFTYPE_EXT));
+  f->layout_index = ctx->ext_count++;
+
+  if (ctx->layout) {
+    UPB_ASSERT(_upb_FieldDef_ExtensionMiniTable(f)->field.number == f->number_);
+  }
+}
+
+static void _upb_FieldDef_CreateNotExt(
+    upb_DefBuilder* ctx, const char* prefix,
+    const google_protobuf_FieldDescriptorProto* field_proto, upb_MessageDef* m,
+    upb_FieldDef* f) {
+  _upb_FieldDef_Create(ctx, prefix, field_proto, m, f);
+  f->is_extension_ = false;
+
+  if (!google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    if (f->proto3_optional_) {
+      _upb_DefBuilder_Errf(
+          ctx,
+          "non-extension field (%s) with proto3_optional was not in a oneof",
+          f->full_name);
+    }
+  }
+
+  _upb_MessageDef_InsertField(ctx, m, f);
+
+  if (!ctx->layout) return;
+
+  const upb_MiniTable* mt = upb_MessageDef_MiniTable(m);
+  const upb_MiniTableField* fields = mt->fields;
+  for (int i = 0; i < mt->field_count; i++) {
+    if (fields[i].number == f->number_) {
+      f->layout_index = i;
+      return;
+    }
+  }
+
+  UPB_ASSERT(false);  // It should be impossible to reach this point.
+}
+
+upb_FieldDef* _upb_FieldDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_FieldDescriptorProto* const* protos, const char* prefix,
+    upb_MessageDef* m, bool* is_sorted) {
+  _upb_DefType_CheckPadding(sizeof(upb_FieldDef));
+  upb_FieldDef* defs =
+      (upb_FieldDef*)_upb_DefBuilder_Alloc(ctx, sizeof(upb_FieldDef) * n);
+
+  // If we are creating extensions then is_sorted will be NULL.
+  // If we are not creating extensions then is_sorted will be non-NULL.
+  if (is_sorted) {
+    uint32_t previous = 0;
+    for (int i = 0; i < n; i++) {
+      upb_FieldDef* f = &defs[i];
+
+      _upb_FieldDef_CreateNotExt(ctx, prefix, protos[i], m, f);
+      f->index_ = i;
+      if (!ctx->layout) f->layout_index = i;
+
+      const uint32_t current = f->number_;
+      if (previous > current) *is_sorted = false;
+      previous = current;
+    }
+  } else {
+    for (int i = 0; i < n; i++) {
+      upb_FieldDef* f = &defs[i];
+
+      _upb_FieldDef_CreateExt(ctx, prefix, protos[i], m, f);
+      f->index_ = i;
+    }
+  }
+
+  return defs;
+}
+
+static void resolve_subdef(upb_DefBuilder* ctx, const char* prefix,
+                           upb_FieldDef* f) {
+  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
+  upb_StringView name =
+      google_protobuf_FieldDescriptorProto_type_name(field_proto);
+  bool has_name =
+      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
+  switch ((int)f->type_) {
+    case UPB_FIELD_TYPE_UNSPECIFIED: {
+      // Type was not specified and must be inferred.
+      UPB_ASSERT(has_name);
+      upb_deftype_t type;
+      const void* def =
+          _upb_DefBuilder_ResolveAny(ctx, f->full_name, prefix, name, &type);
+      switch (type) {
+        case UPB_DEFTYPE_ENUM:
+          f->sub.enumdef = def;
+          f->type_ = kUpb_FieldType_Enum;
+          break;
+        case UPB_DEFTYPE_MSG:
+          f->sub.msgdef = def;
+          f->type_ = kUpb_FieldType_Message;  // It appears there is no way of
+                                              // this being a group.
+          break;
+        default:
+          _upb_DefBuilder_Errf(ctx, "Couldn't resolve type name for field %s",
+                               f->full_name);
+      }
+    }
+    case kUpb_FieldType_Message:
+    case kUpb_FieldType_Group:
+      UPB_ASSERT(has_name);
+      f->sub.msgdef = _upb_DefBuilder_Resolve(ctx, f->full_name, prefix, name,
+                                              UPB_DEFTYPE_MSG);
+      break;
+    case kUpb_FieldType_Enum:
+      UPB_ASSERT(has_name);
+      f->sub.enumdef = _upb_DefBuilder_Resolve(ctx, f->full_name, prefix, name,
+                                               UPB_DEFTYPE_ENUM);
+      break;
+    default:
+      // No resolution necessary.
+      break;
+  }
+}
+
+static int _upb_FieldDef_Compare(const void* p1, const void* p2) {
+  const uint32_t v1 = (*(upb_FieldDef**)p1)->number_;
+  const uint32_t v2 = (*(upb_FieldDef**)p2)->number_;
+  return (v1 < v2) ? -1 : (v1 > v2);
+}
+
+const upb_FieldDef** _upb_FieldDefs_Sorted(const upb_FieldDef* f, int n,
+                                           upb_Arena* a) {
+  // TODO: Try to replace this arena alloc with a persistent scratch buffer.
+  upb_FieldDef** out = (upb_FieldDef**)upb_Arena_Malloc(a, n * sizeof(void*));
+  if (!out) return NULL;
+
+  for (int i = 0; i < n; i++) {
+    out[i] = (upb_FieldDef*)&f[i];
+  }
+  qsort(out, n, sizeof(void*), _upb_FieldDef_Compare);
+
+  for (int i = 0; i < n; i++) {
+    out[i]->layout_index = i;
+  }
+  return (const upb_FieldDef**)out;
+}
+
+bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a,
+                                       upb_StringView* out) {
+  UPB_ASSERT(f->is_extension_);
+
+  upb_DescState s;
+  _upb_DescState_Init(&s);
+
+  const int number = upb_FieldDef_Number(f);
+  const uint64_t modifiers = _upb_FieldDef_Modifiers(f);
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  s.ptr = upb_MtDataEncoder_EncodeExtension(&s.e, s.ptr, f->type_, number,
+                                            modifiers);
+  *s.ptr = '\0';
+
+  out->data = s.buf;
+  out->size = s.ptr - s.buf;
+  return true;
+}
+
+static void resolve_extension(upb_DefBuilder* ctx, const char* prefix,
+                              upb_FieldDef* f,
+                              const google_protobuf_FieldDescriptorProto* field_proto) {
+  if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
+    _upb_DefBuilder_Errf(ctx, "extension for field '%s' had no extendee",
+                         f->full_name);
+  }
+
+  upb_StringView name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
+  const upb_MessageDef* m =
+      _upb_DefBuilder_Resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_MSG);
+  f->msgdef = m;
+
+  if (!_upb_MessageDef_IsValidExtensionNumber(m, f->number_)) {
+    _upb_DefBuilder_Errf(
+        ctx,
+        "field number %u in extension %s has no extension range in message %s",
+        (unsigned)f->number_, f->full_name, upb_MessageDef_FullName(m));
+  }
+
+  const upb_MiniTableExtension* ext = _upb_FieldDef_ExtensionMiniTable(f);
+
+  if (ctx->layout) {
+    UPB_ASSERT(upb_FieldDef_Number(f) == ext->field.number);
+  } else {
+    upb_StringView desc;
+    if (!upb_FieldDef_MiniDescriptorEncode(f, ctx->tmp_arena, &desc)) {
+      _upb_DefBuilder_OomErr(ctx);
+    }
+
+    upb_MiniTableExtension* mut_ext = (upb_MiniTableExtension*)ext;
+    upb_MiniTableSub sub = {NULL};
+    if (upb_FieldDef_IsSubMessage(f)) {
+      sub.submsg = upb_MessageDef_MiniTable(f->sub.msgdef);
+    } else if (_upb_FieldDef_IsClosedEnum(f)) {
+      sub.subenum = _upb_EnumDef_MiniTable(f->sub.enumdef);
+    }
+    bool ok2 = upb_MiniTableExtension_Build(desc.data, desc.size, mut_ext,
+                                            upb_MessageDef_MiniTable(m), sub,
+                                            ctx->status);
+    if (!ok2) _upb_DefBuilder_Errf(ctx, "Could not build extension mini table");
+  }
+
+  bool ok = _upb_DefPool_InsertExt(ctx->symtab, ext, f);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+static void resolve_default(upb_DefBuilder* ctx, upb_FieldDef* f,
+                            const google_protobuf_FieldDescriptorProto* field_proto) {
+  // 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_StringView defaultval =
+        google_protobuf_FieldDescriptorProto_default_value(field_proto);
+
+    if (upb_FileDef_Syntax(f->file) == kUpb_Syntax_Proto3) {
+      _upb_DefBuilder_Errf(ctx,
+                           "proto3 fields cannot have explicit defaults (%s)",
+                           f->full_name);
+    }
+
+    if (upb_FieldDef_IsSubMessage(f)) {
+      _upb_DefBuilder_Errf(ctx,
+                           "message fields cannot have explicit defaults (%s)",
+                           f->full_name);
+    }
+
+    parse_default(ctx, defaultval.data, defaultval.size, f);
+    f->has_default = true;
+  } else {
+    set_default_default(ctx, f);
+    f->has_default = false;
+  }
+}
+
+void _upb_FieldDef_Resolve(upb_DefBuilder* ctx, const char* prefix,
+                           upb_FieldDef* f) {
+  // We have to stash this away since resolve_subdef() may overwrite it.
+  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
+
+  resolve_subdef(ctx, prefix, f);
+  resolve_default(ctx, f, field_proto);
+
+  if (f->is_extension_) {
+    resolve_extension(ctx, prefix, f, field_proto);
+  }
+}
+
+
+// Must be last.
+
+struct upb_FileDef {
+  const google_protobuf_FileOptions* opts;
+  const char* name;
+  const char* package;
+
+  const upb_FileDef** deps;
+  const int32_t* public_deps;
+  const int32_t* weak_deps;
+  const upb_MessageDef* top_lvl_msgs;
+  const upb_EnumDef* top_lvl_enums;
+  const upb_FieldDef* top_lvl_exts;
+  const upb_ServiceDef* services;
+  const upb_MiniTableExtension** ext_layouts;
+  const upb_DefPool* symtab;
+
+  int dep_count;
+  int public_dep_count;
+  int weak_dep_count;
+  int top_lvl_msg_count;
+  int top_lvl_enum_count;
+  int top_lvl_ext_count;
+  int service_count;
+  int ext_count;  // All exts in the file.
+  upb_Syntax syntax;
+};
+
+const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f) {
+  return f->opts;
+}
+
+bool upb_FileDef_HasOptions(const upb_FileDef* f) {
+  return f->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_FileDef_Name(const upb_FileDef* f) { return f->name; }
+
+const char* upb_FileDef_Package(const upb_FileDef* f) {
+  return f->package ? f->package : "";
+}
+
+const char* _upb_FileDef_RawPackage(const upb_FileDef* f) { return f->package; }
+
+upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f) { return f->syntax; }
+
+int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f) {
+  return f->top_lvl_msg_count;
+}
+
+int upb_FileDef_DependencyCount(const upb_FileDef* f) { return f->dep_count; }
+
+int upb_FileDef_PublicDependencyCount(const upb_FileDef* f) {
+  return f->public_dep_count;
+}
+
+int upb_FileDef_WeakDependencyCount(const upb_FileDef* f) {
+  return f->weak_dep_count;
+}
+
+const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f) {
+  return f->public_deps;
+}
+
+const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f) {
+  return f->weak_deps;
+}
+
+int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f) {
+  return f->top_lvl_enum_count;
+}
+
+int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f) {
+  return f->top_lvl_ext_count;
+}
+
+int upb_FileDef_ServiceCount(const upb_FileDef* f) { return f->service_count; }
+
+const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->dep_count);
+  return f->deps[i];
+}
+
+const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->public_dep_count);
+  return f->deps[f->public_deps[i]];
+}
+
+const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->public_dep_count);
+  return f->deps[f->weak_deps[i]];
+}
+
+const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->top_lvl_msg_count);
+  return _upb_MessageDef_At(f->top_lvl_msgs, i);
+}
+
+const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->top_lvl_enum_count);
+  return _upb_EnumDef_At(f->top_lvl_enums, i);
+}
+
+const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->top_lvl_ext_count);
+  return _upb_FieldDef_At(f->top_lvl_exts, i);
+}
+
+const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->service_count);
+  return _upb_ServiceDef_At(f->services, i);
+}
+
+const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f) { return f->symtab; }
+
+const upb_MiniTableExtension* _upb_FileDef_ExtensionMiniTable(
+    const upb_FileDef* f, int i) {
+  return f->ext_layouts[i];
+}
+
+static char* strviewdup(upb_DefBuilder* ctx, upb_StringView view) {
+  char* ret = upb_strdup2(view.data, view.size, _upb_DefBuilder_Arena(ctx));
+  if (!ret) _upb_DefBuilder_OomErr(ctx);
+  return ret;
+}
+
+static bool streql_view(upb_StringView view, const char* b) {
+  return view.size == strlen(b) && memcmp(view.data, b, view.size) == 0;
+}
+
+static int count_exts_in_msg(const google_protobuf_DescriptorProto* msg_proto) {
+  size_t n;
+  google_protobuf_DescriptorProto_extension(msg_proto, &n);
+  int ext_count = n;
+
+  const google_protobuf_DescriptorProto* const* nested_msgs =
+      google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (size_t i = 0; i < n; i++) {
+    ext_count += count_exts_in_msg(nested_msgs[i]);
+  }
+
+  return ext_count;
+}
+
+// Allocate and initialize one file def, and add it to the context object.
+void _upb_FileDef_Create(upb_DefBuilder* ctx,
+                         const google_protobuf_FileDescriptorProto* file_proto) {
+  upb_FileDef* file = _upb_DefBuilder_Alloc(ctx, sizeof(upb_FileDef));
+  ctx->file = file;
+
+  const google_protobuf_DescriptorProto* const* msgs;
+  const google_protobuf_EnumDescriptorProto* const* enums;
+  const google_protobuf_FieldDescriptorProto* const* exts;
+  const google_protobuf_ServiceDescriptorProto* const* services;
+  const upb_StringView* strs;
+  const int32_t* public_deps;
+  const int32_t* weak_deps;
+  size_t n;
+
+  file->symtab = ctx->symtab;
+
+  // Count all extensions in the file, to build a flat array of layouts.
+  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  int ext_count = n;
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (int i = 0; i < n; i++) {
+    ext_count += count_exts_in_msg(msgs[i]);
+  }
+  file->ext_count = ext_count;
+
+  if (ctx->layout) {
+    // We are using the ext layouts that were passed in.
+    file->ext_layouts = ctx->layout->exts;
+    if (ctx->layout->ext_count != file->ext_count) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Extension count did not match layout (%d vs %d)",
+                           ctx->layout->ext_count, file->ext_count);
+    }
+  } else {
+    // We are building ext layouts from scratch.
+    file->ext_layouts = _upb_DefBuilder_Alloc(
+        ctx, sizeof(*file->ext_layouts) * file->ext_count);
+    upb_MiniTableExtension* ext =
+        _upb_DefBuilder_Alloc(ctx, sizeof(*ext) * file->ext_count);
+    for (int i = 0; i < file->ext_count; i++) {
+      file->ext_layouts[i] = &ext[i];
+    }
+  }
+
+  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
+    _upb_DefBuilder_Errf(ctx, "File has no name");
+  }
+
+  file->name = strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
+
+  upb_StringView package = google_protobuf_FileDescriptorProto_package(file_proto);
+  if (package.size) {
+    _upb_DefBuilder_CheckIdentFull(ctx, package);
+    file->package = strviewdup(ctx, package);
+  } else {
+    file->package = NULL;
+  }
+
+  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
+    upb_StringView syntax = google_protobuf_FileDescriptorProto_syntax(file_proto);
+
+    if (streql_view(syntax, "proto2")) {
+      file->syntax = kUpb_Syntax_Proto2;
+    } else if (streql_view(syntax, "proto3")) {
+      file->syntax = kUpb_Syntax_Proto3;
+    } else {
+      _upb_DefBuilder_Errf(ctx, "Invalid syntax '" UPB_STRINGVIEW_FORMAT "'",
+                           UPB_STRINGVIEW_ARGS(syntax));
+    }
+  } else {
+    file->syntax = kUpb_Syntax_Proto2;
+  }
+
+  // Read options.
+  UPB_DEF_SET_OPTIONS(file->opts, FileDescriptorProto, FileOptions, file_proto);
+
+  // Verify dependencies.
+  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
+  file->dep_count = n;
+  file->deps = _upb_DefBuilder_Alloc(ctx, sizeof(*file->deps) * n);
+
+  for (size_t i = 0; i < n; i++) {
+    upb_StringView str = strs[i];
+    file->deps[i] =
+        upb_DefPool_FindFileByNameWithSize(ctx->symtab, str.data, str.size);
+    if (!file->deps[i]) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Depends on file '" UPB_STRINGVIEW_FORMAT
+                           "', but it has not been loaded",
+                           UPB_STRINGVIEW_ARGS(str));
+    }
+  }
+
+  public_deps = google_protobuf_FileDescriptorProto_public_dependency(file_proto, &n);
+  file->public_dep_count = n;
+  file->public_deps =
+      _upb_DefBuilder_Alloc(ctx, sizeof(*file->public_deps) * n);
+  int32_t* mutable_public_deps = (int32_t*)file->public_deps;
+  for (size_t i = 0; i < n; i++) {
+    if (public_deps[i] >= file->dep_count) {
+      _upb_DefBuilder_Errf(ctx, "public_dep %d is out of range",
+                           (int)public_deps[i]);
+    }
+    mutable_public_deps[i] = public_deps[i];
+  }
+
+  weak_deps = google_protobuf_FileDescriptorProto_weak_dependency(file_proto, &n);
+  file->weak_dep_count = n;
+  file->weak_deps = _upb_DefBuilder_Alloc(ctx, sizeof(*file->weak_deps) * n);
+  int32_t* mutable_weak_deps = (int32_t*)file->weak_deps;
+  for (size_t i = 0; i < n; i++) {
+    if (weak_deps[i] >= file->dep_count) {
+      _upb_DefBuilder_Errf(ctx, "weak_dep %d is out of range",
+                           (int)weak_deps[i]);
+    }
+    mutable_weak_deps[i] = weak_deps[i];
+  }
+
+  // Create enums.
+  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  file->top_lvl_enum_count = n;
+  file->top_lvl_enums = _upb_EnumDefs_New(ctx, n, enums, NULL);
+
+  // Create extensions.
+  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->top_lvl_ext_count = n;
+  file->top_lvl_exts =
+      _upb_FieldDefs_New(ctx, n, exts, file->package, NULL, NULL);
+
+  // Create messages.
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  file->top_lvl_msg_count = n;
+  file->top_lvl_msgs = _upb_MessageDefs_New(ctx, n, msgs, NULL);
+
+  // Create services.
+  services = google_protobuf_FileDescriptorProto_service(file_proto, &n);
+  file->service_count = n;
+  file->services = _upb_ServiceDefs_New(ctx, n, services);
+
+  // Now that all names are in the table, build layouts and resolve refs.
+
+  for (int i = 0; i < file->top_lvl_msg_count; i++) {
+    upb_MessageDef* m = (upb_MessageDef*)upb_FileDef_TopLevelMessage(file, i);
+    _upb_MessageDef_Resolve(ctx, m);
+  }
+
+  for (int i = 0; i < file->top_lvl_ext_count; i++) {
+    upb_FieldDef* f = (upb_FieldDef*)upb_FileDef_TopLevelExtension(file, i);
+    _upb_FieldDef_Resolve(ctx, file->package, f);
+  }
+
+  if (!ctx->layout) {
+    for (int i = 0; i < file->top_lvl_msg_count; i++) {
+      upb_MessageDef* m = (upb_MessageDef*)upb_FileDef_TopLevelMessage(file, i);
+      _upb_MessageDef_LinkMiniTable(ctx, m);
+    }
+  }
+
+  if (file->ext_count) {
+    bool ok = upb_ExtensionRegistry_AddArray(
+        _upb_DefPool_ExtReg(ctx->symtab), file->ext_layouts, file->ext_count);
+    if (!ok) _upb_DefBuilder_OomErr(ctx);
+  }
+}
+
+
+#include <string.h>
+
+
+// Must be last.
+
+bool upb_Message_Has(const upb_Message* msg, const upb_FieldDef* f) {
+  UPB_ASSERT(upb_FieldDef_HasPresence(f));
+  return _upb_MiniTable_HasField(msg, upb_FieldDef_MiniTable(f));
+}
+
+const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* 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_Message_Has(msg, f) ? f : NULL;
+  } else {
+    const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
+    uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
+    f = oneof_case ? upb_OneofDef_LookupNumber(o, oneof_case) : NULL;
+    UPB_ASSERT((f != NULL) == (oneof_case != 0));
+    return f;
+  }
+}
+
+upb_MessageValue upb_Message_Get(const upb_Message* msg,
+                                 const upb_FieldDef* f) {
+  upb_MessageValue default_val = upb_FieldDef_Default(f);
+  upb_MessageValue ret;
+  _upb_MiniTable_GetField(msg, upb_FieldDef_MiniTable(f), &default_val, &ret);
+  return ret;
+}
+
+upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg,
+                                            const upb_FieldDef* f,
+                                            upb_Arena* a) {
+  UPB_ASSERT(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_IsRepeated(f));
+  if (upb_FieldDef_HasPresence(f) && !upb_Message_Has(msg, f)) {
+    // We need to skip the upb_Message_Get() call in this case.
+    goto make;
+  }
+
+  upb_MessageValue val = upb_Message_Get(msg, f);
+  if (val.array_val) {
+    return (upb_MutableMessageValue){.array = (upb_Array*)val.array_val};
+  }
+
+  upb_MutableMessageValue ret;
+make:
+  if (!a) return (upb_MutableMessageValue){.array = NULL};
+  if (upb_FieldDef_IsMap(f)) {
+    const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
+    const upb_FieldDef* key =
+        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
+    const upb_FieldDef* value =
+        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
+    ret.map =
+        upb_Map_New(a, upb_FieldDef_CType(key), upb_FieldDef_CType(value));
+  } else if (upb_FieldDef_IsRepeated(f)) {
+    ret.array = upb_Array_New(a, upb_FieldDef_CType(f));
+  } else {
+    UPB_ASSERT(upb_FieldDef_IsSubMessage(f));
+    const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
+    ret.msg = upb_Message_New(upb_MessageDef_MiniTable(m), a);
+  }
+
+  val.array_val = ret.array;
+  upb_Message_Set(msg, f, val, a);
+
+  return ret;
+}
+
+bool upb_Message_Set(upb_Message* msg, const upb_FieldDef* f,
+                     upb_MessageValue val, upb_Arena* a) {
+  return _upb_MiniTable_SetField(msg, upb_FieldDef_MiniTable(f), &val, a);
+}
+
+void upb_Message_ClearField(upb_Message* msg, const upb_FieldDef* f) {
+  _upb_MiniTable_ClearField(msg, upb_FieldDef_MiniTable(f));
+}
+
+void upb_Message_Clear(upb_Message* msg, const upb_MessageDef* m) {
+  _upb_Message_Clear(msg, upb_MessageDef_MiniTable(m));
+}
+
+bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
+                      const upb_DefPool* ext_pool, const upb_FieldDef** out_f,
+                      upb_MessageValue* out_val, size_t* iter) {
+  size_t i = *iter;
+  size_t n = upb_MessageDef_FieldCount(m);
+  UPB_UNUSED(ext_pool);
+
+  // Iterate over normal fields, returning the first one that is set.
+  while (++i < n) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
+    upb_MessageValue val = upb_Message_Get(msg, f);
+
+    // Skip field if unset or empty.
+    if (upb_MiniTableField_HasPresence(field)) {
+      if (!upb_Message_Has(msg, f)) continue;
+    } else {
+      switch (upb_FieldMode_Get(field)) {
+        case kUpb_FieldMode_Map:
+          if (!val.map_val || upb_Map_Size(val.map_val) == 0) continue;
+          break;
+        case kUpb_FieldMode_Array:
+          if (!val.array_val || upb_Array_Size(val.array_val) == 0) continue;
+          break;
+        case kUpb_FieldMode_Scalar:
+          if (!_upb_MiniTable_ValueIsNonZero(&val, field)) continue;
+          break;
+      }
+    }
+
+    *out_val = val;
+    *out_f = f;
+    *iter = i;
+    return true;
+  }
+
+  if (ext_pool) {
+    // Return any extensions that are set.
+    size_t count;
+    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &count);
+    if (i - n < count) {
+      ext += count - 1 - (i - n);
+      memcpy(out_val, &ext->data, sizeof(*out_val));
+      *out_f = upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
+      *iter = i;
+      return true;
+    }
+  }
+
+  *iter = i;
+  return false;
+}
+
+bool _upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
+                                 int depth) {
+  size_t iter = kUpb_Message_Begin;
+  const upb_FieldDef* f;
+  upb_MessageValue val;
+  bool ret = true;
+
+  if (--depth == 0) return false;
+
+  _upb_Message_DiscardUnknown_shallow(msg);
+
+  while (upb_Message_Next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
+    const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
+    if (!subm) continue;
+    if (upb_FieldDef_IsMap(f)) {
+      const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(subm, 2);
+      const upb_MessageDef* val_m = upb_FieldDef_MessageSubDef(val_f);
+      upb_Map* map = (upb_Map*)val.map_val;
+      size_t iter = kUpb_Map_Begin;
+
+      if (!val_m) continue;
+
+      upb_MessageValue map_key, map_val;
+      while (upb_Map_Next(map, &map_key, &map_val, &iter)) {
+        if (!_upb_Message_DiscardUnknown((upb_Message*)map_val.msg_val, val_m,
+                                         depth)) {
+          ret = false;
+        }
+      }
+    } else if (upb_FieldDef_IsRepeated(f)) {
+      const upb_Array* arr = val.array_val;
+      size_t i, n = upb_Array_Size(arr);
+      for (i = 0; i < n; i++) {
+        upb_MessageValue elem = upb_Array_Get(arr, i);
+        if (!_upb_Message_DiscardUnknown((upb_Message*)elem.msg_val, subm,
+                                         depth)) {
+          ret = false;
+        }
+      }
+    } else {
+      if (!_upb_Message_DiscardUnknown((upb_Message*)val.msg_val, subm,
+                                       depth)) {
+        ret = false;
+      }
+    }
+  }
+
+  return ret;
+}
+
+bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
+                                int maxdepth) {
+  return _upb_Message_DiscardUnknown(msg, m, maxdepth);
+}
+
+
+// Must be last.
+
+struct upb_MessageDef {
+  const google_protobuf_MessageOptions* opts;
+  const upb_MiniTable* layout;
+  const upb_FileDef* file;
+  const upb_MessageDef* containing_type;
+  const char* full_name;
+
+  // Tables for looking up fields by number and name.
+  upb_inttable itof;
+  upb_strtable ntof;
+
+  /* All nested defs.
+   * MEM: We could save some space here by putting nested defs in a contiguous
+   * region and calculating counts from offsets or vice-versa. */
+  const upb_FieldDef* fields;
+  const upb_OneofDef* oneofs;
+  const upb_ExtensionRange* ext_ranges;
+  const upb_StringView* res_names;
+  const upb_MessageDef* nested_msgs;
+  const upb_MessageReservedRange* res_ranges;
+  const upb_EnumDef* nested_enums;
+  const upb_FieldDef* nested_exts;
+
+  // TODO(salo): These counters don't need anywhere near 32 bits.
+  int field_count;
+  int real_oneof_count;
+  int oneof_count;
+  int ext_range_count;
+  int res_range_count;
+  int res_name_count;
+  int nested_msg_count;
+  int nested_enum_count;
+  int nested_ext_count;
+  bool in_message_set;
+  bool is_sorted;
+  upb_WellKnown well_known_type;
+#if UINTPTR_MAX == 0xffffffff
+  uint32_t padding;  // Increase size to a multiple of 8.
+#endif
+};
+
+static void assign_msg_wellknowntype(upb_MessageDef* m) {
+  const char* name = m->full_name;
+  if (name == NULL) {
+    m->well_known_type = kUpb_WellKnown_Unspecified;
+    return;
+  }
+  if (!strcmp(name, "google.protobuf.Any")) {
+    m->well_known_type = kUpb_WellKnown_Any;
+  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
+    m->well_known_type = kUpb_WellKnown_FieldMask;
+  } else if (!strcmp(name, "google.protobuf.Duration")) {
+    m->well_known_type = kUpb_WellKnown_Duration;
+  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
+    m->well_known_type = kUpb_WellKnown_Timestamp;
+  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
+    m->well_known_type = kUpb_WellKnown_DoubleValue;
+  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
+    m->well_known_type = kUpb_WellKnown_FloatValue;
+  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
+    m->well_known_type = kUpb_WellKnown_Int64Value;
+  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
+    m->well_known_type = kUpb_WellKnown_UInt64Value;
+  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
+    m->well_known_type = kUpb_WellKnown_Int32Value;
+  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
+    m->well_known_type = kUpb_WellKnown_UInt32Value;
+  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
+    m->well_known_type = kUpb_WellKnown_BoolValue;
+  } else if (!strcmp(name, "google.protobuf.StringValue")) {
+    m->well_known_type = kUpb_WellKnown_StringValue;
+  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
+    m->well_known_type = kUpb_WellKnown_BytesValue;
+  } else if (!strcmp(name, "google.protobuf.Value")) {
+    m->well_known_type = kUpb_WellKnown_Value;
+  } else if (!strcmp(name, "google.protobuf.ListValue")) {
+    m->well_known_type = kUpb_WellKnown_ListValue;
+  } else if (!strcmp(name, "google.protobuf.Struct")) {
+    m->well_known_type = kUpb_WellKnown_Struct;
+  } else {
+    m->well_known_type = kUpb_WellKnown_Unspecified;
+  }
+}
+
+upb_MessageDef* _upb_MessageDef_At(const upb_MessageDef* m, int i) {
+  return (upb_MessageDef*)&m[i];
+}
+
+bool _upb_MessageDef_IsValidExtensionNumber(const upb_MessageDef* m, int n) {
+  for (int i = 0; i < m->ext_range_count; i++) {
+    const upb_ExtensionRange* r = upb_MessageDef_ExtensionRange(m, i);
+    if (upb_ExtensionRange_Start(r) <= n && n < upb_ExtensionRange_End(r)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+const google_protobuf_MessageOptions* upb_MessageDef_Options(const upb_MessageDef* m) {
+  return m->opts;
+}
+
+bool upb_MessageDef_HasOptions(const upb_MessageDef* m) {
+  return m->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_MessageDef_FullName(const upb_MessageDef* m) {
+  return m->full_name;
+}
+
+const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m) {
+  return m->file;
+}
+
+const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m) {
+  return m->containing_type;
+}
+
+const char* upb_MessageDef_Name(const upb_MessageDef* m) {
+  return _upb_DefBuilder_FullToShort(m->full_name);
+}
+
+upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m) {
+  return upb_FileDef_Syntax(m->file);
+}
+
+const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
+                                                     uint32_t i) {
+  upb_value val;
+  return upb_inttable_lookup(&m->itof, i, &val) ? upb_value_getconstptr(val)
+                                                : NULL;
+}
+
+const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, size, &val)) {
+    return NULL;
+  }
+
+  return _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
+}
+
+const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, size, &val)) {
+    return NULL;
+  }
+
+  return _upb_DefType_Unpack(val, UPB_DEFTYPE_ONEOF);
+}
+
+bool _upb_MessageDef_Insert(upb_MessageDef* m, const char* name, size_t len,
+                            upb_value v, upb_Arena* a) {
+  return upb_strtable_insert(&m->ntof, name, len, v, a);
+}
+
+bool upb_MessageDef_FindByNameWithSize(const upb_MessageDef* m,
+                                       const char* name, size_t len,
+                                       const upb_FieldDef** out_f,
+                                       const upb_OneofDef** out_o) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return false;
+  }
+
+  const upb_FieldDef* f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
+  const upb_OneofDef* o = _upb_DefType_Unpack(val, UPB_DEFTYPE_ONEOF);
+  if (out_f) *out_f = f;
+  if (out_o) *out_o = o;
+  return f || o; /* False if this was a JSON name. */
+}
+
+const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size) {
+  upb_value val;
+  const upb_FieldDef* f;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, size, &val)) {
+    return NULL;
+  }
+
+  f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
+  if (!f) f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD_JSONNAME);
+
+  return f;
+}
+
+int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m) {
+  return m->ext_range_count;
+}
+
+int upb_MessageDef_ReservedRangeCount(const upb_MessageDef* m) {
+  return m->res_range_count;
+}
+
+int upb_MessageDef_ReservedNameCount(const upb_MessageDef* m) {
+  return m->res_name_count;
+}
+
+int upb_MessageDef_FieldCount(const upb_MessageDef* m) {
+  return m->field_count;
+}
+
+int upb_MessageDef_OneofCount(const upb_MessageDef* m) {
+  return m->oneof_count;
+}
+
+int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m) {
+  return m->nested_msg_count;
+}
+
+int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m) {
+  return m->nested_enum_count;
+}
+
+int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m) {
+  return m->nested_ext_count;
+}
+
+const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m) {
+  return m->layout;
+}
+
+const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m,
+                                                        int i) {
+  UPB_ASSERT(0 <= i && i < m->ext_range_count);
+  return _upb_ExtensionRange_At(m->ext_ranges, i);
+}
+
+const upb_MessageReservedRange* upb_MessageDef_ReservedRange(
+    const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->res_range_count);
+  return _upb_MessageReservedRange_At(m->res_ranges, i);
+}
+
+upb_StringView upb_MessageDef_ReservedName(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->res_name_count);
+  return m->res_names[i];
+}
+
+const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->field_count);
+  return _upb_FieldDef_At(m->fields, i);
+}
+
+const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->oneof_count);
+  return _upb_OneofDef_At(m->oneofs, i);
+}
+
+const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
+                                                   int i) {
+  UPB_ASSERT(0 <= i && i < m->nested_msg_count);
+  return &m->nested_msgs[i];
+}
+
+const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->nested_enum_count);
+  return _upb_EnumDef_At(m->nested_enums, i);
+}
+
+const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
+                                                   int i) {
+  UPB_ASSERT(0 <= i && i < m->nested_ext_count);
+  return _upb_FieldDef_At(m->nested_exts, i);
+}
+
+upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m) {
+  return m->well_known_type;
+}
+
+bool _upb_MessageDef_InMessageSet(const upb_MessageDef* m) {
+  return m->in_message_set;
+}
+
+const upb_FieldDef* upb_MessageDef_FindFieldByName(const upb_MessageDef* m,
+                                                   const char* name) {
+  return upb_MessageDef_FindFieldByNameWithSize(m, name, strlen(name));
+}
+
+const upb_OneofDef* upb_MessageDef_FindOneofByName(const upb_MessageDef* m,
+                                                   const char* name) {
+  return upb_MessageDef_FindOneofByNameWithSize(m, name, strlen(name));
+}
+
+bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m) {
+  return google_protobuf_MessageOptions_map_entry(m->opts);
+}
+
+bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m) {
+  return google_protobuf_MessageOptions_message_set_wire_format(m->opts);
+}
+
+static upb_MiniTable* _upb_MessageDef_MakeMiniTable(upb_DefBuilder* ctx,
+                                                    const upb_MessageDef* m) {
+  upb_StringView desc;
+  bool ok = upb_MessageDef_MiniDescriptorEncode(m, ctx->tmp_arena, &desc);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  void** scratch_data = _upb_DefPool_ScratchData(ctx->symtab);
+  size_t* scratch_size = _upb_DefPool_ScratchSize(ctx->symtab);
+  upb_MiniTable* ret = upb_MiniTable_BuildWithBuf(
+      desc.data, desc.size, kUpb_MiniTablePlatform_Native, ctx->arena,
+      scratch_data, scratch_size, ctx->status);
+  if (!ret) _upb_DefBuilder_FailJmp(ctx);
+
+  return ret;
+}
+
+void _upb_MessageDef_Resolve(upb_DefBuilder* ctx, upb_MessageDef* m) {
+  for (int i = 0; i < m->field_count; i++) {
+    upb_FieldDef* f = (upb_FieldDef*)upb_MessageDef_Field(m, i);
+    _upb_FieldDef_Resolve(ctx, m->full_name, f);
+  }
+
+  if (!ctx->layout) {
+    m->layout = _upb_MessageDef_MakeMiniTable(ctx, m);
+    if (!m->layout) _upb_DefBuilder_OomErr(ctx);
+  }
+
+#ifndef NDEBUG
+  for (int i = 0; i < m->field_count; i++) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    const int layout_index = _upb_FieldDef_LayoutIndex(f);
+    UPB_ASSERT(layout_index < m->layout->field_count);
+    const upb_MiniTableField* mt_f = &m->layout->fields[layout_index];
+    UPB_ASSERT(upb_FieldDef_Type(f) == upb_MiniTableField_Type(mt_f));
+    UPB_ASSERT(upb_FieldDef_HasPresence(f) ==
+               upb_MiniTableField_HasPresence(mt_f));
+  }
+#endif
+
+  m->in_message_set = false;
+  for (int i = 0; i < upb_MessageDef_NestedExtensionCount(m); i++) {
+    upb_FieldDef* ext = (upb_FieldDef*)upb_MessageDef_NestedExtension(m, i);
+    _upb_FieldDef_Resolve(ctx, m->full_name, ext);
+    if (upb_FieldDef_Type(ext) == kUpb_FieldType_Message &&
+        upb_FieldDef_Label(ext) == kUpb_Label_Optional &&
+        upb_FieldDef_MessageSubDef(ext) == m &&
+        google_protobuf_MessageOptions_message_set_wire_format(
+            upb_MessageDef_Options(upb_FieldDef_ContainingType(ext)))) {
+      m->in_message_set = true;
+    }
+  }
+
+  for (int i = 0; i < upb_MessageDef_NestedMessageCount(m); i++) {
+    upb_MessageDef* n = (upb_MessageDef*)upb_MessageDef_NestedMessage(m, i);
+    _upb_MessageDef_Resolve(ctx, n);
+  }
+}
+
+void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
+                                 const upb_FieldDef* f) {
+  const int32_t field_number = upb_FieldDef_Number(f);
+
+  if (field_number <= 0 || field_number > kUpb_MaxFieldNumber) {
+    _upb_DefBuilder_Errf(ctx, "invalid field number (%u)", field_number);
+  }
+
+  const char* json_name = upb_FieldDef_JsonName(f);
+  const char* shortname = upb_FieldDef_Name(f);
+  const size_t shortnamelen = strlen(shortname);
+
+  upb_value v = upb_value_constptr(f);
+
+  upb_value existing_v;
+  if (upb_strtable_lookup(&m->ntof, shortname, &existing_v)) {
+    _upb_DefBuilder_Errf(ctx, "duplicate field name (%s)", shortname);
+  }
+
+  const upb_value field_v = _upb_DefType_Pack(f, UPB_DEFTYPE_FIELD);
+  bool ok =
+      _upb_MessageDef_Insert(m, shortname, shortnamelen, field_v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  if (strcmp(shortname, json_name) != 0) {
+    if (upb_strtable_lookup(&m->ntof, json_name, &v)) {
+      _upb_DefBuilder_Errf(ctx, "duplicate json_name (%s)", json_name);
+    }
+
+    const size_t json_size = strlen(json_name);
+    const upb_value json_v = _upb_DefType_Pack(f, UPB_DEFTYPE_FIELD_JSONNAME);
+    ok = _upb_MessageDef_Insert(m, json_name, json_size, json_v, ctx->arena);
+    if (!ok) _upb_DefBuilder_OomErr(ctx);
+  }
+
+  if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
+    _upb_DefBuilder_Errf(ctx, "duplicate field number (%u)", field_number);
+  }
+
+  ok = upb_inttable_insert(&m->itof, field_number, v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx,
+                                   const upb_MessageDef* m) {
+  for (int i = 0; i < m->field_count; i++) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    const upb_MessageDef* sub_m = upb_FieldDef_MessageSubDef(f);
+    const upb_EnumDef* sub_e = upb_FieldDef_EnumSubDef(f);
+    const int layout_index = _upb_FieldDef_LayoutIndex(f);
+    upb_MiniTable* mt = (upb_MiniTable*)upb_MessageDef_MiniTable(m);
+
+    UPB_ASSERT(layout_index < m->field_count);
+    upb_MiniTableField* mt_f =
+        (upb_MiniTableField*)&m->layout->fields[layout_index];
+    if (sub_m) {
+      if (!mt->subs) {
+        _upb_DefBuilder_Errf(ctx, "invalid submsg for (%s)", m->full_name);
+      }
+      UPB_ASSERT(mt_f);
+      UPB_ASSERT(sub_m->layout);
+      upb_MiniTable_SetSubMessage(mt, mt_f, sub_m->layout);
+    } else if (_upb_FieldDef_IsClosedEnum(f)) {
+      upb_MiniTable_SetSubEnum(mt, mt_f, _upb_EnumDef_MiniTable(sub_e));
+    }
+  }
+
+  for (int i = 0; i < m->nested_msg_count; i++) {
+    _upb_MessageDef_LinkMiniTable(ctx, upb_MessageDef_NestedMessage(m, i));
+  }
+}
+
+static uint64_t _upb_MessageDef_Modifiers(const upb_MessageDef* m) {
+  uint64_t out = 0;
+  if (upb_FileDef_Syntax(m->file) == kUpb_Syntax_Proto3) {
+    out |= kUpb_MessageModifier_ValidateUtf8;
+    out |= kUpb_MessageModifier_DefaultIsPacked;
+  }
+  if (m->ext_range_count) {
+    out |= kUpb_MessageModifier_IsExtendable;
+  }
+  return out;
+}
+
+static bool _upb_MessageDef_EncodeMap(upb_DescState* s, const upb_MessageDef* m,
+                                      upb_Arena* a) {
+  if (m->field_count != 2) return false;
+
+  const upb_FieldDef* key_field = upb_MessageDef_Field(m, 0);
+  const upb_FieldDef* val_field = upb_MessageDef_Field(m, 1);
+  if (key_field == NULL || val_field == NULL) return false;
+
+  UPB_ASSERT(_upb_FieldDef_LayoutIndex(key_field) == 0);
+  UPB_ASSERT(_upb_FieldDef_LayoutIndex(val_field) == 1);
+
+  s->ptr = upb_MtDataEncoder_EncodeMap(
+      &s->e, s->ptr, upb_FieldDef_Type(key_field), upb_FieldDef_Type(val_field),
+      _upb_FieldDef_Modifiers(key_field), _upb_FieldDef_Modifiers(val_field));
+  return true;
+}
+
+static bool _upb_MessageDef_EncodeMessage(upb_DescState* s,
+                                          const upb_MessageDef* m,
+                                          upb_Arena* a) {
+  const upb_FieldDef** sorted = NULL;
+  if (!m->is_sorted) {
+    sorted = _upb_FieldDefs_Sorted(m->fields, m->field_count, a);
+    if (!sorted) return false;
+  }
+
+  s->ptr = upb_MtDataEncoder_StartMessage(&s->e, s->ptr,
+                                          _upb_MessageDef_Modifiers(m));
+
+  for (int i = 0; i < m->field_count; i++) {
+    const upb_FieldDef* f = sorted ? sorted[i] : upb_MessageDef_Field(m, i);
+    const upb_FieldType type = upb_FieldDef_Type(f);
+    const int number = upb_FieldDef_Number(f);
+    const uint64_t modifiers = _upb_FieldDef_Modifiers(f);
+
+    if (!_upb_DescState_Grow(s, a)) return false;
+    s->ptr = upb_MtDataEncoder_PutField(&s->e, s->ptr, type, number, modifiers);
+  }
+
+  for (int i = 0; i < m->real_oneof_count; i++) {
+    if (!_upb_DescState_Grow(s, a)) return false;
+    s->ptr = upb_MtDataEncoder_StartOneof(&s->e, s->ptr);
+
+    const upb_OneofDef* o = upb_MessageDef_Oneof(m, i);
+    const int field_count = upb_OneofDef_FieldCount(o);
+    for (int j = 0; j < field_count; j++) {
+      const int number = upb_FieldDef_Number(upb_OneofDef_Field(o, j));
+
+      if (!_upb_DescState_Grow(s, a)) return false;
+      s->ptr = upb_MtDataEncoder_PutOneofField(&s->e, s->ptr, number);
+    }
+  }
+
+  return true;
+}
+
+static bool _upb_MessageDef_EncodeMessageSet(upb_DescState* s,
+                                             const upb_MessageDef* m,
+                                             upb_Arena* a) {
+  s->ptr = upb_MtDataEncoder_EncodeMessageSet(&s->e, s->ptr);
+
+  return true;
+}
+
+bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a,
+                                         upb_StringView* out) {
+  upb_DescState s;
+  _upb_DescState_Init(&s);
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+
+  if (upb_MessageDef_IsMapEntry(m)) {
+    if (!_upb_MessageDef_EncodeMap(&s, m, a)) return false;
+  } else if (google_protobuf_MessageOptions_message_set_wire_format(m->opts)) {
+    if (!_upb_MessageDef_EncodeMessageSet(&s, m, a)) return false;
+  } else {
+    if (!_upb_MessageDef_EncodeMessage(&s, m, a)) return false;
+  }
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  *s.ptr = '\0';
+
+  out->data = s.buf;
+  out->size = s.ptr - s.buf;
+  return true;
+}
+
+static upb_StringView* _upb_ReservedNames_New(upb_DefBuilder* ctx, int n,
+                                              const upb_StringView* protos) {
+  upb_StringView* sv = _upb_DefBuilder_Alloc(ctx, sizeof(upb_StringView) * n);
+  for (size_t i = 0; i < n; i++) {
+    sv[i].data =
+        upb_strdup2(protos[i].data, protos[i].size, _upb_DefBuilder_Arena(ctx));
+    sv[i].size = protos[i].size;
+  }
+  return sv;
+}
+
+static void create_msgdef(upb_DefBuilder* ctx, const char* prefix,
+                          const google_protobuf_DescriptorProto* msg_proto,
+                          const upb_MessageDef* containing_type,
+                          upb_MessageDef* m) {
+  const google_protobuf_OneofDescriptorProto* const* oneofs;
+  const google_protobuf_FieldDescriptorProto* const* fields;
+  const google_protobuf_DescriptorProto_ExtensionRange* const* ext_ranges;
+  const google_protobuf_DescriptorProto_ReservedRange* const* res_ranges;
+  const upb_StringView* res_names;
+  size_t n_oneof, n_field, n_enum, n_ext, n_msg;
+  size_t n_ext_range, n_res_range, n_res_name;
+  upb_StringView name;
+
+  // Must happen before _upb_DefBuilder_Add()
+  m->file = _upb_DefBuilder_File(ctx);
+
+  m->containing_type = containing_type;
+  m->is_sorted = true;
+
+  name = google_protobuf_DescriptorProto_name(msg_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+
+  m->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  _upb_DefBuilder_Add(ctx, m->full_name, _upb_DefType_Pack(m, UPB_DEFTYPE_MSG));
+
+  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof);
+  fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field);
+  ext_ranges = google_protobuf_DescriptorProto_extension_range(msg_proto, &n_ext_range);
+  res_ranges = google_protobuf_DescriptorProto_reserved_range(msg_proto, &n_res_range);
+  res_names = google_protobuf_DescriptorProto_reserved_name(msg_proto, &n_res_name);
+
+  bool ok = upb_inttable_init(&m->itof, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  if (ctx->layout) {
+    /* create_fielddef() below depends on this being set. */
+    UPB_ASSERT(ctx->msg_count < ctx->layout->msg_count);
+    m->layout = ctx->layout->msgs[ctx->msg_count++];
+    UPB_ASSERT(n_field == m->layout->field_count);
+  } else {
+    /* Allocate now (to allow cross-linking), populate later. */
+    m->layout = _upb_DefBuilder_Alloc(
+        ctx, sizeof(*m->layout) + sizeof(_upb_FastTable_Entry));
+  }
+
+  UPB_DEF_SET_OPTIONS(m->opts, DescriptorProto, MessageOptions, msg_proto);
+
+  m->oneof_count = n_oneof;
+  m->oneofs = _upb_OneofDefs_New(ctx, n_oneof, oneofs, m);
+
+  m->field_count = n_field;
+  m->fields =
+      _upb_FieldDefs_New(ctx, n_field, fields, m->full_name, m, &m->is_sorted);
+
+  // Message Sets may not contain fields.
+  if (UPB_UNLIKELY(google_protobuf_MessageOptions_message_set_wire_format(m->opts))) {
+    if (UPB_UNLIKELY(n_field > 0)) {
+      _upb_DefBuilder_Errf(ctx, "invalid message set (%s)", m->full_name);
+    }
+  }
+
+  m->ext_range_count = n_ext_range;
+  m->ext_ranges = _upb_ExtensionRanges_New(ctx, n_ext_range, ext_ranges, m);
+
+  m->res_range_count = n_res_range;
+  m->res_ranges =
+      _upb_MessageReservedRanges_New(ctx, n_res_range, res_ranges, m);
+
+  m->res_name_count = n_res_name;
+  m->res_names = _upb_ReservedNames_New(ctx, n_res_name, res_names);
+
+  const size_t synthetic_count = _upb_OneofDefs_Finalize(ctx, m);
+  m->real_oneof_count = m->oneof_count - synthetic_count;
+
+  assign_msg_wellknowntype(m);
+  upb_inttable_compact(&m->itof, ctx->arena);
+
+  const google_protobuf_EnumDescriptorProto* const* enums =
+      google_protobuf_DescriptorProto_enum_type(msg_proto, &n_enum);
+  m->nested_enum_count = n_enum;
+  m->nested_enums = _upb_EnumDefs_New(ctx, n_enum, enums, m);
+
+  const google_protobuf_FieldDescriptorProto* const* exts =
+      google_protobuf_DescriptorProto_extension(msg_proto, &n_ext);
+  m->nested_ext_count = n_ext;
+  m->nested_exts = _upb_FieldDefs_New(ctx, n_ext, exts, m->full_name, m, NULL);
+
+  const google_protobuf_DescriptorProto* const* msgs =
+      google_protobuf_DescriptorProto_nested_type(msg_proto, &n_msg);
+  m->nested_msg_count = n_msg;
+  m->nested_msgs = _upb_MessageDefs_New(ctx, n_msg, msgs, m);
+}
+
+// Allocate and initialize an array of |n| message defs.
+upb_MessageDef* _upb_MessageDefs_New(
+    upb_DefBuilder* ctx, int n, const google_protobuf_DescriptorProto* const* protos,
+    const upb_MessageDef* containing_type) {
+  _upb_DefType_CheckPadding(sizeof(upb_MessageDef));
+
+  const char* name = containing_type ? containing_type->full_name
+                                     : _upb_FileDef_RawPackage(ctx->file);
+
+  upb_MessageDef* m = _upb_DefBuilder_Alloc(ctx, sizeof(upb_MessageDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_msgdef(ctx, name, protos[i], containing_type, &m[i]);
+  }
+  return m;
+}
+
+
+// Must be last.
+
+struct upb_MessageReservedRange {
+  int32_t start;
+  int32_t end;
+};
+
+upb_MessageReservedRange* _upb_MessageReservedRange_At(
+    const upb_MessageReservedRange* r, int i) {
+  return (upb_MessageReservedRange*)&r[i];
+}
+
+int32_t upb_MessageReservedRange_Start(const upb_MessageReservedRange* r) {
+  return r->start;
+}
+int32_t upb_MessageReservedRange_End(const upb_MessageReservedRange* r) {
+  return r->end;
+}
+
+upb_MessageReservedRange* _upb_MessageReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ReservedRange* const* protos,
+    const upb_MessageDef* m) {
+  upb_MessageReservedRange* r =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_MessageReservedRange) * n);
+
+  for (int i = 0; i < n; i++) {
+    const int32_t start = google_protobuf_DescriptorProto_ReservedRange_start(protos[i]);
+    const int32_t end = google_protobuf_DescriptorProto_ReservedRange_end(protos[i]);
+    const int32_t max = kUpb_MaxFieldNumber + 1;
+
+    // A full validation would also check that each range is disjoint, and that
+    // none of the fields overlap with the extension ranges, but we are just
+    // sanity checking here.
+    if (start < 1 || end <= start || end > max) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Reserved range (%d, %d) is invalid, message=%s\n",
+                           (int)start, (int)end, upb_MessageDef_FullName(m));
+    }
+
+    r[i].start = start;
+    r[i].end = end;
+  }
+
+  return r;
+}
+
+
+// Must be last.
+
+struct upb_MethodDef {
+  const google_protobuf_MethodOptions* opts;
+  upb_ServiceDef* service;
+  const char* full_name;
+  const upb_MessageDef* input_type;
+  const upb_MessageDef* output_type;
+  int index;
+  bool client_streaming;
+  bool server_streaming;
+};
+
+upb_MethodDef* _upb_MethodDef_At(const upb_MethodDef* m, int i) {
+  return (upb_MethodDef*)&m[i];
+}
+
+const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m) {
+  return m->service;
+}
+
+const google_protobuf_MethodOptions* upb_MethodDef_Options(const upb_MethodDef* m) {
+  return m->opts;
+}
+
+bool upb_MethodDef_HasOptions(const upb_MethodDef* m) {
+  return m->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_MethodDef_FullName(const upb_MethodDef* m) {
+  return m->full_name;
+}
+
+const char* upb_MethodDef_Name(const upb_MethodDef* m) {
+  return _upb_DefBuilder_FullToShort(m->full_name);
+}
+
+int upb_MethodDef_Index(const upb_MethodDef* m) { return m->index; }
+
+const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m) {
+  return m->input_type;
+}
+
+const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m) {
+  return m->output_type;
+}
+
+bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m) {
+  return m->client_streaming;
+}
+
+bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m) {
+  return m->server_streaming;
+}
+
+static void create_method(upb_DefBuilder* ctx,
+                          const google_protobuf_MethodDescriptorProto* method_proto,
+                          upb_ServiceDef* s, upb_MethodDef* m) {
+  upb_StringView name = google_protobuf_MethodDescriptorProto_name(method_proto);
+
+  m->service = s;
+  m->full_name =
+      _upb_DefBuilder_MakeFullName(ctx, upb_ServiceDef_FullName(s), name);
+  m->client_streaming =
+      google_protobuf_MethodDescriptorProto_client_streaming(method_proto);
+  m->server_streaming =
+      google_protobuf_MethodDescriptorProto_server_streaming(method_proto);
+  m->input_type = _upb_DefBuilder_Resolve(
+      ctx, m->full_name, m->full_name,
+      google_protobuf_MethodDescriptorProto_input_type(method_proto), UPB_DEFTYPE_MSG);
+  m->output_type = _upb_DefBuilder_Resolve(
+      ctx, m->full_name, m->full_name,
+      google_protobuf_MethodDescriptorProto_output_type(method_proto), UPB_DEFTYPE_MSG);
+
+  UPB_DEF_SET_OPTIONS(m->opts, MethodDescriptorProto, MethodOptions,
+                      method_proto);
+}
+
+// Allocate and initialize an array of |n| method defs belonging to |s|.
+upb_MethodDef* _upb_MethodDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_MethodDescriptorProto* const* protos, upb_ServiceDef* s) {
+  upb_MethodDef* m = _upb_DefBuilder_Alloc(ctx, sizeof(upb_MethodDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_method(ctx, protos[i], s, &m[i]);
+    m[i].index = i;
+  }
+  return m;
+}
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// Must be last.
+
+struct upb_OneofDef {
+  const google_protobuf_OneofOptions* opts;
+  const upb_MessageDef* parent;
+  const char* full_name;
+  int field_count;
+  bool synthetic;
+  const upb_FieldDef** fields;
+  upb_strtable ntof;  // lookup a field by name
+  upb_inttable itof;  // lookup a field by number (index)
+#if UINTPTR_MAX == 0xffffffff
+  uint32_t padding;  // Increase size to a multiple of 8.
+#endif
+};
+
+upb_OneofDef* _upb_OneofDef_At(const upb_OneofDef* o, int i) {
+  return (upb_OneofDef*)&o[i];
+}
+
+const google_protobuf_OneofOptions* upb_OneofDef_Options(const upb_OneofDef* o) {
+  return o->opts;
+}
+
+bool upb_OneofDef_HasOptions(const upb_OneofDef* o) {
+  return o->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_OneofDef_FullName(const upb_OneofDef* o) {
+  return o->full_name;
+}
+
+const char* upb_OneofDef_Name(const upb_OneofDef* o) {
+  return _upb_DefBuilder_FullToShort(o->full_name);
+}
+
+const upb_MessageDef* 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) {
+  // Compute index in our parent's array.
+  return o - upb_MessageDef_Oneof(o->parent, 0);
+}
+
+bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o) { return o->synthetic; }
+
+const upb_FieldDef* upb_OneofDef_LookupNameWithSize(const upb_OneofDef* o,
+                                                    const char* name,
+                                                    size_t size) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, size, &val)
+             ? upb_value_getptr(val)
+             : NULL;
+}
+
+const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o,
+                                            const char* name) {
+  return upb_OneofDef_LookupNameWithSize(o, name, strlen(name));
+}
+
+const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
+                                              uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup(&o->itof, num, &val) ? upb_value_getptr(val)
+                                                  : NULL;
+}
+
+bool _upb_OneofDef_Insert(upb_OneofDef* o, const upb_FieldDef* f,
+                          const char* name, size_t size, upb_Arena* a) {
+  o->field_count++;
+  if (_upb_FieldDef_IsProto3Optional(f)) o->synthetic = true;
+
+  const int number = upb_FieldDef_Number(f);
+  const upb_value v = upb_value_constptr(f);
+  return upb_inttable_insert(&o->itof, number, v, a) &&
+         upb_strtable_insert(&o->ntof, name, size, v, a);
+}
+
+// Returns the synthetic count.
+size_t _upb_OneofDefs_Finalize(upb_DefBuilder* ctx, upb_MessageDef* m) {
+  int synthetic_count = 0;
+
+  for (int i = 0; i < upb_MessageDef_OneofCount(m); i++) {
+    upb_OneofDef* o = (upb_OneofDef*)upb_MessageDef_Oneof(m, i);
+
+    if (o->synthetic && o->field_count != 1) {
+      _upb_DefBuilder_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) {
+      _upb_DefBuilder_Errf(
+          ctx, "Synthetic oneofs must be after all other oneofs: %s",
+          upb_OneofDef_Name(o));
+    }
+
+    o->fields =
+        _upb_DefBuilder_Alloc(ctx, sizeof(upb_FieldDef*) * o->field_count);
+    o->field_count = 0;
+  }
+
+  for (int i = 0; i < upb_MessageDef_FieldCount(m); i++) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    upb_OneofDef* o = (upb_OneofDef*)upb_FieldDef_ContainingOneof(f);
+    if (o) {
+      o->fields[o->field_count++] = f;
+    }
+  }
+
+  return synthetic_count;
+}
+
+static void create_oneofdef(upb_DefBuilder* ctx, upb_MessageDef* m,
+                            const google_protobuf_OneofDescriptorProto* oneof_proto,
+                            const upb_OneofDef* _o) {
+  upb_OneofDef* o = (upb_OneofDef*)_o;
+  upb_StringView name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
+
+  o->parent = m;
+  o->full_name =
+      _upb_DefBuilder_MakeFullName(ctx, upb_MessageDef_FullName(m), name);
+  o->field_count = 0;
+  o->synthetic = false;
+
+  UPB_DEF_SET_OPTIONS(o->opts, OneofDescriptorProto, OneofOptions, oneof_proto);
+
+  if (upb_MessageDef_FindByNameWithSize(m, name.data, name.size, NULL, NULL)) {
+    _upb_DefBuilder_Errf(ctx, "duplicate oneof name (%s)", o->full_name);
+  }
+
+  upb_value v = _upb_DefType_Pack(o, UPB_DEFTYPE_ONEOF);
+  bool ok = _upb_MessageDef_Insert(m, name.data, name.size, v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_inttable_init(&o->itof, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_strtable_init(&o->ntof, 4, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+// Allocate and initialize an array of |n| oneof defs.
+upb_OneofDef* _upb_OneofDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_OneofDescriptorProto* const* protos, upb_MessageDef* m) {
+  _upb_DefType_CheckPadding(sizeof(upb_OneofDef));
+
+  upb_OneofDef* o = _upb_DefBuilder_Alloc(ctx, sizeof(upb_OneofDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_oneofdef(ctx, m, protos[i], &o[i]);
+  }
+  return o;
+}
+
+
+// Must be last.
+
+struct upb_ServiceDef {
+  const google_protobuf_ServiceOptions* opts;
+  const upb_FileDef* file;
+  const char* full_name;
+  upb_MethodDef* methods;
+  int method_count;
+  int index;
+};
+
+upb_ServiceDef* _upb_ServiceDef_At(const upb_ServiceDef* s, int index) {
+  return (upb_ServiceDef*)&s[index];
+}
+
+const google_protobuf_ServiceOptions* upb_ServiceDef_Options(const upb_ServiceDef* s) {
+  return s->opts;
+}
+
+bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s) {
+  return s->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_ServiceDef_FullName(const upb_ServiceDef* s) {
+  return s->full_name;
+}
+
+const char* upb_ServiceDef_Name(const upb_ServiceDef* s) {
+  return _upb_DefBuilder_FullToShort(s->full_name);
+}
+
+int upb_ServiceDef_Index(const upb_ServiceDef* s) { return s->index; }
+
+const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s) {
+  return s->file;
+}
+
+int upb_ServiceDef_MethodCount(const upb_ServiceDef* s) {
+  return s->method_count;
+}
+
+const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i) {
+  return (i < 0 || i >= s->method_count) ? NULL
+                                         : _upb_MethodDef_At(s->methods, i);
+}
+
+const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
+                                                     const char* name) {
+  for (int i = 0; i < s->method_count; i++) {
+    const upb_MethodDef* m = _upb_MethodDef_At(s->methods, i);
+    if (strcmp(name, upb_MethodDef_Name(m)) == 0) {
+      return m;
+    }
+  }
+  return NULL;
+}
+
+static void create_service(upb_DefBuilder* ctx,
+                           const google_protobuf_ServiceDescriptorProto* svc_proto,
+                           upb_ServiceDef* s) {
+  upb_StringView name;
+  size_t n;
+
+  // Must happen before _upb_DefBuilder_Add()
+  s->file = _upb_DefBuilder_File(ctx);
+
+  name = google_protobuf_ServiceDescriptorProto_name(svc_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+  const char* package = _upb_FileDef_RawPackage(s->file);
+  s->full_name = _upb_DefBuilder_MakeFullName(ctx, package, name);
+  _upb_DefBuilder_Add(ctx, s->full_name,
+                      _upb_DefType_Pack(s, UPB_DEFTYPE_SERVICE));
+
+  const google_protobuf_MethodDescriptorProto* const* methods =
+      google_protobuf_ServiceDescriptorProto_method(svc_proto, &n);
+  s->method_count = n;
+  s->methods = _upb_MethodDefs_New(ctx, n, methods, s);
+
+  UPB_DEF_SET_OPTIONS(s->opts, ServiceDescriptorProto, ServiceOptions,
+                      svc_proto);
+}
+
+upb_ServiceDef* _upb_ServiceDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_ServiceDescriptorProto* const* protos) {
+  _upb_DefType_CheckPadding(sizeof(upb_ServiceDef));
+
+  upb_ServiceDef* s = _upb_DefBuilder_Alloc(ctx, sizeof(upb_ServiceDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_service(ctx, protos[i], &s[i]);
+    s[i].index = i;
+  }
+  return s;
+}
+
+
+#include <string.h>
+
+
+// Must be last.
+
+// A few fake field types for our tables.
+enum {
+  kUpb_FakeFieldType_FieldNotFound = 0,
+  kUpb_FakeFieldType_MessageSetItem = 19,
+};
+
+// DecodeOp: an action to be performed for a wire-type/field-type combination.
+enum {
+  // Special ops: we don't write data to regular fields for these.
+  kUpb_DecodeOp_UnknownField = -1,
+  kUpb_DecodeOp_MessageSetItem = -2,
+
+  // Scalar-only ops.
+  kUpb_DecodeOp_Scalar1Byte = 0,
+  kUpb_DecodeOp_Scalar4Byte = 2,
+  kUpb_DecodeOp_Scalar8Byte = 3,
+  kUpb_DecodeOp_Enum = 1,
+
+  // Scalar/repeated ops.
+  kUpb_DecodeOp_String = 4,
+  kUpb_DecodeOp_Bytes = 5,
+  kUpb_DecodeOp_SubMessage = 6,
+
+  // Repeated-only ops (also see macros below).
+  kUpb_DecodeOp_PackedEnum = 13,
+};
+
+// For packed fields it is helpful to be able to recover the lg2 of the data
+// size from the 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] */
+
+typedef union {
+  bool bool_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  uint32_t size;
+} wireval;
+
+static const char* _upb_Decoder_DecodeMessage(upb_Decoder* d, const char* ptr,
+                                              upb_Message* msg,
+                                              const upb_MiniTable* layout);
+
+UPB_NORETURN static void* _upb_Decoder_ErrorJmp(upb_Decoder* d,
+                                                upb_DecodeStatus status) {
+  assert(status != kUpb_DecodeStatus_Ok);
+  UPB_LONGJMP(d->err, status);
+}
+
+const char* _upb_FastDecoder_ErrorJmp(upb_Decoder* d, int status) {
+  assert(status != kUpb_DecodeStatus_Ok);
+  UPB_LONGJMP(d->err, status);
+  return NULL;
+}
+static void _upb_Decoder_VerifyUtf8(upb_Decoder* d, const char* buf, int len) {
+  if (!_upb_Decoder_VerifyUtf8Inline(buf, len)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);
+  }
+}
+
+static bool _upb_Decoder_Reserve(upb_Decoder* d, upb_Array* arr, size_t elem) {
+  bool need_realloc = arr->capacity - arr->size < elem;
+  if (need_realloc && !_upb_array_realloc(arr, arr->size + elem, &d->arena)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+  return need_realloc;
+}
+
+typedef struct {
+  const char* ptr;
+  uint64_t val;
+} _upb_DecodeLongVarintReturn;
+
+UPB_NOINLINE
+static _upb_DecodeLongVarintReturn _upb_Decoder_DecodeLongVarint(
+    const char* ptr, uint64_t val) {
+  _upb_DecodeLongVarintReturn 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* _upb_Decoder_DecodeVarint(upb_Decoder* 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 {
+    _upb_DecodeLongVarintReturn res = _upb_Decoder_DecodeLongVarint(ptr, byte);
+    if (!res.ptr) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeTag(upb_Decoder* 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;
+    _upb_DecodeLongVarintReturn res = _upb_Decoder_DecodeLongVarint(ptr, byte);
+    if (!res.ptr || res.ptr - start > 5 || res.val > UINT32_MAX) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+    }
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char* upb_Decoder_DecodeSize(upb_Decoder* d, const char* ptr,
+                                          uint32_t* size) {
+  uint64_t size64;
+  ptr = _upb_Decoder_DecodeVarint(d, ptr, &size64);
+  if (size64 >= INT32_MAX || ptr - d->end + (int)size64 > d->limit) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  *size = size64;
+  return ptr;
+}
+
+static void _upb_Decoder_MungeInt32(wireval* val) {
+  if (!_upb_IsLittleEndian()) {
+    /* The next stage will memcpy(dst, &val, 4) */
+    val->uint32_val = val->uint64_val;
+  }
+}
+
+static void _upb_Decoder_Munge(int type, wireval* val) {
+  switch (type) {
+    case kUpb_FieldType_Bool:
+      val->bool_val = val->uint64_val != 0;
+      break;
+    case kUpb_FieldType_SInt32: {
+      uint32_t n = val->uint64_val;
+      val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
+      break;
+    }
+    case kUpb_FieldType_SInt64: {
+      uint64_t n = val->uint64_val;
+      val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
+      break;
+    }
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_UInt32:
+    case kUpb_FieldType_Enum:
+      _upb_Decoder_MungeInt32(val);
+      break;
+  }
+}
+
+static upb_Message* _upb_Decoder_NewSubMessage(
+    upb_Decoder* d, const upb_MiniTableSub* subs,
+    const upb_MiniTableField* field) {
+  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
+  UPB_ASSERT(subl);
+  upb_Message* msg = _upb_Message_New(subl, &d->arena);
+  if (!msg) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  return msg;
+}
+
+UPB_NOINLINE
+const char* _upb_Decoder_IsDoneFallback(upb_Decoder* d, const char* ptr,
+                                        int overrun) {
+  int status;
+  ptr = _upb_Decoder_IsDoneFallbackInline(d, ptr, overrun, &status);
+  if (ptr == NULL) _upb_Decoder_ErrorJmp(d, status);
+  return ptr;
+}
+
+static const char* _upb_Decoder_ReadString(upb_Decoder* d, const char* ptr,
+                                           int size, upb_StringView* str) {
+  if (d->options & kUpb_DecodeOption_AliasString) {
+    str->data = ptr;
+  } else {
+    char* data = upb_Arena_Malloc(&d->arena, size);
+    if (!data) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    memcpy(data, ptr, size);
+    str->data = data;
+  }
+  str->size = size;
+  return ptr + size;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_RecurseSubMessage(upb_Decoder* d,
+                                                  const char* ptr,
+                                                  upb_Message* submsg,
+                                                  const upb_MiniTable* subl,
+                                                  uint32_t expected_end_group) {
+  if (--d->depth < 0) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded);
+  }
+  ptr = _upb_Decoder_DecodeMessage(d, ptr, submsg, subl);
+  d->depth++;
+  if (d->end_group != expected_end_group) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeSubMessage(
+    upb_Decoder* d, const char* ptr, upb_Message* submsg,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field, int size) {
+  int saved_delta = _upb_Decoder_PushLimit(d, ptr, size);
+  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
+  UPB_ASSERT(subl);
+  ptr = _upb_Decoder_RecurseSubMessage(d, ptr, submsg, subl, DECODE_NOGROUP);
+  _upb_Decoder_PopLimit(d, ptr, saved_delta);
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeGroup(upb_Decoder* d, const char* ptr,
+                                            upb_Message* submsg,
+                                            const upb_MiniTable* subl,
+                                            uint32_t number) {
+  if (_upb_Decoder_IsDone(d, &ptr)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  ptr = _upb_Decoder_RecurseSubMessage(d, ptr, submsg, subl, number);
+  d->end_group = DECODE_NOGROUP;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeUnknownGroup(upb_Decoder* d,
+                                                   const char* ptr,
+                                                   uint32_t number) {
+  return _upb_Decoder_DecodeGroup(d, ptr, NULL, NULL, number);
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeKnownGroup(
+    upb_Decoder* d, const char* ptr, upb_Message* submsg,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field) {
+  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
+  UPB_ASSERT(subl);
+  return _upb_Decoder_DecodeGroup(d, ptr, submsg, subl, field->number);
+}
+
+static char* upb_Decoder_EncodeVarint32(uint32_t val, char* ptr) {
+  do {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    *(ptr++) = byte;
+  } while (val);
+  return ptr;
+}
+
+static void _upb_Decoder_AddUnknownVarints(upb_Decoder* d, upb_Message* msg,
+                                           uint32_t val1, uint32_t val2) {
+  char buf[20];
+  char* end = buf;
+  end = upb_Decoder_EncodeVarint32(val1, end);
+  end = upb_Decoder_EncodeVarint32(val2, end);
+
+  if (!_upb_Message_AddUnknown(msg, buf, end - buf, &d->arena)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+}
+
+UPB_NOINLINE
+static bool _upb_Decoder_CheckEnumSlow(upb_Decoder* d, const char* ptr,
+                                       upb_Message* msg,
+                                       const upb_MiniTableEnum* e,
+                                       const upb_MiniTableField* field,
+                                       uint32_t v) {
+  if (_upb_MiniTable_CheckEnumValueSlow(e, v)) return true;
+
+  // Unrecognized enum goes into unknown fields.
+  // For packed fields the tag could be arbitrarily far in the past, so we
+  // just re-encode the tag and value here.
+  uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Varint;
+  upb_Message* unknown_msg =
+      field->mode & kUpb_LabelFlags_IsExtension ? d->unknown_msg : msg;
+  _upb_Decoder_AddUnknownVarints(d, unknown_msg, tag, v);
+  return false;
+}
+
+UPB_FORCEINLINE
+static bool _upb_Decoder_CheckEnum(upb_Decoder* d, const char* ptr,
+                                   upb_Message* msg, const upb_MiniTableEnum* e,
+                                   const upb_MiniTableField* field,
+                                   wireval* val) {
+  uint32_t v = val->uint32_val;
+
+  _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, v);
+  if (UPB_LIKELY(status == _kUpb_FastEnumCheck_ValueIsInEnum)) return true;
+  return _upb_Decoder_CheckEnumSlow(d, ptr, msg, e, field, v);
+}
+
+UPB_NOINLINE
+static const char* _upb_Decoder_DecodeEnumArray(upb_Decoder* d, const char* ptr,
+                                                upb_Message* msg,
+                                                upb_Array* arr,
+                                                const upb_MiniTableSub* subs,
+                                                const upb_MiniTableField* field,
+                                                wireval* val) {
+  const upb_MiniTableEnum* e = subs[field->submsg_index].subenum;
+  if (!_upb_Decoder_CheckEnum(d, ptr, msg, e, field, val)) return ptr;
+  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->size * 4, void);
+  arr->size++;
+  memcpy(mem, val, 4);
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeFixedPacked(
+    upb_Decoder* d, const char* ptr, upb_Array* arr, wireval* val,
+    const upb_MiniTableField* field, int lg2) {
+  int mask = (1 << lg2) - 1;
+  size_t count = val->size >> lg2;
+  if ((val->size & mask) != 0) {
+    // Length isn't a round multiple of elem size.
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  _upb_Decoder_Reserve(d, arr, count);
+  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << lg2, void);
+  arr->size += count;
+  // Note: if/when the decoder supports multi-buffer input, we will need to
+  // handle buffer seams here.
+  if (_upb_IsLittleEndian()) {
+    memcpy(mem, ptr, val->size);
+    ptr += val->size;
+  } else {
+    const char* end = ptr + val->size;
+    char* dst = mem;
+    while (ptr < end) {
+      if (lg2 == 2) {
+        uint32_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap32(val);
+        memcpy(dst, &val, sizeof(val));
+      } else {
+        UPB_ASSERT(lg2 == 3);
+        uint64_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap64(val);
+        memcpy(dst, &val, sizeof(val));
+      }
+      ptr += 1 << lg2;
+      dst += 1 << lg2;
+    }
+  }
+
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeVarintPacked(
+    upb_Decoder* d, const char* ptr, upb_Array* arr, wireval* val,
+    const upb_MiniTableField* field, int lg2) {
+  int scale = 1 << lg2;
+  int saved_limit = _upb_Decoder_PushLimit(d, ptr, val->size);
+  char* out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << lg2, void);
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    wireval elem;
+    ptr = _upb_Decoder_DecodeVarint(d, ptr, &elem.uint64_val);
+    _upb_Decoder_Munge(field->descriptortype, &elem);
+    if (_upb_Decoder_Reserve(d, arr, 1)) {
+      out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << lg2, void);
+    }
+    arr->size++;
+    memcpy(out, &elem, scale);
+    out += scale;
+  }
+  _upb_Decoder_PopLimit(d, ptr, saved_limit);
+  return ptr;
+}
+
+UPB_NOINLINE
+static const char* _upb_Decoder_DecodeEnumPacked(
+    upb_Decoder* d, const char* ptr, upb_Message* msg, upb_Array* arr,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field,
+    wireval* val) {
+  const upb_MiniTableEnum* e = subs[field->submsg_index].subenum;
+  int saved_limit = _upb_Decoder_PushLimit(d, ptr, val->size);
+  char* out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size * 4, void);
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    wireval elem;
+    ptr = _upb_Decoder_DecodeVarint(d, ptr, &elem.uint64_val);
+    _upb_Decoder_MungeInt32(&elem);
+    if (!_upb_Decoder_CheckEnum(d, ptr, msg, e, field, &elem)) {
+      continue;
+    }
+    if (_upb_Decoder_Reserve(d, arr, 1)) {
+      out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size * 4, void);
+    }
+    arr->size++;
+    memcpy(out, &elem, 4);
+    out += 4;
+  }
+  _upb_Decoder_PopLimit(d, ptr, saved_limit);
+  return ptr;
+}
+
+upb_Array* _upb_Decoder_CreateArray(upb_Decoder* d,
+                                    const upb_MiniTableField* field) {
+  /* Maps descriptor type -> elem_size_lg2.  */
+  static const uint8_t kElemSizeLg2[] = {
+      [0] = -1,  // invalid descriptor type
+      [kUpb_FieldType_Double] = 3,
+      [kUpb_FieldType_Float] = 2,
+      [kUpb_FieldType_Int64] = 3,
+      [kUpb_FieldType_UInt64] = 3,
+      [kUpb_FieldType_Int32] = 2,
+      [kUpb_FieldType_Fixed64] = 3,
+      [kUpb_FieldType_Fixed32] = 2,
+      [kUpb_FieldType_Bool] = 0,
+      [kUpb_FieldType_String] = UPB_SIZE(3, 4),
+      [kUpb_FieldType_Group] = UPB_SIZE(2, 3),
+      [kUpb_FieldType_Message] = UPB_SIZE(2, 3),
+      [kUpb_FieldType_Bytes] = UPB_SIZE(3, 4),
+      [kUpb_FieldType_UInt32] = 2,
+      [kUpb_FieldType_Enum] = 2,
+      [kUpb_FieldType_SFixed32] = 2,
+      [kUpb_FieldType_SFixed64] = 3,
+      [kUpb_FieldType_SInt32] = 2,
+      [kUpb_FieldType_SInt64] = 3,
+  };
+
+  size_t lg2 = kElemSizeLg2[field->descriptortype];
+  upb_Array* ret = _upb_Array_New(&d->arena, 4, lg2);
+  if (!ret) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  return ret;
+}
+
+static const char* _upb_Decoder_DecodeToArray(upb_Decoder* d, const char* ptr,
+                                              upb_Message* msg,
+                                              const upb_MiniTableSub* subs,
+                                              const upb_MiniTableField* field,
+                                              wireval* val, int op) {
+  upb_Array** arrp = UPB_PTR_AT(msg, field->offset, void);
+  upb_Array* arr = *arrp;
+  void* mem;
+
+  if (arr) {
+    _upb_Decoder_Reserve(d, arr, 1);
+  } else {
+    arr = _upb_Decoder_CreateArray(d, field);
+    *arrp = arr;
+  }
+
+  switch (op) {
+    case kUpb_DecodeOp_Scalar1Byte:
+    case kUpb_DecodeOp_Scalar4Byte:
+    case kUpb_DecodeOp_Scalar8Byte:
+      /* Append scalar value. */
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << op, void);
+      arr->size++;
+      memcpy(mem, val, 1 << op);
+      return ptr;
+    case kUpb_DecodeOp_String:
+      _upb_Decoder_VerifyUtf8(d, ptr, val->size);
+      /* Fallthrough. */
+    case kUpb_DecodeOp_Bytes: {
+      /* Append bytes. */
+      upb_StringView* str = (upb_StringView*)_upb_array_ptr(arr) + arr->size;
+      arr->size++;
+      return _upb_Decoder_ReadString(d, ptr, val->size, str);
+    }
+    case kUpb_DecodeOp_SubMessage: {
+      /* Append submessage / group. */
+      upb_Message* submsg = _upb_Decoder_NewSubMessage(d, subs, field);
+      *UPB_PTR_AT(_upb_array_ptr(arr), arr->size * sizeof(void*),
+                  upb_Message*) = submsg;
+      arr->size++;
+      if (UPB_UNLIKELY(field->descriptortype == kUpb_FieldType_Group)) {
+        return _upb_Decoder_DecodeKnownGroup(d, ptr, submsg, subs, field);
+      } else {
+        return _upb_Decoder_DecodeSubMessage(d, ptr, submsg, subs, field,
+                                             val->size);
+      }
+    }
+    case OP_FIXPCK_LG2(2):
+    case OP_FIXPCK_LG2(3):
+      return _upb_Decoder_DecodeFixedPacked(d, ptr, arr, val, field,
+                                            op - OP_FIXPCK_LG2(0));
+    case OP_VARPCK_LG2(0):
+    case OP_VARPCK_LG2(2):
+    case OP_VARPCK_LG2(3):
+      return _upb_Decoder_DecodeVarintPacked(d, ptr, arr, val, field,
+                                             op - OP_VARPCK_LG2(0));
+    case kUpb_DecodeOp_Enum:
+      return _upb_Decoder_DecodeEnumArray(d, ptr, msg, arr, subs, field, val);
+    case kUpb_DecodeOp_PackedEnum:
+      return _upb_Decoder_DecodeEnumPacked(d, ptr, msg, arr, subs, field, val);
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d, const upb_MiniTable* entry) {
+  /* Maps descriptor type -> upb map size.  */
+  static const uint8_t kSizeInMap[] = {
+      [0] = -1,  // invalid descriptor type */
+      [kUpb_FieldType_Double] = 8,
+      [kUpb_FieldType_Float] = 4,
+      [kUpb_FieldType_Int64] = 8,
+      [kUpb_FieldType_UInt64] = 8,
+      [kUpb_FieldType_Int32] = 4,
+      [kUpb_FieldType_Fixed64] = 8,
+      [kUpb_FieldType_Fixed32] = 4,
+      [kUpb_FieldType_Bool] = 1,
+      [kUpb_FieldType_String] = UPB_MAPTYPE_STRING,
+      [kUpb_FieldType_Group] = sizeof(void*),
+      [kUpb_FieldType_Message] = sizeof(void*),
+      [kUpb_FieldType_Bytes] = UPB_MAPTYPE_STRING,
+      [kUpb_FieldType_UInt32] = 4,
+      [kUpb_FieldType_Enum] = 4,
+      [kUpb_FieldType_SFixed32] = 4,
+      [kUpb_FieldType_SFixed64] = 8,
+      [kUpb_FieldType_SInt32] = 4,
+      [kUpb_FieldType_SInt64] = 8,
+  };
+
+  const upb_MiniTableField* key_field = &entry->fields[0];
+  const upb_MiniTableField* val_field = &entry->fields[1];
+  char key_size = kSizeInMap[key_field->descriptortype];
+  char val_size = kSizeInMap[val_field->descriptortype];
+  UPB_ASSERT(key_field->offset == offsetof(upb_MapEntryData, k));
+  UPB_ASSERT(val_field->offset == offsetof(upb_MapEntryData, v));
+  upb_Map* ret = _upb_Map_New(&d->arena, key_size, val_size);
+  if (!ret) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  return ret;
+}
+
+static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr,
+                                            upb_Message* msg,
+                                            const upb_MiniTableSub* subs,
+                                            const upb_MiniTableField* field,
+                                            wireval* val) {
+  upb_Map** map_p = UPB_PTR_AT(msg, field->offset, upb_Map*);
+  upb_Map* map = *map_p;
+  upb_MapEntry ent;
+  const upb_MiniTable* entry = subs[field->submsg_index].submsg;
+
+  if (!map) {
+    map = _upb_Decoder_CreateMap(d, entry);
+    *map_p = map;
+  }
+
+  /* Parse map entry. */
+  memset(&ent, 0, sizeof(ent));
+
+  if (entry->fields[1].descriptortype == kUpb_FieldType_Message ||
+      entry->fields[1].descriptortype == kUpb_FieldType_Group) {
+    /* Create proactively to handle the case where it doesn't appear. */
+    ent.data.v.val =
+        upb_value_ptr(_upb_Message_New(entry->subs[0].submsg, &d->arena));
+  }
+
+  const char* start = ptr;
+  ptr =
+      _upb_Decoder_DecodeSubMessage(d, ptr, &ent.data, subs, field, val->size);
+  // check if ent had any unknown fields
+  size_t size;
+  upb_Message_GetUnknown(&ent.data, &size);
+  if (size != 0) {
+    uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Delimited;
+    _upb_Decoder_AddUnknownVarints(d, msg, tag, (uint32_t)(ptr - start));
+    if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+  } else {
+    if (_upb_Map_Insert(map, &ent.data.k, map->key_size, &ent.data.v,
+                        map->val_size,
+                        &d->arena) == kUpb_MapInsertStatus_OutOfMemory) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+  }
+  return ptr;
+}
+
+static const char* _upb_Decoder_DecodeToSubMessage(
+    upb_Decoder* d, const char* ptr, upb_Message* msg,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field, wireval* val,
+    int op) {
+  void* mem = UPB_PTR_AT(msg, field->offset, void);
+  int type = field->descriptortype;
+
+  if (UPB_UNLIKELY(op == kUpb_DecodeOp_Enum) &&
+      !_upb_Decoder_CheckEnum(d, ptr, msg, subs[field->submsg_index].subenum,
+                              field, val)) {
+    return ptr;
+  }
+
+  /* Set presence if necessary. */
+  if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  } else if (field->presence < 0) {
+    /* Oneof case */
+    uint32_t* oneof_case = _upb_oneofcase_field(msg, field);
+    if (op == kUpb_DecodeOp_SubMessage && *oneof_case != field->number) {
+      memset(mem, 0, sizeof(void*));
+    }
+    *oneof_case = field->number;
+  }
+
+  /* Store into message. */
+  switch (op) {
+    case kUpb_DecodeOp_SubMessage: {
+      upb_Message** submsgp = mem;
+      upb_Message* submsg = *submsgp;
+      if (!submsg) {
+        submsg = _upb_Decoder_NewSubMessage(d, subs, field);
+        *submsgp = submsg;
+      }
+      if (UPB_UNLIKELY(type == kUpb_FieldType_Group)) {
+        ptr = _upb_Decoder_DecodeKnownGroup(d, ptr, submsg, subs, field);
+      } else {
+        ptr = _upb_Decoder_DecodeSubMessage(d, ptr, submsg, subs, field,
+                                            val->size);
+      }
+      break;
+    }
+    case kUpb_DecodeOp_String:
+      _upb_Decoder_VerifyUtf8(d, ptr, val->size);
+      /* Fallthrough. */
+    case kUpb_DecodeOp_Bytes:
+      return _upb_Decoder_ReadString(d, ptr, val->size, mem);
+    case kUpb_DecodeOp_Scalar8Byte:
+      memcpy(mem, val, 8);
+      break;
+    case kUpb_DecodeOp_Enum:
+    case kUpb_DecodeOp_Scalar4Byte:
+      memcpy(mem, val, 4);
+      break;
+    case kUpb_DecodeOp_Scalar1Byte:
+      memcpy(mem, val, 1);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  return ptr;
+}
+
+UPB_NOINLINE
+const char* _upb_Decoder_CheckRequired(upb_Decoder* d, const char* ptr,
+                                       const upb_Message* msg,
+                                       const upb_MiniTable* l) {
+  assert(l->required_count);
+  if (UPB_LIKELY((d->options & kUpb_DecodeOption_CheckRequired) == 0)) {
+    return ptr;
+  }
+  uint64_t msg_head;
+  memcpy(&msg_head, msg, 8);
+  msg_head = _upb_BigEndian_Swap64(msg_head);
+  if (upb_MiniTable_requiredmask(l) & ~msg_head) {
+    d->missing_required = true;
+  }
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool _upb_Decoder_TryFastDispatch(upb_Decoder* d, const char** ptr,
+                                         upb_Message* msg,
+                                         const upb_MiniTable* layout) {
+#if UPB_FASTTABLE
+  if (layout && layout->table_mask != (unsigned char)-1) {
+    uint16_t tag = _upb_FastDecoder_LoadTag(*ptr);
+    intptr_t table = decode_totable(layout);
+    *ptr = _upb_FastDecoder_TagDispatch(d, *ptr, msg, table, 0, tag);
+    return true;
+  }
+#endif
+  return false;
+}
+
+static const char* upb_Decoder_SkipField(upb_Decoder* d, const char* ptr,
+                                         uint32_t tag) {
+  int field_number = tag >> 3;
+  int wire_type = tag & 7;
+  switch (wire_type) {
+    case kUpb_WireType_Varint: {
+      uint64_t val;
+      return _upb_Decoder_DecodeVarint(d, ptr, &val);
+    }
+    case kUpb_WireType_64Bit:
+      return ptr + 8;
+    case kUpb_WireType_32Bit:
+      return ptr + 4;
+    case kUpb_WireType_Delimited: {
+      uint32_t size;
+      ptr = upb_Decoder_DecodeSize(d, ptr, &size);
+      return ptr + size;
+    }
+    case kUpb_WireType_StartGroup:
+      return _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number);
+    default:
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+}
+
+enum {
+  kStartItemTag = ((kUpb_MsgSet_Item << 3) | kUpb_WireType_StartGroup),
+  kEndItemTag = ((kUpb_MsgSet_Item << 3) | kUpb_WireType_EndGroup),
+  kTypeIdTag = ((kUpb_MsgSet_TypeId << 3) | kUpb_WireType_Varint),
+  kMessageTag = ((kUpb_MsgSet_Message << 3) | kUpb_WireType_Delimited),
+};
+
+static void upb_Decoder_AddKnownMessageSetItem(
+    upb_Decoder* d, upb_Message* msg, const upb_MiniTableExtension* item_mt,
+    const char* data, uint32_t size) {
+  upb_Message_Extension* ext =
+      _upb_Message_GetOrCreateExtension(msg, item_mt, &d->arena);
+  if (UPB_UNLIKELY(!ext)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+  upb_Message* submsg =
+      _upb_Decoder_NewSubMessage(d, &ext->ext->sub, &ext->ext->field);
+  upb_DecodeStatus status = upb_Decode(data, size, submsg, item_mt->sub.submsg,
+                                       d->extreg, d->options, &d->arena);
+  memcpy(&ext->data, &submsg, sizeof(submsg));
+  if (status != kUpb_DecodeStatus_Ok) _upb_Decoder_ErrorJmp(d, status);
+}
+
+static void upb_Decoder_AddUnknownMessageSetItem(upb_Decoder* d,
+                                                 upb_Message* msg,
+                                                 uint32_t type_id,
+                                                 const char* message_data,
+                                                 uint32_t message_size) {
+  char buf[60];
+  char* ptr = buf;
+  ptr = upb_Decoder_EncodeVarint32(kStartItemTag, ptr);
+  ptr = upb_Decoder_EncodeVarint32(kTypeIdTag, ptr);
+  ptr = upb_Decoder_EncodeVarint32(type_id, ptr);
+  ptr = upb_Decoder_EncodeVarint32(kMessageTag, ptr);
+  ptr = upb_Decoder_EncodeVarint32(message_size, ptr);
+  char* split = ptr;
+
+  ptr = upb_Decoder_EncodeVarint32(kEndItemTag, ptr);
+  char* end = ptr;
+
+  if (!_upb_Message_AddUnknown(msg, buf, split - buf, &d->arena) ||
+      !_upb_Message_AddUnknown(msg, message_data, message_size, &d->arena) ||
+      !_upb_Message_AddUnknown(msg, split, end - split, &d->arena)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+}
+
+static void upb_Decoder_AddMessageSetItem(upb_Decoder* d, upb_Message* msg,
+                                          const upb_MiniTable* t,
+                                          uint32_t type_id, const char* data,
+                                          uint32_t size) {
+  const upb_MiniTableExtension* item_mt =
+      upb_ExtensionRegistry_Lookup(d->extreg, t, type_id);
+  if (item_mt) {
+    upb_Decoder_AddKnownMessageSetItem(d, msg, item_mt, data, size);
+  } else {
+    upb_Decoder_AddUnknownMessageSetItem(d, msg, type_id, data, size);
+  }
+}
+
+static const char* upb_Decoder_DecodeMessageSetItem(
+    upb_Decoder* d, const char* ptr, upb_Message* msg,
+    const upb_MiniTable* layout) {
+  uint32_t type_id = 0;
+  upb_StringView preserved = {NULL, 0};
+  typedef enum {
+    kUpb_HaveId = 1 << 0,
+    kUpb_HavePayload = 1 << 1,
+  } StateMask;
+  StateMask state_mask = 0;
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    uint32_t tag;
+    ptr = _upb_Decoder_DecodeTag(d, ptr, &tag);
+    switch (tag) {
+      case kEndItemTag:
+        return ptr;
+      case kTypeIdTag: {
+        uint64_t tmp;
+        ptr = _upb_Decoder_DecodeVarint(d, ptr, &tmp);
+        if (state_mask & kUpb_HaveId) break;  // Ignore dup.
+        state_mask |= kUpb_HaveId;
+        type_id = tmp;
+        if (state_mask & kUpb_HavePayload) {
+          upb_Decoder_AddMessageSetItem(d, msg, layout, type_id, preserved.data,
+                                        preserved.size);
+        }
+        break;
+      }
+      case kMessageTag: {
+        uint32_t size;
+        ptr = upb_Decoder_DecodeSize(d, ptr, &size);
+        const char* data = ptr;
+        ptr += size;
+        if (state_mask & kUpb_HavePayload) break;  // Ignore dup.
+        state_mask |= kUpb_HavePayload;
+        if (state_mask & kUpb_HaveId) {
+          upb_Decoder_AddMessageSetItem(d, msg, layout, type_id, data, size);
+        } else {
+          // Out of order, we must preserve the payload.
+          preserved.data = data;
+          preserved.size = size;
+        }
+        break;
+      }
+      default:
+        // We do not preserve unexpected fields inside a message set item.
+        ptr = upb_Decoder_SkipField(d, ptr, tag);
+        break;
+    }
+  }
+  _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+}
+
+static const upb_MiniTableField* _upb_Decoder_FindField(upb_Decoder* d,
+                                                        const upb_MiniTable* t,
+                                                        uint32_t field_number,
+                                                        int* last_field_index) {
+  static upb_MiniTableField none = {
+      0, 0, 0, 0, kUpb_FakeFieldType_FieldNotFound, 0};
+  if (t == NULL) return &none;
+
+  size_t idx = ((size_t)field_number) - 1;  // 0 wraps to SIZE_MAX
+  if (idx < t->dense_below) {
+    /* Fastest case: index into dense fields. */
+    goto found;
+  }
+
+  if (t->dense_below < t->field_count) {
+    /* Linear search non-dense fields. Resume scanning from last_field_index
+     * since fields are usually in order. */
+    int last = *last_field_index;
+    for (idx = last; idx < t->field_count; idx++) {
+      if (t->fields[idx].number == field_number) {
+        goto found;
+      }
+    }
+
+    for (idx = t->dense_below; idx < last; idx++) {
+      if (t->fields[idx].number == field_number) {
+        goto found;
+      }
+    }
+  }
+
+  if (d->extreg) {
+    switch (t->ext) {
+      case kUpb_ExtMode_Extendable: {
+        const upb_MiniTableExtension* ext =
+            upb_ExtensionRegistry_Lookup(d->extreg, t, field_number);
+        if (ext) return &ext->field;
+        break;
+      }
+      case kUpb_ExtMode_IsMessageSet:
+        if (field_number == kUpb_MsgSet_Item) {
+          static upb_MiniTableField item = {
+              0, 0, 0, 0, kUpb_FakeFieldType_MessageSetItem, 0};
+          return &item;
+        }
+        break;
+    }
+  }
+
+  return &none; /* Unknown field. */
+
+found:
+  UPB_ASSERT(t->fields[idx].number == field_number);
+  *last_field_index = idx;
+  return &t->fields[idx];
+}
+
+int _upb_Decoder_GetVarintOp(const upb_MiniTableField* field) {
+  static const int8_t kVarintOps[] = {
+      [kUpb_FakeFieldType_FieldNotFound] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Double] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Float] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Int64] = kUpb_DecodeOp_Scalar8Byte,
+      [kUpb_FieldType_UInt64] = kUpb_DecodeOp_Scalar8Byte,
+      [kUpb_FieldType_Int32] = kUpb_DecodeOp_Scalar4Byte,
+      [kUpb_FieldType_Fixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Fixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Bool] = kUpb_DecodeOp_Scalar1Byte,
+      [kUpb_FieldType_String] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Group] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Message] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Bytes] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_UInt32] = kUpb_DecodeOp_Scalar4Byte,
+      [kUpb_FieldType_Enum] = kUpb_DecodeOp_Enum,
+      [kUpb_FieldType_SFixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SFixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SInt32] = kUpb_DecodeOp_Scalar4Byte,
+      [kUpb_FieldType_SInt64] = kUpb_DecodeOp_Scalar8Byte,
+      [kUpb_FakeFieldType_MessageSetItem] = kUpb_DecodeOp_UnknownField,
+  };
+
+  return kVarintOps[field->descriptortype];
+}
+
+int _upb_Decoder_GetDelimitedOp(const upb_MiniTable* mt,
+                                const upb_MiniTableField* field) {
+  enum { kRepeatedBase = 19 };
+
+  static const int8_t kDelimitedOps[] = {
+      /* For non-repeated field type. */
+      [kUpb_FakeFieldType_FieldNotFound] =
+          kUpb_DecodeOp_UnknownField,  // Field not found.
+      [kUpb_FieldType_Double] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Float] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Int64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_UInt64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Int32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Fixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Fixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Bool] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_String] = kUpb_DecodeOp_String,
+      [kUpb_FieldType_Group] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Message] = kUpb_DecodeOp_SubMessage,
+      [kUpb_FieldType_Bytes] = kUpb_DecodeOp_Bytes,
+      [kUpb_FieldType_UInt32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Enum] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SFixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SFixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SInt32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SInt64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FakeFieldType_MessageSetItem] = kUpb_DecodeOp_UnknownField,
+      // For repeated field type. */
+      [kRepeatedBase + kUpb_FieldType_Double] = OP_FIXPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_Float] = OP_FIXPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Int64] = OP_VARPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_UInt64] = OP_VARPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_Int32] = OP_VARPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Fixed64] = OP_FIXPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_Fixed32] = OP_FIXPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Bool] = OP_VARPCK_LG2(0),
+      [kRepeatedBase + kUpb_FieldType_String] = kUpb_DecodeOp_String,
+      [kRepeatedBase + kUpb_FieldType_Group] = kUpb_DecodeOp_SubMessage,
+      [kRepeatedBase + kUpb_FieldType_Message] = kUpb_DecodeOp_SubMessage,
+      [kRepeatedBase + kUpb_FieldType_Bytes] = kUpb_DecodeOp_Bytes,
+      [kRepeatedBase + kUpb_FieldType_UInt32] = OP_VARPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Enum] = kUpb_DecodeOp_PackedEnum,
+      [kRepeatedBase + kUpb_FieldType_SFixed32] = OP_FIXPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_SFixed64] = OP_FIXPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_SInt32] = OP_VARPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_SInt64] = OP_VARPCK_LG2(3),
+      // Omitting kUpb_FakeFieldType_MessageSetItem, because we never emit a
+      // repeated msgset type
+  };
+
+  int ndx = field->descriptortype;
+  if (upb_FieldMode_Get(field) == kUpb_FieldMode_Array) ndx += kRepeatedBase;
+  int op = kDelimitedOps[ndx];
+
+  // If sub-message is not linked, treat as unknown.
+  if (op == kUpb_DecodeOp_SubMessage &&
+      !(field->mode & kUpb_LabelFlags_IsExtension)) {
+    const upb_MiniTableSub* sub = &mt->subs[field->submsg_index];
+    if (!sub->submsg) {
+      op = kUpb_DecodeOp_UnknownField;
+    }
+  }
+
+  return op;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeWireValue(upb_Decoder* d, const char* ptr,
+                                                const upb_MiniTable* mt,
+                                                const upb_MiniTableField* field,
+                                                int wire_type, wireval* val,
+                                                int* op) {
+  static const unsigned kFixed32OkMask = (1 << kUpb_FieldType_Float) |
+                                         (1 << kUpb_FieldType_Fixed32) |
+                                         (1 << kUpb_FieldType_SFixed32);
+
+  static const unsigned kFixed64OkMask = (1 << kUpb_FieldType_Double) |
+                                         (1 << kUpb_FieldType_Fixed64) |
+                                         (1 << kUpb_FieldType_SFixed64);
+
+  switch (wire_type) {
+    case kUpb_WireType_Varint:
+      ptr = _upb_Decoder_DecodeVarint(d, ptr, &val->uint64_val);
+      *op = _upb_Decoder_GetVarintOp(field);
+      _upb_Decoder_Munge(field->descriptortype, val);
+      return ptr;
+    case kUpb_WireType_32Bit:
+      memcpy(&val->uint32_val, ptr, 4);
+      val->uint32_val = _upb_BigEndian_Swap32(val->uint32_val);
+      *op = kUpb_DecodeOp_Scalar4Byte;
+      if (((1 << field->descriptortype) & kFixed32OkMask) == 0) {
+        *op = kUpb_DecodeOp_UnknownField;
+      }
+      return ptr + 4;
+    case kUpb_WireType_64Bit:
+      memcpy(&val->uint64_val, ptr, 8);
+      val->uint64_val = _upb_BigEndian_Swap64(val->uint64_val);
+      *op = kUpb_DecodeOp_Scalar8Byte;
+      if (((1 << field->descriptortype) & kFixed64OkMask) == 0) {
+        *op = kUpb_DecodeOp_UnknownField;
+      }
+      return ptr + 8;
+    case kUpb_WireType_Delimited:
+      ptr = upb_Decoder_DecodeSize(d, ptr, &val->size);
+      *op = _upb_Decoder_GetDelimitedOp(mt, field);
+      return ptr;
+    case kUpb_WireType_StartGroup:
+      val->uint32_val = field->number;
+      if (field->descriptortype == kUpb_FieldType_Group) {
+        *op = kUpb_DecodeOp_SubMessage;
+      } else if (field->descriptortype == kUpb_FakeFieldType_MessageSetItem) {
+        *op = kUpb_DecodeOp_MessageSetItem;
+      } else {
+        *op = kUpb_DecodeOp_UnknownField;
+      }
+      return ptr;
+    default:
+      break;
+  }
+  _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeKnownField(
+    upb_Decoder* d, const char* ptr, upb_Message* msg,
+    const upb_MiniTable* layout, const upb_MiniTableField* field, int op,
+    wireval* val) {
+  const upb_MiniTableSub* subs = layout->subs;
+  uint8_t mode = field->mode;
+
+  if (UPB_UNLIKELY(mode & kUpb_LabelFlags_IsExtension)) {
+    const upb_MiniTableExtension* ext_layout =
+        (const upb_MiniTableExtension*)field;
+    upb_Message_Extension* ext =
+        _upb_Message_GetOrCreateExtension(msg, ext_layout, &d->arena);
+    if (UPB_UNLIKELY(!ext)) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+    d->unknown_msg = msg;
+    msg = &ext->data;
+    subs = &ext->ext->sub;
+  }
+
+  switch (mode & kUpb_FieldMode_Mask) {
+    case kUpb_FieldMode_Array:
+      return _upb_Decoder_DecodeToArray(d, ptr, msg, subs, field, val, op);
+    case kUpb_FieldMode_Map:
+      return _upb_Decoder_DecodeToMap(d, ptr, msg, subs, field, val);
+    case kUpb_FieldMode_Scalar:
+      return _upb_Decoder_DecodeToSubMessage(d, ptr, msg, subs, field, val, op);
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+static const char* _upb_Decoder_ReverseSkipVarint(const char* ptr,
+                                                  uint32_t val) {
+  uint32_t seen = 0;
+  do {
+    ptr--;
+    seen <<= 7;
+    seen |= *ptr & 0x7f;
+  } while (seen != val);
+  return ptr;
+}
+
+static const char* _upb_Decoder_DecodeUnknownField(upb_Decoder* d,
+                                                   const char* ptr,
+                                                   upb_Message* msg,
+                                                   int field_number,
+                                                   int wire_type, wireval val) {
+  if (field_number == 0) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+
+  // Since unknown fields are the uncommon case, we do a little extra work here
+  // to walk backwards through the buffer to find the field start.  This frees
+  // up a register in the fast paths (when the field is known), which leads to
+  // significant speedups in benchmarks.
+  const char* start = ptr;
+
+  if (wire_type == kUpb_WireType_Delimited) ptr += val.size;
+  if (msg) {
+    switch (wire_type) {
+      case kUpb_WireType_Varint:
+      case kUpb_WireType_Delimited:
+        start--;
+        while (start[-1] & 0x80) start--;
+        break;
+      case kUpb_WireType_32Bit:
+        start -= 4;
+        break;
+      case kUpb_WireType_64Bit:
+        start -= 8;
+        break;
+      default:
+        break;
+    }
+
+    assert(start == d->debug_valstart);
+    uint32_t tag = ((uint32_t)field_number << 3) | wire_type;
+    start = _upb_Decoder_ReverseSkipVarint(start, tag);
+    assert(start == d->debug_tagstart);
+
+    if (wire_type == kUpb_WireType_StartGroup) {
+      d->unknown = start;
+      d->unknown_msg = msg;
+      ptr = _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number);
+      start = d->unknown;
+      d->unknown = NULL;
+    }
+    if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+  } else if (wire_type == kUpb_WireType_StartGroup) {
+    ptr = _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number);
+  }
+  return ptr;
+}
+
+UPB_NOINLINE
+static const char* _upb_Decoder_DecodeMessage(upb_Decoder* d, const char* ptr,
+                                              upb_Message* msg,
+                                              const upb_MiniTable* layout) {
+  int last_field_index = 0;
+
+#if UPB_FASTTABLE
+  // The first time we want to skip fast dispatch, because we may have just been
+  // invoked by the fast parser to handle a case that it bailed on.
+  if (!_upb_Decoder_IsDone(d, &ptr)) goto nofast;
+#endif
+
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    uint32_t tag;
+    const upb_MiniTableField* field;
+    int field_number;
+    int wire_type;
+    wireval val;
+    int op;
+
+    if (_upb_Decoder_TryFastDispatch(d, &ptr, msg, layout)) break;
+
+#if UPB_FASTTABLE
+  nofast:
+#endif
+
+#ifndef NDEBUG
+    d->debug_tagstart = ptr;
+#endif
+
+    UPB_ASSERT(ptr < d->limit_ptr);
+    ptr = _upb_Decoder_DecodeTag(d, ptr, &tag);
+    field_number = tag >> 3;
+    wire_type = tag & 7;
+
+#ifndef NDEBUG
+    d->debug_valstart = ptr;
+#endif
+
+    if (wire_type == kUpb_WireType_EndGroup) {
+      d->end_group = field_number;
+      return ptr;
+    }
+
+    field = _upb_Decoder_FindField(d, layout, field_number, &last_field_index);
+    ptr = _upb_Decoder_DecodeWireValue(d, ptr, layout, field, wire_type, &val,
+                                       &op);
+
+    if (op >= 0) {
+      ptr = _upb_Decoder_DecodeKnownField(d, ptr, msg, layout, field, op, &val);
+    } else {
+      switch (op) {
+        case kUpb_DecodeOp_UnknownField:
+          ptr = _upb_Decoder_DecodeUnknownField(d, ptr, msg, field_number,
+                                                wire_type, val);
+          break;
+        case kUpb_DecodeOp_MessageSetItem:
+          ptr = upb_Decoder_DecodeMessageSetItem(d, ptr, msg, layout);
+          break;
+      }
+    }
+  }
+
+  return UPB_UNLIKELY(layout && layout->required_count)
+             ? _upb_Decoder_CheckRequired(d, ptr, msg, layout)
+             : ptr;
+}
+
+const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d,
+                                           const char* ptr, upb_Message* msg,
+                                           intptr_t table, uint64_t hasbits,
+                                           uint64_t data) {
+  (void)data;
+  *(uint32_t*)msg |= hasbits;
+  return _upb_Decoder_DecodeMessage(d, ptr, msg, decode_totablep(table));
+}
+
+static upb_DecodeStatus _upb_Decoder_DecodeTop(struct upb_Decoder* d,
+                                               const char* buf, void* msg,
+                                               const upb_MiniTable* l) {
+  if (!_upb_Decoder_TryFastDispatch(d, &buf, msg, l)) {
+    _upb_Decoder_DecodeMessage(d, buf, msg, l);
+  }
+  if (d->end_group != DECODE_NOGROUP) return kUpb_DecodeStatus_Malformed;
+  if (d->missing_required) return kUpb_DecodeStatus_MissingRequired;
+  return kUpb_DecodeStatus_Ok;
+}
+
+upb_DecodeStatus upb_Decode(const char* buf, size_t size, void* msg,
+                            const upb_MiniTable* l,
+                            const upb_ExtensionRegistry* extreg, int options,
+                            upb_Arena* arena) {
+  upb_Decoder state;
+  unsigned depth = (unsigned)options >> 16;
+
+  if (size <= 16) {
+    memset(&state.patch, 0, 32);
+    if (size) memcpy(&state.patch, buf, size);
+    buf = state.patch;
+    state.end = buf + size;
+    state.limit = 0;
+    options &= ~kUpb_DecodeOption_AliasString;  // Can't alias patch buf.
+  } else {
+    state.end = buf + size - 16;
+    state.limit = 16;
+  }
+
+  state.extreg = extreg;
+  state.limit_ptr = state.end;
+  state.unknown = NULL;
+  state.depth = depth ? depth : 64;
+  state.end_group = DECODE_NOGROUP;
+  state.options = (uint16_t)options;
+  state.missing_required = false;
+  state.arena.head = arena->head;
+  state.arena.last_size = arena->last_size;
+  state.arena.cleanup_metadata = arena->cleanup_metadata;
+  state.arena.parent = arena;
+
+  upb_DecodeStatus status = UPB_SETJMP(state.err);
+  if (UPB_LIKELY(status == kUpb_DecodeStatus_Ok)) {
+    status = _upb_Decoder_DecodeTop(&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 status;
+}
+
+#undef OP_FIXPCK_LG2
+#undef OP_VARPCK_LG2
+
+// 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_Decoder *d, const char *ptr, upb_Message *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 _upb_FastDecoder_DecodeGeneric(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;
+  int status;
+  ptr = _upb_Decoder_IsDoneFallbackInline(d, ptr, overrun, &status);
+  if (ptr == NULL) _upb_FastDecoder_ErrorJmp(d, status);
+  data = _upb_FastDecoder_LoadTag(ptr);
+  UPB_MUSTTAIL return _upb_FastDecoder_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.
+      const upb_MiniTable* l = decode_totablep(table);
+      return UPB_UNLIKELY(l->required_count)
+                 ? _upb_Decoder_CheckRequired(d, ptr, msg, l)
+                 : 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 = _upb_FastDecoder_LoadTag(ptr);
+  UPB_MUSTTAIL return _upb_FastDecoder_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_Decoder* d, const char* ptr,
+                                         void* ctx);
+
+UPB_FORCEINLINE
+static const char* fastdecode_delimited(upb_Decoder* 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 = _upb_Decoder_PushLimit(d, ptr, len);
+    ptr = func(d, ptr, ctx);
+    _upb_Decoder_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_Decoder* d, void* dst,
+                                  fastdecode_arr* farr, int valbytes) {
+  if (UPB_UNLIKELY(dst == farr->end)) {
+    size_t old_size = farr->arr->capacity;
+    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->capacity = 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->size =
+      (size_t)((char*)dst - (char*)_upb_array_ptr(farr->arr)) / valbytes;
+}
+
+UPB_FORCEINLINE
+static fastdecode_nextret fastdecode_nextrepeated(upb_Decoder* 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(!_upb_Decoder_IsDone(d, ptr))) {
+    ret.tag = _upb_FastDecoder_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_Message* msg, uint64_t data) {
+  size_t ofs = data >> 48;
+  return (char*)msg + ofs;
+}
+
+UPB_FORCEINLINE
+static void* fastdecode_getfield(upb_Decoder* d, const char* ptr,
+                                 upb_Message* 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->capacity * valbytes);
+      *data = _upb_FastDecoder_LoadTag(ptr);
+      return begin + (farr->arr->size * 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) _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);  \
+  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 _upb_FastDecoder_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_Decoder* d, const char* ptr,
+                                             void* ctx) {
+  fastdecode_varintdata* data = ctx;
+  void* dst = data->dst;
+  uint64_t val;
+
+  while (!_upb_Decoder_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)) {                                           \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);               \
+  }                                                                          \
+                                                                             \
+  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 _upb_FastDecoder_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)) {                               \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);              \
+  }                                                                         \
+                                                                            \
+  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) {                                                             \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);            \
+    }                                                                       \
+  } else {                                                                  \
+    _upb_Array_Resize(arr, elems, &d->arena);                               \
+  }                                                                         \
+                                                                            \
+  char* dst = _upb_array_ptr(arr);                                          \
+  memcpy(dst, ptr, size);                                                   \
+  arr->size = 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_Decoder* d,
+                                            const char* ptr, upb_Message* msg,
+                                            const upb_MiniTable* table,
+                                            uint64_t hasbits,
+                                            upb_StringView* dst);
+
+UPB_NOINLINE
+static const char* fastdecode_verifyutf8(upb_Decoder* d, const char* ptr,
+                                         upb_Message* msg, intptr_t table,
+                                         uint64_t hasbits, uint64_t data) {
+  upb_StringView* dst = (upb_StringView*)data;
+  if (!_upb_Decoder_VerifyUtf8Inline(dst->data, dst->size)) {
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);
+  }
+  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;                                                             \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);                 \
+  }                                                                            \
+                                                                               \
+  if (d->options & kUpb_DecodeOption_AliasString) {                            \
+    dst->data = ptr;                                                           \
+    dst->size = size;                                                          \
+  } else {                                                                     \
+    char* data = upb_Arena_Malloc(&d->arena, size);                            \
+    if (!data) {                                                               \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);             \
+    }                                                                          \
+    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_Decoder* d,
+                                              const char* ptr, upb_Message* msg,
+                                              intptr_t table, uint64_t hasbits,
+                                              uint64_t data) {
+  upb_StringView* dst = (upb_StringView*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
+}
+
+UPB_NOINLINE
+static const char* fastdecode_longstring_noutf8(
+    struct upb_Decoder* d, const char* ptr, upb_Message* msg, intptr_t table,
+    uint64_t hasbits, uint64_t data) {
+  upb_StringView* dst = (upb_StringView*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
+}
+
+UPB_FORCEINLINE
+static void fastdecode_docopy(upb_Decoder* d, const char* ptr, uint32_t size,
+                              int copy, char* data, upb_StringView* 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_StringView* dst;                                                        \
+  fastdecode_arr farr;                                                        \
+  int64_t size;                                                               \
+  size_t arena_has;                                                           \
+  size_t common_has;                                                          \
+  char* buf;                                                                  \
+                                                                              \
+  UPB_ASSERT((d->options & kUpb_DecodeOption_AliasString) == 0);              \
+  UPB_ASSERT(fastdecode_checktag(data, tagbytes));                            \
+                                                                              \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,              \
+                            sizeof(upb_StringView), card);                    \
+                                                                              \
+  again:                                                                      \
+  if (card == CARD_r) {                                                       \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));        \
+  }                                                                           \
+                                                                              \
+  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 &&                                                      \
+        !_upb_Decoder_VerifyUtf8Inline(dst->data, dst->size)) {               \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);                \
+    }                                                                         \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                         \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));         \
+    switch (ret.next) {                                                       \
+      case FD_NEXT_SAMEFIELD:                                                 \
+        dst = ret.dst;                                                        \
+        goto again;                                                           \
+      case FD_NEXT_OTHERFIELD:                                                \
+        data = ret.tag;                                                       \
+        UPB_MUSTTAIL return _upb_FastDecoder_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:                                                                    \
+  if (card == CARD_r) {                                                       \
+    fastdecode_commitarr(dst + 1, &farr, sizeof(upb_StringView));             \
+  }                                                                           \
+  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_StringView* 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->options & kUpb_DecodeOption_AliasString) == 0)) {       \
+    UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS);                              \
+  }                                                                            \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
+                            sizeof(upb_StringView), card);                     \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));         \
+  }                                                                            \
+                                                                               \
+  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 &&                                                       \
+        !_upb_Decoder_VerifyUtf8Inline(dst->data, dst->size)) {                \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);                 \
+    }                                                                          \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));          \
+    switch (ret.next) {                                                        \
+      case FD_NEXT_SAMEFIELD:                                                  \
+        dst = ret.dst;                                                         \
+        if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
+          /* 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_StringView));            \
+          data = ret.tag;                                                      \
+          UPB_MUSTTAIL return _upb_FastDecoder_TagDispatch(UPB_PARSE_ARGS);    \
+        }                                                                      \
+        goto again;                                                            \
+      case FD_NEXT_OTHERFIELD:                                                 \
+        data = ret.tag;                                                        \
+        UPB_MUSTTAIL return _upb_FastDecoder_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_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* l,
+                                int msg_ceil_bytes) {
+  size_t size = l->size + sizeof(upb_Message_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_Message_Internal);
+}
+
+typedef struct {
+  intptr_t table;
+  upb_Message* msg;
+} fastdecode_submsgdata;
+
+UPB_FORCEINLINE
+static const char* fastdecode_tosubmsg(upb_Decoder* 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) {                                                  \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded);     \
+  }                                                                       \
+                                                                          \
+  upb_Message** dst;                                                      \
+  uint32_t submsg_idx = (data >> 16) & 0xff;                              \
+  const upb_MiniTable* tablep = decode_totablep(table);                   \
+  const upb_MiniTable* subtablep = tablep->subs[submsg_idx].submsg;       \
+  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_Message*), card);                  \
+                                                                          \
+  if (card == CARD_s) {                                                   \
+    *(uint32_t*)msg |= hasbits;                                           \
+    hasbits = 0;                                                          \
+  }                                                                       \
+                                                                          \
+  again:                                                                  \
+  if (card == CARD_r) {                                                   \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*));      \
+  }                                                                       \
+                                                                          \
+  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)) {      \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);            \
+  }                                                                       \
+                                                                          \
+  if (card == CARD_r) {                                                   \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                     \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*));       \
+    switch (ret.next) {                                                   \
+      case FD_NEXT_SAMEFIELD:                                             \
+        dst = ret.dst;                                                    \
+        goto again;                                                       \
+      case FD_NEXT_OTHERFIELD:                                            \
+        d->depth++;                                                       \
+        data = ret.tag;                                                   \
+        UPB_MUSTTAIL return _upb_FastDecoder_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 */
+
+// We encode backwards, to avoid pre-computing lengths (one-pass encode).
+
+
+#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_Arena* arena;
+  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_EncodeStatus s) {
+  UPB_LONGJMP(e->err, s);
+}
+
+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_Arena_Realloc(e->arena, e->buf, old_size, new_size);
+
+  if (!new_buf) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
+
+  // We want previous data at the end, realloc() put it at the beginning.
+  // TODO(salo): This is somewhat inefficient since we are copying twice.
+  // Maybe create a realloc() that copies to the end of the new buffer?
+  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_BigEndian_Swap64(val);
+  encode_bytes(e, &val, sizeof(uint64_t));
+}
+
+static void encode_fixed32(upb_encstate* e, uint32_t val) {
+  val = _upb_BigEndian_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->size * elem_size;
+  const char* data = _upb_array_constptr(arr);
+  const char* ptr = data + bytes - elem_size;
+
+  if (tag || !_upb_IsLittleEndian()) {
+    while (true) {
+      if (elem_size == 4) {
+        uint32_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap32(val);
+        encode_bytes(e, &val, elem_size);
+      } else {
+        UPB_ASSERT(elem_size == 8);
+        uint64_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap64(val);
+        encode_bytes(e, &val, elem_size);
+      }
+
+      if (tag) 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 upb_Message* msg,
+                           const upb_MiniTable* m, size_t* size);
+
+static void encode_scalar(upb_encstate* e, const void* _field_mem,
+                          const upb_MiniTableSub* subs,
+                          const upb_MiniTableField* f) {
+  const char* field_mem = _field_mem;
+  int wire_type;
+
+#define CASE(ctype, type, wtype, encodeval) \
+  {                                         \
+    ctype val = *(ctype*)field_mem;         \
+    encode_##type(e, encodeval);            \
+    wire_type = wtype;                      \
+    break;                                  \
+  }
+
+  switch (f->descriptortype) {
+    case kUpb_FieldType_Double:
+      CASE(double, double, kUpb_WireType_64Bit, val);
+    case kUpb_FieldType_Float:
+      CASE(float, float, kUpb_WireType_32Bit, val);
+    case kUpb_FieldType_Int64:
+    case kUpb_FieldType_UInt64:
+      CASE(uint64_t, varint, kUpb_WireType_Varint, val);
+    case kUpb_FieldType_UInt32:
+      CASE(uint32_t, varint, kUpb_WireType_Varint, val);
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_Enum:
+      CASE(int32_t, varint, kUpb_WireType_Varint, (int64_t)val);
+    case kUpb_FieldType_SFixed64:
+    case kUpb_FieldType_Fixed64:
+      CASE(uint64_t, fixed64, kUpb_WireType_64Bit, val);
+    case kUpb_FieldType_Fixed32:
+    case kUpb_FieldType_SFixed32:
+      CASE(uint32_t, fixed32, kUpb_WireType_32Bit, val);
+    case kUpb_FieldType_Bool:
+      CASE(bool, varint, kUpb_WireType_Varint, val);
+    case kUpb_FieldType_SInt32:
+      CASE(int32_t, varint, kUpb_WireType_Varint, encode_zz32(val));
+    case kUpb_FieldType_SInt64:
+      CASE(int64_t, varint, kUpb_WireType_Varint, encode_zz64(val));
+    case kUpb_FieldType_String:
+    case kUpb_FieldType_Bytes: {
+      upb_StringView view = *(upb_StringView*)field_mem;
+      encode_bytes(e, view.data, view.size);
+      encode_varint(e, view.size);
+      wire_type = kUpb_WireType_Delimited;
+      break;
+    }
+    case kUpb_FieldType_Group: {
+      size_t size;
+      void* submsg = *(void**)field_mem;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      encode_tag(e, f->number, kUpb_WireType_EndGroup);
+      encode_message(e, submsg, subm, &size);
+      wire_type = kUpb_WireType_StartGroup;
+      e->depth++;
+      break;
+    }
+    case kUpb_FieldType_Message: {
+      size_t size;
+      void* submsg = *(void**)field_mem;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      encode_message(e, submsg, subm, &size);
+      encode_varint(e, size);
+      wire_type = kUpb_WireType_Delimited;
+      e->depth++;
+      break;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+#undef CASE
+
+  encode_tag(e, f->number, wire_type);
+}
+
+static void encode_array(upb_encstate* e, const upb_Message* msg,
+                         const upb_MiniTableSub* subs,
+                         const upb_MiniTableField* f) {
+  const upb_Array* arr = *UPB_PTR_AT(msg, f->offset, upb_Array*);
+  bool packed = f->mode & kUpb_LabelFlags_IsPacked;
+  size_t pre_len = e->limit - e->ptr;
+
+  if (arr == NULL || arr->size == 0) {
+    return;
+  }
+
+#define VARINT_CASE(ctype, encode)                                       \
+  {                                                                      \
+    const ctype* start = _upb_array_constptr(arr);                       \
+    const ctype* ptr = start + arr->size;                                \
+    uint32_t tag = packed ? 0 : (f->number << 3) | kUpb_WireType_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 kUpb_FieldType_Double:
+      encode_fixedarray(e, arr, sizeof(double), TAG(kUpb_WireType_64Bit));
+      break;
+    case kUpb_FieldType_Float:
+      encode_fixedarray(e, arr, sizeof(float), TAG(kUpb_WireType_32Bit));
+      break;
+    case kUpb_FieldType_SFixed64:
+    case kUpb_FieldType_Fixed64:
+      encode_fixedarray(e, arr, sizeof(uint64_t), TAG(kUpb_WireType_64Bit));
+      break;
+    case kUpb_FieldType_Fixed32:
+    case kUpb_FieldType_SFixed32:
+      encode_fixedarray(e, arr, sizeof(uint32_t), TAG(kUpb_WireType_32Bit));
+      break;
+    case kUpb_FieldType_Int64:
+    case kUpb_FieldType_UInt64:
+      VARINT_CASE(uint64_t, *ptr);
+    case kUpb_FieldType_UInt32:
+      VARINT_CASE(uint32_t, *ptr);
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_Enum:
+      VARINT_CASE(int32_t, (int64_t)*ptr);
+    case kUpb_FieldType_Bool:
+      VARINT_CASE(bool, *ptr);
+    case kUpb_FieldType_SInt32:
+      VARINT_CASE(int32_t, encode_zz32(*ptr));
+    case kUpb_FieldType_SInt64:
+      VARINT_CASE(int64_t, encode_zz64(*ptr));
+    case kUpb_FieldType_String:
+    case kUpb_FieldType_Bytes: {
+      const upb_StringView* start = _upb_array_constptr(arr);
+      const upb_StringView* ptr = start + arr->size;
+      do {
+        ptr--;
+        encode_bytes(e, ptr->data, ptr->size);
+        encode_varint(e, ptr->size);
+        encode_tag(e, f->number, kUpb_WireType_Delimited);
+      } while (ptr != start);
+      return;
+    }
+    case kUpb_FieldType_Group: {
+      const void* const* start = _upb_array_constptr(arr);
+      const void* const* ptr = start + arr->size;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      do {
+        size_t size;
+        ptr--;
+        encode_tag(e, f->number, kUpb_WireType_EndGroup);
+        encode_message(e, *ptr, subm, &size);
+        encode_tag(e, f->number, kUpb_WireType_StartGroup);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+    case kUpb_FieldType_Message: {
+      const void* const* start = _upb_array_constptr(arr);
+      const void* const* ptr = start + arr->size;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      do {
+        size_t size;
+        ptr--;
+        encode_message(e, *ptr, subm, &size);
+        encode_varint(e, size);
+        encode_tag(e, f->number, kUpb_WireType_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, kUpb_WireType_Delimited);
+  }
+}
+
+static void encode_mapentry(upb_encstate* e, uint32_t number,
+                            const upb_MiniTable* layout,
+                            const upb_MapEntry* ent) {
+  const upb_MiniTableField* key_field = &layout->fields[0];
+  const upb_MiniTableField* val_field = &layout->fields[1];
+  size_t pre_len = e->limit - e->ptr;
+  size_t size;
+  encode_scalar(e, &ent->data.v, layout->subs, val_field);
+  encode_scalar(e, &ent->data.k, layout->subs, key_field);
+  size = (e->limit - e->ptr) - pre_len;
+  encode_varint(e, size);
+  encode_tag(e, number, kUpb_WireType_Delimited);
+}
+
+static void encode_map(upb_encstate* e, const upb_Message* msg,
+                       const upb_MiniTableSub* subs,
+                       const upb_MiniTableField* f) {
+  const upb_Map* map = *UPB_PTR_AT(msg, f->offset, const upb_Map*);
+  const upb_MiniTable* layout = subs[f->submsg_index].submsg;
+  UPB_ASSERT(layout->field_count == 2);
+
+  if (map == NULL) return;
+
+  if (e->options & kUpb_EncodeOption_Deterministic) {
+    _upb_sortedmap sorted;
+    _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
+                           &sorted);
+    upb_MapEntry ent;
+    while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+    _upb_mapsorter_popmap(&e->sorter, &sorted);
+  } else {
+    intptr_t iter = UPB_STRTABLE_BEGIN;
+    upb_StringView key;
+    upb_value val;
+    while (upb_strtable_next2(&map->table, &key, &val, &iter)) {
+      upb_MapEntry ent;
+      _upb_map_fromkey(key, &ent.data.k, map->key_size);
+      _upb_map_fromvalue(val, &ent.data.v, map->val_size);
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+  }
+}
+
+static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg,
+                                const upb_MiniTableSub* subs,
+                                const upb_MiniTableField* f) {
+  if (f->presence == 0) {
+    /* Proto3 presence or map/array. */
+    const void* mem = UPB_PTR_AT(msg, f->offset, void);
+    switch (_upb_MiniTableField_GetRep(f)) {
+      case kUpb_FieldRep_1Byte: {
+        char ch;
+        memcpy(&ch, mem, 1);
+        return ch != 0;
+      }
+      case kUpb_FieldRep_4Byte: {
+        uint32_t u32;
+        memcpy(&u32, mem, 4);
+        return u32 != 0;
+      }
+      case kUpb_FieldRep_8Byte: {
+        uint64_t u64;
+        memcpy(&u64, mem, 8);
+        return u64 != 0;
+      }
+      case kUpb_FieldRep_StringView: {
+        const upb_StringView* str = (const upb_StringView*)mem;
+        return str->size != 0;
+      }
+      default:
+        UPB_UNREACHABLE();
+    }
+  } else if (f->presence > 0) {
+    /* Proto2 presence: hasbit. */
+    return _upb_hasbit_field(msg, f);
+  } else {
+    /* Field is in a oneof. */
+    return _upb_getoneofcase_field(msg, f) == f->number;
+  }
+}
+
+static void encode_field(upb_encstate* e, const upb_Message* msg,
+                         const upb_MiniTableSub* subs,
+                         const upb_MiniTableField* field) {
+  switch (upb_FieldMode_Get(field)) {
+    case kUpb_FieldMode_Array:
+      encode_array(e, msg, subs, field);
+      break;
+    case kUpb_FieldMode_Map:
+      encode_map(e, msg, subs, field);
+      break;
+    case kUpb_FieldMode_Scalar:
+      encode_scalar(e, UPB_PTR_AT(msg, field->offset, void), subs, field);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+static void encode_msgset_item(upb_encstate* e,
+                               const upb_Message_Extension* ext) {
+  size_t size;
+  encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_EndGroup);
+  encode_message(e, ext->data.ptr, ext->ext->sub.submsg, &size);
+  encode_varint(e, size);
+  encode_tag(e, kUpb_MsgSet_Message, kUpb_WireType_Delimited);
+  encode_varint(e, ext->ext->field.number);
+  encode_tag(e, kUpb_MsgSet_TypeId, kUpb_WireType_Varint);
+  encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_StartGroup);
+}
+
+static void encode_message(upb_encstate* e, const upb_Message* msg,
+                           const upb_MiniTable* m, size_t* size) {
+  size_t pre_len = e->limit - e->ptr;
+
+  if ((e->options & kUpb_EncodeOption_CheckRequired) && m->required_count) {
+    uint64_t msg_head;
+    memcpy(&msg_head, msg, 8);
+    msg_head = _upb_BigEndian_Swap64(msg_head);
+    if (upb_MiniTable_requiredmask(m) & ~msg_head) {
+      encode_err(e, kUpb_EncodeStatus_MissingRequired);
+    }
+  }
+
+  if ((e->options & kUpb_EncodeOption_SkipUnknown) == 0) {
+    size_t unknown_size;
+    const char* unknown = upb_Message_GetUnknown(msg, &unknown_size);
+
+    if (unknown) {
+      encode_bytes(e, unknown, unknown_size);
+    }
+  }
+
+  if (m->ext != kUpb_ExtMode_NonExtendable) {
+    /* Encode all extensions together. Unlike C++, we do not attempt to keep
+     * these in field number order relative to normal fields or even to each
+     * other. */
+    size_t ext_count;
+    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &ext_count);
+    if (ext_count) {
+      const upb_Message_Extension* end = ext + ext_count;
+      for (; ext != end; ext++) {
+        if (UPB_UNLIKELY(m->ext == kUpb_ExtMode_IsMessageSet)) {
+          encode_msgset_item(e, ext);
+        } else {
+          encode_field(e, &ext->data, &ext->ext->sub, &ext->ext->field);
+        }
+      }
+    }
+  }
+
+  if (m->field_count) {
+    const upb_MiniTableField* f = &m->fields[m->field_count];
+    const upb_MiniTableField* first = &m->fields[0];
+    while (f != first) {
+      f--;
+      if (encode_shouldencode(e, msg, m->subs, f)) {
+        encode_field(e, msg, m->subs, f);
+      }
+    }
+  }
+
+  *size = (e->limit - e->ptr) - pre_len;
+}
+
+upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
+                            int options, upb_Arena* arena, char** buf,
+                            size_t* size) {
+  upb_encstate e;
+  unsigned depth = (unsigned)options >> 16;
+
+  e.arena = arena;
+  e.buf = NULL;
+  e.limit = NULL;
+  e.ptr = NULL;
+  e.depth = depth ? depth : 64;
+  e.options = options;
+  _upb_mapsorter_init(&e.sorter);
+
+  upb_EncodeStatus status = UPB_SETJMP(e.err);
+
+  // Unfortunately we must continue to perform hackery here because there are
+  // code paths which blindly copy the returned pointer without bothering to
+  // check for errors until much later (b/235839510). So we still set *buf to
+  // NULL on error and we still set it to non-NULL on a successful empty result.
+  if (status == kUpb_EncodeStatus_Ok) {
+    encode_message(&e, msg, l, size);
+    *size = e.limit - e.ptr;
+    if (*size == 0) {
+      static char ch;
+      *buf = &ch;
+    } else {
+      UPB_ASSERT(e.ptr);
+      *buf = e.ptr;
+    }
+  } else {
+    *buf = NULL;
+    *size = 0;
+  }
+
+  _upb_mapsorter_destroy(&e.sorter);
+  return status;
+}
+
+// This should #undef all macros #defined in def.inc
 
 #undef UPB_SIZE
 #undef UPB_PTR_AT
@@ -11380,6 +13586,7 @@
 #undef UPB_ALIGN_DOWN
 #undef UPB_ALIGN_MALLOC
 #undef UPB_ALIGN_OF
+#undef UPB_MALLOC_ALIGN
 #undef UPB_LIKELY
 #undef UPB_UNLIKELY
 #undef UPB_FORCEINLINE
@@ -11402,3 +13609,6 @@
 #undef UPB_POISON_MEMORY_REGION
 #undef UPB_UNPOISON_MEMORY_REGION
 #undef UPB_ASAN
+#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3
+#undef UPB_DEPRECATED
+#undef UPB_GNUC_MIN
diff --git a/php/ext/google/protobuf/php-upb.h b/php/ext/google/protobuf/php-upb.h
index 5af4e27..bf9f538 100644
--- a/php/ext/google/protobuf/php-upb.h
+++ b/php/ext/google/protobuf/php-upb.h
@@ -1,36 +1,9 @@
 /* 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.
+ * This is where we define internal portability macros used across upb.
  *
- * All of these macros are undef'd in port_undef.inc to avoid leaking them to
- * users.
+ * All of these macros are undef'd in undef.inc to avoid leaking them to users.
  *
  * The correct usage is:
  *
@@ -38,25 +11,38 @@
  *   #include "upb/baz.h"
  *
  *   // MUST be last included header.
- *   #include "upb/port_def.inc"
+ *   #include "upb/port/def.inc"
  *
  *   // Code for this file.
  *   // <...>
  *
  *   // Can be omitted for .c files, required for .h.
- *   #include "upb/port_undef.inc"
+ *   #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(__cplusplus) && __cplusplus >= 201402L) ||           \
       (defined(_MSC_VER) && _MSC_VER >= 1900))
-#error upb requires C99 or C++11 or MSVC >= 2015.
+#error upb requires C99 or C++14 or MSVC >= 2015.
 #endif
 
-#include <stdint.h>
+// 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 UPB_GNUC_MIN(x, y) \
+  (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
+#else
+#define UPB_GNUC_MIN(x, y) 0
+#endif
+
+#include <assert.h>
+#include <setjmp.h>
+#include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
 
 #if UINTPTR_MAX == 0xffffffff
 #define UPB_SIZE(size32, size64) size32
@@ -69,11 +55,6 @@
  */
 #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;
@@ -89,21 +70,22 @@
 #define UPB_INLINE static
 #endif
 
+#define UPB_MALLOC_ALIGN 8
 #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_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN)
 #define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
 
-/* Hints to the compiler about likely/unlikely branches. */
+// 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)
+#define UPB_LIKELY(x) __builtin_expect((bool)(x), 1)
+#define UPB_UNLIKELY(x) __builtin_expect((bool)(x), 0)
 #else
 #define UPB_LIKELY(x) (x)
 #define UPB_UNLIKELY(x) (x)
 #endif
 
-/* Macros for function attributes on compilers that support them. */
+// Macros for function attributes on compilers that support them.
 #ifdef __GNUC__
 #define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
 #define UPB_NOINLINE __attribute__((noinline))
@@ -126,8 +108,7 @@
 
 #define UPB_UNUSED(var) (void)var
 
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
+// 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()
@@ -229,7 +210,11 @@
 
 #undef UPB_FASTTABLE_SUPPORTED
 
-/* ASAN poisoning (for arena) *************************************************/
+/* ASAN poisoning (for arena).
+ * If using UPB from an interpreted language like Ruby, a build of the
+ * interpreter compiled with ASAN enabled must be used in order to get sane and
+ * expected behavior.
+ */
 
 #if defined(__SANITIZE_ADDRESS__)
 #define UPB_ASAN 1
@@ -253,63 +238,51 @@
   ((void)(addr), (void)(size))
 #endif
 
-/** upb/decode.h ************************************************************/
-/*
- * upb_decode: parsing into a upb_Message using a upb_MiniTable.
- */
+/* Disable proto2 arena behavior (TEMPORARY) **********************************/
 
-#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" {
+#ifdef UPB_DISABLE_PROTO2_ENUM_CHECKING
+#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 1
+#else
+#define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0
 #endif
 
-/* upb_Status *****************************************************************/
+#if defined(__cplusplus)
+#if defined(__clang__) || UPB_GNUC_MIN(6, 0)
+// https://gcc.gnu.org/gcc-6/changes.html
+#if __cplusplus >= 201402L
+#define UPB_DEPRECATED [[deprecated]]
+#else
+#define UPB_DEPRECATED __attribute__((deprecated))
+#endif
+#else
+#define UPB_DEPRECATED
+#endif
+#else
+#define UPB_DEPRECATED
+#endif
+
+#ifndef UPB_BASE_STATUS_H_
+#define UPB_BASE_STATUS_H_
+
+#include <stdarg.h>
+
+// Must be last.
 
 #define _kUpb_Status_MaxMessage 127
 
 typedef struct {
   bool ok;
-  char msg[_kUpb_Status_MaxMessage]; /* Error message; NULL-terminated. */
+  char msg[_kUpb_Status_MaxMessage];  // Error message; NULL-terminated.
 } upb_Status;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 const char* upb_Status_ErrorMessage(const upb_Status* status);
 bool upb_Status_IsOk(const upb_Status* status);
 
-/* These are no-op if |status| is NULL. */
+// These are no-op if |status| is NULL.
 void upb_Status_Clear(upb_Status* status);
 void upb_Status_SetErrorMessage(upb_Status* status, const char* msg);
 void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...)
@@ -319,198 +292,36 @@
 void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
                                    va_list args) UPB_PRINTF(2, 0);
 
-/** upb_StringView ************************************************************/
-
-typedef struct {
-  const char* data;
-  size_t size;
-} upb_StringView;
-
-UPB_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data,
-                                                         size_t size) {
-  upb_StringView ret;
-  ret.data = data;
-  ret.size = size;
-  return ret;
-}
-
-UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) {
-  return upb_StringView_FromDataAndSize(data, strlen(data));
-}
-
-UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) {
-  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
-}
-
-#define UPB_STRINGVIEW_INIT(ptr, len) \
-  { ptr, len }
-
-#define UPB_STRINGVIEW_FORMAT "%.*s"
-#define UPB_STRINGVIEW_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_CleanupFunc(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_ArenaHead;
-
-/* 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_CleanupFunc* 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_ArenaHead* h = (_upb_ArenaHead*)a;
-  return (size_t)(h->end - h->ptr);
-}
-
-UPB_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) {
-  _upb_ArenaHead* h = (_upb_ArenaHead*)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;
-    }
-  }
+#ifdef __cplusplus
+} /* extern "C" */
 #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);
+#endif /* UPB_BASE_STATUS_H_ */
 
-  if (ret && oldsize > 0) {
-    memcpy(ret, ptr, oldsize);
-  }
+#ifndef UPB_INTERNAL_ARRAY_INTERNAL_H_
+#define UPB_INTERNAL_ARRAY_INTERNAL_H_
 
-  return ret;
-}
+#include <string.h>
 
-UPB_INLINE upb_Arena* upb_Arena_New(void) {
-  return upb_Arena_Init(NULL, 0, &upb_alloc_global);
-}
 
-/* Constants ******************************************************************/
+#ifndef UPB_COLLECTIONS_ARRAY_H_
+#define UPB_COLLECTIONS_ARRAY_H_
 
-/* A list of types as they are encoded on-the-wire. */
-typedef enum {
-  kUpb_WireType_Varint = 0,
-  kUpb_WireType_64Bit = 1,
-  kUpb_WireType_Delimited = 2,
-  kUpb_WireType_StartGroup = 3,
-  kUpb_WireType_EndGroup = 4,
-  kUpb_WireType_32Bit = 5
-} upb_WireType;
 
-/* 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). */
+#ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_
+#define UPB_BASE_DESCRIPTOR_CONSTANTS_H_
+
+// 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).
+// This enum is an internal convenience only and has no meaning outside of upb.
 typedef enum {
   kUpb_CType_Bool = 1,
   kUpb_CType_Float = 2,
   kUpb_CType_Int32 = 3,
   kUpb_CType_UInt32 = 4,
-  kUpb_CType_Enum = 5, /* Enum values are int32. */
+  kUpb_CType_Enum = 5,  // Enum values are int32.
   kUpb_CType_Message = 6,
   kUpb_CType_Double = 7,
   kUpb_CType_Int64 = 8,
@@ -519,14 +330,14 @@
   kUpb_CType_Bytes = 11
 } upb_CType;
 
-/* The repeated-ness of each field; this matches descriptor.proto. */
+// The repeated-ness of each field; this matches descriptor.proto.
 typedef enum {
   kUpb_Label_Optional = 1,
   kUpb_Label_Required = 2,
   kUpb_Label_Repeated = 3
 } upb_Label;
 
-/* Descriptor types, as defined in descriptor.proto. */
+// Descriptor types, as defined in descriptor.proto.
 typedef enum {
   kUpb_FieldType_Double = 1,
   kUpb_FieldType_Float = 2,
@@ -545,215 +356,631 @@
   kUpb_FieldType_SFixed32 = 15,
   kUpb_FieldType_SFixed64 = 16,
   kUpb_FieldType_SInt32 = 17,
-  kUpb_FieldType_SInt64 = 18
+  kUpb_FieldType_SInt64 = 18,
 } upb_FieldType;
 
-#define kUpb_Map_Begin ((size_t)-1)
+#define kUpb_FieldType_SizeOf 19
 
-UPB_INLINE bool _upb_IsLittleEndian(void) {
-  int x = 1;
-  return *(char*)&x == 1;
-}
+#endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */
 
-UPB_INLINE uint32_t _upb_BigEndian_Swap32(uint32_t val) {
-  if (_upb_IsLittleEndian()) {
-    return val;
-  } else {
-    return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
-           ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
-  }
-}
+// Users should include array.h or map.h instead.
+// IWYU pragma: private, include "upb/collections/array.h"
 
-UPB_INLINE uint64_t _upb_BigEndian_Swap64(uint64_t val) {
-  if (_upb_IsLittleEndian()) {
-    return val;
-  } else {
-    return ((uint64_t)_upb_BigEndian_Swap32(val) << 32) |
-           _upb_BigEndian_Swap32(val >> 32);
-  }
-}
-
-UPB_INLINE int _upb_Log2Ceiling(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_Log2Ceilingsize(int x) { return 1 << _upb_Log2Ceiling(x); }
+#ifndef UPB_MESSAGE_VALUE_H_
+#define UPB_MESSAGE_VALUE_H_
 
 
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
+#ifndef UPB_BASE_STRING_VIEW_H_
+#define UPB_BASE_STRING_VIEW_H_
 
-#endif /* UPB_H_ */
+#include <string.h>
+
+// Must be last.
+
+#define UPB_STRINGVIEW_INIT(ptr, len) \
+  { ptr, len }
+
+#define UPB_STRINGVIEW_FORMAT "%.*s"
+#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data
+
+// LINT.IfChange(struct_definition)
+typedef struct {
+  const char* data;
+  size_t size;
+} upb_StringView;
+// LINT.ThenChange(GoogleInternalName0)
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/** upb_Message
- * *******************************************************************/
+UPB_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data,
+                                                         size_t size) {
+  upb_StringView ret;
+  ret.data = data;
+  ret.size = size;
+  return ret;
+}
+
+UPB_INLINE upb_StringView upb_StringView_FromString(const char* data) {
+  return upb_StringView_FromDataAndSize(data, strlen(data));
+}
+
+UPB_INLINE bool upb_StringView_IsEqual(upb_StringView a, upb_StringView b) {
+  return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_BASE_STRING_VIEW_H_ */
+
+#ifndef UPB_MINI_TABLE_TYPES_H_
+#define UPB_MINI_TABLE_TYPES_H_
 
 typedef void upb_Message;
 
-/* For users these are opaque. They can be obtained from
- * upb_MessageDef_MiniTable() but users cannot access any of the members. */
-struct upb_MiniTable;
 typedef struct upb_MiniTable upb_MiniTable;
+typedef struct upb_MiniTableEnum upb_MiniTableEnum;
+typedef struct upb_MiniTableExtension upb_MiniTableExtension;
+typedef struct upb_MiniTableField upb_MiniTableField;
+typedef struct upb_MiniTableFile upb_MiniTableFile;
+typedef union upb_MiniTableSub upb_MiniTableSub;
 
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-void upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
-                            upb_Arena* arena);
+#endif /* UPB_MINI_TABLE_TYPES_H_ */
 
-/* Returns a reference to the message's unknown data. */
-const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);
+// Must be last.
 
-/* Returns the number of extensions present in this message. */
-size_t upb_Message_ExtensionCount(const upb_Message* msg);
+typedef struct upb_Array upb_Array;
+typedef struct upb_Map upb_Map;
 
-/** upb_ExtensionRegistry *****************************************************/
+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_Array* array_val;
+  const upb_Map* map_val;
+  const upb_Message* msg_val;
+  upb_StringView str_val;
+} upb_MessageValue;
 
-/* Extension registry: a dynamic data structure that stores a map of:
- *   (upb_MiniTable, number) -> extension info
+typedef union {
+  upb_Array* array;
+  upb_Map* map;
+  upb_Message* msg;
+} upb_MutableMessageValue;
+
+
+#endif /* UPB_MESSAGE_VALUE_H_ */
+
+/* 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.
  *
- * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing
- * binary format.
+ * A upb_Arena is *not* thread-safe.
  *
- * upb_ExtensionRegistry is part of the mini-table (msglayout) family of
- * objects. Like all mini-table objects, it is suitable for reflection-less
- * builds that do not want to expose names into the binary.
- *
- * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory
- * allocation and dynamic initialization:
- * * If reflection is being used, then upb_DefPool will construct an appropriate
- *   upb_ExtensionRegistry automatically.
- * * For a mini-table only build, the user must manually construct the
- *   upb_ExtensionRegistry and populate it with all of the extensions the user
- * cares about.
- * * A third alternative is to manually unpack relevant extensions after the
- *   main parse is complete, similar to how Any works. This is perhaps the
- *   nicest solution from the perspective of reducing dependencies, avoiding
- *   dynamic memory allocation, and avoiding the need to parse uninteresting
- *   extensions.  The downsides are:
- *     (1) parse errors are not caught during the main parse
- *     (2) the CPU hit of parsing comes during access, which could cause an
- *         undesirable stutter in application performance.
- *
- * Users cannot directly get or put into this map. Users can only add the
- * extensions from a generated module and pass the extension registry to the
- * binary decoder.
- *
- * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use
- * reflection do not need to populate a upb_ExtensionRegistry directly.
- */
+ * 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. */
 
-struct upb_ExtensionRegistry;
-typedef struct upb_ExtensionRegistry upb_ExtensionRegistry;
+#ifndef UPB_MEM_ARENA_H_
+#define UPB_MEM_ARENA_H_
 
-/* Creates a upb_ExtensionRegistry in the given arena.  The arena must outlive
- * any use of the extreg. */
-upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena);
+#include <string.h>
 
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
 
-#endif /* UPB_MSG_INT_H_ */
+#ifndef UPB_MEM_ALLOC_H_
+#define UPB_MEM_ALLOC_H_
 
-/* Must be last. */
+// Must be last.
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-enum {
-  /* If set, strings will alias the input buffer instead of copying into the
-   * arena. */
-  kUpb_DecodeOption_AliasString = 1,
+typedef struct upb_alloc upb_alloc;
 
-  /* If set, the parse will return failure if any message is missing any
-   * required fields when the message data ends.  The parse will still continue,
-   * and the failure will only be reported at the end.
-   *
-   * IMPORTANT CAVEATS:
-   *
-   * 1. This can throw a false positive failure if an incomplete message is seen
-   *    on the wire but is later completed when the sub-message occurs again.
-   *    For this reason, a second pass is required to verify a failure, to be
-   *    truly robust.
-   *
-   * 2. This can return a false success if you are decoding into a message that
-   *    already has some sub-message fields present.  If the sub-message does
-   *    not occur in the binary payload, we will never visit it and discover the
-   *    incomplete sub-message.  For this reason, this check is only useful for
-   *    implemting ParseFromString() semantics.  For MergeFromString(), a
-   *    post-parse validation step will always be necessary. */
-  kUpb_DecodeOption_CheckRequired = 2,
+/* A combined `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);
+
+/* 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 {
+  upb_alloc_func* func;
 };
 
-#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
+UPB_INLINE void* upb_malloc(upb_alloc* alloc, size_t size) {
+  UPB_ASSERT(alloc);
+  return alloc->func(alloc, NULL, 0, size);
+}
 
-typedef enum {
-  kUpb_DecodeStatus_Ok = 0,
-  kUpb_DecodeStatus_Malformed = 1,         // Wire format was corrupt
-  kUpb_DecodeStatus_OutOfMemory = 2,       // Arena alloc failed
-  kUpb_DecodeStatus_BadUtf8 = 3,           // String field had bad UTF-8
-  kUpb_DecodeStatus_MaxDepthExceeded = 4,  // Exceeded UPB_DECODE_MAXDEPTH
+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);
+}
 
-  // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise
-  // succeeded.
-  kUpb_DecodeStatus_MissingRequired = 5,
-} upb_DecodeStatus;
+UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) {
+  UPB_ASSERT(alloc);
+  alloc->func(alloc, ptr, 0, 0);
+}
 
-upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
-                            const upb_MiniTable* l,
-                            const upb_ExtensionRegistry* extreg, int options,
-                            upb_Arena* arena);
+// 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); }
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 
-#endif /* UPB_DECODE_H_ */
+#endif /* UPB_MEM_ALLOC_H_ */
 
-/** upb/decode_internal.h ************************************************************/
-/*
- * Internal implementation details of the decoder that are shared between
- * decode.c and decode_fast.c.
+// Must be last.
+
+typedef struct upb_Arena upb_Arena;
+
+typedef void upb_CleanupFunc(void* context);
+
+typedef struct {
+  char *ptr, *end;
+} _upb_ArenaHead;
+
+#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_CleanupFunc* func);
+bool upb_Arena_Fuse(upb_Arena* a, upb_Arena* b);
+void* _upb_Arena_SlowMalloc(upb_Arena* a, size_t size);
+size_t upb_Arena_SpaceAllocated(upb_Arena* arena);
+uint32_t upb_Arena_DebugRefCount(upb_Arena* arena);
+
+UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) {
+  _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+  return (size_t)(h->end - h->ptr);
+}
+
+UPB_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) {
+  size = UPB_ALIGN_MALLOC(size);
+  if (UPB_UNLIKELY(_upb_ArenaHas(a) < size)) {
+    return _upb_Arena_SlowMalloc(a, size);
+  }
+
+  // We have enough space to do a fast malloc.
+  _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+  void* ret = h->ptr;
+  UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret);
+  UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size);
+  UPB_UNPOISON_MEMORY_REGION(ret, size);
+
+  h->ptr += 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;
+}
+
+// Shrinks the last alloc from arena.
+// REQUIRES: (ptr, oldsize) was the last malloc/realloc from this arena.
+// We could also add a upb_Arena_TryShrinkLast() which is simply a no-op if
+// this was not the last alloc.
+UPB_INLINE void upb_Arena_ShrinkLast(upb_Arena* a, void* ptr, size_t oldsize,
+                                     size_t size) {
+  _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+  oldsize = UPB_ALIGN_MALLOC(oldsize);
+  size = UPB_ALIGN_MALLOC(size);
+  UPB_ASSERT((char*)ptr + oldsize == h->ptr);  // Must be the last alloc.
+  UPB_ASSERT(size <= oldsize);
+  h->ptr = (char*)ptr + size;
+}
+
+UPB_INLINE void* upb_Arena_Realloc(upb_Arena* a, void* ptr, size_t oldsize,
+                                   size_t size) {
+  _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+  oldsize = UPB_ALIGN_MALLOC(oldsize);
+  size = UPB_ALIGN_MALLOC(size);
+  bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr;
+
+  if (is_most_recent_alloc) {
+    ptrdiff_t diff = size - oldsize;
+    if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) {
+      h->ptr += diff;
+      return ptr;
+    }
+  } else if (size <= oldsize) {
+    return ptr;
+  }
+
+  void* ret = upb_Arena_Malloc(a, size);
+
+  if (ret && oldsize > 0) {
+    memcpy(ret, ptr, UPB_MIN(oldsize, size));
+  }
+
+  return ret;
+}
+
+UPB_INLINE upb_Arena* upb_Arena_New(void) {
+  return upb_Arena_Init(NULL, 0, &upb_alloc_global);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MEM_ARENA_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a new array on the given arena that holds elements of this type. */
+upb_Array* upb_Array_New(upb_Arena* a, upb_CType type);
+
+/* Returns the number of elements in 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_MessageValue 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_MessageValue val);
+
+/* Appends an element to the array.  Returns false on allocation failure. */
+bool upb_Array_Append(upb_Array* array, upb_MessageValue val, upb_Arena* arena);
+
+/* Moves elements within the array using memmove(). Like memmove(), the source
+ * and destination elements may be overlapping. */
+void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
+                    size_t count);
+
+/* Inserts one or more empty elements into the array.  Existing elements are
+ * shifted right.  The new elements have undefined state and must be set with
+ * `upb_Array_Set()`.
+ * REQUIRES: `i <= upb_Array_Size(arr)` */
+bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
+                      upb_Arena* arena);
+
+/* Deletes one or more elements from the array.  Existing elements are shifted
+ * left.
+ * REQUIRES: `i + count <= upb_Array_Size(arr)` */
+void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
+
+/* 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);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_COLLECTIONS_ARRAY_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// LINT.IfChange(struct_definition)
+// Our internal representation for repeated fields.
+struct upb_Array {
+  uintptr_t data;  /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
+  size_t size;     /* The number of elements in the array. */
+  size_t capacity; /* Allocated storage. Measured in elements. */
+};
+// LINT.ThenChange(GoogleInternalName1)
+
+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_capacity,
+                                     int elem_size_lg2) {
+  const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), UPB_MALLOC_ALIGN);
+  const size_t bytes = arr_size + (init_capacity << 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->size = 0;
+  arr->capacity = init_capacity;
+  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->capacity < 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->size = size;
+  return true;
+}
+
+UPB_INLINE void _upb_array_detach(const void* msg, size_t ofs) {
+  *UPB_PTR_AT(msg, ofs, upb_Array*) = NULL;
+}
+
+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->size;
+    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->size;
+    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->capacity < size) {
+    return _upb_Array_Resize_fallback(arr_ptr, size, elem_size_lg2, arena);
+  }
+  arr->size = 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->size == arr->capacity) {
+    return _upb_Array_Append_fallback(arr_ptr, value, elem_size_lg2, arena);
+  }
+  ptr = _upb_array_ptr(arr);
+  memcpy(UPB_PTR_AT(ptr, arr->size * elem_size, char), value, elem_size);
+  arr->size++;
+  return true;
+}
+
+// Used by old generated code, remove once all code has been regenerated.
+UPB_INLINE int _upb_sizelg2(upb_CType type) {
+  switch (type) {
+    case kUpb_CType_Bool:
+      return 0;
+    case kUpb_CType_Float:
+    case kUpb_CType_Int32:
+    case kUpb_CType_UInt32:
+    case kUpb_CType_Enum:
+      return 2;
+    case kUpb_CType_Message:
+      return UPB_SIZE(2, 3);
+    case kUpb_CType_Double:
+    case kUpb_CType_Int64:
+    case kUpb_CType_UInt64:
+      return 3;
+    case kUpb_CType_String:
+    case kUpb_CType_Bytes:
+      return UPB_SIZE(3, 4);
+  }
+  UPB_UNREACHABLE();
+}
+
+UPB_INLINE void* _upb_Array_Resize_accessor(void* msg, size_t ofs, size_t size,
+                                            upb_CType 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_CType type,
+                                           const void* value,
+                                           upb_Arena* arena) {
+  (void)elem_size;
+  return _upb_Array_Append_accessor2(msg, ofs, _upb_sizelg2(type), value,
+                                     arena);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_INTERNAL_ARRAY_INTERNAL_H_ */
+
+#ifndef UPB_COLLECTIONS_MAP_H_
+#define UPB_COLLECTIONS_MAP_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a new map on the given arena with the given key/value size. */
+upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType 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_MessageValue key,
+                 upb_MessageValue* val);
+
+/* Removes all entries in the map. */
+void upb_Map_Clear(upb_Map* map);
+
+typedef enum {
+  kUpb_MapInsertStatus_Inserted = 0,
+  kUpb_MapInsertStatus_Replaced = 1,
+  kUpb_MapInsertStatus_OutOfMemory = 2,
+} upb_MapInsertStatus;
+
+/* Sets the given key to the given value, returning whether the key was inserted
+ * or replaced.  If the key was inserted, then any existing iterators will be
+ * invalidated. */
+upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
+                                   upb_MessageValue val, upb_Arena* arena);
+
+/* Sets the given key to the given value.  Returns false if memory allocation
+ * failed. If the key is newly inserted, then any existing iterators will be
+ * invalidated. */
+UPB_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key,
+                            upb_MessageValue val, upb_Arena* arena) {
+  return upb_Map_Insert(map, key, val, arena) !=
+         kUpb_MapInsertStatus_OutOfMemory;
+}
+
+// Deletes this key from the table. Returns true if the key was present.
+bool upb_Map_Delete(upb_Map* map, upb_MessageValue key);
+
+// Map iteration:
+//
+// size_t iter = kUpb_Map_Begin;
+// upb_MessageValue key, val;
+// while (upb_Map_Next(map, &key, &val, &iter)) {
+//   ...
+// }
+
+#define kUpb_Map_Begin ((size_t)-1)
+
+// Advances to the next entry. Returns false if no more entries are present.
+// Otherwise returns true and populates both *key and *value.
+bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
+                  upb_MessageValue* val, size_t* iter);
+
+// DEPRECATED iterator, slated for removal.
+
+/* Map iteration:
+ *
+ * size_t iter = kUpb_Map_Begin;
+ * while (upb_MapIterator_Next(map, &iter)) {
+ *   upb_MessageValue key = upb_MapIterator_Key(map, iter);
+ *   upb_MessageValue val = upb_MapIterator_Value(map, iter);
+ * }
  */
 
-#ifndef UPB_DECODE_INT_H_
-#define UPB_DECODE_INT_H_
+// Advances to the next entry. Returns false if no more entries are present.
+bool upb_MapIterator_Next(const upb_Map* map, size_t* iter);
 
-#include <setjmp.h>
+/* 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
+ * kUpb_Map_Begin (you must call next() at least once first). */
+bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
 
-#include "third_party/utf8_range/utf8_range.h"
+/* Returns the key and value for this entry of the map. */
+upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
+upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter);
 
-/** 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>
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
 
-/** upb/table_internal.h ************************************************************/
+#endif /* UPB_COLLECTIONS_MAP_H_ */
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+#ifndef UPB_COLLECTIONS_MAP_INTERNAL_H_
+#define UPB_COLLECTIONS_MAP_INTERNAL_H_
+
+
+#ifndef UPB_HASH_STR_TABLE_H_
+#define UPB_HASH_STR_TABLE_H_
+
+
 /*
  * upb_table
  *
@@ -773,10 +1000,9 @@
  * mode, we check this on insert and lookup.
  */
 
-#ifndef UPB_TABLE_H_
-#define UPB_TABLE_H_
+#ifndef UPB_HASH_COMMON_H_
+#define UPB_HASH_COMMON_H_
 
-#include <stdint.h>
 #include <string.h>
 
 
@@ -907,67 +1133,66 @@
   upb_tabent* entries;
 } upb_table;
 
+UPB_INLINE size_t upb_table_size(const upb_table* t) {
+  return t->size_lg2 ? 1 << t->size_lg2 : 0;
+}
+
+// Internal-only functions, in .h file only out of necessity.
+
+UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; }
+
+uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_HASH_COMMON_H_ */
+
+// Must be last.
+
 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;
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-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);
+// Initialize a table. If memory allocation failed, false is returned and
+// the table is uninitialized.
 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);
+// Returns the number of values in the table.
 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);
+// Inserts the given key into the hashtable with the given value.
+// The key must not already exist in the hash table. The key is not required
+// to be NULL-terminated, and the table will make an internal copy of the key.
+//
+// If a table resize was required but memory allocation failed, false is
+// returned and the table is unchanged. */
 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);
+// 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_strtable_lookup2(const upb_strtable* t, const char* key, size_t len,
                           upb_value* v);
 
-/* For NULL-terminated strings. */
+// 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);
+// 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_strtable_remove2(upb_strtable* t, const char* key, size_t len,
                           upb_value* val);
 
@@ -976,40 +1201,12 @@
   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);
-
-/* 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. */
+// Exposed for testing only.
 bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a);
 
-/* Iterators ******************************************************************/
-
-/* Iteration over inttable.
+/* Iteration over strtable:
  *
- *   intptr_t iter = UPB_INTTABLE_BEGIN;
- *   uintptr_t key;
- *   upb_value val;
- *   while (upb_inttable_next2(t, &key, &val, &iter)) {
- *      // ...
- *   }
- */
-
-#define UPB_INTTABLE_BEGIN -1
-
-bool upb_inttable_next2(const upb_inttable* t, uintptr_t* key, upb_value* val,
-                        intptr_t* iter);
-void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter);
-
-/* Iteration over strtable.
- *
- *   intptr_t iter = UPB_INTTABLE_BEGIN;
+ *   intptr_t iter = UPB_STRTABLE_BEGIN;
  *   upb_StringView key;
  *   upb_value val;
  *   while (upb_strtable_next2(t, &key, &val, &iter)) {
@@ -1025,7 +1222,7 @@
 
 /* DEPRECATED iterators, slated for removal.
  *
- * Iterators for int and string tables.  We are subject to some kind of unusual
+ * Iterators for string tables.  We are subject to some kind of unusual
  * design constraints:
  *
  * For high-level languages:
@@ -1045,7 +1242,6 @@
  * 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;
@@ -1062,6 +1258,10 @@
   size_t index;
 } upb_strtable_iter;
 
+UPB_INLINE 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);
 void upb_strtable_next(upb_strtable_iter* i);
 bool upb_strtable_done(const upb_strtable_iter* i);
@@ -1071,610 +1271,35 @@
 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_ */
+#endif /* UPB_HASH_STR_TABLE_H_ */
 
-/* Must be last. */
+// Must be last.
+
+struct upb_Map {
+  // 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;
+};
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/** upb_*Int* conversion routines ********************************************/
-
-UPB_INLINE int32_t _upb_Int32_FromI(int v) { return (int32_t)v; }
-
-UPB_INLINE int64_t _upb_Int64_FromLL(long long v) { return (int64_t)v; }
-
-UPB_INLINE uint32_t _upb_UInt32_FromU(unsigned v) { return (uint32_t)v; }
-
-UPB_INLINE uint64_t _upb_UInt64_FromULL(unsigned long long v) {
-  return (uint64_t)v;
-}
-
-/** upb_MiniTable *************************************************************/
-
-/* upb_MiniTable represents the memory layout of a given upb_MessageDef.  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.  If <0, ~oneof_index
-  uint16_t submsg_index;  // undefined if descriptortype != MESSAGE/GROUP/ENUM
-  uint8_t descriptortype;
-  uint8_t mode; /* upb_FieldMode | upb_LabelFlags |
-                   (upb_FieldRep << upb_FieldRep_Shift) */
-} upb_MiniTable_Field;
-
-typedef enum {
-  kUpb_FieldMode_Map = 0,
-  kUpb_FieldMode_Array = 1,
-  kUpb_FieldMode_Scalar = 2,
-
-  kUpb_FieldMode_Mask = 3, /* Mask to isolate the mode from upb_FieldRep. */
-} upb_FieldMode;
-
-/* Extra flags on the mode field. */
-enum upb_LabelFlags {
-  upb_LabelFlags_IsPacked = 4,
-  upb_LabelFlags_IsExtension = 8,
-};
-
-/* Representation in the message.  Derivable from descriptortype and mode, but
- * fast access helps the serializer. */
-enum upb_FieldRep {
-  upb_FieldRep_1Byte = 0,
-  upb_FieldRep_4Byte = 1,
-  upb_FieldRep_8Byte = 2,
-  upb_FieldRep_StringView = 3,
-
-#if UINTPTR_MAX == 0xffffffff
-  upb_FieldRep_Pointer = upb_FieldRep_4Byte,
-#else
-  upb_FieldRep_Pointer = upb_FieldRep_8Byte,
-#endif
-
-  upb_FieldRep_Shift =
-      6, /* Bit offset of the rep in upb_MiniTable_Field.mode */
-};
-
-UPB_INLINE upb_FieldMode upb_FieldMode_Get(const upb_MiniTable_Field* field) {
-  return (upb_FieldMode)(field->mode & 3);
-}
-
-UPB_INLINE bool upb_IsRepeatedOrMap(const upb_MiniTable_Field* field) {
-  /* This works because upb_FieldMode has no value 3. */
-  return !(field->mode & kUpb_FieldMode_Scalar);
-}
-
-UPB_INLINE bool upb_IsSubMessage(const upb_MiniTable_Field* field) {
-  return field->descriptortype == kUpb_FieldType_Message ||
-         field->descriptortype == kUpb_FieldType_Group;
-}
-
-struct upb_Decoder;
-struct upb_MiniTable;
-
-typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr,
-                                     upb_Message* msg, intptr_t table,
-                                     uint64_t hasbits, uint64_t data);
-
-typedef struct {
-  uint64_t field_data;
-  _upb_FieldParser* field_parser;
-} _upb_FastTable_Entry;
-
-typedef struct {
-  const int32_t* values;  // List of values <0 or >63
-  uint64_t mask;          // Bits are set for acceptable value 0 <= x < 64
-  int value_count;
-} upb_MiniTable_Enum;
-
-UPB_INLINE bool upb_MiniTable_Enum_CheckValue(const upb_MiniTable_Enum* e,
-                                              int32_t val) {
-  uint32_t uval = (uint32_t)val;
-  if (uval < 64) return e->mask & (1 << uval);
-  // OPT: binary search long lists?
-  int n = e->value_count;
-  for (int i = 0; i < n; i++) {
-    if (e->values[i] == val) return true;
-  }
-  return false;
-}
-
-typedef union {
-  const struct upb_MiniTable* submsg;
-  const upb_MiniTable_Enum* subenum;
-} upb_MiniTable_Sub;
-
-typedef enum {
-  upb_ExtMode_NonExtendable = 0,  // Non-extendable message.
-  upb_ExtMode_Extendable = 1,     // Normal extendable message.
-  upb_ExtMode_IsMessageSet = 2,   // MessageSet message.
-  upb_ExtMode_IsMessageSet_ITEM =
-      3,  // MessageSet item (temporary only, see decode.c)
-} upb_ExtMode;
-
-/* MessageSet wire format is:
- *   message MessageSet {
- *     repeated group Item = 1 {
- *       required int32 type_id = 2;
- *       required string message = 3;
- *     }
- *   }
- */
-typedef enum {
-  _UPB_MSGSET_ITEM = 1,
-  _UPB_MSGSET_TYPEID = 2,
-  _UPB_MSGSET_MESSAGE = 3,
-} upb_msgext_fieldnum;
-
-struct upb_MiniTable {
-  const upb_MiniTable_Sub* subs;
-  const upb_MiniTable_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;
-  uint8_t ext;  // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1
-  uint8_t dense_below;
-  uint8_t table_mask;
-  uint8_t required_count;  // Required fields have the lowest hasbits.
-  /* To statically initialize the tables of variable length, we need a flexible
-   * array member, and we need to compile in gnu99 mode (constant initialization
-   * of flexible array members is a GNU extension, not in C99 unfortunately. */
-  _upb_FastTable_Entry fasttable[];
-};
-
-typedef struct {
-  upb_MiniTable_Field field;
-  const upb_MiniTable* extendee;
-  upb_MiniTable_Sub sub; /* NULL unless submessage or proto2 enum */
-} upb_MiniTable_Extension;
-
-typedef struct {
-  const upb_MiniTable** msgs;
-  const upb_MiniTable_Enum** enums;
-  const upb_MiniTable_Extension** exts;
-  int msg_count;
-  int enum_count;
-  int ext_count;
-} upb_MiniTable_File;
-
-// Computes a bitmask in which the |l->required_count| lowest bits are set,
-// except that we skip the lowest bit (because upb never uses hasbit 0).
+// Converting between internal table representation and user values.
 //
-// Sample output:
-//    requiredmask(1) => 0b10 (0x2)
-//    requiredmask(5) => 0b111110 (0x3e)
-UPB_INLINE uint64_t upb_MiniTable_requiredmask(const upb_MiniTable* l) {
-  int n = l->required_count;
-  assert(0 < n && n <= 63);
-  return ((1ULL << n) - 1) << 1;
-}
-
-/** upb_ExtensionRegistry
- * ****************************************************************/
-
-/* Adds the given extension info for message type |l| and field number |num|
- * into the registry. Returns false if this message type and field number were
- * already in the map, or if memory allocation fails. */
-bool _upb_extreg_add(upb_ExtensionRegistry* r,
-                     const upb_MiniTable_Extension** e, size_t count);
-
-/* Looks up the extension (if any) defined for message type |l| and field
- * number |num|.  If an extension was found, copies the field info into |*ext|
- * and returns true. Otherwise returns false. */
-const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
-                                               const upb_MiniTable* l,
-                                               uint32_t num);
-
-/** upb_Message
- * *******************************************************************/
-
-/* Internal members of a upb_Message that track unknown fields and/or
- * extensions. We can change this without breaking binary compatibility.  We put
- * these before the user's data.  The user's upb_Message* points after the
- * upb_Message_Internal. */
-
-typedef struct {
-  /* Total size of this structure, including the data that follows.
-   * Must be aligned to 8, which is alignof(upb_Message_Extension) */
-  uint32_t size;
-
-  /* Offsets relative to the beginning of this structure.
-   *
-   * Unknown data grows forward from the beginning to unknown_end.
-   * Extension data grows backward from size to ext_begin.
-   * When the two meet, we're out of data and have to realloc.
-   *
-   * If we imagine that the final member of this struct is:
-   *   char data[size - overhead];  // overhead =
-   * sizeof(upb_Message_InternalData)
-   *
-   * Then we have:
-   *   unknown data: data[0 .. (unknown_end - overhead)]
-   *   extensions data: data[(ext_begin - overhead) .. (size - overhead)] */
-  uint32_t unknown_end;
-  uint32_t ext_begin;
-  /* Data follows, as if there were an array:
-   *   char data[size - sizeof(upb_Message_InternalData)]; */
-} upb_Message_InternalData;
-
-typedef struct {
-  upb_Message_InternalData* internal;
-  /* Message data follows. */
-} upb_Message_Internal;
-
-/* Maps upb_CType -> memory size. */
-extern char _upb_CTypeo_size[12];
-
-UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* l) {
-  return l->size + sizeof(upb_Message_Internal);
-}
-
-UPB_INLINE upb_Message* _upb_Message_New_inl(const upb_MiniTable* l,
-                                             upb_Arena* a) {
-  size_t size = upb_msg_sizeof(l);
-  void* mem = upb_Arena_Malloc(a, size);
-  upb_Message* msg;
-  if (UPB_UNLIKELY(!mem)) return NULL;
-  msg = UPB_PTR_AT(mem, sizeof(upb_Message_Internal), upb_Message);
-  memset(mem, 0, size);
-  return msg;
-}
-
-/* Creates a new messages with the given layout on the given arena. */
-upb_Message* _upb_Message_New(const upb_MiniTable* l, upb_Arena* a);
-
-UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(upb_Message* msg) {
-  ptrdiff_t size = sizeof(upb_Message_Internal);
-  return (upb_Message_Internal*)((char*)msg - size);
-}
-
-/* Clears the given message. */
-void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l);
-
-/* Discards the unknown fields for this message only. */
-void _upb_Message_DiscardUnknown_shallow(upb_Message* msg);
-
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
-                             upb_Arena* arena);
-
-/** upb_Message_Extension
- * ***************************************************************/
-
-/* The internal representation of an extension is self-describing: it contains
- * enough information that we can serialize it to binary format without needing
- * to look it up in a upb_ExtensionRegistry.
- *
- * This representation allocates 16 bytes to data on 64-bit platforms.  This is
- * rather wasteful for scalars (in the extreme case of bool, it wastes 15
- * bytes). We accept this because we expect messages to be the most common
- * extension type. */
-typedef struct {
-  const upb_MiniTable_Extension* ext;
-  union {
-    upb_StringView str;
-    void* ptr;
-    char scalar_data[8];
-  } data;
-} upb_Message_Extension;
-
-/* Adds the given extension data to the given message. |ext| is copied into the
- * message instance. This logically replaces any previously-added extension with
- * this number */
-upb_Message_Extension* _upb_Message_Getorcreateext(
-    upb_Message* msg, const upb_MiniTable_Extension* ext, upb_Arena* arena);
-
-/* Returns an array of extensions for this message. Note: the array is
- * ordered in reverse relative to the order of creation. */
-const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
-                                                  size_t* count);
-
-/* Returns an extension for the given field number, or NULL if no extension
- * exists for this field number. */
-const upb_Message_Extension* _upb_Message_Getext(
-    const upb_Message* msg, const upb_MiniTable_Extension* ext);
-
-void _upb_Message_Clearext(upb_Message* msg,
-                           const upb_MiniTable_Extension* ext);
-
-void _upb_Message_Clearext(upb_Message* msg,
-                           const upb_MiniTable_Extension* ext);
-
-/** Hasbit access *************************************************************/
-
-UPB_INLINE bool _upb_hasbit(const upb_Message* msg, size_t idx) {
-  return (*UPB_PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
-}
-
-UPB_INLINE void _upb_sethas(const upb_Message* msg, size_t idx) {
-  (*UPB_PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
-}
-
-UPB_INLINE void _upb_clearhas(const upb_Message* msg, size_t idx) {
-  (*UPB_PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
-}
-
-UPB_INLINE size_t _upb_Message_Hasidx(const upb_MiniTable_Field* f) {
-  UPB_ASSERT(f->presence > 0);
-  return f->presence;
-}
-
-UPB_INLINE bool _upb_hasbit_field(const upb_Message* msg,
-                                  const upb_MiniTable_Field* f) {
-  return _upb_hasbit(msg, _upb_Message_Hasidx(f));
-}
-
-UPB_INLINE void _upb_sethas_field(const upb_Message* msg,
-                                  const upb_MiniTable_Field* f) {
-  _upb_sethas(msg, _upb_Message_Hasidx(f));
-}
-
-UPB_INLINE void _upb_clearhas_field(const upb_Message* msg,
-                                    const upb_MiniTable_Field* f) {
-  _upb_clearhas(msg, _upb_Message_Hasidx(f));
-}
-
-/** Oneof case access *********************************************************/
-
-UPB_INLINE uint32_t* _upb_oneofcase(upb_Message* 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_MiniTable_Field* f) {
-  UPB_ASSERT(f->presence < 0);
-  return ~(ptrdiff_t)f->presence;
-}
-
-UPB_INLINE uint32_t* _upb_oneofcase_field(upb_Message* msg,
-                                          const upb_MiniTable_Field* f) {
-  return _upb_oneofcase(msg, _upb_oneofcase_ofs(f));
-}
-
-UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_Message* msg,
-                                            const upb_MiniTable_Field* f) {
-  return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f));
-}
-
-UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_Message* msg, size_t ofs) {
-  return *UPB_PTR_AT(msg, ofs, const upb_Message*) != NULL;
-}
-
-/** 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_CType type) {
-  switch (type) {
-    case kUpb_CType_Bool:
-      return 0;
-    case kUpb_CType_Float:
-    case kUpb_CType_Int32:
-    case kUpb_CType_UInt32:
-    case kUpb_CType_Enum:
-      return 2;
-    case kUpb_CType_Message:
-      return UPB_SIZE(2, 3);
-    case kUpb_CType_Double:
-    case kUpb_CType_Int64:
-    case kUpb_CType_UInt64:
-      return 3;
-    case kUpb_CType_String:
-    case kUpb_CType_Bytes:
-      return UPB_SIZE(3, 4);
-  }
-  UPB_UNREACHABLE();
-}
-UPB_INLINE void* _upb_Array_Resize_accessor(void* msg, size_t ofs, size_t size,
-                                            upb_CType 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_CType 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_Message_Internal internal;
-  union {
-    upb_StringView str; /* For str/bytes. */
-    upb_value val;      /* For all other types. */
-  } k;
-  union {
-    upb_StringView str; /* For str/bytes. */
-    upb_value val;      /* For all other types. */
-  } v;
-} upb_MapEntry;
-
-/* 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_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_StringView _upb_map_tokey(const void* key, size_t size) {
   if (size == UPB_MAPTYPE_STRING) {
@@ -1714,10 +1339,24 @@
   }
 }
 
-/* Map operations, shared by reflection and generated code. */
+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 size_t _upb_Map_Size(const upb_Map* map) {
-  return map->table.t.count;
+UPB_INLINE void _upb_Map_Clear(upb_Map* map) {
+  upb_strtable_clear(&map->table);
+}
+
+UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key,
+                                size_t key_size) {
+  upb_StringView k = _upb_map_tokey(key, key_size);
+  return upb_strtable_remove2(&map->table, k.data, k.size, NULL);
 }
 
 UPB_INLINE bool _upb_Map_Get(const upb_Map* map, const void* key,
@@ -1731,38 +1370,779 @@
   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_INLINE upb_MapInsertStatus _upb_Map_Insert(upb_Map* map, const void* key,
+                                               size_t key_size, void* val,
+                                               size_t val_size, upb_Arena* a) {
   upb_StringView strkey = _upb_map_tokey(key, key_size);
   upb_value tabval = {0};
-  if (!_upb_map_tovalue(val, val_size, &tabval, a)) return false;
+  if (!_upb_map_tovalue(val, val_size, &tabval, a)) {
+    return kUpb_MapInsertStatus_OutOfMemory;
+  }
 
-  /* TODO(haberman): add overwrite operation to minimize number of lookups. */
-  upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
-  return upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a);
+  // TODO(haberman): add overwrite operation to minimize number of lookups.
+  bool removed =
+      upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
+  if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) {
+    return kUpb_MapInsertStatus_OutOfMemory;
+  }
+  return removed ? kUpb_MapInsertStatus_Replaced
+                 : kUpb_MapInsertStatus_Inserted;
 }
 
-UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key,
-                                size_t key_size) {
-  upb_StringView k = _upb_map_tokey(key, key_size);
-  return upb_strtable_remove2(&map->table, k.data, k.size, NULL);
+UPB_INLINE size_t _upb_Map_Size(const upb_Map* map) {
+  return map->table.t.count;
 }
 
-UPB_INLINE void _upb_Map_Clear(upb_Map* map) {
-  upb_strtable_clear(&map->table);
+// 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);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_COLLECTIONS_MAP_INTERNAL_H_ */
+
+#ifndef UPB_BASE_LOG2_H_
+#define UPB_BASE_LOG2_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE int upb_Log2Ceiling(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
 }
 
-/* Message map operations, these get the map from the message first. */
+UPB_INLINE int upb_Log2CeilingSize(int x) { return 1 << upb_Log2Ceiling(x); }
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_BASE_LOG2_H_ */
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+#ifndef UPB_COLLECTIONS_MAP_SORTER_INTERNAL_H_
+#define UPB_COLLECTIONS_MAP_SORTER_INTERNAL_H_
+
+#include <stdlib.h>
+
+
+#ifndef UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
+#define UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_Decoder;
+typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr,
+                                     upb_Message* msg, intptr_t table,
+                                     uint64_t hasbits, uint64_t data);
+typedef struct {
+  uint64_t field_data;
+  _upb_FieldParser* field_parser;
+} _upb_FastTable_Entry;
+
+typedef enum {
+  kUpb_ExtMode_NonExtendable = 0,  // Non-extendable message.
+  kUpb_ExtMode_Extendable = 1,     // Normal extendable message.
+  kUpb_ExtMode_IsMessageSet = 2,   // MessageSet message.
+  kUpb_ExtMode_IsMessageSet_ITEM =
+      3,  // MessageSet item (temporary only, see decode.c)
+
+  // During table building we steal a bit to indicate that the message is a map
+  // entry.  *Only* used during table building!
+  kUpb_ExtMode_IsMapEntry = 4,
+} upb_ExtMode;
+
+// upb_MiniTable represents the memory layout of a given upb_MessageDef.
+// The members are public so generated code can initialize them,
+// but users MUST NOT directly read or write any of its members.
+struct upb_MiniTable {
+  const upb_MiniTableSub* subs;
+  const upb_MiniTableField* 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;
+  uint8_t ext;  // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1
+  uint8_t dense_below;
+  uint8_t table_mask;
+  uint8_t required_count;  // Required fields have the lowest hasbits.
+
+  // To statically initialize the tables of variable length, we need a flexible
+  // array member, and we need to compile in gnu99 mode (constant initialization
+  // of flexible array members is a GNU extension, not in C99 unfortunately.
+  _upb_FastTable_Entry fasttable[];
+};
+
+// Map entries aren't actually stored for map fields, they are only used during
+// parsing. For parsing, it helps a lot if all map entry messages have the same
+// layout. The layout code in mini_table/decode.c will ensure that all map
+// entries have this layout.
+//
+// Note that users can and do create map entries directly, which will also use
+// this layout.
+//
+// NOTE: sync with mini_table/decode.c.
+typedef struct {
+  // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here,
+  // and the uint64_t helps make this clear.
+  uint64_t hasbits;
+  union {
+    upb_StringView str;  // For str/bytes.
+    upb_value val;       // For all other types.
+  } k;
+  union {
+    upb_StringView str;  // For str/bytes.
+    upb_value val;       // For all other types.
+  } v;
+} upb_MapEntryData;
+
+typedef struct {
+  void* internal_data;
+  upb_MapEntryData data;
+} upb_MapEntry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Computes a bitmask in which the |l->required_count| lowest bits are set,
+// except that we skip the lowest bit (because upb never uses hasbit 0).
+//
+// Sample output:
+//    requiredmask(1) => 0b10 (0x2)
+//    requiredmask(5) => 0b111110 (0x3e)
+UPB_INLINE uint64_t upb_MiniTable_requiredmask(const upb_MiniTable* l) {
+  int n = l->required_count;
+  assert(0 < n && n <= 63);
+  return ((1ULL << n) - 1) << 1;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_MESSAGE_INTERNAL_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// _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);
+}
+
+UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
+                                    _upb_sortedmap* sorted, upb_MapEntry* ent) {
+  if (sorted->pos == sorted->end) return false;
+  const upb_tabent* tabent = s->entries[sorted->pos++];
+  upb_StringView key = upb_tabstrview(tabent->key);
+  _upb_map_fromkey(key, &ent->data.k, map->key_size);
+  upb_value val = {tabent->val.val};
+  _upb_map_fromvalue(val, &ent->data.v, map->val_size);
+  return true;
+}
+
+UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter* s,
+                                      _upb_sortedmap* sorted) {
+  s->size = sorted->start;
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
+                            const upb_Map* map, _upb_sortedmap* sorted);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_COLLECTIONS_MAP_SORTER_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_MESSAGE_INTERNAL_H_
+#define UPB_MESSAGE_INTERNAL_H_
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#ifndef UPB_MESSAGE_EXTENSION_INTERNAL_H_
+#define UPB_MESSAGE_EXTENSION_INTERNAL_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_MESSAGE_MESSAGE_H_
+#define UPB_MESSAGE_MESSAGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Creates a new message with the given mini_table on the given arena.
+upb_Message* upb_Message_New(const upb_MiniTable* mini_table, upb_Arena* arena);
+
+// Adds unknown data (serialized protobuf data) to the given message.
+// The data is copied into the message instance.
+void upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
+                            upb_Arena* arena);
+
+// Returns a reference to the message's unknown data.
+const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);
+
+// Removes partial unknown data from message.
+void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len);
+
+// Returns the number of extensions present in this message.
+size_t upb_Message_ExtensionCount(const upb_Message* msg);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_MESSAGE_H_ */
+
+#ifndef UPB_MINI_TABLE_EXTENSION_INTERNAL_H_
+#define UPB_MINI_TABLE_EXTENSION_INTERNAL_H_
+
+
+#ifndef UPB_MINI_TABLE_FIELD_INTERNAL_H_
+#define UPB_MINI_TABLE_FIELD_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_MiniTableField {
+  uint32_t number;
+  uint16_t offset;
+  int16_t presence;       // If >0, hasbit_index.  If <0, ~oneof_index
+  uint16_t submsg_index;  // kUpb_NoSub if descriptortype != MESSAGE/GROUP/ENUM
+  uint8_t descriptortype;
+
+  // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift)
+  uint8_t mode;
+};
+
+#define kUpb_NoSub ((uint16_t)-1)
+
+typedef enum {
+  kUpb_FieldMode_Map = 0,
+  kUpb_FieldMode_Array = 1,
+  kUpb_FieldMode_Scalar = 2,
+} upb_FieldMode;
+
+// Mask to isolate the upb_FieldMode from field.mode.
+#define kUpb_FieldMode_Mask 3
+
+// Extra flags on the mode field.
+typedef enum {
+  kUpb_LabelFlags_IsPacked = 4,
+  kUpb_LabelFlags_IsExtension = 8,
+  // Indicates that this descriptor type is an "alternate type":
+  //   - for Int32, this indicates that the actual type is Enum (but was
+  //     rewritten to Int32 because it is an open enum that requires no check).
+  //   - for Bytes, this indicates that the actual type is String (but does
+  //     not require any UTF-8 check).
+  kUpb_LabelFlags_IsAlternate = 16,
+} upb_LabelFlags;
+
+// Note: we sort by this number when calculating layout order.
+typedef enum {
+  kUpb_FieldRep_1Byte = 0,
+  kUpb_FieldRep_4Byte = 1,
+  kUpb_FieldRep_StringView = 2,
+  kUpb_FieldRep_8Byte = 3,
+
+  kUpb_FieldRep_Max = kUpb_FieldRep_8Byte,
+} upb_FieldRep;
+
+#define kUpb_FieldRep_Shift 6
+
+UPB_INLINE upb_FieldRep
+_upb_MiniTableField_GetRep(const upb_MiniTableField* field) {
+  return (upb_FieldRep)(field->mode >> kUpb_FieldRep_Shift);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE upb_FieldMode upb_FieldMode_Get(const upb_MiniTableField* field) {
+  return (upb_FieldMode)(field->mode & 3);
+}
+
+UPB_INLINE bool upb_IsRepeatedOrMap(const upb_MiniTableField* field) {
+  // This works because upb_FieldMode has no value 3.
+  return !(field->mode & kUpb_FieldMode_Scalar);
+}
+
+UPB_INLINE bool upb_IsSubMessage(const upb_MiniTableField* field) {
+  return field->descriptortype == kUpb_FieldType_Message ||
+         field->descriptortype == kUpb_FieldType_Group;
+}
+
+// LINT.IfChange(presence_logic)
+
+// Hasbit access ///////////////////////////////////////////////////////////////
+
+UPB_INLINE size_t _upb_hasbit_ofs(size_t idx) { return idx / 8; }
+
+UPB_INLINE char _upb_hasbit_mask(size_t idx) { return 1 << (idx % 8); }
+
+UPB_INLINE bool _upb_hasbit(const upb_Message* msg, size_t idx) {
+  return (*UPB_PTR_AT(msg, _upb_hasbit_ofs(idx), const char) &
+          _upb_hasbit_mask(idx)) != 0;
+}
+
+UPB_INLINE void _upb_sethas(const upb_Message* msg, size_t idx) {
+  (*UPB_PTR_AT(msg, _upb_hasbit_ofs(idx), char)) |= _upb_hasbit_mask(idx);
+}
+
+UPB_INLINE void _upb_clearhas(const upb_Message* msg, size_t idx) {
+  (*UPB_PTR_AT(msg, _upb_hasbit_ofs(idx), char)) &= ~_upb_hasbit_mask(idx);
+}
+
+UPB_INLINE size_t _upb_Message_Hasidx(const upb_MiniTableField* f) {
+  UPB_ASSERT(f->presence > 0);
+  return f->presence;
+}
+
+UPB_INLINE bool _upb_hasbit_field(const upb_Message* msg,
+                                  const upb_MiniTableField* f) {
+  return _upb_hasbit(msg, _upb_Message_Hasidx(f));
+}
+
+UPB_INLINE void _upb_sethas_field(const upb_Message* msg,
+                                  const upb_MiniTableField* f) {
+  _upb_sethas(msg, _upb_Message_Hasidx(f));
+}
+
+UPB_INLINE void _upb_clearhas_field(const upb_Message* msg,
+                                    const upb_MiniTableField* f) {
+  _upb_clearhas(msg, _upb_Message_Hasidx(f));
+}
+
+// Oneof case access ///////////////////////////////////////////////////////////
+
+UPB_INLINE uint32_t* _upb_oneofcase(upb_Message* 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_MiniTableField* f) {
+  UPB_ASSERT(f->presence < 0);
+  return ~(ptrdiff_t)f->presence;
+}
+
+UPB_INLINE uint32_t* _upb_oneofcase_field(upb_Message* msg,
+                                          const upb_MiniTableField* f) {
+  return _upb_oneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_Message* msg,
+                                            const upb_MiniTableField* f) {
+  return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_Message* msg, size_t ofs) {
+  return *UPB_PTR_AT(msg, ofs, const upb_Message*) != NULL;
+}
+
+// LINT.ThenChange(GoogleInternalName2)
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_FIELD_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_SUB_INTERNAL_H_
+#define UPB_MINI_TABLE_SUB_INTERNAL_H_
+
+
+union upb_MiniTableSub {
+  const upb_MiniTable* submsg;
+  const upb_MiniTableEnum* subenum;
+};
+
+#endif /* UPB_MINI_TABLE_SUB_INTERNAL_H_ */
+
+// Must be last.
+
+struct upb_MiniTableExtension {
+  upb_MiniTableField field;
+  const upb_MiniTable* extendee;
+  upb_MiniTableSub sub;  // NULL unless submessage or proto2 enum
+};
+
+
+#endif /* UPB_MINI_TABLE_EXTENSION_INTERNAL_H_ */
+
+// Must be last.
+
+// The internal representation of an extension is self-describing: it contains
+// enough information that we can serialize it to binary format without needing
+// to look it up in a upb_ExtensionRegistry.
+//
+// This representation allocates 16 bytes to data on 64-bit platforms.
+// This is rather wasteful for scalars (in the extreme case of bool,
+// it wastes 15 bytes). We accept this because we expect messages to be
+// the most common extension type.
+typedef struct {
+  const upb_MiniTableExtension* ext;
+  union {
+    upb_StringView str;
+    void* ptr;
+    char scalar_data[8];
+  } data;
+} upb_Message_Extension;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Adds the given extension data to the given message.
+// |ext| is copied into the message instance.
+// This logically replaces any previously-added extension with this number.
+upb_Message_Extension* _upb_Message_GetOrCreateExtension(
+    upb_Message* msg, const upb_MiniTableExtension* ext, upb_Arena* arena);
+
+// Returns an array of extensions for this message.
+// Note: the array is ordered in reverse relative to the order of creation.
+const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
+                                                  size_t* count);
+
+// Returns an extension for the given field number, or NULL if no extension
+// exists for this field number.
+const upb_Message_Extension* _upb_Message_Getext(
+    const upb_Message* msg, const upb_MiniTableExtension* ext);
+
+void _upb_Message_Clearext(upb_Message* msg, const upb_MiniTableExtension* ext);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_EXTENSION_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_EXTENSION_REGISTRY_H_
+#define UPB_MINI_TABLE_EXTENSION_REGISTRY_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Extension registry: a dynamic data structure that stores a map of:
+ *   (upb_MiniTable, number) -> extension info
+ *
+ * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing
+ * binary format.
+ *
+ * upb_ExtensionRegistry is part of the mini-table (msglayout) family of
+ * objects. Like all mini-table objects, it is suitable for reflection-less
+ * builds that do not want to expose names into the binary.
+ *
+ * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory
+ * allocation and dynamic initialization:
+ * * If reflection is being used, then upb_DefPool will construct an appropriate
+ *   upb_ExtensionRegistry automatically.
+ * * For a mini-table only build, the user must manually construct the
+ *   upb_ExtensionRegistry and populate it with all of the extensions the user
+ * cares about.
+ * * A third alternative is to manually unpack relevant extensions after the
+ *   main parse is complete, similar to how Any works. This is perhaps the
+ *   nicest solution from the perspective of reducing dependencies, avoiding
+ *   dynamic memory allocation, and avoiding the need to parse uninteresting
+ *   extensions.  The downsides are:
+ *     (1) parse errors are not caught during the main parse
+ *     (2) the CPU hit of parsing comes during access, which could cause an
+ *         undesirable stutter in application performance.
+ *
+ * Users cannot directly get or put into this map. Users can only add the
+ * extensions from a generated module and pass the extension registry to the
+ * binary decoder.
+ *
+ * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use
+ * reflection do not need to populate a upb_ExtensionRegistry directly.
+ */
+
+typedef struct upb_ExtensionRegistry upb_ExtensionRegistry;
+
+// Creates a upb_ExtensionRegistry in the given arena.
+// The arena must outlive any use of the extreg.
+upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena);
+
+// Adds the given extension info for the array |e| of size |count| into the
+// registry. If there are any errors, the entire array is backed out.
+// The extensions must outlive the registry.
+// Possible errors include OOM or an extension number that already exists.
+// TODO: There is currently no way to determine the exact reason for failure.
+bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r,
+                                    const upb_MiniTableExtension** e,
+                                    size_t count);
+
+// Looks up the extension (if any) defined for message type |t| and field
+// number |num|. Returns the extension if found, otherwise NULL.
+const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup(
+    const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ */
+
+#ifndef UPB_MINI_TABLE_FILE_INTERNAL_H_
+#define UPB_MINI_TABLE_FILE_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_MiniTableFile {
+  const upb_MiniTable** msgs;
+  const upb_MiniTableEnum** enums;
+  const upb_MiniTableExtension** exts;
+  int msg_count;
+  int enum_count;
+  int ext_count;
+};
+
+
+#endif /* UPB_MINI_TABLE_FILE_INTERNAL_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const float kUpb_FltInfinity;
+extern const double kUpb_Infinity;
+extern const double kUpb_NaN;
+
+/* Internal members of a upb_Message that track unknown fields and/or
+ * extensions. We can change this without breaking binary compatibility.  We put
+ * these before the user's data.  The user's upb_Message* points after the
+ * upb_Message_Internal. */
+
+typedef struct {
+  /* Total size of this structure, including the data that follows.
+   * Must be aligned to 8, which is alignof(upb_Message_Extension) */
+  uint32_t size;
+
+  /* Offsets relative to the beginning of this structure.
+   *
+   * Unknown data grows forward from the beginning to unknown_end.
+   * Extension data grows backward from size to ext_begin.
+   * When the two meet, we're out of data and have to realloc.
+   *
+   * If we imagine that the final member of this struct is:
+   *   char data[size - overhead];  // overhead =
+   * sizeof(upb_Message_InternalData)
+   *
+   * Then we have:
+   *   unknown data: data[0 .. (unknown_end - overhead)]
+   *   extensions data: data[(ext_begin - overhead) .. (size - overhead)] */
+  uint32_t unknown_end;
+  uint32_t ext_begin;
+  /* Data follows, as if there were an array:
+   *   char data[size - sizeof(upb_Message_InternalData)]; */
+} upb_Message_InternalData;
+
+typedef struct {
+  upb_Message_InternalData* internal;
+  /* Message data follows. */
+} upb_Message_Internal;
+
+/* Maps upb_CType -> memory size. */
+extern char _upb_CTypeo_size[12];
+
+UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* t) {
+  return t->size + sizeof(upb_Message_Internal);
+}
+
+// Inline version upb_Message_New(), for internal use.
+UPB_INLINE upb_Message* _upb_Message_New(const upb_MiniTable* mini_table,
+                                         upb_Arena* arena) {
+  size_t size = upb_msg_sizeof(mini_table);
+  void* mem = upb_Arena_Malloc(arena, size + sizeof(upb_Message_Internal));
+  if (UPB_UNLIKELY(!mem)) return NULL;
+  upb_Message* msg = UPB_PTR_AT(mem, sizeof(upb_Message_Internal), upb_Message);
+  memset(mem, 0, size);
+  return msg;
+}
+
+UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(
+    const upb_Message* msg) {
+  ptrdiff_t size = sizeof(upb_Message_Internal);
+  return (upb_Message_Internal*)((char*)msg - size);
+}
+
+// Clears the given message.
+void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l);
+
+// Discards the unknown fields for this message only.
+void _upb_Message_DiscardUnknown_shallow(upb_Message* msg);
+
+// Adds unknown data (serialized protobuf data) to the given message.
+// The data is copied into the message instance.
+bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
+                             upb_Arena* arena);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_ENUM_INTERNAL_H_
+#define UPB_MINI_TABLE_ENUM_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_MiniTableEnum {
+  uint32_t mask_limit;   // Limit enum value that can be tested with mask.
+  uint32_t value_count;  // Number of values after the bitfield.
+  uint32_t data[];       // Bitmask + enumerated values follow.
+};
+
+typedef enum {
+  _kUpb_FastEnumCheck_ValueIsInEnum = 0,
+  _kUpb_FastEnumCheck_ValueIsNotInEnum = 1,
+  _kUpb_FastEnumCheck_CannotCheckFast = 2,
+} _kUpb_FastEnumCheck_Status;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE _kUpb_FastEnumCheck_Status
+_upb_MiniTable_CheckEnumValueFast(const upb_MiniTableEnum* e, uint32_t val) {
+  if (UPB_UNLIKELY(val >= 64)) return _kUpb_FastEnumCheck_CannotCheckFast;
+  uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32);
+  return (mask & (1ULL << val)) ? _kUpb_FastEnumCheck_ValueIsInEnum
+                                : _kUpb_FastEnumCheck_ValueIsNotInEnum;
+}
+
+UPB_INLINE bool _upb_MiniTable_CheckEnumValueSlow(const upb_MiniTableEnum* e,
+                                                  uint32_t val) {
+  if (val < e->mask_limit) return e->data[val / 32] & (1ULL << (val % 32));
+  // OPT: binary search long lists?
+  const uint32_t* start = &e->data[e->mask_limit / 32];
+  const uint32_t* limit = &e->data[(e->mask_limit / 32) + e->value_count];
+  for (const uint32_t* p = start; p < limit; p++) {
+    if (*p == val) return true;
+  }
+  return false;
+}
+
+// Validates enum value against range defined by enum mini table.
+UPB_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e,
+                                             uint32_t val) {
+  _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, val);
+  if (UPB_UNLIKELY(status == _kUpb_FastEnumCheck_CannotCheckFast)) {
+    return _upb_MiniTable_CheckEnumValueSlow(e, val);
+  }
+  return status == _kUpb_FastEnumCheck_ValueIsInEnum ? true : false;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_ENUM_INTERNAL_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_
+
+
+// These functions are only used by generated code.
+
+#ifndef UPB_COLLECTIONS_MAP_GENCODE_UTIL_H_
+#define UPB_COLLECTIONS_MAP_GENCODE_UTIL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Message map operations, these get the map from the message first.
 
 UPB_INLINE size_t _upb_msg_map_size(const upb_Message* msg, size_t ofs) {
   upb_Map* map = *UPB_PTR_AT(msg, ofs, upb_Map*);
@@ -1791,7 +2171,8 @@
   if (!*map) {
     *map = _upb_Map_New(arena, key_size, val_size);
   }
-  return _upb_Map_Set(*map, key, key_size, val, val_size, arena);
+  return _upb_Map_Insert(*map, key, key_size, val, val_size, arena) !=
+         kUpb_MapInsertStatus_OutOfMemory;
 }
 
 UPB_INLINE bool _upb_msg_map_delete(upb_Message* msg, size_t ofs,
@@ -1807,8 +2188,6 @@
   _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;
@@ -1827,8 +2206,8 @@
 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_StringView for string fields. */
+  // This is like _upb_map_tovalue() except the entry already exists
+  // so we can reuse the allocated upb_StringView for string fields.
   if (size == UPB_MAPTYPE_STRING) {
     upb_StringView* strp = (upb_StringView*)(uintptr_t)ent->val.val;
     memcpy(strp, val, sizeof(*strp));
@@ -1837,52 +2216,68 @@
   }
 }
 
-/** _upb_mapsorter
- * *************************************************************/
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-/* _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;
+#endif /* UPB_COLLECTIONS_MAP_GENCODE_UTIL_H_ */
 
-typedef struct {
-  int start;
-  int pos;
-  int end;
-} _upb_sortedmap;
+#ifndef UPB_MESSAGE_ACCESSORS_H_
+#define UPB_MESSAGE_ACCESSORS_H_
 
-UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter* s) {
-  s->entries = NULL;
-  s->size = 0;
-  s->cap = 0;
+
+#ifndef UPB_MINI_TABLE_COMMON_H_
+#define UPB_MINI_TABLE_COMMON_H_
+
+
+// Must be last.
+
+typedef enum {
+  kUpb_FieldModifier_IsRepeated = 1 << 0,
+  kUpb_FieldModifier_IsPacked = 1 << 1,
+  kUpb_FieldModifier_IsClosedEnum = 1 << 2,
+  kUpb_FieldModifier_IsProto3Singular = 1 << 3,
+  kUpb_FieldModifier_IsRequired = 1 << 4,
+} kUpb_FieldModifier;
+
+typedef enum {
+  kUpb_MessageModifier_ValidateUtf8 = 1 << 0,
+  kUpb_MessageModifier_DefaultIsPacked = 1 << 1,
+  kUpb_MessageModifier_IsExtendable = 1 << 2,
+} kUpb_MessageModifier;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_MiniTableField* upb_MiniTable_FindFieldByNumber(
+    const upb_MiniTable* table, uint32_t number);
+
+upb_FieldType upb_MiniTableField_Type(const upb_MiniTableField* field);
+
+UPB_INLINE bool upb_MiniTableField_IsExtension(
+    const upb_MiniTableField* field) {
+  return field->mode & kUpb_LabelFlags_IsExtension;
 }
 
-UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter* s) {
-  if (s->entries) free(s->entries);
+UPB_INLINE bool upb_MiniTableField_HasPresence(
+    const upb_MiniTableField* field) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    return !upb_IsRepeatedOrMap(field);
+  } else {
+    return field->presence != 0;
+  }
 }
 
-bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType 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 const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
+    const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
+  return mini_table->subs[field->submsg_index].submsg;
 }
 
-UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
-                                    _upb_sortedmap* sorted, upb_MapEntry* ent) {
-  if (sorted->pos == sorted->end) return false;
-  const upb_tabent* tabent = s->entries[sorted->pos++];
-  upb_StringView 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;
+UPB_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable(
+    const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
+  return mini_table->subs[field->submsg_index].subenum;
 }
 
 #ifdef __cplusplus
@@ -1890,262 +2285,638 @@
 #endif
 
 
-#endif /* UPB_MSG_INT_H_ */
+#endif /* UPB_MINI_TABLE_COMMON_H_ */
 
-/** upb/upb_internal.h ************************************************************/
-#ifndef UPB_INT_H_
-#define UPB_INT_H_
+// Must be last.
 
-
-struct mem_block;
-typedef struct mem_block mem_block;
-
-struct upb_Arena {
-  _upb_ArenaHead 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;
-};
-
-// Encodes a float or double that is round-trippable, but as short as possible.
-// These routines are not fully optimal (not guaranteed to be shortest), but are
-// short-ish and match the implementation that has been used in protobuf since
-// the beginning.
-//
-// The given buffer size must be at least kUpb_RoundTripBufferSize.
-enum { kUpb_RoundTripBufferSize = 32 };
-void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size);
-void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size);
-
-#endif /* UPB_INT_H_ */
-
-/* Must be last. */
-
-#define DECODE_NOGROUP (uint32_t) - 1
-
-typedef struct upb_Decoder {
-  const char* end;          /* Can read up to 16 bytes slop beyond this. */
-  const char* limit_ptr;    /* = end + UPB_MIN(limit, 0) */
-  upb_Message* unknown_msg; /* If non-NULL, add unknown data at buffer flip. */
-  const char* unknown;      /* Start of unknown data. */
-  const upb_ExtensionRegistry*
-      extreg;         /* For looking up extensions during the parse. */
-  int limit;          /* Submessage limit relative to end. */
-  int depth;          /* Tracks recursion depth to bound stack usage. */
-  uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */
-  uint16_t options;
-  bool missing_required;
-  char patch[32];
-  upb_Arena arena;
-  jmp_buf err;
-
-#ifndef NDEBUG
-  const char* debug_tagstart;
-  const char* debug_valstart;
+#ifdef __cplusplus
+extern "C" {
 #endif
-} upb_Decoder;
 
-/* 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_Decoder* d, int status);
+UPB_INLINE bool _upb_MiniTableField_InOneOf(const upb_MiniTableField* field) {
+  return field->presence < 0;
+}
 
-extern const uint8_t upb_utf8_offsets[];
+UPB_INLINE void* _upb_MiniTableField_GetPtr(upb_Message* msg,
+                                            const upb_MiniTableField* field) {
+  return (char*)msg + field->offset;
+}
 
-UPB_INLINE
-bool decode_verifyutf8_inl(const char* ptr, int len) {
-  const char* end = ptr + len;
+UPB_INLINE const void* _upb_MiniTableField_GetConstPtr(
+    const upb_Message* msg, const upb_MiniTableField* field) {
+  return (char*)msg + field->offset;
+}
 
-  // Check 8 bytes at a time for any non-ASCII char.
-  while (end - ptr >= 8) {
-    uint64_t data;
-    memcpy(&data, ptr, 8);
-    if (data & 0x8080808080808080) goto non_ascii;
-    ptr += 8;
+UPB_INLINE void _upb_MiniTable_SetPresence(upb_Message* msg,
+                                           const upb_MiniTableField* field) {
+  if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  } else if (_upb_MiniTableField_InOneOf(field)) {
+    *_upb_oneofcase_field(msg, field) = field->number;
   }
-
-  // Check one byte at a time for non-ASCII.
-  while (ptr < end) {
-    if (*ptr & 0x80) goto non_ascii;
-    ptr++;
-  }
-
-  return true;
-
-non_ascii:
-  return utf8_range2((const unsigned char*)ptr, end - ptr) == 0;
 }
 
-const char* decode_checkrequired(upb_Decoder* d, const char* ptr,
-                                 const upb_Message* msg,
-                                 const upb_MiniTable* l);
+UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg,
+                                       const upb_MiniTableField* field);
 
-/* 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_MiniTable* tablep) {
-  return ((intptr_t)tablep << 8) | tablep->table_mask;
-}
-
-UPB_INLINE const upb_MiniTable* decode_totablep(intptr_t table) {
-  return (const upb_MiniTable*)(table >> 8);
-}
-
-UPB_INLINE
-const char* decode_isdonefallback_inl(upb_Decoder* d, const char* ptr,
-                                      int overrun, int* status) {
-  if (overrun < d->limit) {
-    /* Need to copy remaining data into patch buffer. */
-    UPB_ASSERT(overrun < 16);
-    if (d->unknown_msg) {
-      if (!_upb_Message_AddUnknown(d->unknown_msg, d->unknown, ptr - d->unknown,
-                                   &d->arena)) {
-        *status = kUpb_DecodeStatus_OutOfMemory;
-        return NULL;
-      }
-      d->unknown = &d->patch[0] + overrun;
+UPB_INLINE bool _upb_MiniTable_ValueIsNonZero(const void* default_val,
+                                              const upb_MiniTableField* field) {
+  char zero[16] = {0};
+  switch (_upb_MiniTableField_GetRep(field)) {
+    case kUpb_FieldRep_1Byte:
+      return memcmp(&zero, default_val, 1) != 0;
+    case kUpb_FieldRep_4Byte:
+      return memcmp(&zero, default_val, 4) != 0;
+    case kUpb_FieldRep_8Byte:
+      return memcmp(&zero, default_val, 8) != 0;
+    case kUpb_FieldRep_StringView: {
+      const upb_StringView* sv = (const upb_StringView*)default_val;
+      return sv->size != 0;
     }
-    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->options &= ~kUpb_DecodeOption_AliasString;
-    UPB_ASSERT(ptr < d->limit_ptr);
-    return ptr;
+  }
+  UPB_UNREACHABLE();
+}
+
+UPB_INLINE void _upb_MiniTable_CopyFieldData(void* to, const void* from,
+                                             const upb_MiniTableField* field) {
+  switch (_upb_MiniTableField_GetRep(field)) {
+    case kUpb_FieldRep_1Byte:
+      memcpy(to, from, 1);
+      return;
+    case kUpb_FieldRep_4Byte:
+      memcpy(to, from, 4);
+      return;
+    case kUpb_FieldRep_8Byte:
+      memcpy(to, from, 8);
+      return;
+    case kUpb_FieldRep_StringView: {
+      memcpy(to, from, sizeof(upb_StringView));
+      return;
+    }
+  }
+  UPB_UNREACHABLE();
+}
+
+// Here we define universal getter/setter functions for message fields.
+// These look very branchy and inefficient, but as long as the MiniTableField
+// values are known at compile time, all the branches are optimized away and
+// we are left with ideal code.  This can happen either through through
+// literals or UPB_ASSUME():
+//
+//   // Via string literals.
+//   bool FooMessage_set_bool_field(const upb_Message* msg, bool val) {
+//     const upb_MiniTableField field = {1, 0, 0, /* etc... */};
+//     // All value in "field" are compile-time known.
+//     _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+//   }
+//
+//   // Via UPB_ASSUME().
+//   UPB_INLINE void upb_MiniTable_SetBool(upb_Message* msg,
+//                                         const upb_MiniTableField* field,
+//                                         bool value) {
+//     UPB_ASSUME(field->descriptortype == kUpb_FieldType_Bool);
+//     UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+//     UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
+//     _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+//   }
+//
+// As a result, we can use these universal getters/setters for *all* message
+// accessors: generated code, MiniTable accessors, and reflection.  The only
+// exception is the binary encoder/decoder, which need to be a bit more clever
+// about how the read/write the message data, for efficiency.
+
+static UPB_FORCEINLINE void _upb_MiniTable_GetNonExtensionField(
+    const upb_Message* msg, const upb_MiniTableField* field,
+    const void* default_val, void* val) {
+  UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
+  if ((_upb_MiniTableField_InOneOf(field) ||
+       _upb_MiniTable_ValueIsNonZero(default_val, field)) &&
+      !upb_MiniTable_HasField(msg, field)) {
+    _upb_MiniTable_CopyFieldData(val, default_val, field);
+    return;
+  }
+  _upb_MiniTable_CopyFieldData(val, _upb_MiniTableField_GetConstPtr(msg, field),
+                               field);
+}
+
+UPB_INLINE void _upb_MiniTable_GetExtensionField(
+    const upb_Message* msg, const upb_MiniTableExtension* mt_ext,
+    const void* default_val, void* val) {
+  UPB_ASSUME(upb_MiniTableField_IsExtension(&mt_ext->field));
+  const upb_Message_Extension* ext = _upb_Message_Getext(msg, mt_ext);
+  if (ext) {
+    _upb_MiniTable_CopyFieldData(val, &ext->data, &mt_ext->field);
   } else {
-    *status = kUpb_DecodeStatus_Malformed;
-    return NULL;
+    _upb_MiniTable_CopyFieldData(val, default_val, &mt_ext->field);
   }
 }
 
-const char* decode_isdonefallback(upb_Decoder* d, const char* ptr, int overrun);
+UPB_INLINE void _upb_MiniTable_GetField(const upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        const void* default_val, void* val) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    _upb_MiniTable_GetExtensionField(msg, (upb_MiniTableExtension*)field,
+                                     default_val, val);
+  } else {
+    _upb_MiniTable_GetNonExtensionField(msg, field, default_val, val);
+  }
+}
 
-UPB_INLINE
-bool decode_isdone(upb_Decoder* 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)) {
+UPB_INLINE void _upb_MiniTable_SetNonExtensionField(
+    upb_Message* msg, const upb_MiniTableField* field, const void* val) {
+  UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
+  _upb_MiniTable_SetPresence(msg, field);
+  _upb_MiniTable_CopyFieldData(_upb_MiniTableField_GetPtr(msg, field), val,
+                               field);
+}
+
+UPB_INLINE bool _upb_MiniTable_SetExtensionField(
+    upb_Message* msg, const upb_MiniTableExtension* mt_ext, const void* val,
+    upb_Arena* a) {
+  upb_Message_Extension* ext =
+      _upb_Message_GetOrCreateExtension(msg, mt_ext, a);
+  if (!ext) return false;
+  _upb_MiniTable_CopyFieldData(&ext->data, val, &mt_ext->field);
+  return true;
+}
+
+UPB_INLINE bool _upb_MiniTable_SetField(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        const void* val, upb_Arena* a) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    return _upb_MiniTable_SetExtensionField(
+        msg, (const upb_MiniTableExtension*)field, val, a);
+  } else {
+    _upb_MiniTable_SetNonExtensionField(msg, field, val);
     return true;
-  } else {
-    *ptr = decode_isdonefallback(d, *ptr, overrun);
-    return false;
   }
 }
 
-#if UPB_FASTTABLE
-UPB_INLINE
-const char* fastdecode_tagdispatch(upb_Decoder* d, const char* ptr,
-                                   upb_Message* msg, intptr_t table,
-                                   uint64_t hasbits, uint64_t tag) {
-  const upb_MiniTable* 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);
+UPB_INLINE bool _upb_MiniTable_HasExtensionField(
+    const upb_Message* msg, const upb_MiniTableExtension* ext) {
+  UPB_ASSERT(upb_MiniTableField_HasPresence(&ext->field));
+  return _upb_Message_Getext(msg, ext) != NULL;
 }
+
+UPB_INLINE bool _upb_MiniTable_HasNonExtensionField(
+    const upb_Message* msg, const upb_MiniTableField* field) {
+  UPB_ASSERT(upb_MiniTableField_HasPresence(field));
+  UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
+  if (_upb_MiniTableField_InOneOf(field)) {
+    return _upb_getoneofcase_field(msg, field) == field->number;
+  } else {
+    return _upb_hasbit_field(msg, field);
+  }
+}
+
+UPB_INLINE bool _upb_MiniTable_HasField(const upb_Message* msg,
+                                        const upb_MiniTableField* field) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    return _upb_MiniTable_HasExtensionField(
+        msg, (const upb_MiniTableExtension*)field);
+  } else {
+    return _upb_MiniTable_HasNonExtensionField(msg, field);
+  }
+}
+
+UPB_INLINE void _upb_MiniTable_ClearExtensionField(
+    upb_Message* msg, const upb_MiniTableExtension* ext) {
+  _upb_Message_Clearext(msg, ext);
+}
+
+UPB_INLINE void _upb_MiniTable_ClearNonExtensionField(
+    upb_Message* msg, const upb_MiniTableField* field) {
+  if (field->presence > 0) {
+    _upb_clearhas_field(msg, field);
+  } else if (_upb_MiniTableField_InOneOf(field)) {
+    uint32_t* oneof_case = _upb_oneofcase_field(msg, field);
+    if (*oneof_case != field->number) return;
+    *oneof_case = 0;
+  }
+  const char zeros[16] = {0};
+  _upb_MiniTable_CopyFieldData(_upb_MiniTableField_GetPtr(msg, field), zeros,
+                               field);
+}
+
+UPB_INLINE void _upb_MiniTable_ClearField(upb_Message* msg,
+                                          const upb_MiniTableField* field) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    _upb_Message_Clearext(msg, (const upb_MiniTableExtension*)field);
+  } else {
+    _upb_MiniTable_ClearNonExtensionField(msg, field);
+  }
+}
+
+// EVERYTHING ABOVE THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+UPB_INLINE void upb_MiniTable_ClearField(upb_Message* msg,
+                                         const upb_MiniTableField* field) {
+  _upb_MiniTable_ClearNonExtensionField(msg, field);
+}
+
+UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg,
+                                       const upb_MiniTableField* field) {
+  return _upb_MiniTable_HasNonExtensionField(msg, field);
+}
+
+UPB_INLINE bool upb_MiniTable_GetBool(const upb_Message* msg,
+                                      const upb_MiniTableField* field,
+                                      bool default_val) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Bool);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
+  bool ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetBool(upb_Message* msg,
+                                      const upb_MiniTableField* field,
+                                      bool value) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Bool);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE int32_t upb_MiniTable_GetInt32(const upb_Message* msg,
+                                          const upb_MiniTableField* field,
+                                          int32_t default_val) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Int32 ||
+             field->descriptortype == kUpb_FieldType_SInt32 ||
+             field->descriptortype == kUpb_FieldType_SFixed32 ||
+             field->descriptortype == kUpb_FieldType_Enum);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  int32_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetInt32(upb_Message* msg,
+                                       const upb_MiniTableField* field,
+                                       int32_t value) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Int32 ||
+             field->descriptortype == kUpb_FieldType_SInt32 ||
+             field->descriptortype == kUpb_FieldType_SFixed32);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE uint32_t upb_MiniTable_GetUInt32(const upb_Message* msg,
+                                            const upb_MiniTableField* field,
+                                            uint32_t default_val) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_UInt32 ||
+             field->descriptortype == kUpb_FieldType_Fixed32);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  uint32_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetUInt32(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        uint32_t value) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_UInt32 ||
+             field->descriptortype == kUpb_FieldType_Fixed32);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE void upb_MiniTable_SetEnumProto2(upb_Message* msg,
+                                            const upb_MiniTable* msg_mini_table,
+                                            const upb_MiniTableField* field,
+                                            int32_t value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Enum);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  UPB_ASSERT(upb_MiniTableEnum_CheckValue(
+      upb_MiniTable_GetSubEnumTable(msg_mini_table, field), value));
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE int64_t upb_MiniTable_GetInt64(const upb_Message* msg,
+                                          const upb_MiniTableField* field,
+                                          uint64_t default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int64 ||
+             field->descriptortype == kUpb_FieldType_SInt64 ||
+             field->descriptortype == kUpb_FieldType_SFixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  int64_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetInt64(upb_Message* msg,
+                                       const upb_MiniTableField* field,
+                                       int64_t value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int64 ||
+             field->descriptortype == kUpb_FieldType_SInt64 ||
+             field->descriptortype == kUpb_FieldType_SFixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE uint64_t upb_MiniTable_GetUInt64(const upb_Message* msg,
+                                            const upb_MiniTableField* field,
+                                            uint64_t default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt64 ||
+             field->descriptortype == kUpb_FieldType_Fixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  uint64_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetUInt64(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        uint64_t value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt64 ||
+             field->descriptortype == kUpb_FieldType_Fixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE float upb_MiniTable_GetFloat(const upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        float default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Float);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  float ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetFloat(upb_Message* msg,
+                                       const upb_MiniTableField* field,
+                                       float value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Float);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE double upb_MiniTable_GetDouble(const upb_Message* msg,
+                                          const upb_MiniTableField* field,
+                                          double default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Double);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  double ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetDouble(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        double value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Double);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE upb_StringView
+upb_MiniTable_GetString(const upb_Message* msg, const upb_MiniTableField* field,
+                        upb_StringView def_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bytes ||
+             field->descriptortype == kUpb_FieldType_String);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView);
+  upb_StringView ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &def_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetString(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        upb_StringView value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bytes ||
+             field->descriptortype == kUpb_FieldType_String);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE const upb_Message* upb_MiniTable_GetMessage(
+    const upb_Message* msg, const upb_MiniTableField* field,
+    upb_Message* default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message ||
+             field->descriptortype == kUpb_FieldType_Group);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) ==
+             UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte));
+  upb_Message* ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetMessage(upb_Message* msg,
+                                         const upb_MiniTable* mini_table,
+                                         const upb_MiniTableField* field,
+                                         upb_Message* sub_message) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message ||
+             field->descriptortype == kUpb_FieldType_Group);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) ==
+             UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte));
+  UPB_ASSERT(mini_table->subs[field->submsg_index].submsg);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &sub_message);
+}
+
+UPB_INLINE upb_Message* upb_MiniTable_GetMutableMessage(
+    upb_Message* msg, const upb_MiniTable* mini_table,
+    const upb_MiniTableField* field, upb_Arena* arena) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message ||
+             field->descriptortype == kUpb_FieldType_Group);
+  upb_Message* sub_message = *UPB_PTR_AT(msg, field->offset, upb_Message*);
+  if (!sub_message) {
+    const upb_MiniTable* sub_mini_table =
+        mini_table->subs[field->submsg_index].submsg;
+    UPB_ASSERT(sub_mini_table);
+    sub_message = _upb_Message_New(sub_mini_table, arena);
+    *UPB_PTR_AT(msg, field->offset, upb_Message*) = sub_message;
+    _upb_MiniTable_SetPresence(msg, field);
+  }
+  return sub_message;
+}
+
+UPB_INLINE const upb_Array* upb_MiniTable_GetArray(
+    const upb_Message* msg, const upb_MiniTableField* field) {
+  const upb_Array* ret;
+  const upb_Array* default_val = NULL;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE upb_Array* upb_MiniTable_GetMutableArray(
+    upb_Message* msg, const upb_MiniTableField* field) {
+  return (upb_Array*)upb_MiniTable_GetArray(msg, field);
+}
+
+void* upb_MiniTable_ResizeArray(upb_Message* msg,
+                                const upb_MiniTableField* field, size_t len,
+                                upb_Arena* arena);
+typedef enum {
+  kUpb_GetExtension_Ok,
+  kUpb_GetExtension_NotPresent,
+  kUpb_GetExtension_ParseError,
+  kUpb_GetExtension_OutOfMemory,
+} upb_GetExtension_Status;
+
+typedef enum {
+  kUpb_GetExtensionAsBytes_Ok,
+  kUpb_GetExtensionAsBytes_NotPresent,
+  kUpb_GetExtensionAsBytes_EncodeError,
+} upb_GetExtensionAsBytes_Status;
+
+// Returns a message extension or promotes an unknown field to
+// an extension.
+//
+// TODO(ferhat): Only supports extension fields that are messages,
+// expand support to include non-message types.
+upb_GetExtension_Status upb_MiniTable_GetOrPromoteExtension(
+    upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int decode_options, upb_Arena* arena,
+    const upb_Message_Extension** extension);
+
+// Returns a message extension or unknown field matching the extension
+// data as bytes.
+//
+// If an extension has already been decoded it will be re-encoded
+// to bytes.
+upb_GetExtensionAsBytes_Status upb_MiniTable_GetExtensionAsBytes(
+    const upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int encode_options, upb_Arena* arena, const char** extension_data,
+    size_t* len);
+
+typedef enum {
+  kUpb_FindUnknown_Ok,
+  kUpb_FindUnknown_NotPresent,
+  kUpb_FindUnknown_ParseError,
+} upb_FindUnknown_Status;
+
+typedef struct {
+  upb_FindUnknown_Status status;
+  // Start of unknown field data in message arena.
+  const char* ptr;
+  // Size of unknown field data.
+  size_t len;
+} upb_FindUnknownRet;
+
+// Finds first occurrence of unknown data by tag id in message.
+upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg,
+                                             uint32_t field_number);
+
+typedef enum {
+  kUpb_UnknownToMessage_Ok,
+  kUpb_UnknownToMessage_ParseError,
+  kUpb_UnknownToMessage_OutOfMemory,
+  kUpb_UnknownToMessage_NotFound,
+} upb_UnknownToMessage_Status;
+
+typedef struct {
+  upb_UnknownToMessage_Status status;
+  upb_Message* message;
+} upb_UnknownToMessageRet;
+
+// Promotes unknown data inside message to a upb_Message parsing the unknown.
+//
+// The unknown data is removed from message after field value is set
+// using upb_MiniTable_SetMessage.
+upb_UnknownToMessageRet upb_MiniTable_PromoteUnknownToMessage(
+    upb_Message* msg, const upb_MiniTable* mini_table,
+    const upb_MiniTableField* field, const upb_MiniTable* sub_mini_table,
+    int decode_options, upb_Arena* arena);
+
+// Promotes all unknown data that matches field tag id to repeated messages
+// in upb_Array.
+//
+// The unknown data is removed from message after upb_Array is populated.
+// Since repeated messages can't be packed we remove each unknown that
+// contains the target tag id.
+upb_UnknownToMessage_Status upb_MiniTable_PromoteUnknownToMessageArray(
+    upb_Message* msg, const upb_MiniTableField* field,
+    const upb_MiniTable* mini_table, int decode_options, upb_Arena* arena);
+
+#ifdef __cplusplus
+} /* extern "C" */
 #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_Decoder* d) {
-  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
-}
+#endif  // UPB_MESSAGE_ACCESSORS_H_
 
-UPB_INLINE int decode_pushlimit(upb_Decoder* 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_decode: parsing into a upb_Message using a upb_MiniTable.
 
-UPB_INLINE void decode_poplimit(upb_Decoder* 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);
-}
+#ifndef UPB_WIRE_DECODE_H_
+#define UPB_WIRE_DECODE_H_
 
 
-#endif /* UPB_DECODE_INT_H_ */
-
-/** upb/encode.h ************************************************************/
-/*
- * upb_Encode: parsing into a upb_Message using a upb_MiniTable.
- */
-
-#ifndef UPB_ENCODE_H_
-#define UPB_ENCODE_H_
-
-
-/* Must be last. */
+// 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 set, strings will alias the input buffer instead of copying into the
+   * arena. */
+  kUpb_DecodeOption_AliasString = 1,
+
+  /* If set, the parse will return failure if any message is missing any
+   * required fields when the message data ends.  The parse will still continue,
+   * and the failure will only be reported at the end.
    *
-   * If your proto contains maps, the encoder will need to malloc()/free()
-   * memory during encode. */
-  kUpb_Encode_Deterministic = 1,
-
-  /* When set, unknown fields are not printed. */
-  kUpb_Encode_SkipUnknown = 2,
-
-  /* When set, the encode will fail if any required fields are missing. */
-  kUpb_Encode_CheckRequired = 4,
+   * IMPORTANT CAVEATS:
+   *
+   * 1. This can throw a false positive failure if an incomplete message is seen
+   *    on the wire but is later completed when the sub-message occurs again.
+   *    For this reason, a second pass is required to verify a failure, to be
+   *    truly robust.
+   *
+   * 2. This can return a false success if you are decoding into a message that
+   *    already has some sub-message fields present.  If the sub-message does
+   *    not occur in the binary payload, we will never visit it and discover the
+   *    incomplete sub-message.  For this reason, this check is only useful for
+   *    implemting ParseFromString() semantics.  For MergeFromString(), a
+   *    post-parse validation step will always be necessary. */
+  kUpb_DecodeOption_CheckRequired = 2,
 };
 
-#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
 
-char* upb_Encode(const void* msg, const upb_MiniTable* l, int options,
-                 upb_Arena* arena, size_t* size);
+typedef enum {
+  kUpb_DecodeStatus_Ok = 0,
+  kUpb_DecodeStatus_Malformed = 1,         // Wire format was corrupt
+  kUpb_DecodeStatus_OutOfMemory = 2,       // Arena alloc failed
+  kUpb_DecodeStatus_BadUtf8 = 3,           // String field had bad UTF-8
+  kUpb_DecodeStatus_MaxDepthExceeded = 4,  // Exceeded UPB_DECODE_MAXDEPTH
 
+  // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise
+  // succeeded.
+  kUpb_DecodeStatus_MissingRequired = 5,
+} upb_DecodeStatus;
+
+upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
+                            const upb_MiniTable* l,
+                            const upb_ExtensionRegistry* extreg, int options,
+                            upb_Arena* arena);
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
-#endif /* UPB_ENCODE_H_ */
 
-/** upb/decode_fast.h ************************************************************/
+#endif /* UPB_WIRE_DECODE_H_ */
+
 // These are the specialized field parser functions for the fast parser.
 // Generated tables will refer to these by name.
 //
@@ -2180,17 +2951,24 @@
 //   - '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_
+#ifndef UPB_WIRE_DECODE_FAST_H_
+#define UPB_WIRE_DECODE_FAST_H_
 
 
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct upb_Decoder;
 
 // 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_Decoder* d, const char* ptr,
-                               upb_Message* msg, intptr_t table,
-                               uint64_t hasbits, uint64_t data);
+const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d,
+                                           const char* ptr, upb_Message* msg,
+                                           intptr_t table, uint64_t hasbits,
+                                           uint64_t data);
 
 #define UPB_PARSE_PARAMS                                                    \
   struct upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \
@@ -2270,52 +3048,68 @@
 
 #undef UPB_PARSE_PARAMS
 
-#endif /* UPB_DECODE_FAST_H_ */
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-/** 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_
+#endif /* UPB_WIRE_DECODE_FAST_H_ */
 
+// upb_Encode: parsing from a upb_Message using a upb_MiniTable.
+
+#ifndef UPB_WIRE_ENCODE_H_
+#define UPB_WIRE_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. */
+  kUpb_EncodeOption_Deterministic = 1,
+
+  /* When set, unknown fields are not printed. */
+  kUpb_EncodeOption_SkipUnknown = 2,
+
+  /* When set, the encode will fail if any required fields are missing. */
+  kUpb_EncodeOption_CheckRequired = 4,
+};
+
+#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+
+typedef enum {
+  kUpb_EncodeStatus_Ok = 0,
+  kUpb_EncodeStatus_OutOfMemory = 1,       // Arena alloc failed
+  kUpb_EncodeStatus_MaxDepthExceeded = 2,  // Exceeded UPB_ENCODE_MAXDEPTH
+
+  // kUpb_EncodeOption_CheckRequired failed but the parse otherwise succeeded.
+  kUpb_EncodeStatus_MissingRequired = 3,
+} upb_EncodeStatus;
+
+upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
+                            int options, upb_Arena* arena, char** buf,
+                            size_t* size);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_WIRE_ENCODE_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;
@@ -2343,33 +3137,33 @@
 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_MiniTable google_protobuf_FileDescriptorSet_msginit;
-extern const upb_MiniTable google_protobuf_FileDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_DescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msginit;
-extern const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msginit;
-extern const upb_MiniTable google_protobuf_ExtensionRangeOptions_msginit;
-extern const upb_MiniTable google_protobuf_FieldDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_OneofDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_EnumDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
-extern const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_ServiceDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_MethodDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_FileOptions_msginit;
-extern const upb_MiniTable google_protobuf_MessageOptions_msginit;
-extern const upb_MiniTable google_protobuf_FieldOptions_msginit;
-extern const upb_MiniTable google_protobuf_OneofOptions_msginit;
-extern const upb_MiniTable google_protobuf_EnumOptions_msginit;
-extern const upb_MiniTable google_protobuf_EnumValueOptions_msginit;
-extern const upb_MiniTable google_protobuf_ServiceOptions_msginit;
-extern const upb_MiniTable google_protobuf_MethodOptions_msginit;
-extern const upb_MiniTable google_protobuf_UninterpretedOption_msginit;
-extern const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msginit;
-extern const upb_MiniTable google_protobuf_SourceCodeInfo_msginit;
-extern const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msginit;
-extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_msginit;
-extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msginit;
+extern const upb_MiniTable google_protobuf_FileDescriptorSet_msg_init;
+extern const upb_MiniTable google_protobuf_FileDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_DescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msg_init;
+extern const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msg_init;
+extern const upb_MiniTable google_protobuf_ExtensionRangeOptions_msg_init;
+extern const upb_MiniTable google_protobuf_FieldDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_OneofDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_EnumDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init;
+extern const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_ServiceDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_MethodDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_FileOptions_msg_init;
+extern const upb_MiniTable google_protobuf_MessageOptions_msg_init;
+extern const upb_MiniTable google_protobuf_FieldOptions_msg_init;
+extern const upb_MiniTable google_protobuf_OneofOptions_msg_init;
+extern const upb_MiniTable google_protobuf_EnumOptions_msg_init;
+extern const upb_MiniTable google_protobuf_EnumValueOptions_msg_init;
+extern const upb_MiniTable google_protobuf_ServiceOptions_msg_init;
+extern const upb_MiniTable google_protobuf_MethodOptions_msg_init;
+extern const upb_MiniTable google_protobuf_UninterpretedOption_msg_init;
+extern const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msg_init;
+extern const upb_MiniTable google_protobuf_SourceCodeInfo_msg_init;
+extern const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msg_init;
+extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_msg_init;
+extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msg_init;
 
 typedef enum {
   google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
@@ -2417,28 +3211,35 @@
 } google_protobuf_FileOptions_OptimizeMode;
 
 typedef enum {
+  google_protobuf_GeneratedCodeInfo_Annotation_NONE = 0,
+  google_protobuf_GeneratedCodeInfo_Annotation_SET = 1,
+  google_protobuf_GeneratedCodeInfo_Annotation_ALIAS = 2
+} google_protobuf_GeneratedCodeInfo_Annotation_Semantic;
+
+typedef enum {
   google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
   google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
   google_protobuf_MethodOptions_IDEMPOTENT = 2
 } google_protobuf_MethodOptions_IdempotencyLevel;
 
 
-extern const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Label_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Type_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FieldOptions_CType_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FieldOptions_JSType_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FileOptions_OptimizeMode_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_MethodOptions_IdempotencyLevel_enuminit;
+extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init;
+extern const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init;
+extern const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init;
 
 /* google.protobuf.FileDescriptorSet */
 
 UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_new(upb_Arena* arena) {
-  return (google_protobuf_FileDescriptorSet*)_upb_Message_New(&google_protobuf_FileDescriptorSet_msginit, arena);
+  return (google_protobuf_FileDescriptorSet*)_upb_Message_New(&google_protobuf_FileDescriptorSet_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2448,32 +3249,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FileDescriptorSet* ret = google_protobuf_FileDescriptorSet_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorSet_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FileDescriptorSet_serialize_ex(const google_protobuf_FileDescriptorSet* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FileDescriptorSet_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorSet_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_FileDescriptorSet_clear_file(google_protobuf_FileDescriptorSet* msg) {
+  const upb_MiniTableField field = {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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, 0, len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorSet_file(msg, &size);
+  return size != 0;
+}
 
-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_mutable_file(google_protobuf_FileDescriptorSet* msg, size_t* len) {
+  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, 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 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, 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_Message_New(&google_protobuf_FileDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_FileDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -2481,12 +3295,12 @@
 /* google.protobuf.FileDescriptorProto */
 
 UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_FileDescriptorProto*)_upb_Message_New(&google_protobuf_FileDescriptorProto_msginit, arena);
+  return (google_protobuf_FileDescriptorProto*)_upb_Message_New(&google_protobuf_FileDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2496,181 +3310,317 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FileDescriptorProto* ret = google_protobuf_FileDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FileDescriptorProto_serialize_ex(const google_protobuf_FileDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FileDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_name(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_package(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE upb_StringView const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto *msg, size_t *len) { return (upb_StringView 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 bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_dependency(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(4, 40), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE upb_StringView const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(4, 40), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_dependency(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_dependency(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_message_type(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(8, 48), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(8, 48), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_message_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_enum_type(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(12, 56), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(12, 56), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_enum_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_service(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(16, 64), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(16, 64), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_service(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_extension(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(20, 72), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(20, 72), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_extension(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_options(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_FileOptions* default_val = NULL;
+  const google_protobuf_FileOptions* ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_source_code_info(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_SourceCodeInfo* default_val = NULL;
+  const google_protobuf_SourceCodeInfo* ret;
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_public_dependency(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(32, 96), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(32, 96), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_public_dependency(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_public_dependency(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_weak_dependency(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {11, UPB_SIZE(36, 104), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(36, 104), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_weak_dependency(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_weak_dependency(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_syntax(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_edition(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_edition(const google_protobuf_FileDescriptorProto* msg) {
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_edition(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 40), len);
 }
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView) = value;
+UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto* msg, size_t len, upb_Arena* arena) {
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 40), len, UPB_SIZE(3, 4), arena);
 }
-UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto *msg, size_t *len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto* msg, upb_StringView val, upb_Arena* arena) {
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 40), UPB_SIZE(3, 4), &val, arena);
 }
-UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto *msg, size_t len, upb_Arena *arena) {
-  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(3, 4), 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(8, 48), len);
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto *msg, upb_StringView 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_resize_message_type(google_protobuf_FileDescriptorProto* msg, size_t len, upb_Arena* arena) {
+  return (google_protobuf_DescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(8, 48), len, UPB_SIZE(2, 3), 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_Message_New(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_DescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(8, 48), 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_mutable_enum_type(google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 56), 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 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(12, 56), 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_Message_New(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(44, 88), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_EnumDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 56), 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_mutable_service(google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 64), 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 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(16, 64), 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_Message_New(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(48, 96), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_ServiceDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 64), 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_mutable_extension(google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 72), 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 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(20, 72), 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_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(52, 104), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 72), 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) {
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_FileOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_FileOptions*)_upb_Message_New(&google_protobuf_FileOptions_msg_init, arena);
+    if (sub) 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) {
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_SourceCodeInfo_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
+    sub = (struct google_protobuf_SourceCodeInfo*)_upb_Message_New(&google_protobuf_SourceCodeInfo_msg_init, arena);
+    if (sub) 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_mutable_public_dependency(google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 96), 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 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(32, 96), 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 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(32, 96), 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_mutable_weak_dependency(google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 104), 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 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(36, 104), 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 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(36, 104), 2, &val, arena);
 }
 UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView) = value;
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileDescriptorProto_set_edition(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
 }
-
 /* google.protobuf.DescriptorProto */
 
 UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_DescriptorProto*)_upb_Message_New(&google_protobuf_DescriptorProto_msginit, arena);
+  return (google_protobuf_DescriptorProto*)_upb_Message_New(&google_protobuf_DescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2680,171 +3630,267 @@
                            int options, upb_Arena* arena) {
   google_protobuf_DescriptorProto* ret = google_protobuf_DescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_DescriptorProto_serialize_ex(const google_protobuf_DescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_DescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_DescriptorProto_clear_name(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_field(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(4, 24), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_field(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_nested_type(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(8, 32), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_nested_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_enum_type(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(12, 40), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_enum_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_extension_range(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 48), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(16, 48), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_extension_range(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_extension(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(20, 56), 0, 4, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(20, 56), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_extension(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_options(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_MessageOptions* default_val = NULL;
+  const google_protobuf_MessageOptions* ret;
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_StringView const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto *msg, size_t *len) { return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len); }
+UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_oneof_decl(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(28, 72), 0, 6, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(28, 72), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_oneof_decl(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_range(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(32, 80), 0, 7, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(32, 80), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_reserved_range(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_name(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(36, 88), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE upb_StringView const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(36, 88), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_name(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_reserved_name(msg, &size);
+  return size != 0;
+}
 
 UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(4, 24), len);
 }
-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(4, 24), len, UPB_SIZE(2, 3), arena);
 }
-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_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 24), 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_mutable_nested_type(google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 32), 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 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(8, 32), 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_Message_New(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_DescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(8, 32), 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_mutable_enum_type(google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 40), 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 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(12, 40), 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_Message_New(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_EnumDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 40), 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_mutable_extension_range(google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 48), 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 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(16, 48), 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_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 48), 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_mutable_extension(google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 56), 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 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(20, 56), 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_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(32, 64), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 56), 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) {
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_MessageOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_MessageOptions*)_upb_Message_New(&google_protobuf_MessageOptions_msg_init, arena);
+    if (sub) 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_mutable_oneof_decl(google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 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 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(28, 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_Message_New(&google_protobuf_OneofDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(36, 72), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_OneofDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(28, 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_mutable_reserved_range(google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 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 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(32, 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_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(32, 80), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
-UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto *msg, size_t *len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto* msg, size_t* len) {
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 88), len);
 }
-UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto *msg, size_t len, upb_Arena *arena) {
-  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(3, 4), arena);
+UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto* msg, size_t len, upb_Arena* arena) {
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(36, 88), len, UPB_SIZE(3, 4), arena);
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto *msg, upb_StringView val, upb_Arena *arena) {
-  return _upb_Array_Append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(3, 4), &val,
-      arena);
+UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto* msg, upb_StringView val, upb_Arena* arena) {
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(36, 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_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+  return (google_protobuf_DescriptorProto_ExtensionRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2854,50 +3900,83 @@
                            int options, upb_Arena* arena) {
   google_protobuf_DescriptorProto_ExtensionRange* ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_DescriptorProto_ExtensionRange_serialize_ex(const google_protobuf_DescriptorProto_ExtensionRange* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_start(google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_end(google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_options(google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_ExtensionRangeOptions* default_val = NULL;
+  const google_protobuf_ExtensionRangeOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
+    sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google_protobuf_ExtensionRangeOptions_msg_init, arena);
+    if (sub) google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
   }
   return sub;
 }
@@ -2905,12 +3984,12 @@
 /* google.protobuf.DescriptorProto.ReservedRange */
 
 UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_new(upb_Arena* arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+  return (google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2920,46 +3999,70 @@
                            int options, upb_Arena* arena) {
   google_protobuf_DescriptorProto_ReservedRange* ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_DescriptorProto_ReservedRange_serialize_ex(const google_protobuf_DescriptorProto_ReservedRange* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_start(google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_end(google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+  return (google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google_protobuf_ExtensionRangeOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2969,32 +4072,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_ExtensionRangeOptions* ret = google_protobuf_ExtensionRangeOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ExtensionRangeOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_ExtensionRangeOptions_serialize_ex(const google_protobuf_ExtensionRangeOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ExtensionRangeOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_ExtensionRangeOptions_clear_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg) {
+  const upb_MiniTableField field = {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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, 0, len);
+}
+UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions* msg) {
+  size_t size;
+  google_protobuf_ExtensionRangeOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
-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_mutable_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg, size_t* len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, 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 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, 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -3002,12 +4118,12 @@
 /* google.protobuf.FieldDescriptorProto */
 
 UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  return (google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3017,127 +4133,240 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FieldDescriptorProto* ret = google_protobuf_FieldDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FieldDescriptorProto_serialize_ex(const google_protobuf_FieldDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FieldDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_name(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_extendee(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_number(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_label(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto* msg) {
-  return google_protobuf_FieldDescriptorProto_has_label(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) : 1;
+  int32_t default_val = 1;
+  int32_t ret;
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto* msg) {
-  return google_protobuf_FieldDescriptorProto_has_type(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) : 1;
+  int32_t default_val = 1;
+  int32_t ret;
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type_name(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_default_value(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 8); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_options(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_FieldOptions* default_val = NULL;
+  const google_protobuf_FieldOptions* ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 9); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_oneof_index(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_json_name(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_json_name(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_proto3_optional(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_StringView) = 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_StringView value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_FieldOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_FieldOptions*)_upb_Message_New(&google_protobuf_FieldOptions_msg_init, arena);
+    if (sub) 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;
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
 }
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 10);
-  *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_StringView) = 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_Message_New(&google_protobuf_OneofDescriptorProto_msginit, arena);
+  return (google_protobuf_OneofDescriptorProto*)_upb_Message_New(&google_protobuf_OneofDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3147,42 +4376,65 @@
                            int options, upb_Arena* arena) {
   google_protobuf_OneofDescriptorProto* ret = google_protobuf_OneofDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_OneofDescriptorProto_serialize_ex(const google_protobuf_OneofDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_OneofDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_name(google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_options(google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_OneofOptions* default_val = NULL;
+  const google_protobuf_OneofOptions* ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_OneofOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_OneofOptions*)_upb_Message_New(&google_protobuf_OneofOptions_msg_init, arena);
+    if (sub) google_protobuf_OneofDescriptorProto_set_options(msg, sub);
   }
   return sub;
 }
@@ -3190,12 +4442,12 @@
 /* google.protobuf.EnumDescriptorProto */
 
 UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  return (google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3205,96 +4457,147 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumDescriptorProto* ret = google_protobuf_EnumDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumDescriptorProto_serialize_ex(const google_protobuf_EnumDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_name(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_value(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(4, 24), len);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_EnumDescriptorProto_value(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_options(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_EnumOptions* default_val = NULL;
+  const google_protobuf_EnumOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_StringView const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto *msg, size_t *len) { return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_range(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(12, 40), len);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_EnumDescriptorProto_reserved_range(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_name(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 48), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE upb_StringView const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto* msg, size_t* len) {
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(16, 48), len);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_name(const google_protobuf_EnumDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_EnumDescriptorProto_reserved_name(msg, &size);
+  return size != 0;
+}
 
 UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(4, 24), len);
 }
-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(4, 24), len, UPB_SIZE(2, 3), arena);
 }
-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_Message_New(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_EnumValueDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 24), 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) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_EnumOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_EnumOptions*)_upb_Message_New(&google_protobuf_EnumOptions_msg_init, arena);
+    if (sub) 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_mutable_reserved_range(google_protobuf_EnumDescriptorProto* msg, size_t* len) {
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 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 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(12, 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_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 40), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
-UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t *len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t* len) {
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 48), len);
 }
-UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto *msg, size_t len, upb_Arena *arena) {
-  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(3, 4), arena);
+UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t len, upb_Arena* arena) {
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(16, 48), len, UPB_SIZE(3, 4), arena);
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto *msg, upb_StringView val, upb_Arena *arena) {
-  return _upb_Array_Append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(3, 4), &val,
-      arena);
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto* msg, upb_StringView val, upb_Arena* arena) {
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 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_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3304,46 +4607,70 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumDescriptorProto_EnumReservedRange* ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize_ex(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_start(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_end(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+  return (google_protobuf_EnumValueDescriptorProto*)_upb_Message_New(&google_protobuf_EnumValueDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3353,50 +4680,83 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumValueDescriptorProto* ret = google_protobuf_EnumValueDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumValueDescriptorProto_serialize_ex(const google_protobuf_EnumValueDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_name(google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_number(google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_options(google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_EnumValueOptions* default_val = NULL;
+  const google_protobuf_EnumValueOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_EnumValueOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_EnumValueOptions*)_upb_Message_New(&google_protobuf_EnumValueOptions_msg_init, arena);
+    if (sub) google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
   }
   return sub;
 }
@@ -3404,12 +4764,12 @@
 /* google.protobuf.ServiceDescriptorProto */
 
 UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+  return (google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google_protobuf_ServiceDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3419,57 +4779,89 @@
                            int options, upb_Arena* arena) {
   google_protobuf_ServiceDescriptorProto* ret = google_protobuf_ServiceDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_ServiceDescriptorProto_serialize_ex(const google_protobuf_ServiceDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_name(google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_method(google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(4, 24), len);
+}
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_ServiceDescriptorProto_method(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_options(google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_ServiceOptions* default_val = NULL;
+  const google_protobuf_ServiceOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(4, 24), len);
 }
-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(4, 24), len, UPB_SIZE(2, 3), arena);
 }
-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_Message_New(&google_protobuf_MethodDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_MethodDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 24), 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) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_ServiceOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_ServiceOptions*)_upb_Message_New(&google_protobuf_ServiceOptions_msg_init, arena);
+    if (sub) google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
   }
   return sub;
 }
@@ -3477,12 +4869,12 @@
 /* google.protobuf.MethodDescriptorProto */
 
 UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google_protobuf_MethodDescriptorProto_msginit, arena);
+  return (google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google_protobuf_MethodDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3492,87 +4884,150 @@
                            int options, upb_Arena* arena) {
   google_protobuf_MethodDescriptorProto* ret = google_protobuf_MethodDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_MethodDescriptorProto_serialize_ex(const google_protobuf_MethodDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_MethodDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_name(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_input_type(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_output_type(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_options(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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*);
+  const google_protobuf_MethodOptions* default_val = NULL;
+  const google_protobuf_MethodOptions* ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_options(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_client_streaming(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_client_streaming(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_server_streaming(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_MethodOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_MethodOptions*)_upb_Message_New(&google_protobuf_MethodOptions_msg_init, arena);
+    if (sub) 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;
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_FileOptions_msginit, arena);
+  return (google_protobuf_FileOptions*)_upb_Message_New(&google_protobuf_FileOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3582,192 +5037,405 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FileOptions* ret = google_protobuf_FileOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FileOptions_serialize_ex(const google_protobuf_FileOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FileOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_FileOptions_clear_java_package(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_outer_classname(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_optimize_for(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions* msg) {
-  return google_protobuf_FileOptions_has_optimize_for(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) : 1;
+  int32_t default_val = 1;
+  int32_t ret;
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_optimize_for(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_multiple_files(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_go_package(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_go_package(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_cc_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_cc_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_java_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_py_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_py_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_generate_equals_and_hash(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 10); }
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_deprecated(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_deprecated(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_string_check_utf8(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_java_string_check_utf8(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_cc_enable_arenas(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions* msg) {
-  return google_protobuf_FileOptions_has_cc_enable_arenas(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) : true;
+  bool default_val = true;
+  bool ret;
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 13); }
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_objc_class_prefix(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 14); }
+UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_csharp_namespace(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 15); }
+UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_swift_prefix(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 16); }
+UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_class_prefix(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 17); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_namespace(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_php_namespace(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 19); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_metadata_namespace(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions *msg) { return _upb_hasbit(msg, 20); }
+UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_ruby_package(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_uninterpreted_option(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(20, 184), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(20, 184), len);
+}
+UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions* msg) {
+  size_t size;
+  google_protobuf_FileOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_StringView) = value;
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(20, 184), len);
 }
-UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_StringView) = value;
+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(20, 184), len, UPB_SIZE(2, 3), arena);
 }
-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_StringView value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_StringView) = 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_StringView value) {
-  _upb_sethas(msg, 13);
-  *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 14);
-  *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 15);
-  *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 16);
-  *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 17);
-  *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_StringView) = 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_StringView value) {
-  _upb_sethas(msg, 19);
-  *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 20);
-  *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_StringView) = 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(100, 184), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 184), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -3775,12 +5443,12 @@
 /* google.protobuf.MessageOptions */
 
 UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_new(upb_Arena* arena) {
-  return (google_protobuf_MessageOptions*)_upb_Message_New(&google_protobuf_MessageOptions_msginit, arena);
+  return (google_protobuf_MessageOptions*)_upb_Message_New(&google_protobuf_MessageOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3790,64 +5458,117 @@
                            int options, upb_Arena* arena) {
   google_protobuf_MessageOptions* ret = google_protobuf_MessageOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MessageOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_MessageOptions_serialize_ex(const google_protobuf_MessageOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_MessageOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MessageOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_MessageOptions_clear_message_set_wire_format(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_message_set_wire_format(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_no_standard_descriptor_accessor(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_deprecated(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_deprecated(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_map_entry(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_uninterpreted_option(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {999, 8, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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, 8, len);
+}
+UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions* msg) {
+  size_t size;
+  google_protobuf_MessageOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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;
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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, 8, len);
 }
-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 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, 8, len, UPB_SIZE(2, 3), arena);
 }
-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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(8, 8), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 8, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -3855,12 +5576,12 @@
 /* google.protobuf.FieldOptions */
 
 UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_new(upb_Arena* arena) {
-  return (google_protobuf_FieldOptions*)_upb_Message_New(&google_protobuf_FieldOptions_msginit, arena);
+  return (google_protobuf_FieldOptions*)_upb_Message_New(&google_protobuf_FieldOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3870,88 +5591,171 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FieldOptions* ret = google_protobuf_FieldOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FieldOptions_serialize_ex(const google_protobuf_FieldOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FieldOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_FieldOptions_clear_ctype(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_packed(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_deprecated(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_lazy(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_jstype(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t);
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_weak(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_unverified_lazy(const google_protobuf_FieldOptions *msg) { return _upb_hasbit(msg, 7); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_unverified_lazy(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_FieldOptions_unverified_lazy(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions *msg) { return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 24)); }
-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(20, 24), len); }
+UPB_INLINE bool google_protobuf_FieldOptions_has_unverified_lazy(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_uninterpreted_option(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(20, 24), len);
+}
+UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions* msg) {
+  size_t size;
+  google_protobuf_FieldOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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 void google_protobuf_FieldOptions_set_unverified_lazy(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t *len) {
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_unverified_lazy(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(20, 24), len);
 }
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_resize_uninterpreted_option(google_protobuf_FieldOptions *msg, size_t len, upb_Arena *arena) {
+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(20, 24), 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(20, 24), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 24), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -3959,12 +5763,12 @@
 /* google.protobuf.OneofOptions */
 
 UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_new(upb_Arena* arena) {
-  return (google_protobuf_OneofOptions*)_upb_Message_New(&google_protobuf_OneofOptions_msginit, arena);
+  return (google_protobuf_OneofOptions*)_upb_Message_New(&google_protobuf_OneofOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3974,32 +5778,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_OneofOptions* ret = google_protobuf_OneofOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_OneofOptions_serialize_ex(const google_protobuf_OneofOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_OneofOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_OneofOptions_clear_uninterpreted_option(google_protobuf_OneofOptions* msg) {
+  const upb_MiniTableField field = {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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, 0, len);
+}
+UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions* msg) {
+  size_t size;
+  google_protobuf_OneofOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
-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_mutable_uninterpreted_option(google_protobuf_OneofOptions* msg, size_t* len) {
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, 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 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, 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4007,12 +5824,12 @@
 /* google.protobuf.EnumOptions */
 
 UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_new(upb_Arena* arena) {
-  return (google_protobuf_EnumOptions*)_upb_Message_New(&google_protobuf_EnumOptions_msginit, arena);
+  return (google_protobuf_EnumOptions*)_upb_Message_New(&google_protobuf_EnumOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4022,48 +5839,81 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumOptions* ret = google_protobuf_EnumOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumOptions_serialize_ex(const google_protobuf_EnumOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_EnumOptions_clear_allow_alias(google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumOptions_clear_deprecated(google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumOptions_clear_uninterpreted_option(google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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 bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions* msg) {
+  size_t size;
+  google_protobuf_EnumOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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) {
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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) {
+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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4071,12 +5921,12 @@
 /* google.protobuf.EnumValueOptions */
 
 UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_new(upb_Arena* arena) {
-  return (google_protobuf_EnumValueOptions*)_upb_Message_New(&google_protobuf_EnumValueOptions_msginit, arena);
+  return (google_protobuf_EnumValueOptions*)_upb_Message_New(&google_protobuf_EnumValueOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4086,40 +5936,63 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumValueOptions* ret = google_protobuf_EnumValueOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumValueOptions_serialize_ex(const google_protobuf_EnumValueOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumValueOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_EnumValueOptions_clear_deprecated(google_protobuf_EnumValueOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumValueOptions_clear_uninterpreted_option(google_protobuf_EnumValueOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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 bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions* msg) {
+  size_t size;
+  google_protobuf_EnumValueOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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) {
+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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4127,12 +6000,12 @@
 /* google.protobuf.ServiceOptions */
 
 UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_new(upb_Arena* arena) {
-  return (google_protobuf_ServiceOptions*)_upb_Message_New(&google_protobuf_ServiceOptions_msginit, arena);
+  return (google_protobuf_ServiceOptions*)_upb_Message_New(&google_protobuf_ServiceOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4142,40 +6015,63 @@
                            int options, upb_Arena* arena) {
   google_protobuf_ServiceOptions* ret = google_protobuf_ServiceOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_ServiceOptions_serialize_ex(const google_protobuf_ServiceOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_ServiceOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_ServiceOptions_clear_deprecated(google_protobuf_ServiceOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_ServiceOptions_clear_uninterpreted_option(google_protobuf_ServiceOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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 bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions* msg) {
+  size_t size;
+  google_protobuf_ServiceOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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) {
+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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4183,12 +6079,12 @@
 /* google.protobuf.MethodOptions */
 
 UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_new(upb_Arena* arena) {
-  return (google_protobuf_MethodOptions*)_upb_Message_New(&google_protobuf_MethodOptions_msginit, arena);
+  return (google_protobuf_MethodOptions*)_upb_Message_New(&google_protobuf_MethodOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4198,48 +6094,81 @@
                            int options, upb_Arena* arena) {
   google_protobuf_MethodOptions* ret = google_protobuf_MethodOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_MethodOptions_serialize_ex(const google_protobuf_MethodOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_MethodOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_MethodOptions_clear_deprecated(google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodOptions_clear_idempotency_level(google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodOptions_clear_uninterpreted_option(google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {999, 8, 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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, 8, len);
+}
+UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions* msg) {
+  size_t size;
+  google_protobuf_MethodOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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;
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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, 8, len);
 }
-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_resize_uninterpreted_option(google_protobuf_MethodOptions* msg, size_t len, upb_Arena* arena) {
+  return (google_protobuf_UninterpretedOption**)_upb_Array_Resize_accessor2(msg, 8, len, UPB_SIZE(2, 3), arena);
 }
-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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(12, 16), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 8, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4247,12 +6176,12 @@
 /* google.protobuf.UninterpretedOption */
 
 UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_new(upb_Arena* arena) {
-  return (google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
+  return (google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4262,93 +6191,166 @@
                            int options, upb_Arena* arena) {
   google_protobuf_UninterpretedOption* ret = google_protobuf_UninterpretedOption_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_UninterpretedOption_serialize_ex(const google_protobuf_UninterpretedOption* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_UninterpretedOption_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_UninterpretedOption_clear_name(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(4, 8), len);
+}
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption* msg) {
+  size_t size;
+  google_protobuf_UninterpretedOption_name(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_identifier_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_positive_int_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  uint64_t default_val = (uint64_t)0ull;
+  uint64_t ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_negative_int_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int64_t default_val = (int64_t)0ll;
+  int64_t ret;
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 4); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_double_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double);
+  double default_val = 0;
+  double ret;
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 5); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_string_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption *msg) { return _upb_hasbit(msg, 6); }
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_aggregate_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
-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_mutable_name(google_protobuf_UninterpretedOption* msg, size_t* len) {
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), 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 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(4, 8), 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_Message_New(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(56, 80), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_UninterpretedOption_NamePart_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), 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_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_StringView) = value;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) {
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) {
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_StringView value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_StringView) = 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_Message_New(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+  return (google_protobuf_UninterpretedOption_NamePart*)_upb_Message_New(&google_protobuf_UninterpretedOption_NamePart_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4358,46 +6360,70 @@
                            int options, upb_Arena* arena) {
   google_protobuf_UninterpretedOption_NamePart* ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_NamePart_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_UninterpretedOption_NamePart_serialize_ex(const google_protobuf_UninterpretedOption_NamePart* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_NamePart_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart *msg) { return _upb_hasbit(msg, 1); }
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_name_part(google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_is_extension(google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_SourceCodeInfo_msginit, arena);
+  return (google_protobuf_SourceCodeInfo*)_upb_Message_New(&google_protobuf_SourceCodeInfo_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4407,32 +6433,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_SourceCodeInfo* ret = google_protobuf_SourceCodeInfo_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_SourceCodeInfo_serialize_ex(const google_protobuf_SourceCodeInfo* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_SourceCodeInfo_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_SourceCodeInfo_clear_location(google_protobuf_SourceCodeInfo* msg) {
+  const upb_MiniTableField field = {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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, 0, len);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_location(msg, &size);
+  return size != 0;
+}
 
-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_mutable_location(google_protobuf_SourceCodeInfo* msg, size_t* len) {
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, 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 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, 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_Message_New(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_SourceCodeInfo_Location_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4440,12 +6479,12 @@
 /* google.protobuf.SourceCodeInfo.Location */
 
 UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_new(upb_Arena* arena) {
-  return (google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+  return (google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google_protobuf_SourceCodeInfo_Location_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4455,79 +6494,133 @@
                            int options, upb_Arena* arena) {
   google_protobuf_SourceCodeInfo_Location* ret = google_protobuf_SourceCodeInfo_Location_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_Location_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_SourceCodeInfo_Location_serialize_ex(const google_protobuf_SourceCodeInfo_Location* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_Location_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_SourceCodeInfo_Location_clear_path(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(4, 8), len);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_path(const google_protobuf_SourceCodeInfo_Location* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_Location_path(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_span(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(8, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(8, 16), len);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_span(const google_protobuf_SourceCodeInfo_Location* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_Location_span(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_comments(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_trailing_comments(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE upb_StringView const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location *msg, size_t *len) { return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len); }
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(12, 56), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE upb_StringView const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location* msg, size_t* len) {
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(12, 56), len);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_Location_leading_detached_comments(msg, &size);
+  return size != 0;
+}
 
-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_mutable_path(google_protobuf_SourceCodeInfo_Location* msg, size_t* len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), 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 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(4, 8), 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 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(4, 8), 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_mutable_span(google_protobuf_SourceCodeInfo_Location* msg, size_t* len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), 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 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(8, 16), 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 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(8, 16), 2, &val, arena);
 }
 UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t* len) {
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 56), len);
 }
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView) = value;
+UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t len, upb_Arena* arena) {
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 56), len, UPB_SIZE(3, 4), arena);
 }
-UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t *len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
-}
-UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location *msg, size_t len, upb_Arena *arena) {
-  return (upb_StringView*)_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_StringView val, upb_Arena *arena) {
-  return _upb_Array_Append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(3, 4), &val,
-      arena);
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, upb_StringView val, upb_Arena* arena) {
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 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_Message_New(&google_protobuf_GeneratedCodeInfo_msginit, arena);
+  return (google_protobuf_GeneratedCodeInfo*)_upb_Message_New(&google_protobuf_GeneratedCodeInfo_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4537,32 +6630,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_GeneratedCodeInfo* ret = google_protobuf_GeneratedCodeInfo_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_GeneratedCodeInfo_serialize_ex(const google_protobuf_GeneratedCodeInfo* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_GeneratedCodeInfo_clear_annotation(google_protobuf_GeneratedCodeInfo* msg) {
+  const upb_MiniTableField field = {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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, 0, len);
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo* msg) {
+  size_t size;
+  google_protobuf_GeneratedCodeInfo_annotation(msg, &size);
+  return size != 0;
+}
 
-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_mutable_annotation(google_protobuf_GeneratedCodeInfo* msg, size_t* len) {
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, 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 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, 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_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(
-      msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, 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_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4570,12 +6676,12 @@
 /* google.protobuf.GeneratedCodeInfo.Annotation */
 
 UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_new(upb_Arena* arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+  return (google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4585,57 +6691,119 @@
                            int options, upb_Arena* arena) {
   google_protobuf_GeneratedCodeInfo_Annotation* ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_GeneratedCodeInfo_Annotation_serialize_ex(const google_protobuf_GeneratedCodeInfo_Annotation* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_GeneratedCodeInfo_Annotation_clear_path(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+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(4, 16), len);
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_path(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  size_t size;
+  google_protobuf_GeneratedCodeInfo_Annotation_path(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_source_file(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 UPB_INLINE upb_StringView google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 2); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_begin(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation *msg) { return _upb_hasbit(msg, 3); }
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_end(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_semantic(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
-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_mutable_path(google_protobuf_GeneratedCodeInfo_Annotation* msg, size_t* len) {
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 16), 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 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(4, 16), 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 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(4, 16), 2, &val, arena);
 }
 UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_StringView) = value;
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_semantic(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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;
-}
-
-extern const upb_MiniTable_File google_protobuf_descriptor_proto_upb_file_layout;
+extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout;
 
 /* Max size 32 is google.protobuf.FileOptions */
 /* Max size 64 is google.protobuf.FileOptions */
@@ -4648,206 +6816,459 @@
 
 #endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
 
-/** upb/def.h ************************************************************/
-#ifndef UPB_DEF_H_
-#define UPB_DEF_H_
+#ifndef UPB_REFLECTION_DEF_H_
+#define UPB_REFLECTION_DEF_H_
 
 
-/* Must be last. */
+// IWYU pragma: private, include "upb/reflection/def.h"
 
-#ifdef __cplusplus
-extern "C" {
-#endif /* __cplusplus */
+#ifndef UPB_REFLECTION_DEF_POOL_H_
+#define UPB_REFLECTION_DEF_POOL_H_
 
-struct upb_EnumDef;
-typedef struct upb_EnumDef upb_EnumDef;
-struct upb_EnumValueDef;
-typedef struct upb_EnumValueDef upb_EnumValueDef;
-struct upb_ExtensionRange;
-typedef struct upb_ExtensionRange upb_ExtensionRange;
-struct upb_FieldDef;
-typedef struct upb_FieldDef upb_FieldDef;
-struct upb_FileDef;
-typedef struct upb_FileDef upb_FileDef;
-struct upb_MethodDef;
-typedef struct upb_MethodDef upb_MethodDef;
-struct upb_MessageDef;
-typedef struct upb_MessageDef upb_MessageDef;
-struct upb_OneofDef;
-typedef struct upb_OneofDef upb_OneofDef;
-struct upb_ServiceDef;
-typedef struct upb_ServiceDef upb_ServiceDef;
-struct upb_streamdef;
-typedef struct upb_streamdef upb_streamdef;
-struct upb_DefPool;
-typedef struct upb_DefPool upb_DefPool;
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+// Declarations common to all public def types.
+
+#ifndef UPB_REFLECTION_COMMON_H_
+#define UPB_REFLECTION_COMMON_H_
+
 
 typedef enum { kUpb_Syntax_Proto2 = 2, kUpb_Syntax_Proto3 = 3 } upb_Syntax;
 
-/* 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.
- */
+// Forward declarations for circular references.
+typedef struct upb_DefPool upb_DefPool;
+typedef struct upb_EnumDef upb_EnumDef;
+typedef struct upb_EnumReservedRange upb_EnumReservedRange;
+typedef struct upb_EnumValueDef upb_EnumValueDef;
+typedef struct upb_ExtensionRange upb_ExtensionRange;
+typedef struct upb_FieldDef upb_FieldDef;
+typedef struct upb_FileDef upb_FileDef;
+typedef struct upb_MessageDef upb_MessageDef;
+typedef struct upb_MessageReservedRange upb_MessageReservedRange;
+typedef struct upb_MethodDef upb_MethodDef;
+typedef struct upb_OneofDef upb_OneofDef;
+typedef struct upb_ServiceDef upb_ServiceDef;
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+typedef struct upb_DefBuilder upb_DefBuilder;
+
+#endif /* UPB_REFLECTION_COMMON_H_ */
+
+#ifndef UPB_REFLECTION_DEF_TYPE_H_
+#define UPB_REFLECTION_DEF_TYPE_H_
+
+
+// Must be last.
+
+// Inside a symtab we store tagged pointers to specific def types.
+typedef enum {
+  UPB_DEFTYPE_MASK = 7,
+
+  // Only inside symtab table.
+  UPB_DEFTYPE_EXT = 0,
+  UPB_DEFTYPE_MSG = 1,
+  UPB_DEFTYPE_ENUM = 2,
+  UPB_DEFTYPE_ENUMVAL = 3,
+  UPB_DEFTYPE_SERVICE = 4,
+
+  // Only inside message table.
+  UPB_DEFTYPE_FIELD = 0,
+  UPB_DEFTYPE_ONEOF = 1,
+  UPB_DEFTYPE_FIELD_JSONNAME = 2,
+} upb_deftype_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Our 3-bit pointer tagging requires all pointers to be multiples of 8.
+// The arena will always yield 8-byte-aligned addresses, however we put
+// the defs into arrays. For each element in the array to be 8-byte-aligned,
+// the sizes of each def type must also be a multiple of 8.
+//
+// If any of these asserts fail, we need to add or remove padding on 32-bit
+// machines (64-bit machines will have 8-byte alignment already due to
+// pointers, which all of these structs have).
+UPB_INLINE void _upb_DefType_CheckPadding(size_t size) {
+  UPB_ASSERT((size & UPB_DEFTYPE_MASK) == 0);
+}
+
+upb_deftype_t _upb_DefType_Type(upb_value v);
+
+upb_value _upb_DefType_Pack(const void* ptr, upb_deftype_t type);
+
+const void* _upb_DefType_Unpack(upb_value v, upb_deftype_t type);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_TYPE_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void upb_DefPool_Free(upb_DefPool* s);
+
+upb_DefPool* upb_DefPool_New(void);
+
+const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
+                                                    const char* sym);
+
+const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
+    const upb_DefPool* s, const char* sym, size_t len);
+
+const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
+                                              const char* sym);
+
+const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
+                                                      const char* sym);
+
+const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
+                                              const char* name);
+
+const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s,
+                                                      const char* name,
+                                                      size_t len);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByMiniTable(
+    const upb_DefPool* s, const upb_MiniTableExtension* ext);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
+                                                    const char* sym);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
+                                                      const upb_MessageDef* m,
+                                                      int32_t fieldnum);
+
+const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
+                                                    const char* name);
+
+const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size);
+
+const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
+                                                        const char* name);
+
+const upb_FileDef* upb_DefPool_AddFile(
+    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
+    upb_Status* status);
+
+const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
+    const upb_DefPool* s);
+
+const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
+                                                  const upb_MessageDef* m,
+                                                  size_t* count);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_POOL_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ENUM_DEF_H_
+#define UPB_REFLECTION_ENUM_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num);
+const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e);
+int32_t upb_EnumDef_Default(const upb_EnumDef* e);
+const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e);
+const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e,
+                                                    const char* name);
+const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
+    const upb_EnumDef* e, const char* name, size_t size);
+const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e,
+                                                      int32_t num);
+const char* upb_EnumDef_FullName(const upb_EnumDef* e);
+bool upb_EnumDef_HasOptions(const upb_EnumDef* e);
+bool upb_EnumDef_IsClosed(const upb_EnumDef* e);
+
+// Creates a mini descriptor string for an enum, returns true on success.
+bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a,
+                                      upb_StringView* out);
+
+const char* upb_EnumDef_Name(const upb_EnumDef* e);
+const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e);
+
+upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i);
+int upb_EnumDef_ReservedNameCount(const upb_EnumDef* e);
+
+const upb_EnumReservedRange* upb_EnumDef_ReservedRange(const upb_EnumDef* e,
+                                                       int i);
+int upb_EnumDef_ReservedRangeCount(const upb_EnumDef* e);
+
+const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i);
+int upb_EnumDef_ValueCount(const upb_EnumDef* e);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_
+#define UPB_REFLECTION_ENUM_VALUE_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v);
+const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v);
+bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v);
+uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v);
+const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v);
+int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v);
+const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
+    const upb_EnumValueDef* v);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_VALUE_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_EXTENSION_RANGE_H_
+#define UPB_REFLECTION_EXTENSION_RANGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r);
+int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r);
+
+bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r);
+const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
+    const upb_ExtensionRange* r);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_EXTENSION_RANGE_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_FIELD_DEF_H_
+#define UPB_REFLECTION_FIELD_DEF_H_
+
+
+// Must be last.
+
+// Maximum field number allowed for FieldDefs.
+// This is an inherent limit of the protobuf wire format.
+#define kUpb_MaxFieldNumber ((1 << 29) - 1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f);
+const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f);
+upb_CType upb_FieldDef_CType(const upb_FieldDef* f);
+const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f);
+const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f);
+const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f);
+const char* upb_FieldDef_FullName(const upb_FieldDef* f);
+bool upb_FieldDef_HasDefault(const upb_FieldDef* f);
+bool upb_FieldDef_HasJsonName(const upb_FieldDef* f);
+bool upb_FieldDef_HasOptions(const upb_FieldDef* f);
+bool upb_FieldDef_HasPresence(const upb_FieldDef* f);
+bool upb_FieldDef_HasSubDef(const upb_FieldDef* f);
+uint32_t upb_FieldDef_Index(const upb_FieldDef* f);
+bool upb_FieldDef_IsExtension(const upb_FieldDef* f);
+bool upb_FieldDef_IsMap(const upb_FieldDef* f);
+bool upb_FieldDef_IsOptional(const upb_FieldDef* f);
+bool upb_FieldDef_IsPacked(const upb_FieldDef* f);
+bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f);
+bool upb_FieldDef_IsRepeated(const upb_FieldDef* f);
+bool upb_FieldDef_IsRequired(const upb_FieldDef* f);
+bool upb_FieldDef_IsString(const upb_FieldDef* f);
+bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f);
+const char* upb_FieldDef_JsonName(const upb_FieldDef* f);
+upb_Label upb_FieldDef_Label(const upb_FieldDef* f);
+const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f);
+
+// Creates a mini descriptor string for a field, returns true on success.
+bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a,
+                                       upb_StringView* out);
+
+const upb_MiniTableField* upb_FieldDef_MiniTable(const upb_FieldDef* f);
+const char* upb_FieldDef_Name(const upb_FieldDef* f);
+uint32_t upb_FieldDef_Number(const upb_FieldDef* f);
+const google_protobuf_FieldOptions* upb_FieldDef_Options(const upb_FieldDef* f);
+const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f);
+upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FIELD_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_FILE_DEF_H_
+#define UPB_REFLECTION_FILE_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i);
+int upb_FileDef_DependencyCount(const upb_FileDef* f);
+bool upb_FileDef_HasOptions(const upb_FileDef* f);
+const char* upb_FileDef_Name(const upb_FileDef* f);
+const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f);
+const char* upb_FileDef_Package(const upb_FileDef* f);
+const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f);
+
+const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i);
+int upb_FileDef_PublicDependencyCount(const upb_FileDef* f);
+
+const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i);
+int upb_FileDef_ServiceCount(const upb_FileDef* f);
+
+upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f);
+
+const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i);
+int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f);
+
+const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i);
+int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f);
+
+const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i);
+int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f);
+
+const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i);
+int upb_FileDef_WeakDependencyCount(const upb_FileDef* f);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FILE_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_MESSAGE_DEF_H_
+#define UPB_REFLECTION_MESSAGE_DEF_H_
+
+
+// Must be last.
+
+// Well-known field tag numbers for map-entry messages.
+#define kUpb_MapEntry_KeyFieldNumber 1
+#define kUpb_MapEntry_ValueFieldNumber 2
+
+// Well-known field tag numbers for Any messages.
+#define kUpb_Any_TypeFieldNumber 1
+#define kUpb_Any_ValueFieldNumber 2
+
+// Well-known field tag numbers for duration messages.
+#define kUpb_Duration_SecondsFieldNumber 1
+#define kUpb_Duration_NanosFieldNumber 2
+
+// Well-known field tag numbers for timestamp messages.
+#define kUpb_Timestamp_SecondsFieldNumber 1
+#define kUpb_Timestamp_NanosFieldNumber 2
+
+// 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 number of these groups are not changed.
 typedef enum {
   kUpb_WellKnown_Unspecified,
   kUpb_WellKnown_Any,
   kUpb_WellKnown_FieldMask,
   kUpb_WellKnown_Duration,
   kUpb_WellKnown_Timestamp,
-  /* number wrappers */
+
+  // number wrappers
   kUpb_WellKnown_DoubleValue,
   kUpb_WellKnown_FloatValue,
   kUpb_WellKnown_Int64Value,
   kUpb_WellKnown_UInt64Value,
   kUpb_WellKnown_Int32Value,
   kUpb_WellKnown_UInt32Value,
-  /* string wrappers */
+
+  // string wrappers
   kUpb_WellKnown_StringValue,
   kUpb_WellKnown_BytesValue,
   kUpb_WellKnown_BoolValue,
   kUpb_WellKnown_Value,
   kUpb_WellKnown_ListValue,
-  kUpb_WellKnown_Struct
+  kUpb_WellKnown_Struct,
 } upb_WellKnown;
 
-/* upb_FieldDef ***************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
- * protobuf wire format. */
-#define kUpb_MaxFieldNumber ((1 << 29) - 1)
-
-const google_protobuf_FieldOptions* upb_FieldDef_Options(const upb_FieldDef* f);
-bool upb_FieldDef_HasOptions(const upb_FieldDef* f);
-const char* upb_FieldDef_FullName(const upb_FieldDef* f);
-upb_CType upb_FieldDef_CType(const upb_FieldDef* f);
-upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f);
-upb_Label 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_HasJsonName(const upb_FieldDef* f);
-bool upb_FieldDef_IsExtension(const upb_FieldDef* f);
-bool upb_FieldDef_IsPacked(const upb_FieldDef* f);
-const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f);
-const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f);
-const upb_MessageDef* upb_FieldDef_ExtensionScope(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_IsSubMessage(const upb_FieldDef* f);
-bool upb_FieldDef_IsString(const upb_FieldDef* f);
-bool upb_FieldDef_IsRepeated(const upb_FieldDef* f);
-bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f);
-bool upb_FieldDef_IsMap(const upb_FieldDef* f);
-bool upb_FieldDef_HasDefault(const upb_FieldDef* f);
-bool upb_FieldDef_HasSubDef(const upb_FieldDef* f);
-bool upb_FieldDef_HasPresence(const upb_FieldDef* f);
-const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f);
-const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f);
-const upb_MiniTable_Field* upb_FieldDef_MiniTable(const upb_FieldDef* f);
-const upb_MiniTable_Extension* _upb_FieldDef_ExtensionMiniTable(
-    const upb_FieldDef* f);
-bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f);
-
-/* upb_OneofDef ***************************************************************/
-
-const google_protobuf_OneofOptions* upb_OneofDef_Options(const upb_OneofDef* o);
-bool upb_OneofDef_HasOptions(const upb_OneofDef* o);
-const char* upb_OneofDef_Name(const upb_OneofDef* o);
-const upb_MessageDef* 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_LookupNameWithSize(const upb_OneofDef* o,
-                                                    const char* name,
-                                                    size_t length);
-UPB_INLINE const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o,
-                                                       const char* name) {
-  return upb_OneofDef_LookupNameWithSize(o, name, strlen(name));
-}
-const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
-                                              uint32_t num);
-
-/* upb_MessageDef *************************************************************/
-
-/* Well-known field tag numbers for map-entry messages. */
-#define kUpb_MapEntry_KeyFieldNumber 1
-#define kUpb_MapEntry_ValueFieldNumber 2
-
-/* Well-known field tag numbers for Any messages. */
-#define kUpb_Any_TypeFieldNumber 1
-#define kUpb_Any_ValueFieldNumber 2
-
-/* Well-known field tag numbers for timestamp messages. */
-#define kUpb_Duration_SecondsFieldNumber 1
-#define kUpb_Duration_NanosFieldNumber 2
-
-/* Well-known field tag numbers for duration messages. */
-#define kUpb_Timestamp_SecondsFieldNumber 1
-#define kUpb_Timestamp_NanosFieldNumber 2
-
-const google_protobuf_MessageOptions* upb_MessageDef_Options(
-    const upb_MessageDef* m);
-bool upb_MessageDef_HasOptions(const upb_MessageDef* m);
-const char* upb_MessageDef_FullName(const upb_MessageDef* m);
-const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m);
 const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m);
-const char* upb_MessageDef_Name(const upb_MessageDef* m);
-upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m);
-upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m);
-int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m);
-int upb_MessageDef_FieldCount(const upb_MessageDef* m);
-int upb_MessageDef_OneofCount(const upb_MessageDef* m);
+
 const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m,
                                                         int i);
+int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m);
+
 const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, int i);
-const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i);
-const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
-                                                     uint32_t i);
-const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
-    const upb_MessageDef* m, const char* name, size_t len);
-const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize(
-    const upb_MessageDef* m, const char* name, size_t len);
-const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m);
+int upb_MessageDef_FieldCount(const upb_MessageDef* m);
 
-UPB_INLINE const upb_OneofDef* upb_MessageDef_FindOneofByName(
+const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m);
+
+// Returns a field by either JSON name or regular proto name.
+const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size);
+UPB_INLINE const upb_FieldDef* upb_MessageDef_FindByJsonName(
     const upb_MessageDef* m, const char* name) {
-  return upb_MessageDef_FindOneofByNameWithSize(m, name, strlen(name));
+  return upb_MessageDef_FindByJsonNameWithSize(m, name, strlen(name));
 }
 
-UPB_INLINE const upb_FieldDef* upb_MessageDef_FindFieldByName(
-    const upb_MessageDef* m, const char* name) {
-  return upb_MessageDef_FindFieldByNameWithSize(m, name, strlen(name));
-}
-
-UPB_INLINE bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m) {
-  return google_protobuf_MessageOptions_map_entry(upb_MessageDef_Options(m));
-}
-
-/* Nested entities. */
-int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m);
-int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m);
-int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m);
-const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
-                                                   int i);
-const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i);
-const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
-                                                   int i);
-
-/* 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. */
+// 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_MessageDef_FindByNameWithSize(const upb_MessageDef* m,
-                                       const char* name, size_t len,
+                                       const char* name, size_t size,
                                        const upb_FieldDef** f,
                                        const upb_OneofDef** o);
-
 UPB_INLINE bool upb_MessageDef_FindByName(const upb_MessageDef* m,
                                           const char* name,
                                           const upb_FieldDef** f,
@@ -4855,179 +7276,159 @@
   return upb_MessageDef_FindByNameWithSize(m, name, strlen(name), f, o);
 }
 
-/* Returns a field by either JSON name or regular proto name. */
-const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
-    const upb_MessageDef* m, const char* name, size_t len);
-UPB_INLINE const upb_FieldDef* upb_MessageDef_FindByJsonName(
-    const upb_MessageDef* m, const char* name) {
-  return upb_MessageDef_FindByJsonNameWithSize(m, name, strlen(name));
-}
+const upb_FieldDef* upb_MessageDef_FindFieldByName(const upb_MessageDef* m,
+                                                   const char* name);
+const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size);
+const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
+                                                     uint32_t i);
+const upb_OneofDef* upb_MessageDef_FindOneofByName(const upb_MessageDef* m,
+                                                   const char* name);
+const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size);
+const char* upb_MessageDef_FullName(const upb_MessageDef* m);
+bool upb_MessageDef_HasOptions(const upb_MessageDef* m);
+bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m);
+bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m);
 
-/* upb_ExtensionRange *********************************************************/
+// Creates a mini descriptor string for a message, returns true on success.
+bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a,
+                                         upb_StringView* out);
 
-const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
-    const upb_ExtensionRange* r);
-bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r);
-int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r);
-int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r);
+const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m);
+const char* upb_MessageDef_Name(const upb_MessageDef* m);
 
-/* upb_EnumDef ****************************************************************/
+const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i);
+const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
+                                                   int i);
+const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
+                                                   int i);
 
-const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e);
-bool upb_EnumDef_HasOptions(const upb_EnumDef* e);
-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);
-const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e);
-int32_t upb_EnumDef_Default(const upb_EnumDef* e);
-int upb_EnumDef_ValueCount(const upb_EnumDef* e);
-const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i);
+int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m);
+int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m);
+int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m);
 
-const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
-    const upb_EnumDef* e, const char* name, size_t len);
-const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e,
-                                                      int32_t num);
-bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num);
+const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i);
+int upb_MessageDef_OneofCount(const upb_MessageDef* m);
 
-// Convenience wrapper.
-UPB_INLINE const upb_EnumValueDef* upb_EnumDef_FindValueByName(
-    const upb_EnumDef* e, const char* name) {
-  return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name));
-}
+const google_protobuf_MessageOptions* upb_MessageDef_Options(const upb_MessageDef* m);
 
-/* upb_EnumValueDef ***********************************************************/
+upb_StringView upb_MessageDef_ReservedName(const upb_MessageDef* m, int i);
+int upb_MessageDef_ReservedNameCount(const upb_MessageDef* m);
 
-const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
-    const upb_EnumValueDef* e);
-bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* e);
-const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* e);
-const char* upb_EnumValueDef_Name(const upb_EnumValueDef* e);
-int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* e);
-uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* e);
-const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* e);
+const upb_MessageReservedRange* upb_MessageDef_ReservedRange(
+    const upb_MessageDef* m, int i);
+int upb_MessageDef_ReservedRangeCount(const upb_MessageDef* m);
 
-/* upb_FileDef ****************************************************************/
-
-const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f);
-bool upb_FileDef_HasOptions(const upb_FileDef* f);
-const char* upb_FileDef_Name(const upb_FileDef* f);
-const char* upb_FileDef_Package(const upb_FileDef* f);
-upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f);
-int upb_FileDef_DependencyCount(const upb_FileDef* f);
-int upb_FileDef_PublicDependencyCount(const upb_FileDef* f);
-int upb_FileDef_WeakDependencyCount(const upb_FileDef* f);
-int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f);
-int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f);
-int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f);
-int upb_FileDef_ServiceCount(const upb_FileDef* f);
-const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i);
-const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i);
-const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i);
-const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i);
-const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i);
-const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i);
-const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i);
-const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f);
-const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f);
-const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f);
-
-/* upb_MethodDef **************************************************************/
-
-const google_protobuf_MethodOptions* upb_MethodDef_Options(
-    const upb_MethodDef* m);
-bool upb_MethodDef_HasOptions(const upb_MethodDef* m);
-const char* upb_MethodDef_FullName(const upb_MethodDef* m);
-int upb_MethodDef_Index(const upb_MethodDef* m);
-const char* upb_MethodDef_Name(const upb_MethodDef* m);
-const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m);
-const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m);
-const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m);
-bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m);
-bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m);
-
-/* upb_ServiceDef *************************************************************/
-
-const google_protobuf_ServiceOptions* upb_ServiceDef_Options(
-    const upb_ServiceDef* s);
-bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s);
-const char* upb_ServiceDef_FullName(const upb_ServiceDef* s);
-const char* upb_ServiceDef_Name(const upb_ServiceDef* s);
-int upb_ServiceDef_Index(const upb_ServiceDef* s);
-const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s);
-int upb_ServiceDef_MethodCount(const upb_ServiceDef* s);
-const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i);
-const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
-                                                     const char* name);
-
-/* upb_DefPool ****************************************************************/
-
-upb_DefPool* upb_DefPool_New(void);
-void upb_DefPool_Free(upb_DefPool* s);
-const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
-                                                    const char* sym);
-const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
-    const upb_DefPool* s, const char* sym, size_t len);
-const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
-                                              const char* sym);
-const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
-                                                      const char* sym);
-const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
-                                                    const char* sym);
-const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
-    const upb_DefPool* s, const char* sym, size_t len);
-const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
-                                              const char* name);
-const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
-                                                    const char* name);
-const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
-    const upb_DefPool* s, const char* name, size_t size);
-const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
-                                                        const char* name);
-const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s,
-                                                      const char* name,
-                                                      size_t len);
-const upb_FileDef* upb_DefPool_AddFile(
-    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file,
-    upb_Status* status);
-size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s);
-upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s);
-const upb_FieldDef* _upb_DefPool_FindExtensionByMiniTable(
-    const upb_DefPool* s, const upb_MiniTable_Extension* ext);
-const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
-                                                      const upb_MessageDef* m,
-                                                      int32_t fieldnum);
-const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
-    const upb_DefPool* s);
-const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
-                                                  const upb_MessageDef* m,
-                                                  size_t* count);
-
-/* For generated code only: loads a generated descriptor. */
-typedef struct _upb_DefPool_Init {
-  struct _upb_DefPool_Init** deps; /* Dependencies of this file. */
-  const upb_MiniTable_File* layout;
-  const char* filename;
-  upb_StringView descriptor; /* Serialized descriptor. */
-} _upb_DefPool_Init;
-
-// Should only be directly called by tests.  This variant lets us suppress
-// the use of compiled-in tables, forcing a rebuild of the tables at runtime.
-bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
-                                bool rebuild_minitable);
-
-UPB_INLINE bool _upb_DefPool_LoadDefInit(upb_DefPool* s,
-                                         const _upb_DefPool_Init* init) {
-  return _upb_DefPool_LoadDefInitEx(s, init, false);
-}
-
+upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m);
+upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m);
 
 #ifdef __cplusplus
 } /* extern "C" */
-#endif /* __cplusplus */
+#endif
 
-#endif /* UPB_DEF_H_ */
 
-/** google/protobuf/descriptor.upbdefs.h ************************************************************//* This file was generated by upbc (the upb compiler) from the input
+#endif /* UPB_REFLECTION_MESSAGE_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_METHOD_DEF_H_
+#define UPB_REFLECTION_METHOD_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m);
+const char* upb_MethodDef_FullName(const upb_MethodDef* m);
+bool upb_MethodDef_HasOptions(const upb_MethodDef* m);
+int upb_MethodDef_Index(const upb_MethodDef* m);
+const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m);
+const char* upb_MethodDef_Name(const upb_MethodDef* m);
+const google_protobuf_MethodOptions* upb_MethodDef_Options(const upb_MethodDef* m);
+const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m);
+bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m);
+const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_METHOD_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ONEOF_DEF_H_
+#define UPB_REFLECTION_ONEOF_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_MessageDef* upb_OneofDef_ContainingType(const upb_OneofDef* o);
+const upb_FieldDef* upb_OneofDef_Field(const upb_OneofDef* o, int i);
+int upb_OneofDef_FieldCount(const upb_OneofDef* o);
+const char* upb_OneofDef_FullName(const upb_OneofDef* o);
+bool upb_OneofDef_HasOptions(const upb_OneofDef* o);
+uint32_t upb_OneofDef_Index(const upb_OneofDef* o);
+bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o);
+const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o,
+                                            const char* name);
+const upb_FieldDef* upb_OneofDef_LookupNameWithSize(const upb_OneofDef* o,
+                                                    const char* name,
+                                                    size_t size);
+const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
+                                              uint32_t num);
+const char* upb_OneofDef_Name(const upb_OneofDef* o);
+int upb_OneofDef_numfields(const upb_OneofDef* o);
+const google_protobuf_OneofOptions* upb_OneofDef_Options(const upb_OneofDef* o);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ONEOF_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_SERVICE_DEF_H_
+#define UPB_REFLECTION_SERVICE_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s);
+const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
+                                                     const char* name);
+const char* upb_ServiceDef_FullName(const upb_ServiceDef* s);
+bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s);
+int upb_ServiceDef_Index(const upb_ServiceDef* s);
+const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i);
+int upb_ServiceDef_MethodCount(const upb_ServiceDef* s);
+const char* upb_ServiceDef_Name(const upb_ServiceDef* s);
+const google_protobuf_ServiceOptions* upb_ServiceDef_Options(const upb_ServiceDef* s);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_SERVICE_DEF_H_ */
+
+#endif /* UPB_REFLECTION_DEF_H_ */
+/* This file was generated by upbc (the upb compiler) from the input
  * file:
  *
  *     google/protobuf/descriptor.proto
@@ -5038,6 +7439,52 @@
 #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_
 #define GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_
 
+
+#ifndef UPB_REFLECTION_DEF_POOL_INTERNAL_H_
+#define UPB_REFLECTION_DEF_POOL_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s);
+size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s);
+upb_ExtensionRegistry* _upb_DefPool_ExtReg(const upb_DefPool* s);
+
+bool _upb_DefPool_InsertExt(upb_DefPool* s, const upb_MiniTableExtension* ext,
+                            upb_FieldDef* f);
+bool _upb_DefPool_InsertSym(upb_DefPool* s, upb_StringView sym, upb_value v,
+                            upb_Status* status);
+bool _upb_DefPool_LookupSym(const upb_DefPool* s, const char* sym, size_t size,
+                            upb_value* v);
+
+void** _upb_DefPool_ScratchData(const upb_DefPool* s);
+size_t* _upb_DefPool_ScratchSize(const upb_DefPool* s);
+
+// For generated code only: loads a generated descriptor.
+typedef struct _upb_DefPool_Init {
+  struct _upb_DefPool_Init** deps;  // Dependencies of this file.
+  const upb_MiniTableFile* layout;
+  const char* filename;
+  upb_StringView descriptor;  // Serialized descriptor.
+} _upb_DefPool_Init;
+
+bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init);
+
+// Should only be directly called by tests. This variant lets us suppress
+// the use of compiled-in tables, forcing a rebuild of the tables at runtime.
+bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
+                                bool rebuild_minitable);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_POOL_INTERNAL_H_ */
 #ifdef __cplusplus
 extern "C" {
 #endif
@@ -5188,43 +7635,188 @@
 
 #endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPBDEFS_H_ */
 
-/** upb/reflection.h ************************************************************/
-#ifndef UPB_REFLECTION_H_
-#define UPB_REFLECTION_H_
+#ifndef UPB_HASH_INT_TABLE_H_
+#define UPB_HASH_INT_TABLE_H_
 
 
+// Must be last.
+
+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;
+
 #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_Message* msg_val;
-  const upb_Array* array_val;
-  upb_StringView str_val;
-} upb_MessageValue;
+// Initialize a table. If memory allocation failed, false is returned and
+// the table is uninitialized.
+bool upb_inttable_init(upb_inttable* table, upb_Arena* a);
 
-typedef union {
-  upb_Map* map;
-  upb_Message* msg;
-  upb_Array* array;
-} upb_MutableMessageValue;
+// Returns the number of values in the table.
+size_t upb_inttable_count(const upb_inttable* t);
+
+// Inserts the given key into the hashtable with the given value.
+// The key must not already exist in the hash table.
+// The value must not be 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);
+
+// 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);
+
+// 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);
+
+// 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);
+
+// Iteration over inttable:
+//
+//   intptr_t iter = UPB_INTTABLE_BEGIN;
+//   uintptr_t key;
+//   upb_value val;
+//   while (upb_inttable_next(t, &key, &val, &iter)) {
+//      // ...
+//   }
+
+#define UPB_INTTABLE_BEGIN -1
+
+bool upb_inttable_next(const upb_inttable* t, uintptr_t* key, upb_value* val,
+                       intptr_t* iter);
+void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_HASH_INT_TABLE_H_ */
+
+#ifndef UPB_JSON_DECODE_H_
+#define UPB_JSON_DECODE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum { upb_JsonDecode_IgnoreUnknown = 1 };
+
+bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
+                    const upb_MessageDef* m, const upb_DefPool* symtab,
+                    int options, upb_Arena* arena, upb_Status* status);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_JSONDECODE_H_ */
+
+#ifndef UPB_LEX_ATOI_H_
+#define UPB_LEX_ATOI_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 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.
+// Return the new position of the pointer after parsing the int, or NULL on
+// integer overflow.
+
+const char* upb_BufToUint64(const char* ptr, const char* end, uint64_t* val);
+const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val,
+                           bool* is_neg);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_ATOI_H_ */
+
+#ifndef UPB_LEX_UNICODE_H_
+#define UPB_LEX_UNICODE_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Returns true iff a codepoint is the value for a high surrogate.
+UPB_INLINE bool upb_Unicode_IsHigh(uint32_t cp) {
+  return (cp >= 0xd800 && cp <= 0xdbff);
+}
+
+// Returns true iff a codepoint is the value for a low surrogate.
+UPB_INLINE bool upb_Unicode_IsLow(uint32_t cp) {
+  return (cp >= 0xdc00 && cp <= 0xdfff);
+}
+
+// Returns the high 16-bit surrogate value for a supplementary codepoint.
+// Does not sanity-check the input.
+UPB_INLINE uint16_t upb_Unicode_ToHigh(uint32_t cp) {
+  return (cp >> 10) + 0xd7c0;
+}
+
+// Returns the low 16-bit surrogate value for a supplementary codepoint.
+// Does not sanity-check the input.
+UPB_INLINE uint16_t upb_Unicode_ToLow(uint32_t cp) {
+  return (cp & 0x3ff) | 0xdc00;
+}
+
+// Returns the 32-bit value corresponding to a pair of 16-bit surrogates.
+// Does not sanity-check the input.
+UPB_INLINE uint32_t upb_Unicode_FromPair(uint32_t high, uint32_t low) {
+  return ((high & 0x3ff) << 10) + (low & 0x3ff) + 0x10000;
+}
+
+// Outputs a codepoint as UTF8.
+// Returns the number of bytes written (1-4 on success, 0 on error).
+// Does not sanity-check the input. Specifically does not check for surrogates.
+int upb_Unicode_ToUTF8(uint32_t cp, char* out);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_UNICODE_H_ */
+
+#ifndef UPB_REFLECTION_MESSAGE_H_
+#define UPB_REFLECTION_MESSAGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f);
 
-/** upb_Message
- * *******************************************************************/
-
-/* Creates a new message of the given type in the given arena. */
-upb_Message* upb_Message_New(const upb_MessageDef* m, upb_Arena* a);
-
 /* Returns the value associated with this field. */
 upb_MessageValue upb_Message_Get(const upb_Message* msg, const upb_FieldDef* f);
 
@@ -5279,130 +7871,18 @@
 bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* 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_CType 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_MessageValue 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_MessageValue val);
-
-/* Appends an element to the array.  Returns false on allocation failure. */
-bool upb_Array_Append(upb_Array* array, upb_MessageValue val, upb_Arena* arena);
-
-/* Moves elements within the array using memmove(). Like memmove(), the source
- * and destination elements may be overlapping. */
-void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
-                    size_t count);
-
-/* Inserts one or more empty elements into the array.  Existing elements are
- * shifted right.  The new elements have undefined state and must be set with
- * `upb_Array_Set()`.
- * REQUIRES: `i <= upb_Array_Size(arr)` */
-bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
-                      upb_Arena* arena);
-
-/* Deletes one or more elements from the array.  Existing elements are shifted
- * left.
- * REQUIRES: `i + count <= upb_Array_Size(arr)` */
-void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
-
-/* 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_CType key_type, upb_CType 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_MessageValue key,
-                 upb_MessageValue* 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_MessageValue key, upb_MessageValue 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_MessageValue key);
-
-/* Map iteration:
- *
- * size_t iter = kUpb_Map_Begin;
- * while (upb_MapIterator_Next(map, &iter)) {
- *   upb_MessageValue key = upb_MapIterator_Key(map, iter);
- *   upb_MessageValue val = upb_MapIterator_Value(map, iter);
- *
- *   // If mutating is desired.
- *   upb_MapIterator_SetValue(map, iter, value2);
- * }
- */
-
-/* Advances to the next entry.  Returns false if no more entries are present. */
-bool upb_MapIterator_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
- * kUpb_Map_Begin (you must call next() at least once first). */
-bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
-
-/* Returns the key and value for this entry of the map. */
-upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
-upb_MessageValue upb_MapIterator_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_MapIterator_SetValue(upb_Map* map, size_t iter,
-                              upb_MessageValue value);
-
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 
-#endif /* UPB_REFLECTION_H_ */
+#endif /* UPB_REFLECTION_MESSAGE_H_ */
 
-/** upb/json_decode.h ************************************************************/
-#ifndef UPB_JSONDECODE_H_
-#define UPB_JSONDECODE_H_
+#ifndef UPB_JSON_ENCODE_H_
+#define UPB_JSON_ENCODE_H_
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum { upb_JsonDecode_IgnoreUnknown = 1 };
-
-bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
-                    const upb_MessageDef* m, const upb_DefPool* symtab,
-                    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_
-
+// Must be last.
 
 #ifdef __cplusplus
 extern "C" {
@@ -5410,11 +7890,14 @@
 
 enum {
   /* When set, emits 0/default values.  TODO(haberman): proto3 only? */
-  upb_JsonEncode_EmitDefaults = 1,
+  upb_JsonEncode_EmitDefaults = 1 << 0,
 
-  /* When set, use normal (snake_caes) field names instead of JSON (camelCase)
+  /* When set, use normal (snake_case) field names instead of JSON (camelCase)
      names. */
-  upb_JsonEncode_UseProtoNames = 2
+  upb_JsonEncode_UseProtoNames = 1 << 1,
+
+  /* When set, emits enums as their integer values instead of as their names. */
+  upb_JsonEncode_FormatEnumsAsIntegers = 1 << 2
 };
 
 /* Encodes the given |msg| to JSON format.  The message's reflection is given in
@@ -5433,10 +7916,1154 @@
 } /* extern "C" */
 #endif
 
+
 #endif /* UPB_JSONENCODE_H_ */
 
-/** upb/port_undef.inc ************************************************************/
-/* See port_def.inc.  This should #undef all macros #defined there. */
+#ifndef UPB_LEX_ROUND_TRIP_H_
+#define UPB_LEX_ROUND_TRIP_H_
+
+// Must be last.
+
+// Encodes a float or double that is round-trippable, but as short as possible.
+// These routines are not fully optimal (not guaranteed to be shortest), but are
+// short-ish and match the implementation that has been used in protobuf since
+// the beginning.
+
+// The given buffer size must be at least kUpb_RoundTripBufferSize.
+enum { kUpb_RoundTripBufferSize = 32 };
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size);
+void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_ROUND_TRIP_H_ */
+
+#ifndef UPB_PORT_VSNPRINTF_COMPAT_H_
+#define UPB_PORT_VSNPRINTF_COMPAT_H_
+
+// Must be last.
+
+UPB_INLINE int _upb_vsnprintf(char* buf, size_t size, const char* fmt,
+                              va_list ap) {
+#if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER)
+  // The msvc runtime has a non-conforming vsnprintf() that requires the
+  // following compatibility code to become conformant.
+  int n = -1;
+  if (size != 0) n = _vsnprintf_s(buf, size, _TRUNCATE, fmt, ap);
+  if (n == -1) n = _vscprintf(fmt, ap);
+  return n;
+#else
+  return vsnprintf(buf, size, fmt, ap);
+#endif
+}
+
+
+#endif  // UPB_PORT_VSNPRINTF_COMPAT_H_
+
+#ifndef UPB_LEX_STRTOD_H_
+#define UPB_LEX_STRTOD_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+double _upb_NoLocaleStrtod(const char *str, char **endptr);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_STRTOD_H_ */
+
+#ifndef UPB_MEM_ARENA_INTERNAL_H_
+#define UPB_MEM_ARENA_INTERNAL_H_
+
+
+// Must be last.
+
+typedef struct _upb_MemBlock _upb_MemBlock;
+
+struct upb_Arena {
+  _upb_ArenaHead 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. */
+  _upb_MemBlock *freelist, *freelist_tail;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MEM_ARENA_INTERNAL_H_ */
+
+#ifndef UPB_WIRE_TYPES_H_
+#define UPB_WIRE_TYPES_H_
+
+// A list of types as they are encoded on the wire.
+typedef enum {
+  kUpb_WireType_Varint = 0,
+  kUpb_WireType_64Bit = 1,
+  kUpb_WireType_Delimited = 2,
+  kUpb_WireType_StartGroup = 3,
+  kUpb_WireType_EndGroup = 4,
+  kUpb_WireType_32Bit = 5
+} upb_WireType;
+
+#endif /* UPB_WIRE_TYPES_H_ */
+
+#ifndef UPB_MINI_TABLE_COMMON_INTERNAL_H_
+#define UPB_MINI_TABLE_COMMON_INTERNAL_H_
+
+
+// Must be last.
+
+typedef enum {
+  kUpb_EncodedType_Double = 0,
+  kUpb_EncodedType_Float = 1,
+  kUpb_EncodedType_Fixed32 = 2,
+  kUpb_EncodedType_Fixed64 = 3,
+  kUpb_EncodedType_SFixed32 = 4,
+  kUpb_EncodedType_SFixed64 = 5,
+  kUpb_EncodedType_Int32 = 6,
+  kUpb_EncodedType_UInt32 = 7,
+  kUpb_EncodedType_SInt32 = 8,
+  kUpb_EncodedType_Int64 = 9,
+  kUpb_EncodedType_UInt64 = 10,
+  kUpb_EncodedType_SInt64 = 11,
+  kUpb_EncodedType_OpenEnum = 12,
+  kUpb_EncodedType_Bool = 13,
+  kUpb_EncodedType_Bytes = 14,
+  kUpb_EncodedType_String = 15,
+  kUpb_EncodedType_Group = 16,
+  kUpb_EncodedType_Message = 17,
+  kUpb_EncodedType_ClosedEnum = 18,
+
+  kUpb_EncodedType_RepeatedBase = 20,
+} upb_EncodedType;
+
+typedef enum {
+  kUpb_EncodedFieldModifier_FlipPacked = 1 << 0,
+  kUpb_EncodedFieldModifier_IsRequired = 1 << 1,
+  kUpb_EncodedFieldModifier_IsProto3Singular = 1 << 2,
+} upb_EncodedFieldModifier;
+
+enum {
+  kUpb_EncodedValue_MinField = ' ',
+  kUpb_EncodedValue_MaxField = 'I',
+  kUpb_EncodedValue_MinModifier = 'L',
+  kUpb_EncodedValue_MaxModifier = '[',
+  kUpb_EncodedValue_End = '^',
+  kUpb_EncodedValue_MinSkip = '_',
+  kUpb_EncodedValue_MaxSkip = '~',
+  kUpb_EncodedValue_OneofSeparator = '~',
+  kUpb_EncodedValue_FieldSeparator = '|',
+  kUpb_EncodedValue_MinOneofField = ' ',
+  kUpb_EncodedValue_MaxOneofField = 'b',
+  kUpb_EncodedValue_MaxEnumMask = 'A',
+};
+
+enum {
+  kUpb_EncodedVersion_EnumV1 = '!',
+  kUpb_EncodedVersion_ExtensionV1 = '#',
+  kUpb_EncodedVersion_MapV1 = '%',
+  kUpb_EncodedVersion_MessageV1 = '$',
+  kUpb_EncodedVersion_MessageSetV1 = '&',
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE char _upb_ToBase92(int8_t ch) {
+  extern const char _kUpb_ToBase92[];
+  UPB_ASSERT(0 <= ch && ch < 92);
+  return _kUpb_ToBase92[ch];
+}
+
+UPB_INLINE char _upb_FromBase92(uint8_t ch) {
+  extern const int8_t _kUpb_FromBase92[];
+  if (' ' > ch || ch > '~') return -1;
+  return _kUpb_FromBase92[ch - ' '];
+}
+
+UPB_INLINE bool _upb_FieldType_IsPackable(upb_FieldType type) {
+  // clang-format off
+  const unsigned kUnpackableTypes =
+      (1 << kUpb_FieldType_String) |
+      (1 << kUpb_FieldType_Bytes) |
+      (1 << kUpb_FieldType_Message) |
+      (1 << kUpb_FieldType_Group);
+  // clang-format on
+  return (1 << type) & ~kUnpackableTypes;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_COMMON_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_DECODE_H_
+#define UPB_MINI_TABLE_DECODE_H_
+
+
+// Must be last.
+
+typedef enum {
+  kUpb_MiniTablePlatform_32Bit,
+  kUpb_MiniTablePlatform_64Bit,
+  kUpb_MiniTablePlatform_Native =
+      UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit),
+} upb_MiniTablePlatform;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Builds a mini table from the data encoded in the buffer [data, len]. If any
+// errors occur, returns NULL and sets a status message. In the success case,
+// the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum
+// fields to link the table to the appropriate sub-tables.
+upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len,
+                                    upb_MiniTablePlatform platform,
+                                    upb_Arena* arena, upb_Status* status);
+
+UPB_INLINE upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len,
+                                              upb_Arena* arena,
+                                              upb_Status* status) {
+  return _upb_MiniTable_Build(data, len, kUpb_MiniTablePlatform_Native, arena,
+                              status);
+}
+
+// Links a sub-message field to a MiniTable for that sub-message.  If a
+// sub-message field is not linked, it will be treated as an unknown field
+// during parsing, and setting the field will not be allowed.  It is possible
+// to link the message field later, at which point it will no longer be treated
+// as unknown.  However there is no synchronization for this operation, which
+// means parallel mutation requires external synchronization.
+void upb_MiniTable_SetSubMessage(upb_MiniTable* table,
+                                 upb_MiniTableField* field,
+                                 const upb_MiniTable* sub);
+
+// Links an enum field to a MiniTable for that enum.  All enum fields must
+// be linked prior to parsing.
+void upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTableField* field,
+                              const upb_MiniTableEnum* sub);
+
+const char* _upb_MiniTableExtension_Build(const char* data, size_t len,
+                                          upb_MiniTableExtension* ext,
+                                          const upb_MiniTable* extendee,
+                                          upb_MiniTableSub sub,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Status* status);
+
+UPB_INLINE const char* upb_MiniTableExtension_Build(
+    const char* data, size_t len, upb_MiniTableExtension* ext,
+    const upb_MiniTable* extendee, upb_MiniTableSub sub, upb_Status* status) {
+  return _upb_MiniTableExtension_Build(data, len, ext, extendee, sub,
+                                       kUpb_MiniTablePlatform_Native, status);
+}
+
+upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len,
+                                           upb_Arena* arena,
+                                           upb_Status* status);
+
+// Like upb_MiniTable_Build(), but the user provides a buffer of layout data so
+// it can be reused from call to call, avoiding repeated realloc()/free().
+//
+// The caller owns `*buf` both before and after the call, and must free() it
+// when it is no longer in use.  The function will realloc() `*buf` as
+// necessary, updating `*size` accordingly.
+upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Arena* arena, void** buf,
+                                          size_t* buf_size, upb_Status* status);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_DECODE_H_ */
+
+#ifndef UPB_MINI_TABLE_ENCODE_INTERNAL_H_
+#define UPB_MINI_TABLE_ENCODE_INTERNAL_H_
+
+
+// Must be last.
+
+// If the input buffer has at least this many bytes available, the encoder call
+// is guaranteed to succeed (as long as field number order is maintained).
+#define kUpb_MtDataEncoder_MinSize 16
+
+typedef struct {
+  char* end;  // Limit of the buffer passed as a parameter.
+  // Aliased to internal-only members in .cc.
+  char internal[32];
+} upb_MtDataEncoder;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Encodes field/oneof information for a given message.  The sequence of calls
+// should look like:
+//
+//   upb_MtDataEncoder e;
+//   char buf[256];
+//   char* ptr = buf;
+//   e.end = ptr + sizeof(buf);
+//   unit64_t msg_mod = ...; // bitwise & of kUpb_MessageModifiers or zero
+//   ptr = upb_MtDataEncoder_StartMessage(&e, ptr, msg_mod);
+//   // Fields *must* be in field number order.
+//   ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+//   ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+//   ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+//
+//   // If oneofs are present.  Oneofs must be encoded after regular fields.
+//   ptr = upb_MiniTable_StartOneof(&e, ptr)
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//
+//   ptr = upb_MiniTable_StartOneof(&e, ptr);
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//
+// Oneofs must be encoded after all regular fields.
+char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr,
+                                     uint64_t msg_mod);
+char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr,
+                                 upb_FieldType type, uint32_t field_num,
+                                 uint64_t field_mod);
+char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr);
+char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr,
+                                      uint32_t field_num);
+
+// Encodes the set of values for a given enum. The values must be given in
+// order (after casting to uint32_t), and repeats are not allowed.
+char* upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e, char* ptr);
+char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr,
+                                     uint32_t val);
+char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr);
+
+// Encodes an entire mini descriptor for an extension.
+char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr,
+                                        upb_FieldType type, uint32_t field_num,
+                                        uint64_t field_mod);
+
+// Encodes an entire mini descriptor for a map.
+char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr,
+                                  upb_FieldType key_type,
+                                  upb_FieldType value_type, uint64_t key_mod,
+                                  uint64_t value_mod);
+
+// Encodes an entire mini descriptor for a message set.
+char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_ENCODE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_DEF_BUILDER_INTERNAL_H_
+#define UPB_REFLECTION_DEF_BUILDER_INTERNAL_H_
+
+
+// Must be last.
+
+// We want to copy the options verbatim into the destination options proto.
+// We use serialize+parse as our deep copy.
+#define UPB_DEF_SET_OPTIONS(target, desc_type, options_type, proto)          \
+  if (google_protobuf_##desc_type##_has_options(proto)) {                             \
+    size_t size;                                                             \
+    char* pb = google_protobuf_##options_type##_serialize(                            \
+        google_protobuf_##desc_type##_options(proto), ctx->tmp_arena, &size);         \
+    if (!pb) _upb_DefBuilder_OomErr(ctx);                                    \
+    target =                                                                 \
+        google_protobuf_##options_type##_parse(pb, size, _upb_DefBuilder_Arena(ctx)); \
+    if (!target) _upb_DefBuilder_OomErr(ctx);                                \
+  } else {                                                                   \
+    target = (const google_protobuf_##options_type*)kUpbDefOptDefault;                \
+  }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct upb_DefBuilder {
+  upb_DefPool* symtab;
+  upb_FileDef* file;                 // File we are building.
+  upb_Arena* arena;                  // Allocate defs here.
+  upb_Arena* tmp_arena;              // For temporary allocations.
+  upb_Status* status;                // Record errors here.
+  const upb_MiniTableFile* layout;   // NULL if we should build layouts.
+  int enum_count;                    // Count of enums built so far.
+  int msg_count;                     // Count of messages built so far.
+  int ext_count;                     // Count of extensions built so far.
+  jmp_buf err;                       // longjmp() on error.
+};
+
+extern const char* kUpbDefOptDefault;
+
+// ctx->status has already been set elsewhere so just fail/longjmp()
+UPB_NORETURN void _upb_DefBuilder_FailJmp(upb_DefBuilder* ctx);
+
+UPB_NORETURN void _upb_DefBuilder_Errf(upb_DefBuilder* ctx, const char* fmt,
+                                       ...) UPB_PRINTF(2, 3);
+UPB_NORETURN void _upb_DefBuilder_OomErr(upb_DefBuilder* ctx);
+
+const char* _upb_DefBuilder_MakeFullName(upb_DefBuilder* ctx,
+                                         const char* prefix,
+                                         upb_StringView name);
+
+// Given a symbol and the base symbol inside which it is defined,
+// find the symbol's definition.
+const void* _upb_DefBuilder_ResolveAny(upb_DefBuilder* ctx,
+                                       const char* from_name_dbg,
+                                       const char* base, upb_StringView sym,
+                                       upb_deftype_t* type);
+
+const void* _upb_DefBuilder_Resolve(upb_DefBuilder* ctx,
+                                    const char* from_name_dbg, const char* base,
+                                    upb_StringView sym, upb_deftype_t type);
+
+char _upb_DefBuilder_ParseEscape(upb_DefBuilder* ctx, const upb_FieldDef* f,
+                                 const char** src, const char* end);
+
+const char* _upb_DefBuilder_FullToShort(const char* fullname);
+
+UPB_INLINE void* _upb_DefBuilder_Alloc(upb_DefBuilder* ctx, size_t bytes) {
+  if (bytes == 0) return NULL;
+  void* ret = upb_Arena_Malloc(ctx->arena, bytes);
+  if (!ret) _upb_DefBuilder_OomErr(ctx);
+  return ret;
+}
+
+// Adds a symbol |v| to the symtab, which must be a def pointer previously
+// packed with pack_def(). The def's pointer to upb_FileDef* must be set before
+// adding, so we know which entries to remove if building this file fails.
+UPB_INLINE void _upb_DefBuilder_Add(upb_DefBuilder* ctx, const char* name,
+                                    upb_value v) {
+  upb_StringView sym = {.data = name, .size = strlen(name)};
+  bool ok = _upb_DefPool_InsertSym(ctx->symtab, sym, v, ctx->status);
+  if (!ok) _upb_DefBuilder_FailJmp(ctx);
+}
+
+UPB_INLINE upb_Arena* _upb_DefBuilder_Arena(const upb_DefBuilder* ctx) {
+  return ctx->arena;
+}
+
+UPB_INLINE upb_FileDef* _upb_DefBuilder_File(const upb_DefBuilder* ctx) {
+  return ctx->file;
+}
+
+// This version of CheckIdent() is only called by other, faster versions after
+// they detect a parsing error.
+void _upb_DefBuilder_CheckIdentSlow(upb_DefBuilder* ctx, upb_StringView name,
+                                    bool full);
+
+// Verify a relative identifier string. The loop is branchless for speed.
+UPB_INLINE void _upb_DefBuilder_CheckIdentNotFull(upb_DefBuilder* ctx,
+                                                  upb_StringView name) {
+  bool good = name.size > 0;
+
+  for (size_t i = 0; i < name.size; i++) {
+    const char c = name.data[i];
+    const char d = c | 0x20;  // force lowercase
+    const bool is_alpha = (('a' <= d) & (d <= 'z')) | (c == '_');
+    const bool is_numer = ('0' <= c) & (c <= '9') & (i != 0);
+
+    good &= is_alpha | is_numer;
+  }
+
+  if (!good) _upb_DefBuilder_CheckIdentSlow(ctx, name, false);
+}
+
+// Verify a full identifier string. This is slightly more complicated than
+// verifying a relative identifier string because we must track '.' chars.
+UPB_INLINE void _upb_DefBuilder_CheckIdentFull(upb_DefBuilder* ctx,
+                                               upb_StringView name) {
+  bool good = name.size > 0;
+  bool start = true;
+
+  for (size_t i = 0; i < name.size; i++) {
+    const char c = name.data[i];
+    const char d = c | 0x20;  // force lowercase
+    const bool is_alpha = (('a' <= d) & (d <= 'z')) | (c == '_');
+    const bool is_numer = ('0' <= c) & (c <= '9') & !start;
+    const bool is_dot = (c == '.') & !start;
+
+    good &= is_alpha | is_numer | is_dot;
+    start = is_dot;
+  }
+
+  if (!good) _upb_DefBuilder_CheckIdentSlow(ctx, name, true);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_BUILDER_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ENUM_DEF_INTERNAL_H_
+#define UPB_REFLECTION_ENUM_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i);
+bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a);
+const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e);
+
+// Allocate and initialize an array of |n| enum defs.
+upb_EnumDef* _upb_EnumDefs_New(upb_DefBuilder* ctx, int n,
+                               const google_protobuf_EnumDescriptorProto* const* protos,
+                               const upb_MessageDef* containing_type);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ENUM_VALUE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_ENUM_VALUE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_EnumValueDef* _upb_EnumValueDef_At(const upb_EnumValueDef* v, int i);
+
+// Allocate and initialize an array of |n| enum value defs owned by |e|.
+upb_EnumValueDef* _upb_EnumValueDefs_New(
+    upb_DefBuilder* ctx, const char* prefix, int n,
+    const google_protobuf_EnumValueDescriptorProto* const* protos, upb_EnumDef* e,
+    bool* is_sorted);
+
+const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v,
+                                                   int n, upb_Arena* a);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_VALUE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_FIELD_DEF_INTERNAL_H_
+#define UPB_REFLECTION_FIELD_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_FieldDef* _upb_FieldDef_At(const upb_FieldDef* f, int i);
+
+const upb_MiniTableExtension* _upb_FieldDef_ExtensionMiniTable(
+    const upb_FieldDef* f);
+bool _upb_FieldDef_IsClosedEnum(const upb_FieldDef* f);
+bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f);
+int _upb_FieldDef_LayoutIndex(const upb_FieldDef* f);
+uint64_t _upb_FieldDef_Modifiers(const upb_FieldDef* f);
+void _upb_FieldDef_Resolve(upb_DefBuilder* ctx, const char* prefix,
+                           upb_FieldDef* f);
+
+// Allocate and initialize an array of |n| field defs.
+upb_FieldDef* _upb_FieldDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_FieldDescriptorProto* const* protos, const char* prefix,
+    upb_MessageDef* m, bool* is_sorted);
+
+// Allocate and return a list of pointers to the |n| field defs in |ff|,
+// sorted by field number.
+const upb_FieldDef** _upb_FieldDefs_Sorted(const upb_FieldDef* f, int n,
+                                           upb_Arena* a);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FIELD_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_FILE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_FILE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_MiniTableExtension* _upb_FileDef_ExtensionMiniTable(
+    const upb_FileDef* f, int i);
+const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f);
+const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f);
+
+// upb_FileDef_Package() returns "" if f->package is NULL, this does not.
+const char* _upb_FileDef_RawPackage(const upb_FileDef* f);
+
+void _upb_FileDef_Create(upb_DefBuilder* ctx,
+                         const google_protobuf_FileDescriptorProto* file_proto);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FILE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_MESSAGE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_MESSAGE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_MessageDef* _upb_MessageDef_At(const upb_MessageDef* m, int i);
+bool _upb_MessageDef_InMessageSet(const upb_MessageDef* m);
+bool _upb_MessageDef_Insert(upb_MessageDef* m, const char* name, size_t size,
+                            upb_value v, upb_Arena* a);
+void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
+                                 const upb_FieldDef* f);
+bool _upb_MessageDef_IsValidExtensionNumber(const upb_MessageDef* m, int n);
+void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx,
+                                   const upb_MessageDef* m);
+void _upb_MessageDef_Resolve(upb_DefBuilder* ctx, upb_MessageDef* m);
+
+// Allocate and initialize an array of |n| message defs.
+upb_MessageDef* _upb_MessageDefs_New(
+    upb_DefBuilder* ctx, int n, const google_protobuf_DescriptorProto* const* protos,
+    const upb_MessageDef* containing_type);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_MESSAGE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_SERVICE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_SERVICE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_ServiceDef* _upb_ServiceDef_At(const upb_ServiceDef* s, int i);
+
+// Allocate and initialize an array of |n| service defs.
+upb_ServiceDef* _upb_ServiceDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_ServiceDescriptorProto* const* protos);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_SERVICE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_DESC_STATE_INTERNAL_H_
+#define UPB_REFLECTION_DESC_STATE_INTERNAL_H_
+
+
+// Must be last.
+
+// Manages the storage for mini descriptor strings as they are being encoded.
+// TODO(b/234740652): Move some of this state directly into the encoder, maybe.
+typedef struct {
+  upb_MtDataEncoder e;
+  size_t bufsize;
+  char* buf;
+  char* ptr;
+} upb_DescState;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE void _upb_DescState_Init(upb_DescState* d) {
+  d->bufsize = kUpb_MtDataEncoder_MinSize * 2;
+  d->buf = NULL;
+  d->ptr = NULL;
+}
+
+bool _upb_DescState_Grow(upb_DescState* d, upb_Arena* a);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DESC_STATE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ENUM_RESERVED_RANGE_INTERNAL_H_
+#define UPB_REFLECTION_ENUM_RESERVED_RANGE_INTERNAL_H_
+
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ENUM_RESERVED_RANGE_H_
+#define UPB_REFLECTION_ENUM_RESERVED_RANGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t upb_EnumReservedRange_Start(const upb_EnumReservedRange* r);
+int32_t upb_EnumReservedRange_End(const upb_EnumReservedRange* r);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_RESERVED_RANGE_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_EnumReservedRange* _upb_EnumReservedRange_At(const upb_EnumReservedRange* r,
+                                                 int i);
+
+// Allocate and initialize an array of |n| reserved ranges owned by |e|.
+upb_EnumReservedRange* _upb_EnumReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* protos,
+    const upb_EnumDef* e);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_RESERVED_RANGE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_
+#define UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_ExtensionRange* _upb_ExtensionRange_At(const upb_ExtensionRange* r, int i);
+
+// Allocate and initialize an array of |n| extension ranges owned by |m|.
+upb_ExtensionRange* _upb_ExtensionRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ExtensionRange* const* protos,
+    const upb_MessageDef* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ONEOF_DEF_INTERNAL_H_
+#define UPB_REFLECTION_ONEOF_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_OneofDef* _upb_OneofDef_At(const upb_OneofDef* o, int i);
+bool _upb_OneofDef_Insert(upb_OneofDef* o, const upb_FieldDef* f,
+                          const char* name, size_t size, upb_Arena* a);
+
+// Allocate and initialize an array of |n| oneof defs owned by |m|.
+upb_OneofDef* _upb_OneofDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_OneofDescriptorProto* const* protos, upb_MessageDef* m);
+
+size_t _upb_OneofDefs_Finalize(upb_DefBuilder* ctx, upb_MessageDef* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ONEOF_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_MESSAGE_RESERVED_RANGE_INTERNAL_H_
+#define UPB_REFLECTION_MESSAGE_RESERVED_RANGE_INTERNAL_H_
+
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_MESSAGE_RESERVED_RANGE_H_
+#define UPB_REFLECTION_MESSAGE_RESERVED_RANGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t upb_MessageReservedRange_Start(const upb_MessageReservedRange* r);
+int32_t upb_MessageReservedRange_End(const upb_MessageReservedRange* r);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_MESSAGE_RESERVED_RANGE_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_MessageReservedRange* _upb_MessageReservedRange_At(
+    const upb_MessageReservedRange* r, int i);
+
+// Allocate and initialize an array of |n| reserved ranges owned by |m|.
+upb_MessageReservedRange* _upb_MessageReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ReservedRange* const* protos,
+    const upb_MessageDef* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_MESSAGE_RESERVED_RANGE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_METHOD_DEF_INTERNAL_H_
+#define UPB_REFLECTION_METHOD_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_MethodDef* _upb_MethodDef_At(const upb_MethodDef* m, int i);
+
+// Allocate and initialize an array of |n| method defs owned by |s|.
+upb_MethodDef* _upb_MethodDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_MethodDescriptorProto* const* protos, upb_ServiceDef* s);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_METHOD_DEF_INTERNAL_H_ */
+
+#ifndef UPB_WIRE_COMMON_INTERNAL_H_
+#define UPB_WIRE_COMMON_INTERNAL_H_
+
+// Must be last.
+
+// MessageSet wire format is:
+//   message MessageSet {
+//     repeated group Item = 1 {
+//       required int32 type_id = 2;
+//       required bytes message = 3;
+//     }
+//   }
+
+enum {
+  kUpb_MsgSet_Item = 1,
+  kUpb_MsgSet_TypeId = 2,
+  kUpb_MsgSet_Message = 3,
+};
+
+
+#endif /* UPB_WIRE_COMMON_INTERNAL_H_ */
+
+/*
+ * Internal implementation details of the decoder that are shared between
+ * decode.c and decode_fast.c.
+ */
+
+#ifndef UPB_WIRE_DECODE_INTERNAL_H_
+#define UPB_WIRE_DECODE_INTERNAL_H_
+
+#include "third_party/utf8_range/utf8_range.h"
+
+// Must be last.
+
+#define DECODE_NOGROUP (uint32_t) - 1
+
+typedef struct upb_Decoder {
+  const char* end;          /* Can read up to 16 bytes slop beyond this. */
+  const char* limit_ptr;    /* = end + UPB_MIN(limit, 0) */
+  upb_Message* unknown_msg; /* Used for preserving unknown data. */
+  const char* unknown; /* Start of unknown data, preserve at buffer flip. */
+  const upb_ExtensionRegistry*
+      extreg;         /* For looking up extensions during the parse. */
+  int limit;          /* Submessage limit relative to end. */
+  int depth;          /* Tracks recursion depth to bound stack usage. */
+  uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */
+  uint16_t options;
+  bool missing_required;
+  char patch[32];
+  upb_Arena arena;
+  jmp_buf err;
+
+#ifndef NDEBUG
+  const char* debug_tagstart;
+  const char* debug_valstart;
+#endif
+} upb_Decoder;
+
+/* 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* _upb_FastDecoder_ErrorJmp(upb_Decoder* d, int status);
+
+extern const uint8_t upb_utf8_offsets[];
+
+UPB_INLINE
+bool _upb_Decoder_VerifyUtf8Inline(const char* ptr, int len) {
+  const char* end = ptr + len;
+
+  // Check 8 bytes at a time for any non-ASCII char.
+  while (end - ptr >= 8) {
+    uint64_t data;
+    memcpy(&data, ptr, 8);
+    if (data & 0x8080808080808080) goto non_ascii;
+    ptr += 8;
+  }
+
+  // Check one byte at a time for non-ASCII.
+  while (ptr < end) {
+    if (*ptr & 0x80) goto non_ascii;
+    ptr++;
+  }
+
+  return true;
+
+non_ascii:
+  return utf8_range2((const unsigned char*)ptr, end - ptr) == 0;
+}
+
+const char* _upb_Decoder_CheckRequired(upb_Decoder* d, const char* ptr,
+                                       const upb_Message* msg,
+                                       const upb_MiniTable* l);
+
+/* 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_MiniTable* tablep) {
+  return ((intptr_t)tablep << 8) | tablep->table_mask;
+}
+
+UPB_INLINE const upb_MiniTable* decode_totablep(intptr_t table) {
+  return (const upb_MiniTable*)(table >> 8);
+}
+
+UPB_INLINE
+const char* _upb_Decoder_IsDoneFallbackInline(upb_Decoder* d, const char* ptr,
+                                              int overrun, int* status) {
+  if (overrun < d->limit) {
+    /* Need to copy remaining data into patch buffer. */
+    UPB_ASSERT(overrun < 16);
+    if (d->unknown) {
+      if (!_upb_Message_AddUnknown(d->unknown_msg, d->unknown, ptr - d->unknown,
+                                   &d->arena)) {
+        *status = kUpb_DecodeStatus_OutOfMemory;
+        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->options &= ~kUpb_DecodeOption_AliasString;
+    UPB_ASSERT(ptr < d->limit_ptr);
+    return ptr;
+  } else {
+    *status = kUpb_DecodeStatus_Malformed;
+    return NULL;
+  }
+}
+
+const char* _upb_Decoder_IsDoneFallback(upb_Decoder* d, const char* ptr,
+                                        int overrun);
+
+UPB_INLINE
+bool _upb_Decoder_IsDone(upb_Decoder* 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 = _upb_Decoder_IsDoneFallback(d, *ptr, overrun);
+    return false;
+  }
+}
+
+#if UPB_FASTTABLE
+UPB_INLINE
+const char* _upb_FastDecoder_TagDispatch(upb_Decoder* d, const char* ptr,
+                                         upb_Message* msg, intptr_t table,
+                                         uint64_t hasbits, uint64_t tag) {
+  const upb_MiniTable* 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 _upb_FastDecoder_LoadTag(const char* ptr) {
+  uint16_t tag;
+  memcpy(&tag, ptr, 2);
+  return tag;
+}
+
+UPB_INLINE void _upb_Decoder_CheckLimit(upb_Decoder* d) {
+  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+}
+
+UPB_INLINE int _upb_Decoder_PushLimit(upb_Decoder* d, const char* ptr,
+                                      int size) {
+  int limit = size + (int)(ptr - d->end);
+  int delta = d->limit - limit;
+  _upb_Decoder_CheckLimit(d);
+  d->limit = limit;
+  d->limit_ptr = d->end + UPB_MIN(0, limit);
+  _upb_Decoder_CheckLimit(d);
+  return delta;
+}
+
+UPB_INLINE void _upb_Decoder_PopLimit(upb_Decoder* d, const char* ptr,
+                                      int saved_delta) {
+  UPB_ASSERT(ptr - d->end == d->limit);
+  _upb_Decoder_CheckLimit(d);
+  d->limit += saved_delta;
+  d->limit_ptr = d->end + UPB_MIN(0, d->limit);
+  _upb_Decoder_CheckLimit(d);
+}
+
+
+#endif /* UPB_WIRE_DECODE_INTERNAL_H_ */
+
+#ifndef UPB_WIRE_SWAP_INTERNAL_H_
+#define UPB_WIRE_SWAP_INTERNAL_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE bool _upb_IsLittleEndian(void) {
+  int x = 1;
+  return *(char*)&x == 1;
+}
+
+UPB_INLINE uint32_t _upb_BigEndian_Swap32(uint32_t val) {
+  if (_upb_IsLittleEndian()) return val;
+
+  return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+         ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
+}
+
+UPB_INLINE uint64_t _upb_BigEndian_Swap64(uint64_t val) {
+  if (_upb_IsLittleEndian()) return val;
+
+  return ((uint64_t)_upb_BigEndian_Swap32((uint32_t)val) << 32) |
+         _upb_BigEndian_Swap32((uint32_t)(val >> 32));
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_WIRE_SWAP_INTERNAL_H_ */
+
+// This should #undef all macros #defined in def.inc
 
 #undef UPB_SIZE
 #undef UPB_PTR_AT
@@ -5448,6 +9075,7 @@
 #undef UPB_ALIGN_DOWN
 #undef UPB_ALIGN_MALLOC
 #undef UPB_ALIGN_OF
+#undef UPB_MALLOC_ALIGN
 #undef UPB_LIKELY
 #undef UPB_UNLIKELY
 #undef UPB_FORCEINLINE
@@ -5470,3 +9098,6 @@
 #undef UPB_POISON_MEMORY_REGION
 #undef UPB_UNPOISON_MEMORY_REGION
 #undef UPB_ASAN
+#undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3
+#undef UPB_DEPRECATED
+#undef UPB_GNUC_MIN
diff --git a/php/ext/google/protobuf/template_package.xml b/php/ext/google/protobuf/template_package.xml
index c6d2619..f8d6e66 100644
--- a/php/ext/google/protobuf/template_package.xml
+++ b/php/ext/google/protobuf/template_package.xml
@@ -22,7 +22,7 @@
  </stability>
  <license uri="https://opensource.org/licenses/BSD-3-Clause">BSD-3-Clause</license>
  <notes>
- * See github.com/protocolbuffers/protobuf/releases for release notes.
+ * See github.com/protocolbuffers/protobuf/releases/tag/vTEMPLATE_PROTOC_VERSION for release notes.
  </notes>
  <contents>
   <dir baseinstalldir="/" name="/">TEMPLATE_FILES</dir>
@@ -39,4 +39,4 @@
  </dependencies>
  <providesextension>protobuf</providesextension>
  <extsrcrelease/>
-</package>
\ No newline at end of file
+</package>
diff --git a/php/generate_descriptor_protos.sh b/php/generate_descriptor_protos.sh
index 9feaa96..0e5be35 100755
--- a/php/generate_descriptor_protos.sh
+++ b/php/generate_descriptor_protos.sh
@@ -5,6 +5,14 @@
 
 set -e
 
+if [[ -z "${PROTOC}" ]]; then
+  PROTOC=$(realpath protoc)
+fi
+if [ ! -f $PROTOC ]; then
+  bazel build -c opt //:protoc
+  PROTOC=$(realpath bazel-bin/protoc)
+fi
+
 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
@@ -14,8 +22,8 @@
 fi
 
 pushd src
-./protoc --php_out=internal:../php/src google/protobuf/descriptor.proto
-./protoc --php_out=internal_generate_c_wkt:../php/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 \
diff --git a/php/generate_test_protos.sh b/php/generate_test_protos.sh
index 8607499..6d06f95 100755
--- a/php/generate_test_protos.sh
+++ b/php/generate_test_protos.sh
@@ -2,19 +2,17 @@
 
 set -ex
 
-cd `dirname $0`
+cd `dirname $0`/..
 
-if ../src/protoc --help > /dev/null; then
-  PROTOC=src/protoc
-else
-  # Bazel seems to be creating a problematic symlink in
-  # _build/out/external/com_google_protobuf, so we remove the _build directory
-  # before building protoc.
-  (cd .. && bazel build -c opt :protoc)
-  PROTOC=bazel-bin/protoc
+if [[ -z "${PROTOC}" ]]; then
+  PROTOC=$(pwd)/protoc
+fi
+if [ ! -f $PROTOC ]; then
+  bazel build -c opt //:protoc
+  PROTOC=$(pwd)/bazel-bin/protoc
 fi
 
-if [[ -d tmp && -z $(find tests/proto ../$PROTOC -newer tmp) ]]; then
+if [[ -d php/tmp && -z $(find php/tests/proto $PROTOC -newer php/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
@@ -23,10 +21,9 @@
   exit 0
 fi
 
-rm -rf tmp
-mkdir -p tmp
+rm -rf php/tmp
+mkdir -p php/tmp
 
-cd ..
 find php/tests/proto -type f -name "*.proto"| xargs $PROTOC --php_out=php/tmp -Isrc -Iphp/tests
 
 if [ "$1" = "--aggregate_metadata" ]; then
diff --git a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
index d71def9..d26f517 100644
--- a/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
+++ b/php/src/GPBMetadata/Google/Protobuf/Internal/Descriptor.php
@@ -31,6 +31,7 @@
             ->optional('options', \Google\Protobuf\Internal\GPBType::MESSAGE, 8, 'google.protobuf.internal.FileOptions')
             ->optional('source_code_info', \Google\Protobuf\Internal\GPBType::MESSAGE, 9, 'google.protobuf.internal.SourceCodeInfo')
             ->optional('syntax', \Google\Protobuf\Internal\GPBType::STRING, 12)
+            ->optional('edition', \Google\Protobuf\Internal\GPBType::STRING, 13)
             ->finalizeToPool();
 
         $pool->addMessage('google.protobuf.internal.DescriptorProto', \Google\Protobuf\Internal\DescriptorProto::class)
diff --git a/php/src/Google/Protobuf/Internal/FieldOptions.php b/php/src/Google/Protobuf/Internal/FieldOptions.php
index 665cb06..ea32e7f 100644
--- a/php/src/Google/Protobuf/Internal/FieldOptions.php
+++ b/php/src/Google/Protobuf/Internal/FieldOptions.php
@@ -74,10 +74,8 @@
      * implementation must either *always* check its required fields, or *never*
      * check its required fields, regardless of whether or not the message has
      * been parsed.
-     * As of 2021, lazy does no correctness checks on the byte stream during
-     * parsing.  This may lead to crashes if and when an invalid byte stream is
-     * finally parsed upon access.
-     * TODO(b/211906113):  Enable validation on lazy fields.
+     * As of May 2022, lazy verifies the contents of the byte stream during
+     * parsing.  An invalid byte stream will cause the overall parsing to fail.
      *
      * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
      */
@@ -165,10 +163,8 @@
      *           implementation must either *always* check its required fields, or *never*
      *           check its required fields, regardless of whether or not the message has
      *           been parsed.
-     *           As of 2021, lazy does no correctness checks on the byte stream during
-     *           parsing.  This may lead to crashes if and when an invalid byte stream is
-     *           finally parsed upon access.
-     *           TODO(b/211906113):  Enable validation on lazy fields.
+     *           As of May 2022, lazy verifies the contents of the byte stream during
+     *           parsing.  An invalid byte stream will cause the overall parsing to fail.
      *     @type bool $unverified_lazy
      *           unverified_lazy does no correctness checks on the byte stream. This should
      *           only be used where lazy with verification is prohibitive for performance
@@ -354,10 +350,8 @@
      * implementation must either *always* check its required fields, or *never*
      * check its required fields, regardless of whether or not the message has
      * been parsed.
-     * As of 2021, lazy does no correctness checks on the byte stream during
-     * parsing.  This may lead to crashes if and when an invalid byte stream is
-     * finally parsed upon access.
-     * TODO(b/211906113):  Enable validation on lazy fields.
+     * As of May 2022, lazy verifies the contents of the byte stream during
+     * parsing.  An invalid byte stream will cause the overall parsing to fail.
      *
      * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
      * @return bool
@@ -402,10 +396,8 @@
      * implementation must either *always* check its required fields, or *never*
      * check its required fields, regardless of whether or not the message has
      * been parsed.
-     * As of 2021, lazy does no correctness checks on the byte stream during
-     * parsing.  This may lead to crashes if and when an invalid byte stream is
-     * finally parsed upon access.
-     * TODO(b/211906113):  Enable validation on lazy fields.
+     * As of May 2022, lazy verifies the contents of the byte stream during
+     * parsing.  An invalid byte stream will cause the overall parsing to fail.
      *
      * Generated from protobuf field <code>optional bool lazy = 5 [default = false];</code>
      * @param bool $var
diff --git a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
index 5ba7db6..d4c7f6b 100644
--- a/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
+++ b/php/src/Google/Protobuf/Internal/FileDescriptorProto.php
@@ -81,11 +81,18 @@
     protected $source_code_info = null;
     /**
      * The syntax of the proto file.
-     * The supported values are "proto2" and "proto3".
+     * The supported values are "proto2", "proto3", and "editions".
+     * If `edition` is present, this value must be "editions".
      *
      * Generated from protobuf field <code>optional string syntax = 12;</code>
      */
     protected $syntax = null;
+    /**
+     * The edition of the proto file, which is an opaque string.
+     *
+     * Generated from protobuf field <code>optional string edition = 13;</code>
+     */
+    protected $edition = null;
 
     /**
      * Constructor.
@@ -117,7 +124,10 @@
      *           development tools.
      *     @type string $syntax
      *           The syntax of the proto file.
-     *           The supported values are "proto2" and "proto3".
+     *           The supported values are "proto2", "proto3", and "editions".
+     *           If `edition` is present, this value must be "editions".
+     *     @type string $edition
+     *           The edition of the proto file, which is an opaque string.
      * }
      */
     public function __construct($data = NULL) {
@@ -445,7 +455,8 @@
 
     /**
      * The syntax of the proto file.
-     * The supported values are "proto2" and "proto3".
+     * The supported values are "proto2", "proto3", and "editions".
+     * If `edition` is present, this value must be "editions".
      *
      * Generated from protobuf field <code>optional string syntax = 12;</code>
      * @return string
@@ -467,7 +478,8 @@
 
     /**
      * The syntax of the proto file.
-     * The supported values are "proto2" and "proto3".
+     * The supported values are "proto2", "proto3", and "editions".
+     * If `edition` is present, this value must be "editions".
      *
      * Generated from protobuf field <code>optional string syntax = 12;</code>
      * @param string $var
@@ -481,5 +493,41 @@
         return $this;
     }
 
+    /**
+     * The edition of the proto file, which is an opaque string.
+     *
+     * Generated from protobuf field <code>optional string edition = 13;</code>
+     * @return string
+     */
+    public function getEdition()
+    {
+        return isset($this->edition) ? $this->edition : '';
+    }
+
+    public function hasEdition()
+    {
+        return isset($this->edition);
+    }
+
+    public function clearEdition()
+    {
+        unset($this->edition);
+    }
+
+    /**
+     * The edition of the proto file, which is an opaque string.
+     *
+     * Generated from protobuf field <code>optional string edition = 13;</code>
+     * @param string $var
+     * @return $this
+     */
+    public function setEdition($var)
+    {
+        GPBUtil::checkString($var, True);
+        $this->edition = $var;
+
+        return $this;
+    }
+
 }
 
diff --git a/php/src/Google/Protobuf/Internal/Message.php b/php/src/Google/Protobuf/Internal/Message.php
index 1d1fbf2..f412b41 100644
--- a/php/src/Google/Protobuf/Internal/Message.php
+++ b/php/src/Google/Protobuf/Internal/Message.php
@@ -54,6 +54,7 @@
  * or extend this class or its child classes by their own.  See the comment of
  * specific functions for more details.
  */
+#[\AllowDynamicProperties]
 class Message
 {
 
@@ -1980,8 +1981,12 @@
                 $size += 9;
                 $size += $value_msg->jsonByteSize();
             } else {
-                // Size for value. +1 for comma, -2 for "{}".
-                $size += $value_msg->jsonByteSize() -1;
+                $value_size = $value_msg->jsonByteSize();
+                // size === 2 it's empty message {} which is not serialized inside any
+                if ($value_size !== 2) {
+                    // Size for value. +1 for comma, -2 for "{}".
+                    $size += $value_size -1;
+                }
             }
         } elseif (get_class($this) === 'Google\Protobuf\FieldMask') {
             $field_mask = GPBUtil::formatFieldMask($this);
diff --git a/php/src/Google/Protobuf/Internal/MessageOptions.php b/php/src/Google/Protobuf/Internal/MessageOptions.php
index 5c61580..96e6f52 100644
--- a/php/src/Google/Protobuf/Internal/MessageOptions.php
+++ b/php/src/Google/Protobuf/Internal/MessageOptions.php
@@ -53,6 +53,9 @@
      */
     protected $deprecated = null;
     /**
+     * NOTE: Do not set the option in .proto files. Always use the maps syntax
+     * instead. The option should only be implicitly set by the proto compiler
+     * parser.
      * Whether the message is an automatically generated map entry type for the
      * maps field.
      * For maps fields:
@@ -68,9 +71,6 @@
      * use a native map in the target language to hold the keys and values.
      * The reflection APIs in such implementations still need to work as
      * if the field is a repeated message field.
-     * NOTE: Do not set the option in .proto files. Always use the maps syntax
-     * instead. The option should only be implicitly set by the proto compiler
-     * parser.
      *
      * Generated from protobuf field <code>optional bool map_entry = 7;</code>
      */
@@ -114,6 +114,9 @@
      *           for the message, or it will be completely ignored; in the very least,
      *           this is a formalization for deprecating messages.
      *     @type bool $map_entry
+     *           NOTE: Do not set the option in .proto files. Always use the maps syntax
+     *           instead. The option should only be implicitly set by the proto compiler
+     *           parser.
      *           Whether the message is an automatically generated map entry type for the
      *           maps field.
      *           For maps fields:
@@ -129,9 +132,6 @@
      *           use a native map in the target language to hold the keys and values.
      *           The reflection APIs in such implementations still need to work as
      *           if the field is a repeated message field.
-     *           NOTE: Do not set the option in .proto files. Always use the maps syntax
-     *           instead. The option should only be implicitly set by the proto compiler
-     *           parser.
      *     @type array<\Google\Protobuf\Internal\UninterpretedOption>|\Google\Protobuf\Internal\RepeatedField $uninterpreted_option
      *           The parser stores options it doesn't recognize here. See above.
      * }
@@ -288,6 +288,9 @@
     }
 
     /**
+     * NOTE: Do not set the option in .proto files. Always use the maps syntax
+     * instead. The option should only be implicitly set by the proto compiler
+     * parser.
      * Whether the message is an automatically generated map entry type for the
      * maps field.
      * For maps fields:
@@ -303,9 +306,6 @@
      * use a native map in the target language to hold the keys and values.
      * The reflection APIs in such implementations still need to work as
      * if the field is a repeated message field.
-     * NOTE: Do not set the option in .proto files. Always use the maps syntax
-     * instead. The option should only be implicitly set by the proto compiler
-     * parser.
      *
      * Generated from protobuf field <code>optional bool map_entry = 7;</code>
      * @return bool
@@ -326,6 +326,9 @@
     }
 
     /**
+     * NOTE: Do not set the option in .proto files. Always use the maps syntax
+     * instead. The option should only be implicitly set by the proto compiler
+     * parser.
      * Whether the message is an automatically generated map entry type for the
      * maps field.
      * For maps fields:
@@ -341,9 +344,6 @@
      * use a native map in the target language to hold the keys and values.
      * The reflection APIs in such implementations still need to work as
      * if the field is a repeated message field.
-     * NOTE: Do not set the option in .proto files. Always use the maps syntax
-     * instead. The option should only be implicitly set by the proto compiler
-     * parser.
      *
      * Generated from protobuf field <code>optional bool map_entry = 7;</code>
      * @param bool $var
diff --git a/php/tests/EncodeDecodeTest.php b/php/tests/EncodeDecodeTest.php
index 33d8da1..70748e1 100644
--- a/php/tests/EncodeDecodeTest.php
+++ b/php/tests/EncodeDecodeTest.php
@@ -5,6 +5,7 @@
 
 use Google\Protobuf\RepeatedField;
 use Google\Protobuf\GPBType;
+use Foo\EmptyAnySerialization;
 use Foo\TestInt32Value;
 use Foo\TestInt64Value;
 use Foo\TestUInt32Value;
@@ -1513,4 +1514,22 @@
             [TestStringValue::class, "a", "\"a\"", "", "\"\""],
         ];
     }
+
+    public function testEmptyAnySerialization()
+    {
+        $m = new EmptyAnySerialization();
+
+        $any = new Any();
+        $any->pack($m);
+
+        $data = $any->serializeToJsonString();
+        $this->assertEquals('{"@type":"type.googleapis.com/foo.EmptyAnySerialization"}', $data);
+
+        $any = new Any();
+        $any->mergeFromJsonString($data);
+
+        $m = $any->unpack();
+        $this->assertInstanceOf(EmptyAnySerialization::class, $m);
+        $this->assertEquals('', $m->getA());
+    }
 }
diff --git a/php/tests/PhpImplementationTest.php b/php/tests/PhpImplementationTest.php
index 7187315..38c628d 100644
--- a/php/tests/PhpImplementationTest.php
+++ b/php/tests/PhpImplementationTest.php
@@ -275,13 +275,13 @@
             $this->assertSame(0x7FFFFFFE, GPBWire::zigZagEncode64(0x3FFFFFFF));
             $this->assertSame(
                 0x7FFFFFFF,
-                GPBWire::zigZagEncode64(0xFFFFFFFFC0000000));
+                GPBWire::zigZagEncode64(-1073741824));  // 0xFFFFFFFFC0000000
             $this->assertSame(
                 0xFFFFFFFE,
                 GPBWire::zigZagEncode64(0x7FFFFFFF));
             $this->assertSame(
                 0xFFFFFFFF,
-                GPBWire::zigZagEncode64(0xFFFFFFFF80000000));
+                GPBWire::zigZagEncode64(-2147483648));  // 0xFFFFFFFF80000000
             $this->assertSame(
                 -2,  // 0xFFFFFFFFFFFFFFFE
                 GPBWire::zigZagEncode64(0x7FFFFFFFFFFFFFFF));
diff --git a/php/tests/compatibility_test.sh b/php/tests/compatibility_test.sh
deleted file mode 100755
index 7e44cce..0000000
--- a/php/tests/compatibility_test.sh
+++ /dev/null
@@ -1,152 +0,0 @@
-#!/bin/bash
-
-function generate_proto() {
-  PROTOC1=$1
-  PROTOC2=$2
-
-  rm -rf generated
-  mkdir generated
-
-  $PROTOC1 --php_out=generated proto/test_include.proto
-  $PROTOC2 --php_out=generated                 \
-    -I../../src -I.                            \
-    proto/empty/echo.proto                     \
-    proto/test.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
-  $PROTOC2 --php_out=../php/tests/generated -I../php/tests -I. ../php/tests/proto/test_import_descriptor_proto.proto
-  popd
-}
-
-# Remove tests to expect error. These were added to API tests by mistake.
-function remove_error_test() {
-  local TEMPFILE=`tempfile`
-  cat $1 | \
-  awk -v file=`basename $1` -v dir=`basename $(dirname $1)` '
-    BEGIN {
-      show = 1
-    }
-    /@expectedException PHPUnit_Framework_Error/ { show = 0; next; }
-    / *\*\//                                     { print; next; }
-    / *}/ {
-      if (!show) {
-        show = 1;
-        next;
-      }
-    }
-    show { print }
-  ' > $TEMPFILE
-  cp $TEMPFILE $1
-}
-
-set -ex
-
-# Change to the script's directory.
-cd $(dirname $0)
-
-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 "PHP_PROTOBUF_VERSION" ../ext/google/protobuf/protobuf.h | sed "s|#define PHP_PROTOBUF_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
-}
-
-# Download old test.
-rm -rf protobuf
-git clone https://github.com/protocolbuffers/protobuf.git
-pushd protobuf
-git checkout v$OLD_VERSION
-popd
-
-# Build and copy the new runtime
-pushd ../ext/google/protobuf
-make clean || true
-phpize && ./configure && make
-popd
-
-rm -rf protobuf/php/ext
-rm -rf protobuf/php/src
-cp -r ../ext protobuf/php/ext/
-cp -r ../src protobuf/php/src/
-
-# Download old version protoc compiler (for linux)
-wget $OLD_VERSION_PROTOC -O old_protoc
-chmod +x old_protoc
-
-NEW_PROTOC=`pwd`/../../src/protoc
-OLD_PROTOC=`pwd`/old_protoc
-cd protobuf/php
-composer install
-
-# Remove implementation detail tests.
-# 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
-sed -i.bak 's/PHPUnit_Framework_TestCase/\\PHPUnit\\Framework\\TestCase/g' tests/map_field_test.php
-sed -i.bak 's/PHPUnit_Framework_TestCase/\\PHPUnit\\Framework\\TestCase/g' tests/test_base.php
-for t in "${tests[@]}"
-do
-  remove_error_test tests/$t
-done
-
-cd tests
-
-# Test A.1:
-#   proto set 1: use old version
-#   proto set 2 which may import protos in set 1: use old version
-generate_proto $OLD_PROTOC $OLD_PROTOC
-./test.sh
-pushd ..
-./vendor/bin/phpunit
-popd
-
-# Test A.2:
-#   proto set 1: use new version
-#   proto set 2 which may import protos in set 1: use old version
-generate_proto $NEW_PROTOC $OLD_PROTOC
-./test.sh
-pushd ..
-./vendor/bin/phpunit
-popd
-
-# Test A.3:
-#   proto set 1: use old version
-#   proto set 2 which may import protos in set 1: use new version
-generate_proto $OLD_PROTOC $NEW_PROTOC
-./test.sh
-pushd ..
-./vendor/bin/phpunit
-popd
diff --git a/php/tests/compile_extension.sh b/php/tests/compile_extension.sh
index 3261917..a645ed6 100755
--- a/php/tests/compile_extension.sh
+++ b/php/tests/compile_extension.sh
@@ -1,15 +1,18 @@
 #!/bin/bash
 
-set -e
+set -ex
 
 cd $(dirname $0)/..
 
+# Pull in dependencies.
+git submodule update --init --recursive
+
 # utf8_range 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/utf8_range
-cp ../third_party/utf8_range/* ext/google/protobuf/third_party/utf8_range
+cp -r ../third_party/utf8_range/* ext/google/protobuf/third_party/utf8_range
 
 echo "Copied utf8_range from ../third_party -> ext/google/protobuf/third_party"
 
diff --git a/php/tests/proto/test.proto b/php/tests/proto/test.proto
index 421292a..4217800 100644
--- a/php/tests/proto/test.proto
+++ b/php/tests/proto/test.proto
@@ -168,6 +168,10 @@
   int32 a = 1;
 }
 
+message EmptyAnySerialization {
+  string a = 1;
+}
+
 message TestPackedMessage {
   repeated int32    repeated_int32    = 90  [packed = true];
   repeated int64    repeated_int64    = 91  [packed = true];
diff --git a/pkg/BUILD.bazel b/pkg/BUILD.bazel
index ecce255..934e785 100644
--- a/pkg/BUILD.bazel
+++ b/pkg/BUILD.bazel
@@ -7,7 +7,7 @@
     "strip_prefix",
 )
 load("//:protobuf_release.bzl", "package_naming")
-load(":build_systems.bzl", "gen_automake_file_lists", "gen_file_lists")
+load(":build_systems.bzl", "gen_file_lists")
 load(":cc_dist_library.bzl", "cc_dist_library")
 
 package_naming(
@@ -17,17 +17,8 @@
 pkg_files(
     name = "wkt_protos_files",
     srcs = [
-        "//:src/google/protobuf/any.proto",
-        "//:src/google/protobuf/api.proto",
-        "//:src/google/protobuf/descriptor.proto",
-        "//:src/google/protobuf/duration.proto",
-        "//:src/google/protobuf/empty.proto",
-        "//:src/google/protobuf/field_mask.proto",
-        "//:src/google/protobuf/source_context.proto",
-        "//:src/google/protobuf/struct.proto",
-        "//:src/google/protobuf/timestamp.proto",
-        "//:src/google/protobuf/type.proto",
-        "//:src/google/protobuf/wrappers.proto",
+        "//:well_known_type_protos",
+        "//src/google/protobuf:descriptor_proto_srcs",
     ],
     prefix = "include/google/protobuf",
     visibility = ["//visibility:private"],
@@ -35,7 +26,9 @@
 
 pkg_files(
     name = "compiler_plugin_protos_files",
-    srcs = ["//:src/google/protobuf/compiler/plugin.proto"],
+    srcs = [
+        "//src/google/protobuf/compiler:compiler_plugin_protos_files",
+    ],
     prefix = "include/google/protobuf/compiler",
     visibility = ["//visibility:private"],
 )
@@ -95,10 +88,10 @@
     srcs = [
         ":dist_files",
         "//:common_dist_files",
-        "//:cpp_dist_files",  # to build protoc
-        "//benchmarks:all_dist_files",
         "//build_defs:dist_files",
         "//conformance:all_dist_files",
+        "//src:all_dist_files",
+        "//third_party/utf8_range:dist_files",
         "@com_google_protobuf_examples//:dist_files",
     ],
 )
@@ -107,7 +100,7 @@
     name = "cpp_srcs",
     srcs = [
         ":dist_common",
-        "//:cpp_dist_files",
+        "//src:all_dist_files",
     ],
 )
 
@@ -229,7 +222,7 @@
     name = "python_srcs",
     srcs = [
         ":dist_common",
-        "//:python_dist_files",
+        "//python:dist_files",
     ],
 )
 
@@ -311,30 +304,31 @@
     testonly = 1,
     out_stem = "src_file_lists",
     src_libs = {
-        # source rule: name in generated file
-        "//:protobuf": "libprotobuf",
-        "//:protoc_lib": "libprotoc",
-        "//:protobuf_lite": "libprotobuf_lite",
-    },
-)
-
-gen_automake_file_lists(
-    name = "gen_automake_extra_dist_lists",
-    testonly = 1,
-    out = "extra_dist_file_lists.am",
-    src_libs = {
-        # source rule: name in generated file
-        "//:common_dist_files": "dist_common",
-        "//conformance:dist_files": "dist_conformance",
-        "//benchmarks:all_dist_files": "dist_benchmark",
-        "@com_google_protobuf_examples//:dist_files": "dist_example",
-        "//:csharp_dist_files": "dist_csharp",
-        "//csharp:dist_files": "dist_csharp2",
-        "//:objectivec_dist_files": "dist_objectivec",
-        "//objectivec:dist_files": "dist_objectivec2",
-        "//php:dist_files": "dist_php",
-        "//:python_dist_files": "dist_python",
-        "//ruby:dist_files": "dist_ruby",
+        # {[source rule]: [name in generated file]}
+        # Libraries:
+        ":protobuf": "libprotobuf",
+        ":protobuf_lite": "libprotobuf_lite",
+        ":protoc": "libprotoc",
+        # Protos:
+        "//src/google/protobuf:well_known_type_protos": "wkt_protos",
+        "//src/google/protobuf:descriptor_proto": "descriptor_proto",
+        "//src/google/protobuf/compiler:plugin_proto": "plugin_proto",
+        # Test libraries:
+        ":common_test": "common_test",
+        ":lite_test_util": "lite_test_util",
+        ":test_util": "test_util",
+        # Tests and test-only protos:
+        "//src/google/protobuf:full_test_srcs": "protobuf_test",
+        "//src/google/protobuf:test_proto_srcs": "protobuf_test_protos",
+        "//src/google/protobuf:lite_test_srcs": "protobuf_lite_test",
+        "//src/google/protobuf:lite_test_proto_srcs": "protobuf_lite_test_protos",
+        "//src/google/protobuf/compiler:test_srcs": "compiler_test",
+        "//src/google/protobuf/compiler:test_proto_srcs": "compiler_test_protos",
+        "//src/google/protobuf/compiler:test_plugin_srcs": "test_plugin",
+        "//src/google/protobuf/io:test_srcs": "io_test",
+        "//src/google/protobuf/util:test_srcs": "util_test",
+        "//src/google/protobuf/util:test_proto_srcs": "util_test_protos",
+        "//src/google/protobuf/stubs:test_srcs": "stubs_test",
     },
 )
 
@@ -348,8 +342,10 @@
         "//build_defs:config_msvc": [],
         "//conditions:default": ["-lpthread"],
     }),
+    tags = ["manual"],
     deps = [
-        "//:protobuf_lite",
+        "//src/google/protobuf:arena_align",
+        "//src/google/protobuf:protobuf_lite",
     ],
 )
 
@@ -362,9 +358,81 @@
             "-lpthread",
         ],
     }),
+    tags = ["manual"],
     deps = [
-        "//:protobuf",
-        "//:protobuf_lite",
+        "//src/google/protobuf:arena_align",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf:wkt_cc_proto",
+        "//src/google/protobuf/compiler:importer",
+        "//src/google/protobuf/json",
+        "//src/google/protobuf/util:delimited_message_util",
+        "//src/google/protobuf/util:differencer",
+        "//src/google/protobuf/util:field_mask_util",
+        "//src/google/protobuf/util:json_util",
+        "//src/google/protobuf/util:time_util",
+        "//src/google/protobuf/util:type_resolver_util",
+    ],
+)
+
+cc_dist_library(
+    name = "protoc",
+    tags = ["manual"],
+    deps = [
+        "//src/google/protobuf/compiler:command_line_interface",
+        "//src/google/protobuf/compiler/cpp",
+        "//src/google/protobuf/compiler/csharp",
+        "//src/google/protobuf/compiler/java",
+        "//src/google/protobuf/compiler/objectivec",
+        "//src/google/protobuf/compiler/php",
+        "//src/google/protobuf/compiler/python",
+        "//src/google/protobuf/compiler/ruby",
+    ],
+    dist_deps = [
+        ":protobuf",
+        ":protobuf_lite",
+    ],
+)
+
+cc_dist_library(
+    name = "lite_test_util",
+    testonly = 1,
+    tags = ["manual"],
+    deps = ["//src/google/protobuf:lite_test_util"],
+    dist_deps = [":protobuf_lite"],
+)
+
+cc_dist_library(
+    name = "test_util",
+    testonly = 1,
+    tags = ["manual"],
+    deps = [
+        "//src/google/protobuf:lite_test_util",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf:test_util2",
+        "//src/google/protobuf/compiler:annotation_test_util",
+        "//src/google/protobuf/compiler/cpp:unittest_lib",
+    ],
+    dist_deps = [
+      ":common_test",
+      ":lite_test_util",
+      ":protoc",
+      ":protobuf",
+      ":protobuf_lite",
+    ],
+)
+
+cc_dist_library(
+    name = "common_test",
+    testonly = 1,
+    tags = ["manual"],
+    deps = [
+        "//src/google/protobuf/compiler:mock_code_generator",
+        "//src/google/protobuf/testing",
+    ],
+    dist_deps = [
+        ":protobuf",
+        ":protobuf_lite",
+        ":protoc",
     ],
 )
 
diff --git a/pkg/build_systems.bzl b/pkg/build_systems.bzl
index 753d285..c1369c7 100644
--- a/pkg/build_systems.bzl
+++ b/pkg/build_systems.bzl
@@ -1,6 +1,7 @@
 # Starlark utilities for working with other build systems
 
 load("@rules_pkg//:providers.bzl", "PackageFilegroupInfo", "PackageFilesInfo")
+load(":cc_dist_library.bzl", "CcFileList")
 
 ################################################################################
 # Macro to create CMake and Automake source lists.
@@ -13,39 +14,18 @@
         source_prefix = "${protobuf_SOURCE_DIR}/",
         **kwargs
     )
-    gen_automake_file_lists(
-        name = name + "_automake",
-        out = out_stem + ".am",
-        source_prefix = "$(top_srcdir)/",
-        **kwargs
-    )
     native.filegroup(
         name = name,
         srcs = [
             out_stem + ".cmake",
-            out_stem + ".am",
         ],
+        visibility = ["//src:__pkg__"],
     )
 
 ################################################################################
 # Aspect that extracts srcs, hdrs, etc.
 ################################################################################
 
-CcFileList = provider(
-    doc = "List of files to be built into a library.",
-    fields = {
-        # As a rule of thumb, `hdrs` and `textual_hdrs` are the files that
-        # would be installed along with a prebuilt library.
-        "hdrs": "public header files, including those used by generated code",
-        "textual_hdrs": "files which are included but are not self-contained",
-
-        # The `internal_hdrs` are header files which appear in `srcs`.
-        # These are only used when compiling the library.
-        "internal_hdrs": "internal header files (only used to build .cc files)",
-        "srcs": "source files",
-    },
-)
-
 ProtoFileList = provider(
     doc = "List of proto files and generated code to be built into a library.",
     fields = {
@@ -65,56 +45,11 @@
             files.append(tfile)
     return files
 
-def _combine_cc_file_lists(file_lists):
-    hdrs = {}
-    textual_hdrs = {}
-    internal_hdrs = {}
-    srcs = {}
-    for file_list in file_lists:
-        hdrs.update({f: 1 for f in file_list.hdrs})
-        textual_hdrs.update({f: 1 for f in file_list.textual_hdrs})
-        internal_hdrs.update({f: 1 for f in file_list.internal_hdrs})
-        srcs.update({f: 1 for f in file_list.srcs})
-    return CcFileList(
-        hdrs = sorted(hdrs.keys()),
-        textual_hdrs = sorted(textual_hdrs.keys()),
-        internal_hdrs = sorted(internal_hdrs.keys()),
-        srcs = sorted(srcs.keys()),
-    )
-
 def _file_list_aspect_impl(target, ctx):
     # We're going to reach directly into the attrs on the traversed rule.
     rule_attr = ctx.rule.attr
     providers = []
 
-    # Extract sources from a `cc_library` (or similar):
-    if CcInfo in target:
-        # CcInfo is a proxy for what we expect this rule to look like.
-        # However, some deps may expose `CcInfo` without having `srcs`,
-        # `hdrs`, etc., so we use `getattr` to handle that gracefully.
-
-        internal_hdrs = []
-        srcs = []
-
-        # Filter `srcs` so it only contains source files. Headers will go
-        # into `internal_headers`.
-        for src in _flatten_target_files(getattr(rule_attr, "srcs", [])):
-            if src.extension.lower() in ["c", "cc", "cpp", "cxx"]:
-                srcs.append(src)
-            else:
-                internal_hdrs.append(src)
-
-        providers.append(CcFileList(
-            hdrs = _flatten_target_files(getattr(rule_attr, "hdrs", [])),
-            textual_hdrs = _flatten_target_files(getattr(
-                rule_attr,
-                "textual_hdrs",
-                [],
-            )),
-            internal_hdrs = internal_hdrs,
-            srcs = srcs,
-        ))
-
     # Extract sources from a `proto_library`:
     if ProtoInfo in target:
         proto_srcs = []
@@ -178,7 +113,7 @@
 # fragment generator function.
 ################################################################################
 
-def _create_file_list_impl(fragment_generator):
+def _create_file_list_impl(ctx, fragment_generator):
     # `fragment_generator` is a function like:
     #     def fn(originating_rule: Label,
     #            varname: str,
@@ -191,92 +126,98 @@
     # When dealing with `File` objects, the `short_path` is used to strip
     # the output prefix for generated files.
 
-    def _impl(ctx):
-        out = ctx.outputs.out
+    out = ctx.outputs.out
 
-        fragments = []
-        for srcrule, libname in ctx.attr.src_libs.items():
-            if CcFileList in srcrule:
-                cc_file_list = srcrule[CcFileList]
-                fragments.extend([
-                    fragment_generator(
-                        srcrule.label,
-                        libname + "_srcs",
-                        ctx.attr.source_prefix,
-                        [f.short_path for f in cc_file_list.srcs],
-                    ),
-                    fragment_generator(
-                        srcrule.label,
-                        libname + "_hdrs",
-                        ctx.attr.source_prefix,
-                        [f.short_path for f in (cc_file_list.hdrs +
-                                                cc_file_list.textual_hdrs)],
-                    ),
-                ])
+    fragments = []
+    for srcrule, libname in ctx.attr.src_libs.items():
+        if CcFileList in srcrule:
+            cc_file_list = srcrule[CcFileList]
 
-            if ProtoFileList in srcrule:
-                proto_file_list = srcrule[ProtoFileList]
-                fragments.extend([
-                    fragment_generator(
-                        srcrule.label,
-                        libname + "_proto_srcs",
-                        ctx.attr.source_prefix,
-                        [f.short_path for f in proto_file_list.proto_srcs],
-                    ),
-                    fragment_generator(
-                        srcrule.label,
-                        libname + "_srcs",
-                        ctx.attr.source_prefix,
-                        proto_file_list.srcs,
-                    ),
-                    fragment_generator(
-                        srcrule.label,
-                        libname + "_hdrs",
-                        ctx.attr.source_prefix,
-                        proto_file_list.hdrs,
-                    ),
-                ])
+            # Turn depsets of files into sorted lists.
+            srcs = sorted(cc_file_list.srcs.to_list())
+            hdrs = sorted(
+                depset(transitive = [
+                    cc_file_list.textual_hdrs,
+                    cc_file_list.hdrs,
+                ]).to_list(),
+            )
 
-            files = {}
+            fragments.extend([
+                fragment_generator(
+                    srcrule.label,
+                    libname + "_srcs",
+                    ctx.attr.source_prefix,
+                    [f.short_path for f in srcs],
+                ),
+                fragment_generator(
+                    srcrule.label,
+                    libname + "_hdrs",
+                    ctx.attr.source_prefix,
+                    [f.short_path for f in hdrs],
+                ),
+            ])
 
-            if PackageFilegroupInfo in srcrule:
-                for pkg_files_info, origin in srcrule[PackageFilegroupInfo].pkg_files:
-                    # keys are the destination path:
-                    files.update(pkg_files_info.dest_src_map)
+        if ProtoFileList in srcrule:
+            proto_file_list = srcrule[ProtoFileList]
+            fragments.extend([
+                fragment_generator(
+                    srcrule.label,
+                    libname + "_proto_srcs",
+                    ctx.attr.source_prefix,
+                    [f.short_path for f in proto_file_list.proto_srcs],
+                ),
+                fragment_generator(
+                    srcrule.label,
+                    libname + "_srcs",
+                    ctx.attr.source_prefix,
+                    proto_file_list.srcs,
+                ),
+                fragment_generator(
+                    srcrule.label,
+                    libname + "_hdrs",
+                    ctx.attr.source_prefix,
+                    proto_file_list.hdrs,
+                ),
+            ])
 
-            if PackageFilesInfo in srcrule:
-                # keys are the destination:
-                files.update(srcrule[PackageFilesInfo].dest_src_map)
+        files = {}
 
-            if files == {} and DefaultInfo in srcrule and CcInfo not in srcrule:
-                # This could be an individual file or filegroup.
-                # We explicitly ignore rules with CcInfo, since their
-                # output artifacts are libraries or binaries.
-                files.update(
-                    {
-                        f.short_path: 1
-                        for f in srcrule[DefaultInfo].files.to_list()
-                    },
-                )
+        if PackageFilegroupInfo in srcrule:
+            for pkg_files_info, origin in srcrule[PackageFilegroupInfo].pkg_files:
+                # keys are the destination path:
+                files.update(pkg_files_info.dest_src_map)
 
-            if files:
-                fragments.append(
-                    fragment_generator(
-                        srcrule.label,
-                        libname + "_files",
-                        ctx.attr.source_prefix,
-                        sorted(files.keys()),
-                    ),
-                )
+        if PackageFilesInfo in srcrule:
+            # keys are the destination:
+            files.update(srcrule[PackageFilesInfo].dest_src_map)
 
-        ctx.actions.write(
-            output = out,
-            content = (ctx.attr._header % ctx.label) + "\n".join(fragments),
-        )
+        if files == {} and DefaultInfo in srcrule and CcFileList not in srcrule:
+            # This could be an individual file or filegroup.
+            # We explicitly ignore rules with CcInfo, since their
+            # output artifacts are libraries or binaries.
+            files.update(
+                {
+                    f.short_path: 1
+                    for f in srcrule[DefaultInfo].files.to_list()
+                },
+            )
 
-        return [DefaultInfo(files = depset([out]))]
+        if files:
+            fragments.append(
+                fragment_generator(
+                    srcrule.label,
+                    libname + "_files",
+                    ctx.attr.source_prefix,
+                    sorted(files.keys()),
+                ),
+            )
 
-    return _impl
+    ctx.actions.write(
+        output = out,
+        content = (ctx.attr._header % ctx.label) + "\n".join(fragments),
+    )
+
+    return [DefaultInfo(files = depset([out]))]
 
 # Common rule attrs for rules that use `_create_file_list_impl`:
 # (note that `_header` is also required)
@@ -340,9 +281,15 @@
     ).format(
         owner = owner,
         varname = varname,
-        entries = "\n".join(["  %s%s" % (prefix, f) for f in entries]),
+        # Strip out "wkt/google/protobuf/" from the well-known type file paths.
+        # This is currently necessary to allow checked-in and generated
+        # versions of the well-known type generated code to coexist.
+        entries = "\n".join(["  %s%s" % (prefix, f.replace("wkt/google/protobuf/", "")) for f in entries]),
     )
 
+def _cmake_file_list_impl(ctx):
+    _create_file_list_impl(ctx, _cmake_var_fragment)
+
 gen_cmake_file_lists = rule(
     doc = """
 Generates a CMake-syntax file with lists of files.
@@ -361,7 +308,7 @@
     {libname}_hdrs: contains syntesized paths for generated C++ headers.
 
 """,
-    implementation = _create_file_list_impl(_cmake_var_fragment),
+    implementation = _cmake_file_list_impl,
     attrs = dict(
         _source_list_common_attrs,
         _header = attr.string(
@@ -381,72 +328,3 @@
         ),
     ),
 )
-
-################################################################################
-# Automake source lists generation
-################################################################################
-
-def _automake_var_fragment(owner, varname, prefix, entries):
-    """Returns a single variable assignment fragment (Automake syntax).
-
-    Args:
-      owner: Label, the rule that owns these srcs.
-      varname: str, the var name to set.
-      prefix: str, prefix to prepend to each of `entries`.
-      entries: [str], the entries in the list.
-
-    Returns:
-      A string.
-    """
-    if len(entries) == 0:
-        # A backslash followed by a blank line is illegal. We still want
-        # to emit the variable, though.
-        return "# {owner}\n{varname} =\n".format(
-            owner = owner,
-            varname = varname,
-        )
-    fragment = (
-        "# {owner}\n" +
-        "{varname} = \\\n" +
-        "{entries}"
-    ).format(
-        owner = owner,
-        varname = varname,
-        entries = " \\\n".join(["  %s%s" % (prefix, f) for f in entries]),
-    )
-    return fragment.rstrip("\\ ") + "\n"
-
-gen_automake_file_lists = rule(
-    doc = """
-Generates an Automake-syntax file with lists of files.
-
-The generated file defines variables with lists of files from `srcs`. The
-intent is for these files to be included from a non-generated Makefile.am
-file which actually defines the libraries based on these lists.
-
-For C++ rules, the following are generated:
-    {libname}_srcs: contains srcs.
-    {libname}_hdrs: contains hdrs and textual_hdrs.
-
-For proto_library, the following are generated:
-    {libname}_proto_srcs: contains the srcs from the `proto_library` rule.
-    {libname}_srcs: contains syntesized paths for generated C++ sources.
-    {libname}_hdrs: contains syntesized paths for generated C++ headers.
-
-""",
-    implementation = _create_file_list_impl(_automake_var_fragment),
-    attrs = dict(
-        _source_list_common_attrs.items(),
-        _header = attr.string(
-            default = """\
-# Auto-generated by %s
-#
-# This file contains lists of sources based on Bazel rules. It should
-# be included from a hand-written Makefile.am that defines targets.
-#
-# Changes to this file will be overwritten based on Bazel definitions.
-
-""",
-        ),
-    ),
-)
diff --git a/pkg/cc_dist_library.bzl b/pkg/cc_dist_library.bzl
index 654fb73..42553ca 100644
--- a/pkg/cc_dist_library.bzl
+++ b/pkg/cc_dist_library.bzl
@@ -3,12 +3,32 @@
 load("@rules_cc//cc:action_names.bzl", cc_action_names = "ACTION_NAMES")
 load("@rules_cc//cc:find_cc_toolchain.bzl", "find_cc_toolchain")
 
+################################################################################
+# Archive/linking support
+################################################################################
+
+def _collect_linker_input_objects(dep_label, cc_info, objs, pic_objs):
+    """Accumulate .o and .pic.o files into `objs` and `pic_objs`."""
+    link_ctx = cc_info.linking_context
+    if link_ctx == None:
+        return
+
+    linker_inputs = link_ctx.linker_inputs.to_list()
+    for link_input in linker_inputs:
+        if link_input.owner != dep_label:
+            # This is a transitive dep: skip it.
+            continue
+
+        for lib in link_input.libraries:
+            objs.extend(lib.objects or [])
+            pic_objs.extend(lib.pic_objects or [])
+
 # Creates an action to build the `output_file` static library (archive)
 # using `object_files`.
 def _create_archive_action(
         ctx,
         feature_configuration,
-        cc_toolchain,
+        cc_toolchain_info,
         output_file,
         object_files):
     # Based on Bazel's src/main/starlark/builtins_bzl/common/cc/cc_import.bzl:
@@ -16,7 +36,7 @@
     # Build the command line and add args for all of the input files:
     archiver_variables = cc_common.create_link_variables(
         feature_configuration = feature_configuration,
-        cc_toolchain = cc_toolchain,
+        cc_toolchain = cc_toolchain_info,
         output_file = output_file.path,
         is_using_linker = False,
     )
@@ -48,80 +68,23 @@
         inputs = depset(
             direct = object_files,
             transitive = [
-                cc_toolchain.all_files,
+                cc_toolchain_info.all_files,
             ],
         ),
-        use_default_shell_env = True,
+        use_default_shell_env = False,
         outputs = [output_file],
         mnemonic = "CppArchiveDist",
     )
 
-# Implementation for cc_dist_library rule.
-def _cc_dist_library_impl(ctx):
-    cc_toolchain_info = find_cc_toolchain(ctx)
-    if cc_toolchain_info.ar_executable == None:
-        return []
-
-    feature_configuration = cc_common.configure_features(
-        ctx = ctx,
-        cc_toolchain = cc_toolchain_info,
-    )
-
-    # Collect the set of object files from the immediate deps.
-
-    objs = []
-    pic_objs = []
-    for dep in ctx.attr.deps:
-        if CcInfo not in dep:
-            continue
-
-        link_ctx = dep[CcInfo].linking_context
-        if link_ctx == None:
-            continue
-
-        linker_inputs = link_ctx.linker_inputs.to_list()
-        for link_input in linker_inputs:
-            if link_input.owner != dep.label:
-                # This is a transitive dep: skip it.
-                continue
-
-            for lib in link_input.libraries:
-                objs.extend(lib.objects or [])
-                pic_objs.extend(lib.pic_objects or [])
-
-    # For static libraries, build separately with and without pic.
-
-    stemname = "lib" + ctx.label.name
-    outputs = []
-
-    if len(objs) > 0:
-        archive_out = ctx.actions.declare_file(stemname + ".a")
-        _create_archive_action(
-            ctx,
-            feature_configuration,
-            cc_toolchain_info,
-            archive_out,
-            objs,
-        )
-        outputs.append(archive_out)
-
-    if len(pic_objs) > 0:
-        pic_archive_out = ctx.actions.declare_file(stemname + ".pic.a")
-        _create_archive_action(
-            ctx,
-            feature_configuration,
-            cc_toolchain_info,
-            pic_archive_out,
-            pic_objs,
-        )
-        outputs.append(pic_archive_out)
-
-    # For dynamic libraries, use the `cc_common.link` command to ensure
-    # everything gets built correctly according to toolchain definitions.
-
+def _create_dso_link_action(
+        ctx,
+        feature_configuration,
+        cc_toolchain_info,
+        object_files,
+        pic_object_files):
     compilation_outputs = cc_common.create_compilation_outputs(
-        objects = depset(objs),
-        pic_objects = depset(pic_objs),
+        objects = depset(object_files),
+        pic_objects = depset(pic_object_files),
     )
     link_output = cc_common.link(
         actions = ctx.actions,
@@ -134,6 +97,8 @@
     )
     library_to_link = link_output.library_to_link
 
+    outputs = []
+
     # Note: library_to_link.dynamic_library and interface_library are often
     # symlinks in the solib directory. For DefaultInfo, prefer reporting
     # the resolved artifact paths.
@@ -147,6 +112,241 @@
     elif library_to_link.interface_library != None:
         outputs.append(library_to_link.interface_library)
 
+    return outputs
+
+################################################################################
+# Source file/header support
+################################################################################
+
+CcFileList = provider(
+    doc = "List of files to be built into a library.",
+    fields = {
+        # As a rule of thumb, `hdrs` and `textual_hdrs` are the files that
+        # would be installed along with a prebuilt library.
+        "hdrs": "public header files, including those used by generated code",
+        "textual_hdrs": "files which are included but are not self-contained",
+
+        # The `internal_hdrs` are header files which appear in `srcs`.
+        # These are only used when compiling the library.
+        "internal_hdrs": "internal header files (only used to build .cc files)",
+        "srcs": "source files",
+    },
+)
+
+def _flatten_target_files(targets):
+    return depset(transitive = [
+        target.files
+        for target in targets
+        # Filter out targets from external workspaces
+        if target.label.workspace_name == "" or
+           target.label.workspace_name == "com_google_protobuf"
+    ])
+
+def _get_transitive_sources(targets, attr, deps):
+    return depset(targets, transitive = [getattr(dep[CcFileList], attr) for dep in deps if CcFileList in dep])
+
+def _cc_file_list_aspect_impl(target, ctx):
+    # Extract sources from a `cc_library` (or similar):
+    if CcInfo not in target:
+        return []
+
+    # We're going to reach directly into the attrs on the traversed rule.
+    rule_attr = ctx.rule.attr
+
+    # CcInfo is a proxy for what we expect this rule to look like.
+    # However, some deps may expose `CcInfo` without having `srcs`,
+    # `hdrs`, etc., so we use `getattr` to handle that gracefully.
+
+    internal_hdrs = []
+    srcs = []
+
+    # Filter `srcs` so it only contains source files. Headers will go
+    # into `internal_headers`.
+    for src in _flatten_target_files(getattr(rule_attr, "srcs", [])).to_list():
+        if src.extension.lower() in ["c", "cc", "cpp", "cxx"]:
+            srcs.append(src)
+        else:
+            internal_hdrs.append(src)
+
+    return [CcFileList(
+        hdrs = _get_transitive_sources(
+            _flatten_target_files(rule_attr.hdrs).to_list(),
+            "hdrs",
+            rule_attr.deps,
+        ),
+        textual_hdrs = _get_transitive_sources(
+            _flatten_target_files(rule_attr.textual_hdrs).to_list(),
+            "textual_hdrs",
+            rule_attr.deps,
+        ),
+        internal_hdrs = _get_transitive_sources(
+            internal_hdrs,
+            "internal_hdrs",
+            rule_attr.deps,
+        ),
+        srcs = _get_transitive_sources(srcs, "srcs", rule_attr.deps),
+    )]
+
+cc_file_list_aspect = aspect(
+    doc = """
+Aspect to provide the list of sources and headers from a rule.
+
+Output is CcFileList. Example:
+
+  cc_library(
+      name = "foo",
+      srcs = [
+          "foo.cc",
+          "foo_internal.h",
+      ],
+      hdrs = ["foo.h"],
+      textual_hdrs = ["foo_inl.inc"],
+  )
+  # produces:
+  # CcFileList(
+  #     hdrs = depset([File("foo.h")]),
+  #     textual_hdrs = depset([File("foo_inl.inc")]),
+  #     internal_hdrs = depset([File("foo_internal.h")]),
+  #     srcs = depset([File("foo.cc")]),
+  # )
+""",
+    required_providers = [CcInfo],
+    implementation = _cc_file_list_aspect_impl,
+    attr_aspects = ["deps"],
+)
+
+################################################################################
+# Rule impl
+################################################################################
+
+def _collect_inputs(deps):
+    """Collects files from a list of deps.
+
+    This rule collects source files and linker inputs transitively for C++
+    deps.
+
+    The return value is a struct with object files (linker inputs),
+    partitioned by PIC and non-pic, and the rules' source and header files:
+
+        struct(
+            objects = ...,       # non-PIC object files
+            pic_objects = ...,   # PIC objects
+            cc_file_list = ...,  # a CcFileList
+        )
+
+    Args:
+      deps: Iterable of immediate deps, which will be treated as roots to
+            recurse transitively.
+    Returns:
+      A struct with linker inputs, source files, and header files.
+    """
+
+    objs = []
+    pic_objs = []
+
+    # The returned CcFileList will contain depsets of the deps' file lists.
+    # These lists hold `depset()`s from each of `deps`.
+    srcs = []
+    hdrs = []
+    internal_hdrs = []
+    textual_hdrs = []
+
+    for dep in deps:
+        if CcInfo in dep:
+            _collect_linker_input_objects(
+                dep.label,
+                dep[CcInfo],
+                objs,
+                pic_objs,
+            )
+
+        if CcFileList in dep:
+            cfl = dep[CcFileList]
+            srcs.append(cfl.srcs)
+            hdrs.append(cfl.hdrs)
+            internal_hdrs.append(cfl.internal_hdrs)
+            textual_hdrs.append(cfl.textual_hdrs)
+
+    return struct(
+        objects = objs,
+        pic_objects = pic_objs,
+        cc_file_list = CcFileList(
+            srcs = depset(transitive = srcs),
+            hdrs = depset(transitive = hdrs),
+            internal_hdrs = depset(transitive = internal_hdrs),
+            textual_hdrs = depset(transitive = textual_hdrs),
+        ),
+    )
+
+# Given structs a and b returned from _collect_inputs(), returns a copy of a
+# but with all files from b subtracted out.
+def _subtract_files(a, b):
+    result_args = {}
+
+    top_level_fields = ["objects", "pic_objects"]
+    for field in top_level_fields:
+        to_remove = {e: None for e in getattr(b, field)}
+        result_args[field] = [e for e in getattr(a, field) if not e in to_remove]
+
+    cc_file_list_args = {}
+    file_list_fields = ["srcs", "hdrs", "internal_hdrs", "textual_hdrs"]
+    for field in file_list_fields:
+        to_remove = {e: None for e in getattr(b.cc_file_list, field).to_list()}
+        cc_file_list_args[field] = depset(
+            [e for e in getattr(a.cc_file_list, field).to_list() if not e in to_remove],
+        )
+    result_args["cc_file_list"] = CcFileList(**cc_file_list_args)
+
+    return struct(**result_args)
+
+# Implementation for cc_dist_library rule.
+def _cc_dist_library_impl(ctx):
+    cc_toolchain_info = find_cc_toolchain(ctx)
+
+    feature_configuration = cc_common.configure_features(
+        ctx = ctx,
+        cc_toolchain = cc_toolchain_info,
+    )
+
+    inputs = _subtract_files(_collect_inputs(ctx.attr.deps), _collect_inputs(ctx.attr.dist_deps))
+
+    # For static libraries, build separately with and without pic.
+
+    stemname = "lib" + ctx.label.name
+    outputs = []
+
+    if len(inputs.objects) > 0:
+        archive_out = ctx.actions.declare_file(stemname + ".a")
+        _create_archive_action(
+            ctx,
+            feature_configuration,
+            cc_toolchain_info,
+            archive_out,
+            inputs.objects,
+        )
+        outputs.append(archive_out)
+
+    if len(inputs.pic_objects) > 0:
+        pic_archive_out = ctx.actions.declare_file(stemname + ".pic.a")
+        _create_archive_action(
+            ctx,
+            feature_configuration,
+            cc_toolchain_info,
+            pic_archive_out,
+            inputs.pic_objects,
+        )
+        outputs.append(pic_archive_out)
+
+    # For dynamic libraries, use the `cc_common.link` command to ensure
+    # everything gets built correctly according to toolchain definitions.
+    outputs.extend(_create_dso_link_action(
+        ctx,
+        feature_configuration,
+        cc_toolchain_info,
+        inputs.objects,
+        inputs.pic_objects,
+    ))
+
     # We could expose the libraries for use from cc rules:
     #
     # linking_context = cc_common.create_linking_context(
@@ -169,6 +369,7 @@
 
     return [
         DefaultInfo(files = depset(outputs)),
+        inputs.cc_file_list,
     ]
 
 cc_dist_library = rule(
@@ -179,20 +380,17 @@
 This rule creates static and dynamic libraries from the libraries listed in
 'deps'. The resulting libraries are suitable for distributing all of 'deps'
 in a single logical library, for example, in an installable binary package.
-Only the targets listed in 'deps' are included in the result (i.e., the
-output does not include transitive dependencies), allowing precise control
-over the library boundary.
+The result includes all transitive dependencies, excluding those reachable
+from 'dist_deps' or defined in a separate repository (e.g. Abseil).
 
 The outputs of this rule are a dynamic library and a static library. (If
 the build produces both PIC and non-PIC object files, then there is also a
 second static library.) The example below illustrates additional details.
 
-This rule is different from Bazel's experimental `shared_cc_library` in
-several ways. First, this rule ignores transitive dependencies, which means
-that dynamic library dependencies generally need to be specified via
-'linkopts'. Second, this rule produces a static archive library in addition
-to the dynamic shared library. Third, this rule is not directly usable as a
-C++ dependency (although the outputs could be used, e.g., by `cc_import`).
+This rule is different from Bazel's experimental `shared_cc_library` in two
+ways. First, this rule produces a static archive library in addition to the
+dynamic shared library. Second, this rule is not directly usable as a C++
+dependency (although the outputs could be used, e.g., by `cc_import`).
 
 Example:
 
@@ -205,15 +403,19 @@
     cc_dist_library(
         name = "dist",
         linkopts = ["-la"],   # libdist.so dynamically links against liba.so.
-        deps = [":b", ":c"],  # Output contains b.o and c.o, but not a.o.
+        deps = [":b", ":c"],  # Output contains a.o, b.o, and c.o.
     )
 """,
     attrs = {
         "deps": attr.label_list(
-            doc = ("The list of libraries to be included in the outputs. " +
-                   "Only these targets' compilation outputs will be " +
-                   "included (i.e., the transitive dependencies are not " +
-                   "included in the output)."),
+            doc = ("The list of libraries to be included in the outputs, " +
+                   "along with their transitive dependencies."),
+            aspects = [cc_file_list_aspect],
+        ),
+        "dist_deps": attr.label_list(
+            doc = ("The list of cc_dist_library dependencies that " +
+                   "should be excluded."),
+            aspects = [cc_file_list_aspect],
         ),
         "linkopts": attr.string_list(
             doc = ("Add these flags to the C++ linker command when creating " +
diff --git a/post_process_dist.sh b/post_process_dist.sh
deleted file mode 100755
index 2630f97..0000000
--- a/post_process_dist.sh
+++ /dev/null
@@ -1,64 +0,0 @@
-#! /bin/sh
-
-# This script takes the result of "make dist" and:
-# 1) Unpacks it.
-# 2) Ensures all contents are user-writable.  Some version control systems
-#    keep code read-only until you explicitly ask to edit it, and the normal
-#    "make dist" process does not correct for this, so the result is that
-#    the entire dist is still marked read-only when unpacked, which is
-#    annoying.  So, we fix it.
-# 3) Convert MSVC project files to MSVC 2005, so that anyone who has version
-#    2005 *or* 2008 can open them.  (In version control, we keep things in
-#    MSVC 2008 format since that's what we use in development.)
-# 4) Uses the result to create .tar.gz, .tar.bz2, and .zip versions and
-#    deposits them in the "dist" directory.  In the .zip version, all
-#    non-testdata .txt files are converted to Windows-style line endings.
-# 5) Cleans up after itself.
-
-if [ "$1" == "" ]; then
-  echo "USAGE:  $0 DISTFILE" >&2
-  exit 1
-fi
-
-if [ ! -e $1 ]; then
-  echo $1": File not found." >&2
-  exit 1
-fi
-
-set -ex
-
-LANGUAGES="cpp csharp java objectivec python ruby php all"
-BASENAME=`basename $1 .tar.gz`
-VERSION=${BASENAME:9}
-
-# Create a directory called "dist", copy the tarball there and unpack it.
-mkdir dist
-cp $1 dist
-cd dist
-tar zxvf $BASENAME.tar.gz
-rm $BASENAME.tar.gz
-
-# Set the entire contents to be user-writable.
-chmod -R u+w $BASENAME
-cd $BASENAME
-
-for LANG in $LANGUAGES; do
-  # Build the dist again in .tar.gz
-  ./configure DIST_LANG=$LANG
-  make dist-gzip
-  mv $BASENAME.tar.gz ../protobuf-$LANG-$VERSION.tar.gz
-done
-
-# Convert all text files to use DOS-style line endings, then build a .zip
-# distribution.
-todos *.txt */*.txt
-
-for LANG in $LANGUAGES; do
-  # Build the dist again in .zip
-  ./configure DIST_LANG=$LANG
-  make dist-zip
-  mv $BASENAME.zip ../protobuf-$LANG-$VERSION.zip
-done
-
-cd ..
-rm -rf $BASENAME
diff --git a/protobuf-lite.pc.in b/protobuf-lite.pc.in
deleted file mode 100644
index f92e4ad..0000000
--- a/protobuf-lite.pc.in
+++ /dev/null
@@ -1,11 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: Protocol Buffers
-Description: Google's Data Interchange Format
-Version: @VERSION@
-Libs: -L${libdir} -lprotobuf-lite
-Cflags: -I${includedir}
-Conflicts: protobuf
diff --git a/protobuf.bzl b/protobuf.bzl
index c5b8dab..f638f39 100644
--- a/protobuf.bzl
+++ b/protobuf.bzl
@@ -1,7 +1,7 @@
 load("@bazel_skylib//lib:versions.bzl", "versions")
-load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@rules_cc//cc:defs.bzl", "objc_library")
 load("@rules_proto//proto:defs.bzl", "ProtoInfo")
-load("@rules_python//python:defs.bzl", "py_library", "py_test")
+load("@rules_python//python:defs.bzl", "py_library")
 
 def _GetPath(ctx, path):
     if ctx.label.workspace_root:
@@ -37,20 +37,24 @@
         return _GetPath(ctx, ctx.attr.includes[0])
     return _GetPath(ctx, ctx.label.package + "/" + ctx.attr.includes[0])
 
-def _CcHdrs(srcs, use_grpc_plugin = False):
-    ret = [s[:-len(".proto")] + ".pb.h" for s in srcs]
-    if use_grpc_plugin:
-        ret += [s[:-len(".proto")] + ".grpc.pb.h" for s in srcs]
-    return ret
+def _ObjcBase(srcs):
+    return [
+        "".join([token.capitalize() for token in src[:-len(".proto")].split("_")])
+        for src in srcs
+    ]
 
-def _CcSrcs(srcs, use_grpc_plugin = False):
-    ret = [s[:-len(".proto")] + ".pb.cc" for s in srcs]
-    if use_grpc_plugin:
-        ret += [s[:-len(".proto")] + ".grpc.pb.cc" for s in srcs]
-    return ret
+def _ObjcHdrs(srcs):
+    return [src + ".pbobjc.h" for src in _ObjcBase(srcs)]
 
-def _CcOuts(srcs, use_grpc_plugin = False):
-    return _CcHdrs(srcs, use_grpc_plugin) + _CcSrcs(srcs, use_grpc_plugin)
+def _ObjcSrcs(srcs):
+    return [src + ".pbobjc.m" for src in _ObjcBase(srcs)]
+
+def _ObjcOuts(srcs, out_type):
+    if out_type == "hdrs":
+        return _ObjcHdrs(srcs)
+    if out_type == "srcs":
+        return _ObjcSrcs(srcs)
+    return _ObjcHdrs(srcs) + _ObjcSrcs(srcs)
 
 def _PyOuts(srcs, use_grpc_plugin = False):
     ret = [s[:-len(".proto")] + "_pb2.py" for s in srcs]
@@ -58,29 +62,29 @@
         ret += [s[:-len(".proto")] + "_pb2_grpc.py" for s in srcs]
     return ret
 
-def _RelativeOutputPath(path, include, dest = ""):
-    if include == None:
-        return path
+def _RubyOuts(srcs):
+    return [s[:-len(".proto")] + "_pb.rb" for s in srcs]
 
-    if not path.startswith(include):
-        fail("Include path %s isn't part of the path %s." % (include, path))
+def _CsharpOuts(srcs):
+    return [
+        "".join([token.capitalize() for token in src[:-len(".proto")].split("_")]) + ".cs"
+        for src in srcs
+    ]
 
-    if include and include[-1] != "/":
-        include = include + "/"
-    if dest and dest[-1] != "/":
-        dest = dest + "/"
-
-    path = path[len(include):]
-    return dest + path
+ProtoGenInfo = provider(
+    fields = ["srcs", "import_flags", "deps"],
+)
 
 def _proto_gen_impl(ctx):
     """General implementation for generating protos"""
     srcs = ctx.files.srcs
-    deps = depset(direct=ctx.files.srcs)
+    langs = ctx.attr.langs or []
+    out_type = ctx.attr.out_type
+    deps = depset(direct = ctx.files.srcs)
     source_dir = _SourceDir(ctx)
     gen_dir = _GenDir(ctx).rstrip("/")
     import_flags = []
-        
+
     if source_dir:
         has_sources = any([src.is_source for src in srcs])
         if has_sources:
@@ -92,27 +96,38 @@
     if has_generated:
         import_flags += ["-I" + gen_dir]
 
-    import_flags = depset(direct=import_flags)
+    if ctx.attr.includes:
+        for include in ctx.attr.includes:
+            import_flags += ["-I" + _GetPath(ctx, include)]
+
+    import_flags = depset(direct = import_flags)
 
     for dep in ctx.attr.deps:
-        if type(dep.proto.import_flags) == "list":
-            import_flags = depset(transitive=[import_flags], direct=dep.proto.import_flags)
+        dep_proto = dep[ProtoGenInfo]
+        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)
+            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])
+            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(
-            proto = struct(
+    if not langs and not ctx.executable.plugin:
+        return [
+            ProtoGenInfo(
                 srcs = srcs,
                 import_flags = import_flags,
                 deps = deps,
             ),
-        )
+        ]
 
+    generated_files = []
     for src in srcs:
         args = []
 
@@ -123,17 +138,28 @@
                 path = f.replace("-I", "")
                 import_flags_real.append("-I$(realpath -s %s)" % path)
 
-        outs = []
         use_grpc_plugin = (ctx.attr.plugin_language == "grpc" and ctx.attr.plugin)
         path_tpl = "$(realpath %s)" if in_gen_dir else "%s"
-        if ctx.attr.gen_cc:
-            args += [("--cpp_out=" + path_tpl) % gen_dir]
-            outs.extend(_CcOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
-        if ctx.attr.gen_py:
-            args += [("--python_out=" + path_tpl) % gen_dir]
-            outs.extend(_PyOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
 
+        outs = []
+        for lang in langs:
+            if lang == "csharp":
+                outs.extend(_CsharpOuts([src.basename]))
+            elif lang == "objc":
+                outs.extend(_ObjcOuts([src.basename], out_type = out_type))
+            elif lang == "python":
+                outs.extend(_PyOuts([src.basename], use_grpc_plugin = use_grpc_plugin))
+            elif lang == "ruby":
+                outs.extend(_RubyOuts([src.basename]))
+
+            # Otherwise, rely on user-supplied outs.
+            args += [("--%s_out=" + path_tpl) % (lang, gen_dir)]
+
+        if ctx.attr.outs:
+            outs.extend(ctx.attr.outs)
         outs = [ctx.actions.declare_file(out, sibling = src) for out in outs]
+        generated_files.extend(outs)
+
         inputs = [src] + deps.to_list()
         tools = [ctx.executable.protoc]
         if ctx.executable.plugin:
@@ -186,39 +212,15 @@
                     use_default_shell_env = True,
                 )
 
-    return struct(
-        proto = struct(
+    return [
+        ProtoGenInfo(
             srcs = srcs,
             import_flags = import_flags,
             deps = deps,
         ),
-    )
+        DefaultInfo(files = depset(generated_files)),
+    ]
 
-proto_gen = rule(
-    attrs = {
-        "srcs": attr.label_list(allow_files = True),
-        "deps": attr.label_list(providers = ["proto"]),
-        "includes": attr.string_list(),
-        "protoc": attr.label(
-            cfg = "exec",
-            executable = True,
-            allow_single_file = True,
-            mandatory = True,
-        ),
-        "plugin": attr.label(
-            cfg = "exec",
-            allow_files = True,
-            executable = True,
-        ),
-        "plugin_language": attr.string(),
-        "plugin_options": attr.string_list(),
-        "gen_cc": attr.bool(),
-        "gen_py": attr.bool(),
-        "outs": attr.output_list(),
-    },
-    output_to_genfiles = True,
-    implementation = _proto_gen_impl,
-)
 """Generates codes from Protocol Buffers definitions.
 
 This rule helps you to implement Skylark macros specific to the target
@@ -235,103 +237,40 @@
     compiler.
   plugin_language: the language of the generated sources
   plugin_options: a list of options to be passed to the plugin
-  gen_cc: generates C++ sources in addition to the ones from the plugin.
-  gen_py: generates Python sources in addition to the ones from the plugin.
+  langs: generates sources in addition to the ones from the plugin for each
+    specified language.
   outs: a list of labels of the expected outputs from the protocol compiler.
+  out_type: only generated a single type of source file for languages that have
+    split sources (e.g. *.h and *.cc in C++)
 """
-
-def _adapt_proto_library_impl(ctx):
-    deps = [dep[ProtoInfo] for dep in ctx.attr.deps]
-
-    srcs = [src for dep in deps for src in dep.direct_sources]
-    return struct(
-        proto = struct(
-            srcs = srcs,
-            import_flags = ["-I{}".format(path) for dep in deps for path in dep.transitive_proto_path.to_list()],
-            deps = srcs,
-        ),
-    )
-
-adapt_proto_library = rule(
-    implementation = _adapt_proto_library_impl,
+_proto_gen = rule(
     attrs = {
-        "deps": attr.label_list(
+        "srcs": attr.label_list(allow_files = True),
+        "deps": attr.label_list(providers = [ProtoGenInfo]),
+        "includes": attr.string_list(),
+        "protoc": attr.label(
+            cfg = "exec",
+            executable = True,
+            allow_single_file = True,
             mandatory = True,
-            providers = [ProtoInfo],
+        ),
+        "plugin": attr.label(
+            cfg = "exec",
+            allow_files = True,
+            executable = True,
+        ),
+        "plugin_language": attr.string(),
+        "plugin_options": attr.string_list(),
+        "langs": attr.string_list(),
+        "outs": attr.string_list(),
+        "out_type": attr.string(
+            default = "all",
         ),
     },
-    doc = "Adapts `proto_library` from `@rules_proto` to be used with `{cc,py}_proto_library` from this file.",
+    output_to_genfiles = True,
+    implementation = _proto_gen_impl,
 )
 
-def cc_proto_library(
-        name,
-        srcs = [],
-        deps = [],
-        cc_libs = [],
-        include = None,
-        protoc = "@com_google_protobuf//:protoc",
-        use_grpc_plugin = False,
-        default_runtime = "@com_google_protobuf//:protobuf",
-        **kargs):
-    """Bazel rule to create a C++ protobuf library from proto source files
-
-    NOTE: the rule is only an internal workaround to generate protos. The
-    interface may change and the rule may be removed when bazel has introduced
-    the native rule.
-
-    Args:
-      name: the name of the cc_proto_library.
-      srcs: the .proto files of the cc_proto_library.
-      deps: a list of dependency labels; must be cc_proto_library.
-      cc_libs: a list of other cc_library targets depended by the generated
-          cc_library.
-      include: a string indicating the include path of the .proto files.
-      protoc: the label of the protocol compiler to generate the sources.
-      use_grpc_plugin: a flag to indicate whether to call the grpc C++ plugin
-          when processing the proto files.
-      default_runtime: the implicitly default runtime which will be depended on by
-          the generated cc_library target.
-      **kargs: other keyword arguments that are passed to cc_library.
-    """
-
-    includes = []
-    if include != None:
-        includes = [include]
-
-    grpc_cpp_plugin = None
-    if use_grpc_plugin:
-        grpc_cpp_plugin = "//external:grpc_cpp_plugin"
-
-    gen_srcs = _CcSrcs(srcs, use_grpc_plugin)
-    gen_hdrs = _CcHdrs(srcs, use_grpc_plugin)
-    outs = gen_srcs + gen_hdrs
-
-    proto_gen(
-        name = name + "_genproto",
-        srcs = srcs,
-        deps = [s + "_genproto" for s in deps],
-        includes = includes,
-        protoc = protoc,
-        plugin = grpc_cpp_plugin,
-        plugin_language = "grpc",
-        gen_cc = 1,
-        outs = outs,
-        visibility = ["//visibility:public"],
-    )
-
-    if default_runtime and not default_runtime in cc_libs:
-        cc_libs = cc_libs + [default_runtime]
-    if use_grpc_plugin:
-        cc_libs = cc_libs + ["//external:grpc_lib"]
-    cc_library(
-        name = name,
-        srcs = gen_srcs,
-        hdrs = gen_hdrs,
-        deps = cc_libs + deps,
-        includes = includes,
-        **kargs
-    )
-
 def _internal_gen_well_known_protos_java_impl(ctx):
     args = ctx.actions.args()
 
@@ -456,42 +395,97 @@
     },
 )
 
+def internal_objc_proto_library(
+        name,
+        srcs = [],
+        deps = [],
+        outs = [],
+        proto_deps = [],
+        includes = ["."],
+        default_runtime = "@com_google_protobuf//:protobuf_objc",
+        protoc = "@com_google_protobuf//:protoc",
+        testonly = None,
+        visibility = ["//visibility:public"],
+        **kwargs):
+    """Bazel rule to create a Objective-C protobuf library from proto source
+    files
 
-
-def internal_copied_filegroup(name, srcs, strip_prefix, dest, **kwargs):
-    """Macro to copy files to a different directory and then create a filegroup.
-
-    This is used by the //:protobuf_python py_proto_library target to work around
-    an issue caused by Python source files that are part of the same Python
-    package being in separate directories.
+    NOTE: the rule is only an internal workaround to generate protos. The
+    interface may change and the rule may be removed when bazel has introduced
+    the native rule.
 
     Args:
-      srcs: The source files to copy and add to the filegroup.
-      strip_prefix: Path to the root of the files to copy.
-      dest: The directory to copy the source files into.
-      **kwargs: extra arguments that will be passesd to the filegroup.
-    """
-    outs = [_RelativeOutputPath(s, strip_prefix, dest) for s in srcs]
+      name: the name of the objc_proto_library.
+      srcs: the .proto files to compile.
+      deps: a list of dependency labels; must be objc_proto_library.
+      outs: a list of expected output files.
+      proto_deps: a list of proto file dependencies that don't have a
+        objc_proto_library rule.
+      include: a string indicating the include path of the .proto files.
+      default_runtime: the Objective-C Protobuf runtime
+      protoc: the label of the protocol compiler to generate the sources.
+      testonly: common rule attribute (see:
+          https://bazel.build/reference/be/common-definitions#common-attributes)
+      visibility: the visibility of the generated files.
+      **kwargs: other keyword arguments that are passed to py_library.
 
-    native.genrule(
-        name = name + "_genrule",
+    """
+    full_deps = [d + "_genproto" for d in deps]
+
+    if proto_deps:
+        _proto_gen(
+            name = name + "_deps_genproto",
+            testonly = testonly,
+            srcs = proto_deps,
+            protoc = protoc,
+            includes = includes,
+        )
+        full_deps.append(":%s_deps_genproto" % name)
+
+    # Note: we need to run the protoc build twice to get separate targets for
+    # the generated header and the source files.
+    _proto_gen(
+        name = name + "_genproto_hdrs",
         srcs = srcs,
-        outs = outs,
-        cmd_bash = " && ".join(
-            ["cp $(location %s) $(location %s)" %
-             (s, _RelativeOutputPath(s, strip_prefix, dest)) for s in srcs]),
-        cmd_bat = " && ".join(
-            ["@copy /Y $(location %s) $(location %s) >NUL" %
-             (s, _RelativeOutputPath(s, strip_prefix, dest)) for s in srcs]),
+        deps = full_deps,
+        langs = ["objc"],
+        out_type = "hdrs",
+        includes = includes,
+        protoc = protoc,
+        testonly = testonly,
+        visibility = visibility,
+        tags = ["manual"],
     )
 
-    native.filegroup(
+    _proto_gen(
+        name = name + "_genproto",
+        srcs = srcs,
+        deps = full_deps,
+        langs = ["objc"],
+        out_type = "srcs",
+        includes = includes,
+        protoc = protoc,
+        testonly = testonly,
+        visibility = visibility,
+        tags = ["manual"],
+    )
+
+    objc_library(
         name = name,
-        srcs = outs,
+        hdrs = [name + "_genproto_hdrs"],
+        non_arc_srcs = [name + "_genproto"],
+        deps = [default_runtime],
+        includes = includes,
+        testonly = testonly,
+        visibility = visibility,
+        # Don't auto-expand these targets until target_compatible_with
+        # works.  See https://github.com/bazelbuild/bazel/issues/12897.
+        tags = ["manual"],
+        target_compatible_with = ["@platforms//os:osx"],
         **kwargs
     )
 
-def py_proto_library(
+def internal_py_proto_library(
         name,
         srcs = [],
         deps = [],
@@ -501,6 +495,7 @@
         default_runtime = "@com_google_protobuf//:protobuf_python",
         protoc = "@com_google_protobuf//:protoc",
         use_grpc_plugin = False,
+        testonly = None,
         **kargs):
     """Bazel rule to create a Python protobuf library from proto source files
 
@@ -522,11 +517,11 @@
       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.
+      testonly: common rule attribute (see:
+          https://bazel.build/reference/be/common-definitions#common-attributes)
       **kargs: other keyword arguments that are passed to py_library.
 
     """
-    outs = _PyOuts(srcs, use_grpc_plugin)
-
     includes = []
     if include != None:
         includes = [include]
@@ -538,14 +533,14 @@
         # is not explicitly listed in py_libs. Instead, host system is assumed to
         # have grpc installed.
 
-    proto_gen(
+    _proto_gen(
         name = name + "_genproto",
+        testonly = testonly,
         srcs = srcs,
         deps = [s + "_genproto" for s in deps],
         includes = includes,
         protoc = protoc,
-        gen_py = 1,
-        outs = outs,
+        langs = ["python"],
         visibility = ["//visibility:public"],
         plugin = grpc_python_plugin,
         plugin_language = "grpc",
@@ -555,33 +550,158 @@
         py_libs = py_libs + [default_runtime]
     py_library(
         name = name,
-        srcs = outs + py_extra_srcs,
+        testonly = testonly,
+        srcs = [name + "_genproto"] + py_extra_srcs,
         deps = py_libs + deps,
         imports = includes,
         **kargs
     )
 
-def internal_protobuf_py_tests(
-        name,
-        modules = [],
-        **kargs):
-    """Bazel rules to create batch tests for protobuf internal.
+def py_proto_library(
+        *args,
+        **kwargs):
+    """Deprecated alias for use before Bazel 5.3.
 
     Args:
-      name: the name of the rule.
-      modules: a list of modules for tests. The macro will create a py_test for
-          each of the parameter with the source "google/protobuf/%s.py"
-      kargs: extra parameters that will be passed into the py_test.
+      *args: the name of the py_proto_library.
+      **kwargs: other keyword arguments that are passed to py_library.
+
+    Deprecated:
+      This is provided for backwards compatibility only.  Bazel 5.3 will
+      introduce support for py_proto_library, which should be used instead.
+    """
+    internal_py_proto_library(*args, **kwargs)
+
+def _source_proto_library(
+        name,
+        srcs = [],
+        deps = [],
+        proto_deps = [],
+        outs = [],
+        lang = None,
+        includes = ["."],
+        protoc = "@com_google_protobuf//:protoc",
+        testonly = None,
+        visibility = ["//visibility:public"],
+        **kwargs):
+    """Bazel rule to create generated protobuf code from proto source files for
+    languages not well supported by Bazel yet.  This will output the generated
+    code as-is without any compilation.  This is most useful for interpreted
+    languages that don't require it.
+
+    NOTE: the rule is only an internal workaround to generate protos. The
+    interface may change and the rule may be removed when bazel has introduced
+    the native rule.
+
+    Args:
+      name: the name of the unsupported_proto_library.
+      srcs: the .proto files to compile.  Note, that for languages where out
+        needs to be provided, only a single source file is allowed.
+      deps: a list of dependency labels; must be unsupported_proto_library.
+      proto_deps: a list of proto file dependencies that don't have a
+        unsupported_proto_library rule.
+      lang: the language to (optionally) generate code for.
+      outs: a list of expected output files.  This is only required for
+        languages where we can't predict the outputs.
+      includes: strings indicating the include path of the .proto files.
+      protoc: the label of the protocol compiler to generate the sources.
+      testonly: common rule attribute (see:
+          https://bazel.build/reference/be/common-definitions#common-attributes)
+      visibility: the visibility of the generated files.
+      **kwargs: other keyword arguments that are passed to py_library.
 
     """
-    for m in modules:
-        s = "python/google/protobuf/internal/%s.py" % m
-        py_test(
-            name = "py_%s" % m,
-            srcs = [s],
-            main = s,
-            **kargs
+    if outs and len(srcs) != 1:
+        fail("Custom outputs only allowed for single proto targets.")
+
+    langs = []
+    if lang != None:
+        langs = [lang]
+
+    full_deps = [d + "_genproto" for d in deps]
+
+    if proto_deps:
+        _proto_gen(
+            name = name + "_deps_genproto",
+            testonly = testonly,
+            srcs = proto_deps,
+            protoc = protoc,
+            includes = includes,
         )
+        full_deps.append(":%s_deps_genproto" % name)
+
+    _proto_gen(
+        name = name + "_genproto",
+        srcs = srcs,
+        deps = full_deps,
+        langs = langs,
+        outs = outs,
+        includes = includes,
+        protoc = protoc,
+        testonly = testonly,
+        visibility = visibility,
+    )
+
+    native.filegroup(
+        name = name,
+        srcs = [":%s_genproto" % name],
+        testonly = testonly,
+        visibility = visibility,
+        **kwargs
+    )
+
+def internal_csharp_proto_library(**kwargs):
+    """Bazel rule to create a C# protobuf library from proto source files
+
+    NOTE: the rule is only an internal workaround to generate protos. The
+    interface may change and the rule may be removed when bazel has introduced
+    the native rule.
+
+    Args:
+      **kwargs: arguments that are passed to unsupported_proto_library.
+
+    """
+
+    _source_proto_library(
+        lang = "csharp",
+        **kwargs
+    )
+
+def internal_php_proto_library(**kwargs):
+    """Bazel rule to create a PHP protobuf library from proto source files
+
+    NOTE: the rule is only an internal workaround to generate protos. The
+    interface may change and the rule may be removed when bazel has introduced
+    the native rule.
+
+    Args:
+      **kwargs: arguments that are passed to unsupported_proto_library.
+
+    """
+    if not kwargs.get("outs"):
+        fail("Unable to predict the outputs for php_proto_library.  Please specify them via `outs`.")
+
+    _source_proto_library(
+        lang = "php",
+        **kwargs
+    )
+
+def internal_ruby_proto_library(**kwargs):
+    """Bazel rule to create a Ruby protobuf library from proto source files
+
+    NOTE: the rule is only an internal workaround to generate protos. The
+    interface may change and the rule may be removed when bazel has introduced
+    the native rule.
+
+    Args:
+      **kwargs: arguments that are passed to unsupported_proto_library.
+
+    """
+
+    _source_proto_library(
+        lang = "ruby",
+        **kwargs
+    )
 
 def check_protobuf_required_bazel_version():
     """For WORKSPACE files, to check the installed version of bazel.
diff --git a/protobuf.pc.in b/protobuf.pc.in
deleted file mode 100644
index e9bef5d..0000000
--- a/protobuf.pc.in
+++ /dev/null
@@ -1,13 +0,0 @@
-prefix=@prefix@
-exec_prefix=@exec_prefix@
-libdir=@libdir@
-includedir=@includedir@
-
-Name: Protocol Buffers
-Description: Google's Data Interchange Format
-Version: @VERSION@
-Libs: -L${libdir} -lprotobuf
-Libs.private: @LIBS@
-
-Cflags: -I${includedir}
-Conflicts: protobuf-lite
diff --git a/protobuf_deps.bzl b/protobuf_deps.bzl
index f635031..ed24c53 100644
--- a/protobuf_deps.bzl
+++ b/protobuf_deps.bzl
@@ -3,9 +3,10 @@
 load("@bazel_tools//tools/build_defs/repo:http.bzl", "http_archive")
 
 PROTOBUF_MAVEN_ARTIFACTS = [
+    "com.google.caliper:caliper:1.0-beta-3",
     "com.google.code.findbugs:jsr305:3.0.2",
     "com.google.code.gson:gson:2.8.9",
-    "com.google.errorprone:error_prone_annotations:2.3.2",
+    "com.google.errorprone:error_prone_annotations:2.5.1",
     "com.google.j2objc:j2objc-annotations:1.3",
     "com.google.guava:guava:31.1-jre",
     "com.google.guava:guava-testlib:31.1-jre",
@@ -28,11 +29,11 @@
     if not native.existing_rule("bazel_skylib"):
         http_archive(
             name = "bazel_skylib",
-            sha256 = "97e70364e9249702246c0e9444bccdc4b847bed1eb03c5a3ece4f83dfe6abc44",
             urls = [
-                "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
-                "https://github.com/bazelbuild/bazel-skylib/releases/download/1.0.2/bazel-skylib-1.0.2.tar.gz",
+                "https://mirror.bazel.build/github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
+                "https://github.com/bazelbuild/bazel-skylib/releases/download/1.3.0/bazel-skylib-1.3.0.tar.gz",
             ],
+            sha256 = "74d544d96f4a5bb630d465ca8bbcfe231e3594e5aae57e1edbf17a6eb3ca2506",
         )
 
     if not native.existing_rule("com_google_absl"):
@@ -40,8 +41,8 @@
         _github_archive(
             name = "com_google_absl",
             repo = "https://github.com/abseil/abseil-cpp",
-            commit = "215105818dfde3174fe799600bb0f3cae233d0bf",
-            sha256 = "b4e20d9e752a75c10636675691b1e9c2698e0764cb404987d0ffa77223041c19",
+            commit = "273292d1cfc0a94a65082ee350509af1d113344d",
+            sha256 = "6764f226bd6e2d8ab9fe2f3cab5f45fb1a4a15c04b58b87ba7fa87456054f98b",
         )
 
     if not native.existing_rule("zlib"):
@@ -56,6 +57,23 @@
             ],
         )
 
+    if not native.existing_rule("jsoncpp"):
+        http_archive(
+            name = "jsoncpp",
+            build_file = "@com_google_protobuf//:third_party/jsoncpp.BUILD",
+            sha256 = "e34a628a8142643b976c7233ef381457efad79468c67cb1ae0b83a33d7493999",
+            strip_prefix = "jsoncpp-1.9.4",
+            urls = ["https://github.com/open-source-parsers/jsoncpp/archive/refs/tags/1.9.4.tar.gz"],
+        )
+
+    if not native.existing_rule("utf8_range"):
+        _github_archive(
+            name = "utf8_range",
+            repo = "https://github.com/protocolbuffers/utf8_range",
+            commit = "de0b4a8ff9b5d4c98108bdfe723291a33c52c54f",
+            sha256 = "5da960e5e5d92394c809629a03af3c7709d2d3d0ca731dacb3a9fb4bf28f7702",
+        )
+
     if not native.existing_rule("rules_cc"):
         _github_archive(
             name = "rules_cc",
@@ -83,9 +101,9 @@
     if not native.existing_rule("rules_python"):
         http_archive(
             name = "rules_python",
-            sha256 = "9fcf91dbcc31fde6d1edb15f117246d912c33c36f44cf681976bd886538deba6",
-            strip_prefix = "rules_python-0.8.0",
-            url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.8.0.tar.gz",
+            sha256 = "a868059c8c6dd6ad45a205cca04084c652cfe1852e6df2d5aca036f6e5438380",
+            strip_prefix = "rules_python-0.14.0",
+            url = "https://github.com/bazelbuild/rules_python/archive/refs/tags/0.14.0.tar.gz",
         )
 
     if not native.existing_rule("rules_jvm_external"):
@@ -109,14 +127,14 @@
     if not native.existing_rule("io_bazel_rules_kotlin"):
         http_archive(
             name = "io_bazel_rules_kotlin",
-            urls = ["https://github.com/bazelbuild/rules_kotlin/releases/download/v1.5.0-beta-4/rules_kotlin_release.tgz"],
-            sha256 = "6cbd4e5768bdfae1598662e40272729ec9ece8b7bded8f0d2c81c8ff96dc139d",
+            urls = ["https://github.com/bazelbuild/rules_kotlin/releases/download/v1.7.0-RC-1/rules_kotlin_release.tgz"],
+            sha256 = "68b910730026921814d3a504ccbe9adaac9938983d940e626523e6e4ecfb0355",
         )
 
     if not native.existing_rule("upb"):
         _github_archive(
             name = "upb",
             repo = "https://github.com/protocolbuffers/upb",
-            commit = "79462f8a654ef782e149f59cb07d930269af951a",
-            sha256 = "1613eae24fdd0cd7b570860123502f336939094de9af5777815f63ac86ef8d0c",
+            commit = "ee56471047ad8619d0c701f894aa1767ca91f5c2",
+            sha256 = "0c3f86ce497e6cc75e89a0d4a8e32c90ea25aaedabd6d42fb9e2f2ad52d3f4b0",
         )
diff --git a/protoc-artifacts/Dockerfile b/protoc-artifacts/Dockerfile
deleted file mode 100644
index 278bc74..0000000
--- a/protoc-artifacts/Dockerfile
+++ /dev/null
@@ -1,55 +0,0 @@
-FROM centos:6.9
-
-RUN yum install -y git \
-                   tar \
-                   wget \
-                   make \
-                   autoconf \
-                   curl-devel \
-                   unzip \
-                   automake \
-                   libtool \
-                   glibc-static.i686 \
-                   glibc-devel \
-                   glibc-devel.i686 \
-                   && \
-    yum clean all
-
-# Install Java 8
-RUN wget -q --no-cookies --no-check-certificate \
-    --header "Cookie: gpw_e24=http%3A%2F%2Fwww.oracle.com%2F; oraclelicense=accept-securebackup-cookie" \
-    "http://download.oracle.com/otn-pub/java/jdk/8u131-b11/d54c1d3a095b4ff2b6607d096fa80163/jdk-8u131-linux-x64.tar.gz" \
-    -O - | tar xz -C /var/local
-ENV JAVA_HOME /var/local/jdk1.8.0_131
-ENV PATH $JAVA_HOME/bin:$PATH
-
-# Install Maven
-RUN wget -q http://apache.cs.utah.edu/maven/maven-3/3.3.9/binaries/apache-maven-3.3.9-bin.tar.gz -O - | \
-    tar xz -C /var/local
-ENV PATH /var/local/apache-maven-3.3.9/bin:$PATH
-
-# Install GCC 4.8 to support -static-libstdc++
-RUN wget http://people.centos.org/tru/devtools-2/devtools-2.repo -P /etc/yum.repos.d && \
-    bash -c 'echo "enabled=1" >> /etc/yum.repos.d/devtools-2.repo' && \
-    bash -c "sed -e 's/\$basearch/i386/g' /etc/yum.repos.d/devtools-2.repo > /etc/yum.repos.d/devtools-i386-2.repo" && \
-    sed -e 's/testing-/testing-i386-/g' -i /etc/yum.repos.d/devtools-i386-2.repo && \
-    rpm --rebuilddb
-
-RUN yum install -y devtoolset-2-gcc \
-                   devtoolset-2-gcc-c++ \
-                   devtoolset-2-binutils \
-                   devtoolset-2-libstdc++-devel \
-                   devtoolset-2-libatomic-devel \
-                   libatomic \
-                   devtoolset-2-gcc.i686 \
-                   devtoolset-2-gcc-c++.i686 \
-                   devtoolset-2-binutils.i686 \
-                   devtoolset-2-libstdc++-devel.i686 \
-                   devtoolset-2-libatomic-devel.i686 \
-                   libatomic.i686 && \
-    yum clean all
-
-COPY scl-enable-devtoolset.sh /var/local/
-
-# Start in devtoolset environment that uses GCC 4.7
-ENTRYPOINT ["/var/local/scl-enable-devtoolset.sh"]
diff --git a/protoc-artifacts/README.md b/protoc-artifacts/README.md
deleted file mode 100644
index 8fc3669..0000000
--- a/protoc-artifacts/README.md
+++ /dev/null
@@ -1,161 +0,0 @@
-# Build scripts that publish pre-compiled protoc artifacts
-``protoc`` is the compiler for ``.proto`` files. It generates language bindings
-for the messages and/or RPC services from ``.proto`` files.
-
-Because ``protoc`` is a native executable, the scripts under this directory
-build and publish a ``protoc`` executable (a.k.a. artifact) to Maven
-repositories. The artifact can be used by build automation tools so that users
-would not need to compile and install ``protoc`` for their systems.
-
-If you would like us to publish protoc artifact for a new platform, please send
-us a pull request to add support for the new platform. You would need to change
-the following files:
-
-* [build-protoc.sh](build-protoc.sh): script to cross-build the protoc for your
-  platform.
-* [pom.xml](pom.xml): script to upload artifacts to maven.
-* [build-zip.sh](build-zip.sh): script to package published maven artifacts in
-  our release page.
-
-## Maven Location
-The published protoc artifacts are available on Maven here:
-
-    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
-Protobuf project.
-
-## Artifact name
-The name of a published ``protoc`` artifact is in the following format:
-``protoc-<version>-<os>-<arch>.exe``, e.g., ``protoc-3.6.1-linux-x86_64.exe``.
-
-Note that artifacts for linux/macos also have the `.exe` suffix but they are
-not windows binaries.
-
-## System requirement
-Install [Apache Maven](http://maven.apache.org/) if you don't have it.
-
-The scripts only work under Unix-like environments, e.g., Linux, MacOSX, and
-Cygwin or MinGW for Windows. Please see ``README.md`` of the Protobuf project
-for how to set up the build environment.
-
-## Building from a freshly checked-out source
-
-If you just checked out the Protobuf source from github, you need to
-generate the configure script.
-
-Under the protobuf project directory:
-
-
-```
-$ ./autogen.sh
-```
-
-### Build the artifact for each platform
-
-Run the build-protoc.sh script under this protoc-artifacts directory to build the protoc
-artifact for each platform.  For example:
-
-```
-$ cd protoc-artifacts
-$ ./build-protoc.sh linux x86_64 protoc
-```
-
-The above command will produce a `target/linux/x86_64/protoc` binary under the
-protoc-artifacts directory.
-
-For a list of supported platforms, see the comments in the build-protoc.sh
-script. We only use this script to build artifacts on Ubuntu and MacOS (both
-with x86_64, and do cross-compilation for other platforms.
-
-### Tips for building for Linux
-We build on Centos 6.9 to provide a good compatibility for not very new
-systems. We have provided a ``Dockerfile`` under this directory to build the
-environment. It has been tested with Docker 1.6.1.
-
-To build a image:
-
-```
-$ docker build -t protoc-artifacts .
-```
-
-To run the image:
-
-```
-$ docker run -it --rm=true protoc-artifacts bash
-```
-
-To checkout protobuf (run within the container):
-
-```
-$ # Replace v3.5.1 with the version you want
-$ wget -O - https://github.com/protocolbuffers/protobuf/archive/v3.5.1.tar.gz | tar xvzp
-```
-
-### Windows build
-We no longer use scripts in this directory to build windows artifacts. Instead,
-we use Visual Studio 2015 to build our windows release artifacts. See our
-[kokoro windows build scripts here](../kokoro/release/protoc/windows/build.bat).
-
-To upload windows artifacts, copy the built binaries into this directory and
-put it into the target/windows/(x86_64|x86_32) directory the same way as the
-artifacts for other platforms. That will allow the maven script to find and
-upload the artifacts to maven.
-
-## To push artifacts to Maven Central
-Before you can upload artifacts to Maven Central repository, make sure you have
-read [this page](http://central.sonatype.org/pages/apache-maven.html) on how to
-configure GPG and Sonatype account.
-
-Before you do the deployment, make sure you have built the protoc artifacts for
-every supported platform and put them under the target directory. Example
-target directory layout:
-
-    + pom.xml
-    + target
-      + linux
-        + x86_64
-          protoc.exe
-        + x86_32
-          protoc.exe
-        + aarch_64
-          protoc.exe
-        + ppcle_64
-          protoc.exe
-        + s390_64
-          protoc.exe
-      + osx
-        + x86_64
-          protoc.exe
-        + x86_32
-          protoc.exe
-      + windows
-        + x86_64
-          protoc.exe
-        + x86_32
-          protoc.exe
-
-You will need to build the artifacts on multiple machines and gather them
-together into one place.
-
-Use the following command to deploy artifacts for the host platform to a
-staging repository.
-
-```
-$ mvn deploy -P release
-```
-
-It creates a new staging repository. Go to
-https://oss.sonatype.org/#stagingRepositories and find the repository, usually
-in the name like ``comgoogle-123``. Verify that the staging repository has all
-the binaries, close and release this repository.
-
-
-## Tested build environments
-We have successfully built artifacts on the following environments:
-- Linux x86_32 and x86_64:
-  - Centos 6.9 (within Docker 1.6.1)
-  - Ubuntu 14.04.5 64-bit
-- Linux aarch_64: Cross compiled with `g++-aarch64-linux-gnu` on Ubuntu 14.04.5 64-bit
-- Mac OS X x86_32 and x86_64: Mac OS X 10.9.5
diff --git a/protoc-artifacts/build-zip.sh b/protoc-artifacts/build-zip.sh
deleted file mode 100755
index 1d97725..0000000
--- a/protoc-artifacts/build-zip.sh
+++ /dev/null
@@ -1,120 +0,0 @@
-#!/bin/bash
-
-if [ $# -ne 2 ]; then
-  cat <<EOF
-Usage: $0 <TARGET> <VERSION_NUMBER>
-
-TARGET: protoc | protoc-gen-javalite
-
-Example:
-  $ $0 protoc 3.0.0
-  $ $0 protoc-gen-javalite 3.0.0
-
-This script will download pre-built protoc or protoc plugin binaries from maven
-repository and create .zip packages suitable to be included in the github
-release page. If the target is protoc, well-known type .proto files will also be
-included. Each invocation will create 8 zip packages:
-  dist/<TARGET>-<VERSION_NUMBER>-win32.zip
-  dist/<TARGET>-<VERSION_NUMBER>-win64.zip
-  dist/<TARGET>-<VERSION_NUMBER>-osx-aarch_64.zip
-  dist/<TARGET>-<VERSION_NUMBER>-osx-x86_64.zip
-  dist/<TARGET>-<VERSION_NUMBER>-linux-x86_32.zip
-  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-s390_64.zip
-EOF
-  exit 1
-fi
-
-TARGET=$1
-VERSION_NUMBER=$2
-
-# <zip file name> <binary file name> pairs.
-declare -a FILE_NAMES=( \
-  win32.zip windows-x86_32.exe \
-  win64.zip windows-x86_64.exe \
-  osx-aarch_64.zip osx-aarch_64.exe \
-  osx-x86_64.zip osx-x86_64.exe \
-  linux-x86_32.zip linux-x86_32.exe \
-  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-s390_64.zip linux-s390_64.exe \
-)
-
-# List of all well-known types to be included.
-declare -a WELL_KNOWN_TYPES=(           \
-  google/protobuf/descriptor.proto      \
-  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/timestamp.proto       \
-  google/protobuf/type.proto            \
-  google/protobuf/wrappers.proto        \
-  google/protobuf/compiler/plugin.proto \
-)
-
-set -e
-
-# A temporary working directory to put all files.
-DIR=$(mktemp -d)
-
-# Copy over well-known types.
-mkdir -p ${DIR}/include/google/protobuf/compiler
-for PROTO in ${WELL_KNOWN_TYPES[@]}; do
-  cp -f ../src/${PROTO} ${DIR}/include/${PROTO}
-done
-
-# Create a readme file.
-cat <<EOF > ${DIR}/readme.txt
-Protocol Buffers - Google's data interchange format
-Copyright 2008 Google Inc.
-https://developers.google.com/protocol-buffers/
-
-This package contains a precompiled binary version of the protocol buffer
-compiler (protoc). This binary is intended for users who want to use Protocol
-Buffers in languages other than C++ but do not want to compile protoc
-themselves. To install, simply place this binary somewhere in your PATH.
-
-If you intend to use the included well known types then don't forget to
-copy the contents of the 'include' directory somewhere as well, for example
-into '/usr/local/include/'.
-
-Please refer to our official github site for more installation instructions:
-  https://github.com/protocolbuffers/protobuf
-EOF
-
-mkdir -p dist
-mkdir -p ${DIR}/bin
-# Create a zip file for each binary.
-for((i=0;i<${#FILE_NAMES[@]};i+=2));do
-  ZIP_NAME=${FILE_NAMES[$i]}
-  if [ ${ZIP_NAME:0:3} = "win" ]; then
-    BINARY="$TARGET.exe"
-  else
-    BINARY="$TARGET"
-  fi
-  BINARY_NAME=${FILE_NAMES[$(($i+1))]}
-  BINARY_URL=https://repo1.maven.org/maven2/com/google/protobuf/$TARGET/${VERSION_NUMBER}/$TARGET-${VERSION_NUMBER}-${BINARY_NAME}
-  if ! wget ${BINARY_URL} -O ${DIR}/bin/$BINARY &> /dev/null; then
-    echo "[ERROR] Failed to download ${BINARY_URL}" >&2
-    echo "[ERROR] Skipped $TARGET-${VERSION_NAME}-${ZIP_NAME}" >&2
-    continue
-  fi
-  TARGET_ZIP_FILE=`pwd`/dist/$TARGET-${VERSION_NUMBER}-${ZIP_NAME}
-  pushd $DIR &> /dev/null
-  chmod +x bin/$BINARY
-  if [ "$TARGET" = "protoc" ]; then
-    zip -r ${TARGET_ZIP_FILE} include bin readme.txt &> /dev/null
-  else
-    zip -r ${TARGET_ZIP_FILE} bin &> /dev/null
-  fi
-  rm  bin/$BINARY
-  popd &> /dev/null
-  echo "[INFO] Successfully created ${TARGET_ZIP_FILE}"
-done
diff --git a/protoc-artifacts/pom.xml b/protoc-artifacts/pom.xml
deleted file mode 100644
index 019e857..0000000
--- a/protoc-artifacts/pom.xml
+++ /dev/null
@@ -1,144 +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</groupId>
-    <artifactId>google</artifactId>
-    <version>1</version>
-  </parent>
-  <groupId>com.google.protobuf</groupId>
-  <artifactId>protoc</artifactId>
-  <version>3.21.10</version>
-  <packaging>pom</packaging>
-  <name>Protobuf Compiler</name>
-  <description>
-    Protobuf Compiler (protoc) is a compiler for .proto files. It generates
-    language-specific code for Protobuf messages and RPC interfaces.
-  </description>
-  <inceptionYear>2008</inceptionYear>
-  <url>https://developers.google.com/protocol-buffers/</url>
-  <licenses>
-    <license>
-      <name>BSD-3-Clause</name>
-      <url>https://opensource.org/licenses/BSD-3-Clause</url>
-      <distribution>repo</distribution>
-    </license>
-  </licenses>
-  <scm>
-    <url>https://github.com/protocolbuffers/protobuf</url>
-    <connection>
-      scm:git:https://github.com/protocolbuffers/protobuf.git
-    </connection>
-  </scm>
-  <build>
-    <plugins>
-      <plugin>
-        <groupId>org.codehaus.mojo</groupId>
-        <artifactId>build-helper-maven-plugin</artifactId>
-        <version>1.8</version>
-        <executions>
-          <execution>
-            <id>attach-artifacts</id>
-            <phase>package</phase>
-            <goals>
-              <goal>attach-artifact</goal>
-            </goals>
-            <configuration>
-              <artifacts>
-                <artifact>
-                  <file>${basedir}/target/linux/x86_64/protoc.exe</file>
-                  <classifier>linux-x86_64</classifier>
-                  <type>exe</type>
-                </artifact>
-                <artifact>
-                  <file>${basedir}/target/linux/x86_32/protoc.exe</file>
-                  <classifier>linux-x86_32</classifier>
-                  <type>exe</type>
-                </artifact>
-                <artifact>
-                  <file>${basedir}/target/windows/x86_64/protoc.exe</file>
-                  <classifier>windows-x86_64</classifier>
-                  <type>exe</type>
-                </artifact>
-                <artifact>
-                  <file>${basedir}/target/windows/x86_32/protoc.exe</file>
-                  <classifier>windows-x86_32</classifier>
-                  <type>exe</type>
-                </artifact>
-                <artifact>
-                  <file>${basedir}/target/osx/x86_64/protoc.exe</file>
-                  <classifier>osx-x86_64</classifier>
-                  <type>exe</type>
-                </artifact>
-                <artifact>
-                  <file>${basedir}/target/osx/aarch_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>
-                </artifact>
-                <artifact>
-                  <file>${basedir}/target/linux/ppcle_64/protoc.exe</file>
-                  <classifier>linux-ppcle_64</classifier>
-                  <type>exe</type>
-	  	</artifact>
-                <artifact>
-                  <file>${basedir}/target/linux/s390_64/protoc.exe</file>
-                  <classifier>linux-s390_64</classifier>
-                  <type>exe</type>
-                </artifact>
-              </artifacts>
-            </configuration>
-          </execution>
-        </executions>
-      </plugin>
-    </plugins>
-  </build>
-  <profiles>
-    <profile>
-      <id>release</id>
-      <properties>
-        <!-- Specify the staging repository to deploy to. This can be left
-             empty for the first deployment, and Sonatype will create one. For
-             subsequent deployments it should be set to what Sonatype has
-             created, so that all deployments will go to the same repository.
-             -->
-        <staging.repository/>
-      </properties>
-      <build>
-        <plugins>
-          <plugin>
-            <groupId>org.apache.maven.plugins</groupId>
-            <artifactId>maven-gpg-plugin</artifactId>
-            <version>1.5</version>
-            <executions>
-              <execution>
-                <id>sign-artifacts</id>
-                <phase>verify</phase>
-                <goals>
-                  <goal>sign</goal>
-                </goals>
-              </execution>
-            </executions>
-          </plugin>
-          <plugin>
-            <groupId>org.sonatype.plugins</groupId>
-            <artifactId>nexus-staging-maven-plugin</artifactId>
-            <version>1.6.3</version>
-            <extensions>true</extensions>
-            <configuration>
-               <serverId>sonatype-nexus-staging</serverId>
-               <nexusUrl>https://oss.sonatype.org/</nexusUrl>
-               <skipStagingRepositoryClose>true</skipStagingRepositoryClose>
-               <autoReleaseAfterClose>false</autoReleaseAfterClose>
-               <stagingRepositoryId>${staging.repository}</stagingRepositoryId>
-            </configuration>
-          </plugin>
-        </plugins>
-      </build>
-    </profile>
-  </profiles>
-</project>
diff --git a/protoc-artifacts/scl-enable-devtoolset.sh b/protoc-artifacts/scl-enable-devtoolset.sh
deleted file mode 100755
index 3089558..0000000
--- a/protoc-artifacts/scl-enable-devtoolset.sh
+++ /dev/null
@@ -1,13 +0,0 @@
-#!/bin/bash
-set -eu -o pipefail
-
-quote() {
-  local arg
-  for arg in "$@"; do
-    printf "'"
-    printf "%s" "$arg" | sed -e "s/'/'\\\\''/g"
-    printf "' "
-  done
-}
-
-exec scl enable devtoolset-2 "$(quote "$@")"
diff --git a/push_auto_update.sh b/push_auto_update.sh
new file mode 100755
index 0000000..52fe903
--- /dev/null
+++ b/push_auto_update.sh
@@ -0,0 +1,46 @@
+#!/bin/bash
+
+# This script updates src/file_lists.cmake and the checked-in generated code
+# for the well-known types, commits the resulting changes, and pushes them.
+# This does not do anything useful when run manually, but should be run by our
+# GitHub action instead.
+
+set -ex
+
+# Cd to the repo root.
+cd $(dirname -- "$0")
+
+previous_commit_title=$(git log -1 --pretty='%s')
+
+# Exit early if the previous commit was auto-generated. This reduces the risk
+# of a bug causing an infinite loop of auto-generated commits.
+if (echo "$previous_commit_title" | grep -q "^Auto-generate files"); then
+  echo "Previous commit was auto-generated"
+  exit 0
+fi
+
+# Run the staleness tests and use them to update any stale files.
+bazel test //src:cmake_lists_staleness_test || ./bazel-bin/src/cmake_lists_staleness_test --fix
+bazel test //src/google/protobuf:well_known_types_staleness_test || ./bazel-bin/src/google/protobuf/well_known_types_staleness_test --fix
+
+# Try to determine the most recent CL or pull request.
+pr_from_merge=$(echo "$previous_commit_title" | sed -n 's/^Merge pull request #\([0-9]\+\).*/\1/p')
+pr_from_squash=$(echo "$previous_commit_title" | sed -n 's/^.*(#\([0-9]\+\))$/\1/p')
+cl=$(git log -1 --pretty='%b' | sed -n 's/^PiperOrigin-RevId: \([0-9]*\)$/\1/p')
+
+if [ ! -z "$pr_from_merge" ]; then
+  commit_message="Auto-generate files after PR #$pr_from_merge"
+elif [ ! -z "$pr_from_squash" ]; then
+  commit_message="Auto-generate files after PR #$pr_from_squash"
+elif [ ! -z "$cl" ]; then
+  commit_message="Auto-generate files after cl/$cl"
+else
+  # If we are unable to determine the CL or pull request number, we fall back
+  # on this default commit message. Typically this should not occur, but could
+  # happen if a pull request was merged via a rebase.
+  commit_message="Auto-generate files"
+fi
+
+git add -A
+git diff --staged --quiet || git commit -am "$commit_message"
+git push
diff --git a/python/.repo-metadata.json b/python/.repo-metadata.json
new file mode 100644
index 0000000..c8d71a8
--- /dev/null
+++ b/python/.repo-metadata.json
@@ -0,0 +1,11 @@
+{
+  "name": "protobuf",
+  "name_pretty": "Protocol Buffers",
+  "product_documentation": "https://developers.google.com/protocol-buffers ",
+  "client_documentation": "https://developers.google.com/protocol-buffers/docs/pythontutorial",
+  "issue_tracker": "https://github.com/protocolbuffers/protobuf/issues",
+  "release_level": "ga",
+  "language": "python",
+  "repo": "protocolbuffers/protobuf ",
+  "distribution_name": "protobuf"
+}
diff --git a/python/BUILD.bazel b/python/BUILD.bazel
new file mode 100644
index 0000000..d40e76a
--- /dev/null
+++ b/python/BUILD.bazel
@@ -0,0 +1,435 @@
+# Protobuf Python runtime
+#
+# See also code generation logic under /src/google/protobuf/compiler/python.
+#
+# Most users should depend upon public aliases in the root:
+#   //:protobuf_python
+#   //:well_known_types_py_pb2
+
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("@rules_python//python:defs.bzl", "py_library")
+load("@pip_deps//:requirements.bzl", "requirement")
+load("//:protobuf.bzl", "internal_py_proto_library")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+load("//conformance:defs.bzl", "conformance_test")
+load(":internal.bzl", "internal_copy_files", "internal_py_test")
+
+py_library(
+    name = "protobuf_python",
+    data = select({
+        "//conditions:default": [],
+        ":use_fast_cpp_protos": [
+            ":google/protobuf/internal/_api_implementation.so",
+            ":google/protobuf/pyext/_message.so",
+        ],
+    }),
+    visibility = ["//:__pkg__"],
+    deps = [
+        ":python_srcs",
+        ":well_known_types_py_pb2",
+    ],
+)
+
+config_setting(
+    name = "use_fast_cpp_protos",
+    values = {
+        "define": "use_fast_cpp_protos=true",
+    },
+)
+
+internal_py_proto_library(
+    name = "well_known_types_py_pb2",
+    srcs = [":copied_wkt_proto_files"],
+    include = ".",
+    default_runtime = "",
+    protoc = "//:protoc",
+    srcs_version = "PY2AND3",
+    visibility = [
+        "//:__pkg__",
+        "@upb//:__subpackages__",
+    ],
+)
+
+internal_copy_files(
+    name = "copied_wkt_proto_files",
+    srcs = [
+        "//:well_known_type_protos",
+        "//src/google/protobuf:descriptor_proto_srcs",
+    ],
+    strip_prefix = "src",
+)
+
+cc_binary(
+    name = "google/protobuf/internal/_api_implementation.so",
+    srcs = ["google/protobuf/internal/api_implementation.cc"],
+    copts = COPTS + [
+        "-DPYTHON_PROTO2_CPP_IMPL_V2",
+    ],
+    linkshared = 1,
+    linkstatic = 1,
+    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",
+    ],
+    deps = select({
+        "//conditions:default": [],
+        ":use_fast_cpp_protos": ["//external:python_headers"],
+    }),
+)
+
+config_setting(
+    name = "allow_oversize_protos",
+    values = {
+        "define": "allow_oversize_protos=true",
+    },
+)
+
+cc_binary(
+    name = "google/protobuf/pyext/_message.so",
+    srcs = glob([
+        "google/protobuf/pyext/*.cc",
+        "google/protobuf/pyext/*.h",
+    ]),
+    copts = COPTS + [
+        "-DGOOGLE_PROTOBUF_HAS_ONEOF=1",
+    ] + select({
+        "//conditions:default": [],
+        ":allow_oversize_protos": ["-DPROTOBUF_PYTHON_ALLOW_OVERSIZE_PROTOS=1"],
+    }),
+    includes = ["."],
+    linkshared = 1,
+    linkstatic = 1,
+    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",
+    ],
+    deps = [
+        ":proto_api",
+        "//:protobuf",
+    ] + select({
+        "//conditions:default": [],
+        ":use_fast_cpp_protos": ["//external:python_headers"],
+    }),
+)
+
+py_library(
+    name = "python_srcs",
+    srcs = glob(
+        [
+            "google/protobuf/**/*.py",
+        ],
+        exclude = [
+            "google/protobuf/internal/*_test.py",
+            "google/protobuf/internal/test_util.py",
+            "google/protobuf/internal/import_test_package/__init__.py",
+        ],
+    ),
+    imports = ["python"],
+    srcs_version = "PY2AND3",
+    visibility = [
+        "//:__pkg__",
+        "@upb//:__subpackages__",
+    ],
+)
+
+py_library(
+    name = "python_test_srcs",
+    srcs = glob([
+        "google/protobuf/internal/*_test.py",
+    ]) + [
+        "google/protobuf/internal/test_util.py",
+        "google/protobuf/internal/import_test_package/__init__.py",
+    ],
+    imports = ["python"],
+    srcs_version = "PY3",
+    visibility = [
+        "//:__pkg__",
+        "@upb//:__subpackages__",
+    ],
+)
+
+################################################################################
+# Tests
+################################################################################
+
+internal_copy_files(
+    name = "copied_test_proto_files",
+    testonly = 1,
+    srcs = [
+        "//:test_proto_srcs",
+        "//src/google/protobuf/util:test_proto_srcs",
+    ],
+    strip_prefix = "src",
+)
+
+internal_copy_files(
+    name = "copied_test_messages_proto2_files",
+    testonly = 1,
+    srcs = [
+        "//src/google/protobuf:test_messages_proto2.proto",
+    ],
+    strip_prefix = "src",
+)
+
+internal_copy_files(
+    name = "copied_test_messages_proto3_files",
+    testonly = 1,
+    srcs = [
+        "//src/google/protobuf:test_messages_proto3.proto",
+    ],
+    strip_prefix = "src",
+)
+
+internal_py_proto_library(
+    name = "python_common_test_protos",
+    testonly = 1,
+    srcs = [":copied_test_proto_files"],
+    include = ".",
+    default_runtime = "",
+    protoc = "//:protoc",
+    srcs_version = "PY2AND3",
+    visibility = ["//:__pkg__"],
+    deps = [":well_known_types_py_pb2"],
+)
+
+internal_py_proto_library(
+    name = "python_specific_test_protos",
+    testonly = 1,
+    srcs = glob([
+        "google/protobuf/internal/*.proto",
+        "google/protobuf/internal/import_test_package/*.proto",
+    ]),
+    include = ".",
+    default_runtime = ":protobuf_python",
+    protoc = "//:protoc",
+    srcs_version = "PY2AND3",
+    visibility = ["//:__pkg__"],
+    deps = [":python_common_test_protos"],
+)
+
+internal_py_proto_library(
+    name = "test_messages_proto2_py_proto",
+    testonly = 1,
+    srcs = [":copied_test_messages_proto2_files"],
+    include = ".",
+    default_runtime = "//:protobuf_python",
+    protoc = "//:protoc",
+    visibility = [
+        "//conformance:__pkg__",
+        "//python:__subpackages__",
+    ],
+)
+
+internal_py_proto_library(
+    name = "test_messages_proto3_py_proto",
+    testonly = 1,
+    srcs = [":copied_test_messages_proto3_files"],
+    include = ".",
+    default_runtime = "//:protobuf_python",
+    protoc = "//:protoc",
+    visibility = [
+        "//conformance:__pkg__",
+        "//python:__subpackages__",
+    ],
+    deps = [":well_known_types_py_pb2"],
+)
+
+py_library(
+    name = "python_test_lib",
+    testonly = 1,
+    srcs = [
+        "google/protobuf/internal/import_test_package/__init__.py",
+        "google/protobuf/internal/test_util.py",
+    ],
+    imports = ["python"],
+    srcs_version = "PY2AND3",
+    deps = [
+        ":protobuf_python",
+        ":python_common_test_protos",
+        ":python_specific_test_protos",
+    ],
+)
+
+internal_py_test(
+    name = "descriptor_database_test",
+    srcs = ["google/protobuf/internal/descriptor_database_test.py"],
+)
+
+internal_py_test(
+    name = "descriptor_pool_test",
+    srcs = ["google/protobuf/internal/descriptor_pool_test.py"],
+)
+
+internal_py_test(
+    name = "descriptor_test",
+    srcs = ["google/protobuf/internal/descriptor_test.py"],
+)
+
+internal_py_test(
+    name = "field_mask_test",
+    srcs = ["google/protobuf/internal/field_mask_test.py"],
+)
+
+internal_py_test(
+    name = "generator_test",
+    srcs = ["google/protobuf/internal/generator_test.py"],
+)
+
+internal_py_test(
+    name = "import_test",
+    srcs = ["google/protobuf/internal/import_test.py"],
+)
+
+internal_py_test(
+    name = "json_format_test",
+    srcs = ["google/protobuf/internal/json_format_test.py"],
+)
+
+internal_py_test(
+    name = "keywords_test",
+    srcs = ["google/protobuf/internal/keywords_test.py"],
+)
+
+internal_py_test(
+    name = "message_factory_test",
+    srcs = ["google/protobuf/internal/message_factory_test.py"],
+)
+
+internal_py_test(
+    name = "message_test",
+    srcs = ["google/protobuf/internal/message_test.py"],
+    data = glob(["testdata/golden_pickle_*"]) + [
+        "//src/google/protobuf:testdata",
+    ],
+)
+
+internal_py_test(
+    name = "numpy_test",
+    srcs = ["google/protobuf/internal/numpy_test.py"],
+    deps = [
+        requirement("numpy"),
+    ],
+)
+
+internal_py_test(
+    name = "proto_builder_test",
+    srcs = ["google/protobuf/internal/proto_builder_test.py"],
+)
+
+internal_py_test(
+    name = "reflection_test",
+    srcs = ["google/protobuf/internal/reflection_test.py"],
+)
+
+internal_py_test(
+    name = "service_reflection_test",
+    srcs = ["google/protobuf/internal/service_reflection_test.py"],
+)
+
+internal_py_test(
+    name = "symbol_database_test",
+    srcs = ["google/protobuf/internal/symbol_database_test.py"],
+)
+
+internal_py_test(
+    name = "text_encoding_test",
+    srcs = ["google/protobuf/internal/text_encoding_test.py"],
+)
+
+internal_py_test(
+    name = "text_format_test",
+    srcs = ["google/protobuf/internal/text_format_test.py"],
+    data = ["//src/google/protobuf:testdata"],
+)
+
+internal_py_test(
+    name = "unknown_fields_test",
+    srcs = ["google/protobuf/internal/unknown_fields_test.py"],
+)
+
+internal_py_test(
+    name = "well_known_types_test",
+    srcs = ["google/protobuf/internal/well_known_types_test.py"],
+)
+
+internal_py_test(
+    name = "wire_format_test",
+    srcs = ["google/protobuf/internal/wire_format_test.py"],
+)
+
+cc_library(
+    name = "proto_api",
+    hdrs = ["google/protobuf/proto_api.h"],
+    visibility = ["//visibility:public"],
+    deps = [
+        "//external:python_headers",
+    ],
+)
+
+internal_py_test(
+    name = "python_version",
+    srcs = ["python_version.py"],
+)
+
+conformance_test(
+    name = "conformance_test",
+    env = {"PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": "python"},
+    failure_list = "//conformance:failure_list_python.txt",
+    target_compatible_with = select({
+        "@system_python//:none": ["@platforms//:incompatible"],
+        ":use_fast_cpp_protos": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    }),
+    testee = "//conformance:conformance_python",
+    text_format_failure_list = "//conformance:text_format_failure_list_python.txt",
+)
+
+# Note: this requires --define=use_fast_cpp_protos=true
+conformance_test(
+    name = "conformance_test_cpp",
+    env = {"PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION": "cpp"},
+    failure_list = "//conformance:failure_list_python.txt",
+    target_compatible_with = select({
+        "@system_python//:none": ["@platforms//:incompatible"],
+        ":use_fast_cpp_protos": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+    testee = "//conformance:conformance_python",
+    text_format_failure_list = "//conformance:text_format_failure_list_python_cpp.txt",
+)
+
+################################################################################
+# Distribution files
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob([
+        "google/**/*.proto",
+        "google/**/*.py",
+        "google/protobuf/internal/*.cc",
+        "google/protobuf/pyext/*.cc",
+        "google/protobuf/pyext/*.h",
+    ]) + [
+        "BUILD.bazel",
+        "MANIFEST.in",
+        "README.md",
+        "google/protobuf/proto_api.h",
+        "google/protobuf/pyext/README",
+        "google/protobuf/python_protobuf.h",
+        "internal.bzl",
+        "python_version.py",
+        "release.sh",
+        "setup.cfg",
+        "setup.py",
+        "tox.ini",
+    ],
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//pkg:__pkg__"],
+)
diff --git a/python/README.md b/python/README.md
index 27f22c8..6549fb6 100644
--- a/python/README.md
+++ b/python/README.md
@@ -30,33 +30,33 @@
 
        $ python -V
 
-2) If you do not have setuptools installed, note that it will be
+2) Make sure you have Bazel 0.5.4 or later (or CMake 3.5 or later).
+
+3) If you do not have setuptools installed, note that it will be
    downloaded and installed automatically as soon as you run `setup.py`.
    If you would rather install it manually, you may do so by following
-   the instructions on [this page](https://packaging.python.org/en/latest/installing.html#setup-for-installing-packages).
+   the instructions on [this page](https://packaging.python.org/en/latest/tutorials/installing-packages/).
 
-3) Build the C++ code, or install a binary distribution of `protoc`.  If
+4) Build the C++ code, or install a binary distribution of `protoc`.  If
    you install a binary distribution, make sure that it is the same
    version as this package.  If in doubt, run:
 
        $ protoc --version
 
-4) Build and run the tests:
+5) Build and run the tests:
 
        $ python setup.py build
        $ python setup.py test
 
    To build, test, and use the C++ implementation, you must first compile
-   `libprotobuf.so`:
-
-       $ (cd .. && make)
+   `libprotobuf.so` using either [Bazel](../README.md) or [CMake](../src/README.md):
 
    On OS X:
 
    If you are running a Homebrew-provided Python, you must make sure another
    version of protobuf is not already installed, as Homebrew's Python will
-   search `/usr/local/lib` for `libprotobuf.so` before it searches
-   `../src/.libs`.
+   search `/usr/local/lib` for `libprotobuf.so` before it searches the compiled
+   binaries.
 
    You can either unlink Homebrew's protobuf or install the `libprotobuf` you
    built earlier:
@@ -65,18 +65,18 @@
 
    or
 
-       $ (cd .. && make install)
+       $ (cd .. && cmake . && make install)
 
     On other *nix:
 
     You must make `libprotobuf.so` dynamically available. You can either
     install libprotobuf you built earlier, or set `LD_LIBRARY_PATH`:
 
-       $ export LD_LIBRARY_PATH=../src/.libs
+       $ (cd .. && cmake . && make -j20 install)
 
     or
 
-       $ (cd .. && make install)
+       $ export LD_LIBRARY_PATH=../bazel-bin
 
    To build the C++ implementation run:
 
@@ -98,7 +98,7 @@
    We do not know if or when it might be fixed.  We also do not know
    how likely it is that this bug will affect users in practice.
 
-5) Install:
+6) Install:
 
        $ python setup.py install
 
diff --git a/python/docs/google/protobuf.rst b/python/docs/google/protobuf.rst
index b26102e..6c472e1 100644
--- a/python/docs/google/protobuf.rst
+++ b/python/docs/google/protobuf.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/any_pb2.rst b/python/docs/google/protobuf/any_pb2.rst
index b6f47ef..9fca2d2 100644
--- a/python/docs/google/protobuf/any_pb2.rst
+++ b/python/docs/google/protobuf/any_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/descriptor.rst b/python/docs/google/protobuf/descriptor.rst
index 29b0774..5a8a264 100644
--- a/python/docs/google/protobuf/descriptor.rst
+++ b/python/docs/google/protobuf/descriptor.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/descriptor_database.rst b/python/docs/google/protobuf/descriptor_database.rst
index 1b8b390..660fc41 100644
--- a/python/docs/google/protobuf/descriptor_database.rst
+++ b/python/docs/google/protobuf/descriptor_database.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/descriptor_pb2.rst b/python/docs/google/protobuf/descriptor_pb2.rst
index 94eec35..9f20f49 100644
--- a/python/docs/google/protobuf/descriptor_pb2.rst
+++ b/python/docs/google/protobuf/descriptor_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/descriptor_pool.rst b/python/docs/google/protobuf/descriptor_pool.rst
index c2ee33e..aa8de30 100644
--- a/python/docs/google/protobuf/descriptor_pool.rst
+++ b/python/docs/google/protobuf/descriptor_pool.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/duration_pb2.rst b/python/docs/google/protobuf/duration_pb2.rst
index 4233e3c..9e9a032 100644
--- a/python/docs/google/protobuf/duration_pb2.rst
+++ b/python/docs/google/protobuf/duration_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/empty_pb2.rst b/python/docs/google/protobuf/empty_pb2.rst
index c386a4c..f117553 100644
--- a/python/docs/google/protobuf/empty_pb2.rst
+++ b/python/docs/google/protobuf/empty_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/field_mask_pb2.rst b/python/docs/google/protobuf/field_mask_pb2.rst
index d9d8070..1c11f46 100644
--- a/python/docs/google/protobuf/field_mask_pb2.rst
+++ b/python/docs/google/protobuf/field_mask_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/internal/containers.rst b/python/docs/google/protobuf/internal/containers.rst
index c3b8e59..67009bc 100644
--- a/python/docs/google/protobuf/internal/containers.rst
+++ b/python/docs/google/protobuf/internal/containers.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/json_format.rst b/python/docs/google/protobuf/json_format.rst
index eb3b0c5..71023fc 100644
--- a/python/docs/google/protobuf/json_format.rst
+++ b/python/docs/google/protobuf/json_format.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/message.rst b/python/docs/google/protobuf/message.rst
index a204248..c33561f 100644
--- a/python/docs/google/protobuf/message.rst
+++ b/python/docs/google/protobuf/message.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/message_factory.rst b/python/docs/google/protobuf/message_factory.rst
index 93183cc..19f6623 100644
--- a/python/docs/google/protobuf/message_factory.rst
+++ b/python/docs/google/protobuf/message_factory.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/proto_builder.rst b/python/docs/google/protobuf/proto_builder.rst
index 36243a2..718f612 100644
--- a/python/docs/google/protobuf/proto_builder.rst
+++ b/python/docs/google/protobuf/proto_builder.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/reflection.rst b/python/docs/google/protobuf/reflection.rst
index d177fc0..c806834 100644
--- a/python/docs/google/protobuf/reflection.rst
+++ b/python/docs/google/protobuf/reflection.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/service.rst b/python/docs/google/protobuf/service.rst
index 6d71f81..ddc427f 100644
--- a/python/docs/google/protobuf/service.rst
+++ b/python/docs/google/protobuf/service.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/service_reflection.rst b/python/docs/google/protobuf/service_reflection.rst
index 30f30dd..f088c17 100644
--- a/python/docs/google/protobuf/service_reflection.rst
+++ b/python/docs/google/protobuf/service_reflection.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/struct_pb2.rst b/python/docs/google/protobuf/struct_pb2.rst
index 9179eed..7b25487 100644
--- a/python/docs/google/protobuf/struct_pb2.rst
+++ b/python/docs/google/protobuf/struct_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/symbol_database.rst b/python/docs/google/protobuf/symbol_database.rst
index 6ea7352..99a8c10 100644
--- a/python/docs/google/protobuf/symbol_database.rst
+++ b/python/docs/google/protobuf/symbol_database.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/text_encoding.rst b/python/docs/google/protobuf/text_encoding.rst
index a2eb959..5a070e5 100644
--- a/python/docs/google/protobuf/text_encoding.rst
+++ b/python/docs/google/protobuf/text_encoding.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/text_format.rst b/python/docs/google/protobuf/text_format.rst
index 686b8fc..5c2c346 100644
--- a/python/docs/google/protobuf/text_format.rst
+++ b/python/docs/google/protobuf/text_format.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/timestamp_pb2.rst b/python/docs/google/protobuf/timestamp_pb2.rst
index 540df83..62e4708 100644
--- a/python/docs/google/protobuf/timestamp_pb2.rst
+++ b/python/docs/google/protobuf/timestamp_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/type_pb2.rst b/python/docs/google/protobuf/type_pb2.rst
index e9b19d7..cbd4150 100644
--- a/python/docs/google/protobuf/type_pb2.rst
+++ b/python/docs/google/protobuf/type_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/google/protobuf/unknown_fields.rst b/python/docs/google/protobuf/unknown_fields.rst
new file mode 100644
index 0000000..7ba283d
--- /dev/null
+++ b/python/docs/google/protobuf/unknown_fields.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/main/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.unknown_fields
+==============================
+
+.. automodule:: google.protobuf.unknown_fields
+   :members:
+   :inherited-members:
+   :undoc-members:
diff --git a/python/docs/google/protobuf/wrappers_pb2.rst b/python/docs/google/protobuf/wrappers_pb2.rst
index 8f29aa7..64f9cbb 100644
--- a/python/docs/google/protobuf/wrappers_pb2.rst
+++ b/python/docs/google/protobuf/wrappers_pb2.rst
@@ -5,7 +5,7 @@
    .. warning::
 
       You are reading the documentation for the `latest committed changes
-      <https://github.com/protocolbuffers/protobuf/tree/master/python>`_ of
+      <https://github.com/protocolbuffers/protobuf/tree/main/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
diff --git a/python/docs/index.rst b/python/docs/index.rst
index 5535b39..544b18e 100644
--- a/python/docs/index.rst
+++ b/python/docs/index.rst
@@ -52,6 +52,7 @@
    google/protobuf/text_format
    google/protobuf/timestamp_pb2
    google/protobuf/type_pb2
+   google/protobuf/unknown_fields
    google/protobuf/wrappers_pb2
 
 .. END REFTOC.
diff --git a/python/docs/make.bat b/python/docs/make.bat
index 27f573b..7893348 100644
--- a/python/docs/make.bat
+++ b/python/docs/make.bat
@@ -1,35 +1,35 @@
-@ECHO OFF

-

-pushd %~dp0

-

-REM Command file for Sphinx documentation

-

-if "%SPHINXBUILD%" == "" (

-	set SPHINXBUILD=sphinx-build

-)

-set SOURCEDIR=.

-set BUILDDIR=_build

-

-if "%1" == "" goto help

-

-%SPHINXBUILD% >NUL 2>NUL

-if errorlevel 9009 (

-	echo.

-	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx

-	echo.installed, then set the SPHINXBUILD environment variable to point

-	echo.to the full path of the 'sphinx-build' executable. Alternatively you

-	echo.may add the Sphinx directory to PATH.

-	echo.

-	echo.If you don't have Sphinx installed, grab it from

-	echo.http://sphinx-doc.org/

-	exit /b 1

-)

-

-%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%

-goto end

-

-:help

-%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%

-

-:end

-popd

+@ECHO OFF
+
+pushd %~dp0
+
+REM Command file for Sphinx documentation
+
+if "%SPHINXBUILD%" == "" (
+	set SPHINXBUILD=sphinx-build
+)
+set SOURCEDIR=.
+set BUILDDIR=_build
+
+if "%1" == "" goto help
+
+%SPHINXBUILD% >NUL 2>NUL
+if errorlevel 9009 (
+	echo.
+	echo.The 'sphinx-build' command was not found. Make sure you have Sphinx
+	echo.installed, then set the SPHINXBUILD environment variable to point
+	echo.to the full path of the 'sphinx-build' executable. Alternatively you
+	echo.may add the Sphinx directory to PATH.
+	echo.
+	echo.If you don't have Sphinx installed, grab it from
+	echo.http://sphinx-doc.org/
+	exit /b 1
+)
+
+%SPHINXBUILD% -M %1 %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+goto end
+
+:help
+%SPHINXBUILD% -M help %SOURCEDIR% %BUILDDIR% %SPHINXOPTS%
+
+:end
+popd
diff --git a/python/docs/requirements.txt b/python/docs/requirements.txt
index 0049dfb..784c889 100644
--- a/python/docs/requirements.txt
+++ b/python/docs/requirements.txt
@@ -1,5 +1,5 @@
 googleapis-common-protos==1.56.1
 jinja2==3.0.0
-sphinx==2.3.1
+sphinx==3.0.4
 sphinx_rtd_theme==0.4.3
 sphinxcontrib-napoleon==0.7
diff --git a/python/google/protobuf/descriptor.py b/python/google/protobuf/descriptor.py
old mode 100644
new mode 100755
index f5a0caa..e5d547a
--- a/python/google/protobuf/descriptor.py
+++ b/python/google/protobuf/descriptor.py
@@ -66,6 +66,7 @@
   # and make it return True when the descriptor is an instance of the extension
   # type written in C++.
   class DescriptorMetaclass(type):
+
     def __instancecheck__(cls, obj):
       if super(DescriptorMetaclass, cls).__instancecheck__(obj):
         return True
@@ -633,13 +634,29 @@
     if (self.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE or
         self.containing_oneof):
       return True
-    if hasattr(self.file, 'syntax'):
-      return self.file.syntax == 'proto2'
-    if hasattr(self.message_type, 'syntax'):
-      return self.message_type.syntax == 'proto2'
-    raise RuntimeError(
-        'has_presence is not ready to use because field %s is not'
-        ' linked with message type nor file' % self.full_name)
+    # self.containing_type is used here instead of self.file for legacy
+    # compatibility. FieldDescriptor.file was added in cl/153110619
+    # Some old/generated code didn't link file to FieldDescriptor.
+    # TODO(jieluo): remove syntax usage b/240619313
+    return self.containing_type.syntax == 'proto2'
+
+  @property
+  def is_packed(self):
+    """Returns if the field is packed."""
+    if self.label != FieldDescriptor.LABEL_REPEATED:
+      return False
+    field_type = self.type
+    if (field_type == FieldDescriptor.TYPE_STRING or
+        field_type == FieldDescriptor.TYPE_GROUP or
+        field_type == FieldDescriptor.TYPE_MESSAGE or
+        field_type == FieldDescriptor.TYPE_BYTES):
+      return False
+    if self.containing_type.syntax == 'proto2':
+      return self.has_options and self.GetOptions().packed
+    else:
+      return (not self.has_options or
+              not self.GetOptions().HasField('packed') or
+              self.GetOptions().packed)
 
   @staticmethod
   def ProtoTypeToCppProtoType(proto_type):
@@ -720,6 +737,18 @@
     # Values are reversed to ensure that the first alias is retained.
     self.values_by_number = dict((v.number, v) for v in reversed(values))
 
+  @property
+  def is_closed(self):
+    """If the enum is closed.
+
+    closed enum means:
+      - Has a fixed set of named values.
+      - Encountering values not in this set causes them to be treated as
+        unknown fields.
+      - The first value (i.e., the default) may be nonzero.
+    """
+    return self.file.syntax == 'proto2'
+
   def CopyToProto(self, proto):
     """Copies this to a descriptor_pb2.EnumDescriptorProto.
 
@@ -873,11 +902,14 @@
 
     Args:
       name (str): Name of the method.
+
     Returns:
-      MethodDescriptor or None: the descriptor for the requested method, if
-      found.
+      MethodDescriptor: The descriptor for the requested method.
+
+    Raises:
+      KeyError: if the method cannot be found in the service.
     """
-    return self.methods_by_name.get(name, None)
+    return self.methods_by_name[name]
 
   def CopyToProto(self, proto):
     """Copies this to a descriptor_pb2.ServiceDescriptorProto.
@@ -1018,13 +1050,7 @@
       # FileDescriptor() is called from various places, not only from generated
       # files, to register dynamic proto files and messages.
       # pylint: disable=g-explicit-bool-comparison
-      if serialized_pb == b'':
-        # Cpp generated code must be linked in if serialized_pb is ''
-        try:
-          return _message.default_pool.FindFileByName(name)
-        except KeyError:
-          raise RuntimeError('Please link in cpp generated lib for %s' % (name))
-      elif serialized_pb:
+      if serialized_pb:
         return _message.default_pool.AddSerializedFile(serialized_pb)
       else:
         return super(FileDescriptor, cls).__new__(cls)
diff --git a/python/google/protobuf/descriptor_pool.py b/python/google/protobuf/descriptor_pool.py
index 911372a..dccac5e 100644
--- a/python/google/protobuf/descriptor_pool.py
+++ b/python/google/protobuf/descriptor_pool.py
@@ -144,9 +144,6 @@
     self._service_descriptors = {}
     self._file_descriptors = {}
     self._toplevel_extensions = {}
-    # TODO(jieluo): Remove _file_desc_by_toplevel_extension after
-    # maybe year 2020 for compatibility issue (with 3.4.1 only).
-    self._file_desc_by_toplevel_extension = {}
     self._top_enum_values = {}
     # We store extensions in two two-level mappings: The first key is the
     # descriptor of the message being extended, the second key is the extension
@@ -220,7 +217,7 @@
     file_desc.serialized_pb = serialized_file_desc_proto
     return file_desc
 
-  # Add Descriptor to descriptor pool is dreprecated. Please use Add()
+  # Add Descriptor to descriptor pool is deprecated. Please use Add()
   # or AddSerializedFile() to add a FileDescriptorProto instead.
   @_Deprecated
   def AddDescriptor(self, desc):
@@ -245,7 +242,7 @@
     self._descriptors[desc.full_name] = desc
     self._AddFileDescriptor(desc.file)
 
-  # Add EnumDescriptor to descriptor pool is dreprecated. Please use Add()
+  # Add EnumDescriptor to descriptor pool is deprecated. Please use Add()
   # or AddSerializedFile() to add a FileDescriptorProto instead.
   @_Deprecated
   def AddEnumDescriptor(self, enum_desc):
@@ -286,7 +283,7 @@
         self._top_enum_values[full_name] = enum_value
     self._AddFileDescriptor(enum_desc.file)
 
-  # Add ServiceDescriptor to descriptor pool is dreprecated. Please use Add()
+  # Add ServiceDescriptor to descriptor pool is deprecated. Please use Add()
   # or AddSerializedFile() to add a FileDescriptorProto instead.
   @_Deprecated
   def AddServiceDescriptor(self, service_desc):
@@ -307,7 +304,7 @@
                                 service_desc.file.name)
     self._service_descriptors[service_desc.full_name] = service_desc
 
-  # Add ExtensionDescriptor to descriptor pool is dreprecated. Please use Add()
+  # Add ExtensionDescriptor to descriptor pool is deprecated. Please use Add()
   # or AddSerializedFile() to add a FileDescriptorProto instead.
   @_Deprecated
   def AddExtensionDescriptor(self, extension):
@@ -331,6 +328,8 @@
       raise TypeError('Expected an extension descriptor.')
 
     if extension.extension_scope is None:
+      self._CheckConflictRegister(
+          extension, extension.full_name, extension.file.name)
       self._toplevel_extensions[extension.full_name] = extension
 
     try:
@@ -372,12 +371,6 @@
     """
 
     self._AddFileDescriptor(file_desc)
-    # TODO(jieluo): This is a temporary solution for FieldDescriptor.file.
-    # FieldDescriptor.file is added in code gen. Remove this solution after
-    # maybe 2020 for compatibility reason (with 3.4.1 only).
-    for extension in file_desc.extensions_by_name.values():
-      self._file_desc_by_toplevel_extension[
-          extension.full_name] = file_desc
 
   def _AddFileDescriptor(self, file_desc):
     """Adds a FileDescriptor to the pool, non-recursively.
@@ -483,7 +476,7 @@
       pass
 
     try:
-      return self._file_desc_by_toplevel_extension[symbol]
+      return self._toplevel_extensions[symbol].file
     except KeyError:
       pass
 
@@ -792,8 +785,6 @@
                            file_descriptor.package, scope)
         file_descriptor.extensions_by_name[extension_desc.name] = (
             extension_desc)
-        self._file_desc_by_toplevel_extension[extension_desc.full_name] = (
-            file_descriptor)
 
       for desc_proto in file_proto.message_type:
         self._SetAllFieldTypes(file_proto.package, desc_proto, scope)
diff --git a/python/google/protobuf/internal/any_test.proto b/python/google/protobuf/internal/any_test.proto
index 1a563fd..60c29d1 100644
--- a/python/google/protobuf/internal/any_test.proto
+++ b/python/google/protobuf/internal/any_test.proto
@@ -39,7 +39,7 @@
 message TestAny {
   optional google.protobuf.Any value = 1;
   optional int32 int_value = 2;
-  map<string,int32> map_value = 3;
+  map<string, int32> map_value = 3;
   extensions 10 to max;
 }
 
diff --git a/python/google/protobuf/internal/api_implementation.py b/python/google/protobuf/internal/api_implementation.py
old mode 100644
new mode 100755
index 7458648..e4f7687
--- a/python/google/protobuf/internal/api_implementation.py
+++ b/python/google/protobuf/internal/api_implementation.py
@@ -102,6 +102,7 @@
   try:
     # pylint: disable=g-import-not-at-top
     from google.protobuf.pyext import _message
+    sys.modules['google.protobuf.internal.cpp._message'] = _message
     _c_module = _message
     del _message
   except ImportError:
@@ -151,12 +152,6 @@
   return _implementation_type
 
 
-def _SetType(implementation_type):
-  """Never use! Only for protobuf benchmark."""
-  global _implementation_type
-  _implementation_type = implementation_type
-
-
 # See comment on 'Type' above.
 # TODO(jieluo): Remove the API, it returns a constant. b/228102101
 def Version():
diff --git a/python/google/protobuf/internal/containers.py b/python/google/protobuf/internal/containers.py
old mode 100644
new mode 100755
diff --git a/python/google/protobuf/internal/decoder.py b/python/google/protobuf/internal/decoder.py
old mode 100644
new mode 100755
diff --git a/python/google/protobuf/internal/descriptor_database_test.py b/python/google/protobuf/internal/descriptor_database_test.py
index 3c086b9..f7bc719 100644
--- a/python/google/protobuf/internal/descriptor_database_test.py
+++ b/python/google/protobuf/internal/descriptor_database_test.py
@@ -35,12 +35,12 @@
 import unittest
 import warnings
 
-from google.protobuf import unittest_pb2
 from google.protobuf import descriptor_pb2
 from google.protobuf.internal import factory_test2_pb2
 from google.protobuf.internal import no_package_pb2
 from google.protobuf.internal import testing_refleaks
 from google.protobuf import descriptor_database
+from google.protobuf import unittest_pb2
 
 
 @testing_refleaks.TestCase
@@ -119,9 +119,9 @@
       self.assertIs(w[0].category, RuntimeWarning)
       self.assertIn('Conflict register for file "other_file2": ',
                     str(w[0].message))
-      self.assertIn('already defined in file '
-                    '"google/protobuf/unittest.proto"',
-                    str(w[0].message))
+      self.assertIn(
+          'already defined in file '
+          '"google/protobuf/unittest.proto"', str(w[0].message))
 
 if __name__ == '__main__':
   unittest.main()
diff --git a/python/google/protobuf/internal/descriptor_pool_test.py b/python/google/protobuf/internal/descriptor_pool_test.py
index 9e451b4..3305b18 100644
--- a/python/google/protobuf/internal/descriptor_pool_test.py
+++ b/python/google/protobuf/internal/descriptor_pool_test.py
@@ -33,13 +33,9 @@
 __author__ = 'matthewtoia@google.com (Matt Toia)'
 
 import copy
-import os
 import unittest
 import warnings
 
-from google.protobuf import unittest_import_pb2
-from google.protobuf import unittest_import_public_pb2
-from google.protobuf import unittest_pb2
 from google.protobuf import descriptor_pb2
 from google.protobuf.internal import api_implementation
 from google.protobuf.internal import descriptor_pool_test1_pb2
@@ -55,7 +51,9 @@
 from google.protobuf import descriptor_pool
 from google.protobuf import message_factory
 from google.protobuf import symbol_database
-
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_import_public_pb2
+from google.protobuf import unittest_pb2
 
 
 warnings.simplefilter('error', DeprecationWarning)
@@ -415,6 +413,19 @@
     field = file_json.message_types_by_name['class'].fields_by_name['int_field']
     self.assertEqual(field.json_name, 'json_int')
 
+  def testAddSerializedFileTwice(self):
+    if isinstance(self, SecondaryDescriptorFromDescriptorDB):
+      if api_implementation.Type() != 'python':
+        # Cpp extension cannot call Add on a DescriptorPool
+        # that uses a DescriptorDatabase.
+        # TODO(jieluo): Fix python and cpp extension diff.
+        return
+    self.pool = descriptor_pool.DescriptorPool()
+    file1_first = self.pool.AddSerializedFile(
+        self.factory_test1_fd.SerializeToString())
+    file1_again = self.pool.AddSerializedFile(
+        self.factory_test1_fd.SerializeToString())
+    self.assertIs(file1_first, file1_again)
 
   def testEnumDefaultValue(self):
     """Test the default value of enums which don't start at zero."""
@@ -1115,33 +1126,49 @@
 
 TEST2_FILE = ProtoFile(
     'google/protobuf/internal/descriptor_pool_test2.proto',
-    'google.protobuf.python.internal',
-    {
-        'DescriptorPoolTest3': MessageType({
-            'NestedEnum': EnumType([('NU', 13), ('XI', 14)]),
-            'NestedMessage': MessageType({
-                'NestedEnum': EnumType([('OMICRON', 15), ('PI', 16)]),
-                'DeepNestedMessage': MessageType({
-                    'NestedEnum': EnumType([('RHO', 17), ('SIGMA', 18)]),
+    'google.protobuf.python.internal', {
+        'DescriptorPoolTest3':
+            MessageType(
+                {
+                    'NestedEnum':
+                        EnumType([('NU', 13), ('XI', 14)]),
+                    'NestedMessage':
+                        MessageType(
+                            {
+                                'NestedEnum':
+                                    EnumType([('OMICRON', 15), ('PI', 16)]),
+                                'DeepNestedMessage':
+                                    MessageType(
+                                        {
+                                            'NestedEnum':
+                                                EnumType([('RHO', 17),
+                                                          ('SIGMA', 18)]),
+                                        }, [
+                                            ('nested_enum',
+                                             EnumField(1, 'NestedEnum', 'RHO')),
+                                            ('nested_field',
+                                             StringField(2, 'sigma')),
+                                        ]),
+                            }, [
+                                ('nested_enum', EnumField(
+                                    1, 'NestedEnum', 'PI')),
+                                ('nested_field', StringField(2, 'nu')),
+                                ('deep_nested_message',
+                                 MessageField(3, 'DeepNestedMessage')),
+                            ])
                 }, [
-                    ('nested_enum', EnumField(1, 'NestedEnum', 'RHO')),
-                    ('nested_field', StringField(2, 'sigma')),
+                    ('nested_enum', EnumField(1, 'NestedEnum', 'XI')),
+                    ('nested_message', MessageField(2, 'NestedMessage')),
+                ],
+                extensions=[
+                    ('descriptor_pool_test',
+                     ExtensionField(1001, 'DescriptorPoolTest1')),
                 ]),
-            }, [
-                ('nested_enum', EnumField(1, 'NestedEnum', 'PI')),
-                ('nested_field', StringField(2, 'nu')),
-                ('deep_nested_message', MessageField(3, 'DeepNestedMessage')),
-            ])
-        }, [
-            ('nested_enum', EnumField(1, 'NestedEnum', 'XI')),
-            ('nested_message', MessageField(2, 'NestedMessage')),
-        ], extensions=[
-            ('descriptor_pool_test',
-             ExtensionField(1001, 'DescriptorPoolTest1')),
-        ]),
     },
-    dependencies=['google/protobuf/internal/descriptor_pool_test1.proto',
-                  'google/protobuf/internal/more_messages.proto'],
+    dependencies=[
+        'google/protobuf/internal/more_messages.proto',
+        'google/protobuf/internal/descriptor_pool_test1.proto',
+    ],
     public_dependencies=['google/protobuf/internal/more_messages.proto'])
 
 
diff --git a/python/google/protobuf/internal/descriptor_pool_test1.proto b/python/google/protobuf/internal/descriptor_pool_test1.proto
index 00816b7..f52e139 100644
--- a/python/google/protobuf/internal/descriptor_pool_test1.proto
+++ b/python/google/protobuf/internal/descriptor_pool_test1.proto
@@ -32,7 +32,6 @@
 
 package google.protobuf.python.internal;
 
-
 message DescriptorPoolTest1 {
   extensions 1000 to max;
 
diff --git a/python/google/protobuf/internal/descriptor_pool_test2.proto b/python/google/protobuf/internal/descriptor_pool_test2.proto
index a218ecc..dd4924d 100644
--- a/python/google/protobuf/internal/descriptor_pool_test2.proto
+++ b/python/google/protobuf/internal/descriptor_pool_test2.proto
@@ -32,12 +32,11 @@
 
 package google.protobuf.python.internal;
 
-import "google/protobuf/internal/descriptor_pool_test1.proto";
 import public "google/protobuf/internal/more_messages.proto";
 
+import "google/protobuf/internal/descriptor_pool_test1.proto";
 
 message DescriptorPoolTest3 {
-
   extend DescriptorPoolTest1 {
     optional DescriptorPoolTest3 descriptor_pool_test = 1001;
   }
@@ -70,4 +69,3 @@
 
   optional NestedMessage nested_message = 2;
 }
-
diff --git a/python/google/protobuf/internal/descriptor_test.py b/python/google/protobuf/internal/descriptor_test.py
index 6a8532c..614a845 100644
--- a/python/google/protobuf/internal/descriptor_test.py
+++ b/python/google/protobuf/internal/descriptor_test.py
@@ -35,9 +35,6 @@
 import unittest
 import warnings
 
-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.internal import api_implementation
 from google.protobuf.internal import test_util
@@ -45,6 +42,9 @@
 from google.protobuf import descriptor_pool
 from google.protobuf import symbol_database
 from google.protobuf import text_format
+from google.protobuf import unittest_custom_options_pb2
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_pb2
 
 
 TEST_EMPTY_MESSAGE_DESCRIPTOR_ASCII = """
@@ -118,6 +118,112 @@
   def GetDescriptorPool(self):
     return symbol_database.Default().pool
 
+  def testMissingPackage(self):
+    file_proto = descriptor_pb2.FileDescriptorProto(
+        name='some/filename/some.proto')
+    serialized = file_proto.SerializeToString()
+    pool = descriptor_pool.DescriptorPool()
+    file_descriptor = pool.AddSerializedFile(serialized)
+    self.assertEqual('', file_descriptor.package)
+
+  def testEmptyPackage(self):
+    file_proto = descriptor_pb2.FileDescriptorProto(
+        name='some/filename/some.proto', package='')
+    serialized = file_proto.SerializeToString()
+    pool = descriptor_pool.DescriptorPool()
+    file_descriptor = pool.AddSerializedFile(serialized)
+    self.assertEqual('', file_descriptor.package)
+
+  def testReservedName(self):
+    text = """
+      name: "foo.proto"
+      message_type {
+        name: "BrokenMessageFoo"
+        reserved_name: "is_deprecated"
+      }
+      """
+
+    fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto())
+    serialized = fdp.SerializeToString()
+    # AddSerializedFile() will allow duplicate adds but only if the descriptors
+    # are identical and can round-trip through a FileDescriptor losslessly.
+    desc1 = descriptor_pool.Default().AddSerializedFile(serialized)
+    desc2 = descriptor_pool.Default().AddSerializedFile(serialized)
+    self.assertEqual(desc1, desc2)
+
+  def testReservedRange(self):
+    text = """
+      name: "bar.proto"
+      message_type {
+        name: "BrokenMessageBar"
+        reserved_range {
+          start: 101
+          end: 102
+        }
+      }
+      """
+
+    fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto())
+    serialized = fdp.SerializeToString()
+    # AddSerializedFile() will allow duplicate adds but only if the descriptors
+    # are identical and can round-trip through a FileDescriptor losslessly.
+    desc1 = descriptor_pool.Default().AddSerializedFile(serialized)
+    desc2 = descriptor_pool.Default().AddSerializedFile(serialized)
+    self.assertEqual(desc1, desc2)
+
+  def testReservedNameEnum(self):
+    text = """
+      name: "baz.proto"
+      enum_type {
+        name: "BrokenMessageBaz"
+        value: <
+          name: 'ENUM_BAZ'
+          number: 114
+        >
+        reserved_name: "is_deprecated"
+      }
+      """
+
+    fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto())
+    serialized = fdp.SerializeToString()
+    # AddSerializedFile() will allow duplicate adds but only if the descriptors
+    # are identical and can round-trip through a FileDescriptor losslessly.
+    desc1 = descriptor_pool.Default().AddSerializedFile(serialized)
+    desc2 = descriptor_pool.Default().AddSerializedFile(serialized)
+    self.assertEqual(desc1, desc2)
+
+  def testReservedRangeEnum(self):
+    text = """
+      name: "bat.proto"
+      enum_type {
+        name: "BrokenMessageBat"
+        value: <
+          name: 'ENUM_BAT'
+          number: 115
+        >
+        reserved_range {
+          start: 1001
+          end: 1002
+        }
+      }
+      """
+
+    fdp = text_format.Parse(text, descriptor_pb2.FileDescriptorProto())
+    serialized = fdp.SerializeToString()
+    # AddSerializedFile() will allow duplicate adds but only if the descriptors
+    # are identical and can round-trip through a FileDescriptor losslessly.
+    desc1 = descriptor_pool.Default().AddSerializedFile(serialized)
+    desc2 = descriptor_pool.Default().AddSerializedFile(serialized)
+    self.assertEqual(desc1, desc2)
+
+  def testFindMethodByName(self):
+    service_descriptor = (unittest_custom_options_pb2.
+                          TestServiceWithCustomOptions.DESCRIPTOR)
+    method_descriptor = service_descriptor.FindMethodByName('Foo')
+    self.assertEqual(method_descriptor.name, 'Foo')
+    with self.assertRaises(KeyError):
+      service_descriptor.FindMethodByName('MethodDoesNotExist')
+
   def testEnumValueName(self):
     self.assertEqual(self.my_message.EnumValueName('ForeignEnum', 4),
                      'FOREIGN_FOO')
@@ -448,7 +554,6 @@
     self.assertEqual(self.my_file.package, 'protobuf_unittest')
     self.assertEqual(self.my_file.pool, self.pool)
     self.assertFalse(self.my_file.has_options)
-    self.assertEqual('proto2', self.my_file.syntax)
     file_proto = descriptor_pb2.FileDescriptorProto()
     self.my_file.CopyToProto(file_proto)
     self.assertEqual(self.my_file.serialized_pb,
@@ -595,6 +700,12 @@
   def CheckDescriptorMapping(self, mapping):
     # Verifies that a property like 'messageDescriptor.fields' has all the
     # properties of an immutable abc.Mapping.
+    iterated_keys = []
+    for key in mapping:
+      iterated_keys.append(key)
+    self.assertEqual(len(iterated_keys), len(mapping))
+    self.assertEqual(set(iterated_keys), set(mapping.keys()))
+
     self.assertNotEqual(
         mapping, unittest_pb2.TestAllExtensions.DESCRIPTOR.fields_by_name)
     self.assertNotEqual(mapping, {})
@@ -611,10 +722,15 @@
     with self.assertRaises(TypeError):
       mapping.get()
     # TODO(jieluo): Fix python and cpp extension diff.
-    if api_implementation.Type() == 'python':
-      self.assertRaises(TypeError, mapping.get, [])
-    else:
+    if api_implementation.Type() == 'cpp':
       self.assertEqual(None, mapping.get([]))
+    else:
+      self.assertRaises(TypeError, mapping.get, [])
+      with self.assertRaises(TypeError):
+        if [] in mapping:
+          pass
+      with self.assertRaises(TypeError):
+        _ = mapping[[]]
     # keys(), iterkeys() &co
     item = (next(iter(mapping.keys())), next(iter(mapping.values())))
     self.assertEqual(item, next(iter(mapping.items())))
@@ -626,10 +742,12 @@
     self.assertRaises(KeyError, mapping.__getitem__, 'key_error')
     self.assertRaises(KeyError, mapping.__getitem__, len(mapping) + 1)
     # TODO(jieluo): Add __repr__ support for DescriptorMapping.
-    if api_implementation.Type() == 'python':
-      self.assertEqual(len(str(dict(mapping.items()))), len(str(mapping)))
-    else:
+    if api_implementation.Type() == 'cpp':
       self.assertEqual(str(mapping)[0], '<')
+    else:
+      print(str(dict(mapping.items()))[:100])
+      print(str(mapping)[:100])
+      self.assertEqual(len(str(dict(mapping.items()))), len(str(mapping)))
 
   def testDescriptor(self):
     message_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
@@ -786,6 +904,25 @@
           deprecated: true
         >
       >
+      field: {
+        name: 'deprecated_repeated_string'
+        number: 4
+        label: LABEL_REPEATED
+        type: TYPE_STRING
+        options: {
+          deprecated: true
+        }
+      }
+      field {
+        name: "deprecated_message"
+        number: 3
+        label: LABEL_OPTIONAL
+        type: TYPE_MESSAGE
+        type_name: ".protobuf_unittest.TestAllTypes.NestedMessage"
+        options {
+          deprecated: true
+        }
+      }
       field {
         name: "deprecated_int32_in_oneof"
         number: 2
@@ -796,6 +933,13 @@
         }
         oneof_index: 0
       }
+      field {
+        name: "nested"
+        number: 5
+        label: LABEL_OPTIONAL
+        type: TYPE_MESSAGE
+        type_name: ".protobuf_unittest.TestDeprecatedFields"
+      }
       oneof_decl {
         name: "oneof_fields"
       }
diff --git a/python/google/protobuf/internal/encoder.py b/python/google/protobuf/internal/encoder.py
old mode 100644
new mode 100755
diff --git a/python/google/protobuf/internal/factory_test2.proto b/python/google/protobuf/internal/factory_test2.proto
index 5fcbc5a..f1e8500 100644
--- a/python/google/protobuf/internal/factory_test2.proto
+++ b/python/google/protobuf/internal/factory_test2.proto
@@ -36,7 +36,6 @@
 
 import "google/protobuf/internal/factory_test1.proto";
 
-
 enum Factory2Enum {
   FACTORY_2_VALUE_0 = 0;
   FACTORY_2_VALUE_1 = 1;
@@ -73,7 +72,6 @@
   optional Factory2Enum enum_with_default = 20 [default = FACTORY_2_VALUE_1];
   optional bytes bytes_with_default = 21 [default = "a\373\000c"];
 
-
   extend Factory1Message {
     optional string one_more_field = 1001;
   }
@@ -100,5 +98,6 @@
 
 message MessageWithOption {
   option no_standard_descriptor_accessor = true;
+
   optional int32 field1 = 1;
 }
diff --git a/python/google/protobuf/internal/field_mask.py b/python/google/protobuf/internal/field_mask.py
new file mode 100644
index 0000000..4897699
--- /dev/null
+++ b/python/google/protobuf/internal/field_mask.py
@@ -0,0 +1,333 @@
+# 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.
+
+"""Contains FieldMask class."""
+
+from google.protobuf.descriptor import FieldDescriptor
+
+
+class FieldMask(object):
+  """Class for FieldMask message type."""
+
+  __slots__ = ()
+
+  def ToJsonString(self):
+    """Converts FieldMask to string according to proto3 JSON spec."""
+    camelcase_paths = []
+    for path in self.paths:
+      camelcase_paths.append(_SnakeCaseToCamelCase(path))
+    return ','.join(camelcase_paths)
+
+  def FromJsonString(self, value):
+    """Converts string to FieldMask according to proto3 JSON spec."""
+    if not isinstance(value, str):
+      raise ValueError('FieldMask JSON value not a string: {!r}'.format(value))
+    self.Clear()
+    if value:
+      for path in value.split(','):
+        self.paths.append(_CamelCaseToSnakeCase(path))
+
+  def IsValidForDescriptor(self, message_descriptor):
+    """Checks whether the FieldMask is valid for Message Descriptor."""
+    for path in self.paths:
+      if not _IsValidPath(message_descriptor, path):
+        return False
+    return True
+
+  def AllFieldsFromDescriptor(self, message_descriptor):
+    """Gets all direct fields of Message Descriptor to FieldMask."""
+    self.Clear()
+    for field in message_descriptor.fields:
+      self.paths.append(field.name)
+
+  def CanonicalFormFromMask(self, mask):
+    """Converts a FieldMask to the canonical form.
+
+    Removes paths that are covered by another path. For example,
+    "foo.bar" is covered by "foo" and will be removed if "foo"
+    is also in the FieldMask. Then sorts all paths in alphabetical order.
+
+    Args:
+      mask: The original FieldMask to be converted.
+    """
+    tree = _FieldMaskTree(mask)
+    tree.ToFieldMask(self)
+
+  def Union(self, mask1, mask2):
+    """Merges mask1 and mask2 into this FieldMask."""
+    _CheckFieldMaskMessage(mask1)
+    _CheckFieldMaskMessage(mask2)
+    tree = _FieldMaskTree(mask1)
+    tree.MergeFromFieldMask(mask2)
+    tree.ToFieldMask(self)
+
+  def Intersect(self, mask1, mask2):
+    """Intersects mask1 and mask2 into this FieldMask."""
+    _CheckFieldMaskMessage(mask1)
+    _CheckFieldMaskMessage(mask2)
+    tree = _FieldMaskTree(mask1)
+    intersection = _FieldMaskTree()
+    for path in mask2.paths:
+      tree.IntersectPath(path, intersection)
+    intersection.ToFieldMask(self)
+
+  def MergeMessage(
+      self, source, destination,
+      replace_message_field=False, replace_repeated_field=False):
+    """Merges fields specified in FieldMask from source to destination.
+
+    Args:
+      source: Source message.
+      destination: The destination message to be merged into.
+      replace_message_field: Replace message field if True. Merge message
+          field if False.
+      replace_repeated_field: Replace repeated field if True. Append
+          elements of repeated field if False.
+    """
+    tree = _FieldMaskTree(self)
+    tree.MergeMessage(
+        source, destination, replace_message_field, replace_repeated_field)
+
+
+def _IsValidPath(message_descriptor, path):
+  """Checks whether the path is valid for Message Descriptor."""
+  parts = path.split('.')
+  last = parts.pop()
+  for name in parts:
+    field = message_descriptor.fields_by_name.get(name)
+    if (field is None or
+        field.label == FieldDescriptor.LABEL_REPEATED or
+        field.type != FieldDescriptor.TYPE_MESSAGE):
+      return False
+    message_descriptor = field.message_type
+  return last in message_descriptor.fields_by_name
+
+
+def _CheckFieldMaskMessage(message):
+  """Raises ValueError if message is not a FieldMask."""
+  message_descriptor = message.DESCRIPTOR
+  if (message_descriptor.name != 'FieldMask' or
+      message_descriptor.file.name != 'google/protobuf/field_mask.proto'):
+    raise ValueError('Message {0} is not a FieldMask.'.format(
+        message_descriptor.full_name))
+
+
+def _SnakeCaseToCamelCase(path_name):
+  """Converts a path name from snake_case to camelCase."""
+  result = []
+  after_underscore = False
+  for c in path_name:
+    if c.isupper():
+      raise ValueError(
+          'Fail to print FieldMask to Json string: Path name '
+          '{0} must not contain uppercase letters.'.format(path_name))
+    if after_underscore:
+      if c.islower():
+        result.append(c.upper())
+        after_underscore = False
+      else:
+        raise ValueError(
+            'Fail to print FieldMask to Json string: The '
+            'character after a "_" must be a lowercase letter '
+            'in path name {0}.'.format(path_name))
+    elif c == '_':
+      after_underscore = True
+    else:
+      result += c
+
+  if after_underscore:
+    raise ValueError('Fail to print FieldMask to Json string: Trailing "_" '
+                     'in path name {0}.'.format(path_name))
+  return ''.join(result)
+
+
+def _CamelCaseToSnakeCase(path_name):
+  """Converts a field name from camelCase to snake_case."""
+  result = []
+  for c in path_name:
+    if c == '_':
+      raise ValueError('Fail to parse FieldMask: Path name '
+                       '{0} must not contain "_"s.'.format(path_name))
+    if c.isupper():
+      result += '_'
+      result += c.lower()
+    else:
+      result += c
+  return ''.join(result)
+
+
+class _FieldMaskTree(object):
+  """Represents a FieldMask in a tree structure.
+
+  For example, given a FieldMask "foo.bar,foo.baz,bar.baz",
+  the FieldMaskTree will be:
+      [_root] -+- foo -+- bar
+            |       |
+            |       +- baz
+            |
+            +- bar --- baz
+  In the tree, each leaf node represents a field path.
+  """
+
+  __slots__ = ('_root',)
+
+  def __init__(self, field_mask=None):
+    """Initializes the tree by FieldMask."""
+    self._root = {}
+    if field_mask:
+      self.MergeFromFieldMask(field_mask)
+
+  def MergeFromFieldMask(self, field_mask):
+    """Merges a FieldMask to the tree."""
+    for path in field_mask.paths:
+      self.AddPath(path)
+
+  def AddPath(self, path):
+    """Adds a field path into the tree.
+
+    If the field path to add is a sub-path of an existing field path
+    in the tree (i.e., a leaf node), it means the tree already matches
+    the given path so nothing will be added to the tree. If the path
+    matches an existing non-leaf node in the tree, that non-leaf node
+    will be turned into a leaf node with all its children removed because
+    the path matches all the node's children. Otherwise, a new path will
+    be added.
+
+    Args:
+      path: The field path to add.
+    """
+    node = self._root
+    for name in path.split('.'):
+      if name not in node:
+        node[name] = {}
+      elif not node[name]:
+        # Pre-existing empty node implies we already have this entire tree.
+        return
+      node = node[name]
+    # Remove any sub-trees we might have had.
+    node.clear()
+
+  def ToFieldMask(self, field_mask):
+    """Converts the tree to a FieldMask."""
+    field_mask.Clear()
+    _AddFieldPaths(self._root, '', field_mask)
+
+  def IntersectPath(self, path, intersection):
+    """Calculates the intersection part of a field path with this tree.
+
+    Args:
+      path: The field path to calculates.
+      intersection: The out tree to record the intersection part.
+    """
+    node = self._root
+    for name in path.split('.'):
+      if name not in node:
+        return
+      elif not node[name]:
+        intersection.AddPath(path)
+        return
+      node = node[name]
+    intersection.AddLeafNodes(path, node)
+
+  def AddLeafNodes(self, prefix, node):
+    """Adds leaf nodes begin with prefix to this tree."""
+    if not node:
+      self.AddPath(prefix)
+    for name in node:
+      child_path = prefix + '.' + name
+      self.AddLeafNodes(child_path, node[name])
+
+  def MergeMessage(
+      self, source, destination,
+      replace_message, replace_repeated):
+    """Merge all fields specified by this tree from source to destination."""
+    _MergeMessage(
+        self._root, source, destination, replace_message, replace_repeated)
+
+
+def _StrConvert(value):
+  """Converts value to str if it is not."""
+  # This file is imported by c extension and some methods like ClearField
+  # requires string for the field name. py2/py3 has different text
+  # type and may use unicode.
+  if not isinstance(value, str):
+    return value.encode('utf-8')
+  return value
+
+
+def _MergeMessage(
+    node, source, destination, replace_message, replace_repeated):
+  """Merge all fields specified by a sub-tree from source to destination."""
+  source_descriptor = source.DESCRIPTOR
+  for name in node:
+    child = node[name]
+    field = source_descriptor.fields_by_name[name]
+    if field is None:
+      raise ValueError('Error: Can\'t find field {0} in message {1}.'.format(
+          name, source_descriptor.full_name))
+    if child:
+      # Sub-paths are only allowed for singular message fields.
+      if (field.label == FieldDescriptor.LABEL_REPEATED or
+          field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE):
+        raise ValueError('Error: Field {0} in message {1} is not a singular '
+                         'message field and cannot have sub-fields.'.format(
+                             name, source_descriptor.full_name))
+      if source.HasField(name):
+        _MergeMessage(
+            child, getattr(source, name), getattr(destination, name),
+            replace_message, replace_repeated)
+      continue
+    if field.label == FieldDescriptor.LABEL_REPEATED:
+      if replace_repeated:
+        destination.ClearField(_StrConvert(name))
+      repeated_source = getattr(source, name)
+      repeated_destination = getattr(destination, name)
+      repeated_destination.MergeFrom(repeated_source)
+    else:
+      if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
+        if replace_message:
+          destination.ClearField(_StrConvert(name))
+        if source.HasField(name):
+          getattr(destination, name).MergeFrom(getattr(source, name))
+      else:
+        setattr(destination, name, getattr(source, name))
+
+
+def _AddFieldPaths(node, prefix, field_mask):
+  """Adds the field paths descended from node to field_mask."""
+  if not node and prefix:
+    field_mask.paths.append(prefix)
+    return
+  for name in sorted(node):
+    if prefix:
+      child_path = prefix + '.' + name
+    else:
+      child_path = name
+    _AddFieldPaths(node[name], child_path, field_mask)
diff --git a/python/google/protobuf/internal/field_mask_test.py b/python/google/protobuf/internal/field_mask_test.py
new file mode 100644
index 0000000..ac08684
--- /dev/null
+++ b/python/google/protobuf/internal/field_mask_test.py
@@ -0,0 +1,400 @@
+# 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.
+
+"""Test for google.protobuf.internal.well_known_types."""
+
+import unittest
+
+from google.protobuf import field_mask_pb2
+from google.protobuf.internal import field_mask
+from google.protobuf.internal import test_util
+from google.protobuf import descriptor
+from google.protobuf import map_unittest_pb2
+from google.protobuf import unittest_pb2
+
+
+class FieldMaskTest(unittest.TestCase):
+
+  def testStringFormat(self):
+    mask = field_mask_pb2.FieldMask()
+    self.assertEqual('', mask.ToJsonString())
+    mask.paths.append('foo')
+    self.assertEqual('foo', mask.ToJsonString())
+    mask.paths.append('bar')
+    self.assertEqual('foo,bar', mask.ToJsonString())
+
+    mask.FromJsonString('')
+    self.assertEqual('', mask.ToJsonString())
+    mask.FromJsonString('foo')
+    self.assertEqual(['foo'], mask.paths)
+    mask.FromJsonString('foo,bar')
+    self.assertEqual(['foo', 'bar'], mask.paths)
+
+    # Test camel case
+    mask.Clear()
+    mask.paths.append('foo_bar')
+    self.assertEqual('fooBar', mask.ToJsonString())
+    mask.paths.append('bar_quz')
+    self.assertEqual('fooBar,barQuz', mask.ToJsonString())
+
+    mask.FromJsonString('')
+    self.assertEqual('', mask.ToJsonString())
+    self.assertEqual([], mask.paths)
+    mask.FromJsonString('fooBar')
+    self.assertEqual(['foo_bar'], mask.paths)
+    mask.FromJsonString('fooBar,barQuz')
+    self.assertEqual(['foo_bar', 'bar_quz'], mask.paths)
+
+  def testDescriptorToFieldMask(self):
+    mask = field_mask_pb2.FieldMask()
+    msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    mask.AllFieldsFromDescriptor(msg_descriptor)
+    self.assertEqual(76, len(mask.paths))
+    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
+    for field in msg_descriptor.fields:
+      self.assertTrue(field.name in mask.paths)
+
+  def testIsValidForDescriptor(self):
+    msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
+    # Empty mask
+    mask = field_mask_pb2.FieldMask()
+    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
+    # All fields from descriptor
+    mask.AllFieldsFromDescriptor(msg_descriptor)
+    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
+    # Child under optional message
+    mask.paths.append('optional_nested_message.bb')
+    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
+    # Repeated field is only allowed in the last position of path
+    mask.paths.append('repeated_nested_message.bb')
+    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
+    # Invalid top level field
+    mask = field_mask_pb2.FieldMask()
+    mask.paths.append('xxx')
+    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
+    # Invalid field in root
+    mask = field_mask_pb2.FieldMask()
+    mask.paths.append('xxx.zzz')
+    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
+    # Invalid field in internal node
+    mask = field_mask_pb2.FieldMask()
+    mask.paths.append('optional_nested_message.xxx.zzz')
+    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
+    # Invalid field in leaf
+    mask = field_mask_pb2.FieldMask()
+    mask.paths.append('optional_nested_message.xxx')
+    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
+
+  def testCanonicalFrom(self):
+    mask = field_mask_pb2.FieldMask()
+    out_mask = field_mask_pb2.FieldMask()
+    # Paths will be sorted.
+    mask.FromJsonString('baz.quz,bar,foo')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('bar,baz.quz,foo', out_mask.ToJsonString())
+    # Duplicated paths will be removed.
+    mask.FromJsonString('foo,bar,foo')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('bar,foo', out_mask.ToJsonString())
+    # Sub-paths of other paths will be removed.
+    mask.FromJsonString('foo.b1,bar.b1,foo.b2,bar')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('bar,foo.b1,foo.b2', out_mask.ToJsonString())
+
+    # Test more deeply nested cases.
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2.quz,foo.bar.baz2')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo.bar.baz1,foo.bar.baz2',
+                     out_mask.ToJsonString())
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo.bar.baz1,foo.bar.baz2',
+                     out_mask.ToJsonString())
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo.bar')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo.bar', out_mask.ToJsonString())
+    mask.FromJsonString(
+        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo')
+    out_mask.CanonicalFormFromMask(mask)
+    self.assertEqual('foo', out_mask.ToJsonString())
+
+  def testUnion(self):
+    mask1 = field_mask_pb2.FieldMask()
+    mask2 = field_mask_pb2.FieldMask()
+    out_mask = field_mask_pb2.FieldMask()
+    mask1.FromJsonString('foo,baz')
+    mask2.FromJsonString('bar,quz')
+    out_mask.Union(mask1, mask2)
+    self.assertEqual('bar,baz,foo,quz', out_mask.ToJsonString())
+    # Overlap with duplicated paths.
+    mask1.FromJsonString('foo,baz.bb')
+    mask2.FromJsonString('baz.bb,quz')
+    out_mask.Union(mask1, mask2)
+    self.assertEqual('baz.bb,foo,quz', out_mask.ToJsonString())
+    # Overlap with paths covering some other paths.
+    mask1.FromJsonString('foo.bar.baz,quz')
+    mask2.FromJsonString('foo.bar,bar')
+    out_mask.Union(mask1, mask2)
+    self.assertEqual('bar,foo.bar,quz', out_mask.ToJsonString())
+    src = unittest_pb2.TestAllTypes()
+    with self.assertRaises(ValueError):
+      out_mask.Union(src, mask2)
+
+  def testIntersect(self):
+    mask1 = field_mask_pb2.FieldMask()
+    mask2 = field_mask_pb2.FieldMask()
+    out_mask = field_mask_pb2.FieldMask()
+    # Test cases without overlapping.
+    mask1.FromJsonString('foo,baz')
+    mask2.FromJsonString('bar,quz')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('', out_mask.ToJsonString())
+    self.assertEqual(len(out_mask.paths), 0)
+    self.assertEqual(out_mask.paths, [])
+    # Overlap with duplicated paths.
+    mask1.FromJsonString('foo,baz.bb')
+    mask2.FromJsonString('baz.bb,quz')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('baz.bb', out_mask.ToJsonString())
+    # Overlap with paths covering some other paths.
+    mask1.FromJsonString('foo.bar.baz,quz')
+    mask2.FromJsonString('foo.bar,bar')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
+    mask1.FromJsonString('foo.bar,bar')
+    mask2.FromJsonString('foo.bar.baz,quz')
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
+    # Intersect '' with ''
+    mask1.Clear()
+    mask2.Clear()
+    mask1.paths.append('')
+    mask2.paths.append('')
+    self.assertEqual(mask1.paths, [''])
+    self.assertEqual('', mask1.ToJsonString())
+    out_mask.Intersect(mask1, mask2)
+    self.assertEqual(out_mask.paths, [])
+
+  def testMergeMessageWithoutMapFields(self):
+    # Test merge one field.
+    src = unittest_pb2.TestAllTypes()
+    test_util.SetAllFields(src)
+    for field in src.DESCRIPTOR.fields:
+      if field.containing_oneof:
+        continue
+      field_name = field.name
+      dst = unittest_pb2.TestAllTypes()
+      # Only set one path to mask.
+      mask = field_mask_pb2.FieldMask()
+      mask.paths.append(field_name)
+      mask.MergeMessage(src, dst)
+      # The expected result message.
+      msg = unittest_pb2.TestAllTypes()
+      if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
+        repeated_src = getattr(src, field_name)
+        repeated_msg = getattr(msg, field_name)
+        if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+          for item in repeated_src:
+            repeated_msg.add().CopyFrom(item)
+        else:
+          repeated_msg.extend(repeated_src)
+      elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
+        getattr(msg, field_name).CopyFrom(getattr(src, field_name))
+      else:
+        setattr(msg, field_name, getattr(src, field_name))
+      # Only field specified in mask is merged.
+      self.assertEqual(msg, dst)
+
+    # Test merge nested fields.
+    nested_src = unittest_pb2.NestedTestAllTypes()
+    nested_dst = unittest_pb2.NestedTestAllTypes()
+    nested_src.child.payload.optional_int32 = 1234
+    nested_src.child.child.payload.optional_int32 = 5678
+    mask = field_mask_pb2.FieldMask()
+    mask.FromJsonString('child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(0, nested_dst.child.child.payload.optional_int32)
+
+    mask.FromJsonString('child.child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
+
+    nested_dst.Clear()
+    mask.FromJsonString('child.child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(0, nested_dst.child.payload.optional_int32)
+    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
+
+    nested_dst.Clear()
+    mask.FromJsonString('child')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
+
+    # Test MergeOptions.
+    nested_dst.Clear()
+    nested_dst.child.payload.optional_int64 = 4321
+    # Message fields will be merged by default.
+    mask.FromJsonString('child.payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(4321, nested_dst.child.payload.optional_int64)
+    # Change the behavior to replace message fields.
+    mask.FromJsonString('child.payload')
+    mask.MergeMessage(nested_src, nested_dst, True, False)
+    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
+    self.assertEqual(0, nested_dst.child.payload.optional_int64)
+
+    # By default, fields missing in source are not cleared in destination.
+    nested_dst.payload.optional_int32 = 1234
+    self.assertTrue(nested_dst.HasField('payload'))
+    mask.FromJsonString('payload')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertTrue(nested_dst.HasField('payload'))
+    # But they are cleared when replacing message fields.
+    nested_dst.Clear()
+    nested_dst.payload.optional_int32 = 1234
+    mask.FromJsonString('payload')
+    mask.MergeMessage(nested_src, nested_dst, True, False)
+    self.assertFalse(nested_dst.HasField('payload'))
+
+    nested_src.payload.repeated_int32.append(1234)
+    nested_dst.payload.repeated_int32.append(5678)
+    # Repeated fields will be appended by default.
+    mask.FromJsonString('payload.repeatedInt32')
+    mask.MergeMessage(nested_src, nested_dst)
+    self.assertEqual(2, len(nested_dst.payload.repeated_int32))
+    self.assertEqual(5678, nested_dst.payload.repeated_int32[0])
+    self.assertEqual(1234, nested_dst.payload.repeated_int32[1])
+    # Change the behavior to replace repeated fields.
+    mask.FromJsonString('payload.repeatedInt32')
+    mask.MergeMessage(nested_src, nested_dst, False, True)
+    self.assertEqual(1, len(nested_dst.payload.repeated_int32))
+    self.assertEqual(1234, nested_dst.payload.repeated_int32[0])
+
+    # Test Merge oneof field.
+    new_msg = unittest_pb2.TestOneof2()
+    dst = unittest_pb2.TestOneof2()
+    dst.foo_message.moo_int = 1
+    mask = field_mask_pb2.FieldMask()
+    mask.FromJsonString('fooMessage,fooLazyMessage.mooInt')
+    mask.MergeMessage(new_msg, dst)
+    self.assertTrue(dst.HasField('foo_message'))
+    self.assertFalse(dst.HasField('foo_lazy_message'))
+
+  def testMergeMessageWithMapField(self):
+    empty_map = map_unittest_pb2.TestRecursiveMapMessage()
+    src_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
+    src_level_2.a['src level 2'].CopyFrom(empty_map)
+    src = map_unittest_pb2.TestRecursiveMapMessage()
+    src.a['common key'].CopyFrom(src_level_2)
+    src.a['src level 1'].CopyFrom(src_level_2)
+
+    dst_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
+    dst_level_2.a['dst level 2'].CopyFrom(empty_map)
+    dst = map_unittest_pb2.TestRecursiveMapMessage()
+    dst.a['common key'].CopyFrom(dst_level_2)
+    dst.a['dst level 1'].CopyFrom(empty_map)
+
+    mask = field_mask_pb2.FieldMask()
+    mask.FromJsonString('a')
+    mask.MergeMessage(src, dst)
+
+    # map from dst is replaced with map from src.
+    self.assertEqual(dst.a['common key'], src_level_2)
+    self.assertEqual(dst.a['src level 1'], src_level_2)
+    self.assertEqual(dst.a['dst level 1'], empty_map)
+
+  def testMergeErrors(self):
+    src = unittest_pb2.TestAllTypes()
+    dst = unittest_pb2.TestAllTypes()
+    mask = field_mask_pb2.FieldMask()
+    test_util.SetAllFields(src)
+    mask.FromJsonString('optionalInt32.field')
+    with self.assertRaises(ValueError) as e:
+      mask.MergeMessage(src, dst)
+    self.assertEqual('Error: Field optional_int32 in message '
+                     'protobuf_unittest.TestAllTypes is not a singular '
+                     'message field and cannot have sub-fields.',
+                     str(e.exception))
+
+  def testSnakeCaseToCamelCase(self):
+    self.assertEqual('fooBar',
+                     field_mask._SnakeCaseToCamelCase('foo_bar'))
+    self.assertEqual('FooBar',
+                     field_mask._SnakeCaseToCamelCase('_foo_bar'))
+    self.assertEqual('foo3Bar',
+                     field_mask._SnakeCaseToCamelCase('foo3_bar'))
+
+    # No uppercase letter is allowed.
+    self.assertRaisesRegex(
+        ValueError,
+        'Fail to print FieldMask to Json string: Path name Foo must '
+        'not contain uppercase letters.',
+        field_mask._SnakeCaseToCamelCase, 'Foo')
+    # Any character after a "_" must be a lowercase letter.
+    #   1. "_" cannot be followed by another "_".
+    #   2. "_" cannot be followed by a digit.
+    #   3. "_" cannot appear as the last character.
+    self.assertRaisesRegex(
+        ValueError,
+        'Fail to print FieldMask to Json string: The character after a '
+        '"_" must be a lowercase letter in path name foo__bar.',
+        field_mask._SnakeCaseToCamelCase, 'foo__bar')
+    self.assertRaisesRegex(
+        ValueError,
+        'Fail to print FieldMask to Json string: The character after a '
+        '"_" must be a lowercase letter in path name foo_3bar.',
+        field_mask._SnakeCaseToCamelCase, 'foo_3bar')
+    self.assertRaisesRegex(
+        ValueError,
+        'Fail to print FieldMask to Json string: Trailing "_" in path '
+        'name foo_bar_.', field_mask._SnakeCaseToCamelCase, 'foo_bar_')
+
+  def testCamelCaseToSnakeCase(self):
+    self.assertEqual('foo_bar',
+                     field_mask._CamelCaseToSnakeCase('fooBar'))
+    self.assertEqual('_foo_bar',
+                     field_mask._CamelCaseToSnakeCase('FooBar'))
+    self.assertEqual('foo3_bar',
+                     field_mask._CamelCaseToSnakeCase('foo3Bar'))
+    self.assertRaisesRegex(
+        ValueError,
+        'Fail to parse FieldMask: Path name foo_bar must not contain "_"s.',
+        field_mask._CamelCaseToSnakeCase, 'foo_bar')
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/python/google/protobuf/internal/file_options_test.proto b/python/google/protobuf/internal/file_options_test.proto
index 4eceeb0..7b68595 100644
--- a/python/google/protobuf/internal/file_options_test.proto
+++ b/python/google/protobuf/internal/file_options_test.proto
@@ -30,10 +30,10 @@
 
 syntax = "proto2";
 
-import "google/protobuf/descriptor.proto";
-
 package google.protobuf.python.internal;
 
+import "google/protobuf/descriptor.proto";
+
 message FooOptions {
   optional string foo_name = 1;
 }
diff --git a/python/google/protobuf/internal/generator_test.py b/python/google/protobuf/internal/generator_test.py
index 9883fce..291b97d 100644
--- a/python/google/protobuf/internal/generator_test.py
+++ b/python/google/protobuf/internal/generator_test.py
@@ -42,15 +42,15 @@
 import unittest
 
 from google.protobuf.internal import test_bad_identifiers_pb2
-from google.protobuf import unittest_custom_options_pb2
+from google.protobuf import service
+from google.protobuf import symbol_database
 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_mset_wire_format_pb2
-from google.protobuf import unittest_no_generic_services_pb2
 from google.protobuf import unittest_pb2
-from google.protobuf import service
-from google.protobuf import symbol_database
+from google.protobuf import unittest_custom_options_pb2
+from google.protobuf import unittest_no_generic_services_pb2
 
 MAX_EXTENSION = 536870912
 
diff --git a/python/google/protobuf/internal/json_format_test.py b/python/google/protobuf/internal/json_format_test.py
index d018c3f..0e9648c 100644
--- a/python/google/protobuf/internal/json_format_test.py
+++ b/python/google/protobuf/internal/json_format_test.py
@@ -44,12 +44,12 @@
 from google.protobuf import struct_pb2
 from google.protobuf import timestamp_pb2
 from google.protobuf import wrappers_pb2
-from google.protobuf import any_test_pb2
-from google.protobuf import unittest_mset_pb2
-from google.protobuf import unittest_pb2
 from google.protobuf.internal import test_proto3_optional_pb2
 from google.protobuf import descriptor_pool
 from google.protobuf import json_format
+from google.protobuf import any_test_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_mset_pb2
 from google.protobuf.util import json_format_pb2
 from google.protobuf.util import json_format_proto3_pb2
 
diff --git a/python/google/protobuf/internal/message_factory_test.py b/python/google/protobuf/internal/message_factory_test.py
index efba619..3ab3b8e 100644
--- a/python/google/protobuf/internal/message_factory_test.py
+++ b/python/google/protobuf/internal/message_factory_test.py
@@ -118,6 +118,16 @@
         'google.protobuf.python.internal.Factory2Message'))
     self.assertTrue(hasattr(cls, 'additional_field'))
 
+  def testGetExistingPrototype(self):
+    factory = message_factory.MessageFactory()
+    # Get Existing Prototype should not create a new class.
+    cls = factory.GetPrototype(
+        descriptor=factory_test2_pb2.Factory2Message.DESCRIPTOR)
+    msg = factory_test2_pb2.Factory2Message()
+    self.assertIsInstance(msg, cls)
+    self.assertIsInstance(msg.factory_1_message,
+                          factory_test1_pb2.Factory1Message)
+
   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_set_extensions.proto b/python/google/protobuf/internal/message_set_extensions.proto
index 14e5f19..0dcbd60 100644
--- a/python/google/protobuf/internal/message_set_extensions.proto
+++ b/python/google/protobuf/internal/message_set_extensions.proto
@@ -31,12 +31,13 @@
 // This file contains messages that extend MessageSet.
 
 syntax = "proto2";
-package google.protobuf.internal;
 
+package google.protobuf.internal;
 
 // A message with message_set_wire_format.
 message TestMessageSet {
   option message_set_wire_format = true;
+
   extensions 4 to max;
 }
 
diff --git a/python/google/protobuf/internal/message_test.py b/python/google/protobuf/internal/message_test.py
index 40abfe4..cdcc5b0 100644
--- a/python/google/protobuf/internal/message_test.py
+++ b/python/google/protobuf/internal/message_test.py
@@ -34,10 +34,6 @@
 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)'
@@ -54,20 +50,20 @@
 
 cmp = lambda x, y: (x > y) - (x < y)
 
+from google.protobuf.internal import api_implementation # pylint: disable=g-import-not-at-top
+from google.protobuf.internal import encoder
+from google.protobuf.internal import more_extensions_pb2
+from google.protobuf.internal import packed_field_test_pb2
+from google.protobuf.internal import test_proto3_optional_pb2
+from google.protobuf.internal import test_util
+from google.protobuf.internal import testing_refleaks
+from google.protobuf import descriptor
+from google.protobuf import message
+from google.protobuf.internal import _parameterized
 from google.protobuf import map_proto2_unittest_pb2
 from google.protobuf import map_unittest_pb2
 from google.protobuf import unittest_pb2
 from google.protobuf import unittest_proto3_arena_pb2
-from google.protobuf import descriptor
-from google.protobuf.internal import api_implementation
-from google.protobuf.internal import encoder
-from google.protobuf.internal import more_extensions_pb2
-from google.protobuf.internal import packed_field_test_pb2
-from google.protobuf.internal import test_util
-from google.protobuf.internal import test_proto3_optional_pb2
-from google.protobuf.internal import testing_refleaks
-from google.protobuf import message
-from google.protobuf.internal import _parameterized
 
 UCS2_MAXUNICODE = 65535
 
@@ -476,6 +472,12 @@
         '}\n')
     self.assertEqual(sub_msg.bb, 1)
 
+  def testAssignRepeatedField(self, message_module):
+    msg = message_module.NestedTestAllTypes()
+    msg.payload.repeated_int32[:] = [1, 2, 3, 4]
+    self.assertEqual(4, len(msg.payload.repeated_int32))
+    self.assertEqual([1, 2, 3, 4], msg.payload.repeated_int32)
+
   def testMergeFromRepeatedField(self, message_module):
     msg = message_module.TestAllTypes()
     msg.repeated_int32.append(1)
@@ -887,6 +889,7 @@
 
   def testOneofClearField(self, message_module):
     m = message_module.TestAllTypes()
+    m.ClearField('oneof_field')
     m.oneof_uint32 = 11
     m.ClearField('oneof_field')
     if message_module is unittest_pb2:
@@ -1527,7 +1530,6 @@
     self.assertEqual(100, msg.optional_int32)
     self.assertEqual(200, msg.optional_fixed32)
 
-
   def test_documentation(self):
     # Also used by the interactive help() function.
     doc = pydoc.html.document(unittest_pb2.TestAllTypes, 'message')
@@ -1766,6 +1768,19 @@
     with self.assertRaises(TypeError):
       123 in msg.map_string_string
 
+  def testScalarMapComparison(self):
+    msg1 = map_unittest_pb2.TestMap()
+    msg2 = map_unittest_pb2.TestMap()
+
+    self.assertEqual(msg1.map_int32_int32, msg2.map_int32_int32)
+
+  def testMessageMapComparison(self):
+    msg1 = map_unittest_pb2.TestMap()
+    msg2 = map_unittest_pb2.TestMap()
+
+    self.assertEqual(msg1.map_int32_foreign_message,
+                     msg2.map_int32_foreign_message)
+
   def testMapGet(self):
     # Need to test that get() properly returns the default, even though the dict
     # has defaultdict-like semantics.
@@ -2453,7 +2468,25 @@
     with self.assertRaises(ValueError):
       unittest_proto3_arena_pb2.TestAllTypes(optional_string=u'\ud801\ud801')
 
+  def testCrashNullAA(self):
+    self.assertEqual(
+        unittest_proto3_arena_pb2.TestAllTypes.NestedMessage(),
+        unittest_proto3_arena_pb2.TestAllTypes.NestedMessage())
 
+  def testCrashNullAB(self):
+    self.assertEqual(
+        unittest_proto3_arena_pb2.TestAllTypes.NestedMessage(),
+        unittest_proto3_arena_pb2.TestAllTypes().optional_nested_message)
+
+  def testCrashNullBA(self):
+    self.assertEqual(
+        unittest_proto3_arena_pb2.TestAllTypes().optional_nested_message,
+        unittest_proto3_arena_pb2.TestAllTypes.NestedMessage())
+
+  def testCrashNullBB(self):
+    self.assertEqual(
+        unittest_proto3_arena_pb2.TestAllTypes().optional_nested_message,
+        unittest_proto3_arena_pb2.TestAllTypes().optional_nested_message)
 
 
 @testing_refleaks.TestCase
diff --git a/python/google/protobuf/internal/missing_enum_values.proto b/python/google/protobuf/internal/missing_enum_values.proto
index 37baca7..1850be5 100644
--- a/python/google/protobuf/internal/missing_enum_values.proto
+++ b/python/google/protobuf/internal/missing_enum_values.proto
@@ -30,7 +30,6 @@
 
 syntax = "proto2";
 
-
 package google.protobuf.python.internal;
 
 message TestEnumValues {
@@ -44,7 +43,9 @@
 }
 
 message TestMissingEnumValues {
-  enum NestedEnum { TWO = 2; }
+  enum NestedEnum {
+    TWO = 2;
+  }
   optional NestedEnum optional_nested_enum = 1;
   repeated NestedEnum repeated_nested_enum = 2;
   repeated NestedEnum packed_nested_enum = 3 [packed = true];
@@ -53,4 +54,3 @@
 message JustString {
   required string dummy = 1;
 }
-
diff --git a/python/google/protobuf/internal/more_extensions_dynamic.proto b/python/google/protobuf/internal/more_extensions_dynamic.proto
index 98fcbcb..ba7280e 100644
--- a/python/google/protobuf/internal/more_extensions_dynamic.proto
+++ b/python/google/protobuf/internal/more_extensions_dynamic.proto
@@ -36,10 +36,10 @@
 
 syntax = "proto2";
 
-import "google/protobuf/internal/more_extensions.proto";
-
 package google.protobuf.internal;
 
+import "google/protobuf/internal/more_extensions.proto";
+
 message DynamicMessageType {
   optional int32 a = 1;
 }
diff --git a/python/google/protobuf/internal/no_package.proto b/python/google/protobuf/internal/no_package.proto
index 49eda95..b53562d 100644
--- a/python/google/protobuf/internal/no_package.proto
+++ b/python/google/protobuf/internal/no_package.proto
@@ -1,3 +1,5 @@
+// NOLINT(no_package_specified): Test proto with no package
+
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
diff --git a/python/google/protobuf/internal/numpy_test.py b/python/google/protobuf/internal/numpy_test.py
new file mode 100644
index 0000000..8eb20af
--- /dev/null
+++ b/python/google/protobuf/internal/numpy_test.py
@@ -0,0 +1,215 @@
+# 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.
+
+"""Test use of numpy types with repeated and non-repeated scalar fields."""
+
+import unittest
+
+import numpy as np
+
+from google.protobuf.internal import testing_refleaks
+from google.protobuf import unittest_pb2
+
+message = unittest_pb2.TestAllTypes()
+np_float_scalar = np.float64(0.0)
+np_1_float_array = np.zeros(shape=(1,), dtype=np.float64)
+np_2_float_array = np.zeros(shape=(2,), dtype=np.float64)
+np_11_float_array = np.zeros(shape=(1, 1), dtype=np.float64)
+np_22_float_array = np.zeros(shape=(2, 2), dtype=np.float64)
+
+np_int_scalar = np.int64(0)
+np_1_int_array = np.zeros(shape=(1,), dtype=np.int64)
+np_2_int_array = np.zeros(shape=(2,), dtype=np.int64)
+np_11_int_array = np.zeros(shape=(1, 1), dtype=np.int64)
+np_22_int_array = np.zeros(shape=(2, 2), dtype=np.int64)
+
+np_uint_scalar = np.uint64(0)
+np_1_uint_array = np.zeros(shape=(1,), dtype=np.uint64)
+np_2_uint_array = np.zeros(shape=(2,), dtype=np.uint64)
+np_11_uint_array = np.zeros(shape=(1, 1), dtype=np.uint64)
+np_22_uint_array = np.zeros(shape=(2, 2), dtype=np.uint64)
+
+np_bool_scalar = np.bool_(False)
+np_1_bool_array = np.zeros(shape=(1,), dtype=np.bool_)
+np_2_bool_array = np.zeros(shape=(2,), dtype=np.bool_)
+np_11_bool_array = np.zeros(shape=(1, 1), dtype=np.bool_)
+np_22_bool_array = np.zeros(shape=(2, 2), dtype=np.bool_)
+
+
+@testing_refleaks.TestCase
+class NumpyIntProtoTest(unittest.TestCase):
+
+  # Assigning dim 1 ndarray of ints to repeated field should pass
+  def testNumpyDim1IntArrayToRepeated_IsValid(self):
+    message.repeated_int64[:] = np_1_int_array
+    message.repeated_int64[:] = np_2_int_array
+
+    message.repeated_uint64[:] = np_1_uint_array
+    message.repeated_uint64[:] = np_2_uint_array
+
+  # Assigning dim 2 ndarray of ints to repeated field should fail
+  def testNumpyDim2IntArrayToRepeated_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.repeated_int64[:] = np_11_int_array
+    with self.assertRaises(TypeError):
+      message.repeated_int64[:] = np_22_int_array
+
+    with self.assertRaises(TypeError):
+      message.repeated_uint64[:] = np_11_uint_array
+    with self.assertRaises(TypeError):
+      message.repeated_uint64[:] = np_22_uint_array
+
+  # Assigning any ndarray of floats to repeated int field should fail
+  def testNumpyFloatArrayToRepeated_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.repeated_int64[:] = np_1_float_array
+    with self.assertRaises(TypeError):
+      message.repeated_int64[:] = np_11_float_array
+    with self.assertRaises(TypeError):
+      message.repeated_int64[:] = np_22_float_array
+
+  # Assigning any np int to scalar field should pass
+  def testNumpyIntScalarToScalar_IsValid(self):
+    message.optional_int64 = np_int_scalar
+    message.optional_uint64 = np_uint_scalar
+
+  # Assigning any ndarray of ints to scalar field should fail
+  def testNumpyIntArrayToScalar_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.optional_int64 = np_1_int_array
+    with self.assertRaises(TypeError):
+      message.optional_int64 = np_11_int_array
+    with self.assertRaises(TypeError):
+      message.optional_int64 = np_22_int_array
+
+    with self.assertRaises(TypeError):
+      message.optional_uint64 = np_1_uint_array
+    with self.assertRaises(TypeError):
+      message.optional_uint64 = np_11_uint_array
+    with self.assertRaises(TypeError):
+      message.optional_uint64 = np_22_uint_array
+
+  # Assigning any ndarray of floats to scalar field should fail
+  def testNumpyFloatArrayToScalar_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.optional_int64 = np_1_float_array
+    with self.assertRaises(TypeError):
+      message.optional_int64 = np_11_float_array
+    with self.assertRaises(TypeError):
+      message.optional_int64 = np_22_float_array
+
+
+@testing_refleaks.TestCase
+class NumpyFloatProtoTest(unittest.TestCase):
+
+  # Assigning dim 1 ndarray of floats to repeated field should pass
+  def testNumpyDim1FloatArrayToRepeated_IsValid(self):
+    message.repeated_float[:] = np_1_float_array
+    message.repeated_float[:] = np_2_float_array
+
+  # Assigning dim 2 ndarray of floats to repeated field should fail
+  def testNumpyDim2FloatArrayToRepeated_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.repeated_float[:] = np_11_float_array
+    with self.assertRaises(TypeError):
+      message.repeated_float[:] = np_22_float_array
+
+  # Assigning any np float to scalar field should pass
+  def testNumpyFloatScalarToScalar_IsValid(self):
+    message.optional_float = np_float_scalar
+
+  # Assigning any ndarray of float to scalar field should fail
+  def testNumpyFloatArrayToScalar_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.optional_float = np_1_float_array
+    with self.assertRaises(TypeError):
+      message.optional_float = np_11_float_array
+    with self.assertRaises(TypeError):
+      message.optional_float = np_22_float_array
+
+
+@testing_refleaks.TestCase
+class NumpyBoolProtoTest(unittest.TestCase):
+
+  # Assigning dim 1 ndarray of bool to repeated field should pass
+  def testNumpyDim1BoolArrayToRepeated_IsValid(self):
+    message.repeated_bool[:] = np_1_bool_array
+    message.repeated_bool[:] = np_2_bool_array
+
+  # Assigning dim 2 ndarray of bool to repeated field should fail
+  def testNumpyDim2BoolArrayToRepeated_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.repeated_bool[:] = np_11_bool_array
+    with self.assertRaises(TypeError):
+      message.repeated_bool[:] = np_22_bool_array
+
+  # Assigning any np bool to scalar field should pass
+  def testNumpyBoolScalarToScalar_IsValid(self):
+    message.optional_bool = np_bool_scalar
+
+  # Assigning any ndarray of bool to scalar field should fail
+  def testNumpyBoolArrayToScalar_RaisesTypeError(self):
+    with self.assertRaises(TypeError):
+      message.optional_bool = np_1_bool_array
+    with self.assertRaises(TypeError):
+      message.optional_bool = np_11_bool_array
+    with self.assertRaises(TypeError):
+      message.optional_bool = np_22_bool_array
+
+
+@testing_refleaks.TestCase
+class NumpyProtoIndexingTest(unittest.TestCase):
+
+  def testNumpyIntScalarIndexing_Passes(self):
+    data = unittest_pb2.TestAllTypes(repeated_int64=[0, 1, 2])
+    self.assertEqual(0, data.repeated_int64[np.int64(0)])
+
+  def testNumpyNegative1IntScalarIndexing_Passes(self):
+    data = unittest_pb2.TestAllTypes(repeated_int64=[0, 1, 2])
+    self.assertEqual(2, data.repeated_int64[np.int64(-1)])
+
+  def testNumpyFloatScalarIndexing_Fails(self):
+    data = unittest_pb2.TestAllTypes(repeated_int64=[0, 1, 2])
+    with self.assertRaises(TypeError):
+      _ = data.repeated_int64[np.float64(0.0)]
+
+  def testNumpyIntArrayIndexing_Fails(self):
+    data = unittest_pb2.TestAllTypes(repeated_int64=[0, 1, 2])
+    with self.assertRaises(TypeError):
+      _ = data.repeated_int64[np.array([0])]
+    with self.assertRaises(TypeError):
+      _ = data.repeated_int64[np.ndarray((1,), buffer=np.array([0]), dtype=int)]
+    with self.assertRaises(TypeError):
+      _ = data.repeated_int64[np.ndarray((1, 1),
+                                         buffer=np.array([0]),
+                                         dtype=int)]
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/python/google/protobuf/internal/packed_field_test.proto b/python/google/protobuf/internal/packed_field_test.proto
index 0dfdc10..d413072 100644
--- a/python/google/protobuf/internal/packed_field_test.proto
+++ b/python/google/protobuf/internal/packed_field_test.proto
@@ -39,35 +39,36 @@
     BAZ = 2;
   }
 
-  repeated    int32 repeated_int32    =  1;
-  repeated    int64 repeated_int64    =  2;
-  repeated   uint32 repeated_uint32   =  3;
-  repeated   uint64 repeated_uint64   =  4;
-  repeated   sint32 repeated_sint32   =  5;
-  repeated   sint64 repeated_sint64   =  6;
-  repeated  fixed32 repeated_fixed32  =  7;
-  repeated  fixed64 repeated_fixed64  =  8;
-  repeated sfixed32 repeated_sfixed32 =  9;
+  repeated int32 repeated_int32 = 1;
+  repeated int64 repeated_int64 = 2;
+  repeated uint32 repeated_uint32 = 3;
+  repeated uint64 repeated_uint64 = 4;
+  repeated sint32 repeated_sint32 = 5;
+  repeated sint64 repeated_sint64 = 6;
+  repeated fixed32 repeated_fixed32 = 7;
+  repeated fixed64 repeated_fixed64 = 8;
+  repeated sfixed32 repeated_sfixed32 = 9;
   repeated sfixed64 repeated_sfixed64 = 10;
-  repeated    float repeated_float    = 11;
-  repeated   double repeated_double   = 12;
-  repeated     bool repeated_bool     = 13;
+  repeated float repeated_float = 11;
+  repeated double repeated_double = 12;
+  repeated bool repeated_bool = 13;
   repeated NestedEnum repeated_nested_enum = 14;
 }
 
 message TestUnpackedTypes {
-  repeated    int32 repeated_int32    =  1 [packed = false];
-  repeated    int64 repeated_int64    =  2 [packed = false];
-  repeated   uint32 repeated_uint32   =  3 [packed = false];
-  repeated   uint64 repeated_uint64   =  4 [packed = false];
-  repeated   sint32 repeated_sint32   =  5 [packed = false];
-  repeated   sint64 repeated_sint64   =  6 [packed = false];
-  repeated  fixed32 repeated_fixed32  =  7 [packed = false];
-  repeated  fixed64 repeated_fixed64  =  8 [packed = false];
-  repeated sfixed32 repeated_sfixed32 =  9 [packed = false];
+  repeated int32 repeated_int32 = 1 [packed = false];
+  repeated int64 repeated_int64 = 2 [packed = false];
+  repeated uint32 repeated_uint32 = 3 [packed = false];
+  repeated uint64 repeated_uint64 = 4 [packed = false];
+  repeated sint32 repeated_sint32 = 5 [packed = false];
+  repeated sint64 repeated_sint64 = 6 [packed = false];
+  repeated fixed32 repeated_fixed32 = 7 [packed = false];
+  repeated fixed64 repeated_fixed64 = 8 [packed = false];
+  repeated sfixed32 repeated_sfixed32 = 9 [packed = false];
   repeated sfixed64 repeated_sfixed64 = 10 [packed = false];
-  repeated    float repeated_float    = 11 [packed = false];
-  repeated   double repeated_double   = 12 [packed = false];
-  repeated     bool repeated_bool     = 13 [packed = false];
-  repeated TestPackedTypes.NestedEnum repeated_nested_enum = 14 [packed = false];
+  repeated float repeated_float = 11 [packed = false];
+  repeated double repeated_double = 12 [packed = false];
+  repeated bool repeated_bool = 13 [packed = false];
+  repeated TestPackedTypes.NestedEnum repeated_nested_enum = 14
+      [packed = false];
 }
diff --git a/python/google/protobuf/internal/python_message.py b/python/google/protobuf/internal/python_message.py
old mode 100644
new mode 100755
index 5550b42..1e71aa2
--- a/python/google/protobuf/internal/python_message.py
+++ b/python/google/protobuf/internal/python_message.py
@@ -283,20 +283,8 @@
 
 def _AttachFieldHelpers(cls, field_descriptor):
   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':
-    is_packed = (field_descriptor.has_options and
-                field_descriptor.GetOptions().packed)
-  else:
-    has_packed_false = (field_descriptor.has_options and
-                        field_descriptor.GetOptions().HasField('packed') and
-                        field_descriptor.GetOptions().packed == False)
-    is_packed = not has_packed_false
   is_map_entry = _IsMapField(field_descriptor)
+  is_packed = field_descriptor.is_packed
 
   if is_map_entry:
     field_encoder = encoder.MapEncoder(field_descriptor)
@@ -320,16 +308,12 @@
     tag_bytes = encoder.TagBytes(field_descriptor.number, wiretype)
     decode_type = field_descriptor.type
     if (decode_type == _FieldDescriptor.TYPE_ENUM and
-        type_checkers.SupportsOpenEnums(field_descriptor)):
+        not field_descriptor.enum_type.is_closed):
       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)
@@ -341,7 +325,7 @@
       field_decoder = decoder.StringDecoder(
           field_descriptor.number, is_repeated, is_packed,
           field_descriptor, field_descriptor._default_constructor,
-          clear_if_default)
+          not field_descriptor.has_presence)
     elif field_descriptor.cpp_type == _FieldDescriptor.CPPTYPE_MESSAGE:
       field_decoder = type_checkers.TYPE_TO_DECODER[decode_type](
           field_descriptor.number, is_repeated, is_packed,
@@ -351,7 +335,7 @@
           field_descriptor.number, is_repeated, is_packed,
           # pylint: disable=protected-access
           field_descriptor, field_descriptor._default_constructor,
-          clear_if_default)
+          not field_descriptor.has_presence)
 
     cls._decoders_by_tag[tag_bytes] = (field_decoder, oneof_descriptor)
 
@@ -683,7 +667,6 @@
   property_name = _PropertyName(proto_field_name)
   type_checker = type_checkers.GetTypeChecker(field)
   default_value = field.default_value
-  is_proto3 = field.containing_type.syntax == 'proto3'
 
   def getter(self):
     # TODO(protobuf-team): This may be broken since there may not be
@@ -692,8 +675,6 @@
   getter.__module__ = None
   getter.__doc__ = 'Getter for %s.' % proto_field_name
 
-  clear_when_set_to_default = is_proto3 and not field.containing_oneof
-
   def field_setter(self, new_value):
     # pylint: disable=protected-access
     # Testing the value for truthiness captures all of the proto3 defaults
@@ -703,7 +684,7 @@
     except TypeError as e:
       raise TypeError(
           'Cannot set %s to %.1024r: %s' % (field.full_name, new_value, e))
-    if clear_when_set_to_default and not new_value:
+    if not field.has_presence and not new_value:
       self._fields.pop(field, None)
     else:
       self._fields[field] = new_value
@@ -825,24 +806,16 @@
 
   cls.ListFields = ListFields
 
-_PROTO3_ERROR_TEMPLATE = \
-  ('Protocol message %s has no non-repeated submessage field "%s" '
-   'nor marked as optional')
-_PROTO2_ERROR_TEMPLATE = 'Protocol message %s has no non-repeated field "%s"'
 
 def _AddHasFieldMethod(message_descriptor, cls):
   """Helper for _AddMessageMethods()."""
 
-  is_proto3 = (message_descriptor.syntax == "proto3")
-  error_msg = _PROTO3_ERROR_TEMPLATE if is_proto3 else _PROTO2_ERROR_TEMPLATE
-
   hassable_fields = {}
   for field in message_descriptor.fields:
     if field.label == _FieldDescriptor.LABEL_REPEATED:
       continue
     # For proto3, only submessages and fields inside a oneof have presence.
-    if (is_proto3 and field.cpp_type != _FieldDescriptor.CPPTYPE_MESSAGE and
-        not field.containing_oneof):
+    if not field.has_presence:
       continue
     hassable_fields[field.name] = field
 
@@ -853,8 +826,10 @@
   def HasField(self, field_name):
     try:
       field = hassable_fields[field_name]
-    except KeyError:
-      raise ValueError(error_msg % (message_descriptor.full_name, field_name))
+    except KeyError as exc:
+      raise ValueError('Protocol message %s has no non-repeated field "%s" '
+                       'nor has presence is not available for this field.' % (
+                           message_descriptor.full_name, field_name)) from exc
 
     if isinstance(field, descriptor_mod.OneofDescriptor):
       try:
diff --git a/python/google/protobuf/internal/python_protobuf.cc b/python/google/protobuf/internal/python_protobuf.cc
index 26e3a8b..bbef715 100644
--- a/python/google/protobuf/internal/python_protobuf.cc
+++ b/python/google/protobuf/internal/python_protobuf.cc
@@ -30,7 +30,7 @@
 
 // Author: qrczak@google.com (Marcin Kowalczyk)
 
-#include <google/protobuf/python/python_protobuf.h>
+#include "google/protobuf/python_protobuf.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/internal/reflection_test.py b/python/google/protobuf/internal/reflection_test.py
index 62957d3..0708d51 100644
--- a/python/google/protobuf/internal/reflection_test.py
+++ b/python/google/protobuf/internal/reflection_test.py
@@ -41,10 +41,6 @@
 import warnings
 import unittest
 
-from google.protobuf import unittest_import_pb2
-from google.protobuf import unittest_mset_pb2
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf import descriptor_pb2
 from google.protobuf import descriptor
 from google.protobuf import message
@@ -59,6 +55,10 @@
 from google.protobuf.internal import testing_refleaks
 from google.protobuf.internal import decoder
 from google.protobuf.internal import _parameterized
+from google.protobuf import unittest_import_pb2
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
 
 
 warnings.simplefilter('error', DeprecationWarning)
@@ -3220,7 +3220,6 @@
                        field_descriptor.label)
 
 
-
 @testing_refleaks.TestCase
 class ClassAPITest(unittest.TestCase):
 
diff --git a/python/google/protobuf/internal/service_reflection_test.py b/python/google/protobuf/internal/service_reflection_test.py
index 8e72213..bb4cd5e 100644
--- a/python/google/protobuf/internal/service_reflection_test.py
+++ b/python/google/protobuf/internal/service_reflection_test.py
@@ -35,9 +35,9 @@
 
 import unittest
 
-from google.protobuf import unittest_pb2
 from google.protobuf import service_reflection
 from google.protobuf import service
+from google.protobuf import unittest_pb2
 
 
 class FooUnitTest(unittest.TestCase):
diff --git a/python/google/protobuf/internal/symbol_database_test.py b/python/google/protobuf/internal/symbol_database_test.py
index 4fdc4ee..3b12038 100644
--- a/python/google/protobuf/internal/symbol_database_test.py
+++ b/python/google/protobuf/internal/symbol_database_test.py
@@ -32,10 +32,10 @@
 
 import unittest
 
-from google.protobuf import unittest_pb2
 from google.protobuf import descriptor
 from google.protobuf import descriptor_pool
 from google.protobuf import symbol_database
+from google.protobuf import unittest_pb2
 
 
 class SymbolDatabaseTest(unittest.TestCase):
diff --git a/python/google/protobuf/internal/test_util.py b/python/google/protobuf/internal/test_util.py
old mode 100644
new mode 100755
diff --git a/python/google/protobuf/internal/text_format_test.py b/python/google/protobuf/internal/text_format_test.py
index 18b784e..8d15f01 100644
--- a/python/google/protobuf/internal/text_format_test.py
+++ b/python/google/protobuf/internal/text_format_test.py
@@ -41,12 +41,6 @@
 
 from google.protobuf import any_pb2
 from google.protobuf import struct_pb2
-from google.protobuf import any_test_pb2
-from google.protobuf import map_unittest_pb2
-from google.protobuf import unittest_custom_options_pb2
-from google.protobuf import unittest_mset_pb2
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf import descriptor_pb2
 from google.protobuf.internal import any_test_pb2 as test_extend_any
 from google.protobuf.internal import api_implementation
@@ -56,6 +50,12 @@
 from google.protobuf import descriptor_pool
 from google.protobuf import text_format
 from google.protobuf.internal import _parameterized
+from google.protobuf import any_test_pb2
+from google.protobuf import map_unittest_pb2
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_custom_options_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
 # pylint: enable=g-import-not-at-top
 
 
@@ -1598,6 +1598,47 @@
     self.assertEqual(23, message.message_set.Extensions[ext1].i)
     self.assertEqual('foo', message.message_set.Extensions[ext2].str)
 
+    # Handle Any messages inside unknown extensions.
+    message = any_test_pb2.TestAny()
+    text = ('any_value {\n'
+            '  [type.googleapis.com/google.protobuf.internal.TestAny] {\n'
+            '    [unknown_extension] {\n'
+            '      str: "string"\n'
+            '      any_value {\n'
+            '        [type.googleapis.com/protobuf_unittest.OneString] {\n'
+            '          data: "string"\n'
+            '        }\n'
+            '      }\n'
+            '    }\n'
+            '  }\n'
+            '}\n'
+            'int32_value: 123')
+    text_format.Parse(text, message, allow_unknown_extension=True)
+    self.assertEqual(123, message.int32_value)
+
+    # Fail if invalid Any message type url inside unknown extensions.
+    message = any_test_pb2.TestAny()
+    text = ('any_value {\n'
+            '  [type.googleapis.com.invalid/google.protobuf.internal.TestAny] {\n'
+            '    [unknown_extension] {\n'
+            '      str: "string"\n'
+            '      any_value {\n'
+            '        [type.googleapis.com/protobuf_unittest.OneString] {\n'
+            '          data: "string"\n'
+            '        }\n'
+            '      }\n'
+            '    }\n'
+            '  }\n'
+            '}\n'
+            'int32_value: 123')
+    self.assertRaisesRegex(
+        text_format.ParseError,
+        '[type.googleapis.com.invalid/google.protobuf.internal.TestAny]',
+        text_format.Parse,
+        text,
+        message,
+        allow_unknown_extension=True)
+
   def testParseBadIdentifier(self):
     message = unittest_pb2.TestAllTypes()
     text = ('optional_nested_message { "bb": 1 }')
@@ -2442,6 +2483,5 @@
         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
old mode 100644
new mode 100755
index a53e71f..165dcd8
--- a/python/google/protobuf/internal/type_checkers.py
+++ b/python/google/protobuf/internal/type_checkers.py
@@ -75,10 +75,6 @@
   return rounded
 
 
-def SupportsOpenEnums(field_descriptor):
-  return field_descriptor.containing_type.syntax == 'proto3'
-
-
 def GetTypeChecker(field):
   """Returns a type checker for a message field of the specified types.
 
@@ -93,11 +89,11 @@
       field.type == _FieldDescriptor.TYPE_STRING):
     return UnicodeValueChecker()
   if field.cpp_type == _FieldDescriptor.CPPTYPE_ENUM:
-    if SupportsOpenEnums(field):
+    if field.enum_type.is_closed:
+      return EnumValueChecker(field.enum_type)
+    else:
       # When open enums are supported, any int32 can be assigned.
       return _VALUE_CHECKERS[_FieldDescriptor.CPPTYPE_INT32]
-    else:
-      return EnumValueChecker(field.enum_type)
   return _VALUE_CHECKERS[field.cpp_type]
 
 
diff --git a/python/google/protobuf/internal/unknown_fields_test.py b/python/google/protobuf/internal/unknown_fields_test.py
index 64a0367..ec1aa1b 100644
--- a/python/google/protobuf/internal/unknown_fields_test.py
+++ b/python/google/protobuf/internal/unknown_fields_test.py
@@ -36,10 +36,6 @@
 import sys
 import unittest
 
-from google.protobuf import map_unittest_pb2
-from google.protobuf import unittest_mset_pb2
-from google.protobuf import unittest_pb2
-from google.protobuf import unittest_proto3_arena_pb2
 from google.protobuf.internal import api_implementation
 from google.protobuf.internal import encoder
 from google.protobuf.internal import message_set_extensions_pb2
@@ -50,6 +46,10 @@
 from google.protobuf.internal import wire_format
 from google.protobuf import descriptor
 from google.protobuf import unknown_fields
+from google.protobuf import map_unittest_pb2
+from google.protobuf import unittest_mset_pb2
+from google.protobuf import unittest_pb2
+from google.protobuf import unittest_proto3_arena_pb2
 try:
   import tracemalloc  # pylint: disable=g-import-not-at-top
 except ImportError:
diff --git a/python/google/protobuf/internal/well_known_types.py b/python/google/protobuf/internal/well_known_types.py
index 8881d75..e340f90 100644
--- a/python/google/protobuf/internal/well_known_types.py
+++ b/python/google/protobuf/internal/well_known_types.py
@@ -44,7 +44,9 @@
 import collections.abc
 import datetime
 
-from google.protobuf.descriptor import FieldDescriptor
+from google.protobuf.internal import field_mask
+
+FieldMask = field_mask.FieldMask
 
 _TIMESTAMPFOMAT = '%Y-%m-%dT%H:%M:%S'
 _NANOS_PER_SECOND = 1000000000
@@ -430,306 +432,6 @@
     return result
 
 
-class FieldMask(object):
-  """Class for FieldMask message type."""
-
-  __slots__ = ()
-
-  def ToJsonString(self):
-    """Converts FieldMask to string according to proto3 JSON spec."""
-    camelcase_paths = []
-    for path in self.paths:
-      camelcase_paths.append(_SnakeCaseToCamelCase(path))
-    return ','.join(camelcase_paths)
-
-  def FromJsonString(self, value):
-    """Converts string to FieldMask according to proto3 JSON spec."""
-    if not isinstance(value, str):
-      raise ValueError('FieldMask JSON value not a string: {!r}'.format(value))
-    self.Clear()
-    if value:
-      for path in value.split(','):
-        self.paths.append(_CamelCaseToSnakeCase(path))
-
-  def IsValidForDescriptor(self, message_descriptor):
-    """Checks whether the FieldMask is valid for Message Descriptor."""
-    for path in self.paths:
-      if not _IsValidPath(message_descriptor, path):
-        return False
-    return True
-
-  def AllFieldsFromDescriptor(self, message_descriptor):
-    """Gets all direct fields of Message Descriptor to FieldMask."""
-    self.Clear()
-    for field in message_descriptor.fields:
-      self.paths.append(field.name)
-
-  def CanonicalFormFromMask(self, mask):
-    """Converts a FieldMask to the canonical form.
-
-    Removes paths that are covered by another path. For example,
-    "foo.bar" is covered by "foo" and will be removed if "foo"
-    is also in the FieldMask. Then sorts all paths in alphabetical order.
-
-    Args:
-      mask: The original FieldMask to be converted.
-    """
-    tree = _FieldMaskTree(mask)
-    tree.ToFieldMask(self)
-
-  def Union(self, mask1, mask2):
-    """Merges mask1 and mask2 into this FieldMask."""
-    _CheckFieldMaskMessage(mask1)
-    _CheckFieldMaskMessage(mask2)
-    tree = _FieldMaskTree(mask1)
-    tree.MergeFromFieldMask(mask2)
-    tree.ToFieldMask(self)
-
-  def Intersect(self, mask1, mask2):
-    """Intersects mask1 and mask2 into this FieldMask."""
-    _CheckFieldMaskMessage(mask1)
-    _CheckFieldMaskMessage(mask2)
-    tree = _FieldMaskTree(mask1)
-    intersection = _FieldMaskTree()
-    for path in mask2.paths:
-      tree.IntersectPath(path, intersection)
-    intersection.ToFieldMask(self)
-
-  def MergeMessage(
-      self, source, destination,
-      replace_message_field=False, replace_repeated_field=False):
-    """Merges fields specified in FieldMask from source to destination.
-
-    Args:
-      source: Source message.
-      destination: The destination message to be merged into.
-      replace_message_field: Replace message field if True. Merge message
-          field if False.
-      replace_repeated_field: Replace repeated field if True. Append
-          elements of repeated field if False.
-    """
-    tree = _FieldMaskTree(self)
-    tree.MergeMessage(
-        source, destination, replace_message_field, replace_repeated_field)
-
-
-def _IsValidPath(message_descriptor, path):
-  """Checks whether the path is valid for Message Descriptor."""
-  parts = path.split('.')
-  last = parts.pop()
-  for name in parts:
-    field = message_descriptor.fields_by_name.get(name)
-    if (field is None or
-        field.label == FieldDescriptor.LABEL_REPEATED or
-        field.type != FieldDescriptor.TYPE_MESSAGE):
-      return False
-    message_descriptor = field.message_type
-  return last in message_descriptor.fields_by_name
-
-
-def _CheckFieldMaskMessage(message):
-  """Raises ValueError if message is not a FieldMask."""
-  message_descriptor = message.DESCRIPTOR
-  if (message_descriptor.name != 'FieldMask' or
-      message_descriptor.file.name != 'google/protobuf/field_mask.proto'):
-    raise ValueError('Message {0} is not a FieldMask.'.format(
-        message_descriptor.full_name))
-
-
-def _SnakeCaseToCamelCase(path_name):
-  """Converts a path name from snake_case to camelCase."""
-  result = []
-  after_underscore = False
-  for c in path_name:
-    if c.isupper():
-      raise ValueError(
-          'Fail to print FieldMask to Json string: Path name '
-          '{0} must not contain uppercase letters.'.format(path_name))
-    if after_underscore:
-      if c.islower():
-        result.append(c.upper())
-        after_underscore = False
-      else:
-        raise ValueError(
-            'Fail to print FieldMask to Json string: The '
-            'character after a "_" must be a lowercase letter '
-            'in path name {0}.'.format(path_name))
-    elif c == '_':
-      after_underscore = True
-    else:
-      result += c
-
-  if after_underscore:
-    raise ValueError('Fail to print FieldMask to Json string: Trailing "_" '
-                     'in path name {0}.'.format(path_name))
-  return ''.join(result)
-
-
-def _CamelCaseToSnakeCase(path_name):
-  """Converts a field name from camelCase to snake_case."""
-  result = []
-  for c in path_name:
-    if c == '_':
-      raise ValueError('Fail to parse FieldMask: Path name '
-                       '{0} must not contain "_"s.'.format(path_name))
-    if c.isupper():
-      result += '_'
-      result += c.lower()
-    else:
-      result += c
-  return ''.join(result)
-
-
-class _FieldMaskTree(object):
-  """Represents a FieldMask in a tree structure.
-
-  For example, given a FieldMask "foo.bar,foo.baz,bar.baz",
-  the FieldMaskTree will be:
-      [_root] -+- foo -+- bar
-            |       |
-            |       +- baz
-            |
-            +- bar --- baz
-  In the tree, each leaf node represents a field path.
-  """
-
-  __slots__ = ('_root',)
-
-  def __init__(self, field_mask=None):
-    """Initializes the tree by FieldMask."""
-    self._root = {}
-    if field_mask:
-      self.MergeFromFieldMask(field_mask)
-
-  def MergeFromFieldMask(self, field_mask):
-    """Merges a FieldMask to the tree."""
-    for path in field_mask.paths:
-      self.AddPath(path)
-
-  def AddPath(self, path):
-    """Adds a field path into the tree.
-
-    If the field path to add is a sub-path of an existing field path
-    in the tree (i.e., a leaf node), it means the tree already matches
-    the given path so nothing will be added to the tree. If the path
-    matches an existing non-leaf node in the tree, that non-leaf node
-    will be turned into a leaf node with all its children removed because
-    the path matches all the node's children. Otherwise, a new path will
-    be added.
-
-    Args:
-      path: The field path to add.
-    """
-    node = self._root
-    for name in path.split('.'):
-      if name not in node:
-        node[name] = {}
-      elif not node[name]:
-        # Pre-existing empty node implies we already have this entire tree.
-        return
-      node = node[name]
-    # Remove any sub-trees we might have had.
-    node.clear()
-
-  def ToFieldMask(self, field_mask):
-    """Converts the tree to a FieldMask."""
-    field_mask.Clear()
-    _AddFieldPaths(self._root, '', field_mask)
-
-  def IntersectPath(self, path, intersection):
-    """Calculates the intersection part of a field path with this tree.
-
-    Args:
-      path: The field path to calculates.
-      intersection: The out tree to record the intersection part.
-    """
-    node = self._root
-    for name in path.split('.'):
-      if name not in node:
-        return
-      elif not node[name]:
-        intersection.AddPath(path)
-        return
-      node = node[name]
-    intersection.AddLeafNodes(path, node)
-
-  def AddLeafNodes(self, prefix, node):
-    """Adds leaf nodes begin with prefix to this tree."""
-    if not node:
-      self.AddPath(prefix)
-    for name in node:
-      child_path = prefix + '.' + name
-      self.AddLeafNodes(child_path, node[name])
-
-  def MergeMessage(
-      self, source, destination,
-      replace_message, replace_repeated):
-    """Merge all fields specified by this tree from source to destination."""
-    _MergeMessage(
-        self._root, source, destination, replace_message, replace_repeated)
-
-
-def _StrConvert(value):
-  """Converts value to str if it is not."""
-  # This file is imported by c extension and some methods like ClearField
-  # requires string for the field name. py2/py3 has different text
-  # type and may use unicode.
-  if not isinstance(value, str):
-    return value.encode('utf-8')
-  return value
-
-
-def _MergeMessage(
-    node, source, destination, replace_message, replace_repeated):
-  """Merge all fields specified by a sub-tree from source to destination."""
-  source_descriptor = source.DESCRIPTOR
-  for name in node:
-    child = node[name]
-    field = source_descriptor.fields_by_name[name]
-    if field is None:
-      raise ValueError('Error: Can\'t find field {0} in message {1}.'.format(
-          name, source_descriptor.full_name))
-    if child:
-      # Sub-paths are only allowed for singular message fields.
-      if (field.label == FieldDescriptor.LABEL_REPEATED or
-          field.cpp_type != FieldDescriptor.CPPTYPE_MESSAGE):
-        raise ValueError('Error: Field {0} in message {1} is not a singular '
-                         'message field and cannot have sub-fields.'.format(
-                             name, source_descriptor.full_name))
-      if source.HasField(name):
-        _MergeMessage(
-            child, getattr(source, name), getattr(destination, name),
-            replace_message, replace_repeated)
-      continue
-    if field.label == FieldDescriptor.LABEL_REPEATED:
-      if replace_repeated:
-        destination.ClearField(_StrConvert(name))
-      repeated_source = getattr(source, name)
-      repeated_destination = getattr(destination, name)
-      repeated_destination.MergeFrom(repeated_source)
-    else:
-      if field.cpp_type == FieldDescriptor.CPPTYPE_MESSAGE:
-        if replace_message:
-          destination.ClearField(_StrConvert(name))
-        if source.HasField(name):
-          getattr(destination, name).MergeFrom(getattr(source, name))
-      else:
-        setattr(destination, name, getattr(source, name))
-
-
-def _AddFieldPaths(node, prefix, field_mask):
-  """Adds the field paths descended from node to field_mask."""
-  if not node and prefix:
-    field_mask.paths.append(prefix)
-    return
-  for name in sorted(node):
-    if prefix:
-      child_path = prefix + '.' + name
-    else:
-      child_path = name
-    _AddFieldPaths(node[name], child_path, field_mask)
-
-
 def _SetStructValue(struct_value, value):
   if value is None:
     struct_value.null_value = 0
diff --git a/python/google/protobuf/internal/well_known_types_test.py b/python/google/protobuf/internal/well_known_types_test.py
index a32459a..19c5a08 100644
--- a/python/google/protobuf/internal/well_known_types_test.py
+++ b/python/google/protobuf/internal/well_known_types_test.py
@@ -38,17 +38,13 @@
 
 from google.protobuf import any_pb2
 from google.protobuf import duration_pb2
-from google.protobuf import field_mask_pb2
 from google.protobuf import struct_pb2
 from google.protobuf import timestamp_pb2
-from google.protobuf import map_unittest_pb2
-from google.protobuf import unittest_pb2
 from google.protobuf.internal import any_test_pb2
-from google.protobuf.internal import test_util
 from google.protobuf.internal import well_known_types
-from google.protobuf import descriptor
 from google.protobuf import text_format
 from google.protobuf.internal import _parameterized
+from google.protobuf import unittest_pb2
 
 try:
   # New module in Python 3.9:
@@ -390,362 +386,6 @@
                            message.ToJsonString)
 
 
-class FieldMaskTest(unittest.TestCase):
-
-  def testStringFormat(self):
-    mask = field_mask_pb2.FieldMask()
-    self.assertEqual('', mask.ToJsonString())
-    mask.paths.append('foo')
-    self.assertEqual('foo', mask.ToJsonString())
-    mask.paths.append('bar')
-    self.assertEqual('foo,bar', mask.ToJsonString())
-
-    mask.FromJsonString('')
-    self.assertEqual('', mask.ToJsonString())
-    mask.FromJsonString('foo')
-    self.assertEqual(['foo'], mask.paths)
-    mask.FromJsonString('foo,bar')
-    self.assertEqual(['foo', 'bar'], mask.paths)
-
-    # Test camel case
-    mask.Clear()
-    mask.paths.append('foo_bar')
-    self.assertEqual('fooBar', mask.ToJsonString())
-    mask.paths.append('bar_quz')
-    self.assertEqual('fooBar,barQuz', mask.ToJsonString())
-
-    mask.FromJsonString('')
-    self.assertEqual('', mask.ToJsonString())
-    self.assertEqual([], mask.paths)
-    mask.FromJsonString('fooBar')
-    self.assertEqual(['foo_bar'], mask.paths)
-    mask.FromJsonString('fooBar,barQuz')
-    self.assertEqual(['foo_bar', 'bar_quz'], mask.paths)
-
-  def testDescriptorToFieldMask(self):
-    mask = field_mask_pb2.FieldMask()
-    msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
-    mask.AllFieldsFromDescriptor(msg_descriptor)
-    self.assertEqual(76, len(mask.paths))
-    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
-    for field in msg_descriptor.fields:
-      self.assertTrue(field.name in mask.paths)
-
-  def testIsValidForDescriptor(self):
-    msg_descriptor = unittest_pb2.TestAllTypes.DESCRIPTOR
-    # Empty mask
-    mask = field_mask_pb2.FieldMask()
-    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
-    # All fields from descriptor
-    mask.AllFieldsFromDescriptor(msg_descriptor)
-    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
-    # Child under optional message
-    mask.paths.append('optional_nested_message.bb')
-    self.assertTrue(mask.IsValidForDescriptor(msg_descriptor))
-    # Repeated field is only allowed in the last position of path
-    mask.paths.append('repeated_nested_message.bb')
-    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
-    # Invalid top level field
-    mask = field_mask_pb2.FieldMask()
-    mask.paths.append('xxx')
-    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
-    # Invalid field in root
-    mask = field_mask_pb2.FieldMask()
-    mask.paths.append('xxx.zzz')
-    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
-    # Invalid field in internal node
-    mask = field_mask_pb2.FieldMask()
-    mask.paths.append('optional_nested_message.xxx.zzz')
-    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
-    # Invalid field in leaf
-    mask = field_mask_pb2.FieldMask()
-    mask.paths.append('optional_nested_message.xxx')
-    self.assertFalse(mask.IsValidForDescriptor(msg_descriptor))
-
-  def testCanonicalFrom(self):
-    mask = field_mask_pb2.FieldMask()
-    out_mask = field_mask_pb2.FieldMask()
-    # Paths will be sorted.
-    mask.FromJsonString('baz.quz,bar,foo')
-    out_mask.CanonicalFormFromMask(mask)
-    self.assertEqual('bar,baz.quz,foo', out_mask.ToJsonString())
-    # Duplicated paths will be removed.
-    mask.FromJsonString('foo,bar,foo')
-    out_mask.CanonicalFormFromMask(mask)
-    self.assertEqual('bar,foo', out_mask.ToJsonString())
-    # Sub-paths of other paths will be removed.
-    mask.FromJsonString('foo.b1,bar.b1,foo.b2,bar')
-    out_mask.CanonicalFormFromMask(mask)
-    self.assertEqual('bar,foo.b1,foo.b2', out_mask.ToJsonString())
-
-    # Test more deeply nested cases.
-    mask.FromJsonString(
-        'foo.bar.baz1,foo.bar.baz2.quz,foo.bar.baz2')
-    out_mask.CanonicalFormFromMask(mask)
-    self.assertEqual('foo.bar.baz1,foo.bar.baz2',
-                     out_mask.ToJsonString())
-    mask.FromJsonString(
-        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz')
-    out_mask.CanonicalFormFromMask(mask)
-    self.assertEqual('foo.bar.baz1,foo.bar.baz2',
-                     out_mask.ToJsonString())
-    mask.FromJsonString(
-        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo.bar')
-    out_mask.CanonicalFormFromMask(mask)
-    self.assertEqual('foo.bar', out_mask.ToJsonString())
-    mask.FromJsonString(
-        'foo.bar.baz1,foo.bar.baz2,foo.bar.baz2.quz,foo')
-    out_mask.CanonicalFormFromMask(mask)
-    self.assertEqual('foo', out_mask.ToJsonString())
-
-  def testUnion(self):
-    mask1 = field_mask_pb2.FieldMask()
-    mask2 = field_mask_pb2.FieldMask()
-    out_mask = field_mask_pb2.FieldMask()
-    mask1.FromJsonString('foo,baz')
-    mask2.FromJsonString('bar,quz')
-    out_mask.Union(mask1, mask2)
-    self.assertEqual('bar,baz,foo,quz', out_mask.ToJsonString())
-    # Overlap with duplicated paths.
-    mask1.FromJsonString('foo,baz.bb')
-    mask2.FromJsonString('baz.bb,quz')
-    out_mask.Union(mask1, mask2)
-    self.assertEqual('baz.bb,foo,quz', out_mask.ToJsonString())
-    # Overlap with paths covering some other paths.
-    mask1.FromJsonString('foo.bar.baz,quz')
-    mask2.FromJsonString('foo.bar,bar')
-    out_mask.Union(mask1, mask2)
-    self.assertEqual('bar,foo.bar,quz', out_mask.ToJsonString())
-    src = unittest_pb2.TestAllTypes()
-    with self.assertRaises(ValueError):
-      out_mask.Union(src, mask2)
-
-  def testIntersect(self):
-    mask1 = field_mask_pb2.FieldMask()
-    mask2 = field_mask_pb2.FieldMask()
-    out_mask = field_mask_pb2.FieldMask()
-    # Test cases without overlapping.
-    mask1.FromJsonString('foo,baz')
-    mask2.FromJsonString('bar,quz')
-    out_mask.Intersect(mask1, mask2)
-    self.assertEqual('', out_mask.ToJsonString())
-    self.assertEqual(len(out_mask.paths), 0)
-    self.assertEqual(out_mask.paths, [])
-    # Overlap with duplicated paths.
-    mask1.FromJsonString('foo,baz.bb')
-    mask2.FromJsonString('baz.bb,quz')
-    out_mask.Intersect(mask1, mask2)
-    self.assertEqual('baz.bb', out_mask.ToJsonString())
-    # Overlap with paths covering some other paths.
-    mask1.FromJsonString('foo.bar.baz,quz')
-    mask2.FromJsonString('foo.bar,bar')
-    out_mask.Intersect(mask1, mask2)
-    self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
-    mask1.FromJsonString('foo.bar,bar')
-    mask2.FromJsonString('foo.bar.baz,quz')
-    out_mask.Intersect(mask1, mask2)
-    self.assertEqual('foo.bar.baz', out_mask.ToJsonString())
-    # Intersect '' with ''
-    mask1.Clear()
-    mask2.Clear()
-    mask1.paths.append('')
-    mask2.paths.append('')
-    self.assertEqual(mask1.paths, [''])
-    self.assertEqual('', mask1.ToJsonString())
-    out_mask.Intersect(mask1, mask2)
-    self.assertEqual(out_mask.paths, [])
-
-  def testMergeMessageWithoutMapFields(self):
-    # Test merge one field.
-    src = unittest_pb2.TestAllTypes()
-    test_util.SetAllFields(src)
-    for field in src.DESCRIPTOR.fields:
-      if field.containing_oneof:
-        continue
-      field_name = field.name
-      dst = unittest_pb2.TestAllTypes()
-      # Only set one path to mask.
-      mask = field_mask_pb2.FieldMask()
-      mask.paths.append(field_name)
-      mask.MergeMessage(src, dst)
-      # The expected result message.
-      msg = unittest_pb2.TestAllTypes()
-      if field.label == descriptor.FieldDescriptor.LABEL_REPEATED:
-        repeated_src = getattr(src, field_name)
-        repeated_msg = getattr(msg, field_name)
-        if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
-          for item in repeated_src:
-            repeated_msg.add().CopyFrom(item)
-        else:
-          repeated_msg.extend(repeated_src)
-      elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
-        getattr(msg, field_name).CopyFrom(getattr(src, field_name))
-      else:
-        setattr(msg, field_name, getattr(src, field_name))
-      # Only field specified in mask is merged.
-      self.assertEqual(msg, dst)
-
-    # Test merge nested fields.
-    nested_src = unittest_pb2.NestedTestAllTypes()
-    nested_dst = unittest_pb2.NestedTestAllTypes()
-    nested_src.child.payload.optional_int32 = 1234
-    nested_src.child.child.payload.optional_int32 = 5678
-    mask = field_mask_pb2.FieldMask()
-    mask.FromJsonString('child.payload')
-    mask.MergeMessage(nested_src, nested_dst)
-    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
-    self.assertEqual(0, nested_dst.child.child.payload.optional_int32)
-
-    mask.FromJsonString('child.child.payload')
-    mask.MergeMessage(nested_src, nested_dst)
-    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
-    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
-
-    nested_dst.Clear()
-    mask.FromJsonString('child.child.payload')
-    mask.MergeMessage(nested_src, nested_dst)
-    self.assertEqual(0, nested_dst.child.payload.optional_int32)
-    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
-
-    nested_dst.Clear()
-    mask.FromJsonString('child')
-    mask.MergeMessage(nested_src, nested_dst)
-    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
-    self.assertEqual(5678, nested_dst.child.child.payload.optional_int32)
-
-    # Test MergeOptions.
-    nested_dst.Clear()
-    nested_dst.child.payload.optional_int64 = 4321
-    # Message fields will be merged by default.
-    mask.FromJsonString('child.payload')
-    mask.MergeMessage(nested_src, nested_dst)
-    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
-    self.assertEqual(4321, nested_dst.child.payload.optional_int64)
-    # Change the behavior to replace message fields.
-    mask.FromJsonString('child.payload')
-    mask.MergeMessage(nested_src, nested_dst, True, False)
-    self.assertEqual(1234, nested_dst.child.payload.optional_int32)
-    self.assertEqual(0, nested_dst.child.payload.optional_int64)
-
-    # By default, fields missing in source are not cleared in destination.
-    nested_dst.payload.optional_int32 = 1234
-    self.assertTrue(nested_dst.HasField('payload'))
-    mask.FromJsonString('payload')
-    mask.MergeMessage(nested_src, nested_dst)
-    self.assertTrue(nested_dst.HasField('payload'))
-    # But they are cleared when replacing message fields.
-    nested_dst.Clear()
-    nested_dst.payload.optional_int32 = 1234
-    mask.FromJsonString('payload')
-    mask.MergeMessage(nested_src, nested_dst, True, False)
-    self.assertFalse(nested_dst.HasField('payload'))
-
-    nested_src.payload.repeated_int32.append(1234)
-    nested_dst.payload.repeated_int32.append(5678)
-    # Repeated fields will be appended by default.
-    mask.FromJsonString('payload.repeatedInt32')
-    mask.MergeMessage(nested_src, nested_dst)
-    self.assertEqual(2, len(nested_dst.payload.repeated_int32))
-    self.assertEqual(5678, nested_dst.payload.repeated_int32[0])
-    self.assertEqual(1234, nested_dst.payload.repeated_int32[1])
-    # Change the behavior to replace repeated fields.
-    mask.FromJsonString('payload.repeatedInt32')
-    mask.MergeMessage(nested_src, nested_dst, False, True)
-    self.assertEqual(1, len(nested_dst.payload.repeated_int32))
-    self.assertEqual(1234, nested_dst.payload.repeated_int32[0])
-
-    # Test Merge oneof field.
-    new_msg = unittest_pb2.TestOneof2()
-    dst = unittest_pb2.TestOneof2()
-    dst.foo_message.moo_int = 1
-    mask = field_mask_pb2.FieldMask()
-    mask.FromJsonString('fooMessage,fooLazyMessage.mooInt')
-    mask.MergeMessage(new_msg, dst)
-    self.assertTrue(dst.HasField('foo_message'))
-    self.assertFalse(dst.HasField('foo_lazy_message'))
-
-  def testMergeMessageWithMapField(self):
-    empty_map = map_unittest_pb2.TestRecursiveMapMessage()
-    src_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
-    src_level_2.a['src level 2'].CopyFrom(empty_map)
-    src = map_unittest_pb2.TestRecursiveMapMessage()
-    src.a['common key'].CopyFrom(src_level_2)
-    src.a['src level 1'].CopyFrom(src_level_2)
-
-    dst_level_2 = map_unittest_pb2.TestRecursiveMapMessage()
-    dst_level_2.a['dst level 2'].CopyFrom(empty_map)
-    dst = map_unittest_pb2.TestRecursiveMapMessage()
-    dst.a['common key'].CopyFrom(dst_level_2)
-    dst.a['dst level 1'].CopyFrom(empty_map)
-
-    mask = field_mask_pb2.FieldMask()
-    mask.FromJsonString('a')
-    mask.MergeMessage(src, dst)
-
-    # map from dst is replaced with map from src.
-    self.assertEqual(dst.a['common key'], src_level_2)
-    self.assertEqual(dst.a['src level 1'], src_level_2)
-    self.assertEqual(dst.a['dst level 1'], empty_map)
-
-  def testMergeErrors(self):
-    src = unittest_pb2.TestAllTypes()
-    dst = unittest_pb2.TestAllTypes()
-    mask = field_mask_pb2.FieldMask()
-    test_util.SetAllFields(src)
-    mask.FromJsonString('optionalInt32.field')
-    with self.assertRaises(ValueError) as e:
-      mask.MergeMessage(src, dst)
-    self.assertEqual('Error: Field optional_int32 in message '
-                     'protobuf_unittest.TestAllTypes is not a singular '
-                     'message field and cannot have sub-fields.',
-                     str(e.exception))
-
-  def testSnakeCaseToCamelCase(self):
-    self.assertEqual('fooBar',
-                     well_known_types._SnakeCaseToCamelCase('foo_bar'))
-    self.assertEqual('FooBar',
-                     well_known_types._SnakeCaseToCamelCase('_foo_bar'))
-    self.assertEqual('foo3Bar',
-                     well_known_types._SnakeCaseToCamelCase('foo3_bar'))
-
-    # No uppercase letter is allowed.
-    self.assertRaisesRegex(
-        ValueError,
-        'Fail to print FieldMask to Json string: Path name Foo must '
-        'not contain uppercase letters.',
-        well_known_types._SnakeCaseToCamelCase, 'Foo')
-    # Any character after a "_" must be a lowercase letter.
-    #   1. "_" cannot be followed by another "_".
-    #   2. "_" cannot be followed by a digit.
-    #   3. "_" cannot appear as the last character.
-    self.assertRaisesRegex(
-        ValueError,
-        'Fail to print FieldMask to Json string: The character after a '
-        '"_" must be a lowercase letter in path name foo__bar.',
-        well_known_types._SnakeCaseToCamelCase, 'foo__bar')
-    self.assertRaisesRegex(
-        ValueError,
-        'Fail to print FieldMask to Json string: The character after a '
-        '"_" must be a lowercase letter in path name foo_3bar.',
-        well_known_types._SnakeCaseToCamelCase, 'foo_3bar')
-    self.assertRaisesRegex(
-        ValueError,
-        'Fail to print FieldMask to Json string: Trailing "_" in path '
-        'name foo_bar_.', well_known_types._SnakeCaseToCamelCase, 'foo_bar_')
-
-  def testCamelCaseToSnakeCase(self):
-    self.assertEqual('foo_bar',
-                     well_known_types._CamelCaseToSnakeCase('fooBar'))
-    self.assertEqual('_foo_bar',
-                     well_known_types._CamelCaseToSnakeCase('FooBar'))
-    self.assertEqual('foo3_bar',
-                     well_known_types._CamelCaseToSnakeCase('foo3Bar'))
-    self.assertRaisesRegex(
-        ValueError,
-        'Fail to parse FieldMask: Path name foo_bar must not contain "_"s.',
-        well_known_types._CamelCaseToSnakeCase, 'foo_bar')
-
-
 class StructTest(unittest.TestCase):
 
   def testStruct(self):
diff --git a/python/google/protobuf/internal/wire_format.py b/python/google/protobuf/internal/wire_format.py
index 883f525..1f54414 100644
--- a/python/google/protobuf/internal/wire_format.py
+++ b/python/google/protobuf/internal/wire_format.py
@@ -43,7 +43,7 @@
 # These numbers identify the wire type of a protocol buffer value.
 # We use the least-significant TAG_TYPE_BITS bits of the varint-encoded
 # tag-and-type to store one of these WIRETYPE_* constants.
-# These values must match WireType enum in google/protobuf/wire_format.h.
+# These values must match WireType enum in //google/protobuf/wire_format.h.
 WIRETYPE_VARINT = 0
 WIRETYPE_FIXED64 = 1
 WIRETYPE_LENGTH_DELIMITED = 2
diff --git a/python/google/protobuf/json_format.py b/python/google/protobuf/json_format.py
index 5024ed8..1cf29d1 100644
--- a/python/google/protobuf/json_format.py
+++ b/python/google/protobuf/json_format.py
@@ -109,7 +109,8 @@
         names as defined in the .proto file. If False, convert the field
         names to lowerCamelCase.
     indent: The JSON object will be pretty-printed with this indent level.
-        An indent level of 0 or negative will only insert newlines.
+        An indent level of 0 or negative will only insert newlines. If the
+        indent level is None, no newlines will be inserted.
     sort_keys: If True, then the output will be sorted by field names.
     use_integers_for_enums: If true, print integers instead of enum names.
     descriptor_pool: A Descriptor Pool for resolving types. If None use the
@@ -286,10 +287,11 @@
       if enum_value is not None:
         return enum_value.name
       else:
-        if field.file.syntax == 'proto3':
+        if field.enum_type.is_closed:
+          raise SerializeToJsonError('Enum field contains an integer value '
+                                     'which can not mapped to an enum value.')
+        else:
           return value
-        raise SerializeToJsonError('Enum field contains an integer value '
-                                   'which can not mapped to an enum value.')
     elif field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_STRING:
       if field.type == descriptor.FieldDescriptor.TYPE_BYTES:
         # Use base64 Data encoding for bytes
@@ -798,11 +800,11 @@
           raise ParseError('Invalid enum value {0} for enum type {1}'.format(
               value, field.enum_type.full_name))
         if enum_value is None:
-          if field.file.syntax == 'proto3':
-            # Proto3 accepts unknown enums.
+          if field.enum_type.is_closed:
+            raise ParseError('Invalid enum value {0} for enum type {1}'.format(
+                value, field.enum_type.full_name))
+          else:
             return number
-          raise ParseError('Invalid enum value {0} for enum type {1}'.format(
-              value, field.enum_type.full_name))
       return enum_value.number
   except ParseError as e:
     raise ParseError('{0} at {1}'.format(e, path))
diff --git a/python/google/protobuf/message.py b/python/google/protobuf/message.py
old mode 100644
new mode 100755
index 76c6802..0fe6a4f
--- a/python/google/protobuf/message.py
+++ b/python/google/protobuf/message.py
@@ -74,7 +74,8 @@
 
   __slots__ = []
 
-  #: The :class:`google.protobuf.descriptor.Descriptor` for this message type.
+  #: The :class:`google.protobuf.Descriptor`
+  # for this message type.
   DESCRIPTOR = None
 
   def __deepcopy__(self, memo=None):
diff --git a/python/google/protobuf/message_factory.py b/python/google/protobuf/message_factory.py
index 8d65204..ce5b5a7 100644
--- a/python/google/protobuf/message_factory.py
+++ b/python/google/protobuf/message_factory.py
@@ -60,9 +60,6 @@
     """Initializes a new factory."""
     self.pool = pool or descriptor_pool.DescriptorPool()
 
-    # local cache of all classes built from protobuf descriptors
-    self._classes = {}
-
   def GetPrototype(self, descriptor):
     """Obtains a proto2 message class based on the passed in descriptor.
 
@@ -75,14 +72,11 @@
     Returns:
       A class describing the passed in descriptor.
     """
-    if descriptor not in self._classes:
-      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
-      return result_class
-    return self._classes[descriptor]
+    concrete_class = getattr(descriptor, '_concrete_class', None)
+    if concrete_class:
+      return concrete_class
+    result_class = self.CreatePrototype(descriptor)
+    return result_class
 
   def CreatePrototype(self, descriptor):
     """Builds a proto2 message class based on the passed in descriptor.
@@ -107,16 +101,11 @@
             '__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 = self.GetPrototype(extension.containing_type)
       extended_class.RegisterExtension(extension)
       if extension.message_type:
         self.GetPrototype(extension.message_type)
@@ -152,9 +141,7 @@
       # an error if they were different.
 
       for extension in file_desc.extensions_by_name.values():
-        if extension.containing_type not in self._classes:
-          self.GetPrototype(extension.containing_type)
-        extended_class = self._classes[extension.containing_type]
+        extended_class = self.GetPrototype(extension.containing_type)
         extended_class.RegisterExtension(extension)
         if extension.message_type:
           self.GetPrototype(extension.message_type)
diff --git a/python/google/protobuf/proto_api.h b/python/google/protobuf/proto_api.h
index 9969a91..4e910e0 100644
--- a/python/google/protobuf/proto_api.h
+++ b/python/google/protobuf/proto_api.h
@@ -48,8 +48,8 @@
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/descriptor_database.h>
-#include <google/protobuf/message.h>
+#include "google/protobuf/descriptor_database.h"
+#include "google/protobuf/message.h"
 
 namespace google {
 namespace protobuf {
@@ -133,8 +133,7 @@
 };
 
 inline const char* PyProtoAPICapsuleName() {
-  static const char kCapsuleName[] =
-      "google.protobuf.pyext._message.proto_API";
+  static const char kCapsuleName[] = "google.protobuf.pyext._message.proto_API";
   return kCapsuleName;
 }
 
diff --git a/python/google/protobuf/pyext/descriptor.cc b/python/google/protobuf/pyext/descriptor.cc
index 1625312..f6db77a 100644
--- a/python/google/protobuf/pyext/descriptor.cc
+++ b/python/google/protobuf/pyext/descriptor.cc
@@ -30,7 +30,7 @@
 
 // Author: petar@google.com (Petar Petrov)
 
-#include <google/protobuf/pyext/descriptor.h>
+#include "google/protobuf/pyext/descriptor.h"
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
@@ -40,15 +40,15 @@
 #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_containers.h>
-#include <google/protobuf/pyext/descriptor_pool.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/message_factory.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/pyext/descriptor_containers.h"
+#include "google/protobuf/pyext/descriptor_pool.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/message_factory.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/coded_stream.h"
 
 #define PyString_AsStringAndSize(ob, charpp, sizep)              \
   (PyUnicode_Check(ob)                                           \
@@ -58,6 +58,37 @@
               : 0)                                               \
        : PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
 
+#if PY_VERSION_HEX < 0x030900B1 && !defined(PYPY_VERSION)
+static PyCodeObject* PyFrame_GetCode(PyFrameObject *frame)
+{
+    Py_INCREF(frame->f_code);
+    return frame->f_code;
+}
+
+static PyFrameObject* PyFrame_GetBack(PyFrameObject *frame)
+{
+    Py_XINCREF(frame->f_back);
+    return frame->f_back;
+}
+#endif
+
+#if PY_VERSION_HEX < 0x030B00A7 && !defined(PYPY_VERSION)
+static PyObject* PyFrame_GetLocals(PyFrameObject *frame)
+{
+    if (PyFrame_FastToLocalsWithError(frame) < 0) {
+        return NULL;
+    }
+    Py_INCREF(frame->f_locals);
+    return frame->f_locals;
+}
+
+static PyObject* PyFrame_GetGlobals(PyFrameObject *frame)
+{
+    Py_INCREF(frame->f_globals);
+    return frame->f_globals;
+}
+#endif
+
 namespace google {
 namespace protobuf {
 namespace python {
@@ -96,48 +127,66 @@
   // This check is not critical and is somewhat difficult to implement correctly
   // in PyPy.
   PyFrameObject* frame = PyEval_GetFrame();
+  PyCodeObject* frame_code = nullptr;
+  PyObject* frame_globals = nullptr;
+  PyObject* frame_locals = nullptr;
+  bool result = false;
+
   if (frame == nullptr) {
-    return false;
+    goto exit;
   }
+  Py_INCREF(frame);
   while (stacklevel-- > 0) {
-    frame = frame->f_back;
+    PyFrameObject* next_frame = PyFrame_GetBack(frame);
+    Py_DECREF(frame);
+    frame = next_frame;
     if (frame == nullptr) {
-      return false;
+      goto exit;
     }
   }
 
-  if (frame->f_code->co_filename == nullptr) {
-    return false;
+  frame_code = PyFrame_GetCode(frame);
+  if (frame_code->co_filename == nullptr) {
+    goto exit;
   }
   char* filename;
   Py_ssize_t filename_size;
-  if (PyString_AsStringAndSize(frame->f_code->co_filename,
+  if (PyString_AsStringAndSize(frame_code->co_filename,
                                &filename, &filename_size) < 0) {
     // filename is not a string.
     PyErr_Clear();
-    return false;
+    goto exit;
   }
   if ((filename_size < 3) ||
       (strcmp(&filename[filename_size - 3], ".py") != 0)) {
     // Cython's stack does not have .py file name and is not at global module
     // scope.
-    return true;
+    result = true;
+    goto exit;
   }
   if (filename_size < 7) {
     // filename is too short.
-    return false;
+    goto exit;
   }
   if (strcmp(&filename[filename_size - 7], "_pb2.py") != 0) {
     // Filename is not ending with _pb2.
-    return false;
+    goto exit;
   }
 
-  if (frame->f_globals != frame->f_locals) {
+  frame_globals = PyFrame_GetGlobals(frame);
+  frame_locals = PyFrame_GetLocals(frame);
+  if (frame_globals != frame_locals) {
     // Not at global module scope
-    return false;
+    goto exit;
   }
 #endif
-  return true;
+  result = true;
+exit:
+  Py_XDECREF(frame_globals);
+  Py_XDECREF(frame_locals);
+  Py_XDECREF(frame_code);
+  Py_XDECREF(frame);
+  return result;
 }
 
 // If the calling code is not a _pb2.py file, raise AttributeError.
@@ -490,6 +539,12 @@
       GetDescriptorPool_FromPool(
           _GetDescriptor(self)->file()->pool())->py_message_factory,
       _GetDescriptor(self)));
+
+  if (concrete_class == nullptr) {
+    PyErr_Clear();
+    return nullptr;
+  }
+
   Py_XINCREF(concrete_class);
   return concrete_class->AsPyObject();
 }
@@ -1127,6 +1182,11 @@
     Py_RETURN_FALSE;
   }
 }
+
+static PyObject* GetIsClosed(PyBaseDescriptor* self, void* closure) {
+  return PyBool_FromLong(_GetDescriptor(self)->is_closed());
+}
+
 static int SetHasOptions(PyBaseDescriptor *self, PyObject *value,
                          void *closure) {
   return CheckCalledFromGeneratedFile("has_options");
@@ -1170,6 +1230,7 @@
      "Containing type"},
     {"has_options", (getter)GetHasOptions, (setter)SetHasOptions,
      "Has Options"},
+    {"is_closed", (getter)GetIsClosed, nullptr, "If the enum is closed"},
     {"_options", (getter) nullptr, (setter)SetOptions, "Options"},
     {"_serialized_options", (getter) nullptr, (setter)SetSerializedOptions,
      "Serialized Options"},
@@ -1741,7 +1802,8 @@
   }
 
   const MethodDescriptor* method_descriptor =
-      _GetDescriptor(self)->FindMethodByName(StringParam(name, name_size));
+      _GetDescriptor(self)->FindMethodByName(
+          absl::string_view(name, name_size));
   if (method_descriptor == nullptr) {
     PyErr_Format(PyExc_KeyError, "Couldn't find method %.200s", name);
     return nullptr;
diff --git a/python/google/protobuf/pyext/descriptor.h b/python/google/protobuf/pyext/descriptor.h
index d97e2f8..8559c66 100644
--- a/python/google/protobuf/pyext/descriptor.h
+++ b/python/google/protobuf/pyext/descriptor.h
@@ -36,15 +36,12 @@
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 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 a87155b..f38fdc7 100644
--- a/python/google/protobuf/pyext/descriptor_containers.cc
+++ b/python/google/protobuf/pyext/descriptor_containers.cc
@@ -49,14 +49,21 @@
 // because the Python API is based on C, and does not play well with C++
 // inheritance.
 
+// clang-format off
 #define PY_SSIZE_T_CLEAN
+// This inclusion must appear before all the others.
 #include <Python.h>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/pyext/descriptor_containers.h>
-#include <google/protobuf/pyext/descriptor_pool.h>
-#include <google/protobuf/pyext/descriptor.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include <string>
+
+#include "google/protobuf/pyext/descriptor_containers.h"
+// clang-format on
+
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/pyext/descriptor.h"
+#include "google/protobuf/pyext/descriptor_pool.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
+#include "absl/strings/string_view.h"
 
 #define PyString_AsStringAndSize(ob, charpp, sizep)              \
   (PyUnicode_Check(ob)                                           \
@@ -75,9 +82,9 @@
 typedef int (*CountMethod)(PyContainer* self);
 typedef const void* (*GetByIndexMethod)(PyContainer* self, int index);
 typedef const void* (*GetByNameMethod)(PyContainer* self,
-                                       ConstStringParam name);
+                                       absl::string_view name);
 typedef const void* (*GetByCamelcaseNameMethod)(PyContainer* self,
-                                                ConstStringParam name);
+                                                absl::string_view name);
 typedef const void* (*GetByNumberMethod)(PyContainer* self, int index);
 typedef PyObject* (*NewObjectFromItemMethod)(const void* descriptor);
 typedef const std::string& (*GetItemNameMethod)(const void* descriptor);
@@ -175,8 +182,8 @@
         }
         return false;
       }
-      *item = self->container_def->get_by_name_fn(self,
-                                                  StringParam(name, name_size));
+      *item = self->container_def->get_by_name_fn(
+          self, absl::string_view(name, name_size));
       return true;
     }
     case PyContainer::KIND_BYCAMELCASENAME: {
@@ -192,7 +199,7 @@
         return false;
       }
       *item = self->container_def->get_by_camelcase_name_fn(
-          self, StringParam(camelcase_name, name_size));
+          self, absl::string_view(camelcase_name, name_size));
       return true;
     }
     case PyContainer::KIND_BYNUMBER: {
@@ -958,12 +965,12 @@
   return GetDescriptor(self)->field_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindFieldByName(name);
 }
 
 static const void* GetByCamelcaseName(PyContainer* self,
-                                      ConstStringParam name) {
+                                      absl::string_view name) {
   return GetDescriptor(self)->FindFieldByCamelcaseName(name);
 }
 
@@ -1028,7 +1035,7 @@
   return GetDescriptor(self)->nested_type_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindNestedTypeByName(name);
 }
 
@@ -1080,7 +1087,7 @@
   return GetDescriptor(self)->enum_type_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindEnumTypeByName(name);
 }
 
@@ -1143,7 +1150,7 @@
   return count;
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindEnumValueByName(name);
 }
 
@@ -1194,7 +1201,7 @@
   return GetDescriptor(self)->extension_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindExtensionByName(name);
 }
 
@@ -1246,7 +1253,7 @@
   return GetDescriptor(self)->oneof_decl_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindOneofByName(name);
 }
 
@@ -1304,7 +1311,7 @@
   return GetDescriptor(self)->value(index);
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindValueByName(name);
 }
 
@@ -1408,7 +1415,7 @@
   return GetDescriptor(self)->method_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindMethodByName(name);
 }
 
@@ -1462,7 +1469,7 @@
   return GetDescriptor(self)->message_type_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindMessageTypeByName(name);
 }
 
@@ -1502,7 +1509,7 @@
   return GetDescriptor(self)->enum_type_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindEnumTypeByName(name);
 }
 
@@ -1542,7 +1549,7 @@
   return GetDescriptor(self)->extension_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view name) {
   return GetDescriptor(self)->FindExtensionByName(name);
 }
 
@@ -1582,7 +1589,7 @@
   return GetDescriptor(self)->service_count();
 }
 
-static const void* GetByName(PyContainer* self, ConstStringParam name) {
+static const void* GetByName(PyContainer* self, absl::string_view 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 f87f23d..e547306 100644
--- a/python/google/protobuf/pyext/descriptor_database.cc
+++ b/python/google/protobuf/pyext/descriptor_database.cc
@@ -31,15 +31,17 @@
 // This file defines a C++ DescriptorDatabase, which wraps a Python Database
 // and delegate all its operations to Python methods.
 
-#include <google/protobuf/pyext/descriptor_database.h>
+#include "google/protobuf/pyext/descriptor_database.h"
 
 #include <cstdint>
+#include <string>
+#include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/descriptor_database.h b/python/google/protobuf/pyext/descriptor_database.h
index 5621a22..108a858 100644
--- a/python/google/protobuf/pyext/descriptor_database.h
+++ b/python/google/protobuf/pyext/descriptor_database.h
@@ -34,7 +34,10 @@
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/descriptor_database.h>
+#include <string>
+#include <vector>
+
+#include "google/protobuf/descriptor_database.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/descriptor_pool.cc b/python/google/protobuf/pyext/descriptor_pool.cc
index 2f39281..9388f16 100644
--- a/python/google/protobuf/pyext/descriptor_pool.cc
+++ b/python/google/protobuf/pyext/descriptor_pool.cc
@@ -30,19 +30,23 @@
 
 // Implements the DescriptorPool, which collects all descriptors.
 
+#include <string>
 #include <unordered_map>
+#include <utility>
+#include <vector>
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/pyext/descriptor.h>
-#include <google/protobuf/pyext/descriptor_database.h>
-#include <google/protobuf/pyext/descriptor_pool.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/message_factory.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/pyext/descriptor.h"
+#include "google/protobuf/pyext/descriptor_database.h"
+#include "google/protobuf/pyext/descriptor_pool.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/message_factory.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/str_replace.h"
 
 #define PyString_AsStringAndSize(ob, charpp, sizep)              \
   (PyUnicode_Check(ob)                                           \
@@ -246,7 +250,7 @@
 
   const Descriptor* message_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMessageTypeByName(
-          StringParam(name, name_size));
+          absl::string_view(name, name_size));
 
   if (message_descriptor == nullptr) {
     return SetErrorFromCollector(
@@ -270,7 +274,7 @@
 
   PyDescriptorPool* py_pool = reinterpret_cast<PyDescriptorPool*>(self);
   const FileDescriptor* file_descriptor =
-      py_pool->pool->FindFileByName(StringParam(name, name_size));
+      py_pool->pool->FindFileByName(absl::string_view(name, name_size));
 
   if (file_descriptor == nullptr) {
     return SetErrorFromCollector(py_pool->error_collector, name, "file");
@@ -286,7 +290,7 @@
   }
 
   const FieldDescriptor* field_descriptor =
-      self->pool->FindFieldByName(StringParam(name, name_size));
+      self->pool->FindFieldByName(absl::string_view(name, name_size));
   if (field_descriptor == nullptr) {
     return SetErrorFromCollector(self->error_collector, name, "field");
   }
@@ -307,7 +311,7 @@
   }
 
   const FieldDescriptor* field_descriptor =
-      self->pool->FindExtensionByName(StringParam(name, name_size));
+      self->pool->FindExtensionByName(absl::string_view(name, name_size));
   if (field_descriptor == nullptr) {
     return SetErrorFromCollector(self->error_collector, name,
                                  "extension field");
@@ -329,7 +333,7 @@
   }
 
   const EnumDescriptor* enum_descriptor =
-      self->pool->FindEnumTypeByName(StringParam(name, name_size));
+      self->pool->FindEnumTypeByName(absl::string_view(name, name_size));
   if (enum_descriptor == nullptr) {
     return SetErrorFromCollector(self->error_collector, name, "enum");
   }
@@ -350,7 +354,7 @@
   }
 
   const OneofDescriptor* oneof_descriptor =
-      self->pool->FindOneofByName(StringParam(name, name_size));
+      self->pool->FindOneofByName(absl::string_view(name, name_size));
   if (oneof_descriptor == nullptr) {
     return SetErrorFromCollector(self->error_collector, name, "oneof");
   }
@@ -372,7 +376,7 @@
 
   const ServiceDescriptor* service_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindServiceByName(
-          StringParam(name, name_size));
+          absl::string_view(name, name_size));
   if (service_descriptor == nullptr) {
     return SetErrorFromCollector(
         reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
@@ -392,7 +396,7 @@
 
   const MethodDescriptor* method_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindMethodByName(
-          StringParam(name, name_size));
+          absl::string_view(name, name_size));
   if (method_descriptor == nullptr) {
     return SetErrorFromCollector(
         reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
@@ -412,7 +416,7 @@
 
   const FileDescriptor* file_descriptor =
       reinterpret_cast<PyDescriptorPool*>(self)->pool->FindFileContainingSymbol(
-          StringParam(name, name_size));
+          absl::string_view(name, name_size));
   if (file_descriptor == nullptr) {
     return SetErrorFromCollector(
         reinterpret_cast<PyDescriptorPool*>(self)->error_collector, name,
diff --git a/python/google/protobuf/pyext/descriptor_pool.h b/python/google/protobuf/pyext/descriptor_pool.h
index 5d3c3a9..851cf31 100644
--- a/python/google/protobuf/pyext/descriptor_pool.h
+++ b/python/google/protobuf/pyext/descriptor_pool.h
@@ -35,7 +35,7 @@
 #include <Python.h>
 
 #include <unordered_map>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/extension_dict.cc b/python/google/protobuf/pyext/extension_dict.cc
index 66703da..806af4f 100644
--- a/python/google/protobuf/pyext/extension_dict.cc
+++ b/python/google/protobuf/pyext/extension_dict.cc
@@ -31,23 +31,25 @@
 // Author: anuraag@google.com (Anuraag Agrawal)
 // Author: tibell@google.com (Johan Tibell)
 
-#include <google/protobuf/pyext/extension_dict.h>
+#include "google/protobuf/pyext/extension_dict.h"
 
 #include <cstdint>
 #include <memory>
+#include <vector>
 
-#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/pyext/descriptor.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/repeated_scalar_container.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.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/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/pyext/descriptor.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/repeated_scalar_container.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
+#include "absl/strings/string_view.h"
 
 #define PyString_AsStringAndSize(ob, charpp, sizep)              \
   (PyUnicode_Check(ob)                                           \
@@ -125,8 +127,9 @@
   ExtensionIterator* self = reinterpret_cast<ExtensionIterator*>(_self);
   self->fields.clear();
   Py_XDECREF(self->extension_dict);
+  freefunc tp_free = Py_TYPE(_self)->tp_free;
   self->~ExtensionIterator();
-  Py_TYPE(_self)->tp_free(_self);
+  (*tp_free)(_self);
 }
 
 PyObject* subscript(ExtensionDict* self, PyObject* key) {
@@ -238,11 +241,11 @@
 
   PyDescriptorPool* pool = cmessage::GetFactoryForMessage(self->parent)->pool;
   const FieldDescriptor* message_extension =
-      pool->pool->FindExtensionByName(StringParam(name, name_size));
+      pool->pool->FindExtensionByName(absl::string_view(name, name_size));
   if (message_extension == nullptr) {
     // Is is the name of a message set extension?
     const Descriptor* message_descriptor =
-        pool->pool->FindMessageTypeByName(StringParam(name, name_size));
+        pool->pool->FindMessageTypeByName(absl::string_view(name, name_size));
     if (message_descriptor && message_descriptor->extension_count() > 0) {
       const FieldDescriptor* extension = message_descriptor->extension(0);
       if (extension->is_extension() &&
diff --git a/python/google/protobuf/pyext/extension_dict.h b/python/google/protobuf/pyext/extension_dict.h
index 86d2451..c5c2875 100644
--- a/python/google/protobuf/pyext/extension_dict.h
+++ b/python/google/protobuf/pyext/extension_dict.h
@@ -37,7 +37,7 @@
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/pyext/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/field.cc b/python/google/protobuf/pyext/field.cc
index 0d3b0b9..daa95d0 100644
--- a/python/google/protobuf/pyext/field.cc
+++ b/python/google/protobuf/pyext/field.cc
@@ -28,11 +28,11 @@
 // (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/pyext/field.h>
+#include "google/protobuf/pyext/field.h"
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/pyext/descriptor.h>
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/pyext/descriptor.h"
+#include "google/protobuf/pyext/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/map_container.cc b/python/google/protobuf/pyext/map_container.cc
index e8a6888..76c4d88 100644
--- a/python/google/protobuf/pyext/map_container.cc
+++ b/python/google/protobuf/pyext/map_container.cc
@@ -30,21 +30,21 @@
 
 // Author: haberman@google.com (Josh Haberman)
 
-#include <google/protobuf/pyext/map_container.h>
+#include "google/protobuf/pyext/map_container.h"
 
 #include <cstdint>
 #include <memory>
+#include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/map.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/message.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>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/map.h"
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/message.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"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/map_container.h b/python/google/protobuf/pyext/map_container.h
index af334d2..d90d3a5 100644
--- a/python/google/protobuf/pyext/map_container.h
+++ b/python/google/protobuf/pyext/map_container.h
@@ -36,9 +36,9 @@
 
 #include <cstdint>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/pyext/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/message.cc b/python/google/protobuf/pyext/message.cc
index 2c4a957..108dd52 100644
--- a/python/google/protobuf/pyext/message.cc
+++ b/python/google/protobuf/pyext/message.cc
@@ -31,17 +31,18 @@
 // Author: anuraag@google.com (Anuraag Agrawal)
 // Author: tibell@google.com (Johan Tibell)
 
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/pyext/message.h"
 
 #include <structmember.h>  // A Python header file.
 
 #include <cstdint>
 #include <map>
 #include <memory>
+#include <set>
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/strings/match.h"
 
 #ifndef PyVarObject_HEAD_INIT
 #define PyVarObject_HEAD_INIT(type, size) PyObject_HEAD_INIT(type) size,
@@ -49,33 +50,33 @@
 #ifndef Py_TYPE
 #define Py_TYPE(ob) (((PyObject*)(ob))->ob_type)
 #endif
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/pyext/descriptor.h>
-#include <google/protobuf/pyext/descriptor_pool.h>
-#include <google/protobuf/pyext/extension_dict.h>
-#include <google/protobuf/pyext/field.h>
-#include <google/protobuf/pyext/map_container.h>
-#include <google/protobuf/pyext/message_factory.h>
-#include <google/protobuf/pyext/repeated_composite_container.h>
-#include <google/protobuf/pyext/repeated_scalar_container.h>
-#include <google/protobuf/pyext/safe_numerics.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
-#include <google/protobuf/pyext/unknown_field_set.h>
-#include <google/protobuf/pyext/unknown_fields.h>
-#include <google/protobuf/util/message_differencer.h>
-#include <google/protobuf/io/strtod.h>
-#include <google/protobuf/stubs/map_util.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/pyext/descriptor.h"
+#include "google/protobuf/pyext/descriptor_pool.h"
+#include "google/protobuf/pyext/extension_dict.h"
+#include "google/protobuf/pyext/field.h"
+#include "google/protobuf/pyext/map_container.h"
+#include "google/protobuf/pyext/message_factory.h"
+#include "google/protobuf/pyext/repeated_composite_container.h"
+#include "google/protobuf/pyext/repeated_scalar_container.h"
+#include "google/protobuf/pyext/safe_numerics.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
+#include "google/protobuf/pyext/unknown_field_set.h"
+#include "google/protobuf/pyext/unknown_fields.h"
+#include "google/protobuf/util/message_differencer.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 #define PyString_AsString(ob) \
@@ -88,6 +89,9 @@
               : 0)                                               \
        : PyBytes_AsStringAndSize(ob, (charpp), (sizep)))
 
+#define PROTOBUF_PYTHON_PUBLIC "google.protobuf"
+#define PROTOBUF_PYTHON_INTERNAL "google.protobuf.internal"
+
 namespace google {
 namespace protobuf {
 namespace python {
@@ -246,8 +250,8 @@
   ScopedPyObjectPtr new_args;
 
   if (WKT_classes == nullptr) {
-    ScopedPyObjectPtr well_known_types(PyImport_ImportModule(
-        "google.protobuf.internal.well_known_types"));
+    ScopedPyObjectPtr well_known_types(
+        PyImport_ImportModule(PROTOBUF_PYTHON_INTERNAL ".well_known_types"));
     GOOGLE_DCHECK(well_known_types != nullptr);
 
     WKT_classes = PyObject_GetAttrString(well_known_types.get(), "WKTBASES");
@@ -405,7 +409,7 @@
   Py_ssize_t attr_size;
   static const char kSuffix[] = "_FIELD_NUMBER";
   if (PyString_AsStringAndSize(name, &attr, &attr_size) >= 0 &&
-      HasSuffixString(StringPiece(attr, attr_size), kSuffix)) {
+      absl::EndsWith(absl::string_view(attr, attr_size), kSuffix)) {
     std::string field_name(attr, attr_size - sizeof(kSuffix) + 1);
     LowerString(&field_name);
 
@@ -910,7 +914,7 @@
       return nullptr;
     }
     const EnumValueDescriptor* enum_value_descriptor =
-        enum_descriptor->FindValueByName(StringParam(enum_label, size));
+        enum_descriptor->FindValueByName(absl::string_view(enum_label, size));
     if (enum_value_descriptor == nullptr) {
       PyErr_Format(PyExc_ValueError, "unknown enum label \"%s\"", enum_label);
       return nullptr;
@@ -1096,7 +1100,8 @@
             reinterpret_cast<RepeatedCompositeContainer*>(container.get());
         ScopedPyObjectPtr iter(PyObject_GetIter(value));
         if (iter == nullptr) {
-          PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+          PyErr_Format(PyExc_TypeError, "Value of field '%s' must be iterable",
+                       descriptor->name().c_str());
           return -1;
         }
         ScopedPyObjectPtr next;
@@ -1125,7 +1130,8 @@
             reinterpret_cast<RepeatedScalarContainer*>(container.get());
         ScopedPyObjectPtr iter(PyObject_GetIter(value));
         if (iter == nullptr) {
-          PyErr_SetString(PyExc_TypeError, "Value must be iterable");
+          PyErr_Format(PyExc_TypeError, "Value of field '%s' must be iterable",
+                       descriptor->name().c_str());
           return -1;
         }
         ScopedPyObjectPtr next;
@@ -1337,7 +1343,7 @@
 }
 
 const FieldDescriptor* FindFieldWithOneofs(const Message* message,
-                                           ConstStringParam field_name,
+                                           absl::string_view field_name,
                                            bool* in_oneof) {
   *in_oneof = false;
   const Descriptor* descriptor = message->GetDescriptor();
@@ -1386,8 +1392,8 @@
 
   Message* message = self->message;
   bool is_in_oneof;
-  const FieldDescriptor* field_descriptor =
-      FindFieldWithOneofs(message, StringParam(field_name, size), &is_in_oneof);
+  const FieldDescriptor* field_descriptor = FindFieldWithOneofs(
+      message, absl::string_view(field_name, size), &is_in_oneof);
   if (field_descriptor == nullptr) {
     if (!is_in_oneof) {
       PyErr_Format(PyExc_ValueError, "Protocol message %s has no field %s.",
@@ -1571,7 +1577,7 @@
   AssureWritable(self);
   bool is_in_oneof;
   const FieldDescriptor* field_descriptor = FindFieldWithOneofs(
-      self->message, StringParam(field_name, field_size), &is_in_oneof);
+      self->message, absl::string_view(field_name, field_size), &is_in_oneof);
   if (field_descriptor == nullptr) {
     if (is_in_oneof) {
       // We gave the name of a oneof, and none of its fields are set.
@@ -1881,7 +1887,7 @@
   const char* ptr;
   internal::ParseContext ctx(
       depth, false, &ptr,
-      StringPiece(static_cast<const char*>(data.buf), data.len));
+      absl::string_view(static_cast<const char*>(data.buf), data.len));
   PyBuffer_Release(&data);
   ctx.data().pool = factory->pool->pool;
   ctx.data().factory = factory->message_factory;
@@ -1973,7 +1979,7 @@
   if (PyString_AsStringAndSize(arg, &name_data, &name_size) < 0) return nullptr;
   const OneofDescriptor* oneof_desc =
       self->message->GetDescriptor()->FindOneofByName(
-          StringParam(name_data, name_size));
+          absl::string_view(name_data, name_size));
   if (oneof_desc == nullptr) {
     PyErr_Format(PyExc_ValueError,
                  "Protocol message has no oneof \"%s\" field.", name_data);
@@ -2372,7 +2378,7 @@
 PyObject* ToUnicode(CMessage* self) {
   // Lazy import to prevent circular dependencies
   ScopedPyObjectPtr text_format(
-      PyImport_ImportModule("google.protobuf.text_format"));
+      PyImport_ImportModule(PROTOBUF_PYTHON_PUBLIC ".text_format"));
   if (text_format == nullptr) {
     return nullptr;
   }
@@ -2673,22 +2679,22 @@
   if (!this->child_submessages) {
     this->child_submessages = new CMessage::SubMessagesMap();
   }
-  CMessage* cmsg = FindPtrOrNull(
-      *this->child_submessages, sub_message);
-  if (cmsg) {
-    Py_INCREF(cmsg);
-  } else {
-    cmsg = cmessage::NewEmptyMessage(message_class);
-
-    if (cmsg == nullptr) {
-      return nullptr;
-    }
-    cmsg->message = sub_message;
-    Py_INCREF(this);
-    cmsg->parent = this;
-    cmsg->parent_field_descriptor = field_descriptor;
-    cmessage::SetSubmessage(this, cmsg);
+  auto it = this->child_submessages->find(sub_message);
+  if (it != this->child_submessages->end()) {
+    Py_INCREF(it->second);
+    return it->second;
   }
+
+  CMessage* cmsg = cmessage::NewEmptyMessage(message_class);
+
+  if (cmsg == nullptr) {
+    return nullptr;
+  }
+  cmsg->message = sub_message;
+  Py_INCREF(this);
+  cmsg->parent = this;
+  cmsg->parent_field_descriptor = field_descriptor;
+  cmessage::SetSubmessage(this, cmsg);
   return cmsg;
 }
 
@@ -2696,11 +2702,10 @@
   if (!this->child_submessages) {
     return nullptr;
   }
-  CMessage* released = FindPtrOrNull(
-      *this->child_submessages, sub_message);
-  if (!released) {
-    return nullptr;
-  }
+  auto it = this->child_submessages->find(sub_message);
+  if (it == this->child_submessages->end()) return nullptr;
+  CMessage* released = it->second;
+
   // The target message will now own its content.
   Py_CLEAR(released->parent);
   released->parent_field_descriptor = nullptr;
@@ -3034,8 +3039,8 @@
   PyModule_AddObject(m, "MethodDescriptor",
                      reinterpret_cast<PyObject*>(&PyMethodDescriptor_Type));
 
-  PyObject* enum_type_wrapper = PyImport_ImportModule(
-      "google.protobuf.internal.enum_type_wrapper");
+  PyObject* enum_type_wrapper =
+      PyImport_ImportModule(PROTOBUF_PYTHON_INTERNAL ".enum_type_wrapper");
   if (enum_type_wrapper == nullptr) {
     return false;
   }
@@ -3043,8 +3048,8 @@
       PyObject_GetAttrString(enum_type_wrapper, "EnumTypeWrapper");
   Py_DECREF(enum_type_wrapper);
 
-  PyObject* message_module = PyImport_ImportModule(
-      "google.protobuf.message");
+  PyObject* message_module =
+      PyImport_ImportModule(PROTOBUF_PYTHON_PUBLIC ".message");
   if (message_module == nullptr) {
     return false;
   }
diff --git a/python/google/protobuf/pyext/message.h b/python/google/protobuf/pyext/message.h
index b17daa5..1b0172f 100644
--- a/python/google/protobuf/pyext/message.h
+++ b/python/google/protobuf/pyext/message.h
@@ -42,7 +42,7 @@
 #include <string>
 #include <unordered_map>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/message_factory.cc b/python/google/protobuf/pyext/message_factory.cc
index bc44dd4..27aa5e4 100644
--- a/python/google/protobuf/pyext/message_factory.cc
+++ b/python/google/protobuf/pyext/message_factory.cc
@@ -29,15 +29,16 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 #include <unordered_map>
+#include <utility>
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/pyext/descriptor.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/message_factory.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/pyext/descriptor.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/message_factory.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
 
 #define PyString_AsStringAndSize(ob, charpp, sizep)              \
   (PyUnicode_Check(ob)                                           \
diff --git a/python/google/protobuf/pyext/message_factory.h b/python/google/protobuf/pyext/message_factory.h
index 7dfe425..1d911a8 100644
--- a/python/google/protobuf/pyext/message_factory.h
+++ b/python/google/protobuf/pyext/message_factory.h
@@ -35,8 +35,8 @@
 #include <Python.h>
 
 #include <unordered_map>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/pyext/descriptor_pool.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/pyext/descriptor_pool.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/message_module.cc b/python/google/protobuf/pyext/message_module.cc
index 2d3c1d2..f469206 100644
--- a/python/google/protobuf/pyext/message_module.cc
+++ b/python/google/protobuf/pyext/message_module.cc
@@ -31,12 +31,12 @@
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/pyext/descriptor.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"
+#include "google/protobuf/pyext/descriptor.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"
 
 namespace {
 
diff --git a/python/google/protobuf/pyext/repeated_composite_container.cc b/python/google/protobuf/pyext/repeated_composite_container.cc
index 0b63f82..a191670 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.cc
+++ b/python/google/protobuf/pyext/repeated_composite_container.cc
@@ -31,22 +31,21 @@
 // Author: anuraag@google.com (Anuraag Agrawal)
 // Author: tibell@google.com (Johan Tibell)
 
-#include <google/protobuf/pyext/repeated_composite_container.h>
+#include "google/protobuf/pyext/repeated_composite_container.h"
 
 #include <memory>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/reflection.h>
-#include <google/protobuf/pyext/descriptor.h>
-#include <google/protobuf/pyext/descriptor_pool.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/message_factory.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
-#include <google/protobuf/stubs/map_util.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/reflection.h"
+#include "google/protobuf/pyext/descriptor.h"
+#include "google/protobuf/pyext/descriptor_pool.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/message_factory.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/repeated_composite_container.h b/python/google/protobuf/pyext/repeated_composite_container.h
index 6fa6e17..8964374 100644
--- a/python/google/protobuf/pyext/repeated_composite_container.h
+++ b/python/google/protobuf/pyext/repeated_composite_container.h
@@ -37,7 +37,7 @@
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/pyext/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.cc b/python/google/protobuf/pyext/repeated_scalar_container.cc
index f4a8df2..57746dc 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.cc
+++ b/python/google/protobuf/pyext/repeated_scalar_container.cc
@@ -31,20 +31,21 @@
 // Author: anuraag@google.com (Anuraag Agrawal)
 // Author: tibell@google.com (Johan Tibell)
 
-#include <google/protobuf/pyext/repeated_scalar_container.h>
+#include "google/protobuf/pyext/repeated_scalar_container.h"
 
 #include <cstdint>
 #include <memory>
+#include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/pyext/descriptor.h>
-#include <google/protobuf/pyext/descriptor_pool.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/pyext/descriptor.h"
+#include "google/protobuf/pyext/descriptor_pool.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
 
 #define PyString_AsString(ob) \
   (PyUnicode_Check(ob) ? PyUnicode_AsUTF8(ob) : PyBytes_AsString(ob))
diff --git a/python/google/protobuf/pyext/repeated_scalar_container.h b/python/google/protobuf/pyext/repeated_scalar_container.h
index 67423ab..0189886 100644
--- a/python/google/protobuf/pyext/repeated_scalar_container.h
+++ b/python/google/protobuf/pyext/repeated_scalar_container.h
@@ -37,8 +37,8 @@
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/pyext/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/safe_numerics.h b/python/google/protobuf/pyext/safe_numerics.h
index 93ae640..0d4dd25 100644
--- a/python/google/protobuf/pyext/safe_numerics.h
+++ b/python/google/protobuf/pyext/safe_numerics.h
@@ -34,8 +34,8 @@
 
 #include <limits>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/scoped_pyobject_ptr.h b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
index ad3fa94..d39a4d1 100644
--- a/python/google/protobuf/pyext/scoped_pyobject_ptr.h
+++ b/python/google/protobuf/pyext/scoped_pyobject_ptr.h
@@ -33,8 +33,6 @@
 #ifndef GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
 #define GOOGLE_PROTOBUF_PYTHON_CPP_SCOPED_PYOBJECT_PTR_H__
 
-#include <google/protobuf/stubs/common.h>
-
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
 namespace google {
@@ -50,6 +48,8 @@
   // The reference count of the specified py_object is not incremented.
   explicit ScopedPythonPtr(PyObjectStruct* py_object = nullptr)
       : ptr_(py_object) {}
+  ScopedPythonPtr(const ScopedPythonPtr&) = delete;
+  ScopedPythonPtr& operator=(const ScopedPythonPtr&) = delete;
 
   // If a PyObject is owned, decrement its reference count.
   ~ScopedPythonPtr() { Py_XDECREF(ptr_); }
@@ -89,8 +89,6 @@
 
  private:
   PyObjectStruct* ptr_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedPythonPtr);
 };
 
 typedef ScopedPythonPtr<PyObject> ScopedPyObjectPtr;
diff --git a/python/google/protobuf/pyext/unknown_field_set.cc b/python/google/protobuf/pyext/unknown_field_set.cc
index 42f9bbc..59d1d0b 100644
--- a/python/google/protobuf/pyext/unknown_field_set.cc
+++ b/python/google/protobuf/pyext/unknown_field_set.cc
@@ -28,7 +28,7 @@
 // (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/pyext/unknown_field_set.h>
+#include "google/protobuf/pyext/unknown_field_set.h"
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
@@ -36,11 +36,11 @@
 #include <memory>
 #include <set>
 
-#include <google/protobuf/message.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
+#include "google/protobuf/message.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
+#include "google/protobuf/wire_format_lite.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/unknown_field_set.h b/python/google/protobuf/pyext/unknown_field_set.h
index 3fa764d..92a889d 100644
--- a/python/google/protobuf/pyext/unknown_field_set.h
+++ b/python/google/protobuf/pyext/unknown_field_set.h
@@ -37,7 +37,7 @@
 #include <memory>
 #include <set>
 
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/pyext/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/unknown_fields.cc b/python/google/protobuf/pyext/unknown_fields.cc
index dcd63b2..bb6549d 100644
--- a/python/google/protobuf/pyext/unknown_fields.cc
+++ b/python/google/protobuf/pyext/unknown_fields.cc
@@ -28,18 +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/pyext/unknown_fields.h>
+#include "google/protobuf/pyext/unknown_fields.h"
 
 #define PY_SSIZE_T_CLEAN
 #include <Python.h>
-#include <set>
-#include <memory>
 
-#include <google/protobuf/message.h>
-#include <google/protobuf/pyext/message.h>
-#include <google/protobuf/pyext/scoped_pyobject_ptr.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format_lite.h>
+#include <memory>
+#include <set>
+
+#include "google/protobuf/message.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/pyext/message.h"
+#include "google/protobuf/pyext/scoped_pyobject_ptr.h"
+#include "google/protobuf/wire_format_lite.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/pyext/unknown_fields.h b/python/google/protobuf/pyext/unknown_fields.h
index e7b0b35..81ee1a9 100644
--- a/python/google/protobuf/pyext/unknown_fields.h
+++ b/python/google/protobuf/pyext/unknown_fields.h
@@ -37,7 +37,7 @@
 #include <memory>
 #include <set>
 
-#include <google/protobuf/pyext/message.h>
+#include "google/protobuf/pyext/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/python/google/protobuf/symbol_database.py b/python/google/protobuf/symbol_database.py
index fdcf8cf..ed5fce3 100644
--- a/python/google/protobuf/symbol_database.py
+++ b/python/google/protobuf/symbol_database.py
@@ -66,6 +66,9 @@
 class SymbolDatabase(message_factory.MessageFactory):
   """A database of Python generated symbols."""
 
+  # local cache of registered classes.
+  _classes = {}
+
   def RegisterMessage(self, message):
     """Registers the given message type in the local database.
 
diff --git a/python/google/protobuf/text_encoding.py b/python/google/protobuf/text_encoding.py
index 759cf11..1955b6a 100644
--- a/python/google/protobuf/text_encoding.py
+++ b/python/google/protobuf/text_encoding.py
@@ -53,8 +53,7 @@
 del byte, string
 
 
-def CEscape(text, as_utf8):
-  # type: (...) -> str
+def CEscape(text, as_utf8) -> str:
   """Escape a bytes string for use in an text protocol buffer.
 
   Args:
@@ -83,8 +82,7 @@
 _CUNESCAPE_HEX = re.compile(r'(\\+)x([0-9a-fA-F])(?![0-9a-fA-F])')
 
 
-def CUnescape(text):
-  # type: (str) -> bytes
+def CUnescape(text: str) -> bytes:
   """Unescape a text string with C-style escape sequences to UTF-8 bytes.
 
   Args:
diff --git a/python/google/protobuf/text_format.py b/python/google/protobuf/text_format.py
index a6d8bcf..367523c 100644
--- a/python/google/protobuf/text_format.py
+++ b/python/google/protobuf/text_format.py
@@ -67,6 +67,7 @@
 _FLOAT_NAN = re.compile('nanf?$', re.IGNORECASE)
 _QUOTES = frozenset(("'", '"'))
 _ANY_FULL_TYPE_NAME = 'google.protobuf.Any'
+_DEBUG_STRING_SILENT_MARKER = '\t '
 
 
 class Error(Exception):
@@ -125,8 +126,7 @@
     indent=0,
     message_formatter=None,
     print_unknown_fields=False,
-    force_colon=False):
-  # type: (...) -> str
+    force_colon=False) -> str:
   """Convert protobuf message to text format.
 
   Double values can be formatted compactly with 15 digits of
@@ -191,8 +191,7 @@
   return result
 
 
-def MessageToBytes(message, **kwargs):
-  # type: (...) -> bytes
+def MessageToBytes(message, **kwargs) -> bytes:
   """Convert protobuf message to encoded text format.  See MessageToString."""
   text = MessageToString(message, **kwargs)
   if isinstance(text, bytes):
@@ -341,7 +340,7 @@
   return message_type()
 
 
-# These values must match WireType enum in google/protobuf/wire_format.h.
+# These values must match WireType enum in //google/protobuf/wire_format.h.
 WIRETYPE_LENGTH_DELIMITED = 2
 WIRETYPE_START_GROUP = 3
 
@@ -558,7 +557,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):
@@ -856,10 +855,15 @@
       ParseError: On text parsing problems.
     """
     # Tokenize expects native str lines.
-    str_lines = (
-        line if isinstance(line, str) else line.decode('utf-8')
-        for line in lines)
+    try:
+      str_lines = (
+          line if isinstance(line, str) else line.decode('utf-8')
+          for line in lines)
+    except UnicodeDecodeError as e:
+      raise self._StringParseError(e)
     tokenizer = Tokenizer(str_lines)
+    if message:
+      self.root_type = message.DESCRIPTOR.full_name
     while not tokenizer.AtEnd():
       self._MergeField(tokenizer, message)
 
@@ -879,6 +883,8 @@
       type_url_prefix, packed_type_name = self._ConsumeAnyTypeUrl(tokenizer)
       tokenizer.Consume(']')
       tokenizer.TryConsume(':')
+      self._DetectSilentMarker(tokenizer,
+                               type_url_prefix + '/' + packed_type_name)
       if tokenizer.TryConsume('<'):
         expanded_any_end_token = '>'
       else:
@@ -917,8 +923,6 @@
       # pylint: disable=protected-access
       field = message.Extensions._FindExtensionByName(name)
       # pylint: enable=protected-access
-
-
       if not field:
         if self.allow_unknown_extension:
           field = None
@@ -978,9 +982,11 @@
 
       if field.cpp_type == descriptor.FieldDescriptor.CPPTYPE_MESSAGE:
         tokenizer.TryConsume(':')
+        self._DetectSilentMarker(tokenizer, field.full_name)
         merger = self._MergeMessageField
       else:
         tokenizer.Consume(':')
+        self._DetectSilentMarker(tokenizer, field.full_name)
         merger = self._MergeScalarField
 
       if (field.label == descriptor.FieldDescriptor.LABEL_REPEATED and
@@ -998,13 +1004,19 @@
 
     else:  # Proto field is unknown.
       assert (self.allow_unknown_extension or self.allow_unknown_field)
-      _SkipFieldContents(tokenizer)
+      self._SkipFieldContents(tokenizer, name)
 
     # For historical reasons, fields may optionally be separated by commas or
     # semicolons.
     if not tokenizer.TryConsume(','):
       tokenizer.TryConsume(';')
 
+  def _LogSilentMarker(self, field_name):
+    pass
+
+  def _DetectSilentMarker(self, tokenizer, field_name):
+    if tokenizer.contains_silent_marker_before_current_token:
+      self._LogSilentMarker(field_name)
 
   def _ConsumeAnyTypeUrl(self, tokenizer):
     """Consumes a google.protobuf.Any type URL and returns the type name."""
@@ -1079,12 +1091,6 @@
       else:
         getattr(message, field.name)[sub_message.key] = sub_message.value
 
-  @staticmethod
-  def _IsProto3Syntax(message):
-    message_descriptor = message.DESCRIPTOR
-    return (hasattr(message_descriptor, 'syntax') and
-            message_descriptor.syntax == 'proto3')
-
   def _MergeScalarField(self, tokenizer, message, field):
     """Merges a single scalar field into a message.
 
@@ -1136,7 +1142,7 @@
     else:
       if field.is_extension:
         if (not self._allow_multiple_scalars and
-            not self._IsProto3Syntax(message) and
+            field.has_presence and
             message.HasExtension(field)):
           raise tokenizer.ParseErrorPreviousToken(
               'Message type "%s" should not have multiple "%s" extensions.' %
@@ -1146,12 +1152,12 @@
       else:
         duplicate_error = False
         if not self._allow_multiple_scalars:
-          if self._IsProto3Syntax(message):
-            # Proto3 doesn't represent presence so we try best effort to check
-            # multiple scalars by compare to default values.
-            duplicate_error = bool(getattr(message, field.name))
-          else:
+          if field.has_presence:
             duplicate_error = message.HasField(field.name)
+          else:
+            # For field that doesn't represent presence, try best effort to
+            # check multiple scalars by compare to default values.
+            duplicate_error = bool(getattr(message, field.name))
 
         if duplicate_error:
           raise tokenizer.ParseErrorPreviousToken(
@@ -1160,105 +1166,111 @@
         else:
           setattr(message, field.name, value)
 
+  def _SkipFieldContents(self, tokenizer, field_name):
+    """Skips over contents (value or message) of a field.
 
-def _SkipFieldContents(tokenizer):
-  """Skips over contents (value or message) of a field.
-
-  Args:
-    tokenizer: A tokenizer to parse the field name and values.
-  """
-  # Try to guess the type of this field.
-  # If this field is not a message, there should be a ":" between the
-  # field name and the field value and also the field value should not
-  # start with "{" or "<" which indicates the beginning of a message body.
-  # If there is no ":" or there is a "{" or "<" after ":", this field has
-  # to be a message or the input is ill-formed.
-  if tokenizer.TryConsume(
-      ':') and not tokenizer.LookingAt('{') and not tokenizer.LookingAt('<'):
-    if tokenizer.LookingAt('['):
-      _SkipRepeatedFieldValue(tokenizer)
+    Args:
+      tokenizer: A tokenizer to parse the field name and values.
+      field_name: The field name currently being parsed.
+    """
+    # Try to guess the type of this field.
+    # If this field is not a message, there should be a ":" between the
+    # field name and the field value and also the field value should not
+    # start with "{" or "<" which indicates the beginning of a message body.
+    # If there is no ":" or there is a "{" or "<" after ":", this field has
+    # to be a message or the input is ill-formed.
+    if tokenizer.TryConsume(
+        ':') and not tokenizer.LookingAt('{') and not tokenizer.LookingAt('<'):
+      self._DetectSilentMarker(tokenizer, field_name)
+      if tokenizer.LookingAt('['):
+        self._SkipRepeatedFieldValue(tokenizer)
+      else:
+        self._SkipFieldValue(tokenizer)
     else:
-      _SkipFieldValue(tokenizer)
-  else:
-    _SkipFieldMessage(tokenizer)
+      self._DetectSilentMarker(tokenizer, field_name)
+      self._SkipFieldMessage(tokenizer)
 
+  def _SkipField(self, tokenizer):
+    """Skips over a complete field (name and value/message).
 
-def _SkipField(tokenizer):
-  """Skips over a complete field (name and value/message).
+    Args:
+      tokenizer: A tokenizer to parse the field name and values.
+    """
+    field_name = ''
+    if tokenizer.TryConsume('['):
+      # Consume extension or google.protobuf.Any type URL
+      field_name += '[' + tokenizer.ConsumeIdentifier()
+      num_identifiers = 1
+      while tokenizer.TryConsume('.'):
+        field_name += '.' + tokenizer.ConsumeIdentifier()
+        num_identifiers += 1
+      # This is possibly a type URL for an Any message.
+      if num_identifiers == 3 and tokenizer.TryConsume('/'):
+        field_name += '/' + tokenizer.ConsumeIdentifier()
+        while tokenizer.TryConsume('.'):
+          field_name += '.' + tokenizer.ConsumeIdentifier()
+      tokenizer.Consume(']')
+      field_name += ']'
+    else:
+      field_name += tokenizer.ConsumeIdentifierOrNumber()
 
-  Args:
-    tokenizer: A tokenizer to parse the field name and values.
-  """
-  if tokenizer.TryConsume('['):
-    # Consume extension name.
-    tokenizer.ConsumeIdentifier()
-    while tokenizer.TryConsume('.'):
-      tokenizer.ConsumeIdentifier()
+    self._SkipFieldContents(tokenizer, field_name)
+
+    # For historical reasons, fields may optionally be separated by commas or
+    # semicolons.
+    if not tokenizer.TryConsume(','):
+      tokenizer.TryConsume(';')
+
+  def _SkipFieldMessage(self, tokenizer):
+    """Skips over a field message.
+
+    Args:
+      tokenizer: A tokenizer to parse the field name and values.
+    """
+    if tokenizer.TryConsume('<'):
+      delimiter = '>'
+    else:
+      tokenizer.Consume('{')
+      delimiter = '}'
+
+    while not tokenizer.LookingAt('>') and not tokenizer.LookingAt('}'):
+      self._SkipField(tokenizer)
+
+    tokenizer.Consume(delimiter)
+
+  def _SkipFieldValue(self, tokenizer):
+    """Skips over a field value.
+
+    Args:
+      tokenizer: A tokenizer to parse the field name and values.
+
+    Raises:
+      ParseError: In case an invalid field value is found.
+    """
+    # String/bytes tokens can come in multiple adjacent string literals.
+    # If we can consume one, consume as many as we can.
+    if tokenizer.TryConsumeByteString():
+      while tokenizer.TryConsumeByteString():
+        pass
+      return
+
+    if (not tokenizer.TryConsumeIdentifier() and
+        not _TryConsumeInt64(tokenizer) and not _TryConsumeUint64(tokenizer) and
+        not tokenizer.TryConsumeFloat()):
+      raise ParseError('Invalid field value: ' + tokenizer.token)
+
+  def _SkipRepeatedFieldValue(self, tokenizer):
+    """Skips over a repeated field value.
+
+    Args:
+      tokenizer: A tokenizer to parse the field value.
+    """
+    tokenizer.Consume('[')
+    if not tokenizer.LookingAt(']'):
+      self._SkipFieldValue(tokenizer)
+      while tokenizer.TryConsume(','):
+        self._SkipFieldValue(tokenizer)
     tokenizer.Consume(']')
-  else:
-    tokenizer.ConsumeIdentifierOrNumber()
-
-  _SkipFieldContents(tokenizer)
-
-  # For historical reasons, fields may optionally be separated by commas or
-  # semicolons.
-  if not tokenizer.TryConsume(','):
-    tokenizer.TryConsume(';')
-
-
-def _SkipFieldMessage(tokenizer):
-  """Skips over a field message.
-
-  Args:
-    tokenizer: A tokenizer to parse the field name and values.
-  """
-
-  if tokenizer.TryConsume('<'):
-    delimiter = '>'
-  else:
-    tokenizer.Consume('{')
-    delimiter = '}'
-
-  while not tokenizer.LookingAt('>') and not tokenizer.LookingAt('}'):
-    _SkipField(tokenizer)
-
-  tokenizer.Consume(delimiter)
-
-
-def _SkipFieldValue(tokenizer):
-  """Skips over a field value.
-
-  Args:
-    tokenizer: A tokenizer to parse the field name and values.
-
-  Raises:
-    ParseError: In case an invalid field value is found.
-  """
-  # String/bytes tokens can come in multiple adjacent string literals.
-  # If we can consume one, consume as many as we can.
-  if tokenizer.TryConsumeByteString():
-    while tokenizer.TryConsumeByteString():
-      pass
-    return
-
-  if (not tokenizer.TryConsumeIdentifier() and
-      not _TryConsumeInt64(tokenizer) and not _TryConsumeUint64(tokenizer) and
-      not tokenizer.TryConsumeFloat()):
-    raise ParseError('Invalid field value: ' + tokenizer.token)
-
-
-def _SkipRepeatedFieldValue(tokenizer):
-  """Skips over a repeated field value.
-
-  Args:
-    tokenizer: A tokenizer to parse the field value.
-  """
-  tokenizer.Consume('[')
-  if not tokenizer.LookingAt(']'):
-    _SkipFieldValue(tokenizer)
-    while tokenizer.TryConsume(','):
-      _SkipFieldValue(tokenizer)
-  tokenizer.Consume(']')
 
 
 class Tokenizer(object):
@@ -1299,6 +1311,8 @@
     self._skip_comments = skip_comments
     self._whitespace_pattern = (skip_comments and self._WHITESPACE_OR_COMMENT
                                 or self._WHITESPACE)
+    self.contains_silent_marker_before_current_token = False
+
     self._SkipWhitespace()
     self.NextToken()
 
@@ -1331,6 +1345,8 @@
       match = self._whitespace_pattern.match(self._current_line, self._column)
       if not match:
         break
+      self.contains_silent_marker_before_current_token = match.group(0) == (
+          ' ' + _DEBUG_STRING_SILENT_MARKER)
       length = len(match.group(0))
       self._column += length
 
@@ -1583,6 +1599,7 @@
     """Reads the next meaningful token."""
     self._previous_line = self._line
     self._previous_column = self._column
+    self.contains_silent_marker_before_current_token = False
 
     self._column += len(self.token)
     self._SkipWhitespace()
@@ -1829,12 +1846,8 @@
       raise ValueError('Enum type "%s" has no value named %s.' %
                        (enum_descriptor.full_name, value))
   else:
-    # Numeric value.
-    if hasattr(field.file, 'syntax'):
-      # Attribute is checked for compatibility.
-      if field.file.syntax == 'proto3':
-        # Proto3 accept numeric unknown enums.
-        return number
+    if not field.enum_type.is_closed:
+      return number
     enum_value = enum_descriptor.values_by_number.get(number, None)
     if enum_value is None:
       raise ValueError('Enum type "%s" has no value with number %d.' %
diff --git a/python/internal.bzl b/python/internal.bzl
new file mode 100644
index 0000000..d9ba37e
--- /dev/null
+++ b/python/internal.bzl
@@ -0,0 +1,125 @@
+# Internal helpers for building the Python protobuf runtime.
+
+def _internal_copy_files_impl(ctx):
+    strip_prefix = ctx.attr.strip_prefix
+    if strip_prefix[-1] != "/":
+        strip_prefix += "/"
+
+    src_dests = []
+    for src in ctx.files.srcs:
+        if src.short_path[:len(strip_prefix)] != strip_prefix:
+            fail("Source does not start with %s: %s" %
+                 (strip_prefix, src.short_path))
+        dest = ctx.actions.declare_file(src.short_path[len(strip_prefix):])
+        src_dests.append([src, dest])
+
+    if ctx.attr.is_windows:
+        bat_file = ctx.actions.declare_file(ctx.label.name + "_copy.bat")
+        ctx.actions.write(
+            output = bat_file,
+            content = "\r\n".join([
+                '@copy /Y "{}" "{}" >NUL'.format(
+                    src.path.replace("/", "\\"),
+                    dest.path.replace("/", "\\"),
+                )
+                for src, dest in src_dests
+            ]) + "\r\n",
+        )
+        ctx.actions.run(
+            inputs = ctx.files.srcs,
+            tools = [bat_file],
+            outputs = [dest for src, dest in src_dests],
+            executable = "cmd.exe",
+            arguments = ["/C", bat_file.path.replace("/", "\\")],
+            mnemonic = "InternalCopyFile",
+            progress_message = "Copying files",
+            use_default_shell_env = True,
+        )
+
+    else:
+        sh_file = ctx.actions.declare_file(ctx.label.name + "_copy.sh")
+        ctx.actions.write(
+            output = sh_file,
+            content = "\n".join([
+                'cp -f "{}" "{}"'.format(src.path, dest.path)
+                for src, dest in src_dests
+            ]),
+        )
+        ctx.actions.run(
+            inputs = ctx.files.srcs,
+            tools = [sh_file],
+            outputs = [dest for src, dest in src_dests],
+            executable = "bash",
+            arguments = [sh_file.path],
+            mnemonic = "InternalCopyFile",
+            progress_message = "Copying files",
+            use_default_shell_env = True,
+        )
+
+    return [
+        DefaultInfo(files = depset([dest for src, dest in src_dests])),
+    ]
+
+internal_copy_files_impl = rule(
+    doc = """
+Implementation for internal_copy_files macro.
+
+This rule implements file copying, including a compatibility mode for Windows.
+""",
+    implementation = _internal_copy_files_impl,
+    attrs = {
+        "srcs": attr.label_list(allow_files = True, providers = [DefaultInfo]),
+        "strip_prefix": attr.string(),
+        "is_windows": attr.bool(),
+    },
+)
+
+def internal_copy_files(name, srcs, strip_prefix, **kwargs):
+    """Copies common proto files to the python tree.
+
+    In order for Python imports to work, generated proto interfaces under
+    the google.protobuf package need to be in the same directory as other
+    source files. This rule copies the .proto files themselves, e.g. with
+    strip_prefix = 'src', 'src/google/protobuf/blah.proto' could be copied
+    to '<package>/google/protobuf/blah.proto'.
+
+    (An alternative might be to implement a separate rule to generate
+    Python code in a different location for the sources. However, this
+    would be strange behavior that doesn't match any other language's proto
+    library generation.)
+
+    Args:
+      name: the name for the rule.
+      srcs: the sources.
+      strip_prefix: the prefix to remove from each of the paths in 'srcs'. The
+          remainder will be used to construct the output path.
+      **kwargs: common rule arguments.
+
+    """
+    internal_copy_files_impl(
+        name = name,
+        srcs = srcs,
+        strip_prefix = strip_prefix,
+        is_windows = select({
+            "@bazel_tools//src/conditions:host_windows": True,
+            "//conditions:default": False,
+        }),
+        **kwargs
+    )
+
+def internal_py_test(deps = [], **kwargs):
+    """Internal wrapper for shared test configuration
+
+    Args:
+      deps: any additional dependencies of the test.
+      **kwargs: arguments forwarded to py_test.
+    """
+    native.py_test(
+        imports = ["."],
+        deps = deps + [":python_test_lib"],
+        target_compatible_with = select({
+            "@system_python//:supported": [],
+            "//conditions:default": ["@platforms//:incompatible"],
+        }),
+        **kwargs
+    )
diff --git a/python/mox.py b/python/mox.py
deleted file mode 100755
index 9dd8ac7..0000000
--- a/python/mox.py
+++ /dev/null
@@ -1,1401 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Copyright 2008 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file is used for testing.  The original is at:
-#   http://code.google.com/p/pymox/
-
-"""Mox, an object-mocking framework for Python.
-
-Mox works in the record-replay-verify paradigm.  When you first create
-a mock object, it is in record mode.  You then programmatically set
-the expected behavior of the mock object (what methods are to be
-called on it, with what parameters, what they should return, and in
-what order).
-
-Once you have set up the expected mock behavior, you put it in replay
-mode.  Now the mock responds to method calls just as you told it to.
-If an unexpected method (or an expected method with unexpected
-parameters) is called, then an exception will be raised.
-
-Once you are done interacting with the mock, you need to verify that
-all the expected interactions occurred.  (Maybe your code exited
-prematurely without calling some cleanup method!)  The verify phase
-ensures that every expected method was called; otherwise, an exception
-will be raised.
-
-Suggested usage / workflow:
-
-  # Create Mox factory
-  my_mox = Mox()
-
-  # Create a mock data access object
-  mock_dao = my_mox.CreateMock(DAOClass)
-
-  # Set up expected behavior
-  mock_dao.RetrievePersonWithIdentifier('1').AndReturn(person)
-  mock_dao.DeletePerson(person)
-
-  # Put mocks in replay mode
-  my_mox.ReplayAll()
-
-  # Inject mock object and run test
-  controller.SetDao(mock_dao)
-  controller.DeletePersonById('1')
-
-  # Verify all methods were called as expected
-  my_mox.VerifyAll()
-"""
-
-from collections import deque
-import re
-import types
-import unittest
-
-import stubout
-
-class Error(AssertionError):
-  """Base exception for this module."""
-
-  pass
-
-
-class ExpectedMethodCallsError(Error):
-  """Raised when Verify() is called before all expected methods have been called
-  """
-
-  def __init__(self, expected_methods):
-    """Init exception.
-
-    Args:
-      # expected_methods: A sequence of MockMethod objects that should have been
-      #   called.
-      expected_methods: [MockMethod]
-
-    Raises:
-      ValueError: if expected_methods contains no methods.
-    """
-
-    if not expected_methods:
-      raise ValueError("There must be at least one expected method")
-    Error.__init__(self)
-    self._expected_methods = expected_methods
-
-  def __str__(self):
-    calls = "\n".join(["%3d.  %s" % (i, m)
-                       for i, m in enumerate(self._expected_methods)])
-    return "Verify: Expected methods never called:\n%s" % (calls,)
-
-
-class UnexpectedMethodCallError(Error):
-  """Raised when an unexpected method is called.
-
-  This can occur if a method is called with incorrect parameters, or out of the
-  specified order.
-  """
-
-  def __init__(self, unexpected_method, expected):
-    """Init exception.
-
-    Args:
-      # unexpected_method: MockMethod that was called but was not at the head of
-      #   the expected_method queue.
-      # expected: MockMethod or UnorderedGroup the method should have
-      #   been in.
-      unexpected_method: MockMethod
-      expected: MockMethod or UnorderedGroup
-    """
-
-    Error.__init__(self)
-    self._unexpected_method = unexpected_method
-    self._expected = expected
-
-  def __str__(self):
-    return "Unexpected method call: %s.  Expecting: %s" % \
-      (self._unexpected_method, self._expected)
-
-
-class UnknownMethodCallError(Error):
-  """Raised if an unknown method is requested of the mock object."""
-
-  def __init__(self, unknown_method_name):
-    """Init exception.
-
-    Args:
-      # unknown_method_name: Method call that is not part of the mocked class's
-      #   public interface.
-      unknown_method_name: str
-    """
-
-    Error.__init__(self)
-    self._unknown_method_name = unknown_method_name
-
-  def __str__(self):
-    return "Method called is not a member of the object: %s" % \
-      self._unknown_method_name
-
-
-class Mox(object):
-  """Mox: a factory for creating mock objects."""
-
-  # A list of types that should be stubbed out with MockObjects (as
-  # opposed to MockAnythings).
-  _USE_MOCK_OBJECT = [types.ClassType, types.InstanceType, types.ModuleType,
-                      types.ObjectType, types.TypeType]
-
-  def __init__(self):
-    """Initialize a new Mox."""
-
-    self._mock_objects = []
-    self.stubs = stubout.StubOutForTesting()
-
-  def CreateMock(self, class_to_mock):
-    """Create a new mock object.
-
-    Args:
-      # class_to_mock: the class to be mocked
-      class_to_mock: class
-
-    Returns:
-      MockObject that can be used as the class_to_mock would be.
-    """
-
-    new_mock = MockObject(class_to_mock)
-    self._mock_objects.append(new_mock)
-    return new_mock
-
-  def CreateMockAnything(self):
-    """Create a mock that will accept any method calls.
-
-    This does not enforce an interface.
-    """
-
-    new_mock = MockAnything()
-    self._mock_objects.append(new_mock)
-    return new_mock
-
-  def ReplayAll(self):
-    """Set all mock objects to replay mode."""
-
-    for mock_obj in self._mock_objects:
-      mock_obj._Replay()
-
-
-  def VerifyAll(self):
-    """Call verify on all mock objects created."""
-
-    for mock_obj in self._mock_objects:
-      mock_obj._Verify()
-
-  def ResetAll(self):
-    """Call reset on all mock objects.  This does not unset stubs."""
-
-    for mock_obj in self._mock_objects:
-      mock_obj._Reset()
-
-  def StubOutWithMock(self, obj, attr_name, use_mock_anything=False):
-    """Replace a method, attribute, etc. with a Mock.
-
-    This will replace a class or module with a MockObject, and everything else
-    (method, function, etc) with a MockAnything.  This can be overridden to
-    always use a MockAnything by setting use_mock_anything to True.
-
-    Args:
-      obj: A Python object (class, module, instance, callable).
-      attr_name: str.  The name of the attribute to replace with a mock.
-      use_mock_anything: bool. True if a MockAnything should be used regardless
-        of the type of attribute.
-    """
-
-    attr_to_replace = getattr(obj, attr_name)
-    if type(attr_to_replace) in self._USE_MOCK_OBJECT and not use_mock_anything:
-      stub = self.CreateMock(attr_to_replace)
-    else:
-      stub = self.CreateMockAnything()
-
-    self.stubs.Set(obj, attr_name, stub)
-
-  def UnsetStubs(self):
-    """Restore stubs to their original state."""
-
-    self.stubs.UnsetAll()
-
-def Replay(*args):
-  """Put mocks into Replay mode.
-
-  Args:
-    # args is any number of mocks to put into replay mode.
-  """
-
-  for mock in args:
-    mock._Replay()
-
-
-def Verify(*args):
-  """Verify mocks.
-
-  Args:
-    # args is any number of mocks to be verified.
-  """
-
-  for mock in args:
-    mock._Verify()
-
-
-def Reset(*args):
-  """Reset mocks.
-
-  Args:
-    # args is any number of mocks to be reset.
-  """
-
-  for mock in args:
-    mock._Reset()
-
-
-class MockAnything:
-  """A mock that can be used to mock anything.
-
-  This is helpful for mocking classes that do not provide a public interface.
-  """
-
-  def __init__(self):
-    """ """
-    self._Reset()
-
-  def __getattr__(self, method_name):
-    """Intercept method calls on this object.
-
-     A new MockMethod is returned that is aware of the MockAnything's
-     state (record or replay).  The call will be recorded or replayed
-     by the MockMethod's __call__.
-
-    Args:
-      # method name: the name of the method being called.
-      method_name: str
-
-    Returns:
-      A new MockMethod aware of MockAnything's state (record or replay).
-    """
-
-    return self._CreateMockMethod(method_name)
-
-  def _CreateMockMethod(self, method_name):
-    """Create a new mock method call and return it.
-
-    Args:
-      # method name: the name of the method being called.
-      method_name: str
-
-    Returns:
-      A new MockMethod aware of MockAnything's state (record or replay).
-    """
-
-    return MockMethod(method_name, self._expected_calls_queue,
-                      self._replay_mode)
-
-  def __nonzero__(self):
-    """Return 1 for nonzero so the mock can be used as a conditional."""
-
-    return 1
-
-  def __eq__(self, rhs):
-    """Provide custom logic to compare objects."""
-
-    return (isinstance(rhs, MockAnything) and
-            self._replay_mode == rhs._replay_mode and
-            self._expected_calls_queue == rhs._expected_calls_queue)
-
-  def __ne__(self, rhs):
-    """Provide custom logic to compare objects."""
-
-    return not self == rhs
-
-  def _Replay(self):
-    """Start replaying expected method calls."""
-
-    self._replay_mode = True
-
-  def _Verify(self):
-    """Verify that all of the expected calls have been made.
-
-    Raises:
-      ExpectedMethodCallsError: if there are still more method calls in the
-        expected queue.
-    """
-
-    # If the list of expected calls is not empty, raise an exception
-    if self._expected_calls_queue:
-      # The last MultipleTimesGroup is not popped from the queue.
-      if (len(self._expected_calls_queue) == 1 and
-          isinstance(self._expected_calls_queue[0], MultipleTimesGroup) and
-          self._expected_calls_queue[0].IsSatisfied()):
-        pass
-      else:
-        raise ExpectedMethodCallsError(self._expected_calls_queue)
-
-  def _Reset(self):
-    """Reset the state of this mock to record mode with an empty queue."""
-
-    # Maintain a list of method calls we are expecting
-    self._expected_calls_queue = deque()
-
-    # Make sure we are in setup mode, not replay mode
-    self._replay_mode = False
-
-
-class MockObject(MockAnything, object):
-  """A mock object that simulates the public/protected interface of a class."""
-
-  def __init__(self, class_to_mock):
-    """Initialize a mock object.
-
-    This determines the methods and properties of the class and stores them.
-
-    Args:
-      # class_to_mock: class to be mocked
-      class_to_mock: class
-    """
-
-    # This is used to hack around the mixin/inheritance of MockAnything, which
-    # is not a proper object (it can be anything. :-)
-    MockAnything.__dict__['__init__'](self)
-
-    # Get a list of all the public and special methods we should mock.
-    self._known_methods = set()
-    self._known_vars = set()
-    self._class_to_mock = class_to_mock
-    for method in dir(class_to_mock):
-      if callable(getattr(class_to_mock, method)):
-        self._known_methods.add(method)
-      else:
-        self._known_vars.add(method)
-
-  def __getattr__(self, name):
-    """Intercept attribute request on this object.
-
-    If the attribute is a public class variable, it will be returned and not
-    recorded as a call.
-
-    If the attribute is not a variable, it is handled like a method
-    call. The method name is checked against the set of mockable
-    methods, and a new MockMethod is returned that is aware of the
-    MockObject's state (record or replay).  The call will be recorded
-    or replayed by the MockMethod's __call__.
-
-    Args:
-      # name: the name of the attribute being requested.
-      name: str
-
-    Returns:
-      Either a class variable or a new MockMethod that is aware of the state
-      of the mock (record or replay).
-
-    Raises:
-      UnknownMethodCallError if the MockObject does not mock the requested
-          method.
-    """
-
-    if name in self._known_vars:
-      return getattr(self._class_to_mock, name)
-
-    if name in self._known_methods:
-      return self._CreateMockMethod(name)
-
-    raise UnknownMethodCallError(name)
-
-  def __eq__(self, rhs):
-    """Provide custom logic to compare objects."""
-
-    return (isinstance(rhs, MockObject) and
-            self._class_to_mock == rhs._class_to_mock and
-            self._replay_mode == rhs._replay_mode and
-            self._expected_calls_queue == rhs._expected_calls_queue)
-
-  def __setitem__(self, key, value):
-    """Provide custom logic for mocking classes that support item assignment.
-
-    Args:
-      key: Key to set the value for.
-      value: Value to set.
-
-    Returns:
-      Expected return value in replay mode.  A MockMethod object for the
-      __setitem__ method that has already been called if not in replay mode.
-
-    Raises:
-      TypeError if the underlying class does not support item assignment.
-      UnexpectedMethodCallError if the object does not expect the call to
-        __setitem__.
-
-    """
-    setitem = self._class_to_mock.__dict__.get('__setitem__', None)
-
-    # Verify the class supports item assignment.
-    if setitem is None:
-      raise TypeError('object does not support item assignment')
-
-    # If we are in replay mode then simply call the mock __setitem__ method.
-    if self._replay_mode:
-      return MockMethod('__setitem__', self._expected_calls_queue,
-                        self._replay_mode)(key, value)
-
-
-    # Otherwise, create a mock method __setitem__.
-    return self._CreateMockMethod('__setitem__')(key, value)
-
-  def __getitem__(self, key):
-    """Provide custom logic for mocking classes that are subscriptable.
-
-    Args:
-      key: Key to return the value for.
-
-    Returns:
-      Expected return value in replay mode.  A MockMethod object for the
-      __getitem__ method that has already been called if not in replay mode.
-
-    Raises:
-      TypeError if the underlying class is not subscriptable.
-      UnexpectedMethodCallError if the object does not expect the call to
-        __setitem__.
-
-    """
-    getitem = self._class_to_mock.__dict__.get('__getitem__', None)
-
-    # Verify the class supports item assignment.
-    if getitem is None:
-      raise TypeError('unsubscriptable object')
-
-    # If we are in replay mode then simply call the mock __getitem__ method.
-    if self._replay_mode:
-      return MockMethod('__getitem__', self._expected_calls_queue,
-                        self._replay_mode)(key)
-
-
-    # Otherwise, create a mock method __getitem__.
-    return self._CreateMockMethod('__getitem__')(key)
-
-  def __call__(self, *params, **named_params):
-    """Provide custom logic for mocking classes that are callable."""
-
-    # Verify the class we are mocking is callable
-    callable = self._class_to_mock.__dict__.get('__call__', None)
-    if callable is None:
-      raise TypeError('Not callable')
-
-    # Because the call is happening directly on this object instead of a method,
-    # the call on the mock method is made right here
-    mock_method = self._CreateMockMethod('__call__')
-    return mock_method(*params, **named_params)
-
-  @property
-  def __class__(self):
-    """Return the class that is being mocked."""
-
-    return self._class_to_mock
-
-
-class MockMethod(object):
-  """Callable mock method.
-
-  A MockMethod should act exactly like the method it mocks, accepting parameters
-  and returning a value, or throwing an exception (as specified).  When this
-  method is called, it can optionally verify whether the called method (name and
-  signature) matches the expected method.
-  """
-
-  def __init__(self, method_name, call_queue, replay_mode):
-    """Construct a new mock method.
-
-    Args:
-      # method_name: the name of the method
-      # call_queue: deque of calls, verify this call against the head, or add
-      #     this call to the queue.
-      # replay_mode: False if we are recording, True if we are verifying calls
-      #     against the call queue.
-      method_name: str
-      call_queue: list or deque
-      replay_mode: bool
-    """
-
-    self._name = method_name
-    self._call_queue = call_queue
-    if not isinstance(call_queue, deque):
-      self._call_queue = deque(self._call_queue)
-    self._replay_mode = replay_mode
-
-    self._params = None
-    self._named_params = None
-    self._return_value = None
-    self._exception = None
-    self._side_effects = None
-
-  def __call__(self, *params, **named_params):
-    """Log parameters and return the specified return value.
-
-    If the Mock(Anything/Object) associated with this call is in record mode,
-    this MockMethod will be pushed onto the expected call queue.  If the mock
-    is in replay mode, this will pop a MockMethod off the top of the queue and
-    verify this call is equal to the expected call.
-
-    Raises:
-      UnexpectedMethodCall if this call is supposed to match an expected method
-        call and it does not.
-    """
-
-    self._params = params
-    self._named_params = named_params
-
-    if not self._replay_mode:
-      self._call_queue.append(self)
-      return self
-
-    expected_method = self._VerifyMethodCall()
-
-    if expected_method._side_effects:
-      expected_method._side_effects(*params, **named_params)
-
-    if expected_method._exception:
-      raise expected_method._exception
-
-    return expected_method._return_value
-
-  def __getattr__(self, name):
-    """Raise an AttributeError with a helpful message."""
-
-    raise AttributeError('MockMethod has no attribute "%s". '
-        'Did you remember to put your mocks in replay mode?' % name)
-
-  def _PopNextMethod(self):
-    """Pop the next method from our call queue."""
-    try:
-      return self._call_queue.popleft()
-    except IndexError:
-      raise UnexpectedMethodCallError(self, None)
-
-  def _VerifyMethodCall(self):
-    """Verify the called method is expected.
-
-    This can be an ordered method, or part of an unordered set.
-
-    Returns:
-      The expected mock method.
-
-    Raises:
-      UnexpectedMethodCall if the method called was not expected.
-    """
-
-    expected = self._PopNextMethod()
-
-    # Loop here, because we might have a MethodGroup followed by another
-    # group.
-    while isinstance(expected, MethodGroup):
-      expected, method = expected.MethodCalled(self)
-      if method is not None:
-        return method
-
-    # This is a mock method, so just check equality.
-    if expected != self:
-      raise UnexpectedMethodCallError(self, expected)
-
-    return expected
-
-  def __str__(self):
-    params = ', '.join(
-        [repr(p) for p in self._params or []] +
-        ['%s=%r' % x for x in sorted((self._named_params or {}).items())])
-    desc = "%s(%s) -> %r" % (self._name, params, self._return_value)
-    return desc
-
-  def __eq__(self, rhs):
-    """Test whether this MockMethod is equivalent to another MockMethod.
-
-    Args:
-      # rhs: the right hand side of the test
-      rhs: MockMethod
-    """
-
-    return (isinstance(rhs, MockMethod) and
-            self._name == rhs._name and
-            self._params == rhs._params and
-            self._named_params == rhs._named_params)
-
-  def __ne__(self, rhs):
-    """Test whether this MockMethod is not equivalent to another MockMethod.
-
-    Args:
-      # rhs: the right hand side of the test
-      rhs: MockMethod
-    """
-
-    return not self == rhs
-
-  def GetPossibleGroup(self):
-    """Returns a possible group from the end of the call queue or None if no
-    other methods are on the stack.
-    """
-
-    # Remove this method from the tail of the queue so we can add it to a group.
-    this_method = self._call_queue.pop()
-    assert this_method == self
-
-    # Determine if the tail of the queue is a group, or just a regular ordered
-    # mock method.
-    group = None
-    try:
-      group = self._call_queue[-1]
-    except IndexError:
-      pass
-
-    return group
-
-  def _CheckAndCreateNewGroup(self, group_name, group_class):
-    """Checks if the last method (a possible group) is an instance of our
-    group_class. Adds the current method to this group or creates a new one.
-
-    Args:
-
-      group_name: the name of the group.
-      group_class: the class used to create instance of this new group
-    """
-    group = self.GetPossibleGroup()
-
-    # If this is a group, and it is the correct group, add the method.
-    if isinstance(group, group_class) and group.group_name() == group_name:
-      group.AddMethod(self)
-      return self
-
-    # Create a new group and add the method.
-    new_group = group_class(group_name)
-    new_group.AddMethod(self)
-    self._call_queue.append(new_group)
-    return self
-
-  def InAnyOrder(self, group_name="default"):
-    """Move this method into a group of unordered calls.
-
-    A group of unordered calls must be defined together, and must be executed
-    in full before the next expected method can be called.  There can be
-    multiple groups that are expected serially, if they are given
-    different group names.  The same group name can be reused if there is a
-    standard method call, or a group with a different name, spliced between
-    usages.
-
-    Args:
-      group_name: the name of the unordered group.
-
-    Returns:
-      self
-    """
-    return self._CheckAndCreateNewGroup(group_name, UnorderedGroup)
-
-  def MultipleTimes(self, group_name="default"):
-    """Move this method into group of calls which may be called multiple times.
-
-    A group of repeating calls must be defined together, and must be executed in
-    full before the next expected method can be called.
-
-    Args:
-      group_name: the name of the unordered group.
-
-    Returns:
-      self
-    """
-    return self._CheckAndCreateNewGroup(group_name, MultipleTimesGroup)
-
-  def AndReturn(self, return_value):
-    """Set the value to return when this method is called.
-
-    Args:
-      # return_value can be anything.
-    """
-
-    self._return_value = return_value
-    return return_value
-
-  def AndRaise(self, exception):
-    """Set the exception to raise when this method is called.
-
-    Args:
-      # exception: the exception to raise when this method is called.
-      exception: Exception
-    """
-
-    self._exception = exception
-
-  def WithSideEffects(self, side_effects):
-    """Set the side effects that are simulated when this method is called.
-
-    Args:
-      side_effects: A callable which modifies the parameters or other relevant
-        state which a given test case depends on.
-
-    Returns:
-      Self for chaining with AndReturn and AndRaise.
-    """
-    self._side_effects = side_effects
-    return self
-
-class Comparator:
-  """Base class for all Mox comparators.
-
-  A Comparator can be used as a parameter to a mocked method when the exact
-  value is not known.  For example, the code you are testing might build up a
-  long SQL string that is passed to your mock DAO. You're only interested that
-  the IN clause contains the proper primary keys, so you can set your mock
-  up as follows:
-
-  mock_dao.RunQuery(StrContains('IN (1, 2, 4, 5)')).AndReturn(mock_result)
-
-  Now whatever query is passed in must contain the string 'IN (1, 2, 4, 5)'.
-
-  A Comparator may replace one or more parameters, for example:
-  # return at most 10 rows
-  mock_dao.RunQuery(StrContains('SELECT'), 10)
-
-  or
-
-  # Return some non-deterministic number of rows
-  mock_dao.RunQuery(StrContains('SELECT'), IsA(int))
-  """
-
-  def equals(self, rhs):
-    """Special equals method that all comparators must implement.
-
-    Args:
-      rhs: any python object
-    """
-
-    raise NotImplementedError('method must be implemented by a subclass.')
-
-  def __eq__(self, rhs):
-    return self.equals(rhs)
-
-  def __ne__(self, rhs):
-    return not self.equals(rhs)
-
-
-class IsA(Comparator):
-  """This class wraps a basic Python type or class.  It is used to verify
-  that a parameter is of the given type or class.
-
-  Example:
-  mock_dao.Connect(IsA(DbConnectInfo))
-  """
-
-  def __init__(self, class_name):
-    """Initialize IsA
-
-    Args:
-      class_name: basic python type or a class
-    """
-
-    self._class_name = class_name
-
-  def equals(self, rhs):
-    """Check to see if the RHS is an instance of class_name.
-
-    Args:
-      # rhs: the right hand side of the test
-      rhs: object
-
-    Returns:
-      bool
-    """
-
-    try:
-      return isinstance(rhs, self._class_name)
-    except TypeError:
-      # Check raw types if there was a type error.  This is helpful for
-      # things like cStringIO.StringIO.
-      return type(rhs) == type(self._class_name)
-
-  def __repr__(self):
-    return str(self._class_name)
-
-class IsAlmost(Comparator):
-  """Comparison class used to check whether a parameter is nearly equal
-  to a given value.  Generally useful for floating point numbers.
-
-  Example mock_dao.SetTimeout((IsAlmost(3.9)))
-  """
-
-  def __init__(self, float_value, places=7):
-    """Initialize IsAlmost.
-
-    Args:
-      float_value: The value for making the comparison.
-      places: The number of decimal places to round to.
-    """
-
-    self._float_value = float_value
-    self._places = places
-
-  def equals(self, rhs):
-    """Check to see if RHS is almost equal to float_value
-
-    Args:
-      rhs: the value to compare to float_value
-
-    Returns:
-      bool
-    """
-
-    try:
-      return round(rhs-self._float_value, self._places) == 0
-    except TypeError:
-      # This is probably because either float_value or rhs is not a number.
-      return False
-
-  def __repr__(self):
-    return str(self._float_value)
-
-class StrContains(Comparator):
-  """Comparison class used to check whether a substring exists in a
-  string parameter.  This can be useful in mocking a database with SQL
-  passed in as a string parameter, for example.
-
-  Example:
-  mock_dao.RunQuery(StrContains('IN (1, 2, 4, 5)')).AndReturn(mock_result)
-  """
-
-  def __init__(self, search_string):
-    """Initialize.
-
-    Args:
-      # search_string: the string you are searching for
-      search_string: str
-    """
-
-    self._search_string = search_string
-
-  def equals(self, rhs):
-    """Check to see if the search_string is contained in the rhs string.
-
-    Args:
-      # rhs: the right hand side of the test
-      rhs: object
-
-    Returns:
-      bool
-    """
-
-    try:
-      return rhs.find(self._search_string) > -1
-    except Exception:
-      return False
-
-  def __repr__(self):
-    return '<str containing \'%s\'>' % self._search_string
-
-
-class Regex(Comparator):
-  """Checks if a string matches a regular expression.
-
-  This uses a given regular expression to determine equality.
-  """
-
-  def __init__(self, pattern, flags=0):
-    """Initialize.
-
-    Args:
-      # pattern is the regular expression to search for
-      pattern: str
-      # flags passed to re.compile function as the second argument
-      flags: int
-    """
-
-    self.regex = re.compile(pattern, flags=flags)
-
-  def equals(self, rhs):
-    """Check to see if rhs matches regular expression pattern.
-
-    Returns:
-      bool
-    """
-
-    return self.regex.search(rhs) is not None
-
-  def __repr__(self):
-    s = '<regular expression \'%s\'' % self.regex.pattern
-    if self.regex.flags:
-      s += ', flags=%d' % self.regex.flags
-    s += '>'
-    return s
-
-
-class In(Comparator):
-  """Checks whether an item (or key) is in a list (or dict) parameter.
-
-  Example:
-  mock_dao.GetUsersInfo(In('expectedUserName')).AndReturn(mock_result)
-  """
-
-  def __init__(self, key):
-    """Initialize.
-
-    Args:
-      # key is any thing that could be in a list or a key in a dict
-    """
-
-    self._key = key
-
-  def equals(self, rhs):
-    """Check to see whether key is in rhs.
-
-    Args:
-      rhs: dict
-
-    Returns:
-      bool
-    """
-
-    return self._key in rhs
-
-  def __repr__(self):
-    return '<sequence or map containing \'%s\'>' % self._key
-
-
-class ContainsKeyValue(Comparator):
-  """Checks whether a key/value pair is in a dict parameter.
-
-  Example:
-  mock_dao.UpdateUsers(ContainsKeyValue('stevepm', stevepm_user_info))
-  """
-
-  def __init__(self, key, value):
-    """Initialize.
-
-    Args:
-      # key: a key in a dict
-      # value: the corresponding value
-    """
-
-    self._key = key
-    self._value = value
-
-  def equals(self, rhs):
-    """Check whether the given key/value pair is in the rhs dict.
-
-    Returns:
-      bool
-    """
-
-    try:
-      return rhs[self._key] == self._value
-    except Exception:
-      return False
-
-  def __repr__(self):
-    return '<map containing the entry \'%s: %s\'>' % (self._key, self._value)
-
-
-class SameElementsAs(Comparator):
-  """Checks whether iterables contain the same elements (ignoring order).
-
-  Example:
-  mock_dao.ProcessUsers(SameElementsAs('stevepm', 'salomaki'))
-  """
-
-  def __init__(self, expected_seq):
-    """Initialize.
-
-    Args:
-      expected_seq: a sequence
-    """
-
-    self._expected_seq = expected_seq
-
-  def equals(self, actual_seq):
-    """Check to see whether actual_seq has same elements as expected_seq.
-
-    Args:
-      actual_seq: sequence
-
-    Returns:
-      bool
-    """
-
-    try:
-      expected = dict([(element, None) for element in self._expected_seq])
-      actual = dict([(element, None) for element in actual_seq])
-    except TypeError:
-      # Fall back to slower list-compare if any of the objects are unhashable.
-      expected = list(self._expected_seq)
-      actual = list(actual_seq)
-      expected.sort()
-      actual.sort()
-    return expected == actual
-
-  def __repr__(self):
-    return '<sequence with same elements as \'%s\'>' % self._expected_seq
-
-
-class And(Comparator):
-  """Evaluates one or more Comparators on RHS and returns an AND of the results.
-  """
-
-  def __init__(self, *args):
-    """Initialize.
-
-    Args:
-      *args: One or more Comparator
-    """
-
-    self._comparators = args
-
-  def equals(self, rhs):
-    """Checks whether all Comparators are equal to rhs.
-
-    Args:
-      # rhs: can be anything
-
-    Returns:
-      bool
-    """
-
-    for comparator in self._comparators:
-      if not comparator.equals(rhs):
-        return False
-
-    return True
-
-  def __repr__(self):
-    return '<AND %s>' % str(self._comparators)
-
-
-class Or(Comparator):
-  """Evaluates one or more Comparators on RHS and returns an OR of the results.
-  """
-
-  def __init__(self, *args):
-    """Initialize.
-
-    Args:
-      *args: One or more Mox comparators
-    """
-
-    self._comparators = args
-
-  def equals(self, rhs):
-    """Checks whether any Comparator is equal to rhs.
-
-    Args:
-      # rhs: can be anything
-
-    Returns:
-      bool
-    """
-
-    for comparator in self._comparators:
-      if comparator.equals(rhs):
-        return True
-
-    return False
-
-  def __repr__(self):
-    return '<OR %s>' % str(self._comparators)
-
-
-class Func(Comparator):
-  """Call a function that should verify the parameter passed in is correct.
-
-  You may need the ability to perform more advanced operations on the parameter
-  in order to validate it.  You can use this to have a callable validate any
-  parameter. The callable should return either True or False.
-
-
-  Example:
-
-  def myParamValidator(param):
-    # Advanced logic here
-    return True
-
-  mock_dao.DoSomething(Func(myParamValidator), true)
-  """
-
-  def __init__(self, func):
-    """Initialize.
-
-    Args:
-      func: callable that takes one parameter and returns a bool
-    """
-
-    self._func = func
-
-  def equals(self, rhs):
-    """Test whether rhs passes the function test.
-
-    rhs is passed into func.
-
-    Args:
-      rhs: any python object
-
-    Returns:
-      the result of func(rhs)
-    """
-
-    return self._func(rhs)
-
-  def __repr__(self):
-    return str(self._func)
-
-
-class IgnoreArg(Comparator):
-  """Ignore an argument.
-
-  This can be used when we don't care about an argument of a method call.
-
-  Example:
-  # Check if CastMagic is called with 3 as first arg and 'disappear' as third.
-  mymock.CastMagic(3, IgnoreArg(), 'disappear')
-  """
-
-  def equals(self, unused_rhs):
-    """Ignores arguments and returns True.
-
-    Args:
-      unused_rhs: any python object
-
-    Returns:
-      always returns True
-    """
-
-    return True
-
-  def __repr__(self):
-    return '<IgnoreArg>'
-
-
-class MethodGroup(object):
-  """Base class containing common behaviour for MethodGroups."""
-
-  def __init__(self, group_name):
-    self._group_name = group_name
-
-  def group_name(self):
-    return self._group_name
-
-  def __str__(self):
-    return '<%s "%s">' % (self.__class__.__name__, self._group_name)
-
-  def AddMethod(self, mock_method):
-    raise NotImplementedError
-
-  def MethodCalled(self, mock_method):
-    raise NotImplementedError
-
-  def IsSatisfied(self):
-    raise NotImplementedError
-
-class UnorderedGroup(MethodGroup):
-  """UnorderedGroup holds a set of method calls that may occur in any order.
-
-  This construct is helpful for non-deterministic events, such as iterating
-  over the keys of a dict.
-  """
-
-  def __init__(self, group_name):
-    super(UnorderedGroup, self).__init__(group_name)
-    self._methods = []
-
-  def AddMethod(self, mock_method):
-    """Add a method to this group.
-
-    Args:
-      mock_method: A mock method to be added to this group.
-    """
-
-    self._methods.append(mock_method)
-
-  def MethodCalled(self, mock_method):
-    """Remove a method call from the group.
-
-    If the method is not in the set, an UnexpectedMethodCallError will be
-    raised.
-
-    Args:
-      mock_method: a mock method that should be equal to a method in the group.
-
-    Returns:
-      The mock method from the group
-
-    Raises:
-      UnexpectedMethodCallError if the mock_method was not in the group.
-    """
-
-    # Check to see if this method exists, and if so, remove it from the set
-    # and return it.
-    for method in self._methods:
-      if method == mock_method:
-        # Remove the called mock_method instead of the method in the group.
-        # The called method will match any comparators when equality is checked
-        # during removal.  The method in the group could pass a comparator to
-        # another comparator during the equality check.
-        self._methods.remove(mock_method)
-
-        # If this group is not empty, put it back at the head of the queue.
-        if not self.IsSatisfied():
-          mock_method._call_queue.appendleft(self)
-
-        return self, method
-
-    raise UnexpectedMethodCallError(mock_method, self)
-
-  def IsSatisfied(self):
-    """Return True if there are not any methods in this group."""
-
-    return len(self._methods) == 0
-
-
-class MultipleTimesGroup(MethodGroup):
-  """MultipleTimesGroup holds methods that may be called any number of times.
-
-  Note: Each method must be called at least once.
-
-  This is helpful, if you don't know or care how many times a method is called.
-  """
-
-  def __init__(self, group_name):
-    super(MultipleTimesGroup, self).__init__(group_name)
-    self._methods = set()
-    self._methods_called = set()
-
-  def AddMethod(self, mock_method):
-    """Add a method to this group.
-
-    Args:
-      mock_method: A mock method to be added to this group.
-    """
-
-    self._methods.add(mock_method)
-
-  def MethodCalled(self, mock_method):
-    """Remove a method call from the group.
-
-    If the method is not in the set, an UnexpectedMethodCallError will be
-    raised.
-
-    Args:
-      mock_method: a mock method that should be equal to a method in the group.
-
-    Returns:
-      The mock method from the group
-
-    Raises:
-      UnexpectedMethodCallError if the mock_method was not in the group.
-    """
-
-    # Check to see if this method exists, and if so add it to the set of
-    # called methods.
-
-    for method in self._methods:
-      if method == mock_method:
-        self._methods_called.add(mock_method)
-        # Always put this group back on top of the queue, because we don't know
-        # when we are done.
-        mock_method._call_queue.appendleft(self)
-        return self, method
-
-    if self.IsSatisfied():
-      next_method = mock_method._PopNextMethod();
-      return next_method, None
-    else:
-      raise UnexpectedMethodCallError(mock_method, self)
-
-  def IsSatisfied(self):
-    """Return True if all methods in this group are called at least once."""
-    # NOTE(psycho): We can't use the simple set difference here because we want
-    # to match different parameters which are considered the same e.g. IsA(str)
-    # and some string. This solution is O(n^2) but n should be small.
-    tmp = self._methods.copy()
-    for called in self._methods_called:
-      for expected in tmp:
-        if called == expected:
-          tmp.remove(expected)
-          if not tmp:
-            return True
-          break
-    return False
-
-
-class MoxMetaTestBase(type):
-  """Metaclass to add mox cleanup and verification to every test.
-
-  As the mox unit testing class is being constructed (MoxTestBase or a
-  subclass), this metaclass will modify all test functions to call the
-  CleanUpMox method of the test class after they finish. This means that
-  unstubbing and verifying will happen for every test with no additional code,
-  and any failures will result in test failures as opposed to errors.
-  """
-
-  def __init__(cls, name, bases, d):
-    type.__init__(cls, name, bases, d)
-
-    # also get all the attributes from the base classes to account
-    # for a case when test class is not the immediate child of MoxTestBase
-    for base in bases:
-      for attr_name in dir(base):
-        d[attr_name] = getattr(base, attr_name)
-
-    for func_name, func in d.items():
-      if func_name.startswith('test') and callable(func):
-        setattr(cls, func_name, MoxMetaTestBase.CleanUpTest(cls, func))
-
-  @staticmethod
-  def CleanUpTest(cls, func):
-    """Adds Mox cleanup code to any MoxTestBase method.
-
-    Always unsets stubs after a test. Will verify all mocks for tests that
-    otherwise pass.
-
-    Args:
-      cls: MoxTestBase or subclass; the class whose test method we are altering.
-      func: method; the method of the MoxTestBase test class we wish to alter.
-
-    Returns:
-      The modified method.
-    """
-    def new_method(self, *args, **kwargs):
-      mox_obj = getattr(self, 'mox', None)
-      cleanup_mox = False
-      if mox_obj and isinstance(mox_obj, Mox):
-        cleanup_mox = True
-      try:
-        func(self, *args, **kwargs)
-      finally:
-        if cleanup_mox:
-          mox_obj.UnsetStubs()
-      if cleanup_mox:
-        mox_obj.VerifyAll()
-    new_method.__name__ = func.__name__
-    new_method.__doc__ = func.__doc__
-    new_method.__module__ = func.__module__
-    return new_method
-
-
-class MoxTestBase(unittest.TestCase):
-  """Convenience test class to make stubbing easier.
-
-  Sets up a "mox" attribute which is an instance of Mox - any mox tests will
-  want this. Also automatically unsets any stubs and verifies that all mock
-  methods have been called at the end of each test, eliminating boilerplate
-  code.
-  """
-
-  __metaclass__ = MoxMetaTestBase
-
-  def setUp(self):
-    self.mox = Mox()
diff --git a/src/google/protobuf/io/gzip_stream_unittest.sh b/python/python_version.py
old mode 100755
new mode 100644
similarity index 71%
rename from src/google/protobuf/io/gzip_stream_unittest.sh
rename to python/python_version.py
index 16251a9..5bf8d21
--- a/src/google/protobuf/io/gzip_stream_unittest.sh
+++ b/python/python_version.py
@@ -1,7 +1,5 @@
-#!/bin/sh -x
-#
 # Protocol Buffers - Google's data interchange format
-# Copyright 2009 Google Inc.  All rights reserved.
+# Copyright 2008 Google Inc.  All rights reserved.
 # https://developers.google.com/protocol-buffers/
 #
 # Redistribution and use in source and binary forms, with or without
@@ -29,16 +27,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.
-#
-# Author: brianolson@google.com (Brian Olson)
-#
-# Test compatibility between command line gzip/gunzip binaries and
-# ZeroCopyStream versions.
+"""Test that Kokoro is using the expected version of python."""
 
-TESTFILE=Makefile
+import os
+import sys
+import unittest
 
-(./zcgzip < ${TESTFILE} | gunzip | cmp - ${TESTFILE}) && \
-(gzip < ${TESTFILE} | ./zcgunzip | cmp - ${TESTFILE})
 
-# Result of "(cmd) && (cmd)" implicitly becomes result of this script
-# and thus the test.
+class PythonVersionTest(unittest.TestCase):
+
+  def testPython3(self):
+    """Test that we can import nested import public messages."""
+
+    exp = os.getenv('KOKORO_PYTHON_VERSION', '')
+    if not exp:
+      print('No kokoro python version found, skipping check', file=sys.stderr)
+      return
+    self.assertTrue(
+        sys.version.startswith(exp),
+        'Expected Python %s but found Python %s' % (exp, sys.version))
+
+
+if __name__ == '__main__':
+  unittest.main()
diff --git a/python/setup.py b/python/setup.py
index cbb9a59..e656310 100755
--- a/python/setup.py
+++ b/python/setup.py
@@ -1,4 +1,33 @@
 #! /usr/bin/env python
+# 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.
 #
 # See README for usage instructions.
 
@@ -29,10 +58,14 @@
 # Find the Protocol Compiler.
 if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
   protoc = os.environ['PROTOC']
-elif os.path.exists('../src/protoc'):
-  protoc = '../src/protoc'
-elif os.path.exists('../src/protoc.exe'):
-  protoc = '../src/protoc.exe'
+elif os.path.exists('../bazel-bin/protoc'):
+  protoc = '../bazel-bin/protoc'
+elif os.path.exists('../bazel-bin/protoc.exe'):
+  protoc = '../bazel-bin/protoc.exe'
+elif os.path.exists('protoc'):
+  protoc = '../protoc'
+elif os.path.exists('protoc.exe'):
+  protoc = '../protoc.exe'
 elif os.path.exists('../vsprojects/Debug/protoc.exe'):
   protoc = '../vsprojects/Debug/protoc.exe'
 elif os.path.exists('../vsprojects/Release/protoc.exe'):
@@ -203,13 +236,13 @@
 
 
 class TestConformanceCmd(_build_py):
-  target = 'test_python'
+  target = '//python:conformance_test'
 
   def run(self):
     # Python 2.6 dodges these extra failures.
     os.environ['CONFORMANCE_PYTHON_EXTRA_FAILURES'] = (
         '--failure_list failure_list_python-post26.txt')
-    cmd = 'cd ../conformance && make %s' % (TestConformanceCmd.target)
+    cmd = 'bazel test %s' % (TestConformanceCmd.target,)
     subprocess.check_call(cmd, shell=True)
 
 
@@ -220,6 +253,59 @@
   return False
 
 
+def _GetFlagValues(flag_long, flag_short):
+  """Searches sys.argv for distutils-style flags and yields values."""
+
+  expect_value = flag_long.endswith('=')
+  flag_res = [re.compile(r'--?%s(=(.*))?' %
+                         (flag_long[:-1] if expect_value else flag_long))]
+  if flag_short:
+    flag_res.append(re.compile(r'-%s(.*)?' % (flag_short,)))
+
+  flag_match = None
+  for arg in sys.argv:
+    # If the last arg was like '-O', check if this is the library we want.
+    if flag_match is not None:
+      yield arg
+      flag_match = None
+      continue
+
+    for flag_re in flag_res:
+      m = flag_re.match(arg)
+      if m is None:
+        continue
+      if not expect_value:
+        yield arg
+        continue
+      groups = m.groups()
+      # Check for matches:
+      #   --long-name=foo => ('=foo', 'foo')
+      #   -Xfoo => ('foo')
+      # N.B.: if the flag is like '--long-name=', then there is a value
+      # (the empty string).
+      if groups[0] or groups[-1]:
+        yield groups[-1]
+        continue
+      flag_match = m
+
+  return False
+
+
+def HasStaticLibprotobufOpt():
+  """Returns true if there is a --link-objects arg for libprotobuf."""
+
+  lib_re = re.compile(r'(.*[/\\])?(lib)?protobuf([.]pic)?[.](a|lib)')
+  for value in _GetFlagValues('link-objects=', 'O'):
+    if lib_re.match(value):
+      return True
+  return False
+
+
+def HasLibraryDirsOpt():
+  """Returns true if there is a --library-dirs arg."""
+  return any(_GetFlagValues('library-dirs=', 'L'))
+
+
 if __name__ == '__main__':
   ext_module_list = []
   warnings_as_errors = '--warnings_as_errors'
@@ -227,14 +313,39 @@
     # Link libprotobuf.a and libprotobuf-lite.a statically with the
     # extension. Note that those libraries have to be compiled with
     # -fPIC for this to work.
-    compile_static_ext = GetOptionFromArgv('--compile_static_extension')
-    libraries = ['protobuf']
+    compile_static_ext = HasStaticLibprotobufOpt()
+    if GetOptionFromArgv('--compile_static_extension'):
+      # FUTURE: add a warning and deprecate --compile_static_extension.
+      compile_static_ext = True
     extra_objects = None
     if compile_static_ext:
       libraries = None
-      extra_objects = ['../src/.libs/libprotobuf.a',
-                       '../src/.libs/libprotobuf-lite.a']
-    TestConformanceCmd.target = 'test_python_cpp'
+      library_dirs = None
+      if not HasStaticLibprotobufOpt():
+        if os.path.exists('../bazel-bin/src/google/protobuf/libprotobuf.a'):
+          extra_objects = ['../bazel-bin/src/google/protobuf/libprotobuf.a']
+        else:
+          extra_objects = ['../libprotobuf.a']
+          extra_objects += list(
+              glob.iglob('../third_party/utf8_range/*.a'))
+          # Repeat all of these enough times to eliminate order-dependence.
+          extra_objects += list(
+              glob.iglob('../third_party/abseil-cpp/absl/**/*.a'))
+          extra_objects += list(
+              glob.iglob('../third_party/abseil-cpp/absl/**/*.a'))
+          extra_objects += list(
+              glob.iglob('../third_party/abseil-cpp/absl/**/*.a'))
+    else:
+      libraries = ['protobuf']
+      if HasLibraryDirsOpt():
+        library_dirs = None
+      elif os.path.exists('../bazel-bin/src/google/protobuf/libprotobuf.a'):
+        library_dirs = ['../bazel-bin/src/google/protobuf']
+      else:
+        library_dirs = ['..']
+
+    TestConformanceCmd.target = ('//python:conformance_test_cpp '
+                                 '--define=use_fast_cpp_protos=true')
 
     extra_compile_args = []
 
@@ -259,7 +370,7 @@
       extra_compile_args.append('-Wno-invalid-offsetof')
       extra_compile_args.append('-Wno-sign-compare')
       extra_compile_args.append('-Wno-unused-variable')
-      extra_compile_args.append('-std=c++11')
+      extra_compile_args.append('-std=c++14')
 
     if sys.platform == 'darwin':
       extra_compile_args.append('-Wno-shorten-64-to-32')
@@ -301,11 +412,11 @@
         Extension(
             'google.protobuf.pyext._message',
             glob.glob('google/protobuf/pyext/*.cc'),
-            include_dirs=['.', '../src'],
+            include_dirs=['.', '../src', '../third_party/abseil-cpp'],
             libraries=libraries,
             extra_objects=extra_objects,
             extra_link_args=message_extra_link_args,
-            library_dirs=['../src/.libs'],
+            library_dirs=library_dirs,
             extra_compile_args=extra_compile_args,
         ),
         Extension(
@@ -328,6 +439,9 @@
       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/',
+      project_urls={
+          'Source': 'https://github.com/protocolbuffers/protobuf',
+      },
       maintainer='protobuf@googlegroups.com',
       maintainer_email='protobuf@googlegroups.com',
       license='BSD-3-Clause',
diff --git a/python/stubout.py b/python/stubout.py
deleted file mode 100755
index ba39104..0000000
--- a/python/stubout.py
+++ /dev/null
@@ -1,143 +0,0 @@
-#!/usr/bin/python2.4
-#
-# Copyright 2008 Google Inc.
-#
-# Licensed under the Apache License, Version 2.0 (the "License");
-# you may not use this file except in compliance with the License.
-# You may obtain a copy of the License at
-#
-#      http://www.apache.org/licenses/LICENSE-2.0
-#
-# Unless required by applicable law or agreed to in writing, software
-# distributed under the License is distributed on an "AS IS" BASIS,
-# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
-# See the License for the specific language governing permissions and
-# limitations under the License.
-
-# This file is used for testing.  The original is at:
-#   http://code.google.com/p/pymox/
-
-import inspect
-
-
-class StubOutForTesting:
-  """Sample Usage:
-     You want os.path.exists() to always return true during testing.
-
-     stubs = StubOutForTesting()
-     stubs.Set(os.path, 'exists', lambda x: 1)
-       ...
-     stubs.UnsetAll()
-
-     The above changes os.path.exists into a lambda that returns 1.  Once
-     the ... part of the code finishes, the UnsetAll() looks up the old value
-     of os.path.exists and restores it.
-
-  """
-  def __init__(self):
-    self.cache = []
-    self.stubs = []
-
-  def __del__(self):
-    self.SmartUnsetAll()
-    self.UnsetAll()
-
-  def SmartSet(self, obj, attr_name, new_attr):
-    """Replace obj.attr_name with new_attr. This method is smart and works
-       at the module, class, and instance level while preserving proper
-       inheritance. It will not stub out C types however unless that has been
-       explicitly allowed by the type.
-
-       This method supports the case where attr_name is a staticmethod or a
-       classmethod of obj.
-
-       Notes:
-      - If obj is an instance, then it is its class that will actually be
-        stubbed. Note that the method Set() does not do that: if obj is
-        an instance, it (and not its class) will be stubbed.
-      - The stubbing is using the builtin getattr and setattr. So, the __get__
-        and __set__ will be called when stubbing (TODO: A better idea would
-        probably be to manipulate obj.__dict__ instead of getattr() and
-        setattr()).
-
-       Raises AttributeError if the attribute cannot be found.
-    """
-    if (inspect.ismodule(obj) or
-        (not inspect.isclass(obj) and obj.__dict__.has_key(attr_name))):
-      orig_obj = obj
-      orig_attr = getattr(obj, attr_name)
-
-    else:
-      if not inspect.isclass(obj):
-        mro = list(inspect.getmro(obj.__class__))
-      else:
-        mro = list(inspect.getmro(obj))
-
-      mro.reverse()
-
-      orig_attr = None
-
-      for cls in mro:
-        try:
-          orig_obj = cls
-          orig_attr = getattr(obj, attr_name)
-        except AttributeError:
-          continue
-
-    if orig_attr is None:
-      raise AttributeError("Attribute not found.")
-
-    # Calling getattr() on a staticmethod transforms it to a 'normal' function.
-    # We need to ensure that we put it back as a staticmethod.
-    old_attribute = obj.__dict__.get(attr_name)
-    if old_attribute is not None and isinstance(old_attribute, staticmethod):
-      orig_attr = staticmethod(orig_attr)
-
-    self.stubs.append((orig_obj, attr_name, orig_attr))
-    setattr(orig_obj, attr_name, new_attr)
-
-  def SmartUnsetAll(self):
-    """Reverses all the SmartSet() calls, restoring things to their original
-    definition.  Its okay to call SmartUnsetAll() repeatedly, as later calls
-    have no effect if no SmartSet() calls have been made.
-
-    """
-    self.stubs.reverse()
-
-    for args in self.stubs:
-      setattr(*args)
-
-    self.stubs = []
-
-  def Set(self, parent, child_name, new_child):
-    """Replace child_name's old definition with new_child, in the context
-    of the given parent.  The parent could be a module when the child is a
-    function at module scope.  Or the parent could be a class when a class'
-    method is being replaced.  The named child is set to new_child, while
-    the prior definition is saved away for later, when UnsetAll() is called.
-
-    This method supports the case where child_name is a staticmethod or a
-    classmethod of parent.
-    """
-    old_child = getattr(parent, child_name)
-
-    old_attribute = parent.__dict__.get(child_name)
-    if old_attribute is not None and isinstance(old_attribute, staticmethod):
-      old_child = staticmethod(old_child)
-
-    self.cache.append((parent, old_child, child_name))
-    setattr(parent, child_name, new_child)
-
-  def UnsetAll(self):
-    """Reverses all the Set() calls, restoring things to their original
-    definition.  Its okay to call UnsetAll() repeatedly, as later calls have
-    no effect if no Set() calls have been made.
-
-    """
-    # Undo calls to Set() in reverse order, in case Set() was called on the
-    # same arguments repeatedly (want the original call to be last one undone)
-    self.cache.reverse()
-
-    for (parent, old_child, child_name) in self.cache:
-      setattr(parent, child_name, old_child)
-    self.cache = []
diff --git a/python/tox.ini b/python/tox.ini
index b923a4a..346ce21 100644
--- a/python/tox.ini
+++ b/python/tox.ini
@@ -5,10 +5,10 @@
 [testenv]
 usedevelop=true
 passenv =
-    CC KOKORO_BUILD_ID KOKORO_BUILD_NUMBER
+    CC PYTHONPATH KOKORO_BUILD_ID KOKORO_BUILD_NUMBER
 setenv =
-    cpp: LD_LIBRARY_PATH={toxinidir}/../src/.libs
-    cpp: DYLD_LIBRARY_PATH={toxinidir}/../src/.libs
+    cpp: LD_LIBRARY_PATH={toxinidir}/../bazel-bin/src/google
+    cpp: DYLD_LIBRARY_PATH={toxinidir}/../bazel-bin/src/google
     cpp: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=cpp
     python: PROTOCOL_BUFFERS_PYTHON_IMPLEMENTATION=python
 commands =
diff --git a/ruby/BUILD.bazel b/ruby/BUILD.bazel
index fe336e5..d4114b5 100644
--- a/ruby/BUILD.bazel
+++ b/ruby/BUILD.bazel
@@ -3,30 +3,204 @@
 # See also code generation logic under /src/google/protobuf/compiler/ruby.
 
 load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("@upb//cmake:build_defs.bzl", "staleness_test")
+load("//build_defs:internal_shell.bzl", "inline_sh_test")
+load("//conformance:defs.bzl", "conformance_test")
+load("//:protobuf.bzl", "internal_ruby_proto_library")
+load(":internal.bzl", "internal_ruby_extension")
+
+################################################################################
+# Ruby Runtime
+################################################################################
+
+config_setting(
+    name = "java_ruby",
+    values = {"define": "ruby_platform=java"},
+)
+
+config_setting(
+    name = "c_ruby",
+    values = {"define": "ruby_platform=c"},
+)
+
+filegroup(
+    name = "srcs",
+    srcs = glob([
+        "lib/**/*.rb",
+        "src/**/*.proto",
+    ]) + [
+        "Gemfile",
+        "Rakefile",
+        "google-protobuf.gemspec",
+        "pom.xml",
+    ],
+)
+
+internal_ruby_extension(
+    name = "protobuf_c_mac",
+    extension = "lib/google/protobuf_c.bundle",
+    deps = glob(["ext/google/protobuf_c/*"]),
+    target_compatible_with = select({
+        ":java_ruby": ["@platforms//:incompatible"],
+        "//conditions:default": ["@platforms//os:osx"],
+    }),
+)
+
+internal_ruby_extension(
+    name = "protobuf_c",
+    extension = "lib/google/protobuf_c.so",
+    deps = glob(["ext/google/protobuf_c/*"]),
+    target_compatible_with = select({
+        ":java_ruby": ["@platforms//:incompatible"],
+        "@platforms//os:osx": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    }),
+)
+
+internal_ruby_extension(
+    name = "protobuf_java",
+    extension = "lib/google/protobuf_java.jar",
+    deps = glob(["src/**/*.java"]),
+    target_compatible_with = select({
+        ":java_ruby": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+)
+
+filegroup(
+    name = "protobuf",
+    srcs = [
+        ":srcs",
+        "@utf8_range//:utf8_range_srcs",
+    ] + select({
+        ":java_ruby": [":protobuf_java"],
+        "@bazel_tools//src/conditions:darwin": [":protobuf_c_mac"],
+        "//conditions:default": [":protobuf_c"],
+    }),
+    visibility = [
+        "//conformance:__subpackages__",
+        "//ruby:__subpackages__",
+    ],
+)
+
+################################################################################
+# Tests
+################################################################################
+
+filegroup(
+  name = "tests",
+  srcs = glob(["tests/*.rb"]),
+)
+
+filegroup(
+  name = "test_protos",
+  srcs = glob(["tests/*.proto"]),
+)
+
+internal_ruby_proto_library(
+    name = "test_ruby_protos",
+    srcs = [":test_protos"],
+    proto_deps = ["//:well_known_protos"],
+    includes = [".", "src", "ruby/tests"],
+)
+
+inline_sh_test(
+    name = "test",
+    srcs = [
+        "Rakefile",
+    ],
+    deps = [
+        ":protobuf",
+        ":test_ruby_protos",
+        ":tests",
+        "//:well_known_ruby_protos",
+    ],
+    cmd = """
+        pushd `dirname $(location Rakefile)`
+        RUBYLIB=../src:tests:. BAZEL=true rake test
+        popd
+    """,
+)
+
+inline_sh_test(
+    name = "gc_test",
+    srcs = [
+        "Rakefile",
+    ],
+    deps = [
+        ":protobuf",
+        ":test_ruby_protos",
+        ":tests",
+        "//:well_known_ruby_protos",
+    ],
+    cmd = """
+        pushd `dirname $(location Rakefile)`
+        RUBYLIB=../src:tests:. BAZEL=true rake gc_test
+        popd
+    """,
+)
+
+conformance_test(
+    name = "conformance_test",
+    failure_list = "//conformance:failure_list_ruby.txt",
+    testee = "//conformance:conformance_ruby",
+    text_format_failure_list = "//conformance:text_format_failure_list_ruby.txt",
+    target_compatible_with = select({
+        ":java_ruby": ["@platforms//:incompatible"],
+        "//conditions:default": [],
+    }),
+)
+
+conformance_test(
+    name = "conformance_test_jruby",
+    failure_list = "//conformance:failure_list_jruby.txt",
+    testee = "//conformance:conformance_ruby",
+    text_format_failure_list = "//conformance:text_format_failure_list_jruby.txt",
+    target_compatible_with = select({
+        ":java_ruby": [],
+        "//conditions:default": ["@platforms//:incompatible"],
+    }),
+)
+
+genrule(
+    name = "copy_ruby_amalgamation_h",
+    srcs = ["@upb//:ruby-upb.h"],
+    outs = ["generated-in/ext/google/protobuf_c/ruby-upb.h"],
+    cmd = "cp $< $@",
+)
+
+genrule(
+    name = "copy_ruby_amalgamation_c",
+    srcs = ["@upb//:ruby-upb.c"],
+    outs = ["generated-in/ext/google/protobuf_c/ruby-upb.c"],
+    cmd = "cp $< $@",
+)
+
+staleness_test(
+    name = "test_amalgamation_staleness",
+    outs = [
+        "ext/google/protobuf_c/ruby-upb.h",
+        "ext/google/protobuf_c/ruby-upb.c",
+    ],
+    generated_pattern = "generated-in/%s",
+)
+
+################################################################################
+# Distribution files
+################################################################################
 
 pkg_files(
     name = "dist_files",
     srcs = glob([
-        "compatibility_tests/v3.0.0/**/*",
-        "ext/google/protobuf_c/*",
-        "src/main/java/com/google/protobuf/jruby/*.java",
         "tests/*.proto",
         "tests/*.rb",
     ]) + [
+        ":srcs",
         ".gitignore",
         "BUILD.bazel",
+        "internal.bzl",
         "Gemfile",
         "README.md",
-        "Rakefile",
-        "google-protobuf.gemspec",
-        "lib/google/protobuf.rb",
-        "lib/google/protobuf/descriptor_dsl.rb",
-        "lib/google/protobuf/message_exts.rb",
-        "lib/google/protobuf/repeated_field.rb",
-        "lib/google/protobuf/well_known_types.rb",
-        "pom.xml",
-        "src/main/java/google/ProtobufJavaService.java",
-        "src/main/sentinel.proto",
         "travis-test.sh",
     ],
     strip_prefix = strip_prefix.from_root(""),
diff --git a/ruby/README.md b/ruby/README.md
index 42a1ffa..be8d6bc 100644
--- a/ruby/README.md
+++ b/ruby/README.md
@@ -9,7 +9,7 @@
 
 Installation from Gem
 ---------------------
-In Gemfile (Please check a version of Protocol Buffers you needed [RubyGems](https://rubygems.org/gems/google-protobuf)):
+In Gemfile (Please check which version of Protocol Buffers you need: [RubyGems](https://rubygems.org/gems/google-protobuf)):
 
     gem 'google-protobuf'
 
diff --git a/ruby/Rakefile b/ruby/Rakefile
index d8ac763..e6b774c 100644
--- a/ruby/Rakefile
+++ b/ruby/Rakefile
@@ -39,8 +39,8 @@
 
 if !ENV['PROTOC'].nil?
   protoc_command = ENV['PROTOC']
-elsif system('../src/protoc --version')
-  protoc_command = '../src/protoc'
+elsif system('../bazel-bin/protoc --version')
+  protoc_command = '../bazel-bin/protoc'
 else
   protoc_command = 'protoc'
 end
@@ -49,7 +49,7 @@
 
 # We won't have access to .. from within docker, but the proto files
 # will be there, thanks to the :genproto rule dependency for gem:native.
-unless ENV['IN_DOCKER'] == 'true'
+unless ENV['IN_DOCKER'] == 'true' or ENV['BAZEL'] == 'true'
   well_known_protos.each do |proto_file|
     input_file = "../src/" + proto_file
     output_file = "lib/" + proto_file.sub(/\.proto$/, "_pb.rb")
@@ -84,12 +84,16 @@
 else
   unless ENV['IN_DOCKER'] == 'true'
     # We need utf8_range in-tree.
+    if  ENV['BAZEL'] == 'true'
+      utf8_root = '../external/utf8_range'
+    else
+      utf8_root = '../third_party/utf8_range'
+    end
     FileUtils.mkdir_p("ext/google/protobuf_c/third_party/utf8_range")
-    FileUtils.cp("../third_party/utf8_range/utf8_range.h", "ext/google/protobuf_c/third_party/utf8_range")
-    FileUtils.cp("../third_party/utf8_range/naive.c", "ext/google/protobuf_c/third_party/utf8_range")
-    FileUtils.cp("../third_party/utf8_range/range2-neon.c", "ext/google/protobuf_c/third_party/utf8_range")
-    FileUtils.cp("../third_party/utf8_range/range2-sse.c", "ext/google/protobuf_c/third_party/utf8_range")
-    FileUtils.cp("../third_party/utf8_range/LICENSE", "ext/google/protobuf_c/third_party/utf8_range")
+    FileUtils.cp(utf8_root+"/utf8_range.h", "ext/google/protobuf_c/third_party/utf8_range")
+    FileUtils.cp(utf8_root+"/naive.c", "ext/google/protobuf_c/third_party/utf8_range")
+    FileUtils.cp(utf8_root+"/range2-neon.c", "ext/google/protobuf_c/third_party/utf8_range")
+    FileUtils.cp(utf8_root+"/range2-sse.c", "ext/google/protobuf_c/third_party/utf8_range")
   end
 
   Rake::ExtensionTask.new("protobuf_c", spec) do |ext|
@@ -153,13 +157,15 @@
 Gem::PackageTask.new(spec) do |pkg|
 end
 
-Rake::TestTask.new(:test => [:build, :genproto]) do |t|
+# Skip build/genproto in Bazel builds, where we expect this to
+# be done already.
+Rake::TestTask.new(:test => ENV['BAZEL'] == 'true' ? [] : [:build, :genproto]) do |t|
   t.test_files = FileList["tests/*.rb"].exclude("tests/gc_test.rb", "tests/common_tests.rb")
 end
 
 # gc_test needs to be split out to ensure the generated file hasn't been
 # imported by other tests.
-Rake::TestTask.new(:gc_test => :build) do |t|
+Rake::TestTask.new(:gc_test => ENV['BAZEL'] == 'true' ? [] : :build) do |t|
   t.test_files = FileList["tests/gc_test.rb"]
 end
 
diff --git a/ruby/compatibility_tests/v3.0.0/BUILD.bazel b/ruby/compatibility_tests/v3.0.0/BUILD.bazel
new file mode 100644
index 0000000..b5fcede
--- /dev/null
+++ b/ruby/compatibility_tests/v3.0.0/BUILD.bazel
@@ -0,0 +1,56 @@
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:internal_shell.bzl", "inline_sh_test")
+load("//:protobuf.bzl", "internal_ruby_proto_library")
+
+filegroup(
+  name = "tests",
+  srcs = glob(["tests/*.rb"]),
+)
+
+filegroup(
+  name = "test_protos",
+  srcs = glob(["tests/*.proto"]),
+)
+
+internal_ruby_proto_library(
+    name = "test_ruby_protos",
+    srcs = [":test_protos"],
+    includes = ["."],
+)
+
+inline_sh_test(
+    name = "test",
+    srcs = [
+        "Rakefile",
+    ],
+    deps = [
+        ":test_ruby_protos",
+        ":tests",
+        "//:well_known_ruby_protos",
+        "//ruby:protobuf",
+    ],
+    cmd = """
+        pushd `dirname $(location Rakefile)`
+        RUBYLIB=.:tests:../../lib:../../../src BAZEL=true rake test
+        popd
+    """,
+)
+
+################################################################################
+# Distribution files
+############################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob([
+        "**/*.rb",
+        "**/*.proto"
+    ]) + [
+        "BUILD.bazel",
+        "Rakefile",
+        "README.md",
+        "test.sh",
+    ],
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//pkg:__pkg__"],
+)
diff --git a/ruby/compatibility_tests/v3.0.0/Rakefile b/ruby/compatibility_tests/v3.0.0/Rakefile
index 19a4ba1..f72bed2 100644
--- a/ruby/compatibility_tests/v3.0.0/Rakefile
+++ b/ruby/compatibility_tests/v3.0.0/Rakefile
@@ -2,14 +2,17 @@
 
 # Proto for tests.
 genproto_output = []
-genproto_output << "tests/generated_code.rb"
-genproto_output << "tests/test_import.rb"
-file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task|
-  sh "./protoc --ruby_out=. tests/generated_code.proto"
-end
 
-file "tests/test_import.rb" => "tests/test_import.proto" do |file_task|
-  sh "./protoc --ruby_out=. tests/test_import.proto"
+unless ENV['BAZEL'] == 'true'
+  genproto_output << "tests/generated_code.rb"
+  genproto_output << "tests/test_import.rb"
+  file "tests/generated_code.rb" => "tests/generated_code.proto" do |file_task|
+    sh "./protoc --ruby_out=. tests/generated_code.proto"
+  end
+
+  file "tests/test_import.rb" => "tests/test_import.proto" do |file_task|
+    sh "./protoc --ruby_out=. tests/test_import.proto"
+  end
 end
 
 task :genproto => genproto_output
diff --git a/ruby/ext/google/protobuf_c/extconf.rb b/ruby/ext/google/protobuf_c/extconf.rb
index 8bc96ae..38bb8c9 100755
--- a/ruby/ext/google/protobuf_c/extconf.rb
+++ b/ruby/ext/google/protobuf_c/extconf.rb
@@ -6,7 +6,7 @@
 
 dir_config(ext_name)
 
-if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/
+if RUBY_PLATFORM =~ /darwin/ || RUBY_PLATFORM =~ /linux/ || RUBY_PLATFORM =~ /freebsd/
   $CFLAGS += " -std=gnu99 -O3 -DNDEBUG -fvisibility=hidden -Wall -Wsign-compare -Wno-declaration-after-statement"
 else
   $CFLAGS += " -std=gnu99 -O3 -DNDEBUG"
@@ -25,4 +25,4 @@
          "repeated_field.c", "map.c", "ruby-upb.c", "wrap_memcpy.c",
          "naive.c", "range2-neon.c", "range2-sse.c"]
 
-create_makefile(ext_name)
+create_makefile(ext_name, Dir.pwd+"/../../../../ext/google/protobuf_c")
diff --git a/ruby/ext/google/protobuf_c/map.c b/ruby/ext/google/protobuf_c/map.c
index 5d30319..200d644 100644
--- a/ruby/ext/google/protobuf_c/map.c
+++ b/ruby/ext/google/protobuf_c/map.c
@@ -133,14 +133,13 @@
 VALUE Map_CreateHash(const upb_Map* map, upb_CType key_type,
                      TypeInfo val_info) {
   VALUE hash = rb_hash_new();
-  size_t iter = kUpb_Map_Begin;
   TypeInfo key_info = TypeInfo_from_type(key_type);
 
   if (!map) return hash;
 
-  while (upb_MapIterator_Next(map, &iter)) {
-    upb_MessageValue key = upb_MapIterator_Key(map, iter);
-    upb_MessageValue val = upb_MapIterator_Value(map, iter);
+  size_t iter = kUpb_Map_Begin;
+  upb_MessageValue key, val;
+  while (upb_Map_Next(map, &key, &val, &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);
@@ -156,9 +155,8 @@
   upb_Map* new_map =
       upb_Map_New(arena, self->key_type, self->value_type_info.type);
   size_t iter = kUpb_Map_Begin;
-  while (upb_MapIterator_Next(self->map, &iter)) {
-    upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
-    upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
+  upb_MessageValue key, val;
+  while (upb_Map_Next(self->map, &key, &val, &iter)) {
     upb_MessageValue val_copy =
         Msgval_DeepCopy(val, self->value_type_info, arena);
     upb_Map_Set(new_map, key, val_copy, arena);
@@ -202,9 +200,8 @@
   StringBuilder_Printf(b, "{");
   if (map) {
     size_t iter = kUpb_Map_Begin;
-    while (upb_MapIterator_Next(map, &iter)) {
-      upb_MessageValue key = upb_MapIterator_Key(map, iter);
-      upb_MessageValue val = upb_MapIterator_Value(map, iter);
+    upb_MessageValue key, val;
+    while (upb_Map_Next(map, &key, &val, &iter)) {
       if (first) {
         first = false;
       } else {
@@ -239,7 +236,6 @@
     Map* other = ruby_to_Map(hashmap);
     upb_Arena* arena = Arena_get(self->arena);
     upb_Message* self_msg = Map_GetMutable(_self);
-    size_t iter = kUpb_Map_Begin;
 
     Arena_fuse(other->arena, arena);
 
@@ -249,9 +245,9 @@
       rb_raise(rb_eArgError, "Attempt to merge Map with mismatching types");
     }
 
-    while (upb_MapIterator_Next(other->map, &iter)) {
-      upb_MessageValue key = upb_MapIterator_Key(other->map, iter);
-      upb_MessageValue val = upb_MapIterator_Value(other->map, iter);
+    size_t iter = kUpb_Map_Begin;
+    upb_MessageValue key, val;
+    while (upb_Map_Next(other->map, &key, &val, &iter)) {
       upb_Map_Set(self_msg, key, val, arena);
     }
   } else {
@@ -343,10 +339,9 @@
 static VALUE Map_each(VALUE _self) {
   Map* self = ruby_to_Map(_self);
   size_t iter = kUpb_Map_Begin;
+  upb_MessageValue key, val;
 
-  while (upb_MapIterator_Next(self->map, &iter)) {
-    upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
-    upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
+  while (upb_Map_Next(self->map, &key, &val, &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);
@@ -365,9 +360,9 @@
   Map* self = ruby_to_Map(_self);
   size_t iter = kUpb_Map_Begin;
   VALUE ret = rb_ary_new();
+  upb_MessageValue key, val;
 
-  while (upb_MapIterator_Next(self->map, &iter)) {
-    upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
+  while (upb_Map_Next(self->map, &key, &val, &iter)) {
     VALUE key_val = Convert_UpbToRuby(key, Map_keyinfo(self), self->arena);
     rb_ary_push(ret, key_val);
   }
@@ -385,9 +380,9 @@
   Map* self = ruby_to_Map(_self);
   size_t iter = kUpb_Map_Begin;
   VALUE ret = rb_ary_new();
+  upb_MessageValue key, val;
 
-  while (upb_MapIterator_Next(self->map, &iter)) {
-    upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
+  while (upb_Map_Next(self->map, &key, &val, &iter)) {
     VALUE val_val = Convert_UpbToRuby(val, self->value_type_info, self->arena);
     rb_ary_push(ret, val_val);
   }
@@ -523,9 +518,8 @@
 
   Arena_fuse(self->arena, arena);
 
-  while (upb_MapIterator_Next(self->map, &iter)) {
-    upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
-    upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
+  upb_MessageValue key, val;
+  while (upb_Map_Next(self->map, &key, &val, &iter)) {
     upb_Map_Set(new_map, key, val, arena);
   }
 
@@ -574,9 +568,8 @@
   // For each member of self, check that an equal member exists at the same key
   // in other.
   size_t iter = kUpb_Map_Begin;
-  while (upb_MapIterator_Next(self->map, &iter)) {
-    upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
-    upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
+  upb_MessageValue key, val;
+  while (upb_Map_Next(self->map, &key, &val, &iter)) {
     upb_MessageValue other_val;
     if (!upb_Map_Get(other->map, key, &other_val)) {
       // Not present in other map.
@@ -619,9 +612,8 @@
 
   size_t iter = kUpb_Map_Begin;
   TypeInfo key_info = {self->key_type};
-  while (upb_MapIterator_Next(self->map, &iter)) {
-    upb_MessageValue key = upb_MapIterator_Key(self->map, iter);
-    upb_MessageValue val = upb_MapIterator_Value(self->map, iter);
+  upb_MessageValue key, val;
+  while (upb_Map_Next(self->map, &key, &val, &iter)) {
     hash = Msgval_GetHash(key, key_info, hash);
     hash = Msgval_GetHash(val, self->value_type_info, hash);
   }
diff --git a/ruby/ext/google/protobuf_c/message.c b/ruby/ext/google/protobuf_c/message.c
index fd83dc1..3fca506 100644
--- a/ruby/ext/google/protobuf_c/message.c
+++ b/ruby/ext/google/protobuf_c/message.c
@@ -37,6 +37,7 @@
 #include "repeated_field.h"
 
 static VALUE cParseError = Qnil;
+static VALUE cAbstractMessage = Qnil;
 static ID descriptor_instancevar_interned;
 
 static VALUE initialize_rb_class_with_no_args(VALUE klass) {
@@ -510,8 +511,8 @@
   k = Convert_RubyToUpb(key, "", map_init->key_type, NULL);
 
   if (map_init->val_type.type == kUpb_CType_Message && TYPE(val) == T_HASH) {
-    upb_Message* msg =
-        upb_Message_New(map_init->val_type.def.msgdef, map_init->arena);
+    upb_MiniTable* t = upb_MessageDef_MiniTable(map_init->val_type.def.msgdef);
+    upb_Message* msg = upb_Message_New(t, map_init->arena);
     Message_InitFromValue(msg, map_init->val_type.def.msgdef, val,
                           map_init->arena);
     v.msg_val = msg;
@@ -541,7 +542,8 @@
                                                upb_Arena* arena) {
   if (info.type == kUpb_CType_Message) {
     upb_MessageValue msgval;
-    upb_Message* msg = upb_Message_New(info.def.msgdef, arena);
+    upb_MiniTable* t = upb_MessageDef_MiniTable(info.def.msgdef);
+    upb_Message* msg = upb_Message_New(t, arena);
     Message_InitFromValue(msg, info.def.msgdef, val, arena);
     msgval.msg_val = msg;
     return msgval;
@@ -656,7 +658,8 @@
   Message* self = ruby_to_Message(_self);
   VALUE arena_rb = Arena_new();
   upb_Arena* arena = Arena_get(arena_rb);
-  upb_Message* msg = upb_Message_New(self->msgdef, arena);
+  upb_MiniTable* t = upb_MessageDef_MiniTable(self->msgdef);
+  upb_Message* msg = upb_Message_New(t, arena);
 
   Message_InitPtr(_self, msg, arena_rb);
 
@@ -695,15 +698,20 @@
   if (m1 == m2) return true;
 
   size_t size1, size2;
-  int encode_opts = kUpb_Encode_SkipUnknown | kUpb_Encode_Deterministic;
+  int encode_opts =
+      kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic;
   upb_Arena* arena_tmp = upb_Arena_New();
   const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
 
   // Compare deterministically serialized payloads with no unknown fields.
-  char* data1 = upb_Encode(m1, layout, encode_opts, arena_tmp, &size1);
-  char* data2 = upb_Encode(m2, layout, encode_opts, arena_tmp, &size2);
+  char* data1;
+  char* data2;
+  upb_EncodeStatus status1 =
+      upb_Encode(m1, layout, encode_opts, arena_tmp, &data1, &size1);
+  upb_EncodeStatus status2 =
+      upb_Encode(m2, layout, encode_opts, arena_tmp, &data2, &size2);
 
-  if (data1 && data2) {
+  if (status1 == kUpb_EncodeStatus_Ok && status2 == kUpb_EncodeStatus_Ok) {
     bool ret = (size1 == size2) && (memcmp(data1, data2, size1) == 0);
     upb_Arena_Free(arena_tmp);
     return ret;
@@ -735,15 +743,16 @@
 uint64_t Message_Hash(const upb_Message* msg, const upb_MessageDef* m,
                       uint64_t seed) {
   upb_Arena* arena = upb_Arena_New();
-  const char* data;
+  char* data;
   size_t size;
 
   // Hash a deterministically serialized payloads with no unknown fields.
-  data = upb_Encode(msg, upb_MessageDef_MiniTable(m),
-                    kUpb_Encode_SkipUnknown | kUpb_Encode_Deterministic, arena,
-                    &size);
+  upb_EncodeStatus status = upb_Encode(
+      msg, upb_MessageDef_MiniTable(m),
+      kUpb_EncodeOption_SkipUnknown | kUpb_EncodeOption_Deterministic, arena,
+      &data, &size);
 
-  if (data) {
+  if (status == kUpb_EncodeStatus_Ok) {
     uint64_t ret = _upb_Hash(data, size, seed);
     upb_Arena_Free(arena);
     return ret;
@@ -969,7 +978,8 @@
       rb_raise(rb_eArgError, "Expected hash arguments.");
     }
 
-    VALUE depth = rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
+    VALUE depth =
+        rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
 
     if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
       options |= UPB_DECODE_MAXDEPTH(FIX2INT(depth));
@@ -983,9 +993,10 @@
   VALUE msg_rb = initialize_rb_class_with_no_args(klass);
   Message* msg = ruby_to_Message(msg_rb);
 
-  upb_DecodeStatus status = upb_Decode(
-      RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
-      upb_MessageDef_MiniTable(msg->msgdef), NULL, options, Arena_get(msg->arena));
+  upb_DecodeStatus status =
+      upb_Decode(RSTRING_PTR(data), RSTRING_LEN(data), (upb_Message*)msg->msg,
+                 upb_MessageDef_MiniTable(msg->msgdef), NULL, options,
+                 Arena_get(msg->arena));
 
   if (status != kUpb_DecodeStatus_Ok) {
     rb_raise(cParseError, "Error occurred during parsing");
@@ -1069,7 +1080,7 @@
 static VALUE Message_encode(int argc, VALUE* argv, VALUE klass) {
   Message* msg = ruby_to_Message(argv[0]);
   int options = 0;
-  const char* data;
+  char* data;
   size_t size;
 
   if (CLASS_OF(argv[0]) != klass) {
@@ -1085,19 +1096,21 @@
     if (TYPE(hash_args) != T_HASH) {
       rb_raise(rb_eArgError, "Expected hash arguments.");
     }
-    VALUE depth = rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
+    VALUE depth =
+        rb_hash_lookup(hash_args, ID2SYM(rb_intern("recursion_limit")));
 
     if (depth != Qnil && TYPE(depth) == T_FIXNUM) {
       options |= UPB_DECODE_MAXDEPTH(FIX2INT(depth));
     }
   }
 
-  upb_Arena *arena = upb_Arena_New();
+  upb_Arena* arena = upb_Arena_New();
 
-  data = upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef),
-                    options, arena, &size);
+  upb_EncodeStatus status =
+      upb_Encode(msg->msg, upb_MessageDef_MiniTable(msg->msgdef), options,
+                 arena, &data, &size);
 
-  if (data) {
+  if (status == kUpb_EncodeStatus_Ok) {
     VALUE ret = rb_str_new(data, size);
     rb_enc_associate(ret, rb_ascii8bit_encoding());
     upb_Arena_Free(arena);
@@ -1135,7 +1148,8 @@
   if (argc == 2) {
     VALUE hash_args = argv[1];
     if (TYPE(hash_args) != T_HASH) {
-      if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1, rb_str_new2("to_h")))) {
+      if (RTEST(rb_funcall(hash_args, rb_intern("respond_to?"), 1,
+                           rb_str_new2("to_h")))) {
         hash_args = rb_funcall(hash_args, rb_intern("to_h"), 0);
       } else {
         rb_raise(rb_eArgError, "Expected hash arguments.");
@@ -1201,36 +1215,8 @@
   klass = rb_define_class_id(
       // Docs say this parameter is ignored. User will assign return value to
       // their own toplevel constant class name.
-      rb_intern("Message"), rb_cObject);
+      rb_intern("Message"), cAbstractMessage);
   rb_ivar_set(klass, descriptor_instancevar_interned, descriptor);
-  rb_define_alloc_func(klass, Message_alloc);
-  rb_require("google/protobuf/message_exts");
-  rb_include_module(klass, rb_eval_string("::Google::Protobuf::MessageExts"));
-  rb_extend_object(
-      klass, rb_eval_string("::Google::Protobuf::MessageExts::ClassMethods"));
-
-  rb_define_method(klass, "method_missing", Message_method_missing, -1);
-  rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
-                   -1);
-  rb_define_method(klass, "initialize", Message_initialize, -1);
-  rb_define_method(klass, "dup", Message_dup, 0);
-  // Also define #clone so that we don't inherit Object#clone.
-  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);
-  rb_define_method(klass, "to_s", Message_inspect, 0);
-  rb_define_method(klass, "[]", Message_index, 1);
-  rb_define_method(klass, "[]=", Message_index_set, 2);
-  rb_define_singleton_method(klass, "decode", Message_decode, -1);
-  rb_define_singleton_method(klass, "encode", Message_encode, -1);
-  rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
-  rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
-  rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
-
   return klass;
 }
 
@@ -1316,7 +1302,7 @@
   return mod;
 }
 
-// Internal only; used by Google::Protobuf.deep_copy.
+// Internal to the library; used by Google::Protobuf.deep_copy.
 upb_Message* Message_deep_copy(const upb_Message* msg, const upb_MessageDef* m,
                                upb_Arena* arena) {
   // Serialize and parse.
@@ -1324,11 +1310,13 @@
   const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
   size_t size;
 
-  char* data = upb_Encode(msg, layout, 0, tmp_arena, &size);
-  upb_Message* new_msg = upb_Message_New(m, arena);
+  upb_Message* new_msg = upb_Message_New(layout, arena);
+  char* data;
 
-  if (!data || upb_Decode(data, size, new_msg, layout, NULL, 0, arena) !=
-                   kUpb_DecodeStatus_Ok) {
+  if (upb_Encode(msg, layout, 0, tmp_arena, &data, &size) !=
+          kUpb_EncodeStatus_Ok ||
+      upb_Decode(data, size, new_msg, layout, NULL, 0, arena) !=
+          kUpb_DecodeStatus_Ok) {
     upb_Arena_Free(tmp_arena);
     rb_raise(cParseError, "Error occurred copying proto");
   }
@@ -1355,7 +1343,8 @@
     switch (upb_MessageDef_WellKnownType(m)) {
       case kUpb_WellKnown_Timestamp: {
         // Time -> Google::Protobuf::Timestamp
-        upb_Message* msg = upb_Message_New(m, arena);
+        const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
+        upb_Message* msg = upb_Message_New(t, arena);
         upb_MessageValue sec, nsec;
         struct timespec time;
         const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
@@ -1372,7 +1361,8 @@
       }
       case kUpb_WellKnown_Duration: {
         // Numeric -> Google::Protobuf::Duration
-        upb_Message* msg = upb_Message_New(m, arena);
+        const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
+        upb_Message* msg = upb_Message_New(t, arena);
         upb_MessageValue sec, nsec;
         const upb_FieldDef* sec_f = upb_MessageDef_FindFieldByNumber(m, 1);
         const upb_FieldDef* nsec_f = upb_MessageDef_FindFieldByNumber(m, 2);
@@ -1399,11 +1389,42 @@
   return self->msg;
 }
 
+static void Message_define_class(VALUE klass) {
+  rb_define_alloc_func(klass, Message_alloc);
+
+  rb_require("google/protobuf/message_exts");
+  rb_define_method(klass, "method_missing", Message_method_missing, -1);
+  rb_define_method(klass, "respond_to_missing?", Message_respond_to_missing,
+                   -1);
+  rb_define_method(klass, "initialize", Message_initialize, -1);
+  rb_define_method(klass, "dup", Message_dup, 0);
+  // Also define #clone so that we don't inherit Object#clone.
+  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);
+  rb_define_method(klass, "to_s", Message_inspect, 0);
+  rb_define_method(klass, "[]", Message_index, 1);
+  rb_define_method(klass, "[]=", Message_index_set, 2);
+  rb_define_singleton_method(klass, "decode", Message_decode, -1);
+  rb_define_singleton_method(klass, "encode", Message_encode, -1);
+  rb_define_singleton_method(klass, "decode_json", Message_decode_json, -1);
+  rb_define_singleton_method(klass, "encode_json", Message_encode_json, -1);
+  rb_define_singleton_method(klass, "descriptor", Message_descriptor, 0);
+}
+
 void Message_register(VALUE protobuf) {
   cParseError = rb_const_get(protobuf, rb_intern("ParseError"));
+  cAbstractMessage =
+      rb_define_class_under(protobuf, "AbstractMessage", rb_cObject);
+  Message_define_class(cAbstractMessage);
+  rb_gc_register_address(&cAbstractMessage);
 
   // 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");
+  descriptor_instancevar_interned = rb_intern("@descriptor");
 }
diff --git a/ruby/ext/google/protobuf_c/ruby-upb.c b/ruby/ext/google/protobuf_c/ruby-upb.c
old mode 100755
new mode 100644
index d50bd99..430b39e
--- a/ruby/ext/google/protobuf_c/ruby-upb.c
+++ b/ruby/ext/google/protobuf_c/ruby-upb.c
@@ -1,37 +1,10 @@
 /* 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.
+ * This is where we define internal portability macros used across upb.
  *
- * All of these macros are undef'd in port_undef.inc to avoid leaking them to
- * users.
+ * All of these macros are undef'd in undef.inc to avoid leaking them to users.
  *
  * The correct usage is:
  *
@@ -39,25 +12,38 @@
  *   #include "upb/baz.h"
  *
  *   // MUST be last included header.
- *   #include "upb/port_def.inc"
+ *   #include "upb/port/def.inc"
  *
  *   // Code for this file.
  *   // <...>
  *
  *   // Can be omitted for .c files, required for .h.
- *   #include "upb/port_undef.inc"
+ *   #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(__cplusplus) && __cplusplus >= 201402L) ||           \
       (defined(_MSC_VER) && _MSC_VER >= 1900))
-#error upb requires C99 or C++11 or MSVC >= 2015.
+#error upb requires C99 or C++14 or MSVC >= 2015.
 #endif
 
-#include <stdint.h>
+// 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 UPB_GNUC_MIN(x, y) \
+  (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
+#else
+#define UPB_GNUC_MIN(x, y) 0
+#endif
+
+#include <assert.h>
+#include <setjmp.h>
+#include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
 
 #if UINTPTR_MAX == 0xffffffff
 #define UPB_SIZE(size32, size64) size32
@@ -70,11 +56,6 @@
  */
 #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;
@@ -90,21 +71,22 @@
 #define UPB_INLINE static
 #endif
 
+#define UPB_MALLOC_ALIGN 8
 #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_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN)
 #define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
 
-/* Hints to the compiler about likely/unlikely branches. */
+// 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)
+#define UPB_LIKELY(x) __builtin_expect((bool)(x), 1)
+#define UPB_UNLIKELY(x) __builtin_expect((bool)(x), 0)
 #else
 #define UPB_LIKELY(x) (x)
 #define UPB_UNLIKELY(x) (x)
 #endif
 
-/* Macros for function attributes on compilers that support them. */
+// Macros for function attributes on compilers that support them.
 #ifdef __GNUC__
 #define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
 #define UPB_NOINLINE __attribute__((noinline))
@@ -127,8 +109,7 @@
 
 #define UPB_UNUSED(var) (void)var
 
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
+// 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()
@@ -230,7 +211,11 @@
 
 #undef UPB_FASTTABLE_SUPPORTED
 
-/* ASAN poisoning (for arena) *************************************************/
+/* ASAN poisoning (for arena).
+ * If using UPB from an interpreted language like Ruby, a build of the
+ * interpreter compiled with ASAN enabled must be used in order to get sane and
+ * expected behavior.
+ */
 
 #if defined(__SANITIZE_ADDRESS__)
 #define UPB_ASAN 1
@@ -262,1835 +247,172 @@
 #define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0
 #endif
 
-/** upb/decode.c ************************************************************/
+#if defined(__cplusplus)
+#if defined(__clang__) || UPB_GNUC_MIN(6, 0)
+// https://gcc.gnu.org/gcc-6/changes.html
+#if __cplusplus >= 201402L
+#define UPB_DEPRECATED [[deprecated]]
+#else
+#define UPB_DEPRECATED __attribute__((deprecated))
+#endif
+#else
+#define UPB_DEPRECATED
+#endif
+#else
+#define UPB_DEPRECATED
+#endif
 
-#include <setjmp.h>
+
+#include <errno.h>
+#include <float.h>
+#include <stdarg.h>
+#include <stdlib.h>
 #include <string.h>
 
+// Must be last.
 
-/* 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_MASK = (1 << kUpb_FieldType_Float) |
-                                        (1 << kUpb_FieldType_Fixed32) |
-                                        (1 << kUpb_FieldType_SFixed32);
-
-static const unsigned FIXED64_OK_MASK = (1 << kUpb_FieldType_Double) |
-                                        (1 << kUpb_FieldType_Fixed64) |
-                                        (1 << kUpb_FieldType_SFixed64);
-
-/* Three fake field types for MessageSet. */
-#define TYPE_MSGSET_ITEM 19
-#define TYPE_MSGSET_TYPE_ID 20
-#define TYPE_COUNT 20
-
-/* Op: an action to be performed for a wire-type/field-type combination. */
-#define OP_UNKNOWN -1 /* Unknown field. */
-#define OP_MSGSET_ITEM -2
-#define OP_MSGSET_TYPEID -3
-#define OP_SCALAR_LG2(n) (n) /* n in [0, 2, 3] => op in [0, 2, 3] */
-#define OP_ENUM 1
-#define OP_STRING 4
-#define OP_BYTES 5
-#define OP_SUBMSG 6
-/* Scalar fields use only ops above. 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] */
-#define OP_PACKED_ENUM 13
-
-static const int8_t varint_ops[] = {
-    OP_UNKNOWN,       /* field not found */
-    OP_UNKNOWN,       /* DOUBLE */
-    OP_UNKNOWN,       /* FLOAT */
-    OP_SCALAR_LG2(3), /* INT64 */
-    OP_SCALAR_LG2(3), /* UINT64 */
-    OP_SCALAR_LG2(2), /* INT32 */
-    OP_UNKNOWN,       /* FIXED64 */
-    OP_UNKNOWN,       /* FIXED32 */
-    OP_SCALAR_LG2(0), /* BOOL */
-    OP_UNKNOWN,       /* STRING */
-    OP_UNKNOWN,       /* GROUP */
-    OP_UNKNOWN,       /* MESSAGE */
-    OP_UNKNOWN,       /* BYTES */
-    OP_SCALAR_LG2(2), /* UINT32 */
-    OP_ENUM,          /* ENUM */
-    OP_UNKNOWN,       /* SFIXED32 */
-    OP_UNKNOWN,       /* SFIXED64 */
-    OP_SCALAR_LG2(2), /* SINT32 */
-    OP_SCALAR_LG2(3), /* SINT64 */
-    OP_UNKNOWN,       /* MSGSET_ITEM */
-    OP_MSGSET_TYPEID, /* MSGSET TYPEID */
-};
-
-static const int8_t delim_ops[] = {
-    /* For non-repeated field type. */
-    OP_UNKNOWN, /* field not found */
-    OP_UNKNOWN, /* DOUBLE */
-    OP_UNKNOWN, /* FLOAT */
-    OP_UNKNOWN, /* INT64 */
-    OP_UNKNOWN, /* UINT64 */
-    OP_UNKNOWN, /* INT32 */
-    OP_UNKNOWN, /* FIXED64 */
-    OP_UNKNOWN, /* FIXED32 */
-    OP_UNKNOWN, /* BOOL */
-    OP_STRING,  /* STRING */
-    OP_UNKNOWN, /* GROUP */
-    OP_SUBMSG,  /* MESSAGE */
-    OP_BYTES,   /* BYTES */
-    OP_UNKNOWN, /* UINT32 */
-    OP_UNKNOWN, /* ENUM */
-    OP_UNKNOWN, /* SFIXED32 */
-    OP_UNKNOWN, /* SFIXED64 */
-    OP_UNKNOWN, /* SINT32 */
-    OP_UNKNOWN, /* SINT64 */
-    OP_UNKNOWN, /* MSGSET_ITEM */
-    OP_UNKNOWN, /* MSGSET TYPEID */
-    /* 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_PACKED_ENUM,   /* 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 */
-    /* Omitting MSGSET_*, because we never emit a repeated msgset type */
-};
-
-typedef union {
-  bool bool_val;
-  uint32_t uint32_val;
-  uint64_t uint64_val;
-  uint32_t size;
-} wireval;
-
-static const char* decode_msg(upb_Decoder* d, const char* ptr, upb_Message* msg,
-                              const upb_MiniTable* layout);
-
-UPB_NORETURN static void* decode_err(upb_Decoder* d, upb_DecodeStatus status) {
-  assert(status != kUpb_DecodeStatus_Ok);
-  UPB_LONGJMP(d->err, status);
+void upb_Status_Clear(upb_Status* status) {
+  if (!status) return;
+  status->ok = true;
+  status->msg[0] = '\0';
 }
 
-const char* fastdecode_err(upb_Decoder* d, int status) {
-  assert(status != kUpb_DecodeStatus_Ok);
-  UPB_LONGJMP(d->err, status);
-  return NULL;
-}
-static void decode_verifyutf8(upb_Decoder* d, const char* buf, int len) {
-  if (!decode_verifyutf8_inl(buf, len))
-    decode_err(d, kUpb_DecodeStatus_BadUtf8);
+bool upb_Status_IsOk(const upb_Status* status) { return status->ok; }
+
+const char* upb_Status_ErrorMessage(const upb_Status* status) {
+  return status->msg;
 }
 
-static bool decode_reserve(upb_Decoder* 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, kUpb_DecodeStatus_OutOfMemory);
-  }
-  return need_realloc;
+void upb_Status_SetErrorMessage(upb_Status* status, const char* msg) {
+  if (!status) return;
+  status->ok = false;
+  strncpy(status->msg, msg, _kUpb_Status_MaxMessage - 1);
+  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
 }
 
-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;
+void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...) {
+  va_list args;
+  va_start(args, fmt);
+  upb_Status_VSetErrorFormat(status, fmt, args);
+  va_end(args);
 }
 
-UPB_FORCEINLINE
-static const char* decode_varint64(upb_Decoder* 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) return decode_err(d, kUpb_DecodeStatus_Malformed);
-    *val = res.val;
-    return res.ptr;
-  }
+void upb_Status_VSetErrorFormat(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[_kUpb_Status_MaxMessage - 1] = '\0';
 }
 
-UPB_FORCEINLINE
-static const char* decode_tag(upb_Decoder* 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);
-    if (!res.ptr || res.ptr - start > 5 || res.val > UINT32_MAX) {
-      return decode_err(d, kUpb_DecodeStatus_Malformed);
-    }
-    *val = res.val;
-    return res.ptr;
-  }
-}
-
-static void decode_munge_int32(wireval* val) {
-  if (!_upb_IsLittleEndian()) {
-    /* The next stage will memcpy(dst, &val, 4) */
-    val->uint32_val = val->uint64_val;
-  }
-}
-
-static void decode_munge(int type, wireval* val) {
-  switch (type) {
-    case kUpb_FieldType_Bool:
-      val->bool_val = val->uint64_val != 0;
-      break;
-    case kUpb_FieldType_SInt32: {
-      uint32_t n = val->uint64_val;
-      val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
-      break;
-    }
-    case kUpb_FieldType_SInt64: {
-      uint64_t n = val->uint64_val;
-      val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
-      break;
-    }
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_UInt32:
-    case kUpb_FieldType_Enum:
-      decode_munge_int32(val);
-      break;
-  }
-}
-
-static upb_Message* decode_newsubmsg(upb_Decoder* d,
-                                     const upb_MiniTable_Sub* subs,
-                                     const upb_MiniTable_Field* field) {
-  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
-  return _upb_Message_New_inl(subl, &d->arena);
-}
-
-UPB_NOINLINE
-const char* decode_isdonefallback(upb_Decoder* d, const char* ptr,
-                                  int overrun) {
-  int status;
-  ptr = decode_isdonefallback_inl(d, ptr, overrun, &status);
-  if (ptr == NULL) {
-    return decode_err(d, status);
-  }
-  return ptr;
-}
-
-static const char* decode_readstr(upb_Decoder* d, const char* ptr, int size,
-                                  upb_StringView* str) {
-  if (d->options & kUpb_DecodeOption_AliasString) {
-    str->data = ptr;
-  } else {
-    char* data = upb_Arena_Malloc(&d->arena, size);
-    if (!data) return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    memcpy(data, ptr, size);
-    str->data = data;
-  }
-  str->size = size;
-  return ptr + size;
-}
-
-UPB_FORCEINLINE
-static const char* decode_tosubmsg2(upb_Decoder* d, const char* ptr,
-                                    upb_Message* submsg,
-                                    const upb_MiniTable* subl, int size) {
-  int saved_delta = decode_pushlimit(d, ptr, size);
-  if (--d->depth < 0) return decode_err(d, kUpb_DecodeStatus_MaxDepthExceeded);
-  ptr = decode_msg(d, ptr, submsg, subl);
-  if (d->end_group != DECODE_NOGROUP)
-    return decode_err(d, kUpb_DecodeStatus_Malformed);
-  decode_poplimit(d, ptr, saved_delta);
-  d->depth++;
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_tosubmsg(upb_Decoder* d, const char* ptr,
-                                   upb_Message* submsg,
-                                   const upb_MiniTable_Sub* subs,
-                                   const upb_MiniTable_Field* field, int size) {
-  return decode_tosubmsg2(d, ptr, submsg, subs[field->submsg_index].submsg,
-                          size);
-}
-
-UPB_FORCEINLINE
-static const char* decode_group(upb_Decoder* d, const char* ptr,
-                                upb_Message* submsg, const upb_MiniTable* subl,
-                                uint32_t number) {
-  if (--d->depth < 0) return decode_err(d, kUpb_DecodeStatus_MaxDepthExceeded);
-  if (decode_isdone(d, &ptr)) {
-    return decode_err(d, kUpb_DecodeStatus_Malformed);
-  }
-  ptr = decode_msg(d, ptr, submsg, subl);
-  if (d->end_group != number) return decode_err(d, kUpb_DecodeStatus_Malformed);
-  d->end_group = DECODE_NOGROUP;
-  d->depth++;
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_togroup(upb_Decoder* d, const char* ptr,
-                                  upb_Message* submsg,
-                                  const upb_MiniTable_Sub* subs,
-                                  const upb_MiniTable_Field* field) {
-  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
-  return decode_group(d, ptr, submsg, subl, field->number);
-}
-
-static char* encode_varint32(uint32_t val, char* ptr) {
-  do {
-    uint8_t byte = val & 0x7fU;
-    val >>= 7;
-    if (val) byte |= 0x80U;
-    *(ptr++) = byte;
-  } while (val);
-  return ptr;
-}
-
-static void upb_Decode_AddUnknownVarints(upb_Decoder* d, upb_Message* msg,
-                                         uint32_t val1, uint32_t val2) {
-  char buf[20];
-  char* end = buf;
-  end = encode_varint32(val1, end);
-  end = encode_varint32(val2, end);
-
-  if (!_upb_Message_AddUnknown(msg, buf, end - buf, &d->arena)) {
-    decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-  }
-}
-
-UPB_NOINLINE
-static bool decode_checkenum_slow(upb_Decoder* d, const char* ptr,
-                                  upb_Message* msg, const upb_MiniTable_Enum* e,
-                                  const upb_MiniTable_Field* field,
-                                  uint32_t v) {
-  // OPT: binary search long lists?
-  int n = e->value_count;
-  for (int i = 0; i < n; i++) {
-    if ((uint32_t)e->values[i] == v) return true;
-  }
-
-  // Unrecognized enum goes into unknown fields.
-  // For packed fields the tag could be arbitrarily far in the past, so we
-  // just re-encode the tag and value here.
-  uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Varint;
-  upb_Decode_AddUnknownVarints(d, msg, tag, v);
-  return false;
-}
-
-UPB_FORCEINLINE
-static bool decode_checkenum(upb_Decoder* d, const char* ptr, upb_Message* msg,
-                             const upb_MiniTable_Enum* e,
-                             const upb_MiniTable_Field* field, wireval* val) {
-  uint32_t v = val->uint32_val;
-
-  if (UPB_LIKELY(v < 64) && UPB_LIKELY(((1ULL << v) & e->mask))) return true;
-
-  return decode_checkenum_slow(d, ptr, msg, e, field, v);
-}
-
-UPB_NOINLINE
-static const char* decode_enum_toarray(upb_Decoder* d, const char* ptr,
-                                       upb_Message* msg, upb_Array* arr,
-                                       const upb_MiniTable_Sub* subs,
-                                       const upb_MiniTable_Field* field,
-                                       wireval* val) {
-  const upb_MiniTable_Enum* e = subs[field->submsg_index].subenum;
-  if (!decode_checkenum(d, ptr, msg, e, field, val)) return ptr;
-  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len * 4, void);
-  arr->len++;
-  memcpy(mem, val, 4);
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_fixed_packed(upb_Decoder* d, const char* ptr,
-                                       upb_Array* arr, wireval* val,
-                                       const upb_MiniTable_Field* field,
-                                       int lg2) {
-  int mask = (1 << lg2) - 1;
-  size_t count = val->size >> lg2;
-  if ((val->size & mask) != 0) {
-    // Length isn't a round multiple of elem size.
-    return decode_err(d, kUpb_DecodeStatus_Malformed);
-  }
-  decode_reserve(d, arr, count);
-  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->len << lg2, void);
-  arr->len += count;
-  // Note: if/when the decoder supports multi-buffer input, we will need to
-  // handle buffer seams here.
-  if (_upb_IsLittleEndian()) {
-    memcpy(mem, ptr, val->size);
-    ptr += val->size;
-  } else {
-    const char* end = ptr + val->size;
-    char* dst = mem;
-    while (ptr < end) {
-      if (lg2 == 2) {
-        uint32_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap32(val);
-        memcpy(dst, &val, sizeof(val));
-      } else {
-        UPB_ASSERT(lg2 == 3);
-        uint64_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap64(val);
-        memcpy(dst, &val, sizeof(val));
-      }
-      ptr += 1 << lg2;
-      dst += 1 << lg2;
-    }
-  }
-
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static const char* decode_varint_packed(upb_Decoder* d, const char* ptr,
-                                        upb_Array* arr, wireval* val,
-                                        const upb_MiniTable_Field* field,
-                                        int lg2) {
-  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;
-}
-
-UPB_NOINLINE
-static const char* decode_enum_packed(upb_Decoder* d, const char* ptr,
-                                      upb_Message* msg, upb_Array* arr,
-                                      const upb_MiniTable_Sub* subs,
-                                      const upb_MiniTable_Field* field,
-                                      wireval* val) {
-  const upb_MiniTable_Enum* e = subs[field->submsg_index].subenum;
-  int saved_limit = decode_pushlimit(d, ptr, val->size);
-  char* out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len * 4, void);
-  while (!decode_isdone(d, &ptr)) {
-    wireval elem;
-    ptr = decode_varint64(d, ptr, &elem.uint64_val);
-    decode_munge_int32(&elem);
-    if (!decode_checkenum(d, ptr, msg, e, field, &elem)) {
-      continue;
-    }
-    if (decode_reserve(d, arr, 1)) {
-      out = UPB_PTR_AT(_upb_array_ptr(arr), arr->len * 4, void);
-    }
-    arr->len++;
-    memcpy(out, &elem, 4);
-    out += 4;
-  }
-  decode_poplimit(d, ptr, saved_limit);
-  return ptr;
-}
-
-static const char* decode_toarray(upb_Decoder* d, const char* ptr,
-                                  upb_Message* msg,
-                                  const upb_MiniTable_Sub* subs,
-                                  const upb_MiniTable_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) return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    *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_StringView* str = (upb_StringView*)_upb_array_ptr(arr) + arr->len;
-      arr->len++;
-      return decode_readstr(d, ptr, val->size, str);
-    }
-    case OP_SUBMSG: {
-      /* Append submessage / group. */
-      upb_Message* submsg = decode_newsubmsg(d, subs, field);
-      *UPB_PTR_AT(_upb_array_ptr(arr), arr->len * sizeof(void*), upb_Message*) =
-          submsg;
-      arr->len++;
-      if (UPB_UNLIKELY(field->descriptortype == kUpb_FieldType_Group)) {
-        return decode_togroup(d, ptr, submsg, subs, field);
-      } else {
-        return decode_tosubmsg(d, ptr, submsg, subs, field, val->size);
-      }
-    }
-    case OP_FIXPCK_LG2(2):
-    case OP_FIXPCK_LG2(3):
-      return decode_fixed_packed(d, ptr, arr, val, field,
-                                 op - OP_FIXPCK_LG2(0));
-    case OP_VARPCK_LG2(0):
-    case OP_VARPCK_LG2(2):
-    case OP_VARPCK_LG2(3):
-      return decode_varint_packed(d, ptr, arr, val, field,
-                                  op - OP_VARPCK_LG2(0));
-    case OP_ENUM:
-      return decode_enum_toarray(d, ptr, msg, arr, subs, field, val);
-    case OP_PACKED_ENUM:
-      return decode_enum_packed(d, ptr, msg, arr, subs, field, val);
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-static const char* decode_tomap(upb_Decoder* d, const char* ptr,
-                                upb_Message* msg, const upb_MiniTable_Sub* subs,
-                                const upb_MiniTable_Field* field,
-                                wireval* val) {
-  upb_Map** map_p = UPB_PTR_AT(msg, field->offset, upb_Map*);
-  upb_Map* map = *map_p;
-  upb_MapEntry ent;
-  const upb_MiniTable* entry = subs[field->submsg_index].submsg;
-
-  if (!map) {
-    /* Lazily create map. */
-    const upb_MiniTable_Field* key_field = &entry->fields[0];
-    const upb_MiniTable_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_StringView));
-    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 == kUpb_FieldType_Message ||
-      entry->fields[1].descriptortype == kUpb_FieldType_Group) {
-    /* Create proactively to handle the case where it doesn't appear. */
-    ent.v.val =
-        upb_value_ptr(_upb_Message_New(entry->subs[0].submsg, &d->arena));
-  }
-
-  const char* start = ptr;
-  ptr = decode_tosubmsg(d, ptr, &ent.k, subs, field, val->size);
-  // check if ent had any unknown fields
-  size_t size;
-  upb_Message_GetUnknown(&ent.k, &size);
-  if (size != 0) {
-    uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Delimited;
-    upb_Decode_AddUnknownVarints(d, msg, tag, (uint32_t)(ptr - start));
-    if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
-      decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    }
-  } else {
-    _upb_Map_Set(map, &ent.k, map->key_size, &ent.v, map->val_size, &d->arena);
-  }
-  return ptr;
-}
-
-static const char* decode_tomsg(upb_Decoder* d, const char* ptr,
-                                upb_Message* msg, const upb_MiniTable_Sub* subs,
-                                const upb_MiniTable_Field* field, wireval* val,
-                                int op) {
-  void* mem = UPB_PTR_AT(msg, field->offset, void);
-  int type = field->descriptortype;
-
-  if (UPB_UNLIKELY(op == OP_ENUM) &&
-      !decode_checkenum(d, ptr, msg, subs[field->submsg_index].subenum, field,
-                        val)) {
-    return ptr;
-  }
-
-  /* Set presence if necessary. */
-  if (field->presence > 0) {
-    _upb_sethas_field(msg, field);
-  } else 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;
-  }
-
-  /* Store into message. */
-  switch (op) {
-    case OP_SUBMSG: {
-      upb_Message** submsgp = mem;
-      upb_Message* submsg = *submsgp;
-      if (!submsg) {
-        submsg = decode_newsubmsg(d, subs, field);
-        *submsgp = submsg;
-      }
-      if (UPB_UNLIKELY(type == kUpb_FieldType_Group)) {
-        ptr = decode_togroup(d, ptr, submsg, subs, field);
-      } else {
-        ptr = decode_tosubmsg(d, ptr, submsg, subs, 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_ENUM:
-    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_NOINLINE
-const char* decode_checkrequired(upb_Decoder* d, const char* ptr,
-                                 const upb_Message* msg,
-                                 const upb_MiniTable* l) {
-  assert(l->required_count);
-  if (UPB_LIKELY((d->options & kUpb_DecodeOption_CheckRequired) == 0)) {
-    return ptr;
-  }
-  uint64_t msg_head;
-  memcpy(&msg_head, msg, 8);
-  msg_head = _upb_BigEndian_Swap64(msg_head);
-  if (upb_MiniTable_requiredmask(l) & ~msg_head) {
-    d->missing_required = true;
-  }
-  return ptr;
-}
-
-UPB_FORCEINLINE
-static bool decode_tryfastdispatch(upb_Decoder* d, const char** ptr,
-                                   upb_Message* msg,
-                                   const upb_MiniTable* 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;
-}
-
-static const char* decode_msgset(upb_Decoder* d, const char* ptr,
-                                 upb_Message* msg,
-                                 const upb_MiniTable* layout) {
-  // We create a temporary upb_MiniTable here and abuse its fields as temporary
-  // storage, to avoid creating lots of MessageSet-specific parsing code-paths:
-  //   1. We store 'layout' in item_layout.subs.  We will need this later as
-  //      a key to look up extensions for this MessageSet.
-  //   2. We use item_layout.fields as temporary storage to store the extension
-  //   we
-  //      found when parsing the type id.
-  upb_MiniTable item_layout = {
-      .subs = (const upb_MiniTable_Sub[]){{.submsg = layout}},
-      .fields = NULL,
-      .size = 0,
-      .field_count = 0,
-      .ext = kUpb_ExtMode_IsMessageSet_ITEM,
-      .dense_below = 0,
-      .table_mask = -1};
-  return decode_group(d, ptr, msg, &item_layout, 1);
-}
-
-static const upb_MiniTable_Field* decode_findfield(upb_Decoder* d,
-                                                   const upb_MiniTable* l,
-                                                   uint32_t field_number,
-                                                   int* last_field_index) {
-  static upb_MiniTable_Field none = {0, 0, 0, 0, 0, 0};
-  if (l == NULL) return &none;
-
-  size_t idx = ((size_t)field_number) - 1;  // 0 wraps to SIZE_MAX
-  if (idx < l->dense_below) {
-    /* Fastest case: index into dense fields. */
-    goto found;
-  }
-
-  if (l->dense_below < l->field_count) {
-    /* Linear search non-dense fields. Resume scanning from last_field_index
-     * since fields are usually in order. */
-    int last = *last_field_index;
-    for (idx = last; idx < l->field_count; idx++) {
-      if (l->fields[idx].number == field_number) {
-        goto found;
-      }
-    }
-
-    for (idx = l->dense_below; idx < last; idx++) {
-      if (l->fields[idx].number == field_number) {
-        goto found;
-      }
-    }
-  }
-
-  if (d->extreg) {
-    switch (l->ext) {
-      case kUpb_ExtMode_Extendable: {
-        const upb_MiniTable_Extension* ext =
-            _upb_extreg_get(d->extreg, l, field_number);
-        if (ext) return &ext->field;
-        break;
-      }
-      case kUpb_ExtMode_IsMessageSet:
-        if (field_number == _UPB_MSGSET_ITEM) {
-          static upb_MiniTable_Field item = {0, 0, 0, 0, TYPE_MSGSET_ITEM, 0};
-          return &item;
-        }
-        break;
-      case kUpb_ExtMode_IsMessageSet_ITEM:
-        switch (field_number) {
-          case _UPB_MSGSET_TYPEID: {
-            static upb_MiniTable_Field type_id = {
-                0, 0, 0, 0, TYPE_MSGSET_TYPE_ID, 0};
-            return &type_id;
-          }
-          case _UPB_MSGSET_MESSAGE:
-            if (l->fields) {
-              // We saw type_id previously and succeeded in looking up msg.
-              return l->fields;
-            } else {
-              // TODO: out of order MessageSet.
-              // This is a very rare case: all serializers will emit in-order
-              // MessageSets.  To hit this case there has to be some kind of
-              // re-ordering proxy.  We should eventually handle this case, but
-              // not today.
-            }
-            break;
-        }
-    }
-  }
-
-  return &none; /* Unknown field. */
-
-found:
-  UPB_ASSERT(l->fields[idx].number == field_number);
-  *last_field_index = idx;
-  return &l->fields[idx];
-}
-
-UPB_FORCEINLINE
-static const char* decode_wireval(upb_Decoder* d, const char* ptr,
-                                  const upb_MiniTable_Field* field,
-                                  int wire_type, wireval* val, int* op) {
-  switch (wire_type) {
-    case kUpb_WireType_Varint:
-      ptr = decode_varint64(d, ptr, &val->uint64_val);
-      *op = varint_ops[field->descriptortype];
-      decode_munge(field->descriptortype, val);
-      return ptr;
-    case kUpb_WireType_32Bit:
-      memcpy(&val->uint32_val, ptr, 4);
-      val->uint32_val = _upb_BigEndian_Swap32(val->uint32_val);
-      *op = OP_SCALAR_LG2(2);
-      if (((1 << field->descriptortype) & FIXED32_OK_MASK) == 0) {
-        *op = OP_UNKNOWN;
-      }
-      return ptr + 4;
-    case kUpb_WireType_64Bit:
-      memcpy(&val->uint64_val, ptr, 8);
-      val->uint64_val = _upb_BigEndian_Swap64(val->uint64_val);
-      *op = OP_SCALAR_LG2(3);
-      if (((1 << field->descriptortype) & FIXED64_OK_MASK) == 0) {
-        *op = OP_UNKNOWN;
-      }
-      return ptr + 8;
-    case kUpb_WireType_Delimited: {
-      int ndx = field->descriptortype;
-      uint64_t size;
-      if (upb_FieldMode_Get(field) == kUpb_FieldMode_Array) ndx += TYPE_COUNT;
-      ptr = decode_varint64(d, ptr, &size);
-      if (size >= INT32_MAX || ptr - d->end + (int32_t)size > d->limit) {
-        break; /* Length overflow. */
-      }
-      *op = delim_ops[ndx];
-      val->size = size;
-      return ptr;
-    }
-    case kUpb_WireType_StartGroup:
-      val->uint32_val = field->number;
-      if (field->descriptortype == kUpb_FieldType_Group) {
-        *op = OP_SUBMSG;
-      } else if (field->descriptortype == TYPE_MSGSET_ITEM) {
-        *op = OP_MSGSET_ITEM;
-      } else {
-        *op = OP_UNKNOWN;
-      }
-      return ptr;
-    default:
-      break;
-  }
-  return decode_err(d, kUpb_DecodeStatus_Malformed);
-}
-
-UPB_FORCEINLINE
-static const char* decode_known(upb_Decoder* d, const char* ptr,
-                                upb_Message* msg, const upb_MiniTable* layout,
-                                const upb_MiniTable_Field* field, int op,
-                                wireval* val) {
-  const upb_MiniTable_Sub* subs = layout->subs;
-  uint8_t mode = field->mode;
-
-  if (UPB_UNLIKELY(mode & kUpb_LabelFlags_IsExtension)) {
-    const upb_MiniTable_Extension* ext_layout =
-        (const upb_MiniTable_Extension*)field;
-    upb_Message_Extension* ext =
-        _upb_Message_Getorcreateext(msg, ext_layout, &d->arena);
-    if (UPB_UNLIKELY(!ext)) return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    msg = &ext->data;
-    subs = &ext->ext->sub;
-  }
-
-  switch (mode & kUpb_FieldMode_Mask) {
-    case kUpb_FieldMode_Array:
-      return decode_toarray(d, ptr, msg, subs, field, val, op);
-    case kUpb_FieldMode_Map:
-      return decode_tomap(d, ptr, msg, subs, field, val);
-    case kUpb_FieldMode_Scalar:
-      return decode_tomsg(d, ptr, msg, subs, field, val, op);
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-static const char* decode_reverse_skip_varint(const char* ptr, uint32_t val) {
-  uint32_t seen = 0;
-  do {
-    ptr--;
-    seen <<= 7;
-    seen |= *ptr & 0x7f;
-  } while (seen != val);
-  return ptr;
-}
-
-static const char* decode_unknown(upb_Decoder* d, const char* ptr,
-                                  upb_Message* msg, int field_number,
-                                  int wire_type, wireval val) {
-  if (field_number == 0) return decode_err(d, kUpb_DecodeStatus_Malformed);
-
-  // Since unknown fields are the uncommon case, we do a little extra work here
-  // to walk backwards through the buffer to find the field start.  This frees
-  // up a register in the fast paths (when the field is known), which leads to
-  // significant speedups in benchmarks.
-  const char* start = ptr;
-
-  if (wire_type == kUpb_WireType_Delimited) ptr += val.size;
-  if (msg) {
-    switch (wire_type) {
-      case kUpb_WireType_Varint:
-      case kUpb_WireType_Delimited:
-        start--;
-        while (start[-1] & 0x80) start--;
-        break;
-      case kUpb_WireType_32Bit:
-        start -= 4;
-        break;
-      case kUpb_WireType_64Bit:
-        start -= 8;
-        break;
-      default:
-        break;
-    }
-
-    assert(start == d->debug_valstart);
-    uint32_t tag = ((uint32_t)field_number << 3) | wire_type;
-    start = decode_reverse_skip_varint(start, tag);
-    assert(start == d->debug_tagstart);
-
-    if (wire_type == kUpb_WireType_StartGroup) {
-      d->unknown = start;
-      d->unknown_msg = msg;
-      ptr = decode_group(d, ptr, NULL, NULL, field_number);
-      start = d->unknown;
-      d->unknown_msg = NULL;
-      d->unknown = NULL;
-    }
-    if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
-      return decode_err(d, kUpb_DecodeStatus_OutOfMemory);
-    }
-  } else if (wire_type == kUpb_WireType_StartGroup) {
-    ptr = decode_group(d, ptr, NULL, NULL, field_number);
-  }
-  return ptr;
-}
-
-UPB_NOINLINE
-static const char* decode_msg(upb_Decoder* d, const char* ptr, upb_Message* msg,
-                              const upb_MiniTable* layout) {
-  int last_field_index = 0;
-
-#if UPB_FASTTABLE
-  // The first time we want to skip fast dispatch, because we may have just been
-  // invoked by the fast parser to handle a case that it bailed on.
-  if (!decode_isdone(d, &ptr)) goto nofast;
-#endif
-
-  while (!decode_isdone(d, &ptr)) {
-    uint32_t tag;
-    const upb_MiniTable_Field* field;
-    int field_number;
-    int wire_type;
-    wireval val;
-    int op;
-
-    if (decode_tryfastdispatch(d, &ptr, msg, layout)) break;
-
-#if UPB_FASTTABLE
-  nofast:
-#endif
-
-#ifndef NDEBUG
-    d->debug_tagstart = ptr;
-#endif
-
-    UPB_ASSERT(ptr < d->limit_ptr);
-    ptr = decode_tag(d, ptr, &tag);
-    field_number = tag >> 3;
-    wire_type = tag & 7;
-
-#ifndef NDEBUG
-    d->debug_valstart = ptr;
-#endif
-
-    if (wire_type == kUpb_WireType_EndGroup) {
-      d->end_group = field_number;
-      return ptr;
-    }
-
-    field = decode_findfield(d, layout, field_number, &last_field_index);
-    ptr = decode_wireval(d, ptr, field, wire_type, &val, &op);
-
-    if (op >= 0) {
-      ptr = decode_known(d, ptr, msg, layout, field, op, &val);
-    } else {
-      switch (op) {
-        case OP_UNKNOWN:
-          ptr = decode_unknown(d, ptr, msg, field_number, wire_type, val);
-          break;
-        case OP_MSGSET_ITEM:
-          ptr = decode_msgset(d, ptr, msg, layout);
-          break;
-        case OP_MSGSET_TYPEID: {
-          const upb_MiniTable_Extension* ext = _upb_extreg_get(
-              d->extreg, layout->subs[0].submsg, val.uint64_val);
-          if (ext) ((upb_MiniTable*)layout)->fields = &ext->field;
-          break;
-        }
-      }
-    }
-  }
-
-  return UPB_UNLIKELY(layout && layout->required_count)
-             ? decode_checkrequired(d, ptr, msg, layout)
-             : ptr;
-}
-
-const char* fastdecode_generic(struct upb_Decoder* d, const char* ptr,
-                               upb_Message* 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 upb_DecodeStatus decode_top(struct upb_Decoder* d, const char* buf,
-                                   void* msg, const upb_MiniTable* l) {
-  if (!decode_tryfastdispatch(d, &buf, msg, l)) {
-    decode_msg(d, buf, msg, l);
-  }
-  if (d->end_group != DECODE_NOGROUP) return kUpb_DecodeStatus_Malformed;
-  if (d->missing_required) return kUpb_DecodeStatus_MissingRequired;
-  return kUpb_DecodeStatus_Ok;
-}
-
-upb_DecodeStatus upb_Decode(const char* buf, size_t size, void* msg,
-                            const upb_MiniTable* l,
-                            const upb_ExtensionRegistry* extreg, int options,
-                            upb_Arena* arena) {
-  upb_Decoder state;
-  unsigned depth = (unsigned)options >> 16;
-
-  if (size <= 16) {
-    memset(&state.patch, 0, 32);
-    if (size) memcpy(&state.patch, buf, size);
-    buf = state.patch;
-    state.end = buf + size;
-    state.limit = 0;
-    options &= ~kUpb_DecodeOption_AliasString;  // Can't alias patch buf.
-  } else {
-    state.end = buf + size - 16;
-    state.limit = 16;
-  }
-
-  state.extreg = extreg;
-  state.limit_ptr = state.end;
-  state.unknown_msg = NULL;
-  state.depth = depth ? depth : 64;
-  state.end_group = DECODE_NOGROUP;
-  state.options = (uint16_t)options;
-  state.missing_required = false;
-  state.arena.head = arena->head;
-  state.arena.last_size = arena->last_size;
-  state.arena.cleanup_metadata = arena->cleanup_metadata;
-  state.arena.parent = arena;
-
-  upb_DecodeStatus status = UPB_SETJMP(state.err);
-  if (UPB_LIKELY(status == kUpb_DecodeStatus_Ok)) {
-    status = 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 status;
-}
-
-#undef OP_UNKNOWN
-#undef OP_SKIP
-#undef OP_SCALAR_LG2
-#undef OP_FIXPCK_LG2
-#undef OP_VARPCK_LG2
-#undef OP_STRING
-#undef OP_BYTES
-#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_BigEndian_Swap64(val);
-  encode_bytes(e, &val, sizeof(uint64_t));
-}
-
-static void encode_fixed32(upb_encstate* e, uint32_t val) {
-  val = _upb_BigEndian_Swap32(val);
-  encode_bytes(e, &val, sizeof(uint32_t));
-}
-
-UPB_NOINLINE
-static void encode_longvarint(upb_encstate* e, uint64_t val) {
+void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
+                                   va_list args) {
   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;
+  if (!status) return;
+  status->ok = false;
+  len = strlen(status->msg);
+  vsnprintf(status->msg + len, sizeof(status->msg) - len, fmt, args);
+  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
 }
 
-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);
-  }
+#include <string.h>
+
+
+// Must be last.
+
+static const char _upb_CTypeo_sizelg2[12] = {
+    0,
+    0,              /* kUpb_CType_Bool */
+    2,              /* kUpb_CType_Float */
+    2,              /* kUpb_CType_Int32 */
+    2,              /* kUpb_CType_UInt32 */
+    2,              /* kUpb_CType_Enum */
+    UPB_SIZE(2, 3), /* kUpb_CType_Message */
+    3,              /* kUpb_CType_Double */
+    3,              /* kUpb_CType_Int64 */
+    3,              /* kUpb_CType_UInt64 */
+    UPB_SIZE(3, 4), /* kUpb_CType_String */
+    UPB_SIZE(3, 4), /* kUpb_CType_Bytes */
+};
+
+upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) {
+  return _upb_Array_New(a, 4, _upb_CTypeo_sizelg2[type]);
 }
 
-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);
-}
+size_t upb_Array_Size(const upb_Array* arr) { return arr->size; }
 
-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;
+upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) {
+  upb_MessageValue ret;
   const char* data = _upb_array_constptr(arr);
-  const char* ptr = data + bytes - elem_size;
-
-  if (tag || !_upb_IsLittleEndian()) {
-    while (true) {
-      if (elem_size == 4) {
-        uint32_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap32(val);
-        encode_bytes(e, &val, elem_size);
-      } else {
-        UPB_ASSERT(elem_size == 8);
-        uint64_t val;
-        memcpy(&val, ptr, sizeof(val));
-        val = _upb_BigEndian_Swap64(val);
-        encode_bytes(e, &val, elem_size);
-      }
-
-      if (tag) 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 upb_Message* msg,
-                           const upb_MiniTable* m, size_t* size);
-
-static void encode_scalar(upb_encstate* e, const void* _field_mem,
-                          const upb_MiniTable_Sub* subs,
-                          const upb_MiniTable_Field* f) {
-  const char* field_mem = _field_mem;
-  int wire_type;
-
-#define CASE(ctype, type, wtype, encodeval) \
-  {                                         \
-    ctype val = *(ctype*)field_mem;         \
-    encode_##type(e, encodeval);            \
-    wire_type = wtype;                      \
-    break;                                  \
-  }
-
-  switch (f->descriptortype) {
-    case kUpb_FieldType_Double:
-      CASE(double, double, kUpb_WireType_64Bit, val);
-    case kUpb_FieldType_Float:
-      CASE(float, float, kUpb_WireType_32Bit, val);
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_UInt64:
-      CASE(uint64_t, varint, kUpb_WireType_Varint, val);
-    case kUpb_FieldType_UInt32:
-      CASE(uint32_t, varint, kUpb_WireType_Varint, val);
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_Enum:
-      CASE(int32_t, varint, kUpb_WireType_Varint, (int64_t)val);
-    case kUpb_FieldType_SFixed64:
-    case kUpb_FieldType_Fixed64:
-      CASE(uint64_t, fixed64, kUpb_WireType_64Bit, val);
-    case kUpb_FieldType_Fixed32:
-    case kUpb_FieldType_SFixed32:
-      CASE(uint32_t, fixed32, kUpb_WireType_32Bit, val);
-    case kUpb_FieldType_Bool:
-      CASE(bool, varint, kUpb_WireType_Varint, val);
-    case kUpb_FieldType_SInt32:
-      CASE(int32_t, varint, kUpb_WireType_Varint, encode_zz32(val));
-    case kUpb_FieldType_SInt64:
-      CASE(int64_t, varint, kUpb_WireType_Varint, encode_zz64(val));
-    case kUpb_FieldType_String:
-    case kUpb_FieldType_Bytes: {
-      upb_StringView view = *(upb_StringView*)field_mem;
-      encode_bytes(e, view.data, view.size);
-      encode_varint(e, view.size);
-      wire_type = kUpb_WireType_Delimited;
-      break;
-    }
-    case kUpb_FieldType_Group: {
-      size_t size;
-      void* submsg = *(void**)field_mem;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      if (submsg == NULL) {
-        return;
-      }
-      if (--e->depth == 0) encode_err(e);
-      encode_tag(e, f->number, kUpb_WireType_EndGroup);
-      encode_message(e, submsg, subm, &size);
-      wire_type = kUpb_WireType_StartGroup;
-      e->depth++;
-      break;
-    }
-    case kUpb_FieldType_Message: {
-      size_t size;
-      void* submsg = *(void**)field_mem;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      if (submsg == NULL) {
-        return;
-      }
-      if (--e->depth == 0) encode_err(e);
-      encode_message(e, submsg, subm, &size);
-      encode_varint(e, size);
-      wire_type = kUpb_WireType_Delimited;
-      e->depth++;
-      break;
-    }
-    default:
-      UPB_UNREACHABLE();
-  }
-#undef CASE
-
-  encode_tag(e, f->number, wire_type);
-}
-
-static void encode_array(upb_encstate* e, const upb_Message* msg,
-                         const upb_MiniTable_Sub* subs,
-                         const upb_MiniTable_Field* f) {
-  const upb_Array* arr = *UPB_PTR_AT(msg, f->offset, upb_Array*);
-  bool packed = f->mode & kUpb_LabelFlags_IsPacked;
-  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) | kUpb_WireType_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 kUpb_FieldType_Double:
-      encode_fixedarray(e, arr, sizeof(double), TAG(kUpb_WireType_64Bit));
-      break;
-    case kUpb_FieldType_Float:
-      encode_fixedarray(e, arr, sizeof(float), TAG(kUpb_WireType_32Bit));
-      break;
-    case kUpb_FieldType_SFixed64:
-    case kUpb_FieldType_Fixed64:
-      encode_fixedarray(e, arr, sizeof(uint64_t), TAG(kUpb_WireType_64Bit));
-      break;
-    case kUpb_FieldType_Fixed32:
-    case kUpb_FieldType_SFixed32:
-      encode_fixedarray(e, arr, sizeof(uint32_t), TAG(kUpb_WireType_32Bit));
-      break;
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_UInt64:
-      VARINT_CASE(uint64_t, *ptr);
-    case kUpb_FieldType_UInt32:
-      VARINT_CASE(uint32_t, *ptr);
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_Enum:
-      VARINT_CASE(int32_t, (int64_t)*ptr);
-    case kUpb_FieldType_Bool:
-      VARINT_CASE(bool, *ptr);
-    case kUpb_FieldType_SInt32:
-      VARINT_CASE(int32_t, encode_zz32(*ptr));
-    case kUpb_FieldType_SInt64:
-      VARINT_CASE(int64_t, encode_zz64(*ptr));
-    case kUpb_FieldType_String:
-    case kUpb_FieldType_Bytes: {
-      const upb_StringView* start = _upb_array_constptr(arr);
-      const upb_StringView* ptr = start + arr->len;
-      do {
-        ptr--;
-        encode_bytes(e, ptr->data, ptr->size);
-        encode_varint(e, ptr->size);
-        encode_tag(e, f->number, kUpb_WireType_Delimited);
-      } while (ptr != start);
-      return;
-    }
-    case kUpb_FieldType_Group: {
-      const void* const* start = _upb_array_constptr(arr);
-      const void* const* ptr = start + arr->len;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      if (--e->depth == 0) encode_err(e);
-      do {
-        size_t size;
-        ptr--;
-        encode_tag(e, f->number, kUpb_WireType_EndGroup);
-        encode_message(e, *ptr, subm, &size);
-        encode_tag(e, f->number, kUpb_WireType_StartGroup);
-      } while (ptr != start);
-      e->depth++;
-      return;
-    }
-    case kUpb_FieldType_Message: {
-      const void* const* start = _upb_array_constptr(arr);
-      const void* const* ptr = start + arr->len;
-      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
-      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, kUpb_WireType_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, kUpb_WireType_Delimited);
-  }
-}
-
-static void encode_mapentry(upb_encstate* e, uint32_t number,
-                            const upb_MiniTable* layout,
-                            const upb_MapEntry* ent) {
-  const upb_MiniTable_Field* key_field = &layout->fields[0];
-  const upb_MiniTable_Field* val_field = &layout->fields[1];
-  size_t pre_len = e->limit - e->ptr;
-  size_t size;
-  encode_scalar(e, &ent->v, layout->subs, val_field);
-  encode_scalar(e, &ent->k, layout->subs, key_field);
-  size = (e->limit - e->ptr) - pre_len;
-  encode_varint(e, size);
-  encode_tag(e, number, kUpb_WireType_Delimited);
-}
-
-static void encode_map(upb_encstate* e, const upb_Message* msg,
-                       const upb_MiniTable_Sub* subs,
-                       const upb_MiniTable_Field* f) {
-  const upb_Map* map = *UPB_PTR_AT(msg, f->offset, const upb_Map*);
-  const upb_MiniTable* layout = subs[f->submsg_index].submsg;
-  UPB_ASSERT(layout->field_count == 2);
-
-  if (map == NULL) return;
-
-  if (e->options & kUpb_Encode_Deterministic) {
-    _upb_sortedmap sorted;
-    _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
-                           &sorted);
-    upb_MapEntry 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_StringView key = upb_strtable_iter_key(&i);
-      const upb_value val = upb_strtable_iter_value(&i);
-      upb_MapEntry 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 bool encode_shouldencode(upb_encstate* e, const upb_Message* msg,
-                                const upb_MiniTable_Sub* subs,
-                                const upb_MiniTable_Field* f) {
-  if (f->presence == 0) {
-    /* Proto3 presence or map/array. */
-    const void* mem = UPB_PTR_AT(msg, f->offset, void);
-    switch (f->mode >> kUpb_FieldRep_Shift) {
-      case kUpb_FieldRep_1Byte: {
-        char ch;
-        memcpy(&ch, mem, 1);
-        return ch != 0;
-      }
-#if UINTPTR_MAX == 0xffffffff
-      case kUpb_FieldRep_Pointer:
-#endif
-      case kUpb_FieldRep_4Byte: {
-        uint32_t u32;
-        memcpy(&u32, mem, 4);
-        return u32 != 0;
-      }
-#if UINTPTR_MAX != 0xffffffff
-      case kUpb_FieldRep_Pointer:
-#endif
-      case kUpb_FieldRep_8Byte: {
-        uint64_t u64;
-        memcpy(&u64, mem, 8);
-        return u64 != 0;
-      }
-      case kUpb_FieldRep_StringView: {
-        const upb_StringView* str = (const upb_StringView*)mem;
-        return str->size != 0;
-      }
-      default:
-        UPB_UNREACHABLE();
-    }
-  } else if (f->presence > 0) {
-    /* Proto2 presence: hasbit. */
-    return _upb_hasbit_field(msg, f);
-  } else {
-    /* Field is in a oneof. */
-    return _upb_getoneofcase_field(msg, f) == f->number;
-  }
-}
-
-static void encode_field(upb_encstate* e, const upb_Message* msg,
-                         const upb_MiniTable_Sub* subs,
-                         const upb_MiniTable_Field* field) {
-  switch (upb_FieldMode_Get(field)) {
-    case kUpb_FieldMode_Array:
-      encode_array(e, msg, subs, field);
-      break;
-    case kUpb_FieldMode_Map:
-      encode_map(e, msg, subs, field);
-      break;
-    case kUpb_FieldMode_Scalar:
-      encode_scalar(e, UPB_PTR_AT(msg, field->offset, void), subs, field);
-      break;
-    default:
-      UPB_UNREACHABLE();
-  }
-}
-
-/* message MessageSet {
- *   repeated group Item = 1 {
- *     required int32 type_id = 2;
- *     required string message = 3;
- *   }
- * } */
-static void encode_msgset_item(upb_encstate* e,
-                               const upb_Message_Extension* ext) {
-  size_t size;
-  encode_tag(e, 1, kUpb_WireType_EndGroup);
-  encode_message(e, ext->data.ptr, ext->ext->sub.submsg, &size);
-  encode_varint(e, size);
-  encode_tag(e, 3, kUpb_WireType_Delimited);
-  encode_varint(e, ext->ext->field.number);
-  encode_tag(e, 2, kUpb_WireType_Varint);
-  encode_tag(e, 1, kUpb_WireType_StartGroup);
-}
-
-static void encode_message(upb_encstate* e, const upb_Message* msg,
-                           const upb_MiniTable* m, size_t* size) {
-  size_t pre_len = e->limit - e->ptr;
-
-  if ((e->options & kUpb_Encode_CheckRequired) && m->required_count) {
-    uint64_t msg_head;
-    memcpy(&msg_head, msg, 8);
-    msg_head = _upb_BigEndian_Swap64(msg_head);
-    if (upb_MiniTable_requiredmask(m) & ~msg_head) {
-      encode_err(e);
-    }
-  }
-
-  if ((e->options & kUpb_Encode_SkipUnknown) == 0) {
-    size_t unknown_size;
-    const char* unknown = upb_Message_GetUnknown(msg, &unknown_size);
-
-    if (unknown) {
-      encode_bytes(e, unknown, unknown_size);
-    }
-  }
-
-  if (m->ext != kUpb_ExtMode_NonExtendable) {
-    /* Encode all extensions together. Unlike C++, we do not attempt to keep
-     * these in field number order relative to normal fields or even to each
-     * other. */
-    size_t ext_count;
-    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &ext_count);
-    if (ext_count) {
-      const upb_Message_Extension* end = ext + ext_count;
-      for (; ext != end; ext++) {
-        if (UPB_UNLIKELY(m->ext == kUpb_ExtMode_IsMessageSet)) {
-          encode_msgset_item(e, ext);
-        } else {
-          encode_field(e, &ext->data, &ext->ext->sub, &ext->ext->field);
-        }
-      }
-    }
-  }
-
-  if (m->field_count) {
-    const upb_MiniTable_Field* f = &m->fields[m->field_count];
-    const upb_MiniTable_Field* first = &m->fields[0];
-    while (f != first) {
-      f--;
-      if (encode_shouldencode(e, msg, m->subs, f)) {
-        encode_field(e, msg, m->subs, f);
-      }
-    }
-  }
-
-  *size = (e->limit - e->ptr) - pre_len;
-}
-
-char* upb_Encode(const void* msg, const upb_MiniTable* 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);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->size);
+  memcpy(&ret, data + (i << lg2), 1 << lg2);
   return ret;
 }
 
-/** upb/msg.c ************************************************************/
-
-
-/** upb_Message
- * *******************************************************************/
-
-static const size_t overhead = sizeof(upb_Message_InternalData);
-
-static const upb_Message_Internal* upb_Message_Getinternal_const(
-    const upb_Message* msg) {
-  ptrdiff_t size = sizeof(upb_Message_Internal);
-  return (upb_Message_Internal*)((char*)msg - size);
+void upb_Array_Set(upb_Array* arr, size_t i, upb_MessageValue val) {
+  char* data = _upb_array_ptr(arr);
+  int lg2 = arr->data & 7;
+  UPB_ASSERT(i < arr->size);
+  memcpy(data + (i << lg2), &val, 1 << lg2);
 }
 
-upb_Message* _upb_Message_New(const upb_MiniTable* l, upb_Arena* a) {
-  return _upb_Message_New_inl(l, a);
-}
-
-void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l) {
-  void* mem = UPB_PTR_AT(msg, -sizeof(upb_Message_Internal), char);
-  memset(mem, 0, upb_msg_sizeof(l));
-}
-
-static bool realloc_internal(upb_Message* msg, size_t need, upb_Arena* arena) {
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  if (!in->internal) {
-    /* No internal data, allocate from scratch. */
-    size_t size = UPB_MAX(128, _upb_Log2CeilingSize(need + overhead));
-    upb_Message_InternalData* internal = upb_Arena_Malloc(arena, size);
-    if (!internal) return false;
-    internal->size = size;
-    internal->unknown_end = overhead;
-    internal->ext_begin = size;
-    in->internal = internal;
-  } else if (in->internal->ext_begin - in->internal->unknown_end < need) {
-    /* Internal data is too small, reallocate. */
-    size_t new_size = _upb_Log2CeilingSize(in->internal->size + need);
-    size_t ext_bytes = in->internal->size - in->internal->ext_begin;
-    size_t new_ext_begin = new_size - ext_bytes;
-    upb_Message_InternalData* internal =
-        upb_Arena_Realloc(arena, in->internal, in->internal->size, new_size);
-    if (!internal) return false;
-    if (ext_bytes) {
-      /* Need to move extension data to the end. */
-      char* ptr = (char*)internal;
-      memmove(ptr + new_ext_begin, ptr + internal->ext_begin, ext_bytes);
-    }
-    internal->ext_begin = new_ext_begin;
-    internal->size = new_size;
-    in->internal = internal;
+bool upb_Array_Append(upb_Array* arr, upb_MessageValue val, upb_Arena* arena) {
+  if (!upb_Array_Resize(arr, arr->size + 1, arena)) {
+    return false;
   }
-  UPB_ASSERT(in->internal->ext_begin - in->internal->unknown_end >= need);
+  upb_Array_Set(arr, arr->size - 1, val);
   return true;
 }
 
-bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
-                             upb_Arena* arena) {
-  if (!realloc_internal(msg, len, arena)) return false;
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  memcpy(UPB_PTR_AT(in->internal, in->internal->unknown_end, char), data, len);
-  in->internal->unknown_end += len;
+void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
+                    size_t count) {
+  char* data = _upb_array_ptr(arr);
+  int lg2 = arr->data & 7;
+  memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
+}
+
+bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
+                      upb_Arena* arena) {
+  UPB_ASSERT(i <= arr->size);
+  UPB_ASSERT(count + arr->size >= count);
+  size_t oldsize = arr->size;
+  if (!upb_Array_Resize(arr, arr->size + count, arena)) {
+    return false;
+  }
+  upb_Array_Move(arr, i + count, i, oldsize - i);
   return true;
 }
 
-void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  if (in->internal) {
-    in->internal->unknown_end = overhead;
-  }
+/*
+ *              i        end      arr->size
+ * |------------|XXXXXXXX|--------|
+ */
+void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
+  size_t end = i + count;
+  UPB_ASSERT(i <= end);
+  UPB_ASSERT(end <= arr->size);
+  upb_Array_Move(arr, i, end, arr->size - end);
+  arr->size -= count;
 }
 
-const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
-  const upb_Message_Internal* in = upb_Message_Getinternal_const(msg);
-  if (in->internal) {
-    *len = in->internal->unknown_end - overhead;
-    return (char*)(in->internal + 1);
-  } else {
-    *len = 0;
-    return NULL;
-  }
+bool upb_Array_Resize(upb_Array* arr, size_t size, upb_Arena* arena) {
+  return _upb_Array_Resize(arr, size, arena);
 }
 
-const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
-                                                  size_t* count) {
-  const upb_Message_Internal* in = upb_Message_Getinternal_const(msg);
-  if (in->internal) {
-    *count = (in->internal->size - in->internal->ext_begin) /
-             sizeof(upb_Message_Extension);
-    return UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
-  } else {
-    *count = 0;
-    return NULL;
-  }
-}
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
 
-const upb_Message_Extension* _upb_Message_Getext(
-    const upb_Message* msg, const upb_MiniTable_Extension* e) {
-  size_t n;
-  const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &n);
-
-  /* For now we use linear search exclusively to find extensions. If this
-   * becomes an issue due to messages with lots of extensions, we can introduce
-   * a table of some sort. */
-  for (size_t i = 0; i < n; i++) {
-    if (ext[i].ext == e) {
-      return &ext[i];
-    }
-  }
-
-  return NULL;
-}
-
-void _upb_Message_Clearext(upb_Message* msg,
-                           const upb_MiniTable_Extension* ext_l) {
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  if (!in->internal) return;
-  const upb_Message_Extension* base =
-      UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
-  upb_Message_Extension* ext =
-      (upb_Message_Extension*)_upb_Message_Getext(msg, ext_l);
-  if (ext) {
-    *ext = *base;
-    in->internal->ext_begin += sizeof(upb_Message_Extension);
-  }
-}
-
-upb_Message_Extension* _upb_Message_Getorcreateext(
-    upb_Message* msg, const upb_MiniTable_Extension* e, upb_Arena* arena) {
-  upb_Message_Extension* ext =
-      (upb_Message_Extension*)_upb_Message_Getext(msg, e);
-  if (ext) return ext;
-  if (!realloc_internal(msg, sizeof(upb_Message_Extension), arena)) return NULL;
-  upb_Message_Internal* in = upb_Message_Getinternal(msg);
-  in->internal->ext_begin -= sizeof(upb_Message_Extension);
-  ext = UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
-  memset(ext, 0, sizeof(upb_Message_Extension));
-  ext->ext = e;
-  return ext;
-}
-
-size_t upb_Message_ExtensionCount(const upb_Message* msg) {
-  size_t count;
-  _upb_Message_Getexts(msg, &count);
-  return count;
-}
-
-/** 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);
+bool _upb_array_realloc(upb_Array* arr, size_t min_capacity, upb_Arena* arena) {
+  size_t new_capacity = UPB_MAX(arr->capacity, 4);
   int elem_size_lg2 = arr->data & 7;
-  size_t old_bytes = arr->size << elem_size_lg2;
+  size_t old_bytes = arr->capacity << 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;
+  // Log2 ceiling of size.
+  while (new_capacity < min_capacity) new_capacity *= 2;
 
-  new_bytes = new_size << elem_size_lg2;
+  new_bytes = new_capacity << elem_size_lg2;
   ptr = upb_Arena_Realloc(arena, ptr, old_bytes, new_bytes);
 
   if (!ptr) {
@@ -2098,7 +420,7 @@
   }
 
   arr->data = _upb_tag_arrptr(ptr, elem_size_lg2);
-  arr->size = new_size;
+  arr->capacity = new_capacity;
   return true;
 }
 
@@ -2125,7 +447,7 @@
   upb_Array* arr = getorcreate_array(arr_ptr, elem_size_lg2, arena);
   if (!arr) return false;
 
-  size_t elems = arr->len;
+  size_t elems = arr->size;
 
   if (!_upb_Array_Resize(arr, elems + 1, arena)) {
     return false;
@@ -2136,14 +458,100 @@
   return true;
 }
 
-/** upb_Map *******************************************************************/
+
+#include <string.h>
+
+
+// Must be last.
+
+/* Strings/bytes are special-cased in maps. */
+static char _upb_CTypeo_mapsize[12] = {
+    0,
+    1,             /* kUpb_CType_Bool */
+    4,             /* kUpb_CType_Float */
+    4,             /* kUpb_CType_Int32 */
+    4,             /* kUpb_CType_UInt32 */
+    4,             /* kUpb_CType_Enum */
+    sizeof(void*), /* kUpb_CType_Message */
+    8,             /* kUpb_CType_Double */
+    8,             /* kUpb_CType_Int64 */
+    8,             /* kUpb_CType_UInt64 */
+    0,             /* kUpb_CType_String */
+    0,             /* kUpb_CType_Bytes */
+};
+
+upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType value_type) {
+  return _upb_Map_New(a, _upb_CTypeo_mapsize[key_type],
+                      _upb_CTypeo_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_MessageValue key,
+                 upb_MessageValue* 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); }
+
+upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
+                                   upb_MessageValue val, upb_Arena* arena) {
+  return (upb_MapInsertStatus)_upb_Map_Insert(map, &key, map->key_size, &val,
+                                              map->val_size, arena);
+}
+
+bool upb_Map_Delete(upb_Map* map, upb_MessageValue key) {
+  return _upb_Map_Delete(map, &key, map->key_size);
+}
+
+bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
+                  upb_MessageValue* val, size_t* iter) {
+  upb_StringView k;
+  upb_value v;
+  const bool ok = upb_strtable_next2(&map->table, &k, &v, (intptr_t*)iter);
+  if (ok) {
+    _upb_map_fromkey(k, key, map->key_size);
+    _upb_map_fromvalue(v, val, map->val_size);
+  }
+  return ok;
+}
+
+bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) {
+  return _upb_map_next(map, iter);
+}
+
+bool upb_MapIterator_Done(const upb_Map* map, size_t iter) {
+  upb_strtable_iter i;
+  UPB_ASSERT(iter != kUpb_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_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
+  upb_strtable_iter i;
+  upb_MessageValue ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
+  return ret;
+}
+
+upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
+  upb_strtable_iter i;
+  upb_MessageValue ret;
+  i.t = &map->table;
+  i.index = iter;
+  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
+  return ret;
+}
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
 
 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;
-  }
+  if (!map) return NULL;
 
   upb_strtable_init(&map->table, 4, a);
   map->key_size = key_size;
@@ -2152,6 +560,9 @@
   return map;
 }
 
+
+// Must be last.
+
 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;
@@ -2162,36 +573,34 @@
   _upb_map_fromkey(b_tabkey, b_key, size);
 }
 
-#define UPB_COMPARE_INTEGERS(a, b) ((a) < (b) ? -1 : ((a) == (b) ? 0 : 1))
-
 static int _upb_mapsorter_cmpi64(const void* _a, const void* _b) {
   int64_t a, b;
   _upb_mapsorter_getkeys(_a, _b, &a, &b, 8);
-  return UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : 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 UPB_COMPARE_INTEGERS(a, b);
+  return a < b ? -1 : a > b;
 }
 
 static int _upb_mapsorter_cmpstr(const void* _a, const void* _b) {
@@ -2200,10 +609,30 @@
   size_t common_size = UPB_MIN(a.size, b.size);
   int cmp = memcmp(a.data, b.data, common_size);
   if (cmp) return -cmp;
-  return UPB_COMPARE_INTEGERS(a.size, b.size);
+  return a.size < b.size ? -1 : a.size > b.size;
 }
 
-#undef UPB_COMPARE_INTEGERS
+static int (*const compar[kUpb_FieldType_SizeOf])(const void*, const void*) = {
+    [kUpb_FieldType_Int64] = _upb_mapsorter_cmpi64,
+    [kUpb_FieldType_SFixed64] = _upb_mapsorter_cmpi64,
+    [kUpb_FieldType_SInt64] = _upb_mapsorter_cmpi64,
+
+    [kUpb_FieldType_UInt64] = _upb_mapsorter_cmpu64,
+    [kUpb_FieldType_Fixed64] = _upb_mapsorter_cmpu64,
+
+    [kUpb_FieldType_Int32] = _upb_mapsorter_cmpi32,
+    [kUpb_FieldType_SInt32] = _upb_mapsorter_cmpi32,
+    [kUpb_FieldType_SFixed32] = _upb_mapsorter_cmpi32,
+    [kUpb_FieldType_Enum] = _upb_mapsorter_cmpi32,
+
+    [kUpb_FieldType_UInt32] = _upb_mapsorter_cmpu32,
+    [kUpb_FieldType_Fixed32] = _upb_mapsorter_cmpu32,
+
+    [kUpb_FieldType_Bool] = _upb_mapsorter_cmpbool,
+
+    [kUpb_FieldType_String] = _upb_mapsorter_cmpstr,
+    [kUpb_FieldType_Bytes] = _upb_mapsorter_cmpstr,
+};
 
 bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
                             const upb_Map* map, _upb_sortedmap* sorted) {
@@ -2212,16 +641,16 @@
   sorted->pos = sorted->start;
   sorted->end = sorted->start + map_size;
 
-  /* Grow s->entries if necessary. */
+  // Grow s->entries if necessary.
   if (sorted->end > s->cap) {
-    s->cap = _upb_Log2CeilingSize(sorted->end);
+    s->cap = upb_Log2CeilingSize(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. */
+  // 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);
@@ -2233,107 +662,620 @@
   }
   UPB_ASSERT(dst == &s->entries[sorted->end]);
 
-  /* Sort entries according to the key type. */
-
-  int (*compar)(const void*, const void*);
-
-  switch (key_type) {
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_SFixed64:
-    case kUpb_FieldType_SInt64:
-      compar = _upb_mapsorter_cmpi64;
-      break;
-    case kUpb_FieldType_UInt64:
-    case kUpb_FieldType_Fixed64:
-      compar = _upb_mapsorter_cmpu64;
-      break;
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_SInt32:
-    case kUpb_FieldType_SFixed32:
-    case kUpb_FieldType_Enum:
-      compar = _upb_mapsorter_cmpi32;
-      break;
-    case kUpb_FieldType_UInt32:
-    case kUpb_FieldType_Fixed32:
-      compar = _upb_mapsorter_cmpu32;
-      break;
-    case kUpb_FieldType_Bool:
-      compar = _upb_mapsorter_cmpbool;
-      break;
-    case kUpb_FieldType_String:
-    case kUpb_FieldType_Bytes:
-      compar = _upb_mapsorter_cmpstr;
-      break;
-    default:
-      UPB_UNREACHABLE();
-  }
-
-  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries), compar);
+  // Sort entries according to the key type.
+  qsort(&s->entries[sorted->start], map_size, sizeof(*s->entries),
+        compar[key_type]);
   return true;
 }
+/* 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. */
 
-/** upb_ExtensionRegistry
- * ****************************************************************/
+#include <stddef.h>
 
-struct upb_ExtensionRegistry {
-  upb_Arena* arena;
-  upb_strtable exts; /* Key is upb_MiniTable* concatenated with fieldnum. */
+
+static const upb_MiniTableSub google_protobuf_FileDescriptorSet_submsgs[1] = {
+  {.submsg = &google_protobuf_FileDescriptorProto_msg_init},
 };
 
-#define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
+static const upb_MiniTableField google_protobuf_FileDescriptorSet__fields[1] = {
+  {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
 
-static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
-  memcpy(buf, &l, sizeof(l));
-  memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
-}
+const upb_MiniTable google_protobuf_FileDescriptorSet_msg_init = {
+  &google_protobuf_FileDescriptorSet_submsgs[0],
+  &google_protobuf_FileDescriptorSet__fields[0],
+  8, 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+};
 
-upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
-  upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
-  if (!r) return NULL;
-  r->arena = arena;
-  if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
-  return r;
-}
+static const upb_MiniTableSub google_protobuf_FileDescriptorProto_submsgs[6] = {
+  {.submsg = &google_protobuf_DescriptorProto_msg_init},
+  {.submsg = &google_protobuf_EnumDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_ServiceDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_FieldDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_FileOptions_msg_init},
+  {.submsg = &google_protobuf_SourceCodeInfo_msg_init},
+};
 
-bool _upb_extreg_add(upb_ExtensionRegistry* r,
-                     const upb_MiniTable_Extension** e, size_t count) {
-  char buf[EXTREG_KEY_SIZE];
-  const upb_MiniTable_Extension** start = e;
-  const upb_MiniTable_Extension** end = UPB_PTRADD(e, count);
-  for (; e < end; e++) {
-    const upb_MiniTable_Extension* ext = *e;
-    extreg_key(buf, ext->extendee, ext->field.number);
-    if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
-                             upb_value_constptr(ext), r->arena)) {
-      goto failure;
-    }
-  }
-  return true;
+static const upb_MiniTableField google_protobuf_FileDescriptorProto__fields[13] = {
+  {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(4, 40), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(8, 48), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(12, 56), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(16, 64), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(20, 72), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {10, UPB_SIZE(32, 96), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {11, UPB_SIZE(36, 104), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+};
 
-failure:
-  /* Back out the entries previously added. */
-  for (end = e, e = start; e < end; e++) {
-    const upb_MiniTable_Extension* ext = *e;
-    extreg_key(buf, ext->extendee, ext->field.number);
-    upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
-  }
-  return false;
-}
+const upb_MiniTable google_protobuf_FileDescriptorProto_msg_init = {
+  &google_protobuf_FileDescriptorProto_submsgs[0],
+  &google_protobuf_FileDescriptorProto__fields[0],
+  UPB_SIZE(72, 144), 13, kUpb_ExtMode_NonExtendable, 13, 255, 0,
+};
 
-const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
-                                               const upb_MiniTable* l,
-                                               uint32_t num) {
-  char buf[EXTREG_KEY_SIZE];
-  upb_value v;
-  extreg_key(buf, l, num);
-  if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
-    return upb_value_getconstptr(v);
-  } else {
-    return NULL;
-  }
-}
+static const upb_MiniTableSub google_protobuf_DescriptorProto_submsgs[8] = {
+  {.submsg = &google_protobuf_FieldDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_DescriptorProto_msg_init},
+  {.submsg = &google_protobuf_EnumDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_DescriptorProto_ExtensionRange_msg_init},
+  {.submsg = &google_protobuf_FieldDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_MessageOptions_msg_init},
+  {.submsg = &google_protobuf_OneofDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_DescriptorProto_ReservedRange_msg_init},
+};
 
-/** upb/table.c ************************************************************/
+static const upb_MiniTableField google_protobuf_DescriptorProto__fields[10] = {
+  {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 32), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(16, 48), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(20, 56), 0, 4, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(28, 72), 0, 6, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {9, UPB_SIZE(32, 80), 0, 7, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {10, UPB_SIZE(36, 88), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_DescriptorProto_msg_init = {
+  &google_protobuf_DescriptorProto_submsgs[0],
+  &google_protobuf_DescriptorProto__fields[0],
+  UPB_SIZE(48, 96), 10, kUpb_ExtMode_NonExtendable, 10, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
+  {.submsg = &google_protobuf_ExtensionRangeOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
+  {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msg_init = {
+  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
+  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
+  UPB_SIZE(16, 24), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
+  {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msg_init = {
+  NULL,
+  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
+  16, 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_ExtensionRangeOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_ExtensionRangeOptions__fields[1] = {
+  {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_ExtensionRangeOptions_msg_init = {
+  &google_protobuf_ExtensionRangeOptions_submsgs[0],
+  &google_protobuf_ExtensionRangeOptions__fields[0],
+  8, 1, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_FieldDescriptorProto_submsgs[3] = {
+  {.subenum = &google_protobuf_FieldDescriptorProto_Label_enum_init},
+  {.subenum = &google_protobuf_FieldDescriptorProto_Type_enum_init},
+  {.submsg = &google_protobuf_FieldOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_FieldDescriptorProto__fields[11] = {
+  {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_FieldDescriptorProto_msg_init = {
+  &google_protobuf_FieldDescriptorProto_submsgs[0],
+  &google_protobuf_FieldDescriptorProto__fields[0],
+  UPB_SIZE(72, 112), 11, kUpb_ExtMode_NonExtendable, 10, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_OneofDescriptorProto_submsgs[1] = {
+  {.submsg = &google_protobuf_OneofOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_OneofDescriptorProto__fields[2] = {
+  {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_OneofDescriptorProto_msg_init = {
+  &google_protobuf_OneofDescriptorProto_submsgs[0],
+  &google_protobuf_OneofDescriptorProto__fields[0],
+  UPB_SIZE(16, 32), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumDescriptorProto_submsgs[3] = {
+  {.submsg = &google_protobuf_EnumValueDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_EnumOptions_msg_init},
+  {.submsg = &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumDescriptorProto__fields[5] = {
+  {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(16, 48), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumDescriptorProto_msg_init = {
+  &google_protobuf_EnumDescriptorProto_submsgs[0],
+  &google_protobuf_EnumDescriptorProto__fields[0],
+  UPB_SIZE(32, 56), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
+  {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init = {
+  NULL,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
+  16, 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
+  {.submsg = &google_protobuf_EnumValueOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumValueDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msg_init = {
+  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
+  &google_protobuf_EnumValueDescriptorProto__fields[0],
+  UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_ServiceDescriptorProto_submsgs[2] = {
+  {.submsg = &google_protobuf_MethodDescriptorProto_msg_init},
+  {.submsg = &google_protobuf_ServiceOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_ServiceDescriptorProto__fields[3] = {
+  {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_ServiceDescriptorProto_msg_init = {
+  &google_protobuf_ServiceDescriptorProto_submsgs[0],
+  &google_protobuf_ServiceDescriptorProto__fields[0],
+  UPB_SIZE(24, 40), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_MethodDescriptorProto_submsgs[1] = {
+  {.submsg = &google_protobuf_MethodOptions_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_MethodDescriptorProto__fields[6] = {
+  {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_MethodDescriptorProto_msg_init = {
+  &google_protobuf_MethodDescriptorProto_submsgs[0],
+  &google_protobuf_MethodDescriptorProto__fields[0],
+  UPB_SIZE(40, 64), 6, kUpb_ExtMode_NonExtendable, 6, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_FileOptions_submsgs[2] = {
+  {.subenum = &google_protobuf_FileOptions_OptimizeMode_enum_init},
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_FileOptions__fields[21] = {
+  {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(20, 184), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_FileOptions_msg_init = {
+  &google_protobuf_FileOptions_submsgs[0],
+  &google_protobuf_FileOptions__fields[0],
+  UPB_SIZE(104, 192), 21, kUpb_ExtMode_Extendable, 1, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_MessageOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_MessageOptions__fields[5] = {
+  {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, 8, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_MessageOptions_msg_init = {
+  &google_protobuf_MessageOptions_submsgs[0],
+  &google_protobuf_MessageOptions__fields[0],
+  16, 5, kUpb_ExtMode_Extendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_FieldOptions_submsgs[3] = {
+  {.subenum = &google_protobuf_FieldOptions_CType_enum_init},
+  {.subenum = &google_protobuf_FieldOptions_JSType_enum_init},
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_FieldOptions__fields[8] = {
+  {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(20, 24), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_FieldOptions_msg_init = {
+  &google_protobuf_FieldOptions_submsgs[0],
+  &google_protobuf_FieldOptions__fields[0],
+  UPB_SIZE(24, 32), 8, kUpb_ExtMode_Extendable, 3, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_OneofOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_OneofOptions__fields[1] = {
+  {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_OneofOptions_msg_init = {
+  &google_protobuf_OneofOptions_submsgs[0],
+  &google_protobuf_OneofOptions__fields[0],
+  8, 1, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumOptions__fields[3] = {
+  {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumOptions_msg_init = {
+  &google_protobuf_EnumOptions_submsgs[0],
+  &google_protobuf_EnumOptions__fields[0],
+  UPB_SIZE(8, 16), 3, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_EnumValueOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_EnumValueOptions__fields[2] = {
+  {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_EnumValueOptions_msg_init = {
+  &google_protobuf_EnumValueOptions_submsgs[0],
+  &google_protobuf_EnumValueOptions__fields[0],
+  UPB_SIZE(8, 16), 2, kUpb_ExtMode_Extendable, 1, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_ServiceOptions_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_ServiceOptions__fields[2] = {
+  {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_ServiceOptions_msg_init = {
+  &google_protobuf_ServiceOptions_submsgs[0],
+  &google_protobuf_ServiceOptions__fields[0],
+  UPB_SIZE(8, 16), 2, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_MethodOptions_submsgs[2] = {
+  {.subenum = &google_protobuf_MethodOptions_IdempotencyLevel_enum_init},
+  {.submsg = &google_protobuf_UninterpretedOption_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_MethodOptions__fields[3] = {
+  {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+  {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {999, 8, 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_MethodOptions_msg_init = {
+  &google_protobuf_MethodOptions_submsgs[0],
+  &google_protobuf_MethodOptions__fields[0],
+  16, 3, kUpb_ExtMode_Extendable, 0, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_UninterpretedOption_submsgs[1] = {
+  {.submsg = &google_protobuf_UninterpretedOption_NamePart_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_UninterpretedOption__fields[7] = {
+  {2, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
+  {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_UninterpretedOption_msg_init = {
+  &google_protobuf_UninterpretedOption_submsgs[0],
+  &google_protobuf_UninterpretedOption__fields[0],
+  UPB_SIZE(56, 88), 7, kUpb_ExtMode_NonExtendable, 0, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_UninterpretedOption_NamePart__fields[2] = {
+  {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msg_init = {
+  NULL,
+  &google_protobuf_UninterpretedOption_NamePart__fields[0],
+  UPB_SIZE(16, 24), 2, kUpb_ExtMode_NonExtendable, 2, 255, 2,
+};
+
+static const upb_MiniTableSub google_protobuf_SourceCodeInfo_submsgs[1] = {
+  {.submsg = &google_protobuf_SourceCodeInfo_Location_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_SourceCodeInfo__fields[1] = {
+  {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_SourceCodeInfo_msg_init = {
+  &google_protobuf_SourceCodeInfo_submsgs[0],
+  &google_protobuf_SourceCodeInfo__fields[0],
+  8, 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+};
+
+static const upb_MiniTableField google_protobuf_SourceCodeInfo_Location__fields[5] = {
+  {1, UPB_SIZE(4, 8), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(8, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {6, UPB_SIZE(12, 56), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msg_init = {
+  NULL,
+  &google_protobuf_SourceCodeInfo_Location__fields[0],
+  UPB_SIZE(32, 64), 5, kUpb_ExtMode_NonExtendable, 4, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_submsgs[1] = {
+  {.submsg = &google_protobuf_GeneratedCodeInfo_Annotation_msg_init},
+};
+
+static const upb_MiniTableField google_protobuf_GeneratedCodeInfo__fields[1] = {
+  {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_GeneratedCodeInfo_msg_init = {
+  &google_protobuf_GeneratedCodeInfo_submsgs[0],
+  &google_protobuf_GeneratedCodeInfo__fields[0],
+  8, 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
+};
+
+static const upb_MiniTableSub google_protobuf_GeneratedCodeInfo_Annotation_submsgs[1] = {
+  {.subenum = &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init},
+};
+
+static const upb_MiniTableField google_protobuf_GeneratedCodeInfo_Annotation__fields[5] = {
+  {1, UPB_SIZE(4, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)},
+  {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
+  {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+  {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
+};
+
+const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msg_init = {
+  &google_protobuf_GeneratedCodeInfo_Annotation_submsgs[0],
+  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
+  UPB_SIZE(32, 40), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0,
+};
+
+static const upb_MiniTable *messages_layout[27] = {
+  &google_protobuf_FileDescriptorSet_msg_init,
+  &google_protobuf_FileDescriptorProto_msg_init,
+  &google_protobuf_DescriptorProto_msg_init,
+  &google_protobuf_DescriptorProto_ExtensionRange_msg_init,
+  &google_protobuf_DescriptorProto_ReservedRange_msg_init,
+  &google_protobuf_ExtensionRangeOptions_msg_init,
+  &google_protobuf_FieldDescriptorProto_msg_init,
+  &google_protobuf_OneofDescriptorProto_msg_init,
+  &google_protobuf_EnumDescriptorProto_msg_init,
+  &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init,
+  &google_protobuf_EnumValueDescriptorProto_msg_init,
+  &google_protobuf_ServiceDescriptorProto_msg_init,
+  &google_protobuf_MethodDescriptorProto_msg_init,
+  &google_protobuf_FileOptions_msg_init,
+  &google_protobuf_MessageOptions_msg_init,
+  &google_protobuf_FieldOptions_msg_init,
+  &google_protobuf_OneofOptions_msg_init,
+  &google_protobuf_EnumOptions_msg_init,
+  &google_protobuf_EnumValueOptions_msg_init,
+  &google_protobuf_ServiceOptions_msg_init,
+  &google_protobuf_MethodOptions_msg_init,
+  &google_protobuf_UninterpretedOption_msg_init,
+  &google_protobuf_UninterpretedOption_NamePart_msg_init,
+  &google_protobuf_SourceCodeInfo_msg_init,
+  &google_protobuf_SourceCodeInfo_Location_msg_init,
+  &google_protobuf_GeneratedCodeInfo_msg_init,
+  &google_protobuf_GeneratedCodeInfo_Annotation_msg_init,
+};
+
+const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init = {
+    64,
+    0,
+    {
+        0x7fffe,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init = {
+    64,
+    0,
+    {
+        0xe,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init = {
+    64,
+    0,
+    {
+        0xe,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init = {
+    64,
+    0,
+    {
+        0x7,
+        0x0,
+    },
+};
+
+static const upb_MiniTableEnum *enums_layout[7] = {
+  &google_protobuf_FieldDescriptorProto_Type_enum_init,
+  &google_protobuf_FieldDescriptorProto_Label_enum_init,
+  &google_protobuf_FileOptions_OptimizeMode_enum_init,
+  &google_protobuf_FieldOptions_CType_enum_init,
+  &google_protobuf_FieldOptions_JSType_enum_init,
+  &google_protobuf_MethodOptions_IdempotencyLevel_enum_init,
+  &google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init,
+};
+
+const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout = {
+  messages_layout,
+  enums_layout,
+  NULL,
+  27,
+  7,
+  0,
+};
+
+
+
 /*
  * upb_table Implementation
  *
@@ -2343,11 +1285,11 @@
 #include <string.h>
 
 
-/* Must be last. */
+// Must be last.
 
-#define UPB_MAXARRSIZE 16 /* 64k. */
+#define UPB_MAXARRSIZE 16  // 2**16 = 64k.
 
-/* From Chromium. */
+// From Chromium.
 #define ARRAY_SIZE(x) \
   ((sizeof(x) / sizeof(0 [x])) / ((size_t)(!(sizeof(x) % sizeof(0 [x])))))
 
@@ -2370,7 +1312,7 @@
   int ret = 0;
   bool pow2 = is_pow2(v);
   while (v >>= 1) ret++;
-  ret = pow2 ? ret : ret + 1; /* Ceiling. */
+  ret = pow2 ? ret : ret + 1;  // Ceiling.
   return UPB_MIN(UPB_MAXARRSIZE, ret);
 }
 
@@ -2765,7 +1707,7 @@
   // denominator.
   size_t need_entries = (expected_size + 1) * 1204 / 1024;
   UPB_ASSERT(need_entries >= expected_size * 0.85);
-  int size_lg2 = _upb_Log2Ceiling(need_entries);
+  int size_lg2 = upb_Log2Ceiling(need_entries);
   return init(&t->t, size_lg2, a);
 }
 
@@ -2777,14 +1719,13 @@
 
 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_StringView key = upb_strtable_iter_key(&i);
-    upb_strtable_insert(&new_table, key.data, key.size,
-                        upb_strtable_iter_value(&i), a);
+
+  intptr_t iter = UPB_STRTABLE_BEGIN;
+  upb_StringView key;
+  upb_value val;
+  while (upb_strtable_next2(t, &key, &val, &iter)) {
+    upb_strtable_insert(&new_table, key.data, key.size, val, a);
   }
   *t = new_table;
   return true;
@@ -2903,12 +1844,13 @@
   UPB_UNUSED(t);
 #if defined(UPB_DEBUG_TABLE) && !defined(NDEBUG)
   {
-    /* This check is very expensive (makes inserts/deletes O(N)). */
+    // 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));
+    intptr_t iter = UPB_INTTABLE_BEGIN;
+    uintptr_t key;
+    upb_value val;
+    while (upb_inttable_next(t, &key, &val, &iter)) {
+      UPB_ASSERT(upb_inttable_lookup(t, key, NULL));
     }
     UPB_ASSERT(count == upb_inttable_count(t));
   }
@@ -3021,22 +1963,22 @@
   /* 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]++;
+  {
+    intptr_t iter = UPB_INTTABLE_BEGIN;
+    uintptr_t key;
+    upb_value val;
+    while (upb_inttable_next(t, &key, &val, &iter)) {
+      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);
+  size_t arr_count = upb_inttable_count(t);
+  int size_lg2;
+  upb_inttable new_t;
 
   for (size_lg2 = ARRAY_SIZE(counts) - 1; size_lg2 > 0; size_lg2--) {
     if (counts[size_lg2] == 0) {
@@ -3059,55 +2001,28 @@
     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);
+
+    {
+      intptr_t iter = UPB_INTTABLE_BEGIN;
+      uintptr_t key;
+      upb_value val;
+      while (upb_inttable_next(t, &key, &val, &iter)) {
+        upb_inttable_insert(&new_t, key, val, a);
+      }
     }
+
     UPB_ASSERT(new_t.array_size == arr_size);
     UPB_ASSERT(new_t.t.size_lg2 == hashsize_lg2);
   }
   *t = new_t;
 }
 
-/* Iteration. */
+// 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_next2(const upb_inttable* t, uintptr_t* key, upb_value* val,
-                        intptr_t* iter) {
+bool upb_inttable_next(const upb_inttable* t, uintptr_t* key, upb_value* val,
+                       intptr_t* iter) {
   intptr_t i = *iter;
-  if (i < t->array_size) {
+  if ((size_t)(i + 1) <= t->array_size) {
     while (++i < t->array_size) {
       upb_tabval ent = t->array[i];
       if (upb_arrhas(ent)) {
@@ -3117,9 +2032,10 @@
         return true;
       }
     }
+    i--;  // Back up to exactly one position before the start of the table.
   }
 
-  size_t tab_idx = next(&t->t, i == -1 ? -1 : i - t->array_size);
+  size_t tab_idx = next(&t->t, i - t->array_size);
   if (tab_idx < upb_table_size(&t->t)) {
     upb_tabent* ent = &t->t.entries[tab_idx];
     *key = ent->key;
@@ -3198,5672 +2114,17 @@
   ent->next = NULL;
 }
 
-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 <float.h>
-#include <stdarg.h>
-#include <stddef.h>
-#include <stdint.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-
-
-// Must be last.
-
-/* upb_Status *****************************************************************/
-
-void upb_Status_Clear(upb_Status* status) {
-  if (!status) return;
-  status->ok = true;
-  status->msg[0] = '\0';
-}
-
-bool upb_Status_IsOk(const upb_Status* status) { return status->ok; }
-
-const char* upb_Status_ErrorMessage(const upb_Status* status) {
-  return status->msg;
-}
-
-void upb_Status_SetErrorMessage(upb_Status* status, const char* msg) {
-  if (!status) return;
-  status->ok = false;
-  strncpy(status->msg, msg, _kUpb_Status_MaxMessage - 1);
-  status->msg[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
-void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...) {
-  va_list args;
-  va_start(args, fmt);
-  upb_Status_VSetErrorFormat(status, fmt, args);
-  va_end(args);
-}
-
-void upb_Status_VSetErrorFormat(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[_kUpb_Status_MaxMessage - 1] = '\0';
-}
-
-void upb_Status_VAppendErrorFormat(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[_kUpb_Status_MaxMessage - 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_CleanupFunc* 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;
-
-  if (n) {
-    /* Align initial pointer up so that we return properly-aligned pointers. */
-    void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, 16);
-    size_t delta = (uintptr_t)aligned - (uintptr_t)mem;
-    n = delta <= n ? n - delta : 0;
-    mem = aligned;
-  }
-
-  /* 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_CleanupFunc* 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;
-}
-
-/* Miscellaneous utilities ****************************************************/
-
-static void upb_FixLocale(char* p) {
-  /* printf() is dependent on locales; sadly there is no easy and portable way
-   * to avoid this. This little post-processing step will translate 1,2 -> 1.2
-   * since JSON needs the latter. Arguably a hack, but it is simple and the
-   * alternatives are far more complicated, platform-dependent, and/or larger
-   * in code size. */
-  for (; *p; p++) {
-    if (*p == ',') *p = '.';
-  }
-}
-
-void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) {
-  assert(size >= kUpb_RoundTripBufferSize);
-  snprintf(buf, size, "%.*g", DBL_DIG, val);
-  if (strtod(buf, NULL) != val) {
-    snprintf(buf, size, "%.*g", DBL_DIG + 2, val);
-    assert(strtod(buf, NULL) == val);
-  }
-  upb_FixLocale(buf);
-}
-
-void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) {
-  assert(size >= kUpb_RoundTripBufferSize);
-  snprintf(buf, size, "%.*g", FLT_DIG, val);
-  if (strtof(buf, NULL) != val) {
-    snprintf(buf, size, "%.*g", FLT_DIG + 3, val);
-    assert(strtof(buf, NULL) == val);
-  }
-  upb_FixLocale(buf);
-}
-
-/** 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_Decoder *d, const char *ptr, upb_Message *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;
-  int status;
-  ptr = decode_isdonefallback_inl(d, ptr, overrun, &status);
-  if (ptr == NULL) {
-    return fastdecode_err(d, status);
-  }
-  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.
-      const upb_MiniTable* l = decode_totablep(table);
-      return UPB_UNLIKELY(l->required_count)
-                 ? decode_checkrequired(d, ptr, msg, l)
-                 : 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_Decoder* d, const char* ptr,
-                                         void* ctx);
-
-UPB_FORCEINLINE
-static const char* fastdecode_delimited(upb_Decoder* 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_Decoder* 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_Decoder* 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_Message* msg, uint64_t data) {
-  size_t ofs = data >> 48;
-  return (char*)msg + ofs;
-}
-
-UPB_FORCEINLINE
-static void* fastdecode_getfield(upb_Decoder* d, const char* ptr,
-                                 upb_Message* 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, kUpb_DecodeStatus_Malformed);      \
-  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_Decoder* 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, kUpb_DecodeStatus_Malformed);                   \
-  }                                                                          \
-                                                                             \
-  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, kUpb_DecodeStatus_Malformed);                  \
-  }                                                                         \
-                                                                            \
-  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, kUpb_DecodeStatus_Malformed);                \
-    }                                                                       \
-  } 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_Decoder* d,
-                                            const char* ptr, upb_Message* msg,
-                                            const upb_MiniTable* table,
-                                            uint64_t hasbits,
-                                            upb_StringView* dst);
-
-UPB_NOINLINE
-static const char* fastdecode_verifyutf8(upb_Decoder* d, const char* ptr,
-                                         upb_Message* msg, intptr_t table,
-                                         uint64_t hasbits, uint64_t data) {
-  upb_StringView* dst = (upb_StringView*)data;
-  if (!decode_verifyutf8_inl(dst->data, dst->size)) {
-    return fastdecode_err(d, kUpb_DecodeStatus_BadUtf8);
-  }
-  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, kUpb_DecodeStatus_Malformed);                     \
-  }                                                                            \
-                                                                               \
-  if (d->options & kUpb_DecodeOption_AliasString) {                            \
-    dst->data = ptr;                                                           \
-    dst->size = size;                                                          \
-  } else {                                                                     \
-    char* data = upb_Arena_Malloc(&d->arena, size);                            \
-    if (!data) {                                                               \
-      return fastdecode_err(d, kUpb_DecodeStatus_OutOfMemory);                 \
-    }                                                                          \
-    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_Decoder* d,
-                                              const char* ptr, upb_Message* msg,
-                                              intptr_t table, uint64_t hasbits,
-                                              uint64_t data) {
-  upb_StringView* dst = (upb_StringView*)data;
-  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
-}
-
-UPB_NOINLINE
-static const char* fastdecode_longstring_noutf8(
-    struct upb_Decoder* d, const char* ptr, upb_Message* msg, intptr_t table,
-    uint64_t hasbits, uint64_t data) {
-  upb_StringView* dst = (upb_StringView*)data;
-  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
-}
-
-UPB_FORCEINLINE
-static void fastdecode_docopy(upb_Decoder* d, const char* ptr, uint32_t size,
-                              int copy, char* data, upb_StringView* 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_StringView* dst;                                                        \
-  fastdecode_arr farr;                                                        \
-  int64_t size;                                                               \
-  size_t arena_has;                                                           \
-  size_t common_has;                                                          \
-  char* buf;                                                                  \
-                                                                              \
-  UPB_ASSERT((d->options & kUpb_DecodeOption_AliasString) == 0);              \
-  UPB_ASSERT(fastdecode_checktag(data, tagbytes));                            \
-                                                                              \
-  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,              \
-                            sizeof(upb_StringView), card);                    \
-                                                                              \
-  again:                                                                      \
-  if (card == CARD_r) {                                                       \
-    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));        \
-  }                                                                           \
-                                                                              \
-  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, kUpb_DecodeStatus_BadUtf8);                    \
-    }                                                                         \
-    fastdecode_nextret ret = fastdecode_nextrepeated(                         \
-        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));         \
-    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:                                                                    \
-  if (card == CARD_r) {                                                       \
-    fastdecode_commitarr(dst + 1, &farr, sizeof(upb_StringView));             \
-  }                                                                           \
-  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_StringView* 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->options & kUpb_DecodeOption_AliasString) == 0)) {       \
-    UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS);                              \
-  }                                                                            \
-                                                                               \
-  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
-                            sizeof(upb_StringView), card);                     \
-                                                                               \
-  again:                                                                       \
-  if (card == CARD_r) {                                                        \
-    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));         \
-  }                                                                            \
-                                                                               \
-  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, kUpb_DecodeStatus_BadUtf8);                     \
-    }                                                                          \
-    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
-        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));          \
-    switch (ret.next) {                                                        \
-      case FD_NEXT_SAMEFIELD:                                                  \
-        dst = ret.dst;                                                         \
-        if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
-          /* 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_StringView));            \
-          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_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* l,
-                                int msg_ceil_bytes) {
-  size_t size = l->size + sizeof(upb_Message_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_Message_Internal);
-}
-
-typedef struct {
-  intptr_t table;
-  upb_Message* msg;
-} fastdecode_submsgdata;
-
-UPB_FORCEINLINE
-static const char* fastdecode_tosubmsg(upb_Decoder* 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, kUpb_DecodeStatus_MaxDepthExceeded);         \
-  }                                                                       \
-                                                                          \
-  upb_Message** dst;                                                      \
-  uint32_t submsg_idx = (data >> 16) & 0xff;                              \
-  const upb_MiniTable* tablep = decode_totablep(table);                   \
-  const upb_MiniTable* subtablep = tablep->subs[submsg_idx].submsg;       \
-  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_Message*), card);                  \
-                                                                          \
-  if (card == CARD_s) {                                                   \
-    *(uint32_t*)msg |= hasbits;                                           \
-    hasbits = 0;                                                          \
-  }                                                                       \
-                                                                          \
-  again:                                                                  \
-  if (card == CARD_r) {                                                   \
-    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*));      \
-  }                                                                       \
-                                                                          \
-  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, kUpb_DecodeStatus_Malformed);                \
-  }                                                                       \
-                                                                          \
-  if (card == CARD_r) {                                                   \
-    fastdecode_nextret ret = fastdecode_nextrepeated(                     \
-        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*));       \
-    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_MiniTable_Sub google_protobuf_FileDescriptorSet_submsgs[1] = {
-  {.submsg = &google_protobuf_FileDescriptorProto_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FileDescriptorSet__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FileDescriptorSet_msginit = {
-  &google_protobuf_FileDescriptorSet_submsgs[0],
-  &google_protobuf_FileDescriptorSet__fields[0],
-  UPB_SIZE(8, 8), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FileDescriptorProto_submsgs[6] = {
-  {.submsg = &google_protobuf_DescriptorProto_msginit},
-  {.submsg = &google_protobuf_EnumDescriptorProto_msginit},
-  {.submsg = &google_protobuf_FieldDescriptorProto_msginit},
-  {.submsg = &google_protobuf_FileOptions_msginit},
-  {.submsg = &google_protobuf_ServiceDescriptorProto_msginit},
-  {.submsg = &google_protobuf_SourceCodeInfo_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FileDescriptorProto__fields[12] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 24), 2, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(36, 72), 0, 0, 12, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(40, 80), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {5, UPB_SIZE(44, 88), 0, 1, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {6, UPB_SIZE(48, 96), 0, 4, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {7, UPB_SIZE(52, 104), 0, 2, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {8, UPB_SIZE(28, 56), 3, 3, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {9, UPB_SIZE(32, 64), 4, 5, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {10, UPB_SIZE(56, 112), 0, 0, 5, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {11, UPB_SIZE(60, 120), 0, 0, 5, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {12, UPB_SIZE(20, 40), 5, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FileDescriptorProto_msginit = {
-  &google_protobuf_FileDescriptorProto_submsgs[0],
-  &google_protobuf_FileDescriptorProto__fields[0],
-  UPB_SIZE(64, 128), 12, kUpb_ExtMode_NonExtendable, 12, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_DescriptorProto_submsgs[7] = {
-  {.submsg = &google_protobuf_DescriptorProto_msginit},
-  {.submsg = &google_protobuf_DescriptorProto_ExtensionRange_msginit},
-  {.submsg = &google_protobuf_DescriptorProto_ReservedRange_msginit},
-  {.submsg = &google_protobuf_EnumDescriptorProto_msginit},
-  {.submsg = &google_protobuf_FieldDescriptorProto_msginit},
-  {.submsg = &google_protobuf_MessageOptions_msginit},
-  {.submsg = &google_protobuf_OneofDescriptorProto_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_DescriptorProto__fields[10] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(16, 32), 0, 4, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(20, 40), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(24, 48), 0, 3, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {5, UPB_SIZE(28, 56), 0, 1, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {6, UPB_SIZE(32, 64), 0, 4, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {7, UPB_SIZE(12, 24), 2, 5, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {8, UPB_SIZE(36, 72), 0, 6, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {9, UPB_SIZE(40, 80), 0, 2, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {10, UPB_SIZE(44, 88), 0, 0, 12, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_DescriptorProto_msginit = {
-  &google_protobuf_DescriptorProto_submsgs[0],
-  &google_protobuf_DescriptorProto__fields[0],
-  UPB_SIZE(48, 96), 10, kUpb_ExtMode_NonExtendable, 10, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_DescriptorProto_ExtensionRange_submsgs[1] = {
-  {.submsg = &google_protobuf_ExtensionRangeOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_DescriptorProto_ExtensionRange__fields[3] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msginit = {
-  &google_protobuf_DescriptorProto_ExtensionRange_submsgs[0],
-  &google_protobuf_DescriptorProto_ExtensionRange__fields[0],
-  UPB_SIZE(16, 24), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_DescriptorProto_ReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msginit = {
-  NULL,
-  &google_protobuf_DescriptorProto_ReservedRange__fields[0],
-  UPB_SIZE(16, 16), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_ExtensionRangeOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_ExtensionRangeOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_ExtensionRangeOptions_msginit = {
-  &google_protobuf_ExtensionRangeOptions_submsgs[0],
-  &google_protobuf_ExtensionRangeOptions__fields[0],
-  UPB_SIZE(8, 8), 1, kUpb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FieldDescriptorProto_submsgs[3] = {
-  {.submsg = &google_protobuf_FieldOptions_msginit},
-  {.subenum = &google_protobuf_FieldDescriptorProto_Label_enuminit},
-  {.subenum = &google_protobuf_FieldDescriptorProto_Type_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FieldDescriptorProto__fields[11] = {
-  {1, UPB_SIZE(24, 24), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(32, 40), 2, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 12), 3, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(4, 4), 4, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {5, UPB_SIZE(8, 8), 5, 2, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {6, UPB_SIZE(40, 56), 6, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {7, UPB_SIZE(48, 72), 7, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {8, UPB_SIZE(64, 104), 8, 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {9, UPB_SIZE(16, 16), 9, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {10, UPB_SIZE(56, 88), 10, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {17, UPB_SIZE(20, 20), 11, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FieldDescriptorProto_msginit = {
-  &google_protobuf_FieldDescriptorProto_submsgs[0],
-  &google_protobuf_FieldDescriptorProto__fields[0],
-  UPB_SIZE(72, 112), 11, kUpb_ExtMode_NonExtendable, 10, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_OneofDescriptorProto_submsgs[1] = {
-  {.submsg = &google_protobuf_OneofOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_OneofDescriptorProto__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_OneofDescriptorProto_msginit = {
-  &google_protobuf_OneofDescriptorProto_submsgs[0],
-  &google_protobuf_OneofDescriptorProto__fields[0],
-  UPB_SIZE(16, 32), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumDescriptorProto_submsgs[3] = {
-  {.submsg = &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit},
-  {.submsg = &google_protobuf_EnumOptions_msginit},
-  {.submsg = &google_protobuf_EnumValueDescriptorProto_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumDescriptorProto__fields[5] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(16, 32), 0, 2, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(20, 40), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {5, UPB_SIZE(24, 48), 0, 0, 12, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumDescriptorProto_msginit = {
-  &google_protobuf_EnumDescriptorProto_submsgs[0],
-  &google_protobuf_EnumDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 5, kUpb_ExtMode_NonExtendable, 5, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[2] = {
-  {1, UPB_SIZE(4, 4), 1, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(8, 8), 2, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit = {
-  NULL,
-  &google_protobuf_EnumDescriptorProto_EnumReservedRange__fields[0],
-  UPB_SIZE(16, 16), 2, kUpb_ExtMode_NonExtendable, 2, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumValueDescriptorProto_submsgs[1] = {
-  {.submsg = &google_protobuf_EnumValueOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumValueDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(8, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(4, 4), 2, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(16, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msginit = {
-  &google_protobuf_EnumValueDescriptorProto_submsgs[0],
-  &google_protobuf_EnumValueDescriptorProto__fields[0],
-  UPB_SIZE(24, 32), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_ServiceDescriptorProto_submsgs[2] = {
-  {.submsg = &google_protobuf_MethodDescriptorProto_msginit},
-  {.submsg = &google_protobuf_ServiceOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_ServiceDescriptorProto__fields[3] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(16, 32), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(12, 24), 2, 1, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_ServiceDescriptorProto_msginit = {
-  &google_protobuf_ServiceDescriptorProto_submsgs[0],
-  &google_protobuf_ServiceDescriptorProto__fields[0],
-  UPB_SIZE(24, 48), 3, kUpb_ExtMode_NonExtendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_MethodDescriptorProto_submsgs[1] = {
-  {.submsg = &google_protobuf_MethodOptions_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_MethodDescriptorProto__fields[6] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 24), 2, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(20, 40), 3, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(28, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {5, UPB_SIZE(1, 1), 5, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {6, UPB_SIZE(2, 2), 6, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_MethodDescriptorProto_msginit = {
-  &google_protobuf_MethodDescriptorProto_submsgs[0],
-  &google_protobuf_MethodDescriptorProto__fields[0],
-  UPB_SIZE(32, 64), 6, kUpb_ExtMode_NonExtendable, 6, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FileOptions_submsgs[2] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-  {.subenum = &google_protobuf_FileOptions_OptimizeMode_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FileOptions__fields[21] = {
-  {1, UPB_SIZE(20, 24), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {8, UPB_SIZE(28, 40), 2, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {9, UPB_SIZE(4, 4), 3, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {10, UPB_SIZE(8, 8), 4, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {11, UPB_SIZE(36, 56), 5, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {16, UPB_SIZE(9, 9), 6, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {17, UPB_SIZE(10, 10), 7, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {18, UPB_SIZE(11, 11), 8, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {20, UPB_SIZE(12, 12), 9, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {23, UPB_SIZE(13, 13), 10, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {27, UPB_SIZE(14, 14), 11, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {31, UPB_SIZE(15, 15), 12, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {36, UPB_SIZE(44, 72), 13, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {37, UPB_SIZE(52, 88), 14, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {39, UPB_SIZE(60, 104), 15, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {40, UPB_SIZE(68, 120), 16, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {41, UPB_SIZE(76, 136), 17, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {42, UPB_SIZE(16, 16), 18, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {44, UPB_SIZE(84, 152), 19, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {45, UPB_SIZE(92, 168), 20, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {999, UPB_SIZE(100, 184), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FileOptions_msginit = {
-  &google_protobuf_FileOptions_submsgs[0],
-  &google_protobuf_FileOptions__fields[0],
-  UPB_SIZE(104, 192), 21, kUpb_ExtMode_Extendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_MessageOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_MessageOptions__fields[5] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(2, 2), 2, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(3, 3), 3, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {7, UPB_SIZE(4, 4), 4, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {999, UPB_SIZE(8, 8), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_MessageOptions_msginit = {
-  &google_protobuf_MessageOptions_submsgs[0],
-  &google_protobuf_MessageOptions__fields[0],
-  UPB_SIZE(16, 16), 5, kUpb_ExtMode_Extendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_FieldOptions_submsgs[3] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-  {.subenum = &google_protobuf_FieldOptions_CType_enuminit},
-  {.subenum = &google_protobuf_FieldOptions_JSType_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_FieldOptions__fields[8] = {
-  {1, UPB_SIZE(4, 4), 1, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 12), 2, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(13, 13), 3, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {5, UPB_SIZE(14, 14), 4, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {6, UPB_SIZE(8, 8), 5, 2, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {10, UPB_SIZE(15, 15), 6, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {15, UPB_SIZE(16, 16), 7, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {999, UPB_SIZE(20, 24), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_FieldOptions_msginit = {
-  &google_protobuf_FieldOptions_submsgs[0],
-  &google_protobuf_FieldOptions__fields[0],
-  UPB_SIZE(24, 32), 8, kUpb_ExtMode_Extendable, 3, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_OneofOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_OneofOptions__fields[1] = {
-  {999, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_OneofOptions_msginit = {
-  &google_protobuf_OneofOptions_submsgs[0],
-  &google_protobuf_OneofOptions__fields[0],
-  UPB_SIZE(8, 8), 1, kUpb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumOptions__fields[3] = {
-  {2, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(2, 2), 2, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumOptions_msginit = {
-  &google_protobuf_EnumOptions_submsgs[0],
-  &google_protobuf_EnumOptions__fields[0],
-  UPB_SIZE(8, 16), 3, kUpb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_EnumValueOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_EnumValueOptions__fields[2] = {
-  {1, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_EnumValueOptions_msginit = {
-  &google_protobuf_EnumValueOptions_submsgs[0],
-  &google_protobuf_EnumValueOptions__fields[0],
-  UPB_SIZE(8, 16), 2, kUpb_ExtMode_Extendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_ServiceOptions_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_ServiceOptions__fields[2] = {
-  {33, UPB_SIZE(1, 1), 1, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_ServiceOptions_msginit = {
-  &google_protobuf_ServiceOptions_submsgs[0],
-  &google_protobuf_ServiceOptions__fields[0],
-  UPB_SIZE(8, 16), 2, kUpb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_MethodOptions_submsgs[2] = {
-  {.submsg = &google_protobuf_UninterpretedOption_msginit},
-  {.subenum = &google_protobuf_MethodOptions_IdempotencyLevel_enuminit},
-};
-
-static const upb_MiniTable_Field google_protobuf_MethodOptions__fields[3] = {
-  {33, UPB_SIZE(8, 8), 1, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-  {34, UPB_SIZE(4, 4), 2, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {999, UPB_SIZE(12, 16), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_MethodOptions_msginit = {
-  &google_protobuf_MethodOptions_submsgs[0],
-  &google_protobuf_MethodOptions__fields[0],
-  UPB_SIZE(16, 24), 3, kUpb_ExtMode_Extendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_UninterpretedOption_submsgs[1] = {
-  {.submsg = &google_protobuf_UninterpretedOption_NamePart_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_UninterpretedOption__fields[7] = {
-  {2, UPB_SIZE(56, 80), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(32, 32), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(8, 8), 2, 0, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
-  {5, UPB_SIZE(16, 16), 3, 0, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
-  {6, UPB_SIZE(24, 24), 4, 0, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)},
-  {7, UPB_SIZE(40, 48), 5, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {8, UPB_SIZE(48, 64), 6, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_UninterpretedOption_msginit = {
-  &google_protobuf_UninterpretedOption_submsgs[0],
-  &google_protobuf_UninterpretedOption__fields[0],
-  UPB_SIZE(64, 96), 7, kUpb_ExtMode_NonExtendable, 0, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_UninterpretedOption_NamePart__fields[2] = {
-  {1, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(1, 1), 2, 0, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msginit = {
-  NULL,
-  &google_protobuf_UninterpretedOption_NamePart__fields[0],
-  UPB_SIZE(16, 32), 2, kUpb_ExtMode_NonExtendable, 2, 255, 2,
-};
-
-static const upb_MiniTable_Sub google_protobuf_SourceCodeInfo_submsgs[1] = {
-  {.submsg = &google_protobuf_SourceCodeInfo_Location_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_SourceCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_SourceCodeInfo_msginit = {
-  &google_protobuf_SourceCodeInfo_submsgs[0],
-  &google_protobuf_SourceCodeInfo__fields[0],
-  UPB_SIZE(8, 8), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_SourceCodeInfo_Location__fields[5] = {
-  {1, UPB_SIZE(20, 40), 0, 0, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(24, 48), 0, 0, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(4, 8), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(12, 24), 2, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {6, UPB_SIZE(28, 56), 0, 0, 12, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msginit = {
-  NULL,
-  &google_protobuf_SourceCodeInfo_Location__fields[0],
-  UPB_SIZE(32, 64), 5, kUpb_ExtMode_NonExtendable, 4, 255, 0,
-};
-
-static const upb_MiniTable_Sub google_protobuf_GeneratedCodeInfo_submsgs[1] = {
-  {.submsg = &google_protobuf_GeneratedCodeInfo_Annotation_msginit},
-};
-
-static const upb_MiniTable_Field google_protobuf_GeneratedCodeInfo__fields[1] = {
-  {1, UPB_SIZE(0, 0), 0, 0, 11, kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_GeneratedCodeInfo_msginit = {
-  &google_protobuf_GeneratedCodeInfo_submsgs[0],
-  &google_protobuf_GeneratedCodeInfo__fields[0],
-  UPB_SIZE(8, 8), 1, kUpb_ExtMode_NonExtendable, 1, 255, 0,
-};
-
-static const upb_MiniTable_Field google_protobuf_GeneratedCodeInfo_Annotation__fields[4] = {
-  {1, UPB_SIZE(20, 32), 0, 0, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift)},
-  {2, UPB_SIZE(12, 16), 1, 0, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)},
-  {3, UPB_SIZE(4, 4), 2, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-  {4, UPB_SIZE(8, 8), 3, 0, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)},
-};
-
-const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msginit = {
-  NULL,
-  &google_protobuf_GeneratedCodeInfo_Annotation__fields[0],
-  UPB_SIZE(24, 48), 4, kUpb_ExtMode_NonExtendable, 4, 255, 0,
-};
-
-static const upb_MiniTable *messages_layout[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,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Type_enuminit = {
-  NULL,
-  0x7fffeULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Label_enuminit = {
-  NULL,
-  0xeULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FileOptions_OptimizeMode_enuminit = {
-  NULL,
-  0xeULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldOptions_CType_enuminit = {
-  NULL,
-  0x7ULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_FieldOptions_JSType_enuminit = {
-  NULL,
-  0x7ULL,
-  0,
-};
-
-const upb_MiniTable_Enum google_protobuf_MethodOptions_IdempotencyLevel_enuminit = {
-  NULL,
-  0x7ULL,
-  0,
-};
-
-static const upb_MiniTable_Enum *enums_layout[6] = {
-  &google_protobuf_FieldDescriptorProto_Type_enuminit,
-  &google_protobuf_FieldDescriptorProto_Label_enuminit,
-  &google_protobuf_FileOptions_OptimizeMode_enuminit,
-  &google_protobuf_FieldOptions_CType_enuminit,
-  &google_protobuf_FieldOptions_JSType_enuminit,
-  &google_protobuf_MethodOptions_IdempotencyLevel_enuminit,
-};
-
-const upb_MiniTable_File google_protobuf_descriptor_proto_upb_file_layout = {
-  messages_layout,
-  enums_layout,
-  NULL,
-  27,
-  6,
-  0,
-};
-
-
-
-/** 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;
-
-/* The upb core does not generally have a concept of default instances. However
- * for descriptor options we make an exception since the max size is known and
- * modest (<200 bytes). All types can share a default instance since it is
- * initialized to zeroes.
- *
- * We have to allocate an extra pointer for upb's internal metadata. */
-static const char opt_default_buf[_UPB_MAXOPT_SIZE + sizeof(void*)] = {0};
-static const char* opt_default = &opt_default_buf[sizeof(void*)];
-
-struct upb_FieldDef {
-  const google_protobuf_FieldOptions* opts;
-  const upb_FileDef* file;
-  const upb_MessageDef* 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;
-  union {
-    const upb_OneofDef* oneof;
-    const upb_MessageDef* extension_scope;
-  } scope;
-  union {
-    const upb_MessageDef* msgdef;
-    const upb_EnumDef* enumdef;
-    const google_protobuf_FieldDescriptorProto* unresolved;
-  } sub;
-  uint32_t number_;
-  uint16_t index_;
-  uint16_t layout_index; /* Index into msgdef->layout->fields or file->exts */
-  bool has_default;
-  bool is_extension_;
-  bool packed_;
-  bool proto3_optional_;
-  bool has_json_name_;
-  upb_FieldType type_;
-  upb_Label label_;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_ExtensionRange {
-  const google_protobuf_ExtensionRangeOptions* opts;
-  int32_t start;
-  int32_t end;
-};
-
-struct upb_MessageDef {
-  const google_protobuf_MessageOptions* opts;
-  const upb_MiniTable* layout;
-  const upb_FileDef* file;
-  const upb_MessageDef* containing_type;
-  const char* full_name;
-
-  /* Tables for looking up fields by number and name. */
-  upb_inttable itof;
-  upb_strtable ntof;
-
-  /* All nested defs.
-   * MEM: We could save some space here by putting nested defs in a contiguous
-   * region and calculating counts from offsets or vice-versa. */
-  const upb_FieldDef* fields;
-  const upb_OneofDef* oneofs;
-  const upb_ExtensionRange* ext_ranges;
-  const upb_MessageDef* nested_msgs;
-  const upb_EnumDef* nested_enums;
-  const upb_FieldDef* nested_exts;
-  int field_count;
-  int real_oneof_count;
-  int oneof_count;
-  int ext_range_count;
-  int nested_msg_count;
-  int nested_enum_count;
-  int nested_ext_count;
-  bool in_message_set;
-  upb_WellKnown well_known_type;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_EnumDef {
-  const google_protobuf_EnumOptions* opts;
-  const upb_MiniTable_Enum* layout;  // Only for proto2.
-  const upb_FileDef* file;
-  const upb_MessageDef* containing_type;  // Could be merged with "file".
-  const char* full_name;
-  upb_strtable ntoi;
-  upb_inttable iton;
-  const upb_EnumValueDef* values;
-  int value_count;
-  int32_t defaultval;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_EnumValueDef {
-  const google_protobuf_EnumValueOptions* opts;
-  const upb_EnumDef* parent;
-  const char* full_name;
-  int32_t number;
-};
-
-struct upb_OneofDef {
-  const google_protobuf_OneofOptions* opts;
-  const upb_MessageDef* parent;
-  const char* full_name;
-  int field_count;
-  bool synthetic;
-  const upb_FieldDef** fields;
-  upb_strtable ntof;
-  upb_inttable itof;
-#if UINTPTR_MAX == 0xffffffff
-  uint32_t padding;  // Increase size to a multiple of 8.
-#endif
-};
-
-struct upb_FileDef {
-  const google_protobuf_FileOptions* opts;
-  const char* name;
-  const char* package;
-
-  const upb_FileDef** deps;
-  const int32_t* public_deps;
-  const int32_t* weak_deps;
-  const upb_MessageDef* top_lvl_msgs;
-  const upb_EnumDef* top_lvl_enums;
-  const upb_FieldDef* top_lvl_exts;
-  const upb_ServiceDef* services;
-  const upb_MiniTable_Extension** ext_layouts;
-  const upb_DefPool* symtab;
-
-  int dep_count;
-  int public_dep_count;
-  int weak_dep_count;
-  int top_lvl_msg_count;
-  int top_lvl_enum_count;
-  int top_lvl_ext_count;
-  int service_count;
-  int ext_count; /* All exts in the file. */
-  upb_Syntax syntax;
-};
-
-struct upb_MethodDef {
-  const google_protobuf_MethodOptions* opts;
-  upb_ServiceDef* service;
-  const char* full_name;
-  const upb_MessageDef* input_type;
-  const upb_MessageDef* output_type;
-  int index;
-  bool client_streaming;
-  bool server_streaming;
-};
-
-struct upb_ServiceDef {
-  const google_protobuf_ServiceOptions* opts;
-  const upb_FileDef* file;
-  const char* full_name;
-  upb_MethodDef* methods;
-  int method_count;
-  int index;
-};
-
-struct upb_DefPool {
-  upb_Arena* arena;
-  upb_strtable syms;  /* full_name -> packed def ptr */
-  upb_strtable files; /* file_name -> upb_FileDef* */
-  upb_inttable exts;  /* upb_MiniTable_Extension* -> upb_FieldDef* */
-  upb_ExtensionRegistry* extreg;
-  size_t bytes_loaded;
-};
-
-/* Inside a symtab we store tagged pointers to specific def types. */
-typedef enum {
-  UPB_DEFTYPE_MASK = 7,
-
-  /* Only inside symtab table. */
-  UPB_DEFTYPE_EXT = 0,
-  UPB_DEFTYPE_MSG = 1,
-  UPB_DEFTYPE_ENUM = 2,
-  UPB_DEFTYPE_ENUMVAL = 3,
-  UPB_DEFTYPE_SERVICE = 4,
-
-  /* Only inside message table. */
-  UPB_DEFTYPE_FIELD = 0,
-  UPB_DEFTYPE_ONEOF = 1,
-  UPB_DEFTYPE_FIELD_JSONNAME = 2,
-
-  /* Only inside file table. */
-  UPB_DEFTYPE_FILE = 0,
-  UPB_DEFTYPE_LAYOUT = 1
-} upb_deftype_t;
-
-#define FIELD_TYPE_UNSPECIFIED 0
-
-static upb_deftype_t deftype(upb_value v) {
-  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
-  return num & UPB_DEFTYPE_MASK;
-}
-
-static const void* unpack_def(upb_value v, upb_deftype_t type) {
-  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
-  return (num & UPB_DEFTYPE_MASK) == type
-             ? (const void*)(num & ~UPB_DEFTYPE_MASK)
-             : NULL;
-}
-
-static upb_value pack_def(const void* ptr, upb_deftype_t type) {
-  // Our 3-bit pointer tagging requires all pointers to be multiples of 8.
-  // The arena will always yield 8-byte-aligned addresses, however we put
-  // the defs into arrays.  For each element in the array to be 8-byte-aligned,
-  // the sizes of each def type must also be a multiple of 8.
-  //
-  // If any of these asserts fail, we need to add or remove padding on 32-bit
-  // machines (64-bit machines will have 8-byte alignment already due to
-  // pointers, which all of these structs have).
-  UPB_ASSERT((sizeof(upb_FieldDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_MessageDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_EnumDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_EnumValueDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_ServiceDef) & UPB_DEFTYPE_MASK) == 0);
-  UPB_ASSERT((sizeof(upb_OneofDef) & UPB_DEFTYPE_MASK) == 0);
-  uintptr_t num = (uintptr_t)ptr;
-  UPB_ASSERT((num & UPB_DEFTYPE_MASK) == 0);
-  num |= 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(uint8_t c, uint8_t low, uint8_t high) {
-  return c >= low && c <= high;
-}
-
-static char upb_ascii_lower(char ch) {
-  // Per ASCII this will lower-case a letter.  If the result is a letter, the
-  // input was definitely a letter.  If the output is not a letter, this may
-  // have transformed the character unpredictably.
-  return ch | 0x20;
-}
-
-static bool upb_isletter(char c) {
-  char lower = upb_ascii_lower(c);
-  return upb_isbetween(lower, '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_IsSubMessage(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_SetErrorMessage(status, "out of memory");
-}
-
-static void assign_msg_wellknowntype(upb_MessageDef* m) {
-  const char* name = upb_MessageDef_FullName(m);
-  if (name == NULL) {
-    m->well_known_type = kUpb_WellKnown_Unspecified;
-    return;
-  }
-  if (!strcmp(name, "google.protobuf.Any")) {
-    m->well_known_type = kUpb_WellKnown_Any;
-  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
-    m->well_known_type = kUpb_WellKnown_FieldMask;
-  } else if (!strcmp(name, "google.protobuf.Duration")) {
-    m->well_known_type = kUpb_WellKnown_Duration;
-  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
-    m->well_known_type = kUpb_WellKnown_Timestamp;
-  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
-    m->well_known_type = kUpb_WellKnown_DoubleValue;
-  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
-    m->well_known_type = kUpb_WellKnown_FloatValue;
-  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
-    m->well_known_type = kUpb_WellKnown_Int64Value;
-  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
-    m->well_known_type = kUpb_WellKnown_UInt64Value;
-  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
-    m->well_known_type = kUpb_WellKnown_Int32Value;
-  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
-    m->well_known_type = kUpb_WellKnown_UInt32Value;
-  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
-    m->well_known_type = kUpb_WellKnown_BoolValue;
-  } else if (!strcmp(name, "google.protobuf.StringValue")) {
-    m->well_known_type = kUpb_WellKnown_StringValue;
-  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
-    m->well_known_type = kUpb_WellKnown_BytesValue;
-  } else if (!strcmp(name, "google.protobuf.Value")) {
-    m->well_known_type = kUpb_WellKnown_Value;
-  } else if (!strcmp(name, "google.protobuf.ListValue")) {
-    m->well_known_type = kUpb_WellKnown_ListValue;
-  } else if (!strcmp(name, "google.protobuf.Struct")) {
-    m->well_known_type = kUpb_WellKnown_Struct;
-  } else {
-    m->well_known_type = kUpb_WellKnown_Unspecified;
-  }
-}
-
-/* upb_EnumDef ****************************************************************/
-
-const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) {
-  return e->opts;
-}
-
-bool upb_EnumDef_HasOptions(const upb_EnumDef* e) {
-  return e->opts != (void*)opt_default;
-}
-
-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; }
-
-const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e) {
-  return e->containing_type;
-}
-
-int32_t upb_EnumDef_Default(const upb_EnumDef* e) {
-  UPB_ASSERT(upb_EnumDef_FindValueByNumber(e, e->defaultval));
-  return e->defaultval;
-}
-
-int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; }
-
-const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
-    const upb_EnumDef* def, const char* name, size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&def->ntoi, name, len, &v)
-             ? upb_value_getconstptr(v)
-             : NULL;
-}
-
-const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* def,
-                                                      int32_t num) {
-  upb_value v;
-  return upb_inttable_lookup(&def->iton, num, &v) ? upb_value_getconstptr(v)
-                                                  : NULL;
-}
-
-bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num) {
-  // We could use upb_EnumDef_FindValueByNumber(e, num) != NULL, but we expect
-  // this to be faster (especially for small numbers).
-  return upb_MiniTable_Enum_CheckValue(e->layout, num);
-}
-
-const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) {
-  UPB_ASSERT(0 <= i && i < e->value_count);
-  return &e->values[i];
-}
-
-/* upb_EnumValueDef ***********************************************************/
-
-const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
-    const upb_EnumValueDef* e) {
-  return e->opts;
-}
-
-bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* e) {
-  return e->opts != (void*)opt_default;
-}
-
-const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* ev) {
-  return ev->parent;
-}
-
-const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* ev) {
-  return ev->full_name;
-}
-
-const char* upb_EnumValueDef_Name(const upb_EnumValueDef* ev) {
-  return shortdefname(ev->full_name);
-}
-
-int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* ev) {
-  return ev->number;
-}
-
-uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* ev) {
-  // Compute index in our parent's array.
-  return ev - ev->parent->values;
-}
-
-/* upb_ExtensionRange
- * ***************************************************************/
-
-const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
-    const upb_ExtensionRange* r) {
-  return r->opts;
-}
-
-bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r) {
-  return r->opts != (void*)opt_default;
-}
-
-int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* e) {
-  return e->start;
-}
-
-int32_t upb_ExtensionRange_End(const upb_ExtensionRange* e) { return e->end; }
-
-/* upb_FieldDef ***************************************************************/
-
-const google_protobuf_FieldOptions* upb_FieldDef_Options(
-    const upb_FieldDef* f) {
-  return f->opts;
-}
-
-bool upb_FieldDef_HasOptions(const upb_FieldDef* f) {
-  return f->opts != (void*)opt_default;
-}
-
-const char* upb_FieldDef_FullName(const upb_FieldDef* f) {
-  return f->full_name;
-}
-
-upb_CType upb_FieldDef_CType(const upb_FieldDef* f) {
-  switch (f->type_) {
-    case kUpb_FieldType_Double:
-      return kUpb_CType_Double;
-    case kUpb_FieldType_Float:
-      return kUpb_CType_Float;
-    case kUpb_FieldType_Int64:
-    case kUpb_FieldType_SInt64:
-    case kUpb_FieldType_SFixed64:
-      return kUpb_CType_Int64;
-    case kUpb_FieldType_Int32:
-    case kUpb_FieldType_SFixed32:
-    case kUpb_FieldType_SInt32:
-      return kUpb_CType_Int32;
-    case kUpb_FieldType_UInt64:
-    case kUpb_FieldType_Fixed64:
-      return kUpb_CType_UInt64;
-    case kUpb_FieldType_UInt32:
-    case kUpb_FieldType_Fixed32:
-      return kUpb_CType_UInt32;
-    case kUpb_FieldType_Enum:
-      return kUpb_CType_Enum;
-    case kUpb_FieldType_Bool:
-      return kUpb_CType_Bool;
-    case kUpb_FieldType_String:
-      return kUpb_CType_String;
-    case kUpb_FieldType_Bytes:
-      return kUpb_CType_Bytes;
-    case kUpb_FieldType_Group:
-    case kUpb_FieldType_Message:
-      return kUpb_CType_Message;
-  }
-  UPB_UNREACHABLE();
-}
-
-upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { return f->type_; }
-
-uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; }
-
-upb_Label 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_IsPacked(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;
-}
-
-bool upb_FieldDef_HasJsonName(const upb_FieldDef* f) {
-  return f->has_json_name_;
-}
-
-const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f) { return f->file; }
-
-const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f) {
-  return f->msgdef;
-}
-
-const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f) {
-  return f->is_extension_ ? f->scope.extension_scope : NULL;
-}
-
-const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f) {
-  return f->is_extension_ ? NULL : f->scope.oneof;
-}
-
-const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f) {
-  const upb_OneofDef* oneof = upb_FieldDef_ContainingOneof(f);
-  if (!oneof || upb_OneofDef_IsSynthetic(oneof)) return NULL;
-  return oneof;
-}
-
-upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f) {
-  UPB_ASSERT(!upb_FieldDef_IsSubMessage(f));
-  upb_MessageValue ret;
-
-  switch (upb_FieldDef_CType(f)) {
-    case kUpb_CType_Bool:
-      return (upb_MessageValue){.bool_val = f->defaultval.boolean};
-    case kUpb_CType_Int64:
-      return (upb_MessageValue){.int64_val = f->defaultval.sint};
-    case kUpb_CType_UInt64:
-      return (upb_MessageValue){.uint64_val = f->defaultval.uint};
-    case kUpb_CType_Enum:
-    case kUpb_CType_Int32:
-      return (upb_MessageValue){.int32_val = (int32_t)f->defaultval.sint};
-    case kUpb_CType_UInt32:
-      return (upb_MessageValue){.uint32_val = (uint32_t)f->defaultval.uint};
-    case kUpb_CType_Float:
-      return (upb_MessageValue){.float_val = f->defaultval.flt};
-    case kUpb_CType_Double:
-      return (upb_MessageValue){.double_val = f->defaultval.dbl};
-    case kUpb_CType_String:
-    case kUpb_CType_Bytes: {
-      str_t* str = f->defaultval.str;
-      if (str) {
-        return (upb_MessageValue){
-            .str_val = (upb_StringView){.data = str->str, .size = str->len}};
-      } else {
-        return (upb_MessageValue){
-            .str_val = (upb_StringView){.data = NULL, .size = 0}};
-      }
-    }
-    default:
-      UPB_UNREACHABLE();
-  }
-
-  return ret;
-}
-
-const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_Message ? f->sub.msgdef : NULL;
-}
-
-const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_Enum ? f->sub.enumdef : NULL;
-}
-
-const upb_MiniTable_Field* upb_FieldDef_MiniTable(const upb_FieldDef* f) {
-  UPB_ASSERT(!upb_FieldDef_IsExtension(f));
-  return &f->msgdef->layout->fields[f->layout_index];
-}
-
-const upb_MiniTable_Extension* _upb_FieldDef_ExtensionMiniTable(
-    const upb_FieldDef* f) {
-  UPB_ASSERT(upb_FieldDef_IsExtension(f));
-  return f->file->ext_layouts[f->layout_index];
-}
-
-bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f) {
-  return f->proto3_optional_;
-}
-
-bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_Message;
-}
-
-bool upb_FieldDef_IsString(const upb_FieldDef* f) {
-  return upb_FieldDef_CType(f) == kUpb_CType_String ||
-         upb_FieldDef_CType(f) == kUpb_CType_Bytes;
-}
-
-bool upb_FieldDef_IsRepeated(const upb_FieldDef* f) {
-  return upb_FieldDef_Label(f) == kUpb_Label_Repeated;
-}
-
-bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f) {
-  return !upb_FieldDef_IsString(f) && !upb_FieldDef_IsSubMessage(f);
-}
-
-bool upb_FieldDef_IsMap(const upb_FieldDef* f) {
-  return upb_FieldDef_IsRepeated(f) && upb_FieldDef_IsSubMessage(f) &&
-         upb_MessageDef_IsMapEntry(upb_FieldDef_MessageSubDef(f));
-}
-
-bool upb_FieldDef_HasDefault(const upb_FieldDef* f) { return f->has_default; }
-
-bool upb_FieldDef_HasSubDef(const upb_FieldDef* f) {
-  return upb_FieldDef_IsSubMessage(f) ||
-         upb_FieldDef_CType(f) == kUpb_CType_Enum;
-}
-
-bool upb_FieldDef_HasPresence(const upb_FieldDef* f) {
-  if (upb_FieldDef_IsRepeated(f)) return false;
-  return upb_FieldDef_IsSubMessage(f) || upb_FieldDef_ContainingOneof(f) ||
-         f->file->syntax == kUpb_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_MessageDef
- * *****************************************************************/
-
-const google_protobuf_MessageOptions* upb_MessageDef_Options(
-    const upb_MessageDef* m) {
-  return m->opts;
-}
-
-bool upb_MessageDef_HasOptions(const upb_MessageDef* m) {
-  return m->opts != (void*)opt_default;
-}
-
-const char* upb_MessageDef_FullName(const upb_MessageDef* m) {
-  return m->full_name;
-}
-
-const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m) {
-  return m->file;
-}
-
-const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m) {
-  return m->containing_type;
-}
-
-const char* upb_MessageDef_Name(const upb_MessageDef* m) {
-  return shortdefname(m->full_name);
-}
-
-upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m) {
-  return m->file->syntax;
-}
-
-const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
-                                                     uint32_t i) {
-  upb_value val;
-  return upb_inttable_lookup(&m->itof, i, &val) ? upb_value_getconstptr(val)
-                                                : NULL;
-}
-
-const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
-    const upb_MessageDef* 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_MessageDef_FindOneofByNameWithSize(
-    const upb_MessageDef* 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_MessageDef_FindByNameWithSize(const upb_MessageDef* m,
-                                       const char* name, size_t len,
-                                       const upb_FieldDef** out_f,
-                                       const upb_OneofDef** out_o) {
-  upb_value val;
-
-  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
-    return false;
-  }
-
-  const upb_FieldDef* f = unpack_def(val, UPB_DEFTYPE_FIELD);
-  const upb_OneofDef* o = unpack_def(val, UPB_DEFTYPE_ONEOF);
-  if (out_f) *out_f = f;
-  if (out_o) *out_o = o;
-  return f || o; /* False if this was a JSON name. */
-}
-
-const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
-    const upb_MessageDef* 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_MessageDef_numfields(const upb_MessageDef* m) { return m->field_count; }
-
-int upb_MessageDef_numoneofs(const upb_MessageDef* m) { return m->oneof_count; }
-
-int upb_MessageDef_numrealoneofs(const upb_MessageDef* m) {
-  return m->real_oneof_count;
-}
-
-int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m) {
-  return m->ext_range_count;
-}
-
-int upb_MessageDef_FieldCount(const upb_MessageDef* m) {
-  return m->field_count;
-}
-
-int upb_MessageDef_OneofCount(const upb_MessageDef* m) {
-  return m->oneof_count;
-}
-
-int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m) {
-  return m->nested_msg_count;
-}
-
-int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m) {
-  return m->nested_enum_count;
-}
-
-int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m) {
-  return m->nested_ext_count;
-}
-
-int upb_MessageDef_realoneofcount(const upb_MessageDef* m) {
-  return m->real_oneof_count;
-}
-
-const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m) {
-  return m->layout;
-}
-
-const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m,
-                                                        int i) {
-  UPB_ASSERT(0 <= i && i < m->ext_range_count);
-  return &m->ext_ranges[i];
-}
-
-const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, int i) {
-  UPB_ASSERT(0 <= i && i < m->field_count);
-  return &m->fields[i];
-}
-
-const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i) {
-  UPB_ASSERT(0 <= i && i < m->oneof_count);
-  return &m->oneofs[i];
-}
-
-const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
-                                                   int i) {
-  UPB_ASSERT(0 <= i && i < m->nested_msg_count);
-  return &m->nested_msgs[i];
-}
-
-const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i) {
-  UPB_ASSERT(0 <= i && i < m->nested_enum_count);
-  return &m->nested_enums[i];
-}
-
-const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
-                                                   int i) {
-  UPB_ASSERT(0 <= i && i < m->nested_ext_count);
-  return &m->nested_exts[i];
-}
-
-upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m) {
-  return m->well_known_type;
-}
-
-/* upb_OneofDef ***************************************************************/
-
-const google_protobuf_OneofOptions* upb_OneofDef_Options(
-    const upb_OneofDef* o) {
-  return o->opts;
-}
-
-bool upb_OneofDef_HasOptions(const upb_OneofDef* o) {
-  return o->opts != (void*)opt_default;
-}
-
-const char* upb_OneofDef_Name(const upb_OneofDef* o) {
-  return shortdefname(o->full_name);
-}
-
-const upb_MessageDef* 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) {
-  // Compute index in our parent's array.
-  return o - o->parent->oneofs;
-}
-
-bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o) { return o->synthetic; }
-
-const upb_FieldDef* upb_OneofDef_LookupNameWithSize(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_LookupNumber(const upb_OneofDef* o,
-                                              uint32_t num) {
-  upb_value val;
-  return upb_inttable_lookup(&o->itof, num, &val) ? upb_value_getptr(val)
-                                                  : NULL;
-}
-
-/* upb_FileDef ****************************************************************/
-
-const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f) {
-  return f->opts;
-}
-
-bool upb_FileDef_HasOptions(const upb_FileDef* f) {
-  return f->opts != (void*)opt_default;
-}
-
-const char* upb_FileDef_Name(const upb_FileDef* f) { return f->name; }
-
-const char* upb_FileDef_Package(const upb_FileDef* f) { return f->package; }
-
-upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f) { return f->syntax; }
-
-int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f) {
-  return f->top_lvl_msg_count;
-}
-
-int upb_FileDef_DependencyCount(const upb_FileDef* f) { return f->dep_count; }
-
-int upb_FileDef_PublicDependencyCount(const upb_FileDef* f) {
-  return f->public_dep_count;
-}
-
-int upb_FileDef_WeakDependencyCount(const upb_FileDef* f) {
-  return f->weak_dep_count;
-}
-
-const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f) {
-  return f->public_deps;
-}
-
-const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f) {
-  return f->weak_deps;
-}
-
-int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f) {
-  return f->top_lvl_enum_count;
-}
-
-int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f) {
-  return f->top_lvl_ext_count;
-}
-
-int upb_FileDef_ServiceCount(const upb_FileDef* f) { return f->service_count; }
-
-const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->dep_count);
-  return f->deps[i];
-}
-
-const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->public_dep_count);
-  return f->deps[f->public_deps[i]];
-}
-
-const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->public_dep_count);
-  return f->deps[f->weak_deps[i]];
-}
-
-const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->top_lvl_msg_count);
-  return &f->top_lvl_msgs[i];
-}
-
-const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->top_lvl_enum_count);
-  return &f->top_lvl_enums[i];
-}
-
-const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->top_lvl_ext_count);
-  return &f->top_lvl_exts[i];
-}
-
-const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i) {
-  UPB_ASSERT(0 <= i && i < f->service_count);
-  return &f->services[i];
-}
-
-const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f) { return f->symtab; }
-
-/* upb_MethodDef **************************************************************/
-
-const google_protobuf_MethodOptions* upb_MethodDef_Options(
-    const upb_MethodDef* m) {
-  return m->opts;
-}
-
-bool upb_MethodDef_HasOptions(const upb_MethodDef* m) {
-  return m->opts != (void*)opt_default;
-}
-
-const char* upb_MethodDef_FullName(const upb_MethodDef* m) {
-  return m->full_name;
-}
-
-int upb_MethodDef_Index(const upb_MethodDef* m) { return m->index; }
-
-const char* upb_MethodDef_Name(const upb_MethodDef* m) {
-  return shortdefname(m->full_name);
-}
-
-const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m) {
-  return m->service;
-}
-
-const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m) {
-  return m->input_type;
-}
-
-const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m) {
-  return m->output_type;
-}
-
-bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m) {
-  return m->client_streaming;
-}
-
-bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m) {
-  return m->server_streaming;
-}
-
-/* upb_ServiceDef *************************************************************/
-
-const google_protobuf_ServiceOptions* upb_ServiceDef_Options(
-    const upb_ServiceDef* s) {
-  return s->opts;
-}
-
-bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s) {
-  return s->opts != (void*)opt_default;
-}
-
-const char* upb_ServiceDef_FullName(const upb_ServiceDef* s) {
-  return s->full_name;
-}
-
-const char* upb_ServiceDef_Name(const upb_ServiceDef* s) {
-  return shortdefname(s->full_name);
-}
-
-int upb_ServiceDef_Index(const upb_ServiceDef* s) { return s->index; }
-
-const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s) {
-  return s->file;
-}
-
-int upb_ServiceDef_MethodCount(const upb_ServiceDef* s) {
-  return s->method_count;
-}
-
-const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i) {
-  return i < 0 || i >= s->method_count ? NULL : &s->methods[i];
-}
-
-const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
-                                                     const char* name) {
-  for (int i = 0; i < s->method_count; i++) {
-    if (strcmp(name, upb_MethodDef_Name(&s->methods[i])) == 0) {
-      return &s->methods[i];
-    }
-  }
-  return NULL;
-}
-
-/* upb_DefPool ****************************************************************/
-
-void upb_DefPool_Free(upb_DefPool* s) {
-  upb_Arena_Free(s->arena);
-  upb_gfree(s);
-}
-
-upb_DefPool* upb_DefPool_New(void) {
-  upb_DefPool* 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_inttable_init(&s->exts, s->arena)) {
-    goto err;
-  }
-
-  s->extreg = upb_ExtensionRegistry_New(s->arena);
-  if (!s->extreg) goto err;
-  return s;
-
-err:
-  upb_Arena_Free(s->arena);
-  upb_gfree(s);
-  return NULL;
-}
-
-static const void* symtab_lookup(const upb_DefPool* s, const char* sym,
-                                 upb_deftype_t type) {
-  upb_value v;
-  return upb_strtable_lookup(&s->syms, sym, &v) ? unpack_def(v, type) : NULL;
-}
-
-static const void* symtab_lookup2(const upb_DefPool* s, const char* sym,
-                                  size_t size, upb_deftype_t type) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->syms, sym, size, &v) ? unpack_def(v, type)
-                                                       : NULL;
-}
-
-const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
-                                                    const char* sym) {
-  return symtab_lookup(s, sym, UPB_DEFTYPE_MSG);
-}
-
-const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
-    const upb_DefPool* s, const char* sym, size_t len) {
-  return symtab_lookup2(s, sym, len, UPB_DEFTYPE_MSG);
-}
-
-const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
-                                              const char* sym) {
-  return symtab_lookup(s, sym, UPB_DEFTYPE_ENUM);
-}
-
-const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
-                                                      const char* sym) {
-  return symtab_lookup(s, sym, UPB_DEFTYPE_ENUMVAL);
-}
-
-const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
-                                              const char* name) {
-  upb_value v;
-  return upb_strtable_lookup(&s->files, name, &v)
-             ? unpack_def(v, UPB_DEFTYPE_FILE)
-             : NULL;
-}
-
-const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s,
-                                                      const char* name,
-                                                      size_t len) {
-  upb_value v;
-  return upb_strtable_lookup2(&s->files, name, len, &v)
-             ? unpack_def(v, UPB_DEFTYPE_FILE)
-             : NULL;
-}
-
-const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
-    const upb_DefPool* s, const char* name, size_t size) {
-  upb_value v;
-  if (!upb_strtable_lookup2(&s->syms, name, size, &v)) return NULL;
-
-  switch (deftype(v)) {
-    case UPB_DEFTYPE_FIELD:
-      return unpack_def(v, UPB_DEFTYPE_FIELD);
-    case UPB_DEFTYPE_MSG: {
-      const upb_MessageDef* m = unpack_def(v, UPB_DEFTYPE_MSG);
-      return m->in_message_set ? &m->nested_exts[0] : NULL;
-    }
-    default:
-      break;
-  }
-
-  return NULL;
-}
-
-const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
-                                                    const char* sym) {
-  return upb_DefPool_FindExtensionByNameWithSize(s, sym, strlen(sym));
-}
-
-const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
-                                                    const char* name) {
-  return symtab_lookup(s, name, UPB_DEFTYPE_SERVICE);
-}
-
-const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
-    const upb_DefPool* s, const char* name, size_t size) {
-  return symtab_lookup2(s, name, size, UPB_DEFTYPE_SERVICE);
-}
-
-const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
-                                                        const char* name) {
-  upb_value v;
-  // TODO(haberman): non-extension fields and oneofs.
-  if (upb_strtable_lookup(&s->syms, name, &v)) {
-    switch (deftype(v)) {
-      case UPB_DEFTYPE_EXT: {
-        const upb_FieldDef* f = unpack_def(v, UPB_DEFTYPE_EXT);
-        return upb_FieldDef_File(f);
-      }
-      case UPB_DEFTYPE_MSG: {
-        const upb_MessageDef* m = unpack_def(v, UPB_DEFTYPE_MSG);
-        return upb_MessageDef_File(m);
-      }
-      case UPB_DEFTYPE_ENUM: {
-        const upb_EnumDef* e = unpack_def(v, UPB_DEFTYPE_ENUM);
-        return upb_EnumDef_File(e);
-      }
-      case UPB_DEFTYPE_ENUMVAL: {
-        const upb_EnumValueDef* ev = unpack_def(v, UPB_DEFTYPE_ENUMVAL);
-        return upb_EnumDef_File(upb_EnumValueDef_Enum(ev));
-      }
-      case UPB_DEFTYPE_SERVICE: {
-        const upb_ServiceDef* service = unpack_def(v, UPB_DEFTYPE_SERVICE);
-        return upb_ServiceDef_File(service);
-      }
-      default:
-        UPB_UNREACHABLE();
-    }
-  }
-
-  const char* last_dot = strrchr(name, '.');
-  if (last_dot) {
-    const upb_MessageDef* parent =
-        upb_DefPool_FindMessageByNameWithSize(s, name, last_dot - name);
-    if (parent) {
-      const char* shortname = last_dot + 1;
-      if (upb_MessageDef_FindByNameWithSize(parent, shortname,
-                                            strlen(shortname), NULL, NULL)) {
-        return upb_MessageDef_File(parent);
-      }
-    }
-  }
-
-  return NULL;
-}
-
-/* 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_DefPool* symtab;
-  upb_FileDef* file;                /* File we are building. */
-  upb_Arena* arena;                 /* Allocate defs here. */
-  upb_Arena* tmp_arena;             /* For temporary allocations. */
-  const upb_MiniTable_File* layout; /* NULL if we should build layouts. */
-  int enum_count;                   /* Count of enums built so far. */
-  int msg_count;                    /* Count of messages built so far. */
-  int ext_count;                    /* Count of extensions built so far. */
-  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_VSetErrorFormat(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) {
-  if (bytes == 0) return NULL;
-  void* ret = upb_Arena_Malloc(ctx->arena, bytes);
-  if (!ret) symtab_oomerr(ctx);
-  return ret;
-}
-
-// We want to copy the options verbatim into the destination options proto.
-// We use serialize+parse as our deep copy.
-#define SET_OPTIONS(target, desc_type, options_type, proto)                   \
-  if (google_protobuf_##desc_type##_has_options(proto)) {                     \
-    size_t size;                                                              \
-    char* pb = google_protobuf_##options_type##_serialize(                    \
-        google_protobuf_##desc_type##_options(proto), ctx->tmp_arena, &size); \
-    CHK_OOM(pb);                                                              \
-    target = google_protobuf_##options_type##_parse(pb, size, ctx->arena);    \
-    CHK_OOM(target);                                                          \
-  } else {                                                                    \
-    target = (const google_protobuf_##options_type*)opt_default;              \
-  }
-
-static void check_ident(symtab_addctx* ctx, upb_StringView 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_MessageValue_sizeof(upb_CType type) {
-  switch (type) {
-    case kUpb_CType_Double:
-    case kUpb_CType_Int64:
-    case kUpb_CType_UInt64:
-      return 8;
-    case kUpb_CType_Enum:
-    case kUpb_CType_Int32:
-    case kUpb_CType_UInt32:
-    case kUpb_CType_Float:
-      return 4;
-    case kUpb_CType_Bool:
-      return 1;
-    case kUpb_CType_Message:
-      return sizeof(void*);
-    case kUpb_CType_Bytes:
-    case kUpb_CType_String:
-      return sizeof(upb_StringView);
-  }
-  UPB_UNREACHABLE();
-}
-
-static uint8_t upb_msg_fielddefsize(const upb_FieldDef* f) {
-  if (upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f))) {
-    upb_MapEntry ent;
-    UPB_ASSERT(sizeof(ent.k) == sizeof(ent.v));
-    return sizeof(ent.k);
-  } else if (upb_FieldDef_IsRepeated(f)) {
-    return sizeof(void*);
-  } else {
-    return upb_MessageValue_sizeof(upb_FieldDef_CType(f));
-  }
-}
-
-static uint32_t upb_MiniTable_place(symtab_addctx* ctx, upb_MiniTable* l,
-                                    size_t size, const upb_MessageDef* m) {
-  size_t ofs = UPB_ALIGN_UP(l->size, size);
-  size_t next = ofs + size;
-
-  if (next > UINT16_MAX) {
-    symtab_errf(ctx, "size of message %s exceeded max size of %zu bytes",
-                upb_MessageDef_FullName(m), (size_t)UINT16_MAX);
-  }
-
-  l->size = next;
-  return ofs;
-}
-
-static int field_number_cmp(const void* p1, const void* p2) {
-  const upb_MiniTable_Field* f1 = p1;
-  const upb_MiniTable_Field* f2 = p2;
-  return f1->number - f2->number;
-}
-
-static void assign_layout_indices(const upb_MessageDef* m, upb_MiniTable* l,
-                                  upb_MiniTable_Field* fields) {
-  int i;
-  int n = upb_MessageDef_numfields(m);
-  int dense_below = 0;
-  for (i = 0; i < n; i++) {
-    upb_FieldDef* f =
-        (upb_FieldDef*)upb_MessageDef_FindFieldByNumber(m, fields[i].number);
-    UPB_ASSERT(f);
-    f->layout_index = i;
-    if (i < UINT8_MAX && fields[i].number == i + 1 &&
-        (i == 0 || fields[i - 1].number == i)) {
-      dense_below = i + 1;
-    }
-  }
-  l->dense_below = dense_below;
-}
-
-static uint8_t map_descriptortype(const upb_FieldDef* f) {
-  uint8_t type = upb_FieldDef_Type(f);
-  /* See TableDescriptorType() in upbc/generator.cc for details and
-   * rationale of these exceptions. */
-  if (type == kUpb_FieldType_String && f->file->syntax == kUpb_Syntax_Proto2) {
-    return kUpb_FieldType_Bytes;
-  } else if (type == kUpb_FieldType_Enum &&
-             (f->sub.enumdef->file->syntax == kUpb_Syntax_Proto3 ||
-              UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 ||
-              // TODO(https://github.com/protocolbuffers/upb/issues/541):
-              // fix map enum values to check for unknown enum values and put
-              // them in the unknown field set.
-              upb_MessageDef_IsMapEntry(upb_FieldDef_ContainingType(f)))) {
-    return kUpb_FieldType_Int32;
-  }
-  return type;
-}
-
-static void fill_fieldlayout(upb_MiniTable_Field* field,
-                             const upb_FieldDef* f) {
-  field->number = upb_FieldDef_Number(f);
-  field->descriptortype = map_descriptortype(f);
-
-  if (upb_FieldDef_IsMap(f)) {
-    field->mode =
-        kUpb_FieldMode_Map | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift);
-  } else if (upb_FieldDef_IsRepeated(f)) {
-    field->mode =
-        kUpb_FieldMode_Array | (kUpb_FieldRep_Pointer << kUpb_FieldRep_Shift);
-  } else {
-    /* Maps descriptor type -> elem_size_lg2.  */
-    static const uint8_t sizes[] = {
-        -1,                       /* invalid descriptor type */
-        kUpb_FieldRep_8Byte,      /* DOUBLE */
-        kUpb_FieldRep_4Byte,      /* FLOAT */
-        kUpb_FieldRep_8Byte,      /* INT64 */
-        kUpb_FieldRep_8Byte,      /* UINT64 */
-        kUpb_FieldRep_4Byte,      /* INT32 */
-        kUpb_FieldRep_8Byte,      /* FIXED64 */
-        kUpb_FieldRep_4Byte,      /* FIXED32 */
-        kUpb_FieldRep_1Byte,      /* BOOL */
-        kUpb_FieldRep_StringView, /* STRING */
-        kUpb_FieldRep_Pointer,    /* GROUP */
-        kUpb_FieldRep_Pointer,    /* MESSAGE */
-        kUpb_FieldRep_StringView, /* BYTES */
-        kUpb_FieldRep_4Byte,      /* UINT32 */
-        kUpb_FieldRep_4Byte,      /* ENUM */
-        kUpb_FieldRep_4Byte,      /* SFIXED32 */
-        kUpb_FieldRep_8Byte,      /* SFIXED64 */
-        kUpb_FieldRep_4Byte,      /* SINT32 */
-        kUpb_FieldRep_8Byte,      /* SINT64 */
-    };
-    field->mode = kUpb_FieldMode_Scalar |
-                  (sizes[field->descriptortype] << kUpb_FieldRep_Shift);
-  }
-
-  if (upb_FieldDef_IsPacked(f)) {
-    field->mode |= kUpb_LabelFlags_IsPacked;
-  }
-
-  if (upb_FieldDef_IsExtension(f)) {
-    field->mode |= kUpb_LabelFlags_IsExtension;
-  }
-}
-
-/* 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_MessageDef* m) {
-  upb_MiniTable* l = (upb_MiniTable*)m->layout;
-  size_t field_count = upb_MessageDef_numfields(m);
-  size_t sublayout_count = 0;
-  upb_MiniTable_Sub* subs;
-  upb_MiniTable_Field* fields;
-
-  memset(l, 0, sizeof(*l) + sizeof(_upb_FastTable_Entry));
-
-  /* Count sub-messages. */
-  for (size_t i = 0; i < field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    if (upb_FieldDef_IsSubMessage(f)) {
-      sublayout_count++;
-    }
-    if (upb_FieldDef_CType(f) == kUpb_CType_Enum &&
-        f->sub.enumdef->file->syntax == kUpb_Syntax_Proto2) {
-      sublayout_count++;
-    }
-  }
-
-  fields = symtab_alloc(ctx, field_count * sizeof(*fields));
-  subs = symtab_alloc(ctx, sublayout_count * sizeof(*subs));
-
-  l->field_count = upb_MessageDef_numfields(m);
-  l->fields = fields;
-  l->subs = subs;
-  l->table_mask = 0;
-  l->required_count = 0;
-
-  if (upb_MessageDef_ExtensionRangeCount(m) > 0) {
-    if (google_protobuf_MessageOptions_message_set_wire_format(m->opts)) {
-      l->ext = kUpb_ExtMode_IsMessageSet;
-    } else {
-      l->ext = kUpb_ExtMode_Extendable;
-    }
-  } else {
-    l->ext = kUpb_ExtMode_NonExtendable;
-  }
-
-  /* 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_MessageDef_IsMapEntry(m)) {
-    /* TODO(haberman): refactor this method so this special case is more
-     * elegant. */
-    const upb_FieldDef* key = upb_MessageDef_FindFieldByNumber(m, 1);
-    const upb_FieldDef* val = upb_MessageDef_FindFieldByNumber(m, 2);
-    fields[0].number = 1;
-    fields[1].number = 2;
-    fields[0].mode = kUpb_FieldMode_Scalar;
-    fields[1].mode = kUpb_FieldMode_Scalar;
-    fields[0].presence = 0;
-    fields[1].presence = 0;
-    fields[0].descriptortype = map_descriptortype(key);
-    fields[1].descriptortype = map_descriptortype(val);
-    fields[0].offset = 0;
-    fields[1].offset = sizeof(upb_StringView);
-    fields[1].submsg_index = 0;
-
-    if (upb_FieldDef_CType(val) == kUpb_CType_Message) {
-      subs[0].submsg = upb_FieldDef_MessageSubDef(val)->layout;
-    }
-
-    upb_FieldDef* fielddefs = (upb_FieldDef*)&m->fields[0];
-    UPB_ASSERT(fielddefs[0].number_ == 1);
-    UPB_ASSERT(fielddefs[1].number_ == 2);
-    fielddefs[0].layout_index = 0;
-    fielddefs[1].layout_index = 1;
-
-    l->field_count = 2;
-    l->size = 2 * sizeof(upb_StringView);
-    l->size = UPB_ALIGN_UP(l->size, 8);
-    l->dense_below = 2;
-    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.
-   */
-
-  /* Assign hasbits for required fields first. */
-  size_t hasbit = 0;
-
-  for (int i = 0; i < m->field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    upb_MiniTable_Field* field = &fields[upb_FieldDef_Index(f)];
-    if (upb_FieldDef_Label(f) == kUpb_Label_Required) {
-      field->presence = ++hasbit;
-      if (hasbit >= 63) {
-        symtab_errf(ctx, "Message with >=63 required fields: %s",
-                    upb_MessageDef_FullName(m));
-      }
-      l->required_count++;
-    }
-  }
-
-  /* Allocate hasbits and set basic field attributes. */
-  sublayout_count = 0;
-  for (int i = 0; i < m->field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    upb_MiniTable_Field* field = &fields[upb_FieldDef_Index(f)];
-
-    fill_fieldlayout(field, f);
-
-    if (field->descriptortype == kUpb_FieldType_Message ||
-        field->descriptortype == kUpb_FieldType_Group) {
-      field->submsg_index = sublayout_count++;
-      subs[field->submsg_index].submsg = upb_FieldDef_MessageSubDef(f)->layout;
-    } else if (field->descriptortype == kUpb_FieldType_Enum) {
-      field->submsg_index = sublayout_count++;
-      subs[field->submsg_index].subenum = upb_FieldDef_EnumSubDef(f)->layout;
-      UPB_ASSERT(subs[field->submsg_index].subenum);
-    }
-
-    if (upb_FieldDef_Label(f) == kUpb_Label_Required) {
-      /* Hasbit was already assigned. */
-    } else 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 = hasbit ? div_round_up(hasbit + 1, 8) : 0;
-
-  /* Allocate non-oneof fields. */
-  for (int i = 0; i < m->field_count; i++) {
-    const upb_FieldDef* f = &m->fields[i];
-    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_MiniTable_place(ctx, l, field_size, m);
-  }
-
-  /* Allocate oneof fields.  Each oneof field consists of a uint32 for the case
-   * and space for the actual data. */
-  for (int i = 0; i < m->oneof_count; i++) {
-    const upb_OneofDef* o = &m->oneofs[i];
-    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;
-
-    if (o->field_count == 0) {
-      symtab_errf(ctx, "Oneof must have at least one field (%s)", o->full_name);
-    }
-
-    /* Calculate field size: the max of all field sizes. */
-    for (int j = 0; j < o->field_count; j++) {
-      const upb_FieldDef* f = o->fields[j];
-      field_size = UPB_MAX(field_size, upb_msg_fielddefsize(f));
-    }
-
-    /* Align and allocate case offset. */
-    case_offset = upb_MiniTable_place(ctx, l, case_size, m);
-    data_offset = upb_MiniTable_place(ctx, l, field_size, m);
-
-    for (int i = 0; i < o->field_count; i++) {
-      const upb_FieldDef* f = o->fields[i];
-      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. */
-  if (fields) {
-    qsort(fields, upb_MessageDef_numfields(m), sizeof(*fields),
-          field_number_cmp);
-  }
-  assign_layout_indices(m, l, fields);
-}
-
-static char* strviewdup(symtab_addctx* ctx, upb_StringView view) {
-  char* ret = upb_strdup2(view.data, view.size, ctx->arena);
-  CHK_OOM(ret);
-  return ret;
-}
-
-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_StringView view, const char* b) {
-  return streql2(view.data, view.size, b);
-}
-
-static const char* makefullname(symtab_addctx* ctx, const char* prefix,
-                                upb_StringView 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_MessageDef* 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*)upb_FieldDef_ContainingOneof(f);
-    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;
-}
-
-/* Adds a symbol |v| to the symtab, which must be a def pointer previously
- * packed with pack_def().  The def's pointer to upb_FileDef* must be set before
- * adding, so we know which entries to remove if building this file fails. */
-static void symtab_add(symtab_addctx* ctx, const char* name, upb_value v) {
-  // TODO: table should support an operation "tryinsert" to avoid the double
-  // lookup.
-  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));
-}
-
-static bool remove_component(char* base, size_t* len) {
-  if (*len == 0) return false;
-
-  for (size_t i = *len - 1; i > 0; i--) {
-    if (base[i] == '.') {
-      *len = i;
-      return true;
-    }
-  }
-
-  *len = 0;
-  return true;
-}
-
-/* Given a symbol and the base symbol inside which it is defined, find the
- * symbol's definition in t. */
-static const void* symtab_resolveany(symtab_addctx* ctx,
-                                     const char* from_name_dbg,
-                                     const char* base, upb_StringView sym,
-                                     upb_deftype_t* type) {
-  const upb_strtable* t = &ctx->symtab->syms;
-  if (sym.size == 0) goto notfound;
-  upb_value v;
-  if (sym.data[0] == '.') {
-    /* Symbols starting with '.' are absolute, so we do a single lookup.
-     * Slice to omit the leading '.' */
-    if (!upb_strtable_lookup2(t, sym.data + 1, sym.size - 1, &v)) {
-      goto notfound;
-    }
-  } else {
-    /* Remove components from base until we find an entry or run out. */
-    size_t baselen = base ? strlen(base) : 0;
-    char* tmp = malloc(sym.size + baselen + 1);
-    while (1) {
-      char* p = tmp;
-      if (baselen) {
-        memcpy(p, base, baselen);
-        p[baselen] = '.';
-        p += baselen + 1;
-      }
-      memcpy(p, sym.data, sym.size);
-      p += sym.size;
-      if (upb_strtable_lookup2(t, tmp, p - tmp, &v)) {
-        break;
-      }
-      if (!remove_component(tmp, &baselen)) {
-        free(tmp);
-        goto notfound;
-      }
-    }
-    free(tmp);
-  }
-
-  *type = deftype(v);
-  return unpack_def(v, *type);
-
-notfound:
-  symtab_errf(ctx, "couldn't resolve name '" UPB_STRINGVIEW_FORMAT "'",
-              UPB_STRINGVIEW_ARGS(sym));
-}
-
-static const void* symtab_resolve(symtab_addctx* ctx, const char* from_name_dbg,
-                                  const char* base, upb_StringView sym,
-                                  upb_deftype_t type) {
-  upb_deftype_t found_type;
-  const void* ret =
-      symtab_resolveany(ctx, from_name_dbg, base, sym, &found_type);
-  if (ret && found_type != type) {
-    symtab_errf(ctx,
-                "type mismatch when resolving %s: couldn't find "
-                "name " UPB_STRINGVIEW_FORMAT " with type=%d",
-                from_name_dbg, UPB_STRINGVIEW_ARGS(sym), (int)type);
-  }
-  return ret;
-}
-
-static void create_oneofdef(
-    symtab_addctx* ctx, upb_MessageDef* m,
-    const google_protobuf_OneofDescriptorProto* oneof_proto,
-    const upb_OneofDef* _o) {
-  upb_OneofDef* o = (upb_OneofDef*)_o;
-  upb_StringView name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
-  upb_value v;
-
-  o->parent = m;
-  o->full_name = makefullname(ctx, m->full_name, name);
-  o->field_count = 0;
-  o->synthetic = false;
-
-  SET_OPTIONS(o->opts, OneofDescriptorProto, OneofOptions, oneof_proto);
-
-  upb_value existing_v;
-  if (upb_strtable_lookup2(&m->ntof, name.data, name.size, &existing_v)) {
-    symtab_errf(ctx, "duplicate oneof name (%s)", o->full_name);
-  }
-
-  v = pack_def(o, UPB_DEFTYPE_ONEOF);
-  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);
-  CHK_OOM(ret);
-  ret->len = len;
-  if (len) memcpy(ret->str, data, len);
-  ret->str[len] = '\0';
-  return ret;
-}
-
-static bool upb_DefPool_TryGetChar(const char** src, const char* end,
-                                   char* ch) {
-  if (*src == end) return false;
-  *ch = **src;
-  *src += 1;
-  return true;
-}
-
-static char upb_DefPool_TryGetHexDigit(symtab_addctx* ctx,
-                                       const upb_FieldDef* f, const char** src,
-                                       const char* end) {
-  char ch;
-  if (!upb_DefPool_TryGetChar(src, end, &ch)) return -1;
-  if ('0' <= ch && ch <= '9') {
-    return ch - '0';
-  }
-  ch = upb_ascii_lower(ch);
-  if ('a' <= ch && ch <= 'f') {
-    return ch - 'a' + 0xa;
-  }
-  *src -= 1;  // Char wasn't actually a hex digit.
-  return -1;
-}
-
-static char upb_DefPool_ParseHexEscape(symtab_addctx* ctx,
-                                       const upb_FieldDef* f, const char** src,
-                                       const char* end) {
-  char hex_digit = upb_DefPool_TryGetHexDigit(ctx, f, src, end);
-  if (hex_digit < 0) {
-    symtab_errf(ctx,
-                "\\x cannot be followed by non-hex digit in field '%s' default",
-                upb_FieldDef_FullName(f));
-    return 0;
-  }
-  unsigned int ret = hex_digit;
-  while ((hex_digit = upb_DefPool_TryGetHexDigit(ctx, f, src, end)) >= 0) {
-    ret = (ret << 4) | hex_digit;
-  }
-  if (ret > 0xff) {
-    symtab_errf(ctx, "Value of hex escape in field %s exceeds 8 bits",
-                upb_FieldDef_FullName(f));
-    return 0;
-  }
-  return ret;
-}
-
-char upb_DefPool_TryGetOctalDigit(const char** src, const char* end) {
-  char ch;
-  if (!upb_DefPool_TryGetChar(src, end, &ch)) return -1;
-  if ('0' <= ch && ch <= '7') {
-    return ch - '0';
-  }
-  *src -= 1;  // Char wasn't actually an octal digit.
-  return -1;
-}
-
-static char upb_DefPool_ParseOctalEscape(symtab_addctx* ctx,
-                                         const upb_FieldDef* f,
-                                         const char** src, const char* end) {
-  char ch = 0;
-  for (int i = 0; i < 3; i++) {
-    char digit;
-    if ((digit = upb_DefPool_TryGetOctalDigit(src, end)) >= 0) {
-      ch = (ch << 3) | digit;
-    }
-  }
-  return ch;
-}
-
-static char upb_DefPool_ParseEscape(symtab_addctx* ctx, const upb_FieldDef* f,
-                                    const char** src, const char* end) {
-  char ch;
-  if (!upb_DefPool_TryGetChar(src, end, &ch)) {
-    symtab_errf(ctx, "unterminated escape sequence in field %s",
-                upb_FieldDef_FullName(f));
-    return 0;
-  }
-  switch (ch) {
-    case 'a':
-      return '\a';
-    case 'b':
-      return '\b';
-    case 'f':
-      return '\f';
-    case 'n':
-      return '\n';
-    case 'r':
-      return '\r';
-    case 't':
-      return '\t';
-    case 'v':
-      return '\v';
-    case '\\':
-      return '\\';
-    case '\'':
-      return '\'';
-    case '\"':
-      return '\"';
-    case '?':
-      return '\?';
-    case 'x':
-    case 'X':
-      return upb_DefPool_ParseHexEscape(ctx, f, src, end);
-    case '0':
-    case '1':
-    case '2':
-    case '3':
-    case '4':
-    case '5':
-    case '6':
-    case '7':
-      *src -= 1;
-      return upb_DefPool_ParseOctalEscape(ctx, f, src, end);
-  }
-  symtab_errf(ctx, "Unknown escape sequence: \\%c", ch);
-}
-
-static str_t* unescape(symtab_addctx* ctx, const upb_FieldDef* f,
-                       const char* data, size_t len) {
-  // Size here is an upper bound; escape sequences could ultimately shrink it.
-  str_t* ret = symtab_alloc(ctx, sizeof(*ret) + len);
-  char* dst = &ret->str[0];
-  const char* src = data;
-  const char* end = data + len;
-
-  while (src < end) {
-    if (*src == '\\') {
-      src++;
-      *dst++ = upb_DefPool_ParseEscape(ctx, f, &src, end);
-    } else {
-      *dst++ = *src++;
-    }
-  }
-
-  ret->len = dst - &ret->str[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_CType(f)) {
-    case kUpb_CType_Int32:
-    case kUpb_CType_Int64:
-    case kUpb_CType_UInt32:
-    case kUpb_CType_UInt64:
-    case kUpb_CType_Double:
-    case kUpb_CType_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_CType(f)) {
-    case kUpb_CType_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 kUpb_CType_Enum: {
-      const upb_EnumDef* e = f->sub.enumdef;
-      const upb_EnumValueDef* ev =
-          upb_EnumDef_FindValueByNameWithSize(e, str, len);
-      if (!ev) {
-        goto invalid;
-      }
-      f->defaultval.sint = ev->number;
-      break;
-    }
-    case kUpb_CType_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 kUpb_CType_UInt32: {
-      unsigned long val = strtoul(str, &end, 0);
-      if (val > UINT32_MAX || errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.uint = val;
-      break;
-    }
-    case kUpb_CType_UInt64: {
-      unsigned long long val = strtoull(str, &end, 0);
-      if (val > UINT64_MAX || errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.uint = val;
-      break;
-    }
-    case kUpb_CType_Double: {
-      double val = strtod(str, &end);
-      if (errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.dbl = val;
-      break;
-    }
-    case kUpb_CType_Float: {
-      float val = strtof(str, &end);
-      if (errno == ERANGE || *end) {
-        goto invalid;
-      }
-      f->defaultval.flt = val;
-      break;
-    }
-    case kUpb_CType_Bool: {
-      if (streql2(str, len, "false")) {
-        f->defaultval.boolean = false;
-      } else if (streql2(str, len, "true")) {
-        f->defaultval.boolean = true;
-      } else {
-        goto invalid;
-      }
-      break;
-    }
-    case kUpb_CType_String:
-      f->defaultval.str = newstr(ctx, str, len);
-      break;
-    case kUpb_CType_Bytes:
-      f->defaultval.str = unescape(ctx, f, str, len);
-      break;
-    case kUpb_CType_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 of type %d", (int)len,
-              str, upb_FieldDef_FullName(f), (int)upb_FieldDef_Type(f));
-}
-
-static void set_default_default(symtab_addctx* ctx, upb_FieldDef* f) {
-  switch (upb_FieldDef_CType(f)) {
-    case kUpb_CType_Int32:
-    case kUpb_CType_Int64:
-      f->defaultval.sint = 0;
-      break;
-    case kUpb_CType_UInt64:
-    case kUpb_CType_UInt32:
-      f->defaultval.uint = 0;
-      break;
-    case kUpb_CType_Double:
-    case kUpb_CType_Float:
-      f->defaultval.dbl = 0;
-      break;
-    case kUpb_CType_String:
-    case kUpb_CType_Bytes:
-      f->defaultval.str = newstr(ctx, NULL, 0);
-      break;
-    case kUpb_CType_Bool:
-      f->defaultval.boolean = false;
-      break;
-    case kUpb_CType_Enum:
-      f->defaultval.sint = f->sub.enumdef->values[0].number;
-    case kUpb_CType_Message:
-      break;
-  }
-}
-
-static void create_fielddef(
-    symtab_addctx* ctx, const char* prefix, upb_MessageDef* m,
-    const google_protobuf_FieldDescriptorProto* field_proto,
-    const upb_FieldDef* _f, bool is_extension) {
-  upb_FieldDef* f = (upb_FieldDef*)_f;
-  upb_StringView name;
-  const char* full_name;
-  const char* json_name;
-  const char* shortname;
-  int32_t field_number;
-
-  f->file = ctx->file; /* Must happen prior to symtab_add(). */
-
-  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
-    symtab_errf(ctx, "field has no name");
-  }
-
-  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));
-    f->has_json_name_ = true;
-  } else {
-    json_name = makejsonname(ctx, shortname);
-    f->has_json_name_ = false;
-  }
-
-  field_number = google_protobuf_FieldDescriptorProto_number(field_proto);
-
-  f->full_name = full_name;
-  f->json_name = json_name;
-  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
-  f->number_ = field_number;
-  f->scope.oneof = NULL;
-  f->proto3_optional_ =
-      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
-
-  bool has_type = google_protobuf_FieldDescriptorProto_has_type(field_proto);
-  bool has_type_name =
-      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
-
-  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
-
-  if (has_type) {
-    switch (f->type_) {
-      case kUpb_FieldType_Message:
-      case kUpb_FieldType_Group:
-      case kUpb_FieldType_Enum:
-        if (!has_type_name) {
-          symtab_errf(ctx, "field of type %d requires type name (%s)",
-                      (int)f->type_, full_name);
-        }
-        break;
-      default:
-        if (has_type_name) {
-          symtab_errf(ctx, "invalid type for field with type_name set (%s, %d)",
-                      full_name, (int)f->type_);
-        }
-    }
-  } else if (has_type_name) {
-    f->type_ =
-        FIELD_TYPE_UNSPECIFIED;  // We'll fill this in in resolve_fielddef().
-  }
-
-  if (!is_extension) {
-    /* direct message field. */
-    upb_value v, field_v, json_v, existing_v;
-    size_t json_size;
-
-    if (field_number <= 0 || field_number > kUpb_MaxFieldNumber) {
-      symtab_errf(ctx, "invalid field number (%u)", field_number);
-    }
-
-    f->index_ = f - m->fields;
-    f->msgdef = m;
-    f->is_extension_ = 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);
-
-    if (upb_strtable_lookup(&m->ntof, shortname, &existing_v)) {
-      symtab_errf(ctx, "duplicate field name (%s)", shortname);
-    }
-
-    CHK_OOM(upb_strtable_insert(&m->ntof, name.data, name.size, field_v,
-                                ctx->arena));
-
-    if (strcmp(shortname, json_name) != 0) {
-      if (upb_strtable_lookup(&m->ntof, json_name, &v)) {
-        symtab_errf(ctx, "duplicate json_name (%s)", json_name);
-      } else {
-        CHK_OOM(upb_strtable_insert(&m->ntof, json_name, json_size, json_v,
-                                    ctx->arena));
-      }
-    }
-
-    if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
-      symtab_errf(ctx, "duplicate field number (%u)", field_number);
-    }
-
-    CHK_OOM(upb_inttable_insert(&m->itof, field_number, v, ctx->arena));
-
-    if (ctx->layout) {
-      const upb_MiniTable_Field* fields = m->layout->fields;
-      int count = m->layout->field_count;
-      bool found = false;
-      for (int 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->is_extension_ = true;
-    f->scope.extension_scope = m;
-    symtab_add(ctx, full_name, pack_def(f, UPB_DEFTYPE_EXT));
-    f->layout_index = ctx->ext_count++;
-    if (ctx->layout) {
-      UPB_ASSERT(ctx->file->ext_layouts[f->layout_index]->field.number ==
-                 field_number);
-    }
-  }
-
-  if (f->type_ < kUpb_FieldType_Double || f->type_ > kUpb_FieldType_SInt64) {
-    symtab_errf(ctx, "invalid type for field %s (%d)", f->full_name, f->type_);
-  }
-
-  if (f->label_ < kUpb_Label_Optional || f->label_ > kUpb_Label_Repeated) {
-    symtab_errf(ctx, "invalid label for field %s (%d)", f->full_name,
-                f->label_);
-  }
-
-  /* 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_ == kUpb_Label_Required &&
-      f->file->syntax == kUpb_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) != kUpb_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->scope.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 {
-    if (f->proto3_optional_) {
-      symtab_errf(ctx, "field with proto3_optional was not in a oneof (%s)",
-                  f->full_name);
-    }
-  }
-
-  SET_OPTIONS(f->opts, FieldDescriptorProto, FieldOptions, field_proto);
-
-  if (google_protobuf_FieldOptions_has_packed(f->opts)) {
-    f->packed_ = google_protobuf_FieldOptions_packed(f->opts);
-  } else {
-    /* Repeated fields default to packed for proto3 only. */
-    f->packed_ = upb_FieldDef_IsPrimitive(f) &&
-                 f->label_ == kUpb_Label_Repeated &&
-                 f->file->syntax == kUpb_Syntax_Proto3;
-  }
-}
-
-static void create_service(
-    symtab_addctx* ctx, const google_protobuf_ServiceDescriptorProto* svc_proto,
-    const upb_ServiceDef* _s) {
-  upb_ServiceDef* s = (upb_ServiceDef*)_s;
-  upb_StringView name;
-  const google_protobuf_MethodDescriptorProto* const* methods;
-  size_t i, n;
-
-  s->file = ctx->file; /* Must happen prior to symtab_add. */
-
-  name = google_protobuf_ServiceDescriptorProto_name(svc_proto);
-  check_ident(ctx, name, false);
-  s->full_name = makefullname(ctx, ctx->file->package, name);
-  symtab_add(ctx, s->full_name, pack_def(s, UPB_DEFTYPE_SERVICE));
-
-  methods = google_protobuf_ServiceDescriptorProto_method(svc_proto, &n);
-
-  s->method_count = n;
-  s->methods = symtab_alloc(ctx, sizeof(*s->methods) * n);
-
-  SET_OPTIONS(s->opts, ServiceDescriptorProto, ServiceOptions, svc_proto);
-
-  for (i = 0; i < n; i++) {
-    const google_protobuf_MethodDescriptorProto* method_proto = methods[i];
-    upb_MethodDef* m = (upb_MethodDef*)&s->methods[i];
-    upb_StringView name =
-        google_protobuf_MethodDescriptorProto_name(method_proto);
-
-    m->service = s;
-    m->full_name = makefullname(ctx, s->full_name, name);
-    m->index = i;
-    m->client_streaming =
-        google_protobuf_MethodDescriptorProto_client_streaming(method_proto);
-    m->server_streaming =
-        google_protobuf_MethodDescriptorProto_server_streaming(method_proto);
-    m->input_type = symtab_resolve(
-        ctx, m->full_name, m->full_name,
-        google_protobuf_MethodDescriptorProto_input_type(method_proto),
-        UPB_DEFTYPE_MSG);
-    m->output_type = symtab_resolve(
-        ctx, m->full_name, m->full_name,
-        google_protobuf_MethodDescriptorProto_output_type(method_proto),
-        UPB_DEFTYPE_MSG);
-
-    SET_OPTIONS(m->opts, MethodDescriptorProto, MethodOptions, method_proto);
-  }
-}
-
-static int count_bits_debug(uint64_t x) {
-  // For assertions only, speed does not matter.
-  int n = 0;
-  while (x) {
-    if (x & 1) n++;
-    x >>= 1;
-  }
-  return n;
-}
-
-static int compare_int32(const void* a_ptr, const void* b_ptr) {
-  int32_t a = *(int32_t*)a_ptr;
-  int32_t b = *(int32_t*)b_ptr;
-  return a < b ? -1 : (a == b ? 0 : 1);
-}
-
-upb_MiniTable_Enum* create_enumlayout(symtab_addctx* ctx,
-                                      const upb_EnumDef* e) {
-  int n = 0;
-  uint64_t mask = 0;
-
-  for (int i = 0; i < e->value_count; i++) {
-    uint32_t val = (uint32_t)e->values[i].number;
-    if (val < 64) {
-      mask |= 1ULL << val;
-    } else {
-      n++;
-    }
-  }
-
-  int32_t* values = symtab_alloc(ctx, sizeof(*values) * n);
-
-  if (n) {
-    int32_t* p = values;
-
-    // Add values outside the bitmask range to the list, as described in the
-    // comments for upb_MiniTable_Enum.
-    for (int i = 0; i < e->value_count; i++) {
-      int32_t val = e->values[i].number;
-      if ((uint32_t)val >= 64) {
-        *p++ = val;
-      }
-    }
-    UPB_ASSERT(p == values + n);
-  }
-
-  // Enums can have duplicate values; we must sort+uniq them.
-  if (values) qsort(values, n, sizeof(*values), &compare_int32);
-
-  int dst = 0;
-  for (int i = 0; i < n; dst++) {
-    int32_t val = values[i];
-    while (i < n && values[i] == val) i++;  // Skip duplicates.
-    values[dst] = val;
-  }
-  n = dst;
-
-  UPB_ASSERT(upb_inttable_count(&e->iton) == n + count_bits_debug(mask));
-
-  upb_MiniTable_Enum* layout = symtab_alloc(ctx, sizeof(*layout));
-  layout->value_count = n;
-  layout->mask = mask;
-  layout->values = values;
-
-  return layout;
-}
-
-static void create_enumvaldef(
-    symtab_addctx* ctx, const char* prefix,
-    const google_protobuf_EnumValueDescriptorProto* val_proto, upb_EnumDef* e,
-    int i) {
-  upb_EnumValueDef* val = (upb_EnumValueDef*)&e->values[i];
-  upb_StringView name =
-      google_protobuf_EnumValueDescriptorProto_name(val_proto);
-  upb_value v = upb_value_constptr(val);
-
-  val->parent = e; /* Must happen prior to symtab_add(). */
-  val->full_name = makefullname(ctx, prefix, name);
-  val->number = google_protobuf_EnumValueDescriptorProto_number(val_proto);
-  symtab_add(ctx, val->full_name, pack_def(val, UPB_DEFTYPE_ENUMVAL));
-
-  SET_OPTIONS(val->opts, EnumValueDescriptorProto, EnumValueOptions, val_proto);
-
-  if (i == 0 && e->file->syntax == kUpb_Syntax_Proto3 && val->number != 0) {
-    symtab_errf(ctx, "for proto3, the first enum value must be zero (%s)",
-                e->full_name);
-  }
-
-  CHK_OOM(upb_strtable_insert(&e->ntoi, name.data, name.size, v, ctx->arena));
-
-  // Multiple enumerators can have the same number, first one wins.
-  if (!upb_inttable_lookup(&e->iton, val->number, NULL)) {
-    CHK_OOM(upb_inttable_insert(&e->iton, val->number, v, ctx->arena));
-  }
-}
-
-static void create_enumdef(
-    symtab_addctx* ctx, const char* prefix,
-    const google_protobuf_EnumDescriptorProto* enum_proto,
-    const upb_MessageDef* containing_type, const upb_EnumDef* _e) {
-  upb_EnumDef* e = (upb_EnumDef*)_e;
-  ;
-  const google_protobuf_EnumValueDescriptorProto* const* values;
-  upb_StringView name;
-  size_t i, n;
-
-  e->file = ctx->file; /* Must happen prior to symtab_add() */
-  e->containing_type = containing_type;
-
-  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
-  check_ident(ctx, name, false);
-
-  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->defaultval = 0;
-  e->value_count = n;
-  e->values = symtab_alloc(ctx, sizeof(*e->values) * n);
-
-  if (n == 0) {
-    symtab_errf(ctx, "enums must contain at least one value (%s)",
-                e->full_name);
-  }
-
-  SET_OPTIONS(e->opts, EnumDescriptorProto, EnumOptions, enum_proto);
-
-  for (i = 0; i < n; i++) {
-    create_enumvaldef(ctx, prefix, values[i], e, i);
-  }
-
-  upb_inttable_compact(&e->iton, ctx->arena);
-
-  if (e->file->syntax == kUpb_Syntax_Proto2) {
-    if (ctx->layout) {
-      UPB_ASSERT(ctx->enum_count < ctx->layout->enum_count);
-      e->layout = ctx->layout->enums[ctx->enum_count++];
-      UPB_ASSERT(upb_inttable_count(&e->iton) ==
-                 e->layout->value_count + count_bits_debug(e->layout->mask));
-    } else {
-      e->layout = create_enumlayout(ctx, e);
-    }
-  } else {
-    e->layout = NULL;
-  }
-}
-
-static void msgdef_create_nested(
-    symtab_addctx* ctx, const google_protobuf_DescriptorProto* msg_proto,
-    upb_MessageDef* m);
-
-static void create_msgdef(symtab_addctx* ctx, const char* prefix,
-                          const google_protobuf_DescriptorProto* msg_proto,
-                          const upb_MessageDef* containing_type,
-                          const upb_MessageDef* _m) {
-  upb_MessageDef* m = (upb_MessageDef*)_m;
-  const google_protobuf_OneofDescriptorProto* const* oneofs;
-  const google_protobuf_FieldDescriptorProto* const* fields;
-  const google_protobuf_DescriptorProto_ExtensionRange* const* ext_ranges;
-  size_t i, n_oneof, n_field, n_ext_range;
-  upb_StringView name;
-
-  m->file = ctx->file; /* Must happen prior to symtab_add(). */
-  m->containing_type = containing_type;
-
-  name = google_protobuf_DescriptorProto_name(msg_proto);
-  check_ident(ctx, name, false);
-
-  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);
-  ext_ranges =
-      google_protobuf_DescriptorProto_extension_range(msg_proto, &n_ext_range);
-
-  CHK_OOM(upb_inttable_init(&m->itof, ctx->arena));
-  CHK_OOM(upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena));
-
-  if (ctx->layout) {
-    /* create_fielddef() below depends on this being set. */
-    UPB_ASSERT(ctx->msg_count < ctx->layout->msg_count);
-    m->layout = ctx->layout->msgs[ctx->msg_count++];
-    UPB_ASSERT(n_field == m->layout->field_count);
-  } else {
-    /* Allocate now (to allow cross-linking), populate later. */
-    m->layout =
-        symtab_alloc(ctx, sizeof(*m->layout) + sizeof(_upb_FastTable_Entry));
-  }
-
-  SET_OPTIONS(m->opts, DescriptorProto, MessageOptions, msg_proto);
-
-  m->oneof_count = n_oneof;
-  m->oneofs = symtab_alloc(ctx, sizeof(*m->oneofs) * n_oneof);
-  for (i = 0; i < n_oneof; i++) {
-    create_oneofdef(ctx, m, oneofs[i], &m->oneofs[i]);
-  }
-
-  m->field_count = n_field;
-  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], &m->fields[i],
-                    /* is_extension= */ false);
-  }
-
-  m->ext_range_count = n_ext_range;
-  m->ext_ranges = symtab_alloc(ctx, sizeof(*m->ext_ranges) * n_ext_range);
-  for (i = 0; i < n_ext_range; i++) {
-    const google_protobuf_DescriptorProto_ExtensionRange* r = ext_ranges[i];
-    upb_ExtensionRange* r_def = (upb_ExtensionRange*)&m->ext_ranges[i];
-    int32_t start = google_protobuf_DescriptorProto_ExtensionRange_start(r);
-    int32_t end = google_protobuf_DescriptorProto_ExtensionRange_end(r);
-    int32_t max =
-        google_protobuf_MessageOptions_message_set_wire_format(m->opts)
-            ? INT32_MAX
-            : kUpb_MaxFieldNumber + 1;
-
-    // A full validation would also check that each range is disjoint, and that
-    // none of the fields overlap with the extension ranges, but we are just
-    // sanity checking here.
-    if (start < 1 || end <= start || end > max) {
-      symtab_errf(ctx, "Extension range (%d, %d) is invalid, message=%s\n",
-                  (int)start, (int)end, m->full_name);
-    }
-
-    r_def->start = start;
-    r_def->end = end;
-    SET_OPTIONS(r_def->opts, DescriptorProto_ExtensionRange,
-                ExtensionRangeOptions, r);
-  }
-
-  finalize_oneofs(ctx, m);
-  assign_msg_wellknowntype(m);
-  upb_inttable_compact(&m->itof, ctx->arena);
-  msgdef_create_nested(ctx, msg_proto, m);
-}
-
-static void msgdef_create_nested(
-    symtab_addctx* ctx, const google_protobuf_DescriptorProto* msg_proto,
-    upb_MessageDef* m) {
-  size_t n;
-
-  const google_protobuf_EnumDescriptorProto* const* enums =
-      google_protobuf_DescriptorProto_enum_type(msg_proto, &n);
-  m->nested_enum_count = n;
-  m->nested_enums = symtab_alloc(ctx, sizeof(*m->nested_enums) * n);
-  for (size_t i = 0; i < n; i++) {
-    m->nested_enum_count = i + 1;
-    create_enumdef(ctx, m->full_name, enums[i], m, &m->nested_enums[i]);
-  }
-
-  const google_protobuf_FieldDescriptorProto* const* exts =
-      google_protobuf_DescriptorProto_extension(msg_proto, &n);
-  m->nested_ext_count = n;
-  m->nested_exts = symtab_alloc(ctx, sizeof(*m->nested_exts) * n);
-  for (size_t i = 0; i < n; i++) {
-    create_fielddef(ctx, m->full_name, m, exts[i], &m->nested_exts[i],
-                    /* is_extension= */ true);
-    ((upb_FieldDef*)&m->nested_exts[i])->index_ = i;
-  }
-
-  const google_protobuf_DescriptorProto* const* msgs =
-      google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  m->nested_msg_count = n;
-  m->nested_msgs = symtab_alloc(ctx, sizeof(*m->nested_msgs) * n);
-  for (size_t i = 0; i < n; i++) {
-    create_msgdef(ctx, m->full_name, msgs[i], m, &m->nested_msgs[i]);
-  }
-}
-
-static void resolve_subdef(symtab_addctx* ctx, const char* prefix,
-                           upb_FieldDef* f) {
-  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
-  upb_StringView name =
-      google_protobuf_FieldDescriptorProto_type_name(field_proto);
-  bool has_name =
-      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
-  switch ((int)f->type_) {
-    case FIELD_TYPE_UNSPECIFIED: {
-      // Type was not specified and must be inferred.
-      UPB_ASSERT(has_name);
-      upb_deftype_t type;
-      const void* def =
-          symtab_resolveany(ctx, f->full_name, prefix, name, &type);
-      switch (type) {
-        case UPB_DEFTYPE_ENUM:
-          f->sub.enumdef = def;
-          f->type_ = kUpb_FieldType_Enum;
-          break;
-        case UPB_DEFTYPE_MSG:
-          f->sub.msgdef = def;
-          f->type_ = kUpb_FieldType_Message;  // It appears there is no way of
-                                              // this being a group.
-          break;
-        default:
-          symtab_errf(ctx, "Couldn't resolve type name for field %s",
-                      f->full_name);
-      }
-    }
-    case kUpb_FieldType_Message:
-    case kUpb_FieldType_Group:
-      UPB_ASSERT(has_name);
-      f->sub.msgdef =
-          symtab_resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_MSG);
-      break;
-    case kUpb_FieldType_Enum:
-      UPB_ASSERT(has_name);
-      f->sub.enumdef =
-          symtab_resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_ENUM);
-      break;
-    default:
-      // No resolution necessary.
-      break;
-  }
-}
-
-static void resolve_extension(
-    symtab_addctx* ctx, const char* prefix, upb_FieldDef* f,
-    const google_protobuf_FieldDescriptorProto* field_proto) {
-  if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
-    symtab_errf(ctx, "extension for field '%s' had no extendee", f->full_name);
-  }
-
-  upb_StringView name =
-      google_protobuf_FieldDescriptorProto_extendee(field_proto);
-  const upb_MessageDef* m =
-      symtab_resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_MSG);
-  f->msgdef = m;
-
-  bool found = false;
-
-  for (int i = 0, n = m->ext_range_count; i < n; i++) {
-    const upb_ExtensionRange* r = &m->ext_ranges[i];
-    if (r->start <= f->number_ && f->number_ < r->end) {
-      found = true;
-      break;
-    }
-  }
-
-  if (!found) {
-    symtab_errf(ctx,
-                "field number %u in extension %s has no extension range in "
-                "message %s",
-                (unsigned)f->number_, f->full_name, f->msgdef->full_name);
-  }
-
-  const upb_MiniTable_Extension* ext = ctx->file->ext_layouts[f->layout_index];
-  if (ctx->layout) {
-    UPB_ASSERT(upb_FieldDef_Number(f) == ext->field.number);
-  } else {
-    upb_MiniTable_Extension* mut_ext = (upb_MiniTable_Extension*)ext;
-    fill_fieldlayout(&mut_ext->field, f);
-    mut_ext->field.presence = 0;
-    mut_ext->field.offset = 0;
-    mut_ext->field.submsg_index = 0;
-    mut_ext->extendee = f->msgdef->layout;
-    mut_ext->sub.submsg = f->sub.msgdef->layout;
-  }
-
-  CHK_OOM(upb_inttable_insert(&ctx->symtab->exts, (uintptr_t)ext,
-                              upb_value_constptr(f), ctx->arena));
-}
-
-static void resolve_default(
-    symtab_addctx* ctx, upb_FieldDef* f,
-    const google_protobuf_FieldDescriptorProto* field_proto) {
-  // 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_StringView defaultval =
-        google_protobuf_FieldDescriptorProto_default_value(field_proto);
-
-    if (f->file->syntax == kUpb_Syntax_Proto3) {
-      symtab_errf(ctx, "proto3 fields cannot have explicit defaults (%s)",
-                  f->full_name);
-    }
-
-    if (upb_FieldDef_IsSubMessage(f)) {
-      symtab_errf(ctx, "message fields cannot have explicit defaults (%s)",
-                  f->full_name);
-    }
-
-    parse_default(ctx, defaultval.data, defaultval.size, f);
-    f->has_default = true;
-  } else {
-    set_default_default(ctx, f);
-    f->has_default = false;
-  }
-}
-
-static void resolve_fielddef(symtab_addctx* ctx, const char* prefix,
-                             upb_FieldDef* f) {
-  // We have to stash this away since resolve_subdef() may overwrite it.
-  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
-
-  resolve_subdef(ctx, prefix, f);
-  resolve_default(ctx, f, field_proto);
-
-  if (f->is_extension_) {
-    resolve_extension(ctx, prefix, f, field_proto);
-  }
-}
-
-static void resolve_msgdef(symtab_addctx* ctx, upb_MessageDef* m) {
-  for (int i = 0; i < m->field_count; i++) {
-    resolve_fielddef(ctx, m->full_name, (upb_FieldDef*)&m->fields[i]);
-  }
-
-  m->in_message_set = false;
-  for (int i = 0; i < m->nested_ext_count; i++) {
-    upb_FieldDef* ext = (upb_FieldDef*)&m->nested_exts[i];
-    resolve_fielddef(ctx, m->full_name, ext);
-    if (ext->type_ == kUpb_FieldType_Message &&
-        ext->label_ == kUpb_Label_Optional && ext->sub.msgdef == m &&
-        google_protobuf_MessageOptions_message_set_wire_format(
-            ext->msgdef->opts)) {
-      m->in_message_set = true;
-    }
-  }
-
-  if (!ctx->layout) make_layout(ctx, m);
-
-  for (int i = 0; i < m->nested_msg_count; i++) {
-    resolve_msgdef(ctx, (upb_MessageDef*)&m->nested_msgs[i]);
-  }
-}
-
-static int count_exts_in_msg(const google_protobuf_DescriptorProto* msg_proto) {
-  size_t n;
-  google_protobuf_DescriptorProto_extension(msg_proto, &n);
-  int ext_count = n;
-
-  const google_protobuf_DescriptorProto* const* nested_msgs =
-      google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
-  for (size_t i = 0; i < n; i++) {
-    ext_count += count_exts_in_msg(nested_msgs[i]);
-  }
-
-  return ext_count;
-}
-
-static void build_filedef(
-    symtab_addctx* ctx, upb_FileDef* file,
-    const google_protobuf_FileDescriptorProto* file_proto) {
-  const google_protobuf_DescriptorProto* const* msgs;
-  const google_protobuf_EnumDescriptorProto* const* enums;
-  const google_protobuf_FieldDescriptorProto* const* exts;
-  const google_protobuf_ServiceDescriptorProto* const* services;
-  const upb_StringView* strs;
-  const int32_t* public_deps;
-  const int32_t* weak_deps;
-  size_t i, n;
-
-  file->symtab = ctx->symtab;
-
-  /* Count all extensions in the file, to build a flat array of layouts. */
-  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  int ext_count = n;
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  for (int i = 0; i < n; i++) {
-    ext_count += count_exts_in_msg(msgs[i]);
-  }
-  file->ext_count = ext_count;
-
-  if (ctx->layout) {
-    /* We are using the ext layouts that were passed in. */
-    file->ext_layouts = ctx->layout->exts;
-    if (ctx->layout->ext_count != file->ext_count) {
-      symtab_errf(ctx, "Extension count did not match layout (%d vs %d)",
-                  ctx->layout->ext_count, file->ext_count);
-    }
-  } else {
-    /* We are building ext layouts from scratch. */
-    file->ext_layouts =
-        symtab_alloc(ctx, sizeof(*file->ext_layouts) * file->ext_count);
-    upb_MiniTable_Extension* ext =
-        symtab_alloc(ctx, sizeof(*ext) * file->ext_count);
-    for (int i = 0; i < file->ext_count; i++) {
-      file->ext_layouts[i] = &ext[i];
-    }
-  }
-
-  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));
-
-  if (google_protobuf_FileDescriptorProto_has_package(file_proto)) {
-    upb_StringView 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_StringView syntax =
-        google_protobuf_FileDescriptorProto_syntax(file_proto);
-
-    if (streql_view(syntax, "proto2")) {
-      file->syntax = kUpb_Syntax_Proto2;
-    } else if (streql_view(syntax, "proto3")) {
-      file->syntax = kUpb_Syntax_Proto3;
-    } else {
-      symtab_errf(ctx, "Invalid syntax '" UPB_STRINGVIEW_FORMAT "'",
-                  UPB_STRINGVIEW_ARGS(syntax));
-    }
-  } else {
-    file->syntax = kUpb_Syntax_Proto2;
-  }
-
-  /* Read options. */
-  SET_OPTIONS(file->opts, FileDescriptorProto, FileOptions, file_proto);
-
-  /* Verify dependencies. */
-  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
-  file->dep_count = n;
-  file->deps = symtab_alloc(ctx, sizeof(*file->deps) * n);
-
-  for (i = 0; i < n; i++) {
-    upb_StringView str = strs[i];
-    file->deps[i] =
-        upb_DefPool_FindFileByNameWithSize(ctx->symtab, str.data, str.size);
-    if (!file->deps[i]) {
-      symtab_errf(ctx,
-                  "Depends on file '" UPB_STRINGVIEW_FORMAT
-                  "', but it has not been loaded",
-                  UPB_STRINGVIEW_ARGS(str));
-    }
-  }
-
-  public_deps =
-      google_protobuf_FileDescriptorProto_public_dependency(file_proto, &n);
-  file->public_dep_count = n;
-  file->public_deps = symtab_alloc(ctx, sizeof(*file->public_deps) * n);
-  int32_t* mutable_public_deps = (int32_t*)file->public_deps;
-  for (i = 0; i < n; i++) {
-    if (public_deps[i] >= file->dep_count) {
-      symtab_errf(ctx, "public_dep %d is out of range", (int)public_deps[i]);
-    }
-    mutable_public_deps[i] = public_deps[i];
-  }
-
-  weak_deps =
-      google_protobuf_FileDescriptorProto_weak_dependency(file_proto, &n);
-  file->weak_dep_count = n;
-  file->weak_deps = symtab_alloc(ctx, sizeof(*file->weak_deps) * n);
-  int32_t* mutable_weak_deps = (int32_t*)file->weak_deps;
-  for (i = 0; i < n; i++) {
-    if (weak_deps[i] >= file->dep_count) {
-      symtab_errf(ctx, "weak_dep %d is out of range", (int)weak_deps[i]);
-    }
-    mutable_weak_deps[i] = weak_deps[i];
-  }
-
-  /* Create enums. */
-  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
-  file->top_lvl_enum_count = n;
-  file->top_lvl_enums = symtab_alloc(ctx, sizeof(*file->top_lvl_enums) * n);
-  for (i = 0; i < n; i++) {
-    create_enumdef(ctx, file->package, enums[i], NULL, &file->top_lvl_enums[i]);
-  }
-
-  /* Create extensions. */
-  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
-  file->top_lvl_ext_count = n;
-  file->top_lvl_exts = symtab_alloc(ctx, sizeof(*file->top_lvl_exts) * n);
-  for (i = 0; i < n; i++) {
-    create_fielddef(ctx, file->package, NULL, exts[i], &file->top_lvl_exts[i],
-                    /* is_extension= */ true);
-    ((upb_FieldDef*)&file->top_lvl_exts[i])->index_ = i;
-  }
-
-  /* Create messages. */
-  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
-  file->top_lvl_msg_count = n;
-  file->top_lvl_msgs = symtab_alloc(ctx, sizeof(*file->top_lvl_msgs) * n);
-  for (i = 0; i < n; i++) {
-    create_msgdef(ctx, file->package, msgs[i], NULL, &file->top_lvl_msgs[i]);
-  }
-
-  /* Create services. */
-  services = google_protobuf_FileDescriptorProto_service(file_proto, &n);
-  file->service_count = n;
-  file->services = symtab_alloc(ctx, sizeof(*file->services) * n);
-  for (i = 0; i < n; i++) {
-    create_service(ctx, services[i], &file->services[i]);
-    ((upb_ServiceDef*)&file->services[i])->index = i;
-  }
-
-  /* Now that all names are in the table, build layouts and resolve refs. */
-  for (i = 0; i < (size_t)file->top_lvl_ext_count; i++) {
-    resolve_fielddef(ctx, file->package, (upb_FieldDef*)&file->top_lvl_exts[i]);
-  }
-
-  for (i = 0; i < (size_t)file->top_lvl_msg_count; i++) {
-    resolve_msgdef(ctx, (upb_MessageDef*)&file->top_lvl_msgs[i]);
-  }
-
-  if (file->ext_count) {
-    CHK_OOM(_upb_extreg_add(ctx->symtab->extreg, file->ext_layouts,
-                            file->ext_count));
-  }
-}
-
-static void remove_filedef(upb_DefPool* s, upb_FileDef* file) {
-  intptr_t iter = UPB_INTTABLE_BEGIN;
-  upb_StringView key;
-  upb_value val;
-  while (upb_strtable_next2(&s->syms, &key, &val, &iter)) {
-    const upb_FileDef* f;
-    switch (deftype(val)) {
-      case UPB_DEFTYPE_EXT:
-        f = upb_FieldDef_File(unpack_def(val, UPB_DEFTYPE_EXT));
-        break;
-      case UPB_DEFTYPE_MSG:
-        f = upb_MessageDef_File(unpack_def(val, UPB_DEFTYPE_MSG));
-        break;
-      case UPB_DEFTYPE_ENUM:
-        f = upb_EnumDef_File(unpack_def(val, UPB_DEFTYPE_ENUM));
-        break;
-      case UPB_DEFTYPE_ENUMVAL:
-        f = upb_EnumDef_File(
-            upb_EnumValueDef_Enum(unpack_def(val, UPB_DEFTYPE_ENUMVAL)));
-        break;
-      case UPB_DEFTYPE_SERVICE:
-        f = upb_ServiceDef_File(unpack_def(val, UPB_DEFTYPE_SERVICE));
-        break;
-      default:
-        UPB_UNREACHABLE();
-    }
-
-    if (f == file) upb_strtable_removeiter(&s->syms, &iter);
-  }
-}
-
-static const upb_FileDef* _upb_DefPool_AddFile(
-    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
-    const upb_MiniTable_File* layout, upb_Status* status) {
-  symtab_addctx ctx;
-  upb_StringView name = google_protobuf_FileDescriptorProto_name(file_proto);
-  upb_value v;
-
-  if (upb_strtable_lookup2(&s->files, name.data, name.size, &v)) {
-    if (unpack_def(v, UPB_DEFTYPE_FILE)) {
-      upb_Status_SetErrorFormat(status, "duplicate file name (%.*s)",
-                                UPB_STRINGVIEW_ARGS(name));
-      return NULL;
-    }
-    const upb_MiniTable_File* registered = unpack_def(v, UPB_DEFTYPE_LAYOUT);
-    UPB_ASSERT(registered);
-    if (layout && layout != registered) {
-      upb_Status_SetErrorFormat(
-          status, "tried to build with a different layout (filename=%.*s)",
-          UPB_STRINGVIEW_ARGS(name));
-      return NULL;
-    }
-    layout = registered;
-  }
-
-  ctx.symtab = s;
-  ctx.layout = layout;
-  ctx.msg_count = 0;
-  ctx.enum_count = 0;
-  ctx.ext_count = 0;
-  ctx.status = status;
-  ctx.file = NULL;
-  ctx.arena = upb_Arena_New();
-  ctx.tmp_arena = upb_Arena_New();
-
-  if (!ctx.arena || !ctx.tmp_arena) {
-    if (ctx.arena) upb_Arena_Free(ctx.arena);
-    if (ctx.tmp_arena) upb_Arena_Free(ctx.tmp_arena);
-    upb_Status_setoom(status);
-    return NULL;
-  }
-
-  if (UPB_UNLIKELY(UPB_SETJMP(ctx.err))) {
-    UPB_ASSERT(!upb_Status_IsOk(status));
-    if (ctx.file) {
-      remove_filedef(s, ctx.file);
-      ctx.file = NULL;
-    }
-  } else {
-    ctx.file = symtab_alloc(&ctx, sizeof(*ctx.file));
-    build_filedef(&ctx, ctx.file, file_proto);
-    upb_strtable_insert(&s->files, name.data, name.size,
-                        pack_def(ctx.file, UPB_DEFTYPE_FILE), ctx.arena);
-    UPB_ASSERT(upb_Status_IsOk(status));
-    upb_Arena_Fuse(s->arena, ctx.arena);
-  }
-
-  upb_Arena_Free(ctx.arena);
-  upb_Arena_Free(ctx.tmp_arena);
-  return ctx.file;
-}
-
-const upb_FileDef* upb_DefPool_AddFile(
-    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
-    upb_Status* status) {
-  return _upb_DefPool_AddFile(s, file_proto, NULL, status);
-}
-
-/* Include here since we want most of this file to be stdio-free. */
-#include <stdio.h>
-
-bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
-                                bool rebuild_minitable) {
-  /* 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_DefPool_Init** deps = init->deps;
-  google_protobuf_FileDescriptorProto* file;
-  upb_Arena* arena;
-  upb_Status status;
-
-  upb_Status_Clear(&status);
-
-  if (upb_DefPool_FindFileByName(s, init->filename)) {
-    return true;
-  }
-
-  arena = upb_Arena_New();
-
-  for (; *deps; deps++) {
-    if (!_upb_DefPool_LoadDefInitEx(s, *deps, rebuild_minitable)) goto err;
-  }
-
-  file = google_protobuf_FileDescriptorProto_parse_ex(
-      init->descriptor.data, init->descriptor.size, NULL,
-      kUpb_DecodeOption_AliasString, arena);
-  s->bytes_loaded += init->descriptor.size;
-
-  if (!file) {
-    upb_Status_SetErrorFormat(
-        &status,
-        "Failed to parse compiled-in descriptor for file '%s'. This should "
-        "never happen.",
-        init->filename);
-    goto err;
-  }
-
-  const upb_MiniTable_File* mt = rebuild_minitable ? NULL : init->layout;
-  if (!_upb_DefPool_AddFile(s, file, mt, &status)) {
-    goto err;
-  }
-
-  upb_Arena_Free(arena);
-  return true;
-
-err:
-  fprintf(stderr,
-          "Error loading compiled-in descriptor for file '%s' (this should "
-          "never happen): %s\n",
-          init->filename, upb_Status_ErrorMessage(&status));
-  upb_Arena_Free(arena);
-  return false;
-}
-
-size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s) {
-  return s->bytes_loaded;
-}
-
-upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s) { return s->arena; }
-
-const upb_FieldDef* _upb_DefPool_FindExtensionByMiniTable(
-    const upb_DefPool* s, const upb_MiniTable_Extension* ext) {
-  upb_value v;
-  bool ok = upb_inttable_lookup(&s->exts, (uintptr_t)ext, &v);
-  UPB_ASSERT(ok);
-  return upb_value_getconstptr(v);
-}
-
-const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
-                                                      const upb_MessageDef* m,
-                                                      int32_t fieldnum) {
-  const upb_MiniTable* l = upb_MessageDef_MiniTable(m);
-  const upb_MiniTable_Extension* ext = _upb_extreg_get(s->extreg, l, fieldnum);
-  return ext ? _upb_DefPool_FindExtensionByMiniTable(s, ext) : NULL;
-}
-
-bool _upb_DefPool_registerlayout(upb_DefPool* s, const char* filename,
-                                 const upb_MiniTable_File* file) {
-  if (upb_DefPool_FindFileByName(s, filename)) return false;
-  upb_value v = pack_def(file, UPB_DEFTYPE_LAYOUT);
-  return upb_strtable_insert(&s->files, filename, strlen(filename), v,
-                             s->arena);
-}
-
-const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
-    const upb_DefPool* s) {
-  return s->extreg;
-}
-
-const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
-                                                  const upb_MessageDef* m,
-                                                  size_t* count) {
-  size_t n = 0;
-  intptr_t iter = UPB_INTTABLE_BEGIN;
-  uintptr_t key;
-  upb_value val;
-  // This is O(all exts) instead of O(exts for m).  If we need this to be
-  // efficient we may need to make extreg into a two-level table, or have a
-  // second per-message index.
-  while (upb_inttable_next2(&s->exts, &key, &val, &iter)) {
-    const upb_FieldDef* f = upb_value_getconstptr(val);
-    if (upb_FieldDef_ContainingType(f) == m) n++;
-  }
-  const upb_FieldDef** exts = malloc(n * sizeof(*exts));
-  iter = UPB_INTTABLE_BEGIN;
-  size_t i = 0;
-  while (upb_inttable_next2(&s->exts, &key, &val, &iter)) {
-    const upb_FieldDef* f = upb_value_getconstptr(val);
-    if (upb_FieldDef_ContainingType(f) == m) exts[i++] = f;
-  }
-  *count = n;
-  return exts;
-}
-
-#undef CHK_OOM
-
-/** upb/reflection.c ************************************************************/
-
-#include <string.h>
-
-
-static size_t get_field_size(const upb_MiniTable_Field* f) {
-  static unsigned char sizes[] = {
-      0,                      /* 0 */
-      8,                      /* kUpb_FieldType_Double */
-      4,                      /* kUpb_FieldType_Float */
-      8,                      /* kUpb_FieldType_Int64 */
-      8,                      /* kUpb_FieldType_UInt64 */
-      4,                      /* kUpb_FieldType_Int32 */
-      8,                      /* kUpb_FieldType_Fixed64 */
-      4,                      /* kUpb_FieldType_Fixed32 */
-      1,                      /* kUpb_FieldType_Bool */
-      sizeof(upb_StringView), /* kUpb_FieldType_String */
-      sizeof(void*),          /* kUpb_FieldType_Group */
-      sizeof(void*),          /* kUpb_FieldType_Message */
-      sizeof(upb_StringView), /* kUpb_FieldType_Bytes */
-      4,                      /* kUpb_FieldType_UInt32 */
-      4,                      /* kUpb_FieldType_Enum */
-      4,                      /* kUpb_FieldType_SFixed32 */
-      8,                      /* kUpb_FieldType_SFixed64 */
-      4,                      /* kUpb_FieldType_SInt32 */
-      8,                      /* kUpb_FieldType_SInt64 */
-  };
-  return upb_IsRepeatedOrMap(f) ? sizeof(void*) : sizes[f->descriptortype];
-}
-
-/* Strings/bytes are special-cased in maps. */
-static char _upb_CTypeo_mapsize[12] = {
-    0,
-    1,             /* kUpb_CType_Bool */
-    4,             /* kUpb_CType_Float */
-    4,             /* kUpb_CType_Int32 */
-    4,             /* kUpb_CType_UInt32 */
-    4,             /* kUpb_CType_Enum */
-    sizeof(void*), /* kUpb_CType_Message */
-    8,             /* kUpb_CType_Double */
-    8,             /* kUpb_CType_Int64 */
-    8,             /* kUpb_CType_UInt64 */
-    0,             /* kUpb_CType_String */
-    0,             /* kUpb_CType_Bytes */
-};
-
-static const char _upb_CTypeo_sizelg2[12] = {
-    0,
-    0,              /* kUpb_CType_Bool */
-    2,              /* kUpb_CType_Float */
-    2,              /* kUpb_CType_Int32 */
-    2,              /* kUpb_CType_UInt32 */
-    2,              /* kUpb_CType_Enum */
-    UPB_SIZE(2, 3), /* kUpb_CType_Message */
-    3,              /* kUpb_CType_Double */
-    3,              /* kUpb_CType_Int64 */
-    3,              /* kUpb_CType_UInt64 */
-    UPB_SIZE(3, 4), /* kUpb_CType_String */
-    UPB_SIZE(3, 4), /* kUpb_CType_Bytes */
-};
-
-/** upb_Message
- * *******************************************************************/
-
-upb_Message* upb_Message_New(const upb_MessageDef* m, upb_Arena* a) {
-  return _upb_Message_New(upb_MessageDef_MiniTable(m), a);
-}
-
-static bool in_oneof(const upb_MiniTable_Field* field) {
-  return field->presence < 0;
-}
-
-static upb_MessageValue _upb_Message_Getraw(const upb_Message* msg,
-                                            const upb_FieldDef* f) {
-  const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(f);
-  const char* mem = UPB_PTR_AT(msg, field->offset, char);
-  upb_MessageValue val = {0};
-  memcpy(&val, mem, get_field_size(field));
-  return val;
-}
-
-bool upb_Message_Has(const upb_Message* msg, const upb_FieldDef* f) {
-  assert(upb_FieldDef_HasPresence(f));
-  if (upb_FieldDef_IsExtension(f)) {
-    const upb_MiniTable_Extension* ext = _upb_FieldDef_ExtensionMiniTable(f);
-    return _upb_Message_Getext(msg, ext) != NULL;
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(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 == kUpb_FieldType_Message ||
-                 field->descriptortype == kUpb_FieldType_Group);
-      return _upb_Message_Getraw(msg, f).msg_val != NULL;
-    }
-  }
-}
-
-const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* 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_Message_Has(msg, f) ? f : NULL;
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(f);
-    uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
-    f = oneof_case ? upb_OneofDef_LookupNumber(o, oneof_case) : NULL;
-    UPB_ASSERT((f != NULL) == (oneof_case != 0));
-    return f;
-  }
-}
-
-upb_MessageValue upb_Message_Get(const upb_Message* msg,
-                                 const upb_FieldDef* f) {
-  if (upb_FieldDef_IsExtension(f)) {
-    const upb_Message_Extension* ext =
-        _upb_Message_Getext(msg, _upb_FieldDef_ExtensionMiniTable(f));
-    if (ext) {
-      upb_MessageValue val;
-      memcpy(&val, &ext->data, sizeof(val));
-      return val;
-    } else if (upb_FieldDef_IsRepeated(f)) {
-      return (upb_MessageValue){.array_val = NULL};
-    }
-  } else if (!upb_FieldDef_HasPresence(f) || upb_Message_Has(msg, f)) {
-    return _upb_Message_Getraw(msg, f);
-  }
-  return upb_FieldDef_Default(f);
-}
-
-upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg,
-                                            const upb_FieldDef* f,
-                                            upb_Arena* a) {
-  UPB_ASSERT(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_IsRepeated(f));
-  if (upb_FieldDef_HasPresence(f) && !upb_Message_Has(msg, f)) {
-    // We need to skip the upb_Message_Get() call in this case.
-    goto make;
-  }
-
-  upb_MessageValue val = upb_Message_Get(msg, f);
-  if (val.array_val) {
-    return (upb_MutableMessageValue){.array = (upb_Array*)val.array_val};
-  }
-
-  upb_MutableMessageValue ret;
-make:
-  if (!a) return (upb_MutableMessageValue){.array = NULL};
-  if (upb_FieldDef_IsMap(f)) {
-    const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
-    const upb_FieldDef* key =
-        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
-    const upb_FieldDef* value =
-        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
-    ret.map =
-        upb_Map_New(a, upb_FieldDef_CType(key), upb_FieldDef_CType(value));
-  } else if (upb_FieldDef_IsRepeated(f)) {
-    ret.array = upb_Array_New(a, upb_FieldDef_CType(f));
-  } else {
-    UPB_ASSERT(upb_FieldDef_IsSubMessage(f));
-    ret.msg = upb_Message_New(upb_FieldDef_MessageSubDef(f), a);
-  }
-
-  val.array_val = ret.array;
-  upb_Message_Set(msg, f, val, a);
-
-  return ret;
-}
-
-bool upb_Message_Set(upb_Message* msg, const upb_FieldDef* f,
-                     upb_MessageValue val, upb_Arena* a) {
-  if (upb_FieldDef_IsExtension(f)) {
-    upb_Message_Extension* ext = _upb_Message_Getorcreateext(
-        msg, _upb_FieldDef_ExtensionMiniTable(f), a);
-    if (!ext) return false;
-    memcpy(&ext->data, &val, sizeof(val));
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(f);
-    char* mem = UPB_PTR_AT(msg, field->offset, char);
-    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;
-    }
-  }
-  return true;
-}
-
-void upb_Message_ClearField(upb_Message* msg, const upb_FieldDef* f) {
-  if (upb_FieldDef_IsExtension(f)) {
-    _upb_Message_Clearext(msg, _upb_FieldDef_ExtensionMiniTable(f));
-  } else {
-    const upb_MiniTable_Field* field = upb_FieldDef_MiniTable(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_Message_Clear(upb_Message* msg, const upb_MessageDef* m) {
-  _upb_Message_Clear(msg, upb_MessageDef_MiniTable(m));
-}
-
-bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
-                      const upb_DefPool* ext_pool, const upb_FieldDef** out_f,
-                      upb_MessageValue* out_val, size_t* iter) {
-  size_t i = *iter;
-  size_t n = upb_MessageDef_FieldCount(m);
-  const upb_MessageValue zero = {0};
-  UPB_UNUSED(ext_pool);
-
-  /* Iterate over normal fields, returning the first one that is set. */
-  while (++i < n) {
-    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
-    upb_MessageValue val = _upb_Message_Getraw(msg, f);
-
-    /* Skip field if unset or empty. */
-    if (upb_FieldDef_HasPresence(f)) {
-      if (!upb_Message_Has(msg, f)) continue;
-    } else {
-      upb_MessageValue test = val;
-      if (upb_FieldDef_IsString(f) && !upb_FieldDef_IsRepeated(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_IsRepeated(f)) {
-        if (upb_Array_Size(test.array_val) == 0) continue;
-      }
-    }
-
-    *out_val = val;
-    *out_f = f;
-    *iter = i;
-    return true;
-  }
-
-  if (ext_pool) {
-    /* Return any extensions that are set. */
-    size_t count;
-    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &count);
-    if (i - n < count) {
-      ext += count - 1 - (i - n);
-      memcpy(out_val, &ext->data, sizeof(*out_val));
-      *out_f = _upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
-      *iter = i;
-      return true;
-    }
-  }
-
-  *iter = i;
-  return false;
-}
-
-bool _upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
-                                 int depth) {
-  size_t iter = kUpb_Message_Begin;
-  const upb_FieldDef* f;
-  upb_MessageValue val;
-  bool ret = true;
-
-  if (--depth == 0) return false;
-
-  _upb_Message_DiscardUnknown_shallow(msg);
-
-  while (upb_Message_Next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
-    const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
-    if (!subm) continue;
-    if (upb_FieldDef_IsMap(f)) {
-      const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(subm, 2);
-      const upb_MessageDef* val_m = upb_FieldDef_MessageSubDef(val_f);
-      upb_Map* map = (upb_Map*)val.map_val;
-      size_t iter = kUpb_Map_Begin;
-
-      if (!val_m) continue;
-
-      while (upb_MapIterator_Next(map, &iter)) {
-        upb_MessageValue map_val = upb_MapIterator_Value(map, iter);
-        if (!_upb_Message_DiscardUnknown((upb_Message*)map_val.msg_val, val_m,
-                                         depth)) {
-          ret = false;
-        }
-      }
-    } else if (upb_FieldDef_IsRepeated(f)) {
-      const upb_Array* arr = val.array_val;
-      size_t i, n = upb_Array_Size(arr);
-      for (i = 0; i < n; i++) {
-        upb_MessageValue elem = upb_Array_Get(arr, i);
-        if (!_upb_Message_DiscardUnknown((upb_Message*)elem.msg_val, subm,
-                                         depth)) {
-          ret = false;
-        }
-      }
-    } else {
-      if (!_upb_Message_DiscardUnknown((upb_Message*)val.msg_val, subm,
-                                       depth)) {
-        ret = false;
-      }
-    }
-  }
-
-  return ret;
-}
-
-bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
-                                int maxdepth) {
-  return _upb_Message_DiscardUnknown(msg, m, maxdepth);
-}
-
-/** upb_Array *****************************************************************/
-
-upb_Array* upb_Array_New(upb_Arena* a, upb_CType type) {
-  return _upb_Array_New(a, 4, _upb_CTypeo_sizelg2[type]);
-}
-
-size_t upb_Array_Size(const upb_Array* arr) { return arr->len; }
-
-upb_MessageValue upb_Array_Get(const upb_Array* arr, size_t i) {
-  upb_MessageValue 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_MessageValue 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_MessageValue 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;
-}
-
-void upb_Array_Move(upb_Array* arr, size_t dst_idx, size_t src_idx,
-                    size_t count) {
-  char* data = _upb_array_ptr(arr);
-  int lg2 = arr->data & 7;
-  memmove(&data[dst_idx << lg2], &data[src_idx << lg2], count << lg2);
-}
-
-bool upb_Array_Insert(upb_Array* arr, size_t i, size_t count,
-                      upb_Arena* arena) {
-  UPB_ASSERT(i <= arr->len);
-  UPB_ASSERT(count + arr->len >= count);
-  size_t oldsize = arr->len;
-  if (!upb_Array_Resize(arr, arr->len + count, arena)) {
-    return false;
-  }
-  upb_Array_Move(arr, i + count, i, oldsize - i);
-  return true;
-}
-
-/*
- *              i        end      arr->len
- * |------------|XXXXXXXX|--------|
- */
-void upb_Array_Delete(upb_Array* arr, size_t i, size_t count) {
-  size_t end = i + count;
-  UPB_ASSERT(i <= end);
-  UPB_ASSERT(end <= arr->len);
-  upb_Array_Move(arr, i, end, arr->len - end);
-  arr->len -= count;
-}
-
-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_CType key_type, upb_CType value_type) {
-  return _upb_Map_New(a, _upb_CTypeo_mapsize[key_type],
-                      _upb_CTypeo_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_MessageValue key,
-                 upb_MessageValue* 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_MessageValue key, upb_MessageValue 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_MessageValue key) {
-  return _upb_Map_Delete(map, &key, map->key_size);
-}
-
-bool upb_MapIterator_Next(const upb_Map* map, size_t* iter) {
-  return _upb_map_next(map, iter);
-}
-
-bool upb_MapIterator_Done(const upb_Map* map, size_t iter) {
-  upb_strtable_iter i;
-  UPB_ASSERT(iter != kUpb_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_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter) {
-  upb_strtable_iter i;
-  upb_MessageValue ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromkey(upb_strtable_iter_key(&i), &ret, map->key_size);
-  return ret;
-}
-
-upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter) {
-  upb_strtable_iter i;
-  upb_MessageValue ret;
-  i.t = &map->table;
-  i.index = iter;
-  _upb_map_fromvalue(upb_strtable_iter_value(&i), &ret, map->val_size);
-  return ret;
-}
-
-/* void upb_MapIterator_SetValue(upb_Map *map, size_t iter, upb_MessageValue
- * 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. */
+// Must be last.
 
 typedef struct {
   const char *ptr, *end;
@@ -9200,44 +2461,20 @@
 /* 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) {
+  if (upb_Unicode_IsHigh(cp)) {
     /* 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) {
+    uint32_t low = jsondec_codepoint(d);
+    if (!upb_Unicode_IsLow(low)) jsondec_err(d, "Invalid low surrogate");
+    cp = upb_Unicode_FromPair(cp, low);
+  } else if (upb_Unicode_IsLow(cp)) {
     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");
-  }
+  int bytes = upb_Unicode_ToUTF8(cp, out);
+  if (bytes == 0) jsondec_err(d, "Invalid codepoint");
+  return bytes;
 }
 
 static void jsondec_resize(jsondec* d, char** buf, char** end, char** buf_end) {
@@ -9283,7 +2520,7 @@
         if (*d->ptr == 'u') {
           d->ptr++;
           if (buf_end - end < 4) {
-            /* Allow space for maximum-sized code point (4 bytes). */
+            /* Allow space for maximum-sized codepoint (4 bytes). */
             jsondec_resize(d, &buf, &end, &buf_end);
           }
           end += jsondec_unicode(d, end);
@@ -9456,44 +2693,19 @@
 
 /* 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;
+  const char* out = upb_BufToUint64(ptr, end, val);
+  if (!out) jsondec_err(d, "Integer overflow");
+  return out;
 }
 
 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;
+                                      const char* end, int64_t* val,
+                                      bool* is_neg) {
+  const char* out = upb_BufToInt64(ptr, end, val, is_neg);
+  if (!out) jsondec_err(d, "Integer overflow");
+  return out;
 }
 
 static uint64_t jsondec_strtouint64(jsondec* d, upb_StringView str) {
@@ -9508,7 +2720,7 @@
 static int64_t jsondec_strtoint64(jsondec* d, upb_StringView str) {
   const char* end = str.data + str.size;
   int64_t ret;
-  if (jsondec_buftoint64(d, str.data, end, &ret) != end) {
+  if (jsondec_buftoint64(d, str.data, end, &ret, NULL) != end) {
     jsondec_err(d, "Non-number characters in quoted integer");
   }
   return ret;
@@ -9615,11 +2827,11 @@
   }
 
   if (upb_FieldDef_CType(f) == kUpb_CType_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");
+    float f = val.double_val;
+    if (val.double_val != INFINITY && val.double_val != -INFINITY) {
+      if (f == INFINITY || f == -INFINITY) jsondec_err(d, "Float out of range");
     }
-    val.float_val = val.double_val;
+    val.float_val = f;
   }
 
   return val;
@@ -9742,7 +2954,8 @@
 
 static upb_MessageValue jsondec_msg(jsondec* d, const upb_FieldDef* f) {
   const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
-  upb_Message* msg = upb_Message_New(m, d->arena);
+  const upb_MiniTable* layout = upb_MessageDef_MiniTable(m);
+  upb_Message* msg = upb_Message_New(layout, d->arena);
   upb_MessageValue val;
 
   jsondec_tomsg(d, msg, m);
@@ -9977,9 +3190,10 @@
   const char* ptr = str.data;
   const char* end = ptr + str.size;
   const int64_t max = (uint64_t)3652500 * 86400;
+  bool neg = false;
 
   /* "3.000000001s", "3s", etc. */
-  ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val);
+  ptr = jsondec_buftoint64(d, ptr, end, &seconds.int64_val, &neg);
   nanos.int32_val = jsondec_nanos(d, &ptr, end);
 
   if (end - ptr != 1 || *ptr != 's') {
@@ -9990,7 +3204,7 @@
     jsondec_err(d, "Duration out of range");
   }
 
-  if (seconds.int64_val < 0) {
+  if (neg) {
     nanos.int32_val = -nanos.int32_val;
   }
 
@@ -10003,11 +3217,12 @@
                               const upb_MessageDef* m) {
   const upb_FieldDef* values_f = upb_MessageDef_FindFieldByNumber(m, 1);
   const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(values_f);
+  const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m);
   upb_Array* values = upb_Message_Mutable(msg, values_f, d->arena).array;
 
   jsondec_arrstart(d);
   while (jsondec_arrnext(d)) {
-    upb_Message* value_msg = upb_Message_New(value_m, d->arena);
+    upb_Message* value_msg = upb_Message_New(value_layout, d->arena);
     upb_MessageValue value;
     value.msg_val = value_msg;
     upb_Array_Append(values, value, d->arena);
@@ -10022,12 +3237,13 @@
   const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
   const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
   const upb_MessageDef* value_m = upb_FieldDef_MessageSubDef(value_f);
+  const upb_MiniTable* value_layout = upb_MessageDef_MiniTable(value_m);
   upb_Map* fields = upb_Message_Mutable(msg, fields_f, d->arena).map;
 
   jsondec_objstart(d);
   while (jsondec_objnext(d)) {
     upb_MessageValue key, value;
-    upb_Message* value_msg = upb_Message_New(value_m, d->arena);
+    upb_Message* value_msg = upb_Message_New(value_layout, d->arena);
     key.str_val = jsondec_string(d);
     value.msg_val = value_msg;
     upb_Map_Set(fields, key, value, d->arena);
@@ -10229,7 +3445,8 @@
     jsondec_err(d, "Any object didn't contain a '@type' field");
   }
 
-  any_msg = upb_Message_New(any_m, d->arena);
+  const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m);
+  any_msg = upb_Message_New(any_layout, d->arena);
 
   if (pre_type_data) {
     size_t len = pre_type_end - pre_type_data + 1;
@@ -10254,8 +3471,11 @@
 
   jsondec_objend(d);
 
-  encoded.str_val.data = upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0,
-                                    d->arena, &encoded.str_val.size);
+  upb_EncodeStatus status =
+      upb_Encode(any_msg, upb_MessageDef_MiniTable(any_m), 0, d->arena,
+                 (char**)&encoded.str_val.data, &encoded.str_val.size);
+  // TODO(b/235839510): We should fail gracefully here on a bad return status.
+  UPB_ASSERT(status == kUpb_EncodeStatus_Ok);
   upb_Message_Set(msg, value_f, encoded, d->arena);
 }
 
@@ -10331,19 +3551,16 @@
   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. */
+// Must be last.
 
 typedef struct {
   char *buf, *ptr, *end;
@@ -10414,7 +3631,7 @@
   va_list args;
 
   va_start(args, fmt);
-  n = vsnprintf(e->ptr, have, fmt, args);
+  n = _upb_vsnprintf(e->ptr, have, fmt, args);
   va_end(args);
 
   if (UPB_LIKELY(have > n)) {
@@ -10490,17 +3707,27 @@
   const upb_FieldDef* nanos_f = upb_MessageDef_FindFieldByNumber(m, 2);
   int64_t seconds = upb_Message_Get(msg, seconds_f).int64_val;
   int32_t nanos = upb_Message_Get(msg, nanos_f).int32_val;
+  bool negative = false;
 
   if (seconds > 315576000000 || seconds < -315576000000 ||
-      (seconds < 0) != (nanos < 0)) {
+      (seconds != 0 && nanos != 0 && (seconds < 0) != (nanos < 0))) {
     jsonenc_err(e, "bad duration");
   }
 
+  if (seconds < 0) {
+    negative = true;
+    seconds = -seconds;
+  }
   if (nanos < 0) {
+    negative = true;
     nanos = -nanos;
   }
 
-  jsonenc_printf(e, "\"%" PRId64, seconds);
+  jsonenc_putstr(e, "\"");
+  if (negative) {
+    jsonenc_putstr(e, "-");
+  }
+  jsonenc_printf(e, "%" PRId64, seconds);
   jsonenc_nanos(e, nanos);
   jsonenc_putstr(e, "s\"");
 }
@@ -10511,7 +3738,10 @@
   if (strcmp(upb_EnumDef_FullName(e_def), "google.protobuf.NullValue") == 0) {
     jsonenc_putstr(e, "null");
   } else {
-    const upb_EnumValueDef* ev = upb_EnumDef_FindValueByNumber(e_def, val);
+    const upb_EnumValueDef* ev =
+        (e->options & upb_JsonEncode_FormatEnumsAsIntegers)
+            ? NULL
+            : upb_EnumDef_FindValueByNumber(e_def, val);
 
     if (ev) {
       jsonenc_printf(e, "\"%s\"", upb_EnumValueDef_Name(ev));
@@ -10687,7 +3917,7 @@
   const upb_MessageDef* any_m = jsonenc_getanymsg(e, type_url);
   const upb_MiniTable* any_layout = upb_MessageDef_MiniTable(any_m);
   upb_Arena* arena = jsonenc_arena(e);
-  upb_Message* any = upb_Message_New(any_m, arena);
+  upb_Message* any = upb_Message_New(any_layout, arena);
 
   if (upb_Decode(value.data, value.size, any, any_layout, NULL, 0, arena) !=
       kUpb_DecodeStatus_Ok) {
@@ -10759,20 +3989,20 @@
 
 static void jsonenc_struct(jsonenc* e, const upb_Message* msg,
                            const upb_MessageDef* m) {
-  const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1);
-  const upb_Map* fields = upb_Message_Get(msg, fields_f).map_val;
-  const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
-  const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
-  size_t iter = kUpb_Map_Begin;
-  bool first = true;
-
   jsonenc_putstr(e, "{");
 
-  if (fields) {
-    while (upb_MapIterator_Next(fields, &iter)) {
-      upb_MessageValue key = upb_MapIterator_Key(fields, iter);
-      upb_MessageValue val = upb_MapIterator_Value(fields, iter);
+  const upb_FieldDef* fields_f = upb_MessageDef_FindFieldByNumber(m, 1);
+  const upb_Map* fields = upb_Message_Get(msg, fields_f).map_val;
 
+  if (fields) {
+    const upb_MessageDef* entry_m = upb_FieldDef_MessageSubDef(fields_f);
+    const upb_FieldDef* value_f = upb_MessageDef_FindFieldByNumber(entry_m, 2);
+
+    size_t iter = kUpb_Map_Begin;
+    bool first = true;
+
+    upb_MessageValue key, val;
+    while (upb_Map_Next(fields, &key, &val, &iter)) {
       jsonenc_putsep(e, ",", &first);
       jsonenc_string(e, key.str_val);
       jsonenc_putstr(e, ":");
@@ -10966,19 +4196,21 @@
 }
 
 static void jsonenc_map(jsonenc* e, const upb_Map* map, const upb_FieldDef* f) {
+  jsonenc_putstr(e, "{");
+
   const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
   const upb_FieldDef* key_f = upb_MessageDef_FindFieldByNumber(entry, 1);
   const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(entry, 2);
-  size_t iter = kUpb_Map_Begin;
-  bool first = true;
-
-  jsonenc_putstr(e, "{");
 
   if (map) {
-    while (upb_MapIterator_Next(map, &iter)) {
+    size_t iter = kUpb_Map_Begin;
+    bool first = true;
+
+    upb_MessageValue key, val;
+    while (upb_Map_Next(map, &key, &val, &iter)) {
       jsonenc_putsep(e, ",", &first);
-      jsonenc_mapkey(e, upb_MapIterator_Key(map, iter), key_f);
-      jsonenc_scalar(e, upb_MapIterator_Value(map, iter), val_f);
+      jsonenc_mapkey(e, key, key_f);
+      jsonenc_scalar(e, val, val_f);
     }
   }
 
@@ -11070,15 +4302,8945 @@
   e.status = status;
   e.arena = NULL;
 
-  if (setjmp(e.err)) return -1;
+  if (UPB_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. */
+
+// Must be last.
+
+const char* upb_BufToUint64(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) {
+      return NULL;  // integer overflow
+    }
+    u64 *= 10;
+    u64 += ch;
+    ptr++;
+  }
+
+  *val = u64;
+  return ptr;
+}
+
+const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val,
+                           bool* is_neg) {
+  bool neg = false;
+  uint64_t u64;
+
+  if (ptr != end && *ptr == '-') {
+    ptr++;
+    neg = true;
+  }
+
+  ptr = upb_BufToUint64(ptr, end, &u64);
+  if (!ptr || u64 > (uint64_t)INT64_MAX + neg) {
+    return NULL;  // integer overflow
+  }
+
+  *val = neg ? -u64 : u64;
+  if (is_neg) *is_neg = neg;
+  return ptr;
+}
+
+
+#include <float.h>
+#include <stdlib.h>
+
+// Must be last.
+
+/* Miscellaneous utilities ****************************************************/
+
+static void upb_FixLocale(char* p) {
+  /* printf() is dependent on locales; sadly there is no easy and portable way
+   * to avoid this. This little post-processing step will translate 1,2 -> 1.2
+   * since JSON needs the latter. Arguably a hack, but it is simple and the
+   * alternatives are far more complicated, platform-dependent, and/or larger
+   * in code size. */
+  for (; *p; p++) {
+    if (*p == ',') *p = '.';
+  }
+}
+
+void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size) {
+  assert(size >= kUpb_RoundTripBufferSize);
+  snprintf(buf, size, "%.*g", DBL_DIG, val);
+  if (strtod(buf, NULL) != val) {
+    snprintf(buf, size, "%.*g", DBL_DIG + 2, val);
+    assert(strtod(buf, NULL) == val);
+  }
+  upb_FixLocale(buf);
+}
+
+void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size) {
+  assert(size >= kUpb_RoundTripBufferSize);
+  snprintf(buf, size, "%.*g", FLT_DIG, val);
+  if (strtof(buf, NULL) != val) {
+    snprintf(buf, size, "%.*g", FLT_DIG + 3, val);
+    assert(strtof(buf, NULL) == val);
+  }
+  upb_FixLocale(buf);
+}
+
+
+#include <stdlib.h>
+#include <string.h>
+
+// Must be last.
+
+// Determine the locale-specific radix character by calling sprintf() to print
+// the number 1.5, then stripping off the digits.  As far as I can tell, this
+// is the only portable, thread-safe way to get the C library to divulge the
+// locale's radix character.  No, localeconv() is NOT thread-safe.
+
+static int GetLocaleRadix(char *data, size_t capacity) {
+  char temp[16];
+  const int size = snprintf(temp, sizeof(temp), "%.1f", 1.5);
+  UPB_ASSERT(temp[0] == '1');
+  UPB_ASSERT(temp[size - 1] == '5');
+  UPB_ASSERT(size < capacity);
+  temp[size - 1] = '\0';
+  strcpy(data, temp + 1);
+  return size - 2;
+}
+
+// Populates a string identical to *input except that the character pointed to
+// by pos (which should be '.') is replaced with the locale-specific radix.
+
+static void LocalizeRadix(const char *input, const char *pos, char *output) {
+  const int len1 = pos - input;
+
+  char radix[8];
+  const int len2 = GetLocaleRadix(radix, sizeof(radix));
+
+  memcpy(output, input, len1);
+  memcpy(output + len1, radix, len2);
+  strcpy(output + len1 + len2, input + len1 + 1);
+}
+
+double _upb_NoLocaleStrtod(const char *str, char **endptr) {
+  // We cannot simply set the locale to "C" temporarily with setlocale()
+  // as this is not thread-safe.  Instead, we try to parse in the current
+  // locale first.  If parsing stops at a '.' character, then this is a
+  // pretty good hint that we're actually in some other locale in which
+  // '.' is not the radix character.
+
+  char *temp_endptr;
+  double result = strtod(str, &temp_endptr);
+  if (endptr != NULL) *endptr = temp_endptr;
+  if (*temp_endptr != '.') return result;
+
+  // Parsing halted on a '.'.  Perhaps we're in a different locale?  Let's
+  // try to replace the '.' with a locale-specific radix character and
+  // try again.
+
+  char localized[80];
+  LocalizeRadix(str, temp_endptr, localized);
+  char *localized_endptr;
+  result = strtod(localized, &localized_endptr);
+  if ((localized_endptr - &localized[0]) > (temp_endptr - str)) {
+    // This attempt got further, so replacing the decimal must have helped.
+    // Update endptr to point at the right location.
+    if (endptr != NULL) {
+      // size_diff is non-zero if the localized radix has multiple bytes.
+      int size_diff = strlen(localized) - strlen(str);
+      *endptr = (char *)str + (localized_endptr - &localized[0] - size_diff);
+    }
+  }
+
+  return result;
+}
+
+
+// Must be last.
+
+int upb_Unicode_ToUTF8(uint32_t cp, char* out) {
+  if (cp <= 0x7f) {
+    out[0] = cp;
+    return 1;
+  }
+  if (cp <= 0x07ff) {
+    out[0] = (cp >> 6) | 0xc0;
+    out[1] = (cp & 0x3f) | 0x80;
+    return 2;
+  }
+  if (cp <= 0xffff) {
+    out[0] = (cp >> 12) | 0xe0;
+    out[1] = ((cp >> 6) & 0x3f) | 0x80;
+    out[2] = (cp & 0x3f) | 0x80;
+    return 3;
+  }
+  if (cp <= 0x10ffff) {
+    out[0] = (cp >> 18) | 0xf0;
+    out[1] = ((cp >> 12) & 0x3f) | 0x80;
+    out[2] = ((cp >> 6) & 0x3f) | 0x80;
+    out[3] = (cp & 0x3f) | 0x80;
+    return 4;
+  }
+  return 0;
+}
+
+
+#include <stdlib.h>
+
+// Must be last.
+
+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};
+
+
+// Must be last.
+
+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;
+}
+
+struct _upb_MemBlock {
+  struct _upb_MemBlock* next;
+  uint32_t size;
+  uint32_t cleanups;
+  // Data follows.
+};
+
+typedef struct cleanup_ent {
+  upb_CleanupFunc* cleanup;
+  void* ud;
+} cleanup_ent;
+
+static const size_t memblock_reserve =
+    UPB_ALIGN_UP(sizeof(_upb_MemBlock), UPB_MALLOC_ALIGN);
+
+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;
+}
+
+size_t upb_Arena_SpaceAllocated(upb_Arena* arena) {
+  arena = arena_findroot(arena);
+  size_t memsize = 0;
+
+  _upb_MemBlock* block = arena->freelist;
+
+  while (block) {
+    memsize += sizeof(_upb_MemBlock) + block->size;
+    block = block->next;
+  }
+
+  return memsize;
+}
+
+uint32_t upb_Arena_DebugRefCount(upb_Arena* arena) {
+  return arena_findroot(arena)->refcount;
+}
+
+static void upb_Arena_addblock(upb_Arena* a, upb_Arena* root, void* ptr,
+                               size_t size) {
+  _upb_MemBlock* 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;
+  _upb_MemBlock* 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);
+}
+
+/* Public Arena API ***********************************************************/
+
+static 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->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;
+
+  if (n) {
+    /* Align initial pointer up so that we return properly-aligned pointers. */
+    void* aligned = (void*)UPB_ALIGN_UP((uintptr_t)mem, UPB_MALLOC_ALIGN);
+    size_t delta = (uintptr_t)aligned - (uintptr_t)mem;
+    n = delta <= n ? n - delta : 0;
+    mem = aligned;
+  }
+
+  /* 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->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->freelist_tail = NULL;
+  a->cleanup_metadata = upb_cleanup_metadata(NULL, true);
+
+  return a;
+}
+
+static void arena_dofree(upb_Arena* a) {
+  _upb_MemBlock* block = a->freelist;
+  UPB_ASSERT(a->parent == a);
+  UPB_ASSERT(a->refcount == 0);
+
+  while (block) {
+    /* Load first since we are deleting block. */
+    _upb_MemBlock* 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_CleanupFunc* 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;
+}
+
+
+
+// Must be last.
+
+static size_t _upb_MiniTableField_Size(const upb_MiniTableField* f) {
+  static unsigned char sizes[] = {
+      0,                      /* 0 */
+      8,                      /* kUpb_FieldType_Double */
+      4,                      /* kUpb_FieldType_Float */
+      8,                      /* kUpb_FieldType_Int64 */
+      8,                      /* kUpb_FieldType_UInt64 */
+      4,                      /* kUpb_FieldType_Int32 */
+      8,                      /* kUpb_FieldType_Fixed64 */
+      4,                      /* kUpb_FieldType_Fixed32 */
+      1,                      /* kUpb_FieldType_Bool */
+      sizeof(upb_StringView), /* kUpb_FieldType_String */
+      sizeof(void*),          /* kUpb_FieldType_Group */
+      sizeof(void*),          /* kUpb_FieldType_Message */
+      sizeof(upb_StringView), /* kUpb_FieldType_Bytes */
+      4,                      /* kUpb_FieldType_UInt32 */
+      4,                      /* kUpb_FieldType_Enum */
+      4,                      /* kUpb_FieldType_SFixed32 */
+      8,                      /* kUpb_FieldType_SFixed64 */
+      4,                      /* kUpb_FieldType_SInt32 */
+      8,                      /* kUpb_FieldType_SInt64 */
+  };
+  return upb_IsRepeatedOrMap(f) ? sizeof(void*) : sizes[f->descriptortype];
+}
+
+// Maps descriptor type to elem_size_lg2.
+static int _upb_MiniTableField_CTypeLg2Size(const upb_MiniTableField* f) {
+  static const uint8_t sizes[] = {
+      -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 */
+  };
+  return sizes[f->descriptortype];
+}
+
+void* upb_MiniTable_ResizeArray(upb_Message* msg,
+                                const upb_MiniTableField* field, size_t len,
+                                upb_Arena* arena) {
+  return _upb_Array_Resize_accessor2(
+      msg, field->offset, len, _upb_MiniTableField_CTypeLg2Size(field), arena);
+}
+
+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(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) return NULL;
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char* decode_tag(const char* ptr, uint32_t* val) {
+  uint64_t byte = (uint8_t)*ptr;
+  if (UPB_LIKELY((byte & 0x80) == 0)) {
+    *val = (uint32_t)byte;
+    return ptr + 1;
+  } else {
+    const char* start = ptr;
+    decode_vret res = decode_longvarint64(ptr, byte);
+    if (!res.ptr || res.ptr - start > 5 || res.val > UINT32_MAX) {
+      return NULL;  // Malformed.
+    }
+    *val = (uint32_t)res.val;
+    return res.ptr;
+  }
+}
+
+// Parses unknown data by merging into existing base_message or creating a
+// new message usingg mini_table.
+static upb_UnknownToMessageRet upb_MiniTable_ParseUnknownMessage(
+    const char* unknown_data, size_t unknown_size,
+    const upb_MiniTable* mini_table, upb_Message* base_message,
+    int decode_options, upb_Arena* arena) {
+  upb_UnknownToMessageRet ret;
+  ret.message =
+      base_message ? base_message : _upb_Message_New(mini_table, arena);
+  if (!ret.message) {
+    ret.status = kUpb_UnknownToMessage_OutOfMemory;
+    return ret;
+  }
+  // Decode sub message using unknown field contents.
+  const char* data = unknown_data;
+  uint32_t tag;
+  uint64_t message_len = 0;
+  data = decode_tag(data, &tag);
+  data = decode_varint64(data, &message_len);
+  upb_DecodeStatus status = upb_Decode(data, message_len, ret.message,
+                                       mini_table, NULL, decode_options, arena);
+  if (status == kUpb_DecodeStatus_OutOfMemory) {
+    ret.status = kUpb_UnknownToMessage_OutOfMemory;
+  } else if (status == kUpb_DecodeStatus_Ok) {
+    ret.status = kUpb_UnknownToMessage_Ok;
+  } else {
+    ret.status = kUpb_UnknownToMessage_ParseError;
+  }
+  return ret;
+}
+
+upb_GetExtension_Status upb_MiniTable_GetOrPromoteExtension(
+    upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int decode_options, upb_Arena* arena,
+    const upb_Message_Extension** extension) {
+  UPB_ASSERT(ext_table->field.descriptortype == kUpb_FieldType_Message);
+  *extension = _upb_Message_Getext(msg, ext_table);
+  if (*extension) {
+    return kUpb_GetExtension_Ok;
+  }
+
+  // Check unknown fields, if available promote.
+  int field_number = ext_table->field.number;
+  upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number);
+  if (result.status != kUpb_FindUnknown_Ok) {
+    return kUpb_GetExtension_NotPresent;
+  }
+  size_t len;
+  size_t ofs = result.ptr - upb_Message_GetUnknown(msg, &len);
+  // Decode and promote from unknown.
+  const upb_MiniTable* extension_table = ext_table->sub.submsg;
+  upb_UnknownToMessageRet parse_result = upb_MiniTable_ParseUnknownMessage(
+      result.ptr, result.len, extension_table,
+      /* base_message= */ NULL, decode_options, arena);
+  switch (parse_result.status) {
+    case kUpb_UnknownToMessage_OutOfMemory:
+      return kUpb_GetExtension_OutOfMemory;
+    case kUpb_UnknownToMessage_ParseError:
+      return kUpb_GetExtension_ParseError;
+    case kUpb_UnknownToMessage_NotFound:
+      return kUpb_GetExtension_NotPresent;
+    case kUpb_UnknownToMessage_Ok:
+      break;
+  }
+  upb_Message* extension_msg = parse_result.message;
+  // Add to extensions.
+  upb_Message_Extension* ext =
+      _upb_Message_GetOrCreateExtension(msg, ext_table, arena);
+  if (!ext) {
+    return kUpb_GetExtension_OutOfMemory;
+  }
+  memcpy(&ext->data, &extension_msg, sizeof(extension_msg));
+  *extension = ext;
+  const char* delete_ptr = upb_Message_GetUnknown(msg, &len) + ofs;
+  upb_Message_DeleteUnknown(msg, delete_ptr, result.len);
+  return kUpb_GetExtension_Ok;
+}
+
+upb_GetExtensionAsBytes_Status upb_MiniTable_GetExtensionAsBytes(
+    const upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int encode_options, upb_Arena* arena, const char** extension_data,
+    size_t* len) {
+  const upb_Message_Extension* msg_ext = _upb_Message_Getext(msg, ext_table);
+  UPB_ASSERT(ext_table->field.descriptortype == kUpb_FieldType_Message);
+  if (msg_ext) {
+    upb_EncodeStatus status =
+        upb_Encode(msg_ext->data.ptr, msg_ext->ext->sub.submsg, encode_options,
+                   arena, (char**)extension_data, len);
+    if (status != kUpb_EncodeStatus_Ok) {
+      return kUpb_GetExtensionAsBytes_EncodeError;
+    }
+    return kUpb_GetExtensionAsBytes_Ok;
+  }
+  int field_number = ext_table->field.number;
+  upb_FindUnknownRet result = upb_MiniTable_FindUnknown(msg, field_number);
+  if (result.status != kUpb_FindUnknown_Ok) {
+    return kUpb_GetExtensionAsBytes_NotPresent;
+  }
+  const char* data = result.ptr;
+  uint32_t tag;
+  uint64_t message_len = 0;
+  data = decode_tag(data, &tag);
+  data = decode_varint64(data, &message_len);
+  *extension_data = data;
+  *len = message_len;
+  return kUpb_GetExtensionAsBytes_Ok;
+}
+
+static const char* UnknownFieldSet_SkipGroup(const char* ptr, const char* end,
+                                             int group_number);
+
+static const char* UnknownFieldSet_SkipField(const char* ptr, const char* end,
+                                             uint32_t tag) {
+  int field_number = tag >> 3;
+  int wire_type = tag & 7;
+  switch (wire_type) {
+    case kUpb_WireType_Varint: {
+      uint64_t val;
+      return decode_varint64(ptr, &val);
+    }
+    case kUpb_WireType_64Bit:
+      if (end - ptr < 8) return NULL;
+      return ptr + 8;
+    case kUpb_WireType_32Bit:
+      if (end - ptr < 4) return NULL;
+      return ptr + 4;
+    case kUpb_WireType_Delimited: {
+      uint64_t size;
+      ptr = decode_varint64(ptr, &size);
+      if (!ptr || end - ptr < size) return NULL;
+      return ptr + size;
+    }
+    case kUpb_WireType_StartGroup:
+      return UnknownFieldSet_SkipGroup(ptr, end, field_number);
+    case kUpb_WireType_EndGroup:
+      return NULL;
+    default:
+      assert(0);
+      return NULL;
+  }
+}
+
+static const char* UnknownFieldSet_SkipGroup(const char* ptr, const char* end,
+                                             int group_number) {
+  uint32_t end_tag = (group_number << 3) | kUpb_WireType_EndGroup;
+  while (true) {
+    if (ptr == end) return NULL;
+    uint64_t tag;
+    ptr = decode_varint64(ptr, &tag);
+    if (!ptr) return NULL;
+    if (tag == end_tag) return ptr;
+    ptr = UnknownFieldSet_SkipField(ptr, end, (uint32_t)tag);
+    if (!ptr) return NULL;
+  }
+  return ptr;
+}
+
+enum {
+  kUpb_MessageSet_StartItemTag = (1 << 3) | kUpb_WireType_StartGroup,
+  kUpb_MessageSet_EndItemTag = (1 << 3) | kUpb_WireType_EndGroup,
+  kUpb_MessageSet_TypeIdTag = (2 << 3) | kUpb_WireType_Varint,
+  kUpb_MessageSet_MessageTag = (3 << 3) | kUpb_WireType_Delimited,
+};
+
+upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg,
+                                             uint32_t field_number) {
+  size_t size;
+  upb_FindUnknownRet ret;
+
+  const char* ptr = upb_Message_GetUnknown(msg, &size);
+  if (size == 0) {
+    ret.status = kUpb_FindUnknown_NotPresent;
+    ret.ptr = NULL;
+    ret.len = 0;
+    return ret;
+  }
+  const char* end = ptr + size;
+  uint64_t uint64_val;
+
+  while (ptr < end) {
+    uint32_t tag = 0;
+    int field;
+    int wire_type;
+    const char* unknown_begin = ptr;
+    ptr = decode_tag(ptr, &tag);
+    field = tag >> 3;
+    wire_type = tag & 7;
+    switch (wire_type) {
+      case kUpb_WireType_EndGroup:
+        ret.status = kUpb_FindUnknown_ParseError;
+        return ret;
+      case kUpb_WireType_Varint:
+        ptr = decode_varint64(ptr, &uint64_val);
+        if (!ptr) {
+          ret.status = kUpb_FindUnknown_ParseError;
+          return ret;
+        }
+        break;
+      case kUpb_WireType_32Bit:
+        ptr += 4;
+        break;
+      case kUpb_WireType_64Bit:
+        ptr += 8;
+        break;
+      case kUpb_WireType_Delimited:
+        // Read size.
+        ptr = decode_varint64(ptr, &uint64_val);
+        if (uint64_val >= INT32_MAX || !ptr) {
+          ret.status = kUpb_FindUnknown_ParseError;
+          return ret;
+        }
+        ptr += uint64_val;
+        break;
+      case kUpb_WireType_StartGroup:
+        // tag >> 3 specifies the group number, recurse and skip
+        // until we see group end tag.
+        ptr = UnknownFieldSet_SkipGroup(ptr, end, field_number);
+        break;
+      default:
+        ret.status = kUpb_FindUnknown_ParseError;
+        return ret;
+    }
+    if (field_number == field) {
+      ret.status = kUpb_FindUnknown_Ok;
+      ret.ptr = unknown_begin;
+      ret.len = ptr - unknown_begin;
+      return ret;
+    }
+  }
+  ret.status = kUpb_FindUnknown_NotPresent;
+  ret.ptr = NULL;
+  ret.len = 0;
+  return ret;
+}
+
+upb_UnknownToMessageRet upb_MiniTable_PromoteUnknownToMessage(
+    upb_Message* msg, const upb_MiniTable* mini_table,
+    const upb_MiniTableField* field, const upb_MiniTable* sub_mini_table,
+    int decode_options, upb_Arena* arena) {
+  upb_FindUnknownRet unknown;
+  // We need to loop and merge unknowns that have matching tag field->number.
+  upb_Message* message = NULL;
+  // Callers should check that message is not set first before calling
+  // PromotoUnknownToMessage.
+  UPB_ASSERT(upb_MiniTable_GetMessage(msg, field, NULL) == NULL);
+  upb_UnknownToMessageRet ret;
+  ret.status = kUpb_UnknownToMessage_Ok;
+  do {
+    unknown = upb_MiniTable_FindUnknown(msg, field->number);
+    switch (unknown.status) {
+      case kUpb_FindUnknown_Ok: {
+        const char* unknown_data = unknown.ptr;
+        size_t unknown_size = unknown.len;
+        ret = upb_MiniTable_ParseUnknownMessage(unknown_data, unknown_size,
+                                                sub_mini_table, message,
+                                                decode_options, arena);
+        if (ret.status == kUpb_UnknownToMessage_Ok) {
+          message = ret.message;
+          upb_Message_DeleteUnknown(msg, unknown_data, unknown_size);
+        }
+      } break;
+      case kUpb_FindUnknown_ParseError:
+        ret.status = kUpb_UnknownToMessage_ParseError;
+        break;
+      case kUpb_FindUnknown_NotPresent:
+        // If we parsed at least one unknown, we are done.
+        ret.status =
+            message ? kUpb_UnknownToMessage_Ok : kUpb_UnknownToMessage_NotFound;
+        break;
+    }
+  } while (unknown.status == kUpb_FindUnknown_Ok);
+  if (message) {
+    upb_MiniTable_SetMessage(msg, mini_table, field, message);
+    ret.message = message;
+  }
+  return ret;
+}
+
+// Moves repeated messages in unknowns to a upb_Array.
+//
+// Since the repeated field is not a scalar type we don't check for
+// kUpb_LabelFlags_IsPacked.
+// TODO(b/251007554): Optimize. Instead of converting messages one at a time,
+// scan all unknown data once and compact.
+upb_UnknownToMessage_Status upb_MiniTable_PromoteUnknownToMessageArray(
+    upb_Message* msg, const upb_MiniTableField* field,
+    const upb_MiniTable* mini_table, int decode_options, upb_Arena* arena) {
+  upb_Array* repeated_messages = upb_MiniTable_GetMutableArray(msg, field);
+  // Find all unknowns with given field number and parse.
+  upb_FindUnknownRet unknown;
+  do {
+    unknown = upb_MiniTable_FindUnknown(msg, field->number);
+    if (unknown.status == kUpb_FindUnknown_Ok) {
+      upb_UnknownToMessageRet ret = upb_MiniTable_ParseUnknownMessage(
+          unknown.ptr, unknown.len, mini_table,
+          /* base_message= */ NULL, decode_options, arena);
+      if (ret.status == kUpb_UnknownToMessage_Ok) {
+        upb_MessageValue value;
+        value.msg_val = ret.message;
+        if (!upb_Array_Append(repeated_messages, value, arena)) {
+          return kUpb_UnknownToMessage_OutOfMemory;
+        }
+        upb_Message_DeleteUnknown(msg, unknown.ptr, unknown.len);
+      } else {
+        return ret.status;
+      }
+    }
+  } while (unknown.status == kUpb_FindUnknown_Ok);
+  return kUpb_UnknownToMessage_Ok;
+}
+
+
+#include <math.h>
+
+
+// Must be last.
+
+const float kUpb_FltInfinity = INFINITY;
+const double kUpb_Infinity = INFINITY;
+const double kUpb_NaN = NAN;
+
+static const size_t overhead = sizeof(upb_Message_InternalData);
+
+upb_Message* upb_Message_New(const upb_MiniTable* mini_table,
+                             upb_Arena* arena) {
+  return _upb_Message_New(mini_table, arena);
+}
+
+void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l) {
+  // Note: Can't use UPB_PTR_AT() here because we are doing pointer subtraction.
+  char* mem = (char*)msg - sizeof(upb_Message_Internal);
+  memset(mem, 0, upb_msg_sizeof(l));
+}
+
+static bool realloc_internal(upb_Message* msg, size_t need, upb_Arena* arena) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (!in->internal) {
+    /* No internal data, allocate from scratch. */
+    size_t size = UPB_MAX(128, upb_Log2CeilingSize(need + overhead));
+    upb_Message_InternalData* internal = upb_Arena_Malloc(arena, size);
+    if (!internal) return false;
+    internal->size = size;
+    internal->unknown_end = overhead;
+    internal->ext_begin = size;
+    in->internal = internal;
+  } else if (in->internal->ext_begin - in->internal->unknown_end < need) {
+    /* Internal data is too small, reallocate. */
+    size_t new_size = upb_Log2CeilingSize(in->internal->size + need);
+    size_t ext_bytes = in->internal->size - in->internal->ext_begin;
+    size_t new_ext_begin = new_size - ext_bytes;
+    upb_Message_InternalData* internal =
+        upb_Arena_Realloc(arena, in->internal, in->internal->size, new_size);
+    if (!internal) return false;
+    if (ext_bytes) {
+      /* Need to move extension data to the end. */
+      char* ptr = (char*)internal;
+      memmove(ptr + new_ext_begin, ptr + internal->ext_begin, ext_bytes);
+    }
+    internal->ext_begin = new_ext_begin;
+    internal->size = new_size;
+    in->internal = internal;
+  }
+  UPB_ASSERT(in->internal->ext_begin - in->internal->unknown_end >= need);
+  return true;
+}
+
+bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
+                             upb_Arena* arena) {
+  if (!realloc_internal(msg, len, arena)) return false;
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  memcpy(UPB_PTR_AT(in->internal, in->internal->unknown_end, char), data, len);
+  in->internal->unknown_end += len;
+  return true;
+}
+
+void _upb_Message_DiscardUnknown_shallow(upb_Message* msg) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (in->internal) {
+    in->internal->unknown_end = overhead;
+  }
+}
+
+const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len) {
+  const upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (in->internal) {
+    *len = in->internal->unknown_end - overhead;
+    return (char*)(in->internal + 1);
+  } else {
+    *len = 0;
+    return NULL;
+  }
+}
+
+void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  const char* internal_unknown_end =
+      UPB_PTR_AT(in->internal, in->internal->unknown_end, char);
+#ifndef NDEBUG
+  size_t full_unknown_size;
+  const char* full_unknown = upb_Message_GetUnknown(msg, &full_unknown_size);
+  UPB_ASSERT((uintptr_t)data >= (uintptr_t)full_unknown);
+  UPB_ASSERT((uintptr_t)data < (uintptr_t)(full_unknown + full_unknown_size));
+  UPB_ASSERT((uintptr_t)(data + len) > (uintptr_t)data);
+  UPB_ASSERT((uintptr_t)(data + len) <= (uintptr_t)internal_unknown_end);
+#endif
+  if ((data + len) != internal_unknown_end) {
+    memmove((char*)data, data + len, internal_unknown_end - data - len);
+  }
+  in->internal->unknown_end -= len;
+}
+
+const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
+                                                  size_t* count) {
+  const upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (in->internal) {
+    *count = (in->internal->size - in->internal->ext_begin) /
+             sizeof(upb_Message_Extension);
+    return UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
+  } else {
+    *count = 0;
+    return NULL;
+  }
+}
+
+const upb_Message_Extension* _upb_Message_Getext(
+    const upb_Message* msg, const upb_MiniTableExtension* e) {
+  size_t n;
+  const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &n);
+
+  /* For now we use linear search exclusively to find extensions. If this
+   * becomes an issue due to messages with lots of extensions, we can introduce
+   * a table of some sort. */
+  for (size_t i = 0; i < n; i++) {
+    if (ext[i].ext == e) {
+      return &ext[i];
+    }
+  }
+
+  return NULL;
+}
+
+void _upb_Message_Clearext(upb_Message* msg,
+                           const upb_MiniTableExtension* ext_l) {
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  if (!in->internal) return;
+  const upb_Message_Extension* base =
+      UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
+  upb_Message_Extension* ext =
+      (upb_Message_Extension*)_upb_Message_Getext(msg, ext_l);
+  if (ext) {
+    *ext = *base;
+    in->internal->ext_begin += sizeof(upb_Message_Extension);
+  }
+}
+
+upb_Message_Extension* _upb_Message_GetOrCreateExtension(
+    upb_Message* msg, const upb_MiniTableExtension* e, upb_Arena* arena) {
+  upb_Message_Extension* ext =
+      (upb_Message_Extension*)_upb_Message_Getext(msg, e);
+  if (ext) return ext;
+  if (!realloc_internal(msg, sizeof(upb_Message_Extension), arena)) return NULL;
+  upb_Message_Internal* in = upb_Message_Getinternal(msg);
+  in->internal->ext_begin -= sizeof(upb_Message_Extension);
+  ext = UPB_PTR_AT(in->internal, in->internal->ext_begin, void);
+  memset(ext, 0, sizeof(upb_Message_Extension));
+  ext->ext = e;
+  return ext;
+}
+
+size_t upb_Message_ExtensionCount(const upb_Message* msg) {
+  size_t count;
+  _upb_Message_Getexts(msg, &count);
+  return count;
+}
+
+
+#include <inttypes.h>
+
+
+// Must be last.
+
+const char _kUpb_ToBase92[] = {
+    ' ', '!', '#', '$', '%', '&', '(', ')', '*', '+', ',', '-', '.', '/',
+    '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', ':', ';', '<', '=',
+    '>', '?', '@', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K',
+    'L', 'M', 'N', 'O', 'P', 'Q', 'R', 'S', 'T', 'U', 'V', 'W', 'X', 'Y',
+    'Z', '[', ']', '^', '_', '`', 'a', 'b', 'c', 'd', 'e', 'f', 'g', 'h',
+    'i', 'j', 'k', 'l', 'm', 'n', 'o', 'p', 'q', 'r', 's', 't', 'u', 'v',
+    'w', 'x', 'y', 'z', '{', '|', '}', '~',
+};
+
+const int8_t _kUpb_FromBase92[] = {
+    0,  1,  -1, 2,  3,  4,  5,  -1, 6,  7,  8,  9,  10, 11, 12, 13, 14, 15, 16,
+    17, 18, 19, 20, 21, 22, 23, 24, 25, 26, 27, 28, 29, 30, 31, 32, 33, 34, 35,
+    36, 37, 38, 39, 40, 41, 42, 43, 44, 45, 46, 47, 48, 49, 50, 51, 52, 53, 54,
+    55, 56, 57, -1, 58, 59, 60, 61, 62, 63, 64, 65, 66, 67, 68, 69, 70, 71, 72,
+    73, 74, 75, 76, 77, 78, 79, 80, 81, 82, 83, 84, 85, 86, 87, 88, 89, 90, 91,
+};
+
+const upb_MiniTableField* upb_MiniTable_FindFieldByNumber(
+    const upb_MiniTable* table, uint32_t number) {
+  int n = table->field_count;
+  for (int i = 0; i < n; i++) {
+    if (table->fields[i].number == number) {
+      return &table->fields[i];
+    }
+  }
+  return NULL;
+}
+
+upb_FieldType upb_MiniTableField_Type(const upb_MiniTableField* field) {
+  if (field->mode & kUpb_LabelFlags_IsAlternate) {
+    if (field->descriptortype == kUpb_FieldType_Int32) {
+      return kUpb_FieldType_Enum;
+    } else if (field->descriptortype == kUpb_FieldType_Bytes) {
+      return kUpb_FieldType_String;
+    } else {
+      UPB_ASSERT(false);
+    }
+  }
+  return field->descriptortype;
+}
+
+
+#include <inttypes.h>
+#include <stdlib.h>
+
+
+// Must be last.
+
+// Note: we sort by this number when calculating layout order.
+typedef enum {
+  kUpb_LayoutItemType_OneofCase,   // Oneof case.
+  kUpb_LayoutItemType_OneofField,  // Oneof field data.
+  kUpb_LayoutItemType_Field,       // Non-oneof field data.
+
+  kUpb_LayoutItemType_Max = kUpb_LayoutItemType_Field,
+} upb_LayoutItemType;
+
+#define kUpb_LayoutItem_IndexSentinel ((uint16_t)-1)
+
+typedef struct {
+  // Index of the corresponding field.  When this is a oneof field, the field's
+  // offset will be the index of the next field in a linked list.
+  uint16_t field_index;
+  uint16_t offset;
+  upb_FieldRep rep;
+  upb_LayoutItemType type;
+} upb_LayoutItem;
+
+typedef struct {
+  upb_LayoutItem* data;
+  size_t size;
+  size_t capacity;
+} upb_LayoutItemVector;
+
+typedef struct {
+  const char* end;
+  upb_MiniTable* table;
+  upb_MiniTableField* fields;
+  upb_MiniTablePlatform platform;
+  upb_LayoutItemVector vec;
+  upb_Arena* arena;
+  upb_Status* status;
+
+  // When building enums.
+  upb_MiniTableEnum* enum_table;
+  uint32_t enum_value_count;
+  uint32_t enum_data_count;
+  uint32_t enum_data_capacity;
+
+  jmp_buf err;
+} upb_MtDecoder;
+
+UPB_PRINTF(2, 3)
+UPB_NORETURN static void upb_MtDecoder_ErrorFormat(upb_MtDecoder* d,
+                                                   const char* fmt, ...) {
+  if (d->status) {
+    va_list argp;
+    upb_Status_SetErrorMessage(d->status, "Error building mini table: ");
+    va_start(argp, fmt);
+    upb_Status_VAppendErrorFormat(d->status, fmt, argp);
+    va_end(argp);
+  }
+  UPB_LONGJMP(d->err, 1);
+}
+
+static void upb_MtDecoder_CheckOutOfMemory(upb_MtDecoder* d, const void* ptr) {
+  if (!ptr) upb_MtDecoder_ErrorFormat(d, "Out of memory");
+}
+
+// In each field's offset, we temporarily store a presence classifier:
+enum PresenceClass {
+  kNoPresence = 0,
+  kHasbitPresence = 1,
+  kRequiredPresence = 2,
+  kOneofBase = 3,
+  // Negative values refer to a specific oneof with that number.  Positive
+  // values >= kOneofBase indicate that this field is in a oneof, and specify
+  // the next field in this oneof's linked list.
+};
+
+static const char* upb_MiniTable_DecodeBase92Varint(upb_MtDecoder* d,
+                                                    const char* ptr,
+                                                    char first_ch, uint8_t min,
+                                                    uint8_t max,
+                                                    uint32_t* out_val) {
+  uint32_t val = 0;
+  uint32_t shift = 0;
+  const int bits_per_char =
+      upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min));
+  char ch = first_ch;
+  while (1) {
+    uint32_t bits = _upb_FromBase92(ch) - _upb_FromBase92(min);
+    val |= bits << shift;
+    if (ptr == d->end || *ptr < min || max < *ptr) {
+      *out_val = val;
+      return ptr;
+    }
+    ch = *ptr++;
+    shift += bits_per_char;
+    if (shift >= 32) upb_MtDecoder_ErrorFormat(d, "Overlong varint");
+  }
+}
+
+static bool upb_MiniTable_HasSub(upb_MiniTableField* field,
+                                 uint64_t msg_modifiers) {
+  switch (field->descriptortype) {
+    case kUpb_FieldType_Message:
+    case kUpb_FieldType_Group:
+    case kUpb_FieldType_Enum:
+      return true;
+    case kUpb_FieldType_String:
+      if (!(msg_modifiers & kUpb_MessageModifier_ValidateUtf8)) {
+        field->descriptortype = kUpb_FieldType_Bytes;
+        field->mode |= kUpb_LabelFlags_IsAlternate;
+      }
+      return false;
+    default:
+      return false;
+  }
+}
+
+static bool upb_MtDecoder_FieldIsPackable(upb_MiniTableField* field) {
+  return (field->mode & kUpb_FieldMode_Array) &&
+         _upb_FieldType_IsPackable(field->descriptortype);
+}
+
+static void upb_MiniTable_SetTypeAndSub(upb_MiniTableField* field,
+                                        upb_FieldType type, uint32_t* sub_count,
+                                        uint64_t msg_modifiers,
+                                        bool is_proto3_enum) {
+  field->descriptortype = type;
+
+  if (is_proto3_enum) {
+    UPB_ASSERT(field->descriptortype == kUpb_FieldType_Enum);
+    field->descriptortype = kUpb_FieldType_Int32;
+    field->mode |= kUpb_LabelFlags_IsAlternate;
+  }
+
+  if (upb_MiniTable_HasSub(field, msg_modifiers)) {
+    field->submsg_index = sub_count ? (*sub_count)++ : 0;
+  } else {
+    field->submsg_index = kUpb_NoSub;
+  }
+
+  if (upb_MtDecoder_FieldIsPackable(field) &&
+      (msg_modifiers & kUpb_MessageModifier_DefaultIsPacked)) {
+    field->mode |= kUpb_LabelFlags_IsPacked;
+  }
+}
+
+static const char kUpb_EncodedToType[] = {
+    [kUpb_EncodedType_Double] = kUpb_FieldType_Double,
+    [kUpb_EncodedType_Float] = kUpb_FieldType_Float,
+    [kUpb_EncodedType_Int64] = kUpb_FieldType_Int64,
+    [kUpb_EncodedType_UInt64] = kUpb_FieldType_UInt64,
+    [kUpb_EncodedType_Int32] = kUpb_FieldType_Int32,
+    [kUpb_EncodedType_Fixed64] = kUpb_FieldType_Fixed64,
+    [kUpb_EncodedType_Fixed32] = kUpb_FieldType_Fixed32,
+    [kUpb_EncodedType_Bool] = kUpb_FieldType_Bool,
+    [kUpb_EncodedType_String] = kUpb_FieldType_String,
+    [kUpb_EncodedType_Group] = kUpb_FieldType_Group,
+    [kUpb_EncodedType_Message] = kUpb_FieldType_Message,
+    [kUpb_EncodedType_Bytes] = kUpb_FieldType_Bytes,
+    [kUpb_EncodedType_UInt32] = kUpb_FieldType_UInt32,
+    [kUpb_EncodedType_OpenEnum] = kUpb_FieldType_Enum,
+    [kUpb_EncodedType_SFixed32] = kUpb_FieldType_SFixed32,
+    [kUpb_EncodedType_SFixed64] = kUpb_FieldType_SFixed64,
+    [kUpb_EncodedType_SInt32] = kUpb_FieldType_SInt32,
+    [kUpb_EncodedType_SInt64] = kUpb_FieldType_SInt64,
+    [kUpb_EncodedType_ClosedEnum] = kUpb_FieldType_Enum,
+};
+
+static void upb_MiniTable_SetField(upb_MtDecoder* d, uint8_t ch,
+                                   upb_MiniTableField* field,
+                                   uint64_t msg_modifiers,
+                                   uint32_t* sub_count) {
+  static const char kUpb_EncodedToFieldRep[] = {
+      [kUpb_EncodedType_Double] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_Float] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_Int64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_UInt64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_Int32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_Fixed64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_Fixed32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_Bool] = kUpb_FieldRep_1Byte,
+      [kUpb_EncodedType_String] = kUpb_FieldRep_StringView,
+      [kUpb_EncodedType_Bytes] = kUpb_FieldRep_StringView,
+      [kUpb_EncodedType_UInt32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_OpenEnum] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_SFixed32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_SFixed64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_SInt32] = kUpb_FieldRep_4Byte,
+      [kUpb_EncodedType_SInt64] = kUpb_FieldRep_8Byte,
+      [kUpb_EncodedType_ClosedEnum] = kUpb_FieldRep_4Byte,
+  };
+
+  char pointer_rep = d->platform == kUpb_MiniTablePlatform_32Bit
+                         ? kUpb_FieldRep_4Byte
+                         : kUpb_FieldRep_8Byte;
+
+  int8_t type = _upb_FromBase92(ch);
+  if (ch >= _upb_ToBase92(kUpb_EncodedType_RepeatedBase)) {
+    type -= kUpb_EncodedType_RepeatedBase;
+    field->mode = kUpb_FieldMode_Array;
+    field->mode |= pointer_rep << kUpb_FieldRep_Shift;
+    field->offset = kNoPresence;
+  } else {
+    field->mode = kUpb_FieldMode_Scalar;
+    field->offset = kHasbitPresence;
+    if (type == kUpb_EncodedType_Group || type == kUpb_EncodedType_Message) {
+      field->mode |= pointer_rep << kUpb_FieldRep_Shift;
+    } else if (type >= sizeof(kUpb_EncodedToFieldRep)) {
+      upb_MtDecoder_ErrorFormat(d, "Invalid field type: %d", (int)type);
+      UPB_UNREACHABLE();
+    } else {
+      field->mode |= kUpb_EncodedToFieldRep[type] << kUpb_FieldRep_Shift;
+    }
+  }
+  if (type >= sizeof(kUpb_EncodedToType)) {
+    upb_MtDecoder_ErrorFormat(d, "Invalid field type: %d", (int)type);
+    UPB_UNREACHABLE();
+  }
+  upb_MiniTable_SetTypeAndSub(field, kUpb_EncodedToType[type], sub_count,
+                              msg_modifiers, type == kUpb_EncodedType_OpenEnum);
+}
+
+static void upb_MtDecoder_ModifyField(upb_MtDecoder* d,
+                                      uint32_t message_modifiers,
+                                      uint32_t field_modifiers,
+                                      upb_MiniTableField* field) {
+  if (field_modifiers & kUpb_EncodedFieldModifier_FlipPacked) {
+    if (!upb_MtDecoder_FieldIsPackable(field)) {
+      upb_MtDecoder_ErrorFormat(
+          d, "Cannot flip packed on unpackable field %" PRIu32, field->number);
+      UPB_UNREACHABLE();
+    }
+    field->mode ^= kUpb_LabelFlags_IsPacked;
+  }
+
+  bool singular = field_modifiers & kUpb_EncodedFieldModifier_IsProto3Singular;
+  bool required = field_modifiers & kUpb_EncodedFieldModifier_IsRequired;
+
+  // Validate.
+  if ((singular || required) && field->offset != kHasbitPresence) {
+    upb_MtDecoder_ErrorFormat(
+        d, "Invalid modifier(s) for repeated field %" PRIu32, field->number);
+    UPB_UNREACHABLE();
+  }
+  if (singular && required) {
+    upb_MtDecoder_ErrorFormat(
+        d, "Field %" PRIu32 " cannot be both singular and required",
+        field->number);
+    UPB_UNREACHABLE();
+  }
+
+  if (singular) field->offset = kNoPresence;
+  if (required) {
+    field->offset = kRequiredPresence;
+  }
+}
+
+static void upb_MtDecoder_PushItem(upb_MtDecoder* d, upb_LayoutItem item) {
+  if (d->vec.size == d->vec.capacity) {
+    size_t new_cap = UPB_MAX(8, d->vec.size * 2);
+    d->vec.data = realloc(d->vec.data, new_cap * sizeof(*d->vec.data));
+    upb_MtDecoder_CheckOutOfMemory(d, d->vec.data);
+    d->vec.capacity = new_cap;
+  }
+  d->vec.data[d->vec.size++] = item;
+}
+
+static void upb_MtDecoder_PushOneof(upb_MtDecoder* d, upb_LayoutItem item) {
+  if (item.field_index == kUpb_LayoutItem_IndexSentinel) {
+    upb_MtDecoder_ErrorFormat(d, "Empty oneof");
+    UPB_UNREACHABLE();
+  }
+  item.field_index -= kOneofBase;
+
+  // Push oneof data.
+  item.type = kUpb_LayoutItemType_OneofField;
+  upb_MtDecoder_PushItem(d, item);
+
+  // Push oneof case.
+  item.rep = kUpb_FieldRep_4Byte;  // Field Number.
+  item.type = kUpb_LayoutItemType_OneofCase;
+  upb_MtDecoder_PushItem(d, item);
+}
+
+size_t upb_MtDecoder_SizeOfRep(upb_FieldRep rep,
+                               upb_MiniTablePlatform platform) {
+  static const uint8_t kRepToSize32[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 8,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  static const uint8_t kRepToSize64[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 16,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  UPB_ASSERT(sizeof(upb_StringView) ==
+             UPB_SIZE(kRepToSize32, kRepToSize64)[kUpb_FieldRep_StringView]);
+  return platform == kUpb_MiniTablePlatform_32Bit ? kRepToSize32[rep]
+                                                  : kRepToSize64[rep];
+}
+
+size_t upb_MtDecoder_AlignOfRep(upb_FieldRep rep,
+                                upb_MiniTablePlatform platform) {
+  static const uint8_t kRepToAlign32[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 4,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  static const uint8_t kRepToAlign64[] = {
+      [kUpb_FieldRep_1Byte] = 1,
+      [kUpb_FieldRep_4Byte] = 4,
+      [kUpb_FieldRep_StringView] = 8,
+      [kUpb_FieldRep_8Byte] = 8,
+  };
+  UPB_ASSERT(UPB_ALIGN_OF(upb_StringView) ==
+             UPB_SIZE(kRepToAlign32, kRepToAlign64)[kUpb_FieldRep_StringView]);
+  return platform == kUpb_MiniTablePlatform_32Bit ? kRepToAlign32[rep]
+                                                  : kRepToAlign64[rep];
+}
+
+static const char* upb_MtDecoder_DecodeOneofField(upb_MtDecoder* d,
+                                                  const char* ptr,
+                                                  char first_ch,
+                                                  upb_LayoutItem* item) {
+  uint32_t field_num;
+  ptr = upb_MiniTable_DecodeBase92Varint(
+      d, ptr, first_ch, kUpb_EncodedValue_MinOneofField,
+      kUpb_EncodedValue_MaxOneofField, &field_num);
+  upb_MiniTableField* f =
+      (void*)upb_MiniTable_FindFieldByNumber(d->table, field_num);
+
+  if (!f) {
+    upb_MtDecoder_ErrorFormat(d,
+                              "Couldn't add field number %" PRIu32
+                              " to oneof, no such field number.",
+                              field_num);
+    UPB_UNREACHABLE();
+  }
+  if (f->offset != kHasbitPresence) {
+    upb_MtDecoder_ErrorFormat(
+        d,
+        "Cannot add repeated, required, or singular field %" PRIu32
+        " to oneof.",
+        field_num);
+    UPB_UNREACHABLE();
+  }
+
+  // Oneof storage must be large enough to accommodate the largest member.
+  int rep = f->mode >> kUpb_FieldRep_Shift;
+  if (upb_MtDecoder_SizeOfRep(rep, d->platform) >
+      upb_MtDecoder_SizeOfRep(item->rep, d->platform)) {
+    item->rep = rep;
+  }
+  // Prepend this field to the linked list.
+  f->offset = item->field_index;
+  item->field_index = (f - d->fields) + kOneofBase;
+  return ptr;
+}
+
+static const char* upb_MtDecoder_DecodeOneofs(upb_MtDecoder* d,
+                                              const char* ptr) {
+  upb_LayoutItem item = {.rep = 0,
+                         .field_index = kUpb_LayoutItem_IndexSentinel};
+  while (ptr < d->end) {
+    char ch = *ptr++;
+    if (ch == kUpb_EncodedValue_FieldSeparator) {
+      // Field separator, no action needed.
+    } else if (ch == kUpb_EncodedValue_OneofSeparator) {
+      // End of oneof.
+      upb_MtDecoder_PushOneof(d, item);
+      item.field_index = kUpb_LayoutItem_IndexSentinel;  // Move to next oneof.
+    } else {
+      ptr = upb_MtDecoder_DecodeOneofField(d, ptr, ch, &item);
+    }
+  }
+
+  // Push final oneof.
+  upb_MtDecoder_PushOneof(d, item);
+  return ptr;
+}
+
+static const char* upb_MtDecoder_ParseModifier(upb_MtDecoder* d,
+                                               const char* ptr, char first_ch,
+                                               upb_MiniTableField* last_field,
+                                               uint64_t* msg_modifiers) {
+  uint32_t mod;
+  ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, first_ch,
+                                         kUpb_EncodedValue_MinModifier,
+                                         kUpb_EncodedValue_MaxModifier, &mod);
+  if (last_field) {
+    upb_MtDecoder_ModifyField(d, *msg_modifiers, mod, last_field);
+  } else {
+    if (!d->table) {
+      upb_MtDecoder_ErrorFormat(d, "Extensions cannot have message modifiers");
+      UPB_UNREACHABLE();
+    }
+    *msg_modifiers = mod;
+  }
+
+  return ptr;
+}
+
+static void upb_MtDecoder_AllocateSubs(upb_MtDecoder* d, uint32_t sub_count) {
+  size_t subs_bytes = sizeof(*d->table->subs) * sub_count;
+  void* subs = upb_Arena_Malloc(d->arena, subs_bytes);
+  memset(subs, 0, subs_bytes);
+  d->table->subs = subs;
+  upb_MtDecoder_CheckOutOfMemory(d, d->table->subs);
+}
+
+static const char* upb_MtDecoder_Parse(upb_MtDecoder* d, const char* ptr,
+                                       size_t len, void* fields,
+                                       size_t field_size, uint16_t* field_count,
+                                       uint32_t* sub_count) {
+  uint64_t msg_modifiers = 0;
+  uint32_t last_field_number = 0;
+  upb_MiniTableField* last_field = NULL;
+  bool need_dense_below = d->table != NULL;
+
+  d->end = UPB_PTRADD(ptr, len);
+
+  while (ptr < d->end) {
+    char ch = *ptr++;
+    if (ch <= kUpb_EncodedValue_MaxField) {
+      if (!d->table && last_field) {
+        // For extensions, consume only a single field and then return.
+        return --ptr;
+      }
+      upb_MiniTableField* field = fields;
+      *field_count += 1;
+      fields = (char*)fields + field_size;
+      field->number = ++last_field_number;
+      last_field = field;
+      upb_MiniTable_SetField(d, ch, field, msg_modifiers, sub_count);
+    } else if (kUpb_EncodedValue_MinModifier <= ch &&
+               ch <= kUpb_EncodedValue_MaxModifier) {
+      ptr = upb_MtDecoder_ParseModifier(d, ptr, ch, last_field, &msg_modifiers);
+      if (msg_modifiers & kUpb_MessageModifier_IsExtendable) {
+        d->table->ext |= kUpb_ExtMode_Extendable;
+      }
+    } else if (ch == kUpb_EncodedValue_End) {
+      if (!d->table) {
+        upb_MtDecoder_ErrorFormat(d, "Extensions cannot have oneofs.");
+        UPB_UNREACHABLE();
+      }
+      ptr = upb_MtDecoder_DecodeOneofs(d, ptr);
+    } else if (kUpb_EncodedValue_MinSkip <= ch &&
+               ch <= kUpb_EncodedValue_MaxSkip) {
+      if (need_dense_below) {
+        d->table->dense_below = d->table->field_count;
+        need_dense_below = false;
+      }
+      uint32_t skip;
+      ptr = upb_MiniTable_DecodeBase92Varint(d, ptr, ch,
+                                             kUpb_EncodedValue_MinSkip,
+                                             kUpb_EncodedValue_MaxSkip, &skip);
+      last_field_number += skip;
+      last_field_number--;  // Next field seen will increment.
+    } else {
+      upb_MtDecoder_ErrorFormat(d, "Invalid char: %c", ch);
+      UPB_UNREACHABLE();
+    }
+  }
+
+  if (need_dense_below) {
+    d->table->dense_below = d->table->field_count;
+  }
+
+  return ptr;
+}
+
+static void upb_MtDecoder_ParseMessage(upb_MtDecoder* d, const char* data,
+                                       size_t len) {
+  // Buffer length is an upper bound on the number of fields. We will return
+  // what we don't use.
+  d->fields = upb_Arena_Malloc(d->arena, sizeof(*d->fields) * len);
+  upb_MtDecoder_CheckOutOfMemory(d, d->fields);
+
+  uint32_t sub_count = 0;
+  d->table->field_count = 0;
+  d->table->fields = d->fields;
+  upb_MtDecoder_Parse(d, data, len, d->fields, sizeof(*d->fields),
+                      &d->table->field_count, &sub_count);
+
+  upb_Arena_ShrinkLast(d->arena, d->fields, sizeof(*d->fields) * len,
+                       sizeof(*d->fields) * d->table->field_count);
+  d->table->fields = d->fields;
+  upb_MtDecoder_AllocateSubs(d, sub_count);
+}
+
+int upb_MtDecoder_CompareFields(const void* _a, const void* _b) {
+  const upb_LayoutItem* a = _a;
+  const upb_LayoutItem* b = _b;
+  // Currently we just sort by:
+  //  1. rep (smallest fields first)
+  //  2. type (oneof cases first)
+  //  2. field_index (smallest numbers first)
+  // The main goal of this is to reduce space lost to padding.
+  // Later we may have more subtle reasons to prefer a different ordering.
+  const int rep_bits = upb_Log2Ceiling(kUpb_FieldRep_Max);
+  const int type_bits = upb_Log2Ceiling(kUpb_LayoutItemType_Max);
+  const int idx_bits = (sizeof(a->field_index) * 8);
+  UPB_ASSERT(idx_bits + rep_bits + type_bits < 32);
+#define UPB_COMBINE(rep, ty, idx) (((rep << type_bits) | ty) << idx_bits) | idx
+  uint32_t a_packed = UPB_COMBINE(a->rep, a->type, a->field_index);
+  uint32_t b_packed = UPB_COMBINE(b->rep, b->type, b->field_index);
+  assert(a_packed != b_packed);
+#undef UPB_COMBINE
+  return a_packed < b_packed ? -1 : 1;
+}
+
+static bool upb_MtDecoder_SortLayoutItems(upb_MtDecoder* d) {
+  // Add items for all non-oneof fields (oneofs were already added).
+  int n = d->table->field_count;
+  for (int i = 0; i < n; i++) {
+    upb_MiniTableField* f = &d->fields[i];
+    if (f->offset >= kOneofBase) continue;
+    upb_LayoutItem item = {.field_index = i,
+                           .rep = f->mode >> kUpb_FieldRep_Shift,
+                           .type = kUpb_LayoutItemType_Field};
+    upb_MtDecoder_PushItem(d, item);
+  }
+
+  if (d->vec.size) {
+    qsort(d->vec.data, d->vec.size, sizeof(*d->vec.data),
+          upb_MtDecoder_CompareFields);
+  }
+
+  return true;
+}
+
+static size_t upb_MiniTable_DivideRoundUp(size_t n, size_t d) {
+  return (n + d - 1) / d;
+}
+
+static void upb_MtDecoder_AssignHasbits(upb_MiniTable* ret) {
+  int n = ret->field_count;
+  int last_hasbit = 0;  // 0 cannot be used.
+
+  // First assign required fields, which must have the lowest hasbits.
+  for (int i = 0; i < n; i++) {
+    upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i];
+    if (field->offset == kRequiredPresence) {
+      field->presence = ++last_hasbit;
+    } else if (field->offset == kNoPresence) {
+      field->presence = 0;
+    }
+  }
+  ret->required_count = last_hasbit;
+
+  // Next assign non-required hasbit fields.
+  for (int i = 0; i < n; i++) {
+    upb_MiniTableField* field = (upb_MiniTableField*)&ret->fields[i];
+    if (field->offset == kHasbitPresence) {
+      field->presence = ++last_hasbit;
+    }
+  }
+
+  ret->size = last_hasbit ? upb_MiniTable_DivideRoundUp(last_hasbit + 1, 8) : 0;
+}
+
+size_t upb_MtDecoder_Place(upb_MtDecoder* d, upb_FieldRep rep) {
+  size_t size = upb_MtDecoder_SizeOfRep(rep, d->platform);
+  size_t align = upb_MtDecoder_AlignOfRep(rep, d->platform);
+  size_t ret = UPB_ALIGN_UP(d->table->size, align);
+  static const size_t max = UINT16_MAX;
+  size_t new_size = ret + size;
+  if (new_size > max) {
+    upb_MtDecoder_ErrorFormat(
+        d, "Message size exceeded maximum size of %zu bytes", max);
+  }
+  d->table->size = new_size;
+  return ret;
+}
+
+static void upb_MtDecoder_AssignOffsets(upb_MtDecoder* d) {
+  upb_LayoutItem* end = UPB_PTRADD(d->vec.data, d->vec.size);
+
+  // Compute offsets.
+  for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+    item->offset = upb_MtDecoder_Place(d, item->rep);
+  }
+
+  // Assign oneof case offsets.  We must do these first, since assigning
+  // actual offsets will overwrite the links of the linked list.
+  for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+    if (item->type != kUpb_LayoutItemType_OneofCase) continue;
+    upb_MiniTableField* f = &d->fields[item->field_index];
+    while (true) {
+      f->presence = ~item->offset;
+      if (f->offset == kUpb_LayoutItem_IndexSentinel) break;
+      UPB_ASSERT(f->offset - kOneofBase < d->table->field_count);
+      f = &d->fields[f->offset - kOneofBase];
+    }
+  }
+
+  // Assign offsets.
+  for (upb_LayoutItem* item = d->vec.data; item < end; item++) {
+    upb_MiniTableField* f = &d->fields[item->field_index];
+    switch (item->type) {
+      case kUpb_LayoutItemType_OneofField:
+        while (true) {
+          uint16_t next_offset = f->offset;
+          f->offset = item->offset;
+          if (next_offset == kUpb_LayoutItem_IndexSentinel) break;
+          f = &d->fields[next_offset - kOneofBase];
+        }
+        break;
+      case kUpb_LayoutItemType_Field:
+        f->offset = item->offset;
+        break;
+      default:
+        break;
+    }
+  }
+
+  // The fasttable parser (supported on 64-bit only) depends on this being a
+  // multiple of 8 in order to satisfy UPB_MALLOC_ALIGN, which is also 8.
+  //
+  // On 32-bit we could potentially make this smaller, but there is no
+  // compelling reason to optimize this right now.
+  d->table->size = UPB_ALIGN_UP(d->table->size, 8);
+}
+
+static void upb_MtDecoder_ParseMap(upb_MtDecoder* d, const char* data,
+                                   size_t len) {
+  if (len < 2) {
+    upb_MtDecoder_ErrorFormat(d, "Invalid map encode length: %zu", len);
+    UPB_UNREACHABLE();
+  }
+  const upb_EncodedType key_type = _upb_FromBase92(data[0]);
+  switch (key_type) {
+    case kUpb_EncodedType_Fixed32:
+    case kUpb_EncodedType_Fixed64:
+    case kUpb_EncodedType_SFixed32:
+    case kUpb_EncodedType_SFixed64:
+    case kUpb_EncodedType_Int32:
+    case kUpb_EncodedType_UInt32:
+    case kUpb_EncodedType_SInt32:
+    case kUpb_EncodedType_Int64:
+    case kUpb_EncodedType_UInt64:
+    case kUpb_EncodedType_SInt64:
+    case kUpb_EncodedType_Bool:
+    case kUpb_EncodedType_String:
+      break;
+
+    default:
+      upb_MtDecoder_ErrorFormat(d, "Invalid map key field type: %d", key_type);
+      UPB_UNREACHABLE();
+  }
+
+  upb_MtDecoder_ParseMessage(d, data, len);
+  upb_MtDecoder_AssignHasbits(d->table);
+
+  // Map entries have a pre-determined layout, regardless of types.
+  // NOTE: sync with mini_table/message_internal.h.
+  const size_t kv_size = d->platform == kUpb_MiniTablePlatform_32Bit ? 8 : 16;
+  const size_t hasbit_size = 8;
+  d->fields[0].offset = hasbit_size;
+  d->fields[1].offset = hasbit_size + kv_size;
+  d->table->size = UPB_ALIGN_UP(hasbit_size + kv_size + kv_size, 8);
+
+  // Map entries have a special bit set to signal it's a map entry, used in
+  // upb_MiniTable_SetSubMessage() below.
+  d->table->ext |= kUpb_ExtMode_IsMapEntry;
+}
+
+static void upb_MtDecoder_ParseMessageSet(upb_MtDecoder* d, const char* data,
+                                          size_t len) {
+  if (len > 0) {
+    upb_MtDecoder_ErrorFormat(d, "Invalid message set encode length: %zu", len);
+    UPB_UNREACHABLE();
+  }
+
+  upb_MiniTable* ret = d->table;
+  ret->size = 0;
+  ret->field_count = 0;
+  ret->ext = kUpb_ExtMode_IsMessageSet;
+  ret->dense_below = 0;
+  ret->table_mask = -1;
+  ret->required_count = 0;
+}
+
+upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Arena* arena, void** buf,
+                                          size_t* buf_size,
+                                          upb_Status* status) {
+  upb_MtDecoder decoder = {
+      .platform = platform,
+      .vec =
+          {
+              .data = *buf,
+              .capacity = *buf_size / sizeof(*decoder.vec.data),
+              .size = 0,
+          },
+      .arena = arena,
+      .status = status,
+      .table = upb_Arena_Malloc(arena, sizeof(*decoder.table)),
+  };
+
+  if (UPB_SETJMP(decoder.err)) {
+    decoder.table = NULL;
+    goto done;
+  }
+
+  upb_MtDecoder_CheckOutOfMemory(&decoder, decoder.table);
+
+  decoder.table->size = 0;
+  decoder.table->field_count = 0;
+  decoder.table->ext = kUpb_ExtMode_NonExtendable;
+  decoder.table->dense_below = 0;
+  decoder.table->table_mask = -1;
+  decoder.table->required_count = 0;
+
+  // Strip off and verify the version tag.
+  if (!len--) goto done;
+  const char vers = *data++;
+
+  switch (vers) {
+    case kUpb_EncodedVersion_MapV1:
+      upb_MtDecoder_ParseMap(&decoder, data, len);
+      break;
+
+    case kUpb_EncodedVersion_MessageV1:
+      upb_MtDecoder_ParseMessage(&decoder, data, len);
+      upb_MtDecoder_AssignHasbits(decoder.table);
+      upb_MtDecoder_SortLayoutItems(&decoder);
+      upb_MtDecoder_AssignOffsets(&decoder);
+      break;
+
+    case kUpb_EncodedVersion_MessageSetV1:
+      upb_MtDecoder_ParseMessageSet(&decoder, data, len);
+      break;
+
+    default:
+      upb_MtDecoder_ErrorFormat(&decoder, "Invalid message version: %c", vers);
+      UPB_UNREACHABLE();
+  }
+
+done:
+  *buf = decoder.vec.data;
+  *buf_size = decoder.vec.capacity * sizeof(*decoder.vec.data);
+  return decoder.table;
+}
+
+static size_t upb_MiniTableEnum_Size(size_t count) {
+  return sizeof(upb_MiniTableEnum) + count * sizeof(uint32_t);
+}
+
+static upb_MiniTableEnum* _upb_MiniTable_AddEnumDataMember(upb_MtDecoder* d,
+                                                           uint32_t val) {
+  if (d->enum_data_count == d->enum_data_capacity) {
+    size_t old_sz = upb_MiniTableEnum_Size(d->enum_data_capacity);
+    d->enum_data_capacity = UPB_MAX(2, d->enum_data_capacity * 2);
+    size_t new_sz = upb_MiniTableEnum_Size(d->enum_data_capacity);
+    d->enum_table = upb_Arena_Realloc(d->arena, d->enum_table, old_sz, new_sz);
+    upb_MtDecoder_CheckOutOfMemory(d, d->enum_table);
+  }
+  d->enum_table->data[d->enum_data_count++] = val;
+  return d->enum_table;
+}
+
+static void upb_MiniTableEnum_BuildValue(upb_MtDecoder* d, uint32_t val) {
+  upb_MiniTableEnum* table = d->enum_table;
+  d->enum_value_count++;
+  if (table->value_count || (val > 512 && d->enum_value_count < val / 32)) {
+    if (table->value_count == 0) {
+      assert(d->enum_data_count == table->mask_limit / 32);
+    }
+    table = _upb_MiniTable_AddEnumDataMember(d, val);
+    table->value_count++;
+  } else {
+    uint32_t new_mask_limit = ((val / 32) + 1) * 32;
+    while (table->mask_limit < new_mask_limit) {
+      table = _upb_MiniTable_AddEnumDataMember(d, 0);
+      table->mask_limit += 32;
+    }
+    table->data[val / 32] |= 1ULL << (val % 32);
+  }
+}
+
+upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len,
+                                           upb_Arena* arena,
+                                           upb_Status* status) {
+  upb_MtDecoder decoder = {
+      .enum_table = upb_Arena_Malloc(arena, upb_MiniTableEnum_Size(2)),
+      .enum_value_count = 0,
+      .enum_data_count = 0,
+      .enum_data_capacity = 1,
+      .status = status,
+      .end = UPB_PTRADD(data, len),
+      .arena = arena,
+  };
+
+  if (UPB_SETJMP(decoder.err)) return NULL;
+
+  // If the string is non-empty then it must begin with a version tag.
+  if (len) {
+    if (*data != kUpb_EncodedVersion_EnumV1) {
+      upb_MtDecoder_ErrorFormat(&decoder, "Invalid enum version: %c", *data);
+      UPB_UNREACHABLE();
+    }
+    data++;
+    len--;
+  }
+
+  upb_MtDecoder_CheckOutOfMemory(&decoder, decoder.enum_table);
+
+  // Guarantee at least 64 bits of mask without checking mask size.
+  decoder.enum_table->mask_limit = 64;
+  decoder.enum_table = _upb_MiniTable_AddEnumDataMember(&decoder, 0);
+  decoder.enum_table = _upb_MiniTable_AddEnumDataMember(&decoder, 0);
+
+  decoder.enum_table->value_count = 0;
+
+  const char* ptr = data;
+  uint32_t base = 0;
+
+  while (ptr < decoder.end) {
+    char ch = *ptr++;
+    if (ch <= kUpb_EncodedValue_MaxEnumMask) {
+      uint32_t mask = _upb_FromBase92(ch);
+      for (int i = 0; i < 5; i++, base++, mask >>= 1) {
+        if (mask & 1) upb_MiniTableEnum_BuildValue(&decoder, base);
+      }
+    } else if (kUpb_EncodedValue_MinSkip <= ch &&
+               ch <= kUpb_EncodedValue_MaxSkip) {
+      uint32_t skip;
+      ptr = upb_MiniTable_DecodeBase92Varint(&decoder, ptr, ch,
+                                             kUpb_EncodedValue_MinSkip,
+                                             kUpb_EncodedValue_MaxSkip, &skip);
+      base += skip;
+    } else {
+      upb_MtDecoder_ErrorFormat(&decoder, "Unexpected character: %c", ch);
+      return NULL;
+    }
+  }
+
+  return decoder.enum_table;
+}
+
+const char* _upb_MiniTableExtension_Build(const char* data, size_t len,
+                                          upb_MiniTableExtension* ext,
+                                          const upb_MiniTable* extendee,
+                                          upb_MiniTableSub sub,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Status* status) {
+  upb_MtDecoder decoder = {
+      .arena = NULL,
+      .status = status,
+      .table = NULL,
+      .platform = platform,
+  };
+
+  if (UPB_SETJMP(decoder.err)) return NULL;
+
+  // If the string is non-empty then it must begin with a version tag.
+  if (len) {
+    if (*data != kUpb_EncodedVersion_ExtensionV1) {
+      upb_MtDecoder_ErrorFormat(&decoder, "Invalid ext version: %c", *data);
+      UPB_UNREACHABLE();
+    }
+    data++;
+    len--;
+  }
+
+  uint16_t count = 0;
+  const char* ret =
+      upb_MtDecoder_Parse(&decoder, data, len, ext, sizeof(*ext), &count, NULL);
+  if (!ret || count != 1) return NULL;
+
+  upb_MiniTableField* f = &ext->field;
+
+  f->mode |= kUpb_LabelFlags_IsExtension;
+  f->offset = 0;
+  f->presence = 0;
+
+  if (extendee->ext & kUpb_ExtMode_IsMessageSet) {
+    // Extensions of MessageSet must be messages.
+    if (!upb_IsSubMessage(f)) return NULL;
+
+    // Extensions of MessageSet must be non-repeating.
+    if ((f->mode & kUpb_FieldMode_Mask) == kUpb_FieldMode_Array) return NULL;
+  }
+
+  ext->extendee = extendee;
+  ext->sub = sub;
+
+  return ret;
+}
+
+upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len,
+                                    upb_MiniTablePlatform platform,
+                                    upb_Arena* arena, upb_Status* status) {
+  void* buf = NULL;
+  size_t size = 0;
+  upb_MiniTable* ret = upb_MiniTable_BuildWithBuf(data, len, platform, arena,
+                                                  &buf, &size, status);
+  free(buf);
+  return ret;
+}
+
+void upb_MiniTable_SetSubMessage(upb_MiniTable* table,
+                                 upb_MiniTableField* field,
+                                 const upb_MiniTable* sub) {
+  UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
+             (uintptr_t)field <
+                 (uintptr_t)(table->fields + table->field_count));
+  if (sub->ext & kUpb_ExtMode_IsMapEntry) {
+    field->mode = (field->mode & ~kUpb_FieldMode_Mask) | kUpb_FieldMode_Map;
+  }
+  upb_MiniTableSub* table_sub = (void*)&table->subs[field->submsg_index];
+  table_sub->submsg = sub;
+}
+
+void upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTableField* field,
+                              const upb_MiniTableEnum* sub) {
+  UPB_ASSERT((uintptr_t)table->fields <= (uintptr_t)field &&
+             (uintptr_t)field <
+                 (uintptr_t)(table->fields + table->field_count));
+  upb_MiniTableSub* table_sub = (void*)&table->subs[field->submsg_index];
+  table_sub->subenum = sub;
+}
+
+#include <inttypes.h>
+
+
+// Must be last.
+
+typedef struct {
+  uint64_t present_values_mask;
+  uint32_t last_written_value;
+} upb_MtDataEncoderInternal_EnumState;
+
+typedef struct {
+  uint64_t msg_modifiers;
+  uint32_t last_field_num;
+  enum {
+    kUpb_OneofState_NotStarted,
+    kUpb_OneofState_StartedOneof,
+    kUpb_OneofState_EmittedOneofField,
+  } oneof_state;
+} upb_MtDataEncoderInternal_MsgState;
+
+typedef struct {
+  char* buf_start;  // Only for checking kUpb_MtDataEncoder_MinSize.
+  union {
+    upb_MtDataEncoderInternal_EnumState enum_state;
+    upb_MtDataEncoderInternal_MsgState msg_state;
+  } state;
+} upb_MtDataEncoderInternal;
+
+static upb_MtDataEncoderInternal* upb_MtDataEncoder_GetInternal(
+    upb_MtDataEncoder* e, char* buf_start) {
+  UPB_ASSERT(sizeof(upb_MtDataEncoderInternal) <= sizeof(e->internal));
+  upb_MtDataEncoderInternal* ret = (upb_MtDataEncoderInternal*)e->internal;
+  ret->buf_start = buf_start;
+  return ret;
+}
+
+static char* upb_MtDataEncoder_PutRaw(upb_MtDataEncoder* e, char* ptr,
+                                      char ch) {
+  upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal;
+  UPB_ASSERT(ptr - in->buf_start < kUpb_MtDataEncoder_MinSize);
+  if (ptr == e->end) return NULL;
+  *ptr++ = ch;
+  return ptr;
+}
+
+static char* upb_MtDataEncoder_Put(upb_MtDataEncoder* e, char* ptr, char ch) {
+  return upb_MtDataEncoder_PutRaw(e, ptr, _upb_ToBase92(ch));
+}
+
+static char* upb_MtDataEncoder_PutBase92Varint(upb_MtDataEncoder* e, char* ptr,
+                                               uint32_t val, int min, int max) {
+  int shift = upb_Log2Ceiling(_upb_FromBase92(max) - _upb_FromBase92(min) + 1);
+  UPB_ASSERT(shift <= 6);
+  uint32_t mask = (1 << shift) - 1;
+  do {
+    uint32_t bits = val & mask;
+    ptr = upb_MtDataEncoder_Put(e, ptr, bits + _upb_FromBase92(min));
+    if (!ptr) return NULL;
+    val >>= shift;
+  } while (val);
+  return ptr;
+}
+
+char* upb_MtDataEncoder_PutModifier(upb_MtDataEncoder* e, char* ptr,
+                                    uint64_t mod) {
+  if (mod) {
+    ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, mod,
+                                            kUpb_EncodedValue_MinModifier,
+                                            kUpb_EncodedValue_MaxModifier);
+  }
+  return ptr;
+}
+
+char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr,
+                                        upb_FieldType type, uint32_t field_num,
+                                        uint64_t field_mod) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.msg_state.msg_modifiers = 0;
+  in->state.msg_state.last_field_num = 0;
+  in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted;
+
+  ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_ExtensionV1);
+  if (!ptr) return NULL;
+
+  return upb_MtDataEncoder_PutField(e, ptr, type, field_num, field_mod);
+}
+
+char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr,
+                                  upb_FieldType key_type,
+                                  upb_FieldType value_type, uint64_t key_mod,
+                                  uint64_t value_mod) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.msg_state.msg_modifiers = 0;
+  in->state.msg_state.last_field_num = 0;
+  in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted;
+
+  ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MapV1);
+  if (!ptr) return NULL;
+
+  ptr = upb_MtDataEncoder_PutField(e, ptr, key_type, 1, key_mod);
+  if (!ptr) return NULL;
+
+  return upb_MtDataEncoder_PutField(e, ptr, value_type, 2, value_mod);
+}
+
+char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr) {
+  (void)upb_MtDataEncoder_GetInternal(e, ptr);
+  return upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MessageSetV1);
+}
+
+char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr,
+                                     uint64_t msg_mod) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.msg_state.msg_modifiers = msg_mod;
+  in->state.msg_state.last_field_num = 0;
+  in->state.msg_state.oneof_state = kUpb_OneofState_NotStarted;
+
+  ptr = upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_MessageV1);
+  if (!ptr) return NULL;
+
+  return upb_MtDataEncoder_PutModifier(e, ptr, msg_mod);
+}
+
+char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr,
+                                 upb_FieldType type, uint32_t field_num,
+                                 uint64_t field_mod) {
+  static const char kUpb_TypeToEncoded[] = {
+      [kUpb_FieldType_Double] = kUpb_EncodedType_Double,
+      [kUpb_FieldType_Float] = kUpb_EncodedType_Float,
+      [kUpb_FieldType_Int64] = kUpb_EncodedType_Int64,
+      [kUpb_FieldType_UInt64] = kUpb_EncodedType_UInt64,
+      [kUpb_FieldType_Int32] = kUpb_EncodedType_Int32,
+      [kUpb_FieldType_Fixed64] = kUpb_EncodedType_Fixed64,
+      [kUpb_FieldType_Fixed32] = kUpb_EncodedType_Fixed32,
+      [kUpb_FieldType_Bool] = kUpb_EncodedType_Bool,
+      [kUpb_FieldType_String] = kUpb_EncodedType_String,
+      [kUpb_FieldType_Group] = kUpb_EncodedType_Group,
+      [kUpb_FieldType_Message] = kUpb_EncodedType_Message,
+      [kUpb_FieldType_Bytes] = kUpb_EncodedType_Bytes,
+      [kUpb_FieldType_UInt32] = kUpb_EncodedType_UInt32,
+      [kUpb_FieldType_Enum] = kUpb_EncodedType_OpenEnum,
+      [kUpb_FieldType_SFixed32] = kUpb_EncodedType_SFixed32,
+      [kUpb_FieldType_SFixed64] = kUpb_EncodedType_SFixed64,
+      [kUpb_FieldType_SInt32] = kUpb_EncodedType_SInt32,
+      [kUpb_FieldType_SInt64] = kUpb_EncodedType_SInt64,
+  };
+
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (field_num <= in->state.msg_state.last_field_num) return NULL;
+  if (in->state.msg_state.last_field_num + 1 != field_num) {
+    // Put skip.
+    UPB_ASSERT(field_num > in->state.msg_state.last_field_num);
+    uint32_t skip = field_num - in->state.msg_state.last_field_num;
+    ptr = upb_MtDataEncoder_PutBase92Varint(
+        e, ptr, skip, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip);
+    if (!ptr) return NULL;
+  }
+  in->state.msg_state.last_field_num = field_num;
+
+  uint32_t encoded_modifiers = 0;
+
+  // Put field type.
+  int encoded_type = kUpb_TypeToEncoded[type];
+  if (field_mod & kUpb_FieldModifier_IsClosedEnum) {
+    UPB_ASSERT(type == kUpb_FieldType_Enum);
+    encoded_type = kUpb_EncodedType_ClosedEnum;
+  }
+  if (field_mod & kUpb_FieldModifier_IsRepeated) {
+    // Repeated fields shift the type number up (unlike other modifiers which
+    // are bit flags).
+    encoded_type += kUpb_EncodedType_RepeatedBase;
+
+    if (_upb_FieldType_IsPackable(type)) {
+      bool field_is_packed = field_mod & kUpb_FieldModifier_IsPacked;
+      bool default_is_packed = in->state.msg_state.msg_modifiers &
+                               kUpb_MessageModifier_DefaultIsPacked;
+      if (field_is_packed != default_is_packed) {
+        encoded_modifiers |= kUpb_EncodedFieldModifier_FlipPacked;
+      }
+    }
+  }
+  ptr = upb_MtDataEncoder_Put(e, ptr, encoded_type);
+  if (!ptr) return NULL;
+
+  if (field_mod & kUpb_FieldModifier_IsProto3Singular) {
+    encoded_modifiers |= kUpb_EncodedFieldModifier_IsProto3Singular;
+  }
+  if (field_mod & kUpb_FieldModifier_IsRequired) {
+    encoded_modifiers |= kUpb_EncodedFieldModifier_IsRequired;
+  }
+  return upb_MtDataEncoder_PutModifier(e, ptr, encoded_modifiers);
+}
+
+char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (in->state.msg_state.oneof_state == kUpb_OneofState_NotStarted) {
+    ptr = upb_MtDataEncoder_Put(e, ptr, _upb_FromBase92(kUpb_EncodedValue_End));
+  } else {
+    ptr = upb_MtDataEncoder_Put(
+        e, ptr, _upb_FromBase92(kUpb_EncodedValue_OneofSeparator));
+  }
+  in->state.msg_state.oneof_state = kUpb_OneofState_StartedOneof;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr,
+                                      uint32_t field_num) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (in->state.msg_state.oneof_state == kUpb_OneofState_EmittedOneofField) {
+    ptr = upb_MtDataEncoder_Put(
+        e, ptr, _upb_FromBase92(kUpb_EncodedValue_FieldSeparator));
+    if (!ptr) return NULL;
+  }
+  ptr = upb_MtDataEncoder_PutBase92Varint(e, ptr, field_num, _upb_ToBase92(0),
+                                          _upb_ToBase92(63));
+  in->state.msg_state.oneof_state = kUpb_OneofState_EmittedOneofField;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e, char* ptr) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  in->state.enum_state.present_values_mask = 0;
+  in->state.enum_state.last_written_value = 0;
+
+  return upb_MtDataEncoder_PutRaw(e, ptr, kUpb_EncodedVersion_EnumV1);
+}
+
+static char* upb_MtDataEncoder_FlushDenseEnumMask(upb_MtDataEncoder* e,
+                                                  char* ptr) {
+  upb_MtDataEncoderInternal* in = (upb_MtDataEncoderInternal*)e->internal;
+  ptr = upb_MtDataEncoder_Put(e, ptr, in->state.enum_state.present_values_mask);
+  in->state.enum_state.present_values_mask = 0;
+  in->state.enum_state.last_written_value += 5;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr,
+                                     uint32_t val) {
+  // TODO(b/229641772): optimize this encoding.
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  UPB_ASSERT(val >= in->state.enum_state.last_written_value);
+  uint32_t delta = val - in->state.enum_state.last_written_value;
+  if (delta >= 5 && in->state.enum_state.present_values_mask) {
+    ptr = upb_MtDataEncoder_FlushDenseEnumMask(e, ptr);
+    if (!ptr) {
+      return NULL;
+    }
+    delta -= 5;
+  }
+
+  if (delta >= 5) {
+    ptr = upb_MtDataEncoder_PutBase92Varint(
+        e, ptr, delta, kUpb_EncodedValue_MinSkip, kUpb_EncodedValue_MaxSkip);
+    in->state.enum_state.last_written_value += delta;
+    delta = 0;
+  }
+
+  UPB_ASSERT((in->state.enum_state.present_values_mask >> delta) == 0);
+  in->state.enum_state.present_values_mask |= 1ULL << delta;
+  return ptr;
+}
+
+char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr) {
+  upb_MtDataEncoderInternal* in = upb_MtDataEncoder_GetInternal(e, ptr);
+  if (!in->state.enum_state.present_values_mask) return ptr;
+  return upb_MtDataEncoder_FlushDenseEnumMask(e, ptr);
+}
+
+
+
+// Must be last.
+
+#define EXTREG_KEY_SIZE (sizeof(upb_MiniTable*) + sizeof(uint32_t))
+
+struct upb_ExtensionRegistry {
+  upb_Arena* arena;
+  upb_strtable exts;  // Key is upb_MiniTable* concatenated with fieldnum.
+};
+
+static void extreg_key(char* buf, const upb_MiniTable* l, uint32_t fieldnum) {
+  memcpy(buf, &l, sizeof(l));
+  memcpy(buf + sizeof(l), &fieldnum, sizeof(fieldnum));
+}
+
+upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena) {
+  upb_ExtensionRegistry* r = upb_Arena_Malloc(arena, sizeof(*r));
+  if (!r) return NULL;
+  r->arena = arena;
+  if (!upb_strtable_init(&r->exts, 8, arena)) return NULL;
+  return r;
+}
+
+bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r,
+                                    const upb_MiniTableExtension** e,
+                                    size_t count) {
+  char buf[EXTREG_KEY_SIZE];
+  const upb_MiniTableExtension** start = e;
+  const upb_MiniTableExtension** end = UPB_PTRADD(e, count);
+  for (; e < end; e++) {
+    const upb_MiniTableExtension* ext = *e;
+    extreg_key(buf, ext->extendee, ext->field.number);
+    upb_value v;
+    if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
+      goto failure;
+    }
+    if (!upb_strtable_insert(&r->exts, buf, EXTREG_KEY_SIZE,
+                             upb_value_constptr(ext), r->arena)) {
+      goto failure;
+    }
+  }
+  return true;
+
+failure:
+  // Back out the entries previously added.
+  for (end = e, e = start; e < end; e++) {
+    const upb_MiniTableExtension* ext = *e;
+    extreg_key(buf, ext->extendee, ext->field.number);
+    upb_strtable_remove2(&r->exts, buf, EXTREG_KEY_SIZE, NULL);
+  }
+  return false;
+}
+
+const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup(
+    const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num) {
+  char buf[EXTREG_KEY_SIZE];
+  upb_value v;
+  extreg_key(buf, t, num);
+  if (upb_strtable_lookup2(&r->exts, buf, EXTREG_KEY_SIZE, &v)) {
+    return upb_value_getconstptr(v);
+  } else {
+    return NULL;
+  }
+}
+
+#include <string.h>
+
+
+// Must be last.
+
+/* The upb core does not generally have a concept of default instances. However
+ * for descriptor options we make an exception since the max size is known and
+ * modest (<200 bytes). All types can share a default instance since it is
+ * initialized to zeroes.
+ *
+ * We have to allocate an extra pointer for upb's internal metadata. */
+static const char opt_default_buf[_UPB_MAXOPT_SIZE + sizeof(void*)] = {0};
+const char* kUpbDefOptDefault = &opt_default_buf[sizeof(void*)];
+
+const char* _upb_DefBuilder_FullToShort(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;
+  }
+}
+
+void _upb_DefBuilder_FailJmp(upb_DefBuilder* ctx) { UPB_LONGJMP(ctx->err, 1); }
+
+void _upb_DefBuilder_Errf(upb_DefBuilder* ctx, const char* fmt, ...) {
+  va_list argp;
+  va_start(argp, fmt);
+  upb_Status_VSetErrorFormat(ctx->status, fmt, argp);
+  va_end(argp);
+  _upb_DefBuilder_FailJmp(ctx);
+}
+
+void _upb_DefBuilder_OomErr(upb_DefBuilder* ctx) {
+  upb_Status_SetErrorMessage(ctx->status, "out of memory");
+  _upb_DefBuilder_FailJmp(ctx);
+}
+
+const char* _upb_DefBuilder_MakeFullName(upb_DefBuilder* ctx,
+                                         const char* prefix,
+                                         upb_StringView name) {
+  if (prefix) {
+    // ret = prefix + '.' + name;
+    size_t n = strlen(prefix);
+    char* ret = _upb_DefBuilder_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 {
+    char* ret = upb_strdup2(name.data, name.size, ctx->arena);
+    if (!ret) _upb_DefBuilder_OomErr(ctx);
+    return ret;
+  }
+}
+
+static bool remove_component(char* base, size_t* len) {
+  if (*len == 0) return false;
+
+  for (size_t i = *len - 1; i > 0; i--) {
+    if (base[i] == '.') {
+      *len = i;
+      return true;
+    }
+  }
+
+  *len = 0;
+  return true;
+}
+
+const void* _upb_DefBuilder_ResolveAny(upb_DefBuilder* ctx,
+                                       const char* from_name_dbg,
+                                       const char* base, upb_StringView sym,
+                                       upb_deftype_t* type) {
+  if (sym.size == 0) goto notfound;
+  upb_value v;
+  if (sym.data[0] == '.') {
+    /* Symbols starting with '.' are absolute, so we do a single lookup.
+     * Slice to omit the leading '.' */
+    if (!_upb_DefPool_LookupSym(ctx->symtab, sym.data + 1, sym.size - 1, &v)) {
+      goto notfound;
+    }
+  } else {
+    /* Remove components from base until we find an entry or run out. */
+    size_t baselen = base ? strlen(base) : 0;
+    char* tmp = malloc(sym.size + baselen + 1);
+    while (1) {
+      char* p = tmp;
+      if (baselen) {
+        memcpy(p, base, baselen);
+        p[baselen] = '.';
+        p += baselen + 1;
+      }
+      memcpy(p, sym.data, sym.size);
+      p += sym.size;
+      if (_upb_DefPool_LookupSym(ctx->symtab, tmp, p - tmp, &v)) {
+        break;
+      }
+      if (!remove_component(tmp, &baselen)) {
+        free(tmp);
+        goto notfound;
+      }
+    }
+    free(tmp);
+  }
+
+  *type = _upb_DefType_Type(v);
+  return _upb_DefType_Unpack(v, *type);
+
+notfound:
+  _upb_DefBuilder_Errf(ctx, "couldn't resolve name '" UPB_STRINGVIEW_FORMAT "'",
+                       UPB_STRINGVIEW_ARGS(sym));
+}
+
+const void* _upb_DefBuilder_Resolve(upb_DefBuilder* ctx,
+                                    const char* from_name_dbg, const char* base,
+                                    upb_StringView sym, upb_deftype_t type) {
+  upb_deftype_t found_type;
+  const void* ret =
+      _upb_DefBuilder_ResolveAny(ctx, from_name_dbg, base, sym, &found_type);
+  if (ret && found_type != type) {
+    _upb_DefBuilder_Errf(ctx,
+                         "type mismatch when resolving %s: couldn't find "
+                         "name " UPB_STRINGVIEW_FORMAT " with type=%d",
+                         from_name_dbg, UPB_STRINGVIEW_ARGS(sym), (int)type);
+  }
+  return ret;
+}
+
+// Per ASCII this will lower-case a letter. If the result is a letter, the
+// input was definitely a letter. If the output is not a letter, this may
+// have transformed the character unpredictably.
+static char upb_ascii_lower(char ch) { return ch | 0x20; }
+
+// isalpha() etc. from <ctype.h> are locale-dependent, which we don't want.
+static bool upb_isbetween(uint8_t c, uint8_t low, uint8_t high) {
+  return low <= c && c <= high;
+}
+
+static bool upb_isletter(char c) {
+  char lower = upb_ascii_lower(c);
+  return upb_isbetween(lower, 'a', 'z') || c == '_';
+}
+
+static bool upb_isalphanum(char c) {
+  return upb_isletter(c) || upb_isbetween(c, '0', '9');
+}
+
+static bool TryGetChar(const char** src, const char* end, char* ch) {
+  if (*src == end) return false;
+  *ch = **src;
+  *src += 1;
+  return true;
+}
+
+static char TryGetHexDigit(const char** src, const char* end) {
+  char ch;
+  if (!TryGetChar(src, end, &ch)) return -1;
+  if ('0' <= ch && ch <= '9') {
+    return ch - '0';
+  }
+  ch = upb_ascii_lower(ch);
+  if ('a' <= ch && ch <= 'f') {
+    return ch - 'a' + 0xa;
+  }
+  *src -= 1;  // Char wasn't actually a hex digit.
+  return -1;
+}
+
+static char upb_DefBuilder_ParseHexEscape(upb_DefBuilder* ctx,
+                                          const upb_FieldDef* f,
+                                          const char** src, const char* end) {
+  char hex_digit = TryGetHexDigit(src, end);
+  if (hex_digit < 0) {
+    _upb_DefBuilder_Errf(
+        ctx, "\\x cannot be followed by non-hex digit in field '%s' default",
+        upb_FieldDef_FullName(f));
+    return 0;
+  }
+  unsigned int ret = hex_digit;
+  while ((hex_digit = TryGetHexDigit(src, end)) >= 0) {
+    ret = (ret << 4) | hex_digit;
+  }
+  if (ret > 0xff) {
+    _upb_DefBuilder_Errf(ctx, "Value of hex escape in field %s exceeds 8 bits",
+                         upb_FieldDef_FullName(f));
+    return 0;
+  }
+  return ret;
+}
+
+static char TryGetOctalDigit(const char** src, const char* end) {
+  char ch;
+  if (!TryGetChar(src, end, &ch)) return -1;
+  if ('0' <= ch && ch <= '7') {
+    return ch - '0';
+  }
+  *src -= 1;  // Char wasn't actually an octal digit.
+  return -1;
+}
+
+static char upb_DefBuilder_ParseOctalEscape(upb_DefBuilder* ctx,
+                                            const upb_FieldDef* f,
+                                            const char** src, const char* end) {
+  char ch = 0;
+  for (int i = 0; i < 3; i++) {
+    char digit;
+    if ((digit = TryGetOctalDigit(src, end)) >= 0) {
+      ch = (ch << 3) | digit;
+    }
+  }
+  return ch;
+}
+
+char _upb_DefBuilder_ParseEscape(upb_DefBuilder* ctx, const upb_FieldDef* f,
+                                 const char** src, const char* end) {
+  char ch;
+  if (!TryGetChar(src, end, &ch)) {
+    _upb_DefBuilder_Errf(ctx, "unterminated escape sequence in field %s",
+                         upb_FieldDef_FullName(f));
+    return 0;
+  }
+  switch (ch) {
+    case 'a':
+      return '\a';
+    case 'b':
+      return '\b';
+    case 'f':
+      return '\f';
+    case 'n':
+      return '\n';
+    case 'r':
+      return '\r';
+    case 't':
+      return '\t';
+    case 'v':
+      return '\v';
+    case '\\':
+      return '\\';
+    case '\'':
+      return '\'';
+    case '\"':
+      return '\"';
+    case '?':
+      return '\?';
+    case 'x':
+    case 'X':
+      return upb_DefBuilder_ParseHexEscape(ctx, f, src, end);
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+      *src -= 1;
+      return upb_DefBuilder_ParseOctalEscape(ctx, f, src, end);
+  }
+  _upb_DefBuilder_Errf(ctx, "Unknown escape sequence: \\%c", ch);
+}
+
+void _upb_DefBuilder_CheckIdentSlow(upb_DefBuilder* ctx, upb_StringView name,
+                                    bool full) {
+  const char* str = name.data;
+  const size_t len = name.size;
+  bool start = true;
+  for (size_t i = 0; i < len; i++) {
+    const char c = str[i];
+    if (c == '.') {
+      if (start || !full) {
+        _upb_DefBuilder_Errf(
+            ctx, "invalid name: unexpected '.' (" UPB_STRINGVIEW_FORMAT ")",
+            UPB_STRINGVIEW_ARGS(name));
+      }
+      start = true;
+    } else if (start) {
+      if (!upb_isletter(c)) {
+        _upb_DefBuilder_Errf(ctx,
+                             "invalid name: path components must start with a "
+                             "letter (" UPB_STRINGVIEW_FORMAT ")",
+                             UPB_STRINGVIEW_ARGS(name));
+      }
+      start = false;
+    } else if (!upb_isalphanum(c)) {
+      _upb_DefBuilder_Errf(
+          ctx,
+          "invalid name: non-alphanumeric character (" UPB_STRINGVIEW_FORMAT
+          ")",
+          UPB_STRINGVIEW_ARGS(name));
+    }
+  }
+  if (start) {
+    _upb_DefBuilder_Errf(ctx,
+                         "invalid name: empty part (" UPB_STRINGVIEW_FORMAT ")",
+                         UPB_STRINGVIEW_ARGS(name));
+  }
+
+  // We should never reach this point.
+  UPB_ASSERT(false);
+}
+
+
+// Must be last.
+
+struct upb_DefPool {
+  upb_Arena* arena;
+  upb_strtable syms;   // full_name -> packed def ptr
+  upb_strtable files;  // file_name -> (upb_FileDef*)
+  upb_inttable exts;   // (upb_MiniTableExtension*) -> (upb_FieldDef*)
+  upb_ExtensionRegistry* extreg;
+  void* scratch_data;
+  size_t scratch_size;
+  size_t bytes_loaded;
+};
+
+void upb_DefPool_Free(upb_DefPool* s) {
+  upb_Arena_Free(s->arena);
+  upb_gfree(s->scratch_data);
+  upb_gfree(s);
+}
+
+upb_DefPool* upb_DefPool_New(void) {
+  upb_DefPool* s = upb_gmalloc(sizeof(*s));
+  if (!s) return NULL;
+
+  s->arena = upb_Arena_New();
+  s->bytes_loaded = 0;
+
+  s->scratch_size = 240;
+  s->scratch_data = upb_gmalloc(s->scratch_size);
+  if (!s->scratch_data) goto err;
+
+  if (!upb_strtable_init(&s->syms, 32, s->arena)) goto err;
+  if (!upb_strtable_init(&s->files, 4, s->arena)) goto err;
+  if (!upb_inttable_init(&s->exts, s->arena)) goto err;
+
+  s->extreg = upb_ExtensionRegistry_New(s->arena);
+  if (!s->extreg) goto err;
+
+  return s;
+
+err:
+  upb_DefPool_Free(s);
+  return NULL;
+}
+
+bool _upb_DefPool_InsertExt(upb_DefPool* s, const upb_MiniTableExtension* ext,
+                            upb_FieldDef* f) {
+  return upb_inttable_insert(&s->exts, (uintptr_t)ext, upb_value_constptr(f),
+                             s->arena);
+}
+
+bool _upb_DefPool_InsertSym(upb_DefPool* s, upb_StringView sym, upb_value v,
+                            upb_Status* status) {
+  // TODO: table should support an operation "tryinsert" to avoid the double
+  // lookup.
+  if (upb_strtable_lookup2(&s->syms, sym.data, sym.size, NULL)) {
+    upb_Status_SetErrorFormat(status, "duplicate symbol '%s'", sym.data);
+    return false;
+  }
+  if (!upb_strtable_insert(&s->syms, sym.data, sym.size, v, s->arena)) {
+    upb_Status_SetErrorMessage(status, "out of memory");
+    return false;
+  }
+  return true;
+}
+
+static const void* _upb_DefPool_Unpack(const upb_DefPool* s, const char* sym,
+                                       size_t size, upb_deftype_t type) {
+  upb_value v;
+  return upb_strtable_lookup2(&s->syms, sym, size, &v)
+             ? _upb_DefType_Unpack(v, type)
+             : NULL;
+}
+
+bool _upb_DefPool_LookupSym(const upb_DefPool* s, const char* sym, size_t size,
+                            upb_value* v) {
+  return upb_strtable_lookup2(&s->syms, sym, size, v);
+}
+
+upb_ExtensionRegistry* _upb_DefPool_ExtReg(const upb_DefPool* s) {
+  return s->extreg;
+}
+
+void** _upb_DefPool_ScratchData(const upb_DefPool* s) {
+  return (void**)&s->scratch_data;
+}
+
+size_t* _upb_DefPool_ScratchSize(const upb_DefPool* s) {
+  return (size_t*)&s->scratch_size;
+}
+
+const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
+                                                    const char* sym) {
+  return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_MSG);
+}
+
+const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
+    const upb_DefPool* s, const char* sym, size_t len) {
+  return _upb_DefPool_Unpack(s, sym, len, UPB_DEFTYPE_MSG);
+}
+
+const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
+                                              const char* sym) {
+  return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUM);
+}
+
+const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
+                                                      const char* sym) {
+  return _upb_DefPool_Unpack(s, sym, strlen(sym), UPB_DEFTYPE_ENUMVAL);
+}
+
+const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
+                                              const char* name) {
+  upb_value v;
+  return upb_strtable_lookup(&s->files, name, &v) ? upb_value_getconstptr(v)
+                                                  : NULL;
+}
+
+const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* 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_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size) {
+  upb_value v;
+  if (!upb_strtable_lookup2(&s->syms, name, size, &v)) return NULL;
+
+  switch (_upb_DefType_Type(v)) {
+    case UPB_DEFTYPE_FIELD:
+      return _upb_DefType_Unpack(v, UPB_DEFTYPE_FIELD);
+    case UPB_DEFTYPE_MSG: {
+      const upb_MessageDef* m = _upb_DefType_Unpack(v, UPB_DEFTYPE_MSG);
+      return _upb_MessageDef_InMessageSet(m)
+                 ? upb_MessageDef_NestedExtension(m, 0)
+                 : NULL;
+    }
+    default:
+      break;
+  }
+
+  return NULL;
+}
+
+const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
+                                                    const char* sym) {
+  return upb_DefPool_FindExtensionByNameWithSize(s, sym, strlen(sym));
+}
+
+const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
+                                                    const char* name) {
+  return _upb_DefPool_Unpack(s, name, strlen(name), UPB_DEFTYPE_SERVICE);
+}
+
+const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size) {
+  return _upb_DefPool_Unpack(s, name, size, UPB_DEFTYPE_SERVICE);
+}
+
+const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
+                                                        const char* name) {
+  upb_value v;
+  // TODO(haberman): non-extension fields and oneofs.
+  if (upb_strtable_lookup(&s->syms, name, &v)) {
+    switch (_upb_DefType_Type(v)) {
+      case UPB_DEFTYPE_EXT: {
+        const upb_FieldDef* f = _upb_DefType_Unpack(v, UPB_DEFTYPE_EXT);
+        return upb_FieldDef_File(f);
+      }
+      case UPB_DEFTYPE_MSG: {
+        const upb_MessageDef* m = _upb_DefType_Unpack(v, UPB_DEFTYPE_MSG);
+        return upb_MessageDef_File(m);
+      }
+      case UPB_DEFTYPE_ENUM: {
+        const upb_EnumDef* e = _upb_DefType_Unpack(v, UPB_DEFTYPE_ENUM);
+        return upb_EnumDef_File(e);
+      }
+      case UPB_DEFTYPE_ENUMVAL: {
+        const upb_EnumValueDef* ev =
+            _upb_DefType_Unpack(v, UPB_DEFTYPE_ENUMVAL);
+        return upb_EnumDef_File(upb_EnumValueDef_Enum(ev));
+      }
+      case UPB_DEFTYPE_SERVICE: {
+        const upb_ServiceDef* service =
+            _upb_DefType_Unpack(v, UPB_DEFTYPE_SERVICE);
+        return upb_ServiceDef_File(service);
+      }
+      default:
+        UPB_UNREACHABLE();
+    }
+  }
+
+  const char* last_dot = strrchr(name, '.');
+  if (last_dot) {
+    const upb_MessageDef* parent =
+        upb_DefPool_FindMessageByNameWithSize(s, name, last_dot - name);
+    if (parent) {
+      const char* shortname = last_dot + 1;
+      if (upb_MessageDef_FindByNameWithSize(parent, shortname,
+                                            strlen(shortname), NULL, NULL)) {
+        return upb_MessageDef_File(parent);
+      }
+    }
+  }
+
+  return NULL;
+}
+
+static void remove_filedef(upb_DefPool* s, upb_FileDef* file) {
+  intptr_t iter = UPB_INTTABLE_BEGIN;
+  upb_StringView key;
+  upb_value val;
+  while (upb_strtable_next2(&s->syms, &key, &val, &iter)) {
+    const upb_FileDef* f;
+    switch (_upb_DefType_Type(val)) {
+      case UPB_DEFTYPE_EXT:
+        f = upb_FieldDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_EXT));
+        break;
+      case UPB_DEFTYPE_MSG:
+        f = upb_MessageDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_MSG));
+        break;
+      case UPB_DEFTYPE_ENUM:
+        f = upb_EnumDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_ENUM));
+        break;
+      case UPB_DEFTYPE_ENUMVAL:
+        f = upb_EnumDef_File(upb_EnumValueDef_Enum(
+            _upb_DefType_Unpack(val, UPB_DEFTYPE_ENUMVAL)));
+        break;
+      case UPB_DEFTYPE_SERVICE:
+        f = upb_ServiceDef_File(_upb_DefType_Unpack(val, UPB_DEFTYPE_SERVICE));
+        break;
+      default:
+        UPB_UNREACHABLE();
+    }
+
+    if (f == file) upb_strtable_removeiter(&s->syms, &iter);
+  }
+}
+
+static const upb_FileDef* _upb_DefPool_AddFile(
+    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
+    const upb_MiniTableFile* layout, upb_Status* status) {
+  const upb_StringView name = google_protobuf_FileDescriptorProto_name(file_proto);
+
+  if (name.size == 0) {
+    upb_Status_SetErrorFormat(status,
+                              "missing name in google_protobuf_FileDescriptorProto");
+    return NULL;
+  }
+
+  // Determine whether we already know about this file.
+  {
+    upb_value v;
+    if (upb_strtable_lookup2(&s->files, name.data, name.size, &v)) {
+      upb_Status_SetErrorFormat(status,
+                                "duplicate file name " UPB_STRINGVIEW_FORMAT,
+                                UPB_STRINGVIEW_ARGS(name));
+      return NULL;
+    }
+  }
+
+  upb_DefBuilder ctx = {
+      .symtab = s,
+      .layout = layout,
+      .msg_count = 0,
+      .enum_count = 0,
+      .ext_count = 0,
+      .status = status,
+      .file = NULL,
+      .arena = upb_Arena_New(),
+      .tmp_arena = upb_Arena_New(),
+  };
+
+  if (UPB_SETJMP(ctx.err)) {
+    UPB_ASSERT(!upb_Status_IsOk(status));
+    if (ctx.file) {
+      remove_filedef(s, ctx.file);
+      ctx.file = NULL;
+    }
+  } else if (!ctx.arena || !ctx.tmp_arena) {
+    _upb_DefBuilder_OomErr(&ctx);
+  } else {
+    _upb_FileDef_Create(&ctx, file_proto);
+    upb_strtable_insert(&s->files, name.data, name.size,
+                        upb_value_constptr(ctx.file), ctx.arena);
+    UPB_ASSERT(upb_Status_IsOk(status));
+    upb_Arena_Fuse(s->arena, ctx.arena);
+  }
+
+  if (ctx.arena) upb_Arena_Free(ctx.arena);
+  if (ctx.tmp_arena) upb_Arena_Free(ctx.tmp_arena);
+  return ctx.file;
+}
+
+const upb_FileDef* upb_DefPool_AddFile(
+    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
+    upb_Status* status) {
+  return _upb_DefPool_AddFile(s, file_proto, NULL, status);
+}
+
+bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
+                                bool rebuild_minitable) {
+  /* 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_DefPool_Init** deps = init->deps;
+  google_protobuf_FileDescriptorProto* file;
+  upb_Arena* arena;
+  upb_Status status;
+
+  upb_Status_Clear(&status);
+
+  if (upb_DefPool_FindFileByName(s, init->filename)) {
+    return true;
+  }
+
+  arena = upb_Arena_New();
+
+  for (; *deps; deps++) {
+    if (!_upb_DefPool_LoadDefInitEx(s, *deps, rebuild_minitable)) goto err;
+  }
+
+  file = google_protobuf_FileDescriptorProto_parse_ex(
+      init->descriptor.data, init->descriptor.size, NULL,
+      kUpb_DecodeOption_AliasString, arena);
+  s->bytes_loaded += init->descriptor.size;
+
+  if (!file) {
+    upb_Status_SetErrorFormat(
+        &status,
+        "Failed to parse compiled-in descriptor for file '%s'. This should "
+        "never happen.",
+        init->filename);
+    goto err;
+  }
+
+  const upb_MiniTableFile* mt = rebuild_minitable ? NULL : init->layout;
+  if (!_upb_DefPool_AddFile(s, file, mt, &status)) {
+    goto err;
+  }
+
+  upb_Arena_Free(arena);
+  return true;
+
+err:
+  fprintf(stderr,
+          "Error loading compiled-in descriptor for file '%s' (this should "
+          "never happen): %s\n",
+          init->filename, upb_Status_ErrorMessage(&status));
+  upb_Arena_Free(arena);
+  return false;
+}
+
+size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s) {
+  return s->bytes_loaded;
+}
+
+upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s) { return s->arena; }
+
+const upb_FieldDef* upb_DefPool_FindExtensionByMiniTable(
+    const upb_DefPool* s, const upb_MiniTableExtension* ext) {
+  upb_value v;
+  bool ok = upb_inttable_lookup(&s->exts, (uintptr_t)ext, &v);
+  UPB_ASSERT(ok);
+  return upb_value_getconstptr(v);
+}
+
+const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
+                                                      const upb_MessageDef* m,
+                                                      int32_t fieldnum) {
+  const upb_MiniTable* t = upb_MessageDef_MiniTable(m);
+  const upb_MiniTableExtension* ext =
+      upb_ExtensionRegistry_Lookup(s->extreg, t, fieldnum);
+  return ext ? upb_DefPool_FindExtensionByMiniTable(s, ext) : NULL;
+}
+
+const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
+    const upb_DefPool* s) {
+  return s->extreg;
+}
+
+const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
+                                                  const upb_MessageDef* m,
+                                                  size_t* count) {
+  size_t n = 0;
+  intptr_t iter = UPB_INTTABLE_BEGIN;
+  uintptr_t key;
+  upb_value val;
+  // This is O(all exts) instead of O(exts for m).  If we need this to be
+  // efficient we may need to make extreg into a two-level table, or have a
+  // second per-message index.
+  while (upb_inttable_next(&s->exts, &key, &val, &iter)) {
+    const upb_FieldDef* f = upb_value_getconstptr(val);
+    if (upb_FieldDef_ContainingType(f) == m) n++;
+  }
+  const upb_FieldDef** exts = malloc(n * sizeof(*exts));
+  iter = UPB_INTTABLE_BEGIN;
+  size_t i = 0;
+  while (upb_inttable_next(&s->exts, &key, &val, &iter)) {
+    const upb_FieldDef* f = upb_value_getconstptr(val);
+    if (upb_FieldDef_ContainingType(f) == m) exts[i++] = f;
+  }
+  *count = n;
+  return exts;
+}
+
+bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init) {
+  return _upb_DefPool_LoadDefInitEx(s, init, false);
+}
+
+
+// Must be last.
+
+upb_deftype_t _upb_DefType_Type(upb_value v) {
+  const uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+  return num & UPB_DEFTYPE_MASK;
+}
+
+upb_value _upb_DefType_Pack(const void* ptr, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)ptr;
+  UPB_ASSERT((num & UPB_DEFTYPE_MASK) == 0);
+  num |= type;
+  return upb_value_constptr((const void*)num);
+}
+
+const void* _upb_DefType_Unpack(upb_value v, upb_deftype_t type) {
+  uintptr_t num = (uintptr_t)upb_value_getconstptr(v);
+  return (num & UPB_DEFTYPE_MASK) == type
+             ? (const void*)(num & ~UPB_DEFTYPE_MASK)
+             : NULL;
+}
+
+
+// Must be last.
+
+bool _upb_DescState_Grow(upb_DescState* d, upb_Arena* a) {
+  const size_t oldbufsize = d->bufsize;
+  const int used = d->ptr - d->buf;
+
+  if (!d->buf) {
+    d->buf = upb_Arena_Malloc(a, d->bufsize);
+    if (!d->buf) return false;
+    d->ptr = d->buf;
+    d->e.end = d->buf + d->bufsize;
+  }
+
+  if (oldbufsize - used < kUpb_MtDataEncoder_MinSize) {
+    d->bufsize *= 2;
+    d->buf = upb_Arena_Realloc(a, d->buf, oldbufsize, d->bufsize);
+    if (!d->buf) return false;
+    d->ptr = d->buf + used;
+    d->e.end = d->buf + d->bufsize;
+  }
+
+  return true;
+}
+
+
+// Must be last.
+
+struct upb_EnumDef {
+  const google_protobuf_EnumOptions* opts;
+  const upb_MiniTableEnum* layout;  // Only for proto2.
+  const upb_FileDef* file;
+  const upb_MessageDef* containing_type;  // Could be merged with "file".
+  const char* full_name;
+  upb_strtable ntoi;
+  upb_inttable iton;
+  const upb_EnumValueDef* values;
+  const upb_EnumReservedRange* res_ranges;
+  const upb_StringView* res_names;
+  int value_count;
+  int res_range_count;
+  int res_name_count;
+  int32_t defaultval;
+  bool is_sorted;  // Whether all of the values are defined in ascending order.
+};
+
+upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i) {
+  return (upb_EnumDef*)&e[i];
+}
+
+// TODO: Maybe implement this on top of a ZCOS instead?
+void _upb_EnumDef_Debug(const upb_EnumDef* e) {
+  fprintf(stderr, "enum %s (%p) {\n", e->full_name, e);
+  fprintf(stderr, " value_count: %d\n", e->value_count);
+  fprintf(stderr, " default:     %d\n", e->defaultval);
+  fprintf(stderr, " is_sorted:   %d\n", e->is_sorted);
+  fprintf(stderr, "}\n");
+}
+
+const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e) {
+  return e->layout;
+}
+
+bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a) {
+  const char* name = upb_EnumValueDef_Name(v);
+  const upb_value val = upb_value_constptr(v);
+  bool ok = upb_strtable_insert(&e->ntoi, name, strlen(name), val, a);
+  if (!ok) return false;
+
+  // Multiple enumerators can have the same number, first one wins.
+  const int number = upb_EnumValueDef_Number(v);
+  if (!upb_inttable_lookup(&e->iton, number, NULL)) {
+    return upb_inttable_insert(&e->iton, number, val, a);
+  }
+  return true;
+}
+
+const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e) {
+  return e->opts;
+}
+
+bool upb_EnumDef_HasOptions(const upb_EnumDef* e) {
+  return e->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_EnumDef_FullName(const upb_EnumDef* e) { return e->full_name; }
+
+const char* upb_EnumDef_Name(const upb_EnumDef* e) {
+  return _upb_DefBuilder_FullToShort(e->full_name);
+}
+
+const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e) { return e->file; }
+
+const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e) {
+  return e->containing_type;
+}
+
+int32_t upb_EnumDef_Default(const upb_EnumDef* e) {
+  UPB_ASSERT(upb_EnumDef_FindValueByNumber(e, e->defaultval));
+  return e->defaultval;
+}
+
+int upb_EnumDef_ReservedRangeCount(const upb_EnumDef* e) {
+  return e->res_range_count;
+}
+
+const upb_EnumReservedRange* upb_EnumDef_ReservedRange(const upb_EnumDef* e,
+                                                       int i) {
+  UPB_ASSERT(0 <= i && i < e->res_range_count);
+  return _upb_EnumReservedRange_At(e->res_ranges, i);
+}
+
+int upb_EnumDef_ReservedNameCount(const upb_EnumDef* e) {
+  return e->res_name_count;
+}
+
+upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i) {
+  UPB_ASSERT(0 <= i && i < e->res_name_count);
+  return e->res_names[i];
+}
+
+int upb_EnumDef_ValueCount(const upb_EnumDef* e) { return e->value_count; }
+
+const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e,
+                                                    const char* name) {
+  return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name));
+}
+
+const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
+    const upb_EnumDef* e, const char* name, size_t size) {
+  upb_value v;
+  return upb_strtable_lookup2(&e->ntoi, name, size, &v)
+             ? upb_value_getconstptr(v)
+             : NULL;
+}
+
+const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e,
+                                                      int32_t num) {
+  upb_value v;
+  return upb_inttable_lookup(&e->iton, num, &v) ? upb_value_getconstptr(v)
+                                                : NULL;
+}
+
+bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num) {
+  // We could use upb_EnumDef_FindValueByNumber(e, num) != NULL, but we expect
+  // this to be faster (especially for small numbers).
+  return upb_MiniTableEnum_CheckValue(e->layout, num);
+}
+
+const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i) {
+  UPB_ASSERT(0 <= i && i < e->value_count);
+  return _upb_EnumValueDef_At(e->values, i);
+}
+
+bool upb_EnumDef_IsClosed(const upb_EnumDef* e) {
+  if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3) return false;
+  return upb_FileDef_Syntax(e->file) == kUpb_Syntax_Proto2;
+}
+
+bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a,
+                                      upb_StringView* out) {
+  upb_DescState s;
+  _upb_DescState_Init(&s);
+
+  const upb_EnumValueDef** sorted = NULL;
+  if (!e->is_sorted) {
+    sorted = _upb_EnumValueDefs_Sorted(e->values, e->value_count, a);
+    if (!sorted) return false;
+  }
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  s.ptr = upb_MtDataEncoder_StartEnum(&s.e, s.ptr);
+
+  // Duplicate values are allowed but we only encode each value once.
+  uint32_t previous = 0;
+
+  for (size_t i = 0; i < e->value_count; i++) {
+    const uint32_t current =
+        upb_EnumValueDef_Number(sorted ? sorted[i] : upb_EnumDef_Value(e, i));
+    if (i != 0 && previous == current) continue;
+
+    if (!_upb_DescState_Grow(&s, a)) return false;
+    s.ptr = upb_MtDataEncoder_PutEnumValue(&s.e, s.ptr, current);
+    previous = current;
+  }
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  s.ptr = upb_MtDataEncoder_EndEnum(&s.e, s.ptr);
+
+  // There will always be room for this '\0' in the encoder buffer because
+  // kUpb_MtDataEncoder_MinSize is overkill for upb_MtDataEncoder_EndEnum().
+  UPB_ASSERT(s.ptr < s.buf + s.bufsize);
+  *s.ptr = '\0';
+
+  out->data = s.buf;
+  out->size = s.ptr - s.buf;
+  return true;
+}
+
+static upb_MiniTableEnum* create_enumlayout(upb_DefBuilder* ctx,
+                                            const upb_EnumDef* e) {
+  upb_StringView sv;
+  bool ok = upb_EnumDef_MiniDescriptorEncode(e, ctx->tmp_arena, &sv);
+  if (!ok) _upb_DefBuilder_Errf(ctx, "OOM while building enum MiniDescriptor");
+
+  upb_Status status;
+  upb_MiniTableEnum* layout =
+      upb_MiniTableEnum_Build(sv.data, sv.size, ctx->arena, &status);
+  if (!layout)
+    _upb_DefBuilder_Errf(ctx, "Error building enum MiniTable: %s", status.msg);
+  return layout;
+}
+
+static upb_StringView* _upb_EnumReservedNames_New(
+    upb_DefBuilder* ctx, int n, const upb_StringView* protos) {
+  upb_StringView* sv = _upb_DefBuilder_Alloc(ctx, sizeof(upb_StringView) * n);
+  for (size_t i = 0; i < n; i++) {
+    sv[i].data =
+        upb_strdup2(protos[i].data, protos[i].size, _upb_DefBuilder_Arena(ctx));
+    sv[i].size = protos[i].size;
+  }
+  return sv;
+}
+
+static void create_enumdef(upb_DefBuilder* ctx, const char* prefix,
+                           const google_protobuf_EnumDescriptorProto* enum_proto,
+                           upb_EnumDef* e) {
+  const google_protobuf_EnumValueDescriptorProto* const* values;
+  const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* res_ranges;
+  const upb_StringView* res_names;
+  upb_StringView name;
+  size_t n_value, n_res_range, n_res_name;
+
+  // Must happen before _upb_DefBuilder_Add()
+  e->file = _upb_DefBuilder_File(ctx);
+
+  name = google_protobuf_EnumDescriptorProto_name(enum_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+
+  e->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  _upb_DefBuilder_Add(ctx, e->full_name,
+                      _upb_DefType_Pack(e, UPB_DEFTYPE_ENUM));
+
+  values = google_protobuf_EnumDescriptorProto_value(enum_proto, &n_value);
+
+  bool ok = upb_strtable_init(&e->ntoi, n_value, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_inttable_init(&e->iton, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  e->defaultval = 0;
+  e->value_count = n_value;
+  e->values =
+      _upb_EnumValueDefs_New(ctx, prefix, n_value, values, e, &e->is_sorted);
+
+  if (n_value == 0) {
+    _upb_DefBuilder_Errf(ctx, "enums must contain at least one value (%s)",
+                         e->full_name);
+  }
+
+  res_ranges =
+      google_protobuf_EnumDescriptorProto_reserved_range(enum_proto, &n_res_range);
+  e->res_range_count = n_res_range;
+  e->res_ranges = _upb_EnumReservedRanges_New(ctx, n_res_range, res_ranges, e);
+
+  res_names = google_protobuf_EnumDescriptorProto_reserved_name(enum_proto, &n_res_name);
+  e->res_name_count = n_res_name;
+  e->res_names = _upb_EnumReservedNames_New(ctx, n_res_name, res_names);
+
+  UPB_DEF_SET_OPTIONS(e->opts, EnumDescriptorProto, EnumOptions, enum_proto);
+
+  upb_inttable_compact(&e->iton, ctx->arena);
+
+  if (upb_FileDef_Syntax(e->file) == kUpb_Syntax_Proto2) {
+    if (ctx->layout) {
+      UPB_ASSERT(ctx->enum_count < ctx->layout->enum_count);
+      e->layout = ctx->layout->enums[ctx->enum_count++];
+    } else {
+      e->layout = create_enumlayout(ctx, e);
+    }
+  } else {
+    e->layout = NULL;
+  }
+}
+
+upb_EnumDef* _upb_EnumDefs_New(upb_DefBuilder* ctx, int n,
+                               const google_protobuf_EnumDescriptorProto* const* protos,
+                               const upb_MessageDef* containing_type) {
+  _upb_DefType_CheckPadding(sizeof(upb_EnumDef));
+
+  // If a containing type is defined then get the full name from that.
+  // Otherwise use the package name from the file def.
+  const char* name = containing_type ? upb_MessageDef_FullName(containing_type)
+                                     : _upb_FileDef_RawPackage(ctx->file);
+
+  upb_EnumDef* e = _upb_DefBuilder_Alloc(ctx, sizeof(upb_EnumDef) * n);
+  for (size_t i = 0; i < n; i++) {
+    create_enumdef(ctx, name, protos[i], &e[i]);
+    e[i].containing_type = containing_type;
+  }
+  return e;
+}
+
+// #include "upb/reflection/extension_range_internal.h"
+// #include "upb/reflection/message_def.h"
+
+// Must be last.
+
+struct upb_EnumReservedRange {
+  int32_t start;
+  int32_t end;
+};
+
+upb_EnumReservedRange* _upb_EnumReservedRange_At(const upb_EnumReservedRange* r,
+                                                 int i) {
+  return (upb_EnumReservedRange*)&r[i];
+}
+
+int32_t upb_EnumReservedRange_Start(const upb_EnumReservedRange* r) {
+  return r->start;
+}
+int32_t upb_EnumReservedRange_End(const upb_EnumReservedRange* r) {
+  return r->end;
+}
+
+upb_EnumReservedRange* _upb_EnumReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* protos,
+    const upb_EnumDef* e) {
+  upb_EnumReservedRange* r =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_EnumReservedRange) * n);
+
+  for (int i = 0; i < n; i++) {
+    const int32_t start =
+        google_protobuf_EnumDescriptorProto_EnumReservedRange_start(protos[i]);
+    const int32_t end =
+        google_protobuf_EnumDescriptorProto_EnumReservedRange_end(protos[i]);
+    const int32_t max = kUpb_MaxFieldNumber + 1;
+
+    // A full validation would also check that each range is disjoint, and that
+    // none of the fields overlap with the extension ranges, but we are just
+    // sanity checking here.
+
+    // Note: Not a typo! Unlike extension ranges and message reserved ranges,
+    // the end value of an enum reserved range is *inclusive*!
+    if (start < 1 || end < start || end > max) {
+      _upb_DefBuilder_Errf(ctx, "Reserved range (%d, %d) is invalid, enum=%s\n",
+                           (int)start, (int)end, upb_EnumDef_FullName(e));
+    }
+
+    r[i].start = start;
+    r[i].end = end;
+  }
+
+  return r;
+}
+
+
+// Must be last.
+
+struct upb_EnumValueDef {
+  const google_protobuf_EnumValueOptions* opts;
+  const upb_EnumDef* parent;
+  const char* full_name;
+  int32_t number;
+};
+
+upb_EnumValueDef* _upb_EnumValueDef_At(const upb_EnumValueDef* v, int i) {
+  return (upb_EnumValueDef*)&v[i];
+}
+
+static int _upb_EnumValueDef_Compare(const void* p1, const void* p2) {
+  const uint32_t v1 = (*(const upb_EnumValueDef**)p1)->number;
+  const uint32_t v2 = (*(const upb_EnumValueDef**)p2)->number;
+  return (v1 < v2) ? -1 : (v1 > v2);
+}
+
+const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v,
+                                                   int n, upb_Arena* a) {
+  // TODO: Try to replace this arena alloc with a persistent scratch buffer.
+  upb_EnumValueDef** out =
+      (upb_EnumValueDef**)upb_Arena_Malloc(a, n * sizeof(void*));
+  if (!out) return NULL;
+
+  for (int i = 0; i < n; i++) {
+    out[i] = (upb_EnumValueDef*)&v[i];
+  }
+  qsort(out, n, sizeof(void*), _upb_EnumValueDef_Compare);
+
+  return (const upb_EnumValueDef**)out;
+}
+
+const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
+    const upb_EnumValueDef* v) {
+  return v->opts;
+}
+
+bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v) {
+  return v->opts != (void*)kUpbDefOptDefault;
+}
+
+const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v) {
+  return v->parent;
+}
+
+const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v) {
+  return v->full_name;
+}
+
+const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v) {
+  return _upb_DefBuilder_FullToShort(v->full_name);
+}
+
+int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v) { return v->number; }
+
+uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v) {
+  // Compute index in our parent's array.
+  return v - upb_EnumDef_Value(v->parent, 0);
+}
+
+static void create_enumvaldef(upb_DefBuilder* ctx, const char* prefix,
+                              const google_protobuf_EnumValueDescriptorProto* val_proto,
+                              upb_EnumDef* e, upb_EnumValueDef* v) {
+  upb_StringView name = google_protobuf_EnumValueDescriptorProto_name(val_proto);
+
+  v->parent = e;  // Must happen prior to _upb_DefBuilder_Add()
+  v->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  v->number = google_protobuf_EnumValueDescriptorProto_number(val_proto);
+  _upb_DefBuilder_Add(ctx, v->full_name,
+                      _upb_DefType_Pack(v, UPB_DEFTYPE_ENUMVAL));
+
+  UPB_DEF_SET_OPTIONS(v->opts, EnumValueDescriptorProto, EnumValueOptions,
+                      val_proto);
+
+  bool ok = _upb_EnumDef_Insert(e, v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+// Allocate and initialize an array of |n| enum value defs owned by |e|.
+upb_EnumValueDef* _upb_EnumValueDefs_New(
+    upb_DefBuilder* ctx, const char* prefix, int n,
+    const google_protobuf_EnumValueDescriptorProto* const* protos, upb_EnumDef* e,
+    bool* is_sorted) {
+  _upb_DefType_CheckPadding(sizeof(upb_EnumValueDef));
+
+  upb_EnumValueDef* v =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_EnumValueDef) * n);
+
+  *is_sorted = true;
+  uint32_t previous = 0;
+  for (size_t i = 0; i < n; i++) {
+    create_enumvaldef(ctx, prefix, protos[i], e, &v[i]);
+
+    const uint32_t current = v[i].number;
+    if (previous > current) *is_sorted = false;
+    previous = current;
+  }
+
+  if (upb_FileDef_Syntax(ctx->file) == kUpb_Syntax_Proto3 && n > 0 &&
+      v[0].number != 0) {
+    _upb_DefBuilder_Errf(ctx,
+                         "for proto3, the first enum value must be zero (%s)",
+                         upb_EnumDef_FullName(e));
+  }
+
+  return v;
+}
+
+
+// Must be last.
+
+struct upb_ExtensionRange {
+  const google_protobuf_ExtensionRangeOptions* opts;
+  int32_t start;
+  int32_t end;
+};
+
+upb_ExtensionRange* _upb_ExtensionRange_At(const upb_ExtensionRange* r, int i) {
+  return (upb_ExtensionRange*)&r[i];
+}
+
+const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
+    const upb_ExtensionRange* r) {
+  return r->opts;
+}
+
+bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r) {
+  return r->opts != (void*)kUpbDefOptDefault;
+}
+
+int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r) {
+  return r->start;
+}
+
+int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r) { return r->end; }
+
+upb_ExtensionRange* _upb_ExtensionRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ExtensionRange* const* protos,
+    const upb_MessageDef* m) {
+  upb_ExtensionRange* r =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_ExtensionRange) * n);
+
+  for (int i = 0; i < n; i++) {
+    const int32_t start =
+        google_protobuf_DescriptorProto_ExtensionRange_start(protos[i]);
+    const int32_t end = google_protobuf_DescriptorProto_ExtensionRange_end(protos[i]);
+    const int32_t max =
+        google_protobuf_MessageOptions_message_set_wire_format(upb_MessageDef_Options(m))
+            ? INT32_MAX
+            : kUpb_MaxFieldNumber + 1;
+
+    // A full validation would also check that each range is disjoint, and that
+    // none of the fields overlap with the extension ranges, but we are just
+    // sanity checking here.
+    if (start < 1 || end <= start || end > max) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Extension range (%d, %d) is invalid, message=%s\n",
+                           (int)start, (int)end, upb_MessageDef_FullName(m));
+    }
+
+    r[i].start = start;
+    r[i].end = end;
+    UPB_DEF_SET_OPTIONS(r[i].opts, DescriptorProto_ExtensionRange,
+                        ExtensionRangeOptions, protos[i]);
+  }
+
+  return r;
+}
+
+#include <ctype.h>
+#include <errno.h>
+
+
+// Must be last.
+
+#define UPB_FIELD_TYPE_UNSPECIFIED 0
+
+typedef struct {
+  size_t len;
+  char str[1];  // Null-terminated string data follows.
+} str_t;
+
+struct upb_FieldDef {
+  const google_protobuf_FieldOptions* opts;
+  const upb_FileDef* file;
+  const upb_MessageDef* 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;
+    void* msg;  // Always NULL.
+  } defaultval;
+  union {
+    const upb_OneofDef* oneof;
+    const upb_MessageDef* extension_scope;
+  } scope;
+  union {
+    const upb_MessageDef* msgdef;
+    const upb_EnumDef* enumdef;
+    const google_protobuf_FieldDescriptorProto* unresolved;
+  } sub;
+  uint32_t number_;
+  uint16_t index_;
+  uint16_t layout_index;  // Index into msgdef->layout->fields or file->exts
+  bool has_default;
+  bool is_extension_;
+  bool is_packed_;
+  bool proto3_optional_;
+  bool has_json_name_;
+  upb_FieldType type_;
+  upb_Label label_;
+#if UINTPTR_MAX == 0xffffffff
+  uint32_t padding;  // Increase size to a multiple of 8.
+#endif
+};
+
+upb_FieldDef* _upb_FieldDef_At(const upb_FieldDef* f, int i) {
+  return (upb_FieldDef*)&f[i];
+}
+
+const google_protobuf_FieldOptions* upb_FieldDef_Options(const upb_FieldDef* f) {
+  return f->opts;
+}
+
+bool upb_FieldDef_HasOptions(const upb_FieldDef* f) {
+  return f->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_FieldDef_FullName(const upb_FieldDef* f) {
+  return f->full_name;
+}
+
+upb_CType upb_FieldDef_CType(const upb_FieldDef* f) {
+  switch (f->type_) {
+    case kUpb_FieldType_Double:
+      return kUpb_CType_Double;
+    case kUpb_FieldType_Float:
+      return kUpb_CType_Float;
+    case kUpb_FieldType_Int64:
+    case kUpb_FieldType_SInt64:
+    case kUpb_FieldType_SFixed64:
+      return kUpb_CType_Int64;
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_SFixed32:
+    case kUpb_FieldType_SInt32:
+      return kUpb_CType_Int32;
+    case kUpb_FieldType_UInt64:
+    case kUpb_FieldType_Fixed64:
+      return kUpb_CType_UInt64;
+    case kUpb_FieldType_UInt32:
+    case kUpb_FieldType_Fixed32:
+      return kUpb_CType_UInt32;
+    case kUpb_FieldType_Enum:
+      return kUpb_CType_Enum;
+    case kUpb_FieldType_Bool:
+      return kUpb_CType_Bool;
+    case kUpb_FieldType_String:
+      return kUpb_CType_String;
+    case kUpb_FieldType_Bytes:
+      return kUpb_CType_Bytes;
+    case kUpb_FieldType_Group:
+    case kUpb_FieldType_Message:
+      return kUpb_CType_Message;
+  }
+  UPB_UNREACHABLE();
+}
+
+upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f) { return f->type_; }
+
+uint32_t upb_FieldDef_Index(const upb_FieldDef* f) { return f->index_; }
+
+upb_Label 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_IsPacked(const upb_FieldDef* f) { return f->is_packed_; }
+
+const char* upb_FieldDef_Name(const upb_FieldDef* f) {
+  return _upb_DefBuilder_FullToShort(f->full_name);
+}
+
+const char* upb_FieldDef_JsonName(const upb_FieldDef* f) {
+  return f->json_name;
+}
+
+bool upb_FieldDef_HasJsonName(const upb_FieldDef* f) {
+  return f->has_json_name_;
+}
+
+const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f) { return f->file; }
+
+const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f) {
+  return f->msgdef;
+}
+
+const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f) {
+  return f->is_extension_ ? f->scope.extension_scope : NULL;
+}
+
+const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f) {
+  return f->is_extension_ ? NULL : f->scope.oneof;
+}
+
+const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f) {
+  const upb_OneofDef* oneof = upb_FieldDef_ContainingOneof(f);
+  if (!oneof || upb_OneofDef_IsSynthetic(oneof)) return NULL;
+  return oneof;
+}
+
+upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f) {
+  upb_MessageValue ret;
+
+  if (upb_FieldDef_IsRepeated(f) || upb_FieldDef_IsSubMessage(f)) {
+    return (upb_MessageValue){.msg_val = NULL};
+  }
+
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_Bool:
+      return (upb_MessageValue){.bool_val = f->defaultval.boolean};
+    case kUpb_CType_Int64:
+      return (upb_MessageValue){.int64_val = f->defaultval.sint};
+    case kUpb_CType_UInt64:
+      return (upb_MessageValue){.uint64_val = f->defaultval.uint};
+    case kUpb_CType_Enum:
+    case kUpb_CType_Int32:
+      return (upb_MessageValue){.int32_val = (int32_t)f->defaultval.sint};
+    case kUpb_CType_UInt32:
+      return (upb_MessageValue){.uint32_val = (uint32_t)f->defaultval.uint};
+    case kUpb_CType_Float:
+      return (upb_MessageValue){.float_val = f->defaultval.flt};
+    case kUpb_CType_Double:
+      return (upb_MessageValue){.double_val = f->defaultval.dbl};
+    case kUpb_CType_String:
+    case kUpb_CType_Bytes: {
+      str_t* str = f->defaultval.str;
+      if (str) {
+        return (upb_MessageValue){
+            .str_val = (upb_StringView){.data = str->str, .size = str->len}};
+      } else {
+        return (upb_MessageValue){
+            .str_val = (upb_StringView){.data = NULL, .size = 0}};
+      }
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  return ret;
+}
+
+const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_Message ? f->sub.msgdef : NULL;
+}
+
+const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_Enum ? f->sub.enumdef : NULL;
+}
+
+const upb_MiniTableField* upb_FieldDef_MiniTable(const upb_FieldDef* f) {
+  if (upb_FieldDef_IsExtension(f)) {
+    const upb_FileDef* file = upb_FieldDef_File(f);
+    return (upb_MiniTableField*)_upb_FileDef_ExtensionMiniTable(
+        file, f->layout_index);
+  } else {
+    const upb_MiniTable* layout = upb_MessageDef_MiniTable(f->msgdef);
+    return &layout->fields[f->layout_index];
+  }
+}
+
+const upb_MiniTableExtension* _upb_FieldDef_ExtensionMiniTable(
+    const upb_FieldDef* f) {
+  UPB_ASSERT(upb_FieldDef_IsExtension(f));
+  const upb_FileDef* file = upb_FieldDef_File(f);
+  return _upb_FileDef_ExtensionMiniTable(file, f->layout_index);
+}
+
+bool _upb_FieldDef_IsClosedEnum(const upb_FieldDef* f) {
+  if (UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3) return false;
+  if (f->type_ != kUpb_FieldType_Enum) return false;
+
+  // TODO: Maybe make is_proto2 a bool at creation?
+  const upb_FileDef* file = upb_EnumDef_File(f->sub.enumdef);
+  return upb_FileDef_Syntax(file) == kUpb_Syntax_Proto2;
+}
+
+bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f) {
+  return f->proto3_optional_;
+}
+
+int _upb_FieldDef_LayoutIndex(const upb_FieldDef* f) { return f->layout_index; }
+
+uint64_t _upb_FieldDef_Modifiers(const upb_FieldDef* f) {
+  uint64_t out = f->is_packed_ ? kUpb_FieldModifier_IsPacked : 0;
+
+  switch (f->label_) {
+    case kUpb_Label_Optional:
+      if (!upb_FieldDef_HasPresence(f)) {
+        out |= kUpb_FieldModifier_IsProto3Singular;
+      }
+      break;
+    case kUpb_Label_Repeated:
+      out |= kUpb_FieldModifier_IsRepeated;
+      break;
+    case kUpb_Label_Required:
+      out |= kUpb_FieldModifier_IsRequired;
+      break;
+  }
+
+  if (_upb_FieldDef_IsClosedEnum(f)) {
+    out |= kUpb_FieldModifier_IsClosedEnum;
+  }
+  return out;
+}
+
+bool upb_FieldDef_HasDefault(const upb_FieldDef* f) { return f->has_default; }
+
+bool upb_FieldDef_HasPresence(const upb_FieldDef* f) {
+  if (upb_FieldDef_IsRepeated(f)) return false;
+  const upb_FileDef* file = upb_FieldDef_File(f);
+  return upb_FieldDef_IsSubMessage(f) || upb_FieldDef_ContainingOneof(f) ||
+         upb_FileDef_Syntax(file) == kUpb_Syntax_Proto2;
+}
+
+bool upb_FieldDef_HasSubDef(const upb_FieldDef* f) {
+  return upb_FieldDef_IsSubMessage(f) ||
+         upb_FieldDef_CType(f) == kUpb_CType_Enum;
+}
+
+bool upb_FieldDef_IsMap(const upb_FieldDef* f) {
+  return upb_FieldDef_IsRepeated(f) && upb_FieldDef_IsSubMessage(f) &&
+         upb_MessageDef_IsMapEntry(upb_FieldDef_MessageSubDef(f));
+}
+
+bool upb_FieldDef_IsOptional(const upb_FieldDef* f) {
+  return upb_FieldDef_Label(f) == kUpb_Label_Optional;
+}
+
+bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f) {
+  return !upb_FieldDef_IsString(f) && !upb_FieldDef_IsSubMessage(f);
+}
+
+bool upb_FieldDef_IsRepeated(const upb_FieldDef* f) {
+  return upb_FieldDef_Label(f) == kUpb_Label_Repeated;
+}
+
+bool upb_FieldDef_IsRequired(const upb_FieldDef* f) {
+  return upb_FieldDef_Label(f) == kUpb_Label_Required;
+}
+
+bool upb_FieldDef_IsString(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_String ||
+         upb_FieldDef_CType(f) == kUpb_CType_Bytes;
+}
+
+bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f) {
+  return upb_FieldDef_CType(f) == kUpb_CType_Message;
+}
+
+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);
+}
+
+static bool streql2(const char* a, size_t n, const char* b) {
+  return n == strlen(b) && memcmp(a, b, n) == 0;
+}
+
+// Implement the transformation as described in the spec:
+//   1. upper case all letters after an underscore.
+//   2. remove all underscores.
+static char* make_json_name(const char* name, size_t size, upb_Arena* a) {
+  char* out = upb_Arena_Malloc(a, size + 1);  // +1 is to add a trailing '\0'
+  if (out == NULL) return NULL;
+
+  bool ucase_next = false;
+  char* des = out;
+  for (size_t i = 0; i < size; i++) {
+    if (name[i] == '_') {
+      ucase_next = true;
+    } else {
+      *des++ = ucase_next ? toupper(name[i]) : name[i];
+      ucase_next = false;
+    }
+  }
+  *des++ = '\0';
+  return out;
+}
+
+static str_t* newstr(upb_DefBuilder* ctx, const char* data, size_t len) {
+  str_t* ret = _upb_DefBuilder_Alloc(ctx, sizeof(*ret) + len);
+  if (!ret) _upb_DefBuilder_OomErr(ctx);
+  ret->len = len;
+  if (len) memcpy(ret->str, data, len);
+  ret->str[len] = '\0';
+  return ret;
+}
+
+static str_t* unescape(upb_DefBuilder* ctx, const upb_FieldDef* f,
+                       const char* data, size_t len) {
+  // Size here is an upper bound; escape sequences could ultimately shrink it.
+  str_t* ret = _upb_DefBuilder_Alloc(ctx, sizeof(*ret) + len);
+  char* dst = &ret->str[0];
+  const char* src = data;
+  const char* end = data + len;
+
+  while (src < end) {
+    if (*src == '\\') {
+      src++;
+      *dst++ = _upb_DefBuilder_ParseEscape(ctx, f, &src, end);
+    } else {
+      *dst++ = *src++;
+    }
+  }
+
+  ret->len = dst - &ret->str[0];
+  return ret;
+}
+
+static void parse_default(upb_DefBuilder* ctx, const char* str, size_t len,
+                          upb_FieldDef* f) {
+  char* end;
+  char nullz[64];
+  errno = 0;
+
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_Int32:
+    case kUpb_CType_Int64:
+    case kUpb_CType_UInt32:
+    case kUpb_CType_UInt64:
+    case kUpb_CType_Double:
+    case kUpb_CType_Float:
+      // Standard C number parsing functions expect null-terminated strings.
+      if (len >= sizeof(nullz) - 1) {
+        _upb_DefBuilder_Errf(ctx, "Default too long: %.*s", (int)len, str);
+      }
+      memcpy(nullz, str, len);
+      nullz[len] = '\0';
+      str = nullz;
+      break;
+    default:
+      break;
+  }
+
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_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 kUpb_CType_Enum: {
+      const upb_EnumDef* e = f->sub.enumdef;
+      const upb_EnumValueDef* ev =
+          upb_EnumDef_FindValueByNameWithSize(e, str, len);
+      if (!ev) {
+        goto invalid;
+      }
+      f->defaultval.sint = upb_EnumValueDef_Number(ev);
+      break;
+    }
+    case kUpb_CType_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 kUpb_CType_UInt32: {
+      unsigned long val = strtoul(str, &end, 0);
+      if (val > UINT32_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case kUpb_CType_UInt64: {
+      unsigned long long val = strtoull(str, &end, 0);
+      if (val > UINT64_MAX || errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.uint = val;
+      break;
+    }
+    case kUpb_CType_Double: {
+      double val = strtod(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.dbl = val;
+      break;
+    }
+    case kUpb_CType_Float: {
+      float val = strtof(str, &end);
+      if (errno == ERANGE || *end) {
+        goto invalid;
+      }
+      f->defaultval.flt = val;
+      break;
+    }
+    case kUpb_CType_Bool: {
+      if (streql2(str, len, "false")) {
+        f->defaultval.boolean = false;
+      } else if (streql2(str, len, "true")) {
+        f->defaultval.boolean = true;
+      } else {
+        goto invalid;
+      }
+      break;
+    }
+    case kUpb_CType_String:
+      f->defaultval.str = newstr(ctx, str, len);
+      break;
+    case kUpb_CType_Bytes:
+      f->defaultval.str = unescape(ctx, f, str, len);
+      break;
+    case kUpb_CType_Message:
+      /* Should not have a default value. */
+      _upb_DefBuilder_Errf(ctx, "Message should not have a default (%s)",
+                           upb_FieldDef_FullName(f));
+  }
+
+  return;
+
+invalid:
+  _upb_DefBuilder_Errf(ctx, "Invalid default '%.*s' for field %s of type %d",
+                       (int)len, str, upb_FieldDef_FullName(f),
+                       (int)upb_FieldDef_Type(f));
+}
+
+static void set_default_default(upb_DefBuilder* ctx, upb_FieldDef* f) {
+  switch (upb_FieldDef_CType(f)) {
+    case kUpb_CType_Int32:
+    case kUpb_CType_Int64:
+      f->defaultval.sint = 0;
+      break;
+    case kUpb_CType_UInt64:
+    case kUpb_CType_UInt32:
+      f->defaultval.uint = 0;
+      break;
+    case kUpb_CType_Double:
+    case kUpb_CType_Float:
+      f->defaultval.dbl = 0;
+      break;
+    case kUpb_CType_String:
+    case kUpb_CType_Bytes:
+      f->defaultval.str = newstr(ctx, NULL, 0);
+      break;
+    case kUpb_CType_Bool:
+      f->defaultval.boolean = false;
+      break;
+    case kUpb_CType_Enum: {
+      const upb_EnumValueDef* v = upb_EnumDef_Value(f->sub.enumdef, 0);
+      f->defaultval.sint = upb_EnumValueDef_Number(v);
+      break;
+    }
+    case kUpb_CType_Message:
+      break;
+  }
+}
+
+static void _upb_FieldDef_Create(upb_DefBuilder* ctx, const char* prefix,
+                                 const google_protobuf_FieldDescriptorProto* field_proto,
+                                 upb_MessageDef* m, upb_FieldDef* f) {
+  // Must happen before _upb_DefBuilder_Add()
+  f->file = _upb_DefBuilder_File(ctx);
+
+  if (!google_protobuf_FieldDescriptorProto_has_name(field_proto)) {
+    _upb_DefBuilder_Errf(ctx, "field has no name");
+  }
+
+  const upb_StringView name = google_protobuf_FieldDescriptorProto_name(field_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+
+  f->has_json_name_ = google_protobuf_FieldDescriptorProto_has_json_name(field_proto);
+  if (f->has_json_name_) {
+    const upb_StringView sv =
+        google_protobuf_FieldDescriptorProto_json_name(field_proto);
+    f->json_name = upb_strdup2(sv.data, sv.size, ctx->arena);
+  } else {
+    f->json_name = make_json_name(name.data, name.size, ctx->arena);
+  }
+  if (!f->json_name) _upb_DefBuilder_OomErr(ctx);
+
+  f->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  f->label_ = (int)google_protobuf_FieldDescriptorProto_label(field_proto);
+  f->number_ = google_protobuf_FieldDescriptorProto_number(field_proto);
+  f->proto3_optional_ =
+      google_protobuf_FieldDescriptorProto_proto3_optional(field_proto);
+  f->msgdef = m;
+  f->scope.oneof = NULL;
+
+  const bool has_type = google_protobuf_FieldDescriptorProto_has_type(field_proto);
+  const bool has_type_name =
+      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
+
+  f->type_ = (int)google_protobuf_FieldDescriptorProto_type(field_proto);
+
+  if (has_type) {
+    switch (f->type_) {
+      case kUpb_FieldType_Message:
+      case kUpb_FieldType_Group:
+      case kUpb_FieldType_Enum:
+        if (!has_type_name) {
+          _upb_DefBuilder_Errf(ctx, "field of type %d requires type name (%s)",
+                               (int)f->type_, f->full_name);
+        }
+        break;
+      default:
+        if (has_type_name) {
+          _upb_DefBuilder_Errf(
+              ctx, "invalid type for field with type_name set (%s, %d)",
+              f->full_name, (int)f->type_);
+        }
+    }
+  } else if (has_type_name) {
+    f->type_ =
+        UPB_FIELD_TYPE_UNSPECIFIED;  // We'll fill this in in resolve_fielddef()
+  }
+
+  if (f->type_ < kUpb_FieldType_Double || f->type_ > kUpb_FieldType_SInt64) {
+    _upb_DefBuilder_Errf(ctx, "invalid type for field %s (%d)", f->full_name,
+                         f->type_);
+  }
+
+  if (f->label_ < kUpb_Label_Optional || f->label_ > kUpb_Label_Repeated) {
+    _upb_DefBuilder_Errf(ctx, "invalid label for field %s (%d)", f->full_name,
+                         f->label_);
+  }
+
+  /* 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_ == kUpb_Label_Required &&
+      upb_FileDef_Syntax(f->file) == kUpb_Syntax_Proto3) {
+    _upb_DefBuilder_Errf(ctx, "proto3 fields cannot be required (%s)",
+                         f->full_name);
+  }
+
+  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    uint32_t oneof_index = google_protobuf_FieldDescriptorProto_oneof_index(field_proto);
+
+    if (upb_FieldDef_Label(f) != kUpb_Label_Optional) {
+      _upb_DefBuilder_Errf(ctx, "fields in oneof must have OPTIONAL label (%s)",
+                           f->full_name);
+    }
+
+    if (!m) {
+      _upb_DefBuilder_Errf(ctx, "oneof field (%s) has no containing msg",
+                           f->full_name);
+    }
+
+    if (oneof_index >= upb_MessageDef_OneofCount(m)) {
+      _upb_DefBuilder_Errf(ctx, "oneof_index out of range (%s)", f->full_name);
+    }
+
+    upb_OneofDef* oneof = (upb_OneofDef*)upb_MessageDef_Oneof(m, oneof_index);
+    f->scope.oneof = oneof;
+
+    bool ok = _upb_OneofDef_Insert(oneof, f, name.data, name.size, ctx->arena);
+    if (!ok) _upb_DefBuilder_OomErr(ctx);
+  }
+
+  UPB_DEF_SET_OPTIONS(f->opts, FieldDescriptorProto, FieldOptions, field_proto);
+
+  if (google_protobuf_FieldOptions_has_packed(f->opts)) {
+    f->is_packed_ = google_protobuf_FieldOptions_packed(f->opts);
+  } else {
+    // Repeated fields default to packed for proto3 only.
+    f->is_packed_ = upb_FieldDef_IsPrimitive(f) &&
+                    f->label_ == kUpb_Label_Repeated &&
+                    upb_FileDef_Syntax(f->file) == kUpb_Syntax_Proto3;
+  }
+}
+
+static void _upb_FieldDef_CreateExt(
+    upb_DefBuilder* ctx, const char* prefix,
+    const google_protobuf_FieldDescriptorProto* field_proto, upb_MessageDef* m,
+    upb_FieldDef* f) {
+  _upb_FieldDef_Create(ctx, prefix, field_proto, m, f);
+  f->is_extension_ = true;
+
+  if (google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    _upb_DefBuilder_Errf(ctx, "oneof_index provided for extension field (%s)",
+                         f->full_name);
+  }
+
+  f->scope.extension_scope = m;
+  _upb_DefBuilder_Add(ctx, f->full_name, _upb_DefType_Pack(f, UPB_DEFTYPE_EXT));
+  f->layout_index = ctx->ext_count++;
+
+  if (ctx->layout) {
+    UPB_ASSERT(_upb_FieldDef_ExtensionMiniTable(f)->field.number == f->number_);
+  }
+}
+
+static void _upb_FieldDef_CreateNotExt(
+    upb_DefBuilder* ctx, const char* prefix,
+    const google_protobuf_FieldDescriptorProto* field_proto, upb_MessageDef* m,
+    upb_FieldDef* f) {
+  _upb_FieldDef_Create(ctx, prefix, field_proto, m, f);
+  f->is_extension_ = false;
+
+  if (!google_protobuf_FieldDescriptorProto_has_oneof_index(field_proto)) {
+    if (f->proto3_optional_) {
+      _upb_DefBuilder_Errf(
+          ctx,
+          "non-extension field (%s) with proto3_optional was not in a oneof",
+          f->full_name);
+    }
+  }
+
+  _upb_MessageDef_InsertField(ctx, m, f);
+
+  if (!ctx->layout) return;
+
+  const upb_MiniTable* mt = upb_MessageDef_MiniTable(m);
+  const upb_MiniTableField* fields = mt->fields;
+  for (int i = 0; i < mt->field_count; i++) {
+    if (fields[i].number == f->number_) {
+      f->layout_index = i;
+      return;
+    }
+  }
+
+  UPB_ASSERT(false);  // It should be impossible to reach this point.
+}
+
+upb_FieldDef* _upb_FieldDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_FieldDescriptorProto* const* protos, const char* prefix,
+    upb_MessageDef* m, bool* is_sorted) {
+  _upb_DefType_CheckPadding(sizeof(upb_FieldDef));
+  upb_FieldDef* defs =
+      (upb_FieldDef*)_upb_DefBuilder_Alloc(ctx, sizeof(upb_FieldDef) * n);
+
+  // If we are creating extensions then is_sorted will be NULL.
+  // If we are not creating extensions then is_sorted will be non-NULL.
+  if (is_sorted) {
+    uint32_t previous = 0;
+    for (int i = 0; i < n; i++) {
+      upb_FieldDef* f = &defs[i];
+
+      _upb_FieldDef_CreateNotExt(ctx, prefix, protos[i], m, f);
+      f->index_ = i;
+      if (!ctx->layout) f->layout_index = i;
+
+      const uint32_t current = f->number_;
+      if (previous > current) *is_sorted = false;
+      previous = current;
+    }
+  } else {
+    for (int i = 0; i < n; i++) {
+      upb_FieldDef* f = &defs[i];
+
+      _upb_FieldDef_CreateExt(ctx, prefix, protos[i], m, f);
+      f->index_ = i;
+    }
+  }
+
+  return defs;
+}
+
+static void resolve_subdef(upb_DefBuilder* ctx, const char* prefix,
+                           upb_FieldDef* f) {
+  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
+  upb_StringView name =
+      google_protobuf_FieldDescriptorProto_type_name(field_proto);
+  bool has_name =
+      google_protobuf_FieldDescriptorProto_has_type_name(field_proto);
+  switch ((int)f->type_) {
+    case UPB_FIELD_TYPE_UNSPECIFIED: {
+      // Type was not specified and must be inferred.
+      UPB_ASSERT(has_name);
+      upb_deftype_t type;
+      const void* def =
+          _upb_DefBuilder_ResolveAny(ctx, f->full_name, prefix, name, &type);
+      switch (type) {
+        case UPB_DEFTYPE_ENUM:
+          f->sub.enumdef = def;
+          f->type_ = kUpb_FieldType_Enum;
+          break;
+        case UPB_DEFTYPE_MSG:
+          f->sub.msgdef = def;
+          f->type_ = kUpb_FieldType_Message;  // It appears there is no way of
+                                              // this being a group.
+          break;
+        default:
+          _upb_DefBuilder_Errf(ctx, "Couldn't resolve type name for field %s",
+                               f->full_name);
+      }
+    }
+    case kUpb_FieldType_Message:
+    case kUpb_FieldType_Group:
+      UPB_ASSERT(has_name);
+      f->sub.msgdef = _upb_DefBuilder_Resolve(ctx, f->full_name, prefix, name,
+                                              UPB_DEFTYPE_MSG);
+      break;
+    case kUpb_FieldType_Enum:
+      UPB_ASSERT(has_name);
+      f->sub.enumdef = _upb_DefBuilder_Resolve(ctx, f->full_name, prefix, name,
+                                               UPB_DEFTYPE_ENUM);
+      break;
+    default:
+      // No resolution necessary.
+      break;
+  }
+}
+
+static int _upb_FieldDef_Compare(const void* p1, const void* p2) {
+  const uint32_t v1 = (*(upb_FieldDef**)p1)->number_;
+  const uint32_t v2 = (*(upb_FieldDef**)p2)->number_;
+  return (v1 < v2) ? -1 : (v1 > v2);
+}
+
+const upb_FieldDef** _upb_FieldDefs_Sorted(const upb_FieldDef* f, int n,
+                                           upb_Arena* a) {
+  // TODO: Try to replace this arena alloc with a persistent scratch buffer.
+  upb_FieldDef** out = (upb_FieldDef**)upb_Arena_Malloc(a, n * sizeof(void*));
+  if (!out) return NULL;
+
+  for (int i = 0; i < n; i++) {
+    out[i] = (upb_FieldDef*)&f[i];
+  }
+  qsort(out, n, sizeof(void*), _upb_FieldDef_Compare);
+
+  for (int i = 0; i < n; i++) {
+    out[i]->layout_index = i;
+  }
+  return (const upb_FieldDef**)out;
+}
+
+bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a,
+                                       upb_StringView* out) {
+  UPB_ASSERT(f->is_extension_);
+
+  upb_DescState s;
+  _upb_DescState_Init(&s);
+
+  const int number = upb_FieldDef_Number(f);
+  const uint64_t modifiers = _upb_FieldDef_Modifiers(f);
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  s.ptr = upb_MtDataEncoder_EncodeExtension(&s.e, s.ptr, f->type_, number,
+                                            modifiers);
+  *s.ptr = '\0';
+
+  out->data = s.buf;
+  out->size = s.ptr - s.buf;
+  return true;
+}
+
+static void resolve_extension(upb_DefBuilder* ctx, const char* prefix,
+                              upb_FieldDef* f,
+                              const google_protobuf_FieldDescriptorProto* field_proto) {
+  if (!google_protobuf_FieldDescriptorProto_has_extendee(field_proto)) {
+    _upb_DefBuilder_Errf(ctx, "extension for field '%s' had no extendee",
+                         f->full_name);
+  }
+
+  upb_StringView name = google_protobuf_FieldDescriptorProto_extendee(field_proto);
+  const upb_MessageDef* m =
+      _upb_DefBuilder_Resolve(ctx, f->full_name, prefix, name, UPB_DEFTYPE_MSG);
+  f->msgdef = m;
+
+  if (!_upb_MessageDef_IsValidExtensionNumber(m, f->number_)) {
+    _upb_DefBuilder_Errf(
+        ctx,
+        "field number %u in extension %s has no extension range in message %s",
+        (unsigned)f->number_, f->full_name, upb_MessageDef_FullName(m));
+  }
+
+  const upb_MiniTableExtension* ext = _upb_FieldDef_ExtensionMiniTable(f);
+
+  if (ctx->layout) {
+    UPB_ASSERT(upb_FieldDef_Number(f) == ext->field.number);
+  } else {
+    upb_StringView desc;
+    if (!upb_FieldDef_MiniDescriptorEncode(f, ctx->tmp_arena, &desc)) {
+      _upb_DefBuilder_OomErr(ctx);
+    }
+
+    upb_MiniTableExtension* mut_ext = (upb_MiniTableExtension*)ext;
+    upb_MiniTableSub sub = {NULL};
+    if (upb_FieldDef_IsSubMessage(f)) {
+      sub.submsg = upb_MessageDef_MiniTable(f->sub.msgdef);
+    } else if (_upb_FieldDef_IsClosedEnum(f)) {
+      sub.subenum = _upb_EnumDef_MiniTable(f->sub.enumdef);
+    }
+    bool ok2 = upb_MiniTableExtension_Build(desc.data, desc.size, mut_ext,
+                                            upb_MessageDef_MiniTable(m), sub,
+                                            ctx->status);
+    if (!ok2) _upb_DefBuilder_Errf(ctx, "Could not build extension mini table");
+  }
+
+  bool ok = _upb_DefPool_InsertExt(ctx->symtab, ext, f);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+static void resolve_default(upb_DefBuilder* ctx, upb_FieldDef* f,
+                            const google_protobuf_FieldDescriptorProto* field_proto) {
+  // 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_StringView defaultval =
+        google_protobuf_FieldDescriptorProto_default_value(field_proto);
+
+    if (upb_FileDef_Syntax(f->file) == kUpb_Syntax_Proto3) {
+      _upb_DefBuilder_Errf(ctx,
+                           "proto3 fields cannot have explicit defaults (%s)",
+                           f->full_name);
+    }
+
+    if (upb_FieldDef_IsSubMessage(f)) {
+      _upb_DefBuilder_Errf(ctx,
+                           "message fields cannot have explicit defaults (%s)",
+                           f->full_name);
+    }
+
+    parse_default(ctx, defaultval.data, defaultval.size, f);
+    f->has_default = true;
+  } else {
+    set_default_default(ctx, f);
+    f->has_default = false;
+  }
+}
+
+void _upb_FieldDef_Resolve(upb_DefBuilder* ctx, const char* prefix,
+                           upb_FieldDef* f) {
+  // We have to stash this away since resolve_subdef() may overwrite it.
+  const google_protobuf_FieldDescriptorProto* field_proto = f->sub.unresolved;
+
+  resolve_subdef(ctx, prefix, f);
+  resolve_default(ctx, f, field_proto);
+
+  if (f->is_extension_) {
+    resolve_extension(ctx, prefix, f, field_proto);
+  }
+}
+
+
+// Must be last.
+
+struct upb_FileDef {
+  const google_protobuf_FileOptions* opts;
+  const char* name;
+  const char* package;
+
+  const upb_FileDef** deps;
+  const int32_t* public_deps;
+  const int32_t* weak_deps;
+  const upb_MessageDef* top_lvl_msgs;
+  const upb_EnumDef* top_lvl_enums;
+  const upb_FieldDef* top_lvl_exts;
+  const upb_ServiceDef* services;
+  const upb_MiniTableExtension** ext_layouts;
+  const upb_DefPool* symtab;
+
+  int dep_count;
+  int public_dep_count;
+  int weak_dep_count;
+  int top_lvl_msg_count;
+  int top_lvl_enum_count;
+  int top_lvl_ext_count;
+  int service_count;
+  int ext_count;  // All exts in the file.
+  upb_Syntax syntax;
+};
+
+const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f) {
+  return f->opts;
+}
+
+bool upb_FileDef_HasOptions(const upb_FileDef* f) {
+  return f->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_FileDef_Name(const upb_FileDef* f) { return f->name; }
+
+const char* upb_FileDef_Package(const upb_FileDef* f) {
+  return f->package ? f->package : "";
+}
+
+const char* _upb_FileDef_RawPackage(const upb_FileDef* f) { return f->package; }
+
+upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f) { return f->syntax; }
+
+int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f) {
+  return f->top_lvl_msg_count;
+}
+
+int upb_FileDef_DependencyCount(const upb_FileDef* f) { return f->dep_count; }
+
+int upb_FileDef_PublicDependencyCount(const upb_FileDef* f) {
+  return f->public_dep_count;
+}
+
+int upb_FileDef_WeakDependencyCount(const upb_FileDef* f) {
+  return f->weak_dep_count;
+}
+
+const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f) {
+  return f->public_deps;
+}
+
+const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f) {
+  return f->weak_deps;
+}
+
+int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f) {
+  return f->top_lvl_enum_count;
+}
+
+int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f) {
+  return f->top_lvl_ext_count;
+}
+
+int upb_FileDef_ServiceCount(const upb_FileDef* f) { return f->service_count; }
+
+const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->dep_count);
+  return f->deps[i];
+}
+
+const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->public_dep_count);
+  return f->deps[f->public_deps[i]];
+}
+
+const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->public_dep_count);
+  return f->deps[f->weak_deps[i]];
+}
+
+const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->top_lvl_msg_count);
+  return _upb_MessageDef_At(f->top_lvl_msgs, i);
+}
+
+const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->top_lvl_enum_count);
+  return _upb_EnumDef_At(f->top_lvl_enums, i);
+}
+
+const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->top_lvl_ext_count);
+  return _upb_FieldDef_At(f->top_lvl_exts, i);
+}
+
+const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i) {
+  UPB_ASSERT(0 <= i && i < f->service_count);
+  return _upb_ServiceDef_At(f->services, i);
+}
+
+const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f) { return f->symtab; }
+
+const upb_MiniTableExtension* _upb_FileDef_ExtensionMiniTable(
+    const upb_FileDef* f, int i) {
+  return f->ext_layouts[i];
+}
+
+static char* strviewdup(upb_DefBuilder* ctx, upb_StringView view) {
+  char* ret = upb_strdup2(view.data, view.size, _upb_DefBuilder_Arena(ctx));
+  if (!ret) _upb_DefBuilder_OomErr(ctx);
+  return ret;
+}
+
+static bool streql_view(upb_StringView view, const char* b) {
+  return view.size == strlen(b) && memcmp(view.data, b, view.size) == 0;
+}
+
+static int count_exts_in_msg(const google_protobuf_DescriptorProto* msg_proto) {
+  size_t n;
+  google_protobuf_DescriptorProto_extension(msg_proto, &n);
+  int ext_count = n;
+
+  const google_protobuf_DescriptorProto* const* nested_msgs =
+      google_protobuf_DescriptorProto_nested_type(msg_proto, &n);
+  for (size_t i = 0; i < n; i++) {
+    ext_count += count_exts_in_msg(nested_msgs[i]);
+  }
+
+  return ext_count;
+}
+
+// Allocate and initialize one file def, and add it to the context object.
+void _upb_FileDef_Create(upb_DefBuilder* ctx,
+                         const google_protobuf_FileDescriptorProto* file_proto) {
+  upb_FileDef* file = _upb_DefBuilder_Alloc(ctx, sizeof(upb_FileDef));
+  ctx->file = file;
+
+  const google_protobuf_DescriptorProto* const* msgs;
+  const google_protobuf_EnumDescriptorProto* const* enums;
+  const google_protobuf_FieldDescriptorProto* const* exts;
+  const google_protobuf_ServiceDescriptorProto* const* services;
+  const upb_StringView* strs;
+  const int32_t* public_deps;
+  const int32_t* weak_deps;
+  size_t n;
+
+  file->symtab = ctx->symtab;
+
+  // Count all extensions in the file, to build a flat array of layouts.
+  google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  int ext_count = n;
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  for (int i = 0; i < n; i++) {
+    ext_count += count_exts_in_msg(msgs[i]);
+  }
+  file->ext_count = ext_count;
+
+  if (ctx->layout) {
+    // We are using the ext layouts that were passed in.
+    file->ext_layouts = ctx->layout->exts;
+    if (ctx->layout->ext_count != file->ext_count) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Extension count did not match layout (%d vs %d)",
+                           ctx->layout->ext_count, file->ext_count);
+    }
+  } else {
+    // We are building ext layouts from scratch.
+    file->ext_layouts = _upb_DefBuilder_Alloc(
+        ctx, sizeof(*file->ext_layouts) * file->ext_count);
+    upb_MiniTableExtension* ext =
+        _upb_DefBuilder_Alloc(ctx, sizeof(*ext) * file->ext_count);
+    for (int i = 0; i < file->ext_count; i++) {
+      file->ext_layouts[i] = &ext[i];
+    }
+  }
+
+  if (!google_protobuf_FileDescriptorProto_has_name(file_proto)) {
+    _upb_DefBuilder_Errf(ctx, "File has no name");
+  }
+
+  file->name = strviewdup(ctx, google_protobuf_FileDescriptorProto_name(file_proto));
+
+  upb_StringView package = google_protobuf_FileDescriptorProto_package(file_proto);
+  if (package.size) {
+    _upb_DefBuilder_CheckIdentFull(ctx, package);
+    file->package = strviewdup(ctx, package);
+  } else {
+    file->package = NULL;
+  }
+
+  if (google_protobuf_FileDescriptorProto_has_syntax(file_proto)) {
+    upb_StringView syntax = google_protobuf_FileDescriptorProto_syntax(file_proto);
+
+    if (streql_view(syntax, "proto2")) {
+      file->syntax = kUpb_Syntax_Proto2;
+    } else if (streql_view(syntax, "proto3")) {
+      file->syntax = kUpb_Syntax_Proto3;
+    } else {
+      _upb_DefBuilder_Errf(ctx, "Invalid syntax '" UPB_STRINGVIEW_FORMAT "'",
+                           UPB_STRINGVIEW_ARGS(syntax));
+    }
+  } else {
+    file->syntax = kUpb_Syntax_Proto2;
+  }
+
+  // Read options.
+  UPB_DEF_SET_OPTIONS(file->opts, FileDescriptorProto, FileOptions, file_proto);
+
+  // Verify dependencies.
+  strs = google_protobuf_FileDescriptorProto_dependency(file_proto, &n);
+  file->dep_count = n;
+  file->deps = _upb_DefBuilder_Alloc(ctx, sizeof(*file->deps) * n);
+
+  for (size_t i = 0; i < n; i++) {
+    upb_StringView str = strs[i];
+    file->deps[i] =
+        upb_DefPool_FindFileByNameWithSize(ctx->symtab, str.data, str.size);
+    if (!file->deps[i]) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Depends on file '" UPB_STRINGVIEW_FORMAT
+                           "', but it has not been loaded",
+                           UPB_STRINGVIEW_ARGS(str));
+    }
+  }
+
+  public_deps = google_protobuf_FileDescriptorProto_public_dependency(file_proto, &n);
+  file->public_dep_count = n;
+  file->public_deps =
+      _upb_DefBuilder_Alloc(ctx, sizeof(*file->public_deps) * n);
+  int32_t* mutable_public_deps = (int32_t*)file->public_deps;
+  for (size_t i = 0; i < n; i++) {
+    if (public_deps[i] >= file->dep_count) {
+      _upb_DefBuilder_Errf(ctx, "public_dep %d is out of range",
+                           (int)public_deps[i]);
+    }
+    mutable_public_deps[i] = public_deps[i];
+  }
+
+  weak_deps = google_protobuf_FileDescriptorProto_weak_dependency(file_proto, &n);
+  file->weak_dep_count = n;
+  file->weak_deps = _upb_DefBuilder_Alloc(ctx, sizeof(*file->weak_deps) * n);
+  int32_t* mutable_weak_deps = (int32_t*)file->weak_deps;
+  for (size_t i = 0; i < n; i++) {
+    if (weak_deps[i] >= file->dep_count) {
+      _upb_DefBuilder_Errf(ctx, "weak_dep %d is out of range",
+                           (int)weak_deps[i]);
+    }
+    mutable_weak_deps[i] = weak_deps[i];
+  }
+
+  // Create enums.
+  enums = google_protobuf_FileDescriptorProto_enum_type(file_proto, &n);
+  file->top_lvl_enum_count = n;
+  file->top_lvl_enums = _upb_EnumDefs_New(ctx, n, enums, NULL);
+
+  // Create extensions.
+  exts = google_protobuf_FileDescriptorProto_extension(file_proto, &n);
+  file->top_lvl_ext_count = n;
+  file->top_lvl_exts =
+      _upb_FieldDefs_New(ctx, n, exts, file->package, NULL, NULL);
+
+  // Create messages.
+  msgs = google_protobuf_FileDescriptorProto_message_type(file_proto, &n);
+  file->top_lvl_msg_count = n;
+  file->top_lvl_msgs = _upb_MessageDefs_New(ctx, n, msgs, NULL);
+
+  // Create services.
+  services = google_protobuf_FileDescriptorProto_service(file_proto, &n);
+  file->service_count = n;
+  file->services = _upb_ServiceDefs_New(ctx, n, services);
+
+  // Now that all names are in the table, build layouts and resolve refs.
+
+  for (int i = 0; i < file->top_lvl_msg_count; i++) {
+    upb_MessageDef* m = (upb_MessageDef*)upb_FileDef_TopLevelMessage(file, i);
+    _upb_MessageDef_Resolve(ctx, m);
+  }
+
+  for (int i = 0; i < file->top_lvl_ext_count; i++) {
+    upb_FieldDef* f = (upb_FieldDef*)upb_FileDef_TopLevelExtension(file, i);
+    _upb_FieldDef_Resolve(ctx, file->package, f);
+  }
+
+  if (!ctx->layout) {
+    for (int i = 0; i < file->top_lvl_msg_count; i++) {
+      upb_MessageDef* m = (upb_MessageDef*)upb_FileDef_TopLevelMessage(file, i);
+      _upb_MessageDef_LinkMiniTable(ctx, m);
+    }
+  }
+
+  if (file->ext_count) {
+    bool ok = upb_ExtensionRegistry_AddArray(
+        _upb_DefPool_ExtReg(ctx->symtab), file->ext_layouts, file->ext_count);
+    if (!ok) _upb_DefBuilder_OomErr(ctx);
+  }
+}
+
+
+#include <string.h>
+
+
+// Must be last.
+
+bool upb_Message_Has(const upb_Message* msg, const upb_FieldDef* f) {
+  UPB_ASSERT(upb_FieldDef_HasPresence(f));
+  return _upb_MiniTable_HasField(msg, upb_FieldDef_MiniTable(f));
+}
+
+const upb_FieldDef* upb_Message_WhichOneof(const upb_Message* 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_Message_Has(msg, f) ? f : NULL;
+  } else {
+    const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
+    uint32_t oneof_case = _upb_getoneofcase_field(msg, field);
+    f = oneof_case ? upb_OneofDef_LookupNumber(o, oneof_case) : NULL;
+    UPB_ASSERT((f != NULL) == (oneof_case != 0));
+    return f;
+  }
+}
+
+upb_MessageValue upb_Message_Get(const upb_Message* msg,
+                                 const upb_FieldDef* f) {
+  upb_MessageValue default_val = upb_FieldDef_Default(f);
+  upb_MessageValue ret;
+  _upb_MiniTable_GetField(msg, upb_FieldDef_MiniTable(f), &default_val, &ret);
+  return ret;
+}
+
+upb_MutableMessageValue upb_Message_Mutable(upb_Message* msg,
+                                            const upb_FieldDef* f,
+                                            upb_Arena* a) {
+  UPB_ASSERT(upb_FieldDef_IsSubMessage(f) || upb_FieldDef_IsRepeated(f));
+  if (upb_FieldDef_HasPresence(f) && !upb_Message_Has(msg, f)) {
+    // We need to skip the upb_Message_Get() call in this case.
+    goto make;
+  }
+
+  upb_MessageValue val = upb_Message_Get(msg, f);
+  if (val.array_val) {
+    return (upb_MutableMessageValue){.array = (upb_Array*)val.array_val};
+  }
+
+  upb_MutableMessageValue ret;
+make:
+  if (!a) return (upb_MutableMessageValue){.array = NULL};
+  if (upb_FieldDef_IsMap(f)) {
+    const upb_MessageDef* entry = upb_FieldDef_MessageSubDef(f);
+    const upb_FieldDef* key =
+        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_KeyFieldNumber);
+    const upb_FieldDef* value =
+        upb_MessageDef_FindFieldByNumber(entry, kUpb_MapEntry_ValueFieldNumber);
+    ret.map =
+        upb_Map_New(a, upb_FieldDef_CType(key), upb_FieldDef_CType(value));
+  } else if (upb_FieldDef_IsRepeated(f)) {
+    ret.array = upb_Array_New(a, upb_FieldDef_CType(f));
+  } else {
+    UPB_ASSERT(upb_FieldDef_IsSubMessage(f));
+    const upb_MessageDef* m = upb_FieldDef_MessageSubDef(f);
+    ret.msg = upb_Message_New(upb_MessageDef_MiniTable(m), a);
+  }
+
+  val.array_val = ret.array;
+  upb_Message_Set(msg, f, val, a);
+
+  return ret;
+}
+
+bool upb_Message_Set(upb_Message* msg, const upb_FieldDef* f,
+                     upb_MessageValue val, upb_Arena* a) {
+  return _upb_MiniTable_SetField(msg, upb_FieldDef_MiniTable(f), &val, a);
+}
+
+void upb_Message_ClearField(upb_Message* msg, const upb_FieldDef* f) {
+  _upb_MiniTable_ClearField(msg, upb_FieldDef_MiniTable(f));
+}
+
+void upb_Message_Clear(upb_Message* msg, const upb_MessageDef* m) {
+  _upb_Message_Clear(msg, upb_MessageDef_MiniTable(m));
+}
+
+bool upb_Message_Next(const upb_Message* msg, const upb_MessageDef* m,
+                      const upb_DefPool* ext_pool, const upb_FieldDef** out_f,
+                      upb_MessageValue* out_val, size_t* iter) {
+  size_t i = *iter;
+  size_t n = upb_MessageDef_FieldCount(m);
+  UPB_UNUSED(ext_pool);
+
+  // Iterate over normal fields, returning the first one that is set.
+  while (++i < n) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    const upb_MiniTableField* field = upb_FieldDef_MiniTable(f);
+    upb_MessageValue val = upb_Message_Get(msg, f);
+
+    // Skip field if unset or empty.
+    if (upb_MiniTableField_HasPresence(field)) {
+      if (!upb_Message_Has(msg, f)) continue;
+    } else {
+      switch (upb_FieldMode_Get(field)) {
+        case kUpb_FieldMode_Map:
+          if (!val.map_val || upb_Map_Size(val.map_val) == 0) continue;
+          break;
+        case kUpb_FieldMode_Array:
+          if (!val.array_val || upb_Array_Size(val.array_val) == 0) continue;
+          break;
+        case kUpb_FieldMode_Scalar:
+          if (!_upb_MiniTable_ValueIsNonZero(&val, field)) continue;
+          break;
+      }
+    }
+
+    *out_val = val;
+    *out_f = f;
+    *iter = i;
+    return true;
+  }
+
+  if (ext_pool) {
+    // Return any extensions that are set.
+    size_t count;
+    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &count);
+    if (i - n < count) {
+      ext += count - 1 - (i - n);
+      memcpy(out_val, &ext->data, sizeof(*out_val));
+      *out_f = upb_DefPool_FindExtensionByMiniTable(ext_pool, ext->ext);
+      *iter = i;
+      return true;
+    }
+  }
+
+  *iter = i;
+  return false;
+}
+
+bool _upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
+                                 int depth) {
+  size_t iter = kUpb_Message_Begin;
+  const upb_FieldDef* f;
+  upb_MessageValue val;
+  bool ret = true;
+
+  if (--depth == 0) return false;
+
+  _upb_Message_DiscardUnknown_shallow(msg);
+
+  while (upb_Message_Next(msg, m, NULL /*ext_pool*/, &f, &val, &iter)) {
+    const upb_MessageDef* subm = upb_FieldDef_MessageSubDef(f);
+    if (!subm) continue;
+    if (upb_FieldDef_IsMap(f)) {
+      const upb_FieldDef* val_f = upb_MessageDef_FindFieldByNumber(subm, 2);
+      const upb_MessageDef* val_m = upb_FieldDef_MessageSubDef(val_f);
+      upb_Map* map = (upb_Map*)val.map_val;
+      size_t iter = kUpb_Map_Begin;
+
+      if (!val_m) continue;
+
+      upb_MessageValue map_key, map_val;
+      while (upb_Map_Next(map, &map_key, &map_val, &iter)) {
+        if (!_upb_Message_DiscardUnknown((upb_Message*)map_val.msg_val, val_m,
+                                         depth)) {
+          ret = false;
+        }
+      }
+    } else if (upb_FieldDef_IsRepeated(f)) {
+      const upb_Array* arr = val.array_val;
+      size_t i, n = upb_Array_Size(arr);
+      for (i = 0; i < n; i++) {
+        upb_MessageValue elem = upb_Array_Get(arr, i);
+        if (!_upb_Message_DiscardUnknown((upb_Message*)elem.msg_val, subm,
+                                         depth)) {
+          ret = false;
+        }
+      }
+    } else {
+      if (!_upb_Message_DiscardUnknown((upb_Message*)val.msg_val, subm,
+                                       depth)) {
+        ret = false;
+      }
+    }
+  }
+
+  return ret;
+}
+
+bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* m,
+                                int maxdepth) {
+  return _upb_Message_DiscardUnknown(msg, m, maxdepth);
+}
+
+
+// Must be last.
+
+struct upb_MessageDef {
+  const google_protobuf_MessageOptions* opts;
+  const upb_MiniTable* layout;
+  const upb_FileDef* file;
+  const upb_MessageDef* containing_type;
+  const char* full_name;
+
+  // Tables for looking up fields by number and name.
+  upb_inttable itof;
+  upb_strtable ntof;
+
+  /* All nested defs.
+   * MEM: We could save some space here by putting nested defs in a contiguous
+   * region and calculating counts from offsets or vice-versa. */
+  const upb_FieldDef* fields;
+  const upb_OneofDef* oneofs;
+  const upb_ExtensionRange* ext_ranges;
+  const upb_StringView* res_names;
+  const upb_MessageDef* nested_msgs;
+  const upb_MessageReservedRange* res_ranges;
+  const upb_EnumDef* nested_enums;
+  const upb_FieldDef* nested_exts;
+
+  // TODO(salo): These counters don't need anywhere near 32 bits.
+  int field_count;
+  int real_oneof_count;
+  int oneof_count;
+  int ext_range_count;
+  int res_range_count;
+  int res_name_count;
+  int nested_msg_count;
+  int nested_enum_count;
+  int nested_ext_count;
+  bool in_message_set;
+  bool is_sorted;
+  upb_WellKnown well_known_type;
+#if UINTPTR_MAX == 0xffffffff
+  uint32_t padding;  // Increase size to a multiple of 8.
+#endif
+};
+
+static void assign_msg_wellknowntype(upb_MessageDef* m) {
+  const char* name = m->full_name;
+  if (name == NULL) {
+    m->well_known_type = kUpb_WellKnown_Unspecified;
+    return;
+  }
+  if (!strcmp(name, "google.protobuf.Any")) {
+    m->well_known_type = kUpb_WellKnown_Any;
+  } else if (!strcmp(name, "google.protobuf.FieldMask")) {
+    m->well_known_type = kUpb_WellKnown_FieldMask;
+  } else if (!strcmp(name, "google.protobuf.Duration")) {
+    m->well_known_type = kUpb_WellKnown_Duration;
+  } else if (!strcmp(name, "google.protobuf.Timestamp")) {
+    m->well_known_type = kUpb_WellKnown_Timestamp;
+  } else if (!strcmp(name, "google.protobuf.DoubleValue")) {
+    m->well_known_type = kUpb_WellKnown_DoubleValue;
+  } else if (!strcmp(name, "google.protobuf.FloatValue")) {
+    m->well_known_type = kUpb_WellKnown_FloatValue;
+  } else if (!strcmp(name, "google.protobuf.Int64Value")) {
+    m->well_known_type = kUpb_WellKnown_Int64Value;
+  } else if (!strcmp(name, "google.protobuf.UInt64Value")) {
+    m->well_known_type = kUpb_WellKnown_UInt64Value;
+  } else if (!strcmp(name, "google.protobuf.Int32Value")) {
+    m->well_known_type = kUpb_WellKnown_Int32Value;
+  } else if (!strcmp(name, "google.protobuf.UInt32Value")) {
+    m->well_known_type = kUpb_WellKnown_UInt32Value;
+  } else if (!strcmp(name, "google.protobuf.BoolValue")) {
+    m->well_known_type = kUpb_WellKnown_BoolValue;
+  } else if (!strcmp(name, "google.protobuf.StringValue")) {
+    m->well_known_type = kUpb_WellKnown_StringValue;
+  } else if (!strcmp(name, "google.protobuf.BytesValue")) {
+    m->well_known_type = kUpb_WellKnown_BytesValue;
+  } else if (!strcmp(name, "google.protobuf.Value")) {
+    m->well_known_type = kUpb_WellKnown_Value;
+  } else if (!strcmp(name, "google.protobuf.ListValue")) {
+    m->well_known_type = kUpb_WellKnown_ListValue;
+  } else if (!strcmp(name, "google.protobuf.Struct")) {
+    m->well_known_type = kUpb_WellKnown_Struct;
+  } else {
+    m->well_known_type = kUpb_WellKnown_Unspecified;
+  }
+}
+
+upb_MessageDef* _upb_MessageDef_At(const upb_MessageDef* m, int i) {
+  return (upb_MessageDef*)&m[i];
+}
+
+bool _upb_MessageDef_IsValidExtensionNumber(const upb_MessageDef* m, int n) {
+  for (int i = 0; i < m->ext_range_count; i++) {
+    const upb_ExtensionRange* r = upb_MessageDef_ExtensionRange(m, i);
+    if (upb_ExtensionRange_Start(r) <= n && n < upb_ExtensionRange_End(r)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+const google_protobuf_MessageOptions* upb_MessageDef_Options(const upb_MessageDef* m) {
+  return m->opts;
+}
+
+bool upb_MessageDef_HasOptions(const upb_MessageDef* m) {
+  return m->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_MessageDef_FullName(const upb_MessageDef* m) {
+  return m->full_name;
+}
+
+const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m) {
+  return m->file;
+}
+
+const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m) {
+  return m->containing_type;
+}
+
+const char* upb_MessageDef_Name(const upb_MessageDef* m) {
+  return _upb_DefBuilder_FullToShort(m->full_name);
+}
+
+upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m) {
+  return upb_FileDef_Syntax(m->file);
+}
+
+const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
+                                                     uint32_t i) {
+  upb_value val;
+  return upb_inttable_lookup(&m->itof, i, &val) ? upb_value_getconstptr(val)
+                                                : NULL;
+}
+
+const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, size, &val)) {
+    return NULL;
+  }
+
+  return _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
+}
+
+const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, size, &val)) {
+    return NULL;
+  }
+
+  return _upb_DefType_Unpack(val, UPB_DEFTYPE_ONEOF);
+}
+
+bool _upb_MessageDef_Insert(upb_MessageDef* m, const char* name, size_t len,
+                            upb_value v, upb_Arena* a) {
+  return upb_strtable_insert(&m->ntof, name, len, v, a);
+}
+
+bool upb_MessageDef_FindByNameWithSize(const upb_MessageDef* m,
+                                       const char* name, size_t len,
+                                       const upb_FieldDef** out_f,
+                                       const upb_OneofDef** out_o) {
+  upb_value val;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, len, &val)) {
+    return false;
+  }
+
+  const upb_FieldDef* f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
+  const upb_OneofDef* o = _upb_DefType_Unpack(val, UPB_DEFTYPE_ONEOF);
+  if (out_f) *out_f = f;
+  if (out_o) *out_o = o;
+  return f || o; /* False if this was a JSON name. */
+}
+
+const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size) {
+  upb_value val;
+  const upb_FieldDef* f;
+
+  if (!upb_strtable_lookup2(&m->ntof, name, size, &val)) {
+    return NULL;
+  }
+
+  f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD);
+  if (!f) f = _upb_DefType_Unpack(val, UPB_DEFTYPE_FIELD_JSONNAME);
+
+  return f;
+}
+
+int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m) {
+  return m->ext_range_count;
+}
+
+int upb_MessageDef_ReservedRangeCount(const upb_MessageDef* m) {
+  return m->res_range_count;
+}
+
+int upb_MessageDef_ReservedNameCount(const upb_MessageDef* m) {
+  return m->res_name_count;
+}
+
+int upb_MessageDef_FieldCount(const upb_MessageDef* m) {
+  return m->field_count;
+}
+
+int upb_MessageDef_OneofCount(const upb_MessageDef* m) {
+  return m->oneof_count;
+}
+
+int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m) {
+  return m->nested_msg_count;
+}
+
+int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m) {
+  return m->nested_enum_count;
+}
+
+int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m) {
+  return m->nested_ext_count;
+}
+
+const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m) {
+  return m->layout;
+}
+
+const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m,
+                                                        int i) {
+  UPB_ASSERT(0 <= i && i < m->ext_range_count);
+  return _upb_ExtensionRange_At(m->ext_ranges, i);
+}
+
+const upb_MessageReservedRange* upb_MessageDef_ReservedRange(
+    const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->res_range_count);
+  return _upb_MessageReservedRange_At(m->res_ranges, i);
+}
+
+upb_StringView upb_MessageDef_ReservedName(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->res_name_count);
+  return m->res_names[i];
+}
+
+const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->field_count);
+  return _upb_FieldDef_At(m->fields, i);
+}
+
+const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->oneof_count);
+  return _upb_OneofDef_At(m->oneofs, i);
+}
+
+const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
+                                                   int i) {
+  UPB_ASSERT(0 <= i && i < m->nested_msg_count);
+  return &m->nested_msgs[i];
+}
+
+const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i) {
+  UPB_ASSERT(0 <= i && i < m->nested_enum_count);
+  return _upb_EnumDef_At(m->nested_enums, i);
+}
+
+const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
+                                                   int i) {
+  UPB_ASSERT(0 <= i && i < m->nested_ext_count);
+  return _upb_FieldDef_At(m->nested_exts, i);
+}
+
+upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m) {
+  return m->well_known_type;
+}
+
+bool _upb_MessageDef_InMessageSet(const upb_MessageDef* m) {
+  return m->in_message_set;
+}
+
+const upb_FieldDef* upb_MessageDef_FindFieldByName(const upb_MessageDef* m,
+                                                   const char* name) {
+  return upb_MessageDef_FindFieldByNameWithSize(m, name, strlen(name));
+}
+
+const upb_OneofDef* upb_MessageDef_FindOneofByName(const upb_MessageDef* m,
+                                                   const char* name) {
+  return upb_MessageDef_FindOneofByNameWithSize(m, name, strlen(name));
+}
+
+bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m) {
+  return google_protobuf_MessageOptions_map_entry(m->opts);
+}
+
+bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m) {
+  return google_protobuf_MessageOptions_message_set_wire_format(m->opts);
+}
+
+static upb_MiniTable* _upb_MessageDef_MakeMiniTable(upb_DefBuilder* ctx,
+                                                    const upb_MessageDef* m) {
+  upb_StringView desc;
+  bool ok = upb_MessageDef_MiniDescriptorEncode(m, ctx->tmp_arena, &desc);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  void** scratch_data = _upb_DefPool_ScratchData(ctx->symtab);
+  size_t* scratch_size = _upb_DefPool_ScratchSize(ctx->symtab);
+  upb_MiniTable* ret = upb_MiniTable_BuildWithBuf(
+      desc.data, desc.size, kUpb_MiniTablePlatform_Native, ctx->arena,
+      scratch_data, scratch_size, ctx->status);
+  if (!ret) _upb_DefBuilder_FailJmp(ctx);
+
+  return ret;
+}
+
+void _upb_MessageDef_Resolve(upb_DefBuilder* ctx, upb_MessageDef* m) {
+  for (int i = 0; i < m->field_count; i++) {
+    upb_FieldDef* f = (upb_FieldDef*)upb_MessageDef_Field(m, i);
+    _upb_FieldDef_Resolve(ctx, m->full_name, f);
+  }
+
+  if (!ctx->layout) {
+    m->layout = _upb_MessageDef_MakeMiniTable(ctx, m);
+    if (!m->layout) _upb_DefBuilder_OomErr(ctx);
+  }
+
+#ifndef NDEBUG
+  for (int i = 0; i < m->field_count; i++) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    const int layout_index = _upb_FieldDef_LayoutIndex(f);
+    UPB_ASSERT(layout_index < m->layout->field_count);
+    const upb_MiniTableField* mt_f = &m->layout->fields[layout_index];
+    UPB_ASSERT(upb_FieldDef_Type(f) == upb_MiniTableField_Type(mt_f));
+    UPB_ASSERT(upb_FieldDef_HasPresence(f) ==
+               upb_MiniTableField_HasPresence(mt_f));
+  }
+#endif
+
+  m->in_message_set = false;
+  for (int i = 0; i < upb_MessageDef_NestedExtensionCount(m); i++) {
+    upb_FieldDef* ext = (upb_FieldDef*)upb_MessageDef_NestedExtension(m, i);
+    _upb_FieldDef_Resolve(ctx, m->full_name, ext);
+    if (upb_FieldDef_Type(ext) == kUpb_FieldType_Message &&
+        upb_FieldDef_Label(ext) == kUpb_Label_Optional &&
+        upb_FieldDef_MessageSubDef(ext) == m &&
+        google_protobuf_MessageOptions_message_set_wire_format(
+            upb_MessageDef_Options(upb_FieldDef_ContainingType(ext)))) {
+      m->in_message_set = true;
+    }
+  }
+
+  for (int i = 0; i < upb_MessageDef_NestedMessageCount(m); i++) {
+    upb_MessageDef* n = (upb_MessageDef*)upb_MessageDef_NestedMessage(m, i);
+    _upb_MessageDef_Resolve(ctx, n);
+  }
+}
+
+void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
+                                 const upb_FieldDef* f) {
+  const int32_t field_number = upb_FieldDef_Number(f);
+
+  if (field_number <= 0 || field_number > kUpb_MaxFieldNumber) {
+    _upb_DefBuilder_Errf(ctx, "invalid field number (%u)", field_number);
+  }
+
+  const char* json_name = upb_FieldDef_JsonName(f);
+  const char* shortname = upb_FieldDef_Name(f);
+  const size_t shortnamelen = strlen(shortname);
+
+  upb_value v = upb_value_constptr(f);
+
+  upb_value existing_v;
+  if (upb_strtable_lookup(&m->ntof, shortname, &existing_v)) {
+    _upb_DefBuilder_Errf(ctx, "duplicate field name (%s)", shortname);
+  }
+
+  const upb_value field_v = _upb_DefType_Pack(f, UPB_DEFTYPE_FIELD);
+  bool ok =
+      _upb_MessageDef_Insert(m, shortname, shortnamelen, field_v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  if (strcmp(shortname, json_name) != 0) {
+    if (upb_strtable_lookup(&m->ntof, json_name, &v)) {
+      _upb_DefBuilder_Errf(ctx, "duplicate json_name (%s)", json_name);
+    }
+
+    const size_t json_size = strlen(json_name);
+    const upb_value json_v = _upb_DefType_Pack(f, UPB_DEFTYPE_FIELD_JSONNAME);
+    ok = _upb_MessageDef_Insert(m, json_name, json_size, json_v, ctx->arena);
+    if (!ok) _upb_DefBuilder_OomErr(ctx);
+  }
+
+  if (upb_inttable_lookup(&m->itof, field_number, NULL)) {
+    _upb_DefBuilder_Errf(ctx, "duplicate field number (%u)", field_number);
+  }
+
+  ok = upb_inttable_insert(&m->itof, field_number, v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx,
+                                   const upb_MessageDef* m) {
+  for (int i = 0; i < m->field_count; i++) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    const upb_MessageDef* sub_m = upb_FieldDef_MessageSubDef(f);
+    const upb_EnumDef* sub_e = upb_FieldDef_EnumSubDef(f);
+    const int layout_index = _upb_FieldDef_LayoutIndex(f);
+    upb_MiniTable* mt = (upb_MiniTable*)upb_MessageDef_MiniTable(m);
+
+    UPB_ASSERT(layout_index < m->field_count);
+    upb_MiniTableField* mt_f =
+        (upb_MiniTableField*)&m->layout->fields[layout_index];
+    if (sub_m) {
+      if (!mt->subs) {
+        _upb_DefBuilder_Errf(ctx, "invalid submsg for (%s)", m->full_name);
+      }
+      UPB_ASSERT(mt_f);
+      UPB_ASSERT(sub_m->layout);
+      upb_MiniTable_SetSubMessage(mt, mt_f, sub_m->layout);
+    } else if (_upb_FieldDef_IsClosedEnum(f)) {
+      upb_MiniTable_SetSubEnum(mt, mt_f, _upb_EnumDef_MiniTable(sub_e));
+    }
+  }
+
+  for (int i = 0; i < m->nested_msg_count; i++) {
+    _upb_MessageDef_LinkMiniTable(ctx, upb_MessageDef_NestedMessage(m, i));
+  }
+}
+
+static uint64_t _upb_MessageDef_Modifiers(const upb_MessageDef* m) {
+  uint64_t out = 0;
+  if (upb_FileDef_Syntax(m->file) == kUpb_Syntax_Proto3) {
+    out |= kUpb_MessageModifier_ValidateUtf8;
+    out |= kUpb_MessageModifier_DefaultIsPacked;
+  }
+  if (m->ext_range_count) {
+    out |= kUpb_MessageModifier_IsExtendable;
+  }
+  return out;
+}
+
+static bool _upb_MessageDef_EncodeMap(upb_DescState* s, const upb_MessageDef* m,
+                                      upb_Arena* a) {
+  if (m->field_count != 2) return false;
+
+  const upb_FieldDef* key_field = upb_MessageDef_Field(m, 0);
+  const upb_FieldDef* val_field = upb_MessageDef_Field(m, 1);
+  if (key_field == NULL || val_field == NULL) return false;
+
+  UPB_ASSERT(_upb_FieldDef_LayoutIndex(key_field) == 0);
+  UPB_ASSERT(_upb_FieldDef_LayoutIndex(val_field) == 1);
+
+  s->ptr = upb_MtDataEncoder_EncodeMap(
+      &s->e, s->ptr, upb_FieldDef_Type(key_field), upb_FieldDef_Type(val_field),
+      _upb_FieldDef_Modifiers(key_field), _upb_FieldDef_Modifiers(val_field));
+  return true;
+}
+
+static bool _upb_MessageDef_EncodeMessage(upb_DescState* s,
+                                          const upb_MessageDef* m,
+                                          upb_Arena* a) {
+  const upb_FieldDef** sorted = NULL;
+  if (!m->is_sorted) {
+    sorted = _upb_FieldDefs_Sorted(m->fields, m->field_count, a);
+    if (!sorted) return false;
+  }
+
+  s->ptr = upb_MtDataEncoder_StartMessage(&s->e, s->ptr,
+                                          _upb_MessageDef_Modifiers(m));
+
+  for (int i = 0; i < m->field_count; i++) {
+    const upb_FieldDef* f = sorted ? sorted[i] : upb_MessageDef_Field(m, i);
+    const upb_FieldType type = upb_FieldDef_Type(f);
+    const int number = upb_FieldDef_Number(f);
+    const uint64_t modifiers = _upb_FieldDef_Modifiers(f);
+
+    if (!_upb_DescState_Grow(s, a)) return false;
+    s->ptr = upb_MtDataEncoder_PutField(&s->e, s->ptr, type, number, modifiers);
+  }
+
+  for (int i = 0; i < m->real_oneof_count; i++) {
+    if (!_upb_DescState_Grow(s, a)) return false;
+    s->ptr = upb_MtDataEncoder_StartOneof(&s->e, s->ptr);
+
+    const upb_OneofDef* o = upb_MessageDef_Oneof(m, i);
+    const int field_count = upb_OneofDef_FieldCount(o);
+    for (int j = 0; j < field_count; j++) {
+      const int number = upb_FieldDef_Number(upb_OneofDef_Field(o, j));
+
+      if (!_upb_DescState_Grow(s, a)) return false;
+      s->ptr = upb_MtDataEncoder_PutOneofField(&s->e, s->ptr, number);
+    }
+  }
+
+  return true;
+}
+
+static bool _upb_MessageDef_EncodeMessageSet(upb_DescState* s,
+                                             const upb_MessageDef* m,
+                                             upb_Arena* a) {
+  s->ptr = upb_MtDataEncoder_EncodeMessageSet(&s->e, s->ptr);
+
+  return true;
+}
+
+bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a,
+                                         upb_StringView* out) {
+  upb_DescState s;
+  _upb_DescState_Init(&s);
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+
+  if (upb_MessageDef_IsMapEntry(m)) {
+    if (!_upb_MessageDef_EncodeMap(&s, m, a)) return false;
+  } else if (google_protobuf_MessageOptions_message_set_wire_format(m->opts)) {
+    if (!_upb_MessageDef_EncodeMessageSet(&s, m, a)) return false;
+  } else {
+    if (!_upb_MessageDef_EncodeMessage(&s, m, a)) return false;
+  }
+
+  if (!_upb_DescState_Grow(&s, a)) return false;
+  *s.ptr = '\0';
+
+  out->data = s.buf;
+  out->size = s.ptr - s.buf;
+  return true;
+}
+
+static upb_StringView* _upb_ReservedNames_New(upb_DefBuilder* ctx, int n,
+                                              const upb_StringView* protos) {
+  upb_StringView* sv = _upb_DefBuilder_Alloc(ctx, sizeof(upb_StringView) * n);
+  for (size_t i = 0; i < n; i++) {
+    sv[i].data =
+        upb_strdup2(protos[i].data, protos[i].size, _upb_DefBuilder_Arena(ctx));
+    sv[i].size = protos[i].size;
+  }
+  return sv;
+}
+
+static void create_msgdef(upb_DefBuilder* ctx, const char* prefix,
+                          const google_protobuf_DescriptorProto* msg_proto,
+                          const upb_MessageDef* containing_type,
+                          upb_MessageDef* m) {
+  const google_protobuf_OneofDescriptorProto* const* oneofs;
+  const google_protobuf_FieldDescriptorProto* const* fields;
+  const google_protobuf_DescriptorProto_ExtensionRange* const* ext_ranges;
+  const google_protobuf_DescriptorProto_ReservedRange* const* res_ranges;
+  const upb_StringView* res_names;
+  size_t n_oneof, n_field, n_enum, n_ext, n_msg;
+  size_t n_ext_range, n_res_range, n_res_name;
+  upb_StringView name;
+
+  // Must happen before _upb_DefBuilder_Add()
+  m->file = _upb_DefBuilder_File(ctx);
+
+  m->containing_type = containing_type;
+  m->is_sorted = true;
+
+  name = google_protobuf_DescriptorProto_name(msg_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+
+  m->full_name = _upb_DefBuilder_MakeFullName(ctx, prefix, name);
+  _upb_DefBuilder_Add(ctx, m->full_name, _upb_DefType_Pack(m, UPB_DEFTYPE_MSG));
+
+  oneofs = google_protobuf_DescriptorProto_oneof_decl(msg_proto, &n_oneof);
+  fields = google_protobuf_DescriptorProto_field(msg_proto, &n_field);
+  ext_ranges = google_protobuf_DescriptorProto_extension_range(msg_proto, &n_ext_range);
+  res_ranges = google_protobuf_DescriptorProto_reserved_range(msg_proto, &n_res_range);
+  res_names = google_protobuf_DescriptorProto_reserved_name(msg_proto, &n_res_name);
+
+  bool ok = upb_inttable_init(&m->itof, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_strtable_init(&m->ntof, n_oneof + n_field, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  if (ctx->layout) {
+    /* create_fielddef() below depends on this being set. */
+    UPB_ASSERT(ctx->msg_count < ctx->layout->msg_count);
+    m->layout = ctx->layout->msgs[ctx->msg_count++];
+    UPB_ASSERT(n_field == m->layout->field_count);
+  } else {
+    /* Allocate now (to allow cross-linking), populate later. */
+    m->layout = _upb_DefBuilder_Alloc(
+        ctx, sizeof(*m->layout) + sizeof(_upb_FastTable_Entry));
+  }
+
+  UPB_DEF_SET_OPTIONS(m->opts, DescriptorProto, MessageOptions, msg_proto);
+
+  m->oneof_count = n_oneof;
+  m->oneofs = _upb_OneofDefs_New(ctx, n_oneof, oneofs, m);
+
+  m->field_count = n_field;
+  m->fields =
+      _upb_FieldDefs_New(ctx, n_field, fields, m->full_name, m, &m->is_sorted);
+
+  // Message Sets may not contain fields.
+  if (UPB_UNLIKELY(google_protobuf_MessageOptions_message_set_wire_format(m->opts))) {
+    if (UPB_UNLIKELY(n_field > 0)) {
+      _upb_DefBuilder_Errf(ctx, "invalid message set (%s)", m->full_name);
+    }
+  }
+
+  m->ext_range_count = n_ext_range;
+  m->ext_ranges = _upb_ExtensionRanges_New(ctx, n_ext_range, ext_ranges, m);
+
+  m->res_range_count = n_res_range;
+  m->res_ranges =
+      _upb_MessageReservedRanges_New(ctx, n_res_range, res_ranges, m);
+
+  m->res_name_count = n_res_name;
+  m->res_names = _upb_ReservedNames_New(ctx, n_res_name, res_names);
+
+  const size_t synthetic_count = _upb_OneofDefs_Finalize(ctx, m);
+  m->real_oneof_count = m->oneof_count - synthetic_count;
+
+  assign_msg_wellknowntype(m);
+  upb_inttable_compact(&m->itof, ctx->arena);
+
+  const google_protobuf_EnumDescriptorProto* const* enums =
+      google_protobuf_DescriptorProto_enum_type(msg_proto, &n_enum);
+  m->nested_enum_count = n_enum;
+  m->nested_enums = _upb_EnumDefs_New(ctx, n_enum, enums, m);
+
+  const google_protobuf_FieldDescriptorProto* const* exts =
+      google_protobuf_DescriptorProto_extension(msg_proto, &n_ext);
+  m->nested_ext_count = n_ext;
+  m->nested_exts = _upb_FieldDefs_New(ctx, n_ext, exts, m->full_name, m, NULL);
+
+  const google_protobuf_DescriptorProto* const* msgs =
+      google_protobuf_DescriptorProto_nested_type(msg_proto, &n_msg);
+  m->nested_msg_count = n_msg;
+  m->nested_msgs = _upb_MessageDefs_New(ctx, n_msg, msgs, m);
+}
+
+// Allocate and initialize an array of |n| message defs.
+upb_MessageDef* _upb_MessageDefs_New(
+    upb_DefBuilder* ctx, int n, const google_protobuf_DescriptorProto* const* protos,
+    const upb_MessageDef* containing_type) {
+  _upb_DefType_CheckPadding(sizeof(upb_MessageDef));
+
+  const char* name = containing_type ? containing_type->full_name
+                                     : _upb_FileDef_RawPackage(ctx->file);
+
+  upb_MessageDef* m = _upb_DefBuilder_Alloc(ctx, sizeof(upb_MessageDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_msgdef(ctx, name, protos[i], containing_type, &m[i]);
+  }
+  return m;
+}
+
+
+// Must be last.
+
+struct upb_MessageReservedRange {
+  int32_t start;
+  int32_t end;
+};
+
+upb_MessageReservedRange* _upb_MessageReservedRange_At(
+    const upb_MessageReservedRange* r, int i) {
+  return (upb_MessageReservedRange*)&r[i];
+}
+
+int32_t upb_MessageReservedRange_Start(const upb_MessageReservedRange* r) {
+  return r->start;
+}
+int32_t upb_MessageReservedRange_End(const upb_MessageReservedRange* r) {
+  return r->end;
+}
+
+upb_MessageReservedRange* _upb_MessageReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ReservedRange* const* protos,
+    const upb_MessageDef* m) {
+  upb_MessageReservedRange* r =
+      _upb_DefBuilder_Alloc(ctx, sizeof(upb_MessageReservedRange) * n);
+
+  for (int i = 0; i < n; i++) {
+    const int32_t start = google_protobuf_DescriptorProto_ReservedRange_start(protos[i]);
+    const int32_t end = google_protobuf_DescriptorProto_ReservedRange_end(protos[i]);
+    const int32_t max = kUpb_MaxFieldNumber + 1;
+
+    // A full validation would also check that each range is disjoint, and that
+    // none of the fields overlap with the extension ranges, but we are just
+    // sanity checking here.
+    if (start < 1 || end <= start || end > max) {
+      _upb_DefBuilder_Errf(ctx,
+                           "Reserved range (%d, %d) is invalid, message=%s\n",
+                           (int)start, (int)end, upb_MessageDef_FullName(m));
+    }
+
+    r[i].start = start;
+    r[i].end = end;
+  }
+
+  return r;
+}
+
+
+// Must be last.
+
+struct upb_MethodDef {
+  const google_protobuf_MethodOptions* opts;
+  upb_ServiceDef* service;
+  const char* full_name;
+  const upb_MessageDef* input_type;
+  const upb_MessageDef* output_type;
+  int index;
+  bool client_streaming;
+  bool server_streaming;
+};
+
+upb_MethodDef* _upb_MethodDef_At(const upb_MethodDef* m, int i) {
+  return (upb_MethodDef*)&m[i];
+}
+
+const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m) {
+  return m->service;
+}
+
+const google_protobuf_MethodOptions* upb_MethodDef_Options(const upb_MethodDef* m) {
+  return m->opts;
+}
+
+bool upb_MethodDef_HasOptions(const upb_MethodDef* m) {
+  return m->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_MethodDef_FullName(const upb_MethodDef* m) {
+  return m->full_name;
+}
+
+const char* upb_MethodDef_Name(const upb_MethodDef* m) {
+  return _upb_DefBuilder_FullToShort(m->full_name);
+}
+
+int upb_MethodDef_Index(const upb_MethodDef* m) { return m->index; }
+
+const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m) {
+  return m->input_type;
+}
+
+const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m) {
+  return m->output_type;
+}
+
+bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m) {
+  return m->client_streaming;
+}
+
+bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m) {
+  return m->server_streaming;
+}
+
+static void create_method(upb_DefBuilder* ctx,
+                          const google_protobuf_MethodDescriptorProto* method_proto,
+                          upb_ServiceDef* s, upb_MethodDef* m) {
+  upb_StringView name = google_protobuf_MethodDescriptorProto_name(method_proto);
+
+  m->service = s;
+  m->full_name =
+      _upb_DefBuilder_MakeFullName(ctx, upb_ServiceDef_FullName(s), name);
+  m->client_streaming =
+      google_protobuf_MethodDescriptorProto_client_streaming(method_proto);
+  m->server_streaming =
+      google_protobuf_MethodDescriptorProto_server_streaming(method_proto);
+  m->input_type = _upb_DefBuilder_Resolve(
+      ctx, m->full_name, m->full_name,
+      google_protobuf_MethodDescriptorProto_input_type(method_proto), UPB_DEFTYPE_MSG);
+  m->output_type = _upb_DefBuilder_Resolve(
+      ctx, m->full_name, m->full_name,
+      google_protobuf_MethodDescriptorProto_output_type(method_proto), UPB_DEFTYPE_MSG);
+
+  UPB_DEF_SET_OPTIONS(m->opts, MethodDescriptorProto, MethodOptions,
+                      method_proto);
+}
+
+// Allocate and initialize an array of |n| method defs belonging to |s|.
+upb_MethodDef* _upb_MethodDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_MethodDescriptorProto* const* protos, upb_ServiceDef* s) {
+  upb_MethodDef* m = _upb_DefBuilder_Alloc(ctx, sizeof(upb_MethodDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_method(ctx, protos[i], s, &m[i]);
+    m[i].index = i;
+  }
+  return m;
+}
+
+#include <ctype.h>
+#include <stdlib.h>
+#include <string.h>
+
+
+// Must be last.
+
+struct upb_OneofDef {
+  const google_protobuf_OneofOptions* opts;
+  const upb_MessageDef* parent;
+  const char* full_name;
+  int field_count;
+  bool synthetic;
+  const upb_FieldDef** fields;
+  upb_strtable ntof;  // lookup a field by name
+  upb_inttable itof;  // lookup a field by number (index)
+#if UINTPTR_MAX == 0xffffffff
+  uint32_t padding;  // Increase size to a multiple of 8.
+#endif
+};
+
+upb_OneofDef* _upb_OneofDef_At(const upb_OneofDef* o, int i) {
+  return (upb_OneofDef*)&o[i];
+}
+
+const google_protobuf_OneofOptions* upb_OneofDef_Options(const upb_OneofDef* o) {
+  return o->opts;
+}
+
+bool upb_OneofDef_HasOptions(const upb_OneofDef* o) {
+  return o->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_OneofDef_FullName(const upb_OneofDef* o) {
+  return o->full_name;
+}
+
+const char* upb_OneofDef_Name(const upb_OneofDef* o) {
+  return _upb_DefBuilder_FullToShort(o->full_name);
+}
+
+const upb_MessageDef* 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) {
+  // Compute index in our parent's array.
+  return o - upb_MessageDef_Oneof(o->parent, 0);
+}
+
+bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o) { return o->synthetic; }
+
+const upb_FieldDef* upb_OneofDef_LookupNameWithSize(const upb_OneofDef* o,
+                                                    const char* name,
+                                                    size_t size) {
+  upb_value val;
+  return upb_strtable_lookup2(&o->ntof, name, size, &val)
+             ? upb_value_getptr(val)
+             : NULL;
+}
+
+const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o,
+                                            const char* name) {
+  return upb_OneofDef_LookupNameWithSize(o, name, strlen(name));
+}
+
+const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
+                                              uint32_t num) {
+  upb_value val;
+  return upb_inttable_lookup(&o->itof, num, &val) ? upb_value_getptr(val)
+                                                  : NULL;
+}
+
+bool _upb_OneofDef_Insert(upb_OneofDef* o, const upb_FieldDef* f,
+                          const char* name, size_t size, upb_Arena* a) {
+  o->field_count++;
+  if (_upb_FieldDef_IsProto3Optional(f)) o->synthetic = true;
+
+  const int number = upb_FieldDef_Number(f);
+  const upb_value v = upb_value_constptr(f);
+  return upb_inttable_insert(&o->itof, number, v, a) &&
+         upb_strtable_insert(&o->ntof, name, size, v, a);
+}
+
+// Returns the synthetic count.
+size_t _upb_OneofDefs_Finalize(upb_DefBuilder* ctx, upb_MessageDef* m) {
+  int synthetic_count = 0;
+
+  for (int i = 0; i < upb_MessageDef_OneofCount(m); i++) {
+    upb_OneofDef* o = (upb_OneofDef*)upb_MessageDef_Oneof(m, i);
+
+    if (o->synthetic && o->field_count != 1) {
+      _upb_DefBuilder_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) {
+      _upb_DefBuilder_Errf(
+          ctx, "Synthetic oneofs must be after all other oneofs: %s",
+          upb_OneofDef_Name(o));
+    }
+
+    o->fields =
+        _upb_DefBuilder_Alloc(ctx, sizeof(upb_FieldDef*) * o->field_count);
+    o->field_count = 0;
+  }
+
+  for (int i = 0; i < upb_MessageDef_FieldCount(m); i++) {
+    const upb_FieldDef* f = upb_MessageDef_Field(m, i);
+    upb_OneofDef* o = (upb_OneofDef*)upb_FieldDef_ContainingOneof(f);
+    if (o) {
+      o->fields[o->field_count++] = f;
+    }
+  }
+
+  return synthetic_count;
+}
+
+static void create_oneofdef(upb_DefBuilder* ctx, upb_MessageDef* m,
+                            const google_protobuf_OneofDescriptorProto* oneof_proto,
+                            const upb_OneofDef* _o) {
+  upb_OneofDef* o = (upb_OneofDef*)_o;
+  upb_StringView name = google_protobuf_OneofDescriptorProto_name(oneof_proto);
+
+  o->parent = m;
+  o->full_name =
+      _upb_DefBuilder_MakeFullName(ctx, upb_MessageDef_FullName(m), name);
+  o->field_count = 0;
+  o->synthetic = false;
+
+  UPB_DEF_SET_OPTIONS(o->opts, OneofDescriptorProto, OneofOptions, oneof_proto);
+
+  if (upb_MessageDef_FindByNameWithSize(m, name.data, name.size, NULL, NULL)) {
+    _upb_DefBuilder_Errf(ctx, "duplicate oneof name (%s)", o->full_name);
+  }
+
+  upb_value v = _upb_DefType_Pack(o, UPB_DEFTYPE_ONEOF);
+  bool ok = _upb_MessageDef_Insert(m, name.data, name.size, v, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_inttable_init(&o->itof, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+
+  ok = upb_strtable_init(&o->ntof, 4, ctx->arena);
+  if (!ok) _upb_DefBuilder_OomErr(ctx);
+}
+
+// Allocate and initialize an array of |n| oneof defs.
+upb_OneofDef* _upb_OneofDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_OneofDescriptorProto* const* protos, upb_MessageDef* m) {
+  _upb_DefType_CheckPadding(sizeof(upb_OneofDef));
+
+  upb_OneofDef* o = _upb_DefBuilder_Alloc(ctx, sizeof(upb_OneofDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_oneofdef(ctx, m, protos[i], &o[i]);
+  }
+  return o;
+}
+
+
+// Must be last.
+
+struct upb_ServiceDef {
+  const google_protobuf_ServiceOptions* opts;
+  const upb_FileDef* file;
+  const char* full_name;
+  upb_MethodDef* methods;
+  int method_count;
+  int index;
+};
+
+upb_ServiceDef* _upb_ServiceDef_At(const upb_ServiceDef* s, int index) {
+  return (upb_ServiceDef*)&s[index];
+}
+
+const google_protobuf_ServiceOptions* upb_ServiceDef_Options(const upb_ServiceDef* s) {
+  return s->opts;
+}
+
+bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s) {
+  return s->opts != (void*)kUpbDefOptDefault;
+}
+
+const char* upb_ServiceDef_FullName(const upb_ServiceDef* s) {
+  return s->full_name;
+}
+
+const char* upb_ServiceDef_Name(const upb_ServiceDef* s) {
+  return _upb_DefBuilder_FullToShort(s->full_name);
+}
+
+int upb_ServiceDef_Index(const upb_ServiceDef* s) { return s->index; }
+
+const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s) {
+  return s->file;
+}
+
+int upb_ServiceDef_MethodCount(const upb_ServiceDef* s) {
+  return s->method_count;
+}
+
+const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i) {
+  return (i < 0 || i >= s->method_count) ? NULL
+                                         : _upb_MethodDef_At(s->methods, i);
+}
+
+const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
+                                                     const char* name) {
+  for (int i = 0; i < s->method_count; i++) {
+    const upb_MethodDef* m = _upb_MethodDef_At(s->methods, i);
+    if (strcmp(name, upb_MethodDef_Name(m)) == 0) {
+      return m;
+    }
+  }
+  return NULL;
+}
+
+static void create_service(upb_DefBuilder* ctx,
+                           const google_protobuf_ServiceDescriptorProto* svc_proto,
+                           upb_ServiceDef* s) {
+  upb_StringView name;
+  size_t n;
+
+  // Must happen before _upb_DefBuilder_Add()
+  s->file = _upb_DefBuilder_File(ctx);
+
+  name = google_protobuf_ServiceDescriptorProto_name(svc_proto);
+  _upb_DefBuilder_CheckIdentNotFull(ctx, name);
+  const char* package = _upb_FileDef_RawPackage(s->file);
+  s->full_name = _upb_DefBuilder_MakeFullName(ctx, package, name);
+  _upb_DefBuilder_Add(ctx, s->full_name,
+                      _upb_DefType_Pack(s, UPB_DEFTYPE_SERVICE));
+
+  const google_protobuf_MethodDescriptorProto* const* methods =
+      google_protobuf_ServiceDescriptorProto_method(svc_proto, &n);
+  s->method_count = n;
+  s->methods = _upb_MethodDefs_New(ctx, n, methods, s);
+
+  UPB_DEF_SET_OPTIONS(s->opts, ServiceDescriptorProto, ServiceOptions,
+                      svc_proto);
+}
+
+upb_ServiceDef* _upb_ServiceDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_ServiceDescriptorProto* const* protos) {
+  _upb_DefType_CheckPadding(sizeof(upb_ServiceDef));
+
+  upb_ServiceDef* s = _upb_DefBuilder_Alloc(ctx, sizeof(upb_ServiceDef) * n);
+  for (int i = 0; i < n; i++) {
+    create_service(ctx, protos[i], &s[i]);
+    s[i].index = i;
+  }
+  return s;
+}
+
+
+#include <string.h>
+
+
+// Must be last.
+
+// A few fake field types for our tables.
+enum {
+  kUpb_FakeFieldType_FieldNotFound = 0,
+  kUpb_FakeFieldType_MessageSetItem = 19,
+};
+
+// DecodeOp: an action to be performed for a wire-type/field-type combination.
+enum {
+  // Special ops: we don't write data to regular fields for these.
+  kUpb_DecodeOp_UnknownField = -1,
+  kUpb_DecodeOp_MessageSetItem = -2,
+
+  // Scalar-only ops.
+  kUpb_DecodeOp_Scalar1Byte = 0,
+  kUpb_DecodeOp_Scalar4Byte = 2,
+  kUpb_DecodeOp_Scalar8Byte = 3,
+  kUpb_DecodeOp_Enum = 1,
+
+  // Scalar/repeated ops.
+  kUpb_DecodeOp_String = 4,
+  kUpb_DecodeOp_Bytes = 5,
+  kUpb_DecodeOp_SubMessage = 6,
+
+  // Repeated-only ops (also see macros below).
+  kUpb_DecodeOp_PackedEnum = 13,
+};
+
+// For packed fields it is helpful to be able to recover the lg2 of the data
+// size from the 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] */
+
+typedef union {
+  bool bool_val;
+  uint32_t uint32_val;
+  uint64_t uint64_val;
+  uint32_t size;
+} wireval;
+
+static const char* _upb_Decoder_DecodeMessage(upb_Decoder* d, const char* ptr,
+                                              upb_Message* msg,
+                                              const upb_MiniTable* layout);
+
+UPB_NORETURN static void* _upb_Decoder_ErrorJmp(upb_Decoder* d,
+                                                upb_DecodeStatus status) {
+  assert(status != kUpb_DecodeStatus_Ok);
+  UPB_LONGJMP(d->err, status);
+}
+
+const char* _upb_FastDecoder_ErrorJmp(upb_Decoder* d, int status) {
+  assert(status != kUpb_DecodeStatus_Ok);
+  UPB_LONGJMP(d->err, status);
+  return NULL;
+}
+static void _upb_Decoder_VerifyUtf8(upb_Decoder* d, const char* buf, int len) {
+  if (!_upb_Decoder_VerifyUtf8Inline(buf, len)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);
+  }
+}
+
+static bool _upb_Decoder_Reserve(upb_Decoder* d, upb_Array* arr, size_t elem) {
+  bool need_realloc = arr->capacity - arr->size < elem;
+  if (need_realloc && !_upb_array_realloc(arr, arr->size + elem, &d->arena)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+  return need_realloc;
+}
+
+typedef struct {
+  const char* ptr;
+  uint64_t val;
+} _upb_DecodeLongVarintReturn;
+
+UPB_NOINLINE
+static _upb_DecodeLongVarintReturn _upb_Decoder_DecodeLongVarint(
+    const char* ptr, uint64_t val) {
+  _upb_DecodeLongVarintReturn 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* _upb_Decoder_DecodeVarint(upb_Decoder* 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 {
+    _upb_DecodeLongVarintReturn res = _upb_Decoder_DecodeLongVarint(ptr, byte);
+    if (!res.ptr) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeTag(upb_Decoder* 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;
+    _upb_DecodeLongVarintReturn res = _upb_Decoder_DecodeLongVarint(ptr, byte);
+    if (!res.ptr || res.ptr - start > 5 || res.val > UINT32_MAX) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+    }
+    *val = res.val;
+    return res.ptr;
+  }
+}
+
+UPB_FORCEINLINE
+static const char* upb_Decoder_DecodeSize(upb_Decoder* d, const char* ptr,
+                                          uint32_t* size) {
+  uint64_t size64;
+  ptr = _upb_Decoder_DecodeVarint(d, ptr, &size64);
+  if (size64 >= INT32_MAX || ptr - d->end + (int)size64 > d->limit) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  *size = size64;
+  return ptr;
+}
+
+static void _upb_Decoder_MungeInt32(wireval* val) {
+  if (!_upb_IsLittleEndian()) {
+    /* The next stage will memcpy(dst, &val, 4) */
+    val->uint32_val = val->uint64_val;
+  }
+}
+
+static void _upb_Decoder_Munge(int type, wireval* val) {
+  switch (type) {
+    case kUpb_FieldType_Bool:
+      val->bool_val = val->uint64_val != 0;
+      break;
+    case kUpb_FieldType_SInt32: {
+      uint32_t n = val->uint64_val;
+      val->uint32_val = (n >> 1) ^ -(int32_t)(n & 1);
+      break;
+    }
+    case kUpb_FieldType_SInt64: {
+      uint64_t n = val->uint64_val;
+      val->uint64_val = (n >> 1) ^ -(int64_t)(n & 1);
+      break;
+    }
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_UInt32:
+    case kUpb_FieldType_Enum:
+      _upb_Decoder_MungeInt32(val);
+      break;
+  }
+}
+
+static upb_Message* _upb_Decoder_NewSubMessage(
+    upb_Decoder* d, const upb_MiniTableSub* subs,
+    const upb_MiniTableField* field) {
+  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
+  UPB_ASSERT(subl);
+  upb_Message* msg = _upb_Message_New(subl, &d->arena);
+  if (!msg) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  return msg;
+}
+
+UPB_NOINLINE
+const char* _upb_Decoder_IsDoneFallback(upb_Decoder* d, const char* ptr,
+                                        int overrun) {
+  int status;
+  ptr = _upb_Decoder_IsDoneFallbackInline(d, ptr, overrun, &status);
+  if (ptr == NULL) _upb_Decoder_ErrorJmp(d, status);
+  return ptr;
+}
+
+static const char* _upb_Decoder_ReadString(upb_Decoder* d, const char* ptr,
+                                           int size, upb_StringView* str) {
+  if (d->options & kUpb_DecodeOption_AliasString) {
+    str->data = ptr;
+  } else {
+    char* data = upb_Arena_Malloc(&d->arena, size);
+    if (!data) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    memcpy(data, ptr, size);
+    str->data = data;
+  }
+  str->size = size;
+  return ptr + size;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_RecurseSubMessage(upb_Decoder* d,
+                                                  const char* ptr,
+                                                  upb_Message* submsg,
+                                                  const upb_MiniTable* subl,
+                                                  uint32_t expected_end_group) {
+  if (--d->depth < 0) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded);
+  }
+  ptr = _upb_Decoder_DecodeMessage(d, ptr, submsg, subl);
+  d->depth++;
+  if (d->end_group != expected_end_group) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeSubMessage(
+    upb_Decoder* d, const char* ptr, upb_Message* submsg,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field, int size) {
+  int saved_delta = _upb_Decoder_PushLimit(d, ptr, size);
+  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
+  UPB_ASSERT(subl);
+  ptr = _upb_Decoder_RecurseSubMessage(d, ptr, submsg, subl, DECODE_NOGROUP);
+  _upb_Decoder_PopLimit(d, ptr, saved_delta);
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeGroup(upb_Decoder* d, const char* ptr,
+                                            upb_Message* submsg,
+                                            const upb_MiniTable* subl,
+                                            uint32_t number) {
+  if (_upb_Decoder_IsDone(d, &ptr)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  ptr = _upb_Decoder_RecurseSubMessage(d, ptr, submsg, subl, number);
+  d->end_group = DECODE_NOGROUP;
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeUnknownGroup(upb_Decoder* d,
+                                                   const char* ptr,
+                                                   uint32_t number) {
+  return _upb_Decoder_DecodeGroup(d, ptr, NULL, NULL, number);
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeKnownGroup(
+    upb_Decoder* d, const char* ptr, upb_Message* submsg,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field) {
+  const upb_MiniTable* subl = subs[field->submsg_index].submsg;
+  UPB_ASSERT(subl);
+  return _upb_Decoder_DecodeGroup(d, ptr, submsg, subl, field->number);
+}
+
+static char* upb_Decoder_EncodeVarint32(uint32_t val, char* ptr) {
+  do {
+    uint8_t byte = val & 0x7fU;
+    val >>= 7;
+    if (val) byte |= 0x80U;
+    *(ptr++) = byte;
+  } while (val);
+  return ptr;
+}
+
+static void _upb_Decoder_AddUnknownVarints(upb_Decoder* d, upb_Message* msg,
+                                           uint32_t val1, uint32_t val2) {
+  char buf[20];
+  char* end = buf;
+  end = upb_Decoder_EncodeVarint32(val1, end);
+  end = upb_Decoder_EncodeVarint32(val2, end);
+
+  if (!_upb_Message_AddUnknown(msg, buf, end - buf, &d->arena)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+}
+
+UPB_NOINLINE
+static bool _upb_Decoder_CheckEnumSlow(upb_Decoder* d, const char* ptr,
+                                       upb_Message* msg,
+                                       const upb_MiniTableEnum* e,
+                                       const upb_MiniTableField* field,
+                                       uint32_t v) {
+  if (_upb_MiniTable_CheckEnumValueSlow(e, v)) return true;
+
+  // Unrecognized enum goes into unknown fields.
+  // For packed fields the tag could be arbitrarily far in the past, so we
+  // just re-encode the tag and value here.
+  uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Varint;
+  upb_Message* unknown_msg =
+      field->mode & kUpb_LabelFlags_IsExtension ? d->unknown_msg : msg;
+  _upb_Decoder_AddUnknownVarints(d, unknown_msg, tag, v);
+  return false;
+}
+
+UPB_FORCEINLINE
+static bool _upb_Decoder_CheckEnum(upb_Decoder* d, const char* ptr,
+                                   upb_Message* msg, const upb_MiniTableEnum* e,
+                                   const upb_MiniTableField* field,
+                                   wireval* val) {
+  uint32_t v = val->uint32_val;
+
+  _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, v);
+  if (UPB_LIKELY(status == _kUpb_FastEnumCheck_ValueIsInEnum)) return true;
+  return _upb_Decoder_CheckEnumSlow(d, ptr, msg, e, field, v);
+}
+
+UPB_NOINLINE
+static const char* _upb_Decoder_DecodeEnumArray(upb_Decoder* d, const char* ptr,
+                                                upb_Message* msg,
+                                                upb_Array* arr,
+                                                const upb_MiniTableSub* subs,
+                                                const upb_MiniTableField* field,
+                                                wireval* val) {
+  const upb_MiniTableEnum* e = subs[field->submsg_index].subenum;
+  if (!_upb_Decoder_CheckEnum(d, ptr, msg, e, field, val)) return ptr;
+  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->size * 4, void);
+  arr->size++;
+  memcpy(mem, val, 4);
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeFixedPacked(
+    upb_Decoder* d, const char* ptr, upb_Array* arr, wireval* val,
+    const upb_MiniTableField* field, int lg2) {
+  int mask = (1 << lg2) - 1;
+  size_t count = val->size >> lg2;
+  if ((val->size & mask) != 0) {
+    // Length isn't a round multiple of elem size.
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+  _upb_Decoder_Reserve(d, arr, count);
+  void* mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << lg2, void);
+  arr->size += count;
+  // Note: if/when the decoder supports multi-buffer input, we will need to
+  // handle buffer seams here.
+  if (_upb_IsLittleEndian()) {
+    memcpy(mem, ptr, val->size);
+    ptr += val->size;
+  } else {
+    const char* end = ptr + val->size;
+    char* dst = mem;
+    while (ptr < end) {
+      if (lg2 == 2) {
+        uint32_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap32(val);
+        memcpy(dst, &val, sizeof(val));
+      } else {
+        UPB_ASSERT(lg2 == 3);
+        uint64_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap64(val);
+        memcpy(dst, &val, sizeof(val));
+      }
+      ptr += 1 << lg2;
+      dst += 1 << lg2;
+    }
+  }
+
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeVarintPacked(
+    upb_Decoder* d, const char* ptr, upb_Array* arr, wireval* val,
+    const upb_MiniTableField* field, int lg2) {
+  int scale = 1 << lg2;
+  int saved_limit = _upb_Decoder_PushLimit(d, ptr, val->size);
+  char* out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << lg2, void);
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    wireval elem;
+    ptr = _upb_Decoder_DecodeVarint(d, ptr, &elem.uint64_val);
+    _upb_Decoder_Munge(field->descriptortype, &elem);
+    if (_upb_Decoder_Reserve(d, arr, 1)) {
+      out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << lg2, void);
+    }
+    arr->size++;
+    memcpy(out, &elem, scale);
+    out += scale;
+  }
+  _upb_Decoder_PopLimit(d, ptr, saved_limit);
+  return ptr;
+}
+
+UPB_NOINLINE
+static const char* _upb_Decoder_DecodeEnumPacked(
+    upb_Decoder* d, const char* ptr, upb_Message* msg, upb_Array* arr,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field,
+    wireval* val) {
+  const upb_MiniTableEnum* e = subs[field->submsg_index].subenum;
+  int saved_limit = _upb_Decoder_PushLimit(d, ptr, val->size);
+  char* out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size * 4, void);
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    wireval elem;
+    ptr = _upb_Decoder_DecodeVarint(d, ptr, &elem.uint64_val);
+    _upb_Decoder_MungeInt32(&elem);
+    if (!_upb_Decoder_CheckEnum(d, ptr, msg, e, field, &elem)) {
+      continue;
+    }
+    if (_upb_Decoder_Reserve(d, arr, 1)) {
+      out = UPB_PTR_AT(_upb_array_ptr(arr), arr->size * 4, void);
+    }
+    arr->size++;
+    memcpy(out, &elem, 4);
+    out += 4;
+  }
+  _upb_Decoder_PopLimit(d, ptr, saved_limit);
+  return ptr;
+}
+
+upb_Array* _upb_Decoder_CreateArray(upb_Decoder* d,
+                                    const upb_MiniTableField* field) {
+  /* Maps descriptor type -> elem_size_lg2.  */
+  static const uint8_t kElemSizeLg2[] = {
+      [0] = -1,  // invalid descriptor type
+      [kUpb_FieldType_Double] = 3,
+      [kUpb_FieldType_Float] = 2,
+      [kUpb_FieldType_Int64] = 3,
+      [kUpb_FieldType_UInt64] = 3,
+      [kUpb_FieldType_Int32] = 2,
+      [kUpb_FieldType_Fixed64] = 3,
+      [kUpb_FieldType_Fixed32] = 2,
+      [kUpb_FieldType_Bool] = 0,
+      [kUpb_FieldType_String] = UPB_SIZE(3, 4),
+      [kUpb_FieldType_Group] = UPB_SIZE(2, 3),
+      [kUpb_FieldType_Message] = UPB_SIZE(2, 3),
+      [kUpb_FieldType_Bytes] = UPB_SIZE(3, 4),
+      [kUpb_FieldType_UInt32] = 2,
+      [kUpb_FieldType_Enum] = 2,
+      [kUpb_FieldType_SFixed32] = 2,
+      [kUpb_FieldType_SFixed64] = 3,
+      [kUpb_FieldType_SInt32] = 2,
+      [kUpb_FieldType_SInt64] = 3,
+  };
+
+  size_t lg2 = kElemSizeLg2[field->descriptortype];
+  upb_Array* ret = _upb_Array_New(&d->arena, 4, lg2);
+  if (!ret) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  return ret;
+}
+
+static const char* _upb_Decoder_DecodeToArray(upb_Decoder* d, const char* ptr,
+                                              upb_Message* msg,
+                                              const upb_MiniTableSub* subs,
+                                              const upb_MiniTableField* field,
+                                              wireval* val, int op) {
+  upb_Array** arrp = UPB_PTR_AT(msg, field->offset, void);
+  upb_Array* arr = *arrp;
+  void* mem;
+
+  if (arr) {
+    _upb_Decoder_Reserve(d, arr, 1);
+  } else {
+    arr = _upb_Decoder_CreateArray(d, field);
+    *arrp = arr;
+  }
+
+  switch (op) {
+    case kUpb_DecodeOp_Scalar1Byte:
+    case kUpb_DecodeOp_Scalar4Byte:
+    case kUpb_DecodeOp_Scalar8Byte:
+      /* Append scalar value. */
+      mem = UPB_PTR_AT(_upb_array_ptr(arr), arr->size << op, void);
+      arr->size++;
+      memcpy(mem, val, 1 << op);
+      return ptr;
+    case kUpb_DecodeOp_String:
+      _upb_Decoder_VerifyUtf8(d, ptr, val->size);
+      /* Fallthrough. */
+    case kUpb_DecodeOp_Bytes: {
+      /* Append bytes. */
+      upb_StringView* str = (upb_StringView*)_upb_array_ptr(arr) + arr->size;
+      arr->size++;
+      return _upb_Decoder_ReadString(d, ptr, val->size, str);
+    }
+    case kUpb_DecodeOp_SubMessage: {
+      /* Append submessage / group. */
+      upb_Message* submsg = _upb_Decoder_NewSubMessage(d, subs, field);
+      *UPB_PTR_AT(_upb_array_ptr(arr), arr->size * sizeof(void*),
+                  upb_Message*) = submsg;
+      arr->size++;
+      if (UPB_UNLIKELY(field->descriptortype == kUpb_FieldType_Group)) {
+        return _upb_Decoder_DecodeKnownGroup(d, ptr, submsg, subs, field);
+      } else {
+        return _upb_Decoder_DecodeSubMessage(d, ptr, submsg, subs, field,
+                                             val->size);
+      }
+    }
+    case OP_FIXPCK_LG2(2):
+    case OP_FIXPCK_LG2(3):
+      return _upb_Decoder_DecodeFixedPacked(d, ptr, arr, val, field,
+                                            op - OP_FIXPCK_LG2(0));
+    case OP_VARPCK_LG2(0):
+    case OP_VARPCK_LG2(2):
+    case OP_VARPCK_LG2(3):
+      return _upb_Decoder_DecodeVarintPacked(d, ptr, arr, val, field,
+                                             op - OP_VARPCK_LG2(0));
+    case kUpb_DecodeOp_Enum:
+      return _upb_Decoder_DecodeEnumArray(d, ptr, msg, arr, subs, field, val);
+    case kUpb_DecodeOp_PackedEnum:
+      return _upb_Decoder_DecodeEnumPacked(d, ptr, msg, arr, subs, field, val);
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+upb_Map* _upb_Decoder_CreateMap(upb_Decoder* d, const upb_MiniTable* entry) {
+  /* Maps descriptor type -> upb map size.  */
+  static const uint8_t kSizeInMap[] = {
+      [0] = -1,  // invalid descriptor type */
+      [kUpb_FieldType_Double] = 8,
+      [kUpb_FieldType_Float] = 4,
+      [kUpb_FieldType_Int64] = 8,
+      [kUpb_FieldType_UInt64] = 8,
+      [kUpb_FieldType_Int32] = 4,
+      [kUpb_FieldType_Fixed64] = 8,
+      [kUpb_FieldType_Fixed32] = 4,
+      [kUpb_FieldType_Bool] = 1,
+      [kUpb_FieldType_String] = UPB_MAPTYPE_STRING,
+      [kUpb_FieldType_Group] = sizeof(void*),
+      [kUpb_FieldType_Message] = sizeof(void*),
+      [kUpb_FieldType_Bytes] = UPB_MAPTYPE_STRING,
+      [kUpb_FieldType_UInt32] = 4,
+      [kUpb_FieldType_Enum] = 4,
+      [kUpb_FieldType_SFixed32] = 4,
+      [kUpb_FieldType_SFixed64] = 8,
+      [kUpb_FieldType_SInt32] = 4,
+      [kUpb_FieldType_SInt64] = 8,
+  };
+
+  const upb_MiniTableField* key_field = &entry->fields[0];
+  const upb_MiniTableField* val_field = &entry->fields[1];
+  char key_size = kSizeInMap[key_field->descriptortype];
+  char val_size = kSizeInMap[val_field->descriptortype];
+  UPB_ASSERT(key_field->offset == offsetof(upb_MapEntryData, k));
+  UPB_ASSERT(val_field->offset == offsetof(upb_MapEntryData, v));
+  upb_Map* ret = _upb_Map_New(&d->arena, key_size, val_size);
+  if (!ret) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  return ret;
+}
+
+static const char* _upb_Decoder_DecodeToMap(upb_Decoder* d, const char* ptr,
+                                            upb_Message* msg,
+                                            const upb_MiniTableSub* subs,
+                                            const upb_MiniTableField* field,
+                                            wireval* val) {
+  upb_Map** map_p = UPB_PTR_AT(msg, field->offset, upb_Map*);
+  upb_Map* map = *map_p;
+  upb_MapEntry ent;
+  const upb_MiniTable* entry = subs[field->submsg_index].submsg;
+
+  if (!map) {
+    map = _upb_Decoder_CreateMap(d, entry);
+    *map_p = map;
+  }
+
+  /* Parse map entry. */
+  memset(&ent, 0, sizeof(ent));
+
+  if (entry->fields[1].descriptortype == kUpb_FieldType_Message ||
+      entry->fields[1].descriptortype == kUpb_FieldType_Group) {
+    /* Create proactively to handle the case where it doesn't appear. */
+    ent.data.v.val =
+        upb_value_ptr(_upb_Message_New(entry->subs[0].submsg, &d->arena));
+  }
+
+  const char* start = ptr;
+  ptr =
+      _upb_Decoder_DecodeSubMessage(d, ptr, &ent.data, subs, field, val->size);
+  // check if ent had any unknown fields
+  size_t size;
+  upb_Message_GetUnknown(&ent.data, &size);
+  if (size != 0) {
+    uint32_t tag = ((uint32_t)field->number << 3) | kUpb_WireType_Delimited;
+    _upb_Decoder_AddUnknownVarints(d, msg, tag, (uint32_t)(ptr - start));
+    if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+  } else {
+    if (_upb_Map_Insert(map, &ent.data.k, map->key_size, &ent.data.v,
+                        map->val_size,
+                        &d->arena) == kUpb_MapInsertStatus_OutOfMemory) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+  }
+  return ptr;
+}
+
+static const char* _upb_Decoder_DecodeToSubMessage(
+    upb_Decoder* d, const char* ptr, upb_Message* msg,
+    const upb_MiniTableSub* subs, const upb_MiniTableField* field, wireval* val,
+    int op) {
+  void* mem = UPB_PTR_AT(msg, field->offset, void);
+  int type = field->descriptortype;
+
+  if (UPB_UNLIKELY(op == kUpb_DecodeOp_Enum) &&
+      !_upb_Decoder_CheckEnum(d, ptr, msg, subs[field->submsg_index].subenum,
+                              field, val)) {
+    return ptr;
+  }
+
+  /* Set presence if necessary. */
+  if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  } else if (field->presence < 0) {
+    /* Oneof case */
+    uint32_t* oneof_case = _upb_oneofcase_field(msg, field);
+    if (op == kUpb_DecodeOp_SubMessage && *oneof_case != field->number) {
+      memset(mem, 0, sizeof(void*));
+    }
+    *oneof_case = field->number;
+  }
+
+  /* Store into message. */
+  switch (op) {
+    case kUpb_DecodeOp_SubMessage: {
+      upb_Message** submsgp = mem;
+      upb_Message* submsg = *submsgp;
+      if (!submsg) {
+        submsg = _upb_Decoder_NewSubMessage(d, subs, field);
+        *submsgp = submsg;
+      }
+      if (UPB_UNLIKELY(type == kUpb_FieldType_Group)) {
+        ptr = _upb_Decoder_DecodeKnownGroup(d, ptr, submsg, subs, field);
+      } else {
+        ptr = _upb_Decoder_DecodeSubMessage(d, ptr, submsg, subs, field,
+                                            val->size);
+      }
+      break;
+    }
+    case kUpb_DecodeOp_String:
+      _upb_Decoder_VerifyUtf8(d, ptr, val->size);
+      /* Fallthrough. */
+    case kUpb_DecodeOp_Bytes:
+      return _upb_Decoder_ReadString(d, ptr, val->size, mem);
+    case kUpb_DecodeOp_Scalar8Byte:
+      memcpy(mem, val, 8);
+      break;
+    case kUpb_DecodeOp_Enum:
+    case kUpb_DecodeOp_Scalar4Byte:
+      memcpy(mem, val, 4);
+      break;
+    case kUpb_DecodeOp_Scalar1Byte:
+      memcpy(mem, val, 1);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+
+  return ptr;
+}
+
+UPB_NOINLINE
+const char* _upb_Decoder_CheckRequired(upb_Decoder* d, const char* ptr,
+                                       const upb_Message* msg,
+                                       const upb_MiniTable* l) {
+  assert(l->required_count);
+  if (UPB_LIKELY((d->options & kUpb_DecodeOption_CheckRequired) == 0)) {
+    return ptr;
+  }
+  uint64_t msg_head;
+  memcpy(&msg_head, msg, 8);
+  msg_head = _upb_BigEndian_Swap64(msg_head);
+  if (upb_MiniTable_requiredmask(l) & ~msg_head) {
+    d->missing_required = true;
+  }
+  return ptr;
+}
+
+UPB_FORCEINLINE
+static bool _upb_Decoder_TryFastDispatch(upb_Decoder* d, const char** ptr,
+                                         upb_Message* msg,
+                                         const upb_MiniTable* layout) {
+#if UPB_FASTTABLE
+  if (layout && layout->table_mask != (unsigned char)-1) {
+    uint16_t tag = _upb_FastDecoder_LoadTag(*ptr);
+    intptr_t table = decode_totable(layout);
+    *ptr = _upb_FastDecoder_TagDispatch(d, *ptr, msg, table, 0, tag);
+    return true;
+  }
+#endif
+  return false;
+}
+
+static const char* upb_Decoder_SkipField(upb_Decoder* d, const char* ptr,
+                                         uint32_t tag) {
+  int field_number = tag >> 3;
+  int wire_type = tag & 7;
+  switch (wire_type) {
+    case kUpb_WireType_Varint: {
+      uint64_t val;
+      return _upb_Decoder_DecodeVarint(d, ptr, &val);
+    }
+    case kUpb_WireType_64Bit:
+      return ptr + 8;
+    case kUpb_WireType_32Bit:
+      return ptr + 4;
+    case kUpb_WireType_Delimited: {
+      uint32_t size;
+      ptr = upb_Decoder_DecodeSize(d, ptr, &size);
+      return ptr + size;
+    }
+    case kUpb_WireType_StartGroup:
+      return _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number);
+    default:
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+  }
+}
+
+enum {
+  kStartItemTag = ((kUpb_MsgSet_Item << 3) | kUpb_WireType_StartGroup),
+  kEndItemTag = ((kUpb_MsgSet_Item << 3) | kUpb_WireType_EndGroup),
+  kTypeIdTag = ((kUpb_MsgSet_TypeId << 3) | kUpb_WireType_Varint),
+  kMessageTag = ((kUpb_MsgSet_Message << 3) | kUpb_WireType_Delimited),
+};
+
+static void upb_Decoder_AddKnownMessageSetItem(
+    upb_Decoder* d, upb_Message* msg, const upb_MiniTableExtension* item_mt,
+    const char* data, uint32_t size) {
+  upb_Message_Extension* ext =
+      _upb_Message_GetOrCreateExtension(msg, item_mt, &d->arena);
+  if (UPB_UNLIKELY(!ext)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+  upb_Message* submsg =
+      _upb_Decoder_NewSubMessage(d, &ext->ext->sub, &ext->ext->field);
+  upb_DecodeStatus status = upb_Decode(data, size, submsg, item_mt->sub.submsg,
+                                       d->extreg, d->options, &d->arena);
+  memcpy(&ext->data, &submsg, sizeof(submsg));
+  if (status != kUpb_DecodeStatus_Ok) _upb_Decoder_ErrorJmp(d, status);
+}
+
+static void upb_Decoder_AddUnknownMessageSetItem(upb_Decoder* d,
+                                                 upb_Message* msg,
+                                                 uint32_t type_id,
+                                                 const char* message_data,
+                                                 uint32_t message_size) {
+  char buf[60];
+  char* ptr = buf;
+  ptr = upb_Decoder_EncodeVarint32(kStartItemTag, ptr);
+  ptr = upb_Decoder_EncodeVarint32(kTypeIdTag, ptr);
+  ptr = upb_Decoder_EncodeVarint32(type_id, ptr);
+  ptr = upb_Decoder_EncodeVarint32(kMessageTag, ptr);
+  ptr = upb_Decoder_EncodeVarint32(message_size, ptr);
+  char* split = ptr;
+
+  ptr = upb_Decoder_EncodeVarint32(kEndItemTag, ptr);
+  char* end = ptr;
+
+  if (!_upb_Message_AddUnknown(msg, buf, split - buf, &d->arena) ||
+      !_upb_Message_AddUnknown(msg, message_data, message_size, &d->arena) ||
+      !_upb_Message_AddUnknown(msg, split, end - split, &d->arena)) {
+    _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+  }
+}
+
+static void upb_Decoder_AddMessageSetItem(upb_Decoder* d, upb_Message* msg,
+                                          const upb_MiniTable* t,
+                                          uint32_t type_id, const char* data,
+                                          uint32_t size) {
+  const upb_MiniTableExtension* item_mt =
+      upb_ExtensionRegistry_Lookup(d->extreg, t, type_id);
+  if (item_mt) {
+    upb_Decoder_AddKnownMessageSetItem(d, msg, item_mt, data, size);
+  } else {
+    upb_Decoder_AddUnknownMessageSetItem(d, msg, type_id, data, size);
+  }
+}
+
+static const char* upb_Decoder_DecodeMessageSetItem(
+    upb_Decoder* d, const char* ptr, upb_Message* msg,
+    const upb_MiniTable* layout) {
+  uint32_t type_id = 0;
+  upb_StringView preserved = {NULL, 0};
+  typedef enum {
+    kUpb_HaveId = 1 << 0,
+    kUpb_HavePayload = 1 << 1,
+  } StateMask;
+  StateMask state_mask = 0;
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    uint32_t tag;
+    ptr = _upb_Decoder_DecodeTag(d, ptr, &tag);
+    switch (tag) {
+      case kEndItemTag:
+        return ptr;
+      case kTypeIdTag: {
+        uint64_t tmp;
+        ptr = _upb_Decoder_DecodeVarint(d, ptr, &tmp);
+        if (state_mask & kUpb_HaveId) break;  // Ignore dup.
+        state_mask |= kUpb_HaveId;
+        type_id = tmp;
+        if (state_mask & kUpb_HavePayload) {
+          upb_Decoder_AddMessageSetItem(d, msg, layout, type_id, preserved.data,
+                                        preserved.size);
+        }
+        break;
+      }
+      case kMessageTag: {
+        uint32_t size;
+        ptr = upb_Decoder_DecodeSize(d, ptr, &size);
+        const char* data = ptr;
+        ptr += size;
+        if (state_mask & kUpb_HavePayload) break;  // Ignore dup.
+        state_mask |= kUpb_HavePayload;
+        if (state_mask & kUpb_HaveId) {
+          upb_Decoder_AddMessageSetItem(d, msg, layout, type_id, data, size);
+        } else {
+          // Out of order, we must preserve the payload.
+          preserved.data = data;
+          preserved.size = size;
+        }
+        break;
+      }
+      default:
+        // We do not preserve unexpected fields inside a message set item.
+        ptr = upb_Decoder_SkipField(d, ptr, tag);
+        break;
+    }
+  }
+  _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+}
+
+static const upb_MiniTableField* _upb_Decoder_FindField(upb_Decoder* d,
+                                                        const upb_MiniTable* t,
+                                                        uint32_t field_number,
+                                                        int* last_field_index) {
+  static upb_MiniTableField none = {
+      0, 0, 0, 0, kUpb_FakeFieldType_FieldNotFound, 0};
+  if (t == NULL) return &none;
+
+  size_t idx = ((size_t)field_number) - 1;  // 0 wraps to SIZE_MAX
+  if (idx < t->dense_below) {
+    /* Fastest case: index into dense fields. */
+    goto found;
+  }
+
+  if (t->dense_below < t->field_count) {
+    /* Linear search non-dense fields. Resume scanning from last_field_index
+     * since fields are usually in order. */
+    int last = *last_field_index;
+    for (idx = last; idx < t->field_count; idx++) {
+      if (t->fields[idx].number == field_number) {
+        goto found;
+      }
+    }
+
+    for (idx = t->dense_below; idx < last; idx++) {
+      if (t->fields[idx].number == field_number) {
+        goto found;
+      }
+    }
+  }
+
+  if (d->extreg) {
+    switch (t->ext) {
+      case kUpb_ExtMode_Extendable: {
+        const upb_MiniTableExtension* ext =
+            upb_ExtensionRegistry_Lookup(d->extreg, t, field_number);
+        if (ext) return &ext->field;
+        break;
+      }
+      case kUpb_ExtMode_IsMessageSet:
+        if (field_number == kUpb_MsgSet_Item) {
+          static upb_MiniTableField item = {
+              0, 0, 0, 0, kUpb_FakeFieldType_MessageSetItem, 0};
+          return &item;
+        }
+        break;
+    }
+  }
+
+  return &none; /* Unknown field. */
+
+found:
+  UPB_ASSERT(t->fields[idx].number == field_number);
+  *last_field_index = idx;
+  return &t->fields[idx];
+}
+
+int _upb_Decoder_GetVarintOp(const upb_MiniTableField* field) {
+  static const int8_t kVarintOps[] = {
+      [kUpb_FakeFieldType_FieldNotFound] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Double] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Float] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Int64] = kUpb_DecodeOp_Scalar8Byte,
+      [kUpb_FieldType_UInt64] = kUpb_DecodeOp_Scalar8Byte,
+      [kUpb_FieldType_Int32] = kUpb_DecodeOp_Scalar4Byte,
+      [kUpb_FieldType_Fixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Fixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Bool] = kUpb_DecodeOp_Scalar1Byte,
+      [kUpb_FieldType_String] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Group] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Message] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Bytes] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_UInt32] = kUpb_DecodeOp_Scalar4Byte,
+      [kUpb_FieldType_Enum] = kUpb_DecodeOp_Enum,
+      [kUpb_FieldType_SFixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SFixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SInt32] = kUpb_DecodeOp_Scalar4Byte,
+      [kUpb_FieldType_SInt64] = kUpb_DecodeOp_Scalar8Byte,
+      [kUpb_FakeFieldType_MessageSetItem] = kUpb_DecodeOp_UnknownField,
+  };
+
+  return kVarintOps[field->descriptortype];
+}
+
+int _upb_Decoder_GetDelimitedOp(const upb_MiniTable* mt,
+                                const upb_MiniTableField* field) {
+  enum { kRepeatedBase = 19 };
+
+  static const int8_t kDelimitedOps[] = {
+      /* For non-repeated field type. */
+      [kUpb_FakeFieldType_FieldNotFound] =
+          kUpb_DecodeOp_UnknownField,  // Field not found.
+      [kUpb_FieldType_Double] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Float] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Int64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_UInt64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Int32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Fixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Fixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Bool] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_String] = kUpb_DecodeOp_String,
+      [kUpb_FieldType_Group] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Message] = kUpb_DecodeOp_SubMessage,
+      [kUpb_FieldType_Bytes] = kUpb_DecodeOp_Bytes,
+      [kUpb_FieldType_UInt32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_Enum] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SFixed32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SFixed64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SInt32] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FieldType_SInt64] = kUpb_DecodeOp_UnknownField,
+      [kUpb_FakeFieldType_MessageSetItem] = kUpb_DecodeOp_UnknownField,
+      // For repeated field type. */
+      [kRepeatedBase + kUpb_FieldType_Double] = OP_FIXPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_Float] = OP_FIXPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Int64] = OP_VARPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_UInt64] = OP_VARPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_Int32] = OP_VARPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Fixed64] = OP_FIXPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_Fixed32] = OP_FIXPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Bool] = OP_VARPCK_LG2(0),
+      [kRepeatedBase + kUpb_FieldType_String] = kUpb_DecodeOp_String,
+      [kRepeatedBase + kUpb_FieldType_Group] = kUpb_DecodeOp_SubMessage,
+      [kRepeatedBase + kUpb_FieldType_Message] = kUpb_DecodeOp_SubMessage,
+      [kRepeatedBase + kUpb_FieldType_Bytes] = kUpb_DecodeOp_Bytes,
+      [kRepeatedBase + kUpb_FieldType_UInt32] = OP_VARPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_Enum] = kUpb_DecodeOp_PackedEnum,
+      [kRepeatedBase + kUpb_FieldType_SFixed32] = OP_FIXPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_SFixed64] = OP_FIXPCK_LG2(3),
+      [kRepeatedBase + kUpb_FieldType_SInt32] = OP_VARPCK_LG2(2),
+      [kRepeatedBase + kUpb_FieldType_SInt64] = OP_VARPCK_LG2(3),
+      // Omitting kUpb_FakeFieldType_MessageSetItem, because we never emit a
+      // repeated msgset type
+  };
+
+  int ndx = field->descriptortype;
+  if (upb_FieldMode_Get(field) == kUpb_FieldMode_Array) ndx += kRepeatedBase;
+  int op = kDelimitedOps[ndx];
+
+  // If sub-message is not linked, treat as unknown.
+  if (op == kUpb_DecodeOp_SubMessage &&
+      !(field->mode & kUpb_LabelFlags_IsExtension)) {
+    const upb_MiniTableSub* sub = &mt->subs[field->submsg_index];
+    if (!sub->submsg) {
+      op = kUpb_DecodeOp_UnknownField;
+    }
+  }
+
+  return op;
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeWireValue(upb_Decoder* d, const char* ptr,
+                                                const upb_MiniTable* mt,
+                                                const upb_MiniTableField* field,
+                                                int wire_type, wireval* val,
+                                                int* op) {
+  static const unsigned kFixed32OkMask = (1 << kUpb_FieldType_Float) |
+                                         (1 << kUpb_FieldType_Fixed32) |
+                                         (1 << kUpb_FieldType_SFixed32);
+
+  static const unsigned kFixed64OkMask = (1 << kUpb_FieldType_Double) |
+                                         (1 << kUpb_FieldType_Fixed64) |
+                                         (1 << kUpb_FieldType_SFixed64);
+
+  switch (wire_type) {
+    case kUpb_WireType_Varint:
+      ptr = _upb_Decoder_DecodeVarint(d, ptr, &val->uint64_val);
+      *op = _upb_Decoder_GetVarintOp(field);
+      _upb_Decoder_Munge(field->descriptortype, val);
+      return ptr;
+    case kUpb_WireType_32Bit:
+      memcpy(&val->uint32_val, ptr, 4);
+      val->uint32_val = _upb_BigEndian_Swap32(val->uint32_val);
+      *op = kUpb_DecodeOp_Scalar4Byte;
+      if (((1 << field->descriptortype) & kFixed32OkMask) == 0) {
+        *op = kUpb_DecodeOp_UnknownField;
+      }
+      return ptr + 4;
+    case kUpb_WireType_64Bit:
+      memcpy(&val->uint64_val, ptr, 8);
+      val->uint64_val = _upb_BigEndian_Swap64(val->uint64_val);
+      *op = kUpb_DecodeOp_Scalar8Byte;
+      if (((1 << field->descriptortype) & kFixed64OkMask) == 0) {
+        *op = kUpb_DecodeOp_UnknownField;
+      }
+      return ptr + 8;
+    case kUpb_WireType_Delimited:
+      ptr = upb_Decoder_DecodeSize(d, ptr, &val->size);
+      *op = _upb_Decoder_GetDelimitedOp(mt, field);
+      return ptr;
+    case kUpb_WireType_StartGroup:
+      val->uint32_val = field->number;
+      if (field->descriptortype == kUpb_FieldType_Group) {
+        *op = kUpb_DecodeOp_SubMessage;
+      } else if (field->descriptortype == kUpb_FakeFieldType_MessageSetItem) {
+        *op = kUpb_DecodeOp_MessageSetItem;
+      } else {
+        *op = kUpb_DecodeOp_UnknownField;
+      }
+      return ptr;
+    default:
+      break;
+  }
+  _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+}
+
+UPB_FORCEINLINE
+static const char* _upb_Decoder_DecodeKnownField(
+    upb_Decoder* d, const char* ptr, upb_Message* msg,
+    const upb_MiniTable* layout, const upb_MiniTableField* field, int op,
+    wireval* val) {
+  const upb_MiniTableSub* subs = layout->subs;
+  uint8_t mode = field->mode;
+
+  if (UPB_UNLIKELY(mode & kUpb_LabelFlags_IsExtension)) {
+    const upb_MiniTableExtension* ext_layout =
+        (const upb_MiniTableExtension*)field;
+    upb_Message_Extension* ext =
+        _upb_Message_GetOrCreateExtension(msg, ext_layout, &d->arena);
+    if (UPB_UNLIKELY(!ext)) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+    d->unknown_msg = msg;
+    msg = &ext->data;
+    subs = &ext->ext->sub;
+  }
+
+  switch (mode & kUpb_FieldMode_Mask) {
+    case kUpb_FieldMode_Array:
+      return _upb_Decoder_DecodeToArray(d, ptr, msg, subs, field, val, op);
+    case kUpb_FieldMode_Map:
+      return _upb_Decoder_DecodeToMap(d, ptr, msg, subs, field, val);
+    case kUpb_FieldMode_Scalar:
+      return _upb_Decoder_DecodeToSubMessage(d, ptr, msg, subs, field, val, op);
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+static const char* _upb_Decoder_ReverseSkipVarint(const char* ptr,
+                                                  uint32_t val) {
+  uint32_t seen = 0;
+  do {
+    ptr--;
+    seen <<= 7;
+    seen |= *ptr & 0x7f;
+  } while (seen != val);
+  return ptr;
+}
+
+static const char* _upb_Decoder_DecodeUnknownField(upb_Decoder* d,
+                                                   const char* ptr,
+                                                   upb_Message* msg,
+                                                   int field_number,
+                                                   int wire_type, wireval val) {
+  if (field_number == 0) _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);
+
+  // Since unknown fields are the uncommon case, we do a little extra work here
+  // to walk backwards through the buffer to find the field start.  This frees
+  // up a register in the fast paths (when the field is known), which leads to
+  // significant speedups in benchmarks.
+  const char* start = ptr;
+
+  if (wire_type == kUpb_WireType_Delimited) ptr += val.size;
+  if (msg) {
+    switch (wire_type) {
+      case kUpb_WireType_Varint:
+      case kUpb_WireType_Delimited:
+        start--;
+        while (start[-1] & 0x80) start--;
+        break;
+      case kUpb_WireType_32Bit:
+        start -= 4;
+        break;
+      case kUpb_WireType_64Bit:
+        start -= 8;
+        break;
+      default:
+        break;
+    }
+
+    assert(start == d->debug_valstart);
+    uint32_t tag = ((uint32_t)field_number << 3) | wire_type;
+    start = _upb_Decoder_ReverseSkipVarint(start, tag);
+    assert(start == d->debug_tagstart);
+
+    if (wire_type == kUpb_WireType_StartGroup) {
+      d->unknown = start;
+      d->unknown_msg = msg;
+      ptr = _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number);
+      start = d->unknown;
+      d->unknown = NULL;
+    }
+    if (!_upb_Message_AddUnknown(msg, start, ptr - start, &d->arena)) {
+      _upb_Decoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);
+    }
+  } else if (wire_type == kUpb_WireType_StartGroup) {
+    ptr = _upb_Decoder_DecodeUnknownGroup(d, ptr, field_number);
+  }
+  return ptr;
+}
+
+UPB_NOINLINE
+static const char* _upb_Decoder_DecodeMessage(upb_Decoder* d, const char* ptr,
+                                              upb_Message* msg,
+                                              const upb_MiniTable* layout) {
+  int last_field_index = 0;
+
+#if UPB_FASTTABLE
+  // The first time we want to skip fast dispatch, because we may have just been
+  // invoked by the fast parser to handle a case that it bailed on.
+  if (!_upb_Decoder_IsDone(d, &ptr)) goto nofast;
+#endif
+
+  while (!_upb_Decoder_IsDone(d, &ptr)) {
+    uint32_t tag;
+    const upb_MiniTableField* field;
+    int field_number;
+    int wire_type;
+    wireval val;
+    int op;
+
+    if (_upb_Decoder_TryFastDispatch(d, &ptr, msg, layout)) break;
+
+#if UPB_FASTTABLE
+  nofast:
+#endif
+
+#ifndef NDEBUG
+    d->debug_tagstart = ptr;
+#endif
+
+    UPB_ASSERT(ptr < d->limit_ptr);
+    ptr = _upb_Decoder_DecodeTag(d, ptr, &tag);
+    field_number = tag >> 3;
+    wire_type = tag & 7;
+
+#ifndef NDEBUG
+    d->debug_valstart = ptr;
+#endif
+
+    if (wire_type == kUpb_WireType_EndGroup) {
+      d->end_group = field_number;
+      return ptr;
+    }
+
+    field = _upb_Decoder_FindField(d, layout, field_number, &last_field_index);
+    ptr = _upb_Decoder_DecodeWireValue(d, ptr, layout, field, wire_type, &val,
+                                       &op);
+
+    if (op >= 0) {
+      ptr = _upb_Decoder_DecodeKnownField(d, ptr, msg, layout, field, op, &val);
+    } else {
+      switch (op) {
+        case kUpb_DecodeOp_UnknownField:
+          ptr = _upb_Decoder_DecodeUnknownField(d, ptr, msg, field_number,
+                                                wire_type, val);
+          break;
+        case kUpb_DecodeOp_MessageSetItem:
+          ptr = upb_Decoder_DecodeMessageSetItem(d, ptr, msg, layout);
+          break;
+      }
+    }
+  }
+
+  return UPB_UNLIKELY(layout && layout->required_count)
+             ? _upb_Decoder_CheckRequired(d, ptr, msg, layout)
+             : ptr;
+}
+
+const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d,
+                                           const char* ptr, upb_Message* msg,
+                                           intptr_t table, uint64_t hasbits,
+                                           uint64_t data) {
+  (void)data;
+  *(uint32_t*)msg |= hasbits;
+  return _upb_Decoder_DecodeMessage(d, ptr, msg, decode_totablep(table));
+}
+
+static upb_DecodeStatus _upb_Decoder_DecodeTop(struct upb_Decoder* d,
+                                               const char* buf, void* msg,
+                                               const upb_MiniTable* l) {
+  if (!_upb_Decoder_TryFastDispatch(d, &buf, msg, l)) {
+    _upb_Decoder_DecodeMessage(d, buf, msg, l);
+  }
+  if (d->end_group != DECODE_NOGROUP) return kUpb_DecodeStatus_Malformed;
+  if (d->missing_required) return kUpb_DecodeStatus_MissingRequired;
+  return kUpb_DecodeStatus_Ok;
+}
+
+upb_DecodeStatus upb_Decode(const char* buf, size_t size, void* msg,
+                            const upb_MiniTable* l,
+                            const upb_ExtensionRegistry* extreg, int options,
+                            upb_Arena* arena) {
+  upb_Decoder state;
+  unsigned depth = (unsigned)options >> 16;
+
+  if (size <= 16) {
+    memset(&state.patch, 0, 32);
+    if (size) memcpy(&state.patch, buf, size);
+    buf = state.patch;
+    state.end = buf + size;
+    state.limit = 0;
+    options &= ~kUpb_DecodeOption_AliasString;  // Can't alias patch buf.
+  } else {
+    state.end = buf + size - 16;
+    state.limit = 16;
+  }
+
+  state.extreg = extreg;
+  state.limit_ptr = state.end;
+  state.unknown = NULL;
+  state.depth = depth ? depth : 64;
+  state.end_group = DECODE_NOGROUP;
+  state.options = (uint16_t)options;
+  state.missing_required = false;
+  state.arena.head = arena->head;
+  state.arena.last_size = arena->last_size;
+  state.arena.cleanup_metadata = arena->cleanup_metadata;
+  state.arena.parent = arena;
+
+  upb_DecodeStatus status = UPB_SETJMP(state.err);
+  if (UPB_LIKELY(status == kUpb_DecodeStatus_Ok)) {
+    status = _upb_Decoder_DecodeTop(&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 status;
+}
+
+#undef OP_FIXPCK_LG2
+#undef OP_VARPCK_LG2
+
+// 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_Decoder *d, const char *ptr, upb_Message *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 _upb_FastDecoder_DecodeGeneric(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;
+  int status;
+  ptr = _upb_Decoder_IsDoneFallbackInline(d, ptr, overrun, &status);
+  if (ptr == NULL) _upb_FastDecoder_ErrorJmp(d, status);
+  data = _upb_FastDecoder_LoadTag(ptr);
+  UPB_MUSTTAIL return _upb_FastDecoder_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.
+      const upb_MiniTable* l = decode_totablep(table);
+      return UPB_UNLIKELY(l->required_count)
+                 ? _upb_Decoder_CheckRequired(d, ptr, msg, l)
+                 : 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 = _upb_FastDecoder_LoadTag(ptr);
+  UPB_MUSTTAIL return _upb_FastDecoder_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_Decoder* d, const char* ptr,
+                                         void* ctx);
+
+UPB_FORCEINLINE
+static const char* fastdecode_delimited(upb_Decoder* 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 = _upb_Decoder_PushLimit(d, ptr, len);
+    ptr = func(d, ptr, ctx);
+    _upb_Decoder_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_Decoder* d, void* dst,
+                                  fastdecode_arr* farr, int valbytes) {
+  if (UPB_UNLIKELY(dst == farr->end)) {
+    size_t old_size = farr->arr->capacity;
+    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->capacity = 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->size =
+      (size_t)((char*)dst - (char*)_upb_array_ptr(farr->arr)) / valbytes;
+}
+
+UPB_FORCEINLINE
+static fastdecode_nextret fastdecode_nextrepeated(upb_Decoder* 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(!_upb_Decoder_IsDone(d, ptr))) {
+    ret.tag = _upb_FastDecoder_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_Message* msg, uint64_t data) {
+  size_t ofs = data >> 48;
+  return (char*)msg + ofs;
+}
+
+UPB_FORCEINLINE
+static void* fastdecode_getfield(upb_Decoder* d, const char* ptr,
+                                 upb_Message* 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->capacity * valbytes);
+      *data = _upb_FastDecoder_LoadTag(ptr);
+      return begin + (farr->arr->size * 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) _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);  \
+  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 _upb_FastDecoder_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_Decoder* d, const char* ptr,
+                                             void* ctx) {
+  fastdecode_varintdata* data = ctx;
+  void* dst = data->dst;
+  uint64_t val;
+
+  while (!_upb_Decoder_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)) {                                           \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);               \
+  }                                                                          \
+                                                                             \
+  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 _upb_FastDecoder_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)) {                               \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);              \
+  }                                                                         \
+                                                                            \
+  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) {                                                             \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);            \
+    }                                                                       \
+  } else {                                                                  \
+    _upb_Array_Resize(arr, elems, &d->arena);                               \
+  }                                                                         \
+                                                                            \
+  char* dst = _upb_array_ptr(arr);                                          \
+  memcpy(dst, ptr, size);                                                   \
+  arr->size = 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_Decoder* d,
+                                            const char* ptr, upb_Message* msg,
+                                            const upb_MiniTable* table,
+                                            uint64_t hasbits,
+                                            upb_StringView* dst);
+
+UPB_NOINLINE
+static const char* fastdecode_verifyutf8(upb_Decoder* d, const char* ptr,
+                                         upb_Message* msg, intptr_t table,
+                                         uint64_t hasbits, uint64_t data) {
+  upb_StringView* dst = (upb_StringView*)data;
+  if (!_upb_Decoder_VerifyUtf8Inline(dst->data, dst->size)) {
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);
+  }
+  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;                                                             \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);                 \
+  }                                                                            \
+                                                                               \
+  if (d->options & kUpb_DecodeOption_AliasString) {                            \
+    dst->data = ptr;                                                           \
+    dst->size = size;                                                          \
+  } else {                                                                     \
+    char* data = upb_Arena_Malloc(&d->arena, size);                            \
+    if (!data) {                                                               \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_OutOfMemory);             \
+    }                                                                          \
+    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_Decoder* d,
+                                              const char* ptr, upb_Message* msg,
+                                              intptr_t table, uint64_t hasbits,
+                                              uint64_t data) {
+  upb_StringView* dst = (upb_StringView*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, true);
+}
+
+UPB_NOINLINE
+static const char* fastdecode_longstring_noutf8(
+    struct upb_Decoder* d, const char* ptr, upb_Message* msg, intptr_t table,
+    uint64_t hasbits, uint64_t data) {
+  upb_StringView* dst = (upb_StringView*)data;
+  FASTDECODE_LONGSTRING(d, ptr, msg, table, hasbits, dst, false);
+}
+
+UPB_FORCEINLINE
+static void fastdecode_docopy(upb_Decoder* d, const char* ptr, uint32_t size,
+                              int copy, char* data, upb_StringView* 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_StringView* dst;                                                        \
+  fastdecode_arr farr;                                                        \
+  int64_t size;                                                               \
+  size_t arena_has;                                                           \
+  size_t common_has;                                                          \
+  char* buf;                                                                  \
+                                                                              \
+  UPB_ASSERT((d->options & kUpb_DecodeOption_AliasString) == 0);              \
+  UPB_ASSERT(fastdecode_checktag(data, tagbytes));                            \
+                                                                              \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,              \
+                            sizeof(upb_StringView), card);                    \
+                                                                              \
+  again:                                                                      \
+  if (card == CARD_r) {                                                       \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));        \
+  }                                                                           \
+                                                                              \
+  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 &&                                                      \
+        !_upb_Decoder_VerifyUtf8Inline(dst->data, dst->size)) {               \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);                \
+    }                                                                         \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                         \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));         \
+    switch (ret.next) {                                                       \
+      case FD_NEXT_SAMEFIELD:                                                 \
+        dst = ret.dst;                                                        \
+        goto again;                                                           \
+      case FD_NEXT_OTHERFIELD:                                                \
+        data = ret.tag;                                                       \
+        UPB_MUSTTAIL return _upb_FastDecoder_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:                                                                    \
+  if (card == CARD_r) {                                                       \
+    fastdecode_commitarr(dst + 1, &farr, sizeof(upb_StringView));             \
+  }                                                                           \
+  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_StringView* 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->options & kUpb_DecodeOption_AliasString) == 0)) {       \
+    UPB_MUSTTAIL return copyfunc(UPB_PARSE_ARGS);                              \
+  }                                                                            \
+                                                                               \
+  dst = fastdecode_getfield(d, ptr, msg, &data, &hasbits, &farr,               \
+                            sizeof(upb_StringView), card);                     \
+                                                                               \
+  again:                                                                       \
+  if (card == CARD_r) {                                                        \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_StringView));         \
+  }                                                                            \
+                                                                               \
+  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 &&                                                       \
+        !_upb_Decoder_VerifyUtf8Inline(dst->data, dst->size)) {                \
+      _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_BadUtf8);                 \
+    }                                                                          \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                          \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_StringView));          \
+    switch (ret.next) {                                                        \
+      case FD_NEXT_SAMEFIELD:                                                  \
+        dst = ret.dst;                                                         \
+        if (UPB_UNLIKELY((d->options & kUpb_DecodeOption_AliasString) == 0)) { \
+          /* 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_StringView));            \
+          data = ret.tag;                                                      \
+          UPB_MUSTTAIL return _upb_FastDecoder_TagDispatch(UPB_PARSE_ARGS);    \
+        }                                                                      \
+        goto again;                                                            \
+      case FD_NEXT_OTHERFIELD:                                                 \
+        data = ret.tag;                                                        \
+        UPB_MUSTTAIL return _upb_FastDecoder_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_Message* decode_newmsg_ceil(upb_Decoder* d, const upb_MiniTable* l,
+                                int msg_ceil_bytes) {
+  size_t size = l->size + sizeof(upb_Message_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_Message_Internal);
+}
+
+typedef struct {
+  intptr_t table;
+  upb_Message* msg;
+} fastdecode_submsgdata;
+
+UPB_FORCEINLINE
+static const char* fastdecode_tosubmsg(upb_Decoder* 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) {                                                  \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_MaxDepthExceeded);     \
+  }                                                                       \
+                                                                          \
+  upb_Message** dst;                                                      \
+  uint32_t submsg_idx = (data >> 16) & 0xff;                              \
+  const upb_MiniTable* tablep = decode_totablep(table);                   \
+  const upb_MiniTable* subtablep = tablep->subs[submsg_idx].submsg;       \
+  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_Message*), card);                  \
+                                                                          \
+  if (card == CARD_s) {                                                   \
+    *(uint32_t*)msg |= hasbits;                                           \
+    hasbits = 0;                                                          \
+  }                                                                       \
+                                                                          \
+  again:                                                                  \
+  if (card == CARD_r) {                                                   \
+    dst = fastdecode_resizearr(d, dst, &farr, sizeof(upb_Message*));      \
+  }                                                                       \
+                                                                          \
+  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)) {      \
+    _upb_FastDecoder_ErrorJmp(d, kUpb_DecodeStatus_Malformed);            \
+  }                                                                       \
+                                                                          \
+  if (card == CARD_r) {                                                   \
+    fastdecode_nextret ret = fastdecode_nextrepeated(                     \
+        d, dst, &ptr, &farr, data, tagbytes, sizeof(upb_Message*));       \
+    switch (ret.next) {                                                   \
+      case FD_NEXT_SAMEFIELD:                                             \
+        dst = ret.dst;                                                    \
+        goto again;                                                       \
+      case FD_NEXT_OTHERFIELD:                                            \
+        d->depth++;                                                       \
+        data = ret.tag;                                                   \
+        UPB_MUSTTAIL return _upb_FastDecoder_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 */
+
+// We encode backwards, to avoid pre-computing lengths (one-pass encode).
+
+
+#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_Arena* arena;
+  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_EncodeStatus s) {
+  UPB_LONGJMP(e->err, s);
+}
+
+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_Arena_Realloc(e->arena, e->buf, old_size, new_size);
+
+  if (!new_buf) encode_err(e, kUpb_EncodeStatus_OutOfMemory);
+
+  // We want previous data at the end, realloc() put it at the beginning.
+  // TODO(salo): This is somewhat inefficient since we are copying twice.
+  // Maybe create a realloc() that copies to the end of the new buffer?
+  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_BigEndian_Swap64(val);
+  encode_bytes(e, &val, sizeof(uint64_t));
+}
+
+static void encode_fixed32(upb_encstate* e, uint32_t val) {
+  val = _upb_BigEndian_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->size * elem_size;
+  const char* data = _upb_array_constptr(arr);
+  const char* ptr = data + bytes - elem_size;
+
+  if (tag || !_upb_IsLittleEndian()) {
+    while (true) {
+      if (elem_size == 4) {
+        uint32_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap32(val);
+        encode_bytes(e, &val, elem_size);
+      } else {
+        UPB_ASSERT(elem_size == 8);
+        uint64_t val;
+        memcpy(&val, ptr, sizeof(val));
+        val = _upb_BigEndian_Swap64(val);
+        encode_bytes(e, &val, elem_size);
+      }
+
+      if (tag) 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 upb_Message* msg,
+                           const upb_MiniTable* m, size_t* size);
+
+static void encode_scalar(upb_encstate* e, const void* _field_mem,
+                          const upb_MiniTableSub* subs,
+                          const upb_MiniTableField* f) {
+  const char* field_mem = _field_mem;
+  int wire_type;
+
+#define CASE(ctype, type, wtype, encodeval) \
+  {                                         \
+    ctype val = *(ctype*)field_mem;         \
+    encode_##type(e, encodeval);            \
+    wire_type = wtype;                      \
+    break;                                  \
+  }
+
+  switch (f->descriptortype) {
+    case kUpb_FieldType_Double:
+      CASE(double, double, kUpb_WireType_64Bit, val);
+    case kUpb_FieldType_Float:
+      CASE(float, float, kUpb_WireType_32Bit, val);
+    case kUpb_FieldType_Int64:
+    case kUpb_FieldType_UInt64:
+      CASE(uint64_t, varint, kUpb_WireType_Varint, val);
+    case kUpb_FieldType_UInt32:
+      CASE(uint32_t, varint, kUpb_WireType_Varint, val);
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_Enum:
+      CASE(int32_t, varint, kUpb_WireType_Varint, (int64_t)val);
+    case kUpb_FieldType_SFixed64:
+    case kUpb_FieldType_Fixed64:
+      CASE(uint64_t, fixed64, kUpb_WireType_64Bit, val);
+    case kUpb_FieldType_Fixed32:
+    case kUpb_FieldType_SFixed32:
+      CASE(uint32_t, fixed32, kUpb_WireType_32Bit, val);
+    case kUpb_FieldType_Bool:
+      CASE(bool, varint, kUpb_WireType_Varint, val);
+    case kUpb_FieldType_SInt32:
+      CASE(int32_t, varint, kUpb_WireType_Varint, encode_zz32(val));
+    case kUpb_FieldType_SInt64:
+      CASE(int64_t, varint, kUpb_WireType_Varint, encode_zz64(val));
+    case kUpb_FieldType_String:
+    case kUpb_FieldType_Bytes: {
+      upb_StringView view = *(upb_StringView*)field_mem;
+      encode_bytes(e, view.data, view.size);
+      encode_varint(e, view.size);
+      wire_type = kUpb_WireType_Delimited;
+      break;
+    }
+    case kUpb_FieldType_Group: {
+      size_t size;
+      void* submsg = *(void**)field_mem;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      encode_tag(e, f->number, kUpb_WireType_EndGroup);
+      encode_message(e, submsg, subm, &size);
+      wire_type = kUpb_WireType_StartGroup;
+      e->depth++;
+      break;
+    }
+    case kUpb_FieldType_Message: {
+      size_t size;
+      void* submsg = *(void**)field_mem;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (submsg == NULL) {
+        return;
+      }
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      encode_message(e, submsg, subm, &size);
+      encode_varint(e, size);
+      wire_type = kUpb_WireType_Delimited;
+      e->depth++;
+      break;
+    }
+    default:
+      UPB_UNREACHABLE();
+  }
+#undef CASE
+
+  encode_tag(e, f->number, wire_type);
+}
+
+static void encode_array(upb_encstate* e, const upb_Message* msg,
+                         const upb_MiniTableSub* subs,
+                         const upb_MiniTableField* f) {
+  const upb_Array* arr = *UPB_PTR_AT(msg, f->offset, upb_Array*);
+  bool packed = f->mode & kUpb_LabelFlags_IsPacked;
+  size_t pre_len = e->limit - e->ptr;
+
+  if (arr == NULL || arr->size == 0) {
+    return;
+  }
+
+#define VARINT_CASE(ctype, encode)                                       \
+  {                                                                      \
+    const ctype* start = _upb_array_constptr(arr);                       \
+    const ctype* ptr = start + arr->size;                                \
+    uint32_t tag = packed ? 0 : (f->number << 3) | kUpb_WireType_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 kUpb_FieldType_Double:
+      encode_fixedarray(e, arr, sizeof(double), TAG(kUpb_WireType_64Bit));
+      break;
+    case kUpb_FieldType_Float:
+      encode_fixedarray(e, arr, sizeof(float), TAG(kUpb_WireType_32Bit));
+      break;
+    case kUpb_FieldType_SFixed64:
+    case kUpb_FieldType_Fixed64:
+      encode_fixedarray(e, arr, sizeof(uint64_t), TAG(kUpb_WireType_64Bit));
+      break;
+    case kUpb_FieldType_Fixed32:
+    case kUpb_FieldType_SFixed32:
+      encode_fixedarray(e, arr, sizeof(uint32_t), TAG(kUpb_WireType_32Bit));
+      break;
+    case kUpb_FieldType_Int64:
+    case kUpb_FieldType_UInt64:
+      VARINT_CASE(uint64_t, *ptr);
+    case kUpb_FieldType_UInt32:
+      VARINT_CASE(uint32_t, *ptr);
+    case kUpb_FieldType_Int32:
+    case kUpb_FieldType_Enum:
+      VARINT_CASE(int32_t, (int64_t)*ptr);
+    case kUpb_FieldType_Bool:
+      VARINT_CASE(bool, *ptr);
+    case kUpb_FieldType_SInt32:
+      VARINT_CASE(int32_t, encode_zz32(*ptr));
+    case kUpb_FieldType_SInt64:
+      VARINT_CASE(int64_t, encode_zz64(*ptr));
+    case kUpb_FieldType_String:
+    case kUpb_FieldType_Bytes: {
+      const upb_StringView* start = _upb_array_constptr(arr);
+      const upb_StringView* ptr = start + arr->size;
+      do {
+        ptr--;
+        encode_bytes(e, ptr->data, ptr->size);
+        encode_varint(e, ptr->size);
+        encode_tag(e, f->number, kUpb_WireType_Delimited);
+      } while (ptr != start);
+      return;
+    }
+    case kUpb_FieldType_Group: {
+      const void* const* start = _upb_array_constptr(arr);
+      const void* const* ptr = start + arr->size;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      do {
+        size_t size;
+        ptr--;
+        encode_tag(e, f->number, kUpb_WireType_EndGroup);
+        encode_message(e, *ptr, subm, &size);
+        encode_tag(e, f->number, kUpb_WireType_StartGroup);
+      } while (ptr != start);
+      e->depth++;
+      return;
+    }
+    case kUpb_FieldType_Message: {
+      const void* const* start = _upb_array_constptr(arr);
+      const void* const* ptr = start + arr->size;
+      const upb_MiniTable* subm = subs[f->submsg_index].submsg;
+      if (--e->depth == 0) encode_err(e, kUpb_EncodeStatus_MaxDepthExceeded);
+      do {
+        size_t size;
+        ptr--;
+        encode_message(e, *ptr, subm, &size);
+        encode_varint(e, size);
+        encode_tag(e, f->number, kUpb_WireType_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, kUpb_WireType_Delimited);
+  }
+}
+
+static void encode_mapentry(upb_encstate* e, uint32_t number,
+                            const upb_MiniTable* layout,
+                            const upb_MapEntry* ent) {
+  const upb_MiniTableField* key_field = &layout->fields[0];
+  const upb_MiniTableField* val_field = &layout->fields[1];
+  size_t pre_len = e->limit - e->ptr;
+  size_t size;
+  encode_scalar(e, &ent->data.v, layout->subs, val_field);
+  encode_scalar(e, &ent->data.k, layout->subs, key_field);
+  size = (e->limit - e->ptr) - pre_len;
+  encode_varint(e, size);
+  encode_tag(e, number, kUpb_WireType_Delimited);
+}
+
+static void encode_map(upb_encstate* e, const upb_Message* msg,
+                       const upb_MiniTableSub* subs,
+                       const upb_MiniTableField* f) {
+  const upb_Map* map = *UPB_PTR_AT(msg, f->offset, const upb_Map*);
+  const upb_MiniTable* layout = subs[f->submsg_index].submsg;
+  UPB_ASSERT(layout->field_count == 2);
+
+  if (map == NULL) return;
+
+  if (e->options & kUpb_EncodeOption_Deterministic) {
+    _upb_sortedmap sorted;
+    _upb_mapsorter_pushmap(&e->sorter, layout->fields[0].descriptortype, map,
+                           &sorted);
+    upb_MapEntry ent;
+    while (_upb_sortedmap_next(&e->sorter, map, &sorted, &ent)) {
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+    _upb_mapsorter_popmap(&e->sorter, &sorted);
+  } else {
+    intptr_t iter = UPB_STRTABLE_BEGIN;
+    upb_StringView key;
+    upb_value val;
+    while (upb_strtable_next2(&map->table, &key, &val, &iter)) {
+      upb_MapEntry ent;
+      _upb_map_fromkey(key, &ent.data.k, map->key_size);
+      _upb_map_fromvalue(val, &ent.data.v, map->val_size);
+      encode_mapentry(e, f->number, layout, &ent);
+    }
+  }
+}
+
+static bool encode_shouldencode(upb_encstate* e, const upb_Message* msg,
+                                const upb_MiniTableSub* subs,
+                                const upb_MiniTableField* f) {
+  if (f->presence == 0) {
+    /* Proto3 presence or map/array. */
+    const void* mem = UPB_PTR_AT(msg, f->offset, void);
+    switch (_upb_MiniTableField_GetRep(f)) {
+      case kUpb_FieldRep_1Byte: {
+        char ch;
+        memcpy(&ch, mem, 1);
+        return ch != 0;
+      }
+      case kUpb_FieldRep_4Byte: {
+        uint32_t u32;
+        memcpy(&u32, mem, 4);
+        return u32 != 0;
+      }
+      case kUpb_FieldRep_8Byte: {
+        uint64_t u64;
+        memcpy(&u64, mem, 8);
+        return u64 != 0;
+      }
+      case kUpb_FieldRep_StringView: {
+        const upb_StringView* str = (const upb_StringView*)mem;
+        return str->size != 0;
+      }
+      default:
+        UPB_UNREACHABLE();
+    }
+  } else if (f->presence > 0) {
+    /* Proto2 presence: hasbit. */
+    return _upb_hasbit_field(msg, f);
+  } else {
+    /* Field is in a oneof. */
+    return _upb_getoneofcase_field(msg, f) == f->number;
+  }
+}
+
+static void encode_field(upb_encstate* e, const upb_Message* msg,
+                         const upb_MiniTableSub* subs,
+                         const upb_MiniTableField* field) {
+  switch (upb_FieldMode_Get(field)) {
+    case kUpb_FieldMode_Array:
+      encode_array(e, msg, subs, field);
+      break;
+    case kUpb_FieldMode_Map:
+      encode_map(e, msg, subs, field);
+      break;
+    case kUpb_FieldMode_Scalar:
+      encode_scalar(e, UPB_PTR_AT(msg, field->offset, void), subs, field);
+      break;
+    default:
+      UPB_UNREACHABLE();
+  }
+}
+
+static void encode_msgset_item(upb_encstate* e,
+                               const upb_Message_Extension* ext) {
+  size_t size;
+  encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_EndGroup);
+  encode_message(e, ext->data.ptr, ext->ext->sub.submsg, &size);
+  encode_varint(e, size);
+  encode_tag(e, kUpb_MsgSet_Message, kUpb_WireType_Delimited);
+  encode_varint(e, ext->ext->field.number);
+  encode_tag(e, kUpb_MsgSet_TypeId, kUpb_WireType_Varint);
+  encode_tag(e, kUpb_MsgSet_Item, kUpb_WireType_StartGroup);
+}
+
+static void encode_message(upb_encstate* e, const upb_Message* msg,
+                           const upb_MiniTable* m, size_t* size) {
+  size_t pre_len = e->limit - e->ptr;
+
+  if ((e->options & kUpb_EncodeOption_CheckRequired) && m->required_count) {
+    uint64_t msg_head;
+    memcpy(&msg_head, msg, 8);
+    msg_head = _upb_BigEndian_Swap64(msg_head);
+    if (upb_MiniTable_requiredmask(m) & ~msg_head) {
+      encode_err(e, kUpb_EncodeStatus_MissingRequired);
+    }
+  }
+
+  if ((e->options & kUpb_EncodeOption_SkipUnknown) == 0) {
+    size_t unknown_size;
+    const char* unknown = upb_Message_GetUnknown(msg, &unknown_size);
+
+    if (unknown) {
+      encode_bytes(e, unknown, unknown_size);
+    }
+  }
+
+  if (m->ext != kUpb_ExtMode_NonExtendable) {
+    /* Encode all extensions together. Unlike C++, we do not attempt to keep
+     * these in field number order relative to normal fields or even to each
+     * other. */
+    size_t ext_count;
+    const upb_Message_Extension* ext = _upb_Message_Getexts(msg, &ext_count);
+    if (ext_count) {
+      const upb_Message_Extension* end = ext + ext_count;
+      for (; ext != end; ext++) {
+        if (UPB_UNLIKELY(m->ext == kUpb_ExtMode_IsMessageSet)) {
+          encode_msgset_item(e, ext);
+        } else {
+          encode_field(e, &ext->data, &ext->ext->sub, &ext->ext->field);
+        }
+      }
+    }
+  }
+
+  if (m->field_count) {
+    const upb_MiniTableField* f = &m->fields[m->field_count];
+    const upb_MiniTableField* first = &m->fields[0];
+    while (f != first) {
+      f--;
+      if (encode_shouldencode(e, msg, m->subs, f)) {
+        encode_field(e, msg, m->subs, f);
+      }
+    }
+  }
+
+  *size = (e->limit - e->ptr) - pre_len;
+}
+
+upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
+                            int options, upb_Arena* arena, char** buf,
+                            size_t* size) {
+  upb_encstate e;
+  unsigned depth = (unsigned)options >> 16;
+
+  e.arena = arena;
+  e.buf = NULL;
+  e.limit = NULL;
+  e.ptr = NULL;
+  e.depth = depth ? depth : 64;
+  e.options = options;
+  _upb_mapsorter_init(&e.sorter);
+
+  upb_EncodeStatus status = UPB_SETJMP(e.err);
+
+  // Unfortunately we must continue to perform hackery here because there are
+  // code paths which blindly copy the returned pointer without bothering to
+  // check for errors until much later (b/235839510). So we still set *buf to
+  // NULL on error and we still set it to non-NULL on a successful empty result.
+  if (status == kUpb_EncodeStatus_Ok) {
+    encode_message(&e, msg, l, size);
+    *size = e.limit - e.ptr;
+    if (*size == 0) {
+      static char ch;
+      *buf = &ch;
+    } else {
+      UPB_ASSERT(e.ptr);
+      *buf = e.ptr;
+    }
+  } else {
+    *buf = NULL;
+    *size = 0;
+  }
+
+  _upb_mapsorter_destroy(&e.sorter);
+  return status;
+}
+
+// This should #undef all macros #defined in def.inc
 
 #undef UPB_SIZE
 #undef UPB_PTR_AT
@@ -11090,6 +13252,7 @@
 #undef UPB_ALIGN_DOWN
 #undef UPB_ALIGN_MALLOC
 #undef UPB_ALIGN_OF
+#undef UPB_MALLOC_ALIGN
 #undef UPB_LIKELY
 #undef UPB_UNLIKELY
 #undef UPB_FORCEINLINE
@@ -11113,3 +13276,5 @@
 #undef UPB_UNPOISON_MEMORY_REGION
 #undef UPB_ASAN
 #undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3
+#undef UPB_DEPRECATED
+#undef UPB_GNUC_MIN
diff --git a/ruby/ext/google/protobuf_c/ruby-upb.h b/ruby/ext/google/protobuf_c/ruby-upb.h
index e57eb0e..f3e625d 100755
--- a/ruby/ext/google/protobuf_c/ruby-upb.h
+++ b/ruby/ext/google/protobuf_c/ruby-upb.h
@@ -1,38 +1,11 @@
 // Ruby is still using proto3 enum semantics for proto2
 #define UPB_DISABLE_PROTO2_ENUM_CHECKING
 /* 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.
+ * This is where we define internal portability macros used across upb.
  *
- * All of these macros are undef'd in port_undef.inc to avoid leaking them to
- * users.
+ * All of these macros are undef'd in undef.inc to avoid leaking them to users.
  *
  * The correct usage is:
  *
@@ -40,25 +13,38 @@
  *   #include "upb/baz.h"
  *
  *   // MUST be last included header.
- *   #include "upb/port_def.inc"
+ *   #include "upb/port/def.inc"
  *
  *   // Code for this file.
  *   // <...>
  *
  *   // Can be omitted for .c files, required for .h.
- *   #include "upb/port_undef.inc"
+ *   #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(__cplusplus) && __cplusplus >= 201402L) ||           \
       (defined(_MSC_VER) && _MSC_VER >= 1900))
-#error upb requires C99 or C++11 or MSVC >= 2015.
+#error upb requires C99 or C++14 or MSVC >= 2015.
 #endif
 
-#include <stdint.h>
+// 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 UPB_GNUC_MIN(x, y) \
+  (__GNUC__ > (x) || __GNUC__ == (x) && __GNUC_MINOR__ >= (y))
+#else
+#define UPB_GNUC_MIN(x, y) 0
+#endif
+
+#include <assert.h>
+#include <setjmp.h>
+#include <stdbool.h>
 #include <stddef.h>
+#include <stdint.h>
+#include <stdio.h>
 
 #if UINTPTR_MAX == 0xffffffff
 #define UPB_SIZE(size32, size64) size32
@@ -71,11 +57,6 @@
  */
 #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;
@@ -91,21 +72,22 @@
 #define UPB_INLINE static
 #endif
 
+#define UPB_MALLOC_ALIGN 8
 #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_MALLOC(size) UPB_ALIGN_UP(size, UPB_MALLOC_ALIGN)
 #define UPB_ALIGN_OF(type) offsetof (struct { char c; type member; }, member)
 
-/* Hints to the compiler about likely/unlikely branches. */
+// 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)
+#define UPB_LIKELY(x) __builtin_expect((bool)(x), 1)
+#define UPB_UNLIKELY(x) __builtin_expect((bool)(x), 0)
 #else
 #define UPB_LIKELY(x) (x)
 #define UPB_UNLIKELY(x) (x)
 #endif
 
-/* Macros for function attributes on compilers that support them. */
+// Macros for function attributes on compilers that support them.
 #ifdef __GNUC__
 #define UPB_FORCEINLINE __inline__ __attribute__((always_inline))
 #define UPB_NOINLINE __attribute__((noinline))
@@ -128,8 +110,7 @@
 
 #define UPB_UNUSED(var) (void)var
 
-/* UPB_ASSUME(): in release mode, we tell the compiler to assume this is true.
- */
+// 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()
@@ -231,7 +212,11 @@
 
 #undef UPB_FASTTABLE_SUPPORTED
 
-/* ASAN poisoning (for arena) *************************************************/
+/* ASAN poisoning (for arena).
+ * If using UPB from an interpreted language like Ruby, a build of the
+ * interpreter compiled with ASAN enabled must be used in order to get sane and
+ * expected behavior.
+ */
 
 #if defined(__SANITIZE_ADDRESS__)
 #define UPB_ASAN 1
@@ -263,63 +248,43 @@
 #define UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3 0
 #endif
 
-/** upb/decode.h ************************************************************/
-/*
- * upb_decode: parsing into a upb_Message using a upb_MiniTable.
- */
-
-#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" {
+#if defined(__cplusplus)
+#if defined(__clang__) || UPB_GNUC_MIN(6, 0)
+// https://gcc.gnu.org/gcc-6/changes.html
+#if __cplusplus >= 201402L
+#define UPB_DEPRECATED [[deprecated]]
+#else
+#define UPB_DEPRECATED __attribute__((deprecated))
+#endif
+#else
+#define UPB_DEPRECATED
+#endif
+#else
+#define UPB_DEPRECATED
 #endif
 
-/* upb_Status *****************************************************************/
+#ifndef UPB_BASE_STATUS_H_
+#define UPB_BASE_STATUS_H_
+
+#include <stdarg.h>
+
+// Must be last.
 
 #define _kUpb_Status_MaxMessage 127
 
 typedef struct {
   bool ok;
-  char msg[_kUpb_Status_MaxMessage]; /* Error message; NULL-terminated. */
+  char msg[_kUpb_Status_MaxMessage];  // Error message; NULL-terminated.
 } upb_Status;
 
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 const char* upb_Status_ErrorMessage(const upb_Status* status);
 bool upb_Status_IsOk(const upb_Status* status);
 
-/* These are no-op if |status| is NULL. */
+// These are no-op if |status| is NULL.
 void upb_Status_Clear(upb_Status* status);
 void upb_Status_SetErrorMessage(upb_Status* status, const char* msg);
 void upb_Status_SetErrorFormat(upb_Status* status, const char* fmt, ...)
@@ -329,12 +294,107 @@
 void upb_Status_VAppendErrorFormat(upb_Status* status, const char* fmt,
                                    va_list args) UPB_PRINTF(2, 0);
 
-/** upb_StringView ************************************************************/
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
+
+#endif /* UPB_BASE_STATUS_H_ */
+
+#ifndef UPB_INTERNAL_ARRAY_INTERNAL_H_
+#define UPB_INTERNAL_ARRAY_INTERNAL_H_
+
+#include <string.h>
+
+
+#ifndef UPB_COLLECTIONS_ARRAY_H_
+#define UPB_COLLECTIONS_ARRAY_H_
+
+
+#ifndef UPB_BASE_DESCRIPTOR_CONSTANTS_H_
+#define UPB_BASE_DESCRIPTOR_CONSTANTS_H_
+
+// 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).
+// This enum is an internal convenience only and has no meaning outside of upb.
+typedef enum {
+  kUpb_CType_Bool = 1,
+  kUpb_CType_Float = 2,
+  kUpb_CType_Int32 = 3,
+  kUpb_CType_UInt32 = 4,
+  kUpb_CType_Enum = 5,  // Enum values are int32.
+  kUpb_CType_Message = 6,
+  kUpb_CType_Double = 7,
+  kUpb_CType_Int64 = 8,
+  kUpb_CType_UInt64 = 9,
+  kUpb_CType_String = 10,
+  kUpb_CType_Bytes = 11
+} upb_CType;
+
+// The repeated-ness of each field; this matches descriptor.proto.
+typedef enum {
+  kUpb_Label_Optional = 1,
+  kUpb_Label_Required = 2,
+  kUpb_Label_Repeated = 3
+} upb_Label;
+
+// Descriptor types, as defined in descriptor.proto.
+typedef enum {
+  kUpb_FieldType_Double = 1,
+  kUpb_FieldType_Float = 2,
+  kUpb_FieldType_Int64 = 3,
+  kUpb_FieldType_UInt64 = 4,
+  kUpb_FieldType_Int32 = 5,
+  kUpb_FieldType_Fixed64 = 6,
+  kUpb_FieldType_Fixed32 = 7,
+  kUpb_FieldType_Bool = 8,
+  kUpb_FieldType_String = 9,
+  kUpb_FieldType_Group = 10,
+  kUpb_FieldType_Message = 11,
+  kUpb_FieldType_Bytes = 12,
+  kUpb_FieldType_UInt32 = 13,
+  kUpb_FieldType_Enum = 14,
+  kUpb_FieldType_SFixed32 = 15,
+  kUpb_FieldType_SFixed64 = 16,
+  kUpb_FieldType_SInt32 = 17,
+  kUpb_FieldType_SInt64 = 18,
+} upb_FieldType;
+
+#define kUpb_FieldType_SizeOf 19
+
+#endif /* UPB_BASE_DESCRIPTOR_CONSTANTS_H_ */
+
+// Users should include array.h or map.h instead.
+// IWYU pragma: private, include "upb/collections/array.h"
+
+#ifndef UPB_MESSAGE_VALUE_H_
+#define UPB_MESSAGE_VALUE_H_
+
+
+#ifndef UPB_BASE_STRING_VIEW_H_
+#define UPB_BASE_STRING_VIEW_H_
+
+#include <string.h>
+
+// Must be last.
+
+#define UPB_STRINGVIEW_INIT(ptr, len) \
+  { ptr, len }
+
+#define UPB_STRINGVIEW_FORMAT "%.*s"
+#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data
+
+// LINT.IfChange(struct_definition)
 typedef struct {
   const char* data;
   size_t size;
 } upb_StringView;
+// LINT.ThenChange(GoogleInternalName0)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 UPB_INLINE upb_StringView upb_StringView_FromDataAndSize(const char* data,
                                                          size_t size) {
@@ -352,29 +412,97 @@
   return a.size == b.size && memcmp(a.data, b.data, a.size) == 0;
 }
 
-#define UPB_STRINGVIEW_INIT(ptr, len) \
-  { ptr, len }
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-#define UPB_STRINGVIEW_FORMAT "%.*s"
-#define UPB_STRINGVIEW_ARGS(view) (int)(view).size, (view).data
 
-/** upb_alloc *****************************************************************/
+#endif /* UPB_BASE_STRING_VIEW_H_ */
+
+#ifndef UPB_MINI_TABLE_TYPES_H_
+#define UPB_MINI_TABLE_TYPES_H_
+
+typedef void upb_Message;
+
+typedef struct upb_MiniTable upb_MiniTable;
+typedef struct upb_MiniTableEnum upb_MiniTableEnum;
+typedef struct upb_MiniTableExtension upb_MiniTableExtension;
+typedef struct upb_MiniTableField upb_MiniTableField;
+typedef struct upb_MiniTableFile upb_MiniTableFile;
+typedef union upb_MiniTableSub upb_MiniTableSub;
+
+#endif /* UPB_MINI_TABLE_TYPES_H_ */
+
+// Must be last.
+
+typedef struct upb_Array upb_Array;
+typedef struct upb_Map upb_Map;
+
+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_Array* array_val;
+  const upb_Map* map_val;
+  const upb_Message* msg_val;
+  upb_StringView str_val;
+} upb_MessageValue;
+
+typedef union {
+  upb_Array* array;
+  upb_Map* map;
+  upb_Message* msg;
+} upb_MutableMessageValue;
+
+
+#endif /* UPB_MESSAGE_VALUE_H_ */
+
+/* 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. */
+
+#ifndef UPB_MEM_ARENA_H_
+#define UPB_MEM_ARENA_H_
+
+#include <string.h>
+
+
+#ifndef UPB_MEM_ALLOC_H_
+#define UPB_MEM_ALLOC_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+typedef struct upb_alloc upb_alloc;
+
+/* A combined `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);
 
 /* 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);
-
+ * `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 {
   upb_alloc_func* func;
 };
@@ -391,11 +519,11 @@
 }
 
 UPB_INLINE void upb_free(upb_alloc* alloc, void* ptr) {
-  assert(alloc);
+  UPB_ASSERT(alloc);
   alloc->func(alloc, ptr, 0, 0);
 }
 
-/* The global allocator used by upb.  Uses the standard malloc()/free(). */
+// The global allocator used by upb. Uses the standard malloc()/free().
 
 extern upb_alloc upb_alloc_global;
 
@@ -414,44 +542,38 @@
 
 UPB_INLINE void upb_gfree(void* ptr) { upb_free(&upb_alloc_global, ptr); }
 
-/* upb_Arena ******************************************************************/
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-/* 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_CleanupFunc(void* ud);
+#endif /* UPB_MEM_ALLOC_H_ */
 
-struct upb_Arena;
+// Must be last.
+
 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;
+typedef void upb_CleanupFunc(void* context);
 
+typedef struct {
   char *ptr, *end;
 } _upb_ArenaHead;
 
-/* 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. */
+#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_CleanupFunc* 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; }
+size_t upb_Arena_SpaceAllocated(upb_Arena* arena);
+uint32_t upb_Arena_DebugRefCount(upb_Arena* arena);
 
 UPB_INLINE size_t _upb_ArenaHas(upb_Arena* a) {
   _upb_ArenaHead* h = (_upb_ArenaHead*)a;
@@ -459,18 +581,20 @@
 }
 
 UPB_INLINE void* upb_Arena_Malloc(upb_Arena* a, size_t size) {
-  _upb_ArenaHead* h = (_upb_ArenaHead*)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;
+  // We have enough space to do a fast malloc.
+  _upb_ArenaHead* h = (_upb_ArenaHead*)a;
+  void* ret = h->ptr;
+  UPB_ASSERT(UPB_ALIGN_MALLOC((uintptr_t)ret) == (uintptr_t)ret);
+  UPB_ASSERT(UPB_ALIGN_MALLOC(size) == size);
   UPB_UNPOISON_MEMORY_REGION(ret, size);
 
+  h->ptr += size;
+
 #if UPB_ASAN
   {
     size_t guard_size = 32;
@@ -504,17 +628,22 @@
   _upb_ArenaHead* h = (_upb_ArenaHead*)a;
   oldsize = UPB_ALIGN_MALLOC(oldsize);
   size = UPB_ALIGN_MALLOC(size);
-  if (size <= oldsize) {
-    if ((char*)ptr + oldsize == h->ptr) {
-      upb_Arena_ShrinkLast(a, ptr, oldsize, size);
+  bool is_most_recent_alloc = (uintptr_t)ptr + oldsize == (uintptr_t)h->ptr;
+
+  if (is_most_recent_alloc) {
+    ptrdiff_t diff = size - oldsize;
+    if ((ptrdiff_t)_upb_ArenaHas(a) >= diff) {
+      h->ptr += diff;
+      return ptr;
     }
+  } else if (size <= oldsize) {
     return ptr;
   }
 
   void* ret = upb_Arena_Malloc(a, size);
 
   if (ret && oldsize > 0) {
-    memcpy(ret, ptr, oldsize);
+    memcpy(ret, ptr, UPB_MIN(oldsize, size));
   }
 
   return ret;
@@ -524,270 +653,336 @@
   return upb_Arena_Init(NULL, 0, &upb_alloc_global);
 }
 
-/* Constants ******************************************************************/
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-/* A list of types as they are encoded on-the-wire. */
-typedef enum {
-  kUpb_WireType_Varint = 0,
-  kUpb_WireType_64Bit = 1,
-  kUpb_WireType_Delimited = 2,
-  kUpb_WireType_StartGroup = 3,
-  kUpb_WireType_EndGroup = 4,
-  kUpb_WireType_32Bit = 5
-} upb_WireType;
 
-/* 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 {
-  kUpb_CType_Bool = 1,
-  kUpb_CType_Float = 2,
-  kUpb_CType_Int32 = 3,
-  kUpb_CType_UInt32 = 4,
-  kUpb_CType_Enum = 5, /* Enum values are int32. */
-  kUpb_CType_Message = 6,
-  kUpb_CType_Double = 7,
-  kUpb_CType_Int64 = 8,
-  kUpb_CType_UInt64 = 9,
-  kUpb_CType_String = 10,
-  kUpb_CType_Bytes = 11
-} upb_CType;
+#endif /* UPB_MEM_ARENA_H_ */
 
-/* The repeated-ness of each field; this matches descriptor.proto. */
-typedef enum {
-  kUpb_Label_Optional = 1,
-  kUpb_Label_Required = 2,
-  kUpb_Label_Repeated = 3
-} upb_Label;
+// Must be last.
 
-/* Descriptor types, as defined in descriptor.proto. */
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a new array on the given arena that holds elements of this type. */
+upb_Array* upb_Array_New(upb_Arena* a, upb_CType type);
+
+/* Returns the number of elements in 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_MessageValue 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_MessageValue val);
+
+/* Appends an element to the array.  Returns false on allocation failure. */
+bool upb_Array_Append(upb_Array* array, upb_MessageValue val, upb_Arena* arena);
+
+/* Moves elements within the array using memmove(). Like memmove(), the source
+ * and destination elements may be overlapping. */
+void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
+                    size_t count);
+
+/* Inserts one or more empty elements into the array.  Existing elements are
+ * shifted right.  The new elements have undefined state and must be set with
+ * `upb_Array_Set()`.
+ * REQUIRES: `i <= upb_Array_Size(arr)` */
+bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
+                      upb_Arena* arena);
+
+/* Deletes one or more elements from the array.  Existing elements are shifted
+ * left.
+ * REQUIRES: `i + count <= upb_Array_Size(arr)` */
+void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
+
+/* 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);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_COLLECTIONS_ARRAY_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// LINT.IfChange(struct_definition)
+// Our internal representation for repeated fields.
+struct upb_Array {
+  uintptr_t data;  /* Tagged ptr: low 3 bits of ptr are lg2(elem size). */
+  size_t size;     /* The number of elements in the array. */
+  size_t capacity; /* Allocated storage. Measured in elements. */
+};
+// LINT.ThenChange(GoogleInternalName1)
+
+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_capacity,
+                                     int elem_size_lg2) {
+  const size_t arr_size = UPB_ALIGN_UP(sizeof(upb_Array), UPB_MALLOC_ALIGN);
+  const size_t bytes = arr_size + (init_capacity << 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->size = 0;
+  arr->capacity = init_capacity;
+  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->capacity < 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->size = size;
+  return true;
+}
+
+UPB_INLINE void _upb_array_detach(const void* msg, size_t ofs) {
+  *UPB_PTR_AT(msg, ofs, upb_Array*) = NULL;
+}
+
+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->size;
+    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->size;
+    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->capacity < size) {
+    return _upb_Array_Resize_fallback(arr_ptr, size, elem_size_lg2, arena);
+  }
+  arr->size = 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->size == arr->capacity) {
+    return _upb_Array_Append_fallback(arr_ptr, value, elem_size_lg2, arena);
+  }
+  ptr = _upb_array_ptr(arr);
+  memcpy(UPB_PTR_AT(ptr, arr->size * elem_size, char), value, elem_size);
+  arr->size++;
+  return true;
+}
+
+// Used by old generated code, remove once all code has been regenerated.
+UPB_INLINE int _upb_sizelg2(upb_CType type) {
+  switch (type) {
+    case kUpb_CType_Bool:
+      return 0;
+    case kUpb_CType_Float:
+    case kUpb_CType_Int32:
+    case kUpb_CType_UInt32:
+    case kUpb_CType_Enum:
+      return 2;
+    case kUpb_CType_Message:
+      return UPB_SIZE(2, 3);
+    case kUpb_CType_Double:
+    case kUpb_CType_Int64:
+    case kUpb_CType_UInt64:
+      return 3;
+    case kUpb_CType_String:
+    case kUpb_CType_Bytes:
+      return UPB_SIZE(3, 4);
+  }
+  UPB_UNREACHABLE();
+}
+
+UPB_INLINE void* _upb_Array_Resize_accessor(void* msg, size_t ofs, size_t size,
+                                            upb_CType 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_CType type,
+                                           const void* value,
+                                           upb_Arena* arena) {
+  (void)elem_size;
+  return _upb_Array_Append_accessor2(msg, ofs, _upb_sizelg2(type), value,
+                                     arena);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_INTERNAL_ARRAY_INTERNAL_H_ */
+
+#ifndef UPB_COLLECTIONS_MAP_H_
+#define UPB_COLLECTIONS_MAP_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Creates a new map on the given arena with the given key/value size. */
+upb_Map* upb_Map_New(upb_Arena* a, upb_CType key_type, upb_CType 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_MessageValue key,
+                 upb_MessageValue* val);
+
+/* Removes all entries in the map. */
+void upb_Map_Clear(upb_Map* map);
+
 typedef enum {
-  kUpb_FieldType_Double = 1,
-  kUpb_FieldType_Float = 2,
-  kUpb_FieldType_Int64 = 3,
-  kUpb_FieldType_UInt64 = 4,
-  kUpb_FieldType_Int32 = 5,
-  kUpb_FieldType_Fixed64 = 6,
-  kUpb_FieldType_Fixed32 = 7,
-  kUpb_FieldType_Bool = 8,
-  kUpb_FieldType_String = 9,
-  kUpb_FieldType_Group = 10,
-  kUpb_FieldType_Message = 11,
-  kUpb_FieldType_Bytes = 12,
-  kUpb_FieldType_UInt32 = 13,
-  kUpb_FieldType_Enum = 14,
-  kUpb_FieldType_SFixed32 = 15,
-  kUpb_FieldType_SFixed64 = 16,
-  kUpb_FieldType_SInt32 = 17,
-  kUpb_FieldType_SInt64 = 18
-} upb_FieldType;
+  kUpb_MapInsertStatus_Inserted = 0,
+  kUpb_MapInsertStatus_Replaced = 1,
+  kUpb_MapInsertStatus_OutOfMemory = 2,
+} upb_MapInsertStatus;
+
+/* Sets the given key to the given value, returning whether the key was inserted
+ * or replaced.  If the key was inserted, then any existing iterators will be
+ * invalidated. */
+upb_MapInsertStatus upb_Map_Insert(upb_Map* map, upb_MessageValue key,
+                                   upb_MessageValue val, upb_Arena* arena);
+
+/* Sets the given key to the given value.  Returns false if memory allocation
+ * failed. If the key is newly inserted, then any existing iterators will be
+ * invalidated. */
+UPB_INLINE bool upb_Map_Set(upb_Map* map, upb_MessageValue key,
+                            upb_MessageValue val, upb_Arena* arena) {
+  return upb_Map_Insert(map, key, val, arena) !=
+         kUpb_MapInsertStatus_OutOfMemory;
+}
+
+// Deletes this key from the table. Returns true if the key was present.
+bool upb_Map_Delete(upb_Map* map, upb_MessageValue key);
+
+// Map iteration:
+//
+// size_t iter = kUpb_Map_Begin;
+// upb_MessageValue key, val;
+// while (upb_Map_Next(map, &key, &val, &iter)) {
+//   ...
+// }
 
 #define kUpb_Map_Begin ((size_t)-1)
 
-UPB_INLINE bool _upb_IsLittleEndian(void) {
-  int x = 1;
-  return *(char*)&x == 1;
-}
+// Advances to the next entry. Returns false if no more entries are present.
+// Otherwise returns true and populates both *key and *value.
+bool upb_Map_Next(const upb_Map* map, upb_MessageValue* key,
+                  upb_MessageValue* val, size_t* iter);
 
-UPB_INLINE uint32_t _upb_BigEndian_Swap32(uint32_t val) {
-  if (_upb_IsLittleEndian()) {
-    return val;
-  } else {
-    return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
-           ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
-  }
-}
+// DEPRECATED iterator, slated for removal.
 
-UPB_INLINE uint64_t _upb_BigEndian_Swap64(uint64_t val) {
-  if (_upb_IsLittleEndian()) {
-    return val;
-  } else {
-    return ((uint64_t)_upb_BigEndian_Swap32(val) << 32) |
-           _upb_BigEndian_Swap32(val >> 32);
-  }
-}
-
-UPB_INLINE int _upb_Log2Ceiling(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_Log2CeilingSize(int x) { return 1 << _upb_Log2Ceiling(x); }
-
-
-#ifdef __cplusplus
-} /* extern "C" */
-#endif
-
-#endif /* UPB_H_ */
-
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-/** upb_Message
- * *******************************************************************/
-
-typedef void upb_Message;
-
-/* For users these are opaque. They can be obtained from
- * upb_MessageDef_MiniTable() but users cannot access any of the members. */
-struct upb_MiniTable;
-typedef struct upb_MiniTable upb_MiniTable;
-
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-void upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
-                            upb_Arena* arena);
-
-/* Returns a reference to the message's unknown data. */
-const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);
-
-/* Returns the number of extensions present in this message. */
-size_t upb_Message_ExtensionCount(const upb_Message* msg);
-
-/** upb_ExtensionRegistry *****************************************************/
-
-/* Extension registry: a dynamic data structure that stores a map of:
- *   (upb_MiniTable, number) -> extension info
+/* Map iteration:
  *
- * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing
- * binary format.
- *
- * upb_ExtensionRegistry is part of the mini-table (msglayout) family of
- * objects. Like all mini-table objects, it is suitable for reflection-less
- * builds that do not want to expose names into the binary.
- *
- * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory
- * allocation and dynamic initialization:
- * * If reflection is being used, then upb_DefPool will construct an appropriate
- *   upb_ExtensionRegistry automatically.
- * * For a mini-table only build, the user must manually construct the
- *   upb_ExtensionRegistry and populate it with all of the extensions the user
- * cares about.
- * * A third alternative is to manually unpack relevant extensions after the
- *   main parse is complete, similar to how Any works. This is perhaps the
- *   nicest solution from the perspective of reducing dependencies, avoiding
- *   dynamic memory allocation, and avoiding the need to parse uninteresting
- *   extensions.  The downsides are:
- *     (1) parse errors are not caught during the main parse
- *     (2) the CPU hit of parsing comes during access, which could cause an
- *         undesirable stutter in application performance.
- *
- * Users cannot directly get or put into this map. Users can only add the
- * extensions from a generated module and pass the extension registry to the
- * binary decoder.
- *
- * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use
- * reflection do not need to populate a upb_ExtensionRegistry directly.
+ * size_t iter = kUpb_Map_Begin;
+ * while (upb_MapIterator_Next(map, &iter)) {
+ *   upb_MessageValue key = upb_MapIterator_Key(map, iter);
+ *   upb_MessageValue val = upb_MapIterator_Value(map, iter);
+ * }
  */
 
-struct upb_ExtensionRegistry;
-typedef struct upb_ExtensionRegistry upb_ExtensionRegistry;
+// Advances to the next entry. Returns false if no more entries are present.
+bool upb_MapIterator_Next(const upb_Map* map, size_t* iter);
 
-/* Creates a upb_ExtensionRegistry in the given arena.  The arena must outlive
- * any use of the extreg. */
-upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena);
+/* 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
+ * kUpb_Map_Begin (you must call next() at least once first). */
+bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
 
-#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. */
-  kUpb_DecodeOption_AliasString = 1,
-
-  /* If set, the parse will return failure if any message is missing any
-   * required fields when the message data ends.  The parse will still continue,
-   * and the failure will only be reported at the end.
-   *
-   * IMPORTANT CAVEATS:
-   *
-   * 1. This can throw a false positive failure if an incomplete message is seen
-   *    on the wire but is later completed when the sub-message occurs again.
-   *    For this reason, a second pass is required to verify a failure, to be
-   *    truly robust.
-   *
-   * 2. This can return a false success if you are decoding into a message that
-   *    already has some sub-message fields present.  If the sub-message does
-   *    not occur in the binary payload, we will never visit it and discover the
-   *    incomplete sub-message.  For this reason, this check is only useful for
-   *    implemting ParseFromString() semantics.  For MergeFromString(), a
-   *    post-parse validation step will always be necessary. */
-  kUpb_DecodeOption_CheckRequired = 2,
-};
-
-#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
-
-typedef enum {
-  kUpb_DecodeStatus_Ok = 0,
-  kUpb_DecodeStatus_Malformed = 1,         // Wire format was corrupt
-  kUpb_DecodeStatus_OutOfMemory = 2,       // Arena alloc failed
-  kUpb_DecodeStatus_BadUtf8 = 3,           // String field had bad UTF-8
-  kUpb_DecodeStatus_MaxDepthExceeded = 4,  // Exceeded UPB_DECODE_MAXDEPTH
-
-  // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise
-  // succeeded.
-  kUpb_DecodeStatus_MissingRequired = 5,
-} upb_DecodeStatus;
-
-upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
-                            const upb_MiniTable* l,
-                            const upb_ExtensionRegistry* extreg, int options,
-                            upb_Arena* arena);
+/* Returns the key and value for this entry of the map. */
+upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
+upb_MessageValue upb_MapIterator_Value(const upb_Map* map, size_t iter);
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 
-#endif /* UPB_DECODE_H_ */
+#endif /* UPB_COLLECTIONS_MAP_H_ */
 
-/** upb/decode_internal.h ************************************************************/
-/*
- * Internal implementation details of the decoder that are shared between
- * decode.c and decode_fast.c.
- */
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
 
-#ifndef UPB_DECODE_INT_H_
-#define UPB_DECODE_INT_H_
-
-#include <setjmp.h>
-
-#include "third_party/utf8_range/utf8_range.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>
+#ifndef UPB_COLLECTIONS_MAP_INTERNAL_H_
+#define UPB_COLLECTIONS_MAP_INTERNAL_H_
 
 
-/** upb/table_internal.h ************************************************************/
+#ifndef UPB_HASH_STR_TABLE_H_
+#define UPB_HASH_STR_TABLE_H_
+
+
 /*
  * upb_table
  *
@@ -807,10 +1002,9 @@
  * mode, we check this on insert and lookup.
  */
 
-#ifndef UPB_TABLE_H_
-#define UPB_TABLE_H_
+#ifndef UPB_HASH_COMMON_H_
+#define UPB_HASH_COMMON_H_
 
-#include <stdint.h>
 #include <string.h>
 
 
@@ -941,67 +1135,66 @@
   upb_tabent* entries;
 } upb_table;
 
+UPB_INLINE size_t upb_table_size(const upb_table* t) {
+  return t->size_lg2 ? 1 << t->size_lg2 : 0;
+}
+
+// Internal-only functions, in .h file only out of necessity.
+
+UPB_INLINE bool upb_tabent_isempty(const upb_tabent* e) { return e->key == 0; }
+
+uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_HASH_COMMON_H_ */
+
+// Must be last.
+
 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;
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-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);
+// Initialize a table. If memory allocation failed, false is returned and
+// the table is uninitialized.
 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);
+// Returns the number of values in the table.
 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);
+// Inserts the given key into the hashtable with the given value.
+// The key must not already exist in the hash table. The key is not required
+// to be NULL-terminated, and the table will make an internal copy of the key.
+//
+// If a table resize was required but memory allocation failed, false is
+// returned and the table is unchanged. */
 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);
+// 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_strtable_lookup2(const upb_strtable* t, const char* key, size_t len,
                           upb_value* v);
 
-/* For NULL-terminated strings. */
+// 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);
+// 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_strtable_remove2(upb_strtable* t, const char* key, size_t len,
                           upb_value* val);
 
@@ -1010,40 +1203,12 @@
   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);
-
-/* 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. */
+// Exposed for testing only.
 bool upb_strtable_resize(upb_strtable* t, size_t size_lg2, upb_Arena* a);
 
-/* Iterators ******************************************************************/
-
-/* Iteration over inttable.
+/* Iteration over strtable:
  *
- *   intptr_t iter = UPB_INTTABLE_BEGIN;
- *   uintptr_t key;
- *   upb_value val;
- *   while (upb_inttable_next2(t, &key, &val, &iter)) {
- *      // ...
- *   }
- */
-
-#define UPB_INTTABLE_BEGIN -1
-
-bool upb_inttable_next2(const upb_inttable* t, uintptr_t* key, upb_value* val,
-                        intptr_t* iter);
-void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter);
-
-/* Iteration over strtable.
- *
- *   intptr_t iter = UPB_INTTABLE_BEGIN;
+ *   intptr_t iter = UPB_STRTABLE_BEGIN;
  *   upb_StringView key;
  *   upb_value val;
  *   while (upb_strtable_next2(t, &key, &val, &iter)) {
@@ -1059,7 +1224,7 @@
 
 /* DEPRECATED iterators, slated for removal.
  *
- * Iterators for int and string tables.  We are subject to some kind of unusual
+ * Iterators for string tables.  We are subject to some kind of unusual
  * design constraints:
  *
  * For high-level languages:
@@ -1079,7 +1244,6 @@
  * 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;
@@ -1096,6 +1260,10 @@
   size_t index;
 } upb_strtable_iter;
 
+UPB_INLINE 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);
 void upb_strtable_next(upb_strtable_iter* i);
 bool upb_strtable_done(const upb_strtable_iter* i);
@@ -1105,607 +1273,35 @@
 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);
-
-uint32_t _upb_Hash(const void* p, size_t n, uint64_t seed);
-
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 
-#endif /* UPB_TABLE_H_ */
+#endif /* UPB_HASH_STR_TABLE_H_ */
 
-/* Must be last. */
+// Must be last.
+
+struct upb_Map {
+  // 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;
+};
 
 #ifdef __cplusplus
 extern "C" {
 #endif
 
-/** upb_*Int* conversion routines ********************************************/
-
-UPB_INLINE int32_t _upb_Int32_FromI(int v) { return (int32_t)v; }
-
-UPB_INLINE int64_t _upb_Int64_FromLL(long long v) { return (int64_t)v; }
-
-UPB_INLINE uint32_t _upb_UInt32_FromU(unsigned v) { return (uint32_t)v; }
-
-UPB_INLINE uint64_t _upb_UInt64_FromULL(unsigned long long v) {
-  return (uint64_t)v;
-}
-
-/** upb_MiniTable *************************************************************/
-
-/* upb_MiniTable represents the memory layout of a given upb_MessageDef.  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.  If <0, ~oneof_index
-  uint16_t submsg_index;  // undefined if descriptortype != MESSAGE/GROUP/ENUM
-  uint8_t descriptortype;
-  uint8_t mode; /* upb_FieldMode | upb_LabelFlags |
-                   (upb_FieldRep << kUpb_FieldRep_Shift) */
-} upb_MiniTable_Field;
-
-typedef enum {
-  kUpb_FieldMode_Map = 0,
-  kUpb_FieldMode_Array = 1,
-  kUpb_FieldMode_Scalar = 2,
-
-  kUpb_FieldMode_Mask = 3, /* Mask to isolate the mode from upb_FieldRep. */
-} upb_FieldMode;
-
-/* Extra flags on the mode field. */
-typedef enum {
-  kUpb_LabelFlags_IsPacked = 4,
-  kUpb_LabelFlags_IsExtension = 8,
-} upb_LabelFlags;
-
-// Note: we sort by this number when calculating layout order.
-typedef enum {
-  kUpb_FieldRep_1Byte = 0,
-  kUpb_FieldRep_4Byte = 1,
-  kUpb_FieldRep_StringView = 2,
-  kUpb_FieldRep_Pointer = 3,
-  kUpb_FieldRep_8Byte = 4,
-
-  kUpb_FieldRep_Shift = 5,  // Bit offset of the rep in upb_MiniTable_Field.mode
-  kUpb_FieldRep_Max = kUpb_FieldRep_8Byte,
-} upb_FieldRep;
-
-UPB_INLINE upb_FieldMode upb_FieldMode_Get(const upb_MiniTable_Field* field) {
-  return (upb_FieldMode)(field->mode & 3);
-}
-
-UPB_INLINE bool upb_IsRepeatedOrMap(const upb_MiniTable_Field* field) {
-  /* This works because upb_FieldMode has no value 3. */
-  return !(field->mode & kUpb_FieldMode_Scalar);
-}
-
-UPB_INLINE bool upb_IsSubMessage(const upb_MiniTable_Field* field) {
-  return field->descriptortype == kUpb_FieldType_Message ||
-         field->descriptortype == kUpb_FieldType_Group;
-}
-
-struct upb_Decoder;
-struct upb_MiniTable;
-
-typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr,
-                                     upb_Message* msg, intptr_t table,
-                                     uint64_t hasbits, uint64_t data);
-
-typedef struct {
-  uint64_t field_data;
-  _upb_FieldParser* field_parser;
-} _upb_FastTable_Entry;
-
-typedef struct {
-  const int32_t* values;  // List of values <0 or >63
-  uint64_t mask;          // Bits are set for acceptable value 0 <= x < 64
-  int value_count;
-} upb_MiniTable_Enum;
-
-UPB_INLINE bool upb_MiniTable_Enum_CheckValue(const upb_MiniTable_Enum* e,
-                                              int32_t val) {
-  uint32_t uval = (uint32_t)val;
-  if (uval < 64) return e->mask & (1 << uval);
-  // OPT: binary search long lists?
-  int n = e->value_count;
-  for (int i = 0; i < n; i++) {
-    if (e->values[i] == val) return true;
-  }
-  return false;
-}
-
-typedef union {
-  const struct upb_MiniTable* submsg;
-  const upb_MiniTable_Enum* subenum;
-} upb_MiniTable_Sub;
-
-typedef enum {
-  kUpb_ExtMode_NonExtendable = 0,  // Non-extendable message.
-  kUpb_ExtMode_Extendable = 1,     // Normal extendable message.
-  kUpb_ExtMode_IsMessageSet = 2,   // MessageSet message.
-  kUpb_ExtMode_IsMessageSet_ITEM =
-      3,  // MessageSet item (temporary only, see decode.c)
-
-  // During table building we steal a bit to indicate that the message is a map
-  // entry.  *Only* used during table building!
-  kUpb_ExtMode_IsMapEntry = 4,
-} upb_ExtMode;
-
-/* MessageSet wire format is:
- *   message MessageSet {
- *     repeated group Item = 1 {
- *       required int32 type_id = 2;
- *       required string message = 3;
- *     }
- *   }
- */
-typedef enum {
-  _UPB_MSGSET_ITEM = 1,
-  _UPB_MSGSET_TYPEID = 2,
-  _UPB_MSGSET_MESSAGE = 3,
-} upb_msgext_fieldnum;
-
-struct upb_MiniTable {
-  const upb_MiniTable_Sub* subs;
-  const upb_MiniTable_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;
-  uint8_t ext;  // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1
-  uint8_t dense_below;
-  uint8_t table_mask;
-  uint8_t required_count;  // Required fields have the lowest hasbits.
-  /* To statically initialize the tables of variable length, we need a flexible
-   * array member, and we need to compile in gnu99 mode (constant initialization
-   * of flexible array members is a GNU extension, not in C99 unfortunately. */
-  _upb_FastTable_Entry fasttable[];
-};
-
-typedef struct {
-  upb_MiniTable_Field field;
-  const upb_MiniTable* extendee;
-  upb_MiniTable_Sub sub; /* NULL unless submessage or proto2 enum */
-} upb_MiniTable_Extension;
-
-typedef struct {
-  const upb_MiniTable** msgs;
-  const upb_MiniTable_Enum** enums;
-  const upb_MiniTable_Extension** exts;
-  int msg_count;
-  int enum_count;
-  int ext_count;
-} upb_MiniTable_File;
-
-// Computes a bitmask in which the |l->required_count| lowest bits are set,
-// except that we skip the lowest bit (because upb never uses hasbit 0).
+// Converting between internal table representation and user values.
 //
-// Sample output:
-//    requiredmask(1) => 0b10 (0x2)
-//    requiredmask(5) => 0b111110 (0x3e)
-UPB_INLINE uint64_t upb_MiniTable_requiredmask(const upb_MiniTable* l) {
-  int n = l->required_count;
-  assert(0 < n && n <= 63);
-  return ((1ULL << n) - 1) << 1;
-}
-
-/** upb_ExtensionRegistry *****************************************************/
-
-/* Adds the given extension info for message type |l| and field number |num|
- * into the registry. Returns false if this message type and field number were
- * already in the map, or if memory allocation fails. */
-bool _upb_extreg_add(upb_ExtensionRegistry* r,
-                     const upb_MiniTable_Extension** e, size_t count);
-
-/* Looks up the extension (if any) defined for message type |l| and field
- * number |num|.  If an extension was found, copies the field info into |*ext|
- * and returns true. Otherwise returns false. */
-const upb_MiniTable_Extension* _upb_extreg_get(const upb_ExtensionRegistry* r,
-                                               const upb_MiniTable* l,
-                                               uint32_t num);
-
-/** upb_Message ***************************************************************/
-
-/* Internal members of a upb_Message that track unknown fields and/or
- * extensions. We can change this without breaking binary compatibility.  We put
- * these before the user's data.  The user's upb_Message* points after the
- * upb_Message_Internal. */
-
-typedef struct {
-  /* Total size of this structure, including the data that follows.
-   * Must be aligned to 8, which is alignof(upb_Message_Extension) */
-  uint32_t size;
-
-  /* Offsets relative to the beginning of this structure.
-   *
-   * Unknown data grows forward from the beginning to unknown_end.
-   * Extension data grows backward from size to ext_begin.
-   * When the two meet, we're out of data and have to realloc.
-   *
-   * If we imagine that the final member of this struct is:
-   *   char data[size - overhead];  // overhead =
-   * sizeof(upb_Message_InternalData)
-   *
-   * Then we have:
-   *   unknown data: data[0 .. (unknown_end - overhead)]
-   *   extensions data: data[(ext_begin - overhead) .. (size - overhead)] */
-  uint32_t unknown_end;
-  uint32_t ext_begin;
-  /* Data follows, as if there were an array:
-   *   char data[size - sizeof(upb_Message_InternalData)]; */
-} upb_Message_InternalData;
-
-typedef struct {
-  upb_Message_InternalData* internal;
-  /* Message data follows. */
-} upb_Message_Internal;
-
-/* Maps upb_CType -> memory size. */
-extern char _upb_CTypeo_size[12];
-
-UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* l) {
-  return l->size + sizeof(upb_Message_Internal);
-}
-
-UPB_INLINE upb_Message* _upb_Message_New_inl(const upb_MiniTable* l,
-                                             upb_Arena* a) {
-  size_t size = upb_msg_sizeof(l);
-  void* mem = upb_Arena_Malloc(a, size);
-  upb_Message* msg;
-  if (UPB_UNLIKELY(!mem)) return NULL;
-  msg = UPB_PTR_AT(mem, sizeof(upb_Message_Internal), upb_Message);
-  memset(mem, 0, size);
-  return msg;
-}
-
-/* Creates a new messages with the given layout on the given arena. */
-upb_Message* _upb_Message_New(const upb_MiniTable* l, upb_Arena* a);
-
-UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(upb_Message* msg) {
-  ptrdiff_t size = sizeof(upb_Message_Internal);
-  return (upb_Message_Internal*)((char*)msg - size);
-}
-
-/* Clears the given message. */
-void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l);
-
-/* Discards the unknown fields for this message only. */
-void _upb_Message_DiscardUnknown_shallow(upb_Message* msg);
-
-/* Adds unknown data (serialized protobuf data) to the given message.  The data
- * is copied into the message instance. */
-bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
-                             upb_Arena* arena);
-
-/** upb_Message_Extension *****************************************************/
-
-/* The internal representation of an extension is self-describing: it contains
- * enough information that we can serialize it to binary format without needing
- * to look it up in a upb_ExtensionRegistry.
- *
- * This representation allocates 16 bytes to data on 64-bit platforms.  This is
- * rather wasteful for scalars (in the extreme case of bool, it wastes 15
- * bytes). We accept this because we expect messages to be the most common
- * extension type. */
-typedef struct {
-  const upb_MiniTable_Extension* ext;
-  union {
-    upb_StringView str;
-    void* ptr;
-    char scalar_data[8];
-  } data;
-} upb_Message_Extension;
-
-/* Adds the given extension data to the given message. |ext| is copied into the
- * message instance. This logically replaces any previously-added extension with
- * this number */
-upb_Message_Extension* _upb_Message_Getorcreateext(
-    upb_Message* msg, const upb_MiniTable_Extension* ext, upb_Arena* arena);
-
-/* Returns an array of extensions for this message. Note: the array is
- * ordered in reverse relative to the order of creation. */
-const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
-                                                  size_t* count);
-
-/* Returns an extension for the given field number, or NULL if no extension
- * exists for this field number. */
-const upb_Message_Extension* _upb_Message_Getext(
-    const upb_Message* msg, const upb_MiniTable_Extension* ext);
-
-void _upb_Message_Clearext(upb_Message* msg,
-                           const upb_MiniTable_Extension* ext);
-
-void _upb_Message_Clearext(upb_Message* msg,
-                           const upb_MiniTable_Extension* ext);
-
-/** Hasbit access *************************************************************/
-
-UPB_INLINE bool _upb_hasbit(const upb_Message* msg, size_t idx) {
-  return (*UPB_PTR_AT(msg, idx / 8, const char) & (1 << (idx % 8))) != 0;
-}
-
-UPB_INLINE void _upb_sethas(const upb_Message* msg, size_t idx) {
-  (*UPB_PTR_AT(msg, idx / 8, char)) |= (char)(1 << (idx % 8));
-}
-
-UPB_INLINE void _upb_clearhas(const upb_Message* msg, size_t idx) {
-  (*UPB_PTR_AT(msg, idx / 8, char)) &= (char)(~(1 << (idx % 8)));
-}
-
-UPB_INLINE size_t _upb_Message_Hasidx(const upb_MiniTable_Field* f) {
-  UPB_ASSERT(f->presence > 0);
-  return f->presence;
-}
-
-UPB_INLINE bool _upb_hasbit_field(const upb_Message* msg,
-                                  const upb_MiniTable_Field* f) {
-  return _upb_hasbit(msg, _upb_Message_Hasidx(f));
-}
-
-UPB_INLINE void _upb_sethas_field(const upb_Message* msg,
-                                  const upb_MiniTable_Field* f) {
-  _upb_sethas(msg, _upb_Message_Hasidx(f));
-}
-
-UPB_INLINE void _upb_clearhas_field(const upb_Message* msg,
-                                    const upb_MiniTable_Field* f) {
-  _upb_clearhas(msg, _upb_Message_Hasidx(f));
-}
-
-/** Oneof case access *********************************************************/
-
-UPB_INLINE uint32_t* _upb_oneofcase(upb_Message* 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_MiniTable_Field* f) {
-  UPB_ASSERT(f->presence < 0);
-  return ~(ptrdiff_t)f->presence;
-}
-
-UPB_INLINE uint32_t* _upb_oneofcase_field(upb_Message* msg,
-                                          const upb_MiniTable_Field* f) {
-  return _upb_oneofcase(msg, _upb_oneofcase_ofs(f));
-}
-
-UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_Message* msg,
-                                            const upb_MiniTable_Field* f) {
-  return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f));
-}
-
-UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_Message* msg, size_t ofs) {
-  return *UPB_PTR_AT(msg, ofs, const upb_Message*) != NULL;
-}
-
-/** 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_CType type) {
-  switch (type) {
-    case kUpb_CType_Bool:
-      return 0;
-    case kUpb_CType_Float:
-    case kUpb_CType_Int32:
-    case kUpb_CType_UInt32:
-    case kUpb_CType_Enum:
-      return 2;
-    case kUpb_CType_Message:
-      return UPB_SIZE(2, 3);
-    case kUpb_CType_Double:
-    case kUpb_CType_Int64:
-    case kUpb_CType_UInt64:
-      return 3;
-    case kUpb_CType_String:
-    case kUpb_CType_Bytes:
-      return UPB_SIZE(3, 4);
-  }
-  UPB_UNREACHABLE();
-}
-UPB_INLINE void* _upb_Array_Resize_accessor(void* msg, size_t ofs, size_t size,
-                                            upb_CType 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_CType 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_Message_Internal internal;
-  union {
-    upb_StringView str; /* For str/bytes. */
-    upb_value val;      /* For all other types. */
-  } k;
-  union {
-    upb_StringView str; /* For str/bytes. */
-    upb_value val;      /* For all other types. */
-  } v;
-} upb_MapEntry;
-
-/* 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_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_StringView _upb_map_tokey(const void* key, size_t size) {
   if (size == UPB_MAPTYPE_STRING) {
@@ -1745,10 +1341,24 @@
   }
 }
 
-/* Map operations, shared by reflection and generated code. */
+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 size_t _upb_Map_Size(const upb_Map* map) {
-  return map->table.t.count;
+UPB_INLINE void _upb_Map_Clear(upb_Map* map) {
+  upb_strtable_clear(&map->table);
+}
+
+UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key,
+                                size_t key_size) {
+  upb_StringView k = _upb_map_tokey(key, key_size);
+  return upb_strtable_remove2(&map->table, k.data, k.size, NULL);
 }
 
 UPB_INLINE bool _upb_Map_Get(const upb_Map* map, const void* key,
@@ -1762,38 +1372,779 @@
   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_INLINE upb_MapInsertStatus _upb_Map_Insert(upb_Map* map, const void* key,
+                                               size_t key_size, void* val,
+                                               size_t val_size, upb_Arena* a) {
   upb_StringView strkey = _upb_map_tokey(key, key_size);
   upb_value tabval = {0};
-  if (!_upb_map_tovalue(val, val_size, &tabval, a)) return false;
+  if (!_upb_map_tovalue(val, val_size, &tabval, a)) {
+    return kUpb_MapInsertStatus_OutOfMemory;
+  }
 
-  /* TODO(haberman): add overwrite operation to minimize number of lookups. */
-  upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
-  return upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a);
+  // TODO(haberman): add overwrite operation to minimize number of lookups.
+  bool removed =
+      upb_strtable_remove2(&map->table, strkey.data, strkey.size, NULL);
+  if (!upb_strtable_insert(&map->table, strkey.data, strkey.size, tabval, a)) {
+    return kUpb_MapInsertStatus_OutOfMemory;
+  }
+  return removed ? kUpb_MapInsertStatus_Replaced
+                 : kUpb_MapInsertStatus_Inserted;
 }
 
-UPB_INLINE bool _upb_Map_Delete(upb_Map* map, const void* key,
-                                size_t key_size) {
-  upb_StringView k = _upb_map_tokey(key, key_size);
-  return upb_strtable_remove2(&map->table, k.data, k.size, NULL);
+UPB_INLINE size_t _upb_Map_Size(const upb_Map* map) {
+  return map->table.t.count;
 }
 
-UPB_INLINE void _upb_Map_Clear(upb_Map* map) {
-  upb_strtable_clear(&map->table);
+// 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);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_COLLECTIONS_MAP_INTERNAL_H_ */
+
+#ifndef UPB_BASE_LOG2_H_
+#define UPB_BASE_LOG2_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE int upb_Log2Ceiling(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
 }
 
-/* Message map operations, these get the map from the message first. */
+UPB_INLINE int upb_Log2CeilingSize(int x) { return 1 << upb_Log2Ceiling(x); }
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_BASE_LOG2_H_ */
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+#ifndef UPB_COLLECTIONS_MAP_SORTER_INTERNAL_H_
+#define UPB_COLLECTIONS_MAP_SORTER_INTERNAL_H_
+
+#include <stdlib.h>
+
+
+#ifndef UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
+#define UPB_MINI_TABLE_MESSAGE_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_Decoder;
+typedef const char* _upb_FieldParser(struct upb_Decoder* d, const char* ptr,
+                                     upb_Message* msg, intptr_t table,
+                                     uint64_t hasbits, uint64_t data);
+typedef struct {
+  uint64_t field_data;
+  _upb_FieldParser* field_parser;
+} _upb_FastTable_Entry;
+
+typedef enum {
+  kUpb_ExtMode_NonExtendable = 0,  // Non-extendable message.
+  kUpb_ExtMode_Extendable = 1,     // Normal extendable message.
+  kUpb_ExtMode_IsMessageSet = 2,   // MessageSet message.
+  kUpb_ExtMode_IsMessageSet_ITEM =
+      3,  // MessageSet item (temporary only, see decode.c)
+
+  // During table building we steal a bit to indicate that the message is a map
+  // entry.  *Only* used during table building!
+  kUpb_ExtMode_IsMapEntry = 4,
+} upb_ExtMode;
+
+// upb_MiniTable represents the memory layout of a given upb_MessageDef.
+// The members are public so generated code can initialize them,
+// but users MUST NOT directly read or write any of its members.
+struct upb_MiniTable {
+  const upb_MiniTableSub* subs;
+  const upb_MiniTableField* 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;
+  uint8_t ext;  // upb_ExtMode, declared as uint8_t so sizeof(ext) == 1
+  uint8_t dense_below;
+  uint8_t table_mask;
+  uint8_t required_count;  // Required fields have the lowest hasbits.
+
+  // To statically initialize the tables of variable length, we need a flexible
+  // array member, and we need to compile in gnu99 mode (constant initialization
+  // of flexible array members is a GNU extension, not in C99 unfortunately.
+  _upb_FastTable_Entry fasttable[];
+};
+
+// Map entries aren't actually stored for map fields, they are only used during
+// parsing. For parsing, it helps a lot if all map entry messages have the same
+// layout. The layout code in mini_table/decode.c will ensure that all map
+// entries have this layout.
+//
+// Note that users can and do create map entries directly, which will also use
+// this layout.
+//
+// NOTE: sync with mini_table/decode.c.
+typedef struct {
+  // We only need 2 hasbits max, but due to alignment we'll use 8 bytes here,
+  // and the uint64_t helps make this clear.
+  uint64_t hasbits;
+  union {
+    upb_StringView str;  // For str/bytes.
+    upb_value val;       // For all other types.
+  } k;
+  union {
+    upb_StringView str;  // For str/bytes.
+    upb_value val;       // For all other types.
+  } v;
+} upb_MapEntryData;
+
+typedef struct {
+  void* internal_data;
+  upb_MapEntryData data;
+} upb_MapEntry;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Computes a bitmask in which the |l->required_count| lowest bits are set,
+// except that we skip the lowest bit (because upb never uses hasbit 0).
+//
+// Sample output:
+//    requiredmask(1) => 0b10 (0x2)
+//    requiredmask(5) => 0b111110 (0x3e)
+UPB_INLINE uint64_t upb_MiniTable_requiredmask(const upb_MiniTable* l) {
+  int n = l->required_count;
+  assert(0 < n && n <= 63);
+  return ((1ULL << n) - 1) << 1;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_MESSAGE_INTERNAL_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// _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);
+}
+
+UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
+                                    _upb_sortedmap* sorted, upb_MapEntry* ent) {
+  if (sorted->pos == sorted->end) return false;
+  const upb_tabent* tabent = s->entries[sorted->pos++];
+  upb_StringView key = upb_tabstrview(tabent->key);
+  _upb_map_fromkey(key, &ent->data.k, map->key_size);
+  upb_value val = {tabent->val.val};
+  _upb_map_fromvalue(val, &ent->data.v, map->val_size);
+  return true;
+}
+
+UPB_INLINE void _upb_mapsorter_popmap(_upb_mapsorter* s,
+                                      _upb_sortedmap* sorted) {
+  s->size = sorted->start;
+}
+
+bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType key_type,
+                            const upb_Map* map, _upb_sortedmap* sorted);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_COLLECTIONS_MAP_SORTER_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_MESSAGE_INTERNAL_H_
+#define UPB_MESSAGE_INTERNAL_H_
+
+#include <stdlib.h>
+#include <string.h>
+
+
+#ifndef UPB_MESSAGE_EXTENSION_INTERNAL_H_
+#define UPB_MESSAGE_EXTENSION_INTERNAL_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_MESSAGE_MESSAGE_H_
+#define UPB_MESSAGE_MESSAGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Creates a new message with the given mini_table on the given arena.
+upb_Message* upb_Message_New(const upb_MiniTable* mini_table, upb_Arena* arena);
+
+// Adds unknown data (serialized protobuf data) to the given message.
+// The data is copied into the message instance.
+void upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
+                            upb_Arena* arena);
+
+// Returns a reference to the message's unknown data.
+const char* upb_Message_GetUnknown(const upb_Message* msg, size_t* len);
+
+// Removes partial unknown data from message.
+void upb_Message_DeleteUnknown(upb_Message* msg, const char* data, size_t len);
+
+// Returns the number of extensions present in this message.
+size_t upb_Message_ExtensionCount(const upb_Message* msg);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_MESSAGE_H_ */
+
+#ifndef UPB_MINI_TABLE_EXTENSION_INTERNAL_H_
+#define UPB_MINI_TABLE_EXTENSION_INTERNAL_H_
+
+
+#ifndef UPB_MINI_TABLE_FIELD_INTERNAL_H_
+#define UPB_MINI_TABLE_FIELD_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_MiniTableField {
+  uint32_t number;
+  uint16_t offset;
+  int16_t presence;       // If >0, hasbit_index.  If <0, ~oneof_index
+  uint16_t submsg_index;  // kUpb_NoSub if descriptortype != MESSAGE/GROUP/ENUM
+  uint8_t descriptortype;
+
+  // upb_FieldMode | upb_LabelFlags | (upb_FieldRep << kUpb_FieldRep_Shift)
+  uint8_t mode;
+};
+
+#define kUpb_NoSub ((uint16_t)-1)
+
+typedef enum {
+  kUpb_FieldMode_Map = 0,
+  kUpb_FieldMode_Array = 1,
+  kUpb_FieldMode_Scalar = 2,
+} upb_FieldMode;
+
+// Mask to isolate the upb_FieldMode from field.mode.
+#define kUpb_FieldMode_Mask 3
+
+// Extra flags on the mode field.
+typedef enum {
+  kUpb_LabelFlags_IsPacked = 4,
+  kUpb_LabelFlags_IsExtension = 8,
+  // Indicates that this descriptor type is an "alternate type":
+  //   - for Int32, this indicates that the actual type is Enum (but was
+  //     rewritten to Int32 because it is an open enum that requires no check).
+  //   - for Bytes, this indicates that the actual type is String (but does
+  //     not require any UTF-8 check).
+  kUpb_LabelFlags_IsAlternate = 16,
+} upb_LabelFlags;
+
+// Note: we sort by this number when calculating layout order.
+typedef enum {
+  kUpb_FieldRep_1Byte = 0,
+  kUpb_FieldRep_4Byte = 1,
+  kUpb_FieldRep_StringView = 2,
+  kUpb_FieldRep_8Byte = 3,
+
+  kUpb_FieldRep_Max = kUpb_FieldRep_8Byte,
+} upb_FieldRep;
+
+#define kUpb_FieldRep_Shift 6
+
+UPB_INLINE upb_FieldRep
+_upb_MiniTableField_GetRep(const upb_MiniTableField* field) {
+  return (upb_FieldRep)(field->mode >> kUpb_FieldRep_Shift);
+}
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE upb_FieldMode upb_FieldMode_Get(const upb_MiniTableField* field) {
+  return (upb_FieldMode)(field->mode & 3);
+}
+
+UPB_INLINE bool upb_IsRepeatedOrMap(const upb_MiniTableField* field) {
+  // This works because upb_FieldMode has no value 3.
+  return !(field->mode & kUpb_FieldMode_Scalar);
+}
+
+UPB_INLINE bool upb_IsSubMessage(const upb_MiniTableField* field) {
+  return field->descriptortype == kUpb_FieldType_Message ||
+         field->descriptortype == kUpb_FieldType_Group;
+}
+
+// LINT.IfChange(presence_logic)
+
+// Hasbit access ///////////////////////////////////////////////////////////////
+
+UPB_INLINE size_t _upb_hasbit_ofs(size_t idx) { return idx / 8; }
+
+UPB_INLINE char _upb_hasbit_mask(size_t idx) { return 1 << (idx % 8); }
+
+UPB_INLINE bool _upb_hasbit(const upb_Message* msg, size_t idx) {
+  return (*UPB_PTR_AT(msg, _upb_hasbit_ofs(idx), const char) &
+          _upb_hasbit_mask(idx)) != 0;
+}
+
+UPB_INLINE void _upb_sethas(const upb_Message* msg, size_t idx) {
+  (*UPB_PTR_AT(msg, _upb_hasbit_ofs(idx), char)) |= _upb_hasbit_mask(idx);
+}
+
+UPB_INLINE void _upb_clearhas(const upb_Message* msg, size_t idx) {
+  (*UPB_PTR_AT(msg, _upb_hasbit_ofs(idx), char)) &= ~_upb_hasbit_mask(idx);
+}
+
+UPB_INLINE size_t _upb_Message_Hasidx(const upb_MiniTableField* f) {
+  UPB_ASSERT(f->presence > 0);
+  return f->presence;
+}
+
+UPB_INLINE bool _upb_hasbit_field(const upb_Message* msg,
+                                  const upb_MiniTableField* f) {
+  return _upb_hasbit(msg, _upb_Message_Hasidx(f));
+}
+
+UPB_INLINE void _upb_sethas_field(const upb_Message* msg,
+                                  const upb_MiniTableField* f) {
+  _upb_sethas(msg, _upb_Message_Hasidx(f));
+}
+
+UPB_INLINE void _upb_clearhas_field(const upb_Message* msg,
+                                    const upb_MiniTableField* f) {
+  _upb_clearhas(msg, _upb_Message_Hasidx(f));
+}
+
+// Oneof case access ///////////////////////////////////////////////////////////
+
+UPB_INLINE uint32_t* _upb_oneofcase(upb_Message* 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_MiniTableField* f) {
+  UPB_ASSERT(f->presence < 0);
+  return ~(ptrdiff_t)f->presence;
+}
+
+UPB_INLINE uint32_t* _upb_oneofcase_field(upb_Message* msg,
+                                          const upb_MiniTableField* f) {
+  return _upb_oneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE uint32_t _upb_getoneofcase_field(const upb_Message* msg,
+                                            const upb_MiniTableField* f) {
+  return _upb_getoneofcase(msg, _upb_oneofcase_ofs(f));
+}
+
+UPB_INLINE bool _upb_has_submsg_nohasbit(const upb_Message* msg, size_t ofs) {
+  return *UPB_PTR_AT(msg, ofs, const upb_Message*) != NULL;
+}
+
+// LINT.ThenChange(GoogleInternalName2)
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_FIELD_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_SUB_INTERNAL_H_
+#define UPB_MINI_TABLE_SUB_INTERNAL_H_
+
+
+union upb_MiniTableSub {
+  const upb_MiniTable* submsg;
+  const upb_MiniTableEnum* subenum;
+};
+
+#endif /* UPB_MINI_TABLE_SUB_INTERNAL_H_ */
+
+// Must be last.
+
+struct upb_MiniTableExtension {
+  upb_MiniTableField field;
+  const upb_MiniTable* extendee;
+  upb_MiniTableSub sub;  // NULL unless submessage or proto2 enum
+};
+
+
+#endif /* UPB_MINI_TABLE_EXTENSION_INTERNAL_H_ */
+
+// Must be last.
+
+// The internal representation of an extension is self-describing: it contains
+// enough information that we can serialize it to binary format without needing
+// to look it up in a upb_ExtensionRegistry.
+//
+// This representation allocates 16 bytes to data on 64-bit platforms.
+// This is rather wasteful for scalars (in the extreme case of bool,
+// it wastes 15 bytes). We accept this because we expect messages to be
+// the most common extension type.
+typedef struct {
+  const upb_MiniTableExtension* ext;
+  union {
+    upb_StringView str;
+    void* ptr;
+    char scalar_data[8];
+  } data;
+} upb_Message_Extension;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Adds the given extension data to the given message.
+// |ext| is copied into the message instance.
+// This logically replaces any previously-added extension with this number.
+upb_Message_Extension* _upb_Message_GetOrCreateExtension(
+    upb_Message* msg, const upb_MiniTableExtension* ext, upb_Arena* arena);
+
+// Returns an array of extensions for this message.
+// Note: the array is ordered in reverse relative to the order of creation.
+const upb_Message_Extension* _upb_Message_Getexts(const upb_Message* msg,
+                                                  size_t* count);
+
+// Returns an extension for the given field number, or NULL if no extension
+// exists for this field number.
+const upb_Message_Extension* _upb_Message_Getext(
+    const upb_Message* msg, const upb_MiniTableExtension* ext);
+
+void _upb_Message_Clearext(upb_Message* msg, const upb_MiniTableExtension* ext);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_EXTENSION_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_EXTENSION_REGISTRY_H_
+#define UPB_MINI_TABLE_EXTENSION_REGISTRY_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+/* Extension registry: a dynamic data structure that stores a map of:
+ *   (upb_MiniTable, number) -> extension info
+ *
+ * upb_decode() uses upb_ExtensionRegistry to look up extensions while parsing
+ * binary format.
+ *
+ * upb_ExtensionRegistry is part of the mini-table (msglayout) family of
+ * objects. Like all mini-table objects, it is suitable for reflection-less
+ * builds that do not want to expose names into the binary.
+ *
+ * Unlike most mini-table types, upb_ExtensionRegistry requires dynamic memory
+ * allocation and dynamic initialization:
+ * * If reflection is being used, then upb_DefPool will construct an appropriate
+ *   upb_ExtensionRegistry automatically.
+ * * For a mini-table only build, the user must manually construct the
+ *   upb_ExtensionRegistry and populate it with all of the extensions the user
+ * cares about.
+ * * A third alternative is to manually unpack relevant extensions after the
+ *   main parse is complete, similar to how Any works. This is perhaps the
+ *   nicest solution from the perspective of reducing dependencies, avoiding
+ *   dynamic memory allocation, and avoiding the need to parse uninteresting
+ *   extensions.  The downsides are:
+ *     (1) parse errors are not caught during the main parse
+ *     (2) the CPU hit of parsing comes during access, which could cause an
+ *         undesirable stutter in application performance.
+ *
+ * Users cannot directly get or put into this map. Users can only add the
+ * extensions from a generated module and pass the extension registry to the
+ * binary decoder.
+ *
+ * A upb_DefPool provides a upb_ExtensionRegistry, so any users who use
+ * reflection do not need to populate a upb_ExtensionRegistry directly.
+ */
+
+typedef struct upb_ExtensionRegistry upb_ExtensionRegistry;
+
+// Creates a upb_ExtensionRegistry in the given arena.
+// The arena must outlive any use of the extreg.
+upb_ExtensionRegistry* upb_ExtensionRegistry_New(upb_Arena* arena);
+
+// Adds the given extension info for the array |e| of size |count| into the
+// registry. If there are any errors, the entire array is backed out.
+// The extensions must outlive the registry.
+// Possible errors include OOM or an extension number that already exists.
+// TODO: There is currently no way to determine the exact reason for failure.
+bool upb_ExtensionRegistry_AddArray(upb_ExtensionRegistry* r,
+                                    const upb_MiniTableExtension** e,
+                                    size_t count);
+
+// Looks up the extension (if any) defined for message type |t| and field
+// number |num|. Returns the extension if found, otherwise NULL.
+const upb_MiniTableExtension* upb_ExtensionRegistry_Lookup(
+    const upb_ExtensionRegistry* r, const upb_MiniTable* t, uint32_t num);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_EXTENSION_REGISTRY_H_ */
+
+#ifndef UPB_MINI_TABLE_FILE_INTERNAL_H_
+#define UPB_MINI_TABLE_FILE_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_MiniTableFile {
+  const upb_MiniTable** msgs;
+  const upb_MiniTableEnum** enums;
+  const upb_MiniTableExtension** exts;
+  int msg_count;
+  int enum_count;
+  int ext_count;
+};
+
+
+#endif /* UPB_MINI_TABLE_FILE_INTERNAL_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+extern const float kUpb_FltInfinity;
+extern const double kUpb_Infinity;
+extern const double kUpb_NaN;
+
+/* Internal members of a upb_Message that track unknown fields and/or
+ * extensions. We can change this without breaking binary compatibility.  We put
+ * these before the user's data.  The user's upb_Message* points after the
+ * upb_Message_Internal. */
+
+typedef struct {
+  /* Total size of this structure, including the data that follows.
+   * Must be aligned to 8, which is alignof(upb_Message_Extension) */
+  uint32_t size;
+
+  /* Offsets relative to the beginning of this structure.
+   *
+   * Unknown data grows forward from the beginning to unknown_end.
+   * Extension data grows backward from size to ext_begin.
+   * When the two meet, we're out of data and have to realloc.
+   *
+   * If we imagine that the final member of this struct is:
+   *   char data[size - overhead];  // overhead =
+   * sizeof(upb_Message_InternalData)
+   *
+   * Then we have:
+   *   unknown data: data[0 .. (unknown_end - overhead)]
+   *   extensions data: data[(ext_begin - overhead) .. (size - overhead)] */
+  uint32_t unknown_end;
+  uint32_t ext_begin;
+  /* Data follows, as if there were an array:
+   *   char data[size - sizeof(upb_Message_InternalData)]; */
+} upb_Message_InternalData;
+
+typedef struct {
+  upb_Message_InternalData* internal;
+  /* Message data follows. */
+} upb_Message_Internal;
+
+/* Maps upb_CType -> memory size. */
+extern char _upb_CTypeo_size[12];
+
+UPB_INLINE size_t upb_msg_sizeof(const upb_MiniTable* t) {
+  return t->size + sizeof(upb_Message_Internal);
+}
+
+// Inline version upb_Message_New(), for internal use.
+UPB_INLINE upb_Message* _upb_Message_New(const upb_MiniTable* mini_table,
+                                         upb_Arena* arena) {
+  size_t size = upb_msg_sizeof(mini_table);
+  void* mem = upb_Arena_Malloc(arena, size + sizeof(upb_Message_Internal));
+  if (UPB_UNLIKELY(!mem)) return NULL;
+  upb_Message* msg = UPB_PTR_AT(mem, sizeof(upb_Message_Internal), upb_Message);
+  memset(mem, 0, size);
+  return msg;
+}
+
+UPB_INLINE upb_Message_Internal* upb_Message_Getinternal(
+    const upb_Message* msg) {
+  ptrdiff_t size = sizeof(upb_Message_Internal);
+  return (upb_Message_Internal*)((char*)msg - size);
+}
+
+// Clears the given message.
+void _upb_Message_Clear(upb_Message* msg, const upb_MiniTable* l);
+
+// Discards the unknown fields for this message only.
+void _upb_Message_DiscardUnknown_shallow(upb_Message* msg);
+
+// Adds unknown data (serialized protobuf data) to the given message.
+// The data is copied into the message instance.
+bool _upb_Message_AddUnknown(upb_Message* msg, const char* data, size_t len,
+                             upb_Arena* arena);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MESSAGE_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_ENUM_INTERNAL_H_
+#define UPB_MINI_TABLE_ENUM_INTERNAL_H_
+
+
+// Must be last.
+
+struct upb_MiniTableEnum {
+  uint32_t mask_limit;   // Limit enum value that can be tested with mask.
+  uint32_t value_count;  // Number of values after the bitfield.
+  uint32_t data[];       // Bitmask + enumerated values follow.
+};
+
+typedef enum {
+  _kUpb_FastEnumCheck_ValueIsInEnum = 0,
+  _kUpb_FastEnumCheck_ValueIsNotInEnum = 1,
+  _kUpb_FastEnumCheck_CannotCheckFast = 2,
+} _kUpb_FastEnumCheck_Status;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE _kUpb_FastEnumCheck_Status
+_upb_MiniTable_CheckEnumValueFast(const upb_MiniTableEnum* e, uint32_t val) {
+  if (UPB_UNLIKELY(val >= 64)) return _kUpb_FastEnumCheck_CannotCheckFast;
+  uint64_t mask = e->data[0] | ((uint64_t)e->data[1] << 32);
+  return (mask & (1ULL << val)) ? _kUpb_FastEnumCheck_ValueIsInEnum
+                                : _kUpb_FastEnumCheck_ValueIsNotInEnum;
+}
+
+UPB_INLINE bool _upb_MiniTable_CheckEnumValueSlow(const upb_MiniTableEnum* e,
+                                                  uint32_t val) {
+  if (val < e->mask_limit) return e->data[val / 32] & (1ULL << (val % 32));
+  // OPT: binary search long lists?
+  const uint32_t* start = &e->data[e->mask_limit / 32];
+  const uint32_t* limit = &e->data[(e->mask_limit / 32) + e->value_count];
+  for (const uint32_t* p = start; p < limit; p++) {
+    if (*p == val) return true;
+  }
+  return false;
+}
+
+// Validates enum value against range defined by enum mini table.
+UPB_INLINE bool upb_MiniTableEnum_CheckValue(const upb_MiniTableEnum* e,
+                                             uint32_t val) {
+  _kUpb_FastEnumCheck_Status status = _upb_MiniTable_CheckEnumValueFast(e, val);
+  if (UPB_UNLIKELY(status == _kUpb_FastEnumCheck_CannotCheckFast)) {
+    return _upb_MiniTable_CheckEnumValueSlow(e, val);
+  }
+  return status == _kUpb_FastEnumCheck_ValueIsInEnum ? true : false;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_ENUM_INTERNAL_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_
+
+
+// These functions are only used by generated code.
+
+#ifndef UPB_COLLECTIONS_MAP_GENCODE_UTIL_H_
+#define UPB_COLLECTIONS_MAP_GENCODE_UTIL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Message map operations, these get the map from the message first.
 
 UPB_INLINE size_t _upb_msg_map_size(const upb_Message* msg, size_t ofs) {
   upb_Map* map = *UPB_PTR_AT(msg, ofs, upb_Map*);
@@ -1822,7 +2173,8 @@
   if (!*map) {
     *map = _upb_Map_New(arena, key_size, val_size);
   }
-  return _upb_Map_Set(*map, key, key_size, val, val_size, arena);
+  return _upb_Map_Insert(*map, key, key_size, val, val_size, arena) !=
+         kUpb_MapInsertStatus_OutOfMemory;
 }
 
 UPB_INLINE bool _upb_msg_map_delete(upb_Message* msg, size_t ofs,
@@ -1838,8 +2190,6 @@
   _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;
@@ -1858,8 +2208,8 @@
 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_StringView for string fields. */
+  // This is like _upb_map_tovalue() except the entry already exists
+  // so we can reuse the allocated upb_StringView for string fields.
   if (size == UPB_MAPTYPE_STRING) {
     upb_StringView* strp = (upb_StringView*)(uintptr_t)ent->val.val;
     memcpy(strp, val, sizeof(*strp));
@@ -1868,51 +2218,68 @@
   }
 }
 
-/** _upb_mapsorter ************************************************************/
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-/* _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;
+#endif /* UPB_COLLECTIONS_MAP_GENCODE_UTIL_H_ */
 
-typedef struct {
-  int start;
-  int pos;
-  int end;
-} _upb_sortedmap;
+#ifndef UPB_MESSAGE_ACCESSORS_H_
+#define UPB_MESSAGE_ACCESSORS_H_
 
-UPB_INLINE void _upb_mapsorter_init(_upb_mapsorter* s) {
-  s->entries = NULL;
-  s->size = 0;
-  s->cap = 0;
+
+#ifndef UPB_MINI_TABLE_COMMON_H_
+#define UPB_MINI_TABLE_COMMON_H_
+
+
+// Must be last.
+
+typedef enum {
+  kUpb_FieldModifier_IsRepeated = 1 << 0,
+  kUpb_FieldModifier_IsPacked = 1 << 1,
+  kUpb_FieldModifier_IsClosedEnum = 1 << 2,
+  kUpb_FieldModifier_IsProto3Singular = 1 << 3,
+  kUpb_FieldModifier_IsRequired = 1 << 4,
+} kUpb_FieldModifier;
+
+typedef enum {
+  kUpb_MessageModifier_ValidateUtf8 = 1 << 0,
+  kUpb_MessageModifier_DefaultIsPacked = 1 << 1,
+  kUpb_MessageModifier_IsExtendable = 1 << 2,
+} kUpb_MessageModifier;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_MiniTableField* upb_MiniTable_FindFieldByNumber(
+    const upb_MiniTable* table, uint32_t number);
+
+upb_FieldType upb_MiniTableField_Type(const upb_MiniTableField* field);
+
+UPB_INLINE bool upb_MiniTableField_IsExtension(
+    const upb_MiniTableField* field) {
+  return field->mode & kUpb_LabelFlags_IsExtension;
 }
 
-UPB_INLINE void _upb_mapsorter_destroy(_upb_mapsorter* s) {
-  if (s->entries) free(s->entries);
+UPB_INLINE bool upb_MiniTableField_HasPresence(
+    const upb_MiniTableField* field) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    return !upb_IsRepeatedOrMap(field);
+  } else {
+    return field->presence != 0;
+  }
 }
 
-bool _upb_mapsorter_pushmap(_upb_mapsorter* s, upb_FieldType 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 const upb_MiniTable* upb_MiniTable_GetSubMessageTable(
+    const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
+  return mini_table->subs[field->submsg_index].submsg;
 }
 
-UPB_INLINE bool _upb_sortedmap_next(_upb_mapsorter* s, const upb_Map* map,
-                                    _upb_sortedmap* sorted, upb_MapEntry* ent) {
-  if (sorted->pos == sorted->end) return false;
-  const upb_tabent* tabent = s->entries[sorted->pos++];
-  upb_StringView 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;
+UPB_INLINE const upb_MiniTableEnum* upb_MiniTable_GetSubEnumTable(
+    const upb_MiniTable* mini_table, const upb_MiniTableField* field) {
+  return mini_table->subs[field->submsg_index].subenum;
 }
 
 #ifdef __cplusplus
@@ -1920,262 +2287,638 @@
 #endif
 
 
-#endif /* UPB_MSG_INT_H_ */
+#endif /* UPB_MINI_TABLE_COMMON_H_ */
 
-/** upb/upb_internal.h ************************************************************/
-#ifndef UPB_INT_H_
-#define UPB_INT_H_
+// Must be last.
 
-
-struct mem_block;
-typedef struct mem_block mem_block;
-
-struct upb_Arena {
-  _upb_ArenaHead 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;
-};
-
-// Encodes a float or double that is round-trippable, but as short as possible.
-// These routines are not fully optimal (not guaranteed to be shortest), but are
-// short-ish and match the implementation that has been used in protobuf since
-// the beginning.
-//
-// The given buffer size must be at least kUpb_RoundTripBufferSize.
-enum { kUpb_RoundTripBufferSize = 32 };
-void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size);
-void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size);
-
-#endif /* UPB_INT_H_ */
-
-/* Must be last. */
-
-#define DECODE_NOGROUP (uint32_t) - 1
-
-typedef struct upb_Decoder {
-  const char* end;          /* Can read up to 16 bytes slop beyond this. */
-  const char* limit_ptr;    /* = end + UPB_MIN(limit, 0) */
-  upb_Message* unknown_msg; /* If non-NULL, add unknown data at buffer flip. */
-  const char* unknown;      /* Start of unknown data. */
-  const upb_ExtensionRegistry*
-      extreg;         /* For looking up extensions during the parse. */
-  int limit;          /* Submessage limit relative to end. */
-  int depth;          /* Tracks recursion depth to bound stack usage. */
-  uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */
-  uint16_t options;
-  bool missing_required;
-  char patch[32];
-  upb_Arena arena;
-  jmp_buf err;
-
-#ifndef NDEBUG
-  const char* debug_tagstart;
-  const char* debug_valstart;
+#ifdef __cplusplus
+extern "C" {
 #endif
-} upb_Decoder;
 
-/* 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_Decoder* d, int status);
+UPB_INLINE bool _upb_MiniTableField_InOneOf(const upb_MiniTableField* field) {
+  return field->presence < 0;
+}
 
-extern const uint8_t upb_utf8_offsets[];
+UPB_INLINE void* _upb_MiniTableField_GetPtr(upb_Message* msg,
+                                            const upb_MiniTableField* field) {
+  return (char*)msg + field->offset;
+}
 
-UPB_INLINE
-bool decode_verifyutf8_inl(const char* ptr, int len) {
-  const char* end = ptr + len;
+UPB_INLINE const void* _upb_MiniTableField_GetConstPtr(
+    const upb_Message* msg, const upb_MiniTableField* field) {
+  return (char*)msg + field->offset;
+}
 
-  // Check 8 bytes at a time for any non-ASCII char.
-  while (end - ptr >= 8) {
-    uint64_t data;
-    memcpy(&data, ptr, 8);
-    if (data & 0x8080808080808080) goto non_ascii;
-    ptr += 8;
+UPB_INLINE void _upb_MiniTable_SetPresence(upb_Message* msg,
+                                           const upb_MiniTableField* field) {
+  if (field->presence > 0) {
+    _upb_sethas_field(msg, field);
+  } else if (_upb_MiniTableField_InOneOf(field)) {
+    *_upb_oneofcase_field(msg, field) = field->number;
   }
-
-  // Check one byte at a time for non-ASCII.
-  while (ptr < end) {
-    if (*ptr & 0x80) goto non_ascii;
-    ptr++;
-  }
-
-  return true;
-
-non_ascii:
-  return utf8_range2((const unsigned char*)ptr, end - ptr) == 0;
 }
 
-const char* decode_checkrequired(upb_Decoder* d, const char* ptr,
-                                 const upb_Message* msg,
-                                 const upb_MiniTable* l);
+UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg,
+                                       const upb_MiniTableField* field);
 
-/* 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_MiniTable* tablep) {
-  return ((intptr_t)tablep << 8) | tablep->table_mask;
-}
-
-UPB_INLINE const upb_MiniTable* decode_totablep(intptr_t table) {
-  return (const upb_MiniTable*)(table >> 8);
-}
-
-UPB_INLINE
-const char* decode_isdonefallback_inl(upb_Decoder* d, const char* ptr,
-                                      int overrun, int* status) {
-  if (overrun < d->limit) {
-    /* Need to copy remaining data into patch buffer. */
-    UPB_ASSERT(overrun < 16);
-    if (d->unknown_msg) {
-      if (!_upb_Message_AddUnknown(d->unknown_msg, d->unknown, ptr - d->unknown,
-                                   &d->arena)) {
-        *status = kUpb_DecodeStatus_OutOfMemory;
-        return NULL;
-      }
-      d->unknown = &d->patch[0] + overrun;
+UPB_INLINE bool _upb_MiniTable_ValueIsNonZero(const void* default_val,
+                                              const upb_MiniTableField* field) {
+  char zero[16] = {0};
+  switch (_upb_MiniTableField_GetRep(field)) {
+    case kUpb_FieldRep_1Byte:
+      return memcmp(&zero, default_val, 1) != 0;
+    case kUpb_FieldRep_4Byte:
+      return memcmp(&zero, default_val, 4) != 0;
+    case kUpb_FieldRep_8Byte:
+      return memcmp(&zero, default_val, 8) != 0;
+    case kUpb_FieldRep_StringView: {
+      const upb_StringView* sv = (const upb_StringView*)default_val;
+      return sv->size != 0;
     }
-    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->options &= ~kUpb_DecodeOption_AliasString;
-    UPB_ASSERT(ptr < d->limit_ptr);
-    return ptr;
+  }
+  UPB_UNREACHABLE();
+}
+
+UPB_INLINE void _upb_MiniTable_CopyFieldData(void* to, const void* from,
+                                             const upb_MiniTableField* field) {
+  switch (_upb_MiniTableField_GetRep(field)) {
+    case kUpb_FieldRep_1Byte:
+      memcpy(to, from, 1);
+      return;
+    case kUpb_FieldRep_4Byte:
+      memcpy(to, from, 4);
+      return;
+    case kUpb_FieldRep_8Byte:
+      memcpy(to, from, 8);
+      return;
+    case kUpb_FieldRep_StringView: {
+      memcpy(to, from, sizeof(upb_StringView));
+      return;
+    }
+  }
+  UPB_UNREACHABLE();
+}
+
+// Here we define universal getter/setter functions for message fields.
+// These look very branchy and inefficient, but as long as the MiniTableField
+// values are known at compile time, all the branches are optimized away and
+// we are left with ideal code.  This can happen either through through
+// literals or UPB_ASSUME():
+//
+//   // Via string literals.
+//   bool FooMessage_set_bool_field(const upb_Message* msg, bool val) {
+//     const upb_MiniTableField field = {1, 0, 0, /* etc... */};
+//     // All value in "field" are compile-time known.
+//     _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+//   }
+//
+//   // Via UPB_ASSUME().
+//   UPB_INLINE void upb_MiniTable_SetBool(upb_Message* msg,
+//                                         const upb_MiniTableField* field,
+//                                         bool value) {
+//     UPB_ASSUME(field->descriptortype == kUpb_FieldType_Bool);
+//     UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+//     UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
+//     _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+//   }
+//
+// As a result, we can use these universal getters/setters for *all* message
+// accessors: generated code, MiniTable accessors, and reflection.  The only
+// exception is the binary encoder/decoder, which need to be a bit more clever
+// about how the read/write the message data, for efficiency.
+
+static UPB_FORCEINLINE void _upb_MiniTable_GetNonExtensionField(
+    const upb_Message* msg, const upb_MiniTableField* field,
+    const void* default_val, void* val) {
+  UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
+  if ((_upb_MiniTableField_InOneOf(field) ||
+       _upb_MiniTable_ValueIsNonZero(default_val, field)) &&
+      !upb_MiniTable_HasField(msg, field)) {
+    _upb_MiniTable_CopyFieldData(val, default_val, field);
+    return;
+  }
+  _upb_MiniTable_CopyFieldData(val, _upb_MiniTableField_GetConstPtr(msg, field),
+                               field);
+}
+
+UPB_INLINE void _upb_MiniTable_GetExtensionField(
+    const upb_Message* msg, const upb_MiniTableExtension* mt_ext,
+    const void* default_val, void* val) {
+  UPB_ASSUME(upb_MiniTableField_IsExtension(&mt_ext->field));
+  const upb_Message_Extension* ext = _upb_Message_Getext(msg, mt_ext);
+  if (ext) {
+    _upb_MiniTable_CopyFieldData(val, &ext->data, &mt_ext->field);
   } else {
-    *status = kUpb_DecodeStatus_Malformed;
-    return NULL;
+    _upb_MiniTable_CopyFieldData(val, default_val, &mt_ext->field);
   }
 }
 
-const char* decode_isdonefallback(upb_Decoder* d, const char* ptr, int overrun);
+UPB_INLINE void _upb_MiniTable_GetField(const upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        const void* default_val, void* val) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    _upb_MiniTable_GetExtensionField(msg, (upb_MiniTableExtension*)field,
+                                     default_val, val);
+  } else {
+    _upb_MiniTable_GetNonExtensionField(msg, field, default_val, val);
+  }
+}
 
-UPB_INLINE
-bool decode_isdone(upb_Decoder* 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)) {
+UPB_INLINE void _upb_MiniTable_SetNonExtensionField(
+    upb_Message* msg, const upb_MiniTableField* field, const void* val) {
+  UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
+  _upb_MiniTable_SetPresence(msg, field);
+  _upb_MiniTable_CopyFieldData(_upb_MiniTableField_GetPtr(msg, field), val,
+                               field);
+}
+
+UPB_INLINE bool _upb_MiniTable_SetExtensionField(
+    upb_Message* msg, const upb_MiniTableExtension* mt_ext, const void* val,
+    upb_Arena* a) {
+  upb_Message_Extension* ext =
+      _upb_Message_GetOrCreateExtension(msg, mt_ext, a);
+  if (!ext) return false;
+  _upb_MiniTable_CopyFieldData(&ext->data, val, &mt_ext->field);
+  return true;
+}
+
+UPB_INLINE bool _upb_MiniTable_SetField(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        const void* val, upb_Arena* a) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    return _upb_MiniTable_SetExtensionField(
+        msg, (const upb_MiniTableExtension*)field, val, a);
+  } else {
+    _upb_MiniTable_SetNonExtensionField(msg, field, val);
     return true;
-  } else {
-    *ptr = decode_isdonefallback(d, *ptr, overrun);
-    return false;
   }
 }
 
-#if UPB_FASTTABLE
-UPB_INLINE
-const char* fastdecode_tagdispatch(upb_Decoder* d, const char* ptr,
-                                   upb_Message* msg, intptr_t table,
-                                   uint64_t hasbits, uint64_t tag) {
-  const upb_MiniTable* 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);
+UPB_INLINE bool _upb_MiniTable_HasExtensionField(
+    const upb_Message* msg, const upb_MiniTableExtension* ext) {
+  UPB_ASSERT(upb_MiniTableField_HasPresence(&ext->field));
+  return _upb_Message_Getext(msg, ext) != NULL;
 }
+
+UPB_INLINE bool _upb_MiniTable_HasNonExtensionField(
+    const upb_Message* msg, const upb_MiniTableField* field) {
+  UPB_ASSERT(upb_MiniTableField_HasPresence(field));
+  UPB_ASSUME(!upb_MiniTableField_IsExtension(field));
+  if (_upb_MiniTableField_InOneOf(field)) {
+    return _upb_getoneofcase_field(msg, field) == field->number;
+  } else {
+    return _upb_hasbit_field(msg, field);
+  }
+}
+
+UPB_INLINE bool _upb_MiniTable_HasField(const upb_Message* msg,
+                                        const upb_MiniTableField* field) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    return _upb_MiniTable_HasExtensionField(
+        msg, (const upb_MiniTableExtension*)field);
+  } else {
+    return _upb_MiniTable_HasNonExtensionField(msg, field);
+  }
+}
+
+UPB_INLINE void _upb_MiniTable_ClearExtensionField(
+    upb_Message* msg, const upb_MiniTableExtension* ext) {
+  _upb_Message_Clearext(msg, ext);
+}
+
+UPB_INLINE void _upb_MiniTable_ClearNonExtensionField(
+    upb_Message* msg, const upb_MiniTableField* field) {
+  if (field->presence > 0) {
+    _upb_clearhas_field(msg, field);
+  } else if (_upb_MiniTableField_InOneOf(field)) {
+    uint32_t* oneof_case = _upb_oneofcase_field(msg, field);
+    if (*oneof_case != field->number) return;
+    *oneof_case = 0;
+  }
+  const char zeros[16] = {0};
+  _upb_MiniTable_CopyFieldData(_upb_MiniTableField_GetPtr(msg, field), zeros,
+                               field);
+}
+
+UPB_INLINE void _upb_MiniTable_ClearField(upb_Message* msg,
+                                          const upb_MiniTableField* field) {
+  if (upb_MiniTableField_IsExtension(field)) {
+    _upb_Message_Clearext(msg, (const upb_MiniTableExtension*)field);
+  } else {
+    _upb_MiniTable_ClearNonExtensionField(msg, field);
+  }
+}
+
+// EVERYTHING ABOVE THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+UPB_INLINE void upb_MiniTable_ClearField(upb_Message* msg,
+                                         const upb_MiniTableField* field) {
+  _upb_MiniTable_ClearNonExtensionField(msg, field);
+}
+
+UPB_INLINE bool upb_MiniTable_HasField(const upb_Message* msg,
+                                       const upb_MiniTableField* field) {
+  return _upb_MiniTable_HasNonExtensionField(msg, field);
+}
+
+UPB_INLINE bool upb_MiniTable_GetBool(const upb_Message* msg,
+                                      const upb_MiniTableField* field,
+                                      bool default_val) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Bool);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
+  bool ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetBool(upb_Message* msg,
+                                      const upb_MiniTableField* field,
+                                      bool value) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Bool);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_1Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE int32_t upb_MiniTable_GetInt32(const upb_Message* msg,
+                                          const upb_MiniTableField* field,
+                                          int32_t default_val) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Int32 ||
+             field->descriptortype == kUpb_FieldType_SInt32 ||
+             field->descriptortype == kUpb_FieldType_SFixed32 ||
+             field->descriptortype == kUpb_FieldType_Enum);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  int32_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetInt32(upb_Message* msg,
+                                       const upb_MiniTableField* field,
+                                       int32_t value) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_Int32 ||
+             field->descriptortype == kUpb_FieldType_SInt32 ||
+             field->descriptortype == kUpb_FieldType_SFixed32);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE uint32_t upb_MiniTable_GetUInt32(const upb_Message* msg,
+                                            const upb_MiniTableField* field,
+                                            uint32_t default_val) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_UInt32 ||
+             field->descriptortype == kUpb_FieldType_Fixed32);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  uint32_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetUInt32(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        uint32_t value) {
+  UPB_ASSUME(field->descriptortype == kUpb_FieldType_UInt32 ||
+             field->descriptortype == kUpb_FieldType_Fixed32);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE void upb_MiniTable_SetEnumProto2(upb_Message* msg,
+                                            const upb_MiniTable* msg_mini_table,
+                                            const upb_MiniTableField* field,
+                                            int32_t value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Enum);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  UPB_ASSERT(upb_MiniTableEnum_CheckValue(
+      upb_MiniTable_GetSubEnumTable(msg_mini_table, field), value));
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE int64_t upb_MiniTable_GetInt64(const upb_Message* msg,
+                                          const upb_MiniTableField* field,
+                                          uint64_t default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int64 ||
+             field->descriptortype == kUpb_FieldType_SInt64 ||
+             field->descriptortype == kUpb_FieldType_SFixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  int64_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetInt64(upb_Message* msg,
+                                       const upb_MiniTableField* field,
+                                       int64_t value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Int64 ||
+             field->descriptortype == kUpb_FieldType_SInt64 ||
+             field->descriptortype == kUpb_FieldType_SFixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE uint64_t upb_MiniTable_GetUInt64(const upb_Message* msg,
+                                            const upb_MiniTableField* field,
+                                            uint64_t default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt64 ||
+             field->descriptortype == kUpb_FieldType_Fixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  uint64_t ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetUInt64(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        uint64_t value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_UInt64 ||
+             field->descriptortype == kUpb_FieldType_Fixed64);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE float upb_MiniTable_GetFloat(const upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        float default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Float);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  float ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetFloat(upb_Message* msg,
+                                       const upb_MiniTableField* field,
+                                       float value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Float);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_4Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE double upb_MiniTable_GetDouble(const upb_Message* msg,
+                                          const upb_MiniTableField* field,
+                                          double default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Double);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  double ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetDouble(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        double value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Double);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_8Byte);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE upb_StringView
+upb_MiniTable_GetString(const upb_Message* msg, const upb_MiniTableField* field,
+                        upb_StringView def_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bytes ||
+             field->descriptortype == kUpb_FieldType_String);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView);
+  upb_StringView ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &def_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetString(upb_Message* msg,
+                                        const upb_MiniTableField* field,
+                                        upb_StringView value) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Bytes ||
+             field->descriptortype == kUpb_FieldType_String);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) == kUpb_FieldRep_StringView);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &value);
+}
+
+UPB_INLINE const upb_Message* upb_MiniTable_GetMessage(
+    const upb_Message* msg, const upb_MiniTableField* field,
+    upb_Message* default_val) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message ||
+             field->descriptortype == kUpb_FieldType_Group);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) ==
+             UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte));
+  upb_Message* ret;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE void upb_MiniTable_SetMessage(upb_Message* msg,
+                                         const upb_MiniTable* mini_table,
+                                         const upb_MiniTableField* field,
+                                         upb_Message* sub_message) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message ||
+             field->descriptortype == kUpb_FieldType_Group);
+  UPB_ASSUME(!upb_IsRepeatedOrMap(field));
+  UPB_ASSUME(_upb_MiniTableField_GetRep(field) ==
+             UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte));
+  UPB_ASSERT(mini_table->subs[field->submsg_index].submsg);
+  _upb_MiniTable_SetNonExtensionField(msg, field, &sub_message);
+}
+
+UPB_INLINE upb_Message* upb_MiniTable_GetMutableMessage(
+    upb_Message* msg, const upb_MiniTable* mini_table,
+    const upb_MiniTableField* field, upb_Arena* arena) {
+  UPB_ASSERT(field->descriptortype == kUpb_FieldType_Message ||
+             field->descriptortype == kUpb_FieldType_Group);
+  upb_Message* sub_message = *UPB_PTR_AT(msg, field->offset, upb_Message*);
+  if (!sub_message) {
+    const upb_MiniTable* sub_mini_table =
+        mini_table->subs[field->submsg_index].submsg;
+    UPB_ASSERT(sub_mini_table);
+    sub_message = _upb_Message_New(sub_mini_table, arena);
+    *UPB_PTR_AT(msg, field->offset, upb_Message*) = sub_message;
+    _upb_MiniTable_SetPresence(msg, field);
+  }
+  return sub_message;
+}
+
+UPB_INLINE const upb_Array* upb_MiniTable_GetArray(
+    const upb_Message* msg, const upb_MiniTableField* field) {
+  const upb_Array* ret;
+  const upb_Array* default_val = NULL;
+  _upb_MiniTable_GetNonExtensionField(msg, field, &default_val, &ret);
+  return ret;
+}
+
+UPB_INLINE upb_Array* upb_MiniTable_GetMutableArray(
+    upb_Message* msg, const upb_MiniTableField* field) {
+  return (upb_Array*)upb_MiniTable_GetArray(msg, field);
+}
+
+void* upb_MiniTable_ResizeArray(upb_Message* msg,
+                                const upb_MiniTableField* field, size_t len,
+                                upb_Arena* arena);
+typedef enum {
+  kUpb_GetExtension_Ok,
+  kUpb_GetExtension_NotPresent,
+  kUpb_GetExtension_ParseError,
+  kUpb_GetExtension_OutOfMemory,
+} upb_GetExtension_Status;
+
+typedef enum {
+  kUpb_GetExtensionAsBytes_Ok,
+  kUpb_GetExtensionAsBytes_NotPresent,
+  kUpb_GetExtensionAsBytes_EncodeError,
+} upb_GetExtensionAsBytes_Status;
+
+// Returns a message extension or promotes an unknown field to
+// an extension.
+//
+// TODO(ferhat): Only supports extension fields that are messages,
+// expand support to include non-message types.
+upb_GetExtension_Status upb_MiniTable_GetOrPromoteExtension(
+    upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int decode_options, upb_Arena* arena,
+    const upb_Message_Extension** extension);
+
+// Returns a message extension or unknown field matching the extension
+// data as bytes.
+//
+// If an extension has already been decoded it will be re-encoded
+// to bytes.
+upb_GetExtensionAsBytes_Status upb_MiniTable_GetExtensionAsBytes(
+    const upb_Message* msg, const upb_MiniTableExtension* ext_table,
+    int encode_options, upb_Arena* arena, const char** extension_data,
+    size_t* len);
+
+typedef enum {
+  kUpb_FindUnknown_Ok,
+  kUpb_FindUnknown_NotPresent,
+  kUpb_FindUnknown_ParseError,
+} upb_FindUnknown_Status;
+
+typedef struct {
+  upb_FindUnknown_Status status;
+  // Start of unknown field data in message arena.
+  const char* ptr;
+  // Size of unknown field data.
+  size_t len;
+} upb_FindUnknownRet;
+
+// Finds first occurrence of unknown data by tag id in message.
+upb_FindUnknownRet upb_MiniTable_FindUnknown(const upb_Message* msg,
+                                             uint32_t field_number);
+
+typedef enum {
+  kUpb_UnknownToMessage_Ok,
+  kUpb_UnknownToMessage_ParseError,
+  kUpb_UnknownToMessage_OutOfMemory,
+  kUpb_UnknownToMessage_NotFound,
+} upb_UnknownToMessage_Status;
+
+typedef struct {
+  upb_UnknownToMessage_Status status;
+  upb_Message* message;
+} upb_UnknownToMessageRet;
+
+// Promotes unknown data inside message to a upb_Message parsing the unknown.
+//
+// The unknown data is removed from message after field value is set
+// using upb_MiniTable_SetMessage.
+upb_UnknownToMessageRet upb_MiniTable_PromoteUnknownToMessage(
+    upb_Message* msg, const upb_MiniTable* mini_table,
+    const upb_MiniTableField* field, const upb_MiniTable* sub_mini_table,
+    int decode_options, upb_Arena* arena);
+
+// Promotes all unknown data that matches field tag id to repeated messages
+// in upb_Array.
+//
+// The unknown data is removed from message after upb_Array is populated.
+// Since repeated messages can't be packed we remove each unknown that
+// contains the target tag id.
+upb_UnknownToMessage_Status upb_MiniTable_PromoteUnknownToMessageArray(
+    upb_Message* msg, const upb_MiniTableField* field,
+    const upb_MiniTable* mini_table, int decode_options, upb_Arena* arena);
+
+#ifdef __cplusplus
+} /* extern "C" */
 #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_Decoder* d) {
-  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
-}
+#endif  // UPB_MESSAGE_ACCESSORS_H_
 
-UPB_INLINE int decode_pushlimit(upb_Decoder* 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_decode: parsing into a upb_Message using a upb_MiniTable.
 
-UPB_INLINE void decode_poplimit(upb_Decoder* 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);
-}
+#ifndef UPB_WIRE_DECODE_H_
+#define UPB_WIRE_DECODE_H_
 
 
-#endif /* UPB_DECODE_INT_H_ */
-
-/** upb/encode.h ************************************************************/
-/*
- * upb_Encode: parsing into a upb_Message using a upb_MiniTable.
- */
-
-#ifndef UPB_ENCODE_H_
-#define UPB_ENCODE_H_
-
-
-/* Must be last. */
+// 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 set, strings will alias the input buffer instead of copying into the
+   * arena. */
+  kUpb_DecodeOption_AliasString = 1,
+
+  /* If set, the parse will return failure if any message is missing any
+   * required fields when the message data ends.  The parse will still continue,
+   * and the failure will only be reported at the end.
    *
-   * If your proto contains maps, the encoder will need to malloc()/free()
-   * memory during encode. */
-  kUpb_Encode_Deterministic = 1,
-
-  /* When set, unknown fields are not printed. */
-  kUpb_Encode_SkipUnknown = 2,
-
-  /* When set, the encode will fail if any required fields are missing. */
-  kUpb_Encode_CheckRequired = 4,
+   * IMPORTANT CAVEATS:
+   *
+   * 1. This can throw a false positive failure if an incomplete message is seen
+   *    on the wire but is later completed when the sub-message occurs again.
+   *    For this reason, a second pass is required to verify a failure, to be
+   *    truly robust.
+   *
+   * 2. This can return a false success if you are decoding into a message that
+   *    already has some sub-message fields present.  If the sub-message does
+   *    not occur in the binary payload, we will never visit it and discover the
+   *    incomplete sub-message.  For this reason, this check is only useful for
+   *    implemting ParseFromString() semantics.  For MergeFromString(), a
+   *    post-parse validation step will always be necessary. */
+  kUpb_DecodeOption_CheckRequired = 2,
 };
 
-#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+#define UPB_DECODE_MAXDEPTH(depth) ((depth) << 16)
 
-char* upb_Encode(const void* msg, const upb_MiniTable* l, int options,
-                 upb_Arena* arena, size_t* size);
+typedef enum {
+  kUpb_DecodeStatus_Ok = 0,
+  kUpb_DecodeStatus_Malformed = 1,         // Wire format was corrupt
+  kUpb_DecodeStatus_OutOfMemory = 2,       // Arena alloc failed
+  kUpb_DecodeStatus_BadUtf8 = 3,           // String field had bad UTF-8
+  kUpb_DecodeStatus_MaxDepthExceeded = 4,  // Exceeded UPB_DECODE_MAXDEPTH
 
+  // kUpb_DecodeOption_CheckRequired failed (see above), but the parse otherwise
+  // succeeded.
+  kUpb_DecodeStatus_MissingRequired = 5,
+} upb_DecodeStatus;
+
+upb_DecodeStatus upb_Decode(const char* buf, size_t size, upb_Message* msg,
+                            const upb_MiniTable* l,
+                            const upb_ExtensionRegistry* extreg, int options,
+                            upb_Arena* arena);
 
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
-#endif /* UPB_ENCODE_H_ */
 
-/** upb/decode_fast.h ************************************************************/
+#endif /* UPB_WIRE_DECODE_H_ */
+
 // These are the specialized field parser functions for the fast parser.
 // Generated tables will refer to these by name.
 //
@@ -2210,17 +2953,24 @@
 //   - '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_
+#ifndef UPB_WIRE_DECODE_FAST_H_
+#define UPB_WIRE_DECODE_FAST_H_
 
 
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
 struct upb_Decoder;
 
 // 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_Decoder* d, const char* ptr,
-                               upb_Message* msg, intptr_t table,
-                               uint64_t hasbits, uint64_t data);
+const char* _upb_FastDecoder_DecodeGeneric(struct upb_Decoder* d,
+                                           const char* ptr, upb_Message* msg,
+                                           intptr_t table, uint64_t hasbits,
+                                           uint64_t data);
 
 #define UPB_PARSE_PARAMS                                                    \
   struct upb_Decoder *d, const char *ptr, upb_Message *msg, intptr_t table, \
@@ -2300,52 +3050,68 @@
 
 #undef UPB_PARSE_PARAMS
 
-#endif /* UPB_DECODE_FAST_H_ */
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
 
-/** 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_
+#endif /* UPB_WIRE_DECODE_FAST_H_ */
 
+// upb_Encode: parsing from a upb_Message using a upb_MiniTable.
+
+#ifndef UPB_WIRE_ENCODE_H_
+#define UPB_WIRE_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. */
+  kUpb_EncodeOption_Deterministic = 1,
+
+  /* When set, unknown fields are not printed. */
+  kUpb_EncodeOption_SkipUnknown = 2,
+
+  /* When set, the encode will fail if any required fields are missing. */
+  kUpb_EncodeOption_CheckRequired = 4,
+};
+
+#define UPB_ENCODE_MAXDEPTH(depth) ((depth) << 16)
+
+typedef enum {
+  kUpb_EncodeStatus_Ok = 0,
+  kUpb_EncodeStatus_OutOfMemory = 1,       // Arena alloc failed
+  kUpb_EncodeStatus_MaxDepthExceeded = 2,  // Exceeded UPB_ENCODE_MAXDEPTH
+
+  // kUpb_EncodeOption_CheckRequired failed but the parse otherwise succeeded.
+  kUpb_EncodeStatus_MissingRequired = 3,
+} upb_EncodeStatus;
+
+upb_EncodeStatus upb_Encode(const void* msg, const upb_MiniTable* l,
+                            int options, upb_Arena* arena, char** buf,
+                            size_t* size);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_WIRE_ENCODE_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;
@@ -2373,33 +3139,33 @@
 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_MiniTable google_protobuf_FileDescriptorSet_msginit;
-extern const upb_MiniTable google_protobuf_FileDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_DescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msginit;
-extern const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msginit;
-extern const upb_MiniTable google_protobuf_ExtensionRangeOptions_msginit;
-extern const upb_MiniTable google_protobuf_FieldDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_OneofDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_EnumDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit;
-extern const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_ServiceDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_MethodDescriptorProto_msginit;
-extern const upb_MiniTable google_protobuf_FileOptions_msginit;
-extern const upb_MiniTable google_protobuf_MessageOptions_msginit;
-extern const upb_MiniTable google_protobuf_FieldOptions_msginit;
-extern const upb_MiniTable google_protobuf_OneofOptions_msginit;
-extern const upb_MiniTable google_protobuf_EnumOptions_msginit;
-extern const upb_MiniTable google_protobuf_EnumValueOptions_msginit;
-extern const upb_MiniTable google_protobuf_ServiceOptions_msginit;
-extern const upb_MiniTable google_protobuf_MethodOptions_msginit;
-extern const upb_MiniTable google_protobuf_UninterpretedOption_msginit;
-extern const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msginit;
-extern const upb_MiniTable google_protobuf_SourceCodeInfo_msginit;
-extern const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msginit;
-extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_msginit;
-extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msginit;
+extern const upb_MiniTable google_protobuf_FileDescriptorSet_msg_init;
+extern const upb_MiniTable google_protobuf_FileDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_DescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_DescriptorProto_ExtensionRange_msg_init;
+extern const upb_MiniTable google_protobuf_DescriptorProto_ReservedRange_msg_init;
+extern const upb_MiniTable google_protobuf_ExtensionRangeOptions_msg_init;
+extern const upb_MiniTable google_protobuf_FieldDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_OneofDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_EnumDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init;
+extern const upb_MiniTable google_protobuf_EnumValueDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_ServiceDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_MethodDescriptorProto_msg_init;
+extern const upb_MiniTable google_protobuf_FileOptions_msg_init;
+extern const upb_MiniTable google_protobuf_MessageOptions_msg_init;
+extern const upb_MiniTable google_protobuf_FieldOptions_msg_init;
+extern const upb_MiniTable google_protobuf_OneofOptions_msg_init;
+extern const upb_MiniTable google_protobuf_EnumOptions_msg_init;
+extern const upb_MiniTable google_protobuf_EnumValueOptions_msg_init;
+extern const upb_MiniTable google_protobuf_ServiceOptions_msg_init;
+extern const upb_MiniTable google_protobuf_MethodOptions_msg_init;
+extern const upb_MiniTable google_protobuf_UninterpretedOption_msg_init;
+extern const upb_MiniTable google_protobuf_UninterpretedOption_NamePart_msg_init;
+extern const upb_MiniTable google_protobuf_SourceCodeInfo_msg_init;
+extern const upb_MiniTable google_protobuf_SourceCodeInfo_Location_msg_init;
+extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_msg_init;
+extern const upb_MiniTable google_protobuf_GeneratedCodeInfo_Annotation_msg_init;
 
 typedef enum {
   google_protobuf_FieldDescriptorProto_LABEL_OPTIONAL = 1,
@@ -2447,28 +3213,35 @@
 } google_protobuf_FileOptions_OptimizeMode;
 
 typedef enum {
+  google_protobuf_GeneratedCodeInfo_Annotation_NONE = 0,
+  google_protobuf_GeneratedCodeInfo_Annotation_SET = 1,
+  google_protobuf_GeneratedCodeInfo_Annotation_ALIAS = 2
+} google_protobuf_GeneratedCodeInfo_Annotation_Semantic;
+
+typedef enum {
   google_protobuf_MethodOptions_IDEMPOTENCY_UNKNOWN = 0,
   google_protobuf_MethodOptions_NO_SIDE_EFFECTS = 1,
   google_protobuf_MethodOptions_IDEMPOTENT = 2
 } google_protobuf_MethodOptions_IdempotencyLevel;
 
 
-extern const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Label_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FieldDescriptorProto_Type_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FieldOptions_CType_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FieldOptions_JSType_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_FileOptions_OptimizeMode_enuminit;
-extern const upb_MiniTable_Enum google_protobuf_MethodOptions_IdempotencyLevel_enuminit;
+extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Label_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FieldDescriptorProto_Type_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FieldOptions_CType_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FieldOptions_JSType_enum_init;
+extern const upb_MiniTableEnum google_protobuf_FileOptions_OptimizeMode_enum_init;
+extern const upb_MiniTableEnum google_protobuf_GeneratedCodeInfo_Annotation_Semantic_enum_init;
+extern const upb_MiniTableEnum google_protobuf_MethodOptions_IdempotencyLevel_enum_init;
 
 /* google.protobuf.FileDescriptorSet */
 
 UPB_INLINE google_protobuf_FileDescriptorSet* google_protobuf_FileDescriptorSet_new(upb_Arena* arena) {
-  return (google_protobuf_FileDescriptorSet*)_upb_Message_New(&google_protobuf_FileDescriptorSet_msginit, arena);
+  return (google_protobuf_FileDescriptorSet*)_upb_Message_New(&google_protobuf_FileDescriptorSet_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2478,35 +3251,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FileDescriptorSet* ret = google_protobuf_FileDescriptorSet_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorSet_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorSet_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FileDescriptorSet_serialize_ex(const google_protobuf_FileDescriptorSet* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FileDescriptorSet_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorSet_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_FileDescriptorSet_clear_file(google_protobuf_FileDescriptorSet* msg) {
+  const upb_MiniTableField field = {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_FileDescriptorProto* const*)_upb_array_accessor(msg, 0, len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorSet_has_file(const google_protobuf_FileDescriptorSet* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorSet_file(msg, &size);
+  return size != 0;
 }
 
 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);
+  return (google_protobuf_FileDescriptorProto**)_upb_array_mutable_accessor(msg, 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);
+  return (google_protobuf_FileDescriptorProto**)_upb_Array_Resize_accessor2(msg, 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_Message_New(&google_protobuf_FileDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_FileDescriptorProto* sub = (struct google_protobuf_FileDescriptorProto*)_upb_Message_New(&google_protobuf_FileDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -2514,12 +3297,12 @@
 /* google.protobuf.FileDescriptorProto */
 
 UPB_INLINE google_protobuf_FileDescriptorProto* google_protobuf_FileDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_FileDescriptorProto*)_upb_Message_New(&google_protobuf_FileDescriptorProto_msginit, arena);
+  return (google_protobuf_FileDescriptorProto*)_upb_Message_New(&google_protobuf_FileDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2529,206 +3312,317 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FileDescriptorProto* ret = google_protobuf_FileDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FileDescriptorProto_serialize_ex(const google_protobuf_FileDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FileDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_name(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_name(const google_protobuf_FileDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_name(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_package(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_package(const google_protobuf_FileDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_package(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_dependency(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(4, 40), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView const* google_protobuf_FileDescriptorProto_dependency(const google_protobuf_FileDescriptorProto* msg, size_t* len) {
-  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(36, 72), len);
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(4, 40), 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 bool google_protobuf_FileDescriptorProto_has_dependency(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_dependency(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_message_type(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(8, 48), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(8, 48), 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 bool google_protobuf_FileDescriptorProto_has_message_type(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_message_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_enum_type(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(12, 56), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(12, 56), 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 bool google_protobuf_FileDescriptorProto_has_enum_type(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_enum_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_service(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(16, 64), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_ServiceDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(16, 64), 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 bool google_protobuf_FileDescriptorProto_has_service(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_service(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_extension(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(20, 72), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 72), len);
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_extension(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_extension(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_options(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_FileOptions* default_val = NULL;
+  const google_protobuf_FileOptions* ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto* msg) {
-  return _upb_hasbit(msg, 4);
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_options(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_source_code_info(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_SourceCodeInfo* default_val = NULL;
+  const google_protobuf_SourceCodeInfo* ret;
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_source_code_info(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_public_dependency(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(32, 96), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(32, 96), len);
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_public_dependency(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_public_dependency(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_weak_dependency(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {11, UPB_SIZE(36, 104), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(36, 104), len);
 }
-UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto* msg) {
-  return _upb_hasbit(msg, 5);
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_weak_dependency(const google_protobuf_FileDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_FileDescriptorProto_weak_dependency(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_syntax(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_syntax(const google_protobuf_FileDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_syntax(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileDescriptorProto_clear_edition(google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE upb_StringView google_protobuf_FileDescriptorProto_edition(const google_protobuf_FileDescriptorProto* msg) {
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FileDescriptorProto_has_edition(const google_protobuf_FileDescriptorProto* msg) {
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_FileDescriptorProto_set_name(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView) = value;
-}
-UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto* msg, size_t* len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 72), len);
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileDescriptorProto_set_package(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(48, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_mutable_dependency(google_protobuf_FileDescriptorProto* msg, size_t* len) {
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 40), len);
 }
 UPB_INLINE upb_StringView* google_protobuf_FileDescriptorProto_resize_dependency(google_protobuf_FileDescriptorProto* msg, size_t len, upb_Arena* arena) {
-  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(36, 72), len, UPB_SIZE(3, 4), arena);
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 40), len, UPB_SIZE(3, 4), arena);
 }
 UPB_INLINE bool google_protobuf_FileDescriptorProto_add_dependency(google_protobuf_FileDescriptorProto* msg, upb_StringView val, upb_Arena* arena) {
-  return _upb_Array_Append_accessor2(msg, UPB_SIZE(36, 72), UPB_SIZE(3, 4), &val, arena);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 40), 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);
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 48), 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);
+  return (google_protobuf_DescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(8, 48), 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_Message_New(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_Message_New(&google_protobuf_DescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(8, 48), 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);
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 56), 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);
+  return (google_protobuf_EnumDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 56), 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_Message_New(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 56), 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);
+  return (google_protobuf_ServiceDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 64), 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);
+  return (google_protobuf_ServiceDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(16, 64), 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_Message_New(&google_protobuf_ServiceDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(48, 96), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_ServiceDescriptorProto* sub = (struct google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google_protobuf_ServiceDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 64), 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);
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 72), 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);
+  return (google_protobuf_FieldDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(20, 72), 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_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(52, 104), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 72), 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) {
+  const upb_MiniTableField field = {8, UPB_SIZE(24, 80), 3, 4, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_FileOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_FileOptions*)_upb_Message_New(&google_protobuf_FileOptions_msg_init, arena);
+    if (sub) 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) {
+  const upb_MiniTableField field = {9, UPB_SIZE(28, 88), 4, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_SourceCodeInfo_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FileDescriptorProto_set_source_code_info(msg, sub);
+    sub = (struct google_protobuf_SourceCodeInfo*)_upb_Message_New(&google_protobuf_SourceCodeInfo_msg_init, arena);
+    if (sub) 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);
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 96), 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);
+  return (int32_t*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(32, 96), 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);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(32, 96), 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);
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 104), 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);
+  return (int32_t*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(36, 104), 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);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(36, 104), 2, &val, arena);
 }
 UPB_INLINE void google_protobuf_FileDescriptorProto_set_syntax(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView) = value;
+  const upb_MiniTableField field = {12, UPB_SIZE(56, 112), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileDescriptorProto_set_edition(google_protobuf_FileDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {13, UPB_SIZE(64, 128), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
 }
-
 /* google.protobuf.DescriptorProto */
 
 UPB_INLINE google_protobuf_DescriptorProto* google_protobuf_DescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_DescriptorProto*)_upb_Message_New(&google_protobuf_DescriptorProto_msginit, arena);
+  return (google_protobuf_DescriptorProto*)_upb_Message_New(&google_protobuf_DescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2738,197 +3632,267 @@
                            int options, upb_Arena* arena) {
   google_protobuf_DescriptorProto* ret = google_protobuf_DescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_DescriptorProto_serialize_ex(const google_protobuf_DescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_DescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_DescriptorProto_clear_name(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_DescriptorProto_name(const google_protobuf_DescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_DescriptorProto_has_name(const google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_field(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(4, 24), 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 bool google_protobuf_DescriptorProto_has_field(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_field(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_nested_type(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_DescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(8, 32), 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 bool google_protobuf_DescriptorProto_has_nested_type(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_nested_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_enum_type(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_EnumDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(12, 40), 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 bool google_protobuf_DescriptorProto_has_enum_type(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_enum_type(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_extension_range(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 48), 0, 3, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_DescriptorProto_ExtensionRange* const*)_upb_array_accessor(msg, UPB_SIZE(16, 48), 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 bool google_protobuf_DescriptorProto_has_extension_range(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_extension_range(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_extension(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(20, 56), 0, 4, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_FieldDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(20, 56), len);
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_DescriptorProto_has_extension(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_extension(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_options(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_MessageOptions* default_val = NULL;
+  const google_protobuf_MessageOptions* ret;
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_DescriptorProto_has_options(const google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_oneof_decl(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(28, 72), 0, 6, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_OneofDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(28, 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 bool google_protobuf_DescriptorProto_has_oneof_decl(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_oneof_decl(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_range(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(32, 80), 0, 7, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_DescriptorProto_ReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(32, 80), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_range(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_reserved_range(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_DescriptorProto_clear_reserved_name(google_protobuf_DescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(36, 88), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView const* google_protobuf_DescriptorProto_reserved_name(const google_protobuf_DescriptorProto* msg, size_t* len) {
-  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(44, 88), len);
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(36, 88), len);
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_has_reserved_name(const google_protobuf_DescriptorProto* msg) {
+  size_t size;
+  google_protobuf_DescriptorProto_reserved_name(msg, &size);
+  return size != 0;
 }
 
 UPB_INLINE void google_protobuf_DescriptorProto_set_name(google_protobuf_DescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = 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);
+  const upb_MiniTableField field = {1, UPB_SIZE(40, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(4, 24), 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);
+  return (google_protobuf_FieldDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 24), 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_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 24), 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);
+  return (google_protobuf_DescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 32), 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);
+  return (google_protobuf_DescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(8, 32), 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_Message_New(&google_protobuf_DescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_DescriptorProto* sub = (struct google_protobuf_DescriptorProto*)_upb_Message_New(&google_protobuf_DescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(8, 32), 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);
+  return (google_protobuf_EnumDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 40), 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);
+  return (google_protobuf_EnumDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 40), 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_Message_New(&google_protobuf_EnumDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_EnumDescriptorProto* sub = (struct google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 40), 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);
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 48), 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);
+  return (google_protobuf_DescriptorProto_ExtensionRange**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(16, 48), 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_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_DescriptorProto_ExtensionRange* sub = (struct google_protobuf_DescriptorProto_ExtensionRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 48), 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);
+  return (google_protobuf_FieldDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(20, 56), 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);
+  return (google_protobuf_FieldDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(20, 56), 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_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(32, 64), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_FieldDescriptorProto* sub = (struct google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 56), 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) {
+  const upb_MiniTableField field = {7, UPB_SIZE(24, 64), 2, 5, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_MessageOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_MessageOptions*)_upb_Message_New(&google_protobuf_MessageOptions_msg_init, arena);
+    if (sub) 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);
+  return (google_protobuf_OneofDescriptorProto**)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 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);
+  return (google_protobuf_OneofDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(28, 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_Message_New(&google_protobuf_OneofDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(36, 72), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_OneofDescriptorProto* sub = (struct google_protobuf_OneofDescriptorProto*)_upb_Message_New(&google_protobuf_OneofDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(28, 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);
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(32, 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);
+  return (google_protobuf_DescriptorProto_ReservedRange**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(32, 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_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(40, 80), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_DescriptorProto_ReservedRange* sub = (struct google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(32, 80), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
 UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_mutable_reserved_name(google_protobuf_DescriptorProto* msg, size_t* len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(44, 88), len);
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(36, 88), len);
 }
 UPB_INLINE upb_StringView* google_protobuf_DescriptorProto_resize_reserved_name(google_protobuf_DescriptorProto* msg, size_t len, upb_Arena* arena) {
-  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(44, 88), len, UPB_SIZE(3, 4), arena);
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(36, 88), len, UPB_SIZE(3, 4), arena);
 }
 UPB_INLINE bool google_protobuf_DescriptorProto_add_reserved_name(google_protobuf_DescriptorProto* msg, upb_StringView val, upb_Arena* arena) {
-  return _upb_Array_Append_accessor2(msg, UPB_SIZE(44, 88), UPB_SIZE(3, 4), &val, arena);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(36, 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_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msginit, arena);
+  return (google_protobuf_DescriptorProto_ExtensionRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ExtensionRange_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -2938,56 +3902,83 @@
                            int options, upb_Arena* arena) {
   google_protobuf_DescriptorProto_ExtensionRange* ret = google_protobuf_DescriptorProto_ExtensionRange_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_DescriptorProto_ExtensionRange_serialize_ex(const google_protobuf_DescriptorProto_ExtensionRange* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ExtensionRange_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_start(google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_start(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_end(google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_end(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_clear_options(google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_ExtensionRangeOptions* default_val = NULL;
+  const google_protobuf_ExtensionRangeOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_ExtensionRange_has_options(const google_protobuf_DescriptorProto_ExtensionRange* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_end(google_protobuf_DescriptorProto_ExtensionRange *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_DescriptorProto_ExtensionRange_set_options(google_protobuf_DescriptorProto_ExtensionRange *msg, google_protobuf_ExtensionRangeOptions* value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(12, 16), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_ExtensionRangeOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
+    sub = (struct google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google_protobuf_ExtensionRangeOptions_msg_init, arena);
+    if (sub) google_protobuf_DescriptorProto_ExtensionRange_set_options(msg, sub);
   }
   return sub;
 }
@@ -2995,12 +3986,12 @@
 /* google.protobuf.DescriptorProto.ReservedRange */
 
 UPB_INLINE google_protobuf_DescriptorProto_ReservedRange* google_protobuf_DescriptorProto_ReservedRange_new(upb_Arena* arena) {
-  return (google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msginit, arena);
+  return (google_protobuf_DescriptorProto_ReservedRange*)_upb_Message_New(&google_protobuf_DescriptorProto_ReservedRange_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3010,50 +4001,70 @@
                            int options, upb_Arena* arena) {
   google_protobuf_DescriptorProto_ReservedRange* ret = google_protobuf_DescriptorProto_ReservedRange_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_DescriptorProto_ReservedRange_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_DescriptorProto_ReservedRange_serialize_ex(const google_protobuf_DescriptorProto_ReservedRange* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_DescriptorProto_ReservedRange_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_start(google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_start(const google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_clear_end(google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_DescriptorProto_ReservedRange_has_end(const google_protobuf_DescriptorProto_ReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_DescriptorProto_ReservedRange_set_end(google_protobuf_DescriptorProto_ReservedRange *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_ExtensionRangeOptions_msginit, arena);
+  return (google_protobuf_ExtensionRangeOptions*)_upb_Message_New(&google_protobuf_ExtensionRangeOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3063,35 +4074,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_ExtensionRangeOptions* ret = google_protobuf_ExtensionRangeOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_ExtensionRangeOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ExtensionRangeOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_ExtensionRangeOptions_serialize_ex(const google_protobuf_ExtensionRangeOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_ExtensionRangeOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ExtensionRangeOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_ExtensionRangeOptions_clear_uninterpreted_option(google_protobuf_ExtensionRangeOptions* msg) {
+  const upb_MiniTableField field = {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, 0, len);
+}
+UPB_INLINE bool google_protobuf_ExtensionRangeOptions_has_uninterpreted_option(const google_protobuf_ExtensionRangeOptions* msg) {
+  size_t size;
+  google_protobuf_ExtensionRangeOptions_uninterpreted_option(msg, &size);
+  return size != 0;
 }
 
 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);
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, 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);
+  return (google_protobuf_UninterpretedOption**)_upb_Array_Resize_accessor2(msg, 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -3099,12 +4120,12 @@
 /* google.protobuf.FieldDescriptorProto */
 
 UPB_INLINE google_protobuf_FieldDescriptorProto* google_protobuf_FieldDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google_protobuf_FieldDescriptorProto_msginit, arena);
+  return (google_protobuf_FieldDescriptorProto*)_upb_Message_New(&google_protobuf_FieldDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3114,149 +4135,240 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FieldDescriptorProto* ret = google_protobuf_FieldDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FieldDescriptorProto_serialize_ex(const google_protobuf_FieldDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FieldDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_name(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_name(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_extendee(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_extendee(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_extendee(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_number(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_number(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), int32_t);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 4);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_number(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_label(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_label(const google_protobuf_FieldDescriptorProto* msg) {
-  return google_protobuf_FieldDescriptorProto_has_label(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) : 1;
+  int32_t default_val = 1;
+  int32_t ret;
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 5);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_label(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE int32_t google_protobuf_FieldDescriptorProto_type(const google_protobuf_FieldDescriptorProto* msg) {
-  return google_protobuf_FieldDescriptorProto_has_type(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t) : 1;
+  int32_t default_val = 1;
+  int32_t ret;
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 6);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_type_name(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_type_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 7);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_type_name(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_default_value(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_default_value(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 8);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_default_value(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_options(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_FieldOptions* default_val = NULL;
+  const google_protobuf_FieldOptions* ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 9);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_options(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_oneof_index(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_json_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return _upb_hasbit(msg, 10);
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_oneof_index(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_json_name(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FieldDescriptorProto_json_name(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_json_name(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldDescriptorProto_clear_proto3_optional(google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FieldDescriptorProto_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 20), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_FieldDescriptorProto_has_proto3_optional(const google_protobuf_FieldDescriptorProto* msg) {
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_FieldDescriptorProto_set_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(24, 24), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 40), upb_StringView) = 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_StringView value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(40, 56), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(48, 72), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, UPB_SIZE(28, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_extendee(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(36, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_number(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {3, 4, 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_label(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {4, 8, 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type(google_protobuf_FieldDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {5, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_type_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {6, UPB_SIZE(44, 56), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_default_value(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {7, UPB_SIZE(52, 72), 7, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_options(google_protobuf_FieldDescriptorProto *msg, google_protobuf_FieldOptions* value) {
+  const upb_MiniTableField field = {8, UPB_SIZE(16, 88), 8, 2, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_FieldOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_FieldDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_FieldOptions*)_upb_Message_New(&google_protobuf_FieldOptions_msg_init, arena);
+    if (sub) 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;
+  const upb_MiniTableField field = {9, UPB_SIZE(20, 16), 9, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {10, UPB_SIZE(60, 96), 10, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldDescriptorProto_set_proto3_optional(google_protobuf_FieldDescriptorProto *msg, bool value) {
+  const upb_MiniTableField field = {17, UPB_SIZE(24, 20), 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
 }
-UPB_INLINE void google_protobuf_FieldDescriptorProto_set_json_name(google_protobuf_FieldDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 10);
-  *UPB_PTR_AT(msg, UPB_SIZE(56, 88), upb_StringView) = 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_Message_New(&google_protobuf_OneofDescriptorProto_msginit, arena);
+  return (google_protobuf_OneofDescriptorProto*)_upb_Message_New(&google_protobuf_OneofDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3266,46 +4378,65 @@
                            int options, upb_Arena* arena) {
   google_protobuf_OneofDescriptorProto* ret = google_protobuf_OneofDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_OneofDescriptorProto_serialize_ex(const google_protobuf_OneofDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_OneofDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_name(google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_OneofDescriptorProto_name(const google_protobuf_OneofDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_name(const google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_OneofDescriptorProto_clear_options(google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_OneofOptions* default_val = NULL;
+  const google_protobuf_OneofOptions* ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_OneofDescriptorProto_has_options(const google_protobuf_OneofDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_OneofDescriptorProto_set_name(google_protobuf_OneofDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, 8, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_OneofDescriptorProto_set_options(google_protobuf_OneofDescriptorProto *msg, google_protobuf_OneofOptions* value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 2, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_OneofOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_OneofDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_OneofOptions*)_upb_Message_New(&google_protobuf_OneofOptions_msg_init, arena);
+    if (sub) google_protobuf_OneofDescriptorProto_set_options(msg, sub);
   }
   return sub;
 }
@@ -3313,12 +4444,12 @@
 /* google.protobuf.EnumDescriptorProto */
 
 UPB_INLINE google_protobuf_EnumDescriptorProto* google_protobuf_EnumDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_msginit, arena);
+  return (google_protobuf_EnumDescriptorProto*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3328,107 +4459,147 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumDescriptorProto* ret = google_protobuf_EnumDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumDescriptorProto_serialize_ex(const google_protobuf_EnumDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_name(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_EnumDescriptorProto_name(const google_protobuf_EnumDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_EnumDescriptorProto_has_name(const google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_value(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_EnumValueDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(4, 24), len);
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_value(const google_protobuf_EnumDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_EnumDescriptorProto_value(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_options(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_EnumOptions* default_val = NULL;
+  const google_protobuf_EnumOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_EnumDescriptorProto_has_options(const google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_range(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 40), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_EnumDescriptorProto_EnumReservedRange* const*)_upb_array_accessor(msg, UPB_SIZE(12, 40), len);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_range(const google_protobuf_EnumDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_EnumDescriptorProto_reserved_range(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_clear_reserved_name(google_protobuf_EnumDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 48), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView const* google_protobuf_EnumDescriptorProto_reserved_name(const google_protobuf_EnumDescriptorProto* msg, size_t* len) {
-  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(24, 48), len);
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(16, 48), len);
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_has_reserved_name(const google_protobuf_EnumDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_EnumDescriptorProto_reserved_name(msg, &size);
+  return size != 0;
 }
 
 UPB_INLINE void google_protobuf_EnumDescriptorProto_set_name(google_protobuf_EnumDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = 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);
+  const upb_MiniTableField field = {1, UPB_SIZE(20, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(4, 24), 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);
+  return (google_protobuf_EnumValueDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 24), 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_Message_New(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_EnumValueDescriptorProto* sub = (struct google_protobuf_EnumValueDescriptorProto*)_upb_Message_New(&google_protobuf_EnumValueDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 24), 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) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_EnumOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_EnumOptions*)_upb_Message_New(&google_protobuf_EnumOptions_msg_init, arena);
+    if (sub) 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);
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 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);
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 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_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 40), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_EnumDescriptorProto_EnumReservedRange* sub = (struct google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 40), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
 UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_mutable_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t* len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(24, 48), len);
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(16, 48), len);
 }
 UPB_INLINE upb_StringView* google_protobuf_EnumDescriptorProto_resize_reserved_name(google_protobuf_EnumDescriptorProto* msg, size_t len, upb_Arena* arena) {
-  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(24, 48), len, UPB_SIZE(3, 4), arena);
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(16, 48), len, UPB_SIZE(3, 4), arena);
 }
 UPB_INLINE bool google_protobuf_EnumDescriptorProto_add_reserved_name(google_protobuf_EnumDescriptorProto* msg, upb_StringView val, upb_Arena* arena) {
-  return _upb_Array_Append_accessor2(msg, UPB_SIZE(24, 48), UPB_SIZE(3, 4), &val, arena);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 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_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, arena);
+  return (google_protobuf_EnumDescriptorProto_EnumReservedRange*)_upb_Message_New(&google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3438,50 +4609,70 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumDescriptorProto_EnumReservedRange* ret = google_protobuf_EnumDescriptorProto_EnumReservedRange_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumDescriptorProto_EnumReservedRange_serialize_ex(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumDescriptorProto_EnumReservedRange_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_start(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_start(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_clear_end(google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_EnumDescriptorProto_EnumReservedRange_has_end(const google_protobuf_EnumDescriptorProto_EnumReservedRange* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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;
+  const upb_MiniTableField field = {1, 4, 1, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumDescriptorProto_EnumReservedRange_set_end(google_protobuf_EnumDescriptorProto_EnumReservedRange *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_EnumValueDescriptorProto_msginit, arena);
+  return (google_protobuf_EnumValueDescriptorProto*)_upb_Message_New(&google_protobuf_EnumValueDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3491,56 +4682,83 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumValueDescriptorProto* ret = google_protobuf_EnumValueDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumValueDescriptorProto_serialize_ex(const google_protobuf_EnumValueDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumValueDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_name(google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_EnumValueDescriptorProto_name(const google_protobuf_EnumValueDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_name(const google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_number(google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE int32_t google_protobuf_EnumValueDescriptorProto_number(const google_protobuf_EnumValueDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_number(const google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumValueDescriptorProto_clear_options(google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_EnumValueOptions* default_val = NULL;
+  const google_protobuf_EnumValueOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_EnumValueDescriptorProto_has_options(const google_protobuf_EnumValueDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_name(google_protobuf_EnumValueDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(8, 8), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_number(google_protobuf_EnumValueDescriptorProto *msg, int32_t value) {
+  const upb_MiniTableField field = {2, 4, 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumValueDescriptorProto_set_options(google_protobuf_EnumValueDescriptorProto *msg, google_protobuf_EnumValueOptions* value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 24), 3, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_EnumValueOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_EnumValueOptions*)_upb_Message_New(&google_protobuf_EnumValueOptions_msg_init, arena);
+    if (sub) google_protobuf_EnumValueDescriptorProto_set_options(msg, sub);
   }
   return sub;
 }
@@ -3548,12 +4766,12 @@
 /* google.protobuf.ServiceDescriptorProto */
 
 UPB_INLINE google_protobuf_ServiceDescriptorProto* google_protobuf_ServiceDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google_protobuf_ServiceDescriptorProto_msginit, arena);
+  return (google_protobuf_ServiceDescriptorProto*)_upb_Message_New(&google_protobuf_ServiceDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3563,64 +4781,89 @@
                            int options, upb_Arena* arena) {
   google_protobuf_ServiceDescriptorProto* ret = google_protobuf_ServiceDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_ServiceDescriptorProto_serialize_ex(const google_protobuf_ServiceDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_ServiceDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_name(google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_ServiceDescriptorProto_name(const google_protobuf_ServiceDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_ServiceDescriptorProto_has_name(const google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_method(google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 24), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_MethodDescriptorProto* const*)_upb_array_accessor(msg, UPB_SIZE(4, 24), len);
 }
-UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_method(const google_protobuf_ServiceDescriptorProto* msg) {
+  size_t size;
+  google_protobuf_ServiceDescriptorProto_method(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_ServiceDescriptorProto_clear_options(google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_ServiceOptions* default_val = NULL;
+  const google_protobuf_ServiceOptions* ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_ServiceDescriptorProto_has_options(const google_protobuf_ServiceDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_ServiceDescriptorProto_set_name(google_protobuf_ServiceDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = 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);
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(4, 24), 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);
+  return (google_protobuf_MethodDescriptorProto**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 24), 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_Message_New(&google_protobuf_MethodDescriptorProto_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(16, 32), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_MethodDescriptorProto* sub = (struct google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google_protobuf_MethodDescriptorProto_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 24), 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) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 32), 2, 1, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_ServiceOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_ServiceOptions*)_upb_Message_New(&google_protobuf_ServiceOptions_msg_init, arena);
+    if (sub) google_protobuf_ServiceDescriptorProto_set_options(msg, sub);
   }
   return sub;
 }
@@ -3628,12 +4871,12 @@
 /* google.protobuf.MethodDescriptorProto */
 
 UPB_INLINE google_protobuf_MethodDescriptorProto* google_protobuf_MethodDescriptorProto_new(upb_Arena* arena) {
-  return (google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google_protobuf_MethodDescriptorProto_msginit, arena);
+  return (google_protobuf_MethodDescriptorProto*)_upb_Message_New(&google_protobuf_MethodDescriptorProto_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3643,99 +4886,150 @@
                            int options, upb_Arena* arena) {
   google_protobuf_MethodDescriptorProto* ret = google_protobuf_MethodDescriptorProto_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodDescriptorProto_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodDescriptorProto_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_MethodDescriptorProto_serialize_ex(const google_protobuf_MethodDescriptorProto* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_MethodDescriptorProto_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodDescriptorProto_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_name(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_name(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_name(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_input_type(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_input_type(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_input_type(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_output_type(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_MethodDescriptorProto_output_type(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_options(const google_protobuf_MethodDescriptorProto* msg) {
-  return _upb_hasbit(msg, 4);
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_output_type(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_options(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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*);
+  const google_protobuf_MethodOptions* default_val = NULL;
+  const google_protobuf_MethodOptions* ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_options(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_client_streaming(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_MethodDescriptorProto_client_streaming(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_client_streaming(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodDescriptorProto_clear_server_streaming(google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_MethodDescriptorProto_server_streaming(const google_protobuf_MethodDescriptorProto* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_MethodDescriptorProto_has_server_streaming(const google_protobuf_MethodDescriptorProto* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_MethodDescriptorProto_set_name(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
-  _upb_sethas(msg, 3);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 40), upb_StringView) = 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) {
+  const upb_MiniTableField field = {1, UPB_SIZE(12, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_input_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_output_type(google_protobuf_MethodDescriptorProto *msg, upb_StringView value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(28, 40), 3, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_options(google_protobuf_MethodDescriptorProto *msg, google_protobuf_MethodOptions* value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(4, 56), 4, 0, 11, kUpb_FieldMode_Scalar | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_MethodOptions_msginit, arena);
-    if (!sub) return NULL;
-    google_protobuf_MethodDescriptorProto_set_options(msg, sub);
+    sub = (struct google_protobuf_MethodOptions*)_upb_Message_New(&google_protobuf_MethodOptions_msg_init, arena);
+    if (sub) 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;
+  const upb_MiniTableField field = {5, UPB_SIZE(8, 1), 5, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodDescriptorProto_set_server_streaming(google_protobuf_MethodDescriptorProto *msg, bool value) {
+  const upb_MiniTableField field = {6, UPB_SIZE(9, 2), 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_FileOptions_msginit, arena);
+  return (google_protobuf_FileOptions*)_upb_Message_New(&google_protobuf_FileOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3745,235 +5039,405 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FileOptions* ret = google_protobuf_FileOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FileOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FileOptions_serialize_ex(const google_protobuf_FileOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FileOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FileOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_FileOptions_clear_java_package(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_java_package(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_FileOptions_has_java_package(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_outer_classname(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_java_outer_classname(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_optimize_for(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_FileOptions_has_java_outer_classname(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_optimize_for(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE int32_t google_protobuf_FileOptions_optimize_for(const google_protobuf_FileOptions* msg) {
-  return google_protobuf_FileOptions_has_optimize_for(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t) : 1;
+  int32_t default_val = 1;
+  int32_t ret;
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_optimize_for(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_multiple_files(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FileOptions_java_multiple_files(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_go_package(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 5);
+UPB_INLINE bool google_protobuf_FileOptions_has_java_multiple_files(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_go_package(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_go_package(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_go_package(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_cc_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FileOptions_cc_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(9, 9), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_cc_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FileOptions_java_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(10, 10), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_java_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_py_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FileOptions_py_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(11, 11), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_py_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_generate_equals_and_hash(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_deprecated(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 10);
+UPB_INLINE bool google_protobuf_FileOptions_has_java_generate_equals_and_hash(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_deprecated(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FileOptions_deprecated(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_deprecated(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_java_string_check_utf8(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_java_string_check_utf8(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_cc_enable_arenas(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FileOptions_cc_enable_arenas(const google_protobuf_FileOptions* msg) {
-  return google_protobuf_FileOptions_has_cc_enable_arenas(msg) ? *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool) : true;
+  bool default_val = true;
+  bool ret;
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 13);
+UPB_INLINE bool google_protobuf_FileOptions_has_cc_enable_arenas(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_objc_class_prefix(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_objc_class_prefix(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 14);
+UPB_INLINE bool google_protobuf_FileOptions_has_objc_class_prefix(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_csharp_namespace(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_csharp_namespace(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 15);
+UPB_INLINE bool google_protobuf_FileOptions_has_csharp_namespace(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_swift_prefix(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_swift_prefix(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 16);
+UPB_INLINE bool google_protobuf_FileOptions_has_swift_prefix(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_class_prefix(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_php_class_prefix(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_namespace(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 17);
+UPB_INLINE bool google_protobuf_FileOptions_has_php_class_prefix(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_namespace(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_php_namespace(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_php_namespace(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_generic_services(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FileOptions_php_generic_services(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 19);
+UPB_INLINE bool google_protobuf_FileOptions_has_php_generic_services(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_php_metadata_namespace(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_php_metadata_namespace(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions* msg) {
-  return _upb_hasbit(msg, 20);
+UPB_INLINE bool google_protobuf_FileOptions_has_php_metadata_namespace(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_ruby_package(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_FileOptions_ruby_package(const google_protobuf_FileOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_FileOptions_has_ruby_package(const google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FileOptions_clear_uninterpreted_option(google_protobuf_FileOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(20, 184), 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, UPB_SIZE(20, 184), len);
+}
+UPB_INLINE bool google_protobuf_FileOptions_has_uninterpreted_option(const google_protobuf_FileOptions* msg) {
+  size_t size;
+  google_protobuf_FileOptions_uninterpreted_option(msg, &size);
+  return size != 0;
 }
 
 UPB_INLINE void google_protobuf_FileOptions_set_java_package(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(20, 24), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(28, 40), upb_StringView) = 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_StringView value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(36, 56), upb_StringView) = 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_StringView value) {
-  _upb_sethas(msg, 13);
-  *UPB_PTR_AT(msg, UPB_SIZE(44, 72), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 14);
-  *UPB_PTR_AT(msg, UPB_SIZE(52, 88), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 15);
-  *UPB_PTR_AT(msg, UPB_SIZE(60, 104), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 16);
-  *UPB_PTR_AT(msg, UPB_SIZE(68, 120), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 17);
-  *UPB_PTR_AT(msg, UPB_SIZE(76, 136), upb_StringView) = 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_StringView value) {
-  _upb_sethas(msg, 19);
-  *UPB_PTR_AT(msg, UPB_SIZE(84, 152), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_StringView value) {
-  _upb_sethas(msg, 20);
-  *UPB_PTR_AT(msg, UPB_SIZE(92, 168), upb_StringView) = 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);
+  const upb_MiniTableField field = {1, 24, 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_outer_classname(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {8, UPB_SIZE(32, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_optimize_for(google_protobuf_FileOptions *msg, int32_t value) {
+  const upb_MiniTableField field = {9, 4, 3, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_multiple_files(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {10, 8, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_go_package(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {11, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_cc_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {16, 9, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {17, 10, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_py_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {18, 11, 8, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_generate_equals_and_hash(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {20, 12, 9, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_deprecated(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {23, 13, 10, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_java_string_check_utf8(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {27, 14, 11, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_cc_enable_arenas(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {31, 15, 12, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_objc_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {36, UPB_SIZE(48, 72), 13, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_csharp_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {37, UPB_SIZE(56, 88), 14, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_swift_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {39, UPB_SIZE(64, 104), 15, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_class_prefix(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {40, UPB_SIZE(72, 120), 16, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {41, UPB_SIZE(80, 136), 17, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_generic_services(google_protobuf_FileOptions *msg, bool value) {
+  const upb_MiniTableField field = {42, 16, 18, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_php_metadata_namespace(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {44, UPB_SIZE(88, 152), 19, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FileOptions_set_ruby_package(google_protobuf_FileOptions *msg, upb_StringView value) {
+  const upb_MiniTableField field = {45, UPB_SIZE(96, 168), 20, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(20, 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);
+  return (google_protobuf_UninterpretedOption**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(20, 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(100, 184), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 184), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -3981,12 +5445,12 @@
 /* google.protobuf.MessageOptions */
 
 UPB_INLINE google_protobuf_MessageOptions* google_protobuf_MessageOptions_new(upb_Arena* arena) {
-  return (google_protobuf_MessageOptions*)_upb_Message_New(&google_protobuf_MessageOptions_msginit, arena);
+  return (google_protobuf_MessageOptions*)_upb_Message_New(&google_protobuf_MessageOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -3996,75 +5460,117 @@
                            int options, upb_Arena* arena) {
   google_protobuf_MessageOptions* ret = google_protobuf_MessageOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_MessageOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MessageOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_MessageOptions_serialize_ex(const google_protobuf_MessageOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_MessageOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MessageOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_MessageOptions_has_message_set_wire_format(const google_protobuf_MessageOptions* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_MessageOptions_clear_message_set_wire_format(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_message_set_wire_format(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_no_standard_descriptor_accessor(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MessageOptions_has_deprecated(const google_protobuf_MessageOptions* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_MessageOptions_has_no_standard_descriptor_accessor(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_deprecated(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_MessageOptions_deprecated(const google_protobuf_MessageOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(3, 3), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_deprecated(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_map_entry(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_MessageOptions_map_entry(const google_protobuf_MessageOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_MessageOptions_has_map_entry(const google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MessageOptions_clear_uninterpreted_option(google_protobuf_MessageOptions* msg) {
+  const upb_MiniTableField field = {999, 8, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, 8, len);
+}
+UPB_INLINE bool google_protobuf_MessageOptions_has_uninterpreted_option(const google_protobuf_MessageOptions* msg) {
+  size_t size;
+  google_protobuf_MessageOptions_uninterpreted_option(msg, &size);
+  return size != 0;
 }
 
 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);
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MessageOptions_set_no_standard_descriptor_accessor(google_protobuf_MessageOptions *msg, bool value) {
+  const upb_MiniTableField field = {2, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MessageOptions_set_deprecated(google_protobuf_MessageOptions *msg, bool value) {
+  const upb_MiniTableField field = {3, 3, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MessageOptions_set_map_entry(google_protobuf_MessageOptions *msg, bool value) {
+  const upb_MiniTableField field = {7, 4, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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, 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);
+  return (google_protobuf_UninterpretedOption**)_upb_Array_Resize_accessor2(msg, 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(8, 8), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 8, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4072,12 +5578,12 @@
 /* google.protobuf.FieldOptions */
 
 UPB_INLINE google_protobuf_FieldOptions* google_protobuf_FieldOptions_new(upb_Arena* arena) {
-  return (google_protobuf_FieldOptions*)_upb_Message_New(&google_protobuf_FieldOptions_msginit, arena);
+  return (google_protobuf_FieldOptions*)_upb_Message_New(&google_protobuf_FieldOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4087,104 +5593,170 @@
                            int options, upb_Arena* arena) {
   google_protobuf_FieldOptions* ret = google_protobuf_FieldOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_FieldOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_FieldOptions_serialize_ex(const google_protobuf_FieldOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_FieldOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_FieldOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_FieldOptions_clear_ctype(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE int32_t google_protobuf_FieldOptions_ctype(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 4), int32_t);
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_FieldOptions_has_ctype(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_packed(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FieldOptions_packed(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 12), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_FieldOptions_has_packed(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_deprecated(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FieldOptions_deprecated(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(13, 13), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions* msg) {
-  return _upb_hasbit(msg, 4);
+UPB_INLINE bool google_protobuf_FieldOptions_has_deprecated(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_lazy(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FieldOptions_lazy(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(14, 14), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions* msg) {
-  return _upb_hasbit(msg, 5);
+UPB_INLINE bool google_protobuf_FieldOptions_has_lazy(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_jstype(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE int32_t google_protobuf_FieldOptions_jstype(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), int32_t);
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions* msg) {
-  return _upb_hasbit(msg, 6);
+UPB_INLINE bool google_protobuf_FieldOptions_has_jstype(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_weak(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FieldOptions_weak(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(15, 15), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_unverified_lazy(const google_protobuf_FieldOptions* msg) {
-  return _upb_hasbit(msg, 7);
+UPB_INLINE bool google_protobuf_FieldOptions_has_weak(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_unverified_lazy(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_FieldOptions_unverified_lazy(const google_protobuf_FieldOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions* msg) {
-  return _upb_has_submsg_nohasbit(msg, UPB_SIZE(20, 24));
+UPB_INLINE bool google_protobuf_FieldOptions_has_unverified_lazy(const google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_FieldOptions_clear_uninterpreted_option(google_protobuf_FieldOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(20, 24), 0, 2, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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(20, 24), len);
 }
+UPB_INLINE bool google_protobuf_FieldOptions_has_uninterpreted_option(const google_protobuf_FieldOptions* msg) {
+  size_t size;
+  google_protobuf_FieldOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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 void google_protobuf_FieldOptions_set_unverified_lazy(google_protobuf_FieldOptions *msg, bool value) {
-  _upb_sethas(msg, 7);
-  *UPB_PTR_AT(msg, UPB_SIZE(16, 16), bool) = value;
-}
-UPB_INLINE google_protobuf_UninterpretedOption** google_protobuf_FieldOptions_mutable_uninterpreted_option(google_protobuf_FieldOptions* msg, size_t* len) {
+  const upb_MiniTableField field = {1, 4, 1, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_packed(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {2, 8, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_deprecated(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {3, 9, 3, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_lazy(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {5, 10, 4, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_jstype(google_protobuf_FieldOptions *msg, int32_t value) {
+  const upb_MiniTableField field = {6, 12, 5, 1, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_weak(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {10, 16, 6, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_FieldOptions_set_unverified_lazy(google_protobuf_FieldOptions *msg, bool value) {
+  const upb_MiniTableField field = {15, 17, 7, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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(20, 24), 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(20, 24), 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
   bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(20, 24), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
@@ -4193,12 +5765,12 @@
 /* google.protobuf.OneofOptions */
 
 UPB_INLINE google_protobuf_OneofOptions* google_protobuf_OneofOptions_new(upb_Arena* arena) {
-  return (google_protobuf_OneofOptions*)_upb_Message_New(&google_protobuf_OneofOptions_msginit, arena);
+  return (google_protobuf_OneofOptions*)_upb_Message_New(&google_protobuf_OneofOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4208,35 +5780,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_OneofOptions* ret = google_protobuf_OneofOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_OneofOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_OneofOptions_serialize_ex(const google_protobuf_OneofOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_OneofOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_OneofOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_OneofOptions_clear_uninterpreted_option(google_protobuf_OneofOptions* msg) {
+  const upb_MiniTableField field = {999, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, 0, len);
+}
+UPB_INLINE bool google_protobuf_OneofOptions_has_uninterpreted_option(const google_protobuf_OneofOptions* msg) {
+  size_t size;
+  google_protobuf_OneofOptions_uninterpreted_option(msg, &size);
+  return size != 0;
 }
 
 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);
+  return (google_protobuf_UninterpretedOption**)_upb_array_mutable_accessor(msg, 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);
+  return (google_protobuf_UninterpretedOption**)_upb_Array_Resize_accessor2(msg, 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4244,12 +5826,12 @@
 /* google.protobuf.EnumOptions */
 
 UPB_INLINE google_protobuf_EnumOptions* google_protobuf_EnumOptions_new(upb_Arena* arena) {
-  return (google_protobuf_EnumOptions*)_upb_Message_New(&google_protobuf_EnumOptions_msginit, arena);
+  return (google_protobuf_EnumOptions*)_upb_Message_New(&google_protobuf_EnumOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4259,54 +5841,80 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumOptions* ret = google_protobuf_EnumOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumOptions_serialize_ex(const google_protobuf_EnumOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_EnumOptions_clear_allow_alias(google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_EnumOptions_allow_alias(const google_protobuf_EnumOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_EnumOptions_has_allow_alias(const google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumOptions_clear_deprecated(google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_EnumOptions_deprecated(const google_protobuf_EnumOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(2, 2), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_EnumOptions_has_deprecated(const google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumOptions_clear_uninterpreted_option(google_protobuf_EnumOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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 bool google_protobuf_EnumOptions_has_uninterpreted_option(const google_protobuf_EnumOptions* msg) {
+  size_t size;
+  google_protobuf_EnumOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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) {
+  const upb_MiniTableField field = {2, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_EnumOptions_set_deprecated(google_protobuf_EnumOptions *msg, bool value) {
+  const upb_MiniTableField field = {3, 2, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
   bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
@@ -4315,12 +5923,12 @@
 /* google.protobuf.EnumValueOptions */
 
 UPB_INLINE google_protobuf_EnumValueOptions* google_protobuf_EnumValueOptions_new(upb_Arena* arena) {
-  return (google_protobuf_EnumValueOptions*)_upb_Message_New(&google_protobuf_EnumValueOptions_msginit, arena);
+  return (google_protobuf_EnumValueOptions*)_upb_Message_New(&google_protobuf_EnumValueOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4330,44 +5938,62 @@
                            int options, upb_Arena* arena) {
   google_protobuf_EnumValueOptions* ret = google_protobuf_EnumValueOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_EnumValueOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_EnumValueOptions_serialize_ex(const google_protobuf_EnumValueOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_EnumValueOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_EnumValueOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_EnumValueOptions_clear_deprecated(google_protobuf_EnumValueOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_EnumValueOptions_deprecated(const google_protobuf_EnumValueOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_EnumValueOptions_has_deprecated(const google_protobuf_EnumValueOptions* msg) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_EnumValueOptions_clear_uninterpreted_option(google_protobuf_EnumValueOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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 bool google_protobuf_EnumValueOptions_has_uninterpreted_option(const google_protobuf_EnumValueOptions* msg) {
+  size_t size;
+  google_protobuf_EnumValueOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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) {
+  const upb_MiniTableField field = {1, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
   bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
@@ -4376,12 +6002,12 @@
 /* google.protobuf.ServiceOptions */
 
 UPB_INLINE google_protobuf_ServiceOptions* google_protobuf_ServiceOptions_new(upb_Arena* arena) {
-  return (google_protobuf_ServiceOptions*)_upb_Message_New(&google_protobuf_ServiceOptions_msginit, arena);
+  return (google_protobuf_ServiceOptions*)_upb_Message_New(&google_protobuf_ServiceOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4391,44 +6017,62 @@
                            int options, upb_Arena* arena) {
   google_protobuf_ServiceOptions* ret = google_protobuf_ServiceOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_ServiceOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_ServiceOptions_serialize_ex(const google_protobuf_ServiceOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_ServiceOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_ServiceOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_ServiceOptions_clear_deprecated(google_protobuf_ServiceOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_ServiceOptions_deprecated(const google_protobuf_ServiceOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(1, 1), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_ServiceOptions_has_deprecated(const google_protobuf_ServiceOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_ServiceOptions_clear_uninterpreted_option(google_protobuf_ServiceOptions* msg) {
+  const upb_MiniTableField field = {999, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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 bool google_protobuf_ServiceOptions_has_uninterpreted_option(const google_protobuf_ServiceOptions* msg) {
+  size_t size;
+  google_protobuf_ServiceOptions_uninterpreted_option(msg, &size);
+  return size != 0;
+}
 
 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) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
   bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
@@ -4437,12 +6081,12 @@
 /* google.protobuf.MethodOptions */
 
 UPB_INLINE google_protobuf_MethodOptions* google_protobuf_MethodOptions_new(upb_Arena* arena) {
-  return (google_protobuf_MethodOptions*)_upb_Message_New(&google_protobuf_MethodOptions_msginit, arena);
+  return (google_protobuf_MethodOptions*)_upb_Message_New(&google_protobuf_MethodOptions_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4452,55 +6096,81 @@
                            int options, upb_Arena* arena) {
   google_protobuf_MethodOptions* ret = google_protobuf_MethodOptions_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_MethodOptions_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodOptions_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_MethodOptions_serialize_ex(const google_protobuf_MethodOptions* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_MethodOptions_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_MethodOptions_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_MethodOptions_clear_deprecated(google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE bool google_protobuf_MethodOptions_deprecated(const google_protobuf_MethodOptions* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(8, 8), bool);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_MethodOptions_has_deprecated(const google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodOptions_clear_idempotency_level(google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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 bool google_protobuf_MethodOptions_has_idempotency_level(const google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_MethodOptions_clear_uninterpreted_option(google_protobuf_MethodOptions* msg) {
+  const upb_MiniTableField field = {999, 8, 0, 1, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_UninterpretedOption* const*)_upb_array_accessor(msg, 8, len);
+}
+UPB_INLINE bool google_protobuf_MethodOptions_has_uninterpreted_option(const google_protobuf_MethodOptions* msg) {
+  size_t size;
+  google_protobuf_MethodOptions_uninterpreted_option(msg, &size);
+  return size != 0;
 }
 
 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);
+  const upb_MiniTableField field = {33, 1, 1, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_MethodOptions_set_idempotency_level(google_protobuf_MethodOptions *msg, int32_t value) {
+  const upb_MiniTableField field = {34, 4, 2, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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, 8, 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);
+  return (google_protobuf_UninterpretedOption**)_upb_Array_Resize_accessor2(msg, 8, 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_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 16), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_UninterpretedOption* sub = (struct google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 8, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4508,12 +6178,12 @@
 /* google.protobuf.UninterpretedOption */
 
 UPB_INLINE google_protobuf_UninterpretedOption* google_protobuf_UninterpretedOption_new(upb_Arena* arena) {
-  return (google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msginit, arena);
+  return (google_protobuf_UninterpretedOption*)_upb_Message_New(&google_protobuf_UninterpretedOption_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4523,108 +6193,166 @@
                            int options, upb_Arena* arena) {
   google_protobuf_UninterpretedOption* ret = google_protobuf_UninterpretedOption_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_UninterpretedOption_serialize_ex(const google_protobuf_UninterpretedOption* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_UninterpretedOption_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_UninterpretedOption_clear_name(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(4, 8), 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_UninterpretedOption_NamePart* const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len);
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_name(const google_protobuf_UninterpretedOption* msg) {
+  size_t size;
+  google_protobuf_UninterpretedOption_name(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_identifier_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_identifier_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_identifier_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_positive_int_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  uint64_t default_val = (uint64_t)0ull;
+  uint64_t ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_positive_int_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_negative_int_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int64_t default_val = (int64_t)0ll;
+  int64_t ret;
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption* msg) {
-  return _upb_hasbit(msg, 4);
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_negative_int_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_double_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE double google_protobuf_UninterpretedOption_double_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(24, 24), double);
+  double default_val = 0;
+  double ret;
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption* msg) {
-  return _upb_hasbit(msg, 5);
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_double_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_string_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_string_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption* msg) {
-  return _upb_hasbit(msg, 6);
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_string_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_clear_aggregate_value(google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_aggregate_value(const google_protobuf_UninterpretedOption* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_UninterpretedOption_has_aggregate_value(const google_protobuf_UninterpretedOption* msg) {
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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);
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), 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);
+  return (google_protobuf_UninterpretedOption_NamePart**)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 8), 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_Message_New(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(56, 80), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_UninterpretedOption_NamePart* sub = (struct google_protobuf_UninterpretedOption_NamePart*)_upb_Message_New(&google_protobuf_UninterpretedOption_NamePart_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), 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_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(32, 32), upb_StringView) = value;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 16), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_positive_int_value(google_protobuf_UninterpretedOption *msg, uint64_t value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(16, 32), 2, kUpb_NoSub, 4, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_negative_int_value(google_protobuf_UninterpretedOption *msg, int64_t value) {
+  const upb_MiniTableField field = {5, UPB_SIZE(24, 40), 3, kUpb_NoSub, 3, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_double_value(google_protobuf_UninterpretedOption *msg, double value) {
+  const upb_MiniTableField field = {6, UPB_SIZE(32, 48), 4, kUpb_NoSub, 1, kUpb_FieldMode_Scalar | (kUpb_FieldRep_8Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_string_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) {
+  const upb_MiniTableField field = {7, UPB_SIZE(40, 56), 5, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) {
+  const upb_MiniTableField field = {8, UPB_SIZE(48, 72), 6, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_StringView value) {
-  _upb_sethas(msg, 5);
-  *UPB_PTR_AT(msg, UPB_SIZE(40, 48), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_UninterpretedOption_set_aggregate_value(google_protobuf_UninterpretedOption *msg, upb_StringView value) {
-  _upb_sethas(msg, 6);
-  *UPB_PTR_AT(msg, UPB_SIZE(48, 64), upb_StringView) = 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_Message_New(&google_protobuf_UninterpretedOption_NamePart_msginit, arena);
+  return (google_protobuf_UninterpretedOption_NamePart*)_upb_Message_New(&google_protobuf_UninterpretedOption_NamePart_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4634,50 +6362,70 @@
                            int options, upb_Arena* arena) {
   google_protobuf_UninterpretedOption_NamePart* ret = google_protobuf_UninterpretedOption_NamePart_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_UninterpretedOption_NamePart_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_NamePart_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_UninterpretedOption_NamePart_serialize_ex(const google_protobuf_UninterpretedOption_NamePart* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_UninterpretedOption_NamePart_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_UninterpretedOption_NamePart_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_name_part(google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_UninterpretedOption_NamePart_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-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_has_name_part(const google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_clear_is_extension(google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  bool default_val = false;
+  bool ret;
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_UninterpretedOption_NamePart_has_is_extension(const google_protobuf_UninterpretedOption_NamePart* msg) {
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_name_part(google_protobuf_UninterpretedOption_NamePart *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_UninterpretedOption_NamePart_set_is_extension(google_protobuf_UninterpretedOption_NamePart *msg, bool value) {
+  const upb_MiniTableField field = {2, 1, 2, kUpb_NoSub, 8, kUpb_FieldMode_Scalar | (kUpb_FieldRep_1Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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_Message_New(&google_protobuf_SourceCodeInfo_msginit, arena);
+  return (google_protobuf_SourceCodeInfo*)_upb_Message_New(&google_protobuf_SourceCodeInfo_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4687,35 +6435,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_SourceCodeInfo* ret = google_protobuf_SourceCodeInfo_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_SourceCodeInfo_serialize_ex(const google_protobuf_SourceCodeInfo* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_SourceCodeInfo_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_SourceCodeInfo_clear_location(google_protobuf_SourceCodeInfo* msg) {
+  const upb_MiniTableField field = {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_SourceCodeInfo_Location* const*)_upb_array_accessor(msg, 0, len);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_has_location(const google_protobuf_SourceCodeInfo* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_location(msg, &size);
+  return size != 0;
 }
 
 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);
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_array_mutable_accessor(msg, 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);
+  return (google_protobuf_SourceCodeInfo_Location**)_upb_Array_Resize_accessor2(msg, 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_Message_New(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_SourceCodeInfo_Location* sub = (struct google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google_protobuf_SourceCodeInfo_Location_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4723,12 +6481,12 @@
 /* google.protobuf.SourceCodeInfo.Location */
 
 UPB_INLINE google_protobuf_SourceCodeInfo_Location* google_protobuf_SourceCodeInfo_Location_new(upb_Arena* arena) {
-  return (google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google_protobuf_SourceCodeInfo_Location_msginit, arena);
+  return (google_protobuf_SourceCodeInfo_Location*)_upb_Message_New(&google_protobuf_SourceCodeInfo_Location_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4738,86 +6496,133 @@
                            int options, upb_Arena* arena) {
   google_protobuf_SourceCodeInfo_Location* ret = google_protobuf_SourceCodeInfo_Location_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_SourceCodeInfo_Location_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_Location_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_SourceCodeInfo_Location_serialize_ex(const google_protobuf_SourceCodeInfo_Location* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_SourceCodeInfo_Location_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_SourceCodeInfo_Location_msg_init, options, arena, &ptr, len);
+  return ptr;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_path(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 8), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(4, 8), len);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_path(const google_protobuf_SourceCodeInfo_Location* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_Location_path(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_span(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(8, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(8, 16), len);
 }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_span(const google_protobuf_SourceCodeInfo_Location* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_Location_span(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_comments(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_trailing_comments(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_SourceCodeInfo_Location_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_trailing_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_SourceCodeInfo_Location_clear_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg) {
+  const upb_MiniTableField field = {6, UPB_SIZE(12, 56), 0, kUpb_NoSub, 12, kUpb_FieldMode_Array | kUpb_LabelFlags_IsAlternate | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView const* google_protobuf_SourceCodeInfo_Location_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location* msg, size_t* len) {
-  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(28, 56), len);
+  return (upb_StringView const*)_upb_array_accessor(msg, UPB_SIZE(12, 56), len);
+}
+UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_has_leading_detached_comments(const google_protobuf_SourceCodeInfo_Location* msg) {
+  size_t size;
+  google_protobuf_SourceCodeInfo_Location_leading_detached_comments(msg, &size);
+  return size != 0;
 }
 
 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);
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 8), 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);
+  return (int32_t*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 8), 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);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 8), 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);
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(8, 16), 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);
+  return (int32_t*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(8, 16), 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);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(8, 16), 2, &val, arena);
 }
 UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_leading_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(4, 8), upb_StringView) = value;
-}
-UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) {
-  _upb_sethas(msg, 2);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 24), upb_StringView) = value;
-}
-UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t* len) {
-  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(28, 56), len);
+  const upb_MiniTableField field = {3, UPB_SIZE(16, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_SourceCodeInfo_Location_set_trailing_comments(google_protobuf_SourceCodeInfo_Location *msg, upb_StringView value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(24, 40), 2, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_mutable_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t* len) {
+  return (upb_StringView*)_upb_array_mutable_accessor(msg, UPB_SIZE(12, 56), len);
 }
 UPB_INLINE upb_StringView* google_protobuf_SourceCodeInfo_Location_resize_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, size_t len, upb_Arena* arena) {
-  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(28, 56), len, UPB_SIZE(3, 4), arena);
+  return (upb_StringView*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(12, 56), len, UPB_SIZE(3, 4), arena);
 }
 UPB_INLINE bool google_protobuf_SourceCodeInfo_Location_add_leading_detached_comments(google_protobuf_SourceCodeInfo_Location* msg, upb_StringView val, upb_Arena* arena) {
-  return _upb_Array_Append_accessor2(msg, UPB_SIZE(28, 56), UPB_SIZE(3, 4), &val, arena);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(12, 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_Message_New(&google_protobuf_GeneratedCodeInfo_msginit, arena);
+  return (google_protobuf_GeneratedCodeInfo*)_upb_Message_New(&google_protobuf_GeneratedCodeInfo_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4827,35 +6632,45 @@
                            int options, upb_Arena* arena) {
   google_protobuf_GeneratedCodeInfo* ret = google_protobuf_GeneratedCodeInfo_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_GeneratedCodeInfo_serialize_ex(const google_protobuf_GeneratedCodeInfo* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_msg_init, options, arena, &ptr, len);
+  return ptr;
 }
-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 void google_protobuf_GeneratedCodeInfo_clear_annotation(google_protobuf_GeneratedCodeInfo* msg) {
+  const upb_MiniTableField field = {1, 0, 0, 0, 11, kUpb_FieldMode_Array | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (const google_protobuf_GeneratedCodeInfo_Annotation* const*)_upb_array_accessor(msg, 0, len);
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_has_annotation(const google_protobuf_GeneratedCodeInfo* msg) {
+  size_t size;
+  google_protobuf_GeneratedCodeInfo_annotation(msg, &size);
+  return size != 0;
 }
 
 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);
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_array_mutable_accessor(msg, 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);
+  return (google_protobuf_GeneratedCodeInfo_Annotation**)_upb_Array_Resize_accessor2(msg, 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_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
-  bool ok = _upb_Array_Append_accessor2(msg, UPB_SIZE(0, 0), UPB_SIZE(2, 3), &sub, arena);
+  struct google_protobuf_GeneratedCodeInfo_Annotation* sub = (struct google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msg_init, arena);
+  bool ok = _upb_Array_Append_accessor2(msg, 0, UPB_SIZE(2, 3), &sub, arena);
   if (!ok) return NULL;
   return sub;
 }
@@ -4863,12 +6678,12 @@
 /* google.protobuf.GeneratedCodeInfo.Annotation */
 
 UPB_INLINE google_protobuf_GeneratedCodeInfo_Annotation* google_protobuf_GeneratedCodeInfo_Annotation_new(upb_Arena* arena) {
-  return (google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msginit, arena);
+  return (google_protobuf_GeneratedCodeInfo_Annotation*)_upb_Message_New(&google_protobuf_GeneratedCodeInfo_Annotation_msg_init, 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);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, NULL, 0, arena) != kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
@@ -4878,64 +6693,119 @@
                            int options, upb_Arena* arena) {
   google_protobuf_GeneratedCodeInfo_Annotation* ret = google_protobuf_GeneratedCodeInfo_Annotation_new(arena);
   if (!ret) return NULL;
-  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, extreg, options, arena) !=
+  if (upb_Decode(buf, size, ret, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, extreg, options, arena) !=
       kUpb_DecodeStatus_Ok) {
     return NULL;
   }
   return ret;
 }
 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, 0, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, 0, arena, &ptr, len);
+  return ptr;
 }
 UPB_INLINE char* google_protobuf_GeneratedCodeInfo_Annotation_serialize_ex(const google_protobuf_GeneratedCodeInfo_Annotation* msg, int options,
                                  upb_Arena* arena, size_t* len) {
-  return upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msginit, options, arena, len);
+  char* ptr;
+  (void)upb_Encode(msg, &google_protobuf_GeneratedCodeInfo_Annotation_msg_init, options, arena, &ptr, len);
+  return ptr;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_path(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {1, UPB_SIZE(4, 16), 0, kUpb_NoSub, 5, kUpb_FieldMode_Array | kUpb_LabelFlags_IsPacked | (UPB_SIZE(kUpb_FieldRep_4Byte, kUpb_FieldRep_8Byte) << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  return (int32_t const*)_upb_array_accessor(msg, UPB_SIZE(4, 16), len);
 }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
-  return _upb_hasbit(msg, 1);
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_path(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  size_t size;
+  google_protobuf_GeneratedCodeInfo_Annotation_path(msg, &size);
+  return size != 0;
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_source_file(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 UPB_INLINE upb_StringView google_protobuf_GeneratedCodeInfo_Annotation_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
-  return *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_StringView);
+  upb_StringView default_val = upb_StringView_FromString("");
+  upb_StringView ret;
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
-  return _upb_hasbit(msg, 2);
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_source_file(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_begin(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
 }
-UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
-  return _upb_hasbit(msg, 3);
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_begin(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_end(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
 }
 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);
+  int32_t default_val = (int32_t)0;
+  int32_t ret;
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_end(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
+}
+UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_clear_semantic(google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_ClearNonExtensionField(msg, &field);
+}
+UPB_INLINE int32_t google_protobuf_GeneratedCodeInfo_Annotation_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  int32_t default_val = 0;
+  int32_t ret;
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_GetNonExtensionField(msg, &field, &default_val, &ret);
+  return ret;
+}
+UPB_INLINE bool google_protobuf_GeneratedCodeInfo_Annotation_has_semantic(const google_protobuf_GeneratedCodeInfo_Annotation* msg) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  return _upb_MiniTable_HasNonExtensionField(msg, &field);
 }
 
 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);
+  return (int32_t*)_upb_array_mutable_accessor(msg, UPB_SIZE(4, 16), 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);
+  return (int32_t*)_upb_Array_Resize_accessor2(msg, UPB_SIZE(4, 16), 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);
+  return _upb_Array_Append_accessor2(msg, UPB_SIZE(4, 16), 2, &val, arena);
 }
 UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_source_file(google_protobuf_GeneratedCodeInfo_Annotation *msg, upb_StringView value) {
-  _upb_sethas(msg, 1);
-  *UPB_PTR_AT(msg, UPB_SIZE(12, 16), upb_StringView) = value;
+  const upb_MiniTableField field = {2, UPB_SIZE(20, 24), 1, kUpb_NoSub, 12, kUpb_FieldMode_Scalar | kUpb_LabelFlags_IsAlternate | (kUpb_FieldRep_StringView << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_begin(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  const upb_MiniTableField field = {3, UPB_SIZE(8, 4), 2, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_end(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  const upb_MiniTableField field = {4, UPB_SIZE(12, 8), 3, kUpb_NoSub, 5, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &value);
+}UPB_INLINE void google_protobuf_GeneratedCodeInfo_Annotation_set_semantic(google_protobuf_GeneratedCodeInfo_Annotation *msg, int32_t value) {
+  const upb_MiniTableField field = {5, UPB_SIZE(16, 12), 4, 0, 14, kUpb_FieldMode_Scalar | (kUpb_FieldRep_4Byte << kUpb_FieldRep_Shift)};
+  _upb_MiniTable_SetNonExtensionField(msg, &field, &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;
-}
-
-extern const upb_MiniTable_File google_protobuf_descriptor_proto_upb_file_layout;
+extern const upb_MiniTableFile google_protobuf_descriptor_proto_upb_file_layout;
 
 /* Max size 32 is google.protobuf.FileOptions */
 /* Max size 64 is google.protobuf.FileOptions */
@@ -4948,206 +6818,536 @@
 
 #endif  /* GOOGLE_PROTOBUF_DESCRIPTOR_PROTO_UPB_H_ */
 
-/** upb/def.h ************************************************************/
-#ifndef UPB_DEF_H_
-#define UPB_DEF_H_
+#ifndef UPB_HASH_INT_TABLE_H_
+#define UPB_HASH_INT_TABLE_H_
 
 
-/* Must be last. */
+// Must be last.
+
+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;
 
 #ifdef __cplusplus
 extern "C" {
-#endif /* __cplusplus */
+#endif
 
-struct upb_EnumDef;
-typedef struct upb_EnumDef upb_EnumDef;
-struct upb_EnumValueDef;
-typedef struct upb_EnumValueDef upb_EnumValueDef;
-struct upb_ExtensionRange;
-typedef struct upb_ExtensionRange upb_ExtensionRange;
-struct upb_FieldDef;
-typedef struct upb_FieldDef upb_FieldDef;
-struct upb_FileDef;
-typedef struct upb_FileDef upb_FileDef;
-struct upb_MethodDef;
-typedef struct upb_MethodDef upb_MethodDef;
-struct upb_MessageDef;
-typedef struct upb_MessageDef upb_MessageDef;
-struct upb_OneofDef;
-typedef struct upb_OneofDef upb_OneofDef;
-struct upb_ServiceDef;
-typedef struct upb_ServiceDef upb_ServiceDef;
-struct upb_streamdef;
-typedef struct upb_streamdef upb_streamdef;
-struct upb_DefPool;
-typedef struct upb_DefPool upb_DefPool;
+// Initialize a table. If memory allocation failed, false is returned and
+// the table is uninitialized.
+bool upb_inttable_init(upb_inttable* table, upb_Arena* a);
+
+// Returns the number of values in the table.
+size_t upb_inttable_count(const upb_inttable* t);
+
+// Inserts the given key into the hashtable with the given value.
+// The key must not already exist in the hash table.
+// The value must not be 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);
+
+// 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);
+
+// 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);
+
+// 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);
+
+// Iteration over inttable:
+//
+//   intptr_t iter = UPB_INTTABLE_BEGIN;
+//   uintptr_t key;
+//   upb_value val;
+//   while (upb_inttable_next(t, &key, &val, &iter)) {
+//      // ...
+//   }
+
+#define UPB_INTTABLE_BEGIN -1
+
+bool upb_inttable_next(const upb_inttable* t, uintptr_t* key, upb_value* val,
+                       intptr_t* iter);
+void upb_inttable_removeiter(upb_inttable* t, intptr_t* iter);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_HASH_INT_TABLE_H_ */
+
+#ifndef UPB_JSON_DECODE_H_
+#define UPB_JSON_DECODE_H_
+
+
+#ifndef UPB_REFLECTION_DEF_H_
+#define UPB_REFLECTION_DEF_H_
+
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_DEF_POOL_H_
+#define UPB_REFLECTION_DEF_POOL_H_
+
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+// Declarations common to all public def types.
+
+#ifndef UPB_REFLECTION_COMMON_H_
+#define UPB_REFLECTION_COMMON_H_
+
 
 typedef enum { kUpb_Syntax_Proto2 = 2, kUpb_Syntax_Proto3 = 3 } upb_Syntax;
 
-/* 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.
- */
+// Forward declarations for circular references.
+typedef struct upb_DefPool upb_DefPool;
+typedef struct upb_EnumDef upb_EnumDef;
+typedef struct upb_EnumReservedRange upb_EnumReservedRange;
+typedef struct upb_EnumValueDef upb_EnumValueDef;
+typedef struct upb_ExtensionRange upb_ExtensionRange;
+typedef struct upb_FieldDef upb_FieldDef;
+typedef struct upb_FileDef upb_FileDef;
+typedef struct upb_MessageDef upb_MessageDef;
+typedef struct upb_MessageReservedRange upb_MessageReservedRange;
+typedef struct upb_MethodDef upb_MethodDef;
+typedef struct upb_OneofDef upb_OneofDef;
+typedef struct upb_ServiceDef upb_ServiceDef;
+
+// EVERYTHING BELOW THIS LINE IS INTERNAL - DO NOT USE /////////////////////////
+
+typedef struct upb_DefBuilder upb_DefBuilder;
+
+#endif /* UPB_REFLECTION_COMMON_H_ */
+
+#ifndef UPB_REFLECTION_DEF_TYPE_H_
+#define UPB_REFLECTION_DEF_TYPE_H_
+
+
+// Must be last.
+
+// Inside a symtab we store tagged pointers to specific def types.
+typedef enum {
+  UPB_DEFTYPE_MASK = 7,
+
+  // Only inside symtab table.
+  UPB_DEFTYPE_EXT = 0,
+  UPB_DEFTYPE_MSG = 1,
+  UPB_DEFTYPE_ENUM = 2,
+  UPB_DEFTYPE_ENUMVAL = 3,
+  UPB_DEFTYPE_SERVICE = 4,
+
+  // Only inside message table.
+  UPB_DEFTYPE_FIELD = 0,
+  UPB_DEFTYPE_ONEOF = 1,
+  UPB_DEFTYPE_FIELD_JSONNAME = 2,
+} upb_deftype_t;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Our 3-bit pointer tagging requires all pointers to be multiples of 8.
+// The arena will always yield 8-byte-aligned addresses, however we put
+// the defs into arrays. For each element in the array to be 8-byte-aligned,
+// the sizes of each def type must also be a multiple of 8.
+//
+// If any of these asserts fail, we need to add or remove padding on 32-bit
+// machines (64-bit machines will have 8-byte alignment already due to
+// pointers, which all of these structs have).
+UPB_INLINE void _upb_DefType_CheckPadding(size_t size) {
+  UPB_ASSERT((size & UPB_DEFTYPE_MASK) == 0);
+}
+
+upb_deftype_t _upb_DefType_Type(upb_value v);
+
+upb_value _upb_DefType_Pack(const void* ptr, upb_deftype_t type);
+
+const void* _upb_DefType_Unpack(upb_value v, upb_deftype_t type);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_TYPE_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void upb_DefPool_Free(upb_DefPool* s);
+
+upb_DefPool* upb_DefPool_New(void);
+
+const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
+                                                    const char* sym);
+
+const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
+    const upb_DefPool* s, const char* sym, size_t len);
+
+const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
+                                              const char* sym);
+
+const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
+                                                      const char* sym);
+
+const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
+                                              const char* name);
+
+const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s,
+                                                      const char* name,
+                                                      size_t len);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByMiniTable(
+    const upb_DefPool* s, const upb_MiniTableExtension* ext);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
+                                                    const char* sym);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size);
+
+const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
+                                                      const upb_MessageDef* m,
+                                                      int32_t fieldnum);
+
+const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
+                                                    const char* name);
+
+const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
+    const upb_DefPool* s, const char* name, size_t size);
+
+const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
+                                                        const char* name);
+
+const upb_FileDef* upb_DefPool_AddFile(
+    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file_proto,
+    upb_Status* status);
+
+const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
+    const upb_DefPool* s);
+
+const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
+                                                  const upb_MessageDef* m,
+                                                  size_t* count);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_POOL_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ENUM_DEF_H_
+#define UPB_REFLECTION_ENUM_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num);
+const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e);
+int32_t upb_EnumDef_Default(const upb_EnumDef* e);
+const upb_FileDef* upb_EnumDef_File(const upb_EnumDef* e);
+const upb_EnumValueDef* upb_EnumDef_FindValueByName(const upb_EnumDef* e,
+                                                    const char* name);
+const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
+    const upb_EnumDef* e, const char* name, size_t size);
+const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e,
+                                                      int32_t num);
+const char* upb_EnumDef_FullName(const upb_EnumDef* e);
+bool upb_EnumDef_HasOptions(const upb_EnumDef* e);
+bool upb_EnumDef_IsClosed(const upb_EnumDef* e);
+
+// Creates a mini descriptor string for an enum, returns true on success.
+bool upb_EnumDef_MiniDescriptorEncode(const upb_EnumDef* e, upb_Arena* a,
+                                      upb_StringView* out);
+
+const char* upb_EnumDef_Name(const upb_EnumDef* e);
+const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e);
+
+upb_StringView upb_EnumDef_ReservedName(const upb_EnumDef* e, int i);
+int upb_EnumDef_ReservedNameCount(const upb_EnumDef* e);
+
+const upb_EnumReservedRange* upb_EnumDef_ReservedRange(const upb_EnumDef* e,
+                                                       int i);
+int upb_EnumDef_ReservedRangeCount(const upb_EnumDef* e);
+
+const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i);
+int upb_EnumDef_ValueCount(const upb_EnumDef* e);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ENUM_VALUE_DEF_H_
+#define UPB_REFLECTION_ENUM_VALUE_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* v);
+const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* v);
+bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* v);
+uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* v);
+const char* upb_EnumValueDef_Name(const upb_EnumValueDef* v);
+int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* v);
+const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
+    const upb_EnumValueDef* v);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_VALUE_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_EXTENSION_RANGE_H_
+#define UPB_REFLECTION_EXTENSION_RANGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r);
+int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r);
+
+bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r);
+const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
+    const upb_ExtensionRange* r);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_EXTENSION_RANGE_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_FIELD_DEF_H_
+#define UPB_REFLECTION_FIELD_DEF_H_
+
+
+// Must be last.
+
+// Maximum field number allowed for FieldDefs.
+// This is an inherent limit of the protobuf wire format.
+#define kUpb_MaxFieldNumber ((1 << 29) - 1)
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_OneofDef* upb_FieldDef_ContainingOneof(const upb_FieldDef* f);
+const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f);
+upb_CType upb_FieldDef_CType(const upb_FieldDef* f);
+const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f);
+const upb_MessageDef* upb_FieldDef_ExtensionScope(const upb_FieldDef* f);
+const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f);
+const char* upb_FieldDef_FullName(const upb_FieldDef* f);
+bool upb_FieldDef_HasDefault(const upb_FieldDef* f);
+bool upb_FieldDef_HasJsonName(const upb_FieldDef* f);
+bool upb_FieldDef_HasOptions(const upb_FieldDef* f);
+bool upb_FieldDef_HasPresence(const upb_FieldDef* f);
+bool upb_FieldDef_HasSubDef(const upb_FieldDef* f);
+uint32_t upb_FieldDef_Index(const upb_FieldDef* f);
+bool upb_FieldDef_IsExtension(const upb_FieldDef* f);
+bool upb_FieldDef_IsMap(const upb_FieldDef* f);
+bool upb_FieldDef_IsOptional(const upb_FieldDef* f);
+bool upb_FieldDef_IsPacked(const upb_FieldDef* f);
+bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f);
+bool upb_FieldDef_IsRepeated(const upb_FieldDef* f);
+bool upb_FieldDef_IsRequired(const upb_FieldDef* f);
+bool upb_FieldDef_IsString(const upb_FieldDef* f);
+bool upb_FieldDef_IsSubMessage(const upb_FieldDef* f);
+const char* upb_FieldDef_JsonName(const upb_FieldDef* f);
+upb_Label upb_FieldDef_Label(const upb_FieldDef* f);
+const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f);
+
+// Creates a mini descriptor string for a field, returns true on success.
+bool upb_FieldDef_MiniDescriptorEncode(const upb_FieldDef* f, upb_Arena* a,
+                                       upb_StringView* out);
+
+const upb_MiniTableField* upb_FieldDef_MiniTable(const upb_FieldDef* f);
+const char* upb_FieldDef_Name(const upb_FieldDef* f);
+uint32_t upb_FieldDef_Number(const upb_FieldDef* f);
+const google_protobuf_FieldOptions* upb_FieldDef_Options(const upb_FieldDef* f);
+const upb_OneofDef* upb_FieldDef_RealContainingOneof(const upb_FieldDef* f);
+upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FIELD_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_FILE_DEF_H_
+#define UPB_REFLECTION_FILE_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i);
+int upb_FileDef_DependencyCount(const upb_FileDef* f);
+bool upb_FileDef_HasOptions(const upb_FileDef* f);
+const char* upb_FileDef_Name(const upb_FileDef* f);
+const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f);
+const char* upb_FileDef_Package(const upb_FileDef* f);
+const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f);
+
+const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i);
+int upb_FileDef_PublicDependencyCount(const upb_FileDef* f);
+
+const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i);
+int upb_FileDef_ServiceCount(const upb_FileDef* f);
+
+upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f);
+
+const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i);
+int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f);
+
+const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i);
+int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f);
+
+const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i);
+int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f);
+
+const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i);
+int upb_FileDef_WeakDependencyCount(const upb_FileDef* f);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FILE_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_MESSAGE_DEF_H_
+#define UPB_REFLECTION_MESSAGE_DEF_H_
+
+
+// Must be last.
+
+// Well-known field tag numbers for map-entry messages.
+#define kUpb_MapEntry_KeyFieldNumber 1
+#define kUpb_MapEntry_ValueFieldNumber 2
+
+// Well-known field tag numbers for Any messages.
+#define kUpb_Any_TypeFieldNumber 1
+#define kUpb_Any_ValueFieldNumber 2
+
+// Well-known field tag numbers for duration messages.
+#define kUpb_Duration_SecondsFieldNumber 1
+#define kUpb_Duration_NanosFieldNumber 2
+
+// Well-known field tag numbers for timestamp messages.
+#define kUpb_Timestamp_SecondsFieldNumber 1
+#define kUpb_Timestamp_NanosFieldNumber 2
+
+// 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 number of these groups are not changed.
 typedef enum {
   kUpb_WellKnown_Unspecified,
   kUpb_WellKnown_Any,
   kUpb_WellKnown_FieldMask,
   kUpb_WellKnown_Duration,
   kUpb_WellKnown_Timestamp,
-  /* number wrappers */
+
+  // number wrappers
   kUpb_WellKnown_DoubleValue,
   kUpb_WellKnown_FloatValue,
   kUpb_WellKnown_Int64Value,
   kUpb_WellKnown_UInt64Value,
   kUpb_WellKnown_Int32Value,
   kUpb_WellKnown_UInt32Value,
-  /* string wrappers */
+
+  // string wrappers
   kUpb_WellKnown_StringValue,
   kUpb_WellKnown_BytesValue,
   kUpb_WellKnown_BoolValue,
   kUpb_WellKnown_Value,
   kUpb_WellKnown_ListValue,
-  kUpb_WellKnown_Struct
+  kUpb_WellKnown_Struct,
 } upb_WellKnown;
 
-/* upb_FieldDef ***************************************************************/
+#ifdef __cplusplus
+extern "C" {
+#endif
 
-/* Maximum field number allowed for FieldDefs.  This is an inherent limit of the
- * protobuf wire format. */
-#define kUpb_MaxFieldNumber ((1 << 29) - 1)
-
-const google_protobuf_FieldOptions* upb_FieldDef_Options(const upb_FieldDef* f);
-bool upb_FieldDef_HasOptions(const upb_FieldDef* f);
-const char* upb_FieldDef_FullName(const upb_FieldDef* f);
-upb_CType upb_FieldDef_CType(const upb_FieldDef* f);
-upb_FieldType upb_FieldDef_Type(const upb_FieldDef* f);
-upb_Label 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_HasJsonName(const upb_FieldDef* f);
-bool upb_FieldDef_IsExtension(const upb_FieldDef* f);
-bool upb_FieldDef_IsPacked(const upb_FieldDef* f);
-const upb_FileDef* upb_FieldDef_File(const upb_FieldDef* f);
-const upb_MessageDef* upb_FieldDef_ContainingType(const upb_FieldDef* f);
-const upb_MessageDef* upb_FieldDef_ExtensionScope(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_IsSubMessage(const upb_FieldDef* f);
-bool upb_FieldDef_IsString(const upb_FieldDef* f);
-bool upb_FieldDef_IsRepeated(const upb_FieldDef* f);
-bool upb_FieldDef_IsPrimitive(const upb_FieldDef* f);
-bool upb_FieldDef_IsMap(const upb_FieldDef* f);
-bool upb_FieldDef_HasDefault(const upb_FieldDef* f);
-bool upb_FieldDef_HasSubDef(const upb_FieldDef* f);
-bool upb_FieldDef_HasPresence(const upb_FieldDef* f);
-const upb_MessageDef* upb_FieldDef_MessageSubDef(const upb_FieldDef* f);
-const upb_EnumDef* upb_FieldDef_EnumSubDef(const upb_FieldDef* f);
-const upb_MiniTable_Field* upb_FieldDef_MiniTable(const upb_FieldDef* f);
-const upb_MiniTable_Extension* _upb_FieldDef_ExtensionMiniTable(
-    const upb_FieldDef* f);
-bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f);
-
-/* upb_OneofDef ***************************************************************/
-
-const google_protobuf_OneofOptions* upb_OneofDef_Options(const upb_OneofDef* o);
-bool upb_OneofDef_HasOptions(const upb_OneofDef* o);
-const char* upb_OneofDef_Name(const upb_OneofDef* o);
-const upb_MessageDef* 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_LookupNameWithSize(const upb_OneofDef* o,
-                                                    const char* name,
-                                                    size_t length);
-UPB_INLINE const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o,
-                                                       const char* name) {
-  return upb_OneofDef_LookupNameWithSize(o, name, strlen(name));
-}
-const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
-                                              uint32_t num);
-
-/* upb_MessageDef *************************************************************/
-
-/* Well-known field tag numbers for map-entry messages. */
-#define kUpb_MapEntry_KeyFieldNumber 1
-#define kUpb_MapEntry_ValueFieldNumber 2
-
-/* Well-known field tag numbers for Any messages. */
-#define kUpb_Any_TypeFieldNumber 1
-#define kUpb_Any_ValueFieldNumber 2
-
-/* Well-known field tag numbers for timestamp messages. */
-#define kUpb_Duration_SecondsFieldNumber 1
-#define kUpb_Duration_NanosFieldNumber 2
-
-/* Well-known field tag numbers for duration messages. */
-#define kUpb_Timestamp_SecondsFieldNumber 1
-#define kUpb_Timestamp_NanosFieldNumber 2
-
-const google_protobuf_MessageOptions* upb_MessageDef_Options(
-    const upb_MessageDef* m);
-bool upb_MessageDef_HasOptions(const upb_MessageDef* m);
-const char* upb_MessageDef_FullName(const upb_MessageDef* m);
-const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m);
 const upb_MessageDef* upb_MessageDef_ContainingType(const upb_MessageDef* m);
-const char* upb_MessageDef_Name(const upb_MessageDef* m);
-upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m);
-upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m);
-int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m);
-int upb_MessageDef_FieldCount(const upb_MessageDef* m);
-int upb_MessageDef_OneofCount(const upb_MessageDef* m);
+
 const upb_ExtensionRange* upb_MessageDef_ExtensionRange(const upb_MessageDef* m,
                                                         int i);
+int upb_MessageDef_ExtensionRangeCount(const upb_MessageDef* m);
+
 const upb_FieldDef* upb_MessageDef_Field(const upb_MessageDef* m, int i);
-const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i);
-const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
-                                                     uint32_t i);
-const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
-    const upb_MessageDef* m, const char* name, size_t len);
-const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize(
-    const upb_MessageDef* m, const char* name, size_t len);
-const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m);
+int upb_MessageDef_FieldCount(const upb_MessageDef* m);
 
-UPB_INLINE const upb_OneofDef* upb_MessageDef_FindOneofByName(
+const upb_FileDef* upb_MessageDef_File(const upb_MessageDef* m);
+
+// Returns a field by either JSON name or regular proto name.
+const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size);
+UPB_INLINE const upb_FieldDef* upb_MessageDef_FindByJsonName(
     const upb_MessageDef* m, const char* name) {
-  return upb_MessageDef_FindOneofByNameWithSize(m, name, strlen(name));
+  return upb_MessageDef_FindByJsonNameWithSize(m, name, strlen(name));
 }
 
-UPB_INLINE const upb_FieldDef* upb_MessageDef_FindFieldByName(
-    const upb_MessageDef* m, const char* name) {
-  return upb_MessageDef_FindFieldByNameWithSize(m, name, strlen(name));
-}
-
-UPB_INLINE bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m) {
-  return google_protobuf_MessageOptions_map_entry(upb_MessageDef_Options(m));
-}
-
-/* Nested entities. */
-int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m);
-int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m);
-int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m);
-const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
-                                                   int i);
-const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i);
-const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
-                                                   int i);
-
-/* 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. */
+// 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_MessageDef_FindByNameWithSize(const upb_MessageDef* m,
-                                       const char* name, size_t len,
+                                       const char* name, size_t size,
                                        const upb_FieldDef** f,
                                        const upb_OneofDef** o);
-
 UPB_INLINE bool upb_MessageDef_FindByName(const upb_MessageDef* m,
                                           const char* name,
                                           const upb_FieldDef** f,
@@ -5155,215 +7355,264 @@
   return upb_MessageDef_FindByNameWithSize(m, name, strlen(name), f, o);
 }
 
-/* Returns a field by either JSON name or regular proto name. */
-const upb_FieldDef* upb_MessageDef_FindByJsonNameWithSize(
-    const upb_MessageDef* m, const char* name, size_t len);
-UPB_INLINE const upb_FieldDef* upb_MessageDef_FindByJsonName(
-    const upb_MessageDef* m, const char* name) {
-  return upb_MessageDef_FindByJsonNameWithSize(m, name, strlen(name));
-}
+const upb_FieldDef* upb_MessageDef_FindFieldByName(const upb_MessageDef* m,
+                                                   const char* name);
+const upb_FieldDef* upb_MessageDef_FindFieldByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size);
+const upb_FieldDef* upb_MessageDef_FindFieldByNumber(const upb_MessageDef* m,
+                                                     uint32_t i);
+const upb_OneofDef* upb_MessageDef_FindOneofByName(const upb_MessageDef* m,
+                                                   const char* name);
+const upb_OneofDef* upb_MessageDef_FindOneofByNameWithSize(
+    const upb_MessageDef* m, const char* name, size_t size);
+const char* upb_MessageDef_FullName(const upb_MessageDef* m);
+bool upb_MessageDef_HasOptions(const upb_MessageDef* m);
+bool upb_MessageDef_IsMapEntry(const upb_MessageDef* m);
+bool upb_MessageDef_IsMessageSet(const upb_MessageDef* m);
 
-/* upb_ExtensionRange *********************************************************/
+// Creates a mini descriptor string for a message, returns true on success.
+bool upb_MessageDef_MiniDescriptorEncode(const upb_MessageDef* m, upb_Arena* a,
+                                         upb_StringView* out);
 
-const google_protobuf_ExtensionRangeOptions* upb_ExtensionRange_Options(
-    const upb_ExtensionRange* r);
-bool upb_ExtensionRange_HasOptions(const upb_ExtensionRange* r);
-int32_t upb_ExtensionRange_Start(const upb_ExtensionRange* r);
-int32_t upb_ExtensionRange_End(const upb_ExtensionRange* r);
+const upb_MiniTable* upb_MessageDef_MiniTable(const upb_MessageDef* m);
+const char* upb_MessageDef_Name(const upb_MessageDef* m);
 
-/* upb_EnumDef ****************************************************************/
+const upb_EnumDef* upb_MessageDef_NestedEnum(const upb_MessageDef* m, int i);
+const upb_FieldDef* upb_MessageDef_NestedExtension(const upb_MessageDef* m,
+                                                   int i);
+const upb_MessageDef* upb_MessageDef_NestedMessage(const upb_MessageDef* m,
+                                                   int i);
 
-const google_protobuf_EnumOptions* upb_EnumDef_Options(const upb_EnumDef* e);
-bool upb_EnumDef_HasOptions(const upb_EnumDef* e);
-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);
-const upb_MessageDef* upb_EnumDef_ContainingType(const upb_EnumDef* e);
-int32_t upb_EnumDef_Default(const upb_EnumDef* e);
-int upb_EnumDef_ValueCount(const upb_EnumDef* e);
-const upb_EnumValueDef* upb_EnumDef_Value(const upb_EnumDef* e, int i);
+int upb_MessageDef_NestedEnumCount(const upb_MessageDef* m);
+int upb_MessageDef_NestedExtensionCount(const upb_MessageDef* m);
+int upb_MessageDef_NestedMessageCount(const upb_MessageDef* m);
 
-const upb_EnumValueDef* upb_EnumDef_FindValueByNameWithSize(
-    const upb_EnumDef* e, const char* name, size_t len);
-const upb_EnumValueDef* upb_EnumDef_FindValueByNumber(const upb_EnumDef* e,
-                                                      int32_t num);
-bool upb_EnumDef_CheckNumber(const upb_EnumDef* e, int32_t num);
+const upb_OneofDef* upb_MessageDef_Oneof(const upb_MessageDef* m, int i);
+int upb_MessageDef_OneofCount(const upb_MessageDef* m);
 
-// Convenience wrapper.
-UPB_INLINE const upb_EnumValueDef* upb_EnumDef_FindValueByName(
-    const upb_EnumDef* e, const char* name) {
-  return upb_EnumDef_FindValueByNameWithSize(e, name, strlen(name));
-}
+const google_protobuf_MessageOptions* upb_MessageDef_Options(const upb_MessageDef* m);
 
-/* upb_EnumValueDef ***********************************************************/
+upb_StringView upb_MessageDef_ReservedName(const upb_MessageDef* m, int i);
+int upb_MessageDef_ReservedNameCount(const upb_MessageDef* m);
 
-const google_protobuf_EnumValueOptions* upb_EnumValueDef_Options(
-    const upb_EnumValueDef* e);
-bool upb_EnumValueDef_HasOptions(const upb_EnumValueDef* e);
-const char* upb_EnumValueDef_FullName(const upb_EnumValueDef* e);
-const char* upb_EnumValueDef_Name(const upb_EnumValueDef* e);
-int32_t upb_EnumValueDef_Number(const upb_EnumValueDef* e);
-uint32_t upb_EnumValueDef_Index(const upb_EnumValueDef* e);
-const upb_EnumDef* upb_EnumValueDef_Enum(const upb_EnumValueDef* e);
+const upb_MessageReservedRange* upb_MessageDef_ReservedRange(
+    const upb_MessageDef* m, int i);
+int upb_MessageDef_ReservedRangeCount(const upb_MessageDef* m);
 
-/* upb_FileDef ****************************************************************/
-
-const google_protobuf_FileOptions* upb_FileDef_Options(const upb_FileDef* f);
-bool upb_FileDef_HasOptions(const upb_FileDef* f);
-const char* upb_FileDef_Name(const upb_FileDef* f);
-const char* upb_FileDef_Package(const upb_FileDef* f);
-upb_Syntax upb_FileDef_Syntax(const upb_FileDef* f);
-int upb_FileDef_DependencyCount(const upb_FileDef* f);
-int upb_FileDef_PublicDependencyCount(const upb_FileDef* f);
-int upb_FileDef_WeakDependencyCount(const upb_FileDef* f);
-int upb_FileDef_TopLevelMessageCount(const upb_FileDef* f);
-int upb_FileDef_TopLevelEnumCount(const upb_FileDef* f);
-int upb_FileDef_TopLevelExtensionCount(const upb_FileDef* f);
-int upb_FileDef_ServiceCount(const upb_FileDef* f);
-const upb_FileDef* upb_FileDef_Dependency(const upb_FileDef* f, int i);
-const upb_FileDef* upb_FileDef_PublicDependency(const upb_FileDef* f, int i);
-const upb_FileDef* upb_FileDef_WeakDependency(const upb_FileDef* f, int i);
-const upb_MessageDef* upb_FileDef_TopLevelMessage(const upb_FileDef* f, int i);
-const upb_EnumDef* upb_FileDef_TopLevelEnum(const upb_FileDef* f, int i);
-const upb_FieldDef* upb_FileDef_TopLevelExtension(const upb_FileDef* f, int i);
-const upb_ServiceDef* upb_FileDef_Service(const upb_FileDef* f, int i);
-const upb_DefPool* upb_FileDef_Pool(const upb_FileDef* f);
-const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f);
-const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f);
-
-/* upb_MethodDef **************************************************************/
-
-const google_protobuf_MethodOptions* upb_MethodDef_Options(
-    const upb_MethodDef* m);
-bool upb_MethodDef_HasOptions(const upb_MethodDef* m);
-const char* upb_MethodDef_FullName(const upb_MethodDef* m);
-int upb_MethodDef_Index(const upb_MethodDef* m);
-const char* upb_MethodDef_Name(const upb_MethodDef* m);
-const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m);
-const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m);
-const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m);
-bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m);
-bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m);
-
-/* upb_ServiceDef *************************************************************/
-
-const google_protobuf_ServiceOptions* upb_ServiceDef_Options(
-    const upb_ServiceDef* s);
-bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s);
-const char* upb_ServiceDef_FullName(const upb_ServiceDef* s);
-const char* upb_ServiceDef_Name(const upb_ServiceDef* s);
-int upb_ServiceDef_Index(const upb_ServiceDef* s);
-const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s);
-int upb_ServiceDef_MethodCount(const upb_ServiceDef* s);
-const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i);
-const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
-                                                     const char* name);
-
-/* upb_DefPool ****************************************************************/
-
-upb_DefPool* upb_DefPool_New(void);
-void upb_DefPool_Free(upb_DefPool* s);
-const upb_MessageDef* upb_DefPool_FindMessageByName(const upb_DefPool* s,
-                                                    const char* sym);
-const upb_MessageDef* upb_DefPool_FindMessageByNameWithSize(
-    const upb_DefPool* s, const char* sym, size_t len);
-const upb_EnumDef* upb_DefPool_FindEnumByName(const upb_DefPool* s,
-                                              const char* sym);
-const upb_EnumValueDef* upb_DefPool_FindEnumByNameval(const upb_DefPool* s,
-                                                      const char* sym);
-const upb_FieldDef* upb_DefPool_FindExtensionByName(const upb_DefPool* s,
-                                                    const char* sym);
-const upb_FieldDef* upb_DefPool_FindExtensionByNameWithSize(
-    const upb_DefPool* s, const char* sym, size_t len);
-const upb_FileDef* upb_DefPool_FindFileByName(const upb_DefPool* s,
-                                              const char* name);
-const upb_ServiceDef* upb_DefPool_FindServiceByName(const upb_DefPool* s,
-                                                    const char* name);
-const upb_ServiceDef* upb_DefPool_FindServiceByNameWithSize(
-    const upb_DefPool* s, const char* name, size_t size);
-const upb_FileDef* upb_DefPool_FindFileContainingSymbol(const upb_DefPool* s,
-                                                        const char* name);
-const upb_FileDef* upb_DefPool_FindFileByNameWithSize(const upb_DefPool* s,
-                                                      const char* name,
-                                                      size_t len);
-const upb_FileDef* upb_DefPool_AddFile(
-    upb_DefPool* s, const google_protobuf_FileDescriptorProto* file,
-    upb_Status* status);
-size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s);
-upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s);
-const upb_FieldDef* _upb_DefPool_FindExtensionByMiniTable(
-    const upb_DefPool* s, const upb_MiniTable_Extension* ext);
-const upb_FieldDef* upb_DefPool_FindExtensionByNumber(const upb_DefPool* s,
-                                                      const upb_MessageDef* m,
-                                                      int32_t fieldnum);
-const upb_ExtensionRegistry* upb_DefPool_ExtensionRegistry(
-    const upb_DefPool* s);
-const upb_FieldDef** upb_DefPool_GetAllExtensions(const upb_DefPool* s,
-                                                  const upb_MessageDef* m,
-                                                  size_t* count);
-
-/* For generated code only: loads a generated descriptor. */
-typedef struct _upb_DefPool_Init {
-  struct _upb_DefPool_Init** deps; /* Dependencies of this file. */
-  const upb_MiniTable_File* layout;
-  const char* filename;
-  upb_StringView descriptor; /* Serialized descriptor. */
-} _upb_DefPool_Init;
-
-// Should only be directly called by tests.  This variant lets us suppress
-// the use of compiled-in tables, forcing a rebuild of the tables at runtime.
-bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
-                                bool rebuild_minitable);
-
-UPB_INLINE bool _upb_DefPool_LoadDefInit(upb_DefPool* s,
-                                         const _upb_DefPool_Init* init) {
-  return _upb_DefPool_LoadDefInitEx(s, init, false);
-}
-
+upb_Syntax upb_MessageDef_Syntax(const upb_MessageDef* m);
+upb_WellKnown upb_MessageDef_WellKnownType(const upb_MessageDef* m);
 
 #ifdef __cplusplus
 } /* extern "C" */
-#endif /* __cplusplus */
+#endif
 
-#endif /* UPB_DEF_H_ */
 
-/** upb/reflection.h ************************************************************/
-#ifndef UPB_REFLECTION_H_
-#define UPB_REFLECTION_H_
+#endif /* UPB_REFLECTION_MESSAGE_DEF_H_ */
 
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_METHOD_DEF_H_
+#define UPB_REFLECTION_METHOD_DEF_H_
+
+
+// Must be last.
 
 #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_Message* msg_val;
-  const upb_Array* array_val;
-  upb_StringView str_val;
-} upb_MessageValue;
+bool upb_MethodDef_ClientStreaming(const upb_MethodDef* m);
+const char* upb_MethodDef_FullName(const upb_MethodDef* m);
+bool upb_MethodDef_HasOptions(const upb_MethodDef* m);
+int upb_MethodDef_Index(const upb_MethodDef* m);
+const upb_MessageDef* upb_MethodDef_InputType(const upb_MethodDef* m);
+const char* upb_MethodDef_Name(const upb_MethodDef* m);
+const google_protobuf_MethodOptions* upb_MethodDef_Options(const upb_MethodDef* m);
+const upb_MessageDef* upb_MethodDef_OutputType(const upb_MethodDef* m);
+bool upb_MethodDef_ServerStreaming(const upb_MethodDef* m);
+const upb_ServiceDef* upb_MethodDef_Service(const upb_MethodDef* m);
 
-typedef union {
-  upb_Map* map;
-  upb_Message* msg;
-  upb_Array* array;
-} upb_MutableMessageValue;
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_METHOD_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ONEOF_DEF_H_
+#define UPB_REFLECTION_ONEOF_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_MessageDef* upb_OneofDef_ContainingType(const upb_OneofDef* o);
+const upb_FieldDef* upb_OneofDef_Field(const upb_OneofDef* o, int i);
+int upb_OneofDef_FieldCount(const upb_OneofDef* o);
+const char* upb_OneofDef_FullName(const upb_OneofDef* o);
+bool upb_OneofDef_HasOptions(const upb_OneofDef* o);
+uint32_t upb_OneofDef_Index(const upb_OneofDef* o);
+bool upb_OneofDef_IsSynthetic(const upb_OneofDef* o);
+const upb_FieldDef* upb_OneofDef_LookupName(const upb_OneofDef* o,
+                                            const char* name);
+const upb_FieldDef* upb_OneofDef_LookupNameWithSize(const upb_OneofDef* o,
+                                                    const char* name,
+                                                    size_t size);
+const upb_FieldDef* upb_OneofDef_LookupNumber(const upb_OneofDef* o,
+                                              uint32_t num);
+const char* upb_OneofDef_Name(const upb_OneofDef* o);
+int upb_OneofDef_numfields(const upb_OneofDef* o);
+const google_protobuf_OneofOptions* upb_OneofDef_Options(const upb_OneofDef* o);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ONEOF_DEF_H_ */
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_SERVICE_DEF_H_
+#define UPB_REFLECTION_SERVICE_DEF_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_FileDef* upb_ServiceDef_File(const upb_ServiceDef* s);
+const upb_MethodDef* upb_ServiceDef_FindMethodByName(const upb_ServiceDef* s,
+                                                     const char* name);
+const char* upb_ServiceDef_FullName(const upb_ServiceDef* s);
+bool upb_ServiceDef_HasOptions(const upb_ServiceDef* s);
+int upb_ServiceDef_Index(const upb_ServiceDef* s);
+const upb_MethodDef* upb_ServiceDef_Method(const upb_ServiceDef* s, int i);
+int upb_ServiceDef_MethodCount(const upb_ServiceDef* s);
+const char* upb_ServiceDef_Name(const upb_ServiceDef* s);
+const google_protobuf_ServiceOptions* upb_ServiceDef_Options(const upb_ServiceDef* s);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_SERVICE_DEF_H_ */
+
+#endif /* UPB_REFLECTION_DEF_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+enum { upb_JsonDecode_IgnoreUnknown = 1 };
+
+bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
+                    const upb_MessageDef* m, const upb_DefPool* symtab,
+                    int options, upb_Arena* arena, upb_Status* status);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_JSONDECODE_H_ */
+
+#ifndef UPB_LEX_ATOI_H_
+#define UPB_LEX_ATOI_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// 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.
+// Return the new position of the pointer after parsing the int, or NULL on
+// integer overflow.
+
+const char* upb_BufToUint64(const char* ptr, const char* end, uint64_t* val);
+const char* upb_BufToInt64(const char* ptr, const char* end, int64_t* val,
+                           bool* is_neg);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_ATOI_H_ */
+
+#ifndef UPB_LEX_UNICODE_H_
+#define UPB_LEX_UNICODE_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Returns true iff a codepoint is the value for a high surrogate.
+UPB_INLINE bool upb_Unicode_IsHigh(uint32_t cp) {
+  return (cp >= 0xd800 && cp <= 0xdbff);
+}
+
+// Returns true iff a codepoint is the value for a low surrogate.
+UPB_INLINE bool upb_Unicode_IsLow(uint32_t cp) {
+  return (cp >= 0xdc00 && cp <= 0xdfff);
+}
+
+// Returns the high 16-bit surrogate value for a supplementary codepoint.
+// Does not sanity-check the input.
+UPB_INLINE uint16_t upb_Unicode_ToHigh(uint32_t cp) {
+  return (cp >> 10) + 0xd7c0;
+}
+
+// Returns the low 16-bit surrogate value for a supplementary codepoint.
+// Does not sanity-check the input.
+UPB_INLINE uint16_t upb_Unicode_ToLow(uint32_t cp) {
+  return (cp & 0x3ff) | 0xdc00;
+}
+
+// Returns the 32-bit value corresponding to a pair of 16-bit surrogates.
+// Does not sanity-check the input.
+UPB_INLINE uint32_t upb_Unicode_FromPair(uint32_t high, uint32_t low) {
+  return ((high & 0x3ff) << 10) + (low & 0x3ff) + 0x10000;
+}
+
+// Outputs a codepoint as UTF8.
+// Returns the number of bytes written (1-4 on success, 0 on error).
+// Does not sanity-check the input. Specifically does not check for surrogates.
+int upb_Unicode_ToUTF8(uint32_t cp, char* out);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_UNICODE_H_ */
+
+#ifndef UPB_REFLECTION_MESSAGE_H_
+#define UPB_REFLECTION_MESSAGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 upb_MessageValue upb_FieldDef_Default(const upb_FieldDef* f);
 
-/** upb_Message
- * *******************************************************************/
-
-/* Creates a new message of the given type in the given arena. */
-upb_Message* upb_Message_New(const upb_MessageDef* m, upb_Arena* a);
-
 /* Returns the value associated with this field. */
 upb_MessageValue upb_Message_Get(const upb_Message* msg, const upb_FieldDef* f);
 
@@ -5418,130 +7667,18 @@
 bool upb_Message_DiscardUnknown(upb_Message* msg, const upb_MessageDef* 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_CType 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_MessageValue 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_MessageValue val);
-
-/* Appends an element to the array.  Returns false on allocation failure. */
-bool upb_Array_Append(upb_Array* array, upb_MessageValue val, upb_Arena* arena);
-
-/* Moves elements within the array using memmove(). Like memmove(), the source
- * and destination elements may be overlapping. */
-void upb_Array_Move(upb_Array* array, size_t dst_idx, size_t src_idx,
-                    size_t count);
-
-/* Inserts one or more empty elements into the array.  Existing elements are
- * shifted right.  The new elements have undefined state and must be set with
- * `upb_Array_Set()`.
- * REQUIRES: `i <= upb_Array_Size(arr)` */
-bool upb_Array_Insert(upb_Array* array, size_t i, size_t count,
-                      upb_Arena* arena);
-
-/* Deletes one or more elements from the array.  Existing elements are shifted
- * left.
- * REQUIRES: `i + count <= upb_Array_Size(arr)` */
-void upb_Array_Delete(upb_Array* array, size_t i, size_t count);
-
-/* 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_CType key_type, upb_CType 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_MessageValue key,
-                 upb_MessageValue* 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_MessageValue key, upb_MessageValue 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_MessageValue key);
-
-/* Map iteration:
- *
- * size_t iter = kUpb_Map_Begin;
- * while (upb_MapIterator_Next(map, &iter)) {
- *   upb_MessageValue key = upb_MapIterator_Key(map, iter);
- *   upb_MessageValue val = upb_MapIterator_Value(map, iter);
- *
- *   // If mutating is desired.
- *   upb_MapIterator_SetValue(map, iter, value2);
- * }
- */
-
-/* Advances to the next entry.  Returns false if no more entries are present. */
-bool upb_MapIterator_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
- * kUpb_Map_Begin (you must call next() at least once first). */
-bool upb_MapIterator_Done(const upb_Map* map, size_t iter);
-
-/* Returns the key and value for this entry of the map. */
-upb_MessageValue upb_MapIterator_Key(const upb_Map* map, size_t iter);
-upb_MessageValue upb_MapIterator_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_MapIterator_SetValue(upb_Map* map, size_t iter,
-                              upb_MessageValue value);
-
 #ifdef __cplusplus
 } /* extern "C" */
 #endif
 
 
-#endif /* UPB_REFLECTION_H_ */
+#endif /* UPB_REFLECTION_MESSAGE_H_ */
 
-/** upb/json_decode.h ************************************************************/
-#ifndef UPB_JSONDECODE_H_
-#define UPB_JSONDECODE_H_
+#ifndef UPB_JSON_ENCODE_H_
+#define UPB_JSON_ENCODE_H_
 
 
-#ifdef __cplusplus
-extern "C" {
-#endif
-
-enum { upb_JsonDecode_IgnoreUnknown = 1 };
-
-bool upb_JsonDecode(const char* buf, size_t size, upb_Message* msg,
-                    const upb_MessageDef* m, const upb_DefPool* symtab,
-                    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_
-
+// Must be last.
 
 #ifdef __cplusplus
 extern "C" {
@@ -5549,11 +7686,14 @@
 
 enum {
   /* When set, emits 0/default values.  TODO(haberman): proto3 only? */
-  upb_JsonEncode_EmitDefaults = 1,
+  upb_JsonEncode_EmitDefaults = 1 << 0,
 
-  /* When set, use normal (snake_caes) field names instead of JSON (camelCase)
+  /* When set, use normal (snake_case) field names instead of JSON (camelCase)
      names. */
-  upb_JsonEncode_UseProtoNames = 2
+  upb_JsonEncode_UseProtoNames = 1 << 1,
+
+  /* When set, emits enums as their integer values instead of as their names. */
+  upb_JsonEncode_FormatEnumsAsIntegers = 1 << 2
 };
 
 /* Encodes the given |msg| to JSON format.  The message's reflection is given in
@@ -5572,10 +7712,1200 @@
 } /* extern "C" */
 #endif
 
+
 #endif /* UPB_JSONENCODE_H_ */
 
-/** upb/port_undef.inc ************************************************************/
-/* See port_def.inc.  This should #undef all macros #defined there. */
+#ifndef UPB_LEX_ROUND_TRIP_H_
+#define UPB_LEX_ROUND_TRIP_H_
+
+// Must be last.
+
+// Encodes a float or double that is round-trippable, but as short as possible.
+// These routines are not fully optimal (not guaranteed to be shortest), but are
+// short-ish and match the implementation that has been used in protobuf since
+// the beginning.
+
+// The given buffer size must be at least kUpb_RoundTripBufferSize.
+enum { kUpb_RoundTripBufferSize = 32 };
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+void _upb_EncodeRoundTripDouble(double val, char* buf, size_t size);
+void _upb_EncodeRoundTripFloat(float val, char* buf, size_t size);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_ROUND_TRIP_H_ */
+
+#ifndef UPB_PORT_VSNPRINTF_COMPAT_H_
+#define UPB_PORT_VSNPRINTF_COMPAT_H_
+
+// Must be last.
+
+UPB_INLINE int _upb_vsnprintf(char* buf, size_t size, const char* fmt,
+                              va_list ap) {
+#if defined(__MINGW64__) || defined(__MINGW32__) || defined(_MSC_VER)
+  // The msvc runtime has a non-conforming vsnprintf() that requires the
+  // following compatibility code to become conformant.
+  int n = -1;
+  if (size != 0) n = _vsnprintf_s(buf, size, _TRUNCATE, fmt, ap);
+  if (n == -1) n = _vscprintf(fmt, ap);
+  return n;
+#else
+  return vsnprintf(buf, size, fmt, ap);
+#endif
+}
+
+
+#endif  // UPB_PORT_VSNPRINTF_COMPAT_H_
+
+#ifndef UPB_LEX_STRTOD_H_
+#define UPB_LEX_STRTOD_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+double _upb_NoLocaleStrtod(const char *str, char **endptr);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_LEX_STRTOD_H_ */
+
+#ifndef UPB_MEM_ARENA_INTERNAL_H_
+#define UPB_MEM_ARENA_INTERNAL_H_
+
+
+// Must be last.
+
+typedef struct _upb_MemBlock _upb_MemBlock;
+
+struct upb_Arena {
+  _upb_ArenaHead 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. */
+  _upb_MemBlock *freelist, *freelist_tail;
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MEM_ARENA_INTERNAL_H_ */
+
+#ifndef UPB_WIRE_TYPES_H_
+#define UPB_WIRE_TYPES_H_
+
+// A list of types as they are encoded on the wire.
+typedef enum {
+  kUpb_WireType_Varint = 0,
+  kUpb_WireType_64Bit = 1,
+  kUpb_WireType_Delimited = 2,
+  kUpb_WireType_StartGroup = 3,
+  kUpb_WireType_EndGroup = 4,
+  kUpb_WireType_32Bit = 5
+} upb_WireType;
+
+#endif /* UPB_WIRE_TYPES_H_ */
+
+#ifndef UPB_MINI_TABLE_COMMON_INTERNAL_H_
+#define UPB_MINI_TABLE_COMMON_INTERNAL_H_
+
+
+// Must be last.
+
+typedef enum {
+  kUpb_EncodedType_Double = 0,
+  kUpb_EncodedType_Float = 1,
+  kUpb_EncodedType_Fixed32 = 2,
+  kUpb_EncodedType_Fixed64 = 3,
+  kUpb_EncodedType_SFixed32 = 4,
+  kUpb_EncodedType_SFixed64 = 5,
+  kUpb_EncodedType_Int32 = 6,
+  kUpb_EncodedType_UInt32 = 7,
+  kUpb_EncodedType_SInt32 = 8,
+  kUpb_EncodedType_Int64 = 9,
+  kUpb_EncodedType_UInt64 = 10,
+  kUpb_EncodedType_SInt64 = 11,
+  kUpb_EncodedType_OpenEnum = 12,
+  kUpb_EncodedType_Bool = 13,
+  kUpb_EncodedType_Bytes = 14,
+  kUpb_EncodedType_String = 15,
+  kUpb_EncodedType_Group = 16,
+  kUpb_EncodedType_Message = 17,
+  kUpb_EncodedType_ClosedEnum = 18,
+
+  kUpb_EncodedType_RepeatedBase = 20,
+} upb_EncodedType;
+
+typedef enum {
+  kUpb_EncodedFieldModifier_FlipPacked = 1 << 0,
+  kUpb_EncodedFieldModifier_IsRequired = 1 << 1,
+  kUpb_EncodedFieldModifier_IsProto3Singular = 1 << 2,
+} upb_EncodedFieldModifier;
+
+enum {
+  kUpb_EncodedValue_MinField = ' ',
+  kUpb_EncodedValue_MaxField = 'I',
+  kUpb_EncodedValue_MinModifier = 'L',
+  kUpb_EncodedValue_MaxModifier = '[',
+  kUpb_EncodedValue_End = '^',
+  kUpb_EncodedValue_MinSkip = '_',
+  kUpb_EncodedValue_MaxSkip = '~',
+  kUpb_EncodedValue_OneofSeparator = '~',
+  kUpb_EncodedValue_FieldSeparator = '|',
+  kUpb_EncodedValue_MinOneofField = ' ',
+  kUpb_EncodedValue_MaxOneofField = 'b',
+  kUpb_EncodedValue_MaxEnumMask = 'A',
+};
+
+enum {
+  kUpb_EncodedVersion_EnumV1 = '!',
+  kUpb_EncodedVersion_ExtensionV1 = '#',
+  kUpb_EncodedVersion_MapV1 = '%',
+  kUpb_EncodedVersion_MessageV1 = '$',
+  kUpb_EncodedVersion_MessageSetV1 = '&',
+};
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE char _upb_ToBase92(int8_t ch) {
+  extern const char _kUpb_ToBase92[];
+  UPB_ASSERT(0 <= ch && ch < 92);
+  return _kUpb_ToBase92[ch];
+}
+
+UPB_INLINE char _upb_FromBase92(uint8_t ch) {
+  extern const int8_t _kUpb_FromBase92[];
+  if (' ' > ch || ch > '~') return -1;
+  return _kUpb_FromBase92[ch - ' '];
+}
+
+UPB_INLINE bool _upb_FieldType_IsPackable(upb_FieldType type) {
+  // clang-format off
+  const unsigned kUnpackableTypes =
+      (1 << kUpb_FieldType_String) |
+      (1 << kUpb_FieldType_Bytes) |
+      (1 << kUpb_FieldType_Message) |
+      (1 << kUpb_FieldType_Group);
+  // clang-format on
+  return (1 << type) & ~kUnpackableTypes;
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_COMMON_INTERNAL_H_ */
+
+#ifndef UPB_MINI_TABLE_DECODE_H_
+#define UPB_MINI_TABLE_DECODE_H_
+
+
+// Must be last.
+
+typedef enum {
+  kUpb_MiniTablePlatform_32Bit,
+  kUpb_MiniTablePlatform_64Bit,
+  kUpb_MiniTablePlatform_Native =
+      UPB_SIZE(kUpb_MiniTablePlatform_32Bit, kUpb_MiniTablePlatform_64Bit),
+} upb_MiniTablePlatform;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Builds a mini table from the data encoded in the buffer [data, len]. If any
+// errors occur, returns NULL and sets a status message. In the success case,
+// the caller must call upb_MiniTable_SetSub*() for all message or proto2 enum
+// fields to link the table to the appropriate sub-tables.
+upb_MiniTable* _upb_MiniTable_Build(const char* data, size_t len,
+                                    upb_MiniTablePlatform platform,
+                                    upb_Arena* arena, upb_Status* status);
+
+UPB_INLINE upb_MiniTable* upb_MiniTable_Build(const char* data, size_t len,
+                                              upb_Arena* arena,
+                                              upb_Status* status) {
+  return _upb_MiniTable_Build(data, len, kUpb_MiniTablePlatform_Native, arena,
+                              status);
+}
+
+// Links a sub-message field to a MiniTable for that sub-message.  If a
+// sub-message field is not linked, it will be treated as an unknown field
+// during parsing, and setting the field will not be allowed.  It is possible
+// to link the message field later, at which point it will no longer be treated
+// as unknown.  However there is no synchronization for this operation, which
+// means parallel mutation requires external synchronization.
+void upb_MiniTable_SetSubMessage(upb_MiniTable* table,
+                                 upb_MiniTableField* field,
+                                 const upb_MiniTable* sub);
+
+// Links an enum field to a MiniTable for that enum.  All enum fields must
+// be linked prior to parsing.
+void upb_MiniTable_SetSubEnum(upb_MiniTable* table, upb_MiniTableField* field,
+                              const upb_MiniTableEnum* sub);
+
+const char* _upb_MiniTableExtension_Build(const char* data, size_t len,
+                                          upb_MiniTableExtension* ext,
+                                          const upb_MiniTable* extendee,
+                                          upb_MiniTableSub sub,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Status* status);
+
+UPB_INLINE const char* upb_MiniTableExtension_Build(
+    const char* data, size_t len, upb_MiniTableExtension* ext,
+    const upb_MiniTable* extendee, upb_MiniTableSub sub, upb_Status* status) {
+  return _upb_MiniTableExtension_Build(data, len, ext, extendee, sub,
+                                       kUpb_MiniTablePlatform_Native, status);
+}
+
+upb_MiniTableEnum* upb_MiniTableEnum_Build(const char* data, size_t len,
+                                           upb_Arena* arena,
+                                           upb_Status* status);
+
+// Like upb_MiniTable_Build(), but the user provides a buffer of layout data so
+// it can be reused from call to call, avoiding repeated realloc()/free().
+//
+// The caller owns `*buf` both before and after the call, and must free() it
+// when it is no longer in use.  The function will realloc() `*buf` as
+// necessary, updating `*size` accordingly.
+upb_MiniTable* upb_MiniTable_BuildWithBuf(const char* data, size_t len,
+                                          upb_MiniTablePlatform platform,
+                                          upb_Arena* arena, void** buf,
+                                          size_t* buf_size, upb_Status* status);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_DECODE_H_ */
+
+#ifndef UPB_MINI_TABLE_ENCODE_INTERNAL_H_
+#define UPB_MINI_TABLE_ENCODE_INTERNAL_H_
+
+
+// Must be last.
+
+// If the input buffer has at least this many bytes available, the encoder call
+// is guaranteed to succeed (as long as field number order is maintained).
+#define kUpb_MtDataEncoder_MinSize 16
+
+typedef struct {
+  char* end;  // Limit of the buffer passed as a parameter.
+  // Aliased to internal-only members in .cc.
+  char internal[32];
+} upb_MtDataEncoder;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+// Encodes field/oneof information for a given message.  The sequence of calls
+// should look like:
+//
+//   upb_MtDataEncoder e;
+//   char buf[256];
+//   char* ptr = buf;
+//   e.end = ptr + sizeof(buf);
+//   unit64_t msg_mod = ...; // bitwise & of kUpb_MessageModifiers or zero
+//   ptr = upb_MtDataEncoder_StartMessage(&e, ptr, msg_mod);
+//   // Fields *must* be in field number order.
+//   ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+//   ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+//   ptr = upb_MtDataEncoder_PutField(&e, ptr, ...);
+//
+//   // If oneofs are present.  Oneofs must be encoded after regular fields.
+//   ptr = upb_MiniTable_StartOneof(&e, ptr)
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//
+//   ptr = upb_MiniTable_StartOneof(&e, ptr);
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//   ptr = upb_MiniTable_PutOneofField(&e, ptr, ...);
+//
+// Oneofs must be encoded after all regular fields.
+char* upb_MtDataEncoder_StartMessage(upb_MtDataEncoder* e, char* ptr,
+                                     uint64_t msg_mod);
+char* upb_MtDataEncoder_PutField(upb_MtDataEncoder* e, char* ptr,
+                                 upb_FieldType type, uint32_t field_num,
+                                 uint64_t field_mod);
+char* upb_MtDataEncoder_StartOneof(upb_MtDataEncoder* e, char* ptr);
+char* upb_MtDataEncoder_PutOneofField(upb_MtDataEncoder* e, char* ptr,
+                                      uint32_t field_num);
+
+// Encodes the set of values for a given enum. The values must be given in
+// order (after casting to uint32_t), and repeats are not allowed.
+char* upb_MtDataEncoder_StartEnum(upb_MtDataEncoder* e, char* ptr);
+char* upb_MtDataEncoder_PutEnumValue(upb_MtDataEncoder* e, char* ptr,
+                                     uint32_t val);
+char* upb_MtDataEncoder_EndEnum(upb_MtDataEncoder* e, char* ptr);
+
+// Encodes an entire mini descriptor for an extension.
+char* upb_MtDataEncoder_EncodeExtension(upb_MtDataEncoder* e, char* ptr,
+                                        upb_FieldType type, uint32_t field_num,
+                                        uint64_t field_mod);
+
+// Encodes an entire mini descriptor for a map.
+char* upb_MtDataEncoder_EncodeMap(upb_MtDataEncoder* e, char* ptr,
+                                  upb_FieldType key_type,
+                                  upb_FieldType value_type, uint64_t key_mod,
+                                  uint64_t value_mod);
+
+// Encodes an entire mini descriptor for a message set.
+char* upb_MtDataEncoder_EncodeMessageSet(upb_MtDataEncoder* e, char* ptr);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_MINI_TABLE_ENCODE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_DEF_BUILDER_INTERNAL_H_
+#define UPB_REFLECTION_DEF_BUILDER_INTERNAL_H_
+
+
+#ifndef UPB_REFLECTION_DEF_POOL_INTERNAL_H_
+#define UPB_REFLECTION_DEF_POOL_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_Arena* _upb_DefPool_Arena(const upb_DefPool* s);
+size_t _upb_DefPool_BytesLoaded(const upb_DefPool* s);
+upb_ExtensionRegistry* _upb_DefPool_ExtReg(const upb_DefPool* s);
+
+bool _upb_DefPool_InsertExt(upb_DefPool* s, const upb_MiniTableExtension* ext,
+                            upb_FieldDef* f);
+bool _upb_DefPool_InsertSym(upb_DefPool* s, upb_StringView sym, upb_value v,
+                            upb_Status* status);
+bool _upb_DefPool_LookupSym(const upb_DefPool* s, const char* sym, size_t size,
+                            upb_value* v);
+
+void** _upb_DefPool_ScratchData(const upb_DefPool* s);
+size_t* _upb_DefPool_ScratchSize(const upb_DefPool* s);
+
+// For generated code only: loads a generated descriptor.
+typedef struct _upb_DefPool_Init {
+  struct _upb_DefPool_Init** deps;  // Dependencies of this file.
+  const upb_MiniTableFile* layout;
+  const char* filename;
+  upb_StringView descriptor;  // Serialized descriptor.
+} _upb_DefPool_Init;
+
+bool _upb_DefPool_LoadDefInit(upb_DefPool* s, const _upb_DefPool_Init* init);
+
+// Should only be directly called by tests. This variant lets us suppress
+// the use of compiled-in tables, forcing a rebuild of the tables at runtime.
+bool _upb_DefPool_LoadDefInitEx(upb_DefPool* s, const _upb_DefPool_Init* init,
+                                bool rebuild_minitable);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_POOL_INTERNAL_H_ */
+
+// Must be last.
+
+// We want to copy the options verbatim into the destination options proto.
+// We use serialize+parse as our deep copy.
+#define UPB_DEF_SET_OPTIONS(target, desc_type, options_type, proto)          \
+  if (google_protobuf_##desc_type##_has_options(proto)) {                             \
+    size_t size;                                                             \
+    char* pb = google_protobuf_##options_type##_serialize(                            \
+        google_protobuf_##desc_type##_options(proto), ctx->tmp_arena, &size);         \
+    if (!pb) _upb_DefBuilder_OomErr(ctx);                                    \
+    target =                                                                 \
+        google_protobuf_##options_type##_parse(pb, size, _upb_DefBuilder_Arena(ctx)); \
+    if (!target) _upb_DefBuilder_OomErr(ctx);                                \
+  } else {                                                                   \
+    target = (const google_protobuf_##options_type*)kUpbDefOptDefault;                \
+  }
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+struct upb_DefBuilder {
+  upb_DefPool* symtab;
+  upb_FileDef* file;                 // File we are building.
+  upb_Arena* arena;                  // Allocate defs here.
+  upb_Arena* tmp_arena;              // For temporary allocations.
+  upb_Status* status;                // Record errors here.
+  const upb_MiniTableFile* layout;   // NULL if we should build layouts.
+  int enum_count;                    // Count of enums built so far.
+  int msg_count;                     // Count of messages built so far.
+  int ext_count;                     // Count of extensions built so far.
+  jmp_buf err;                       // longjmp() on error.
+};
+
+extern const char* kUpbDefOptDefault;
+
+// ctx->status has already been set elsewhere so just fail/longjmp()
+UPB_NORETURN void _upb_DefBuilder_FailJmp(upb_DefBuilder* ctx);
+
+UPB_NORETURN void _upb_DefBuilder_Errf(upb_DefBuilder* ctx, const char* fmt,
+                                       ...) UPB_PRINTF(2, 3);
+UPB_NORETURN void _upb_DefBuilder_OomErr(upb_DefBuilder* ctx);
+
+const char* _upb_DefBuilder_MakeFullName(upb_DefBuilder* ctx,
+                                         const char* prefix,
+                                         upb_StringView name);
+
+// Given a symbol and the base symbol inside which it is defined,
+// find the symbol's definition.
+const void* _upb_DefBuilder_ResolveAny(upb_DefBuilder* ctx,
+                                       const char* from_name_dbg,
+                                       const char* base, upb_StringView sym,
+                                       upb_deftype_t* type);
+
+const void* _upb_DefBuilder_Resolve(upb_DefBuilder* ctx,
+                                    const char* from_name_dbg, const char* base,
+                                    upb_StringView sym, upb_deftype_t type);
+
+char _upb_DefBuilder_ParseEscape(upb_DefBuilder* ctx, const upb_FieldDef* f,
+                                 const char** src, const char* end);
+
+const char* _upb_DefBuilder_FullToShort(const char* fullname);
+
+UPB_INLINE void* _upb_DefBuilder_Alloc(upb_DefBuilder* ctx, size_t bytes) {
+  if (bytes == 0) return NULL;
+  void* ret = upb_Arena_Malloc(ctx->arena, bytes);
+  if (!ret) _upb_DefBuilder_OomErr(ctx);
+  return ret;
+}
+
+// Adds a symbol |v| to the symtab, which must be a def pointer previously
+// packed with pack_def(). The def's pointer to upb_FileDef* must be set before
+// adding, so we know which entries to remove if building this file fails.
+UPB_INLINE void _upb_DefBuilder_Add(upb_DefBuilder* ctx, const char* name,
+                                    upb_value v) {
+  upb_StringView sym = {.data = name, .size = strlen(name)};
+  bool ok = _upb_DefPool_InsertSym(ctx->symtab, sym, v, ctx->status);
+  if (!ok) _upb_DefBuilder_FailJmp(ctx);
+}
+
+UPB_INLINE upb_Arena* _upb_DefBuilder_Arena(const upb_DefBuilder* ctx) {
+  return ctx->arena;
+}
+
+UPB_INLINE upb_FileDef* _upb_DefBuilder_File(const upb_DefBuilder* ctx) {
+  return ctx->file;
+}
+
+// This version of CheckIdent() is only called by other, faster versions after
+// they detect a parsing error.
+void _upb_DefBuilder_CheckIdentSlow(upb_DefBuilder* ctx, upb_StringView name,
+                                    bool full);
+
+// Verify a relative identifier string. The loop is branchless for speed.
+UPB_INLINE void _upb_DefBuilder_CheckIdentNotFull(upb_DefBuilder* ctx,
+                                                  upb_StringView name) {
+  bool good = name.size > 0;
+
+  for (size_t i = 0; i < name.size; i++) {
+    const char c = name.data[i];
+    const char d = c | 0x20;  // force lowercase
+    const bool is_alpha = (('a' <= d) & (d <= 'z')) | (c == '_');
+    const bool is_numer = ('0' <= c) & (c <= '9') & (i != 0);
+
+    good &= is_alpha | is_numer;
+  }
+
+  if (!good) _upb_DefBuilder_CheckIdentSlow(ctx, name, false);
+}
+
+// Verify a full identifier string. This is slightly more complicated than
+// verifying a relative identifier string because we must track '.' chars.
+UPB_INLINE void _upb_DefBuilder_CheckIdentFull(upb_DefBuilder* ctx,
+                                               upb_StringView name) {
+  bool good = name.size > 0;
+  bool start = true;
+
+  for (size_t i = 0; i < name.size; i++) {
+    const char c = name.data[i];
+    const char d = c | 0x20;  // force lowercase
+    const bool is_alpha = (('a' <= d) & (d <= 'z')) | (c == '_');
+    const bool is_numer = ('0' <= c) & (c <= '9') & !start;
+    const bool is_dot = (c == '.') & !start;
+
+    good &= is_alpha | is_numer | is_dot;
+    start = is_dot;
+  }
+
+  if (!good) _upb_DefBuilder_CheckIdentSlow(ctx, name, true);
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DEF_BUILDER_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ENUM_DEF_INTERNAL_H_
+#define UPB_REFLECTION_ENUM_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_EnumDef* _upb_EnumDef_At(const upb_EnumDef* e, int i);
+bool _upb_EnumDef_Insert(upb_EnumDef* e, upb_EnumValueDef* v, upb_Arena* a);
+const upb_MiniTableEnum* _upb_EnumDef_MiniTable(const upb_EnumDef* e);
+
+// Allocate and initialize an array of |n| enum defs.
+upb_EnumDef* _upb_EnumDefs_New(upb_DefBuilder* ctx, int n,
+                               const google_protobuf_EnumDescriptorProto* const* protos,
+                               const upb_MessageDef* containing_type);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ENUM_VALUE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_ENUM_VALUE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_EnumValueDef* _upb_EnumValueDef_At(const upb_EnumValueDef* v, int i);
+
+// Allocate and initialize an array of |n| enum value defs owned by |e|.
+upb_EnumValueDef* _upb_EnumValueDefs_New(
+    upb_DefBuilder* ctx, const char* prefix, int n,
+    const google_protobuf_EnumValueDescriptorProto* const* protos, upb_EnumDef* e,
+    bool* is_sorted);
+
+const upb_EnumValueDef** _upb_EnumValueDefs_Sorted(const upb_EnumValueDef* v,
+                                                   int n, upb_Arena* a);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_VALUE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_FIELD_DEF_INTERNAL_H_
+#define UPB_REFLECTION_FIELD_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_FieldDef* _upb_FieldDef_At(const upb_FieldDef* f, int i);
+
+const upb_MiniTableExtension* _upb_FieldDef_ExtensionMiniTable(
+    const upb_FieldDef* f);
+bool _upb_FieldDef_IsClosedEnum(const upb_FieldDef* f);
+bool _upb_FieldDef_IsProto3Optional(const upb_FieldDef* f);
+int _upb_FieldDef_LayoutIndex(const upb_FieldDef* f);
+uint64_t _upb_FieldDef_Modifiers(const upb_FieldDef* f);
+void _upb_FieldDef_Resolve(upb_DefBuilder* ctx, const char* prefix,
+                           upb_FieldDef* f);
+
+// Allocate and initialize an array of |n| field defs.
+upb_FieldDef* _upb_FieldDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_FieldDescriptorProto* const* protos, const char* prefix,
+    upb_MessageDef* m, bool* is_sorted);
+
+// Allocate and return a list of pointers to the |n| field defs in |ff|,
+// sorted by field number.
+const upb_FieldDef** _upb_FieldDefs_Sorted(const upb_FieldDef* f, int n,
+                                           upb_Arena* a);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FIELD_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_FILE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_FILE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+const upb_MiniTableExtension* _upb_FileDef_ExtensionMiniTable(
+    const upb_FileDef* f, int i);
+const int32_t* _upb_FileDef_PublicDependencyIndexes(const upb_FileDef* f);
+const int32_t* _upb_FileDef_WeakDependencyIndexes(const upb_FileDef* f);
+
+// upb_FileDef_Package() returns "" if f->package is NULL, this does not.
+const char* _upb_FileDef_RawPackage(const upb_FileDef* f);
+
+void _upb_FileDef_Create(upb_DefBuilder* ctx,
+                         const google_protobuf_FileDescriptorProto* file_proto);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_FILE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_MESSAGE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_MESSAGE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_MessageDef* _upb_MessageDef_At(const upb_MessageDef* m, int i);
+bool _upb_MessageDef_InMessageSet(const upb_MessageDef* m);
+bool _upb_MessageDef_Insert(upb_MessageDef* m, const char* name, size_t size,
+                            upb_value v, upb_Arena* a);
+void _upb_MessageDef_InsertField(upb_DefBuilder* ctx, upb_MessageDef* m,
+                                 const upb_FieldDef* f);
+bool _upb_MessageDef_IsValidExtensionNumber(const upb_MessageDef* m, int n);
+void _upb_MessageDef_LinkMiniTable(upb_DefBuilder* ctx,
+                                   const upb_MessageDef* m);
+void _upb_MessageDef_Resolve(upb_DefBuilder* ctx, upb_MessageDef* m);
+
+// Allocate and initialize an array of |n| message defs.
+upb_MessageDef* _upb_MessageDefs_New(
+    upb_DefBuilder* ctx, int n, const google_protobuf_DescriptorProto* const* protos,
+    const upb_MessageDef* containing_type);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_MESSAGE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_SERVICE_DEF_INTERNAL_H_
+#define UPB_REFLECTION_SERVICE_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_ServiceDef* _upb_ServiceDef_At(const upb_ServiceDef* s, int i);
+
+// Allocate and initialize an array of |n| service defs.
+upb_ServiceDef* _upb_ServiceDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_ServiceDescriptorProto* const* protos);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_SERVICE_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_DESC_STATE_INTERNAL_H_
+#define UPB_REFLECTION_DESC_STATE_INTERNAL_H_
+
+
+// Must be last.
+
+// Manages the storage for mini descriptor strings as they are being encoded.
+// TODO(b/234740652): Move some of this state directly into the encoder, maybe.
+typedef struct {
+  upb_MtDataEncoder e;
+  size_t bufsize;
+  char* buf;
+  char* ptr;
+} upb_DescState;
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE void _upb_DescState_Init(upb_DescState* d) {
+  d->bufsize = kUpb_MtDataEncoder_MinSize * 2;
+  d->buf = NULL;
+  d->ptr = NULL;
+}
+
+bool _upb_DescState_Grow(upb_DescState* d, upb_Arena* a);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_DESC_STATE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ENUM_RESERVED_RANGE_INTERNAL_H_
+#define UPB_REFLECTION_ENUM_RESERVED_RANGE_INTERNAL_H_
+
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_ENUM_RESERVED_RANGE_H_
+#define UPB_REFLECTION_ENUM_RESERVED_RANGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t upb_EnumReservedRange_Start(const upb_EnumReservedRange* r);
+int32_t upb_EnumReservedRange_End(const upb_EnumReservedRange* r);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_RESERVED_RANGE_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_EnumReservedRange* _upb_EnumReservedRange_At(const upb_EnumReservedRange* r,
+                                                 int i);
+
+// Allocate and initialize an array of |n| reserved ranges owned by |e|.
+upb_EnumReservedRange* _upb_EnumReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_EnumDescriptorProto_EnumReservedRange* const* protos,
+    const upb_EnumDef* e);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ENUM_RESERVED_RANGE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_
+#define UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_ExtensionRange* _upb_ExtensionRange_At(const upb_ExtensionRange* r, int i);
+
+// Allocate and initialize an array of |n| extension ranges owned by |m|.
+upb_ExtensionRange* _upb_ExtensionRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ExtensionRange* const* protos,
+    const upb_MessageDef* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_EXTENSION_RANGE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_ONEOF_DEF_INTERNAL_H_
+#define UPB_REFLECTION_ONEOF_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_OneofDef* _upb_OneofDef_At(const upb_OneofDef* o, int i);
+bool _upb_OneofDef_Insert(upb_OneofDef* o, const upb_FieldDef* f,
+                          const char* name, size_t size, upb_Arena* a);
+
+// Allocate and initialize an array of |n| oneof defs owned by |m|.
+upb_OneofDef* _upb_OneofDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_OneofDescriptorProto* const* protos, upb_MessageDef* m);
+
+size_t _upb_OneofDefs_Finalize(upb_DefBuilder* ctx, upb_MessageDef* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_ONEOF_DEF_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_MESSAGE_RESERVED_RANGE_INTERNAL_H_
+#define UPB_REFLECTION_MESSAGE_RESERVED_RANGE_INTERNAL_H_
+
+
+// IWYU pragma: private, include "upb/reflection/def.h"
+
+#ifndef UPB_REFLECTION_MESSAGE_RESERVED_RANGE_H_
+#define UPB_REFLECTION_MESSAGE_RESERVED_RANGE_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+int32_t upb_MessageReservedRange_Start(const upb_MessageReservedRange* r);
+int32_t upb_MessageReservedRange_End(const upb_MessageReservedRange* r);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_MESSAGE_RESERVED_RANGE_H_ */
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_MessageReservedRange* _upb_MessageReservedRange_At(
+    const upb_MessageReservedRange* r, int i);
+
+// Allocate and initialize an array of |n| reserved ranges owned by |m|.
+upb_MessageReservedRange* _upb_MessageReservedRanges_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_DescriptorProto_ReservedRange* const* protos,
+    const upb_MessageDef* m);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_MESSAGE_RESERVED_RANGE_INTERNAL_H_ */
+
+#ifndef UPB_REFLECTION_METHOD_DEF_INTERNAL_H_
+#define UPB_REFLECTION_METHOD_DEF_INTERNAL_H_
+
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+upb_MethodDef* _upb_MethodDef_At(const upb_MethodDef* m, int i);
+
+// Allocate and initialize an array of |n| method defs owned by |s|.
+upb_MethodDef* _upb_MethodDefs_New(
+    upb_DefBuilder* ctx, int n,
+    const google_protobuf_MethodDescriptorProto* const* protos, upb_ServiceDef* s);
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_REFLECTION_METHOD_DEF_INTERNAL_H_ */
+
+#ifndef UPB_WIRE_COMMON_INTERNAL_H_
+#define UPB_WIRE_COMMON_INTERNAL_H_
+
+// Must be last.
+
+// MessageSet wire format is:
+//   message MessageSet {
+//     repeated group Item = 1 {
+//       required int32 type_id = 2;
+//       required bytes message = 3;
+//     }
+//   }
+
+enum {
+  kUpb_MsgSet_Item = 1,
+  kUpb_MsgSet_TypeId = 2,
+  kUpb_MsgSet_Message = 3,
+};
+
+
+#endif /* UPB_WIRE_COMMON_INTERNAL_H_ */
+
+/*
+ * Internal implementation details of the decoder that are shared between
+ * decode.c and decode_fast.c.
+ */
+
+#ifndef UPB_WIRE_DECODE_INTERNAL_H_
+#define UPB_WIRE_DECODE_INTERNAL_H_
+
+#include "third_party/utf8_range/utf8_range.h"
+
+// Must be last.
+
+#define DECODE_NOGROUP (uint32_t) - 1
+
+typedef struct upb_Decoder {
+  const char* end;          /* Can read up to 16 bytes slop beyond this. */
+  const char* limit_ptr;    /* = end + UPB_MIN(limit, 0) */
+  upb_Message* unknown_msg; /* Used for preserving unknown data. */
+  const char* unknown; /* Start of unknown data, preserve at buffer flip. */
+  const upb_ExtensionRegistry*
+      extreg;         /* For looking up extensions during the parse. */
+  int limit;          /* Submessage limit relative to end. */
+  int depth;          /* Tracks recursion depth to bound stack usage. */
+  uint32_t end_group; /* field number of END_GROUP tag, else DECODE_NOGROUP */
+  uint16_t options;
+  bool missing_required;
+  char patch[32];
+  upb_Arena arena;
+  jmp_buf err;
+
+#ifndef NDEBUG
+  const char* debug_tagstart;
+  const char* debug_valstart;
+#endif
+} upb_Decoder;
+
+/* 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* _upb_FastDecoder_ErrorJmp(upb_Decoder* d, int status);
+
+extern const uint8_t upb_utf8_offsets[];
+
+UPB_INLINE
+bool _upb_Decoder_VerifyUtf8Inline(const char* ptr, int len) {
+  const char* end = ptr + len;
+
+  // Check 8 bytes at a time for any non-ASCII char.
+  while (end - ptr >= 8) {
+    uint64_t data;
+    memcpy(&data, ptr, 8);
+    if (data & 0x8080808080808080) goto non_ascii;
+    ptr += 8;
+  }
+
+  // Check one byte at a time for non-ASCII.
+  while (ptr < end) {
+    if (*ptr & 0x80) goto non_ascii;
+    ptr++;
+  }
+
+  return true;
+
+non_ascii:
+  return utf8_range2((const unsigned char*)ptr, end - ptr) == 0;
+}
+
+const char* _upb_Decoder_CheckRequired(upb_Decoder* d, const char* ptr,
+                                       const upb_Message* msg,
+                                       const upb_MiniTable* l);
+
+/* 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_MiniTable* tablep) {
+  return ((intptr_t)tablep << 8) | tablep->table_mask;
+}
+
+UPB_INLINE const upb_MiniTable* decode_totablep(intptr_t table) {
+  return (const upb_MiniTable*)(table >> 8);
+}
+
+UPB_INLINE
+const char* _upb_Decoder_IsDoneFallbackInline(upb_Decoder* d, const char* ptr,
+                                              int overrun, int* status) {
+  if (overrun < d->limit) {
+    /* Need to copy remaining data into patch buffer. */
+    UPB_ASSERT(overrun < 16);
+    if (d->unknown) {
+      if (!_upb_Message_AddUnknown(d->unknown_msg, d->unknown, ptr - d->unknown,
+                                   &d->arena)) {
+        *status = kUpb_DecodeStatus_OutOfMemory;
+        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->options &= ~kUpb_DecodeOption_AliasString;
+    UPB_ASSERT(ptr < d->limit_ptr);
+    return ptr;
+  } else {
+    *status = kUpb_DecodeStatus_Malformed;
+    return NULL;
+  }
+}
+
+const char* _upb_Decoder_IsDoneFallback(upb_Decoder* d, const char* ptr,
+                                        int overrun);
+
+UPB_INLINE
+bool _upb_Decoder_IsDone(upb_Decoder* 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 = _upb_Decoder_IsDoneFallback(d, *ptr, overrun);
+    return false;
+  }
+}
+
+#if UPB_FASTTABLE
+UPB_INLINE
+const char* _upb_FastDecoder_TagDispatch(upb_Decoder* d, const char* ptr,
+                                         upb_Message* msg, intptr_t table,
+                                         uint64_t hasbits, uint64_t tag) {
+  const upb_MiniTable* 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 _upb_FastDecoder_LoadTag(const char* ptr) {
+  uint16_t tag;
+  memcpy(&tag, ptr, 2);
+  return tag;
+}
+
+UPB_INLINE void _upb_Decoder_CheckLimit(upb_Decoder* d) {
+  UPB_ASSERT(d->limit_ptr == d->end + UPB_MIN(0, d->limit));
+}
+
+UPB_INLINE int _upb_Decoder_PushLimit(upb_Decoder* d, const char* ptr,
+                                      int size) {
+  int limit = size + (int)(ptr - d->end);
+  int delta = d->limit - limit;
+  _upb_Decoder_CheckLimit(d);
+  d->limit = limit;
+  d->limit_ptr = d->end + UPB_MIN(0, limit);
+  _upb_Decoder_CheckLimit(d);
+  return delta;
+}
+
+UPB_INLINE void _upb_Decoder_PopLimit(upb_Decoder* d, const char* ptr,
+                                      int saved_delta) {
+  UPB_ASSERT(ptr - d->end == d->limit);
+  _upb_Decoder_CheckLimit(d);
+  d->limit += saved_delta;
+  d->limit_ptr = d->end + UPB_MIN(0, d->limit);
+  _upb_Decoder_CheckLimit(d);
+}
+
+
+#endif /* UPB_WIRE_DECODE_INTERNAL_H_ */
+
+#ifndef UPB_WIRE_SWAP_INTERNAL_H_
+#define UPB_WIRE_SWAP_INTERNAL_H_
+
+// Must be last.
+
+#ifdef __cplusplus
+extern "C" {
+#endif
+
+UPB_INLINE bool _upb_IsLittleEndian(void) {
+  int x = 1;
+  return *(char*)&x == 1;
+}
+
+UPB_INLINE uint32_t _upb_BigEndian_Swap32(uint32_t val) {
+  if (_upb_IsLittleEndian()) return val;
+
+  return ((val & 0xff) << 24) | ((val & 0xff00) << 8) |
+         ((val & 0xff0000) >> 8) | ((val & 0xff000000) >> 24);
+}
+
+UPB_INLINE uint64_t _upb_BigEndian_Swap64(uint64_t val) {
+  if (_upb_IsLittleEndian()) return val;
+
+  return ((uint64_t)_upb_BigEndian_Swap32((uint32_t)val) << 32) |
+         _upb_BigEndian_Swap32((uint32_t)(val >> 32));
+}
+
+#ifdef __cplusplus
+} /* extern "C" */
+#endif
+
+
+#endif /* UPB_WIRE_SWAP_INTERNAL_H_ */
+
+// This should #undef all macros #defined in def.inc
 
 #undef UPB_SIZE
 #undef UPB_PTR_AT
@@ -5587,6 +8917,7 @@
 #undef UPB_ALIGN_DOWN
 #undef UPB_ALIGN_MALLOC
 #undef UPB_ALIGN_OF
+#undef UPB_MALLOC_ALIGN
 #undef UPB_LIKELY
 #undef UPB_UNLIKELY
 #undef UPB_FORCEINLINE
@@ -5610,3 +8941,5 @@
 #undef UPB_UNPOISON_MEMORY_REGION
 #undef UPB_ASAN
 #undef UPB_TREAT_PROTO2_ENUMS_LIKE_PROTO3
+#undef UPB_DEPRECATED
+#undef UPB_GNUC_MIN
diff --git a/ruby/internal.bzl b/ruby/internal.bzl
new file mode 100644
index 0000000..b7ec026
--- /dev/null
+++ b/ruby/internal.bzl
@@ -0,0 +1,34 @@
+def internal_ruby_extension(
+        name,
+        extension,
+        deps = [],
+        **kwargs):
+    """Bazel rule to wrap up a generated ruby extension.
+
+    NOTE: the rule is only an internal workaround. The interface may change and
+    the rule may be removed when everything is properly "Bazelified".
+
+    Args:
+      name: the name of the target.
+      extension: the path of the extension file.
+      deps: extra dependencies to add.
+      **kwargs: extra arguments to forward to the genrule.
+    """
+
+    native.genrule(
+        name = name,
+        srcs = deps + [
+            "Rakefile",
+            ":srcs",
+            ":test_ruby_protos",
+            ":tests",
+            "@utf8_range//:utf8_range_srcs",
+        ],
+        tags = ["manual"],
+        outs = [extension],
+        cmd = "pushd `dirname $(location Rakefile)`\n" +
+              "BAZEL=true rake\n" +
+              "popd\n" +
+              "cp `dirname $(location Rakefile)`/%s $(OUTS)\n" % extension,
+        **kwargs
+    )
diff --git a/ruby/lib/google/protobuf/message_exts.rb b/ruby/lib/google/protobuf/message_exts.rb
index 6608521..3cc1a08 100644
--- a/ruby/lib/google/protobuf/message_exts.rb
+++ b/ruby/lib/google/protobuf/message_exts.rb
@@ -49,5 +49,10 @@
       end
 
     end
+    class AbstractMessage
+      include MessageExts
+      extend MessageExts::ClassMethods
+    end
+    private_constant :AbstractMessage
   end
 end
diff --git a/ruby/tests/ruby_version.rb b/ruby/tests/ruby_version.rb
new file mode 100644
index 0000000..eb98960
--- /dev/null
+++ b/ruby/tests/ruby_version.rb
@@ -0,0 +1,33 @@
+#!/usr/bin/ruby
+
+# Test that Kokoro is using the expected version of ruby.
+
+require 'test/unit'
+
+class RubyVersionTest < Test::Unit::TestCase
+
+  def test_ruby_version
+    return if RUBY_PLATFORM == "java"
+    if not ENV["KOKORO_RUBY_VERSION"]
+      STDERR.puts("No kokoro ruby version found, skipping check")
+      return
+    end
+
+    actual = RUBY_VERSION
+    expected = ENV["KOKORO_RUBY_VERSION"].delete_prefix("ruby-")
+    assert actual.start_with?(expected), "Version #{actual} found, expecting #{expected}"
+  end
+
+  def test_jruby_version
+    return if RUBY_PLATFORM != "java"
+    if not ENV["KOKORO_RUBY_VERSION"]
+      STDERR.puts("No kokoro ruby version found, skipping check")
+      return
+    end
+
+    expected = ENV["KOKORO_RUBY_VERSION"].delete_prefix("jruby-")
+    actual = JRUBY_VERSION
+    assert actual.start_with?(expected), "Version #{actual} found, expecting #{expected}"
+  end
+
+end
diff --git a/ruby/travis-test.sh b/ruby/travis-test.sh
index f7fa815..39f58a2 100755
--- a/ruby/travis-test.sh
+++ b/ruby/travis-test.sh
@@ -5,8 +5,12 @@
 
 test_version() {
   version=$1
-
-  RUBY_CONFORMANCE=test_ruby
+  bazel_args="\
+    $(../kokoro/common/bazel_flags.sh) \
+    --action_env=PATH \
+    --action_env=GEM_PATH \
+    --action_env=GEM_HOME \
+    --test_env=KOKORO_RUBY_VERSION=$version"
 
   if [[ $version == jruby-9* ]] ; then
     bash --login -c \
@@ -14,21 +18,14 @@
        which ruby && \
        git clean -f && \
        gem install --no-document bundler && bundle && \
-       rake test && \
-       rake gc_test && \
-       cd ../conformance && make test_jruby && \
-       cd ../ruby/compatibility_tests/v3.0.0 && ./test.sh"
+       bazel test //ruby/... $bazel_args --define=ruby_platform=java"
   else
     bash --login -c \
       "rvm install $version && rvm use $version && \
        which ruby && \
        git clean -f && \
        gem install --no-document bundler -v 1.17.3 && bundle && \
-       rake test && \
-       rake gc_test && \
-       cd ../conformance && make ${RUBY_CONFORMANCE} && \
-       cd ../ruby/compatibility_tests/v3.0.0 && \
-       cp -R ../../lib lib && ./test.sh"
+       bazel test //ruby/... $bazel_args --define=ruby_platform=c"
   fi
 }
 
diff --git a/src/BUILD.bazel b/src/BUILD.bazel
new file mode 100644
index 0000000..aae838c
--- /dev/null
+++ b/src/BUILD.bazel
@@ -0,0 +1,64 @@
+################################################################################
+# Protocol Buffers: C++ Runtime
+################################################################################
+
+# Most rules are under google/protobuf. This package exists for convenience.
+load("@rules_pkg//:mappings.bzl", "pkg_filegroup", "pkg_files", "strip_prefix")
+load("@upb//cmake:build_defs.bzl", "staleness_test")
+load("//conformance:defs.bzl", "conformance_test")
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+pkg_filegroup(
+    name = "all_dist_files",
+    srcs = [
+        ":dist_files",
+        "//src/google/protobuf:dist_files",
+        "//src/google/protobuf/compiler:dist_files",
+        "//src/google/protobuf/compiler/cpp:dist_files",
+        "//src/google/protobuf/compiler/csharp:dist_files",
+        "//src/google/protobuf/compiler/java:dist_files",
+        "//src/google/protobuf/compiler/objectivec:dist_files",
+        "//src/google/protobuf/compiler/php:dist_files",
+        "//src/google/protobuf/compiler/python:dist_files",
+        "//src/google/protobuf/compiler/ruby:dist_files",
+        "//src/google/protobuf/io:dist_files",
+        "//src/google/protobuf/stubs:dist_files",
+        "//src/google/protobuf/testing:dist_files",
+        "//src/google/protobuf/util:dist_files",
+    ],
+    visibility = ["//pkg:__pkg__"],
+)
+
+conformance_test(
+    name = "conformance_test",
+    failure_list = "//conformance:failure_list_cpp.txt",
+    testee = "//conformance:conformance_cpp",
+    text_format_failure_list = "//conformance:text_format_failure_list_cpp.txt",
+)
+
+# Copy the generated file_lists.cmake into a place where the staleness test
+# below can use it.
+genrule(
+    name = "copy_cmake_lists",
+    srcs = ["//pkg:gen_src_file_lists"],
+    outs = ["cmake_copy/file_lists.cmake"],
+    cmd = "cp $< $@",
+    visibility = ["//visibility:private"],
+)
+
+staleness_test(
+    name = "cmake_lists_staleness_test",
+    outs = ["file_lists.cmake"],
+    generated_pattern = "cmake_copy/%s",
+    # Only run this test if it is explicitly specified on the command line (not
+    # via //src:all or ...). This file will be automatically updated in a
+    # GitHub action, so developers should not worry about failures from this
+    # test.
+    tags = ["manual"],
+)
diff --git a/src/Makefile.am b/src/Makefile.am
deleted file mode 100644
index 02abe55..0000000
--- a/src/Makefile.am
+++ /dev/null
@@ -1,918 +0,0 @@
-## Process this file with automake to produce Makefile.in
-
-if HAVE_ZLIB
-GZCHECKPROGRAMS = zcgzip zcgunzip
-GZHEADERS = google/protobuf/io/gzip_stream.h
-GZTESTS = google/protobuf/io/gzip_stream_unittest.sh
-ZLIB_DEF = -DHAVE_ZLIB=1
-else
-GZCHECKPROGRAMS =
-GZHEADERS =
-GZTESTS =
-ZLIB_DEF =
-endif
-
-if HAVE_PTHREAD
-PTHREAD_DEF = -DHAVE_PTHREAD=1
-else
-PTHREAD_DEF =
-endif
-
-PROTOBUF_VERSION = 32:10:0
-
-if GCC
-# Turn on all warnings except for sign comparison (we ignore sign comparison
-# in Google so our code base have tons of such warnings).
-NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) -Wall -Wno-sign-compare
-else
-NO_OPT_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF)
-endif
-
-AM_CXXFLAGS = $(NO_OPT_CXXFLAGS) $(PROTOBUF_OPT_FLAG)
-
-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.
-protodir = $(includedir)
-
-# If you are adding new files here, also remember to change the build files for
-# all other languages, //protoc-artifacts/build-zip.sh and run
-# //update_file_list.sh for bazel.
-nobase_dist_proto_DATA =                \
-  google/protobuf/any.proto             \
-  google/protobuf/api.proto             \
-  google/protobuf/compiler/plugin.proto \
-  google/protobuf/descriptor.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/timestamp.proto       \
-  google/protobuf/type.proto            \
-  google/protobuf/wrappers.proto
-
-# Not sure why these don't get cleaned automatically.
-clean-local:
-	rm -f *.loT
-
-CLEANFILES = $(protoc_outputs) unittest_proto_middleman \
-             testzip.jar testzip.list testzip.proto testzip.zip \
-             no_warning_test.cc
-
-MAINTAINERCLEANFILES =   \
-  Makefile.in
-
-nobase_include_HEADERS =                                         \
-  google/protobuf/any.h                                          \
-  google/protobuf/any.pb.h                                       \
-  google/protobuf/api.pb.h                                       \
-  google/protobuf/arena.h                                        \
-  google/protobuf/arena_impl.h                                   \
-  google/protobuf/arenastring.h                                  \
-  google/protobuf/arenaz_sampler.h                               \
-  google/protobuf/compiler/code_generator.h                      \
-  google/protobuf/compiler/command_line_interface.h              \
-  google/protobuf/compiler/cpp/cpp_generator.h                   \
-  google/protobuf/compiler/cpp/file.h                            \
-  google/protobuf/compiler/cpp/generator.h                       \
-  google/protobuf/compiler/cpp/helpers.h                         \
-  google/protobuf/compiler/cpp/names.h                           \
-  google/protobuf/compiler/csharp/csharp_doc_comment.h           \
-  google/protobuf/compiler/csharp/csharp_generator.h             \
-  google/protobuf/compiler/csharp/csharp_names.h                 \
-  google/protobuf/compiler/csharp/csharp_options.h               \
-  google/protobuf/compiler/importer.h                            \
-  google/protobuf/compiler/java/generator.h                      \
-  google/protobuf/compiler/java/java_generator.h                 \
-  google/protobuf/compiler/java/kotlin_generator.h               \
-  google/protobuf/compiler/java/names.h                          \
-  google/protobuf/compiler/objectivec/objectivec_generator.h     \
-  google/protobuf/compiler/objectivec/objectivec_helpers.h       \
-  google/protobuf/compiler/parser.h                              \
-  google/protobuf/compiler/php/php_generator.h                   \
-  google/protobuf/compiler/plugin.h                              \
-  google/protobuf/compiler/plugin.pb.h                           \
-  google/protobuf/compiler/python/generator.h                    \
-  google/protobuf/compiler/python/pyi_generator.h                \
-  google/protobuf/compiler/python/python_generator.h             \
-  google/protobuf/compiler/ruby/ruby_generator.h                 \
-  google/protobuf/descriptor.h                                   \
-  google/protobuf/descriptor.pb.h                                \
-  google/protobuf/descriptor_database.h                          \
-  google/protobuf/duration.pb.h                                  \
-  google/protobuf/dynamic_message.h                              \
-  google/protobuf/empty.pb.h                                     \
-  google/protobuf/endian.h                                       \
-  google/protobuf/explicitly_constructed.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_bases.h                      \
-  google/protobuf/generated_message_reflection.h                 \
-  google/protobuf/generated_message_tctable_decl.h               \
-  google/protobuf/generated_message_tctable_impl.h               \
-  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/coded_stream.h                              \
-  $(GZHEADERS)                                                   \
-  google/protobuf/io/io_win32.h                                  \
-  google/protobuf/io/printer.h                                   \
-  google/protobuf/io/strtod.h                                    \
-  google/protobuf/io/tokenizer.h                                 \
-  google/protobuf/io/zero_copy_stream.h                          \
-  google/protobuf/io/zero_copy_stream_impl.h                     \
-  google/protobuf/io/zero_copy_stream_impl_lite.h                \
-  google/protobuf/map.h                                          \
-  google/protobuf/map_entry.h                                    \
-  google/protobuf/map_entry_lite.h                               \
-  google/protobuf/map_field.h                                    \
-  google/protobuf/map_field_inl.h                                \
-  google/protobuf/map_field_lite.h                               \
-  google/protobuf/map_type_handler.h                             \
-  google/protobuf/message.h                                      \
-  google/protobuf/message_lite.h                                 \
-  google/protobuf/metadata.h                                     \
-  google/protobuf/metadata_lite.h                                \
-  google/protobuf/parse_context.h                                \
-  google/protobuf/port.h                                         \
-  google/protobuf/port_def.inc                                   \
-  google/protobuf/port_undef.inc                                 \
-  google/protobuf/reflection.h                                   \
-  google/protobuf/reflection_internal.h                          \
-  google/protobuf/reflection_ops.h                               \
-  google/protobuf/repeated_field.h                               \
-  google/protobuf/repeated_ptr_field.h                           \
-  google/protobuf/service.h                                      \
-  google/protobuf/source_context.pb.h                            \
-  google/protobuf/struct.pb.h                                    \
-  google/protobuf/stubs/bytestream.h                             \
-  google/protobuf/stubs/callback.h                               \
-  google/protobuf/stubs/casts.h                                  \
-  google/protobuf/stubs/common.h                                 \
-  google/protobuf/stubs/hash.h                                   \
-  google/protobuf/stubs/logging.h                                \
-  google/protobuf/stubs/macros.h                                 \
-  google/protobuf/stubs/map_util.h                               \
-  google/protobuf/stubs/mutex.h                                  \
-  google/protobuf/stubs/once.h                                   \
-  google/protobuf/stubs/platform_macros.h                        \
-  google/protobuf/stubs/port.h                                   \
-  google/protobuf/stubs/status.h                                 \
-  google/protobuf/stubs/stl_util.h                               \
-  google/protobuf/stubs/stringpiece.h                            \
-  google/protobuf/stubs/strutil.h                                \
-  google/protobuf/stubs/template_util.h                          \
-  google/protobuf/text_format.h                                  \
-  google/protobuf/timestamp.pb.h                                 \
-  google/protobuf/type.pb.h                                      \
-  google/protobuf/unknown_field_set.h                            \
-  google/protobuf/util/delimited_message_util.h                  \
-  google/protobuf/util/field_comparator.h                        \
-  google/protobuf/util/field_mask_util.h                         \
-  google/protobuf/util/json_util.h                               \
-  google/protobuf/util/message_differencer.h                     \
-  google/protobuf/util/time_util.h                               \
-  google/protobuf/util/type_resolver.h                           \
-  google/protobuf/util/type_resolver_util.h                      \
-  google/protobuf/wire_format.h                                  \
-  google/protobuf/wire_format_lite.h                             \
-  google/protobuf/wrappers.pb.h
-
-lib_LTLIBRARIES = libprotobuf-lite.la libprotobuf.la libprotoc.la
-
-libprotobuf_lite_la_LIBADD = $(PTHREAD_LIBS) $(LIBATOMIC_LIBS)
-libprotobuf_lite_la_LDFLAGS = -version-info $(PROTOBUF_VERSION) -export-dynamic -no-undefined
-if HAVE_LD_VERSION_SCRIPT
-libprotobuf_lite_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf-lite.map
-EXTRA_libprotobuf_lite_la_DEPENDENCIES = libprotobuf-lite.map
-endif
-libprotobuf_lite_la_SOURCES =                                  \
-  google/protobuf/any_lite.cc                                  \
-  google/protobuf/arena.cc                                     \
-  google/protobuf/arenastring.cc                               \
-  google/protobuf/arenaz_sampler.cc                            \
-  google/protobuf/extension_set.cc                             \
-  google/protobuf/generated_enum_util.cc                       \
-  google/protobuf/generated_message_tctable_lite.cc            \
-  google/protobuf/generated_message_util.cc                    \
-  google/protobuf/implicit_weak_message.cc                     \
-  google/protobuf/inlined_string_field.cc                      \
-  google/protobuf/io/coded_stream.cc                           \
-  google/protobuf/io/io_win32.cc                               \
-  google/protobuf/io/strtod.cc                                 \
-  google/protobuf/io/zero_copy_stream.cc                       \
-  google/protobuf/io/zero_copy_stream_impl.cc                  \
-  google/protobuf/io/zero_copy_stream_impl_lite.cc             \
-  google/protobuf/map.cc                                       \
-  google/protobuf/message_lite.cc                              \
-  google/protobuf/parse_context.cc                             \
-  google/protobuf/repeated_field.cc                            \
-  google/protobuf/repeated_ptr_field.cc                        \
-  google/protobuf/string_member_robber.h                       \
-  google/protobuf/stubs/bytestream.cc                          \
-  google/protobuf/stubs/common.cc                              \
-  google/protobuf/stubs/int128.cc                              \
-  google/protobuf/stubs/int128.h                               \
-  google/protobuf/stubs/mathutil.h                             \
-  google/protobuf/stubs/status.cc                              \
-  google/protobuf/stubs/status_macros.h                        \
-  google/protobuf/stubs/statusor.cc                            \
-  google/protobuf/stubs/statusor.h                             \
-  google/protobuf/stubs/stringpiece.cc                         \
-  google/protobuf/stubs/stringprintf.cc                        \
-  google/protobuf/stubs/stringprintf.h                         \
-  google/protobuf/stubs/structurally_valid.cc                  \
-  google/protobuf/stubs/strutil.cc                             \
-  google/protobuf/stubs/time.cc                                \
-  google/protobuf/stubs/time.h                                 \
-  google/protobuf/wire_format_lite.cc
-
-libprotobuf_la_LIBADD = $(PTHREAD_LIBS) $(LIBATOMIC_LIBS)
-libprotobuf_la_LDFLAGS = -version-info $(PROTOBUF_VERSION) -export-dynamic -no-undefined
-if HAVE_LD_VERSION_SCRIPT
-libprotobuf_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotobuf.map
-EXTRA_libprotobuf_la_DEPENDENCIES = libprotobuf.map
-endif
-libprotobuf_la_SOURCES =                                       \
-  $(libprotobuf_lite_la_SOURCES)                               \
-  google/protobuf/any.cc                                       \
-  google/protobuf/any.pb.cc                                    \
-  google/protobuf/api.pb.cc                                    \
-  google/protobuf/compiler/importer.cc                         \
-  google/protobuf/compiler/parser.cc                           \
-  google/protobuf/descriptor.cc                                \
-  google/protobuf/descriptor.pb.cc                             \
-  google/protobuf/descriptor_database.cc                       \
-  google/protobuf/duration.pb.cc                               \
-  google/protobuf/dynamic_message.cc                           \
-  google/protobuf/empty.pb.cc                                  \
-  google/protobuf/extension_set_heavy.cc                       \
-  google/protobuf/field_mask.pb.cc                             \
-  google/protobuf/generated_message_bases.cc                   \
-  google/protobuf/generated_message_reflection.cc              \
-  google/protobuf/generated_message_tctable_full.cc            \
-  google/protobuf/io/gzip_stream.cc                            \
-  google/protobuf/io/printer.cc                                \
-  google/protobuf/io/tokenizer.cc                              \
-  google/protobuf/map_field.cc                                 \
-  google/protobuf/message.cc                                   \
-  google/protobuf/reflection_ops.cc                            \
-  google/protobuf/service.cc                                   \
-  google/protobuf/source_context.pb.cc                         \
-  google/protobuf/struct.pb.cc                                 \
-  google/protobuf/stubs/substitute.cc                          \
-  google/protobuf/stubs/substitute.h                           \
-  google/protobuf/text_format.cc                               \
-  google/protobuf/timestamp.pb.cc                              \
-  google/protobuf/type.pb.cc                                   \
-  google/protobuf/unknown_field_set.cc                         \
-  google/protobuf/util/delimited_message_util.cc               \
-  google/protobuf/util/field_comparator.cc                     \
-  google/protobuf/util/field_mask_util.cc                      \
-  google/protobuf/util/internal/constants.h                    \
-  google/protobuf/util/internal/datapiece.cc                   \
-  google/protobuf/util/internal/datapiece.h                    \
-  google/protobuf/util/internal/default_value_objectwriter.cc  \
-  google/protobuf/util/internal/default_value_objectwriter.h   \
-  google/protobuf/util/internal/error_listener.cc              \
-  google/protobuf/util/internal/error_listener.h               \
-  google/protobuf/util/internal/expecting_objectwriter.h       \
-  google/protobuf/util/internal/field_mask_utility.cc          \
-  google/protobuf/util/internal/field_mask_utility.h           \
-  google/protobuf/util/internal/json_escaping.cc               \
-  google/protobuf/util/internal/json_escaping.h                \
-  google/protobuf/util/internal/json_objectwriter.cc           \
-  google/protobuf/util/internal/json_objectwriter.h            \
-  google/protobuf/util/internal/json_stream_parser.cc          \
-  google/protobuf/util/internal/json_stream_parser.h           \
-  google/protobuf/util/internal/location_tracker.h             \
-  google/protobuf/util/internal/mock_error_listener.h          \
-  google/protobuf/util/internal/object_location_tracker.h      \
-  google/protobuf/util/internal/object_source.h                \
-  google/protobuf/util/internal/object_writer.cc               \
-  google/protobuf/util/internal/object_writer.h                \
-  google/protobuf/util/internal/proto_writer.cc                \
-  google/protobuf/util/internal/proto_writer.h                 \
-  google/protobuf/util/internal/protostream_objectsource.cc    \
-  google/protobuf/util/internal/protostream_objectsource.h     \
-  google/protobuf/util/internal/protostream_objectwriter.cc    \
-  google/protobuf/util/internal/protostream_objectwriter.h     \
-  google/protobuf/util/internal/structured_objectwriter.h      \
-  google/protobuf/util/internal/type_info.cc                   \
-  google/protobuf/util/internal/type_info.h                    \
-  google/protobuf/util/internal/type_info_test_helper.h        \
-  google/protobuf/util/internal/utility.cc                     \
-  google/protobuf/util/internal/utility.h                      \
-  google/protobuf/util/json_util.cc                            \
-  google/protobuf/util/message_differencer.cc                  \
-  google/protobuf/util/time_util.cc                            \
-  google/protobuf/util/type_resolver_util.cc                   \
-  google/protobuf/wire_format.cc                               \
-  google/protobuf/wrappers.pb.cc
-
-nodist_libprotobuf_la_SOURCES = $(nodist_libprotobuf_lite_la_SOURCES)
-
-libprotoc_la_LIBADD = $(PTHREAD_LIBS) libprotobuf.la
-libprotoc_la_LDFLAGS = -version-info $(PROTOBUF_VERSION) -export-dynamic -no-undefined
-if HAVE_LD_VERSION_SCRIPT
-libprotoc_la_LDFLAGS += -Wl,--version-script=$(srcdir)/libprotoc.map
-EXTRA_libprotoc_la_DEPENDENCIES = libprotoc.map
-endif
-libprotoc_la_SOURCES =                                         \
-  google/protobuf/compiler/code_generator.cc                   \
-  google/protobuf/compiler/command_line_interface.cc           \
-  google/protobuf/compiler/cpp/enum.cc                         \
-  google/protobuf/compiler/cpp/enum.h                          \
-  google/protobuf/compiler/cpp/enum_field.cc                   \
-  google/protobuf/compiler/cpp/enum_field.h                    \
-  google/protobuf/compiler/cpp/extension.cc                    \
-  google/protobuf/compiler/cpp/extension.h                     \
-  google/protobuf/compiler/cpp/field.cc                        \
-  google/protobuf/compiler/cpp/field.h                         \
-  google/protobuf/compiler/cpp/file.cc                         \
-  google/protobuf/compiler/cpp/generator.cc                    \
-  google/protobuf/compiler/cpp/helpers.cc                      \
-  google/protobuf/compiler/cpp/map_field.cc                    \
-  google/protobuf/compiler/cpp/map_field.h                     \
-  google/protobuf/compiler/cpp/message.cc                      \
-  google/protobuf/compiler/cpp/message.h                       \
-  google/protobuf/compiler/cpp/message_field.cc                \
-  google/protobuf/compiler/cpp/message_field.h                 \
-  google/protobuf/compiler/cpp/message_layout_helper.h         \
-  google/protobuf/compiler/cpp/options.h                       \
-  google/protobuf/compiler/cpp/padding_optimizer.cc            \
-  google/protobuf/compiler/cpp/padding_optimizer.h             \
-  google/protobuf/compiler/cpp/parse_function_generator.cc     \
-  google/protobuf/compiler/cpp/parse_function_generator.h      \
-  google/protobuf/compiler/cpp/primitive_field.cc              \
-  google/protobuf/compiler/cpp/primitive_field.h               \
-  google/protobuf/compiler/cpp/service.cc                      \
-  google/protobuf/compiler/cpp/service.h                       \
-  google/protobuf/compiler/cpp/string_field.cc                 \
-  google/protobuf/compiler/cpp/string_field.h                  \
-  google/protobuf/compiler/csharp/csharp_doc_comment.cc        \
-  google/protobuf/compiler/csharp/csharp_enum.cc               \
-  google/protobuf/compiler/csharp/csharp_enum.h                \
-  google/protobuf/compiler/csharp/csharp_enum_field.cc         \
-  google/protobuf/compiler/csharp/csharp_enum_field.h          \
-  google/protobuf/compiler/csharp/csharp_field_base.cc         \
-  google/protobuf/compiler/csharp/csharp_field_base.h          \
-  google/protobuf/compiler/csharp/csharp_generator.cc          \
-  google/protobuf/compiler/csharp/csharp_helpers.cc            \
-  google/protobuf/compiler/csharp/csharp_helpers.h             \
-  google/protobuf/compiler/csharp/csharp_map_field.cc          \
-  google/protobuf/compiler/csharp/csharp_map_field.h           \
-  google/protobuf/compiler/csharp/csharp_message.cc            \
-  google/protobuf/compiler/csharp/csharp_message.h             \
-  google/protobuf/compiler/csharp/csharp_message_field.cc      \
-  google/protobuf/compiler/csharp/csharp_message_field.h       \
-  google/protobuf/compiler/csharp/csharp_primitive_field.cc    \
-  google/protobuf/compiler/csharp/csharp_primitive_field.h     \
-  google/protobuf/compiler/csharp/csharp_reflection_class.cc   \
-  google/protobuf/compiler/csharp/csharp_reflection_class.h    \
-  google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc \
-  google/protobuf/compiler/csharp/csharp_repeated_enum_field.h \
-  google/protobuf/compiler/csharp/csharp_repeated_message_field.cc \
-  google/protobuf/compiler/csharp/csharp_repeated_message_field.h \
-  google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc \
-  google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h \
-  google/protobuf/compiler/csharp/csharp_source_generator_base.cc \
-  google/protobuf/compiler/csharp/csharp_source_generator_base.h \
-  google/protobuf/compiler/csharp/csharp_wrapper_field.cc      \
-  google/protobuf/compiler/csharp/csharp_wrapper_field.h       \
-  google/protobuf/compiler/java/context.cc                     \
-  google/protobuf/compiler/java/context.h                      \
-  google/protobuf/compiler/java/doc_comment.cc                 \
-  google/protobuf/compiler/java/doc_comment.h                  \
-  google/protobuf/compiler/java/enum.cc                        \
-  google/protobuf/compiler/java/enum.h                         \
-  google/protobuf/compiler/java/enum_field.cc                  \
-  google/protobuf/compiler/java/enum_field.h                   \
-  google/protobuf/compiler/java/enum_field_lite.cc             \
-  google/protobuf/compiler/java/enum_field_lite.h              \
-  google/protobuf/compiler/java/enum_lite.cc                   \
-  google/protobuf/compiler/java/enum_lite.h                    \
-  google/protobuf/compiler/java/extension.cc                   \
-  google/protobuf/compiler/java/extension.h                    \
-  google/protobuf/compiler/java/extension_lite.cc              \
-  google/protobuf/compiler/java/extension_lite.h               \
-  google/protobuf/compiler/java/field.cc                       \
-  google/protobuf/compiler/java/field.h                        \
-  google/protobuf/compiler/java/file.cc                        \
-  google/protobuf/compiler/java/file.h                         \
-  google/protobuf/compiler/java/generator.cc                   \
-  google/protobuf/compiler/java/generator_factory.cc           \
-  google/protobuf/compiler/java/generator_factory.h            \
-  google/protobuf/compiler/java/helpers.cc                     \
-  google/protobuf/compiler/java/helpers.h                      \
-  google/protobuf/compiler/java/kotlin_generator.cc            \
-  google/protobuf/compiler/java/map_field.cc                   \
-  google/protobuf/compiler/java/map_field.h                    \
-  google/protobuf/compiler/java/map_field_lite.cc              \
-  google/protobuf/compiler/java/map_field_lite.h               \
-  google/protobuf/compiler/java/message.cc                     \
-  google/protobuf/compiler/java/message.h                      \
-  google/protobuf/compiler/java/message_builder.cc             \
-  google/protobuf/compiler/java/message_builder.h              \
-  google/protobuf/compiler/java/message_builder_lite.cc        \
-  google/protobuf/compiler/java/message_builder_lite.h         \
-  google/protobuf/compiler/java/message_field.cc               \
-  google/protobuf/compiler/java/message_field.h                \
-  google/protobuf/compiler/java/message_field_lite.cc          \
-  google/protobuf/compiler/java/message_field_lite.h           \
-  google/protobuf/compiler/java/message_lite.cc                \
-  google/protobuf/compiler/java/message_lite.h                 \
-  google/protobuf/compiler/java/name_resolver.cc               \
-  google/protobuf/compiler/java/name_resolver.h                \
-  google/protobuf/compiler/java/options.h                      \
-  google/protobuf/compiler/java/primitive_field.cc             \
-  google/protobuf/compiler/java/primitive_field.h              \
-  google/protobuf/compiler/java/primitive_field_lite.cc        \
-  google/protobuf/compiler/java/primitive_field_lite.h         \
-  google/protobuf/compiler/java/service.cc                     \
-  google/protobuf/compiler/java/service.h                      \
-  google/protobuf/compiler/java/shared_code_generator.cc       \
-  google/protobuf/compiler/java/shared_code_generator.h        \
-  google/protobuf/compiler/java/string_field.cc                \
-  google/protobuf/compiler/java/string_field.h                 \
-  google/protobuf/compiler/java/string_field_lite.cc           \
-  google/protobuf/compiler/java/string_field_lite.h            \
-  google/protobuf/compiler/objectivec/objectivec_enum.cc       \
-  google/protobuf/compiler/objectivec/objectivec_enum.h        \
-  google/protobuf/compiler/objectivec/objectivec_enum_field.cc \
-  google/protobuf/compiler/objectivec/objectivec_enum_field.h  \
-  google/protobuf/compiler/objectivec/objectivec_extension.cc  \
-  google/protobuf/compiler/objectivec/objectivec_extension.h   \
-  google/protobuf/compiler/objectivec/objectivec_field.cc      \
-  google/protobuf/compiler/objectivec/objectivec_field.h       \
-  google/protobuf/compiler/objectivec/objectivec_file.cc       \
-  google/protobuf/compiler/objectivec/objectivec_file.h        \
-  google/protobuf/compiler/objectivec/objectivec_generator.cc  \
-  google/protobuf/compiler/objectivec/objectivec_helpers.cc    \
-  google/protobuf/compiler/objectivec/objectivec_map_field.cc  \
-  google/protobuf/compiler/objectivec/objectivec_map_field.h   \
-  google/protobuf/compiler/objectivec/objectivec_message.cc    \
-  google/protobuf/compiler/objectivec/objectivec_message.h     \
-  google/protobuf/compiler/objectivec/objectivec_message_field.cc \
-  google/protobuf/compiler/objectivec/objectivec_message_field.h \
-  google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h \
-  google/protobuf/compiler/objectivec/objectivec_oneof.cc      \
-  google/protobuf/compiler/objectivec/objectivec_oneof.h       \
-  google/protobuf/compiler/objectivec/objectivec_primitive_field.cc \
-  google/protobuf/compiler/objectivec/objectivec_primitive_field.h \
-  google/protobuf/compiler/php/php_generator.cc                \
-  google/protobuf/compiler/plugin.cc                           \
-  google/protobuf/compiler/plugin.pb.cc                        \
-  google/protobuf/compiler/python/generator.cc                 \
-  google/protobuf/compiler/python/helpers.cc                   \
-  google/protobuf/compiler/python/helpers.h                    \
-  google/protobuf/compiler/python/pyi_generator.cc             \
-  google/protobuf/compiler/ruby/ruby_generator.cc              \
-  google/protobuf/compiler/scc.h                               \
-  google/protobuf/compiler/subprocess.cc                       \
-  google/protobuf/compiler/subprocess.h                        \
-  google/protobuf/compiler/zip_writer.cc                       \
-  google/protobuf/compiler/zip_writer.h
-
-bin_PROGRAMS = protoc
-protoc_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
-protoc_SOURCES = google/protobuf/compiler/main.cc
-
-# Tests ==============================================================
-
-protoc_inputs =                                                   \
-  google/protobuf/any_test.proto                                  \
-  google/protobuf/compiler/cpp/test_bad_identifiers.proto         \
-  google/protobuf/compiler/cpp/test_large_enum_value.proto        \
-  google/protobuf/map_lite_unittest.proto                         \
-  google/protobuf/map_proto2_unittest.proto                       \
-  google/protobuf/map_unittest.proto                              \
-  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_lite.proto                      \
-  google/protobuf/unittest_import_public.proto                    \
-  google/protobuf/unittest_import_public_lite.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.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                 \
-  google/protobuf/util/internal/testdata/anys.proto               \
-  google/protobuf/util/internal/testdata/books.proto              \
-  google/protobuf/util/internal/testdata/default_value.proto      \
-  google/protobuf/util/internal/testdata/default_value_test.proto \
-  google/protobuf/util/internal/testdata/field_mask.proto         \
-  google/protobuf/util/internal/testdata/maps.proto               \
-  google/protobuf/util/internal/testdata/oneofs.proto             \
-  google/protobuf/util/internal/testdata/proto3.proto             \
-  google/protobuf/util/internal/testdata/struct.proto             \
-  google/protobuf/util/internal/testdata/timestamp_duration.proto \
-  google/protobuf/util/internal/testdata/wrappers.proto           \
-  google/protobuf/util/json_format.proto                          \
-  google/protobuf/util/json_format_proto3.proto                   \
-  google/protobuf/util/message_differencer_unittest.proto
-
-EXTRA_DIST =                                                   \
-  $(protoc_inputs)                                             \
-  README.md                                                    \
-  google/protobuf/compiler/package_info.h                      \
-  google/protobuf/compiler/ruby/ruby_generated_code.proto      \
-  google/protobuf/compiler/ruby/ruby_generated_code_pb.rb      \
-  google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto \
-  google/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto \
-  google/protobuf/compiler/ruby/ruby_generated_code_proto2_pb.rb \
-  google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto \
-  google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto \
-  google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy_pb.rb \
-  google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_pb.rb \
-  google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto \
-  google/protobuf/compiler/ruby/ruby_generated_pkg_implicit_pb.rb \
-  google/protobuf/compiler/zip_output_unittest.sh              \
-  google/protobuf/io/gzip_stream.h                             \
-  google/protobuf/io/gzip_stream_unittest.sh                   \
-  google/protobuf/io/package_info.h                            \
-  google/protobuf/package_info.h                               \
-  google/protobuf/test_messages_proto2.proto                   \
-  google/protobuf/test_messages_proto3.proto                   \
-  google/protobuf/testdata/bad_utf8_string                     \
-  google/protobuf/testdata/golden_message                      \
-  google/protobuf/testdata/golden_message_maps                 \
-  google/protobuf/testdata/golden_message_oneof_implemented    \
-  google/protobuf/testdata/golden_message_proto3               \
-  google/protobuf/testdata/golden_packed_fields_message        \
-  google/protobuf/testdata/map_test_data.txt                   \
-  google/protobuf/testdata/text_format_unittest_data.txt       \
-  google/protobuf/testdata/text_format_unittest_data_oneof_implemented.txt \
-  google/protobuf/testdata/text_format_unittest_data_pointy.txt \
-  google/protobuf/testdata/text_format_unittest_data_pointy_oneof.txt \
-  google/protobuf/testdata/text_format_unittest_extensions_data.txt \
-  google/protobuf/testdata/text_format_unittest_extensions_data_pointy.txt \
-  google/protobuf/util/package_info.h                          \
-  libprotobuf-lite.map                                         \
-  libprotobuf.map                                              \
-  libprotoc.map                                                \
-  solaris/libstdc++.la                                        
-
-protoc_lite_outputs =                                          \
-  google/protobuf/map_lite_unittest.pb.cc                      \
-  google/protobuf/map_lite_unittest.pb.h                       \
-  google/protobuf/unittest_import_lite.pb.cc                   \
-  google/protobuf/unittest_import_lite.pb.h                    \
-  google/protobuf/unittest_import_public_lite.pb.cc            \
-  google/protobuf/unittest_import_public_lite.pb.h             \
-  google/protobuf/unittest_lite.pb.cc                          \
-  google/protobuf/unittest_lite.pb.h
-
-protoc_outputs =                                                  \
-  $(protoc_lite_outputs)                                          \
-  google/protobuf/any_test.pb.cc                                  \
-  google/protobuf/any_test.pb.h                                   \
-  google/protobuf/compiler/cpp/test_bad_identifiers.pb.cc         \
-  google/protobuf/compiler/cpp/test_bad_identifiers.pb.h          \
-  google/protobuf/compiler/cpp/test_large_enum_value.pb.cc        \
-  google/protobuf/compiler/cpp/test_large_enum_value.pb.h         \
-  google/protobuf/map_proto2_unittest.pb.cc                       \
-  google/protobuf/map_proto2_unittest.pb.h                        \
-  google/protobuf/map_unittest.pb.cc                              \
-  google/protobuf/map_unittest.pb.h                               \
-  google/protobuf/unittest.pb.cc                                  \
-  google/protobuf/unittest.pb.h                                   \
-  google/protobuf/unittest_arena.pb.cc                            \
-  google/protobuf/unittest_arena.pb.h                             \
-  google/protobuf/unittest_custom_options.pb.cc                   \
-  google/protobuf/unittest_custom_options.pb.h                    \
-  google/protobuf/unittest_drop_unknown_fields.pb.cc              \
-  google/protobuf/unittest_drop_unknown_fields.pb.h               \
-  google/protobuf/unittest_embed_optimize_for.pb.cc               \
-  google/protobuf/unittest_embed_optimize_for.pb.h                \
-  google/protobuf/unittest_empty.pb.cc                            \
-  google/protobuf/unittest_empty.pb.h                             \
-  google/protobuf/unittest_enormous_descriptor.pb.cc              \
-  google/protobuf/unittest_enormous_descriptor.pb.h               \
-  google/protobuf/unittest_import.pb.cc                           \
-  google/protobuf/unittest_import.pb.h                            \
-  google/protobuf/unittest_import_public.pb.cc                    \
-  google/protobuf/unittest_import_public.pb.h                     \
-  google/protobuf/unittest_lazy_dependencies.pb.cc                \
-  google/protobuf/unittest_lazy_dependencies.pb.h                 \
-  google/protobuf/unittest_lazy_dependencies_custom_option.pb.cc  \
-  google/protobuf/unittest_lazy_dependencies_custom_option.pb.h   \
-  google/protobuf/unittest_lazy_dependencies_enum.pb.cc           \
-  google/protobuf/unittest_lazy_dependencies_enum.pb.h            \
-  google/protobuf/unittest_lite_imports_nonlite.pb.cc             \
-  google/protobuf/unittest_lite_imports_nonlite.pb.h              \
-  google/protobuf/unittest_mset.pb.cc                             \
-  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_field_presence.pb.cc                \
-  google/protobuf/unittest_no_field_presence.pb.h                 \
-  google/protobuf/unittest_no_generic_services.pb.cc              \
-  google/protobuf/unittest_no_generic_services.pb.h               \
-  google/protobuf/unittest_optimize_for.pb.cc                     \
-  google/protobuf/unittest_optimize_for.pb.h                      \
-  google/protobuf/unittest_preserve_unknown_enum.pb.cc            \
-  google/protobuf/unittest_preserve_unknown_enum.pb.h             \
-  google/protobuf/unittest_preserve_unknown_enum2.pb.cc           \
-  google/protobuf/unittest_preserve_unknown_enum2.pb.h            \
-  google/protobuf/unittest_proto3.pb.cc                           \
-  google/protobuf/unittest_proto3.pb.h                            \
-  google/protobuf/unittest_proto3_arena.pb.cc                     \
-  google/protobuf/unittest_proto3_arena.pb.h                      \
-  google/protobuf/unittest_proto3_arena_lite.pb.cc                \
-  google/protobuf/unittest_proto3_arena_lite.pb.h                 \
-  google/protobuf/unittest_proto3_lite.pb.cc                      \
-  google/protobuf/unittest_proto3_lite.pb.h                       \
-  google/protobuf/unittest_proto3_optional.pb.cc                  \
-  google/protobuf/unittest_proto3_optional.pb.h                   \
-  google/protobuf/unittest_well_known_types.pb.cc                 \
-  google/protobuf/unittest_well_known_types.pb.h                  \
-  google/protobuf/util/internal/testdata/anys.pb.cc               \
-  google/protobuf/util/internal/testdata/anys.pb.h                \
-  google/protobuf/util/internal/testdata/books.pb.cc              \
-  google/protobuf/util/internal/testdata/books.pb.h               \
-  google/protobuf/util/internal/testdata/default_value.pb.cc      \
-  google/protobuf/util/internal/testdata/default_value.pb.h       \
-  google/protobuf/util/internal/testdata/default_value_test.pb.cc \
-  google/protobuf/util/internal/testdata/default_value_test.pb.h  \
-  google/protobuf/util/internal/testdata/field_mask.pb.cc         \
-  google/protobuf/util/internal/testdata/field_mask.pb.h          \
-  google/protobuf/util/internal/testdata/maps.pb.cc               \
-  google/protobuf/util/internal/testdata/maps.pb.h                \
-  google/protobuf/util/internal/testdata/oneofs.pb.cc             \
-  google/protobuf/util/internal/testdata/oneofs.pb.h              \
-  google/protobuf/util/internal/testdata/proto3.pb.cc             \
-  google/protobuf/util/internal/testdata/proto3.pb.h              \
-  google/protobuf/util/internal/testdata/struct.pb.cc             \
-  google/protobuf/util/internal/testdata/struct.pb.h              \
-  google/protobuf/util/internal/testdata/timestamp_duration.pb.cc \
-  google/protobuf/util/internal/testdata/timestamp_duration.pb.h  \
-  google/protobuf/util/internal/testdata/wrappers.pb.cc           \
-  google/protobuf/util/internal/testdata/wrappers.pb.h            \
-  google/protobuf/util/json_format.pb.cc                          \
-  google/protobuf/util/json_format.pb.h                           \
-  google/protobuf/util/json_format_proto3.pb.cc                   \
-  google/protobuf/util/json_format_proto3.pb.h                    \
-  google/protobuf/util/message_differencer_unittest.pb.cc         \
-  google/protobuf/util/message_differencer_unittest.pb.h
-
-if USE_EXTERNAL_PROTOC
-
-unittest_proto_middleman: $(protoc_inputs)
-	$(PROTOC) -I$(srcdir) --cpp_out=. $^
-	touch unittest_proto_middleman
-
-else
-
-# We have to cd to $(srcdir) before executing protoc because $(protoc_inputs) is
-# relative to srcdir, which may not be the same as the current directory when
-# building out-of-tree.
-unittest_proto_middleman: protoc$(EXEEXT) $(protoc_inputs)
-	oldpwd=`pwd` && ( cd $(srcdir) && $$oldpwd/protoc$(EXEEXT) -I. --cpp_out=$$oldpwd $(protoc_inputs) --experimental_allow_proto3_optional )
-	touch unittest_proto_middleman
-
-endif
-
-$(protoc_outputs): unittest_proto_middleman
-
-COMMON_TEST_SOURCES =                                          \
-  $(COMMON_LITE_TEST_SOURCES)                                  \
-  google/protobuf/compiler/cpp/unittest.h                      \
-  google/protobuf/map_test_util.h                              \
-  google/protobuf/map_test_util.inc                            \
-  google/protobuf/reflection_tester.cc                         \
-  google/protobuf/reflection_tester.h                          \
-  google/protobuf/test_util.cc                                 \
-  google/protobuf/test_util.h                                  \
-  google/protobuf/test_util.inc                                \
-  google/protobuf/test_util2.h                                 \
-  google/protobuf/testing/file.cc                              \
-  google/protobuf/testing/file.h                               \
-  google/protobuf/testing/googletest.cc                        \
-  google/protobuf/testing/googletest.h
-
-GOOGLETEST_BUILD_DIR=../third_party/googletest/googletest
-GOOGLEMOCK_BUILD_DIR=../third_party/googletest/googlemock
-GOOGLETEST_SRC_DIR=$(srcdir)/../third_party/googletest/googletest
-GOOGLEMOCK_SRC_DIR=$(srcdir)/../third_party/googletest/googlemock
-check_PROGRAMS = protoc protobuf-test protobuf-lazy-descriptor-test \
-                 protobuf-lite-test test_plugin protobuf-lite-arena-test \
-                 no-warning-test $(GZCHECKPROGRAMS)
-protobuf_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
-                      $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la     \
-                      $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la     \
-                      $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la
-protobuf_test_CPPFLAGS = -I$(GOOGLETEST_SRC_DIR)/include \
-                         -I$(GOOGLEMOCK_SRC_DIR)/include
-# Disable optimization for tests unless the user explicitly asked for it,
-# since test_util.cc takes forever to compile with optimization (with GCC).
-# See configure.ac for more info.
-protobuf_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
-protobuf_test_SOURCES =                                        \
-  $(COMMON_TEST_SOURCES)                                       \
-  google/protobuf/any_test.cc                                  \
-  google/protobuf/arena_unittest.cc                            \
-  google/protobuf/arenastring_unittest.cc                      \
-  google/protobuf/arenaz_sampler_test.cc                       \
-  google/protobuf/compiler/annotation_test_util.cc             \
-  google/protobuf/compiler/annotation_test_util.h              \
-  google/protobuf/compiler/command_line_interface_unittest.cc  \
-  google/protobuf/compiler/cpp/bootstrap_unittest.cc           \
-  google/protobuf/compiler/cpp/message_size_unittest.cc        \
-  google/protobuf/compiler/cpp/metadata_test.cc                \
-  google/protobuf/compiler/cpp/move_unittest.cc                \
-  google/protobuf/compiler/cpp/plugin_unittest.cc              \
-  google/protobuf/compiler/cpp/unittest.cc                     \
-  google/protobuf/compiler/cpp/unittest.inc                    \
-  google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc \
-  google/protobuf/compiler/csharp/csharp_generator_unittest.cc \
-  google/protobuf/compiler/importer_unittest.cc                \
-  google/protobuf/compiler/java/doc_comment_unittest.cc        \
-  google/protobuf/compiler/java/plugin_unittest.cc             \
-  google/protobuf/compiler/mock_code_generator.cc              \
-  google/protobuf/compiler/mock_code_generator.h               \
-  google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc \
-  google/protobuf/compiler/parser_unittest.cc                  \
-  google/protobuf/compiler/python/plugin_unittest.cc           \
-  google/protobuf/compiler/ruby/ruby_generator_unittest.cc     \
-  google/protobuf/descriptor_database_unittest.cc              \
-  google/protobuf/descriptor_unittest.cc                       \
-  google/protobuf/drop_unknown_fields_test.cc                  \
-  google/protobuf/dynamic_message_unittest.cc                  \
-  google/protobuf/extension_set_unittest.cc                    \
-  google/protobuf/generated_message_reflection_unittest.cc     \
-  google/protobuf/generated_message_tctable_lite_test.cc       \
-  google/protobuf/inlined_string_field_unittest.cc             \
-  google/protobuf/io/coded_stream_unittest.cc                  \
-  google/protobuf/io/io_win32_unittest.cc                      \
-  google/protobuf/io/printer_unittest.cc                       \
-  google/protobuf/io/tokenizer_unittest.cc                     \
-  google/protobuf/io/zero_copy_stream_unittest.cc              \
-  google/protobuf/map_field_test.cc                            \
-  google/protobuf/map_test.cc                                  \
-  google/protobuf/map_test.inc                                 \
-  google/protobuf/message_unittest.cc                          \
-  google/protobuf/message_unittest.inc                         \
-  google/protobuf/no_field_presence_test.cc                    \
-  google/protobuf/preserve_unknown_enum_test.cc                \
-  google/protobuf/proto3_arena_lite_unittest.cc                \
-  google/protobuf/proto3_arena_unittest.cc                     \
-  google/protobuf/proto3_lite_unittest.cc                      \
-  google/protobuf/proto3_lite_unittest.inc                     \
-  google/protobuf/reflection_ops_unittest.cc                   \
-  google/protobuf/repeated_field_reflection_unittest.cc        \
-  google/protobuf/repeated_field_unittest.cc                   \
-  google/protobuf/stubs/bytestream_unittest.cc                 \
-  google/protobuf/stubs/common_unittest.cc                     \
-  google/protobuf/stubs/int128_unittest.cc                     \
-  google/protobuf/stubs/status_test.cc                         \
-  google/protobuf/stubs/statusor_test.cc                       \
-  google/protobuf/stubs/stringpiece_unittest.cc                \
-  google/protobuf/stubs/stringprintf_unittest.cc               \
-  google/protobuf/stubs/structurally_valid_unittest.cc         \
-  google/protobuf/stubs/strutil_unittest.cc                    \
-  google/protobuf/stubs/template_util_unittest.cc              \
-  google/protobuf/stubs/time_test.cc                           \
-  google/protobuf/text_format_unittest.cc                      \
-  google/protobuf/unknown_field_set_unittest.cc                \
-  google/protobuf/util/delimited_message_util_test.cc          \
-  google/protobuf/util/field_comparator_test.cc                \
-  google/protobuf/util/field_mask_util_test.cc                 \
-  google/protobuf/util/internal/default_value_objectwriter_test.cc \
-  google/protobuf/util/internal/json_objectwriter_test.cc      \
-  google/protobuf/util/internal/json_stream_parser_test.cc     \
-  google/protobuf/util/internal/protostream_objectsource_test.cc \
-  google/protobuf/util/internal/protostream_objectwriter_test.cc \
-  google/protobuf/util/internal/type_info_test_helper.cc       \
-  google/protobuf/util/json_util_test.cc                       \
-  google/protobuf/util/message_differencer_unittest.cc         \
-  google/protobuf/util/time_util_test.cc                       \
-  google/protobuf/util/type_resolver_util_test.cc              \
-  google/protobuf/well_known_types_unittest.cc                 \
-  google/protobuf/wire_format_unittest.cc                      \
-  google/protobuf/wire_format_unittest.inc
-
-nodist_protobuf_test_SOURCES = $(protoc_outputs)
-$(am_protobuf_test_OBJECTS): unittest_proto_middleman
-
-# Run cpp_unittest again with PROTOBUF_TEST_NO_DESCRIPTORS defined.
-protobuf_lazy_descriptor_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la \
-                      libprotoc.la                                   \
-                      $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la        \
-                      $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la        \
-                      $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la
-protobuf_lazy_descriptor_test_CPPFLAGS = -I$(GOOGLEMOCK_SRC_DIR)/include \
-                                         -I$(GOOGLETEST_SRC_DIR)/include \
-                                         -DPROTOBUF_TEST_NO_DESCRIPTORS
-protobuf_lazy_descriptor_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
-protobuf_lazy_descriptor_test_SOURCES =                        \
-  google/protobuf/compiler/cpp/unittest.cc                     \
-  $(COMMON_TEST_SOURCES)
-nodist_protobuf_lazy_descriptor_test_SOURCES = $(protoc_outputs)
-$(am_protobuf_lazy_descriptor_test_OBJECTS): unittest_proto_middleman
-
-COMMON_LITE_TEST_SOURCES =                                             \
-  google/protobuf/arena_test_util.cc                                   \
-  google/protobuf/arena_test_util.h                                    \
-  google/protobuf/map_lite_test_util.cc                                \
-  google/protobuf/map_lite_test_util.h                                 \
-  google/protobuf/map_test_util_impl.h                                 \
-  google/protobuf/test_util_lite.cc                                    \
-  google/protobuf/test_util_lite.h
-
-# Build lite_unittest separately, since it doesn't use gtest. It can't
-# depend on gtest because our internal version of gtest depend on proto
-# full runtime and we want to make sure this test builds without full
-# runtime.
-protobuf_lite_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la     \
-                           $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la \
-                           $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la \
-                           $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la
-protobuf_lite_test_CPPFLAGS= -I$(GOOGLEMOCK_SRC_DIR)/include \
-                             -I$(GOOGLETEST_SRC_DIR)/include
-protobuf_lite_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
-protobuf_lite_test_SOURCES =                                           \
-  google/protobuf/lite_unittest.cc                                     \
-  $(COMMON_LITE_TEST_SOURCES)
-nodist_protobuf_lite_test_SOURCES = $(protoc_lite_outputs)
-$(am_protobuf_lite_test_OBJECTS): unittest_proto_middleman
-
-# lite_arena_unittest depends on gtest because teboring@ found that without
-# gtest when building the test internally our memory sanitizer doesn't detect
-# memory leaks (don't know why).
-protobuf_lite_arena_test_LDADD = $(PTHREAD_LIBS) libprotobuf-lite.la \
-                      $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la        \
-                      $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock.la        \
-                      $(GOOGLEMOCK_BUILD_DIR)/lib/libgmock_main.la
-protobuf_lite_arena_test_CPPFLAGS = -I$(GOOGLEMOCK_SRC_DIR)/include  \
-                                    -I$(GOOGLETEST_SRC_DIR)/include
-protobuf_lite_arena_test_CXXFLAGS = $(NO_OPT_CXXFLAGS)
-protobuf_lite_arena_test_SOURCES =       \
-  google/protobuf/lite_arena_unittest.cc \
-  $(COMMON_LITE_TEST_SOURCES)
-nodist_protobuf_lite_arena_test_SOURCES = $(protoc_lite_outputs)
-$(am_protobuf_lite_arena_test_OBJECTS): unittest_proto_middleman
-
-# Test plugin binary.
-test_plugin_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la \
-                    $(GOOGLETEST_BUILD_DIR)/lib/libgtest.la
-test_plugin_CPPFLAGS = -I$(GOOGLETEST_SRC_DIR)/include
-test_plugin_SOURCES =                                          \
-  google/protobuf/compiler/mock_code_generator.cc              \
-  google/protobuf/compiler/test_plugin.cc                      \
-  google/protobuf/testing/file.cc                              \
-  google/protobuf/testing/file.h
-
-if HAVE_ZLIB
-zcgzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
-zcgzip_SOURCES = google/protobuf/testing/zcgzip.cc
-
-zcgunzip_LDADD = $(PTHREAD_LIBS) libprotobuf.la
-zcgunzip_SOURCES = google/protobuf/testing/zcgunzip.cc
-endif
-
-# This test target is to ensure all our public header files and generated
-# code is free from warnings. We have to be more pedantic about these
-# files because they are compiled by users with different compiler flags.
-no_warning_test.cc:
-	echo "// Generated from Makefile.am" > no_warning_test.cc
-	for FILE in $(nobase_include_HEADERS); do \
-		case $$FILE in *.inc) continue;; esac; \
-		echo "#include <$${FILE}>" >> no_warning_test.cc; \
-	done
-	echo "int main(int, char**) { return 0; }" >> no_warning_test.cc
-
-no_warning_test_LDADD = $(PTHREAD_LIBS) libprotobuf.la libprotoc.la
-no_warning_test_CXXFLAGS = $(PTHREAD_CFLAGS) $(PTHREAD_DEF) $(ZLIB_DEF) \
-                           -Wall -Wextra -Werror -Wno-unused-parameter
-nodist_no_warning_test_SOURCES = no_warning_test.cc $(protoc_outputs)
-
-TESTS = protobuf-test protobuf-lazy-descriptor-test protobuf-lite-test \
-        google/protobuf/compiler/zip_output_unittest.sh $(GZTESTS)     \
-        protobuf-lite-arena-test no-warning-test
diff --git a/src/README.md b/src/README.md
index cf843d7..b28b0f0 100644
--- a/src/README.md
+++ b/src/README.md
@@ -5,26 +5,31 @@
 
 https://developers.google.com/protocol-buffers/
 
-C++ Installation - Unix
+CMake Installation
+-----------------------
+
+To compile or install protobuf from source using CMake, see
+[cmake/README.md](../cmake/README.md).
+
+C++ Protobuf - Unix
 -----------------------
 
 To build protobuf from source, the following tools are needed:
 
-  * autoconf
-  * automake
-  * libtool
-  * make
+  * bazel
+  * git
   * g++
-  * unzip
 
-On Ubuntu/Debian, you can install them with:
+On Ubuntu/Debian, for example, you can install them with:
 
-    sudo apt-get install autoconf automake libtool curl make g++ unzip
+    sudo apt-get install g++ git bazel
 
 On other platforms, please use the corresponding package managing tool to
-install them before proceeding.
+install them before proceeding.  See https://bazel.build/install for further
+instructions on installing Bazel, or to build from source using CMake, see
+[cmake/README.md](../cmake/README.md).
 
-To get the source, download one of the release .tar.gz or .zip packages in the
+To get the source, download the release .tar.gz or .zip package in the
 release page:
 
     https://github.com/protocolbuffers/protobuf/releases/latest
@@ -41,79 +46,23 @@
     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:
+To build the C++ Protocol Buffer runtime and the Protocol Buffer compiler
+(protoc) execute the following:
 
+    bazel build :protoc :protobuf
 
-     ./configure
-     make -j$(nproc) # $(nproc) ensures it uses all cores for compilation
-     make check
-     sudo make install
-     sudo ldconfig # refresh shared library cache.
+The compiler can then be installed, for example on Linux:
 
-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.
+    cp bazel-bin/protoc /usr/local/bin
 
-For advanced usage information on configure and make, please refer to the
-autoconf documentation:
-
-    http://www.gnu.org/software/autoconf/manual/autoconf.html#Running-configure-Scripts
-
-**Hint on install location**
-
-By default, the package will be installed to /usr/local.  However,
-on many platforms, /usr/local/lib is not part of LD_LIBRARY_PATH.
-You can add it, but it may be easier to just install to /usr
-instead.  To do this, invoke configure as follows:
-
-    ./configure --prefix=/usr
-
-If you already built the package with a different prefix, make sure
-to run "make clean" before building again.
+For more usage information on Bazel, please refer to http://bazel.build.
 
 **Compiling dependent packages**
 
-To compile a package that uses Protocol Buffers, you need to pass
-various flags to your compiler and linker.  As of version 2.2.0,
-Protocol Buffers integrates with pkg-config to manage this.  If you
-have pkg-config installed, then you can invoke it to get a list of
-flags like so:
-
-
-    pkg-config --cflags protobuf         # print compiler flags
-    pkg-config --libs protobuf           # print linker flags
-    pkg-config --cflags --libs protobuf  # print both
-
-
-For example:
-
-    c++ my_program.cc my_proto.pb.cc `pkg-config --cflags --libs protobuf`
-
-Note that packages written prior to the 2.2.0 release of Protocol
-Buffers may not yet integrate with pkg-config to get flags, and may
-not pass the correct set of flags to correctly link against
-libprotobuf.  If the package in question uses autoconf, you can
-often fix the problem by invoking its configure script like:
-
-
-    configure CXXFLAGS="$(pkg-config --cflags protobuf)" \
-              LIBS="$(pkg-config --libs protobuf)"
-
-This will force it to use the correct flags.
-
-If you are writing an autoconf-based package that uses Protocol
-Buffers, you should probably use the PKG_CHECK_MODULES macro in your
-configure script like:
-
-    PKG_CHECK_MODULES([protobuf], [protobuf])
-
-See the pkg-config man page for more info.
-
-If you only want protobuf-lite, substitute "protobuf-lite" in place
-of "protobuf" in these examples.
+To compile a package that uses Protocol Buffers, you need to setup a Bazel
+WORKSPACE that's hooked up to the protobuf repository and loads its
+dependencies.  For an example, see [WORKSPACE](../examples/WORKSPACE).
 
 **Note for Mac users**
 
@@ -127,64 +76,16 @@
 https://www.macports.org . This will reside in /opt/local/bin/port for most
 Mac installations.
 
-    sudo /opt/local/bin/port install autoconf automake libtool
+    sudo /opt/local/bin/port install bazel
 
 Alternative for Homebrew users:
 
-    brew install autoconf automake libtool
+    brew install bazel
 
 Then follow the Unix instructions above.
 
-**Note for cross-compiling**
 
-The makefiles normally invoke the protoc executable that they just
-built in order to build tests.  When cross-compiling, the protoc
-executable may not be executable on the host machine.  In this case,
-you must build a copy of protoc for the host machine first, then use
-the --with-protoc option to tell configure to use it instead.  For
-example:
-
-    ./configure --with-protoc=protoc
-
-This will use the installed protoc (found in your $PATH) instead of
-trying to execute the one built during the build process.  You can
-also use an executable that hasn't been installed.  For example, if
-you built the protobuf package for your host machine in ../host,
-you might do:
-
-    ./configure --with-protoc=../host/src/protoc
-
-Either way, you must make sure that the protoc executable you use
-has the same version as the protobuf source code you are trying to
-use it with.
-
-**Note for Solaris users**
-
-Solaris 10 x86 has a bug that will make linking fail, complaining
-about libstdc++.la being invalid.  We have included a work-around
-in this package.  To use the work-around, run configure as follows:
-
-    ./configure LDFLAGS=-L$PWD/src/solaris
-
-See src/solaris/libstdc++.la for more info on this bug.
-
-**Note for HP C++ Tru64 users**
-
-To compile invoke configure as follows:
-
-    ./configure CXXFLAGS="-O -std ansi -ieee -D__USE_STD_IOSTREAM"
-
-Also, you will need to use gmake instead of make.
-
-**Note for AIX users**
-
-Compile using the IBM xlC C++ compiler as follows:
-
-    ./configure CXX=xlC
-
-Also, you will need to use GNU `make` (`gmake`) instead of AIX `make`.
-
-C++ Installation - Windows
+C++ Protobuf - Windows
 --------------------------
 
 If you only need the protoc binary, you can download it from the release
@@ -220,10 +121,10 @@
 libprotobuf, it is unlikely to work with a newer version without
 re-compiling.  This problem, when it occurs, will normally be detected
 immediately on startup of your app.  Still, you may want to consider
-using static linkage.  You can configure this package to install
-static libraries only using:
+using static linkage.  You can configure this in your `cc_binary` Bazel rules
+by specifying:
 
-    ./configure --disable-shared
+    linkstatic=True
 
 Usage
 -----
diff --git a/src/file_lists.cmake b/src/file_lists.cmake
new file mode 100644
index 0000000..1e326bc
--- /dev/null
+++ b/src/file_lists.cmake
@@ -0,0 +1,721 @@
+# Auto-generated by //pkg:gen_src_file_lists_cmake
+#
+# This file contains lists of sources based on Bazel rules. It should
+# be included from a hand-written CMake file that defines targets.
+#
+# Changes to this file will be overwritten based on Bazel definitions.
+
+if(${CMAKE_VERSION} VERSION_GREATER 3.10 OR ${CMAKE_VERSION} VERSION_EQUAL 3.10)
+  include_guard()
+endif()
+
+# //pkg:protobuf
+set(libprotobuf_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/duration.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/empty.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/type.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_align.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_config.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/dynamic_message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_heavy.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_bases.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_full.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_gen.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/gzip_stream.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/strtod.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_sink.cc
+  ${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/json/internal/lexer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/message_path.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/parser.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/unparser.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/untyped_message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/writer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/json.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/message.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/reflection_ops.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/service.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/text_format.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.cc
+)
+
+# //pkg:protobuf
+set(libprotobuf_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/api.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/duration.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/empty.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/type.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_align.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_allocation_policy.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_cleanup.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_config.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_impl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/dynamic_message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/endian.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/explicitly_constructed.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_inl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/field_access_listener.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_reflection.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_bases.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_decl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_gen.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_impl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/has_bits.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/gzip_stream.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/strtod.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_sink.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/descriptor_traits.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/lexer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/message_path.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/parser.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/parser_traits.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/unparser.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/unparser_traits.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/untyped_message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/writer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/internal/zero_copy_buffered_stream.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/json/json.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_entry.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_entry_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_inl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_type_handler.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/message_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/metadata.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/metadata_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/parse_context.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/port.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/port_def.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/port_undef.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_internal.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/service.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/callback.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/logging.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/mathutil.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/platform_macros.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/port.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status_macros.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/text_format.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.h
+)
+
+# //pkg:protobuf_lite
+set(libprotobuf_lite_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_align.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_config.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler.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_tctable_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.cc
+  ${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
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.cc
+)
+
+# //pkg:protobuf_lite
+set(libprotobuf_lite_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_align.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_allocation_policy.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_cleanup.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_config.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_impl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/endian.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/explicitly_constructed.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_inl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_enum_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_decl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_impl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/has_bits.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/implicit_weak_message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_entry_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_type_handler.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/message_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/metadata_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/parse_context.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/port.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/port_def.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/port_undef.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_ptr_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/callback.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/logging.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/mathutil.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/platform_macros.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/port.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/status_macros.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_lite.h
+)
+
+# //pkg:protoc
+set(libprotoc_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/extension.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/map_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/padding_optimizer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/parse_function_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/primitive_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/service.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/string_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/names.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/context.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/file.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator_factory.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/helpers.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_serialization.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/name_resolver.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/names.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/service.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/shared_code_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field_lite.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/extension.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/file.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/helpers.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/import_writer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/line_consumer.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/map_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/message.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/message_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/names.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/oneof.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/primitive_field.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/names.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.pb.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/helpers.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/pyi_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/subprocess.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/zip_writer.cc
+)
+
+# //pkg:protoc
+set(libprotoc_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/code_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/enum_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/extension.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/file.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/helpers.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/map_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_layout_helper.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/names.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/options.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/padding_optimizer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/parse_function_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/primitive_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/service.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/string_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_enum_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_field_base.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_helpers.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_map_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_message_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_options.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/names.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/context.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_field_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/enum_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/extension_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/file.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/generator_factory.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/helpers.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/kotlin_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/map_field_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_builder_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_field_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_serialization.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/name_resolver.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/names.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/options.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/primitive_field_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/service.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/shared_code_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/string_field_lite.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/enum_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/extension.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/file.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/helpers.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/import_writer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/line_consumer.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/map_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/message.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/message_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/names.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/nsobject_methods.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/oneof.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/options.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/primitive_field.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/text_format_decode_data.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/names.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/php/php_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.pb.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/helpers.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/pyi_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/scc.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/subprocess.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/zip_writer.h
+)
+
+# //src/google/protobuf:well_known_type_protos
+set(wkt_protos_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/api.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/duration.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/empty.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/field_mask.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/source_context.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/struct.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/timestamp.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/type.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wrappers.proto
+)
+
+# //src/google/protobuf:descriptor_proto
+set(descriptor_proto_proto_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.proto
+)
+
+# //src/google/protobuf:descriptor_proto
+set(descriptor_proto_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.proto.pb.cc
+)
+
+# //src/google/protobuf:descriptor_proto
+set(descriptor_proto_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor.proto.pb.h
+)
+
+# //src/google/protobuf:descriptor_proto
+set(descriptor_proto_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_proto-descriptor-set.proto.bin
+)
+
+# //src/google/protobuf/compiler:plugin_proto
+set(plugin_proto_proto_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.proto
+)
+
+# //src/google/protobuf/compiler:plugin_proto
+set(plugin_proto_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.proto.pb.cc
+)
+
+# //src/google/protobuf/compiler:plugin_proto
+set(plugin_proto_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin.proto.pb.h
+)
+
+# //src/google/protobuf/compiler:plugin_proto
+set(plugin_proto_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/plugin_proto-descriptor-set.proto.bin
+)
+
+# //pkg:common_test
+set(common_test_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/googletest.cc
+)
+
+# //pkg:common_test
+set(common_test_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/mock_code_generator.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/file.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/testing/googletest.h
+)
+
+# //pkg:lite_test_util
+set(lite_test_util_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_test_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_test_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util_lite.cc
+)
+
+# //pkg:lite_test_util
+set(lite_test_util_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_test_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_test_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test_util_impl.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_lite_unittest.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util2.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util_lite.h
+)
+
+# //pkg:test_util
+set(test_util_srcs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_tester.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util.cc
+)
+
+# //pkg:test_util
+set(test_util_hdrs
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/annotation_test_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/unittest.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/unittest.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test_util.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/message_unittest.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_tester.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util.h
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/test_util.inc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_unittest.inc
+)
+
+# //src/google/protobuf:full_test_srcs
+set(protobuf_test_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_align_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arena_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenastring_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/arenaz_sampler_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_database_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/descriptor_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/drop_unknown_fields_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/dynamic_message_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/extension_set_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_reflection_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/generated_message_tctable_lite_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/inlined_string_field_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_field_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/message_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/no_field_presence_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/preserve_unknown_enum_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_arena_lite_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_arena_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/proto3_lite_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/reflection_ops_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_reflection_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/repeated_field_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/text_format_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unknown_field_set_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/well_known_types_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/wire_format_unittest.cc
+)
+
+# //src/google/protobuf:test_proto_srcs
+set(protobuf_test_protos_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/any_test.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_proto2_unittest.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_unittest.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_arena.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_custom_options.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_drop_unknown_fields.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_embed_optimize_for.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_empty.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_enormous_descriptor.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lazy_dependencies_enum.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite_imports_nonlite.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_mset_wire_format.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_field_presence.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_no_generic_services.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_optimize_for.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_preserve_unknown_enum2.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_arena_lite.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_lite.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_proto3_optional.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_well_known_types.proto
+)
+
+# //src/google/protobuf:lite_test_srcs
+set(protobuf_lite_test_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/lite_arena_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/lite_unittest.cc
+)
+
+# //src/google/protobuf:lite_test_proto_srcs
+set(protobuf_lite_test_protos_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/map_lite_unittest.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_lite.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_import_public_lite.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/unittest_lite.proto
+)
+
+# //src/google/protobuf/compiler:test_srcs
+set(compiler_test_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/command_line_interface_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/message_size_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/metadata_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/move_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/plugin_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/importer_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/doc_comment_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/message_serialization_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/java/plugin_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/names_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/parser_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/python/plugin_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
+)
+
+# //src/google/protobuf/compiler:test_proto_srcs
+set(compiler_test_protos_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/cpp/test_large_enum_value.proto
+)
+
+# //src/google/protobuf/compiler:test_plugin_srcs
+set(test_plugin_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/compiler/test_plugin.cc
+)
+
+# //src/google/protobuf/io:test_srcs
+set(io_test_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/coded_stream_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/io_win32_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer_death_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/printer_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/tokenizer_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_sink_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/io/zero_copy_stream_unittest.cc
+)
+
+# //src/google/protobuf/util:test_srcs
+set(util_test_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/delimited_message_util_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_comparator_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/field_mask_util_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer_unittest.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/time_util_test.cc
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/type_resolver_util_test.cc
+)
+
+# //src/google/protobuf/util:test_proto_srcs
+set(util_test_protos_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_format.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/json_format_proto3.proto
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/util/message_differencer_unittest.proto
+)
+
+# //src/google/protobuf/stubs:test_srcs
+set(stubs_test_files
+  ${protobuf_SOURCE_DIR}/src/google/protobuf/stubs/common_unittest.cc
+)
diff --git a/src/google/protobuf/BUILD.bazel b/src/google/protobuf/BUILD.bazel
new file mode 100644
index 0000000..48a8115
--- /dev/null
+++ b/src/google/protobuf/BUILD.bazel
@@ -0,0 +1,1311 @@
+################################################################################
+# Protocol Buffers: C++ Runtime and common proto files
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_proto_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("@upb//cmake:build_defs.bzl", "staleness_test")
+load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS")
+
+package(
+    default_visibility = [
+        "//:__pkg__",  # "public" targets are alias rules in //.
+        "//json:__subpackages__",
+    ],
+)
+
+proto_library(
+    name = "any_proto",
+    srcs = ["any.proto"],
+    strip_import_prefix = "/src",
+)
+
+proto_library(
+    name = "api_proto",
+    srcs = ["api.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:source_context_proto",
+        "//:type_proto",
+    ],
+)
+
+proto_library(
+    name = "duration_proto",
+    srcs = ["duration.proto"],
+    strip_import_prefix = "/src",
+)
+
+proto_library(
+    name = "empty_proto",
+    srcs = ["empty.proto"],
+    strip_import_prefix = "/src",
+)
+
+proto_library(
+    name = "field_mask_proto",
+    srcs = ["field_mask.proto"],
+    strip_import_prefix = "/src",
+)
+
+proto_library(
+    name = "source_context_proto",
+    srcs = ["source_context.proto"],
+    strip_import_prefix = "/src",
+)
+
+proto_library(
+    name = "struct_proto",
+    srcs = ["struct.proto"],
+    strip_import_prefix = "/src",
+)
+
+proto_library(
+    name = "timestamp_proto",
+    srcs = ["timestamp.proto"],
+    strip_import_prefix = "/src",
+)
+
+proto_library(
+    name = "type_proto",
+    srcs = ["type.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:any_proto",
+        "//:source_context_proto",
+    ],
+)
+
+proto_library(
+    name = "wrappers_proto",
+    srcs = ["wrappers.proto"],
+    strip_import_prefix = "/src",
+)
+
+# Generate code for the well-known types on demand.
+# This needs to be done in a separate genrule because we publish protoc and the
+# C++ runtime with the WKT code linked in.  We need to use a stripped down
+# compiler and runtime library to generate them, and cc_proto_library doesn't
+# support swapping out the compiler binary (even though a custom runtime can
+# be passed to proto_lang_toolchain).
+#
+# TODO(b/246826624) We still check in generated pb.h and pb.cc files purely to
+# support CMake builds.  These aren't used at all by Bazel and will be removed
+# in the future once CMake can generate them too.
+
+WELL_KNOWN_TYPES = [
+    "any",
+    "api",
+    "duration",
+    "empty",
+    "field_mask",
+    "source_context",
+    "struct",
+    "timestamp",
+    "type",
+    "wrappers",
+]
+
+# When we generate code for the well-known types, we put the resulting files in
+# wkt/google/protobuf and add ./wkt to the include paths below. This is a
+# somewhat strange setup but is necessary to satisfy these two constraints:
+# - We need to keep the checked-in sources for now, since Cocoapods relies on
+#   them.
+# - The Bazel build should always use the generated sources so that developers
+#   don't have to worry about manually updating the checked-in sources.
+genrule(
+    name = "gen_wkt_cc_sources",
+    srcs = [wkt + ".proto" for wkt in WELL_KNOWN_TYPES],
+    outs =
+        ["wkt/google/protobuf/" + wkt + ".pb.h" for wkt in WELL_KNOWN_TYPES] +
+        ["wkt/google/protobuf/" + wkt + ".pb.cc" for wkt in WELL_KNOWN_TYPES],
+    cmd = """
+        $(execpath //src/google/protobuf/compiler:protoc_nowkt) \
+            --cpp_out=dllexport_decl=PROTOBUF_EXPORT:$(RULEDIR)/wkt \
+            --proto_path=$$(dirname $$(dirname $$(dirname $(location any.proto)))) \
+            $(SRCS)
+    """,
+    exec_tools = ["//src/google/protobuf/compiler:protoc_nowkt"],
+    visibility = ["//visibility:private"],
+)
+
+staleness_test(
+    name = "well_known_types_staleness_test",
+    outs =
+        [wkt + ".pb.h" for wkt in WELL_KNOWN_TYPES] +
+        [wkt + ".pb.cc" for wkt in WELL_KNOWN_TYPES],
+    generated_pattern = "wkt/google/protobuf/%s",
+    tags = ["manual"],
+)
+
+cc_library(
+    name = "wkt_cc_proto",
+    srcs = ["wkt/google/protobuf/" + wkt + ".pb.cc" for wkt in WELL_KNOWN_TYPES],
+    hdrs = ["wkt/google/protobuf/" + wkt + ".pb.h" for wkt in WELL_KNOWN_TYPES],
+    copts = COPTS,
+    includes = ["wkt"],
+    linkopts = LINK_OPTS,
+    visibility = ["//pkg:__pkg__"],
+    deps = [":protobuf_nowkt"],
+)
+
+# Built-in runtime types
+
+proto_library(
+    name = "descriptor_proto",
+    srcs = ["descriptor.proto"],
+    strip_import_prefix = "/src",
+    visibility = [
+        "//:__pkg__",
+        "//pkg:__pkg__",
+    ],
+)
+
+################################################################################
+# C++ Runtime Library
+################################################################################
+
+cc_library(
+    name = "port_def",
+    hdrs = [
+        "port.h",
+        "port_def.inc",
+        "port_undef.inc",
+    ],
+    include_prefix = "google/protobuf",
+    visibility = [
+        "//:__subpackages__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+)
+
+cc_library(
+    name = "arena_align",
+    srcs = ["arena_align.cc"],
+    hdrs = ["arena_align.h"],
+    include_prefix = "google/protobuf",
+    visibility = [
+        "//:__subpackages__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        "//src/google/protobuf/stubs:lite",
+        "@com_google_absl//absl/numeric:bits",
+    ],
+)
+
+cc_library(
+    name = "arena_cleanup",
+    hdrs = ["arena_cleanup.h"],
+    include_prefix = "google/protobuf",
+    visibility = [
+        "//:__subpackages__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        "@com_google_absl//absl/base:core_headers",
+    ],
+)
+
+cc_library(
+    name = "arena_config",
+    srcs = ["arena_config.cc"],
+    hdrs = ["arena_config.h"],
+    include_prefix = "google/protobuf",
+    visibility = [
+        "//:__subpackages__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        "//src/google/protobuf/stubs:lite",
+    ],
+)
+
+cc_library(
+    name = "arena_allocation_policy",
+    hdrs = ["arena_allocation_policy.h"],
+    include_prefix = "google/protobuf",
+    visibility = [
+        "//:__subpackages__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        ":arena_config",
+        "//src/google/protobuf/stubs:lite",
+    ],
+)
+
+cc_library(
+    name = "arena",
+    srcs = [
+        "arena.cc",
+    ],
+    hdrs = [
+        "arena.h",
+        "arena_config.h",
+        "arena_impl.h",
+        "arenaz_sampler.h",
+    ],
+    include_prefix = "google/protobuf",
+    visibility = [
+        "//:__subpackages__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        ":arena_allocation_policy",
+        ":arena_cleanup",
+        ":arena_config",
+        "//src/google/protobuf/stubs:lite",
+        "@com_google_absl//absl/synchronization",
+    ],
+)
+
+cc_library(
+    name = "protobuf_lite",
+    srcs = [
+        "any_lite.cc",
+        "arenastring.cc",
+        "arenaz_sampler.cc",
+        "extension_set.cc",
+        "generated_enum_util.cc",
+        "generated_message_tctable_lite.cc",
+        "generated_message_util.cc",
+        "implicit_weak_message.cc",
+        "inlined_string_field.cc",
+        "map.cc",
+        "message_lite.cc",
+        "parse_context.cc",
+        "repeated_field.cc",
+        "repeated_ptr_field.cc",
+        "wire_format_lite.cc",
+    ],
+    hdrs = [
+        "any.h",
+        "arena.h",
+        "arena_impl.h",
+        "arenastring.h",
+        "arenaz_sampler.h",
+        "endian.h",
+        "explicitly_constructed.h",
+        "extension_set.h",
+        "extension_set_inl.h",
+        "generated_enum_util.h",
+        "generated_message_tctable_decl.h",
+        "generated_message_tctable_impl.h",
+        "generated_message_util.h",
+        "has_bits.h",
+        "implicit_weak_message.h",
+        "inlined_string_field.h",
+        "map.h",
+        "map_entry_lite.h",
+        "map_field_lite.h",
+        "map_type_handler.h",
+        "message_lite.h",
+        "metadata_lite.h",
+        "parse_context.h",
+        "port.h",
+        "repeated_field.h",
+        "repeated_ptr_field.h",
+        "wire_format_lite.h",
+    ],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error",
+        ],
+    }),
+    include_prefix = "google/protobuf",
+    linkopts = LINK_OPTS,
+    visibility = [
+        "//:__pkg__",
+        "//pkg:__pkg__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    # In Bazel 6.0+, these will be `interface_deps`:
+    deps = [
+        ":arena",
+        ":arena_config",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs:lite",
+        "@com_google_absl//absl/cleanup",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/numeric:bits",
+        "@com_google_absl//absl/strings:internal",
+        "@com_google_absl//absl/synchronization",
+        "@com_google_absl//absl/time",
+        "@utf8_range//:utf8_validity",
+    ],
+)
+
+cc_library(
+    name = "protobuf_nowkt",
+    srcs = [
+        "any.cc",
+        "descriptor.cc",
+        "descriptor.pb.cc",
+        "descriptor_database.cc",
+        "dynamic_message.cc",
+        "extension_set_heavy.cc",
+        "generated_message_bases.cc",
+        "generated_message_reflection.cc",
+        "generated_message_tctable_full.cc",
+        "generated_message_tctable_gen.cc",
+        "map_field.cc",
+        "message.cc",
+        "reflection_ops.cc",
+        "service.cc",
+        "text_format.cc",
+        "unknown_field_set.cc",
+        "wire_format.cc",
+    ],
+    hdrs = [
+        "descriptor.h",
+        "descriptor.pb.h",
+        "descriptor_database.h",
+        "dynamic_message.h",
+        "field_access_listener.h",
+        "generated_enum_reflection.h",
+        "generated_message_bases.h",
+        "generated_message_reflection.h",
+        "generated_message_tctable_gen.h",
+        "map_entry.h",
+        "map_field.h",
+        "map_field_inl.h",
+        "message.h",
+        "metadata.h",
+        "reflection.h",
+        "reflection_internal.h",
+        "reflection_ops.h",
+        "service.h",
+        "text_format.h",
+        "unknown_field_set.h",
+        "wire_format.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf",
+    linkopts = LINK_OPTS,
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        ":protobuf_lite",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/io:gzip_stream",
+        "//src/google/protobuf/io:printer",
+        "//src/google/protobuf/io:tokenizer",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/base",
+        "@com_google_absl//absl/base:dynamic_annotations",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/hash",
+        "@com_google_absl//absl/strings:internal",
+        "@com_google_absl//absl/synchronization",
+        "@com_google_absl//absl/time",
+        "@utf8_range//:utf8_validity",
+    ],
+)
+
+cc_library(
+    name = "protobuf",
+    copts = COPTS,
+    include_prefix = "google/protobuf",
+    linkopts = LINK_OPTS,
+    visibility = [
+        "//:__pkg__",
+        "//pkg:__pkg__",
+        "//src/google/protobuf:__subpackages__",
+    ],
+    deps = [
+        ":protobuf_nowkt",
+        ":wkt_cc_proto",
+    ],
+)
+
+# This provides just the header files for use in projects that need to build
+# shared libraries for dynamic loading. This target is available until Bazel
+# adds native support for such use cases.
+# TODO(keveman): Remove this target once the support gets added to Bazel.
+cc_library(
+    name = "protobuf_headers",
+    hdrs = glob([
+        "**/*.h",
+        "**/*.inc",
+    ]),
+)
+
+filegroup(
+    name = "well_known_type_protos",
+    srcs = [
+        "any.proto",
+        "api.proto",
+        "duration.proto",
+        "empty.proto",
+        "field_mask.proto",
+        "source_context.proto",
+        "struct.proto",
+        "timestamp.proto",
+        "type.proto",
+        "wrappers.proto",
+    ],
+    visibility = ["//:__subpackages__"],
+)
+
+filegroup(
+    name = "descriptor_proto_srcs",
+    srcs = ["descriptor.proto"],
+    visibility = ["//:__subpackages__"],
+)
+
+filegroup(
+    name = "testdata",
+    srcs = glob(["testdata/**/*"]) + [
+        "descriptor.cc",
+    ],
+    visibility = [
+        "//:__subpackages__",
+        "@upb//:__subpackages__",
+    ],
+)
+
+filegroup(
+    name = "lite_test_proto_srcs",
+    srcs = [
+        "map_lite_unittest.proto",
+        "unittest_import_lite.proto",
+        "unittest_import_public_lite.proto",
+        "unittest_lite.proto",
+    ],
+    visibility = ["//:__subpackages__"],
+)
+
+proto_library(
+    name = "lite_test_protos",
+    srcs = [":lite_test_proto_srcs"],
+    strip_import_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    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",
+    ],
+)
+
+filegroup(
+    name = "test_proto_srcs",
+    srcs = [
+        "any_test.proto",
+        "map_proto2_unittest.proto",
+        "map_unittest.proto",
+        "unittest.proto",
+        "unittest_arena.proto",
+        "unittest_custom_options.proto",
+        "unittest_drop_unknown_fields.proto",
+        "unittest_embed_optimize_for.proto",
+        "unittest_empty.proto",
+        "unittest_enormous_descriptor.proto",
+        "unittest_import.proto",
+        "unittest_import_public.proto",
+        "unittest_lazy_dependencies.proto",
+        "unittest_lazy_dependencies_custom_option.proto",
+        "unittest_lazy_dependencies_enum.proto",
+        "unittest_lite_imports_nonlite.proto",
+        "unittest_mset.proto",
+        "unittest_mset_wire_format.proto",
+        "unittest_no_field_presence.proto",
+        "unittest_no_generic_services.proto",
+        "unittest_optimize_for.proto",
+        "unittest_preserve_unknown_enum.proto",
+        "unittest_preserve_unknown_enum2.proto",
+        "unittest_proto3.proto",
+        "unittest_proto3_arena.proto",
+        "unittest_proto3_arena_lite.proto",
+        "unittest_proto3_lite.proto",
+        "unittest_proto3_optional.proto",
+        "unittest_well_known_types.proto",
+    ],
+    visibility = ["//:__subpackages__"],
+)
+
+proto_library(
+    name = "test_protos",
+    srcs = [":test_proto_srcs"],
+    strip_import_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    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",
+    ],
+)
+
+proto_library(
+    name = "generic_test_protos",
+    srcs = [
+        "map_proto2_unittest.proto",
+        "map_unittest.proto",
+        "unittest.proto",
+        "unittest_arena.proto",
+        "unittest_custom_options.proto",
+        "unittest_drop_unknown_fields.proto",
+        "unittest_embed_optimize_for.proto",
+        "unittest_empty.proto",
+        "unittest_enormous_descriptor.proto",
+        "unittest_import.proto",
+        "unittest_import_public.proto",
+        "unittest_lazy_dependencies.proto",
+        "unittest_lazy_dependencies_custom_option.proto",
+        "unittest_lazy_dependencies_enum.proto",
+        "unittest_lite_imports_nonlite.proto",
+        "unittest_mset.proto",
+        "unittest_mset_wire_format.proto",
+        "unittest_no_field_presence.proto",
+        "unittest_no_generic_services.proto",
+        "unittest_optimize_for.proto",
+        "unittest_preserve_unknown_enum.proto",
+        "unittest_preserve_unknown_enum2.proto",
+        "unittest_proto3.proto",
+        "unittest_proto3_arena.proto",
+        "unittest_proto3_arena_lite.proto",
+        "unittest_proto3_lite.proto",
+        "unittest_proto3_optional.proto",
+        "unittest_well_known_types.proto",
+    ],
+    strip_import_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    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",
+    ],
+)
+
+exports_files(
+    [
+        "test_messages_proto2.proto",
+        "test_messages_proto3.proto",
+    ],
+    visibility = [
+        "//:__pkg__",
+        "//python:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "test_messages_proto2_proto",
+    srcs = ["test_messages_proto2.proto"],
+    strip_import_prefix = "/src",
+    visibility = [
+        "//:__pkg__",
+        "//conformance:__pkg__",
+        "@upb//:__subpackages__",
+    ],
+)
+
+proto_library(
+    name = "test_messages_proto3_proto",
+    srcs = ["test_messages_proto3.proto"],
+    strip_import_prefix = "/src",
+    visibility = [
+        "//:__pkg__",
+        "//conformance:__pkg__",
+        "@upb//:__subpackages__",
+    ],
+    deps = [
+        ":any_proto",
+        ":duration_proto",
+        ":field_mask_proto",
+        ":struct_proto",
+        ":timestamp_proto",
+        ":wrappers_proto",
+    ],
+)
+
+cc_proto_library(
+    name = "cc_lite_test_protos",
+    deps = [":lite_test_protos"],
+)
+
+cc_proto_library(
+    name = "cc_test_protos",
+    visibility = ["//src/google/protobuf:__subpackages__"],
+    deps = [":test_protos"],
+)
+
+# Filegroup for golden comparison test:
+filegroup(
+    name = "descriptor_cc_srcs",
+    testonly = 1,
+    data = [
+        "descriptor.pb.cc",
+        "descriptor.pb.h",
+    ],
+    visibility = ["//src/google/protobuf/compiler/cpp:__pkg__"],
+)
+
+cc_library(
+    name = "lite_test_util",
+    testonly = 1,
+    srcs = [
+        "arena_test_util.cc",
+        "map_lite_test_util.cc",
+        "test_util_lite.cc",
+    ],
+    hdrs = [
+        "arena_test_util.h",
+        "map_lite_test_util.h",
+        "map_test_util_impl.h",
+        "proto3_lite_unittest.inc",
+        "test_util_lite.h",
+    ],
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        ":cc_lite_test_protos",
+        ":test_util2",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "test_util",
+    testonly = 1,
+    srcs = [
+        "reflection_tester.cc",
+        "test_util.cc",
+    ],
+    hdrs = [
+        "map_test.inc",
+        "map_test_util.h",
+        "map_test_util.inc",
+        "message_unittest.inc",
+        "reflection_tester.h",
+        "test_util.h",
+        "test_util.inc",
+        "test_util_lite.h",
+        "wire_format_unittest.inc",
+    ],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        ":cc_lite_test_protos",
+        ":cc_test_protos",
+        ":lite_test_util",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_library(
+    name = "test_util2",
+    testonly = 1,
+    hdrs = ["test_util2.h"],
+    strip_include_prefix = "/src",
+    textual_hdrs = ["test_util.inc"],
+    visibility = ["//:__subpackages__"],
+    deps = [
+        "//src/google/protobuf/io",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+cc_test(
+    name = "any_test",
+    srcs = ["any_test.cc"],
+    deps = [
+        ":protobuf",
+        ":test_util",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "arena_align_test",
+    srcs = ["arena_align_test.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":arena_align",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "arena_unittest",
+    srcs = ["arena_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":lite_test_util",
+        ":protobuf",
+        ":test_util",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "arenastring_unittest",
+    srcs = ["arenastring_unittest.cc"],
+    deps = [
+        ":protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "arenaz_sampler_test",
+    srcs = ["arenaz_sampler_test.cc"],
+    deps = [
+        ":protobuf",
+        "//src/google/protobuf/stubs",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "descriptor_database_unittest",
+    srcs = ["descriptor_database_unittest.cc"],
+    deps = [
+        ":protobuf",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "descriptor_unittest",
+    srcs = ["descriptor_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "//src/google/protobuf/compiler:importer",
+        "//src/google/protobuf/testing",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "drop_unknown_fields_test",
+    srcs = ["drop_unknown_fields_test.cc"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "dynamic_message_unittest",
+    srcs = ["dynamic_message_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "extension_set_unittest",
+    srcs = ["extension_set_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "generated_message_reflection_unittest",
+    srcs = ["generated_message_reflection_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "generated_message_tctable_lite_test",
+    srcs = ["generated_message_tctable_lite_test.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":protobuf_lite",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "inlined_string_field_unittest",
+    srcs = ["inlined_string_field_unittest.cc"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "lite_arena_unittest",
+    srcs = ["lite_arena_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":lite_test_util",
+        ":protobuf",
+        ":test_util",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "lite_unittest",
+    srcs = ["lite_unittest.cc"],
+    deps = [
+        ":cc_lite_test_protos",
+        ":lite_test_util",
+        ":protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "map_field_test",
+    srcs = ["map_field_test.cc"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "map_test",
+    srcs = [
+        "map_test.cc",
+        "map_test.inc",
+    ],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    data = [":testdata"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "message_unittest",
+    srcs = [
+        "message_unittest.cc",
+        "message_unittest.inc",
+    ],
+    data = [":testdata"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "no_field_presence_test",
+    srcs = ["no_field_presence_test.cc"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "preserve_unknown_enum_test",
+    srcs = ["preserve_unknown_enum_test.cc"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "proto3_arena_lite_unittest",
+    srcs = ["proto3_arena_lite_unittest.cc"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "proto3_arena_unittest",
+    srcs = ["proto3_arena_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "proto3_lite_unittest",
+    srcs = [
+        "proto3_lite_unittest.cc",
+        "proto3_lite_unittest.inc",
+    ],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":lite_test_util",
+        ":protobuf",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "reflection_ops_unittest",
+    srcs = ["reflection_ops_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "repeated_field_reflection_unittest",
+    srcs = ["repeated_field_reflection_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/stubs",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "repeated_field_unittest",
+    srcs = ["repeated_field_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "text_format_unittest",
+    srcs = ["text_format_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    data = [":testdata"],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "unknown_field_set_unittest",
+    srcs = ["unknown_field_set_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-error=sign-compare",
+        ],
+    }),
+    deps = [
+        ":cc_lite_test_protos",
+        ":protobuf",
+        ":test_util",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_absl//absl/synchronization",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "well_known_types_unittest",
+    srcs = ["well_known_types_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "wire_format_unittest",
+    srcs = [
+        "wire_format_unittest.cc",
+        "wire_format_unittest.inc",
+    ],
+    deps = [
+        ":cc_test_protos",
+        ":protobuf",
+        ":test_util",
+        ":test_util2",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Helper targets for Kotlin tests
+################################################################################
+
+proto_library(
+    name = "kt_unittest_protos",
+    srcs = [
+        "map_proto2_unittest.proto",
+        "unittest.proto",
+        "unittest_import.proto",
+        "unittest_import_public.proto",
+    ],
+    strip_import_prefix = "/src",
+    visibility = ["//java/kotlin:__pkg__"],
+)
+
+proto_library(
+    name = "kt_proto3_unittest_protos",
+    srcs = [
+        "unittest_import.proto",
+        "unittest_import_public.proto",
+        "unittest_proto3.proto",
+    ],
+    strip_import_prefix = "/src",
+    visibility = [
+        "//java/kotlin:__pkg__",
+        "//java/kotlin-lite:__pkg__",
+    ],
+)
+
+################################################################################
+# Packaging rules
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "full_test_srcs",
+    srcs = glob(
+        include = [
+            "*_test.cc",
+            "*unittest.cc",
+        ],
+        exclude = [
+            "lite_unittest.cc",
+            "lite_arena_unittest.cc",
+        ],
+    ),
+    visibility = ["//pkg:__pkg__"],
+)
+
+filegroup(
+    name = "lite_test_srcs",
+    srcs = [
+        "lite_arena_unittest.cc",
+        "lite_unittest.cc",
+    ],
+    visibility = ["//pkg:__pkg__"],
+)
diff --git a/src/google/protobuf/any.cc b/src/google/protobuf/any.cc
index 346fa19..1f6ef87 100644
--- a/src/google/protobuf/any.cc
+++ b/src/google/protobuf/any.cc
@@ -28,15 +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.
 
-#include <google/protobuf/any.h>
+#include "google/protobuf/any.h"
 
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/message.h>
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/message.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -47,7 +47,7 @@
 }
 
 bool AnyMetadata::PackFrom(Arena* arena, const Message& message,
-                           StringPiece type_url_prefix) {
+                           absl::string_view type_url_prefix) {
   type_url_->Set(
       GetTypeUrl(message.GetDescriptor()->full_name(), type_url_prefix), arena);
   return message.SerializeToString(value_->Mutable(arena));
@@ -79,4 +79,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/any.h b/src/google/protobuf/any.h
index 92ea2bb..ab71a6c 100644
--- a/src/google/protobuf/any.h
+++ b/src/google/protobuf/any.h
@@ -33,12 +33,12 @@
 
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/port.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/message_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -52,8 +52,8 @@
 extern const char kTypeGoogleApisComPrefix[];  // "type.googleapis.com/".
 extern const char kTypeGoogleProdComPrefix[];  // "type.googleprod.com/".
 
-std::string GetTypeUrl(StringPiece message_name,
-                       StringPiece type_url_prefix);
+std::string GetTypeUrl(absl::string_view message_name,
+                       absl::string_view type_url_prefix);
 
 // Helper class used to implement google::protobuf::Any.
 class PROTOBUF_EXPORT AnyMetadata {
@@ -63,6 +63,8 @@
   // AnyMetadata does not take ownership of "type_url" and "value".
   constexpr AnyMetadata(UrlType* type_url, ValueType* value)
       : type_url_(type_url), value_(value) {}
+  AnyMetadata(const AnyMetadata&) = delete;
+  AnyMetadata& operator=(const AnyMetadata&) = delete;
 
   // Packs a message using the default type URL prefix: "type.googleapis.com".
   // The resulted type URL will be "type.googleapis.com/<message_full_name>".
@@ -84,13 +86,13 @@
   // Returns false if serializing the message failed.
   template <typename T>
   bool PackFrom(Arena* arena, const T& message,
-                StringPiece type_url_prefix) {
+                absl::string_view type_url_prefix) {
     return InternalPackFrom(arena, message, type_url_prefix,
                             T::FullMessageName());
   }
 
   bool PackFrom(Arena* arena, const Message& message,
-                StringPiece type_url_prefix);
+                absl::string_view 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
@@ -113,16 +115,14 @@
 
  private:
   bool InternalPackFrom(Arena* arena, const MessageLite& message,
-                        StringPiece type_url_prefix,
-                        StringPiece type_name);
-  bool InternalUnpackTo(StringPiece type_name,
+                        absl::string_view type_url_prefix,
+                        absl::string_view type_name);
+  bool InternalUnpackTo(absl::string_view type_name,
                         MessageLite* message) const;
-  bool InternalIs(StringPiece type_name) const;
+  bool InternalIs(absl::string_view type_name) const;
 
   UrlType* type_url_;
   ValueType* value_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AnyMetadata);
 };
 
 // Get the proto type name from Any::type_url value. For example, passing
@@ -132,14 +132,14 @@
 //
 // NOTE: this function is available publicly as a static method on the
 // generated message type: google::protobuf::Any::ParseAnyTypeUrl()
-bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name);
+bool ParseAnyTypeUrl(absl::string_view 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(StringPiece type_url, std::string* url_prefix,
+bool ParseAnyTypeUrl(absl::string_view 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
@@ -152,6 +152,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_ANY_H__
diff --git a/src/google/protobuf/any.pb.cc b/src/google/protobuf/any.pb.cc
index c02f9eb..7331418 100644
--- a/src/google/protobuf/any.pb.cc
+++ b/src/google/protobuf/any.pb.cc
@@ -1,28 +1,26 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/any.proto
 
-#include <google/protobuf/any.pb.h>
+#include "google/protobuf/any.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 #if defined(__llvm__)
-  #pragma clang diagnostic push
-  #pragma clang diagnostic ignored "-Wuninitialized"
+#pragma clang diagnostic push
+#pragma clang diagnostic ignored "-Wuninitialized"
 #endif  // __llvm__
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR Any::Any(
@@ -32,62 +30,88 @@
   , /*decltype(_impl_._cached_size_)*/{}
   , /*decltype(_impl_._any_metadata_)*/{&_impl_.type_url_, &_impl_.value_}} {}
 struct AnyDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR AnyDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR AnyDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~AnyDefaultTypeInternal() {}
   union {
     Any _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 AnyDefaultTypeInternal _Any_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 AnyDefaultTypeInternal _Any_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fany_2eproto[1];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _impl_.type_url_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _impl_.value_),
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fany_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fany_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _impl_.type_url_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Any, _impl_.value_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Any)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Any)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_Any_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Any_default_instance_._instance,
 };
-
-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(\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
+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(\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2fany_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fany_2eproto = {
-    false, false, 212, descriptor_table_protodef_google_2fprotobuf_2fany_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fany_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fany_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fany_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fany_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fany_2eproto(&descriptor_table_google_2fprotobuf_2fany_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 bool Any::GetAnyFieldDescriptors(
@@ -98,7 +122,7 @@
       message, type_url_field, value_field);
 }
 bool Any::ParseAnyTypeUrl(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
+    ::absl::string_view type_url,
     std::string* full_type_name) {
   return ::_pbi::ParseAnyTypeUrl(type_url, full_type_name);
 }
@@ -184,7 +208,7 @@
 
 void Any::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Any)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -194,29 +218,32 @@
 }
 
 const char* Any::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string type_url = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_type_url();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Any.type_url"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // bytes value = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -241,10 +268,11 @@
 #undef CHK_
 }
 
-uint8_t* Any::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Any::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Any)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string type_url = 1;
@@ -271,11 +299,12 @@
   return target;
 }
 
-size_t Any::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
-  size_t total_size = 0;
+::size_t Any::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Any)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -306,9 +335,10 @@
 void Any::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Any*>(&to_msg);
   auto& from = static_cast<const Any&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Any)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (!from._internal_type_url().empty()) {
@@ -347,11 +377,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Any::GetMetadata() const {
+
   return ::_pbi::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
@@ -360,9 +390,8 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Any >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
 #if defined(__llvm__)
-  #pragma clang diagnostic pop
+#pragma clang diagnostic pop
 #endif  // __llvm__
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/any.pb.h b/src/google/protobuf/any.pb.h
index 40837ea..82f60be 100644
--- a/src/google/protobuf/any.pb.h
+++ b/src/google/protobuf/any.pb.h
@@ -1,38 +1,43 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/any.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fany_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -41,21 +46,25 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fany_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct AnyDefaultTypeInternal;
 PROTOBUF_EXPORT extern AnyDefaultTypeInternal _Any_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Any* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Any>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT Any final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Any) */ {
  public:
@@ -113,7 +122,7 @@
     return _impl_._any_metadata_.PackFrom(GetArena(), message);
   }
   bool PackFrom(const ::PROTOBUF_NAMESPACE_ID::Message& message,
-                ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
+                ::absl::string_view type_url_prefix) {
     GOOGLE_DCHECK_NE(&message, this);
     return _impl_._any_metadata_.PackFrom(GetArena(), message, type_url_prefix);
   }
@@ -130,7 +139,7 @@
   }
   template <typename T, class = typename std::enable_if<!std::is_convertible<T, const ::PROTOBUF_NAMESPACE_ID::Message&>::value>::type>
   bool PackFrom(const T& message,
-                ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url_prefix) {
+                ::absl::string_view type_url_prefix) {
     return _impl_._any_metadata_.PackFrom<T>(GetArena(), 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 {
@@ -139,7 +148,7 @@
   template<typename T> bool Is() const {
     return _impl_._any_metadata_.Is<T>();
   }
-  static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,
+  static bool ParseAnyTypeUrl(::absl::string_view type_url,
                               std::string* full_type_name);
   friend void swap(Any& a, Any& b) {
     a.Swap(&b);
@@ -180,10 +189,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -194,7 +203,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Any";
   }
   protected:
@@ -262,12 +271,17 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // Any
 
 // string type_url = 1;
@@ -294,11 +308,11 @@
   return _impl_.type_url_.Get();
 }
 inline void Any::_internal_set_type_url(const std::string& value) {
-  
+
   _impl_.type_url_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Any::_internal_mutable_type_url() {
-  
+
   return _impl_.type_url_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Any::release_type_url() {
@@ -306,11 +320,6 @@
   return _impl_.type_url_.Release();
 }
 inline void Any::set_allocated_type_url(std::string* type_url) {
-  if (type_url != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.type_url_.SetAllocated(type_url, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.type_url_.IsDefault()) {
@@ -344,11 +353,11 @@
   return _impl_.value_.Get();
 }
 inline void Any::_internal_set_value(const std::string& value) {
-  
+
   _impl_.value_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Any::_internal_mutable_value() {
-  
+
   return _impl_.value_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Any::release_value() {
@@ -356,11 +365,6 @@
   return _impl_.value_.Release();
 }
 inline void Any::set_allocated_value(std::string* value) {
-  if (value != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.value_.SetAllocated(value, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.value_.IsDefault()) {
@@ -371,14 +375,15 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fany_2eproto_2epb_2eh
diff --git a/src/google/protobuf/any.proto b/src/google/protobuf/any.proto
index e2c2042..561da0c 100644
--- a/src/google/protobuf/any.proto
+++ b/src/google/protobuf/any.proto
@@ -32,12 +32,12 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 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;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 
 // `Any` contains an arbitrary serialized protocol buffer message along with a
 // URL that describes the type of the serialized message.
@@ -63,6 +63,10 @@
 //     if (any.is(Foo.class)) {
 //       foo = any.unpack(Foo.class);
 //     }
+//     // or ...
+//     if (any.isSameTypeAs(Foo.getDefaultInstance())) {
+//       foo = any.unpack(Foo.getDefaultInstance());
+//     }
 //
 // Example 3: Pack and unpack a message in Python.
 //
@@ -93,7 +97,6 @@
 // in the type URL, for example "foo.bar.com/x/y.z" will yield type
 // name "y.z".
 //
-//
 // JSON
 //
 // The JSON representation of an `Any` value uses the regular
diff --git a/src/google/protobuf/any_lite.cc b/src/google/protobuf/any_lite.cc
index f283a31..6f689af 100644
--- a/src/google/protobuf/any_lite.cc
+++ b/src/google/protobuf/any_lite.cc
@@ -28,23 +28,24 @@
 // (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/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/any.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/any.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
 namespace google {
 namespace protobuf {
 namespace internal {
 
-std::string GetTypeUrl(StringPiece message_name,
-                       StringPiece type_url_prefix) {
+std::string GetTypeUrl(absl::string_view message_name,
+                       absl::string_view type_url_prefix) {
   if (!type_url_prefix.empty() &&
       type_url_prefix[type_url_prefix.size() - 1] == '/') {
-    return StrCat(type_url_prefix, message_name);
+    return absl::StrCat(type_url_prefix, message_name);
   } else {
-    return StrCat(type_url_prefix, "/", message_name);
+    return absl::StrCat(type_url_prefix, "/", message_name);
   }
 }
 
@@ -53,13 +54,13 @@
 const char kTypeGoogleProdComPrefix[] = "type.googleprod.com/";
 
 bool AnyMetadata::InternalPackFrom(Arena* arena, const MessageLite& message,
-                                   StringPiece type_url_prefix,
-                                   StringPiece type_name) {
+                                   absl::string_view type_url_prefix,
+                                   absl::string_view type_name) {
   type_url_->Set(GetTypeUrl(type_name, type_url_prefix), arena);
   return message.SerializeToString(value_->Mutable(arena));
 }
 
-bool AnyMetadata::InternalUnpackTo(StringPiece type_name,
+bool AnyMetadata::InternalUnpackTo(absl::string_view type_name,
                                    MessageLite* message) const {
   if (!InternalIs(type_name)) {
     return false;
@@ -67,14 +68,14 @@
   return message->ParseFromString(value_->Get());
 }
 
-bool AnyMetadata::InternalIs(StringPiece type_name) const {
-  StringPiece type_url = type_url_->Get();
+bool AnyMetadata::InternalIs(absl::string_view type_name) const {
+  absl::string_view 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);
+         absl::EndsWith(type_url, type_name);
 }
 
-bool ParseAnyTypeUrl(StringPiece type_url, std::string* url_prefix,
+bool ParseAnyTypeUrl(absl::string_view type_url, std::string* url_prefix,
                      std::string* full_type_name) {
   size_t pos = type_url.find_last_of('/');
   if (pos == std::string::npos || pos + 1 == type_url.size()) {
@@ -87,7 +88,7 @@
   return true;
 }
 
-bool ParseAnyTypeUrl(StringPiece type_url, std::string* full_type_name) {
+bool ParseAnyTypeUrl(absl::string_view 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 a82afb2..5a3c7a4 100644
--- a/src/google/protobuf/any_test.cc
+++ b/src/google/protobuf/any_test.cc
@@ -28,13 +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.
 
-#include <google/protobuf/any_test.pb.h>
-#include <google/protobuf/unittest.pb.h>
+#include "google/protobuf/any.pb.h"
 #include <gtest/gtest.h>
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/any_test.pb.h"
+#include "google/protobuf/unittest.pb.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -191,4 +193,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/api.pb.cc b/src/google/protobuf/api.pb.cc
index 24b6049..7f23f9a 100644
--- a/src/google/protobuf/api.pb.cc
+++ b/src/google/protobuf/api.pb.cc
@@ -1,25 +1,23 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/api.proto
 
-#include <google/protobuf/api.pb.h>
+#include "google/protobuf/api.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR Api::Api(
     ::_pbi::ConstantInitialized): _impl_{
@@ -32,14 +30,15 @@
   , /*decltype(_impl_.syntax_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct ApiDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR ApiDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR ApiDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~ApiDefaultTypeInternal() {}
   union {
     Api _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ApiDefaultTypeInternal _Api_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ApiDefaultTypeInternal _Api_default_instance_;
 PROTOBUF_CONSTEXPR Method::Method(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.options_)*/{}
@@ -51,123 +50,155 @@
   , /*decltype(_impl_.syntax_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct MethodDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR MethodDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR MethodDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~MethodDefaultTypeInternal() {}
   union {
     Method _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodDefaultTypeInternal _Method_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodDefaultTypeInternal _Method_default_instance_;
 PROTOBUF_CONSTEXPR Mixin::Mixin(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.root_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct MixinDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR MixinDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR MixinDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~MixinDefaultTypeInternal() {}
   union {
     Mixin _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MixinDefaultTypeInternal _Mixin_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MixinDefaultTypeInternal _Mixin_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fapi_2eproto[3];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fapi_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.methods_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.version_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.source_context_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.mixins_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.syntax_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.request_type_url_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.request_streaming_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.response_type_url_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.response_streaming_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.syntax_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _impl_.root_),
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fapi_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.methods_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.version_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.source_context_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.mixins_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Api, _impl_.syntax_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.request_type_url_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.request_streaming_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.response_type_url_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.response_streaming_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Method, _impl_.syntax_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Mixin, _impl_.root_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Api)},
-  { 13, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Method)},
-  { 26, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Mixin)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Api)},
+        { 15, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Method)},
+        { 30, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Mixin)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_Api_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Method_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Api_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Method_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Mixin_default_instance_._instance,
 };
-
-const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
-  "\n\031google/protobuf/api.proto\022\017google.prot"
-  "obuf\032$google/protobuf/source_context.pro"
-  "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014"
-  "\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p"
-  "rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google"
-  ".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou"
-  "rce_context\030\005 \001(\0132\036.google.protobuf.Sour"
-  "ceContext\022&\n\006mixins\030\006 \003(\0132\026.google.proto"
-  "buf.Mixin\022\'\n\006syntax\030\007 \001(\0162\027.google.proto"
-  "buf.Syntax\"\325\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020r"
-  "equest_type_url\030\002 \001(\t\022\031\n\021request_streami"
-  "ng\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022r"
-  "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(\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 ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fapi_2eproto_deps[2] = {
-  &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
-  &::descriptor_table_google_2fprotobuf_2ftype_2eproto,
+const char descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+    "\n\031google/protobuf/api.proto\022\017google.prot"
+    "obuf\032$google/protobuf/source_context.pro"
+    "to\032\032google/protobuf/type.proto\"\201\002\n\003Api\022\014"
+    "\n\004name\030\001 \001(\t\022(\n\007methods\030\002 \003(\0132\027.google.p"
+    "rotobuf.Method\022(\n\007options\030\003 \003(\0132\027.google"
+    ".protobuf.Option\022\017\n\007version\030\004 \001(\t\0226\n\016sou"
+    "rce_context\030\005 \001(\0132\036.google.protobuf.Sour"
+    "ceContext\022&\n\006mixins\030\006 \003(\0132\026.google.proto"
+    "buf.Mixin\022\'\n\006syntax\030\007 \001(\0162\027.google.proto"
+    "buf.Syntax\"\325\001\n\006Method\022\014\n\004name\030\001 \001(\t\022\030\n\020r"
+    "equest_type_url\030\002 \001(\t\022\031\n\021request_streami"
+    "ng\030\003 \001(\010\022\031\n\021response_type_url\030\004 \001(\t\022\032\n\022r"
+    "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(\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once;
+static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fapi_2eproto_deps[2] =
+    {
+        &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
+        &::descriptor_table_google_2fprotobuf_2ftype_2eproto,
+};
+static ::absl::once_flag descriptor_table_google_2fprotobuf_2fapi_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fapi_2eproto = {
-    false, false, 751, descriptor_table_protodef_google_2fprotobuf_2fapi_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fapi_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fapi_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fapi_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fapi_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fapi_2eproto(&descriptor_table_google_2fprotobuf_2fapi_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 class Api::_Internal {
@@ -280,7 +311,7 @@
 
 void Api::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Api)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -298,24 +329,26 @@
 }
 
 const char* Api::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Api.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Method methods = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -323,12 +356,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Option options = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -336,30 +370,33 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string version = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           auto str = _internal_mutable_version();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Api.version"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.SourceContext source_context = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 42)) {
           ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Mixin mixins = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -367,17 +404,19 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.Syntax syntax = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 56)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -402,10 +441,11 @@
 #undef CHK_
 }
 
-uint8_t* Api::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Api::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Api)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string name = 1;
@@ -474,11 +514,12 @@
   return target;
 }
 
-size_t Api::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api)
-  size_t total_size = 0;
+::size_t Api::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Api)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -543,9 +584,10 @@
 void Api::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Api*>(&to_msg);
   auto& from = static_cast<const Api&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Api)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.methods_.MergeFrom(from._impl_.methods_);
@@ -603,11 +645,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Api::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fapi_2eproto[0]);
 }
-
 // ===================================================================
 
 class Method::_Internal {
@@ -662,7 +704,7 @@
       _this->GetArenaForAllocation());
   }
   ::memcpy(&_impl_.request_streaming_, &from._impl_.request_streaming_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.syntax_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.syntax_) -
     reinterpret_cast<char*>(&_impl_.request_streaming_)) + sizeof(_impl_.syntax_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Method)
 }
@@ -718,7 +760,7 @@
 
 void Method::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Method)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -726,67 +768,73 @@
   _impl_.name_.ClearToEmpty();
   _impl_.request_type_url_.ClearToEmpty();
   _impl_.response_type_url_.ClearToEmpty();
-  ::memset(&_impl_.request_streaming_, 0, static_cast<size_t>(
+  ::memset(&_impl_.request_streaming_, 0, static_cast<::size_t>(
       reinterpret_cast<char*>(&_impl_.syntax_) -
       reinterpret_cast<char*>(&_impl_.request_streaming_)) + sizeof(_impl_.syntax_));
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Method::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Method.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string request_type_url = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_request_type_url();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Method.request_type_url"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // bool request_streaming = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _impl_.request_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string response_type_url = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           auto str = _internal_mutable_response_type_url();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Method.response_type_url"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // bool response_streaming = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 40)) {
           _impl_.response_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Option options = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -794,17 +842,19 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.Syntax syntax = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 56)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -829,10 +879,11 @@
 #undef CHK_
 }
 
-uint8_t* Method::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Method::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Method)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string name = 1;
@@ -900,11 +951,12 @@
   return target;
 }
 
-size_t Method::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method)
-  size_t total_size = 0;
+::size_t Method::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Method)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -965,9 +1017,10 @@
 void Method::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Method*>(&to_msg);
   auto& from = static_cast<const Method&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Method)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.options_.MergeFrom(from._impl_.options_);
@@ -1030,11 +1083,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Method::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fapi_2eproto_getter, &descriptor_table_google_2fprotobuf_2fapi_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fapi_2eproto[1]);
 }
-
 // ===================================================================
 
 class Mixin::_Internal {
@@ -1115,7 +1168,7 @@
 
 void Mixin::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Mixin)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1125,30 +1178,33 @@
 }
 
 const char* Mixin::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Mixin.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string root = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_root();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Mixin.root"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1173,10 +1229,11 @@
 #undef CHK_
 }
 
-uint8_t* Mixin::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Mixin::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Mixin)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string name = 1;
@@ -1207,11 +1264,12 @@
   return target;
 }
 
-size_t Mixin::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin)
-  size_t total_size = 0;
+::size_t Mixin::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Mixin)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1242,9 +1300,10 @@
 void Mixin::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Mixin*>(&to_msg);
   auto& from = static_cast<const Mixin&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Mixin)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (!from._internal_name().empty()) {
@@ -1283,11 +1342,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Mixin::GetMetadata() const {
+
   return ::_pbi::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
@@ -1304,6 +1363,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Mixin >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/api.pb.h b/src/google/protobuf/api.pb.h
index b81b18e..cfbccf8 100644
--- a/src/google/protobuf/api.pb.h
+++ b/src/google/protobuf/api.pb.h
@@ -1,40 +1,45 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/api.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/source_context.pb.h>
-#include <google/protobuf/type.pb.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/source_context.pb.h"
+#include "google/protobuf/type.pb.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fapi_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -43,9 +48,10 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fapi_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct ApiDefaultTypeInternal;
@@ -56,16 +62,21 @@
 class Mixin;
 struct MixinDefaultTypeInternal;
 PROTOBUF_EXPORT extern MixinDefaultTypeInternal _Mixin_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Api* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Api>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Method* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Method>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Mixin* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Mixin>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Api* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Api>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Method* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Method>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Mixin* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Mixin>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT Api final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Api) */ {
  public:
@@ -155,10 +166,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -169,7 +180,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Api";
   }
   protected:
@@ -323,8 +334,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Method final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Method) */ {
@@ -415,10 +425,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -429,7 +439,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Method";
   }
   protected:
@@ -561,8 +571,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fapi_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Mixin final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Mixin) */ {
@@ -653,10 +662,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -667,7 +676,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Mixin";
   }
   protected:
@@ -734,12 +743,17 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // Api
 
 // string name = 1;
@@ -766,11 +780,11 @@
   return _impl_.name_.Get();
 }
 inline void Api::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Api::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Api::release_name() {
@@ -778,11 +792,6 @@
   return _impl_.name_.Release();
 }
 inline void Api::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -893,11 +902,11 @@
   return _impl_.version_.Get();
 }
 inline void Api::_internal_set_version(const std::string& value) {
-  
+
   _impl_.version_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Api::_internal_mutable_version() {
-  
+
   return _impl_.version_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Api::release_version() {
@@ -905,11 +914,6 @@
   return _impl_.version_.Release();
 }
 inline void Api::set_allocated_version(std::string* version) {
-  if (version != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.version_.SetAllocated(version, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.version_.IsDefault()) {
@@ -941,11 +945,6 @@
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_);
   }
   _impl_.source_context_ = source_context;
-  if (source_context) {
-    
-  } else {
-    
-  }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Api.source_context)
 }
 inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Api::release_source_context() {
@@ -996,9 +995,9 @@
       source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_context, submessage_arena);
     }
-    
+
   } else {
-    
+
   }
   _impl_.source_context_ = source_context;
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Api.source_context)
@@ -1092,11 +1091,11 @@
   return _impl_.name_.Get();
 }
 inline void Method::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Method::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Method::release_name() {
@@ -1104,11 +1103,6 @@
   return _impl_.name_.Release();
 }
 inline void Method::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -1142,11 +1136,11 @@
   return _impl_.request_type_url_.Get();
 }
 inline void Method::_internal_set_request_type_url(const std::string& value) {
-  
+
   _impl_.request_type_url_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Method::_internal_mutable_request_type_url() {
-  
+
   return _impl_.request_type_url_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Method::release_request_type_url() {
@@ -1154,11 +1148,6 @@
   return _impl_.request_type_url_.Release();
 }
 inline void Method::set_allocated_request_type_url(std::string* request_type_url) {
-  if (request_type_url != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.request_type_url_.SetAllocated(request_type_url, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.request_type_url_.IsDefault()) {
@@ -1180,7 +1169,7 @@
   return _internal_request_streaming();
 }
 inline void Method::_internal_set_request_streaming(bool value) {
-  
+
   _impl_.request_streaming_ = value;
 }
 inline void Method::set_request_streaming(bool value) {
@@ -1212,11 +1201,11 @@
   return _impl_.response_type_url_.Get();
 }
 inline void Method::_internal_set_response_type_url(const std::string& value) {
-  
+
   _impl_.response_type_url_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Method::_internal_mutable_response_type_url() {
-  
+
   return _impl_.response_type_url_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Method::release_response_type_url() {
@@ -1224,11 +1213,6 @@
   return _impl_.response_type_url_.Release();
 }
 inline void Method::set_allocated_response_type_url(std::string* response_type_url) {
-  if (response_type_url != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.response_type_url_.SetAllocated(response_type_url, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.response_type_url_.IsDefault()) {
@@ -1250,7 +1234,7 @@
   return _internal_response_streaming();
 }
 inline void Method::_internal_set_response_streaming(bool value) {
-  
+
   _impl_.response_streaming_ = value;
 }
 inline void Method::set_response_streaming(bool value) {
@@ -1343,11 +1327,11 @@
   return _impl_.name_.Get();
 }
 inline void Mixin::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Mixin::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Mixin::release_name() {
@@ -1355,11 +1339,6 @@
   return _impl_.name_.Release();
 }
 inline void Mixin::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -1393,11 +1372,11 @@
   return _impl_.root_.Get();
 }
 inline void Mixin::_internal_set_root(const std::string& value) {
-  
+
   _impl_.root_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Mixin::_internal_mutable_root() {
-  
+
   return _impl_.root_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Mixin::release_root() {
@@ -1405,11 +1384,6 @@
   return _impl_.root_.Release();
 }
 inline void Mixin::set_allocated_root(std::string* root) {
-  if (root != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.root_.SetAllocated(root, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.root_.IsDefault()) {
@@ -1420,18 +1394,15 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fapi_2eproto_2epb_2eh
diff --git a/src/google/protobuf/api.proto b/src/google/protobuf/api.proto
index 3d598fc..afc9cc1 100644
--- a/src/google/protobuf/api.proto
+++ b/src/google/protobuf/api.proto
@@ -35,11 +35,11 @@
 import "google/protobuf/source_context.proto";
 import "google/protobuf/type.proto";
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "ApiProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option go_package = "google.golang.org/protobuf/types/known/apipb";
 
 // Api is a light-weight descriptor for an API Interface.
@@ -82,7 +82,6 @@
   // be omitted. Zero major versions must only be used for
   // experimental, non-GA interfaces.
   //
-  //
   string version = 4;
 
   // Source context for the protocol buffer service represented by this
diff --git a/src/google/protobuf/arena.cc b/src/google/protobuf/arena.cc
index 6ba508a..327c26e 100644
--- a/src/google/protobuf/arena.cc
+++ b/src/google/protobuf/arena.cc
@@ -28,7 +28,7 @@
 // (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/arena.h>
+#include "google/protobuf/arena.h"
 
 #include <algorithm>
 #include <atomic>
@@ -37,21 +37,47 @@
 #include <limits>
 #include <typeinfo>
 
-#include <google/protobuf/arena_impl.h>
-#include <google/protobuf/arenaz_sampler.h>
-#include <google/protobuf/port.h>
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/arena_allocation_policy.h"
+#include "google/protobuf/arena_impl.h"
+#include "google/protobuf/arenaz_sampler.h"
+#include "google/protobuf/port.h"
 
-#include <google/protobuf/stubs/mutex.h>
+
 #ifdef ADDRESS_SANITIZER
 #include <sanitizer/asan_interface.h>
 #endif  // ADDRESS_SANITIZER
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace internal {
+namespace {
+
+#if defined(__GNUC__) && __GNUC__ >= 5
+// kSentryArenaBlock is used for arenas which can be referenced pre-main. So,
+// constexpr is required.
+constexpr ArenaBlock kSentryArenaBlock;
+
+ArenaBlock* SentryArenaBlock() {
+  // const_cast<> is okay as kSentryArenaBlock will never be mutated.
+  return const_cast<ArenaBlock*>(&kSentryArenaBlock);
+}
+#else
+// TODO(b/248322260) Remove this once we're not using GCC 4.9 for tests.
+// There is a compiler bug in this version that causes the above constexpr to
+// fail.  This version is no longer in our support window, but we use it in
+// some of our aarch64 docker images.
+ArenaBlock* SentryArenaBlock() {
+  static const ArenaBlock kSentryArenaBlock;
+  // const_cast<> is okay as kSentryArenaBlock will never be mutated.
+  return const_cast<ArenaBlock*>(&kSentryArenaBlock);
+}
+#endif
+
+}  // namespace
 
 static SerialArena::Memory AllocateMemory(const AllocationPolicy* policy_ptr,
                                           size_t last_size, size_t min_bytes) {
@@ -104,27 +130,54 @@
   size_t* space_allocated_;
 };
 
-SerialArena::SerialArena(Block* b, void* owner, ThreadSafeArenaStats* stats)
-    : space_allocated_(b->size) {
-  owner_ = owner;
-  head_ = b;
-  ptr_ = b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize);
-  limit_ = b->Pointer(b->size & static_cast<size_t>(-8));
-  arena_stats_ = stats;
+// It is guaranteed that this is constructed in `b`. IOW, this is not the first
+// arena and `b` cannot be sentry.
+SerialArena::SerialArena(ArenaBlock* b, ThreadSafeArena& parent)
+    : ptr_{b->Pointer(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize)},
+      limit_{b->Limit()},
+      head_{b},
+      space_allocated_{b->size},
+      parent_{parent} {
+  GOOGLE_DCHECK(!b->IsSentry());
 }
 
-SerialArena* SerialArena::New(Memory mem, void* owner,
-                              ThreadSafeArenaStats* stats) {
+// It is guaranteed that this is the first SerialArena. Use sentry block.
+SerialArena::SerialArena(ThreadSafeArena& parent)
+    : head_{SentryArenaBlock()}, parent_{parent} {}
+
+// It is guaranteed that this is the first SerialArena but `b` may be user
+// provided or newly allocated to store AllocationPolicy.
+SerialArena::SerialArena(FirstSerialArena, ArenaBlock* b,
+                         ThreadSafeArena& parent)
+    : head_{b}, space_allocated_{b->size}, parent_{parent} {
+  if (b->IsSentry()) return;
+
+  set_ptr(b->Pointer(kBlockHeaderSize));
+  limit_ = b->Limit();
+}
+
+void SerialArena::Init(ArenaBlock* b, size_t offset) {
+  set_ptr(b->Pointer(offset));
+  limit_ = b->Limit();
+  head_.store(b, std::memory_order_relaxed);
+  space_used_.store(0, std::memory_order_relaxed);
+  space_allocated_.store(b->size, std::memory_order_relaxed);
+  cached_block_length_ = 0;
+  cached_blocks_ = nullptr;
+}
+
+SerialArena* SerialArena::New(Memory mem, ThreadSafeArena& parent) {
   GOOGLE_DCHECK_LE(kBlockHeaderSize + ThreadSafeArena::kSerialArenaSize, mem.size);
-  ThreadSafeArenaStats::RecordAllocateStats(
-      stats, /*requested=*/mem.size, /*allocated=*/mem.size, /*wasted=*/0);
-  auto b = new (mem.ptr) Block{nullptr, mem.size};
-  return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, owner, stats);
+  ThreadSafeArenaStats::RecordAllocateStats(parent.arena_stats_.MutableStats(),
+                                            /*used=*/0, /*allocated=*/mem.size,
+                                            /*wasted=*/0);
+  auto b = new (mem.ptr) ArenaBlock{nullptr, mem.size};
+  return new (b->Pointer(kBlockHeaderSize)) SerialArena(b, parent);
 }
 
 template <typename Deallocator>
 SerialArena::Memory SerialArena::Free(Deallocator deallocator) {
-  Block* b = head_;
+  ArenaBlock* b = head();
   Memory mem = {b, b->size};
   while (b->next) {
     b = b->next;  // We must first advance before deleting this block
@@ -135,76 +188,288 @@
 }
 
 PROTOBUF_NOINLINE
-std::pair<void*, SerialArena::CleanupNode*>
-SerialArena::AllocateAlignedWithCleanupFallback(
-    size_t n, const AllocationPolicy* policy) {
-  AllocateNewBlock(n + kCleanupSize, policy);
-  return AllocateFromExistingWithCleanupFallback(n);
-}
-
-PROTOBUF_NOINLINE
-void* SerialArena::AllocateAlignedFallback(size_t n,
-                                           const AllocationPolicy* policy) {
-  AllocateNewBlock(n, policy);
+void* SerialArena::AllocateAlignedFallback(size_t n) {
+  AllocateNewBlock(n);
   return AllocateFromExisting(n);
 }
 
-void SerialArena::AllocateNewBlock(size_t n, const AllocationPolicy* policy) {
-  // Sync limit to block
-  head_->start = reinterpret_cast<CleanupNode*>(limit_);
+PROTOBUF_NOINLINE
+void* SerialArena::AllocateAlignedWithCleanupFallback(
+    size_t n, size_t align, void (*destructor)(void*)) {
+  size_t required = AlignUpTo(n, align) + cleanup::Size(destructor);
+  AllocateNewBlock(required);
+  return AllocateFromExistingWithCleanupFallback(n, align, destructor);
+}
 
-  // Record how much used in this block.
-  size_t used = ptr_ - head_->Pointer(kBlockHeaderSize);
-  size_t wasted = head_->size - used;
-  space_used_ += used;
+PROTOBUF_NOINLINE
+void SerialArena::AddCleanupFallback(void* elem, void (*destructor)(void*)) {
+  size_t required = cleanup::Size(destructor);
+  AllocateNewBlock(required);
+  AddCleanupFromExisting(elem, destructor);
+}
+
+void SerialArena::AllocateNewBlock(size_t n) {
+  size_t used = 0;
+  size_t wasted = 0;
+  ArenaBlock* old_head = head();
+  if (!old_head->IsSentry()) {
+    // Sync limit to block
+    old_head->cleanup_nodes = limit_;
+
+    // Record how much used in this block.
+    used = static_cast<size_t>(ptr() - old_head->Pointer(kBlockHeaderSize));
+    wasted = old_head->size - used;
+    space_used_.store(space_used_.load(std::memory_order_relaxed) + used,
+                      std::memory_order_relaxed);
+  }
 
   // TODO(sbenza): Evaluate if pushing unused space into the cached blocks is a
   // win. In preliminary testing showed increased memory savings as expected,
   // but with a CPU regression. The regression might have been an artifact of
   // the microbenchmark.
 
-  auto mem = AllocateMemory(policy, head_->size, n);
+  auto mem = AllocateMemory(parent_.AllocPolicy(), old_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);
-  ThreadSafeArenaStats::RecordAllocateStats(arena_stats_, /*requested=*/n,
+  space_allocated_.store(
+      space_allocated_.load(std::memory_order_relaxed) + mem.size,
+      std::memory_order_relaxed);
+  ThreadSafeArenaStats::RecordAllocateStats(parent_.arena_stats_.MutableStats(),
+                                            /*used=*/used,
                                             /*allocated=*/mem.size, wasted);
-  head_ = new (mem.ptr) Block{head_, mem.size};
-  ptr_ = head_->Pointer(kBlockHeaderSize);
-  limit_ = head_->Pointer(head_->size);
+  auto* new_head = new (mem.ptr) ArenaBlock{old_head, mem.size};
+  set_ptr(new_head->Pointer(kBlockHeaderSize));
+  limit_ = new_head->Limit();
+  // Previous writes must take effect before writing new head.
+  head_.store(new_head, std::memory_order_release);
 
 #ifdef ADDRESS_SANITIZER
-  ASAN_POISON_MEMORY_REGION(ptr_, limit_ - ptr_);
+  ASAN_POISON_MEMORY_REGION(ptr(), limit_ - ptr());
 #endif  // ADDRESS_SANITIZER
 }
 
 uint64_t SerialArena::SpaceUsed() const {
-  uint64_t space_used = ptr_ - head_->Pointer(kBlockHeaderSize);
-  space_used += space_used_;
-  // Remove the overhead of the SerialArena itself.
-  space_used -= ThreadSafeArena::kSerialArenaSize;
-  return space_used;
+  // Note: the calculation below technically causes a race with
+  // AllocateNewBlock when called from another thread (which happens in
+  // ThreadSafeArena::SpaceUsed).  However, worst-case space_used_ will have
+  // stale data and the calculation will incorrectly assume 100%
+  // usage of the *current* block.
+  // TODO(mkruskal) Consider eliminating this race in exchange for a possible
+  // performance hit on ARM (see cl/455186837).
+  const ArenaBlock* h = head_.load(std::memory_order_acquire);
+  if (h->IsSentry()) return 0;
+
+  const uint64_t current_block_size = h->size;
+  uint64_t current_space_used = std::min(
+      static_cast<uint64_t>(
+          ptr() - const_cast<ArenaBlock*>(h)->Pointer(kBlockHeaderSize)),
+      current_block_size);
+  return current_space_used + space_used_.load(std::memory_order_relaxed);
 }
 
 void SerialArena::CleanupList() {
-  Block* b = head_;
-  b->start = reinterpret_cast<CleanupNode*>(limit_);
+  ArenaBlock* b = head();
+  if (b->IsSentry()) return;
+
+  b->cleanup_nodes = 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);
+    char* limit = b->Limit();
+    char* it = reinterpret_cast<char*>(b->cleanup_nodes);
+    GOOGLE_DCHECK(!b->IsSentry() || it == limit);
+    if (it < limit) {
+      // A prefetch distance of 8 here was chosen arbitrarily.  It makes the
+      // pending nodes fill a cacheline which seemed nice.
+      constexpr int kPrefetchDist = 8;
+      cleanup::Tag pending_type[kPrefetchDist];
+      char* pending_node[kPrefetchDist];
+
+      int pos = 0;
+      for (; pos < kPrefetchDist && it < limit; ++pos) {
+        pending_type[pos] = cleanup::Type(it);
+        pending_node[pos] = it;
+        it += cleanup::Size(pending_type[pos]);
+      }
+
+      if (pos < kPrefetchDist) {
+        for (int i = 0; i < pos; ++i) {
+          cleanup::DestroyNode(pending_type[i], pending_node[i]);
+        }
+      } else {
+        pos = 0;
+        while (it < limit) {
+          cleanup::PrefetchNode(it);
+          cleanup::DestroyNode(pending_type[pos], pending_node[pos]);
+          pending_type[pos] = cleanup::Type(it);
+          pending_node[pos] = it;
+          it += cleanup::Size(pending_type[pos]);
+          pos = (pos + 1) % kPrefetchDist;
+        }
+        for (int i = pos; i < pos + kPrefetchDist; ++i) {
+          cleanup::DestroyNode(pending_type[i % kPrefetchDist],
+                               pending_node[i % kPrefetchDist]);
+        }
       }
     }
     b = b->next;
   } while (b);
 }
 
+// Stores arrays of void* and SerialArena* instead of linked list of
+// SerialArena* to speed up traversing all SerialArena. The cost of walk is non
+// trivial when there are many nodes. Separately storing "ids" minimizes cache
+// footprints and more efficient when looking for matching arena.
+//
+// Uses absl::container_internal::Layout to emulate the following:
+//
+// struct SerialArenaChunk {
+//   struct SerialArenaChunkHeader {
+//     SerialArenaChunk* next_chunk;
+//     uint32_t capacity;
+//     std::atomic<uint32_t> size;
+//   } header;
+//   std::atomic<void*> ids[];
+//   std::atomic<SerialArena*> arenas[];
+// };
+//
+// where the size of "ids" and "arenas" is determined at runtime; hence the use
+// of Layout.
+struct SerialArenaChunkHeader {
+  constexpr SerialArenaChunkHeader(uint32_t capacity, uint32_t size)
+      : next_chunk(nullptr), capacity(capacity), size(size) {}
+
+  ThreadSafeArena::SerialArenaChunk* next_chunk;
+  uint32_t capacity;
+  std::atomic<uint32_t> size;
+};
+
+class ThreadSafeArena::SerialArenaChunk {
+ public:
+  SerialArenaChunk(uint32_t capacity, void* me, SerialArena* serial) {
+    new (&header()) SerialArenaChunkHeader{capacity, 1};
+
+    new (&id(0)) std::atomic<void*>{me};
+    for (uint32_t i = 1; i < capacity; ++i) {
+      new (&id(i)) std::atomic<void*>{nullptr};
+    }
+
+    new (&arena(0)) std::atomic<SerialArena*>{serial};
+    for (uint32_t i = 1; i < capacity; ++i) {
+      new (&arena(i)) std::atomic<void*>{nullptr};
+    }
+  }
+
+  bool IsSentry() const { return capacity() == 0; }
+
+  // next_chunk
+  const SerialArenaChunk* next_chunk() const { return header().next_chunk; }
+  SerialArenaChunk* next_chunk() { return header().next_chunk; }
+  void set_next(SerialArenaChunk* next_chunk) {
+    header().next_chunk = next_chunk;
+  }
+
+  // capacity
+  uint32_t capacity() const { return header().capacity; }
+  void set_capacity(uint32_t capacity) { header().capacity = capacity; }
+
+  // ids: returns up to size().
+  absl::Span<const std::atomic<void*>> ids() const {
+    return Layout(capacity()).Slice<kIds>(ptr()).first(safe_size());
+  }
+  absl::Span<std::atomic<void*>> ids() {
+    return Layout(capacity()).Slice<kIds>(ptr()).first(safe_size());
+  }
+  std::atomic<void*>& id(uint32_t i) {
+    GOOGLE_DCHECK_LT(i, capacity());
+    return Layout(capacity()).Pointer<kIds>(ptr())[i];
+  }
+
+  // arenas: returns up to size().
+  absl::Span<const std::atomic<SerialArena*>> arenas() const {
+    return Layout(capacity()).Slice<kArenas>(ptr()).first(safe_size());
+  }
+  absl::Span<std::atomic<SerialArena*>> arenas() {
+    return Layout(capacity()).Slice<kArenas>(ptr()).first(safe_size());
+  }
+  const std::atomic<SerialArena*>& arena(uint32_t i) const {
+    GOOGLE_DCHECK_LT(i, capacity());
+    return Layout(capacity()).Pointer<kArenas>(ptr())[i];
+  }
+  std::atomic<SerialArena*>& arena(uint32_t i) {
+    GOOGLE_DCHECK_LT(i, capacity());
+    return Layout(capacity()).Pointer<kArenas>(ptr())[i];
+  }
+
+  // Tries to insert {id, serial} to head chunk. Returns false if the head is
+  // already full.
+  //
+  // Note that the updating "size", "id", "arena" is individually atomic but
+  // those are not protected by a mutex. This is acceptable because concurrent
+  // lookups from SpaceUsed or SpaceAllocated accept inaccuracy due to race. On
+  // other paths, either race is not possible (GetSerialArenaFallback) or must
+  // be prevented by users (CleanupList, Free).
+  bool insert(void* me, SerialArena* serial) {
+    uint32_t idx = size().fetch_add(1, std::memory_order_relaxed);
+    // Bail out if this chunk is full.
+    if (idx >= capacity()) {
+      // Write old value back to avoid potential overflow.
+      size().store(capacity(), std::memory_order_relaxed);
+      return false;
+    }
+
+    id(idx).store(me, std::memory_order_relaxed);
+    arena(idx).store(serial, std::memory_order_release);
+    return true;
+  }
+
+  constexpr static size_t AllocSize(size_t n) { return Layout(n).AllocSize(); }
+
+ private:
+  constexpr static int kHeader = 0;
+  constexpr static int kIds = 1;
+  constexpr static int kArenas = 2;
+
+  using layout_type = absl::container_internal::Layout<
+      SerialArenaChunkHeader, std::atomic<void*>, std::atomic<SerialArena*>>;
+
+  const char* ptr() const { return reinterpret_cast<const char*>(this); }
+  char* ptr() { return reinterpret_cast<char*>(this); }
+
+  SerialArenaChunkHeader& header() {
+    return *layout_type::Partial().Pointer<kHeader>(ptr());
+  }
+  const SerialArenaChunkHeader& header() const {
+    return *layout_type::Partial().Pointer<kHeader>(ptr());
+  }
+
+  std::atomic<uint32_t>& size() { return header().size; }
+  const std::atomic<uint32_t>& size() const { return header().size; }
+
+  // Returns the size capped by the capacity as fetch_add may result in a size
+  // greater than capacity.
+  uint32_t safe_size() const {
+    return std::min(capacity(), size().load(std::memory_order_relaxed));
+  }
+
+  constexpr static layout_type Layout(size_t n) {
+    return layout_type(
+        /*header*/ 1,
+        /*ids*/ n,
+        /*arenas*/ n);
+  }
+};
+
+constexpr SerialArenaChunkHeader kSentryArenaChunk = {0, 0};
+
+ThreadSafeArena::SerialArenaChunk* ThreadSafeArena::SentrySerialArenaChunk() {
+  // const_cast is okay because the sentry chunk is never mutated. Also,
+  // reinterpret_cast is acceptable here as it should be identical to
+  // SerialArenaChunk with zero payload. This is a necessary trick to
+  // constexpr initialize kSentryArenaChunk.
+  return reinterpret_cast<SerialArenaChunk*>(
+      const_cast<SerialArenaChunkHeader*>(&kSentryArenaChunk));
+}
+
 
 ThreadSafeArena::CacheAlignedLifecycleIdGenerator
     ThreadSafeArena::lifecycle_id_generator_;
@@ -226,66 +491,71 @@
                                       nullptr};
 #endif
 
-void ThreadSafeArena::InitializeFrom(void* mem, size_t size) {
-  GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
-  GOOGLE_DCHECK(!AllocPolicy());  // Reset should call InitializeWithPolicy instead.
-  Init();
+ThreadSafeArena::ThreadSafeArena() : first_arena_(*this) { Init(); }
 
-  // Ignore initial block if it is too small.
-  if (mem != nullptr && size >= kBlockHeaderSize + kSerialArenaSize) {
-    alloc_policy_.set_is_user_owned_initial_block(true);
-    SetInitialBlock(mem, size);
-  }
+// Constructor solely used by message-owned arena.
+ThreadSafeArena::ThreadSafeArena(internal::MessageOwned)
+    : tag_and_id_(kMessageOwnedArena), first_arena_(*this) {
+  Init();
 }
 
-void ThreadSafeArena::InitializeWithPolicy(void* mem, size_t size,
-                                           AllocationPolicy policy) {
+ThreadSafeArena::ThreadSafeArena(char* mem, size_t size)
+    : first_arena_(FirstSerialArena{}, FirstBlock(mem, size), *this) {
+  Init();
+}
+
+ThreadSafeArena::ThreadSafeArena(void* mem, size_t size,
+                                 const AllocationPolicy& policy)
+    : first_arena_(FirstSerialArena{}, FirstBlock(mem, size, policy), *this) {
+  InitializeWithPolicy(policy);
+}
+
+ArenaBlock* ThreadSafeArena::FirstBlock(void* buf, size_t size) {
+  GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(buf) & 7, 0u);
+  if (buf == nullptr || size <= kBlockHeaderSize) {
+    return SentryArenaBlock();
+  }
+  // Record user-owned block.
+  alloc_policy_.set_is_user_owned_initial_block(true);
+  return new (buf) ArenaBlock{nullptr, size};
+}
+
+ArenaBlock* ThreadSafeArena::FirstBlock(void* buf, size_t size,
+                                        const AllocationPolicy& policy) {
+  if (policy.IsDefault()) return FirstBlock(buf, size);
+
+  GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(buf) & 7, 0u);
+
+  SerialArena::Memory mem;
+  if (buf == nullptr || size < kBlockHeaderSize + kAllocPolicySize) {
+    mem = AllocateMemory(&policy, 0, kAllocPolicySize);
+  } else {
+    mem = {buf, size};
+    // Record user-owned block.
+    alloc_policy_.set_is_user_owned_initial_block(true);
+  }
+
+  return new (mem.ptr) ArenaBlock{nullptr, mem.size};
+}
+
+void ThreadSafeArena::InitializeWithPolicy(const AllocationPolicy& policy) {
+  Init();
+
+  if (policy.IsDefault()) return;
+
 #ifndef NDEBUG
   const uint64_t old_alloc_policy = alloc_policy_.get_raw();
   // If there was a policy (e.g., in Reset()), make sure flags were preserved.
 #define GOOGLE_DCHECK_POLICY_FLAGS_() \
   if (old_alloc_policy > 3)    \
-    GOOGLE_CHECK_EQ(old_alloc_policy & 3, alloc_policy_.get_raw() & 3)
+  GOOGLE_CHECK_EQ(old_alloc_policy & 3, alloc_policy_.get_raw() & 3)
 #else
 #define GOOGLE_DCHECK_POLICY_FLAGS_()
 #endif  // NDEBUG
 
-  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);
-    GOOGLE_DCHECK_POLICY_FLAGS_();
-    return;
-  }
-  GOOGLE_DCHECK_EQ(reinterpret_cast<uintptr_t>(mem) & 7, 0u);
-  Init();
-
-  // 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;
-
-  // The value for alloc_policy_ stores whether or not allocations should be
-  // recorded.
-  alloc_policy_.set_should_record_allocs(
-      policy.metrics_collector != nullptr &&
-      policy.metrics_collector->RecordAllocs());
-  // Make sure we have an initial block to store the AllocationPolicy.
-  if (mem != nullptr && size >= kMinimumSize) {
-    alloc_policy_.set_is_user_owned_initial_block(true);
-  } else {
-    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)) {
+  if (!first_arena_.MaybeAllocateAligned(kAllocPolicySize, &p)) {
     GOOGLE_LOG(FATAL) << "MaybeAllocateAligned cannot fail here.";
     return;
   }
@@ -298,41 +568,100 @@
 #undef GOOGLE_DCHECK_POLICY_FLAGS_
 }
 
-void ThreadSafeArena::Init() {
-#ifndef NDEBUG
-  const bool was_message_owned = IsMessageOwned();
-#endif  // NDEBUG
+uint64_t ThreadSafeArena::GetNextLifeCycleId() {
   ThreadCache& tc = thread_cache();
-  auto id = tc.next_lifecycle_id;
+  uint64_t 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_t kDelta = 2;
   constexpr uint64_t 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_t 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;
+    id = lifecycle_id_generator_.id.fetch_add(1, std::memory_order_relaxed) *
+         kInc;
   }
   tc.next_lifecycle_id = id + kDelta;
-  // Message ownership is stored in tag_and_id_, and is set in the constructor.
-  // This flag bit must be preserved, even across calls to Reset().
-  tag_and_id_ = id | (tag_and_id_ & kMessageOwnedArena);
-  hint_.store(nullptr, std::memory_order_relaxed);
-  threads_.store(nullptr, std::memory_order_relaxed);
-#ifndef NDEBUG
-  GOOGLE_CHECK_EQ(was_message_owned, IsMessageOwned());
-#endif  // NDEBUG
-  arena_stats_ = Sample();
+  return id;
 }
 
-void ThreadSafeArena::SetInitialBlock(void* mem, size_t size) {
-  SerialArena* serial = SerialArena::New({mem, size}, &thread_cache(),
-                                         arena_stats_.MutableStats());
-  serial->set_next(NULL);
-  threads_.store(serial, std::memory_order_relaxed);
-  CacheSerialArena(serial);
+// We assume that #threads / arena is bimodal; i.e. majority small ones are
+// single threaded but some big ones are highly concurrent. To balance between
+// memory overhead and minimum pointer chasing, we start with few entries and
+// exponentially (4x) grow with a limit (255 entries). Note that parameters are
+// picked for x64 architectures as hint and the actual size is calculated by
+// Layout.
+ThreadSafeArena::SerialArenaChunk* ThreadSafeArena::NewSerialArenaChunk(
+    uint32_t prev_capacity, void* id, SerialArena* serial) {
+  constexpr size_t kMaxBytes = 4096;  // Can hold up to 255 entries.
+  constexpr size_t kGrowthFactor = 4;
+  constexpr size_t kHeaderSize = SerialArenaChunk::AllocSize(0);
+  constexpr size_t kEntrySize = SerialArenaChunk::AllocSize(1) - kHeaderSize;
+
+  // On x64 arch: {4, 16, 64, 256, 256, ...} * 16.
+  size_t prev_bytes = SerialArenaChunk::AllocSize(prev_capacity);
+  size_t next_bytes = std::min(kMaxBytes, prev_bytes * kGrowthFactor);
+  uint32_t next_capacity =
+      static_cast<uint32_t>(next_bytes - kHeaderSize) / kEntrySize;
+  // Growth based on bytes needs to be adjusted by AllocSize.
+  next_bytes = SerialArenaChunk::AllocSize(next_capacity);
+  void* mem;
+  mem = ::operator new(next_bytes);
+
+  return new (mem) SerialArenaChunk{next_capacity, id, serial};
+}
+
+// Tries to reserve an entry by atomic fetch_add. If the head chunk is already
+// full (size >= capacity), acquires the mutex and adds a new head.
+void ThreadSafeArena::AddSerialArena(void* id, SerialArena* serial) {
+  SerialArenaChunk* head = head_.load(std::memory_order_acquire);
+  // Fast path without acquiring mutex.
+  if (!head->IsSentry() && head->insert(id, serial)) {
+    return;
+  }
+
+  // Slow path with acquiring mutex.
+  absl::MutexLock lock(&mutex_);
+
+  // Refetch and if someone else installed a new head, try allocating on that!
+  SerialArenaChunk* new_head = head_.load(std::memory_order_acquire);
+  if (new_head != head) {
+    if (new_head->insert(id, serial)) return;
+    // Update head to link to the latest one.
+    head = new_head;
+  }
+
+  new_head = NewSerialArenaChunk(head->capacity(), id, serial);
+  new_head->set_next(head);
+
+  // Use "std::memory_order_release" to make sure prior stores are visible after
+  // this one.
+  head_.store(new_head, std::memory_order_release);
+}
+
+void ThreadSafeArena::Init() {
+  const bool message_owned = IsMessageOwned();
+  if (!message_owned) {
+    // Message-owned arenas bypass thread cache and do not need life cycle ID.
+    tag_and_id_ = GetNextLifeCycleId();
+  } else {
+    GOOGLE_DCHECK_EQ(tag_and_id_, kMessageOwnedArena);
+  }
+  arena_stats_ = Sample();
+  head_.store(SentrySerialArenaChunk(), std::memory_order_relaxed);
+  GOOGLE_DCHECK_EQ(message_owned, IsMessageOwned());
+  first_owner_ = &thread_cache();
+
+  // Record allocation for the first block that was either user-provided or
+  // newly allocated.
+  ThreadSafeArenaStats::RecordAllocateStats(
+      arena_stats_.MutableStats(),
+      /*used=*/0,
+      /*allocated=*/first_arena_.SpaceAllocated(),
+      /*wasted=*/0);
+
+  CacheSerialArena(&first_arena_);
 }
 
 ThreadSafeArena::~ThreadSafeArena() {
@@ -342,32 +671,41 @@
 
   size_t space_allocated = 0;
   auto mem = Free(&space_allocated);
-
-  // Policy is about to get deleted.
-  auto* p = alloc_policy_.get();
-  ArenaMetricsCollector* collector = p ? p->metrics_collector : nullptr;
-
   if (alloc_policy_.is_user_owned_initial_block()) {
 #ifdef ADDRESS_SANITIZER
     // Unpoison the initial block, now that it's going back to the user.
     ASAN_UNPOISON_MEMORY_REGION(mem.ptr, mem.size);
 #endif  // ADDRESS_SANITIZER
     space_allocated += mem.size;
-  } else {
+  } else if (mem.size > 0) {
     GetDeallocator(alloc_policy_.get(), &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(alloc_policy_.get(), space_allocated);
-  PerSerialArena([deallocator, &mem](SerialArena* a) {
-    if (mem.ptr) deallocator(mem);
-    mem = a->Free(deallocator);
+
+  WalkSerialArenaChunk([deallocator](SerialArenaChunk* chunk) {
+    absl::Span<std::atomic<SerialArena*>> span = chunk->arenas();
+    // Walks arenas backward to handle the first serial arena the last. Freeing
+    // in reverse-order to the order in which objects were created may not be
+    // necessary to Free and we should revisit this. (b/247560530)
+    for (auto it = span.rbegin(); it != span.rend(); ++it) {
+      SerialArena* serial = it->load(std::memory_order_relaxed);
+      GOOGLE_DCHECK_NE(serial, nullptr);
+      // Always frees the first block of "serial" as it cannot be user-provided.
+      SerialArena::Memory mem = serial->Free(deallocator);
+      GOOGLE_DCHECK_NE(mem.ptr, nullptr);
+      deallocator(mem);
+    }
+
+    // Delete the chunk as we're done with it.
+    internal::SizedDelete(chunk,
+                          SerialArenaChunk::AllocSize(chunk->capacity()));
   });
-  return mem;
+
+  // The first block of the first arena is special and let the caller handle it.
+  return first_arena_.Free(deallocator);
 }
 
 uint64_t ThreadSafeArena::Reset() {
@@ -375,132 +713,169 @@
   // refer to memory in other blocks.
   CleanupList();
 
-  // Discard all blocks except the special block (if present).
+  // Discard all blocks except the first one. Whether it is user-provided or
+  // allocated, always reuse the first block for the first arena.
   size_t space_allocated = 0;
   auto mem = Free(&space_allocated);
-  arena_stats_.RecordReset();
+  space_allocated += mem.size;
 
-  AllocationPolicy* policy = alloc_policy_.get();
-  if (policy) {
-    auto saved_policy = *policy;
-    if (alloc_policy_.is_user_owned_initial_block()) {
-      space_allocated += mem.size;
-    } else {
-      GetDeallocator(alloc_policy_.get(), &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, saved_policy);
+  // Reset the first arena with the first block. This avoids redundant
+  // free / allocation and re-allocating for AllocationPolicy. Adjust offset if
+  // we need to preserve alloc_policy_.
+  if (alloc_policy_.is_user_owned_initial_block() ||
+      alloc_policy_.get() != nullptr) {
+    size_t offset = alloc_policy_.get() == nullptr
+                        ? kBlockHeaderSize
+                        : kBlockHeaderSize + kAllocPolicySize;
+    first_arena_.Init(new (mem.ptr) ArenaBlock{nullptr, mem.size}, offset);
   } else {
-    GOOGLE_DCHECK(!alloc_policy_.should_record_allocs());
-    // Nullptr policy
-    if (alloc_policy_.is_user_owned_initial_block()) {
-      space_allocated += mem.size;
-      InitializeFrom(mem.ptr, mem.size);
-    } else {
-      GetDeallocator(alloc_policy_.get(), &space_allocated)(mem);
-      Init();
-    }
+    first_arena_.Init(SentryArenaBlock(), 0);
   }
 
+  // Since the first block and potential alloc_policy on the first block is
+  // preserved, this can be initialized by Init().
+  Init();
+
   return space_allocated;
 }
 
-std::pair<void*, SerialArena::CleanupNode*>
-ThreadSafeArena::AllocateAlignedWithCleanup(size_t n,
-                                            const std::type_info* type) {
+void* ThreadSafeArena::AllocateAlignedWithCleanup(size_t n, size_t align,
+                                                  void (*destructor)(void*)) {
   SerialArena* arena;
-  if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
-                            GetSerialArenaFast(&arena))) {
-    return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
+  if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
+    return arena->AllocateAlignedWithCleanup(n, align, destructor);
   } else {
-    return AllocateAlignedWithCleanupFallback(n, type);
+    return AllocateAlignedWithCleanupFallback(n, align, destructor);
   }
 }
 
 void ThreadSafeArena::AddCleanup(void* elem, void (*cleanup)(void*)) {
   SerialArena* arena;
   if (PROTOBUF_PREDICT_FALSE(!GetSerialArenaFast(&arena))) {
-    arena = GetSerialArenaFallback(&thread_cache());
+    arena = GetSerialArenaFallback(kMaxCleanupNodeSize);
   }
-  arena->AddCleanup(elem, cleanup, AllocPolicy());
+  arena->AddCleanup(elem, cleanup);
 }
 
 PROTOBUF_NOINLINE
-void* ThreadSafeArena::AllocateAlignedFallback(size_t n,
-                                               const std::type_info* type) {
-  if (alloc_policy_.should_record_allocs()) {
-    alloc_policy_.RecordAlloc(type, n);
-    SerialArena* arena;
-    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
-      return arena->AllocateAligned(n, alloc_policy_.get());
-    }
-  }
-  return GetSerialArenaFallback(&thread_cache())
-      ->AllocateAligned(n, alloc_policy_.get());
+void* ThreadSafeArena::AllocateAlignedWithCleanupFallback(
+    size_t n, size_t align, void (*destructor)(void*)) {
+  return GetSerialArenaFallback(n + kMaxCleanupNodeSize)
+      ->AllocateAlignedWithCleanup(n, align, destructor);
 }
 
-PROTOBUF_NOINLINE
-std::pair<void*, SerialArena::CleanupNode*>
-ThreadSafeArena::AllocateAlignedWithCleanupFallback(
-    size_t n, const std::type_info* type) {
-  if (alloc_policy_.should_record_allocs()) {
-    alloc_policy_.RecordAlloc(type, n);
-    SerialArena* arena;
-    if (GetSerialArenaFast(&arena)) {
-      return arena->AllocateAlignedWithCleanup(n, alloc_policy_.get());
-    }
+template <typename Functor>
+void ThreadSafeArena::WalkConstSerialArenaChunk(Functor fn) const {
+  const SerialArenaChunk* chunk = head_.load(std::memory_order_acquire);
+
+  for (; !chunk->IsSentry(); chunk = chunk->next_chunk()) {
+    fn(chunk);
   }
-  return GetSerialArenaFallback(&thread_cache())
-      ->AllocateAlignedWithCleanup(n, alloc_policy_.get());
+}
+
+template <typename Functor>
+void ThreadSafeArena::WalkSerialArenaChunk(Functor fn) {
+  // By omitting an Acquire barrier we help the sanitizer that any user code
+  // that doesn't properly synchronize Reset() or the destructor will throw a
+  // TSAN warning.
+  SerialArenaChunk* chunk = head_.load(std::memory_order_relaxed);
+
+  while (!chunk->IsSentry()) {
+    // Cache next chunk in case this chunk is destroyed.
+    SerialArenaChunk* next_chunk = chunk->next_chunk();
+    fn(chunk);
+    chunk = next_chunk;
+  }
+}
+
+template <typename Functor>
+void ThreadSafeArena::PerConstSerialArenaInChunk(Functor fn) const {
+  WalkConstSerialArenaChunk([&fn](const SerialArenaChunk* chunk) {
+    for (const auto& each : chunk->arenas()) {
+      const SerialArena* serial = each.load(std::memory_order_acquire);
+      // It is possible that newly added SerialArena is not updated although
+      // size was. This is acceptable for SpaceAllocated and SpaceUsed.
+      if (serial == nullptr) continue;
+      fn(serial);
+    }
+  });
 }
 
 uint64_t ThreadSafeArena::SpaceAllocated() const {
-  SerialArena* serial = threads_.load(std::memory_order_acquire);
-  uint64_t res = 0;
-  for (; serial; serial = serial->next()) {
-    res += serial->SpaceAllocated();
-  }
-  return res;
+  uint64_t space_allocated = first_arena_.SpaceAllocated();
+  PerConstSerialArenaInChunk([&space_allocated](const SerialArena* serial) {
+    space_allocated += serial->SpaceAllocated();
+  });
+  return space_allocated;
 }
 
 uint64_t ThreadSafeArena::SpaceUsed() const {
-  SerialArena* serial = threads_.load(std::memory_order_acquire);
-  uint64_t space_used = 0;
-  for (; serial; serial = serial->next()) {
-    space_used += serial->SpaceUsed();
-  }
+  // First arena is inlined to ThreadSafeArena and the first block's overhead is
+  // smaller than others that contain SerialArena.
+  uint64_t space_used = first_arena_.SpaceUsed();
+  PerConstSerialArenaInChunk([&space_used](const SerialArena* serial) {
+    // SerialArena on chunks directly allocated from the block and needs to be
+    // subtracted from SpaceUsed.
+    space_used += serial->SpaceUsed() - kSerialArenaSize;
+  });
   return space_used - (alloc_policy_.get() ? sizeof(AllocationPolicy) : 0);
 }
 
+template <AllocationClient alloc_client>
+PROTOBUF_NOINLINE void* ThreadSafeArena::AllocateAlignedFallback(size_t n) {
+  return GetSerialArenaFallback(n)->AllocateAligned<alloc_client>(n);
+}
+
+template void* ThreadSafeArena::AllocateAlignedFallback<
+    AllocationClient::kDefault>(size_t);
+template void*
+    ThreadSafeArena::AllocateAlignedFallback<AllocationClient::kArray>(size_t);
+
 void ThreadSafeArena::CleanupList() {
-  PerSerialArena([](SerialArena* a) { a->CleanupList(); });
+  WalkSerialArenaChunk([](SerialArenaChunk* chunk) {
+    absl::Span<std::atomic<SerialArena*>> span = chunk->arenas();
+    // Walks arenas backward to handle the first serial arena the last.
+    // Destroying in reverse-order to the construction is often assumed by users
+    // and required not to break inter-object dependencies. (b/247560530)
+    for (auto it = span.rbegin(); it != span.rend(); ++it) {
+      SerialArena* serial = it->load(std::memory_order_relaxed);
+      GOOGLE_DCHECK_NE(serial, nullptr);
+      serial->CleanupList();
+    }
+  });
+  // First arena must be cleaned up last. (b/247560530)
+  first_arena_.CleanupList();
 }
 
 PROTOBUF_NOINLINE
-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()) {
-    if (serial->owner() == me) {
-      break;
-    }
+SerialArena* ThreadSafeArena::GetSerialArenaFallback(size_t n) {
+  void* const id = &thread_cache();
+  if (id == first_owner_) {
+    CacheSerialArena(&first_arena_);
+    return &first_arena_;
   }
 
+  // Search matching SerialArena.
+  SerialArena* serial = nullptr;
+  WalkConstSerialArenaChunk([&serial, id](const SerialArenaChunk* chunk) {
+    absl::Span<const std::atomic<void*>> ids = chunk->ids();
+    for (uint32_t i = 0; i < ids.size(); ++i) {
+      if (ids[i].load(std::memory_order_relaxed) == id) {
+        serial = chunk->arena(i).load(std::memory_order_relaxed);
+        GOOGLE_DCHECK_NE(serial, nullptr);
+        break;
+      }
+    }
+  });
+
   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.
+    // have any blocks yet.  So we'll allocate its first block now. It must be
+    // big enough to host SerialArena and the pending request.
     serial = SerialArena::New(
-        AllocateMemory(alloc_policy_.get(), 0, kSerialArenaSize), me,
-        arena_stats_.MutableStats());
+        AllocateMemory(alloc_policy_.get(), 0, n + kSerialArenaSize), *this);
 
-    SerialArena* head = threads_.load(std::memory_order_relaxed);
-    do {
-      serial->set_next(head);
-    } while (!threads_.compare_exchange_weak(
-        head, serial, std::memory_order_release, std::memory_order_relaxed));
+    AddSerialArena(id, serial);
   }
 
   CacheSerialArena(serial);
@@ -509,29 +884,18 @@
 
 }  // namespace internal
 
-PROTOBUF_FUNC_ALIGN(32)
-void* Arena::AllocateAlignedNoHook(size_t n) {
-  return impl_.AllocateAligned(n, nullptr);
+void* Arena::Allocate(size_t n) { return impl_.AllocateAligned(n); }
+
+void* Arena::AllocateForArray(size_t n) {
+  return impl_.AllocateAligned<internal::AllocationClient::kArray>(n);
 }
 
-PROTOBUF_FUNC_ALIGN(32)
-void* Arena::AllocateAlignedWithHook(size_t n, const std::type_info* type) {
-  return impl_.AllocateAligned(n, type);
-}
-
-PROTOBUF_FUNC_ALIGN(32)
-void* Arena::AllocateAlignedWithHookForArray(size_t n,
-                                             const std::type_info* type) {
-  return impl_.AllocateAligned<internal::AllocationClient::kArray>(n, type);
-}
-
-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);
+void* Arena::AllocateAlignedWithCleanup(size_t n, size_t align,
+                                        void (*destructor)(void*)) {
+  return impl_.AllocateAlignedWithCleanup(n, align, destructor);
 }
 
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/arena.h b/src/google/protobuf/arena.h
index 3b5f16c..abce219 100644
--- a/src/google/protobuf/arena.h
+++ b/src/google/protobuf/arena.h
@@ -49,11 +49,12 @@
 #endif
 
 #include <type_traits>
-#include <google/protobuf/arena_impl.h>
-#include <google/protobuf/port.h>
+#include "google/protobuf/arena_config.h"
+#include "google/protobuf/arena_impl.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -86,25 +87,15 @@
 class LazyField;             // defined in lazy_field.h
 class EpsCopyInputStream;    // defined in parse_context.h
 class RepeatedPtrFieldBase;  // defined in repeated_ptr_field.h
+class TcParser;              // defined in generated_message_tctable_impl.h
 
 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>;
+  constexpr static void (*destructor)(void*) =
+      &internal::cleanup::arena_destruct_object<T>;
 };
 
 template <typename T>
@@ -123,77 +114,48 @@
 struct ArenaOptions {
   // This defines the size of the first block requested from the system malloc.
   // Subsequent block sizes will increase in a geometric series up to a maximum.
-  size_t start_block_size;
+  size_t start_block_size = internal::AllocationPolicy::kDefaultStartBlockSize;
 
   // This defines the maximum block size requested from system malloc (unless an
   // individual arena allocation request occurs with a size larger than this
   // maximum). Requested block sizes increase up to this value, then remain
   // here.
-  size_t max_block_size;
+  size_t max_block_size = internal::GetDefaultArenaMaxBlockSize();
 
-  // An initial block of memory for the arena to use, or NULL for none. If
+  // An initial block of memory for the arena to use, or nullptr for none. If
   // provided, the block must live at least as long as the arena itself. The
   // creator of the Arena retains ownership of the block after the Arena is
   // destroyed.
-  char* initial_block;
+  char* initial_block = nullptr;
 
   // The size of the initial block, if provided.
-  size_t initial_block_size;
+  size_t initial_block_size = 0;
 
   // A function pointer to an alloc method that returns memory blocks of size
   // requested. By default, it contains a ptr to the malloc function.
   //
   // NOTE: block_alloc and dealloc functions are expected to behave like
   // malloc and free, including Asan poisoning.
-  void* (*block_alloc)(size_t);
+  void* (*block_alloc)(size_t) = nullptr;
   // A function pointer to a dealloc method that takes ownership of the blocks
   // from the arena. By default, it contains a ptr to a wrapper function that
   // calls free.
-  void (*block_dealloc)(void*, size_t);
-
-  ArenaOptions()
-      : start_block_size(internal::AllocationPolicy::kDefaultStartBlockSize),
-        max_block_size(internal::AllocationPolicy::kDefaultMaxBlockSize),
-        initial_block(NULL),
-        initial_block_size(0),
-        block_alloc(nullptr),
-        block_dealloc(nullptr),
-        make_metrics_collector(nullptr) {}
+  void (*block_dealloc)(void*, size_t) = nullptr;
 
  private:
-  // 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)();
-
-  internal::ArenaMetricsCollector* MetricsCollector() const {
-    return make_metrics_collector ? (*make_metrics_collector)() : nullptr;
-  }
-
   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;
 };
 
-// Support for non-RTTI environments. (The metrics hooks API uses type
-// information.)
-#if PROTOBUF_RTTI
-#define RTTI_TYPE_ID(type) (&typeid(type))
-#else
-#define RTTI_TYPE_ID(type) (NULL)
-#endif
-
 // Arena allocator. Arena allocation replaces ordinary (heap-based) allocation
 // with new/delete, and improves performance by aggregating allocations into
 // larger blocks and freeing allocations all at once. Protocol messages are
@@ -221,7 +183,7 @@
 //   with `args` (without `arena`), called when a T is allocated on the heap;
 //   and a constructor callable with `Arena* arena, Args&&... args`, called when
 //   a T is allocated on an arena. If the second constructor is called with a
-//   NULL arena pointer, it must be equivalent to invoking the first
+//   null arena pointer, it must be equivalent to invoking the first
 //   (`args`-only) constructor.
 //
 // - The type T must have a particular type trait: a nested type
@@ -231,7 +193,7 @@
 //
 // - The type T *may* have the type trait |DestructorSkippable_|. If this type
 //   trait is present in the type, then its destructor will not be called if and
-//   only if it was passed a non-NULL arena pointer. If this type trait is not
+//   only if it was passed a non-null arena pointer. If this type trait is not
 //   present on the type, then its destructor is always called when the
 //   containing arena is destroyed.
 //
@@ -270,13 +232,10 @@
 
   inline ~Arena() {}
 
-  // 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
-  // defined in a .proto file with cc_enable_arenas set to true, otherwise a
-  // compilation error will occur.
+  // is nullptr, then a heap allocated object is returned. Type T must be a
+  // message defined in a .proto file with cc_enable_arenas set to true,
+  // otherwise a compilation error will occur.
   //
   // RepeatedField and RepeatedPtrField may also be instantiated directly on an
   // arena with this method.
@@ -311,21 +270,36 @@
   // is obtained from the arena).
   template <typename T, typename... Args>
   PROTOBUF_NDEBUG_INLINE static T* Create(Arena* arena, Args&&... args) {
-    return CreateInternal<T>(arena, std::is_convertible<T*, MessageLite*>(),
-                             static_cast<Args&&>(args)...);
+    if (arena == nullptr) {
+      return new T(std::forward<Args>(args)...);
+    }
+    auto destructor =
+        internal::ObjectDestructor<std::is_trivially_destructible<T>::value,
+                                   T>::destructor;
+    return new (arena->AllocateInternal(sizeof(T), alignof(T), destructor))
+        T(std::forward<Args>(args)...);
+  }
+
+  // API to delete any objects not on an arena.  This can be used to safely
+  // clean up messages or repeated fields without knowing whether or not they're
+  // owned by an arena.  The pointer passed to this function should not be used
+  // again.
+  template <typename T>
+  PROTOBUF_ALWAYS_INLINE static void Destroy(T* obj) {
+    if (InternalGetOwningArena(obj) == nullptr) delete obj;
   }
 
   // Allocates memory with the specific size and alignment.
   void* AllocateAligned(size_t size, size_t align = 8) {
     if (align <= 8) {
-      return AllocateAlignedNoHook(internal::AlignUpTo8(size));
+      return Allocate(internal::AlignUpTo8(size));
     } 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(size + align - 8), align);
+      return internal::AlignTo(Allocate(size + align - 8), align);
     }
   }
 
@@ -344,7 +318,7 @@
                   "CreateArray requires a trivially destructible type");
     GOOGLE_CHECK_LE(num_elements, std::numeric_limits<size_t>::max() / sizeof(T))
         << "Requested size is too large to fit into size_t.";
-    if (arena == NULL) {
+    if (arena == nullptr) {
       return static_cast<T*>(::operator new[](num_elements * sizeof(T)));
     } else {
       return arena->CreateInternalRawArray<T>(num_elements);
@@ -359,9 +333,12 @@
   // sizes of the underlying blocks.
   uint64_t 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
-  // may not include space used by other threads executing concurrently with
-  // the call to this method.
+  // does not include free space and block overhead.  This is a best-effort
+  // estimate and may inaccurately calculate space used by other threads
+  // executing concurrently with the call to this method.  These inaccuracies
+  // are due to race conditions, and are bounded but unpredictable.  Stale data
+  // can lead to underestimates of the space used, and race conditions can lead
+  // to overestimates (up to the current block size).
   uint64_t SpaceUsed() const { return impl_.SpaceUsed(); }
 
   // Frees all storage allocated by this arena after calling destructors
@@ -375,7 +352,15 @@
   // when the arena is destroyed or reset.
   template <typename T>
   PROTOBUF_ALWAYS_INLINE void Own(T* object) {
-    OwnInternal(object, std::is_convertible<T*, MessageLite*>());
+    // Collapsing all template instantiations to one for generic Message reduces
+    // code size, using the virtual destructor instead.
+    using TypeToUse =
+        std::conditional_t<std::is_convertible<T*, MessageLite*>::value,
+                           MessageLite, T>;
+    if (object != nullptr) {
+      impl_.AddCleanup(static_cast<TypeToUse*>(object),
+                       &internal::arena_delete_object<TypeToUse>);
+    }
   }
 
   // Adds |object| to a list of objects whose destructors will be manually
@@ -385,8 +370,8 @@
   // arena-allocated memory.
   template <typename T>
   PROTOBUF_ALWAYS_INLINE void OwnDestructor(T* object) {
-    if (object != NULL) {
-      impl_.AddCleanup(object, &internal::arena_destruct_object<T>);
+    if (object != nullptr) {
+      impl_.AddCleanup(object, &internal::cleanup::arena_destruct_object<T>);
     }
   }
 
@@ -400,9 +385,9 @@
   }
 
   // Retrieves the arena associated with |value| if |value| is an arena-capable
-  // message, or NULL otherwise. If possible, the call resolves at compile time.
-  // Note that we can often devirtualize calls to `value->GetArena()` so usually
-  // calling this method is unnecessary.
+  // message, or nullptr otherwise. If possible, the call resolves at compile
+  // time. Note that we can often devirtualize calls to `value->GetArena()` so
+  // usually calling this method is unnecessary.
   template <typename T>
   PROTOBUF_ALWAYS_INLINE static Arena* GetArena(const T* value) {
     return GetArenaInternal(value);
@@ -411,40 +396,62 @@
   template <typename T>
   class InternalHelper {
    private:
-    // Provides access to protected GetOwningArena to generated messages.
-    static Arena* GetOwningArena(const T* p) { return p->GetOwningArena(); }
+    // A SFINAE friendly trait that probes for `U` but always evalues to
+    // `Arena*`.
+    template <typename U>
+    using EnableIfArena =
+        typename std::enable_if<std::is_same<Arena*, U>::value, Arena*>::type;
+
+    // Rather than use SFINAE that must fully cover the space of options in a
+    // mutually exclusive fashion, we use implicit conversions to base classes
+    // to force an explicit ranking for our preferences.  The lowest ranked
+    // version that compiles will be accepted.
+    struct Rank2 {};
+    struct Rank1 : Rank2 {};
+    struct Rank0 : Rank1 {};
+
+    static Arena* GetOwningArena(const T* p) {
+      return GetOwningArena(Rank0{}, p);
+    }
+
+    template <typename U>
+    static auto GetOwningArena(Rank0, const U* p)
+        -> EnableIfArena<decltype(p->GetOwningArena())> {
+      return p->GetOwningArena();
+    }
+
+    template <typename U>
+    static Arena* GetOwningArena(Rank1, const U* p) {
+      return nullptr;
+    }
 
     static void InternalSwap(T* a, T* b) { a->InternalSwap(b); }
 
-    static Arena* GetArenaForAllocationInternal(
-        const T* p, std::true_type /*is_derived_from<MessageLite>*/) {
+    static Arena* GetArenaForAllocation(const T* p) {
+      return GetArenaForAllocation(Rank0{}, p);
+    }
+
+    static Arena* GetArena(const T* p) {
+      // Rather than replicate probing for `GetArena` with fallback to nullptr,
+      // we borrow the implementation of `GetArenaForAllocation` but skip
+      // `Rank0` which probes for `GetArenaForAllocation`.
+      return GetArenaForAllocation(Rank1{}, p);
+    }
+
+    template <typename U>
+    static auto GetArenaForAllocation(Rank0, const U* p)
+        -> EnableIfArena<decltype(p->GetArenaForAllocation())> {
       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*/) {
+    template <typename U>
+    static auto GetArenaForAllocation(Rank1, const U* p)
+        -> EnableIfArena<decltype(p->GetArena())> {
       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*/) {
+    template <typename U>
+    static Arena* GetArenaForAllocation(Rank2, const U* p) {
       return nullptr;
     }
 
@@ -470,18 +477,6 @@
                                              sizeof(char)>
         is_arena_constructable;
 
-    template <typename U,
-              typename std::enable_if<
-                  std::is_same<Arena*, decltype(std::declval<const U>()
-                                                    .GetArena())>::value,
-                  int>::type = 0>
-    static char HasGetArena(decltype(&U::GetArena));
-    template <typename U>
-    static double HasGetArena(...);
-
-    typedef std::integral_constant<bool, sizeof(HasGetArena<T>(nullptr)) ==
-                                             sizeof(char)>
-        has_get_arena;
 
     template <typename... Args>
     static T* Construct(void* ptr, Args&&... args) {
@@ -492,8 +487,6 @@
       return new T(nullptr);
     }
 
-    static Arena* GetArena(const T* p) { return p->GetArena(); }
-
     friend class Arena;
     friend class TestUtil::ReflectionTester;
   };
@@ -509,8 +502,7 @@
   // For internal use only.
   template <typename T>
   static Arena* InternalGetArenaForAllocation(const T* p) {
-    return InternalHelper<T>::GetArenaForAllocationInternal(
-        p, std::is_convertible<T*, MessageLite*>());
+    return InternalHelper<T>::GetArenaForAllocation(p);
   }
 
   // Creates message-owned arena.  For internal use only.
@@ -542,9 +534,6 @@
  private:
   internal::ThreadSafeArena impl_;
 
-  template <typename T>
-  struct has_get_arena : InternalHelper<T>::has_get_arena {};
-
   // Constructor solely used by message-owned arena.
   inline Arena(internal::MessageOwned) : impl_(internal::MessageOwned{}) {}
 
@@ -563,7 +552,7 @@
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
         "CreateMessage can only construct types that are ArenaConstructable");
-    if (arena == NULL) {
+    if (arena == nullptr) {
       return new T(nullptr, static_cast<Args&&>(args)...);
     } else {
       return arena->DoCreateMessage<T>(static_cast<Args&&>(args)...);
@@ -578,7 +567,7 @@
     static_assert(
         InternalHelper<T>::is_arena_constructable::value,
         "CreateMessage can only construct types that are ArenaConstructable");
-    if (arena == NULL) {
+    if (arena == nullptr) {
       // Generated arena constructor T(Arena*) is protected. Call via
       // InternalHelper.
       return InternalHelper<T>::New();
@@ -587,27 +576,13 @@
     }
   }
 
-  // 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) {
+                                                void (*destructor)(void*)) {
     // Monitor allocation if needed.
     if (destructor == nullptr) {
-      return AllocateAlignedWithHook(size, align, type);
+      return AllocateAligned(size, align);
     } else {
-      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;
-      }
+      return AllocateAlignedWithCleanup(size, align, destructor);
     }
   }
 
@@ -646,8 +621,7 @@
     // 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*>(
-        AllocateAlignedWithHookForArray(n, alignof(T), RTTI_TYPE_ID(T)));
+    return static_cast<T*>(AllocateAlignedForArray(n, alignof(T)));
   }
 
   template <typename T, typename... Args>
@@ -656,8 +630,7 @@
         AllocateInternal(sizeof(T), alignof(T),
                          internal::ObjectDestructor<
                              InternalHelper<T>::is_destructor_skippable::value,
-                             T>::destructor,
-                         RTTI_TYPE_ID(T)),
+                             T>::destructor),
         this, std::forward<Args>(args)...);
   }
 
@@ -696,141 +669,38 @@
     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
-  // all template instantiations to one for generic Message reduces code size,
-  // using the virtual destructor instead.
-  template <typename T>
-  PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::true_type) {
-    if (object != NULL) {
-      impl_.AddCleanup(object, &internal::arena_delete_object<MessageLite>);
-    }
-  }
-  template <typename T>
-  PROTOBUF_ALWAYS_INLINE void OwnInternal(T* object, std::false_type) {
-    if (object != NULL) {
-      impl_.AddCleanup(object, &internal::arena_delete_object<T>);
-    }
-  }
-
   // Implementation for GetArena(). Only message objects with
   // InternalArenaConstructable_ tags can be associated with an arena, and such
   // objects must implement a GetArena() method.
-  template <typename T, typename std::enable_if<
-                            is_arena_constructable<T>::value, int>::type = 0>
+  template <typename T>
   PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
     return InternalHelper<T>::GetArena(value);
   }
-  template <typename T,
-            typename std::enable_if<!is_arena_constructable<T>::value &&
-                                        has_get_arena<T>::value,
-                                    int>::type = 0>
-  PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
-    return value->GetArena();
-  }
-  template <typename T,
-            typename std::enable_if<!is_arena_constructable<T>::value &&
-                                        !has_get_arena<T>::value,
-                                    int>::type = 0>
-  PROTOBUF_ALWAYS_INLINE static Arena* GetArenaInternal(const T* value) {
-    (void)value;
-    return nullptr;
-  }
 
-  template <typename T>
-  PROTOBUF_ALWAYS_INLINE static Arena* GetOwningArena(const T* value) {
-    return GetOwningArenaInternal(
-        value, std::is_convertible<T*, MessageLite*>());
-  }
-
-  // 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;
-  }
-
-  void* AllocateAlignedWithHookForArray(size_t n, size_t align,
-                                        const std::type_info* type) {
+  void* AllocateAlignedForArray(size_t n, size_t align) {
     if (align <= 8) {
-      return AllocateAlignedWithHookForArray(internal::AlignUpTo8(n), type);
+      return AllocateForArray(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(
-          AllocateAlignedWithHookForArray(n + align - 8, type), align);
+      return internal::AlignTo(AllocateForArray(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 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(AllocateAlignedWithHook(n + align - 8, type),
-                               align);
-    }
-  }
-
-  void* AllocateAlignedNoHook(size_t n);
-  void* AllocateAlignedWithHook(size_t n, const std::type_info* type);
-  void* AllocateAlignedWithHookForArray(size_t n, const std::type_info* type);
-  std::pair<void*, internal::SerialArena::CleanupNode*>
-  AllocateAlignedWithCleanup(size_t n, const std::type_info* type);
+  void* Allocate(size_t n);
+  void* AllocateForArray(size_t n);
+  void* AllocateAlignedWithCleanup(size_t n, size_t align,
+                                   void (*destructor)(void*));
 
   template <typename Type>
   friend class internal::GenericTypeHandler;
   friend class internal::InternalMetadata;  // For user_arena().
   friend class internal::LazyField;        // For CreateMaybeMessage.
   friend class internal::EpsCopyInputStream;  // For parser performance
+  friend class internal::TcParser;            // For parser performance
   friend class MessageLite;
   template <typename Key, typename T>
   friend class Map;
@@ -840,12 +710,9 @@
   friend struct internal::ArenaTestPeer;
 };
 
-// Defined above for supporting environments without RTTI.
-#undef RTTI_TYPE_ID
-
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_ARENA_H__
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/arena_align.cc
similarity index 86%
rename from src/google/protobuf/util/internal/error_listener.cc
rename to src/google/protobuf/arena_align.cc
index 538307b..882ae5a 100644
--- a/src/google/protobuf/util/internal/error_listener.cc
+++ b/src/google/protobuf/arena_align.cc
@@ -28,15 +28,18 @@
 // (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/util/internal/error_listener.h>
+#include "google/protobuf/arena_align.h"
+
+#include <cstddef>
+#include <cstdint>
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace converter {
+namespace internal {
 
+// There are still compilers (open source) requiring a definition for constexpr.
+constexpr size_t ArenaAlignDefault::align;  // NOLINT
 
-}  // namespace converter
-}  // namespace util
+}  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/arena_align.h b/src/google/protobuf/arena_align.h
new file mode 100644
index 0000000..fde9b4d
--- /dev/null
+++ b/src/google/protobuf/arena_align.h
@@ -0,0 +1,160 @@
+// 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 provides alignment utilities for use in arenas.
+//
+// `ArenaAlign` contains a single `align` data member and provides
+// the below functions which operate on the given alignment.
+//
+//   Ceil(size_t n)      - rounds `n` up to the nearest `align` boundary.
+//   Floor(size_t n)     - rounds `n` down to the nearest `align` boundary.
+//   Ceil(T* P)          - rounds `p` up to the nearest `align` boundary.
+//   IsAligned(size_t n) - returns true if `n` is aligned to `align`
+//   IsAligned(T* p)     - returns true if `p` is aligned to `align`
+//   CheckAligned(T* p)  - returns `p`. Checks alignment of `p` in debug.
+//
+// Additionally there is an optimized `CeilDefaultAligned(T*)` method which is
+// equivalent to `Ceil(ArenaAlignDefault().CheckAlign(p))` but more efficiently
+// implemented as a 'check only' for ArenaAlignDefault.
+//
+// These classes allow for generic arena logic using 'alignment policies'.
+//
+// For example:
+//
+//  template <Align>
+//  void* NaiveAlloc(size_t n, Align align) {
+//    align.CheckAligned(n);
+//    uint8_t* ptr = align.CeilDefaultAligned(ptr_);
+//    ptr_ += n;
+//    return ptr;
+//  }
+//
+//  void CallSites() {
+//    void *p1 = NaiveAlloc(n, ArenaAlignDefault());
+//    void *p2 = NaiveAlloc(n, ArenaAlignAs(32));
+//  }
+//
+#ifndef GOOGLE_PROTOBUF_ARENA_ALIGN_H__
+#define GOOGLE_PROTOBUF_ARENA_ALIGN_H__
+
+#include <cstddef>
+#include <cstdint>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/numeric/bits.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+struct ArenaAlignDefault {
+  PROTOBUF_EXPORT static constexpr size_t align = 8;  // NOLINT
+
+  static constexpr bool IsAligned(size_t n) { return (n & (align - 1)) == 0; }
+
+  template <typename T>
+  static bool IsAligned(T* ptr) {
+    return (reinterpret_cast<uintptr_t>(ptr) & (align - 1)) == 0;
+  }
+
+  static constexpr size_t Ceil(size_t n) { return (n + align - 1) & -align; }
+  static constexpr size_t Floor(size_t n) { return (n & ~(align - 1)); }
+
+  template <typename T>
+  T* Ceil(T* ptr) const {
+    uintptr_t intptr = reinterpret_cast<uintptr_t>(ptr);
+    return reinterpret_cast<T*>((intptr + align - 1) & -align);
+  }
+
+  template <typename T>
+  T* CeilDefaultAligned(T* ptr) const {
+    return ArenaAlignDefault().CheckAligned(ptr);
+  }
+
+  // Address sanitizer enabled alignment check
+  template <typename T>
+  static T* CheckAligned(T* ptr) {
+    GOOGLE_DCHECK(IsAligned(ptr)) << static_cast<void*>(ptr);
+    return ptr;
+  }
+};
+
+struct ArenaAlign {
+  static constexpr bool IsDefault() { return false; };
+
+  size_t align;
+
+  constexpr bool IsAligned(size_t n) const { return (n & (align - 1)) == 0; }
+
+  template <typename T>
+  bool IsAligned(T* ptr) const {
+    return (reinterpret_cast<uintptr_t>(ptr) & (align - 1)) == 0;
+  }
+
+  constexpr size_t Ceil(size_t n) const { return (n + align - 1) & -align; }
+  constexpr size_t Floor(size_t n) const { return (n & ~(align - 1)); }
+
+  template <typename T>
+  T* Ceil(T* ptr) const {
+    uintptr_t intptr = reinterpret_cast<uintptr_t>(ptr);
+    return reinterpret_cast<T*>((intptr + align - 1) & -align);
+  }
+
+  template <typename T>
+  T* CeilDefaultAligned(T* ptr) const {
+    return Ceil(ArenaAlignDefault().CheckAligned(ptr));
+  }
+
+  // Address sanitizer enabled alignment check
+  template <typename T>
+  T* CheckAligned(T* ptr) const {
+    GOOGLE_DCHECK(IsAligned(ptr)) << static_cast<void*>(ptr);
+    return ptr;
+  }
+};
+
+inline ArenaAlign ArenaAlignAs(size_t align) {
+  // align must be a non zero power of 2 >= 8
+  GOOGLE_DCHECK_NE(align, 0);
+  GOOGLE_DCHECK(absl::has_single_bit(align)) << "Invalid alignment " << align;
+  return ArenaAlign{align};
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_ARENA_ALIGN_H__
diff --git a/src/google/protobuf/arena_align_test.cc b/src/google/protobuf/arena_align_test.cc
new file mode 100644
index 0000000..e17cb33
--- /dev/null
+++ b/src/google/protobuf/arena_align_test.cc
@@ -0,0 +1,215 @@
+// 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/arena_align.h"
+
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace {
+
+using ::testing::Eq;
+
+TEST(ArenaAlignDefault, Align) {
+  auto align_default = ArenaAlignDefault();
+  EXPECT_THAT(align_default.align, Eq(8));
+}
+
+TEST(ArenaAlignDefault, Floor) {
+  auto align_default = ArenaAlignDefault();
+  EXPECT_THAT(align_default.Floor(0), Eq(0));
+  EXPECT_THAT(align_default.Floor(1), Eq(0));
+  EXPECT_THAT(align_default.Floor(7), Eq(0));
+  EXPECT_THAT(align_default.Floor(8), Eq(8));
+  EXPECT_THAT(align_default.Floor(9), Eq(8));
+  EXPECT_THAT(align_default.Floor(15), Eq(8));
+  EXPECT_THAT(align_default.Floor(16), Eq(16));
+}
+
+TEST(ArenaAlignDefault, Ceil) {
+  auto align_default = ArenaAlignDefault();
+  EXPECT_THAT(align_default.Ceil(0), Eq(0));
+  EXPECT_THAT(align_default.Ceil(1), Eq(8));
+  EXPECT_THAT(align_default.Ceil(7), Eq(8));
+  EXPECT_THAT(align_default.Ceil(8), Eq(8));
+  EXPECT_THAT(align_default.Ceil(9), Eq(16));
+  EXPECT_THAT(align_default.Ceil(15), Eq(16));
+  EXPECT_THAT(align_default.Ceil(16), Eq(16));
+}
+
+TEST(ArenaAlignDefault, CeilPtr) {
+  alignas(8) char p[17] = {0};
+  auto align_default = ArenaAlignDefault();
+  EXPECT_THAT(align_default.Ceil(p + 0), Eq(p + 0));
+  EXPECT_THAT(align_default.Ceil(p + 1), Eq(p + 8));
+  EXPECT_THAT(align_default.Ceil(p + 7), Eq(p + 8));
+  EXPECT_THAT(align_default.Ceil(p + 8), Eq(p + 8));
+  EXPECT_THAT(align_default.Ceil(p + 9), Eq(p + 16));
+  EXPECT_THAT(align_default.Ceil(p + 15), Eq(p + 16));
+  EXPECT_THAT(align_default.Ceil(p + 16), Eq(p + 16));
+}
+
+TEST(ArenaAlignDefault, CheckAligned) {
+  alignas(8) char p[17] = {0};
+  auto align_default = ArenaAlignDefault();
+  EXPECT_THAT(align_default.CheckAligned(p + 0), Eq(p + 0));
+  EXPECT_THAT(align_default.CheckAligned(p + 8), Eq(p + 8));
+  EXPECT_THAT(align_default.CheckAligned(p + 16), Eq(p + 16));
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 1), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 7), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 9), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 15), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CheckAligned(p + 17), ".*");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST(ArenaAlignDefault, CeilDefaultAligned) {
+  alignas(8) char p[17] = {0};
+  auto align_default = ArenaAlignDefault();
+  EXPECT_THAT(align_default.CeilDefaultAligned(p + 0), Eq(p + 0));
+  EXPECT_THAT(align_default.CeilDefaultAligned(p + 8), Eq(p + 8));
+  EXPECT_THAT(align_default.CeilDefaultAligned(p + 16), Eq(p + 16));
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 1), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 7), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 9), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 15), ".*");
+  EXPECT_DEBUG_DEATH(align_default.CeilDefaultAligned(p + 17), ".*");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST(ArenaAlignDefault, IsAligned) {
+  auto align_default = ArenaAlignDefault();
+  EXPECT_TRUE(align_default.IsAligned(0));
+  EXPECT_FALSE(align_default.IsAligned(1));
+  EXPECT_FALSE(align_default.IsAligned(7));
+  EXPECT_TRUE(align_default.IsAligned(8));
+  EXPECT_FALSE(align_default.IsAligned(9));
+  EXPECT_FALSE(align_default.IsAligned(15));
+  EXPECT_TRUE(align_default.IsAligned(16));
+}
+
+TEST(ArenaAlign, Align) {
+  auto align_64 = ArenaAlignAs(64);
+  EXPECT_THAT(align_64.align, Eq(64));
+}
+
+TEST(ArenaAlign, Floor) {
+  auto align_64 = ArenaAlignAs(64);
+  EXPECT_THAT(align_64.Floor(0), Eq(0));
+  EXPECT_THAT(align_64.Floor(1), Eq(0));
+  EXPECT_THAT(align_64.Floor(63), Eq(0));
+  EXPECT_THAT(align_64.Floor(64), Eq(64));
+  EXPECT_THAT(align_64.Floor(65), Eq(64));
+  EXPECT_THAT(align_64.Floor(127), Eq(64));
+  EXPECT_THAT(align_64.Floor(128), Eq(128));
+}
+
+TEST(ArenaAlign, Ceil) {
+  auto align_64 = ArenaAlignAs(64);
+  EXPECT_THAT(align_64.Ceil(0), Eq(0));
+  EXPECT_THAT(align_64.Ceil(1), Eq(64));
+  EXPECT_THAT(align_64.Ceil(63), Eq(64));
+  EXPECT_THAT(align_64.Ceil(64), Eq(64));
+  EXPECT_THAT(align_64.Ceil(65), Eq(128));
+  EXPECT_THAT(align_64.Ceil(127), Eq(128));
+  EXPECT_THAT(align_64.Ceil(128), Eq(128));
+}
+
+TEST(ArenaAlign, CeilPtr) {
+  alignas(64) char p[129] = {0};
+  auto align_64 = ArenaAlignAs(64);
+  EXPECT_THAT(align_64.Ceil(p + 0), Eq(p));
+  EXPECT_THAT(align_64.Ceil(p + 1), Eq(p + 64));
+  EXPECT_THAT(align_64.Ceil(p + 63), Eq(p + 64));
+  EXPECT_THAT(align_64.Ceil(p + 64), Eq(p + 64));
+  EXPECT_THAT(align_64.Ceil(p + 65), Eq(p + 128));
+  EXPECT_THAT(align_64.Ceil(p + 127), Eq(p + 128));
+  EXPECT_THAT(align_64.Ceil(p + 128), Eq(p + 128));
+}
+
+TEST(ArenaAlign, CheckAligned) {
+  alignas(128) char p[129] = {0};
+  auto align_64 = ArenaAlignAs(64);
+  EXPECT_THAT(align_64.CheckAligned(p + 0), Eq(p));
+  EXPECT_THAT(align_64.CheckAligned(p + 64), Eq(p + 64));
+  EXPECT_THAT(align_64.CheckAligned(p + 128), Eq(p + 128));
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 1), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 7), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 8), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 56), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 63), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 65), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 72), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 120), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CheckAligned(p + 129), ".*");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST(ArenaAlign, CeilDefaultAligned) {
+  alignas(128) char p[129] = {0};
+  auto align_64 = ArenaAlignAs(64);
+  EXPECT_THAT(align_64.CeilDefaultAligned(p + 0), Eq(p));
+  EXPECT_THAT(align_64.CeilDefaultAligned(p + 8), Eq(p + 64));
+  EXPECT_THAT(align_64.CeilDefaultAligned(p + 56), Eq(p + 64));
+  EXPECT_THAT(align_64.CeilDefaultAligned(p + 64), Eq(p + 64));
+  EXPECT_THAT(align_64.CeilDefaultAligned(p + 72), Eq(p + 128));
+  EXPECT_THAT(align_64.CeilDefaultAligned(p + 120), Eq(p + 128));
+  EXPECT_THAT(align_64.CeilDefaultAligned(p + 128), Eq(p + 128));
+#ifdef PROTOBUF_HAS_DEATH_TEST
+  EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 1), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 7), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 63), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 65), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 127), ".*");
+  EXPECT_DEBUG_DEATH(align_64.CeilDefaultAligned(p + 129), ".*");
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}
+
+TEST(ArenaAlign, IsAligned) {
+  auto align_64 = ArenaAlignAs(64);
+  EXPECT_TRUE(align_64.IsAligned(0));
+  EXPECT_FALSE(align_64.IsAligned(1));
+  EXPECT_FALSE(align_64.IsAligned(63));
+  EXPECT_TRUE(align_64.IsAligned(64));
+  EXPECT_FALSE(align_64.IsAligned(65));
+  EXPECT_FALSE(align_64.IsAligned(127));
+  EXPECT_TRUE(align_64.IsAligned(128));
+}
+
+}  // namespace
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/arena_allocation_policy.h b/src/google/protobuf/arena_allocation_policy.h
new file mode 100644
index 0000000..2427cf4
--- /dev/null
+++ b/src/google/protobuf/arena_allocation_policy.h
@@ -0,0 +1,126 @@
+// 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_ARENA_ALLOCATION_POLICY_H__
+#define GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__
+
+#include <cstddef>
+#include <cstdint>
+
+#include "google/protobuf/arena_config.h"
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+// `AllocationPolicy` defines `Arena` allocation policies. Applications can
+// customize the initial and maximum sizes for arena allocation, as well as set
+// custom allocation and deallocation functions. `AllocationPolicy` is for
+// protocol buffer internal use only, and typically created from a user facing
+// public configuration class such as `ArenaOptions`.
+struct AllocationPolicy {
+  static constexpr size_t kDefaultStartBlockSize = 256;
+
+  size_t start_block_size = kDefaultStartBlockSize;
+  size_t max_block_size = GetDefaultArenaMaxBlockSize();
+
+  void* (*block_alloc)(size_t) = nullptr;
+  void (*block_dealloc)(void*, size_t) = nullptr;
+
+  bool IsDefault() const {
+    return start_block_size == kDefaultStartBlockSize &&
+           max_block_size == GetDefaultArenaMaxBlockSize() &&
+           block_alloc == nullptr && block_dealloc == nullptr;
+  }
+};
+
+// Tagged pointer to an AllocationPolicy.
+class TaggedAllocationPolicyPtr {
+ public:
+  constexpr TaggedAllocationPolicyPtr() : policy_(0) {}
+
+  explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy)
+      : policy_(reinterpret_cast<uintptr_t>(policy)) {}
+
+  void set_policy(AllocationPolicy* policy) {
+    auto bits = policy_ & kTagsMask;
+    policy_ = reinterpret_cast<uintptr_t>(policy) | bits;
+  }
+
+  AllocationPolicy* get() {
+    return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask);
+  }
+  const AllocationPolicy* get() const {
+    return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask);
+  }
+
+  AllocationPolicy& operator*() { return *get(); }
+  const AllocationPolicy& operator*() const { return *get(); }
+
+  AllocationPolicy* operator->() { return get(); }
+  const AllocationPolicy* operator->() const { return get(); }
+
+  bool is_user_owned_initial_block() const {
+    return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
+  }
+  void set_is_user_owned_initial_block(bool v) {
+    set_mask<kUserOwnedInitialBlock>(v);
+  }
+
+  uintptr_t get_raw() const { return policy_; }
+
+ private:
+  enum : uintptr_t {
+    kUserOwnedInitialBlock = 1,
+  };
+
+  static constexpr uintptr_t kTagsMask = 7;
+  static constexpr uintptr_t kPtrMask = ~kTagsMask;
+
+  template <uintptr_t kMask>
+  uintptr_t get_mask() const {
+    return policy_ & kMask;
+  }
+  template <uintptr_t kMask>
+  void set_mask(bool v) {
+    if (v) {
+      policy_ |= kMask;
+    } else {
+      policy_ &= ~kMask;
+    }
+  }
+  uintptr_t policy_;
+};
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_ARENA_ALLOCATION_POLICY_H__
diff --git a/src/google/protobuf/arena_cleanup.h b/src/google/protobuf/arena_cleanup.h
new file mode 100644
index 0000000..0ca60c2
--- /dev/null
+++ b/src/google/protobuf/arena_cleanup.h
@@ -0,0 +1,193 @@
+// 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_ARENA_CLEANUP_H__
+#define GOOGLE_PROTOBUF_ARENA_CLEANUP_H__
+
+#include <cstddef>
+#include <cstdint>
+#include <string>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/base/attributes.h"
+
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace cleanup {
+
+// Helper function invoking the destructor of `object`
+template <typename T>
+void arena_destruct_object(void* object) {
+  reinterpret_cast<T*>(object)->~T();
+}
+
+// Tag defines the type of cleanup / cleanup object. This tag is stored in the
+// lowest 2 bits of the `elem` value identifying the type of node. All node
+// types must start with a `uintptr_t` that stores `Tag` in its low two bits.
+enum class Tag : uintptr_t {
+  kDynamic = 0,  // DynamicNode
+  kString = 1,   // StringNode (std::string)
+};
+
+// DynamicNode contains the object (`elem`) that needs to be
+// destroyed, and the function to destroy it (`destructor`)
+// elem must be aligned at minimum on a 4 byte boundary.
+struct DynamicNode {
+  uintptr_t elem;
+  void (*destructor)(void*);
+};
+
+// StringNode contains a `std::string` object (`elem`) that needs to be
+// destroyed. The lowest 2 bits of `elem` contain the non-zero kString tag.
+struct StringNode {
+  uintptr_t elem;
+};
+
+
+// EnableSpecializedTags() return true if the alignment of tagged objects
+// such as std::string allow us to poke tags in the 2 LSB bits.
+inline constexpr bool EnableSpecializedTags() {
+  // For now we require 2 bits
+  return alignof(std::string) >= 8;
+}
+
+// Adds a cleanup entry identified by `tag` at memory location `pos`.
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE void CreateNode(Tag tag, void* pos,
+                                                    const void* elem_raw,
+                                                    void (*destructor)(void*)) {
+  auto elem = reinterpret_cast<uintptr_t>(elem_raw);
+  if (EnableSpecializedTags()) {
+    GOOGLE_DCHECK_EQ(elem & 3, 0ULL);  // Must be aligned
+    switch (tag) {
+      case Tag::kString: {
+        StringNode n = {elem | static_cast<uintptr_t>(Tag::kString)};
+        memcpy(pos, &n, sizeof(n));
+        return;
+      }
+      default:
+        break;
+    }
+  }
+  DynamicNode n = {elem, destructor};
+  memcpy(pos, &n, sizeof(n));
+}
+
+// Optimization: performs a prefetch on `elem_address`.
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE void PrefetchNode(
+    const void* elem_address) {
+  (void)elem_address;
+}
+
+// Destroys the node idenitfied by `tag` stored at memory location `pos`.
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE void DestroyNode(Tag tag, const void* pos) {
+  if (EnableSpecializedTags()) {
+    switch (tag) {
+      case Tag::kString: {
+        StringNode n;
+        memcpy(&n, pos, sizeof(n));
+        auto* s = reinterpret_cast<std::string*>(n.elem & ~0x7ULL);
+        // Some compilers don't like fully qualified explicit dtor calls,
+        // so use an alias to avoid having to type `::`.
+        using string_type = std::string;
+        s->~string_type();
+        return;
+      }
+      default:
+        break;
+    }
+  }
+  DynamicNode n;
+  memcpy(&n, pos, sizeof(n));
+  n.destructor(reinterpret_cast<void*>(n.elem));
+}
+
+// Returns the `tag` identifying the type of object for `destructor` or
+// kDynamic if `destructor` does not identify a well know object type.
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE Tag Type(void (*destructor)(void*)) {
+  if (EnableSpecializedTags()) {
+    if (destructor == &arena_destruct_object<std::string>) {
+      return Tag::kString;
+    }
+  }
+  return Tag::kDynamic;
+}
+
+// Returns the `tag` identifying the type of object stored at memory location
+// `elem`, which represents the first uintptr_t value in the node.
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE Tag Type(void* raw) {
+  if (!EnableSpecializedTags()) return Tag::kDynamic;
+
+  uintptr_t elem;
+  memcpy(&elem, raw, sizeof(elem));
+  switch (static_cast<Tag>(elem & 0x7ULL)) {
+    case Tag::kDynamic:
+      return Tag::kDynamic;
+    case Tag::kString:
+      return Tag::kString;
+    default:
+      GOOGLE_LOG(FATAL) << "Corrupted cleanup tag: " << (elem & 0x7ULL);
+      return Tag::kDynamic;
+  }
+}
+
+// Returns the required size in bytes off the node type identified by `tag`.
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE size_t Size(Tag tag) {
+  if (!EnableSpecializedTags()) return sizeof(DynamicNode);
+
+  switch (tag) {
+    case Tag::kDynamic:
+      return sizeof(DynamicNode);
+    case Tag::kString:
+      return sizeof(StringNode);
+    default:
+      GOOGLE_LOG(FATAL) << "Corrupted cleanup tag: " << static_cast<int>(tag);
+      return sizeof(DynamicNode);
+  }
+}
+
+// Returns the required size in bytes off the node type for `destructor`.
+inline ABSL_ATTRIBUTE_ALWAYS_INLINE size_t Size(void (*destructor)(void*)) {
+  return destructor == nullptr ? 0 : Size(Type(destructor));
+}
+
+}  // namespace cleanup
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_ARENA_CLEANUP_H__
diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/arena_config.cc
similarity index 81%
rename from src/google/protobuf/stubs/once.h
rename to src/google/protobuf/arena_config.cc
index 070d36d..1fe7d05 100644
--- a/src/google/protobuf/stubs/once.h
+++ b/src/google/protobuf/arena_config.cc
@@ -28,28 +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.
 
-#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
-#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
+#include "google/protobuf/arena_config.h"
 
-#include <mutex>
-#include <utility>
+#include <atomic>
+#include <cstddef>
 
-#include <google/protobuf/port_def.inc>
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace internal {
 
-using once_flag = std::once_flag;
-template <typename... Args>
-void call_once(Args&&... args ) {
-  std::call_once(std::forward<Args>(args)...);
-}
+PROTOBUF_CONSTINIT const size_t kDefaultDefaultArenaMaxBlockSize = 32 << 10;
 
+namespace arena_config_internal {
+
+std::atomic<size_t> default_arena_max_block_size{
+    kDefaultDefaultArenaMaxBlockSize};
+
+}  // namespace arena_config_internal
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_ONCE_H__
diff --git a/src/google/protobuf/arena_config.h b/src/google/protobuf/arena_config.h
new file mode 100644
index 0000000..f16d86a
--- /dev/null
+++ b/src/google/protobuf/arena_config.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 GOOGLE_PROTOBUF_ARENA_CONFIG_H__
+#define GOOGLE_PROTOBUF_ARENA_CONFIG_H__
+
+#include <atomic>
+#include <cstddef>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace internal {
+namespace arena_config_internal {
+
+// We use an atomic here only for correctness so that we can read/write
+// concurrently. We don't have memory order requirements so we use relaxed
+// memory ordering.
+PROTOBUF_EXPORT extern std::atomic<size_t> default_arena_max_block_size;
+
+}  // namespace arena_config_internal
+
+// The default value to use for DefaultArenaMaxBlockSize when
+// SetDefaultArenaMaxBlockSize hasn't been called.
+PROTOBUF_EXPORT extern const size_t kDefaultDefaultArenaMaxBlockSize;
+
+// The default value to use for arena max block size when no value is provided
+// in ArenaOptions.
+inline size_t GetDefaultArenaMaxBlockSize() {
+  return arena_config_internal::default_arena_max_block_size.load(
+      std::memory_order_relaxed);
+}
+inline void SetDefaultArenaMaxBlockSize(size_t default_arena_max_block_size) {
+  return arena_config_internal::default_arena_max_block_size.store(
+      default_arena_max_block_size, std::memory_order_relaxed);
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_ARENA_CONFIG_H__
diff --git a/src/google/protobuf/arena_impl.h b/src/google/protobuf/arena_impl.h
index 7672768..9d2de93 100644
--- a/src/google/protobuf/arena_impl.h
+++ b/src/google/protobuf/arena_impl.h
@@ -35,20 +35,23 @@
 
 #include <atomic>
 #include <limits>
+#include <string>
+#include <type_traits>
 #include <typeinfo>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/port.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/numeric/bits.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/arena_allocation_policy.h"
+#include "google/protobuf/arena_cleanup.h"
+#include "google/protobuf/arena_config.h"
+#include "google/protobuf/arenaz_sampler.h"
+#include "google/protobuf/port.h"
 
-#ifdef ADDRESS_SANITIZER
-#include <sanitizer/asan_interface.h>
-#endif  // ADDRESS_SANITIZER
-
-#include <google/protobuf/arenaz_sampler.h>
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 
 namespace google {
@@ -62,11 +65,56 @@
 enum { kCacheAlignment = alignof(max_align_t) };  // do the best we can
 #endif
 
-inline constexpr size_t AlignUpTo8(size_t n) {
+inline PROTOBUF_ALWAYS_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);
 }
 
+inline PROTOBUF_ALWAYS_INLINE constexpr size_t AlignUpTo(size_t n, size_t a) {
+  // 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 a <= 8 ? AlignUpTo8(n) : n + a - 8;
+}
+
+inline PROTOBUF_ALWAYS_INLINE void* AlignTo(void* p, size_t a) {
+  if (a <= 8) {
+    return p;
+  } else {
+    auto u = reinterpret_cast<uintptr_t>(p);
+    return reinterpret_cast<void*>((u + a - 1) & (~a + 1));
+  }
+}
+
+// Arena blocks are variable length malloc-ed objects.  The following structure
+// describes the common header for all blocks.
+struct ArenaBlock {
+  // For the sentry block with zero-size where ptr_, limit_, cleanup_nodes all
+  // point to "this".
+  constexpr ArenaBlock()
+      : next(nullptr), cleanup_nodes(this), size(0) {}
+
+  ArenaBlock(ArenaBlock* next, size_t size)
+      : next(next), cleanup_nodes(nullptr), size(size) {
+    GOOGLE_DCHECK_GT(size, sizeof(ArenaBlock));
+  }
+
+  char* Pointer(size_t n) {
+    GOOGLE_DCHECK_LE(n, size);
+    return reinterpret_cast<char*>(this) + n;
+  }
+  char* Limit() { return Pointer(size & static_cast<size_t>(-8)); }
+
+  bool IsSentry() const { return size == 0; }
+
+  ArenaBlock* const next;
+  void* cleanup_nodes;
+  const size_t size;
+  // data follows
+};
+
 using LifecycleIdAtomic = uint64_t;
 
 // MetricsCollector collects stats for a particular arena.
@@ -102,94 +150,15 @@
   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;
-  }
-};
-
-// Tagged pointer to an AllocationPolicy.
-class TaggedAllocationPolicyPtr {
- public:
-  constexpr TaggedAllocationPolicyPtr() : policy_(0) {}
-
-  explicit TaggedAllocationPolicyPtr(AllocationPolicy* policy)
-      : policy_(reinterpret_cast<uintptr_t>(policy)) {}
-
-  void set_policy(AllocationPolicy* policy) {
-    auto bits = policy_ & kTagsMask;
-    policy_ = reinterpret_cast<uintptr_t>(policy) | bits;
-  }
-
-  AllocationPolicy* get() {
-    return reinterpret_cast<AllocationPolicy*>(policy_ & kPtrMask);
-  }
-  const AllocationPolicy* get() const {
-    return reinterpret_cast<const AllocationPolicy*>(policy_ & kPtrMask);
-  }
-
-  AllocationPolicy& operator*() { return *get(); }
-  const AllocationPolicy& operator*() const { return *get(); }
-
-  AllocationPolicy* operator->() { return get(); }
-  const AllocationPolicy* operator->() const { return get(); }
-
-  bool is_user_owned_initial_block() const {
-    return static_cast<bool>(get_mask<kUserOwnedInitialBlock>());
-  }
-  void set_is_user_owned_initial_block(bool v) {
-    set_mask<kUserOwnedInitialBlock>(v);
-  }
-
-  bool should_record_allocs() const {
-    return static_cast<bool>(get_mask<kRecordAllocs>());
-  }
-  void set_should_record_allocs(bool v) { set_mask<kRecordAllocs>(v); }
-
-  uintptr_t get_raw() const { return policy_; }
-
-  inline void RecordAlloc(const std::type_info* allocated_type,
-                          size_t n) const {
-    get()->metrics_collector->OnAlloc(allocated_type, n);
-  }
-
- private:
-  enum : uintptr_t {
-    kUserOwnedInitialBlock = 1,
-    kRecordAllocs = 2,
-  };
-
-  static constexpr uintptr_t kTagsMask = 7;
-  static constexpr uintptr_t kPtrMask = ~kTagsMask;
-
-  template <uintptr_t kMask>
-  uintptr_t get_mask() const {
-    return policy_ & kMask;
-  }
-  template <uintptr_t kMask>
-  void set_mask(bool v) {
-    if (v) {
-      policy_ |= kMask;
-    } else {
-      policy_ &= ~kMask;
-    }
-  }
-  uintptr_t policy_;
-};
-
 enum class AllocationClient { kDefault, kArray };
 
+class ThreadSafeArena;
+
+// Tag type used to invoke the constructor of the first SerialArena.
+struct FirstSerialArena {
+  explicit FirstSerialArena() = default;
+};
+
 // 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
@@ -198,7 +167,7 @@
 // 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
+// It delegates the actual memory allocation back to ThreadSafeArena, which
 // contains the information on block growth policy and backing memory allocation
 // used.
 class PROTOBUF_EXPORT SerialArena {
@@ -208,13 +177,6 @@
     size_t size;
   };
 
-  // Node contains the ptr of the object to be cleaned up and the associated
-  // cleanup function ptr.
-  struct CleanupNode {
-    void* elem;              // Pointer to the object to be cleaned up.
-    void (*cleanup)(void*);  // Function pointer to the destructor or deleter.
-  };
-
   void CleanupList();
   uint64_t SpaceAllocated() const {
     return space_allocated_.load(std::memory_order_relaxed);
@@ -222,7 +184,7 @@
   uint64_t SpaceUsed() const;
 
   bool HasSpace(size_t n) const {
-    return n <= static_cast<size_t>(limit_ - ptr_);
+    return n <= static_cast<size_t>(limit_ - ptr());
   }
 
   // See comments on `cached_blocks_` member for details.
@@ -230,16 +192,14 @@
     if (PROTOBUF_PREDICT_FALSE(size < 16)) return nullptr;
     // We round up to the next larger block in case the memory doesn't match
     // the pattern we are looking for.
-    const size_t index = Bits::Log2FloorNonZero64(size - 1) - 3;
+    const size_t index = absl::bit_width(size - 1) - 4;
 
     if (index >= cached_block_length_) return nullptr;
     auto& cached_head = cached_blocks_[index];
     if (cached_head == nullptr) return nullptr;
 
     void* ret = cached_head;
-#ifdef ADDRESS_SANITIZER
-    ASAN_UNPOISON_MEMORY_REGION(ret, size);
-#endif  // ADDRESS_SANITIZER
+    PROTOBUF_UNPOISON_MEMORY_REGION(ret, size);
     cached_head = cached_head->next;
     return ret;
   }
@@ -252,9 +212,9 @@
   // the right size. We can statically know if the allocation size can benefit
   // from it.
   template <AllocationClient alloc_client = AllocationClient::kDefault>
-  void* AllocateAligned(size_t n, const AllocationPolicy* policy) {
+  void* AllocateAligned(size_t n) {
     GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
-    GOOGLE_DCHECK_GE(limit_, ptr_);
+    GOOGLE_DCHECK_GE(limit_, ptr());
 
     if (alloc_client == AllocationClient::kArray) {
       if (void* res = TryAllocateFromCachedBlock(n)) {
@@ -263,18 +223,16 @@
     }
 
     if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) {
-      return AllocateAlignedFallback(n, policy);
+      return AllocateAlignedFallback(n);
     }
     return AllocateFromExisting(n);
   }
 
  private:
   void* AllocateFromExisting(size_t n) {
-    void* ret = ptr_;
-    ptr_ += n;
-#ifdef ADDRESS_SANITIZER
-    ASAN_UNPOISON_MEMORY_REGION(ret, n);
-#endif  // ADDRESS_SANITIZER
+    PROTOBUF_UNPOISON_MEMORY_REGION(ptr(), n);
+    void* ret = ptr();
+    set_ptr(static_cast<char*>(ret) + n);
     return ret;
   }
 
@@ -286,13 +244,13 @@
     if (sizeof(void*) < 8) {
       if (PROTOBUF_PREDICT_FALSE(size < 16)) return;
     } else {
-      GOOGLE_DCHECK(size >= 16);
+      PROTOBUF_ASSUME(size >= 16);
     }
 
     // We round down to the next smaller block in case the memory doesn't match
     // the pattern we are looking for. eg, someone might have called Reserve()
     // on the repeated field.
-    const size_t index = Bits::Log2FloorNonZero64(size) - 4;
+    const size_t index = absl::bit_width(size) - 5;
 
     if (PROTOBUF_PREDICT_FALSE(index >= cached_block_length_)) {
       // We can't put this object on the freelist so make this object the
@@ -303,7 +261,15 @@
 
       std::copy(cached_blocks_, cached_blocks_ + cached_block_length_,
                 new_list);
+
+      // We need to unpoison this memory before filling it in case it has been
+      // poisoned by another santizer client.
+      PROTOBUF_UNPOISON_MEMORY_REGION(
+          new_list + cached_block_length_,
+          (new_size - cached_block_length_) * sizeof(CachedBlock*));
+
       std::fill(new_list + cached_block_length_, new_list + new_size, nullptr);
+
       cached_blocks_ = new_list;
       // Make the size fit in uint8_t. This is the power of two, so we don't
       // need anything larger.
@@ -317,98 +283,108 @@
     auto* new_node = static_cast<CachedBlock*>(p);
     new_node->next = cached_head;
     cached_head = new_node;
-#ifdef ADDRESS_SANITIZER
-    ASAN_POISON_MEMORY_REGION(p, size);
-#endif  // ADDRESS_SANITIZER
+    PROTOBUF_POISON_MEMORY_REGION(p, size);
   }
 
  public:
   // 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_);
+    GOOGLE_DCHECK_GE(limit_, ptr());
     if (PROTOBUF_PREDICT_FALSE(!HasSpace(n))) return false;
     *out = AllocateFromExisting(n);
     return true;
   }
 
-  std::pair<void*, CleanupNode*> AllocateAlignedWithCleanup(
-      size_t n, const AllocationPolicy* policy) {
-    GOOGLE_DCHECK_EQ(internal::AlignUpTo8(n), n);  // Must be already aligned.
-    if (PROTOBUF_PREDICT_FALSE(!HasSpace(n + kCleanupSize))) {
-      return AllocateAlignedWithCleanupFallback(n, policy);
+  // If there is enough space in the current block, allocate space for one `T`
+  // object and register for destruction. The object has not been constructed
+  // and the memory returned is uninitialized.
+  template <typename T>
+  PROTOBUF_ALWAYS_INLINE void* MaybeAllocateWithCleanup() {
+    GOOGLE_DCHECK_GE(limit_, ptr());
+    static_assert(!std::is_trivially_destructible<T>::value,
+                  "This function is only for non-trivial types.");
+
+    constexpr int aligned_size = AlignUpTo8(sizeof(T));
+    constexpr auto destructor = cleanup::arena_destruct_object<T>;
+    size_t required = aligned_size + cleanup::Size(destructor);
+    if (PROTOBUF_PREDICT_FALSE(!HasSpace(required))) {
+      return nullptr;
     }
-    return AllocateFromExistingWithCleanupFallback(n);
+    void* ptr = AllocateFromExistingWithCleanupFallback(aligned_size,
+                                                        alignof(T), destructor);
+    PROTOBUF_ASSUME(ptr != nullptr);
+    return ptr;
+  }
+
+  PROTOBUF_ALWAYS_INLINE
+  void* AllocateAlignedWithCleanup(size_t n, size_t align,
+                                   void (*destructor)(void*)) {
+    size_t required = AlignUpTo(n, align) + cleanup::Size(destructor);
+    if (PROTOBUF_PREDICT_FALSE(!HasSpace(required))) {
+      return AllocateAlignedWithCleanupFallback(n, align, destructor);
+    }
+    return AllocateFromExistingWithCleanupFallback(n, align, destructor);
+  }
+
+  PROTOBUF_ALWAYS_INLINE
+  void AddCleanup(void* elem, void (*destructor)(void*)) {
+    size_t required = cleanup::Size(destructor);
+    if (PROTOBUF_PREDICT_FALSE(!HasSpace(required))) {
+      return AddCleanupFallback(elem, destructor);
+    }
+    AddCleanupFromExisting(elem, destructor);
   }
 
  private:
-  std::pair<void*, CleanupNode*> AllocateFromExistingWithCleanupFallback(
-      size_t n) {
-    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* AllocateFromExistingWithCleanupFallback(size_t n, size_t align,
+                                                void (*destructor)(void*)) {
+    n = AlignUpTo(n, align);
+    PROTOBUF_UNPOISON_MEMORY_REGION(ptr(), n);
+    void* ret = internal::AlignTo(ptr(), align);
+    set_ptr(ptr() + n);
+    GOOGLE_DCHECK_GE(limit_, ptr());
+    AddCleanupFromExisting(ret, destructor);
+    return ret;
   }
 
- public:
-  void AddCleanup(void* elem, void (*cleanup)(void*),
-                  const AllocationPolicy* policy) {
-    auto res = AllocateAlignedWithCleanup(0, policy);
-    res.second->elem = elem;
-    res.second->cleanup = cleanup;
-  }
+  PROTOBUF_ALWAYS_INLINE
+  void AddCleanupFromExisting(void* elem, void (*destructor)(void*)) {
+    cleanup::Tag tag = cleanup::Type(destructor);
+    size_t n = cleanup::Size(tag);
 
-  void* owner() const { return owner_; }
-  SerialArena* next() const { return next_; }
-  void set_next(SerialArena* next) { next_ = next; }
+    PROTOBUF_UNPOISON_MEMORY_REGION(limit_ - n, n);
+    limit_ -= n;
+    GOOGLE_DCHECK_GE(limit_, ptr());
+    cleanup::CreateNode(tag, limit_, elem, destructor);
+  }
 
  private:
   friend class ThreadSafeArena;
-  friend class ArenaBenchmark;
 
   // Creates a new SerialArena inside mem using the remaining memory as for
   // future allocations.
-  static SerialArena* New(SerialArena::Memory mem, void* owner,
-                          ThreadSafeArenaStats* stats);
+  // The `parent` arena must outlive the serial arena, which is guaranteed
+  // because the parent manages the lifetime of the serial arenas.
+  static SerialArena* New(SerialArena::Memory mem, ThreadSafeArena& parent);
   // Free SerialArena returning the memory passed in to New
   template <typename Deallocator>
   Memory Free(Deallocator deallocator);
 
-  // Blocks are variable length malloc-ed objects.  The following structure
-  // describes the common header for all blocks.
-  struct Block {
-    Block(Block* next, size_t size) : next(next), size(size), start(nullptr) {}
-
-    char* Pointer(size_t n) {
-      GOOGLE_DCHECK(n <= size);
-      return reinterpret_cast<char*>(this) + n;
-    }
-
-    Block* const next;
-    const size_t size;
-    CleanupNode* start;
-    // data follows
-  };
-
-  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_;
+  // Members are declared here to track sizeof(SerialArena) and hotness
+  // centrally. They are (roughly) laid out in descending order of hotness.
 
   // 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_;
+  std::atomic<char*> ptr_{nullptr};
   // Limiting address up to which memory can be allocated from the head block.
-  char* limit_;
-  // For holding sampling information.  The pointer is owned by the
-  // ThreadSafeArena that holds this serial arena.
-  ThreadSafeArenaStats* arena_stats_;
+  char* limit_ = nullptr;
+
+  std::atomic<ArenaBlock*> head_{nullptr};  // Head of linked list of blocks.
+  std::atomic<size_t> space_used_{0};       // Necessary for metrics.
+  std::atomic<size_t> space_allocated_{0};
+  ThreadSafeArena& parent_;
 
   // Repeated*Field and Arena play together to reduce memory consumption by
   // reusing blocks. Currently, natural growth of the repeated field types makes
@@ -424,20 +400,32 @@
   uint8_t cached_block_length_ = 0;
   CachedBlock** cached_blocks_ = nullptr;
 
-  // Constructor is private as only New() should be used.
-  inline SerialArena(Block* b, void* owner, ThreadSafeArenaStats* stats);
-  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);
-
-  std::pair<void*, CleanupNode*> CreatePair(void* ptr, CleanupNode* node) {
-    return {ptr, node};
+  // Helper getters/setters to handle relaxed operations on atomic variables.
+  ArenaBlock* head() { return head_.load(std::memory_order_relaxed); }
+  const ArenaBlock* head() const {
+    return head_.load(std::memory_order_relaxed);
   }
 
+  char* ptr() { return ptr_.load(std::memory_order_relaxed); }
+  const char* ptr() const { return ptr_.load(std::memory_order_relaxed); }
+  void set_ptr(char* ptr) { return ptr_.store(ptr, std::memory_order_relaxed); }
+
+  // Constructor is private as only New() should be used.
+  inline SerialArena(ArenaBlock* b, ThreadSafeArena& parent);
+
+  // Constructors to handle the first SerialArena.
+  inline explicit SerialArena(ThreadSafeArena& parent);
+  inline SerialArena(FirstSerialArena, ArenaBlock* b, ThreadSafeArena& parent);
+
+  void* AllocateAlignedFallback(size_t n);
+  void* AllocateAlignedWithCleanupFallback(size_t n, size_t align,
+                                           void (*destructor)(void*));
+  void AddCleanupFallback(void* elem, void (*destructor)(void*));
+  inline void AllocateNewBlock(size_t n);
+  inline void Init(ArenaBlock* b, size_t offset);
+
  public:
-  static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(Block));
-  static constexpr size_t kCleanupSize = AlignUpTo8(sizeof(CleanupNode));
+  static constexpr size_t kBlockHeaderSize = AlignUpTo8(sizeof(ArenaBlock));
 };
 
 // Tag type used to invoke the constructor of message-owned arena.
@@ -455,19 +443,22 @@
 // use #ifdef the select the best implementation based on hardware / OS.
 class PROTOBUF_EXPORT ThreadSafeArena {
  public:
-  ThreadSafeArena() { Init(); }
+  ThreadSafeArena();
 
   // Constructor solely used by message-owned arena.
-  ThreadSafeArena(internal::MessageOwned) : tag_and_id_(kMessageOwnedArena) {
-    Init();
-  }
+  explicit ThreadSafeArena(internal::MessageOwned);
 
-  ThreadSafeArena(char* mem, size_t size) { InitializeFrom(mem, size); }
+  ThreadSafeArena(char* mem, size_t size);
 
   explicit ThreadSafeArena(void* mem, size_t size,
-                           const AllocationPolicy& policy) {
-    InitializeWithPolicy(mem, size, policy);
-  }
+                           const AllocationPolicy& policy);
+
+  // All protos have pointers back to the arena hence Arena must have
+  // pointer stability.
+  ThreadSafeArena(const ThreadSafeArena&) = delete;
+  ThreadSafeArena& operator=(const ThreadSafeArena&) = delete;
+  ThreadSafeArena(ThreadSafeArena&&) = delete;
+  ThreadSafeArena& operator=(ThreadSafeArena&&) = delete;
 
   // Destructor deletes all owned heap allocated objects, and destructs objects
   // that have non-trivial destructors, except for proto2 message objects whose
@@ -481,13 +472,12 @@
   uint64_t SpaceUsed() const;
 
   template <AllocationClient alloc_client = AllocationClient::kDefault>
-  void* AllocateAligned(size_t n, const std::type_info* type) {
+  void* AllocateAligned(size_t n) {
     SerialArena* arena;
-    if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
-                              GetSerialArenaFast(&arena))) {
-      return arena->AllocateAligned<alloc_client>(n, AllocPolicy());
+    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
+      return arena->AllocateAligned<alloc_client>(n);
     } else {
-      return AllocateAlignedFallback(n, type);
+      return AllocateAlignedFallback<alloc_client>(n);
     }
   }
 
@@ -505,15 +495,14 @@
   // code for the happy path.
   PROTOBUF_NDEBUG_INLINE bool MaybeAllocateAligned(size_t n, void** out) {
     SerialArena* arena;
-    if (PROTOBUF_PREDICT_TRUE(!alloc_policy_.should_record_allocs() &&
-                              GetSerialArenaFromThreadCache(&arena))) {
+    if (PROTOBUF_PREDICT_TRUE(GetSerialArenaFast(&arena))) {
       return arena->MaybeAllocateAligned(n, out);
     }
     return false;
   }
 
-  std::pair<void*, SerialArena::CleanupNode*> AllocateAlignedWithCleanup(
-      size_t n, const std::type_info* type);
+  void* AllocateAlignedWithCleanup(size_t n, size_t align,
+                                   void (*destructor)(void*));
 
   // Add object pointer and cleanup function pointer to the list.
   void AddCleanup(void* elem, void (*cleanup)(void*));
@@ -524,62 +513,73 @@
   }
 
  private:
+  friend class ArenaBenchmark;
+  friend class TcParser;
+  friend class SerialArena;
+  friend struct SerialArenaChunkHeader;
+  static uint64_t GetNextLifeCycleId();
+
+  class SerialArenaChunk;
+
+  // Returns a new SerialArenaChunk that has {id, serial} at slot 0. It may
+  // grow based on "prev_num_slots".
+  static SerialArenaChunk* NewSerialArenaChunk(uint32_t prev_capacity, void* id,
+                                               SerialArena* serial);
+  static SerialArenaChunk* SentrySerialArenaChunk();
+
+  // Returns the first ArenaBlock* for the first SerialArena. If users provide
+  // one, use it if it's acceptable. Otherwise returns a sentry block.
+  ArenaBlock* FirstBlock(void* buf, size_t size);
+  // Same as the above but returns a valid block if "policy" is not default.
+  ArenaBlock* FirstBlock(void* buf, size_t size,
+                         const AllocationPolicy& policy);
+
+  // Adds SerialArena to the chunked list. May create a new chunk.
+  void AddSerialArena(void* id, SerialArena* serial);
+
+  // Members are declared here to track sizeof(ThreadSafeArena) and hotness
+  // centrally.
+
   // Unique for each arena. Changes on Reset().
   uint64_t tag_and_id_ = 0;
+
+  TaggedAllocationPolicyPtr alloc_policy_;  // Tagged pointer to AllocPolicy.
+  ThreadSafeArenaStatsHandle arena_stats_;
+
+  // Adding a new chunk to head_ must be protected by mutex_.
+  absl::Mutex mutex_;
+  // Pointer to a linked list of SerialArenaChunk.
+  std::atomic<SerialArenaChunk*> head_{nullptr};
+
+  void* first_owner_;
+  // Must be declared after alloc_policy_; otherwise, it may lose info on
+  // user-provided initial block.
+  SerialArena first_arena_;
+
   // The LSB of tag_and_id_ indicates if the arena is message-owned.
   enum : uint64_t { kMessageOwnedArena = 1 };
 
-  TaggedAllocationPolicyPtr alloc_policy_;  // Tagged pointer to AllocPolicy.
-
   static_assert(std::is_trivially_destructible<SerialArena>{},
                 "SerialArena needs to be trivially destructible.");
-  // 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 alloc_policy_.get(); }
-  void InitializeFrom(void* mem, size_t size);
-  void InitializeWithPolicy(void* mem, size_t size, 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 InitializeWithPolicy(const AllocationPolicy& policy);
+  void* AllocateAlignedWithCleanupFallback(size_t n, size_t align,
+                                           void (*destructor)(void*));
 
   void Init();
-  void SetInitialBlock(void* mem, size_t size);
 
   // Delete or Destruct all objects owned by the arena.
   void CleanupList();
 
-  inline uint64_t LifeCycleId() const {
-    return tag_and_id_ & ~kMessageOwnedArena;
-  }
-
   inline void CacheSerialArena(SerialArena* serial) {
-    thread_cache().last_serial_arena = serial;
-    thread_cache().last_lifecycle_id_seen = tag_and_id_;
-    // TODO(haberman): evaluate whether we would gain efficiency by getting rid
-    // 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);
+    if (!IsMessageOwned()) {
+      thread_cache().last_serial_arena = serial;
+      thread_cache().last_lifecycle_id_seen = tag_and_id_;
+    }
   }
 
   PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFast(SerialArena** arena) {
-    if (GetSerialArenaFromThreadCache(arena)) return true;
-
-    // Check whether we own the last accessed SerialArena on this arena.  This
-    // fast path optimizes the case where a single thread uses multiple arenas.
-    ThreadCache* tc = &thread_cache();
-    SerialArena* serial = hint_.load(std::memory_order_acquire);
-    if (PROTOBUF_PREDICT_TRUE(serial != nullptr && serial->owner() == tc)) {
-      *arena = serial;
-      return true;
-    }
-    return false;
-  }
-
-  PROTOBUF_NDEBUG_INLINE bool GetSerialArenaFromThreadCache(
-      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.
@@ -590,16 +590,27 @@
     }
     return false;
   }
-  SerialArena* GetSerialArenaFallback(void* me);
 
+  // Finds SerialArena or creates one if not found. When creating a new one,
+  // create a big enough block to accommodate n bytes.
+  SerialArena* GetSerialArenaFallback(size_t n);
+
+  template <AllocationClient alloc_client = AllocationClient::kDefault>
+  void* AllocateAlignedFallback(size_t n);
+
+  // Executes callback function over SerialArenaChunk. Passes const
+  // SerialArenaChunk*.
   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);
+  void WalkConstSerialArenaChunk(Functor fn) const;
 
-    for (; serial; serial = serial->next()) fn(serial);
-  }
+  // Executes callback function over SerialArenaChunk.
+  template <typename Functor>
+  void WalkSerialArenaChunk(Functor fn);
+
+  // Executes callback function over SerialArena in chunked list in reverse
+  // chronological order. Passes const SerialArena*.
+  template <typename Functor>
+  void PerConstSerialArenaInChunk(Functor fn) const;
 
   // 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
@@ -641,6 +652,8 @@
 #pragma warning(disable : 4324)
 #endif
   struct alignas(kCacheAlignment) CacheAlignedLifecycleIdGenerator {
+    constexpr CacheAlignedLifecycleIdGenerator() : id{0} {}
+
     std::atomic<LifecycleIdAtomic> id;
   };
   static CacheAlignedLifecycleIdGenerator lifecycle_id_generator_;
@@ -657,20 +670,15 @@
   static ThreadCache& thread_cache() { return thread_cache_; }
 #endif
 
-  ThreadSafeArenaStatsHandle arena_stats_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadSafeArena);
-  // All protos have pointers back to the arena hence Arena must have
-  // pointer stability.
-  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.
+  // kBlockHeaderSize is sizeof(ArenaBlock), aligned up to the nearest multiple
+  // of 8 to protect the invariant that pos is always at a multiple of 8.
   static constexpr size_t kBlockHeaderSize = SerialArena::kBlockHeaderSize;
   static constexpr size_t kSerialArenaSize =
       (sizeof(SerialArena) + 7) & static_cast<size_t>(-8);
+  static constexpr size_t kAllocPolicySize =
+      AlignUpTo8(sizeof(AllocationPolicy));
+  static constexpr size_t kMaxCleanupNodeSize = 16;
   static_assert(kBlockHeaderSize % 8 == 0,
                 "kBlockHeaderSize must be a multiple of 8.");
   static_assert(kSerialArenaSize % 8 == 0,
@@ -681,6 +689,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_ARENA_IMPL_H__
diff --git a/src/google/protobuf/arena_test_util.cc b/src/google/protobuf/arena_test_util.cc
index 2cb5075..50f20a1 100644
--- a/src/google/protobuf/arena_test_util.cc
+++ b/src/google/protobuf/arena_test_util.cc
@@ -28,10 +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 <google/protobuf/arena_test_util.h>
+#include "google/protobuf/arena_test_util.h"
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 
 
 #define EXPECT_EQ GOOGLE_CHECK_EQ
diff --git a/src/google/protobuf/arena_test_util.h b/src/google/protobuf/arena_test_util.h
index 6e42d4b..0c00e76 100644
--- a/src/google/protobuf/arena_test_util.h
+++ b/src/google/protobuf/arena_test_util.h
@@ -31,11 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
 #define GOOGLE_PROTOBUF_ARENA_TEST_UTIL_H__
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/arena_unittest.cc b/src/google/protobuf/arena_unittest.cc
index 7539b4b..592cd9d 100644
--- a/src/google/protobuf/arena_unittest.cc
+++ b/src/google/protobuf/arena_unittest.cc
@@ -28,7 +28,7 @@
 // (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/arena.h>
+#include "google/protobuf/arena.h"
 
 #include <algorithm>
 #include <cstddef>
@@ -39,28 +39,30 @@
 #include <typeinfo>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_arena.pb.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/arena_test_util.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/barrier.h"
+#include "google/protobuf/arena_test_util.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_arena.pb.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/wire_format_lite.h"
 
+#include "absl/synchronization/mutex.h"
 
 // Must be included last
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 using proto2_arena_unittest::ArenaMessage;
 using protobuf_unittest::ForeignMessage;
@@ -68,6 +70,7 @@
 using protobuf_unittest::TestAllTypes;
 using protobuf_unittest::TestEmptyMessage;
 using protobuf_unittest::TestOneof2;
+using protobuf_unittest::TestRepeatedString;
 
 namespace google {
 namespace protobuf {
@@ -84,10 +87,10 @@
 
 class SimpleDataType {
  public:
-  SimpleDataType() : notifier_(NULL) {}
+  SimpleDataType() : notifier_(nullptr) {}
   void SetNotifier(Notifier* notifier) { notifier_ = notifier; }
   virtual ~SimpleDataType() {
-    if (notifier_ != NULL) {
+    if (notifier_ != nullptr) {
       notifier_->Notify();
     }
   };
@@ -101,12 +104,13 @@
 class PleaseDontCopyMe {
  public:
   explicit PleaseDontCopyMe(int value) : value_(value) {}
+  PleaseDontCopyMe(const PleaseDontCopyMe&) = delete;
+  PleaseDontCopyMe& operator=(const PleaseDontCopyMe&) = delete;
 
   int value() const { return value_; }
 
  private:
   int value_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PleaseDontCopyMe);
 };
 
 // A class that takes four different types as constructor arguments.
@@ -116,14 +120,15 @@
                                       const std::string& three,
                                       const PleaseDontCopyMe* four)
       : one_(one), two_(two), three_(three), four_(four) {}
+  MustBeConstructedWithOneThroughFour(
+      const MustBeConstructedWithOneThroughFour&) = delete;
+  MustBeConstructedWithOneThroughFour& operator=(
+      const MustBeConstructedWithOneThroughFour&) = delete;
 
   int one_;
   const char* const two_;
   std::string three_;
   const PleaseDontCopyMe* four_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughFour);
 };
 
 // A class that takes eight different types as constructor arguments.
@@ -143,6 +148,10 @@
         six_(six),
         seven_(seven),
         eight_(eight) {}
+  MustBeConstructedWithOneThroughEight(
+      const MustBeConstructedWithOneThroughEight&) = delete;
+  MustBeConstructedWithOneThroughEight& operator=(
+      const MustBeConstructedWithOneThroughEight&) = delete;
 
   int one_;
   const char* const two_;
@@ -152,9 +161,6 @@
   const char* const six_;
   std::string seven_;
   std::string eight_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MustBeConstructedWithOneThroughEight);
 };
 
 TEST(ArenaTest, ArenaConstructable) {
@@ -171,17 +177,17 @@
 
 TEST(ArenaTest, BasicCreate) {
   Arena arena;
-  EXPECT_TRUE(Arena::Create<int32_t>(&arena) != NULL);
-  EXPECT_TRUE(Arena::Create<int64_t>(&arena) != NULL);
-  EXPECT_TRUE(Arena::Create<float>(&arena) != NULL);
-  EXPECT_TRUE(Arena::Create<double>(&arena) != NULL);
-  EXPECT_TRUE(Arena::Create<std::string>(&arena) != NULL);
+  EXPECT_TRUE(Arena::Create<int32_t>(&arena) != nullptr);
+  EXPECT_TRUE(Arena::Create<int64_t>(&arena) != nullptr);
+  EXPECT_TRUE(Arena::Create<float>(&arena) != nullptr);
+  EXPECT_TRUE(Arena::Create<double>(&arena) != nullptr);
+  EXPECT_TRUE(Arena::Create<std::string>(&arena) != nullptr);
   arena.Own(new int32_t);
   arena.Own(new int64_t);
   arena.Own(new float);
   arena.Own(new double);
   arena.Own(new std::string);
-  arena.Own<int>(NULL);
+  arena.Own<int>(nullptr);
   Notifier notifier;
   SimpleDataType* data = Arena::Create<SimpleDataType>(&arena);
   data->SetNotifier(&notifier);
@@ -196,7 +202,7 @@
   Arena arena;
   const std::string s("foo");
   const std::string* s_copy = Arena::Create<std::string>(&arena, s);
-  EXPECT_TRUE(s_copy != NULL);
+  EXPECT_TRUE(s_copy != nullptr);
   EXPECT_EQ("foo", s);
   EXPECT_EQ("foo", *s_copy);
 }
@@ -205,7 +211,7 @@
   Arena arena;
   std::string s("foo");
   const std::string* s_copy = Arena::Create<std::string>(&arena, s);
-  EXPECT_TRUE(s_copy != NULL);
+  EXPECT_TRUE(s_copy != nullptr);
   EXPECT_EQ("foo", s);
   EXPECT_EQ("foo", *s_copy);
 }
@@ -214,7 +220,7 @@
   Arena arena;
   std::string s("foo");
   const std::string* s_move = Arena::Create<std::string>(&arena, std::move(s));
-  EXPECT_TRUE(s_move != NULL);
+  EXPECT_TRUE(s_move != nullptr);
   EXPECT_TRUE(s.empty());  // NOLINT
   EXPECT_EQ("foo", *s_move);
 }
@@ -226,7 +232,7 @@
   const MustBeConstructedWithOneThroughFour* new_object =
       Arena::Create<MustBeConstructedWithOneThroughFour>(&arena, 1, "2", three,
                                                          &four);
-  EXPECT_TRUE(new_object != NULL);
+  EXPECT_TRUE(new_object != nullptr);
   ASSERT_EQ(1, new_object->one_);
   ASSERT_STREQ("2", new_object->two_);
   ASSERT_EQ("3", new_object->three_);
@@ -242,7 +248,7 @@
   const MustBeConstructedWithOneThroughEight* new_object =
       Arena::Create<MustBeConstructedWithOneThroughEight>(
           &arena, 1, "2", three, &four, 5, "6", seven, eight);
-  EXPECT_TRUE(new_object != NULL);
+  EXPECT_TRUE(new_object != nullptr);
   ASSERT_EQ(1, new_object->one_);
   ASSERT_STREQ("2", new_object->two_);
   ASSERT_EQ("3", new_object->three_);
@@ -277,7 +283,8 @@
 TEST(ArenaTest, InitialBlockTooSmall) {
   // 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++) {
+  for (uint32_t size = 0; size <= internal::SerialArena::kBlockHeaderSize + 32;
+       size++) {
     std::vector<char> arena_block(size);
     ArenaOptions options;
     options.initial_block = arena_block.data();
@@ -307,6 +314,36 @@
   }
 }
 
+TEST(ArenaTest, CreateDestroy) {
+  TestAllTypes original;
+  TestUtil::SetAllFields(&original);
+
+  // Test memory leak.
+  Arena arena;
+  TestAllTypes* heap_message = Arena::CreateMessage<TestAllTypes>(nullptr);
+  TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
+
+  *heap_message = original;
+  *arena_message = original;
+
+  Arena::Destroy(heap_message);
+  Arena::Destroy(arena_message);
+
+  // The arena message should still exist.
+  EXPECT_EQ(strlen(original.optional_string().c_str()),
+            strlen(arena_message->optional_string().c_str()));
+}
+
+struct OnlyArenaConstructible {
+  using InternalArenaConstructable_ = void;
+  explicit OnlyArenaConstructible(Arena* arena) {}
+};
+
+TEST(ArenaTest, ArenaOnlyTypesCanBeConstructed) {
+  Arena arena;
+  Arena::CreateMessage<OnlyArenaConstructible>(&arena);
+}
+
 TEST(ArenaTest, Parsing) {
   TestAllTypes original;
   TestUtil::SetAllFields(&original);
@@ -484,7 +521,7 @@
 
   TestAllTypes::NestedMessage* released_null =
       arena_message->release_optional_nested_message();
-  EXPECT_EQ(NULL, released_null);
+  EXPECT_EQ(nullptr, released_null);
 }
 
 TEST(ArenaTest, SetAllocatedString) {
@@ -585,8 +622,8 @@
 }
 
 TEST(ArenaTest, ReleaseFromArenaMessageMakesCopy) {
-  TestAllTypes::NestedMessage* nested_msg = NULL;
-  std::string* nested_string = NULL;
+  TestAllTypes::NestedMessage* nested_msg = nullptr;
+  std::string* nested_string = nullptr;
   {
     Arena arena;
     TestAllTypes* arena_message = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -603,7 +640,7 @@
 
 #if PROTOBUF_RTTI
 TEST(ArenaTest, ReleaseFromArenaMessageUsingReflectionMakesCopy) {
-  TestAllTypes::NestedMessage* nested_msg = NULL;
+  TestAllTypes::NestedMessage* nested_msg = nullptr;
   // Note: no string: reflection API only supports releasing submessages.
   {
     Arena arena;
@@ -771,7 +808,7 @@
 }
 
 TEST(ArenaTest, RepeatedPtrFieldAddClearedTest) {
-#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES
+#ifndef PROTOBUF_FUTURE_REMOVE_CLEARED_API
   {
     RepeatedPtrField<TestAllTypes> repeated_field;
     EXPECT_TRUE(repeated_field.empty());
@@ -782,7 +819,7 @@
     EXPECT_TRUE(repeated_field.empty());
     EXPECT_EQ(0, repeated_field.size());
   }
-#endif  // !PROTOBUF_FUTURE_BREAKING_CHANGES
+#endif  // !PROTOBUF_FUTURE_REMOVE_CLEARED_API
   {
     RepeatedPtrField<TestAllTypes> repeated_field;
     EXPECT_TRUE(repeated_field.empty());
@@ -1078,7 +1115,7 @@
   EXPECT_TRUE(refl->HasOneof(*message, oneof));
   submsg = refl->ReleaseMessage(message, msg_field);
   EXPECT_FALSE(refl->HasOneof(*message, oneof));
-  EXPECT_TRUE(submsg->GetArena() == NULL);
+  EXPECT_TRUE(submsg->GetArena() == nullptr);
   delete submsg;
 }
 
@@ -1091,7 +1128,7 @@
     TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena1);
     t->set_optional_string("field1");
     t->set_optional_int32(i);
-    if (arena1 != NULL) {
+    if (arena1 != nullptr) {
       field1.UnsafeArenaAddAllocated(t);
     } else {
       field1.AddAllocated(t);
@@ -1101,7 +1138,7 @@
     TestAllTypes* t = Arena::CreateMessage<TestAllTypes>(arena2);
     t->set_optional_string("field2");
     t->set_optional_int32(i);
-    if (arena2 != NULL) {
+    if (arena2 != nullptr) {
       field2.UnsafeArenaAddAllocated(t);
     } else {
       field2.AddAllocated(t);
@@ -1134,12 +1171,12 @@
 
 TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnRightHandSide) {
   Arena arena;
-  TestSwapRepeatedField(&arena, NULL);
+  TestSwapRepeatedField(&arena, nullptr);
 }
 
 TEST(ArenaTest, SwapRepeatedFieldWithNoArenaOnLeftHandSide) {
   Arena arena;
-  TestSwapRepeatedField(NULL, &arena);
+  TestSwapRepeatedField(nullptr, &arena);
 }
 
 TEST(ArenaTest, ExtensionsOnArena) {
@@ -1198,11 +1235,11 @@
     TestAllTypes* extracted_messages[5];
     // ExtractSubrange should copy to the heap.
     repeated_message.ExtractSubrange(0, 5, extracted_messages);
-    EXPECT_EQ(NULL, extracted_messages[0]->GetArena());
+    EXPECT_EQ(nullptr, extracted_messages[0]->GetArena());
     // We need to free the heap-allocated messages to prevent a leak.
     for (int i = 0; i < 5; i++) {
       delete extracted_messages[i];
-      extracted_messages[i] = NULL;
+      extracted_messages[i] = nullptr;
     }
   }
 
@@ -1322,7 +1359,7 @@
   {
 
     MessageLite* generic_message = prototype->New(&arena);
-    EXPECT_TRUE(generic_message != NULL);
+    EXPECT_TRUE(generic_message != nullptr);
     EXPECT_EQ(&arena, generic_message->GetArena());
     EXPECT_TRUE(generic_message->ParseFromString(serialized));
     TestAllTypes* deserialized = static_cast<TestAllTypes*>(generic_message);
@@ -1383,6 +1420,31 @@
   EXPECT_EQ(1024, arena_2.Reset());
 }
 
+namespace {
+
+void VerifyArenaOverhead(Arena& arena, size_t overhead) {
+  EXPECT_EQ(0, arena.SpaceAllocated());
+
+  // Allocate a tiny block and record the allocation size.
+  constexpr size_t kTinySize = 8;
+  Arena::CreateArray<char>(&arena, kTinySize);
+  uint64_t space_allocated = arena.SpaceAllocated();
+
+  // Next allocation expects to fill up the block but no new block.
+  uint64_t next_size = space_allocated - overhead - kTinySize;
+  Arena::CreateArray<char>(&arena, next_size);
+
+  EXPECT_EQ(space_allocated, arena.SpaceAllocated());
+}
+
+}  // namespace
+
+TEST(ArenaTest, FirstArenaOverhead) {
+  Arena arena;
+  VerifyArenaOverhead(arena, internal::SerialArena::kBlockHeaderSize);
+}
+
+
 TEST(ArenaTest, BlockSizeDoubling) {
   Arena arena;
   EXPECT_EQ(0, arena.SpaceUsed());
@@ -1399,7 +1461,7 @@
   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);
+  EXPECT_GE(second_block_size, 2*first_block_size);
 }
 
 TEST(ArenaTest, Alignment) {
@@ -1443,8 +1505,8 @@
 TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaAllocatedMessages) {
   ArenaMessage message;
   const ArenaMessage* const_pointer_to_message = &message;
-  EXPECT_EQ(NULL, Arena::GetArena(&message));
-  EXPECT_EQ(NULL, Arena::GetArena(const_pointer_to_message));
+  EXPECT_EQ(nullptr, Arena::GetArena(&message));
+  EXPECT_EQ(nullptr, Arena::GetArena(const_pointer_to_message));
 }
 
 TEST(ArenaTest, GetArenaShouldReturnNullForNonArenaCompatibleTypes) {
@@ -1510,14 +1572,19 @@
 TEST(ArenaTest, SpaceReusePoisonsAndUnpoisonsMemory) {
 #ifdef ADDRESS_SANITIZER
   char buf[1024]{};
+  constexpr int kSize = 32;
   {
     Arena arena(buf, sizeof(buf));
     std::vector<void*> pointers;
     for (int i = 0; i < 100; ++i) {
-      pointers.push_back(Arena::CreateArray<char>(&arena, 16));
+      void* p = Arena::CreateArray<char>(&arena, kSize);
+      // Simulate other ASan client managing shadow memory.
+      ASAN_POISON_MEMORY_REGION(p, kSize);
+      ASAN_UNPOISON_MEMORY_REGION(p, kSize - 4);
+      pointers.push_back(p);
     }
     for (void* p : pointers) {
-      internal::ArenaTestPeer::ReturnArrayMemory(&arena, p, 16);
+      internal::ArenaTestPeer::ReturnArrayMemory(&arena, p, kSize);
       // The first one is not poisoned because it becomes the freelist.
       if (p != pointers[0]) EXPECT_TRUE(__asan_address_is_poisoned(p));
     }
@@ -1542,93 +1609,8 @@
 #endif  // ADDRESS_SANITIZER
 }
 
-namespace {
-uint32_t hooks_num_init = 0;
-uint32_t hooks_num_allocations = 0;
-uint32_t hooks_num_reset = 0;
-uint32_t hooks_num_destruct = 0;
-
-void ClearHookCounts() {
-  hooks_num_init = 0;
-  hooks_num_allocations = 0;
-  hooks_num_reset = 0;
-  hooks_num_destruct = 0;
-}
-}  // namespace
-
-// A helper utility class that handles arena callbacks.
-class ArenaOptionsTestFriend final : public internal::ArenaMetricsCollector {
- public:
-  static internal::ArenaMetricsCollector* NewWithAllocs() {
-    return new ArenaOptionsTestFriend(true);
-  }
-
-  static internal::ArenaMetricsCollector* NewWithoutAllocs() {
-    return new ArenaOptionsTestFriend(false);
-  }
-
-  static void Enable(ArenaOptions* options) {
-    ClearHookCounts();
-    options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithAllocs;
-  }
-
-  static void EnableWithoutAllocs(ArenaOptions* options) {
-    ClearHookCounts();
-    options->make_metrics_collector = &ArenaOptionsTestFriend::NewWithoutAllocs;
-  }
-
-  explicit ArenaOptionsTestFriend(bool record_allocs)
-      : ArenaMetricsCollector(record_allocs) {
-    ++hooks_num_init;
-  }
-  void OnDestroy(uint64_t space_allocated) override {
-    ++hooks_num_destruct;
-    delete this;
-  }
-  void OnReset(uint64_t space_allocated) override { ++hooks_num_reset; }
-  void OnAlloc(const std::type_info* allocated_type,
-               uint64_t alloc_size) override {
-    ++hooks_num_allocations;
-  }
-};
-
-// Test the hooks are correctly called.
-TEST(ArenaTest, ArenaHooksSanity) {
-  ArenaOptions options;
-  ArenaOptionsTestFriend::Enable(&options);
-
-  // Scope for defining the arena
-  {
-    Arena arena(options);
-    EXPECT_EQ(1, hooks_num_init);
-    EXPECT_EQ(0, hooks_num_allocations);
-    Arena::Create<uint64_t>(&arena);
-    if (std::is_trivially_destructible<uint64_t>::value) {
-      EXPECT_EQ(1, hooks_num_allocations);
-    } else {
-      EXPECT_EQ(2, hooks_num_allocations);
-    }
-    arena.Reset();
-    arena.Reset();
-    EXPECT_EQ(2, hooks_num_reset);
-  }
-  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_t>(&arena);
-  EXPECT_EQ(0, hooks_num_allocations);
-}
-
 
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/arenastring.cc b/src/google/protobuf/arenastring.cc
index af0c9df..8c21b1d 100644
--- a/src/google/protobuf/arenastring.cc
+++ b/src/google/protobuf/arenastring.cc
@@ -28,20 +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.
 
-#include <google/protobuf/arenastring.h>
+#include "google/protobuf/arenastring.h"
 
 #include <cstddef>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/stubs/stl_util.h>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -71,7 +71,7 @@
 }  // namespace
 
 const std::string& LazyString::Init() const {
-  static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
+  static absl::Mutex mu{absl::kConstInit};
   mu.Lock();
   const std::string* res = inited_.load(std::memory_order_acquire);
   if (res == nullptr) {
@@ -87,7 +87,7 @@
 namespace {
 
 
-#if defined(NDEBUG) || !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL
+#if defined(NDEBUG) || !defined(GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL)
 
 class ScopedCheckPtrInvariants {
  public:
@@ -97,16 +97,16 @@
 #endif  // NDEBUG || !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL
 
 // Creates a heap allocated std::string value.
-inline TaggedStringPtr CreateString(ConstStringParam value) {
+inline TaggedStringPtr CreateString(absl::string_view value) {
   TaggedStringPtr res;
   res.SetAllocated(new std::string(value.data(), value.length()));
   return res;
 }
 
-#if !GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL
+#ifndef GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL
 
 // Creates an arena allocated std::string value.
-TaggedStringPtr CreateArenaString(Arena& arena, ConstStringParam s) {
+TaggedStringPtr CreateArenaString(Arena& arena, absl::string_view s) {
   TaggedStringPtr res;
   res.SetMutableArena(Arena::Create<std::string>(&arena, s.data(), s.length()));
   return res;
@@ -116,7 +116,7 @@
 
 }  // namespace
 
-void ArenaStringPtr::Set(ConstStringParam value, Arena* arena) {
+void ArenaStringPtr::Set(absl::string_view value, Arena* arena) {
   ScopedCheckPtrInvariants check(&tagged_ptr_);
   if (IsDefault()) {
     // If we're not on an arena, skip straight to a true string to avoid
@@ -124,7 +124,44 @@
     tagged_ptr_ = arena != nullptr ? CreateArenaString(*arena, value)
                                    : CreateString(value);
   } else {
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+    if (arena == nullptr) {
+      auto* old = tagged_ptr_.GetIfAllocated();
+      tagged_ptr_ = CreateString(value);
+      delete old;
+    } else {
+      auto* old = UnsafeMutablePointer();
+      tagged_ptr_ = CreateArenaString(*arena, value);
+      old->assign("garbagedata");
+    }
+#else   // PROTOBUF_FORCE_COPY_DEFAULT_STRING
     UnsafeMutablePointer()->assign(value.data(), value.length());
+#endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  }
+}
+
+template <>
+void ArenaStringPtr::Set(const std::string& value, Arena* arena) {
+  ScopedCheckPtrInvariants check(&tagged_ptr_);
+  if (IsDefault()) {
+    // If we're not on an arena, skip straight to a true string to avoid
+    // possible copy cost later.
+    tagged_ptr_ = arena != nullptr ? CreateArenaString(*arena, value)
+                                   : CreateString(value);
+  } else {
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+    if (arena == nullptr) {
+      auto* old = tagged_ptr_.GetIfAllocated();
+      tagged_ptr_ = CreateString(value);
+      delete old;
+    } else {
+      auto* old = UnsafeMutablePointer();
+      tagged_ptr_ = CreateArenaString(*arena, value);
+      old->assign("garbagedata");
+    }
+#else   // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+    UnsafeMutablePointer()->assign(value);
+#endif  // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   }
 }
 
@@ -264,4 +301,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/arenastring.h b/src/google/protobuf/arenastring.h
index 6bc8395..c6d61d7 100644
--- a/src/google/protobuf/arenastring.h
+++ b/src/google/protobuf/arenastring.h
@@ -36,14 +36,15 @@
 #include <type_traits>
 #include <utility>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/explicitly_constructed.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/port.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/explicitly_constructed.h"
 
 // must be last:
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -99,9 +100,9 @@
   // Bit flags qualifying string properties. We can use 2 bits as
   // ptr_ is guaranteed and enforced to be aligned on 4 byte boundaries.
   enum Flags {
-    kArenaBit = 0x1,      // ptr is arena allocated
-    kMutableBit = 0x2,    // ptr contents are fully mutable
-    kMask = 0x3           // Bit mask
+    kArenaBit = 0x1,    // ptr is arena allocated
+    kMutableBit = 0x2,  // ptr contents are fully mutable
+    kMask = 0x3         // Bit mask
   };
 
   // Composed logical types
@@ -167,7 +168,7 @@
 
   // If the current string is a heap-allocated mutable value, returns a pointer
   // to it.  Returns nullptr otherwise.
-  inline std::string *GetIfAllocated() const {
+  inline std::string* GetIfAllocated() const {
     auto allocated = as_int() ^ kAllocated;
     if (allocated & kMask) return nullptr;
 
@@ -259,13 +260,17 @@
   // instance known to not carry any heap allocated value.
   inline void InitAllocated(std::string* str, Arena* arena);
 
-  void Set(ConstStringParam value, Arena* arena);
+  void Set(absl::string_view value, Arena* arena);
   void Set(std::string&& value, Arena* arena);
+  template <typename... OverloadDisambiguator>
+  void Set(const std::string& value, Arena* arena);
   void Set(const char* s, Arena* arena);
   void Set(const char* s, size_t n, Arena* arena);
 
-  void SetBytes(ConstStringParam value, Arena* arena);
+  void SetBytes(absl::string_view value, Arena* arena);
   void SetBytes(std::string&& value, Arena* arena);
+  template <typename... OverloadDisambiguator>
+  void SetBytes(const std::string& value, Arena* arena);
   void SetBytes(const char* s, Arena* arena);
   void SetBytes(const void* p, size_t n, Arena* arena);
 
@@ -406,14 +411,23 @@
 }
 
 inline void ArenaStringPtr::Set(const char* s, Arena* arena) {
-  Set(ConstStringParam{s}, arena);
+  Set(absl::string_view{s}, arena);
 }
 
 inline void ArenaStringPtr::Set(const char* s, size_t n, Arena* arena) {
-  Set(ConstStringParam{s, n}, arena);
+  Set(absl::string_view{s, n}, arena);
 }
 
-inline void ArenaStringPtr::SetBytes(ConstStringParam value, Arena* arena) {
+inline void ArenaStringPtr::SetBytes(absl::string_view value, Arena* arena) {
+  Set(value, arena);
+}
+
+template <>
+PROTOBUF_EXPORT void ArenaStringPtr::Set(const std::string& value,
+                                         Arena* arena);
+
+template <>
+inline void ArenaStringPtr::SetBytes(const std::string& value, Arena* arena) {
   Set(value, arena);
 }
 
@@ -426,7 +440,7 @@
 }
 
 inline void ArenaStringPtr::SetBytes(const void* p, size_t n, Arena* arena) {
-  Set(ConstStringParam{static_cast<const char*>(p), n}, arena);
+  Set(absl::string_view{static_cast<const char*>(p), n}, arena);
 }
 
 // Make sure rhs_arena allocated rhs, and lhs_arena allocated lhs.
@@ -475,6 +489,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 0e5ea9b..6aa500b 100644
--- a/src/google/protobuf/arenastring_unittest.cc
+++ b/src/google/protobuf/arenastring_unittest.cc
@@ -28,7 +28,7 @@
 // (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/arenastring.h"
 
 #include <algorithm>
 #include <cstdlib>
@@ -37,18 +37,18 @@
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#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 "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/message_lite.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -151,4 +151,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/arenaz_sampler.cc b/src/google/protobuf/arenaz_sampler.cc
index 0eac693..44e53e5 100644
--- a/src/google/protobuf/arenaz_sampler.cc
+++ b/src/google/protobuf/arenaz_sampler.cc
@@ -28,15 +28,16 @@
 // (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/arenaz_sampler.h>
+#include "google/protobuf/arenaz_sampler.h"
 
 #include <atomic>
 #include <cstdint>
 #include <limits>
+#include <utility>
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -56,64 +57,93 @@
 
 PROTOBUF_CONSTINIT std::atomic<bool> g_arenaz_enabled{true};
 PROTOBUF_CONSTINIT std::atomic<int32_t> g_arenaz_sample_parameter{1 << 10};
+PROTOBUF_CONSTINIT std::atomic<ThreadSafeArenazConfigListener>
+    g_arenaz_config_listener{nullptr};
 PROTOBUF_THREAD_LOCAL absl::profiling_internal::ExponentialBiased
     g_exponential_biased_generator;
 
+void TriggerThreadSafeArenazConfigListener() {
+  auto* listener = g_arenaz_config_listener.load(std::memory_order_acquire);
+  if (listener != nullptr) listener();
+}
+
 }  // namespace
 
-PROTOBUF_THREAD_LOCAL int64_t global_next_sample = 1LL << 10;
+PROTOBUF_THREAD_LOCAL SamplingState global_sampling_state = {
+    /*next_sample=*/0, /*sample_stride=*/0};
 
-ThreadSafeArenaStats::ThreadSafeArenaStats() { PrepareForSampling(); }
+ThreadSafeArenaStats::ThreadSafeArenaStats() { PrepareForSampling(0); }
 ThreadSafeArenaStats::~ThreadSafeArenaStats() = default;
 
-void ThreadSafeArenaStats::PrepareForSampling() {
+void ThreadSafeArenaStats::BlockStats::PrepareForSampling() {
   num_allocations.store(0, std::memory_order_relaxed);
-  num_resets.store(0, std::memory_order_relaxed);
-  bytes_requested.store(0, std::memory_order_relaxed);
   bytes_allocated.store(0, std::memory_order_relaxed);
+  bytes_used.store(0, std::memory_order_relaxed);
   bytes_wasted.store(0, std::memory_order_relaxed);
-  max_bytes_allocated.store(0, std::memory_order_relaxed);
+}
+
+void ThreadSafeArenaStats::PrepareForSampling(int64_t stride) {
+  for (auto& blockstats : block_histogram) blockstats.PrepareForSampling();
+  max_block_size.store(0, std::memory_order_relaxed);
   thread_ids.store(0, std::memory_order_relaxed);
+  weight = stride;
   // The inliner makes hardcoded skip_count difficult (especially when combined
   // with LTO).  We use the ability to exclude stacks by regex when encoding
   // instead.
   depth = absl::GetStackTrace(stack, kMaxStackDepth, /* skip_count= */ 0);
 }
 
-void RecordResetSlow(ThreadSafeArenaStats* info) {
-  const size_t max_bytes =
-      info->max_bytes_allocated.load(std::memory_order_relaxed);
-  const size_t allocated_bytes =
-      info->bytes_allocated.load(std::memory_order_relaxed);
-  if (max_bytes < allocated_bytes) {
-    info->max_bytes_allocated.store(allocated_bytes);
+size_t ThreadSafeArenaStats::FindBin(size_t bytes) {
+  if (bytes <= kMaxSizeForBinZero) return 0;
+  if (bytes <= kMaxSizeForPenultimateBin) {
+    // absl::bit_width() returns one plus the base-2 logarithm of x, with any
+    // fractional part discarded.
+    return absl::bit_width(absl::bit_ceil(bytes)) - kLogMaxSizeForBinZero - 1;
   }
-  info->bytes_requested.store(0, std::memory_order_relaxed);
-  info->bytes_allocated.store(0, std::memory_order_relaxed);
-  info->bytes_wasted.fetch_add(0, std::memory_order_relaxed);
-  info->num_allocations.fetch_add(0, std::memory_order_relaxed);
-  info->num_resets.fetch_add(1, std::memory_order_relaxed);
+  return kBlockHistogramBins - 1;
 }
 
-void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested,
+std::pair<size_t, size_t> ThreadSafeArenaStats::MinMaxBlockSizeForBin(
+    size_t bin) {
+  ABSL_ASSERT(bin < kBlockHistogramBins);
+  if (bin == 0) return {1, kMaxSizeForBinZero};
+  if (bin < kBlockHistogramBins - 1) {
+    return {(1 << (kLogMaxSizeForBinZero + bin - 1)) + 1,
+            1 << (kLogMaxSizeForBinZero + bin)};
+  }
+  return {kMaxSizeForPenultimateBin + 1, std::numeric_limits<size_t>::max()};
+}
+
+void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t used,
                         size_t allocated, size_t wasted) {
-  info->bytes_requested.fetch_add(requested, std::memory_order_relaxed);
-  info->bytes_allocated.fetch_add(allocated, std::memory_order_relaxed);
-  info->bytes_wasted.fetch_add(wasted, std::memory_order_relaxed);
-  info->num_allocations.fetch_add(1, std::memory_order_relaxed);
-  const uint64_t tid = (1ULL << (GetCachedTID() % 63));
-  const uint64_t thread_ids = info->thread_ids.load(std::memory_order_relaxed);
-  if (!(thread_ids & tid)) {
-    info->thread_ids.store(thread_ids | tid, std::memory_order_relaxed);
+  // Update the allocated bytes for the current block.
+  ThreadSafeArenaStats::BlockStats& curr =
+      info->block_histogram[ThreadSafeArenaStats::FindBin(allocated)];
+  curr.bytes_allocated.fetch_add(allocated, std::memory_order_relaxed);
+  curr.num_allocations.fetch_add(1, std::memory_order_relaxed);
+
+  // Update the used and wasted bytes for the previous block.
+  ThreadSafeArenaStats::BlockStats& prev =
+      info->block_histogram[ThreadSafeArenaStats::FindBin(used + wasted)];
+  prev.bytes_used.fetch_add(used, std::memory_order_relaxed);
+  prev.bytes_wasted.fetch_add(wasted, std::memory_order_relaxed);
+
+  if (info->max_block_size.load(std::memory_order_relaxed) < allocated) {
+    info->max_block_size.store(allocated, std::memory_order_relaxed);
   }
+  const uint64_t tid = 1ULL << (GetCachedTID() % 63);
+  info->thread_ids.fetch_or(tid, std::memory_order_relaxed);
 }
 
-ThreadSafeArenaStats* SampleSlow(int64_t* next_sample) {
-  bool first = *next_sample < 0;
-  *next_sample = g_exponential_biased_generator.GetStride(
+ThreadSafeArenaStats* SampleSlow(SamplingState& sampling_state) {
+  bool first = sampling_state.next_sample < 0;
+  const int64_t next_stride = g_exponential_biased_generator.GetStride(
       g_arenaz_sample_parameter.load(std::memory_order_relaxed));
   // Small values of interval are equivalent to just sampling next time.
-  ABSL_ASSERT(*next_sample >= 1);
+  ABSL_ASSERT(next_stride >= 1);
+  sampling_state.next_sample = next_stride;
+  const int64_t old_stride =
+      absl::exchange(sampling_state.sample_stride, next_stride);
 
   // g_arenaz_enabled can be dynamically flipped, we need to set a threshold low
   // enough that we will start sampling in a reasonable time, so we just use the
@@ -122,18 +152,36 @@
   // We will only be negative on our first count, so we should just retry in
   // that case.
   if (first) {
-    if (PROTOBUF_PREDICT_TRUE(--*next_sample > 0)) return nullptr;
-    return SampleSlow(next_sample);
+    if (PROTOBUF_PREDICT_TRUE(--sampling_state.next_sample > 0)) return nullptr;
+    return SampleSlow(sampling_state);
   }
 
-  return GlobalThreadSafeArenazSampler().Register();
+  return GlobalThreadSafeArenazSampler().Register(old_stride);
+}
+
+void SetThreadSafeArenazConfigListener(ThreadSafeArenazConfigListener l) {
+  g_arenaz_config_listener.store(l, std::memory_order_release);
+}
+
+bool IsThreadSafeArenazEnabled() {
+  return g_arenaz_enabled.load(std::memory_order_acquire);
 }
 
 void SetThreadSafeArenazEnabled(bool enabled) {
+  SetThreadSafeArenazEnabledInternal(enabled);
+  TriggerThreadSafeArenazConfigListener();
+}
+
+void SetThreadSafeArenazEnabledInternal(bool enabled) {
   g_arenaz_enabled.store(enabled, std::memory_order_release);
 }
 
 void SetThreadSafeArenazSampleParameter(int32_t rate) {
+  SetThreadSafeArenazSampleParameterInternal(rate);
+  TriggerThreadSafeArenazConfigListener();
+}
+
+void SetThreadSafeArenazSampleParameterInternal(int32_t rate) {
   if (rate > 0) {
     g_arenaz_sample_parameter.store(rate, std::memory_order_release);
   } else {
@@ -142,7 +190,16 @@
   }
 }
 
+int32_t ThreadSafeArenazSampleParameter() {
+  return g_arenaz_sample_parameter.load(std::memory_order_relaxed);
+}
+
 void SetThreadSafeArenazMaxSamples(int32_t max) {
+  SetThreadSafeArenazMaxSamplesInternal(max);
+  TriggerThreadSafeArenazConfigListener();
+}
+
+void SetThreadSafeArenazMaxSamplesInternal(int32_t max) {
   if (max > 0) {
     GlobalThreadSafeArenazSampler().SetMaxSamples(max);
   } else {
@@ -151,9 +208,14 @@
   }
 }
 
+size_t ThreadSafeArenazMaxSamples() {
+  return GlobalThreadSafeArenazSampler().GetMaxSamples();
+}
+
 void SetThreadSafeArenazGlobalNextSample(int64_t next_sample) {
   if (next_sample >= 0) {
-    global_next_sample = next_sample;
+    global_sampling_state.next_sample = next_sample;
+    global_sampling_state.sample_stride = next_sample;
   } else {
     ABSL_RAW_LOG(ERROR, "Invalid thread safe arenaz next sample: %lld",
                  static_cast<long long>(next_sample));  // NOLINT(runtime/int)
@@ -166,9 +228,16 @@
   return nullptr;
 }
 
+void SetThreadSafeArenazConfigListener(ThreadSafeArenazConfigListener) {}
 void SetThreadSafeArenazEnabled(bool enabled) {}
+void SetThreadSafeArenazEnabledInternal(bool enabled) {}
+bool IsThreadSafeArenazEnabled() { return false; }
 void SetThreadSafeArenazSampleParameter(int32_t rate) {}
+void SetThreadSafeArenazSampleParameterInternal(int32_t rate) {}
+int32_t ThreadSafeArenazSampleParameter() { return 0; }
 void SetThreadSafeArenazMaxSamples(int32_t max) {}
+void SetThreadSafeArenazMaxSamplesInternal(int32_t max) {}
+size_t ThreadSafeArenazMaxSamples() { return 0; }
 void SetThreadSafeArenazGlobalNextSample(int64_t next_sample) {}
 #endif  // defined(PROTOBUF_ARENAZ_SAMPLE)
 
diff --git a/src/google/protobuf/arenaz_sampler.h b/src/google/protobuf/arenaz_sampler.h
index b04b0cc..23ab83a 100644
--- a/src/google/protobuf/arenaz_sampler.h
+++ b/src/google/protobuf/arenaz_sampler.h
@@ -31,13 +31,15 @@
 #ifndef GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
 #define GOOGLE_PROTOBUF_SRC_GOOGLE_PROTOBUF_ARENAZ_SAMPLER_H__
 
+#include <array>
 #include <atomic>
 #include <cstddef>
 #include <cstdint>
+#include <utility>
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -45,8 +47,7 @@
 
 #if defined(PROTOBUF_ARENAZ_SAMPLE)
 struct ThreadSafeArenaStats;
-void RecordResetSlow(ThreadSafeArenaStats* info);
-void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t requested,
+void RecordAllocateSlow(ThreadSafeArenaStats* info, size_t used,
                         size_t allocated, size_t wasted);
 // Stores information about a sampled thread safe arena.  All mutations to this
 // *must* be made through `Record*` functions below.  All reads from this *must*
@@ -58,20 +59,42 @@
   ~ThreadSafeArenaStats();
 
   // Puts the object into a clean state, fills in the logically `const` members,
-  // blocking for any readers that are currently sampling the object.
-  void PrepareForSampling() ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
+  // blocking for any readers that are currently sampling the object.  The
+  // 'stride' parameter is the number of ThreadSafeArenas that were instantiated
+  // between this sample and the previous one.
+  void PrepareForSampling(int64_t stride)
+      ABSL_EXCLUSIVE_LOCKS_REQUIRED(init_mu);
 
   // These fields are mutated by the various Record* APIs and need to be
   // thread-safe.
-  std::atomic<int> num_allocations;
-  std::atomic<int> num_resets;
-  std::atomic<size_t> bytes_requested;
-  std::atomic<size_t> bytes_allocated;
-  std::atomic<size_t> bytes_wasted;
-  // Records the largest size an arena ever had.  Maintained across resets.
-  std::atomic<size_t> max_bytes_allocated;
-  // Bit i when set to 1 indicates that a thread with tid % 63 = i accessed the
-  // underlying arena.  The field is maintained across resets.
+  struct BlockStats {
+    std::atomic<int> num_allocations;
+    std::atomic<size_t> bytes_allocated;
+    std::atomic<size_t> bytes_used;
+    std::atomic<size_t> bytes_wasted;
+
+    void PrepareForSampling();
+  };
+
+  // block_histogram is a kBlockHistogramBins sized histogram.  The zeroth bin
+  // stores info about blocks of size \in [1, 1 << kLogMaxSizeForBinZero]. Bin
+  // i, where i > 0, stores info for blocks of size \in (max_size_bin (i-1),
+  // 1 << (kLogMaxSizeForBinZero + i)].  The final bin stores info about blocks
+  // of size \in [kMaxSizeForPenultimateBin + 1,
+  // std::numeric_limits<size_t>::max()].
+  static constexpr size_t kBlockHistogramBins = 15;
+  static constexpr size_t kLogMaxSizeForBinZero = 7;
+  static constexpr size_t kMaxSizeForBinZero = (1 << kLogMaxSizeForBinZero);
+  static constexpr size_t kMaxSizeForPenultimateBin =
+      1 << (kLogMaxSizeForBinZero + kBlockHistogramBins - 2);
+  std::array<BlockStats, kBlockHistogramBins> block_histogram;
+
+  // Records the largest block allocated for the arena.
+  std::atomic<size_t> max_block_size;
+  // Bit `i` is set to 1 indicates that a thread with `tid % 63 = i` accessed
+  // the underlying arena.  We use `% 63` as a rudimentary hash to ensure some
+  // bit mixing for thread-ids; `% 64` would only grab the low bits and might
+  // create sampling artifacts.
   std::atomic<uint64_t> thread_ids;
 
   // All of the fields below are set by `PrepareForSampling`, they must not
@@ -82,14 +105,32 @@
   static constexpr int kMaxStackDepth = 64;
   int32_t depth;
   void* stack[kMaxStackDepth];
-  static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t requested,
+  static void RecordAllocateStats(ThreadSafeArenaStats* info, size_t used,
                                   size_t allocated, size_t wasted) {
     if (PROTOBUF_PREDICT_TRUE(info == nullptr)) return;
-    RecordAllocateSlow(info, requested, allocated, wasted);
+    RecordAllocateSlow(info, used, allocated, wasted);
   }
+
+  // Returns the bin for the provided size.
+  static size_t FindBin(size_t bytes);
+
+  // Returns the min and max bytes that can be stored in the histogram for
+  // blocks in the provided bin.
+  static std::pair<size_t, size_t> MinMaxBlockSizeForBin(size_t bin);
 };
 
-ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
+struct SamplingState {
+  // Number of ThreadSafeArenas that should be instantiated before the next
+  // ThreadSafeArena is sampled.  This variable is decremented with each
+  // instantiation.
+  int64_t next_sample;
+  // When we make a sampling decision, we record that distance between from the
+  // previous sample so we can weight each sample.  'distance' here is the
+  // number of instantiations of ThreadSafeArena.
+  int64_t sample_stride;
+};
+
+ThreadSafeArenaStats* SampleSlow(SamplingState& sampling_state);
 void UnsampleSlow(ThreadSafeArenaStats* info);
 
 class ThreadSafeArenaStatsHandle {
@@ -115,11 +156,6 @@
     return *this;
   }
 
-  void RecordReset() {
-    if (PROTOBUF_PREDICT_TRUE(info_ == nullptr)) return;
-    RecordResetSlow(info_);
-  }
-
   ThreadSafeArenaStats* MutableStats() { return info_; }
 
   friend void swap(ThreadSafeArenaStatsHandle& lhs,
@@ -136,24 +172,27 @@
 using ThreadSafeArenazSampler =
     ::absl::profiling_internal::SampleRecorder<ThreadSafeArenaStats>;
 
-extern PROTOBUF_THREAD_LOCAL int64_t global_next_sample;
+extern PROTOBUF_THREAD_LOCAL SamplingState global_sampling_state;
 
 // Returns an RAII sampling handle that manages registration and unregistation
 // with the global sampler.
 inline ThreadSafeArenaStatsHandle Sample() {
-  if (PROTOBUF_PREDICT_TRUE(--global_next_sample > 0)) {
+  if (PROTOBUF_PREDICT_TRUE(--global_sampling_state.next_sample > 0)) {
     return ThreadSafeArenaStatsHandle(nullptr);
   }
-  return ThreadSafeArenaStatsHandle(SampleSlow(&global_next_sample));
+  return ThreadSafeArenaStatsHandle(SampleSlow(global_sampling_state));
 }
 
 #else
+
+using SamplingState = int64_t;
+
 struct ThreadSafeArenaStats {
   static void RecordAllocateStats(ThreadSafeArenaStats*, size_t /*requested*/,
                                   size_t /*allocated*/, size_t /*wasted*/) {}
 };
 
-ThreadSafeArenaStats* SampleSlow(int64_t* next_sample);
+ThreadSafeArenaStats* SampleSlow(SamplingState& next_sample);
 void UnsampleSlow(ThreadSafeArenaStats* info);
 
 class ThreadSafeArenaStatsHandle {
@@ -187,14 +226,29 @@
 // Returns a global Sampler.
 ThreadSafeArenazSampler& GlobalThreadSafeArenazSampler();
 
+using ThreadSafeArenazConfigListener = void (*)();
+void SetThreadSafeArenazConfigListener(ThreadSafeArenazConfigListener l);
+
 // Enables or disables sampling for thread safe arenas.
 void SetThreadSafeArenazEnabled(bool enabled);
+void SetThreadSafeArenazEnabledInternal(bool enabled);
+
+// Returns true if sampling is on, false otherwise.
+bool IsThreadSafeArenazEnabled();
 
 // Sets the rate at which thread safe arena will be sampled.
 void SetThreadSafeArenazSampleParameter(int32_t rate);
+void SetThreadSafeArenazSampleParameterInternal(int32_t rate);
+
+// Returns the rate at which thread safe arena will be sampled.
+int32_t ThreadSafeArenazSampleParameter();
 
 // Sets a soft max for the number of samples that will be kept.
 void SetThreadSafeArenazMaxSamples(int32_t max);
+void SetThreadSafeArenazMaxSamplesInternal(int32_t max);
+
+// Returns the max number of samples that will be kept.
+size_t ThreadSafeArenazMaxSamples();
 
 // Sets the current value for when arenas should be next sampled.
 void SetThreadSafeArenazGlobalNextSample(int64_t next_sample);
@@ -203,5 +257,5 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 #endif  // GOOGLE_PROTOBUF_SRC_PROTOBUF_ARENAZ_SAMPLER_H__
diff --git a/src/google/protobuf/arenaz_sampler_test.cc b/src/google/protobuf/arenaz_sampler_test.cc
index 1bfec54..98ff042 100644
--- a/src/google/protobuf/arenaz_sampler_test.cc
+++ b/src/google/protobuf/arenaz_sampler_test.cc
@@ -28,19 +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.
 
-#include <google/protobuf/arenaz_sampler.h>
+#include "google/protobuf/arenaz_sampler.h"
 
+#include <atomic>
+#include <limits>
 #include <memory>
 #include <random>
+#include <utility>
 #include <vector>
 
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -56,18 +58,27 @@
     return h->info_;
   }
 };
+
 std::vector<size_t> GetBytesAllocated(ThreadSafeArenazSampler* s) {
   std::vector<size_t> res;
   s->Iterate([&](const ThreadSafeArenaStats& info) {
-    res.push_back(info.bytes_allocated.load(std::memory_order_acquire));
+    for (const auto& block_stats : info.block_histogram) {
+      size_t bytes_allocated =
+          block_stats.bytes_allocated.load(std::memory_order_acquire);
+      if (bytes_allocated != 0) {
+        res.push_back(bytes_allocated);
+      }
+    }
   });
   return res;
 }
 
-ThreadSafeArenaStats* Register(ThreadSafeArenazSampler* s, size_t size) {
-  auto* info = s->Register();
+ThreadSafeArenaStats* Register(ThreadSafeArenazSampler* s, size_t size,
+                               int64_t stride) {
+  auto* info = s->Register(stride);
   assert(info != nullptr);
-  info->bytes_allocated.store(size);
+  info->block_histogram[0].bytes_allocated.store(size,
+                                                 std::memory_order_relaxed);
   return info;
 }
 
@@ -79,75 +90,148 @@
 
 TEST(ThreadSafeArenaStatsTest, PrepareForSampling) {
   ThreadSafeArenaStats info;
-  MutexLock l(&info.init_mu);
-  info.PrepareForSampling();
+  constexpr int64_t kTestStride = 107;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling(kTestStride);
 
-  EXPECT_EQ(info.num_allocations.load(), 0);
-  EXPECT_EQ(info.num_resets.load(), 0);
-  EXPECT_EQ(info.bytes_requested.load(), 0);
-  EXPECT_EQ(info.bytes_allocated.load(), 0);
-  EXPECT_EQ(info.bytes_wasted.load(), 0);
-  EXPECT_EQ(info.max_bytes_allocated.load(), 0);
+  for (const auto& block_stats : info.block_histogram) {
+    EXPECT_EQ(block_stats.num_allocations.load(std::memory_order_relaxed), 0);
+    EXPECT_EQ(block_stats.bytes_used.load(std::memory_order_relaxed), 0);
+    EXPECT_EQ(block_stats.bytes_allocated.load(std::memory_order_relaxed), 0);
+    EXPECT_EQ(block_stats.bytes_wasted.load(std::memory_order_relaxed), 0);
+  }
+  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 0);
+  EXPECT_EQ(info.weight, kTestStride);
 
-  info.num_allocations.store(1, std::memory_order_relaxed);
-  info.num_resets.store(1, std::memory_order_relaxed);
-  info.bytes_requested.store(1, std::memory_order_relaxed);
-  info.bytes_allocated.store(1, std::memory_order_relaxed);
-  info.bytes_wasted.store(1, std::memory_order_relaxed);
-  info.max_bytes_allocated.store(1, std::memory_order_relaxed);
+  for (auto& block_stats : info.block_histogram) {
+    block_stats.num_allocations.store(1, std::memory_order_relaxed);
+    block_stats.bytes_used.store(1, std::memory_order_relaxed);
+    block_stats.bytes_allocated.store(1, std::memory_order_relaxed);
+    block_stats.bytes_wasted.store(1, std::memory_order_relaxed);
+  }
+  info.max_block_size.store(1, std::memory_order_relaxed);
 
-  info.PrepareForSampling();
-  EXPECT_EQ(info.num_allocations.load(), 0);
-  EXPECT_EQ(info.num_resets.load(), 0);
-  EXPECT_EQ(info.bytes_requested.load(), 0);
-  EXPECT_EQ(info.bytes_allocated.load(), 0);
-  EXPECT_EQ(info.bytes_wasted.load(), 0);
-  EXPECT_EQ(info.max_bytes_allocated.load(), 0);
+  info.PrepareForSampling(2 * kTestStride);
+  for (auto& block_stats : info.block_histogram) {
+    EXPECT_EQ(block_stats.num_allocations.load(std::memory_order_relaxed), 0);
+    EXPECT_EQ(block_stats.bytes_used.load(std::memory_order_relaxed), 0);
+    EXPECT_EQ(block_stats.bytes_allocated.load(std::memory_order_relaxed), 0);
+    EXPECT_EQ(block_stats.bytes_wasted.load(std::memory_order_relaxed), 0);
+  }
+  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 0);
+  EXPECT_EQ(info.weight, 2 * kTestStride);
+}
+
+TEST(ThreadSafeArenaStatsTest, FindBin) {
+  size_t current_bin = 0;
+  size_t bytes = 1;
+  while (current_bin < ThreadSafeArenaStats::kBlockHistogramBins - 1) {
+    size_t next_bin = ThreadSafeArenaStats::FindBin(bytes);
+    if (next_bin != current_bin) {
+      // Test the bins increase linearly.
+      EXPECT_EQ(next_bin, current_bin + 1);
+      // Test the bins change only at values of the form 2^k + 1.
+      EXPECT_EQ(absl::popcount(bytes - 1), 1);
+      current_bin = next_bin;
+    }
+    ++bytes;
+  }
+}
+
+TEST(ThreadSafeArenaStatsTest, MinMaxBlockSizeForBin) {
+  std::pair<size_t, size_t> current_limits =
+      ThreadSafeArenaStats::MinMaxBlockSizeForBin(0);
+  EXPECT_EQ(current_limits.first, 1);
+  EXPECT_LT(current_limits.first, current_limits.second);
+  for (size_t i = 1; i < ThreadSafeArenaStats::kBlockHistogramBins; ++i) {
+    std::pair<size_t, size_t> next_limits =
+        ThreadSafeArenaStats::MinMaxBlockSizeForBin(i);
+    EXPECT_LT(next_limits.first, next_limits.second);
+    // Test the limits do not have gaps.
+    EXPECT_EQ(next_limits.first, current_limits.second + 1);
+    if (i != ThreadSafeArenaStats::kBlockHistogramBins - 1) {
+      EXPECT_EQ(next_limits.second, 2 * current_limits.second);
+    }
+    current_limits = next_limits;
+  }
+  // Test the limits cover the entire range possible.
+  EXPECT_EQ(current_limits.second, std::numeric_limits<size_t>::max());
 }
 
 TEST(ThreadSafeArenaStatsTest, RecordAllocateSlow) {
   ThreadSafeArenaStats info;
-  MutexLock l(&info.init_mu);
-  info.PrepareForSampling();
-  RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/128, /*wasted=*/0);
-  EXPECT_EQ(info.num_allocations.load(), 1);
-  EXPECT_EQ(info.num_resets.load(), 0);
-  EXPECT_EQ(info.bytes_requested.load(), 100);
-  EXPECT_EQ(info.bytes_allocated.load(), 128);
-  EXPECT_EQ(info.bytes_wasted.load(), 0);
-  EXPECT_EQ(info.max_bytes_allocated.load(), 0);
+  constexpr int64_t kTestStride = 458;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling(kTestStride);
+  RecordAllocateSlow(&info, /*requested=*/0, /*allocated=*/128, /*wasted=*/0);
+  EXPECT_EQ(
+      info.block_histogram[0].num_allocations.load(std::memory_order_relaxed),
+      1);
+  EXPECT_EQ(info.block_histogram[0].bytes_used.load(std::memory_order_relaxed),
+            0);
+  EXPECT_EQ(
+      info.block_histogram[0].bytes_allocated.load(std::memory_order_relaxed),
+      128);
+  EXPECT_EQ(
+      info.block_histogram[0].bytes_wasted.load(std::memory_order_relaxed), 0);
+  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 128);
   RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/256,
                      /*wasted=*/28);
-  EXPECT_EQ(info.num_allocations.load(), 2);
-  EXPECT_EQ(info.num_resets.load(), 0);
-  EXPECT_EQ(info.bytes_requested.load(), 200);
-  EXPECT_EQ(info.bytes_allocated.load(), 384);
-  EXPECT_EQ(info.bytes_wasted.load(), 28);
-  EXPECT_EQ(info.max_bytes_allocated.load(), 0);
+  EXPECT_EQ(info.block_histogram[0].bytes_used.load(std::memory_order_relaxed),
+            100);
+  EXPECT_EQ(
+      info.block_histogram[0].bytes_wasted.load(std::memory_order_relaxed), 28);
+  EXPECT_EQ(
+      info.block_histogram[1].num_allocations.load(std::memory_order_relaxed),
+      1);
+  EXPECT_EQ(
+      info.block_histogram[1].bytes_allocated.load(std::memory_order_relaxed),
+      256);
+  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 256);
 }
 
-TEST(ThreadSafeArenaStatsTest, RecordResetSlow) {
+TEST(ThreadSafeArenaStatsTest, RecordAllocateSlowMaxBlockSizeTest) {
   ThreadSafeArenaStats info;
-  MutexLock l(&info.init_mu);
-  info.PrepareForSampling();
-  EXPECT_EQ(info.num_resets.load(), 0);
-  EXPECT_EQ(info.bytes_allocated.load(), 0);
+  constexpr int64_t kTestStride = 458;
+  absl::MutexLock l(&info.init_mu);
+  info.PrepareForSampling(kTestStride);
   RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/128, /*wasted=*/0);
-  EXPECT_EQ(info.num_resets.load(), 0);
-  EXPECT_EQ(info.bytes_allocated.load(), 128);
-  RecordResetSlow(&info);
-  EXPECT_EQ(info.num_resets.load(), 1);
-  EXPECT_EQ(info.bytes_allocated.load(), 0);
+  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 128);
+  RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/256,
+                     /*wasted=*/28);
+  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 256);
+  RecordAllocateSlow(&info, /*requested=*/100, /*allocated=*/128,
+                     /*wasted=*/28);
+  EXPECT_EQ(info.max_block_size.load(std::memory_order_relaxed), 256);
+}
+
+TEST(ThreadSafeArenazSamplerTest, SamplingCorrectness) {
+  SetThreadSafeArenazEnabled(true);
+  for (int p = 0; p <= 15; ++p) {
+    SetThreadSafeArenazSampleParameter(1 << p);
+    SetThreadSafeArenazGlobalNextSample(1 << p);
+    const int kTrials = 1000 << p;
+    std::vector<ThreadSafeArenaStatsHandle> hv;
+    for (int i = 0; i < kTrials; ++i) {
+      ThreadSafeArenaStatsHandle h = Sample();
+      if (h.MutableStats() != nullptr) hv.push_back(std::move(h));
+    }
+    // Ideally samples << p should be very close to kTrials.  But we keep a
+    // factor of two guard band.
+    EXPECT_GE(hv.size() << p, kTrials / 2);
+    EXPECT_LE(hv.size() << p, 2 * kTrials);
+  }
 }
 
 TEST(ThreadSafeArenazSamplerTest, SmallSampleParameter) {
   SetThreadSafeArenazEnabled(true);
   SetThreadSafeArenazSampleParameter(100);
+  constexpr int64_t kTestStride = 0;
 
   for (int i = 0; i < 1000; ++i) {
-    int64_t next_sample = 0;
-    ThreadSafeArenaStats* sample = SampleSlow(&next_sample);
-    EXPECT_GT(next_sample, 0);
+    SamplingState sampling_state = {kTestStride, kTestStride};
+    ThreadSafeArenaStats* sample = SampleSlow(sampling_state);
+    EXPECT_GT(sampling_state.next_sample, 0);
     EXPECT_NE(sample, nullptr);
     UnsampleSlow(sample);
   }
@@ -156,11 +240,12 @@
 TEST(ThreadSafeArenazSamplerTest, LargeSampleParameter) {
   SetThreadSafeArenazEnabled(true);
   SetThreadSafeArenazSampleParameter(std::numeric_limits<int32_t>::max());
+  constexpr int64_t kTestStride = 0;
 
   for (int i = 0; i < 1000; ++i) {
-    int64_t next_sample = 0;
-    ThreadSafeArenaStats* sample = SampleSlow(&next_sample);
-    EXPECT_GT(next_sample, 0);
+    SamplingState sampling_state = {kTestStride, kTestStride};
+    ThreadSafeArenaStats* sample = SampleSlow(sampling_state);
+    EXPECT_GT(sampling_state.next_sample, 0);
     EXPECT_NE(sample, nullptr);
     UnsampleSlow(sample);
   }
@@ -187,14 +272,19 @@
 
 TEST(ThreadSafeArenazSamplerTest, Handle) {
   auto& sampler = GlobalThreadSafeArenazSampler();
-  ThreadSafeArenaStatsHandle h(sampler.Register());
+  constexpr int64_t kTestStride = 17;
+  ThreadSafeArenaStatsHandle h(sampler.Register(kTestStride));
   auto* info = ThreadSafeArenaStatsHandlePeer::GetInfo(&h);
-  info->bytes_allocated.store(0x12345678, std::memory_order_relaxed);
+  info->block_histogram[0].bytes_allocated.store(0x12345678,
+                                                 std::memory_order_relaxed);
 
   bool found = false;
   sampler.Iterate([&](const ThreadSafeArenaStats& h) {
     if (&h == info) {
-      EXPECT_EQ(h.bytes_allocated.load(), 0x12345678);
+      EXPECT_EQ(
+          h.block_histogram[0].bytes_allocated.load(std::memory_order_relaxed),
+          0x12345678);
+      EXPECT_EQ(h.weight, kTestStride);
       found = true;
     }
   });
@@ -206,7 +296,8 @@
     if (&h == info) {
       // this will only happen if some other thread has resurrected the info
       // the old handle was using.
-      if (h.bytes_allocated.load() == 0x12345678) {
+      if (h.block_histogram[0].bytes_allocated.load(
+              std::memory_order_relaxed) == 0x12345678) {
         found = true;
       }
     }
@@ -216,12 +307,13 @@
 
 TEST(ThreadSafeArenazSamplerTest, Registration) {
   ThreadSafeArenazSampler sampler;
-  auto* info1 = Register(&sampler, 1);
+  constexpr int64_t kTestStride = 100;
+  auto* info1 = Register(&sampler, 1, kTestStride);
   EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1));
 
-  auto* info2 = Register(&sampler, 2);
+  auto* info2 = Register(&sampler, 2, kTestStride);
   EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 2));
-  info1->bytes_allocated.store(3);
+  info1->block_histogram[0].bytes_allocated.store(3, std::memory_order_relaxed);
   EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(3, 2));
 
   sampler.Unregister(info1);
@@ -231,19 +323,20 @@
 TEST(ThreadSafeArenazSamplerTest, Unregistration) {
   ThreadSafeArenazSampler sampler;
   std::vector<ThreadSafeArenaStats*> infos;
+  constexpr int64_t kTestStride = 200;
   for (size_t i = 0; i < 3; ++i) {
-    infos.push_back(Register(&sampler, i));
+    infos.push_back(Register(&sampler, i + 1, kTestStride));
   }
-  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(0, 1, 2));
+  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 2, 3));
 
   sampler.Unregister(infos[1]);
-  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(0, 2));
+  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 3));
 
-  infos.push_back(Register(&sampler, 3));
-  infos.push_back(Register(&sampler, 4));
-  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(0, 2, 3, 4));
+  infos.push_back(Register(&sampler, 3, kTestStride));
+  infos.push_back(Register(&sampler, 4, kTestStride));
+  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 3, 3, 4));
   sampler.Unregister(infos[3]);
-  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(0, 2, 4));
+  EXPECT_THAT(GetBytesAllocated(&sampler), UnorderedElementsAre(1, 3, 4));
 
   sampler.Unregister(infos[0]);
   sampler.Unregister(infos[2]);
@@ -257,18 +350,19 @@
   ThreadPool pool(10);
 
   for (int i = 0; i < 10; ++i) {
-    pool.Schedule([&sampler, &stop]() {
+    const int64_t sampling_stride = 11 + i % 3;
+    pool.Schedule([&sampler, &stop, sampling_stride]() {
       std::random_device rd;
       std::mt19937 gen(rd());
 
       std::vector<ThreadSafeArenaStats*> infoz;
       while (!stop.HasBeenNotified()) {
         if (infoz.empty()) {
-          infoz.push_back(sampler.Register());
+          infoz.push_back(sampler.Register(sampling_stride));
         }
         switch (std::uniform_int_distribution<>(0, 1)(gen)) {
           case 0: {
-            infoz.push_back(sampler.Register());
+            infoz.push_back(sampler.Register(sampling_stride));
             break;
           }
           case 1: {
@@ -277,6 +371,7 @@
             ThreadSafeArenaStats* info = infoz[p];
             infoz[p] = infoz.back();
             infoz.pop_back();
+            EXPECT_EQ(info->weight, sampling_stride);
             sampler.Unregister(info);
             break;
           }
@@ -292,9 +387,10 @@
 
 TEST(ThreadSafeArenazSamplerTest, Callback) {
   ThreadSafeArenazSampler sampler;
+  constexpr int64_t kTestStride = 203;
 
-  auto* info1 = Register(&sampler, 1);
-  auto* info2 = Register(&sampler, 2);
+  auto* info1 = Register(&sampler, 1, kTestStride);
+  auto* info2 = Register(&sampler, 2, kTestStride);
 
   static const ThreadSafeArenaStats* expected;
 
@@ -315,6 +411,33 @@
   sampler.Unregister(info2);
 }
 
+TEST(ThreadSafeArenazSamplerTest, InitialBlockReportsZeroUsedAndWasted) {
+  SetThreadSafeArenazEnabled(true);
+  // Setting 1 as the parameter value means one in every two arenas would be
+  // sampled, on average.
+  int32_t oldparam = ThreadSafeArenazSampleParameter();
+  SetThreadSafeArenazSampleParameter(1);
+  SetThreadSafeArenazGlobalNextSample(0);
+  constexpr int kSize = 571;
+  int count_found_allocation = 0;
+  auto& sampler = GlobalThreadSafeArenazSampler();
+  for (int i = 0; i < 10; ++i) {
+    char block[kSize];
+    google::protobuf::Arena arena(/*initial_block=*/block, /*initial_block_size=*/kSize);
+    sampler.Iterate([&](const ThreadSafeArenaStats& h) {
+      const auto& histbin =
+          h.block_histogram[ThreadSafeArenaStats::FindBin(kSize)];
+      if (histbin.bytes_allocated.load(std::memory_order_relaxed) == kSize) {
+        count_found_allocation++;
+        EXPECT_EQ(histbin.bytes_used, 0);
+        EXPECT_EQ(histbin.bytes_wasted, 0);
+      }
+    });
+  }
+  EXPECT_GT(count_found_allocation, 0);
+  SetThreadSafeArenazSampleParameter(oldparam);
+}
+
 class ThreadSafeArenazSamplerTestThread : public Thread {
  protected:
   void Run() override {
@@ -332,7 +455,7 @@
 
  public:
   ThreadSafeArenazSamplerTestThread(const thread::Options& options,
-                                    StringPiece name,
+                                    absl::string_view name,
                                     google::protobuf::Arena* arena,
                                     absl::Barrier* barrier)
       : Thread(options, name), arena_(arena), barrier_(barrier) {}
@@ -346,6 +469,7 @@
   SetThreadSafeArenazEnabled(true);
   // Setting 1 as the parameter value means one in every two arenas would be
   // sampled, on average.
+  int32_t oldparam = ThreadSafeArenazSampleParameter();
   SetThreadSafeArenazSampleParameter(1);
   SetThreadSafeArenazGlobalNextSample(0);
   auto& sampler = GlobalThreadSafeArenazSampler();
@@ -359,7 +483,7 @@
     std::vector<std::unique_ptr<ThreadSafeArenazSamplerTestThread>> threads;
     for (int i = 0; i < kNumThreads; i++) {
       auto t = std::make_unique<ThreadSafeArenazSamplerTestThread>(
-          options, StrCat("thread", i), &arena, barrier);
+          options, absl::StrCat("thread", i), &arena, barrier);
       t->Start();
       threads.push_back(std::move(t));
     }
@@ -373,6 +497,95 @@
     }
   }
   EXPECT_GT(count, 0);
+  SetThreadSafeArenazSampleParameter(oldparam);
+}
+
+class SampleFirstArenaThread : public Thread {
+ protected:
+  void Run() override {
+    google::protobuf::Arena arena;
+    google::protobuf::ArenaSafeUniquePtr<
+        protobuf_test_messages::proto2::TestAllTypesProto2>
+        message = google::protobuf::MakeArenaSafeUnique<
+            protobuf_test_messages::proto2::TestAllTypesProto2>(&arena);
+    GOOGLE_CHECK(message != nullptr);
+    arena_created_.Notify();
+    samples_counted_.WaitForNotification();
+  }
+
+ public:
+  explicit SampleFirstArenaThread(const thread::Options& options)
+      : Thread(options, "SampleFirstArenaThread") {}
+
+  absl::Notification arena_created_;
+  absl::Notification samples_counted_;
+};
+
+// Test that the first arena created on a thread may and may not be chosen for
+// sampling.
+TEST(ThreadSafeArenazSamplerTest, SampleFirstArena) {
+  SetThreadSafeArenazEnabled(true);
+  auto& sampler = GlobalThreadSafeArenazSampler();
+
+  enum class SampleResult {
+    kSampled,
+    kUnsampled,
+    kSpoiled,
+  };
+
+  auto count_samples = [&]() {
+    int count = 0;
+    sampler.Iterate([&](const ThreadSafeArenaStats& h) { ++count; });
+    return count;
+  };
+
+  auto run_sample_experiment = [&]() {
+    int before = count_samples();
+    thread::Options options;
+    options.set_joinable(true);
+    SampleFirstArenaThread t(options);
+    t.Start();
+    t.arena_created_.WaitForNotification();
+    int during = count_samples();
+    t.samples_counted_.Notify();
+    t.Join();
+    int after = count_samples();
+
+    // If we didn't get back where we were, some other thread may have
+    // created an arena and produced an invalid experiment run.
+    if (before != after) return SampleResult::kSpoiled;
+
+    switch (during - before) {
+      case 1:
+        return SampleResult::kSampled;
+      case 0:
+        return SampleResult::kUnsampled;
+      default:
+        return SampleResult::kSpoiled;
+    }
+  };
+
+  constexpr int kTrials = 10000;
+  bool sampled = false;
+  bool unsampled = false;
+  for (int i = 0; i < kTrials; ++i) {
+    switch (run_sample_experiment()) {
+      case SampleResult::kSampled:
+        sampled = true;
+        break;
+      case SampleResult::kUnsampled:
+        unsampled = true;
+        break;
+      default:
+        break;
+    }
+
+    // This is the success criteria for the entire test.  At some point
+    // we sampled the first arena and at some point we did not.
+    if (sampled && unsampled) return;
+  }
+  EXPECT_TRUE(sampled);
+  EXPECT_TRUE(unsampled);
 }
 #endif  // defined(PROTOBUF_ARENAZ_SAMPLE)
 
diff --git a/src/google/protobuf/bridge/BUILD.bazel b/src/google/protobuf/bridge/BUILD.bazel
new file mode 100644
index 0000000..b76bbae
--- /dev/null
+++ b/src/google/protobuf/bridge/BUILD.bazel
@@ -0,0 +1,11 @@
+load("@rules_proto//proto:defs.bzl", "proto_library")
+
+package(
+    default_visibility = ["//visibility:public"],
+)
+
+proto_library(
+    name = "message_set_proto",
+    srcs = ["message_set.proto"],
+    strip_import_prefix = "/src",
+)
\ No newline at end of file
diff --git a/src/google/protobuf/bridge/message_set.proto b/src/google/protobuf/bridge/message_set.proto
new file mode 100644
index 0000000..2f23f9b
--- /dev/null
+++ b/src/google/protobuf/bridge/message_set.proto
@@ -0,0 +1,76 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2007 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)
+//
+// This is proto2's version of MessageSet.  See go/messageset to learn what
+// MessageSets are and how they are used.
+//
+// In proto2, we implement MessageSet in terms of extensions, except with a
+// special wire format for backwards-compatibility.  To define a message that
+// goes in a MessageSet in proto2, you must declare within that message's
+// scope an extension of MessageSet named "message_set_extension" and with
+// the field number matching the type ID.  So, for example, this proto1 code:
+//   message Foo {
+//     enum TypeId { MESSAGE_TYPE_ID = 1234; }
+//   }
+// becomes this proto2 code:
+//   message Foo {
+//     extend google.protobuf.bridge.MessageSet {
+//       optional Foo message_set_extension = 1234;
+//     }
+//   }
+//
+// Now you can use the usual proto2 extensions accessors to access this
+// message.  For example, the proto1 code:
+//   MessageSet mset;
+//   Foo* foo = mset.get_mutable<Foo>();
+// becomes this proto2 code:
+//   google::protobuf::bridge::MessageSet mset;
+//   Foo* foo = mset.MutableExtension(Foo::message_set_extension);
+//
+// Of course, new code that doesn't have backwards-compatibility requirements
+// should just use extensions themselves and not worry about MessageSet.
+
+syntax = "proto2";
+
+package google.protobuf.bridge;
+
+option java_outer_classname = "MessageSetProtos";
+option java_multiple_files = true;
+option cc_enable_arenas = true;
+option objc_class_prefix = "GPB";
+
+// This is proto2's version of MessageSet.
+message MessageSet {
+  option message_set_wire_format = true;
+
+  extensions 4 to max;
+}
diff --git a/src/google/protobuf/compiler/BUILD.bazel b/src/google/protobuf/compiler/BUILD.bazel
new file mode 100644
index 0000000..8cc1186
--- /dev/null
+++ b/src/google/protobuf/compiler/BUILD.bazel
@@ -0,0 +1,378 @@
+################################################################################
+# Protocol Buffers Compiler
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_binary", "cc_library", "cc_test")
+load(
+    "@rules_pkg//:mappings.bzl",
+    "pkg_attributes",
+    "pkg_files",
+    "strip_prefix",
+)
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("//build_defs:arch_tests.bzl", "aarch64_test", "x86_64_test")
+load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS", "PROTOC_LINK_OPTS")
+
+proto_library(
+    name = "plugin_proto",
+    srcs = ["plugin.proto"],
+    visibility = [
+        "//:__pkg__",
+        "//pkg:__pkg__",
+    ],
+    deps = ["//:descriptor_proto"],
+)
+
+cc_library(
+    name = "importer",
+    srcs = [
+        "importer.cc",
+        "parser.cc",
+    ],
+    hdrs = [
+        "importer.h",
+        "parser.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler",
+    visibility = ["//visibility:public"],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "code_generator",
+    srcs = [
+        "code_generator.cc",
+        "plugin.cc",
+        "plugin.pb.cc",
+    ],
+    hdrs = [
+        "code_generator.h",
+        "plugin.h",
+        "plugin.pb.h",
+        "scc.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler",
+    visibility = ["//visibility:public"],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/memory",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "command_line_interface",
+    srcs = [
+        "command_line_interface.cc",
+        "subprocess.cc",
+        "zip_writer.cc",
+    ],
+    hdrs = [
+        "command_line_interface.h",
+        "subprocess.h",
+        "zip_writer.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler",
+    visibility = ["//visibility:public"],
+    deps = [
+        ":code_generator",
+        ":importer",
+        "//src/google/protobuf:protobuf_nowkt",
+        "@com_google_absl//absl/container:btree",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+    ],
+)
+
+cc_library(
+    name = "protoc_lib_nowkt",
+    srcs = [
+        "main.cc",
+    ],
+    copts = COPTS,
+    deps = [
+        ":code_generator",
+        ":command_line_interface",
+        ":importer",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler/cpp",
+        "//src/google/protobuf/compiler/csharp",
+        "//src/google/protobuf/compiler/java",
+        "//src/google/protobuf/compiler/objectivec",
+        "//src/google/protobuf/compiler/php",
+        "//src/google/protobuf/compiler/python",
+        "//src/google/protobuf/compiler/ruby",
+    ],
+)
+
+cc_binary(
+    name = "protoc_nowkt",
+    copts = COPTS,
+    linkopts = LINK_OPTS + PROTOC_LINK_OPTS,
+    visibility = [
+        "//src/google/protobuf:__pkg__",
+    ],
+    deps = [":protoc_lib_nowkt"],
+)
+
+cc_library(
+    name = "protoc_lib",
+    copts = COPTS,
+    visibility = [
+        "//:__pkg__",
+        "//pkg:__pkg__",
+    ],
+    deps = [
+        ":protoc_lib_nowkt",
+        "//:protobuf",
+    ],
+)
+
+# Note: this is an alias for now. In the future, this rule will become the
+# cc_binary for protoc, and //:protoc will become an alias.
+alias(
+    name = "protoc",
+    actual = "//:protoc",
+    visibility = ["//visibility:public"],
+)
+
+# Test that the protoc binary is built for the correct architecture.
+aarch64_test(
+    name = "protoc_aarch64_test",
+    bazel_binaries = ["//:protoc"],
+)
+
+x86_64_test(
+    name = "protoc_x86_64_test",
+    bazel_binaries = ["//:protoc"],
+)
+
+################################################################################
+# Tests and support libraries
+################################################################################
+
+cc_library(
+    name = "annotation_test_util",
+    testonly = 1,
+    srcs = ["annotation_test_util.cc"],
+    hdrs = ["annotation_test_util.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//visibility:public"],
+    deps = [
+        ":code_generator",
+        ":command_line_interface",
+        "//:protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/testing",
+    ],
+)
+
+################################################################################
+# Tests
+################################################################################
+
+filegroup(
+    name = "plugin_proto_srcs",
+    testonly = 1,
+    srcs = [
+        "plugin.pb.cc",
+        "plugin.pb.h",
+        "plugin.proto",
+    ],
+    visibility = [
+        "//src/google/protobuf/compiler/cpp:__pkg__",
+    ],
+)
+
+exports_files(
+    srcs = ["plugin.proto"],
+    visibility = ["//:__pkg__"],
+)
+
+cc_library(
+    name = "mock_code_generator",
+    testonly = 1,
+    srcs = ["mock_code_generator.cc"],
+    hdrs = ["mock_code_generator.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//pkg:__pkg__"],
+    deps = [
+        ":code_generator",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+    ],
+)
+
+cc_binary(
+    name = "test_plugin",
+    testonly = 1,
+    srcs = ["test_plugin.cc"],
+    copts = COPTS,
+    deps = [
+        ":code_generator",
+        ":mock_code_generator",
+    ],
+)
+
+cc_test(
+    name = "command_line_interface_unittest",
+    srcs = ["command_line_interface_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated",
+            "-Wno-deprecated-declarations",
+        ],
+    }) + [
+        # Note: This only works on Windows with symlinks and runfiles enabled.
+        "-DGOOGLE_PROTOBUF_TEST_PLUGIN_PATH=\\\"$(rootpath :test_plugin)\\\"",
+    ],
+    data = [
+        ":test_plugin",
+        "//:test_proto_srcs",
+        "//src/google/protobuf:testdata",
+    ],
+    deps = [
+        ":code_generator",
+        ":command_line_interface",
+        ":mock_code_generator",
+        "//:protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util2",
+        "//src/google/protobuf/compiler/cpp:names",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "importer_unittest",
+    srcs = ["importer_unittest.cc"],
+    copts = COPTS,
+    deps = [
+        ":importer",
+        "//:protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "parser_unittest",
+    srcs = ["parser_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated",
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    deps = [
+        ":importer",
+        "//:protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util2",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Generates protoc release artifacts.
+################################################################################
+
+genrule(
+    name = "protoc_readme",
+    outs = ["readme.txt"],
+    cmd = """
+echo "Protocol Buffers - Google's data interchange format
+Copyright 2008 Google Inc.
+https://developers.google.com/protocol-buffers/
+This package contains a precompiled binary version of the protocol buffer
+compiler (protoc). This binary is intended for users who want to use Protocol
+Buffers in languages other than C++ but do not want to compile protoc
+themselves. To install, simply place this binary somewhere in your PATH.
+If you intend to use the included well known types then don't forget to
+copy the contents of the 'include' directory somewhere as well, for example
+into '/usr/local/include/'.
+Please refer to our official github site for more installation instructions:
+  https://github.com/protocolbuffers/protobuf" > $@
+    """,
+    visibility = ["//:__pkg__"],
+)
+
+pkg_files(
+    name = "compiler_plugin_protos_files",
+    srcs = ["plugin.proto"],
+    prefix = "include/google/protobuf/compiler",
+    visibility = ["//pkg:__pkg__"],
+)
+
+pkg_files(
+    name = "protoc_files",
+    srcs = [":protoc"],
+    attributes = pkg_attributes(mode = "0555"),
+    prefix = "bin/",
+    visibility = ["//:__pkg__"],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]) + [
+        "//src/google/protobuf/compiler/cpp:test_srcs",
+        "//src/google/protobuf/compiler/csharp:test_srcs",
+        "//src/google/protobuf/compiler/java:test_srcs",
+        "//src/google/protobuf/compiler/objectivec:test_srcs",
+        "//src/google/protobuf/compiler/php:test_srcs",
+        "//src/google/protobuf/compiler/python:test_srcs",
+        "//src/google/protobuf/compiler/ruby:test_srcs",
+    ],
+    visibility = ["//pkg:__pkg__"],
+)
+
+filegroup(
+    name = "test_plugin_srcs",
+    srcs = ["test_plugin.cc"],
+    visibility = ["//pkg:__pkg__"],
+)
+
+filegroup(
+    name = "test_proto_srcs",
+    srcs = [
+        "//src/google/protobuf/compiler/cpp:test_proto_srcs",
+    ],
+    visibility = ["//pkg:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/annotation_test_util.cc b/src/google/protobuf/compiler/annotation_test_util.cc
index f0815c5..f8ffeec 100644
--- a/src/google/protobuf/compiler/annotation_test_util.cc
+++ b/src/google/protobuf/compiler/annotation_test_util.cc
@@ -28,21 +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.
 
-#include <google/protobuf/compiler/annotation_test_util.h>
+#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/googletest.h>
+#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/descriptor.pb.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.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"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/annotation_test_util.h b/src/google/protobuf/compiler/annotation_test_util.h
index b7c6ddd..b8356c2 100644
--- a/src/google/protobuf/compiler/annotation_test_util.h
+++ b/src/google/protobuf/compiler/annotation_test_util.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
 #define GOOGLE_PROTOBUF_COMPILER_ANNOTATION_TEST_UTIL_H__
 
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
 
 // Utilities that assist in writing tests for generator annotations.
diff --git a/src/google/protobuf/compiler/code_generator.cc b/src/google/protobuf/compiler/code_generator.cc
index dc9d450..3f48e37 100644
--- a/src/google/protobuf/compiler/code_generator.cc
+++ b/src/google/protobuf/compiler/code_generator.cc
@@ -32,13 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/code_generator.h>
+#include "google/protobuf/compiler/code_generator.h"
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/plugin.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/compiler/plugin.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/strip.h"
 
 namespace google {
 namespace protobuf {
@@ -107,7 +108,7 @@
 void ParseGeneratorParameter(
     const std::string& text,
     std::vector<std::pair<std::string, std::string> >* output) {
-  std::vector<std::string> parts = Split(text, ",", true);
+  std::vector<std::string> parts = absl::StrSplit(text, ",", absl::SkipEmpty());
 
   for (int i = 0; i < parts.size(); i++) {
     std::string::size_type equals_pos = parts[i].find_first_of('=');
@@ -125,10 +126,10 @@
 
 // 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");
+  if (absl::EndsWith(filename, ".protodevel")) {
+    return std::string(absl::StripSuffix(filename, ".protodevel"));
   } else {
-    return StripSuffixString(filename, ".proto");
+    return std::string(absl::StripSuffix(filename, ".proto"));
   }
 }
 
diff --git a/src/google/protobuf/compiler/code_generator.h b/src/google/protobuf/compiler/code_generator.h
index 9c0b115..55b510a 100644
--- a/src/google/protobuf/compiler/code_generator.h
+++ b/src/google/protobuf/compiler/code_generator.h
@@ -41,10 +41,11 @@
 #include <string>
 #include <utility>
 #include <vector>
-#include <google/protobuf/stubs/common.h>
+
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -69,7 +70,9 @@
 // be registered with CommandLineInterface to support various languages.
 class PROTOC_EXPORT CodeGenerator {
  public:
-  inline CodeGenerator() {}
+  CodeGenerator() {}
+  CodeGenerator(const CodeGenerator&) = delete;
+  CodeGenerator& operator=(const CodeGenerator&) = delete;
   virtual ~CodeGenerator();
 
   // Generates code for the given proto file, generating one or more files in
@@ -120,9 +123,6 @@
   // version of the library. When protobufs does a api breaking change, the
   // method can be removed.
   virtual bool HasGenerateAll() const { return true; }
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodeGenerator);
 };
 
 // CodeGenerators generate one or more files in a given directory.  This
@@ -131,8 +131,10 @@
 // runs.
 class PROTOC_EXPORT GeneratorContext {
  public:
-  inline GeneratorContext() {
+  GeneratorContext() {
   }
+  GeneratorContext(const GeneratorContext&) = delete;
+  GeneratorContext& operator=(const GeneratorContext&) = delete;
   virtual ~GeneratorContext();
 
   // Opens the given file, truncating it if it exists, and returns a
@@ -177,9 +179,6 @@
   // this GeneratorContext.
   virtual void GetCompilerVersion(Version* version) const;
 
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorContext);
 };
 
 // The type GeneratorContext was once called OutputDirectory. This typedef
@@ -202,6 +201,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CODE_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/command_line_interface.cc b/src/google/protobuf/compiler/command_line_interface.cc
index 5e9a2c4..6a44b04 100644
--- a/src/google/protobuf/compiler/command_line_interface.cc
+++ b/src/google/protobuf/compiler/command_line_interface.cc
@@ -32,11 +32,15 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/command_line_interface.h>
+#include "google/protobuf/compiler/command_line_interface.h"
 
-#include <google/protobuf/stubs/platform_macros.h>
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
+
+#include "google/protobuf/stubs/platform_macros.h"
 
 #include <stdio.h>
+#include <stdlib.h>
 #include <sys/types.h>
 #ifdef major
 #undef major
@@ -58,6 +62,9 @@
 #include <limits.h>  // For PATH_MAX
 
 #include <memory>
+#include <string>
+#include <utility>
+#include <vector>
 
 #if defined(__APPLE__)
 #include <mach-o/dyld.h>
@@ -65,29 +72,31 @@
 #include <sys/sysctl.h>
 #endif
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/compiler/subprocess.h>
-#include <google/protobuf/compiler/plugin.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/compiler/zip_writer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/compiler/subprocess.h"
+#include "google/protobuf/compiler/plugin.pb.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/importer.h"
+#include "google/protobuf/compiler/zip_writer.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/text_format.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -174,7 +183,7 @@
   // Recursively create parent directories to the output file.
   // On Windows, both '/' and '\' are valid path separators.
   std::vector<std::string> parts =
-      Split(filename, "/\\", true);
+      absl::StrSplit(filename, absl::ByAnyChar("/\\"), absl::SkipEmpty());
   std::string path_so_far = prefix;
   for (int i = 0; i < parts.size() - 1; i++) {
     path_so_far += parts[i];
@@ -339,9 +348,12 @@
   void AddErrorOrWarning(const std::string& filename, int line, int column,
                          const std::string& message, const std::string& type,
                          std::ostream& out) {
-    // Print full path when running under MSVS
     std::string dfile;
-    if (format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
+    if (
+#ifndef PROTOBUF_OPENSOURCE
+        // Print full path when running under MSVS
+        format_ == CommandLineInterface::ERROR_FORMAT_MSVS &&
+#endif  // !PROTOBUF_OPENSOURCE
         tree_ != nullptr && tree_->VirtualFileToDiskFile(filename, &dfile)) {
       out << dfile;
     } else {
@@ -398,7 +410,6 @@
 
   // Get name of all output files.
   void GetOutputFilenames(std::vector<std::string>* output_filenames);
-
   // implements GeneratorContext --------------------------------------
   io::ZeroCopyOutputStream* Open(const std::string& filename) override;
   io::ZeroCopyOutputStream* OpenForAppend(const std::string& filename) override;
@@ -417,7 +428,7 @@
   // 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_;
+  absl::btree_map<std::string, std::string> files_;
   const std::vector<const FileDescriptor*>& parsed_files_;
   bool had_error_;
 };
@@ -795,96 +806,95 @@
     }
 
     it->second.swap(data_);
+    return;
+  }
+  // This was an OpenForInsert().
+
+  // If the data doesn't end with a clean line break, add one.
+  if (!data_.empty() && data_[data_.size() - 1] != '\n') {
+    data_.push_back('\n');
+  }
+
+  // Find the file we are going to insert into.
+  if (!already_present) {
+    std::cerr << filename_ << ": Tried to insert into file that doesn't exist."
+              << std::endl;
+    directory_->had_error_ = true;
+    return;
+  }
+  std::string* target = &it->second;
+
+  // Find the insertion point.
+  std::string magic_string =
+      absl::Substitute("@@protoc_insertion_point($0)", insertion_point_);
+  std::string::size_type pos = target->find(magic_string);
+
+  if (pos == std::string::npos) {
+    std::cerr << filename_ << ": insertion point \"" << insertion_point_
+              << "\" not found." << std::endl;
+    directory_->had_error_ = true;
+    return;
+  }
+
+  if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) {
+    // Support for inline "/* @@protoc_insertion_point() */"
+    pos = pos - 3;
   } else {
-    // This was an OpenForInsert().
-
-    // If the data doesn't end with a clean line break, add one.
-    if (!data_.empty() && data_[data_.size() - 1] != '\n') {
-      data_.push_back('\n');
-    }
-
-    // Find the file we are going to insert into.
-    if (!already_present) {
-      std::cerr << filename_
-                << ": Tried to insert into file that doesn't exist."
-                << std::endl;
-      directory_->had_error_ = true;
-      return;
-    }
-    std::string* target = &it->second;
-
-    // Find the insertion point.
-    std::string magic_string =
-        strings::Substitute("@@protoc_insertion_point($0)", insertion_point_);
-    std::string::size_type pos = target->find(magic_string);
-
+    // Seek backwards to the beginning of the line, which is where we will
+    // insert the data.  Note that this has the effect of pushing the
+    // insertion point down, so the data is inserted before it.  This is
+    // intentional because it means that multiple insertions at the same point
+    // will end up in the expected order in the final output.
+    pos = target->find_last_of('\n', pos);
     if (pos == std::string::npos) {
-      std::cerr << filename_ << ": insertion point \"" << insertion_point_
-                << "\" not found." << std::endl;
-      directory_->had_error_ = true;
-      return;
-    }
-
-    if ((pos > 3) && (target->substr(pos - 3, 2) == "/*")) {
-      // Support for inline "/* @@protoc_insertion_point() */"
-      pos = pos - 3;
+      // Insertion point is on the first line.
+      pos = 0;
     } else {
-      // Seek backwards to the beginning of the line, which is where we will
-      // insert the data.  Note that this has the effect of pushing the
-      // insertion point down, so the data is inserted before it.  This is
-      // intentional because it means that multiple insertions at the same point
-      // will end up in the expected order in the final output.
-      pos = target->find_last_of('\n', pos);
-      if (pos == std::string::npos) {
-        // Insertion point is on the first line.
-        pos = 0;
-      } else {
-        // Advance to character after '\n'.
-        ++pos;
-      }
-    }
-
-    // Extract indent.
-    std::string indent_(*target, pos,
-                        target->find_first_not_of(" \t", pos) - pos);
-
-    if (indent_.empty()) {
-      // No indent.  This makes things easier.
-      target->insert(pos, data_);
-      UpdateMetadata(data_, pos, data_.size(), 0);
-    } else {
-      // Calculate how much space we need.
-      int indent_size = 0;
-      for (int i = 0; i < data_.size(); i++) {
-        if (data_[i] == '\n') indent_size += indent_.size();
-      }
-
-      // Make a hole for it.
-      target->insert(pos, data_.size() + indent_size, '\0');
-
-      // Now copy in the data.
-      std::string::size_type data_pos = 0;
-      char* target_ptr = ::google::protobuf::string_as_array(target) + pos;
-      while (data_pos < data_.size()) {
-        // Copy indent.
-        memcpy(target_ptr, indent_.data(), indent_.size());
-        target_ptr += indent_.size();
-
-        // Copy line from data_.
-        // We already guaranteed that data_ ends with a newline (above), so this
-        // search can't fail.
-        std::string::size_type line_length =
-            data_.find_first_of('\n', data_pos) + 1 - data_pos;
-        memcpy(target_ptr, data_.data() + data_pos, line_length);
-        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);
+      // Advance to character after '\n'.
+      ++pos;
     }
   }
+
+  // Extract indent.
+  std::string indent_(*target, pos,
+                      target->find_first_not_of(" \t", pos) - pos);
+
+  if (indent_.empty()) {
+    // No indent.  This makes things easier.
+    target->insert(pos, data_);
+    UpdateMetadata(data_, pos, data_.size(), 0);
+    return;
+  }
+  // Calculate how much space we need.
+  int indent_size = 0;
+  for (int i = 0; i < data_.size(); i++) {
+    if (data_[i] == '\n') indent_size += indent_.size();
+  }
+
+  // Make a hole for it.
+  target->insert(pos, data_.size() + indent_size, '\0');
+
+  // Now copy in the data.
+  std::string::size_type data_pos = 0;
+  char* target_ptr = &(*target)[pos];
+  while (data_pos < data_.size()) {
+    // Copy indent.
+    memcpy(target_ptr, indent_.data(), indent_.size());
+    target_ptr += indent_.size();
+
+    // Copy line from data_.
+    // We already guaranteed that data_ ends with a newline (above), so this
+    // search can't fail.
+    std::string::size_type line_length =
+        data_.find_first_of('\n', data_pos) + 1 - data_pos;
+    memcpy(target_ptr, data_.data() + data_pos, line_length);
+    target_ptr += line_length;
+    data_pos += line_length;
+  }
+
+  GOOGLE_CHECK_EQ(target_ptr, &(*target)[pos] + data_.size() + indent_size);
+
+  UpdateMetadata(data_, pos, data_.size() + indent_size, indent_.size());
 }
 
 // ===================================================================
@@ -963,6 +973,7 @@
 
 int CommandLineInterface::Run(int argc, const char* const argv[]) {
   Clear();
+
   switch (ParseArguments(argc, argv)) {
     case PARSE_ARGUMENT_DONE_AND_EXIT:
       return 0;
@@ -1056,9 +1067,9 @@
   if (mode_ == MODE_COMPILE) {
     for (int i = 0; i < output_directives_.size(); i++) {
       std::string output_location = output_directives_[i].output_location;
-      if (!HasSuffixString(output_location, ".zip") &&
-          !HasSuffixString(output_location, ".jar") &&
-          !HasSuffixString(output_location, ".srcjar")) {
+      if (!absl::EndsWith(output_location, ".zip") &&
+          !absl::EndsWith(output_location, ".jar") &&
+          !absl::EndsWith(output_location, ".srcjar")) {
         AddTrailingSlash(&output_location);
       }
 
@@ -1066,7 +1077,7 @@
 
       if (!generator) {
         // First time we've seen this output location.
-        generator.reset(new GeneratorContextImpl(parsed_files));
+        generator = std::make_unique<GeneratorContextImpl>(parsed_files);
       }
 
       if (!GenerateOutput(parsed_files, output_directives_[i],
@@ -1076,16 +1087,15 @@
     }
   }
 
-  // Write all output to disk.
   for (const auto& pair : output_directories) {
     const std::string& location = pair.first;
     GeneratorContextImpl* directory = pair.second.get();
-    if (HasSuffixString(location, "/")) {
+    if (absl::EndsWith(location, "/")) {
       if (!directory->WriteAllToDisk(location)) {
         return 1;
       }
     } else {
-      if (HasSuffixString(location, ".jar")) {
+      if (absl::EndsWith(location, ".jar")) {
         directory->AddJarManifest();
       }
 
@@ -1151,7 +1161,6 @@
         // Do not add a default case.
     }
   }
-
   return 0;
 }
 
@@ -1276,6 +1285,7 @@
     }
     parsed_files->push_back(parsed_file);
 
+
     // Enforce --disallow_services.
     if (disallow_services_ && parsed_file->service_count() > 0) {
       std::cerr << parsed_file->name()
@@ -1295,9 +1305,9 @@
             direct_dependencies_.end()) {
           indirect_imports = true;
           std::cerr << parsed_file->name() << ": "
-                    << StringReplace(direct_dependencies_violation_msg_, "%s",
-                                     parsed_file->dependency(i)->name(),
-                                     true /* replace_all */)
+                    << absl::StrReplaceAll(
+                           direct_dependencies_violation_msg_,
+                           {{"%s", parsed_file->dependency(i)->name()}})
                     << std::endl;
         }
       }
@@ -1486,19 +1496,15 @@
 
   // Make sure each plugin option has a matching plugin output.
   bool foundUnknownPluginOption = false;
-  for (std::map<std::string, std::string>::const_iterator i =
-           plugin_parameters_.begin();
-       i != plugin_parameters_.end(); ++i) {
-    if (plugins_.find(i->first) != plugins_.end()) {
+  for (const auto& kv : plugin_parameters_) {
+    if (plugins_.find(kv.first) != plugins_.end()) {
       continue;
     }
     bool foundImplicitPlugin = false;
-    for (std::vector<OutputDirective>::const_iterator j =
-             output_directives_.begin();
-         j != output_directives_.end(); ++j) {
-      if (j->generator == nullptr) {
-        std::string plugin_name = PluginName(plugin_prefix_, j->name);
-        if (plugin_name == i->first) {
+    for (const auto& d : output_directives_) {
+      if (d.generator == nullptr) {
+        std::string plugin_name = PluginName(plugin_prefix_, d.name);
+        if (plugin_name == kv.first) {
           foundImplicitPlugin = true;
           break;
         }
@@ -1507,7 +1513,7 @@
     if (!foundImplicitPlugin) {
       std::cerr << "Unknown flag: "
                 // strip prefix + "gen-" and add back "_opt"
-                << "--" + i->first.substr(plugin_prefix_.size() + 4) + "_opt"
+                << "--" + kv.first.substr(plugin_prefix_.size() + 4) + "_opt"
                 << std::endl;
       foundUnknownPluginOption = true;
     }
@@ -1679,8 +1685,7 @@
         })) {
       case google::protobuf::io::win32::ExpandWildcardsResult::kSuccess:
         break;
-      case google::protobuf::io::win32::ExpandWildcardsResult::
-          kErrorNoMatchingFile:
+      case google::protobuf::io::win32::ExpandWildcardsResult::kErrorNoMatchingFile:
         // Path does not exist, is not a file, or it's longer than MAX_PATH and
         // long path handling is disabled.
         std::cerr << "Invalid file name pattern or missing input file \""
@@ -1701,9 +1706,9 @@
     // Java's -classpath (and some other languages) delimits path components
     // with colons.  Let's accept that syntax too just to make things more
     // intuitive.
-    std::vector<std::string> parts = Split(
-        value, CommandLineInterface::kPathSeparator,
-        true);
+    std::vector<std::string> parts = absl::StrSplit(
+        value, absl::ByAnyChar(CommandLineInterface::kPathSeparator),
+        absl::SkipEmpty());
 
     for (int i = 0; i < parts.size(); i++) {
       std::string virtual_path;
@@ -1757,7 +1762,7 @@
 
     direct_dependencies_explicitly_set_ = true;
     std::vector<std::string> direct =
-        Split(value, ":", true);
+        absl::StrSplit(value, ":", absl::SkipEmpty());
     GOOGLE_DCHECK(direct_dependencies_.empty());
     direct_dependencies_.insert(direct.begin(), direct.end());
 
@@ -1783,9 +1788,9 @@
       return PARSE_ARGUMENT_FAIL;
     }
 
-    descriptor_set_in_names_ = Split(
-        value, CommandLineInterface::kPathSeparator,
-        true);
+    descriptor_set_in_names_ = absl::StrSplit(
+        value, absl::ByAnyChar(CommandLineInterface::kPathSeparator),
+        absl::SkipEmpty());
 
   } else if (name == "-o" || name == "--descriptor_set_out") {
     if (!descriptor_set_out_name_.empty()) {
@@ -1843,7 +1848,7 @@
     if (!version_info_.empty()) {
       std::cout << version_info_ << std::endl;
     }
-    std::cout << "libprotoc " << internal::VersionString(PROTOBUF_VERSION)
+    std::cout << "libprotoc " << internal::ProtocVersionString(PROTOBUF_VERSION)
               << PROTOBUF_VERSION_SUFFIX << std::endl;
     return PARSE_ARGUMENT_DONE_AND_EXIT;  // Exit without running compiler.
 
@@ -1943,14 +1948,30 @@
     }
     mode_ = MODE_PRINT;
     print_mode_ = PRINT_FREE_FIELDS;
+  } else if (name == "--enable_codegen_trace") {
+    // We use environment variables here so that subprocesses see this setting
+    // when we spawn them.
+    //
+    // Setting environment variables is more-or-less asking for a data race,
+    // because C got this wrong and did not mandate synchronization.
+    // In practice, this code path is "only" in the main thread of protoc, and
+    // it is common knowledge that touching setenv in a library is asking for
+    // life-ruining bugs *anyways*. As such, there is a reasonable probability
+    // that there isn't another thread kicking environment variables at this
+    // moment.
+
+#ifdef _WIN32
+    ::_putenv(absl::StrCat(io::Printer::kProtocCodegenTrace, "=yes").c_str());
+#else
+    ::setenv(io::Printer::kProtocCodegenTrace.data(), "yes", 0);
+#endif
   } else {
     // Some other flag.  Look it up in the generators list.
-    const GeneratorInfo* generator_info =
-        FindOrNull(generators_by_flag_name_, name);
+    const GeneratorInfo* generator_info = FindGeneratorByFlag(name);
     if (generator_info == nullptr &&
-        (plugin_prefix_.empty() || !HasSuffixString(name, "_out"))) {
+        (plugin_prefix_.empty() || !absl::EndsWith(name, "_out"))) {
       // Check if it's a generator option flag.
-      generator_info = FindOrNull(generators_by_option_name_, name);
+      generator_info = FindGeneratorByOption(name);
       if (generator_info != nullptr) {
         std::string* parameters =
             &generator_parameters_[generator_info->flag_name];
@@ -1958,7 +1979,7 @@
           parameters->append(",");
         }
         parameters->append(value);
-      } else if (HasPrefixString(name, "--") && HasSuffixString(name, "_opt")) {
+      } else if (absl::StartsWith(name, "--") && absl::EndsWith(name, "_opt")) {
         std::string* parameters =
             &plugin_parameters_[PluginName(plugin_prefix_, name)];
         if (!parameters->empty()) {
@@ -2069,7 +2090,10 @@
                               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.)";
+                              occupied fields numbers.
+  --enable_codegen_trace      Enables tracing which parts of protoc are
+                              responsible for what codegen output. Not supported
+                              by all backends or on all platforms.)";
   if (!plugin_prefix_.empty()) {
     std::cout << R"(
   --plugin=EXECUTABLE         Specifies a plugin executable to use.
@@ -2082,16 +2106,15 @@
                               the executable's own name differs.)";
   }
 
-  for (GeneratorMap::iterator iter = generators_by_flag_name_.begin();
-       iter != generators_by_flag_name_.end(); ++iter) {
+  for (const auto& kv : generators_by_flag_name_) {
     // 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 << std::endl
-              << "  " << iter->first << "=OUT_DIR "
-              << std::string(19 - iter->first.size(),
+              << "  " << kv.first << "=OUT_DIR "
+              << std::string(19 - kv.first.size(),
                              ' ')  // Spaces for alignment.
-              << iter->second.help_text;
+              << kv.second.help_text;
   }
   std::cout << R"(
   @<filename>                 Read options and filenames from file. If a
@@ -2123,7 +2146,8 @@
                   << codegen_name
                   << " hasn't been updated to support optional fields in "
                      "proto3. Please ask the owner of this code generator to "
-                     "support proto3 optional.";
+                     "support proto3 optional."
+                  << std::endl;
         return false;
       }
     }
@@ -2139,8 +2163,8 @@
   std::string error;
   if (output_directive.generator == nullptr) {
     // This is a plugin.
-    GOOGLE_CHECK(HasPrefixString(output_directive.name, "--") &&
-          HasSuffixString(output_directive.name, "_out"))
+    GOOGLE_CHECK(absl::StartsWith(output_directive.name, "--") &&
+          absl::EndsWith(output_directive.name, "_out"))
         << "Bad name for plugin generator: " << output_directive.name;
 
     std::string plugin_name = PluginName(plugin_prefix_, output_directive.name);
@@ -2188,7 +2212,7 @@
     DiskSourceTree* source_tree) {
   FileDescriptorSet file_set;
 
-  std::set<const FileDescriptor*> already_seen;
+  absl::flat_hash_set<const FileDescriptor*> already_seen;
   for (int i = 0; i < parsed_files.size(); i++) {
     GetTransitiveDependencies(parsed_files[i], false, false, &already_seen,
                               file_set.mutable_file());
@@ -2228,7 +2252,7 @@
   io::Printer printer(&out, '$');
 
   for (int i = 0; i < output_filenames.size(); i++) {
-    printer.Print(output_filenames[i].c_str());
+    printer.Print(output_filenames[i]);
     if (i == output_filenames.size() - 1) {
       printer.Print(":");
     } else {
@@ -2269,7 +2293,7 @@
   }
 
 
-  std::set<const FileDescriptor*> already_seen;
+  absl::flat_hash_set<const FileDescriptor*> already_seen;
   for (int i = 0; i < parsed_files.size(); i++) {
     request.add_file_to_generate(parsed_files[i]->name());
     GetTransitiveDependencies(parsed_files[i],
@@ -2296,7 +2320,7 @@
 
   std::string communicate_error;
   if (!subprocess.Communicate(request, &response, &communicate_error)) {
-    *error = strings::Substitute("$0: $1", plugin_name, communicate_error);
+    *error = absl::Substitute("$0: $1", plugin_name, communicate_error);
     return false;
   }
 
@@ -2323,7 +2347,7 @@
       current_output.reset();
       current_output.reset(generator_context->Open(output_file.name()));
     } else if (current_output == nullptr) {
-      *error = strings::Substitute(
+      *error = absl::Substitute(
           "$0: First file chunk returned by plugin did not specify a file "
           "name.",
           plugin_name);
@@ -2418,13 +2442,13 @@
     const std::vector<const FileDescriptor*>& parsed_files) {
   FileDescriptorSet file_set;
 
-  std::set<const FileDescriptor*> already_seen;
+  absl::flat_hash_set<const FileDescriptor*> already_seen;
   if (!imports_in_descriptor_set_) {
     // Since we don't want to output transitive dependencies, but we do want
     // things to be in dependency order, add all dependencies that aren't in
     // parsed_files to already_seen.  This will short circuit the recursion
     // in GetTransitiveDependencies.
-    std::set<const FileDescriptor*> to_output;
+    absl::flat_hash_set<const FileDescriptor*> to_output;
     to_output.insert(parsed_files.begin(), parsed_files.end());
     for (int i = 0; i < parsed_files.size(); i++) {
       const FileDescriptor* file = parsed_files[i];
@@ -2482,7 +2506,7 @@
 void CommandLineInterface::GetTransitiveDependencies(
     const FileDescriptor* file, bool include_json_name,
     bool include_source_code_info,
-    std::set<const FileDescriptor*>* already_seen,
+    absl::flat_hash_set<const FileDescriptor*>* already_seen,
     RepeatedPtrField<FileDescriptorProto>* output) {
   if (!already_seen->insert(file).second) {
     // Already saw this file.  Skip.
@@ -2506,6 +2530,20 @@
   }
 }
 
+const CommandLineInterface::GeneratorInfo*
+CommandLineInterface::FindGeneratorByFlag(const std::string& name) const {
+  auto it = generators_by_flag_name_.find(name);
+  if (it == generators_by_flag_name_.end()) return nullptr;
+  return &it->second;
+}
+
+const CommandLineInterface::GeneratorInfo*
+CommandLineInterface::FindGeneratorByOption(const std::string& option) const {
+  auto it = generators_by_option_name_.find(option);
+  if (it == generators_by_option_name_.end()) return nullptr;
+  return &it->second;
+}
+
 namespace {
 
 // Utility function for PrintFreeFieldNumbers.
@@ -2541,9 +2579,9 @@
 // order of the nested messages is also preserved.
 typedef std::pair<int, int> FieldRange;
 void GatherOccupiedFieldRanges(
-    const Descriptor* descriptor, std::set<FieldRange>* ranges,
+    const Descriptor* descriptor, absl::btree_set<FieldRange>* ranges,
     std::vector<const Descriptor*>* nested_messages) {
-  std::set<const Descriptor*> groups;
+  absl::flat_hash_set<const Descriptor*> groups;
   for (int i = 0; i < descriptor->field_count(); ++i) {
     const FieldDescriptor* fd = descriptor->field(i);
     ranges->insert(FieldRange(fd->number(), fd->number() + 1));
@@ -2575,30 +2613,29 @@
 // Actually prints the formatted free field numbers for given message name and
 // occupied ranges.
 void FormatFreeFieldNumbers(const std::string& name,
-                            const std::set<FieldRange>& ranges) {
+                            const absl::btree_set<FieldRange>& ranges) {
   std::string output;
-  StringAppendF(&output, "%-35s free:", name.c_str());
+  absl::StrAppendFormat(&output, "%-35s free:", name.c_str());
   int next_free_number = 1;
-  for (std::set<FieldRange>::const_iterator i = ranges.begin();
-       i != ranges.end(); ++i) {
+  for (const auto& range : ranges) {
     // This happens when groups re-use parent field numbers, in which
     // case we skip the FieldRange entirely.
-    if (next_free_number >= i->second) continue;
+    if (next_free_number >= range.second) continue;
 
-    if (next_free_number < i->first) {
-      if (next_free_number + 1 == i->first) {
+    if (next_free_number < range.first) {
+      if (next_free_number + 1 == range.first) {
         // Singleton
-        StringAppendF(&output, " %d", next_free_number);
+        absl::StrAppendFormat(&output, " %d", next_free_number);
       } else {
         // Range
-        StringAppendF(&output, " %d-%d", next_free_number,
-                              i->first - 1);
+        absl::StrAppendFormat(&output, " %d-%d", next_free_number,
+                              range.first - 1);
       }
     }
-    next_free_number = i->second;
+    next_free_number = range.second;
   }
   if (next_free_number <= FieldDescriptor::kMaxNumber) {
-    StringAppendF(&output, " %d-INF", next_free_number);
+    absl::StrAppendFormat(&output, " %d-INF", next_free_number);
   }
   std::cout << output << std::endl;
 }
@@ -2606,7 +2643,7 @@
 }  // namespace
 
 void CommandLineInterface::PrintFreeFieldNumbers(const Descriptor* descriptor) {
-  std::set<FieldRange> ranges;
+  absl::btree_set<FieldRange> ranges;
   std::vector<const Descriptor*> nested_messages;
   GatherOccupiedFieldRanges(descriptor, &ranges, &nested_messages);
 
diff --git a/src/google/protobuf/compiler/command_line_interface.h b/src/google/protobuf/compiler/command_line_interface.h
index e842550..4abe0d6 100644
--- a/src/google/protobuf/compiler/command_line_interface.h
+++ b/src/google/protobuf/compiler/command_line_interface.h
@@ -39,19 +39,20 @@
 #define GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
 
 #include <cstdint>
-#include <map>
+#include <functional>
 #include <memory>
-#include <set>
 #include <string>
-#include <unordered_map>
-#include <unordered_set>
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
+#include "absl/container/btree_map.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -115,6 +116,8 @@
   static const char* const kPathSeparator;
 
   CommandLineInterface();
+  CommandLineInterface(const CommandLineInterface&) = delete;
+  CommandLineInterface& operator=(const CommandLineInterface&) = delete;
   ~CommandLineInterface();
 
   // Register a code generator for a language.
@@ -212,8 +215,8 @@
   class ErrorPrinter;
   class GeneratorContextImpl;
   class MemoryOutputStream;
-  typedef std::unordered_map<std::string, std::unique_ptr<GeneratorContextImpl>>
-      GeneratorContextMap;
+  using GeneratorContextMap =
+      absl::flat_hash_map<std::string, std::unique_ptr<GeneratorContextImpl>>;
 
   // Clear state from previous Run().
   void Clear();
@@ -318,7 +321,7 @@
   static void GetTransitiveDependencies(
       const FileDescriptor* file, bool include_json_name,
       bool include_source_code_info,
-      std::set<const FileDescriptor*>* already_seen,
+      absl::flat_hash_set<const FileDescriptor*>* already_seen,
       RepeatedPtrField<FileDescriptorProto>* output);
 
   // Implements the --print_free_field_numbers. This function prints free field
@@ -352,16 +355,19 @@
     CodeGenerator* generator;
     std::string help_text;
   };
-  typedef std::map<std::string, GeneratorInfo> GeneratorMap;
-  GeneratorMap generators_by_flag_name_;
-  GeneratorMap generators_by_option_name_;
+
+  const GeneratorInfo* FindGeneratorByFlag(const std::string& name) const;
+  const GeneratorInfo* FindGeneratorByOption(const std::string& option) const;
+
+  absl::btree_map<std::string, GeneratorInfo> generators_by_flag_name_;
+  absl::flat_hash_map<std::string, GeneratorInfo> generators_by_option_name_;
   // A map from generator names to the parameters specified using the option
   // flag. For example, if the user invokes the compiler with:
   //   protoc --foo_out=outputdir --foo_opt=enable_bar ...
   // Then there will be an entry ("--foo_out", "enable_bar") in this map.
-  std::map<std::string, std::string> generator_parameters_;
+  absl::flat_hash_map<std::string, std::string> generator_parameters_;
   // Similar to generator_parameters_, but stores the parameters for plugins.
-  std::map<std::string, std::string> plugin_parameters_;
+  absl::flat_hash_map<std::string, std::string> plugin_parameters_;
 
   // See AllowPlugins().  If this is empty, plugins aren't allowed.
   std::string plugin_prefix_;
@@ -369,7 +375,7 @@
   // Maps specific plugin names to files.  When executing a plugin, this map
   // is searched first to find the plugin executable.  If not found here, the
   // PATH (or other OS-specific search strategy) is searched.
-  std::map<std::string, std::string> plugins_;
+  absl::flat_hash_map<std::string, std::string> plugins_;
 
   // Stuff parsed from command line.
   enum Mode {
@@ -398,13 +404,13 @@
   // True if we should treat warnings as errors that fail the compilation.
   bool fatal_warnings_ = false;
 
-  std::vector<std::pair<std::string, std::string> >
+  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.
 
   // Names of proto files which are allowed to be imported. Used by build
   // systems to enforce depend-on-what-you-import.
-  std::set<std::string> direct_dependencies_;
+  absl::flat_hash_set<std::string> direct_dependencies_;
   bool direct_dependencies_explicitly_set_ = false;
 
   // If there's a violation of depend-on-what-you-import, this string will be
@@ -451,14 +457,12 @@
 
   // When using --encode, this will be passed to SetSerializationDeterministic.
   bool deterministic_output_ = false;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CommandLineInterface);
 };
 
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_COMMAND_LINE_INTERFACE_H__
diff --git a/src/google/protobuf/compiler/command_line_interface_unittest.cc b/src/google/protobuf/compiler/command_line_interface_unittest.cc
index f48135e..b595cf1 100644
--- a/src/google/protobuf/compiler/command_line_interface_unittest.cc
+++ b/src/google/protobuf/compiler/command_line_interface_unittest.cc
@@ -38,6 +38,8 @@
 
 #include <cstdint>
 
+#include "absl/strings/str_format.h"
+
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
@@ -45,31 +47,32 @@
 #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/test_util2.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_custom_options.pb.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/testing/googletest.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/descriptor.pb.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/compiler/code_generator.h>
-#include <google/protobuf/compiler/command_line_interface.h>
-#include <google/protobuf/compiler/mock_code_generator.h>
-#include <google/protobuf/compiler/subprocess.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-
+#include "absl/status/status.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/command_line_interface.h"
+#include "google/protobuf/compiler/cpp/names.h"
+#include "google/protobuf/compiler/mock_code_generator.h"
+#include "google/protobuf/compiler/subprocess.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/test_util2.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_custom_options.pb.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -319,7 +322,7 @@
 }
 
 void CommandLineInterfaceTest::Run(const std::string& command) {
-  RunWithArgs(Split(command, " ", true));
+  RunWithArgs(absl::StrSplit(command, " ", absl::SkipEmpty()));
 }
 
 void CommandLineInterfaceTest::RunWithArgs(std::vector<std::string> args) {
@@ -349,7 +352,7 @@
         "test_plugin.exe",        // Other Win32 (MSVC)
         "test_plugin",            // Unix
     };
-    for (int i = 0; i < GOOGLE_ARRAYSIZE(possible_paths); i++) {
+    for (int i = 0; i < ABSL_ARRAYSIZE(possible_paths); i++) {
       if (access(possible_paths[i], F_OK) == 0) {
         plugin_path = possible_paths[i];
         break;
@@ -357,9 +360,10 @@
     }
 #endif
 
-    if (plugin_path.empty()) {
+    if (plugin_path.empty() || !FileExists(plugin_path)) {
       GOOGLE_LOG(ERROR)
-          << "Plugin executable not found.  Plugin tests are likely to fail.";
+          << "Plugin executable not found.  Plugin tests are likely to fail."
+          << plugin_path;
     } else {
       args.push_back("--plugin=prefix-gen-plug=" + plugin_path);
     }
@@ -367,8 +371,8 @@
 
   std::unique_ptr<const char*[]> argv(new const char*[args.size()]);
 
-  for (int i = 0; i < args.size(); i++) {
-    args[i] = StringReplace(args[i], "$tmpdir", temp_directory_, true);
+  for (size_t i = 0; i < args.size(); i++) {
+    args[i] = absl::StrReplaceAll(args[i], {{"$tmpdir", temp_directory_}});
     argv[i] = args[i].c_str();
   }
 
@@ -405,7 +409,7 @@
   // Write file.
   std::string full_name = temp_directory_ + "/" + name;
   GOOGLE_CHECK_OK(File::SetContents(
-      full_name, StringReplace(contents, "$tmpdir", temp_directory_, true),
+      full_name, absl::StrReplaceAll(contents, {{"$tmpdir", temp_directory_}}),
       true));
 }
 
@@ -424,7 +428,7 @@
 void CommandLineInterfaceTest::ExpectErrorText(
     const std::string& expected_text) {
   EXPECT_NE(0, return_code_);
-  EXPECT_EQ(StringReplace(expected_text, "$tmpdir", temp_directory_, true),
+  EXPECT_EQ(absl::StrReplaceAll(expected_text, {{"$tmpdir", temp_directory_}}),
             error_text_);
 }
 
@@ -537,7 +541,7 @@
   std::string file_contents;
   GOOGLE_CHECK_OK(File::GetContents(path, &file_contents, true));
 
-  EXPECT_EQ(StringReplace(content, "$tmpdir", temp_directory_, true),
+  EXPECT_EQ(absl::StrReplaceAll(content, {{"$tmpdir", temp_directory_}}),
             file_contents);
 }
 
@@ -789,6 +793,7 @@
                                     "bar.proto", "Bar");
 }
 
+
 TEST_F(CommandLineInterfaceTest, MultipleInputsWithImport_DescriptorSetIn) {
   // Test parsing multiple input files with an import of a separate file.
   FileDescriptorSet file_descriptor_set;
@@ -825,7 +830,7 @@
   field->set_number(1);
 
   WriteDescriptorSet("baz_and_bat.bin", &file_descriptor_set);
-  Run(strings::Substitute(
+  Run(absl::Substitute(
       "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
       "--descriptor_set_in=$0 foo.proto bar.proto",
       std::string("$tmpdir/foo_and_bar.bin") +
@@ -841,7 +846,7 @@
   ExpectGeneratedWithMultipleInputs("test_plugin", "foo.proto,bar.proto",
                                     "bar.proto", "Bar");
 
-  Run(strings::Substitute(
+  Run(absl::Substitute(
       "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
       "--descriptor_set_in=$0 baz.proto bat.proto",
       std::string("$tmpdir/foo_and_bar.bin") +
@@ -899,7 +904,7 @@
   field->set_number(1);
   WriteDescriptorSet("foo_and_baz.bin", &file_descriptor_set);
 
-  Run(strings::Substitute(
+  Run(absl::Substitute(
       "protocol_compiler --test_out=$$tmpdir --plug_out=$$tmpdir "
       "--descriptor_set_in=$0 bar.proto",
       std::string("$tmpdir/foo_and_bar.bin") +
@@ -1305,7 +1310,7 @@
                  "}\n");
   CreateTempFile("b/foo.proto", "this should not be parsed\n");
 
-  Run(strings::Substitute(
+  Run(absl::Substitute(
       "protocol_compiler --test_out=$$tmpdir --proto_path=$0 foo.proto",
       std::string("$tmpdir/a") + CommandLineInterface::kPathSeparator +
           "$tmpdir/b"));
@@ -2253,9 +2258,9 @@
 
   Run("protocol_compiler --plug_out=$tmpdir --proto_path=$tmpdir foo.proto");
 
-  ExpectErrorSubstring(StringPrintf("Saw compiler_version: %d %s",
-                                    GOOGLE_PROTOBUF_VERSION,
-                                    GOOGLE_PROTOBUF_VERSION_SUFFIX));
+  ExpectErrorSubstring(absl::StrFormat("Saw compiler_version: %d %s",
+                                       GOOGLE_PROTOBUF_VERSION,
+                                       GOOGLE_PROTOBUF_VERSION_SUFFIX));
 }
 
 TEST_F(CommandLineInterfaceTest, GeneratorPluginNotFound) {
@@ -2586,8 +2591,8 @@
   bool Run(const std::string& command, bool specify_proto_files = true) {
     std::vector<std::string> args;
     args.push_back("protoc");
-    for (StringPiece split_piece :
-         Split(command, " ", true)) {
+    for (absl::string_view split_piece :
+         absl::StrSplit(command, " ", absl::SkipEmpty())) {
       args.push_back(std::string(split_piece));
     }
     if (specify_proto_files) {
@@ -2596,7 +2601,7 @@
           args.push_back("--proto_path=" + TestUtil::TestSourceDir());
           break;
         case DESCRIPTOR_SET_IN:
-          args.push_back(StrCat("--descriptor_set_in=",
+          args.push_back(absl::StrCat("--descriptor_set_in=",
                                       unittest_proto_descriptor_set_filename_));
           break;
         default:
@@ -2681,27 +2686,27 @@
 
 TEST_P(EncodeDecodeTest, Encode) {
   RedirectStdinFromFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/"
+      "third_party/protobuf/"
       "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"));
+        TestUtil::MaybeTranslatePath("third_party/protobuf/unittest.proto"));
   }
   EXPECT_TRUE(Run(args + " --encode=protobuf_unittest.TestAllTypes"));
   ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+      "third_party/protobuf/testdata/golden_message_oneof_implemented"));
   ExpectStderrMatchesText("");
 }
 
 TEST_P(EncodeDecodeTest, Decode) {
   RedirectStdinFromFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+      "third_party/protobuf/testdata/golden_message_oneof_implemented"));
   EXPECT_TRUE(
-      Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+      Run(TestUtil::MaybeTranslatePath("third_party/protobuf/unittest.proto") +
           " --decode=protobuf_unittest.TestAllTypes"));
   ExpectStdoutMatchesTextFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/"
+      "third_party/protobuf/"
       "testdata/text_format_unittest_data_oneof_implemented.txt"));
   ExpectStderrMatchesText("");
 }
@@ -2709,7 +2714,7 @@
 TEST_P(EncodeDecodeTest, Partial) {
   RedirectStdinFromText("");
   EXPECT_TRUE(
-      Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+      Run(TestUtil::MaybeTranslatePath("third_party/protobuf/unittest.proto") +
           " --encode=protobuf_unittest.TestRequired"));
   ExpectStdoutMatchesText("");
   ExpectStderrMatchesText(
@@ -2733,7 +2738,7 @@
 
 TEST_P(EncodeDecodeTest, UnknownType) {
   EXPECT_FALSE(
-      Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+      Run(TestUtil::MaybeTranslatePath("third_party/protobuf/unittest.proto") +
           " --encode=NoSuchType"));
   ExpectStdoutMatchesText("");
   ExpectStderrMatchesText("Type not defined: NoSuchType\n");
@@ -2750,25 +2755,25 @@
 
 TEST_P(EncodeDecodeTest, EncodeDeterministicOutput) {
   RedirectStdinFromFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/"
+      "third_party/protobuf/"
       "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"));
+        TestUtil::MaybeTranslatePath("third_party/protobuf/unittest.proto"));
   }
   EXPECT_TRUE(Run(
       args + " --encode=protobuf_unittest.TestAllTypes --deterministic_output"));
   ExpectStdoutMatchesBinaryFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+      "third_party/protobuf/testdata/golden_message_oneof_implemented"));
   ExpectStderrMatchesText("");
 }
 
 TEST_P(EncodeDecodeTest, DecodeDeterministicOutput) {
   RedirectStdinFromFile(TestUtil::GetTestDataPath(
-      "net/proto2/internal/testdata/golden_message_oneof_implemented"));
+      "third_party/protobuf/testdata/golden_message_oneof_implemented"));
   EXPECT_FALSE(
-      Run(TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto") +
+      Run(TestUtil::MaybeTranslatePath("third_party/protobuf/unittest.proto") +
           " --decode=protobuf_unittest.TestAllTypes --deterministic_output"));
   ExpectStderrMatchesText(
       "Can only use --deterministic_output with --encode.\n");
@@ -2780,7 +2785,7 @@
 
 #endif  // !GOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/BUILD.bazel b/src/google/protobuf/compiler/cpp/BUILD.bazel
new file mode 100644
index 0000000..2f2b709
--- /dev/null
+++ b/src/google/protobuf/compiler/cpp/BUILD.bazel
@@ -0,0 +1,261 @@
+################################################################################
+# Protocol Buffers Compiler - C++ code generator
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_proto_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "names",
+    hdrs = ["names.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/cpp",
+    visibility = ["//visibility:public"],
+    deps = [
+        ":names_internal",
+        "//src/google/protobuf/compiler:code_generator",
+        "//src/google/protobuf:protobuf_nowkt",
+    ],
+)
+
+cc_library(
+    name = "names_internal",
+    hdrs = [
+        "helpers.h",
+        "names.h",
+        "options.h",
+    ],
+    srcs = [
+        "helpers.cc",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/cpp",
+    visibility = ["//pkg:__pkg__"],
+    deps = [
+        "//src/google/protobuf/compiler:code_generator",
+        "//src/google/protobuf:protobuf_nowkt",
+    ],
+)
+
+cc_library(
+    name = "cpp",
+    srcs = [
+        "enum.cc",
+        "enum_field.cc",
+        "extension.cc",
+        "field.cc",
+        "file.cc",
+        "generator.cc",
+        "map_field.cc",
+        "message.cc",
+        "message_field.cc",
+        "padding_optimizer.cc",
+        "parse_function_generator.cc",
+        "primitive_field.cc",
+        "service.cc",
+        "string_field.cc",
+    ],
+    hdrs = [
+        "enum.h",
+        "enum_field.h",
+        "extension.h",
+        "field.h",
+        "file.h",
+        "generator.h",
+        "map_field.h",
+        "message.h",
+        "message_field.h",
+        "message_layout_helper.h",
+        "padding_optimizer.h",
+        "parse_function_generator.h",
+        "primitive_field.h",
+        "service.h",
+        "string_field.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/cpp",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+        "@io_kythe//kythe/cxx/tools:__subpackages__",
+    ],
+    deps = [
+        ":names_internal",
+        ":names",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/container:btree",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/container:layout",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/synchronization",
+    ],
+)
+
+proto_library(
+    name = "test_bad_identifiers_proto",
+    testonly = 1,
+    srcs = ["test_bad_identifiers.proto"],
+    strip_import_prefix = "/src",
+)
+
+cc_proto_library(
+    name = "test_bad_identifiers_cc_proto",
+    testonly = 1,
+    deps = [":test_bad_identifiers_proto"],
+)
+
+proto_library(
+    name = "test_large_enum_value_proto",
+    testonly = 1,
+    srcs = ["test_large_enum_value.proto"],
+    strip_import_prefix = "/src",
+)
+
+cc_proto_library(
+    name = "test_large_enum_value_cc_proto",
+    testonly = 1,
+    deps = [":test_large_enum_value_proto"],
+)
+
+cc_library(
+    name = "unittest_lib",
+    hdrs = [
+        "unittest.h",
+        "unittest.inc",
+    ],
+    strip_include_prefix = "/src",
+    visibility = ["//pkg:__pkg__"],
+)
+
+cc_test(
+    name = "unittest",
+    srcs = ["unittest.cc"],
+    copts = COPTS,
+    data = [
+        "//:test_proto_srcs",
+        "//src/google/protobuf:testdata",
+    ],
+    deps = [
+        ":cpp",
+        ":test_bad_identifiers_cc_proto",
+        ":unittest_lib",
+        "//:protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf:test_util2",
+        "//src/google/protobuf/compiler:importer",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "bootstrap_unittest",
+    srcs = ["bootstrap_unittest.cc"],
+    data = [
+        "//:well_known_type_protos",
+        "//src/google/protobuf:descriptor_cc_srcs",
+        "//src/google/protobuf:descriptor_proto_srcs",
+        "//src/google/protobuf:testdata",
+        "//src/google/protobuf/compiler:plugin_proto_srcs",
+    ],
+    deps = [
+        ":cpp",
+        "//:protobuf",
+        "//src/google/protobuf:test_util2",
+        "//src/google/protobuf/compiler:importer",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "message_size_unittest",
+    srcs = ["message_size_unittest.cc"],
+    deps = [
+        "//:protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "metadata_test",
+    srcs = ["metadata_test.cc"],
+    deps = [
+        ":cpp",
+        "//:protobuf",
+        "//src/google/protobuf/compiler:annotation_test_util",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "move_unittest",
+    srcs = ["move_unittest.cc"],
+    copts = COPTS,
+    deps = [
+        "//:protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf/stubs:lite",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "plugin_unittest",
+    srcs = ["plugin_unittest.cc"],
+    deps = [
+        ":cpp",
+        "//:protobuf",
+        "//src/google/protobuf/compiler:command_line_interface",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
+
+filegroup(
+    name = "test_proto_srcs",
+    srcs = [
+        "test_bad_identifiers.proto",
+        "test_large_enum_value.proto",
+    ],
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc b/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc
index 2619e60..036a434 100644
--- a/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/bootstrap_unittest.cc
@@ -42,29 +42,34 @@
 // "generate_descriptor_proto.sh" and add
 // descriptor.pb.{h,cc} to your changelist.
 
-#include <map>
+#include <memory>
+#include <string>
 
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/compiler/cpp/generator.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/test_util2.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/compiler/cpp/generator.h"
+#include "google/protobuf/compiler/importer.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/test_util2.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
 namespace {
+std::string FindWithDefault(
+    const absl::flat_hash_map<absl::string_view, std::string>& m,
+    const std::string& k, const std::string& v) {
+  auto it = m.find(k);
+  if (it == m.end()) return v;
+  return it->second;
+}
 
 class MockErrorCollector : public MultiFileErrorCollector {
  public:
@@ -76,7 +81,7 @@
   // implements ErrorCollector ---------------------------------------
   void AddError(const std::string& filename, int line, int column,
                 const std::string& message) override {
-    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
+    absl::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
                               message);
   }
 };
@@ -95,7 +100,6 @@
         File::GetContents(TestUtil::TestSourceDir() + "/" + physical_filename,
                           &actual_contents, true))
         << physical_filename;
-    CleanStringLineEndings(&actual_contents, false);
 
 #ifdef WRITE_FILES  // Define to debug mismatched files.
     GOOGLE_CHECK_OK(File::SetContents("/tmp/expected.cc", expected_contents,
@@ -120,7 +124,7 @@
   }
 
  private:
-  std::map<std::string, std::unique_ptr<std::string>> files_;
+  absl::flat_hash_map<std::string, std::unique_ptr<std::string>> files_;
 };
 
 const char kDescriptorParameter[] = "dllexport_decl=PROTOBUF_EXPORT";
@@ -135,8 +139,8 @@
 TEST(BootstrapTest, GeneratedFilesMatch) {
   // We need a mapping from the actual file to virtual and actual path
   // of the data to compare to.
-  std::map<std::string, std::string> vpath_map;
-  std::map<std::string, std::string> rpath_map;
+  absl::flat_hash_map<absl::string_view, std::string> vpath_map;
+  absl::flat_hash_map<absl::string_view, std::string> rpath_map;
   rpath_map["third_party/protobuf/test_messages_proto2"] =
       "net/proto2/z_generated_example/test_messages_proto2";
   rpath_map["third_party/protobuf/test_messages_proto3"] =
diff --git a/src/google/protobuf/compiler/cpp/cpp_generator.h b/src/google/protobuf/compiler/cpp/cpp_generator.h
index 1716ab2..599b4ab 100644
--- a/src/google/protobuf/compiler/cpp/cpp_generator.h
+++ b/src/google/protobuf/compiler/cpp/cpp_generator.h
@@ -1,6 +1,36 @@
+// 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_CPP_GENERATOR_H_
 #define GOOGLE_PROTOBUF_COMPILER_CPP_CPP_GENERATOR_H_
 
-#include <google/protobuf/compiler/cpp/generator.h>
+#include "google/protobuf/compiler/cpp/generator.h"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_CPP_GENERATOR_H_
diff --git a/src/google/protobuf/compiler/cpp/enum.cc b/src/google/protobuf/compiler/cpp/enum.cc
index 8124369..7d03aa5 100644
--- a/src/google/protobuf/compiler/cpp/enum.cc
+++ b/src/google/protobuf/compiler/cpp/enum.cc
@@ -32,26 +32,47 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/enum.h>
+#include "google/protobuf/compiler/cpp/enum.h"
 
+#include <algorithm>
 #include <cstdint>
 #include <limits>
-#include <map>
+#include <string>
+#include <utility>
+#include <vector>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/names.h>
+#include "google/protobuf/descriptor.h"
+#include "absl/container/btree_map.h"
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/names.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
 namespace {
-// The GOOGLE_ARRAYSIZE constant is the max enum value plus 1. If the max enum value
-// is kint32max, GOOGLE_ARRAYSIZE will overflow. In such cases we should omit the
-// generation of the GOOGLE_ARRAYSIZE constant.
+absl::flat_hash_map<absl::string_view, std::string> EnumVars(
+    const EnumDescriptor* enum_, const Options& options,
+    const EnumValueDescriptor* min, const EnumValueDescriptor* max) {
+  auto classname = ClassName(enum_, false);
+  return {
+      {"Enum", enum_->name()},
+      {"Enum_", ResolveKeyword(enum_->name())},
+      {"Msg_Enum", classname},
+      {"::Msg_Enum", QualifiedClassName(enum_, options)},
+      {"Msg_Enum_",
+       enum_->containing_type() == nullptr ? "" : absl::StrCat(classname, "_")},
+      {"kMin", absl::StrCat(min->number())},
+      {"kMax", absl::StrCat(max->number())},
+  };
+}
+
+// The ARRAYSIZE constant is the max enum value plus 1. If the max enum value
+// is kint32max, ARRAYSIZE will overflow. In such cases we should omit the
+// generation of the ARRAYSIZE constant.
 bool ShouldGenerateArraySize(const EnumDescriptor* descriptor) {
   int32_t max_value = descriptor->value(0)->number();
   for (int i = 0; i < descriptor->value_count(); i++) {
@@ -61,251 +82,320 @@
   }
   return max_value != std::numeric_limits<int32_t>::max();
 }
-
-// Returns the number of unique numeric enum values. This is less than
-// descriptor->value_count() when there are aliased values.
-int CountUniqueValues(const EnumDescriptor* descriptor) {
-  std::set<int> values;
-  for (int i = 0; i < descriptor->value_count(); ++i) {
-    values.insert(descriptor->value(i)->number());
-  }
-  return values.size();
-}
-
 }  // namespace
+EnumGenerator::ValueLimits EnumGenerator::ValueLimits::FromEnum(
+    const EnumDescriptor* descriptor) {
+  const EnumValueDescriptor* min_desc = descriptor->value(0);
+  const EnumValueDescriptor* max_desc = descriptor->value(0);
+
+  for (int i = 1; i < descriptor->value_count(); ++i) {
+    if (descriptor->value(i)->number() < min_desc->number()) {
+      min_desc = descriptor->value(i);
+    }
+    if (descriptor->value(i)->number() > max_desc->number()) {
+      max_desc = descriptor->value(i);
+    }
+  }
+
+  return EnumGenerator::ValueLimits{min_desc, max_desc};
+}
 
 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor,
-                             const std::map<std::string, std::string>& vars,
                              const Options& options)
-    : descriptor_(descriptor),
-      classname_(ClassName(descriptor, false)),
+    : enum_(descriptor),
       options_(options),
       generate_array_size_(ShouldGenerateArraySize(descriptor)),
-      variables_(vars) {
-  variables_["classname"] = classname_;
-  variables_["classtype"] = QualifiedClassName(descriptor_, options);
-  variables_["short_name"] = descriptor_->name();
-  variables_["nested_name"] = descriptor_->name();
-  variables_["resolved_name"] = ResolveKeyword(descriptor_->name());
-  variables_["prefix"] =
-      (descriptor_->containing_type() == nullptr) ? "" : classname_ + "_";
+      has_reflection_(HasDescriptorMethods(enum_->file(), options_)),
+      limits_(ValueLimits::FromEnum(enum_)) {
+  // The conditions here for what is "sparse" are not rigorously
+  // chosen.
+  size_t values_range = static_cast<size_t>(limits_.max->number()) -
+                        static_cast<size_t>(limits_.min->number());
+  size_t total_values = static_cast<size_t>(enum_->value_count());
+  should_cache_ = has_reflection_ &&
+                  (values_range < 16u || values_range < total_values * 2u);
 }
 
-EnumGenerator::~EnumGenerator() {}
+void EnumGenerator::GenerateDefinition(io::Printer* p) {
+  auto v1 = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max));
 
-void EnumGenerator::GenerateDefinition(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  format("enum ${1$$classname$$}$ : int {\n", descriptor_);
-  format.Indent();
+  auto v2 = p->WithVars({
+      {"Msg_Enum_Enum_MIN",
+       absl::StrCat(p->LookupVar("Msg_Enum_"), enum_->name(), "_MIN"), enum_},
+      {"Msg_Enum_Enum_MAX",
+       absl::StrCat(p->LookupVar("Msg_Enum_"), enum_->name(), "_MAX"), enum_},
+  });
+  p->Emit(
+      {
+          {"values",
+           [&] {
+             for (int i = 0; i < enum_->value_count(); ++i) {
+               const auto* value = enum_->value(i);
+               p->Emit(
+                   {
+                       {
+                           "Msg_Enum_VALUE",
+                           absl::StrCat(p->LookupVar("Msg_Enum_"),
+                                        EnumValueName(value)),
+                           value,
+                       },
+                       {"kNumber", Int32ToString(value->number())},
+                       {"DEPRECATED", value->options().deprecated()
+                                          ? "PROTOBUF_DEPRECATED_ENUM"
+                                          : ""},
+                   },
+                   R"cc(
+                     $Msg_Enum_VALUE$$ DEPRECATED$ = $kNumber$,
+                   )cc");
+             }
+           }},
+          // Only emit annotations for the $Msg_Enum$ used in the `enum`
+          // definition.
+          {"Msg_Enum_annotated", p->LookupVar("Msg_Enum"), enum_},
+          {"open_enum_sentinels",
+           [&] {
+             if (enum_->is_closed()) {
+               return;
+             }
 
-  const EnumValueDescriptor* min_value = descriptor_->value(0);
-  const EnumValueDescriptor* max_value = descriptor_->value(0);
+             // For open enum semantics: generate min and max sentinel values
+             // equal to INT32_MIN and INT32_MAX
+             p->Emit({{"Msg_Enum_Msg_Enum_",
+                       absl::StrCat(p->LookupVar("Msg_Enum"), "_",
+                                    p->LookupVar("Msg_Enum_"))}},
+                     R"cc(
+                       $Msg_Enum_Msg_Enum_$INT_MIN_SENTINEL_DO_NOT_USE_ =
+                           std::numeric_limits<::int32_t>::min(),
+                       $Msg_Enum_Msg_Enum_$INT_MAX_SENTINEL_DO_NOT_USE_ =
+                           std::numeric_limits<::int32_t>::max(),
+                     )cc");
+           }},
+      },
+      R"cc(
+        enum $Msg_Enum_annotated$ : int {
+          $values$,
+          $open_enum_sentinels$,
+        };
 
-  for (int i = 0; i < descriptor_->value_count(); i++) {
-    auto format_value = format;
-    format_value.Set("name", EnumValueName(descriptor_->value(i)));
-    // In C++, an value of -2147483648 gets interpreted as the negative of
-    // 2147483648, and since 2147483648 can't fit in an integer, this produces a
-    // compiler warning.  This works around that issue.
-    format_value.Set("number", Int32ToString(descriptor_->value(i)->number()));
-    format_value.Set("deprecation",
-                     DeprecatedAttribute(options_, descriptor_->value(i)));
-
-    if (i > 0) format_value(",\n");
-    format_value("${1$$prefix$$name$$}$ $deprecation$= $number$",
-                 descriptor_->value(i));
-
-    if (descriptor_->value(i)->number() < min_value->number()) {
-      min_value = descriptor_->value(i);
-    }
-    if (descriptor_->value(i)->number() > max_value->number()) {
-      max_value = descriptor_->value(i);
-    }
-  }
-
-  if (descriptor_->file()->syntax() == FileDescriptor::SYNTAX_PROTO3) {
-    // For new enum semantics: generate min and max sentinel values equal to
-    // INT32_MIN and INT32_MAX
-    if (descriptor_->value_count() > 0) format(",\n");
-    format(
-        "$classname$_$prefix$INT_MIN_SENTINEL_DO_NOT_USE_ = "
-        "std::numeric_limits<$int32$>::min(),\n"
-        "$classname$_$prefix$INT_MAX_SENTINEL_DO_NOT_USE_ = "
-        "std::numeric_limits<$int32$>::max()");
-  }
-
-  format.Outdent();
-  format("\n};\n");
-
-  format(
-      "$dllexport_decl $bool $classname$_IsValid(int value);\n"
-      "constexpr $classname$ ${1$$prefix$$short_name$_MIN$}$ = "
-      "$prefix$$2$;\n"
-      "constexpr $classname$ ${1$$prefix$$short_name$_MAX$}$ = "
-      "$prefix$$3$;\n",
-      descriptor_, EnumValueName(min_value), EnumValueName(max_value));
+        $dllexport_decl $bool $Msg_Enum$_IsValid(int value);
+        constexpr $Msg_Enum$ $Msg_Enum_Enum_MIN$ = static_cast<$Msg_Enum$>($kMin$);
+        constexpr $Msg_Enum$ $Msg_Enum_Enum_MAX$ = static_cast<$Msg_Enum$>($kMax$);
+      )cc");
 
   if (generate_array_size_) {
-    format(
-        "constexpr int ${1$$prefix$$short_name$_ARRAYSIZE$}$ = "
-        "$prefix$$short_name$_MAX + 1;\n\n",
-        descriptor_);
+    p->Emit(
+        {{"Msg_Enum_Enum_ARRAYSIZE",
+          absl::StrCat(p->LookupVar("Msg_Enum_"), enum_->name(), "_ARRAYSIZE"),
+          enum_}},
+        R"cc(
+          constexpr int $Msg_Enum_Enum_ARRAYSIZE$ = $kMax$ + 1;
+        )cc");
   }
 
-  if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    format(
-        "$dllexport_decl $const ::$proto_ns$::EnumDescriptor* "
-        "$classname$_descriptor();\n");
-  }
-
-  // The _Name and _Parse functions. The lite implementation is table-based, so
-  // we make sure to keep the tables hidden in the .cc file.
-  if (!HasDescriptorMethods(descriptor_->file(), options_)) {
-    format("const std::string& $classname$_Name($classname$ value);\n");
-  }
-  // The _Name() function accepts the enum type itself but also any integral
-  // type.
-  format(
-      "template<typename T>\n"
-      "inline const std::string& $classname$_Name(T enum_t_value) {\n"
-      "  static_assert(::std::is_same<T, $classname$>::value ||\n"
-      "    ::std::is_integral<T>::value,\n"
-      "    \"Incorrect type passed to function $classname$_Name.\");\n");
-  if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    format(
-        "  return ::$proto_ns$::internal::NameOfEnum(\n"
-        "    $classname$_descriptor(), enum_t_value);\n");
+  if (has_reflection_) {
+    p->Emit(R"cc(
+      $dllexport_decl $const ::$proto_ns$::EnumDescriptor*
+      $Msg_Enum$_descriptor();
+    )cc");
   } else {
-    format(
-        "  return $classname$_Name(static_cast<$classname$>(enum_t_value));\n");
+    p->Emit(R"cc(
+      const std::string& $Msg_Enum$_Name($Msg_Enum$ value);
+    )cc");
   }
-  format("}\n");
 
-  if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    format(
-        "inline bool $classname$_Parse(\n"
-        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
-        "value) "
-        "{\n"
-        "  return ::$proto_ns$::internal::ParseNamedEnum<$classname$>(\n"
-        "    $classname$_descriptor(), name, value);\n"
-        "}\n");
+  // There are three possible implementations of $Enum$_Name() and
+  // $Msg_Enum$_Parse(), depending on whether we are using a dense enum name
+  // cache or not, and whether or not we have reflection. Very little code is
+  // shared between the three, so it is split into three Emit() calls.
+
+  // Can't use WithVars here, since callbacks can only be passed to Emit()
+  // directly. Because this includes $Enum$, it must be a callback.
+  auto write_assert = [&] {
+    p->Emit(R"cc(
+      static_assert(std::is_same<T, $Msg_Enum$>::value ||
+                        std::is_integral<T>::value,
+                    "Incorrect type passed to $Enum$_Name().");
+    )cc");
+  };
+
+  if (should_cache_ || !has_reflection_) {
+    p->Emit({{"static_assert", write_assert}}, R"cc(
+      template <typename T>
+      const std::string& $Msg_Enum$_Name(T value) {
+        $static_assert$;
+        return $Msg_Enum$_Name(static_cast<$Msg_Enum$>(value));
+      }
+    )cc");
+    if (should_cache_) {
+      // Using the NameOfEnum routine can be slow, so we create a small
+      // cache of pointers to the std::string objects that reflection
+      // stores internally.  This cache is a simple contiguous array of
+      // pointers, so if the enum values are sparse, it's not worth it.
+      p->Emit(R"cc(
+        template <>
+        inline const std::string& $Msg_Enum$_Name($Msg_Enum$ value) {
+          return ::$proto_ns$::internal::NameOfDenseEnum<$Msg_Enum$_descriptor,
+                                                         $kMin$, $kMax$>(
+              static_cast<int>(value));
+        }
+      )cc");
+    } else {
+      p->Emit(R"cc(
+        const std::string& $Msg_Enum$_Name($Msg_Enum$ value);
+      )cc");
+    }
   } else {
-    format(
-        "bool $classname$_Parse(\n"
-        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, $classname$* "
-        "value);\n");
+    p->Emit({{"static_assert", write_assert}}, R"cc(
+      template <typename T>
+      const std::string& $Msg_Enum$_Name(T value) {
+        $static_assert$;
+        return ::$proto_ns$::internal::NameOfEnum($Msg_Enum$_descriptor(), value);
+      }
+    )cc");
+  }
+
+  if (has_reflection_) {
+    p->Emit(R"cc(
+      inline bool $Msg_Enum$_Parse(absl::string_view name, $Msg_Enum$* value) {
+        return ::$proto_ns$::internal::ParseNamedEnum<$Msg_Enum$>(
+            $Msg_Enum$_descriptor(), name, value);
+      }
+    )cc");
+  } else {
+    p->Emit(R"cc(
+      bool $Msg_Enum$_Parse(absl::string_view name, $Msg_Enum$* value);
+    )cc");
   }
 }
 
-void EnumGenerator::GenerateGetEnumDescriptorSpecializations(
-    io::Printer* printer) {
-  Formatter format(printer, variables_);
-  format(
-      "template <> struct is_proto_enum< $classtype$> : ::std::true_type "
-      "{};\n");
-  if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    format(
-        "template <>\n"
-        "inline const EnumDescriptor* GetEnumDescriptor< $classtype$>() {\n"
-        "  return $classtype$_descriptor();\n"
-        "}\n");
+void EnumGenerator::GenerateGetEnumDescriptorSpecializations(io::Printer* p) {
+  auto v = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max));
+
+  p->Emit(R"cc(
+    template <>
+    struct is_proto_enum<$::Msg_Enum$> : std::true_type {};
+  )cc");
+  if (!has_reflection_) {
+    return;
   }
+  p->Emit(R"cc(
+    template <>
+    inline const EnumDescriptor* GetEnumDescriptor<$::Msg_Enum$>() {
+      return $::Msg_Enum$_descriptor();
+    }
+  )cc");
 }
 
-void EnumGenerator::GenerateSymbolImports(io::Printer* printer) const {
-  Formatter format(printer, variables_);
-  format("typedef $classname$ $resolved_name$;\n");
+void EnumGenerator::GenerateSymbolImports(io::Printer* p) const {
+  auto v = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max));
 
-  for (int j = 0; j < descriptor_->value_count(); j++) {
-    std::string deprecated_attr =
-        DeprecatedAttribute(options_, descriptor_->value(j));
-    format(
-        "$1$static constexpr $resolved_name$ ${2$$3$$}$ =\n"
-        "  $classname$_$3$;\n",
-        deprecated_attr, descriptor_->value(j),
-        EnumValueName(descriptor_->value(j)));
+  {
+    auto a = p->WithVars({{"Enum_annotated", p->LookupVar("Enum_"), enum_}});
+    p->Emit(R"cc(
+      using $Enum_annotated$ = $Msg_Enum$;
+    )cc");
   }
 
-  format(
-      "static inline bool $nested_name$_IsValid(int value) {\n"
-      "  return $classname$_IsValid(value);\n"
-      "}\n"
-      "static constexpr $resolved_name$ ${1$$nested_name$_MIN$}$ =\n"
-      "  $classname$_$nested_name$_MIN;\n"
-      "static constexpr $resolved_name$ ${1$$nested_name$_MAX$}$ =\n"
-      "  $classname$_$nested_name$_MAX;\n",
-      descriptor_);
+  for (int j = 0; j < enum_->value_count(); ++j) {
+    const auto* value = enum_->value(j);
+    p->Emit(
+        {
+            {"VALUE", EnumValueName(enum_->value(j)), value},
+            {"DEPRECATED",
+             value->options().deprecated() ? "PROTOBUF_DEPRECATED_ENUM" : ""},
+        },
+        R"cc(
+          $DEPRECATED $static constexpr $Enum_$ $VALUE$ = $Msg_Enum$_$VALUE$;
+        )cc");
+  }
+
+  p->Emit(
+      {
+          {"Enum_MIN", absl::StrCat(enum_->name(), "_MIN"), enum_},
+          {"Enum_MAX", absl::StrCat(enum_->name(), "_MAX"), enum_},
+      },
+      R"cc(
+        static inline bool $Enum$_IsValid(int value) {
+          return $Msg_Enum$_IsValid(value);
+        }
+        static constexpr $Enum_$ $Enum_MIN$ = $Msg_Enum$_$Enum$_MIN;
+        static constexpr $Enum_$ $Enum_MAX$ = $Msg_Enum$_$Enum$_MAX;
+      )cc");
+
   if (generate_array_size_) {
-    format(
-        "static constexpr int ${1$$nested_name$_ARRAYSIZE$}$ =\n"
-        "  $classname$_$nested_name$_ARRAYSIZE;\n",
-        descriptor_);
+    p->Emit(
+        {{"Enum_ARRAYSIZE", absl::StrCat(enum_->name(), "_ARRAYSIZE"), enum_}},
+        R"cc(
+          static constexpr int $Enum_ARRAYSIZE$ = $Msg_Enum$_$Enum$_ARRAYSIZE;
+        )cc");
   }
 
-  if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    format(
-        "static inline const ::$proto_ns$::EnumDescriptor*\n"
-        "$nested_name$_descriptor() {\n"
-        "  return $classname$_descriptor();\n"
-        "}\n");
+  if (has_reflection_) {
+    p->Emit(R"cc(
+      static inline const ::$proto_ns$::EnumDescriptor* $Enum$_descriptor() {
+        return $Msg_Enum$_descriptor();
+      }
+    )cc");
   }
 
-  format(
-      "template<typename T>\n"
-      "static inline const std::string& $nested_name$_Name(T enum_t_value) {\n"
-      "  static_assert(::std::is_same<T, $resolved_name$>::value ||\n"
-      "    ::std::is_integral<T>::value,\n"
-      "    \"Incorrect type passed to function $nested_name$_Name.\");\n"
-      "  return $classname$_Name(enum_t_value);\n"
-      "}\n");
-  format(
-      "static inline bool "
-      "$nested_name$_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,\n"
-      "    $resolved_name$* value) {\n"
-      "  return $classname$_Parse(name, value);\n"
-      "}\n");
+  p->Emit(R"cc(
+    template <typename T>
+    static inline const std::string& $Enum$_Name(T value) {
+      return $Msg_Enum$_Name(value);
+    }
+    static inline bool $Enum$_Parse(absl::string_view name, $Enum_$* value) {
+      return $Msg_Enum$_Parse(name, value);
+    }
+  )cc");
 }
 
-void EnumGenerator::GenerateMethods(int idx, io::Printer* printer) {
-  Formatter format(printer, variables_);
-  if (HasDescriptorMethods(descriptor_->file(), options_)) {
-    format(
-        "const ::$proto_ns$::EnumDescriptor* $classname$_descriptor() {\n"
-        "  ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
-        "  return $file_level_enum_descriptors$[$1$];\n"
-        "}\n",
-        idx);
+void EnumGenerator::GenerateMethods(int idx, io::Printer* p) {
+  auto v = p->WithVars(EnumVars(enum_, options_, limits_.min, limits_.max));
+
+  if (has_reflection_) {
+    p->Emit({{"idx", idx}}, R"cc(
+      const ::$proto_ns$::EnumDescriptor* $Msg_Enum$_descriptor() {
+        ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);
+        return $file_level_enum_descriptors$[$idx$];
+      }
+    )cc");
   }
 
-  format(
-      "bool $classname$_IsValid(int value) {\n"
-      "  switch (value) {\n");
+  p->Emit({{"cases",
+            [&] {
+              // Multiple values may have the same number.  Make sure we only
+              // cover each number once by first constructing a set containing
+              // all valid numbers, then printing a case statement for each
+              // element.
 
-  // Multiple values may have the same number.  Make sure we only cover
-  // each number once by first constructing a set containing all valid
-  // numbers, then printing a case statement for each element.
+              std::vector<int> numbers;
+              numbers.reserve(enum_->value_count());
+              for (int i = 0; i < enum_->value_count(); ++i) {
+                numbers.push_back(enum_->value(i)->number());
+              }
+              // Sort and deduplicate `numbers`.
+              absl::c_sort(numbers);
+              numbers.erase(std::unique(numbers.begin(), numbers.end()),
+                            numbers.end());
 
-  std::set<int> numbers;
-  for (int j = 0; j < descriptor_->value_count(); j++) {
-    const EnumValueDescriptor* value = descriptor_->value(j);
-    numbers.insert(value->number());
-  }
+              for (int n : numbers) {
+                p->Emit({{"n", n}}, R"cc(
+                  case $n$:
+                )cc");
+              }
+            }}},
+          R"(
+            bool $Msg_Enum$_IsValid(int value) {
+              switch (value) {
+                $cases$;
+                  return true;
+                default:
+                  return false;
+              }
+            }
+          )");
 
-  for (std::set<int>::iterator iter = numbers.begin(); iter != numbers.end();
-       ++iter) {
-    format("    case $1$:\n", Int32ToString(*iter));
-  }
-
-  format(
-      "      return true;\n"
-      "    default:\n"
-      "      return false;\n"
-      "  }\n"
-      "}\n"
-      "\n");
-
-  if (!HasDescriptorMethods(descriptor_->file(), options_)) {
+  if (!has_reflection_) {
     // In lite mode (where descriptors are unavailable), we generate separate
     // tables for mapping between enum names and numbers. The _entries table
     // contains the bulk of the data and is sorted by name, while
@@ -319,119 +409,168 @@
     // numerical value. In cases where there are multiple names for the same
     // number, we treat the first name appearing in the .proto file as the
     // canonical one.
-    std::map<std::string, int> name_to_number;
-    std::map<int, std::string> number_to_canonical_name;
-    for (int i = 0; i < descriptor_->value_count(); i++) {
-      const EnumValueDescriptor* value = descriptor_->value(i);
+
+    absl::btree_map<std::string, int> name_to_number;
+    absl::flat_hash_map<int, std::string> number_to_canonical_name;
+    for (int i = 0; i < enum_->value_count(); ++i) {
+      const auto* value = enum_->value(i);
       name_to_number.emplace(value->name(), value->number());
+
       // The same number may appear with multiple names, so we use emplace() to
       // let the first name win.
       number_to_canonical_name.emplace(value->number(), value->name());
     }
 
-    format(
-        "static ::$proto_ns$::internal::ExplicitlyConstructed<std::string> "
-        "$classname$_strings[$1$] = {};\n\n",
-        CountUniqueValues(descriptor_));
-
-    // We concatenate all the names for a given enum into one big string
-    // literal. If instead we store an array of string literals, the linker
-    // seems to put all enum strings for a given .proto file in the same
-    // section, which hinders its ability to strip out unused strings.
-    format("static const char $classname$_names[] =");
-    for (const auto& p : name_to_number) {
-      format("\n  \"$1$\"", p.first);
+    // Build the offset table for the strings table.
+    struct Offset {
+      int number;
+      size_t index, byte_offset, len;
+    };
+    std::vector<Offset> offsets;
+    size_t index = 0;
+    size_t offset = 0;
+    for (const auto& e : name_to_number) {
+      offsets.push_back(Offset{e.second, index, offset, e.first.size()});
+      ++index;
+      offset += e.first.size();
     }
-    format(";\n\n");
+    absl::c_sort(offsets, [](const auto& a, const auto& b) {
+      return a.byte_offset < b.byte_offset;
+    });
 
-    format(
-        "static const ::$proto_ns$::internal::EnumEntry $classname$_entries[] "
-        "= {\n");
-    int i = 0;
-    std::map<int, int> number_to_index;
-    int data_index = 0;
-    for (const auto& p : name_to_number) {
-      format("  { {$classname$_names + $1$, $2$}, $3$ },\n", data_index,
-             p.first.size(), p.second);
-      if (number_to_canonical_name[p.second] == p.first) {
-        number_to_index.emplace(p.second, i);
-      }
-      ++i;
-      data_index += p.first.size();
-    }
+    std::vector<Offset> offsets_by_number = offsets;
+    absl::c_sort(offsets_by_number, [](const auto& a, const auto& b) {
+      return a.number < b.number;
+    });
 
-    format(
-        "};\n"
-        "\n"
-        "static const int $classname$_entries_by_number[] = {\n");
-    for (const auto& p : number_to_index) {
-      format("  $1$, // $2$ -> $3$\n", p.second, p.first,
-             number_to_canonical_name[p.first]);
-    }
-    format(
-        "};\n"
-        "\n");
+    offsets_by_number.erase(
+        std::unique(
+            offsets_by_number.begin(), offsets_by_number.end(),
+            [](const auto& a, const auto& b) { return a.number == b.number; }),
+        offsets_by_number.end());
 
-    format(
-        "const std::string& $classname$_Name(\n"
-        "    $classname$ value) {\n"
-        "  static const bool dummy =\n"
-        "      ::$proto_ns$::internal::InitializeEnumStrings(\n"
-        "          $classname$_entries,\n"
-        "          $classname$_entries_by_number,\n"
-        "          $1$, $classname$_strings);\n"
-        "  (void) dummy;\n"
-        "  int idx = ::$proto_ns$::internal::LookUpEnumName(\n"
-        "      $classname$_entries,\n"
-        "      $classname$_entries_by_number,\n"
-        "      $1$, value);\n"
-        "  return idx == -1 ? ::$proto_ns$::internal::GetEmptyString() :\n"
-        "                     $classname$_strings[idx].get();\n"
-        "}\n",
-        CountUniqueValues(descriptor_));
-    format(
-        "bool $classname$_Parse(\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"
-        "  if (success) {\n"
-        "    *value = static_cast<$classname$>(int_value);\n"
-        "  }\n"
-        "  return success;\n"
-        "}\n",
-        descriptor_->value_count());
+    p->Emit(
+        {
+            {"num_unique", number_to_canonical_name.size()},
+            {"num_declared", enum_->value_count()},
+            {"names",
+             // We concatenate all the names for a given enum into one big
+             // string literal. If instead we store an array of string
+             // literals, the linker seems to put all enum strings for a given
+             // .proto file in the same section, which hinders its ability to
+             // strip out unused strings.
+             [&] {
+               for (const auto& e : name_to_number) {
+                 p->Emit({{"name", e.first}}, R"cc(
+                   "$name$"
+                 )cc");
+               }
+             }},
+            {"entries",
+             [&] {
+               for (const auto& offset : offsets) {
+                 p->Emit({{"number", offset.number},
+                          {"offset", offset.byte_offset},
+                          {"len", offset.len}},
+                         R"cc(
+                           {{&$Msg_Enum$_names[$offset$], $len$}, $number$},
+                         )cc");
+               }
+             }},
+            {"entries_by_number",
+             [&] {
+               for (const auto& offset : offsets_by_number) {
+                 p->Emit({{"number", offset.number},
+                          {"index", offset.index},
+                          {"name", number_to_canonical_name[offset.number]}},
+                         R"cc(
+                           $index$,  // $number$ -> $name$
+                         )cc");
+               }
+             }},
+        },
+        R"cc(
+          static ::$proto_ns$::internal::ExplicitlyConstructed<std::string>
+              $Msg_Enum$_strings[$num_unique$] = {};
+
+          static const char $Msg_Enum$_names[] = {
+              $names$,
+          };
+
+          static const ::$proto_ns$::internal::EnumEntry $Msg_Enum$_entries[] =
+              {
+                  $entries$,
+          };
+
+          static const int $Msg_Enum$_entries_by_number[] = {
+              $entries_by_number$,
+          };
+
+          const std::string& $Msg_Enum$_Name($Msg_Enum$ value) {
+            static const bool kDummy =
+                ::$proto_ns$::internal::InitializeEnumStrings(
+                    $Msg_Enum$_entries, $Msg_Enum$_entries_by_number,
+                    $num_unique$, $Msg_Enum$_strings);
+            (void)kDummy;
+
+            int idx = ::$proto_ns$::internal::LookUpEnumName(
+                $Msg_Enum$_entries, $Msg_Enum$_entries_by_number, $num_unique$,
+                value);
+            return idx == -1 ? ::$proto_ns$::internal::GetEmptyString()
+                             : $Msg_Enum$_strings[idx].get();
+          }
+
+          bool $Msg_Enum$_Parse(absl::string_view name, $Msg_Enum$* value) {
+            int int_value;
+            bool success = ::$proto_ns$::internal::LookUpEnumValue(
+                $Msg_Enum$_entries, $num_declared$, name, &int_value);
+            if (success) {
+              *value = static_cast<$Msg_Enum$>(int_value);
+            }
+            return success;
+          }
+        )cc");
   }
 
-  if (descriptor_->containing_type() != nullptr) {
-    std::string parent = ClassName(descriptor_->containing_type(), false);
+  if (enum_->containing_type() != nullptr) {
     // Before C++17, we must define the static constants which were
     // declared in the header, to give the linker a place to put them.
     // But MSVC++ pre-2015 and post-2017 (version 15.5+) insists that we not.
-    format(
-        "#if (__cplusplus < 201703) && "
-        "(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n");
+    p->Emit(
+        {
+            {"Msg_", ClassName(enum_->containing_type(), false)},
+            {"constexpr_storage",
+             [&] {
+               for (int i = 0; i < enum_->value_count(); i++) {
+                 p->Emit({{"VALUE", EnumValueName(enum_->value(i))}},
+                         R"cc(
+                           constexpr $Msg_Enum$ $Msg_$::$VALUE$;
+                         )cc");
+               }
+             }},
+            {"array_size",
+             [&] {
+               if (generate_array_size_) {
+                 p->Emit(R"cc(
+                   constexpr int $Msg_$::$Enum$_ARRAYSIZE;
+                 )cc");
+               }
+             }},
+        },
+        R"(
+          #if (__cplusplus < 201703) && \
+            (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+          
+          $constexpr_storage$;
+          constexpr $Msg_Enum$ $Msg_$::$Enum$_MIN;
+          constexpr $Msg_Enum$ $Msg_$::$Enum$_MAX;
+          $array_size$;
 
-    for (int i = 0; i < descriptor_->value_count(); i++) {
-      format("constexpr $classname$ $1$::$2$;\n", parent,
-             EnumValueName(descriptor_->value(i)));
-    }
-    format(
-        "constexpr $classname$ $1$::$nested_name$_MIN;\n"
-        "constexpr $classname$ $1$::$nested_name$_MAX;\n",
-        parent);
-    if (generate_array_size_) {
-      format("constexpr int $1$::$nested_name$_ARRAYSIZE;\n", parent);
-    }
-
-    format(
-        "#endif  // (__cplusplus < 201703) && "
-        "(!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))\n");
+          #endif  // (__cplusplus < 201703) &&
+                  // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+        )");
   }
 }
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/enum.h b/src/google/protobuf/compiler/cpp/enum.h
index 610d4fc..58a62f5 100644
--- a/src/google/protobuf/compiler/cpp/enum.h
+++ b/src/google/protobuf/compiler/cpp/enum.h
@@ -35,67 +35,64 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_H__
 
-#include <map>
-#include <set>
 #include <string>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/options.h>
-
-namespace google {
-namespace protobuf {
-namespace io {
-class Printer;  // printer.h
-}
-}  // namespace protobuf
-}  // namespace google
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
 class EnumGenerator {
  public:
-  // See generator.cc for the meaning of dllexport_decl.
-  EnumGenerator(const EnumDescriptor* descriptor,
-                const std::map<std::string, std::string>& vars,
-                const Options& options);
-  ~EnumGenerator();
+  EnumGenerator(const EnumDescriptor* descriptor, const Options& options);
+
+  EnumGenerator(const EnumGenerator&) = delete;
+  EnumGenerator& operator=(const EnumGenerator&) = delete;
+
+  ~EnumGenerator() = default;
 
   // Generate header code defining the enum.  This code should be placed
   // within the enum's package namespace, but NOT within any class, even for
   // nested enums.
-  void GenerateDefinition(io::Printer* printer);
+  void GenerateDefinition(io::Printer* p);
 
   // Generate specialization of GetEnumDescriptor<MyEnum>().
   // Precondition: in ::google::protobuf namespace.
-  void GenerateGetEnumDescriptorSpecializations(io::Printer* printer);
+  void GenerateGetEnumDescriptorSpecializations(io::Printer* p);
 
   // For enums nested within a message, generate code to import all the enum's
   // symbols (e.g. the enum type name, all its values, etc.) into the class's
   // namespace.  This should be placed inside the class definition in the
   // header.
-  void GenerateSymbolImports(io::Printer* printer) const;
+  void GenerateSymbolImports(io::Printer* p) const;
 
   // Source file stuff.
 
   // Generate non-inline methods related to the enum, such as IsValidValue().
   // Goes in the .cc file. EnumDescriptors are stored in an array, idx is
   // the index in this array that corresponds with this enum.
-  void GenerateMethods(int idx, io::Printer* printer);
+  void GenerateMethods(int idx, io::Printer* p);
 
  private:
-  const EnumDescriptor* descriptor_;
-  const std::string classname_;
-  const Options& options_;
-  // whether to generate the *_ARRAYSIZE constant.
-  const bool generate_array_size_;
-
-  std::map<std::string, std::string> variables_;
-
   friend class FileGenerator;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
+
+  struct ValueLimits {
+    const EnumValueDescriptor* min;
+    const EnumValueDescriptor* max;
+
+    static ValueLimits FromEnum(const EnumDescriptor* descriptor);
+  };
+
+  const EnumDescriptor* enum_;
+  Options options_;
+
+  bool generate_array_size_;
+  bool should_cache_;
+  bool has_reflection_;
+  ValueLimits limits_;
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/enum_field.cc b/src/google/protobuf/compiler/cpp/enum_field.cc
index 8ffb699..1221f83 100644
--- a/src/google/protobuf/compiler/cpp/enum_field.cc
+++ b/src/google/protobuf/compiler/cpp/enum_field.cc
@@ -32,13 +32,16 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/enum_field.h>
+#include "google/protobuf/compiler/cpp/enum_field.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/field.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include <string>
+#include <tuple>
+
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -47,9 +50,10 @@
 
 namespace {
 
-void SetEnumVariables(const FieldDescriptor* descriptor,
-                      std::map<std::string, std::string>* variables,
-                      const Options& options) {
+void SetEnumVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   const EnumValueDescriptor* default_value = descriptor->default_value_enum();
   (*variables)["type"] = QualifiedClassName(descriptor->enum_type(), options);
@@ -81,9 +85,10 @@
 void EnumFieldGenerator::GenerateAccessorDeclarations(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
+  format("$deprecated_attr$$type$ ${1$$name$$}$() const;\n", descriptor_);
+  format("$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n",
+         std::make_tuple(descriptor_, GeneratedCodeInfo::Annotation::SET));
   format(
-      "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
-      "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
       "private:\n"
       "$type$ ${1$_internal_$name$$}$() const;\n"
       "void ${1$_internal_set_$name$$}$($type$ value);\n"
@@ -104,7 +109,7 @@
       "  return _internal_$name$();\n"
       "}\n"
       "inline void $classname$::_internal_set_$name$($type$ value) {\n");
-  if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+  if (!internal::cpp::HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
@@ -193,7 +198,7 @@
   Formatter format(printer, variables_);
   format(
       "inline $type$ $classname$::_internal_$name$() const {\n"
-      "  if (_internal_has_$name$()) {\n"
+      "  if ($has_field$) {\n"
       "    return static_cast< $type$ >($field$);\n"
       "  }\n"
       "  return static_cast< $type$ >($default$);\n"
@@ -204,11 +209,11 @@
       "  return _internal_$name$();\n"
       "}\n"
       "inline void $classname$::_internal_set_$name$($type$ value) {\n");
-  if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+  if (!internal::cpp::HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
-      "  if (!_internal_has_$name$()) {\n"
+      "  if ($not_has_field$) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "  }\n"
@@ -252,7 +257,9 @@
   format("::$proto_ns$::RepeatedField<int> $name$_;\n");
   if (descriptor_->is_packed() &&
       HasGeneratedMethods(descriptor_->file(), options_)) {
-    format("mutable std::atomic<int> $cached_byte_size_name$;\n");
+    format(
+        "mutable ::$proto_ns$::internal::CachedSize "
+        "$cached_byte_size_name$;\n");
   }
 }
 
@@ -289,7 +296,7 @@
       "  return _internal_$name$(index);\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, $type$ value) {\n");
-  if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+  if (!internal::cpp::HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
@@ -298,7 +305,7 @@
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline void $classname$::_internal_add_$name$($type$ value) {\n");
-  if (!HasPreservingUnknownEnumSemantics(descriptor_)) {
+  if (!internal::cpp::HasPreservingUnknownEnumSemantics(descriptor_)) {
     format("  assert($type$_IsValid(value));\n");
   }
   format(
@@ -364,7 +371,7 @@
     format(
         "{\n"
         "  int byte_size = "
-        "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"
+        "$cached_byte_size_field$.Get();\n"
         "  if (byte_size > 0) {\n"
         "    target = stream->WriteEnumPacked(\n"
         "        $number$, $field$, byte_size, target);\n"
@@ -384,7 +391,7 @@
   Formatter format(printer, variables_);
   format(
       "{\n"
-      "  size_t data_size = 0;\n"
+      "  ::size_t data_size = 0;\n"
       "  unsigned int count = static_cast<unsigned "
       "int>(this->_internal_$name$_size());");
   format.Indent();
@@ -402,8 +409,7 @@
         "::_pbi::WireFormatLite::Int32Size(static_cast<$int32$>(data_size));\n"
         "}\n"
         "int cached_size = ::_pbi::ToCachedSize(data_size);\n"
-        "$cached_byte_size_field$.store(cached_size,\n"
-        "                                std::memory_order_relaxed);\n"
+        "$cached_byte_size_field$.Set(cached_size);\n"
         "total_size += data_size;\n");
   } else {
     format("total_size += ($tag_size$UL * count) + data_size;\n");
diff --git a/src/google/protobuf/compiler/cpp/enum_field.h b/src/google/protobuf/compiler/cpp/enum_field.h
index 61bae85..496f146 100644
--- a/src/google/protobuf/compiler/cpp/enum_field.h
+++ b/src/google/protobuf/compiler/cpp/enum_field.h
@@ -35,10 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_ENUM_FIELD_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/field.h>
+#include "google/protobuf/compiler/cpp/field.h"
 
 namespace google {
 namespace protobuf {
@@ -48,6 +47,8 @@
 class EnumFieldGenerator : public FieldGenerator {
  public:
   EnumFieldGenerator(const FieldDescriptor* descriptor, const Options& options);
+  EnumFieldGenerator(const EnumFieldGenerator&) = delete;
+  EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
   ~EnumFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -66,15 +67,14 @@
       io::Printer* printer) const override;
   void GenerateAggregateInitializer(io::Printer* printer) const override;
   void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumFieldGenerator);
 };
 
 class EnumOneofFieldGenerator : public EnumFieldGenerator {
  public:
   EnumOneofFieldGenerator(const FieldDescriptor* descriptor,
                           const Options& options);
+  EnumOneofFieldGenerator(const EnumOneofFieldGenerator&) = delete;
+  EnumOneofFieldGenerator& operator=(const EnumOneofFieldGenerator&) = delete;
   ~EnumOneofFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -82,9 +82,6 @@
   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);
 };
 
 class RepeatedEnumFieldGenerator : public FieldGenerator {
@@ -92,6 +89,9 @@
   RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor,
                              const Options& options);
   ~RepeatedEnumFieldGenerator() override;
+  RepeatedEnumFieldGenerator(const RepeatedEnumFieldGenerator&) = delete;
+  RepeatedEnumFieldGenerator& operator=(const RepeatedEnumFieldGenerator&) =
+      delete;
 
   // implements FieldGenerator ---------------------------------------
   void GeneratePrivateMembers(io::Printer* printer) const override;
@@ -112,9 +112,6 @@
       io::Printer* printer) const override;
   void GenerateAggregateInitializer(io::Printer* printer) const override;
   void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedEnumFieldGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/extension.cc b/src/google/protobuf/compiler/cpp/extension.cc
index 950ed9e..3b43ccb 100644
--- a/src/google/protobuf/compiler/cpp/extension.cc
+++ b/src/google/protobuf/compiler/cpp/extension.cc
@@ -32,14 +32,13 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/extension.h>
+#include "google/protobuf/compiler/cpp/extension.h"
 
-#include <map>
-
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -77,7 +76,6 @@
       type_traits_.append(" >");
       break;
   }
-  SetCommonVars(options, &variables_);
   SetCommonMessageDataVariables(descriptor_->containing_type(), &variables_);
   variables_["extendee"] =
       QualifiedClassName(descriptor_->containing_type(), options_);
@@ -86,14 +84,14 @@
   variables_["name"] = ResolveKeyword(name);
   variables_["constant_name"] = FieldConstantName(descriptor_);
   variables_["field_type"] =
-      StrCat(static_cast<int>(descriptor_->type()));
+      absl::StrCat(static_cast<int>(descriptor_->type()));
   variables_["packed"] = descriptor_->is_packed() ? "true" : "false";
 
   std::string scope =
       IsScoped() ? ClassName(descriptor_->extension_scope(), false) + "::" : "";
   variables_["scope"] = scope;
   variables_["scoped_name"] = ExtensionName(descriptor_);
-  variables_["number"] = StrCat(descriptor_->number());
+  variables_["number"] = absl::StrCat(descriptor_->number());
 
   bool add_verify_fn =
       // Only verify msgs.
@@ -104,7 +102,7 @@
 
   variables_["verify_fn"] =
       add_verify_fn
-          ? StrCat("&", FieldMessageTypeName(descriptor_, options_),
+          ? absl::StrCat("&", FieldMessageTypeName(descriptor_, options_),
                          "::InternalVerify")
           : "nullptr";
 }
@@ -159,7 +157,8 @@
     // it in the header which would be annoying for other reasons.  So we
     // replace :: with _ in the name and declare it as a global.
     default_str =
-        StringReplace(variables_["scoped_name"], "::", "_", true) + "_default";
+        absl::StrReplaceAll(variables_["scoped_name"], {{"::", "_"}}) +
+        "_default";
     format("const std::string $1$($2$);\n", default_str,
            DefaultValue(options_, descriptor_));
   } else if (descriptor_->message_type()) {
diff --git a/src/google/protobuf/compiler/cpp/extension.h b/src/google/protobuf/compiler/cpp/extension.h
index 282931f..7044189 100644
--- a/src/google/protobuf/compiler/cpp/extension.h
+++ b/src/google/protobuf/compiler/cpp/extension.h
@@ -35,11 +35,11 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_EXTENSION_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/cpp/options.h>
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -66,6 +66,8 @@
   explicit ExtensionGenerator(const FieldDescriptor* descriptor,
                               const Options& options,
                               MessageSCCAnalyzer* scc_analyzer);
+  ExtensionGenerator(const ExtensionGenerator&) = delete;
+  ExtensionGenerator& operator=(const ExtensionGenerator&) = delete;
   ~ExtensionGenerator();
 
   // Header stuff.
@@ -82,9 +84,7 @@
   Options options_;
   MessageSCCAnalyzer* scc_analyzer_;
 
-  std::map<std::string, std::string> variables_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/field.cc b/src/google/protobuf/compiler/cpp/field.cc
index 90d2084..681b917 100644
--- a/src/google/protobuf/compiler/cpp/field.cc
+++ b/src/google/protobuf/compiler/cpp/field.cc
@@ -32,25 +32,28 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/field.h>
+#include "google/protobuf/compiler/cpp/field.h"
 
 #include <cstdint>
 #include <memory>
 #include <string>
 
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/primitive_field.h>
-#include <google/protobuf/compiler/cpp/string_field.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/compiler/cpp/enum_field.h>
-#include <google/protobuf/compiler/cpp/map_field.h>
-#include <google/protobuf/compiler/cpp/message_field.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "google/protobuf/descriptor.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/primitive_field.h"
+#include "google/protobuf/compiler/cpp/string_field.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/compiler/cpp/enum_field.h"
+#include "google/protobuf/compiler/cpp/map_field.h"
+#include "google/protobuf/compiler/cpp/message_field.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -61,71 +64,73 @@
 
 namespace {
 
-void MaySetAnnotationVariable(const Options& options,
-                              StringPiece annotation_name,
-                              StringPiece substitute_template_prefix,
-                              StringPiece prepared_template,
-                              int field_index, StringPiece access_type,
-                              std::map<std::string, std::string>* variables) {
-  if (options.field_listener_options.forbidden_field_listener_events.count(
-          std::string(annotation_name)))
+void MaySetAnnotationVariable(
+    const Options& options, absl::string_view annotation_name,
+    absl::string_view substitute_template_prefix,
+    absl::string_view prepared_template, int field_index,
+    absl::string_view access_type,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
+  if (options.field_listener_options.forbidden_field_listener_events.contains(
+          annotation_name))
     return;
-  (*variables)[StrCat("annotate_", annotation_name)] = strings::Substitute(
-      StrCat(substitute_template_prefix, prepared_template, ");\n"),
+  (*variables)[absl::StrCat("annotate_", annotation_name)] = absl::Substitute(
+      absl::StrCat(substitute_template_prefix, prepared_template, ");\n"),
       field_index, access_type);
 }
 
 std::string GenerateTemplateForOneofString(const FieldDescriptor* descriptor,
-                                           StringPiece proto_ns,
-                                           StringPiece field_member) {
+                                           absl::string_view proto_ns,
+                                           absl::string_view field_member) {
   std::string field_name = google::protobuf::compiler::cpp::FieldName(descriptor);
   std::string field_pointer =
       descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
           ? "$0.UnsafeGetPointer()"
           : "$0";
+  std::string has_field = absl::StrFormat(
+      "%s_case() == k%s", descriptor->containing_oneof()->name(),
+      UnderscoresToCamelCase(descriptor->name(), true));
 
   if (descriptor->default_value_string().empty()) {
-    return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
-                                         field_pointer, ": nullptr"),
-                            field_member);
+    return absl::Substitute(
+        absl::StrCat(has_field, " ? ", field_pointer, ": nullptr"),
+        field_member);
   }
 
   if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING_PIECE) {
-    return strings::Substitute(StrCat("_internal_has_", field_name, "() ? ",
-                                         field_pointer, ": nullptr"),
-                            field_member);
+    return absl::Substitute(
+        absl::StrCat(has_field, " ? ", field_pointer, ": nullptr"),
+        field_member);
   }
 
   std::string default_value_pointer =
       descriptor->options().ctype() == google::protobuf::FieldOptions::STRING
           ? "&$1.get()"
           : "&$1";
-  return strings::Substitute(
-      StrCat("_internal_has_", field_name, "() ? ", field_pointer, " : ",
-                   default_value_pointer),
-      field_member, MakeDefaultFieldName(descriptor));
+  return absl::Substitute(absl::StrCat(has_field, " ? ", field_pointer, " : ",
+                                       default_value_pointer),
+                          field_member, MakeDefaultFieldName(descriptor));
 }
 
 std::string GenerateTemplateForSingleString(const FieldDescriptor* descriptor,
-                                            StringPiece field_member) {
+                                            absl::string_view field_member) {
   if (descriptor->default_value_string().empty()) {
-    return StrCat("&", field_member);
+    return absl::StrCat("&", field_member);
   }
 
   if (descriptor->options().ctype() == google::protobuf::FieldOptions::STRING) {
-    return strings::Substitute(
+    return absl::Substitute(
         "$0.IsDefault() ? &$1.get() : $0.UnsafeGetPointer()", field_member,
         MakeDefaultFieldName(descriptor));
   }
 
-  return StrCat("&", field_member);
+  return absl::StrCat("&", field_member);
 }
 
 }  // namespace
 
-void AddAccessorAnnotations(const FieldDescriptor* descriptor,
-                            const Options& options,
-                            std::map<std::string, std::string>* variables) {
+void AddAccessorAnnotations(
+    const FieldDescriptor* descriptor, const Options& options,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   // Can be expanded to include more specific calls, for example, for arena or
   // clear calls.
   static constexpr const char* kAccessorsAnnotations[] = {
@@ -134,12 +139,12 @@
       "annotate_release", "annotate_set",         "annotate_size",
       "annotate_clear",   "annotate_add_mutable",
   };
-  for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
+  for (size_t i = 0; i < ABSL_ARRAYSIZE(kAccessorsAnnotations); ++i) {
     (*variables)[kAccessorsAnnotations[i]] = "";
   }
   if (options.annotate_accessor) {
-    for (size_t i = 0; i < GOOGLE_ARRAYSIZE(kAccessorsAnnotations); ++i) {
-      (*variables)[kAccessorsAnnotations[i]] = StrCat(
+    for (size_t i = 0; i < ABSL_ARRAYSIZE(kAccessorsAnnotations); ++i) {
+      (*variables)[kAccessorsAnnotations[i]] = absl::StrCat(
           "  ", FieldName(descriptor), "_AccessedNoStrip = true;\n");
     }
   }
@@ -153,9 +158,8 @@
   std::string field_member = (*variables)["field"];
   const google::protobuf::OneofDescriptor* oneof_member =
       descriptor->real_containing_oneof();
-  const std::string proto_ns = (*variables)["proto_ns"];
   const std::string substitute_template_prefix =
-      StrCat("  ", (*variables)["tracker"], ".$1<$0>(this, ");
+      absl::StrCat("  ", (*variables)["tracker"], ".$1<$0>(this, ");
   std::string prepared_template;
 
   // Flat template is needed if the prepared one is introspecting the values
@@ -166,9 +170,9 @@
   if (descriptor->is_repeated() && !descriptor->is_map()) {
     if (descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
         descriptor->type() != FieldDescriptor::TYPE_GROUP) {
-      prepared_template = strings::Substitute("&$0.Get(index)", field_member);
+      prepared_template = absl::Substitute("&$0.Get(index)", field_member);
       prepared_add_template =
-          strings::Substitute("&$0.Get($0.size() - 1)", field_member);
+          absl::Substitute("&$0.Get($0.size() - 1)", field_member);
     } else {
       prepared_template = "nullptr";
       prepared_add_template = "nullptr";
@@ -181,18 +185,18 @@
   } else if (descriptor->cpp_type() == FieldDescriptor::CPPTYPE_STRING) {
     if (oneof_member) {
       prepared_template = GenerateTemplateForOneofString(
-          descriptor, (*variables)["proto_ns"], field_member);
+          descriptor, ProtobufNamespace(options), field_member);
     } else {
       prepared_template =
           GenerateTemplateForSingleString(descriptor, field_member);
     }
   } else {
-    prepared_template = StrCat("&", field_member);
+    prepared_template = absl::StrCat("&", field_member);
   }
   if (descriptor->is_repeated() && !descriptor->is_map() &&
       descriptor->type() != FieldDescriptor::TYPE_MESSAGE &&
       descriptor->type() != FieldDescriptor::TYPE_GROUP) {
-    prepared_flat_template = StrCat("&", field_member);
+    prepared_flat_template = absl::StrCat("&", field_member);
   } else {
     prepared_flat_template = prepared_template;
   }
@@ -232,51 +236,101 @@
                            "OnAddMutable", variables);
 }
 
-void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             std::map<std::string, std::string>* variables,
-                             const Options& options) {
-  SetCommonVars(options, variables);
+absl::flat_hash_map<absl::string_view, std::string> FieldVars(
+    const FieldDescriptor* desc, const Options& opts) {
+  bool split = ShouldSplit(desc, opts);
+  absl::flat_hash_map<absl::string_view, std::string> vars = {
+      {"ns", Namespace(desc, opts)},
+      {"name", FieldName(desc)},
+      {"index", absl::StrCat(desc->index())},
+      {"number", absl::StrCat(desc->number())},
+      {"classname", ClassName(FieldScope(desc), false)},
+      {"declared_type", DeclaredTypeMethodName(desc->type())},
+      {"field", FieldMemberName(desc, split)},
+      {"tag_size",
+       absl::StrCat(WireFormat::TagSize(desc->number(), desc->type()))},
+      {"deprecated_attr", DeprecatedAttribute(opts, desc)},
+      {"set_hasbit", ""},
+      {"clear_hasbit", ""},
+      {"maybe_prepare_split_message",
+       split ? "PrepareSplitMessageForWrite();" : ""},
+
+      // 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.
+      {"{", ""},
+      {"}", ""},
+  };
+
+  // TODO(b/245791219): Refactor AddAccessorAnnotations to avoid this
+  // workaround.
+  absl::flat_hash_map<absl::string_view, std::string> workaround = {
+      {"field", vars["field"]},
+      {"tracker", "Impl_::_tracker_"},
+  };
+  AddAccessorAnnotations(desc, opts, &workaround);
+  for (auto& pair : workaround) {
+    vars.emplace(pair);
+  }
+
+  return vars;
+}
+
+void SetCommonFieldVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    const Options& options) {
   SetCommonMessageDataVariables(descriptor->containing_type(), variables);
 
-  (*variables)["ns"] = Namespace(descriptor, options);
-  (*variables)["name"] = FieldName(descriptor);
-  (*variables)["index"] = StrCat(descriptor->index());
-  (*variables)["number"] = StrCat(descriptor->number());
-  (*variables)["classname"] = ClassName(FieldScope(descriptor), false);
-  (*variables)["declared_type"] = DeclaredTypeMethodName(descriptor->type());
-  bool split = ShouldSplit(descriptor, options);
-  (*variables)["field"] = FieldMemberName(descriptor, split);
+  for (auto& pair : FieldVars(descriptor, options)) {
+    variables->emplace(pair);
+  }
+}
 
-  (*variables)["tag_size"] = StrCat(
-      WireFormat::TagSize(descriptor->number(), descriptor->type()));
-  (*variables)["deprecated_attr"] = DeprecatedAttribute(options, descriptor);
+absl::flat_hash_map<absl::string_view, std::string> OneofFieldVars(
+    const FieldDescriptor* descriptor) {
+  if (descriptor->containing_oneof() == nullptr) {
+    return {};
+  }
+  std::string oneof_name = descriptor->containing_oneof()->name();
+  std::string field_name = UnderscoresToCamelCase(descriptor->name(), true);
 
-  (*variables)["set_hasbit"] = "";
-  (*variables)["clear_hasbit"] = "";
-  (*variables)["maybe_prepare_split_message"] =
-      split ? "  PrepareSplitMessageForWrite();\n" : "";
+  return {
+      {"oneof_name", oneof_name},
+      {"field_name", field_name},
+      {"oneof_index", absl::StrCat(descriptor->containing_oneof()->index())},
+      {"has_field",
+       absl::StrFormat("%s_case() == k%s", oneof_name, field_name)},
+      {"not_has_field",
+       absl::StrFormat("%s_case() != k%s", oneof_name, field_name)},
+  };
+}
 
-  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
-  // be ambiguous or impossible). They should never be set to anything but the
-  // empty string.
-  (*variables)["{"] = "";
-  (*variables)["}"] = "";
+void SetCommonOneofFieldVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
+  for (auto& pair : OneofFieldVars(descriptor)) {
+    variables->emplace(pair);
+  }
 }
 
 void FieldGenerator::SetHasBitIndex(int32_t has_bit_index) {
-  if (!HasHasbit(descriptor_)) {
+  if (!internal::cpp::HasHasbit(descriptor_) || has_bit_index < 0) {
     GOOGLE_CHECK_EQ(has_bit_index, -1);
     return;
   }
-  variables_["set_hasbit"] = StrCat(
-      variables_["has_bits"], "[", has_bit_index / 32, "] |= 0x",
-      strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
-  variables_["clear_hasbit"] = StrCat(
-      variables_["has_bits"], "[", has_bit_index / 32, "] &= ~0x",
-      strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8), "u;");
+  int32_t index = has_bit_index / 32;
+  std::string mask =
+      absl::StrCat(absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8));
+  const std::string& has_bits = variables_["has_bits"];
+
+  variables_["has_hasbit"] =
+      absl::StrFormat("%s[%d] & 0x%su", has_bits, index, mask);
+  variables_["set_hasbit"] =
+      absl::StrFormat("%s[%d] |= 0x%su;", has_bits, index, mask);
+  variables_["clear_hasbit"] =
+      absl::StrFormat("%s[%d] &= ~0x%su;", has_bits, index, mask);
 }
 
 void FieldGenerator::SetInlinedStringIndex(int32_t inlined_string_index) {
@@ -287,16 +341,16 @@
   // The first bit is the tracking bit for on demand registering ArenaDtor.
   GOOGLE_CHECK_GT(inlined_string_index, 0)
       << "_inlined_string_donated_'s bit 0 is reserved for arena dtor tracking";
-  variables_["inlined_string_donated"] = StrCat(
+  variables_["inlined_string_donated"] = absl::StrCat(
       "(", variables_["inlined_string_donated_array"], "[",
       inlined_string_index / 32, "] & 0x",
-      strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8),
+      absl::Hex(1u << (inlined_string_index % 32), absl::kZeroPad8),
       "u) != 0;");
   variables_["donating_states_word"] =
-      StrCat(variables_["inlined_string_donated_array"], "[",
+      absl::StrCat(variables_["inlined_string_donated_array"], "[",
                    inlined_string_index / 32, "]");
-  variables_["mask_for_undonate"] = StrCat(
-      "~0x", strings::Hex(1u << (inlined_string_index % 32), strings::ZERO_PAD_8),
+  variables_["mask_for_undonate"] = absl::StrCat(
+      "~0x", absl::Hex(1u << (inlined_string_index % 32), absl::kZeroPad8),
       "u");
 }
 
@@ -330,11 +384,12 @@
   }
 }
 
-void SetCommonOneofFieldVariables(
-    const FieldDescriptor* descriptor,
-    std::map<std::string, std::string>* variables) {
-  const std::string prefix = descriptor->containing_oneof()->name() + "_.";
-  (*variables)["oneof_name"] = descriptor->containing_oneof()->name();
+void FieldGenerator::GenerateIfHasField(io::Printer* printer) const {
+  GOOGLE_CHECK(internal::cpp::HasHasbit(descriptor_));
+  GOOGLE_CHECK(variables_.find("has_hasbit") != variables_.end());
+
+  Formatter format(printer, variables_);
+  format("if (($has_hasbit$) != 0) {\n");
 }
 
 FieldGenerator::~FieldGenerator() {}
diff --git a/src/google/protobuf/compiler/cpp/field.h b/src/google/protobuf/compiler/cpp/field.h
index dd2a51a..a196918 100644
--- a/src/google/protobuf/compiler/cpp/field.h
+++ b/src/google/protobuf/compiler/cpp/field.h
@@ -36,13 +36,13 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_FIELD_H__
 
 #include <cstdint>
-#include <map>
 #include <memory>
 #include <string>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/options.h>
+#include "google/protobuf/descriptor.h"
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/options.h"
 
 namespace google {
 namespace protobuf {
@@ -57,23 +57,32 @@
 namespace compiler {
 namespace cpp {
 
+absl::flat_hash_map<absl::string_view, std::string> FieldVars(
+    const FieldDescriptor* desc, const Options& opts);
+
+absl::flat_hash_map<absl::string_view, std::string> OneofFieldVars(
+    const FieldDescriptor* descriptor);
+
 // Helper function: set variables in the map that are the same for all
 // field code generators.
 // ['name', 'index', 'number', 'classname', 'declared_type', 'tag_size',
 // 'deprecation'].
-void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             std::map<std::string, std::string>* variables,
-                             const Options& options);
+void SetCommonFieldVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    const Options& options);
 
 void SetCommonOneofFieldVariables(
     const FieldDescriptor* descriptor,
-    std::map<std::string, std::string>* variables);
+    absl::flat_hash_map<absl::string_view, std::string>* variables);
 
 class FieldGenerator {
  public:
   explicit FieldGenerator(const FieldDescriptor* descriptor,
                           const Options& options)
       : descriptor_(descriptor), options_(options) {}
+  FieldGenerator(const FieldGenerator&) = delete;
+  FieldGenerator& operator=(const FieldGenerator&) = delete;
   virtual ~FieldGenerator();
   virtual void GenerateSerializeWithCachedSizes(
       io::Printer* printer) const final{};
@@ -150,9 +159,6 @@
   // method, invoked by each of the generated constructors.
   virtual void GenerateConstructorCode(io::Printer* printer) const = 0;
 
-  // Generate initialization code for private members in the cold struct.
-  virtual void GenerateCreateSplitMessageCode(io::Printer* printer) const {}
-
   // Generate any code that needs to go in the class's SharedDtor() method,
   // invoked by the destructor.
   // Most field types don't need this, so the default implementation is empty.
@@ -209,6 +215,8 @@
   // message fields won't need to override this function.
   virtual void GenerateIsInitialized(io::Printer* printer) const {}
 
+  virtual void GenerateIfHasField(io::Printer* printer) const;
+
   virtual bool IsInlined() const { return false; }
 
   virtual ArenaDtorNeeds NeedsArenaDestructor() const {
@@ -221,10 +229,7 @@
  protected:
   const FieldDescriptor* descriptor_;
   const Options& options_;
-  std::map<std::string, std::string> variables_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGenerator);
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
 };
 
 // Convenience class which constructs FieldGenerators for a Descriptor.
@@ -232,6 +237,8 @@
  public:
   FieldGeneratorMap(const Descriptor* descriptor, const Options& options,
                     MessageSCCAnalyzer* scc_analyzer);
+  FieldGeneratorMap(const FieldGeneratorMap&) = delete;
+  FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete;
   ~FieldGeneratorMap();
 
   const FieldGenerator& get(const FieldDescriptor* field) const;
@@ -258,8 +265,6 @@
   static FieldGenerator* MakeGenerator(const FieldDescriptor* field,
                                        const Options& options,
                                        MessageSCCAnalyzer* scc_analyzer);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/file.cc b/src/google/protobuf/compiler/cpp/file.cc
index 838e0ab..afba7ef 100644
--- a/src/google/protobuf/compiler/cpp/file.cc
+++ b/src/google/protobuf/compiler/cpp/file.cc
@@ -32,132 +32,137 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/file.h>
+#include "google/protobuf/compiler/cpp/file.h"
 
 #include <iostream>
-#include <map>
 #include <memory>
-#include <set>
-#include <unordered_map>
-#include <unordered_set>
+#include <string>
+#include <utility>
 #include <vector>
 
-#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/enum.h>
-#include <google/protobuf/compiler/cpp/extension.h>
-#include <google/protobuf/compiler/cpp/field.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/message.h>
-#include <google/protobuf/compiler/cpp/service.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "google/protobuf/compiler/scc.h"
+#include "absl/container/btree_map.h"
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "google/protobuf/compiler/cpp/enum.h"
+#include "google/protobuf/compiler/cpp/extension.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/message.h"
+#include "google/protobuf/compiler/cpp/names.h"
+#include "google/protobuf/compiler/cpp/service.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
 namespace {
-
-// When we forward-declare things, we want to create a sorted order so our
-// output is deterministic and minimizes namespace changes.
-template <class T>
-std::string GetSortKey(const T& val) {
-  return val.full_name();
-}
-
-template <>
-std::string GetSortKey<FileDescriptor>(const FileDescriptor& val) {
-  return val.name();
-}
-
-template <class T>
-bool CompareSortKeys(const T* a, const T* b) {
-  return GetSortKey(*a) < GetSortKey(*b);
-}
-
-template <class T>
-std::vector<const T*> Sorted(const std::unordered_set<const T*>& vals) {
-  std::vector<const T*> sorted(vals.begin(), vals.end());
-  std::sort(sorted.begin(), sorted.end(), CompareSortKeys<T>);
-  return sorted;
+absl::flat_hash_map<absl::string_view, std::string> FileVars(
+    const FileDescriptor* file, const Options& options) {
+  return {
+      {"filename", file->name()},
+      {"package_ns", Namespace(file, options)},
+      {"tablename", UniqueName("TableStruct", file, options)},
+      {"desc_table", DescriptorTableName(file, options)},
+      {"dllexport_decl", options.dllexport_decl},
+      {"file_level_metadata", UniqueName("file_level_metadata", file, options)},
+      {"file_level_enum_descriptors",
+       UniqueName("file_level_enum_descriptors", file, options)},
+      {"file_level_service_descriptors",
+       UniqueName("file_level_service_descriptors", file, options)},
+  };
 }
 
 // TODO(b/203101078): remove pragmas that suppresses uninitialized warnings when
 // clang bug is fixed.
-inline void MuteWuninitialized(Formatter& format) {
-  format(
-      "#if defined(__llvm__)\n"
-      "  #pragma clang diagnostic push\n"
-      "  #pragma clang diagnostic ignored \"-Wuninitialized\"\n"
-      "#endif  // __llvm__\n");
+void MuteWuninitialized(io::Printer* p) {
+  p->Emit(R"(
+    #if defined(__llvm__)
+    #pragma clang diagnostic push
+    #pragma clang diagnostic ignored "-Wuninitialized"
+    #endif  // __llvm__
+  )");
 }
 
-inline void UnmuteWuninitialized(Formatter& format) {
-  format(
-      "#if defined(__llvm__)\n"
-      "  #pragma clang diagnostic pop\n"
-      "#endif  // __llvm__\n");
+void UnmuteWuninitialized(io::Printer* p) {
+  p->Emit(R"(
+    #if defined(__llvm__)
+    #pragma clang diagnostic pop
+    #endif  // __llvm__
+  )");
 }
-
 }  // namespace
 
 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options)
     : file_(file), options_(options), scc_analyzer_(options) {
-  // These variables are the same on a file level
-  SetCommonVars(options, &variables_);
-  variables_["dllexport_decl"] = options.dllexport_decl;
-  variables_["tablename"] = UniqueName("TableStruct", file_, options_);
-  variables_["file_level_metadata"] =
-      UniqueName("file_level_metadata", file_, options_);
-  variables_["desc_table"] = DescriptorTableName(file_, options_);
-  variables_["file_level_enum_descriptors"] =
-      UniqueName("file_level_enum_descriptors", file_, options_);
-  variables_["file_level_service_descriptors"] =
-      UniqueName("file_level_service_descriptors", file_, options_);
-  variables_["filename"] = file_->name();
-  variables_["package_ns"] = Namespace(file_, options);
-
   std::vector<const Descriptor*> msgs = FlattenMessagesInFile(file);
-  for (int i = 0; i < msgs.size(); i++) {
-    // Deleted in destructor
-    MessageGenerator* msg_gen =
-        new MessageGenerator(msgs[i], variables_, i, options, &scc_analyzer_);
-    message_generators_.emplace_back(msg_gen);
-    msg_gen->AddGenerators(&enum_generators_, &extension_generators_);
+
+  for (int i = 0; i < msgs.size(); ++i) {
+    message_generators_.push_back(std::make_unique<MessageGenerator>(
+        msgs[i], variables_, i, options, &scc_analyzer_));
+    message_generators_.back()->AddGenerators(&enum_generators_,
+                                              &extension_generators_);
   }
 
-  for (int i = 0; i < file->enum_type_count(); i++) {
-    enum_generators_.emplace_back(
-        new EnumGenerator(file->enum_type(i), variables_, options));
+  for (int i = 0; i < file->enum_type_count(); ++i) {
+    enum_generators_.push_back(
+        std::make_unique<EnumGenerator>(file->enum_type(i), options));
   }
 
-  for (int i = 0; i < file->service_count(); i++) {
-    service_generators_.emplace_back(
-        new ServiceGenerator(file->service(i), variables_, options));
+  for (int i = 0; i < file->service_count(); ++i) {
+    service_generators_.push_back(std::make_unique<ServiceGenerator>(
+        file->service(i), variables_, options));
   }
   if (HasGenericServices(file_, options_)) {
-    for (int i = 0; i < service_generators_.size(); i++) {
+    for (int i = 0; i < service_generators_.size(); ++i) {
       service_generators_[i]->index_in_metadata_ = i;
     }
   }
-  for (int i = 0; i < file->extension_count(); i++) {
-    extension_generators_.emplace_back(
-        new ExtensionGenerator(file->extension(i), options, &scc_analyzer_));
+
+  for (int i = 0; i < file->extension_count(); ++i) {
+    extension_generators_.push_back(std::make_unique<ExtensionGenerator>(
+        file->extension(i), options, &scc_analyzer_));
   }
+
   for (int i = 0; i < file->weak_dependency_count(); ++i) {
     weak_deps_.insert(file->weak_dependency(i));
   }
 }
 
-FileGenerator::~FileGenerator() = default;
+void FileGenerator::GenerateFile(io::Printer* p, GeneratedFileType file_type,
+                                 std::function<void()> cb) {
+  auto v = p->WithVars(FileVars(file_, options_));
+  auto guard = IncludeGuard(file_, file_type, options_);
+  p->Emit({{"cb", cb}, {"guard", guard}}, R"(
+    // Generated by the protocol buffer compiler.  DO NOT EDIT!
+    // source: $filename$
 
-void FileGenerator::GenerateMacroUndefs(io::Printer* printer) {
-  Formatter format(printer, variables_);
+    #ifndef $guard$
+    #define $guard$
+
+    #include <limits>
+    #include <string>
+    #include <type_traits>
+
+    $cb$;
+
+    #endif  // $guard$
+  )");
+}
+
+void FileGenerator::GenerateMacroUndefs(io::Printer* p) {
   // Only do this for protobuf's own types. There are some google3 protos using
   // macros as field names and the generated code compiles after the macro
   // expansion. Undefing these macros actually breaks such code.
@@ -165,410 +170,480 @@
       file_->name() != "google/protobuf/compiler/plugin.proto") {
     return;
   }
-  std::vector<std::string> names_to_undef;
+
   std::vector<const FieldDescriptor*> fields;
   ListAllFields(file_, &fields);
-  for (int i = 0; i < fields.size(); i++) {
-    const std::string& name = fields[i]->name();
-    static const char* kMacroNames[] = {"major", "minor"};
-    for (int j = 0; j < GOOGLE_ARRAYSIZE(kMacroNames); ++j) {
-      if (name == kMacroNames[j]) {
-        names_to_undef.push_back(name);
-        break;
-      }
+
+  absl::flat_hash_set<absl::string_view> all_fields;
+  for (const FieldDescriptor* field : fields) {
+    all_fields.insert(field->name());
+  }
+
+  for (absl::string_view name : {"major", "minor"}) {
+    if (!all_fields.contains(name)) {
+      continue;
     }
-  }
-  for (int i = 0; i < names_to_undef.size(); ++i) {
-    format(
-        "#ifdef $1$\n"
-        "#undef $1$\n"
-        "#endif\n",
-        names_to_undef[i]);
+
+    p->Emit({{"name", std::string(name)}}, R"(
+      #ifdef $name$
+      #undef $name$
+      #endif  // $name$
+    )");
   }
 }
 
-void FileGenerator::GenerateHeader(io::Printer* printer) {
-  Formatter format(printer, variables_);
 
-  // port_def.inc must be included after all other includes.
-  IncludeFile("net/proto2/public/port_def.inc", printer);
-  format("#define $1$$ dllexport_decl$\n", FileDllExport(file_, options_));
-  GenerateMacroUndefs(printer);
+void FileGenerator::GenerateSharedHeaderCode(io::Printer* p) {
+  p->Emit(
+      {
+          {"port_def",
+           [&] { IncludeFile("net/proto2/public/port_def.inc", p); }},
+          {"port_undef",
+           [&] { IncludeFile("net/proto2/public/port_undef.inc", p); }},
+          {"dllexport_macro", FileDllExport(file_, options_)},
+          {"undefs", [&] { GenerateMacroUndefs(p); }},
+          {"global_state_decls",
+           [&] { GenerateGlobalStateFunctionDeclarations(p); }},
+          {"fwd_decls", [&] { GenerateForwardDeclarations(p); }},
+          {"proto2_ns_enums",
+           [&] { GenerateProto2NamespaceEnumSpecializations(p); }},
+          {"main_decls",
+           [&] {
+             NamespaceOpener ns(Namespace(file_, options_), p);
+             p->Emit(
+                 {
+                     {"enums", [&] { GenerateEnumDefinitions(p); }},
+                     {"messages", [&] { GenerateMessageDefinitions(p); }},
+                     {"services", [&] { GenerateServiceDefinitions(p); }},
+                     {"extensions", [&] { GenerateExtensionIdentifiers(p); }},
+                     {"inline_fns",
+                      [&] { GenerateInlineFunctionDefinitions(p); }},
+                 },
+                 R"(
+                   $enums$
 
-  // For Any support with lite protos, we need to friend AnyMetadata, so we
-  // forward-declare it here.
-  format(
-      "PROTOBUF_NAMESPACE_OPEN\n"
-      "namespace internal {\n"
-      "class AnyMetadata;\n"
-      "}  // namespace internal\n"
-      "PROTOBUF_NAMESPACE_CLOSE\n");
+                   $hrule_thick$
 
-  GenerateGlobalStateFunctionDeclarations(printer);
+                   $messages$
 
-  GenerateForwardDeclarations(printer);
+                   $hrule_thick$
 
-  {
-    NamespaceOpener ns(Namespace(file_, options_), format);
+                   $services$
 
-    format("\n");
+                   $extensions$
 
-    GenerateEnumDefinitions(printer);
+                   $hrule_thick$
 
-    format(kThickSeparator);
-    format("\n");
+                   $inline_fns$
 
-    GenerateMessageDefinitions(printer);
+                   // @@protoc_insertion_point(namespace_scope)
+                 )");
+           }},
+      },
+      R"(
+          // Must be included last.
+          $port_def$
 
-    format("\n");
-    format(kThickSeparator);
-    format("\n");
+          #define $dllexport_macro$$ dllexport_decl$
+          $undefs$
 
-    GenerateServiceDefinitions(printer);
+          PROTOBUF_NAMESPACE_OPEN
+          namespace internal {
+          class AnyMetadata;
+          }  // namespace internal
+          PROTOBUF_NAMESPACE_CLOSE
 
-    GenerateExtensionIdentifiers(printer);
+          $global_state_decls$;
+          $fwd_decls$
 
-    format("\n");
-    format(kThickSeparator);
-    format("\n");
+          $main_decls$
 
-    GenerateInlineFunctionDefinitions(printer);
+          $proto2_ns_enums$
 
-    format(
-        "\n"
-        "// @@protoc_insertion_point(namespace_scope)\n"
-        "\n");
-  }
+          // @@protoc_insertion_point(global_scope)
 
-  // We need to specialize some templates in the ::google::protobuf namespace:
-  GenerateProto2NamespaceEnumSpecializations(printer);
-
-  format(
-      "\n"
-      "// @@protoc_insertion_point(global_scope)\n"
-      "\n");
-  IncludeFile("net/proto2/public/port_undef.inc", printer);
+          $port_undef$
+      )");
 }
 
-void FileGenerator::GenerateProtoHeader(io::Printer* printer,
-                                        const std::string& info_path) {
-  Formatter format(printer, variables_);
+void FileGenerator::GenerateProtoHeader(io::Printer* p,
+                                        absl::string_view info_path) {
   if (!options_.proto_h) {
     return;
   }
 
-  GenerateTopHeaderGuard(printer, false);
-
-  if (!options_.opensource_runtime) {
-    format(
-        "#ifdef SWIG\n"
-        "#error \"Do not SWIG-wrap protobufs.\"\n"
-        "#endif  // SWIG\n"
-        "\n");
-  }
-
-  if (IsBootstrapProto(options_, file_)) {
-    format("// IWYU pragma: private, include \"$1$.proto.h\"\n\n",
-           StripProto(file_->name()));
-  }
-
-  GenerateLibraryIncludes(printer);
-
-  for (int i = 0; i < file_->public_dependency_count(); i++) {
-    const FileDescriptor* dep = file_->public_dependency(i);
-    format("#include \"$1$.proto.h\"\n", StripProto(dep->name()));
-  }
-
-  format("// @@protoc_insertion_point(includes)\n");
-
-  GenerateMetadataPragma(printer, info_path);
-
-  GenerateHeader(printer);
-
-  GenerateBottomHeaderGuard(printer, false);
-}
-
-void FileGenerator::GeneratePBHeader(io::Printer* printer,
-                                     const std::string& info_path) {
-  Formatter format(printer, variables_);
-  GenerateTopHeaderGuard(printer, true);
-
-  if (options_.proto_h) {
-    std::string target_basename = StripProto(file_->name());
+  GenerateFile(p, GeneratedFileType::kProtoH, [&] {
     if (!options_.opensource_runtime) {
-      GetBootstrapBasename(options_, target_basename, &target_basename);
+      p->Emit(R"(
+          #ifdef SWIG
+          #error "Do not SWIG-wrap protobufs."
+          #endif  // SWIG
+        )");
     }
-    format("#include \"$1$.proto.h\"  // IWYU pragma: export\n",
-           target_basename);
-  } else {
-    GenerateLibraryIncludes(printer);
-  }
-
-  if (options_.transitive_pb_h) {
-    GenerateDependencyIncludes(printer);
-  }
-
-  // This is unfortunately necessary for some plugins. I don't see why we
-  // need two of the same insertion points.
-  // TODO(gerbens) remove this.
-  format("// @@protoc_insertion_point(includes)\n");
-
-  GenerateMetadataPragma(printer, info_path);
-
-  if (!options_.proto_h) {
-    GenerateHeader(printer);
-  } else {
-    {
-      NamespaceOpener ns(Namespace(file_, options_), format);
-      format(
-          "\n"
-          "// @@protoc_insertion_point(namespace_scope)\n");
+    if (IsBootstrapProto(options_, file_)) {
+      p->Emit({{"name", StripProto(file_->name())}}, R"cc(
+        // IWYU pragma: private, include "$name$.proto.h"
+      )cc");
     }
-    format(
-        "\n"
-        "// @@protoc_insertion_point(global_scope)\n"
-        "\n");
-  }
 
-  GenerateBottomHeaderGuard(printer, true);
+    p->Emit(
+        {
+            {"library_includes", [&] { GenerateLibraryIncludes(p); }},
+            {"proto_includes",
+             [&] {
+               for (int i = 0; i < file_->public_dependency_count(); ++i) {
+                 const FileDescriptor* dep = file_->public_dependency(i);
+                 p->Emit({{"name", StripProto(dep->name())}}, R"(
+                    #include "$name$.proto.h"
+                 )");
+               }
+             }},
+            {"metadata_pragma", [&] { GenerateMetadataPragma(p, info_path); }},
+            {"header_main", [&] { GenerateSharedHeaderCode(p); }},
+        },
+        R"cc(
+          $library_includes$;
+          $proto_includes$;
+          // @@protoc_insertion_point(includes)
+
+          $metadata_pragma$;
+          $header_main$;
+        )cc");
+  });
 }
 
-void FileGenerator::DoIncludeFile(const std::string& google3_name,
-                                  bool do_export, io::Printer* printer) {
-  Formatter format(printer, variables_);
-  const std::string prefix = "net/proto2/";
-  GOOGLE_CHECK(google3_name.find(prefix) == 0) << google3_name;
+void FileGenerator::GeneratePBHeader(io::Printer* p,
+                                     absl::string_view info_path) {
+  GenerateFile(p, GeneratedFileType::kPbH, [&] {
+    p->Emit(
+        {
+            {"library_includes",
+             [&] {
+               if (options_.proto_h) {
+                 std::string target_basename = StripProto(file_->name());
+                 if (!options_.opensource_runtime) {
+                   GetBootstrapBasename(options_, target_basename,
+                                        &target_basename);
+                 }
+                 p->Emit({{"name", target_basename}}, R"(
+              #include "$name$.proto.h"  // IWYU pragma: export
+              )");
+               } else {
+                 GenerateLibraryIncludes(p);
+               }
+             }},
+            {"proto_includes",
+             [&] {
+               if (options_.transitive_pb_h) {
+                 GenerateDependencyIncludes(p);
+               }
+             }},
+            {"metadata_pragma", [&] { GenerateMetadataPragma(p, info_path); }},
+            {"header_main",
+             [&] {
+               if (!options_.proto_h) {
+                 GenerateSharedHeaderCode(p);
+                 return;
+               }
+
+               {
+                 NamespaceOpener ns(Namespace(file_, options_), p);
+                 p->Emit(R"cc(
+
+                   // @@protoc_insertion_point(namespace_scope)
+                 )cc");
+               }
+               p->Emit(R"cc(
+
+                 // @@protoc_insertion_point(global_scope)
+               )cc");
+             }},
+        },
+        R"cc(
+          $library_includes$;
+          $proto_includes$;
+          // @@protoc_insertion_point(includes)
+
+          $metadata_pragma$;
+          $header_main$;
+        )cc");
+  });
+}
+
+void FileGenerator::DoIncludeFile(absl::string_view google3_name,
+                                  bool do_export, io::Printer* p) {
+  constexpr absl::string_view prefix = "net/proto2/";
+  GOOGLE_CHECK(absl::StartsWith(google3_name, prefix)) << google3_name;
+
+  auto v = p->WithVars(
+      {{"export_suffix", do_export ? "// IWYU pragma: export" : ""}});
 
   if (options_.opensource_runtime) {
-    std::string path = google3_name.substr(prefix.size());
+    absl::ConsumePrefix(&google3_name, prefix);
+    absl::ConsumePrefix(&google3_name, "internal/");
+    absl::ConsumePrefix(&google3_name, "proto/");
+    absl::ConsumePrefix(&google3_name, "public/");
 
-    path = StringReplace(path, "internal/", "", false);
-    path = StringReplace(path, "proto/", "", false);
-    path = StringReplace(path, "public/", "", false);
-    if (options_.runtime_include_base.empty()) {
-      format("#include <google/protobuf/$1$>", path);
+    std::string path;
+    if (absl::ConsumePrefix(&google3_name, "io/public/")) {
+      path = absl::StrCat("io/", google3_name);
     } else {
-      format("#include \"$1$google/protobuf/$2$\"",
-             options_.runtime_include_base, path);
+      path = std::string(google3_name);
+    }
+
+    if (options_.runtime_include_base.empty()) {
+      p->Emit({{"path", path}}, R"(
+        #include "google/protobuf/$path$"$  export_suffix$
+      )");
+    } else {
+      p->Emit({{"base", options_.runtime_include_base}, {"path", path}},
+              R"(
+        #include "$base$google/protobuf/$path$"$  export_suffix$
+      )");
     }
   } else {
-    std::string path = google3_name;
+    std::string path(google3_name);
     // The bootstrapped proto generated code needs to use the
     // third_party/protobuf header paths to avoid circular dependencies.
     if (options_.bootstrap) {
-      path = StringReplace(google3_name, "net/proto2/public",
-                           "third_party/protobuf", false);
-    }
-    format("#include \"$1$\"", path);
-  }
-
-  if (do_export) {
-    format("  // IWYU pragma: export");
-  }
-
-  format("\n");
-}
-
-std::string FileGenerator::CreateHeaderInclude(const std::string& basename,
-                                               const FileDescriptor* file) {
-  bool use_system_include = false;
-  std::string name = basename;
-
-  if (options_.opensource_runtime) {
-    if (IsWellKnownMessage(file)) {
-      if (options_.runtime_include_base.empty()) {
-        use_system_include = true;
-      } else {
-        name = options_.runtime_include_base + basename;
+      constexpr absl::string_view bootstrap_prefix = "net/proto2/public";
+      if (absl::ConsumePrefix(&google3_name, bootstrap_prefix)) {
+        path = absl::StrCat("third_party/protobuf", google3_name);
       }
     }
-  }
 
-  std::string left = "\"";
-  std::string right = "\"";
-  if (use_system_include) {
-    left = "<";
-    right = ">";
+    p->Emit({{"path", path}}, R"(
+      #include "$path$"$  export_suffix$
+    )");
   }
-  return left + name + right;
 }
 
-void FileGenerator::GenerateSourceIncludes(io::Printer* printer) {
-  Formatter format(printer, variables_);
+std::string FileGenerator::CreateHeaderInclude(absl::string_view basename,
+                                               const FileDescriptor* file) {
+  if (options_.opensource_runtime && IsWellKnownMessage(file) &&
+      !options_.runtime_include_base.empty()) {
+    return absl::StrCat("\"", options_.runtime_include_base, basename, "\"");
+  }
+
+  return absl::StrCat("\"", basename, "\"");
+}
+
+void FileGenerator::GenerateSourceIncludes(io::Printer* p) {
   std::string target_basename = StripProto(file_->name());
   if (!options_.opensource_runtime) {
     GetBootstrapBasename(options_, target_basename, &target_basename);
   }
-  target_basename += options_.proto_h ? ".proto.h" : ".pb.h";
-  format(
-      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-      "// source: $filename$\n"
-      "\n"
-      "#include $1$\n"
-      "\n"
-      "#include <algorithm>\n"  // for swap()
-      "\n",
-      CreateHeaderInclude(target_basename, file_));
 
-  IncludeFile("net/proto2/io/public/coded_stream.h", printer);
+  absl::StrAppend(&target_basename, options_.proto_h ? ".proto.h" : ".pb.h");
+  p->Emit({{"h_include", CreateHeaderInclude(target_basename, file_)}},
+          R"(
+        // Generated by the protocol buffer compiler.  DO NOT EDIT!
+        // source: $filename$
+
+        #include $h_include$
+
+        #include <algorithm>
+      )");
+
+  IncludeFile("net/proto2/io/public/coded_stream.h", p);
   // TODO(gerbens) This is to include parse_context.h, we need a better way
-  IncludeFile("net/proto2/public/extension_set.h", printer);
-  IncludeFile("net/proto2/public/wire_format_lite.h", printer);
+  IncludeFile("net/proto2/public/extension_set.h", p);
+  IncludeFile("net/proto2/public/wire_format_lite.h", p);
 
   // Unknown fields implementation in lite mode uses StringOutputStream
   if (!UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
-    IncludeFile("net/proto2/io/public/zero_copy_stream_impl_lite.h", printer);
+    IncludeFile("net/proto2/io/public/zero_copy_stream_impl_lite.h", p);
   }
 
   if (HasDescriptorMethods(file_, options_)) {
-    IncludeFile("net/proto2/public/descriptor.h", printer);
-    IncludeFile("net/proto2/public/generated_message_reflection.h", printer);
-    IncludeFile("net/proto2/public/reflection_ops.h", printer);
-    IncludeFile("net/proto2/public/wire_format.h", printer);
+    IncludeFile("net/proto2/public/descriptor.h", p);
+    IncludeFile("net/proto2/public/generated_message_reflection.h", p);
+    IncludeFile("net/proto2/public/reflection_ops.h", p);
+    IncludeFile("net/proto2/public/wire_format.h", p);
   }
 
   if (HasGeneratedMethods(file_, options_) &&
       options_.tctable_mode != Options::kTCTableNever) {
-    IncludeFile("net/proto2/public/generated_message_tctable_impl.h", printer);
+    IncludeFile("net/proto2/public/generated_message_tctable_impl.h", p);
   }
 
   if (options_.proto_h) {
     // Use the smaller .proto.h files.
-    for (int i = 0; i < file_->dependency_count(); i++) {
+    for (int i = 0; i < file_->dependency_count(); ++i) {
       const FileDescriptor* dep = file_->dependency(i);
-      // Do not import weak deps.
-      if (!options_.opensource_runtime && IsDepWeak(dep)) continue;
+
+      if (!options_.opensource_runtime &&
+          IsDepWeak(dep)) {  // Do not import weak deps.
+        continue;
+      }
+
       std::string basename = StripProto(dep->name());
       if (IsBootstrapProto(options_, file_)) {
         GetBootstrapBasename(options_, basename, &basename);
       }
-      format("#include \"$1$.proto.h\"\n", basename);
+      p->Emit({{"name", basename}}, R"(
+        #include "$name$.proto.h"
+      )");
     }
   }
+
   if (HasCordFields(file_, options_)) {
-    format(
-        "#include \"third_party/absl/strings/internal/string_constant.h\"\n");
+    p->Emit(R"(
+      #include "third_party/absl/strings/internal/string_constant.h"
+    )");
   }
 
-  format("// @@protoc_insertion_point(includes)\n");
-  IncludeFile("net/proto2/public/port_def.inc", printer);
+  p->Emit(R"cc(
+    // @@protoc_insertion_point(includes)
+
+    // Must be included last.
+  )cc");
+  IncludeFile("net/proto2/public/port_def.inc", p);
 }
 
-void FileGenerator::GenerateSourcePrelude(io::Printer* printer) {
-  Formatter format(printer, variables_);
-
+void FileGenerator::GenerateSourcePrelude(io::Printer* p) {
   // 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");
+  p->Emit(R"cc(
+    PROTOBUF_PRAGMA_INIT_SEG
+    namespace _pb = ::$proto_ns$;
+    namespace _pbi = ::$proto_ns$::internal;
+  )cc");
 
-  // Generate convenience aliases.
-  format(
-      "\n"
-      "namespace _pb = ::$1$;\n"
-      "namespace _pbi = _pb::internal;\n",
-      ProtobufNamespace(options_));
   if (HasGeneratedMethods(file_, options_) &&
       options_.tctable_mode != Options::kTCTableNever) {
-    format("namespace _fl = _pbi::field_layout;\n");
+    p->Emit(R"cc(
+      namespace _fl = ::$proto_ns$::internal::field_layout;
+    )cc");
   }
-  format("\n");
 }
 
-void FileGenerator::GenerateSourceDefaultInstance(int idx,
-                                                  io::Printer* printer) {
-  Formatter format(printer, variables_);
+void FileGenerator::GenerateSourceDefaultInstance(int idx, io::Printer* p) {
   MessageGenerator* generator = message_generators_[idx].get();
+
   // Generate the split instance first because it's needed in the constexpr
   // constructor.
-  if (ShouldSplit(generator->descriptor_, options_)) {
+  if (ShouldSplit(generator->descriptor(), options_)) {
     // 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(
-        "struct $1$ {\n"
-        "  PROTOBUF_CONSTEXPR $1$()\n"
-        "      : _instance{",
-        DefaultInstanceType(generator->descriptor_, options_,
-                            /*split=*/true));
-    generator->GenerateInitDefaultSplitInstance(printer);
-    format(
-        "} {}\n"
-        "  ~$1$() {}\n"
-        "  union {\n"
-        "    $2$ _instance;\n"
-        "  };\n"
-        "};\n",
-        DefaultInstanceType(generator->descriptor_, options_, /*split=*/true),
-        StrCat(generator->classname_, "::Impl_::Split"));
+    //
     // 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 "
-        "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n",
-        DefaultInstanceType(generator->descriptor_, options_, /*split=*/true),
-        DefaultInstanceName(generator->descriptor_, options_, /*split=*/true));
+    p->Emit(
+        {
+            {"type", DefaultInstanceType(generator->descriptor(), options_,
+                                         /*split=*/true)},
+            {"name", DefaultInstanceName(generator->descriptor(), options_,
+                                         /*split=*/true)},
+            {"default",
+             [&] { generator->GenerateInitDefaultSplitInstance(p); }},
+            {"class", absl::StrCat(ClassName(generator->descriptor()),
+                                   "::Impl_::Split")},
+        },
+        R"cc(
+          struct $type$ {
+            PROTOBUF_CONSTEXPR $type$() : _instance{$default$} {}
+            union {
+              $class$ _instance;
+            };
+          };
+
+          PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+              PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 const $type$ $name$;
+        )cc");
   }
 
-  generator->GenerateConstexprConstructor(printer);
-  format(
-      "struct $1$ {\n"
-      "  PROTOBUF_CONSTEXPR $1$()\n"
-      "      : _instance(::_pbi::ConstantInitialized{}) {}\n"
-      "  ~$1$() {}\n"
-      "  union {\n"
-      "    $2$ _instance;\n"
-      "  };\n"
-      "};\n",
-      DefaultInstanceType(generator->descriptor_, options_),
-      generator->classname_);
-  format(
-      "PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT "
-      "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $1$ $2$;\n",
-      DefaultInstanceType(generator->descriptor_, options_),
-      DefaultInstanceName(generator->descriptor_, options_));
+  generator->GenerateConstexprConstructor(p);
 
-  for (int i = 0; i < generator->descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = generator->descriptor_->field(i);
-    if (IsStringInlined(field, options_)) {
-      // Force the initialization of the inlined string in the default instance.
-      format(
-          "PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type "
-          "$1$::Impl_::_init_inline_$2$_ = "
-          "($3$._instance.$4$.Init(), std::true_type{});\n",
-          ClassName(generator->descriptor_), FieldName(field),
-          DefaultInstanceName(generator->descriptor_, options_),
-          FieldMemberName(field, ShouldSplit(field, options_)));
+  p->Emit(
+      {
+          {"type", DefaultInstanceType(generator->descriptor(), options_)},
+          {"name", DefaultInstanceName(generator->descriptor(), options_)},
+          {"default", [&] { generator->GenerateInitDefaultSplitInstance(p); }},
+          {"class", ClassName(generator->descriptor())},
+      },
+      R"cc(
+        struct $type$ {
+          PROTOBUF_CONSTEXPR $type$() : _instance(::_pbi::ConstantInitialized{}) {}
+          ~$type$() {}
+          union {
+            $class$ _instance;
+          };
+        };
+
+        PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+            PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 $type$ $name$;
+      )cc");
+
+  for (int i = 0; i < generator->descriptor()->field_count(); ++i) {
+    const FieldDescriptor* field = generator->descriptor()->field(i);
+    if (!IsStringInlined(field, options_)) {
+      continue;
     }
+
+    // Force the initialization of the inlined string in the default instance.
+    p->Emit(
+        {
+            {"class", ClassName(generator->descriptor())},
+            {"field", FieldName(field)},
+            {"default", DefaultInstanceName(generator->descriptor(), options_)},
+            {"member", FieldMemberName(field, ShouldSplit(field, options_))},
+        },
+        R"cc(
+          PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 std::true_type
+              $class$::Impl_::_init_inline_$field$_ =
+                  ($default$._instance.$member$.Init(), std::true_type{});
+        )cc");
   }
 
   if (options_.lite_implicit_weak_fields) {
-    format(
-        "PROTOBUF_CONSTINIT const void* $1$ =\n"
-        "    &$2$;\n",
-        DefaultInstancePtr(generator->descriptor_, options_),
-        DefaultInstanceName(generator->descriptor_, options_));
+    p->Emit(
+        {
+            {"ptr", DefaultInstancePtr(generator->descriptor(), options_)},
+            {"name", DefaultInstanceName(generator->descriptor(), options_)},
+        },
+        R"cc(
+          PROTOBUF_CONSTINIT const void* $ptr$ = &$name$;
+        )cc");
   }
 }
 
 // A list of things defined in one .pb.cc file that we need to reference from
 // another .pb.cc file.
 struct FileGenerator::CrossFileReferences {
+  // When we forward-declare things, we want to create a sorted order so our
+  // output is deterministic and minimizes namespace changes.
+  struct DescCompare {
+    template <typename T>
+    bool operator()(const T* const& a, const T* const& b) const {
+      return a->full_name() < b->full_name();
+    }
+
+    bool operator()(const FileDescriptor* const& a,
+                    const FileDescriptor* const& b) const {
+      return a->name() < b->name();
+    }
+  };
+
   // Populated if we are referencing from messages or files.
-  std::unordered_set<const Descriptor*> weak_default_instances;
+  absl::btree_set<const Descriptor*, DescCompare> weak_default_instances;
 
   // Only if we are referencing from files.
-  std::unordered_set<const FileDescriptor*> strong_reflection_files;
-  std::unordered_set<const FileDescriptor*> weak_reflection_files;
+  absl::btree_set<const FileDescriptor*, DescCompare> strong_reflection_files;
+  absl::btree_set<const FileDescriptor*, DescCompare> weak_reflection_files;
 };
 
 void FileGenerator::GetCrossFileReferencesForField(const FieldDescriptor* field,
                                                    CrossFileReferences* refs) {
   const Descriptor* msg = field->message_type();
-  if (msg == nullptr) return;
+  if (msg == nullptr) {
+    return;
+  }
 
   if (IsImplicitWeakField(field, options_, &scc_analyzer_) ||
       IsWeak(field, options_)) {
@@ -582,10 +657,13 @@
     GetCrossFileReferencesForField(field, refs);
   });
 
-  if (!HasDescriptorMethods(file, options_)) return;
+  if (!HasDescriptorMethods(file, options_)) {
+    return;
+  }
 
-  for (int i = 0; i < file->dependency_count(); i++) {
+  for (int i = 0; i < file->dependency_count(); ++i) {
     const FileDescriptor* dep = file->dependency(i);
+
     if (IsDepWeak(dep)) {
       refs->weak_reflection_files.insert(dep);
     } else {
@@ -596,119 +674,128 @@
 
 // Generates references to variables defined in other files.
 void FileGenerator::GenerateInternalForwardDeclarations(
-    const CrossFileReferences& refs, io::Printer* printer) {
-  Formatter format(printer, variables_);
-
+    const CrossFileReferences& refs, io::Printer* p) {
   {
-    NamespaceOpener ns(format);
-    for (auto instance : Sorted(refs.weak_default_instances)) {
+    NamespaceOpener ns(p);
+    for (auto instance : refs.weak_default_instances) {
       ns.ChangeTo(Namespace(instance, options_));
+
       if (options_.lite_implicit_weak_fields) {
-        format(
-            "PROTOBUF_CONSTINIT __attribute__((weak)) const void* $1$ =\n"
-            "    &::_pbi::implicit_weak_message_default_instance;\n",
-            DefaultInstancePtr(instance, options_));
+        p->Emit({{"ptr", DefaultInstancePtr(instance, options_)}}, R"cc(
+          PROTOBUF_CONSTINIT __attribute__((weak)) const void* $ptr$ =
+              &::_pbi::implicit_weak_message_default_instance;
+        )cc");
       } else {
-        format("extern __attribute__((weak)) $1$ $2$;\n",
-               DefaultInstanceType(instance, options_),
-               DefaultInstanceName(instance, options_));
+        p->Emit({{"type", DefaultInstanceType(instance, options_)},
+                 {"name", DefaultInstanceName(instance, options_)}},
+                R"cc(
+                  extern __attribute__((weak)) $type$ $name$;
+                )cc");
       }
     }
   }
 
-  for (auto file : Sorted(refs.weak_reflection_files)) {
-    format(
-        "extern __attribute__((weak)) const ::_pbi::DescriptorTable $1$;\n",
-        DescriptorTableName(file, options_));
+  for (auto file : refs.weak_reflection_files) {
+    p->Emit({{"table", DescriptorTableName(file, options_)}}, R"cc(
+      extern __attribute__((weak)) const ::_pbi::DescriptorTable $table$;
+    )cc");
   }
 }
 
-void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* printer) {
-  Formatter format(printer, variables_);
-  GenerateSourceIncludes(printer);
-  GenerateSourcePrelude(printer);
+void FileGenerator::GenerateSourceForMessage(int idx, io::Printer* p) {
+  auto v = p->WithVars(FileVars(file_, options_));
 
-  if (IsAnyMessage(file_, options_)) MuteWuninitialized(format);
+  GenerateSourceIncludes(p);
+  GenerateSourcePrelude(p);
+
+  if (IsAnyMessage(file_, options_)) {
+    MuteWuninitialized(p);
+  }
 
   CrossFileReferences refs;
-  ForEachField(message_generators_[idx]->descriptor_,
+  ForEachField(message_generators_[idx]->descriptor(),
                [this, &refs](const FieldDescriptor* field) {
                  GetCrossFileReferencesForField(field, &refs);
                });
-  GenerateInternalForwardDeclarations(refs, printer);
 
-  {  // package namespace
-    NamespaceOpener ns(Namespace(file_, options_), format);
-
-    // Define default instances
-    GenerateSourceDefaultInstance(idx, printer);
-
-    // Generate classes.
-    format("\n");
-    message_generators_[idx]->GenerateClassMethods(printer);
-
-    format(
-        "\n"
-        "// @@protoc_insertion_point(namespace_scope)\n");
-  }  // end package namespace
+  GenerateInternalForwardDeclarations(refs, p);
 
   {
-    NamespaceOpener proto_ns(ProtobufNamespace(options_), format);
-    message_generators_[idx]->GenerateSourceInProto2Namespace(printer);
+    NamespaceOpener ns(Namespace(file_, options_), p);
+    p->Emit(
+        {
+            {"defaults", [&] { GenerateSourceDefaultInstance(idx, p); }},
+            {"class_methods",
+             [&] { message_generators_[idx]->GenerateClassMethods(p); }},
+        },
+        R"cc(
+          $defaults$;
+
+          $class_methods$;
+
+          // @@protoc_insertion_point(namespace_scope)
+        )cc");
   }
 
-  if (IsAnyMessage(file_, options_)) UnmuteWuninitialized(format);
+  {
+    NamespaceOpener proto_ns(ProtobufNamespace(options_), p);
+    message_generators_[idx]->GenerateSourceInProto2Namespace(p);
+  }
 
-  format(
-      "\n"
-      "// @@protoc_insertion_point(global_scope)\n");
+  if (IsAnyMessage(file_, options_)) {
+    UnmuteWuninitialized(p);
+  }
+
+  p->Emit(R"cc(
+    // @@protoc_insertion_point(global_scope)
+  )cc");
 }
 
-void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* printer) {
-  Formatter format(printer, variables_);
-  GenerateSourceIncludes(printer);
-  GenerateSourcePrelude(printer);
-  NamespaceOpener ns(Namespace(file_, options_), format);
-  extension_generators_[idx]->GenerateDefinition(printer);
+void FileGenerator::GenerateSourceForExtension(int idx, io::Printer* p) {
+  auto v = p->WithVars(FileVars(file_, options_));
+  GenerateSourceIncludes(p);
+  GenerateSourcePrelude(p);
+
+  NamespaceOpener ns(Namespace(file_, options_), p);
+  extension_generators_[idx]->GenerateDefinition(p);
 }
 
-void FileGenerator::GenerateGlobalSource(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  GenerateSourceIncludes(printer);
-  GenerateSourcePrelude(printer);
+void FileGenerator::GenerateGlobalSource(io::Printer* p) {
+  auto v = p->WithVars(FileVars(file_, options_));
+  GenerateSourceIncludes(p);
+  GenerateSourcePrelude(p);
 
   {
     // Define the code to initialize reflection. This code uses a global
     // constructor to register reflection data with the runtime pre-main.
     if (HasDescriptorMethods(file_, options_)) {
-      GenerateReflectionInitializationCode(printer);
+      GenerateReflectionInitializationCode(p);
     }
   }
 
-  NamespaceOpener ns(Namespace(file_, options_), format);
-
-  // Generate enums.
-  for (int i = 0; i < enum_generators_.size(); i++) {
-    enum_generators_[i]->GenerateMethods(i, printer);
+  NamespaceOpener ns(Namespace(file_, options_), p);
+  for (int i = 0; i < enum_generators_.size(); ++i) {
+    enum_generators_[i]->GenerateMethods(i, p);
   }
 }
 
-void FileGenerator::GenerateSource(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  GenerateSourceIncludes(printer);
-  GenerateSourcePrelude(printer);
+void FileGenerator::GenerateSource(io::Printer* p) {
+  auto v = p->WithVars(FileVars(file_, options_));
+
+  GenerateSourceIncludes(p);
+  GenerateSourcePrelude(p);
   CrossFileReferences refs;
   GetCrossFileReferencesForFile(file_, &refs);
-  GenerateInternalForwardDeclarations(refs, printer);
+  GenerateInternalForwardDeclarations(refs, p);
 
-  if (IsAnyMessage(file_, options_)) MuteWuninitialized(format);
+  if (IsAnyMessage(file_, options_)) {
+    MuteWuninitialized(p);
+  }
 
   {
-    NamespaceOpener ns(Namespace(file_, options_), format);
-
-    // Define default instances
-    for (int i = 0; i < message_generators_.size(); i++) {
-      GenerateSourceDefaultInstance(i, printer);
+    NamespaceOpener ns(Namespace(file_, options_), p);
+    for (int i = 0; i < message_generators_.size(); ++i) {
+      GenerateSourceDefaultInstance(i, p);
     }
   }
 
@@ -716,144 +803,155 @@
     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.
-      GenerateReflectionInitializationCode(printer);
+      GenerateReflectionInitializationCode(p);
     }
   }
 
   {
-    NamespaceOpener ns(Namespace(file_, options_), format);
+    NamespaceOpener ns(Namespace(file_, options_), p);
 
     // Actually implement the protos
 
     // Generate enums.
-    for (int i = 0; i < enum_generators_.size(); i++) {
-      enum_generators_[i]->GenerateMethods(i, printer);
+    for (int i = 0; i < enum_generators_.size(); ++i) {
+      enum_generators_[i]->GenerateMethods(i, p);
     }
 
     // Generate classes.
-    for (int i = 0; i < message_generators_.size(); i++) {
-      format("\n");
-      format(kThickSeparator);
-      format("\n");
-      message_generators_[i]->GenerateClassMethods(printer);
+    for (int i = 0; i < message_generators_.size(); ++i) {
+      p->Emit(R"(
+        $hrule_thick$
+      )");
+      message_generators_[i]->GenerateClassMethods(p);
     }
 
     if (HasGenericServices(file_, options_)) {
       // Generate services.
-      for (int i = 0; i < service_generators_.size(); i++) {
-        if (i == 0) format("\n");
-        format(kThickSeparator);
-        format("\n");
-        service_generators_[i]->GenerateImplementation(printer);
+      for (int i = 0; i < service_generators_.size(); ++i) {
+        p->Emit(R"(
+          $hrule_thick$
+        )");
+        service_generators_[i]->GenerateImplementation(p);
       }
     }
 
     // Define extensions.
-    for (int i = 0; i < extension_generators_.size(); i++) {
-      extension_generators_[i]->GenerateDefinition(printer);
+    for (int i = 0; i < extension_generators_.size(); ++i) {
+      extension_generators_[i]->GenerateDefinition(p);
     }
 
-    format(
-        "\n"
-        "// @@protoc_insertion_point(namespace_scope)\n");
+    p->Emit(R"cc(
+      // @@protoc_insertion_point(namespace_scope)
+    )cc");
   }
 
   {
-    NamespaceOpener proto_ns(ProtobufNamespace(options_), format);
-    for (int i = 0; i < message_generators_.size(); i++) {
-      message_generators_[i]->GenerateSourceInProto2Namespace(printer);
+    NamespaceOpener proto_ns(ProtobufNamespace(options_), p);
+    for (int i = 0; i < message_generators_.size(); ++i) {
+      message_generators_[i]->GenerateSourceInProto2Namespace(p);
     }
   }
 
-  format(
-      "\n"
-      "// @@protoc_insertion_point(global_scope)\n");
+  p->Emit(R"cc(
+    // @@protoc_insertion_point(global_scope)
+  )cc");
 
-  if (IsAnyMessage(file_, options_)) UnmuteWuninitialized(format);
+  if (IsAnyMessage(file_, options_)) {
+    UnmuteWuninitialized(p);
+  }
 
-  IncludeFile("net/proto2/public/port_undef.inc", printer);
+  IncludeFile("net/proto2/public/port_undef.inc", p);
 }
 
-void FileGenerator::GenerateReflectionInitializationCode(io::Printer* printer) {
-  Formatter format(printer, variables_);
-
+void FileGenerator::GenerateReflectionInitializationCode(io::Printer* p) {
   if (!message_generators_.empty()) {
-    format("static ::_pb::Metadata $file_level_metadata$[$1$];\n",
-           message_generators_.size());
+    p->Emit({{"len", message_generators_.size()}}, R"cc(
+      static ::_pb::Metadata $file_level_metadata$[$len$];
+    )cc");
   }
+
   if (!enum_generators_.empty()) {
-    format(
-        "static const ::_pb::EnumDescriptor* "
-        "$file_level_enum_descriptors$[$1$];\n",
-        enum_generators_.size());
+    p->Emit({{"len", enum_generators_.size()}}, R"cc(
+      static const ::_pb::EnumDescriptor* $file_level_enum_descriptors$[$len$];
+    )cc");
   } else {
-    format(
-        "static "
-        "constexpr ::_pb::EnumDescriptor const** "
-        "$file_level_enum_descriptors$ = nullptr;\n");
+    p->Emit(R"cc(
+      static constexpr const ::_pb::EnumDescriptor**
+          $file_level_enum_descriptors$ = nullptr;
+    )cc");
   }
+
   if (HasGenericServices(file_, options_) && file_->service_count() > 0) {
-    format(
-        "static "
-        "const ::_pb::ServiceDescriptor* "
-        "$file_level_service_descriptors$[$1$];\n",
-        file_->service_count());
+    p->Emit({{"len", file_->service_count()}}, R"cc(
+      static const ::_pb::ServiceDescriptor*
+          $file_level_service_descriptors$[$len$];
+    )cc");
   } else {
-    format(
-        "static "
-        "constexpr ::_pb::ServiceDescriptor const** "
-        "$file_level_service_descriptors$ = nullptr;\n");
+    p->Emit(R"cc(
+      static constexpr const ::_pb::ServiceDescriptor**
+          $file_level_service_descriptors$ = nullptr;
+    )cc");
   }
 
   if (!message_generators_.empty()) {
-    format(
-        "\n"
-        "const $uint32$ $tablename$::offsets[] "
-        "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
-    format.Indent();
-    std::vector<std::pair<size_t, size_t> > pairs;
-    pairs.reserve(message_generators_.size());
-    for (int i = 0; i < message_generators_.size(); i++) {
-      pairs.push_back(message_generators_[i]->GenerateOffsets(printer));
-    }
-    format.Outdent();
-    format(
-        "};\n"
-        "static const ::_pbi::MigrationSchema schemas[] "
-        "PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {\n");
-    format.Indent();
-    {
-      int offset = 0;
-      for (int i = 0; i < message_generators_.size(); i++) {
-        message_generators_[i]->GenerateSchema(printer, offset,
-                                               pairs[i].second);
-        offset += pairs[i].first;
-      }
-    }
-    format.Outdent();
-    format(
-        "};\n"
-        "\nstatic const ::_pb::Message* const file_default_instances[] = {\n");
-    format.Indent();
-    for (int i = 0; i < message_generators_.size(); i++) {
-      const Descriptor* descriptor = message_generators_[i]->descriptor_;
-      format("&$1$::_$2$_default_instance_._instance,\n",
-             Namespace(descriptor, options_),  // 1
-             ClassName(descriptor));           // 2
-    }
-    format.Outdent();
-    format(
-        "};\n"
-        "\n");
+    std::vector<std::pair<size_t, size_t>> offsets;
+    offsets.reserve(message_generators_.size());
+
+    p->Emit(
+        {
+            {"offsets",
+             [&] {
+               for (int i = 0; i < message_generators_.size(); ++i) {
+                 offsets.push_back(message_generators_[i]->GenerateOffsets(p));
+               }
+             }},
+            {"schemas",
+             [&] {
+               int offset = 0;
+               for (int i = 0; i < message_generators_.size(); ++i) {
+                 message_generators_[i]->GenerateSchema(p, offset,
+                                                        offsets[i].second);
+                 offset += offsets[i].first;
+               }
+             }},
+            {"defaults",
+             [&] {
+               for (auto& gen : message_generators_) {
+                 p->Emit(
+                     {
+                         {"ns", Namespace(gen->descriptor(), options_)},
+                         {"class", ClassName(gen->descriptor())},
+                     },
+                     R"cc(
+                       &$ns$::_$class$_default_instance_._instance,
+                     )cc");
+               }
+             }},
+        },
+        R"cc(
+          const ::uint32_t $tablename$::offsets[] PROTOBUF_SECTION_VARIABLE(
+              protodesc_cold) = {
+              $offsets$,
+          };
+
+          static const ::_pbi::MigrationSchema
+              schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+                  $schemas$,
+          };
+
+          static const ::_pb::Message* const file_default_instances[] = {
+              $defaults$,
+          };
+        )cc");
   } else {
-    // we still need these symbols to exist
-    format(
-        // MSVC doesn't like empty arrays, so we add a dummy.
-        "const $uint32$ $tablename$::offsets[1] = {};\n"
-        "static constexpr ::_pbi::MigrationSchema* schemas = nullptr;\n"
-        "static constexpr ::_pb::Message* const* "
-        "file_default_instances = nullptr;\n"
-        "\n");
+    // Ee still need these symbols to exist.
+    //
+    // MSVC doesn't like empty arrays, so we add a dummy.
+    p->Emit(R"cc(
+      const ::uint32_t $tablename$::offsets[1] = {};
+      static constexpr ::_pbi::MigrationSchema* schemas = nullptr;
+      static constexpr ::_pb::Message* const* file_default_instances = nullptr;
+    )cc");
   }
 
   // ---------------------------------------------------------------
@@ -861,63 +959,88 @@
   // Embed the descriptor.  We simply serialize the entire
   // FileDescriptorProto/ and embed it as a string literal, which is parsed and
   // built into real descriptors at initialization time.
-  const std::string protodef_name =
-      UniqueName("descriptor_table_protodef", file_, options_);
-  format("const char $1$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =\n",
-         protodef_name);
-  format.Indent();
+
   FileDescriptorProto file_proto;
   file_->CopyTo(&file_proto);
   std::string file_data;
   file_proto.SerializeToString(&file_data);
 
-  {
-    if (file_data.size() > 65535) {
-      // Workaround for MSVC: "Error C1091: compiler limit: string exceeds
-      // 65535 bytes in length". Declare a static array of chars rather than
-      // use a string literal. Only write 25 bytes per line.
-      static const int kBytesPerLine = 25;
-      format("{ ");
-      for (int i = 0; i < file_data.size();) {
-        for (int j = 0; j < kBytesPerLine && i < file_data.size(); ++i, ++j) {
-          format("'$1$', ", CEscape(file_data.substr(i, 1)));
-        }
-        format("\n");
-      }
-      format("'\\0' }");  // null-terminate
-    } else {
-      // Only write 40 bytes per line.
-      static const int kBytesPerLine = 40;
-      for (int i = 0; i < file_data.size(); i += kBytesPerLine) {
-        format(
-            "\"$1$\"\n",
-            EscapeTrigraphs(CEscape(file_data.substr(i, kBytesPerLine))));
-      }
-    }
-    format(";\n");
-  }
-  format.Outdent();
+  auto desc_name = UniqueName("descriptor_table_protodef", file_, options_);
+  p->Emit(
+      {{"desc_name", desc_name},
+       {"encoded_file_proto",
+        [&] {
+          absl::string_view data = file_data;
+          if (data.size() <= 65535) {
+            static constexpr size_t kBytesPerLine = 40;
+            while (!data.empty()) {
+              auto to_write = std::min(kBytesPerLine, data.size());
+              auto chunk = data.substr(0, to_write);
+              data = data.substr(to_write);
+
+              p->Emit({{"text", EscapeTrigraphs(absl::CEscape(chunk))}}, R"cc(
+                "$text$"
+              )cc");
+            }
+            return;
+          }
+
+          // Workaround for MSVC: "Error C1091: compiler limit: string exceeds
+          // 65535 bytes in length". Declare a static array of chars rather than
+          // use a string literal. Only write 25 bytes per line.
+          static constexpr size_t kBytesPerLine = 25;
+          while (!data.empty()) {
+            auto to_write = std::min(kBytesPerLine, data.size());
+            auto chunk = data.substr(0, to_write);
+            data = data.substr(to_write);
+
+            std::string line;
+            for (char c : chunk) {
+              absl::StrAppend(&line, "'",
+                              absl::CEscape(absl::string_view(&c, 1)), "', ");
+            }
+
+            p->Emit({{"line", line}}, R"cc(
+              $line$
+            )cc");
+          }
+        }}},
+      R"cc(
+        const char $desc_name$[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+            $encoded_file_proto$,
+        };
+      )cc");
 
   CrossFileReferences refs;
   GetCrossFileReferencesForFile(file_, &refs);
-  int num_deps =
+  size_t num_deps =
       refs.strong_reflection_files.size() + refs.weak_reflection_files.size();
 
   // Build array of DescriptorTable deps.
   if (num_deps > 0) {
-    format(
-        "static const ::_pbi::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.weak_reflection_files)) {
-      format("  &::$1$,\n", DescriptorTableName(dep, options_));
-    }
-
-    format("};\n");
+    p->Emit(
+        {
+            {"len", num_deps},
+            {"deps",
+             [&] {
+               for (auto dep : refs.strong_reflection_files) {
+                 p->Emit({{"name", DescriptorTableName(dep, options_)}}, R"cc(
+                   &::$name$,
+                 )cc");
+               }
+               for (auto dep : refs.weak_reflection_files) {
+                 p->Emit({{"name", DescriptorTableName(dep, options_)}}, R"cc(
+                   &::$name$,
+                 )cc");
+               }
+             }},
+        },
+        R"cc(
+          static const ::_pbi::DescriptorTable* const $desc_table$_deps[$len$] =
+              {
+                  $deps$,
+          };
+        )cc");
   }
 
   // The DescriptorTable itself.
@@ -925,342 +1048,355 @@
   // however this might cause a tsan failure in superroot b/148382879,
   // so disable for now.
   bool eager = false;
-  format(
-      "static ::_pbi::once_flag $desc_table$_once;\n"
-      "const ::_pbi::DescriptorTable $desc_table$ = {\n"
-      "    false, $1$, $2$, $3$,\n"
-      "    \"$filename$\",\n"
-      "    &$desc_table$_once, $4$, $5$, $6$,\n"
-      "    schemas, file_default_instances, $tablename$::offsets,\n"
-      "    $7$, $file_level_enum_descriptors$,\n"
-      "    $file_level_service_descriptors$,\n"
-      "};\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 ::_pbi::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"]);
+  p->Emit(
+      {
+          {"eager", eager ? "true" : "false"},
+          {"file_proto_len", file_data.size()},
+          {"proto_name", desc_name},
+          {"deps_ptr", num_deps == 0
+                           ? "nullptr"
+                           : absl::StrCat(p->LookupVar("desc_table"), "_deps")},
+          {"num_deps", num_deps},
+          {"num_msgs", message_generators_.size()},
+          {"msgs_ptr", message_generators_.empty()
+                           ? "nullptr"
+                           : std::string(p->LookupVar("file_level_metadata"))},
+      },
+      R"cc(
+        static ::absl::once_flag $desc_table$_once;
+        const ::_pbi::DescriptorTable $desc_table$ = {
+            false,
+            $eager$,
+            $file_proto_len$,
+            $proto_name$,
+            "$filename$",
+            &$desc_table$_once,
+            $deps_ptr$,
+            $num_deps$,
+            $num_msgs$,
+            schemas,
+            file_default_instances,
+            $tablename$::offsets,
+            $msgs_ptr$,
+            $file_level_enum_descriptors$,
+            $file_level_service_descriptors$,
+        };
+
+        // 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 ::_pbi::DescriptorTable* $desc_table$_getter() {
+          return &$desc_table$;
+        }
+      )cc");
 
   // For descriptor.proto we want to avoid doing any dynamic initialization,
   // because in some situations that would otherwise pull in a lot of
   // unnecessary code that can't be stripped by --gc-sections. Descriptor
   // initialization will still be performed lazily when it's needed.
-  if (file_->name() != "net/proto2/proto/descriptor.proto") {
-    format(
-        "// Force running AddDescriptors() at dynamic initialization time.\n"
-        "PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 "
-        "static ::_pbi::AddDescriptorsRunner $1$(&$desc_table$);\n",
-        UniqueName("dynamic_init_dummy", file_, options_));
+  if (file_->name() == "net/proto2/proto/descriptor.proto") {
+    return;
   }
+
+  p->Emit({{"dummy", UniqueName("dynamic_init_dummy", file_, options_)}}, R"cc(
+    // Force running AddDescriptors() at dynamic initialization time.
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+    static ::_pbi::AddDescriptorsRunner $dummy$(&$desc_table$);
+  )cc");
 }
 
 class FileGenerator::ForwardDeclarations {
  public:
-  void AddMessage(const Descriptor* d) { classes_[ClassName(d)] = d; }
-  void AddEnum(const EnumDescriptor* d) { enums_[ClassName(d)] = d; }
-  void AddSplit(const Descriptor* d) { splits_[ClassName(d)] = d; }
+  void AddMessage(const Descriptor* d) { classes_.emplace(ClassName(d), d); }
+  void AddEnum(const EnumDescriptor* d) { enums_.emplace(ClassName(d), d); }
+  void AddSplit(const Descriptor* d) { splits_.emplace(ClassName(d), d); }
 
-  void Print(const Formatter& format, const Options& options) const {
-    for (const auto& p : enums_) {
-      const std::string& enumname = p.first;
-      const EnumDescriptor* enum_desc = p.second;
-      format(
-          "enum ${1$$2$$}$ : int;\n"
-          "bool $2$_IsValid(int value);\n",
-          enum_desc, enumname);
+  void Print(io::Printer* p, const Options& options) const {
+    for (const auto& e : enums_) {
+      p->Emit({{"enum", e.first, e.second}}, R"cc(
+        enum $enum$ : int;
+        bool $enum$_IsValid(int value);
+      )cc");
     }
-    for (const auto& p : classes_) {
-      const std::string& classname = p.first;
-      const Descriptor* class_desc = p.second;
-      format(
-          "class ${1$$2$$}$;\n"
-          "struct $3$;\n"
-          "$dllexport_decl $extern $3$ $4$;\n",
-          class_desc, classname, DefaultInstanceType(class_desc, options),
-          DefaultInstanceName(class_desc, options));
+
+    for (const auto& c : classes_) {
+      const Descriptor* desc = c.second;
+      p->Emit(
+          {
+              {"class", c.first, desc},
+              {"default_type", DefaultInstanceType(desc, options)},
+              {"default_name", DefaultInstanceName(desc, options)},
+          },
+          R"cc(
+            class $class$;
+            struct $default_type$;
+            $dllexport_decl $extern $default_type$ $default_name$;
+          )cc");
     }
-    for (const auto& p : splits_) {
-      const Descriptor* class_desc = p.second;
-      format(
-          "struct $1$;\n"
-          "$dllexport_decl $extern $1$ $2$;\n",
-          DefaultInstanceType(class_desc, options, /*split=*/true),
-          DefaultInstanceName(class_desc, options, /*split=*/true));
+
+    for (const auto& s : splits_) {
+      const Descriptor* desc = s.second;
+      p->Emit(
+          {
+              {"default_type",
+               DefaultInstanceType(desc, options, /*split=*/true)},
+              {"default_name",
+               DefaultInstanceName(desc, options, /*split=*/true)},
+          },
+          R"cc(
+            struct $default_type$;
+            $dllexport_decl $extern const $default_type$ $default_name$;
+          )cc");
     }
   }
 
-  void PrintTopLevelDecl(const Formatter& format,
-                         const Options& options) const {
-    for (const auto& pair : classes_) {
-      format(
-          "template<> $dllexport_decl $"
-          "$1$* Arena::CreateMaybeMessage<$1$>(Arena*);\n",
-          QualifiedClassName(pair.second, options));
+  void PrintTopLevelDecl(io::Printer* p, const Options& options) const {
+    for (const auto& c : classes_) {
+      p->Emit({{"class", QualifiedClassName(c.second, options)}}, R"cc(
+        template <>
+        $dllexport_decl $$class$* Arena::CreateMaybeMessage<$class$>(Arena*);
+      )cc");
     }
   }
 
  private:
-  std::map<std::string, const Descriptor*> classes_;
-  std::map<std::string, const EnumDescriptor*> enums_;
-  std::map<std::string, const Descriptor*> splits_;
+  absl::btree_map<std::string, const Descriptor*> classes_;
+  absl::btree_map<std::string, const EnumDescriptor*> enums_;
+  absl::btree_map<std::string, const Descriptor*> splits_;
 };
 
-static void PublicImportDFS(const FileDescriptor* fd,
-                            std::unordered_set<const FileDescriptor*>* fd_set) {
-  for (int i = 0; i < fd->public_dependency_count(); i++) {
+static void PublicImportDFS(
+    const FileDescriptor* fd,
+    absl::flat_hash_set<const FileDescriptor*>& fd_set) {
+  for (int i = 0; i < fd->public_dependency_count(); ++i) {
     const FileDescriptor* dep = fd->public_dependency(i);
-    if (fd_set->insert(dep).second) PublicImportDFS(dep, fd_set);
+    if (fd_set.insert(dep).second) {
+      PublicImportDFS(dep, fd_set);
+    }
   }
 }
 
-void FileGenerator::GenerateForwardDeclarations(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void FileGenerator::GenerateForwardDeclarations(io::Printer* p) {
   std::vector<const Descriptor*> classes;
-  std::vector<const EnumDescriptor*> enums;
-
   FlattenMessagesInFile(file_, &classes);  // All messages need forward decls.
 
+  std::vector<const EnumDescriptor*> enums;
   if (options_.proto_h) {  // proto.h needs extra forward declarations.
     // All classes / enums referred to as field members
     std::vector<const FieldDescriptor*> fields;
     ListAllFields(file_, &fields);
-    for (int i = 0; i < fields.size(); i++) {
-      classes.push_back(fields[i]->containing_type());
-      classes.push_back(fields[i]->message_type());
-      enums.push_back(fields[i]->enum_type());
+    for (const auto* field : fields) {
+      classes.push_back(field->containing_type());
+      classes.push_back(field->message_type());
+      enums.push_back(field->enum_type());
     }
+
     ListAllTypesForServices(file_, &classes);
   }
 
   // Calculate the set of files whose definitions we get through include.
   // No need to forward declare types that are defined in these.
-  std::unordered_set<const FileDescriptor*> public_set;
-  PublicImportDFS(file_, &public_set);
+  absl::flat_hash_set<const FileDescriptor*> public_set;
+  PublicImportDFS(file_, public_set);
 
-  std::map<std::string, ForwardDeclarations> decls;
-  for (int i = 0; i < classes.size(); i++) {
-    const Descriptor* d = classes[i];
-    if (d && !public_set.count(d->file()))
+  absl::btree_map<std::string, ForwardDeclarations> decls;
+  for (const auto* d : classes) {
+    if (d != nullptr && !public_set.count(d->file()))
       decls[Namespace(d, options_)].AddMessage(d);
   }
-  for (int i = 0; i < enums.size(); i++) {
-    const EnumDescriptor* d = enums[i];
-    if (d && !public_set.count(d->file()))
-      decls[Namespace(d, options_)].AddEnum(d);
+  for (const auto* e : enums) {
+    if (e != nullptr && !public_set.count(e->file()))
+      decls[Namespace(e, options_)].AddEnum(e);
   }
   for (const auto& mg : message_generators_) {
-    const Descriptor* d = mg->descriptor_;
-    if ((d != nullptr) && (public_set.count(d->file()) == 0u) &&
-        ShouldSplit(mg->descriptor_, options_))
+    const Descriptor* d = mg->descriptor();
+    if (d != nullptr && public_set.count(d->file()) == 0u &&
+        ShouldSplit(mg->descriptor(), options_))
       decls[Namespace(d, options_)].AddSplit(d);
   }
 
-  {
-    NamespaceOpener ns(format);
-    for (const auto& pair : decls) {
-      ns.ChangeTo(pair.first);
-      pair.second.Print(format, options_);
-    }
+  NamespaceOpener ns(p);
+  for (const auto& decl : decls) {
+    ns.ChangeTo(decl.first);
+    decl.second.Print(p, options_);
   }
-  format("PROTOBUF_NAMESPACE_OPEN\n");
-  for (const auto& pair : decls) {
-    pair.second.PrintTopLevelDecl(format, options_);
+
+  ns.ChangeTo("PROTOBUF_NAMESPACE_ID");
+  for (const auto& decl : decls) {
+    decl.second.PrintTopLevelDecl(p, options_);
   }
-  format("PROTOBUF_NAMESPACE_CLOSE\n");
 }
 
-void FileGenerator::GenerateTopHeaderGuard(io::Printer* printer, bool pb_h) {
-  Formatter format(printer, variables_);
-  // Generate top of header.
-  format(
-      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-      "// source: $filename$\n"
-      "\n"
-      "#ifndef $1$\n"
-      "#define $1$\n"
-      "\n"
-      "#include <limits>\n"
-      "#include <string>\n",
-      IncludeGuard(file_, pb_h, options_));
-  if (!options_.opensource_runtime && !enum_generators_.empty()) {
-    // Add header to provide std::is_integral for safe Enum_Name() function.
-    format("#include <type_traits>\n");
-  }
-  format("\n");
-}
-
-void FileGenerator::GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h) {
-  Formatter format(printer, variables_);
-  format("#endif  // $GOOGLE_PROTOBUF$_INCLUDED_$1$\n",
-         IncludeGuard(file_, pb_h, options_));
-}
-
-void FileGenerator::GenerateLibraryIncludes(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void FileGenerator::GenerateLibraryIncludes(io::Printer* p) {
   if (UsingImplicitWeakFields(file_, options_)) {
-    IncludeFile("net/proto2/public/implicit_weak_message.h", printer);
+    IncludeFile("net/proto2/public/implicit_weak_message.h", p);
   }
   if (HasWeakFields(file_, options_)) {
     GOOGLE_CHECK(!options_.opensource_runtime);
-    IncludeFile("net/proto2/public/weak_field_map.h", printer);
+    IncludeFile("net/proto2/public/weak_field_map.h", p);
   }
   if (HasLazyFields(file_, options_, &scc_analyzer_)) {
     GOOGLE_CHECK(!options_.opensource_runtime);
-    IncludeFile("net/proto2/public/lazy_field.h", printer);
+    IncludeFile("net/proto2/public/lazy_field.h", p);
   }
   if (ShouldVerify(file_, options_, &scc_analyzer_)) {
-    IncludeFile("net/proto2/public/wire_format_verify.h", printer);
+    IncludeFile("net/proto2/public/wire_format_verify.h", p);
   }
 
   if (options_.opensource_runtime) {
     // Verify the protobuf library header version is compatible with the protoc
     // version before going any further.
-    IncludeFile("net/proto2/public/port_def.inc", printer);
-    format(
-        "#if PROTOBUF_VERSION < $1$\n"
-        "#error This file was generated by a newer version of protoc which is\n"
-        "#error incompatible with your Protocol Buffer headers. Please update\n"
-        "#error your headers.\n"
-        "#endif\n"
-        "#if $2$ < PROTOBUF_MIN_PROTOC_VERSION\n"
-        "#error This file was generated by an older version of protoc which "
-        "is\n"
-        "#error incompatible with your Protocol Buffer headers. Please\n"
-        "#error regenerate this file with a newer version of protoc.\n"
-        "#endif\n"
-        "\n",
-        PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC,  // 1
-        PROTOBUF_VERSION);                       // 2
-    IncludeFile("net/proto2/public/port_undef.inc", printer);
+    IncludeFile("net/proto2/public/port_def.inc", p);
+    p->Emit(
+        {
+            {"min_version", PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC},
+            {"version", PROTOBUF_VERSION},
+        },
+        R"(
+        #if PROTOBUF_VERSION < $min_version$
+        #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  // PROTOBUF_VERSION
+
+        #if $version$ < 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."
+        #endif  // PROTOBUF_MIN_PROTOC_VERSION
+    )");
+    IncludeFile("net/proto2/public/port_undef.inc", p);
   }
 
   // OK, it's now safe to #include other files.
-  IncludeFile("net/proto2/io/public/coded_stream.h", printer);
-  IncludeFile("net/proto2/public/arena.h", printer);
-  IncludeFile("net/proto2/public/arenastring.h", printer);
+  IncludeFile("net/proto2/io/public/coded_stream.h", p);
+  IncludeFile("net/proto2/public/arena.h", p);
+  IncludeFile("net/proto2/public/arenastring.h", p);
   if ((options_.force_inline_string || options_.profile_driven_inline_string) &&
       !options_.opensource_runtime) {
-    IncludeFile("net/proto2/public/inlined_string_field.h", printer);
+    IncludeFile("net/proto2/public/inlined_string_field.h", p);
   }
   if (HasSimpleBaseClasses(file_, options_)) {
-    IncludeFile("net/proto2/public/generated_message_bases.h", printer);
+    IncludeFile("net/proto2/public/generated_message_bases.h", p);
   }
   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_tctable_decl.h", p);
   }
-  IncludeFile("net/proto2/public/generated_message_util.h", printer);
-  IncludeFile("net/proto2/public/metadata_lite.h", printer);
+  IncludeFile("net/proto2/public/generated_message_util.h", p);
+  IncludeFile("net/proto2/public/metadata_lite.h", p);
 
   if (HasDescriptorMethods(file_, options_)) {
-    IncludeFile("net/proto2/public/generated_message_reflection.h", printer);
+    IncludeFile("net/proto2/public/generated_message_reflection.h", p);
   }
 
   if (!message_generators_.empty()) {
     if (HasDescriptorMethods(file_, options_)) {
-      IncludeFile("net/proto2/public/message.h", printer);
+      IncludeFile("net/proto2/public/message.h", p);
     } else {
-      IncludeFile("net/proto2/public/message_lite.h", printer);
+      IncludeFile("net/proto2/public/message_lite.h", p);
     }
   }
   if (options_.opensource_runtime) {
     // Open-source relies on unconditional includes of these.
-    IncludeFileAndExport("net/proto2/public/repeated_field.h", printer);
-    IncludeFileAndExport("net/proto2/public/extension_set.h", printer);
+    IncludeFileAndExport("net/proto2/public/repeated_field.h", p);
+    IncludeFileAndExport("net/proto2/public/extension_set.h", p);
   } else {
     // Google3 includes these files only when they are necessary.
     if (HasExtensionsOrExtendableMessage(file_)) {
-      IncludeFileAndExport("net/proto2/public/extension_set.h", printer);
+      IncludeFileAndExport("net/proto2/public/extension_set.h", p);
     }
     if (HasRepeatedFields(file_)) {
-      IncludeFileAndExport("net/proto2/public/repeated_field.h", printer);
+      IncludeFileAndExport("net/proto2/public/repeated_field.h", p);
     }
     if (HasStringPieceFields(file_, options_)) {
-      IncludeFile("net/proto2/public/string_piece_field_support.h", printer);
+      IncludeFile("net/proto2/public/string_piece_field_support.h", p);
     }
     if (HasCordFields(file_, options_)) {
-      format("#include \"third_party/absl/strings/cord.h\"\n");
+      p->Emit(R"(
+        #include "third_party/absl/strings/cord.h"
+      )");
     }
   }
   if (HasMapFields(file_)) {
-    IncludeFileAndExport("net/proto2/public/map.h", printer);
+    IncludeFileAndExport("net/proto2/public/map.h", p);
     if (HasDescriptorMethods(file_, options_)) {
-      IncludeFile("net/proto2/public/map_entry.h", printer);
-      IncludeFile("net/proto2/public/map_field_inl.h", printer);
+      IncludeFile("net/proto2/public/map_entry.h", p);
+      IncludeFile("net/proto2/public/map_field_inl.h", p);
     } else {
-      IncludeFile("net/proto2/public/map_entry_lite.h", printer);
-      IncludeFile("net/proto2/public/map_field_lite.h", printer);
+      IncludeFile("net/proto2/public/map_entry_lite.h", p);
+      IncludeFile("net/proto2/public/map_field_lite.h", p);
     }
   }
 
   if (HasEnumDefinitions(file_)) {
     if (HasDescriptorMethods(file_, options_)) {
-      IncludeFile("net/proto2/public/generated_enum_reflection.h", printer);
+      IncludeFile("net/proto2/public/generated_enum_reflection.h", p);
     } else {
-      IncludeFile("net/proto2/public/generated_enum_util.h", printer);
+      IncludeFile("net/proto2/public/generated_enum_util.h", p);
     }
   }
 
   if (HasGenericServices(file_, options_)) {
-    IncludeFile("net/proto2/public/service.h", printer);
+    IncludeFile("net/proto2/public/service.h", p);
   }
 
   if (UseUnknownFieldSet(file_, options_) && !message_generators_.empty()) {
-    IncludeFile("net/proto2/public/unknown_field_set.h", printer);
+    IncludeFile("net/proto2/public/unknown_field_set.h", p);
   }
 }
 
-void FileGenerator::GenerateMetadataPragma(io::Printer* printer,
-                                           const std::string& info_path) {
-  Formatter format(printer, variables_);
-  if (!info_path.empty() && !options_.annotation_pragma_name.empty() &&
-      !options_.annotation_guard_name.empty()) {
-    format.Set("guard", options_.annotation_guard_name);
-    format.Set("pragma", options_.annotation_pragma_name);
-    format.Set("info_path", info_path);
-    format(
-        "#ifdef $guard$\n"
-        "#pragma $pragma$ \"$info_path$\"\n"
-        "#endif  // $guard$\n");
+void FileGenerator::GenerateMetadataPragma(io::Printer* p,
+                                           absl::string_view info_path) {
+  if (info_path.empty() || options_.annotation_pragma_name.empty() ||
+      options_.annotation_guard_name.empty()) {
+    return;
   }
+
+  p->Emit(
+      {
+          {"guard", options_.annotation_guard_name},
+          {"pragma", options_.annotation_pragma_name},
+          {"info_path", std::string(info_path)},
+      },
+      R"(
+        #ifdef $guard$
+        #pragma $pragma$ "$info_path$"
+        #endif  // $guard$
+      )");
 }
 
-void FileGenerator::GenerateDependencyIncludes(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  for (int i = 0; i < file_->dependency_count(); i++) {
-    std::string basename = StripProto(file_->dependency(i)->name());
+void FileGenerator::GenerateDependencyIncludes(io::Printer* p) {
+  for (int i = 0; i < file_->dependency_count(); ++i) {
+    const FileDescriptor* dep = file_->dependency(i);
 
     // Do not import weak deps.
-    if (IsDepWeak(file_->dependency(i))) continue;
+    if (IsDepWeak(dep)) {
+      continue;
+    }
 
+    std::string basename = StripProto(dep->name());
     if (IsBootstrapProto(options_, file_)) {
       GetBootstrapBasename(options_, basename, &basename);
     }
 
-    format("#include $1$\n",
-           CreateHeaderInclude(basename + ".pb.h", file_->dependency(i)));
+    p->Emit(
+        {{"name", CreateHeaderInclude(absl::StrCat(basename, ".pb.h"), dep)}},
+        R"(
+          #include $name$
+        )");
   }
 }
 
-void FileGenerator::GenerateGlobalStateFunctionDeclarations(
-    io::Printer* printer) {
-  Formatter format(printer, variables_);
+void FileGenerator::GenerateGlobalStateFunctionDeclarations(io::Printer* p) {
   // Forward-declare the DescriptorTable because this is referenced by .pb.cc
   // files depending on this file.
   //
@@ -1268,114 +1404,102 @@
   // weak fields must refer to table struct but cannot include the header.
   // Also it annotates extra weak attributes.
   // TODO(gerbens) make sure this situation is handled better.
-  format(
-      "\n"
-      "// Internal implementation detail -- do not use these members.\n"
-      "struct $dllexport_decl $$tablename$ {\n"
-      "  static const $uint32$ offsets[];\n"
-      "};\n");
+  p->Emit(R"cc(
+    // Internal implementation detail -- do not use these members.
+    struct $dllexport_decl $$tablename$ {
+      static const ::uint32_t offsets[];
+    };
+  )cc");
+
   if (HasDescriptorMethods(file_, options_)) {
-    format(
-        "$dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable "
-        "$desc_table$;\n");
+    p->Emit(R"cc(
+      $dllexport_decl $extern const ::$proto_ns$::internal::DescriptorTable
+          $desc_table$;
+    )cc");
   }
 }
 
-void FileGenerator::GenerateMessageDefinitions(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  // Generate class definitions.
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (i > 0) {
-      format("\n");
-      format(kThinSeparator);
-      format("\n");
-    }
-    message_generators_[i]->GenerateClassDefinition(printer);
+void FileGenerator::GenerateMessageDefinitions(io::Printer* p) {
+  for (int i = 0; i < message_generators_.size(); ++i) {
+    p->Emit(R"cc(
+      $hrule_thin$
+    )cc");
+    message_generators_[i]->GenerateClassDefinition(p);
   }
 }
 
-void FileGenerator::GenerateEnumDefinitions(io::Printer* printer) {
-  // Generate enum definitions.
-  for (int i = 0; i < enum_generators_.size(); i++) {
-    enum_generators_[i]->GenerateDefinition(printer);
+void FileGenerator::GenerateEnumDefinitions(io::Printer* p) {
+  for (int i = 0; i < enum_generators_.size(); ++i) {
+    enum_generators_[i]->GenerateDefinition(p);
   }
 }
 
-void FileGenerator::GenerateServiceDefinitions(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  if (HasGenericServices(file_, options_)) {
-    // Generate service definitions.
-    for (int i = 0; i < service_generators_.size(); i++) {
-      if (i > 0) {
-        format("\n");
-        format(kThinSeparator);
-        format("\n");
-      }
-      service_generators_[i]->GenerateDeclarations(printer);
-    }
-
-    format("\n");
-    format(kThickSeparator);
-    format("\n");
+void FileGenerator::GenerateServiceDefinitions(io::Printer* p) {
+  if (!HasGenericServices(file_, options_)) {
+    return;
   }
+
+  for (int i = 0; i < service_generators_.size(); ++i) {
+    p->Emit(R"cc(
+      $hrule_thin$
+    )cc");
+    service_generators_[i]->GenerateDeclarations(p);
+  }
+
+  p->Emit(R"cc(
+    $hrule_thick$
+  )cc");
 }
 
-void FileGenerator::GenerateExtensionIdentifiers(io::Printer* printer) {
+void FileGenerator::GenerateExtensionIdentifiers(io::Printer* p) {
   // Declare extension identifiers. These are in global scope and so only
   // the global scope extensions.
   for (auto& extension_generator : extension_generators_) {
-    if (extension_generator->IsScoped()) continue;
-    extension_generator->GenerateDeclaration(printer);
+    if (extension_generator->IsScoped()) {
+      continue;
+    }
+    extension_generator->GenerateDeclaration(p);
   }
 }
 
-void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void FileGenerator::GenerateInlineFunctionDefinitions(io::Printer* p) {
   // TODO(gerbens) remove pragmas when gcc is no longer used. Current version
   // of gcc fires a bogus error when compiled with strict-aliasing.
-  format(
-      "#ifdef __GNUC__\n"
-      "  #pragma GCC diagnostic push\n"
-      "  #pragma GCC diagnostic ignored \"-Wstrict-aliasing\"\n"
-      "#endif  // __GNUC__\n");
-  // Generate class inline methods.
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (i > 0) {
-      format(kThinSeparator);
-      format("\n");
-    }
-    message_generators_[i]->GenerateInlineMethods(printer);
-  }
-  format(
-      "#ifdef __GNUC__\n"
-      "  #pragma GCC diagnostic pop\n"
-      "#endif  // __GNUC__\n");
+  p->Emit(R"(
+      #ifdef __GNUC__
+      #pragma GCC diagnostic push
+      #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+      #endif  // __GNUC__
+  )");
 
-  for (int i = 0; i < message_generators_.size(); i++) {
-    if (i > 0) {
-      format(kThinSeparator);
-      format("\n");
-    }
+  for (int i = 0; i < message_generators_.size(); ++i) {
+    p->Emit(R"cc(
+      $hrule_thin$
+    )cc");
+    message_generators_[i]->GenerateInlineMethods(p);
   }
+
+  p->Emit(R"(
+      #ifdef __GNUC__
+      #pragma GCC diagnostic pop
+      #endif  // __GNUC__
+  )");
 }
 
-void FileGenerator::GenerateProto2NamespaceEnumSpecializations(
-    io::Printer* printer) {
-  Formatter format(printer, variables_);
-  // Emit GetEnumDescriptor specializations into google::protobuf namespace:
-  if (HasEnumDefinitions(file_)) {
-    format("\n");
-    {
-      NamespaceOpener proto_ns(ProtobufNamespace(options_), format);
-      format("\n");
-      for (int i = 0; i < enum_generators_.size(); i++) {
-        enum_generators_[i]->GenerateGetEnumDescriptorSpecializations(printer);
-      }
-      format("\n");
-    }
+void FileGenerator::GenerateProto2NamespaceEnumSpecializations(io::Printer* p) {
+  // Emit GetEnumDescriptor specializations into google::protobuf namespace.
+  if (!HasEnumDefinitions(file_)) {
+    return;
   }
-}
 
+  p->PrintRaw("\n");
+  NamespaceOpener ns(ProtobufNamespace(options_), p);
+  p->PrintRaw("\n");
+  for (auto& gen : enum_generators_) {
+    gen->GenerateGetEnumDescriptorSpecializations(p);
+  }
+  p->PrintRaw("\n");
+}
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/file.h b/src/google/protobuf/compiler/cpp/file.h
index ca05361..5f8ffcf 100644
--- a/src/google/protobuf/compiler/cpp/file.h
+++ b/src/google/protobuf/compiler/cpp/file.h
@@ -36,52 +36,47 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_FILE_H__
 
 #include <algorithm>
+#include <functional>
 #include <memory>
-#include <set>
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/cpp/field.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/compiler/cpp/options.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/compiler/scc.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "google/protobuf/compiler/cpp/enum.h"
+#include "google/protobuf/compiler/cpp/extension.h"
+#include "google/protobuf/compiler/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/message.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/compiler/cpp/service.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/port.h"
 
-namespace google {
-namespace protobuf {
-class FileDescriptor;  // descriptor.h
-namespace io {
-class Printer;  // printer.h
-}
-}  // namespace protobuf
-}  // namespace google
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
-class EnumGenerator;       // enum.h
-class MessageGenerator;    // message.h
-class ServiceGenerator;    // service.h
-class ExtensionGenerator;  // extension.h
-
 class FileGenerator {
  public:
-  // See generator.cc for the meaning of dllexport_decl.
   FileGenerator(const FileDescriptor* file, const Options& options);
-  ~FileGenerator();
 
-  // Shared code between the two header generators below.
-  void GenerateHeader(io::Printer* printer);
+  FileGenerator(const FileGenerator&) = delete;
+  FileGenerator& operator=(const FileGenerator&) = delete;
+
+  ~FileGenerator() = default;
 
   // info_path, if non-empty, should be the path (relative to printer's
   // output) to the metadata file describing this proto header.
-  void GenerateProtoHeader(io::Printer* printer, const std::string& info_path);
+  void GenerateProtoHeader(io::Printer* p, absl::string_view info_path);
   // info_path, if non-empty, should be the path (relative to printer's
   // output) to the metadata file describing this PB header.
-  void GeneratePBHeader(io::Printer* printer, const std::string& info_path);
-  void GenerateSource(io::Printer* printer);
+  void GeneratePBHeader(io::Printer* p, absl::string_view info_path);
+  void GenerateSource(io::Printer* p);
 
   // The following member functions are used when the lite_implicit_weak_fields
   // option is set. In this mode the code is organized a bit differently to
@@ -92,78 +87,86 @@
   int NumMessages() const { return message_generators_.size(); }
   int NumExtensions() const { return extension_generators_.size(); }
   // Generates the source file for one message.
-  void GenerateSourceForMessage(int idx, io::Printer* printer);
+  void GenerateSourceForMessage(int idx, io::Printer* p);
   // Generates the source file for one extension.
-  void GenerateSourceForExtension(int idx, io::Printer* printer);
+  void GenerateSourceForExtension(int idx, io::Printer* p);
   // Generates a source file containing everything except messages and
   // extensions.
-  void GenerateGlobalSource(io::Printer* printer);
+  void GenerateGlobalSource(io::Printer* p);
 
  private:
+  // Generates a file, setting up the necessary accoutrements that start and
+  // end the file, calling `cb` in between.
+  //
+  // This includes header guards and file-global variables.
+  void GenerateFile(io::Printer* p, GeneratedFileType file_type,
+                    std::function<void()> cb);
+
+  // Shared code between the two header generators.
+  void GenerateSharedHeaderCode(io::Printer* p);
+
   // Internal type used by GenerateForwardDeclarations (defined in file.cc).
   class ForwardDeclarations;
   struct CrossFileReferences;
 
-  void IncludeFile(const std::string& google3_name, io::Printer* printer) {
-    DoIncludeFile(google3_name, false, printer);
+  void IncludeFile(absl::string_view google3_name, io::Printer* p) {
+    DoIncludeFile(google3_name, false, p);
   }
-  void IncludeFileAndExport(const std::string& google3_name,
-                            io::Printer* printer) {
-    DoIncludeFile(google3_name, true, printer);
+  void IncludeFileAndExport(absl::string_view google3_name, io::Printer* p) {
+    DoIncludeFile(google3_name, true, p);
   }
-  void DoIncludeFile(const std::string& google3_name, bool do_export,
-                     io::Printer* printer);
+  void DoIncludeFile(absl::string_view google3_name, bool do_export,
+                     io::Printer* p);
 
-  std::string CreateHeaderInclude(const std::string& basename,
+  std::string CreateHeaderInclude(absl::string_view basename,
                                   const FileDescriptor* file);
   void GetCrossFileReferencesForField(const FieldDescriptor* field,
                                       CrossFileReferences* refs);
   void GetCrossFileReferencesForFile(const FileDescriptor* file,
                                      CrossFileReferences* refs);
   void GenerateInternalForwardDeclarations(const CrossFileReferences& refs,
-                                           io::Printer* printer);
-  void GenerateSourceIncludes(io::Printer* printer);
-  void GenerateSourcePrelude(io::Printer* printer);
-  void GenerateSourceDefaultInstance(int idx, io::Printer* printer);
+                                           io::Printer* p);
+  void GenerateSourceIncludes(io::Printer* p);
+  void GenerateSourcePrelude(io::Printer* p);
+  void GenerateSourceDefaultInstance(int idx, io::Printer* p);
 
   void GenerateInitForSCC(const SCC* scc, const CrossFileReferences& refs,
-                          io::Printer* printer);
-  void GenerateReflectionInitializationCode(io::Printer* printer);
+                          io::Printer* p);
+  void GenerateReflectionInitializationCode(io::Printer* p);
 
   // For other imports, generates their forward-declarations.
-  void GenerateForwardDeclarations(io::Printer* printer);
+  void GenerateForwardDeclarations(io::Printer* p);
 
   // Generates top or bottom of a header file.
-  void GenerateTopHeaderGuard(io::Printer* printer, bool pb_h);
-  void GenerateBottomHeaderGuard(io::Printer* printer, bool pb_h);
+  void GenerateTopHeaderGuard(io::Printer* p, GeneratedFileType file_type);
+  void GenerateBottomHeaderGuard(io::Printer* p, GeneratedFileType file_type);
 
   // Generates #include directives.
-  void GenerateLibraryIncludes(io::Printer* printer);
-  void GenerateDependencyIncludes(io::Printer* printer);
+  void GenerateLibraryIncludes(io::Printer* p);
+  void GenerateDependencyIncludes(io::Printer* p);
 
   // Generate a pragma to pull in metadata using the given info_path (if
   // non-empty). info_path should be relative to printer's output.
-  void GenerateMetadataPragma(io::Printer* printer,
-                              const std::string& info_path);
+  void GenerateMetadataPragma(io::Printer* p, absl::string_view info_path);
 
   // Generates a couple of different pieces before definitions:
-  void GenerateGlobalStateFunctionDeclarations(io::Printer* printer);
+  void GenerateGlobalStateFunctionDeclarations(io::Printer* p);
 
   // Generates types for classes.
-  void GenerateMessageDefinitions(io::Printer* printer);
+  void GenerateMessageDefinitions(io::Printer* p);
 
-  void GenerateEnumDefinitions(io::Printer* printer);
+  void GenerateEnumDefinitions(io::Printer* p);
 
   // Generates generic service definitions.
-  void GenerateServiceDefinitions(io::Printer* printer);
+  void GenerateServiceDefinitions(io::Printer* p);
 
   // Generates extension identifiers.
-  void GenerateExtensionIdentifiers(io::Printer* printer);
+  void GenerateExtensionIdentifiers(io::Printer* p);
 
   // Generates inline function definitions.
-  void GenerateInlineFunctionDefinitions(io::Printer* printer);
+  void GenerateInlineFunctionDefinitions(io::Printer* p);
 
-  void GenerateProto2NamespaceEnumSpecializations(io::Printer* printer);
+  void GenerateProto2NamespaceEnumSpecializations(io::Printer* p);
 
   // Sometimes the names we use in a .proto file happen to be defined as
   // macros on some platforms (e.g., macro/minor used in plugin.proto are
@@ -172,7 +175,7 @@
   // undef the macro for these few platforms, or rename the field name for all
   // platforms. Since these names are part of protobuf public API, renaming is
   // generally a breaking change so we prefer the #undef approach.
-  void GenerateMacroUndefs(io::Printer* printer);
+  void GenerateMacroUndefs(io::Printer* p);
 
   bool IsDepWeak(const FileDescriptor* dep) const {
     if (weak_deps_.count(dep) != 0) {
@@ -182,14 +185,17 @@
     return false;
   }
 
-  std::set<const FileDescriptor*> weak_deps_;
+  absl::flat_hash_set<const FileDescriptor*> weak_deps_;
 
   const FileDescriptor* file_;
-  const Options options_;
+  Options options_;
 
   MessageSCCAnalyzer scc_analyzer_;
 
-  std::map<std::string, std::string> variables_;
+  // This member is unused and should be deleted once all old-style variable
+  // maps are gone.
+  // TODO(b/245791219)
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
 
   // Contains the post-order walk of all the messages (and child messages) in
   // this file. If you need a pre-order walk just reverse iterate.
@@ -197,8 +203,6 @@
   std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
   std::vector<std::unique_ptr<ServiceGenerator>> service_generators_;
   std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/generator.cc b/src/google/protobuf/compiler/cpp/generator.cc
index 63a2bce..b45b16b 100644
--- a/src/google/protobuf/compiler/cpp/generator.cc
+++ b/src/google/protobuf/compiler/cpp/generator.cc
@@ -32,31 +32,65 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/generator.h>
+#include "google/protobuf/compiler/cpp/generator.h"
 
+#include <cstdlib>
 #include <memory>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/compiler/cpp/file.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/compiler/cpp/file.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/descriptor.pb.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
-CppGenerator::CppGenerator() {}
-CppGenerator::~CppGenerator() {}
-
 namespace {
-std::string NumberedCcFileName(const std::string& basename, int number) {
-  return StrCat(basename, ".out/", number, ".cc");
+std::string NumberedCcFileName(absl::string_view basename, int number) {
+  return absl::StrCat(basename, ".out/", number, ".cc");
+}
+
+absl::flat_hash_map<absl::string_view, std::string> CommonVars(
+    const Options& options) {
+  bool is_oss = options.opensource_runtime;
+  return {
+      {"proto_ns", ProtobufNamespace(options)},
+      {"string", "std::string"},
+      {"int8", "::int8_t"},
+      {"int32", "::int32_t"},
+      {"int64", "::int64_t"},
+      {"uint8", "::uint8_t"},
+      {"uint32", "::uint32_t"},
+      {"uint64", "::uint64_t"},
+
+      {"hrule_thick", kThickSeparator},
+      {"hrule_thin", kThinSeparator},
+
+      // Warning: there is some clever naming/splitting here to avoid extract
+      // script rewrites.  The names of these variables must not be things that
+      // the extract script will rewrite.  That's why we use "CHK" (for example)
+      // instead of "GOOGLE_CHECK".
+      //
+      // These values are things the extract script would rewrite if we did not
+      // split them.  It might not strictly matter since we don't generate
+      // google3 code in open-source.  But it's good to prevent surprising
+      // things from happening.
+      {"GOOGLE_PROTOBUF", is_oss ? "GOOGLE_PROTOBUF"
+                                 : "GOOGLE3_PROTOBU"
+                                   "F"},
+      {"CHK", is_oss ? "GOOGLE_CHECK"
+                     : "CHEC"
+                       "K"},
+      {"DCHK", is_oss ? "GOOGLE_DCHECK"
+                      : "DCHEC"
+                        "K"},
+  };
 }
 }  // namespace
 
@@ -64,7 +98,7 @@
                             const std::string& parameter,
                             GeneratorContext* generator_context,
                             std::string* error) const {
-  std::vector<std::pair<std::string, std::string> > options;
+  std::vector<std::pair<std::string, std::string>> options;
   ParseGeneratorParameter(parameter, &options);
 
   // -----------------------------------------------------------------
@@ -93,70 +127,71 @@
   file_options.opensource_runtime = opensource_runtime_;
   file_options.runtime_include_base = runtime_include_base_;
 
-  for (int i = 0; i < options.size(); i++) {
-    if (options[i].first == "dllexport_decl") {
-      file_options.dllexport_decl = options[i].second;
-    } else if (options[i].first == "safe_boundary_check") {
+  for (const auto& option : options) {
+    const auto& key = option.first;
+    const auto& value = option.second;
+
+    if (key == "dllexport_decl") {
+      file_options.dllexport_decl = value;
+    } else if (key == "safe_boundary_check") {
       file_options.safe_boundary_check = true;
-    } else if (options[i].first == "annotate_headers") {
+    } else if (key == "annotate_headers") {
       file_options.annotate_headers = true;
-    } else if (options[i].first == "annotation_pragma_name") {
-      file_options.annotation_pragma_name = options[i].second;
-    } else if (options[i].first == "annotation_guard_name") {
-      file_options.annotation_guard_name = options[i].second;
-    } else if (options[i].first == "speed") {
+    } else if (key == "annotation_pragma_name") {
+      file_options.annotation_pragma_name = value;
+    } else if (key == "annotation_guard_name") {
+      file_options.annotation_guard_name = value;
+    } else if (key == "speed") {
       file_options.enforce_mode = EnforceOptimizeMode::kSpeed;
-    } else if (options[i].first == "code_size") {
+    } else if (key == "code_size") {
       file_options.enforce_mode = EnforceOptimizeMode::kCodeSize;
-    } else if (options[i].first == "lite") {
+    } else if (key == "lite") {
       file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
-    } else if (options[i].first == "lite_implicit_weak_fields") {
+    } else if (key == "lite_implicit_weak_fields") {
       file_options.enforce_mode = EnforceOptimizeMode::kLiteRuntime;
       file_options.lite_implicit_weak_fields = true;
-      if (!options[i].second.empty()) {
-        file_options.num_cc_files =
-            strto32(options[i].second.c_str(), nullptr, 10);
+      if (!value.empty()) {
+        file_options.num_cc_files = std::strtol(value.c_str(), nullptr, 10);
       }
-    } else if (options[i].first == "proto_h") {
+    } else if (key == "proto_h") {
       file_options.proto_h = true;
-    } else if (options[i].first == "annotate_accessor") {
+    } else if (key == "proto_static_reflection_h") {
+    } else if (key == "annotate_accessor") {
       file_options.annotate_accessor = true;
-    } else if (options[i].first == "inject_field_listener_events") {
+    } else if (key == "inject_field_listener_events") {
       file_options.field_listener_options.inject_field_listener_events = true;
-    } else if (options[i].first == "forbidden_field_listener_events") {
+    } else if (key == "forbidden_field_listener_events") {
       std::size_t pos = 0;
       do {
-        std::size_t next_pos = options[i].second.find_first_of("+", pos);
+        std::size_t next_pos = value.find_first_of("+", pos);
         if (next_pos == std::string::npos) {
-          next_pos = options[i].second.size();
+          next_pos = value.size();
         }
         if (next_pos > pos)
           file_options.field_listener_options.forbidden_field_listener_events
-              .insert(options[i].second.substr(pos, next_pos - pos));
+              .emplace(value.substr(pos, next_pos - pos));
         pos = next_pos + 1;
-      } while (pos < options[i].second.size());
-    } else if (options[i].first == "verified_lazy") {
-      file_options.unverified_lazy = false;
-    } else if (options[i].first == "unverified_lazy_message_sets") {
+      } while (pos < value.size());
+    } else if (key == "unverified_lazy_message_sets") {
       file_options.unverified_lazy_message_sets = true;
-    } else if (options[i].first == "message_owned_arena_trial") {
+    } else if (key == "message_owned_arena_trial") {
       file_options.message_owned_arena_trial = true;
-    } else if (options[i].first == "force_eagerly_verified_lazy") {
+    } else if (key == "force_eagerly_verified_lazy") {
       file_options.force_eagerly_verified_lazy = true;
-    } else if (options[i].first == "experimental_tail_call_table_mode") {
-      if (options[i].second == "never") {
+    } else if (key == "experimental_tail_call_table_mode") {
+      if (value == "never") {
         file_options.tctable_mode = Options::kTCTableNever;
-      } else if (options[i].second == "guarded") {
+      } else if (value == "guarded") {
         file_options.tctable_mode = Options::kTCTableGuarded;
-      } else if (options[i].second == "always") {
+      } else if (value == "always") {
         file_options.tctable_mode = Options::kTCTableAlways;
       } else {
-        *error = "Unknown value for experimental_tail_call_table_mode: " +
-                 options[i].second;
+        *error =
+            "Unknown value for experimental_tail_call_table_mode: " + value;
         return false;
       }
     } else {
-      *error = "Unknown generator option: " + options[i].first;
+      *error = "Unknown generator option: " + key;
       return false;
     }
   }
@@ -174,6 +209,17 @@
 
   std::string basename = StripProto(file->name());
 
+  auto generate_reserved_static_reflection_header = [&basename,
+                                                     &generator_context]() {
+    auto output = absl::WrapUnique(generator_context->Open(
+        absl::StrCat(basename, ".proto.static_reflection.h")));
+    io::Printer(output.get()).Emit(R"cc(
+      // Reserved for future use.
+    )cc");
+  };
+  // Suppress maybe unused warning.
+  (void)generate_reserved_static_reflection_header;
+
   if (MaybeBootstrap(file_options, generator_context, file_options.bootstrap,
                      &basename)) {
     return true;
@@ -183,39 +229,51 @@
 
   // Generate header(s).
   if (file_options.proto_h) {
-    std::unique_ptr<io::ZeroCopyOutputStream> output(
-        generator_context->Open(basename + ".proto.h"));
+    auto output = absl::WrapUnique(
+        generator_context->Open(absl::StrCat(basename, ".proto.h")));
+
     GeneratedCodeInfo annotations;
     io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
         &annotations);
-    std::string info_path = basename + ".proto.h.meta";
-    io::Printer printer(
-        output.get(), '$',
-        file_options.annotate_headers ? &annotation_collector : nullptr);
-    file_generator.GenerateProtoHeader(
-        &printer, file_options.annotate_headers ? info_path : "");
+    io::Printer::Options options;
     if (file_options.annotate_headers) {
-      std::unique_ptr<io::ZeroCopyOutputStream> info_output(
-          generator_context->Open(info_path));
+      options.annotation_collector = &annotation_collector;
+    }
+
+    io::Printer p(output.get(), options);
+    auto v = p.WithVars(CommonVars(file_options));
+
+    std::string info_path = absl::StrCat(basename, ".proto.h.meta");
+    file_generator.GenerateProtoHeader(
+        &p, file_options.annotate_headers ? info_path : "");
+
+    if (file_options.annotate_headers) {
+      auto info_output = absl::WrapUnique(generator_context->Open(info_path));
       annotations.SerializeToZeroCopyStream(info_output.get());
     }
   }
 
   {
-    std::unique_ptr<io::ZeroCopyOutputStream> output(
-        generator_context->Open(basename + ".pb.h"));
+    auto output = absl::WrapUnique(
+        generator_context->Open(absl::StrCat(basename, ".pb.h")));
+
     GeneratedCodeInfo annotations;
     io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
         &annotations);
-    std::string info_path = basename + ".pb.h.meta";
-    io::Printer printer(
-        output.get(), '$',
-        file_options.annotate_headers ? &annotation_collector : nullptr);
-    file_generator.GeneratePBHeader(
-        &printer, file_options.annotate_headers ? info_path : "");
+    io::Printer::Options options;
     if (file_options.annotate_headers) {
-      std::unique_ptr<io::ZeroCopyOutputStream> info_output(
-          generator_context->Open(info_path));
+      options.annotation_collector = &annotation_collector;
+    }
+
+    io::Printer p(output.get(), options);
+    auto v = p.WithVars(CommonVars(file_options));
+
+    std::string info_path = absl::StrCat(basename, ".pb.h.meta");
+    file_generator.GeneratePBHeader(
+        &p, file_options.annotate_headers ? info_path : "");
+
+    if (file_options.annotate_headers) {
+      auto info_output = absl::WrapUnique(generator_context->Open(info_path));
       annotations.SerializeToZeroCopyStream(info_output.get());
     }
   }
@@ -225,10 +283,12 @@
     {
       // This is the global .cc file, containing
       // enum/services/tables/reflection
-      std::unique_ptr<io::ZeroCopyOutputStream> output(
-          generator_context->Open(basename + ".pb.cc"));
-      io::Printer printer(output.get(), '$');
-      file_generator.GenerateGlobalSource(&printer);
+      auto output = absl::WrapUnique(
+          generator_context->Open(absl::StrCat(basename, ".pb.cc")));
+      io::Printer p(output.get());
+      auto v = p.WithVars(CommonVars(file_options));
+
+      file_generator.GenerateGlobalSource(&p);
     }
 
     int num_cc_files =
@@ -244,35 +304,43 @@
              "and extensions.";
       num_cc_files = file_options.num_cc_files;
     }
+
     int cc_file_number = 0;
-    for (int i = 0; i < file_generator.NumMessages(); i++) {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
+    for (int i = 0; i < file_generator.NumMessages(); ++i) {
+      auto output = absl::WrapUnique(generator_context->Open(
           NumberedCcFileName(basename, cc_file_number++)));
-      io::Printer printer(output.get(), '$');
-      file_generator.GenerateSourceForMessage(i, &printer);
+      io::Printer p(output.get());
+      auto v = p.WithVars(CommonVars(file_options));
+
+      file_generator.GenerateSourceForMessage(i, &p);
     }
-    for (int i = 0; i < file_generator.NumExtensions(); i++) {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
+
+    for (int i = 0; i < file_generator.NumExtensions(); ++i) {
+      auto output = absl::WrapUnique(generator_context->Open(
           NumberedCcFileName(basename, cc_file_number++)));
-      io::Printer printer(output.get(), '$');
-      file_generator.GenerateSourceForExtension(i, &printer);
+      io::Printer p(output.get());
+      auto v = p.WithVars(CommonVars(file_options));
+
+      file_generator.GenerateSourceForExtension(i, &p);
     }
+
     // Create empty placeholder files if necessary to match the expected number
     // of files.
-    for (; cc_file_number < num_cc_files; ++cc_file_number) {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(generator_context->Open(
-          NumberedCcFileName(basename, cc_file_number)));
+    while (cc_file_number < num_cc_files) {
+      (void)absl::WrapUnique(generator_context->Open(
+          NumberedCcFileName(basename, cc_file_number++)));
     }
   } else {
-    std::unique_ptr<io::ZeroCopyOutputStream> output(
-        generator_context->Open(basename + ".pb.cc"));
-    io::Printer printer(output.get(), '$');
-    file_generator.GenerateSource(&printer);
+    auto output = absl::WrapUnique(
+        generator_context->Open(absl::StrCat(basename, ".pb.cc")));
+    io::Printer p(output.get());
+    auto v = p.WithVars(CommonVars(file_options));
+
+    file_generator.GenerateSource(&p);
   }
 
   return true;
 }
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/generator.h b/src/google/protobuf/compiler/cpp/generator.h
index 1a374b9..aa4ee82 100644
--- a/src/google/protobuf/compiler/cpp/generator.h
+++ b/src/google/protobuf/compiler/cpp/generator.h
@@ -38,24 +38,27 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
 
 #include <string>
-#include <google/protobuf/compiler/code_generator.h>
+#include <utility>
+
+#include "google/protobuf/compiler/code_generator.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
 // CodeGenerator implementation which generates a C++ source file and
 // header.  If you create your own protocol compiler binary and you want
 // it to support C++ output, you can do so by registering an instance of this
 // CodeGenerator with the CommandLineInterface in your main() function.
 class PROTOC_EXPORT CppGenerator : public CodeGenerator {
  public:
-  CppGenerator();
-  ~CppGenerator() override;
+  CppGenerator() = default;
+  CppGenerator(const CppGenerator&) = delete;
+  CppGenerator& operator=(const CppGenerator&) = delete;
+  ~CppGenerator() override = default;
 
   enum class Runtime {
     kGoogle3,     // Use the internal google3 runtime.
@@ -74,34 +77,29 @@
   // If set to a non-empty string, generated code will do:
   //   #include "<BASE>/google/protobuf/message.h"
   // instead of:
-  //   #include <google/protobuf/message.h>
+  //   #include "google/protobuf/message.h"
   // This has no effect if opensource_runtime = false.
-  void set_runtime_include_base(const std::string& base) {
-    runtime_include_base_ = base;
+  void set_runtime_include_base(std::string base) {
+    runtime_include_base_ = std::move(base);
   }
 
-  // implements CodeGenerator ----------------------------------------
   bool Generate(const FileDescriptor* file, const std::string& parameter,
                 GeneratorContext* generator_context,
                 std::string* error) 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;
   }
 
  private:
-  bool opensource_runtime_ = true;
+  bool opensource_runtime_ = PROTO2_IS_OSS;
   std::string runtime_include_base_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CppGenerator);
 };
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/cpp/helpers.cc b/src/google/protobuf/compiler/cpp/helpers.cc
index 4b7c5c9..5898717 100644
--- a/src/google/protobuf/compiler/cpp/helpers.cc
+++ b/src/google/protobuf/compiler/cpp/helpers.cc
@@ -32,35 +32,43 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include "google/protobuf/compiler/cpp/helpers.h"
 
+#include <algorithm>
 #include <cstdint>
 #include <functional>
 #include <limits>
-#include <map>
 #include <memory>
 #include <queue>
-#include <unordered_set>
+#include <string>
+#include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/names.h>
-#include <google/protobuf/compiler/cpp/options.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/compiler/scc.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/strings/substitute.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/compiler/cpp/names.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -72,11 +80,12 @@
 static const char kAnyMessageName[] = "Any";
 static const char kAnyProtoFile[] = "google/protobuf/any.proto";
 
-std::string DotsToColons(const std::string& name) {
-  return StringReplace(name, ".", "::", true);
+std::string DotsToColons(absl::string_view name) {
+  return absl::StrReplaceAll(name, {{".", "::"}});
 }
 
-static const char* const kKeywordList[] = {  //
+static const char* const kKeywordList[] = {
+    //
     "NULL",
     "alignas",
     "alignof",
@@ -159,25 +168,33 @@
     "wchar_t",
     "while",
     "xor",
-    "xor_eq"};
+    "xor_eq",
+    "char8_t",
+    "char16_t",
+    "char32_t",
+    "concept",
+    "consteval",
+    "constinit",
+    "co_await",
+    "co_return",
+    "co_yield",
+    "requires",
+};
 
-static std::unordered_set<std::string>* MakeKeywordsMap() {
-  auto* result = new std::unordered_set<std::string>();
-  for (const auto keyword : kKeywordList) {
-    result->emplace(keyword);
-  }
-  return result;
+const absl::flat_hash_set<absl::string_view>& Keywords() {
+  static const auto* keywords = [] {
+    auto* keywords = new absl::flat_hash_set<absl::string_view>();
+
+    for (const auto keyword : kKeywordList) {
+      keywords->emplace(keyword);
+    }
+    return keywords;
+  }();
+  return *keywords;
 }
 
-static std::unordered_set<std::string>& kKeywords = *MakeKeywordsMap();
-
 std::string IntTypeName(const Options& options, const std::string& type) {
-  return type + "_t";
-}
-
-void SetIntVar(const Options& options, const std::string& type,
-               std::map<std::string, std::string>* variables) {
-  (*variables)[type] = IntTypeName(options, type);
+  return absl::StrCat("::", type, "_t");
 }
 
 // Returns true if the message can potentially allocate memory for its field.
@@ -186,21 +203,6 @@
   return false;
 }
 
-// Describes different approaches to detect non-canonical int32 encoding. Only
-// kNever or kAlways is eligible for *simple* verification methods.
-enum class VerifyInt32Type {
-  kCustom,  // Only check if field number matches.
-  kNever,   // Do not check.
-  kAlways,  // Always check.
-};
-
-inline VerifySimpleType VerifyInt32TypeToVerifyCustom(VerifyInt32Type t) {
-  static VerifySimpleType kCustomTypes[] = {
-      VerifySimpleType::kCustom, VerifySimpleType::kCustomInt32Never,
-      VerifySimpleType::kCustomInt32Always};
-  return kCustomTypes[static_cast<int32_t>(t) -
-                      static_cast<int32_t>(VerifyInt32Type::kCustom)];
-}
 
 }  // namespace
 
@@ -228,83 +230,66 @@
   return false;
 }
 
-void SetCommonVars(const Options& options,
-                   std::map<std::string, std::string>* variables) {
-  (*variables)["proto_ns"] = ProtobufNamespace(options);
-
-  // Warning: there is some clever naming/splitting here to avoid extract script
-  // rewrites.  The names of these variables must not be things that the extract
-  // script will rewrite.  That's why we use "CHK" (for example) instead of
-  // "GOOGLE_CHECK".
-  if (options.opensource_runtime) {
-    (*variables)["GOOGLE_PROTOBUF"] = "GOOGLE_PROTOBUF";
-    (*variables)["CHK"] = "GOOGLE_CHECK";
-    (*variables)["DCHK"] = "GOOGLE_DCHECK";
-  } else {
-    // These values are things the extract script would rewrite if we did not
-    // split them.  It might not strictly matter since we don't generate google3
-    // code in open-source.  But it's good to prevent surprising things from
-    // happening.
-    (*variables)["GOOGLE_PROTOBUF"] =
-        "GOOGLE3"
-        "_PROTOBUF";
-    (*variables)["CHK"] =
-        "CH"
-        "ECK";
-    (*variables)["DCHK"] =
-        "DCH"
-        "ECK";
-  }
-
-  SetIntVar(options, "int8", variables);
-  SetIntVar(options, "uint8", variables);
-  SetIntVar(options, "uint32", variables);
-  SetIntVar(options, "uint64", variables);
-  SetIntVar(options, "int32", variables);
-  SetIntVar(options, "int64", variables);
-  (*variables)["string"] = "std::string";
+absl::flat_hash_map<absl::string_view, std::string> MessageVars(
+    const Descriptor* desc) {
+  absl::string_view prefix = IsMapEntryMessage(desc) ? "" : "_impl_.";
+  return {
+      {"any_metadata", absl::StrCat(prefix, "_any_metadata_")},
+      {"cached_size", absl::StrCat(prefix, "_cached_size_")},
+      {"extensions", absl::StrCat(prefix, "_extensions_")},
+      {"has_bits", absl::StrCat(prefix, "_has_bits_")},
+      {"inlined_string_donated_array",
+       absl::StrCat(prefix, "_inlined_string_donated_")},
+      {"oneof_case", absl::StrCat(prefix, "_oneof_case_")},
+      {"tracker", "Impl_::_tracker_"},
+      {"weak_field_map", absl::StrCat(prefix, "_weak_field_map_")},
+      {"split", absl::StrCat(prefix, "_split_")},
+      {"cached_split_ptr", "cached_split_ptr"},
+  };
 }
 
 void SetCommonMessageDataVariables(
     const Descriptor* descriptor,
-    std::map<std::string, std::string>* variables) {
-  std::string prefix = IsMapEntryMessage(descriptor) ? "" : "_impl_.";
-  (*variables)["any_metadata"] = prefix + "_any_metadata_";
-  (*variables)["cached_size"] = prefix + "_cached_size_";
-  (*variables)["extensions"] = prefix + "_extensions_";
-  (*variables)["has_bits"] = prefix + "_has_bits_";
-  (*variables)["inlined_string_donated_array"] =
-      prefix + "_inlined_string_donated_";
-  (*variables)["oneof_case"] = prefix + "_oneof_case_";
-  (*variables)["tracker"] = "Impl_::_tracker_";
-  (*variables)["weak_field_map"] = prefix + "_weak_field_map_";
-  (*variables)["split"] = prefix + "_split_";
-  (*variables)["cached_split_ptr"] = "cached_split_ptr";
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
+  for (auto& pair : MessageVars(descriptor)) {
+    variables->emplace(pair);
+  }
 }
 
-void SetUnknownFieldsVariable(const Descriptor* descriptor,
-                              const Options& options,
-                              std::map<std::string, std::string>* variables) {
-  std::string proto_ns = ProtobufNamespace(options);
+absl::flat_hash_map<absl::string_view, std::string> UnknownFieldsVars(
+    const Descriptor* desc, const Options& opts) {
+  std::string proto_ns = ProtobufNamespace(opts);
+
   std::string unknown_fields_type;
-  if (UseUnknownFieldSet(descriptor->file(), options)) {
-    unknown_fields_type = "::" + proto_ns + "::UnknownFieldSet";
-    (*variables)["unknown_fields"] =
-        "_internal_metadata_.unknown_fields<" + unknown_fields_type + ">(" +
-        unknown_fields_type + "::default_instance)";
+  std::string default_instance;
+  if (UseUnknownFieldSet(desc->file(), opts)) {
+    unknown_fields_type = absl::StrCat("::", proto_ns, "::UnknownFieldSet");
+    default_instance = absl::StrCat(unknown_fields_type, "::default_instance");
   } else {
     unknown_fields_type =
-        PrimitiveTypeName(options, FieldDescriptor::CPPTYPE_STRING);
-    (*variables)["unknown_fields"] = "_internal_metadata_.unknown_fields<" +
-                                     unknown_fields_type + ">(::" + proto_ns +
-                                     "::internal::GetEmptyString)";
+        PrimitiveTypeName(opts, FieldDescriptor::CPPTYPE_STRING);
+    default_instance =
+        absl::StrCat("::", proto_ns, "::internal::GetEmptyString");
   }
-  (*variables)["unknown_fields_type"] = unknown_fields_type;
-  (*variables)["have_unknown_fields"] =
-      "_internal_metadata_.have_unknown_fields()";
-  (*variables)["mutable_unknown_fields"] =
-      "_internal_metadata_.mutable_unknown_fields<" + unknown_fields_type +
-      ">()";
+
+  return {
+      {"unknown_fields",
+       absl::Substitute("_internal_metadata_.unknown_fields<$0>($1)",
+                        unknown_fields_type, default_instance)},
+      {"unknown_fields_type", unknown_fields_type},
+      {"have_unknown_fields", "_internal_metadata_.have_unknown_fields()"},
+      {"mutable_unknown_fields",
+       absl::Substitute("_internal_metadata_.mutable_unknown_fields<$0>()",
+                        unknown_fields_type)},
+  };
+}
+
+void SetUnknownFieldsVariable(
+    const Descriptor* descriptor, const Options& options,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
+  for (auto& pair : UnknownFieldsVars(descriptor, options)) {
+    variables->emplace(pair);
+  }
 }
 
 std::string UnderscoresToCamelCase(const std::string& input,
@@ -338,7 +323,9 @@
 const char kThinSeparator[] =
     "// -------------------------------------------------------------------\n";
 
-bool CanInitializeByZeroing(const FieldDescriptor* field) {
+bool CanInitializeByZeroing(const FieldDescriptor* field,
+                            const Options& options,
+                            MessageSCCAnalyzer* scc_analyzer) {
   if (field->is_repeated() || field->is_extension()) return false;
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_ENUM:
@@ -357,6 +344,57 @@
       return field->default_value_double() == 0;
     case FieldDescriptor::CPPTYPE_BOOL:
       return field->default_value_bool() == false;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      // Non-repeated, non-lazy message fields are raw pointers initialized to
+      // null.
+      return !IsLazy(field, options, scc_analyzer);
+    default:
+      return false;
+  }
+}
+
+bool CanClearByZeroing(const FieldDescriptor* field) {
+  if (field->is_repeated() || field->is_extension()) return false;
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return field->default_value_enum()->number() == 0;
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() == 0;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() == 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() == 0;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() == 0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() == 0;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() == 0;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() == false;
+    default:
+      return false;
+  }
+}
+
+// Determines if swap can be implemented via memcpy.
+bool HasTrivialSwap(const FieldDescriptor* field, const Options& options,
+                    MessageSCCAnalyzer* scc_analyzer) {
+  if (field->is_repeated() || field->is_extension()) return false;
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_ENUM:
+    case FieldDescriptor::CPPTYPE_INT32:
+    case FieldDescriptor::CPPTYPE_INT64:
+    case FieldDescriptor::CPPTYPE_UINT32:
+    case FieldDescriptor::CPPTYPE_UINT64:
+    case FieldDescriptor::CPPTYPE_FLOAT:
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return true;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      // Non-repeated, non-lazy message fields are simply raw pointers, so we
+      // can swap them with memcpy.
+      return !IsLazy(field, options, scc_analyzer);
     default:
       return false;
   }
@@ -399,7 +437,7 @@
 
 std::string ExtensionName(const FieldDescriptor* d) {
   if (const Descriptor* scope = d->extension_scope())
-    return StrCat(ClassName(scope), "::", ResolveKeyword(d->name()));
+    return absl::StrCat(ClassName(scope), "::", ResolveKeyword(d->name()));
   return ResolveKeyword(d->name());
 }
 
@@ -418,27 +456,33 @@
   return "::" + DotsToColons(package);
 }
 
+std::string Namespace(const FileDescriptor* d) { return Namespace(d, {}); }
 std::string Namespace(const FileDescriptor* d, const Options& options) {
-  std::string ret = Namespace(d->package());
+  std::string ns = Namespace(d->package());
   if (IsWellKnownMessage(d) && options.opensource_runtime) {
     // Written with string concatenation to prevent rewriting of
     // ::google::protobuf.
-    ret = StringReplace(ret,
-                        "::google::"
-                        "protobuf",
-                        "::PROTOBUF_NAMESPACE_ID", false);
+    constexpr absl::string_view prefix =
+        "::google::"  // prevent clang-format reflowing
+        "protobuf";
+    absl::string_view new_ns(ns);
+    absl::ConsumePrefix(&new_ns, prefix);
+    return absl::StrCat("::PROTOBUF_NAMESPACE_ID", new_ns);
   }
-  return ret;
+  return ns;
 }
 
+std::string Namespace(const Descriptor* d) { return Namespace(d, {}); }
 std::string Namespace(const Descriptor* d, const Options& options) {
   return Namespace(d->file(), options);
 }
 
+std::string Namespace(const FieldDescriptor* d) { return Namespace(d, {}); }
 std::string Namespace(const FieldDescriptor* d, const Options& options) {
   return Namespace(d->file(), options);
 }
 
+std::string Namespace(const EnumDescriptor* d) { return Namespace(d, {}); }
 std::string Namespace(const EnumDescriptor* d, const Options& options) {
   return Namespace(d->file(), options);
 }
@@ -494,7 +538,7 @@
 }
 
 std::string ResolveKeyword(const std::string& name) {
-  if (kKeywords.count(name) > 0) {
+  if (Keywords().count(name) > 0) {
     return name + "_";
   }
   return name;
@@ -502,23 +546,23 @@
 
 std::string FieldName(const FieldDescriptor* field) {
   std::string result = field->name();
-  LowerString(&result);
-  if (kKeywords.count(result) > 0) {
+  absl::AsciiStrToLower(&result);
+  if (Keywords().count(result) > 0) {
     result.append("_");
   }
   return result;
 }
 
 std::string FieldMemberName(const FieldDescriptor* field, bool split) {
-  StringPiece prefix =
+  absl::string_view prefix =
       IsMapEntryMessage(field->containing_type()) ? "" : "_impl_.";
-  StringPiece split_prefix = split ? "_split_->" : "";
+  absl::string_view split_prefix = split ? "_split_->" : "";
   if (field->real_containing_oneof() == nullptr) {
-    return StrCat(prefix, split_prefix, FieldName(field), "_");
+    return absl::StrCat(prefix, split_prefix, FieldName(field), "_");
   }
   // Oneof fields are never split.
   GOOGLE_CHECK(!split);
-  return StrCat(prefix, field->containing_oneof()->name(), "_.",
+  return absl::StrCat(prefix, field->containing_oneof()->name(), "_.",
                       FieldName(field), "_");
 }
 
@@ -532,12 +576,12 @@
   GOOGLE_DCHECK(field->containing_oneof());
   const std::string qualification =
       QualifiedClassName(field->containing_type());
-  return StrCat(qualification, "::", OneofCaseConstantName(field));
+  return absl::StrCat(qualification, "::", OneofCaseConstantName(field));
 }
 
 std::string EnumValueName(const EnumValueDescriptor* enum_value) {
   std::string result = enum_value->name();
-  if (kKeywords.count(result) > 0) {
+  if (Keywords().count(result) > 0) {
     result.append("_");
   }
   return result;
@@ -577,7 +621,7 @@
     // This field's camelcase name is not unique.  As a hack, add the field
     // number to the constant name.  This makes the constant rather useless,
     // but what can we do?
-    result += "_" + StrCat(field->number());
+    result += "_" + absl::StrCat(field->number());
   }
 
   return result;
@@ -601,13 +645,13 @@
 const char* PrimitiveTypeName(FieldDescriptor::CppType type) {
   switch (type) {
     case FieldDescriptor::CPPTYPE_INT32:
-      return "int32_t";
+      return "::int32_t";
     case FieldDescriptor::CPPTYPE_INT64:
-      return "int64_t";
+      return "::int64_t";
     case FieldDescriptor::CPPTYPE_UINT32:
-      return "uint32_t";
+      return "::uint32_t";
     case FieldDescriptor::CPPTYPE_UINT64:
-      return "uint64_t";
+      return "::uint64_t";
     case FieldDescriptor::CPPTYPE_DOUBLE:
       return "double";
     case FieldDescriptor::CPPTYPE_FLOAT:
@@ -713,9 +757,9 @@
   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");
+    return absl::StrCat(number + 1, " - 1");
   } else {
-    return StrCat(number);
+    return absl::StrCat(number);
   }
 }
 
@@ -723,13 +767,13 @@
   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("int64_t{", number + 1, "} - 1");
+    return absl::StrCat("::int64_t{", number + 1, "} - 1");
   }
-  return StrCat("int64_t{", number, "}");
+  return absl::StrCat("::int64_t{", number, "}");
 }
 
 static std::string UInt64ToString(uint64_t number) {
-  return StrCat("uint64_t{", number, "u}");
+  return absl::StrCat("::uint64_t{", number, "u}");
 }
 
 std::string DefaultValue(const FieldDescriptor* field) {
@@ -741,7 +785,7 @@
     case FieldDescriptor::CPPTYPE_INT32:
       return Int32ToString(field->default_value_int32());
     case FieldDescriptor::CPPTYPE_UINT32:
-      return StrCat(field->default_value_uint32()) + "u";
+      return absl::StrCat(field->default_value_uint32()) + "u";
     case FieldDescriptor::CPPTYPE_INT64:
       return Int64ToString(field->default_value_int64());
     case FieldDescriptor::CPPTYPE_UINT64:
@@ -755,7 +799,7 @@
       } else if (value != value) {
         return "std::numeric_limits<double>::quiet_NaN()";
       } else {
-        return SimpleDtoa(value);
+        return io::SimpleDtoa(value);
       }
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
@@ -767,7 +811,7 @@
       } else if (value != value) {
         return "std::numeric_limits<float>::quiet_NaN()";
       } else {
-        std::string float_value = SimpleFtoa(value);
+        std::string float_value = io::SimpleFtoa(value);
         // If floating point value contains a period (.) or an exponent
         // (either E or e), then append suffix 'f' to make it a float
         // literal.
@@ -782,12 +826,12 @@
     case FieldDescriptor::CPPTYPE_ENUM:
       // Lazy:  Generate a static_cast because we don't have a helper function
       //   that constructs the full name of an enum value.
-      return strings::Substitute(
+      return absl::Substitute(
           "static_cast< $0 >($1)", ClassName(field->enum_type(), true),
           Int32ToString(field->default_value_enum()->number()));
     case FieldDescriptor::CPPTYPE_STRING:
       return "\"" +
-             EscapeTrigraphs(CEscape(field->default_value_string())) +
+             EscapeTrigraphs(absl::CEscape(field->default_value_string())) +
              "\"";
     case FieldDescriptor::CPPTYPE_MESSAGE:
       return "*" + FieldMessageTypeName(field, options) +
@@ -804,13 +848,13 @@
 std::string FilenameIdentifier(const std::string& filename) {
   std::string result;
   for (int i = 0; i < filename.size(); i++) {
-    if (ascii_isalnum(filename[i])) {
+    if (absl::ascii_isalnum(filename[i])) {
       result.push_back(filename[i]);
     } 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_t>(filename[i])));
+      absl::StrAppend(&result, "_",
+                      absl::Hex(static_cast<uint8_t>(filename[i])));
     }
   }
   return result;
@@ -826,14 +870,14 @@
                                      const std::string& name,
                                      const Options& options) {
   if (file->package().empty()) {
-    return StrCat("::", name);
+    return absl::StrCat("::", name);
   }
-  return StrCat(Namespace(file, options), "::", name);
+  return absl::StrCat(Namespace(file, options), "::", name);
 }
 
 // Escape C++ trigraphs by escaping question marks to \?
-std::string EscapeTrigraphs(const std::string& to_escape) {
-  return StringReplace(to_escape, "?", "\\?", true);
+std::string EscapeTrigraphs(absl::string_view to_escape) {
+  return absl::StrReplaceAll(to_escape, {{"?", "\\?"}});
 }
 
 // Escaped function name to eliminate naming conflict.
@@ -842,13 +886,13 @@
                              const std::string& prefix) {
   // Do not use FieldName() since it will escape keywords.
   std::string name = field->name();
-  LowerString(&name);
+  absl::AsciiStrToLower(&name);
   std::string function_name = prefix + name;
   if (descriptor->FindFieldByName(function_name)) {
     // Single underscore will also make it conflicting with the private data
     // member. We use double underscore to escape function names.
     function_name.append("__");
-  } else if (kKeywords.count(name) > 0) {
+  } else if (Keywords().count(name) > 0) {
     // If the field name is a keyword, we append the underscore back to keep it
     // consistent with other function names.
     function_name.append("_");
@@ -856,6 +900,9 @@
   return function_name;
 }
 
+bool IsProfileDriven(const Options& options) {
+  return options.access_info_map != nullptr;
+}
 bool IsStringInlined(const FieldDescriptor* descriptor,
                      const Options& options) {
   (void)descriptor;
@@ -903,6 +950,13 @@
 bool ShouldSplit(const Descriptor*, const Options&) { return false; }
 bool ShouldSplit(const FieldDescriptor*, const Options&) { return false; }
 
+bool ShouldForceAllocationOnConstruction(const Descriptor* desc,
+                                         const Options& options) {
+  (void)desc;
+  (void)options;
+  return false;
+}
+
 static bool HasRepeatedFields(const Descriptor* descriptor) {
   for (int i = 0; i < descriptor->field_count(); ++i) {
     if (descriptor->field(i)->label() == FieldDescriptor::LABEL_REPEATED) {
@@ -1041,7 +1095,7 @@
 
 bool IsUtf8String(const FieldDescriptor* field) {
   return IsProto3(field->file()) &&
-      field->type() == FieldDescriptor::TYPE_STRING;
+         field->type() == FieldDescriptor::TYPE_STRING;
 }
 
 VerifySimpleType ShouldVerifySimple(const Descriptor* descriptor) {
@@ -1091,7 +1145,7 @@
 }
 
 bool IsWellKnownMessage(const FileDescriptor* file) {
-  static const std::unordered_set<std::string> well_known_files{
+  static const auto* well_known_files = new absl::flat_hash_set<std::string>{
       "google/protobuf/any.proto",
       "google/protobuf/api.proto",
       "google/protobuf/compiler/plugin.proto",
@@ -1105,32 +1159,47 @@
       "google/protobuf/type.proto",
       "google/protobuf/wrappers.proto",
   };
-  return well_known_files.find(file->name()) != well_known_files.end();
+  return well_known_files->find(file->name()) != well_known_files->end();
 }
 
-static bool FieldEnforceUtf8(const FieldDescriptor* field,
-                             const Options& options) {
-  return true;
-}
-
-static bool FileUtf8Verification(const FileDescriptor* file,
-                                 const Options& options) {
-  return true;
-}
-
-// Which level of UTF-8 enforcemant is placed on this file.
-Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
-                               const Options& options) {
-  if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
-      FieldEnforceUtf8(field, options)) {
-    return Utf8CheckMode::kStrict;
-  } else if (GetOptimizeFor(field->file(), options) !=
-                 FileOptions::LITE_RUNTIME &&
-             FileUtf8Verification(field->file(), options)) {
-    return Utf8CheckMode::kVerify;
-  } else {
-    return Utf8CheckMode::kNone;
+void NamespaceOpener::ChangeTo(absl::string_view name) {
+  std::vector<std::string> new_stack =
+      absl::StrSplit(name, "::", absl::SkipEmpty());
+  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 (size_t i = name_stack_.size(); i > common_idx; i--) {
+    const auto& ns = name_stack_[i - 1];
+    if (ns == "PROTOBUF_NAMESPACE_ID") {
+      p_->Emit(R"cc(
+        PROTOBUF_NAMESPACE_CLOSE
+      )cc");
+    } else {
+      p_->Emit({{"ns", ns}}, R"(
+          }  // namespace $ns$
+        )");
+    }
+  }
+  for (size_t i = common_idx; i < new_stack.size(); ++i) {
+    const auto& ns = new_stack[i];
+    if (ns == "PROTOBUF_NAMESPACE_ID") {
+      p_->Emit(R"cc(
+        PROTOBUF_NAMESPACE_OPEN
+      )cc");
+    } else {
+      p_->Emit({{"ns", ns}}, R"(
+        namespace $ns$ {
+      )");
+    }
+  }
+
+  name_stack_ = std::move(new_stack);
 }
 
 static void GenerateUtf8CheckCode(const FieldDescriptor* field,
@@ -1139,8 +1208,10 @@
                                   const char* strict_function,
                                   const char* verify_function,
                                   const Formatter& format) {
-  switch (GetUtf8CheckMode(field, options)) {
-    case Utf8CheckMode::kStrict: {
+  switch (internal::cpp::GetUtf8CheckMode(
+      field,
+      GetOptimizeFor(field->file(), options) == FileOptions::LITE_RUNTIME)) {
+    case internal::cpp::Utf8CheckMode::kStrict: {
       if (for_parse) {
         format("DO_(");
       }
@@ -1160,7 +1231,7 @@
       format.Outdent();
       break;
     }
-    case Utf8CheckMode::kVerify: {
+    case internal::cpp::Utf8CheckMode::kVerify: {
       format("::$proto_ns$::internal::WireFormat::$1$(\n", verify_function);
       format.Indent();
       format(parameters);
@@ -1173,7 +1244,7 @@
       format.Outdent();
       break;
     }
-    case Utf8CheckMode::kNone:
+    case internal::cpp::Utf8CheckMode::kNone:
       break;
   }
 }
@@ -1239,7 +1310,9 @@
 }
 
 MessageAnalysis MessageSCCAnalyzer::GetSCCAnalysis(const SCC* scc) {
-  if (analysis_cache_.count(scc)) return analysis_cache_[scc];
+  auto it = analysis_cache_.find(scc);
+  if (it != analysis_cache_.end()) return it->second;
+
   MessageAnalysis result;
   if (UsingImplicitWeakFields(scc->GetFile(), options_)) {
     result.contains_weak = true;
@@ -1294,7 +1367,7 @@
   // in the graph, the graph should be a DAG. Hence we shouldn't need to mark
   // nodes visited as we can never return to them. By inserting them here
   // we will go in an infinite loop if the SCC is not correct.
-  return analysis_cache_[scc] = result;
+  return analysis_cache_[scc] = std::move(result);
 }
 
 void ListAllFields(const Descriptor* d,
@@ -1343,16 +1416,19 @@
     return false;
   }
 
-  std::unordered_map<std::string, std::string> bootstrap_mapping{
-      {"net/proto2/proto/descriptor",
-       "third_party/protobuf/descriptor"},
-      {"net/proto2/compiler/proto/plugin",
-       "net/proto2/compiler/proto/plugin"},
-      {"net/proto2/compiler/proto/profile",
-       "net/proto2/compiler/proto/profile_bootstrap"},
-  };
-  auto iter = bootstrap_mapping.find(basename);
-  if (iter == bootstrap_mapping.end()) {
+  static const auto* bootstrap_mapping =
+      // TODO(b/242858704) Replace these with string_view once we remove
+      // StringPiece.
+      new absl::flat_hash_map<absl::string_view, std::string>{
+          {"net/proto2/proto/descriptor",
+           "third_party/protobuf/descriptor"},
+          {"net/proto2/compiler/proto/plugin",
+           "net/proto2/compiler/proto/plugin"},
+          {"net/proto2/compiler/proto/profile",
+           "net/proto2/compiler/proto/profile_bootstrap"},
+      };
+  auto iter = bootstrap_mapping->find(basename);
+  if (iter == bootstrap_mapping->end()) {
     *bootstrap_basename = basename;
     return false;
   } else {
@@ -1377,70 +1453,64 @@
     // Adjust basename, but don't abort code generation.
     *basename = bootstrap_basename;
     return false;
-  } else {
-    const std::string& forward_to_basename = bootstrap_basename;
-
-    // Generate forwarding headers and empty .pb.cc.
-    {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(
-          generator_context->Open(*basename + ".pb.h"));
-      io::Printer printer(output.get(), '$', nullptr);
-      printer.Print(
-          "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n"
-          "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n"
-          "#include \"$forward_to_basename$.pb.h\"  // IWYU pragma: export\n"
-          "#endif  // PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PB_H\n",
-          "forward_to_basename", forward_to_basename, "filename_identifier",
-          FilenameIdentifier(*basename));
-
-      if (!options.opensource_runtime) {
-        // HACK HACK HACK, tech debt from the deeps of proto1 and SWIG
-        // protocoltype is SWIG'ed and we need to forward
-        if (*basename == "net/proto/protocoltype") {
-          printer.Print(
-              "#ifdef SWIG\n"
-              "%include \"$forward_to_basename$.pb.h\"\n"
-              "#endif  // SWIG\n",
-              "forward_to_basename", forward_to_basename);
-        }
-      }
-    }
-
-    {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(
-          generator_context->Open(*basename + ".proto.h"));
-      io::Printer printer(output.get(), '$', nullptr);
-      printer.Print(
-          "#ifndef PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n"
-          "#define PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n"
-          "#include \"$forward_to_basename$.proto.h\"  // IWYU pragma: "
-          "export\n"
-          "#endif  // "
-          "PROTOBUF_INCLUDED_$filename_identifier$_FORWARD_PROTO_H\n",
-          "forward_to_basename", forward_to_basename, "filename_identifier",
-          FilenameIdentifier(*basename));
-    }
-
-    {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(
-          generator_context->Open(*basename + ".pb.cc"));
-      io::Printer printer(output.get(), '$', nullptr);
-      printer.Print("\n");
-    }
-
-    {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(
-          generator_context->Open(*basename + ".pb.h.meta"));
-    }
-
-    {
-      std::unique_ptr<io::ZeroCopyOutputStream> output(
-          generator_context->Open(*basename + ".proto.h.meta"));
-    }
-
-    // Abort code generation.
-    return true;
   }
+
+  auto pb_h = absl::WrapUnique(
+      generator_context->Open(absl::StrCat(*basename, ".pb.h")));
+
+  io::Printer p(pb_h.get());
+  p.Emit(
+      {
+          {"fwd_to", bootstrap_basename},
+          {"file", FilenameIdentifier(*basename)},
+          {"fwd_to_suffix", options.opensource_runtime ? "pb" : "proto"},
+          {"swig_evil",
+           [&] {
+             if (options.opensource_runtime) {
+               return;
+             }
+             p.Emit(R"(
+               #ifdef SWIG
+               %include "$fwd_to$.pb.h"
+               #endif  // SWIG
+             )");
+           }},
+      },
+      R"(
+          #ifndef PROTOBUF_INCLUDED_$file$_FORWARD_PB_H
+          #define PROTOBUF_INCLUDED_$file$_FORWARD_PB_H
+          #include "$fwd_to$.$fwd_to_suffix$.h"  // IWYU pragma: export
+          #endif  // PROTOBUF_INCLUDED_$file$_FORWARD_PB_H
+          $swig_evil$;
+      )");
+
+  auto proto_h = absl::WrapUnique(
+      generator_context->Open(absl::StrCat(*basename, ".proto.h")));
+  io::Printer(proto_h.get())
+      .Emit(
+          {
+              {"fwd_to", bootstrap_basename},
+              {"file", FilenameIdentifier(*basename)},
+          },
+          R"(
+            #ifndef PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H
+            #define PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H
+            #include "$fwd_to$.proto.h"  // IWYU pragma: export
+            #endif // PROTOBUF_INCLUDED_$file$_FORWARD_PROTO_H
+          )");
+
+  auto pb_cc = absl::WrapUnique(
+      generator_context->Open(absl::StrCat(*basename, ".pb.cc")));
+  io::Printer(pb_cc.get()).PrintRaw("\n");
+
+  (void)absl::WrapUnique(
+      generator_context->Open(absl::StrCat(*basename, ".pb.h.meta")));
+
+  (void)absl::WrapUnique(
+      generator_context->Open(absl::StrCat(*basename, ".proto.h.meta")));
+
+  // Abort code generation.
+  return true;
 }
 
 static bool HasExtensionFromFile(const Message& msg, const FileDescriptor* file,
@@ -1488,9 +1558,18 @@
 static bool HasBootstrapProblem(const FileDescriptor* file,
                                 const Options& options,
                                 bool* has_opt_codesize_extension) {
-  static auto& cache = *new std::unordered_map<const FileDescriptor*, bool>;
-  auto it = cache.find(file);
-  if (it != cache.end()) return it->second;
+  struct BoostrapGlobals {
+    absl::Mutex mutex;
+    absl::flat_hash_set<const FileDescriptor*> cached ABSL_GUARDED_BY(mutex);
+    absl::flat_hash_set<const FileDescriptor*> non_cached
+        ABSL_GUARDED_BY(mutex);
+  };
+  static auto& bootstrap_cache = *new BoostrapGlobals();
+
+  absl::MutexLock lock(&bootstrap_cache.mutex);
+  if (bootstrap_cache.cached.contains(file)) return true;
+  if (bootstrap_cache.non_cached.contains(file)) return false;
+
   // In order to build the data structures for the reflective parse, it needs
   // to parse the serialized descriptor describing all the messages defined in
   // this file. Obviously this presents a bootstrap problem for descriptor
@@ -1526,9 +1605,13 @@
   Message* fd_proto = factory.GetPrototype(fd_proto_descriptor)->New();
   fd_proto->ParseFromString(linkedin_fd_proto.SerializeAsString());
 
-  bool& res = cache[file];
-  res = HasExtensionFromFile(*fd_proto, file, options,
-                             has_opt_codesize_extension);
+  bool res = HasExtensionFromFile(*fd_proto, file, options,
+                                  has_opt_codesize_extension);
+  if (res) {
+    bootstrap_cache.cached.insert(file);
+  } else {
+    bootstrap_cache.non_cached.insert(file);
+  }
   delete fd_proto;
   return res;
 }
diff --git a/src/google/protobuf/compiler/cpp/helpers.h b/src/google/protobuf/compiler/cpp/helpers.h
index d8dcda7..ae1ed68 100644
--- a/src/google/protobuf/compiler/cpp/helpers.h
+++ b/src/google/protobuf/compiler/cpp/helpers.h
@@ -38,21 +38,25 @@
 #include <algorithm>
 #include <cstdint>
 #include <iterator>
-#include <map>
 #include <string>
+#include <tuple>
 
-#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/cpp/names.h>
-#include <google/protobuf/compiler/cpp/options.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/compiler/scc.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/compiler/cpp/names.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/port.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -84,17 +88,20 @@
 extern const char kThickSeparator[];
 extern const char kThinSeparator[];
 
-void SetCommonVars(const Options& options,
-                   std::map<std::string, std::string>* variables);
+absl::flat_hash_map<absl::string_view, std::string> MessageVars(
+    const Descriptor* desc);
 
 // Variables to access message data from the message scope.
 void SetCommonMessageDataVariables(
     const Descriptor* descriptor,
-    std::map<std::string, std::string>* variables);
+    absl::flat_hash_map<absl::string_view, std::string>* variables);
 
-void SetUnknownFieldsVariable(const Descriptor* descriptor,
-                              const Options& options,
-                              std::map<std::string, std::string>* variables);
+absl::flat_hash_map<absl::string_view, std::string> UnknownFieldsVars(
+    const Descriptor* desc, const Options& opts);
+
+void SetUnknownFieldsVariable(
+    const Descriptor* descriptor, const Options& options,
+    absl::flat_hash_map<absl::string_view, std::string>* variables);
 
 bool GetBootstrapBasename(const Options& options, const std::string& basename,
                           std::string* bootstrap_basename);
@@ -110,9 +117,22 @@
 std::string Namespace(const Descriptor* d, const Options& options);
 std::string Namespace(const FieldDescriptor* d, const Options& options);
 std::string Namespace(const EnumDescriptor* d, const Options& options);
+std::string Namespace(const FileDescriptor* d);
+std::string Namespace(const Descriptor* d);
+std::string Namespace(const FieldDescriptor* d);
+std::string Namespace(const EnumDescriptor* d);
 
+class MessageSCCAnalyzer;
+
+// Returns true if it's safe to init "field" to zero.
+bool CanInitializeByZeroing(const FieldDescriptor* field,
+                            const Options& options,
+                            MessageSCCAnalyzer* scc_analyzer);
 // Returns true if it's safe to reset "field" to zero.
-bool CanInitializeByZeroing(const FieldDescriptor* field);
+bool CanClearByZeroing(const FieldDescriptor* field);
+// Determines if swap can be implemented via memcpy.
+bool HasTrivialSwap(const FieldDescriptor* field, const Options& options,
+                    MessageSCCAnalyzer* scc_analyzer);
 
 std::string ClassName(const Descriptor* descriptor);
 std::string ClassName(const EnumDescriptor* enum_descriptor);
@@ -220,7 +240,7 @@
 std::string FieldMessageTypeName(const FieldDescriptor* field,
                                  const Options& options);
 
-// Get the C++ type name for a primitive type (e.g. "double", "::google::protobuf::int32", etc.).
+// Get the C++ type name for a primitive type (e.g. "double", "::int32", etc.).
 const char* PrimitiveTypeName(FieldDescriptor::CppType type);
 std::string PrimitiveTypeName(const Options& options,
                               FieldDescriptor::CppType type);
@@ -296,7 +316,7 @@
                                      const Options& options);
 
 // Escape C++ trigraphs by escaping question marks to \?
-std::string EscapeTrigraphs(const std::string& to_escape);
+std::string EscapeTrigraphs(absl::string_view to_escape);
 
 // Escaped function name to eliminate naming conflict.
 std::string SafeFunctionName(const Descriptor* descriptor,
@@ -327,6 +347,8 @@
   return false;
 }
 
+bool IsProfileDriven(const Options& options);
+
 bool IsStringInlined(const FieldDescriptor* descriptor, const Options& options);
 
 // For a string field, returns the effective ctype.  If the actual ctype is
@@ -350,8 +372,6 @@
          EffectiveStringCType(field, options) == FieldOptions::STRING_PIECE;
 }
 
-class MessageSCCAnalyzer;
-
 // Does the given FileDescriptor use lazy fields?
 bool HasLazyFields(const FileDescriptor* file, const Options& options,
                    MessageSCCAnalyzer* scc_analyzer);
@@ -377,6 +397,11 @@
 // Is the given field being split out?
 bool ShouldSplit(const FieldDescriptor* field, const Options& options);
 
+// Should we generate code that force creating an allocation in the constructor
+// of the given message?
+bool ShouldForceAllocationOnConstruction(const Descriptor* desc,
+                                         const Options& options);
+
 inline bool IsFieldUsed(const FieldDescriptor* /* field */,
                         const Options& /* options */) {
   return true;
@@ -455,35 +480,13 @@
   return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
 }
 
-inline bool HasHasbit(const FieldDescriptor* field) {
-  // This predicate includes proto3 message fields only if they have "optional".
-  //   Foo submsg1 = 1;           // HasHasbit() == false
-  //   optional Foo submsg2 = 2;  // HasHasbit() == true
-  // This is slightly odd, as adding "optional" to a singular proto3 field does
-  // not change the semantics or API. However whenever any field in a message
-  // has a hasbit, it forces reflection to include hasbit offsets for *all*
-  // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
-  // causing a sudden size regression for ~all proto3 messages, we give proto3
-  // message fields a hasbit only if "optional" is present. If the user is
-  // explicitly writing "optional", it is likely they are writing it on
-  // primitive fields also.
-  return (field->has_optional_keyword() || field->is_required()) &&
-         !field->options().weak();
-}
-
-// Returns true if 'enum' semantics are such that unknown values are preserved
-// in the enum field itself, rather than going to the UnknownFieldSet.
-inline bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
-  return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
-}
-
 inline bool IsCrossFileMessage(const FieldDescriptor* field) {
   return field->type() == FieldDescriptor::TYPE_MESSAGE &&
          field->message_type()->file() != field->file();
 }
 
 inline std::string MakeDefaultName(const FieldDescriptor* field) {
-  return StrCat("_i_give_permission_to_break_this_code_default_",
+  return absl::StrCat("_i_give_permission_to_break_this_code_default_",
                       FieldName(field), "_");
 }
 
@@ -498,11 +501,11 @@
 // exists at some nested level like:
 //   internal_container_._i_give_permission_to_break_this_code_default_field_;
 inline std::string MakeDefaultFieldName(const FieldDescriptor* field) {
-  return StrCat("Impl_::", MakeDefaultName(field));
+  return absl::StrCat("Impl_::", MakeDefaultName(field));
 }
 
 inline std::string MakeVarintCachedSizeName(const FieldDescriptor* field) {
-  return StrCat("_", FieldName(field), "_cached_byte_size_");
+  return absl::StrCat("_", FieldName(field), "_cached_byte_size_");
 }
 
 // Semantically distinct from MakeVarintCachedSizeName in that it gives the C++
@@ -518,7 +521,7 @@
 //   internal_container_._field_cached_byte_size_;
 inline std::string MakeVarintCachedSizeFieldName(const FieldDescriptor* field,
                                                  bool split) {
-  return StrCat("_impl_.", split ? "_split_->" : "", "_",
+  return absl::StrCat("_impl_.", split ? "_split_->" : "", "_",
                       FieldName(field), "_cached_byte_size_");
 }
 
@@ -531,12 +534,26 @@
 
 bool IsWellKnownMessage(const FileDescriptor* descriptor);
 
-inline std::string IncludeGuard(const FileDescriptor* file, bool pb_h,
+enum class GeneratedFileType : int { kPbH, kProtoH, kProtoStaticReflectionH };
+
+inline std::string IncludeGuard(const FileDescriptor* file,
+                                GeneratedFileType file_type,
                                 const Options& options) {
   // If we are generating a .pb.h file and the proto_h option is enabled, then
   // the .pb.h gets an extra suffix.
-  std::string filename_identifier = FilenameIdentifier(
-      file->name() + (pb_h && options.proto_h ? ".pb.h" : ""));
+  std::string extension;
+  switch (file_type) {
+    case GeneratedFileType::kPbH:
+      extension = ".pb.h";
+      break;
+    case GeneratedFileType::kProtoH:
+      extension = ".proto.h";
+      break;
+    case GeneratedFileType::kProtoStaticReflectionH:
+      extension = ".proto.static_reflection.h";
+  }
+  std::string filename_identifier =
+      FilenameIdentifier(file->name() + extension);
 
   if (IsWellKnownMessage(file)) {
     // For well-known messages we need third_party/protobuf and net/proto2 to
@@ -662,7 +679,7 @@
   };
   SCCAnalyzer<DepsGenerator> analyzer_;
   Options options_;
-  std::map<const SCC*, MessageAnalysis> analysis_cache_;
+  absl::flat_hash_map<const SCC*, MessageAnalysis> analysis_cache_;
 };
 
 void ListAllFields(const Descriptor* d,
@@ -788,15 +805,15 @@
  public:
   explicit Formatter(io::Printer* printer) : printer_(printer) {}
   Formatter(io::Printer* printer,
-            const std::map<std::string, std::string>& vars)
+            const absl::flat_hash_map<absl::string_view, std::string>& vars)
       : printer_(printer), vars_(vars) {}
 
   template <typename T>
-  void Set(const std::string& key, const T& value) {
+  void Set(absl::string_view key, const T& value) {
     vars_[key] = ToString(value);
   }
 
-  void AddMap(const std::map<std::string, std::string>& vars) {
+  void AddMap(const absl::flat_hash_map<absl::string_view, std::string>& vars) {
     for (const auto& keyval : vars) vars_[keyval.first] = keyval.second;
   }
 
@@ -838,31 +855,69 @@
 
    private:
     Formatter* format_;
-    std::map<std::string, std::string> vars_;
+    absl::flat_hash_map<absl::string_view, std::string> vars_;
   };
 
  private:
   io::Printer* printer_;
-  std::map<std::string, std::string> vars_;
+  absl::flat_hash_map<absl::string_view, std::string> vars_;
 
   // Convenience overloads to accept different types as arguments.
   static std::string ToString(const std::string& s) { return s; }
   template <typename I, typename = typename std::enable_if<
                             std::is_integral<I>::value>::type>
   static std::string ToString(I x) {
-    return StrCat(x);
+    return absl::StrCat(x);
   }
-  static std::string ToString(strings::Hex x) { return StrCat(x); }
-  static std::string ToString(const FieldDescriptor* d) { return Payload(d); }
-  static std::string ToString(const Descriptor* d) { return Payload(d); }
-  static std::string ToString(const EnumDescriptor* d) { return Payload(d); }
+  static std::string ToString(absl::Hex x) { return absl::StrCat(x); }
+  static std::string ToString(const FieldDescriptor* d) {
+    return Payload(d, GeneratedCodeInfo::Annotation::NONE);
+  }
+  static std::string ToString(const Descriptor* d) {
+    return Payload(d, GeneratedCodeInfo::Annotation::NONE);
+  }
+  static std::string ToString(const EnumDescriptor* d) {
+    return Payload(d, GeneratedCodeInfo::Annotation::NONE);
+  }
   static std::string ToString(const EnumValueDescriptor* d) {
-    return Payload(d);
+    return Payload(d, GeneratedCodeInfo::Annotation::NONE);
   }
-  static std::string ToString(const OneofDescriptor* d) { return Payload(d); }
+  static std::string ToString(const OneofDescriptor* d) {
+    return Payload(d, GeneratedCodeInfo::Annotation::NONE);
+  }
+
+  static std::string ToString(
+      std::tuple<const FieldDescriptor*,
+                 GeneratedCodeInfo::Annotation::Semantic>
+          p) {
+    return Payload(std::get<0>(p), std::get<1>(p));
+  }
+  static std::string ToString(
+      std::tuple<const Descriptor*, GeneratedCodeInfo::Annotation::Semantic>
+          p) {
+    return Payload(std::get<0>(p), std::get<1>(p));
+  }
+  static std::string ToString(
+      std::tuple<const EnumDescriptor*, GeneratedCodeInfo::Annotation::Semantic>
+          p) {
+    return Payload(std::get<0>(p), std::get<1>(p));
+  }
+  static std::string ToString(
+      std::tuple<const EnumValueDescriptor*,
+                 GeneratedCodeInfo::Annotation::Semantic>
+          p) {
+    return Payload(std::get<0>(p), std::get<1>(p));
+  }
+  static std::string ToString(
+      std::tuple<const OneofDescriptor*,
+                 GeneratedCodeInfo::Annotation::Semantic>
+          p) {
+    return Payload(std::get<0>(p), std::get<1>(p));
+  }
 
   template <typename Descriptor>
-  static std::string Payload(const Descriptor* descriptor) {
+  static std::string Payload(const Descriptor* descriptor,
+                             GeneratedCodeInfo::Annotation::Semantic semantic) {
     std::vector<int> path;
     descriptor->GetLocationPath(&path);
     GeneratedCodeInfo::Annotation annotation;
@@ -870,73 +925,53 @@
       annotation.add_path(index);
     }
     annotation.set_source_file(descriptor->file()->name());
+    annotation.set_semantic(semantic);
     return annotation.SerializeAsString();
   }
 };
 
-template <class T>
-void PrintFieldComment(const Formatter& format, const T* field) {
+template <typename T>
+std::string FieldComment(const T* field) {
   // Print the field's (or oneof's) proto-syntax definition as a comment.
   // We don't want to print group bodies so we cut off after the first
   // line.
   DebugStringOptions options;
   options.elide_group_body = true;
   options.elide_oneof_body = true;
-  std::string def = field->DebugStringWithOptions(options);
-  format("// $1$\n", def.substr(0, def.find_first_of('\n')));
+
+  for (absl::string_view chunk :
+       absl::StrSplit(field->DebugStringWithOptions(options), '\n')) {
+    return std::string(chunk);
+  }
+
+  return "<unknown>";
+}
+
+template <class T>
+void PrintFieldComment(const Formatter& format, const T* field) {
+  format("// $1$\n", FieldComment(field));
 }
 
 class PROTOC_EXPORT NamespaceOpener {
  public:
-  explicit NamespaceOpener(const Formatter& format)
-      : printer_(format.printer()) {}
-  NamespaceOpener(const std::string& name, const Formatter& format)
+  explicit NamespaceOpener(io::Printer* p) : p_(p) {}
+  explicit NamespaceOpener(const Formatter& format) : p_(format.printer()) {}
+  NamespaceOpener(absl::string_view name, const Formatter& format)
       : NamespaceOpener(format) {
     ChangeTo(name);
   }
+  NamespaceOpener(absl::string_view name, io::Printer* p) : NamespaceOpener(p) {
+    ChangeTo(name);
+  }
   ~NamespaceOpener() { ChangeTo(""); }
 
-  void ChangeTo(const std::string& name) {
-    std::vector<std::string> new_stack_ =
-        Split(name, "::", true);
-    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 (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", *it);
-      }
-    }
-    name_stack_.swap(new_stack_);
-    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 {
-        printer_->Print("namespace $ns$ {\n", "ns", name_stack_[i]);
-      }
-    }
-  }
+  void ChangeTo(absl::string_view name);
 
  private:
-  io::Printer* printer_;
+  io::Printer* p_;
   std::vector<std::string> name_stack_;
 };
 
-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,
-                               const Options& options);
-
 void GenerateUtf8CheckCodeForString(const FieldDescriptor* field,
                                     const Options& options, bool for_parse,
                                     const char* parameters,
@@ -947,43 +982,6 @@
                                   const char* parameters,
                                   const Formatter& format);
 
-template <typename T>
-struct FieldRangeImpl {
-  struct Iterator {
-    using iterator_category = std::forward_iterator_tag;
-    using value_type = const FieldDescriptor*;
-    using difference_type = int;
-
-    value_type operator*() { return descriptor->field(idx); }
-
-    friend bool operator==(const Iterator& a, const Iterator& b) {
-      GOOGLE_DCHECK(a.descriptor == b.descriptor);
-      return a.idx == b.idx;
-    }
-    friend bool operator!=(const Iterator& a, const Iterator& b) {
-      return !(a == b);
-    }
-
-    Iterator& operator++() {
-      idx++;
-      return *this;
-    }
-
-    int idx;
-    const T* descriptor;
-  };
-
-  Iterator begin() const { return {0, descriptor}; }
-  Iterator end() const { return {descriptor->field_count(), descriptor}; }
-
-  const T* descriptor;
-};
-
-template <typename T>
-FieldRangeImpl<T> FieldRange(const T* desc) {
-  return {desc};
-}
-
 struct OneOfRangeImpl {
   struct Iterator {
     using iterator_category = std::forward_iterator_tag;
@@ -1059,6 +1057,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_HELPERS_H__
diff --git a/src/google/protobuf/compiler/cpp/map_field.cc b/src/google/protobuf/compiler/cpp/map_field.cc
index 3a55ef5..dd9f0a6 100644
--- a/src/google/protobuf/compiler/cpp/map_field.cc
+++ b/src/google/protobuf/compiler/cpp/map_field.cc
@@ -28,27 +28,24 @@
 // (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/map_field.h>
+#include "google/protobuf/compiler/cpp/map_field.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include <string>
 
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
-bool IsProto3Field(const FieldDescriptor* field_descriptor) {
-  const FileDescriptor* file_descriptor = field_descriptor->file();
-  return file_descriptor->syntax() == FileDescriptor::SYNTAX_PROTO3;
-}
-
-void SetMessageVariables(const FieldDescriptor* descriptor,
-                         std::map<std::string, std::string>* variables,
-                         const Options& options) {
+void SetMessageVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = ClassName(descriptor->message_type(), false);
   (*variables)["full_name"] = descriptor->full_name();
@@ -67,12 +64,12 @@
       (*variables)["val_cpp"] = PrimitiveTypeName(options, val->cpp_type());
   }
   (*variables)["key_wire_type"] =
-      "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
+      "TYPE_" + absl::AsciiStrToUpper(DeclaredTypeMethodName(key->type()));
   (*variables)["val_wire_type"] =
-      "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type()));
+      "TYPE_" + absl::AsciiStrToUpper(DeclaredTypeMethodName(val->type()));
   (*variables)["map_classname"] = ClassName(descriptor->message_type(), false);
-  (*variables)["number"] = StrCat(descriptor->number());
-  (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
+  (*variables)["number"] = absl::StrCat(descriptor->number());
+  (*variables)["tag"] = absl::StrCat(internal::WireFormat::MakeTag(descriptor));
 
   if (HasDescriptorMethods(descriptor->file(), options)) {
     (*variables)["lite"] = "";
diff --git a/src/google/protobuf/compiler/cpp/map_field.h b/src/google/protobuf/compiler/cpp/map_field.h
index 678a128..1465566 100644
--- a/src/google/protobuf/compiler/cpp/map_field.h
+++ b/src/google/protobuf/compiler/cpp/map_field.h
@@ -31,11 +31,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MAP_FIELD_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/message_field.h>
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/message_field.h"
 
 namespace google {
 namespace protobuf {
@@ -46,6 +45,8 @@
  public:
   MapFieldGenerator(const FieldDescriptor* descriptor, const Options& options,
                     MessageSCCAnalyzer* scc_analyzer);
+  MapFieldGenerator(const MapFieldGenerator&) = delete;
+  MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
   ~MapFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -71,8 +72,6 @@
 
  private:
   const bool has_required_fields_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/message.cc b/src/google/protobuf/compiler/cpp/message.cc
index 69069da..58beb66 100644
--- a/src/google/protobuf/compiler/cpp/message.cc
+++ b/src/google/protobuf/compiler/cpp/message.cc
@@ -32,39 +32,46 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/message.h>
+#include "google/protobuf/compiler/cpp/message.h"
 
 #include <algorithm>
+#include <array>
+#include <cmath>
 #include <cstdint>
 #include <functional>
-#include <map>
+#include <limits>
 #include <memory>
-#include <unordered_map>
+#include <type_traits>
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/map_entry_lite.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/cpp/enum.h>
-#include <google/protobuf/compiler/cpp/extension.h>
-#include <google/protobuf/compiler/cpp/field.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/padding_optimizer.h>
-#include <google/protobuf/compiler/cpp/parse_function_generator.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/map_entry_lite.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/cpp/enum.h"
+#include "google/protobuf/compiler/cpp/extension.h"
+#include "google/protobuf/compiler/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/names.h"
+#include "google/protobuf/compiler/cpp/padding_optimizer.h"
+#include "google/protobuf/compiler/cpp/parse_function_generator.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -73,6 +80,8 @@
 
 using internal::WireFormat;
 using internal::WireFormatLite;
+using internal::cpp::HasHasbit;
+using internal::cpp::Utf8CheckMode;
 
 namespace {
 
@@ -84,27 +93,28 @@
 // masks must be non-zero.
 std::string ConditionalToCheckBitmasks(
     const std::vector<uint32_t>& masks, bool return_success = true,
-    StringPiece has_bits_var = "_impl_._has_bits_") {
+    absl::string_view has_bits_var = "_impl_._has_bits_") {
   std::vector<std::string> parts;
   for (int i = 0; i < masks.size(); i++) {
     if (masks[i] == 0) continue;
-    std::string m = StrCat("0x", strings::Hex(masks[i], strings::ZERO_PAD_8));
+    std::string m = absl::StrCat("0x", absl::Hex(masks[i], absl::kZeroPad8));
     // Each xor evaluates to 0 if the expected bits are present.
     parts.push_back(
-        StrCat("((", has_bits_var, "[", i, "] & ", m, ") ^ ", m, ")"));
+        absl::StrCat("((", has_bits_var, "[", i, "] & ", m, ") ^ ", m, ")"));
   }
   GOOGLE_CHECK(!parts.empty());
   // If we have multiple parts, each expected to be 0, then bitwise-or them.
   std::string result =
       parts.size() == 1
           ? parts[0]
-          : StrCat("(", Join(parts, "\n       | "), ")");
+          : absl::StrCat("(", absl::StrJoin(parts, "\n       | "), ")");
   return result + (return_success ? " == 0" : " != 0");
 }
 
-void PrintPresenceCheck(const Formatter& format, const FieldDescriptor* field,
-                        const std::vector<int>& has_bit_indices,
-                        io::Printer* printer, int* cached_has_word_index) {
+void PrintPresenceCheck(const FieldDescriptor* field,
+                        const std::vector<int>& has_bit_indices, io::Printer* p,
+                        int* cached_has_word_index) {
+  Formatter format(p);
   if (!field->options().weak()) {
     int has_bit_index = has_bit_indices[field->index()];
     if (*cached_has_word_index != (has_bit_index / 32)) {
@@ -112,7 +122,7 @@
       format("cached_has_bits = $has_bits$[$1$];\n", *cached_has_word_index);
     }
     const std::string mask =
-        StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+        absl::StrCat(absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8));
     format("if (cached_has_bits & 0x$1$u) {\n", mask);
   } else {
     format("if (has_$1$()) {\n", FieldName(field));
@@ -166,32 +176,11 @@
   }
 }
 
-// Helper for the code that emits the SharedCtor() and InternalSwap() methods.
-// 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,
-                                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, scc_analyzer) &&
-              field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE);
-  return ret;
-}
-
-bool StrContains(const std::string& haystack, const std::string& needle) {
-  return haystack.find(needle) != std::string::npos;
-}
-
 // Finds runs of fields for which `predicate` is true.
 // RunMap maps from fields that start each run to the number of fields in that
 // run.  This is optimized for the common case that there are very few runs in
 // a message and that most of the eligible fields appear together.
-using RunMap = std::unordered_map<const FieldDescriptor*, size_t>;
+using RunMap = absl::flat_hash_map<const FieldDescriptor*, size_t>;
 RunMap FindRuns(const std::vector<const FieldDescriptor*>& fields,
                 const std::function<bool(const FieldDescriptor*)>& predicate) {
   RunMap runs;
@@ -215,13 +204,14 @@
 // considered non-default (will be sent over the wire), for message types
 // without true field presence. Should only be called if
 // !HasHasbit(field).
-bool EmitFieldNonDefaultCondition(io::Printer* printer,
-                                  const std::string& prefix,
+bool EmitFieldNonDefaultCondition(io::Printer* p, const std::string& prefix,
                                   const FieldDescriptor* field) {
   GOOGLE_CHECK(!HasHasbit(field));
-  Formatter format(printer);
-  format.Set("prefix", prefix);
-  format.Set("name", FieldName(field));
+  Formatter format(p);
+  auto v = p->WithVars({{
+      {"prefix", prefix},
+      {"name", FieldName(field)},
+  }});
   // Merge and serialize semantics: primitive fields are merged/serialized only
   // if non-zero (numeric) or non-empty (string).
   if (!field->is_repeated() && !field->containing_oneof()) {
@@ -232,18 +222,18 @@
       format("if ($prefix$_internal_has_$name$()) {\n");
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_FLOAT) {
       format(
-          "static_assert(sizeof(uint32_t) == sizeof(float), \"Code assumes "
-          "uint32_t and float are the same size.\");\n"
+          "static_assert(sizeof(::uint32_t) == sizeof(float), \"Code assumes "
+          "::uint32_t and float are the same size.\");\n"
           "float tmp_$name$ = $prefix$_internal_$name$();\n"
-          "uint32_t raw_$name$;\n"
+          "::uint32_t raw_$name$;\n"
           "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
           "if (raw_$name$ != 0) {\n");
     } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_DOUBLE) {
       format(
-          "static_assert(sizeof(uint64_t) == sizeof(double), \"Code assumes "
-          "uint64_t and double are the same size.\");\n"
+          "static_assert(sizeof(::uint64_t) == sizeof(double), \"Code assumes "
+          "::uint64_t and double are the same size.\");\n"
           "double tmp_$name$ = $prefix$_internal_$name$();\n"
-          "uint64_t raw_$name$;\n"
+          "::uint64_t raw_$name$;\n"
           "memcpy(&raw_$name$, &tmp_$name$, sizeof(tmp_$name$));\n"
           "if (raw_$name$ != 0) {\n");
     } else {
@@ -252,7 +242,8 @@
     format.Indent();
     return true;
   } else if (field->real_containing_oneof()) {
-    format("if (_internal_has_$name$()) {\n");
+    auto v = p->WithVars(OneofFieldVars(field));
+    format("if ($has_field$) {\n");
     format.Indent();
     return true;
   }
@@ -271,11 +262,17 @@
          field->has_optional_keyword() || field->real_containing_oneof();
 }
 
+bool HasInternalHasMethod(const FieldDescriptor* field) {
+  return !HasHasbit(field) &&
+         field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE;
+}
+
 // Collects map entry message type information.
-void CollectMapInfo(const Options& options, const Descriptor* descriptor,
-                    std::map<std::string, std::string>* variables) {
+void CollectMapInfo(
+    const Options& options, const Descriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   GOOGLE_CHECK(IsMapEntryMessage(descriptor));
-  std::map<std::string, std::string>& vars = *variables;
+  absl::flat_hash_map<absl::string_view, std::string>& vars = *variables;
   const FieldDescriptor* key = descriptor->map_key();
   const FieldDescriptor* val = descriptor->map_value();
   vars["key_cpp"] = PrimitiveTypeName(options, key->cpp_type());
@@ -290,25 +287,9 @@
       vars["val_cpp"] = PrimitiveTypeName(options, val->cpp_type());
   }
   vars["key_wire_type"] =
-      "TYPE_" + ToUpper(DeclaredTypeMethodName(key->type()));
+      "TYPE_" + absl::AsciiStrToUpper(DeclaredTypeMethodName(key->type()));
   vars["val_wire_type"] =
-      "TYPE_" + ToUpper(DeclaredTypeMethodName(val->type()));
-}
-
-// Does the given field have a private (internal helper only) has_$name$()
-// method?
-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 IsProto3(field->file()) && field->real_containing_oneof();
-}
-
-// TODO(ckennelly):  Cull these exclusions if/when these protos do not have
-// their methods overridden by subclasses.
-
-bool ShouldMarkClassAsFinal(const Descriptor* descriptor,
-                            const Options& options) {
-  return true;
+      "TYPE_" + absl::AsciiStrToUpper(DeclaredTypeMethodName(val->type()));
 }
 
 
@@ -411,7 +392,6 @@
         has_bit_indices_(has_bit_indices),
         access_info_map_(options.access_info_map),
         cold_threshold_(cold_threshold) {
-    SetCommonVars(options, &variables_);
     SetCommonMessageDataVariables(descriptor, &variables_);
   }
 
@@ -419,8 +399,8 @@
   // prefix to _has_bits_ to allow MergeFrom to use "from._has_bits_".
   // Otherwise, it should be "".
   void OnStartChunk(int chunk, int cached_has_word_index,
-                    const std::string& from, io::Printer* printer);
-  bool OnEndChunk(int chunk, io::Printer* printer);
+                    const std::string& from, io::Printer* p);
+  bool OnEndChunk(int chunk, io::Printer* p);
 
  private:
   bool IsColdChunk(int chunk);
@@ -433,7 +413,7 @@
   const std::vector<int>& has_bit_indices_;
   const AccessInfoMap* access_info_map_;
   const double cold_threshold_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   int limit_chunk_ = -1;
 };
 
@@ -448,9 +428,8 @@
 
 
 void ColdChunkSkipper::OnStartChunk(int chunk, int cached_has_word_index,
-                                    const std::string& from,
-                                    io::Printer* printer) {
-  Formatter format(printer, variables_);
+                                    const std::string& from, io::Printer* p) {
+  Formatter format(p);
   if (!access_info_map_) {
     return;
   } else if (chunk < limit_chunk_) {
@@ -492,7 +471,7 @@
     if (this_word != first_word) {
       format(" ||\n    ");
     }
-    format.Set("mask", strings::Hex(mask, strings::ZERO_PAD_8));
+    auto v = p->WithVars({{"mask", absl::Hex(mask, absl::kZeroPad8)}});
     if (this_word == cached_has_word_index) {
       format("(cached_has_bits & 0x$mask$u) != 0");
     } else {
@@ -503,8 +482,8 @@
   format.Indent();
 }
 
-bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* printer) {
-  Formatter format(printer, variables_);
+bool ColdChunkSkipper::OnEndChunk(int chunk, io::Printer* p) {
+  Formatter format(p);
   if (chunk != limit_chunk_ - 1) {
     return false;
   }
@@ -513,86 +492,142 @@
   return true;
 }
 
-void MaySetAnnotationVariable(const Options& options,
-                              StringPiece annotation_name,
-                              StringPiece injector_template_prefix,
-                              StringPiece injector_template_suffix,
-                              std::map<std::string, std::string>* variables) {
-  if (options.field_listener_options.forbidden_field_listener_events.count(
-          std::string(annotation_name)))
-    return;
-  (*variables)[StrCat("annotate_", annotation_name)] = strings::Substitute(
-      StrCat(injector_template_prefix, injector_template_suffix),
-      (*variables)["classtype"]);
+void AnnotationVar(const Descriptor* desc, const Options& options,
+                   absl::flat_hash_map<absl::string_view, std::string>& vars,
+                   absl::string_view name, absl::string_view val) {
+  if (!HasTracker(desc, options) ||
+      options.field_listener_options.forbidden_field_listener_events.contains(
+          absl::StripPrefix(name, "annotate_"))) {
+    val = "";
+  }
+
+  vars.emplace(name, absl::StrCat(absl::StripAsciiWhitespace(val), "\n"));
 }
 
-void GenerateExtensionAnnotations(
-    const Descriptor* descriptor, const Options& options,
-    std::map<std::string, std::string>* variables) {
-  const std::map<std::string, std::string> accessor_annotations_to_hooks = {
-      {"annotate_extension_has", "OnHasExtension"},
-      {"annotate_extension_clear", "OnClearExtension"},
-      {"annotate_extension_repeated_size", "OnExtensionSize"},
-      {"annotate_extension_get", "OnGetExtension"},
-      {"annotate_extension_mutable", "OnMutableExtension"},
-      {"annotate_extension_set", "OnSetExtension"},
-      {"annotate_extension_release", "OnReleaseExtension"},
-      {"annotate_repeated_extension_get", "OnGetExtension"},
-      {"annotate_repeated_extension_mutable", "OnMutableExtension"},
-      {"annotate_repeated_extension_set", "OnSetExtension"},
-      {"annotate_repeated_extension_add", "OnAddExtension"},
-      {"annotate_repeated_extension_add_mutable", "OnAddMutableExtension"},
-      {"annotate_repeated_extension_list", "OnListExtension"},
-      {"annotate_repeated_extension_list_mutable", "OnMutableListExtension"},
-  };
-  for (const auto& annotation : accessor_annotations_to_hooks) {
-    (*variables)[annotation.first] = "";
+absl::flat_hash_map<absl::string_view, std::string> ClassVars(
+    const Descriptor* desc, Options opts) {
+  absl::flat_hash_map<absl::string_view, std::string> vars = MessageVars(desc);
+  vars.emplace("classname", ClassName(desc, false));
+  vars.emplace("classtype", QualifiedClassName(desc, opts));
+  vars.emplace("full_name", desc->full_name());
+  vars.emplace("superclass", SuperClassName(desc, opts));
+
+  for (auto& pair : UnknownFieldsVars(desc, opts)) {
+    vars.emplace(pair);
   }
-  if (!HasTracker(descriptor, options)) {
-    return;
+
+  AnnotationVar(desc, opts, vars, "annotate_serialize", R"cc(
+    Impl_::_tracker_.OnSerialize(this);
+  )cc");
+  AnnotationVar(desc, opts, vars, "annotate_deserialize", R"cc(
+    Impl_::_tracker_.OnDeserialize(this);
+  )cc");
+  // 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.
+  AnnotationVar(desc, opts, vars, "annotate_reflection", R"cc(
+    Impl_::_tracker_.OnGetMetadata();
+  )cc");
+  AnnotationVar(desc, opts, vars, "annotate_bytesize", R"cc(
+    Impl_::_tracker_.OnByteSize(this);
+  )cc");
+  AnnotationVar(desc, opts, vars, "annotate_mergefrom", R"cc(
+    Impl_::_tracker_.OnMergeFrom(_this, &from);
+  )cc");
+
+  static constexpr std::array<std::pair<absl::string_view, absl::string_view>,
+                              14>
+      kVarToHook = {{
+          {"annotate_extension_has", "OnHasExtension"},
+          {"annotate_extension_clear", "OnClearExtension"},
+          {"annotate_extension_repeated_size", "OnExtensionSize"},
+          {"annotate_extension_get", "OnGetExtension"},
+          {"annotate_extension_mutable", "OnMutableExtension"},
+          {"annotate_extension_set", "OnSetExtension"},
+          {"annotate_extension_release", "OnReleaseExtension"},
+          {"annotate_repeated_extension_get", "OnGetExtension"},
+          {"annotate_repeated_extension_mutable", "OnMutableExtension"},
+          {"annotate_repeated_extension_set", "OnSetExtension"},
+          {"annotate_repeated_extension_add", "OnAddExtension"},
+          {"annotate_repeated_extension_add_mutable", "OnAddMutableExtension"},
+          {"annotate_repeated_extension_list", "OnListExtension"},
+          {"annotate_repeated_extension_list_mutable",
+           "OnMutableListExtension"},
+      }};
+
+  for (const auto& annotation : kVarToHook) {
+    vars[annotation.first] = "";
   }
-  StringPiece tracker = (*variables)["tracker"];
-  StringPiece extensions = (*variables)["extensions"];
-  for (const auto& annotation : accessor_annotations_to_hooks) {
-    const std::string& annotation_name = annotation.first;
-    const std::string& listener_call = annotation.second;
-    if (!StrContains(annotation_name, "repeated") &&
-        !StrContains(annotation_name, "size") &&
-        !StrContains(annotation_name, "clear")) {
+  if (!HasTracker(desc, opts)) {
+    return vars;
+  }
+
+  absl::string_view extensions = vars["extensions"];
+  for (const auto& annotation : kVarToHook) {
+    absl::string_view name = annotation.first;
+    absl::string_view call = annotation.second;
+
+    if (!absl::StrContains(name, "repeated") &&
+        !absl::StrContains(name, "size") && !absl::StrContains(name, "clear")) {
       // Primitive fields accessors.
       // "Has" is here as users calling "has" on a repeated field is a mistake.
-      (*variables)[annotation_name] = StrCat(
-          "  ", tracker, ".", listener_call,
-          "(this, id.number(), _proto_TypeTraits::GetPtr(id.number(), ",
-          extensions, ", id.default_value_ref()));");
-    } else if (StrContains(annotation_name, "repeated") &&
-               !StrContains(annotation_name, "list") &&
-               !StrContains(annotation_name, "size")) {
+      vars[name] = std::string(absl::StripAsciiWhitespace(absl::Substitute(
+          R"cc(
+            Impl_::_tracker_.$0(this, id.number(),
+                                _proto_TypeTraits::GetPtr(
+                                    id.number(), $1, id.default_value_ref()));
+          )cc",
+          call, extensions)));
+      continue;
+    }
+
+    if (absl::StrContains(name, "repeated") &&
+        !absl::StrContains(name, "list") && !absl::StrContains(name, "size")) {
       // Repeated index accessors.
       std::string str_index = "index";
-      if (StrContains(annotation_name, "add")) {
-        str_index = StrCat(extensions, ".ExtensionSize(id.number()) - 1");
+      if (absl::StrContains(name, "add")) {
+        str_index = absl::StrCat(extensions, ".ExtensionSize(id.number()) - 1");
       }
-      (*variables)[annotation_name] =
-          StrCat("  ", tracker, ".", listener_call,
-                       "(this, id.number(), "
-                       "_proto_TypeTraits::GetPtr(id.number(), ",
-                       extensions, ", ", str_index, "));");
-    } else if (StrContains(annotation_name, "list") ||
-               StrContains(annotation_name, "size")) {
-      // Repeated full accessors.
-      (*variables)[annotation_name] = StrCat(
-          "  ", tracker, ".", listener_call,
-          "(this, id.number(), _proto_TypeTraits::GetRepeatedPtr(id.number(), ",
-          extensions, "));");
-    } else {
-      // Generic accessors such as "clear".
-      // TODO(b/190614678): Generalize clear from both repeated and non repeated
-      // calls, currently their underlying memory interfaces are very different.
-      // Or think of removing clear callback as no usages are needed and no
-      // memory exist after calling clear().
+      vars[name] = std::string(absl::StripAsciiWhitespace(absl::Substitute(
+          R"cc(
+            Impl_::_tracker_.$0(this, id.number(),
+                                _proto_TypeTraits::GetPtr(id.number(), $1, $2));
+          )cc",
+          call, extensions, str_index)));
+      continue;
     }
+
+    if (absl::StrContains(name, "list") || absl::StrContains(name, "size")) {
+      // Repeated full accessors.
+      vars[name] = std::string(absl::StripAsciiWhitespace(absl::Substitute(
+          R"cc(
+            Impl_::_tracker_.$0(this, id.number(),
+                                _proto_TypeTraits::GetRepeatedPtr(id.number(),
+                                                                  $1));
+          )cc",
+          call, extensions)));
+      continue;
+    }
+
+    // Generic accessors such as "clear".
+    // TODO(b/190614678): Generalize clear from both repeated and non repeated
+    // calls, currently their underlying memory interfaces are very different.
+    // Or think of removing clear callback as no usages are needed and no
+    // memory exist after calling clear().
   }
+
+  return vars;
+}
+
+absl::flat_hash_map<absl::string_view, std::string> HasbitVars(
+    int has_bit_index) {
+  return {
+      {"has_array_index", absl::StrCat(has_bit_index / 32)},
+      {"has_mask",
+       absl::StrCat(
+           "0x", absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8), "u")},
+  };
 }
 
 }  // anonymous namespace
@@ -601,57 +636,18 @@
 
 MessageGenerator::MessageGenerator(
     const Descriptor* descriptor,
-    const std::map<std::string, std::string>& vars, int index_in_file_messages,
-    const Options& options, MessageSCCAnalyzer* scc_analyzer)
+    const absl::flat_hash_map<absl::string_view, std::string>&,
+    int index_in_file_messages, const Options& options,
+    MessageSCCAnalyzer* scc_analyzer)
     : descriptor_(descriptor),
       index_in_file_messages_(index_in_file_messages),
-      classname_(ClassName(descriptor, false)),
       options_(options),
       field_generators_(descriptor, options, scc_analyzer),
-      max_has_bit_index_(0),
-      max_inlined_string_index_(0),
-      num_weak_fields_(0),
-      scc_analyzer_(scc_analyzer),
-      variables_(vars) {
+      scc_analyzer_(scc_analyzer) {
+
   if (!message_layout_helper_) {
-    message_layout_helper_.reset(new PaddingOptimizer());
+    message_layout_helper_ = std::make_unique<PaddingOptimizer>();
   }
-  SetCommonMessageDataVariables(descriptor, &variables_);
-
-  // Variables that apply to this class
-  variables_["classname"] = classname_;
-  variables_["classtype"] = QualifiedClassName(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"] = "";
-  variables_["annotate_mergefrom"] = "";
-
-  if (HasTracker(descriptor_, options_)) {
-    const std::string injector_template =
-        StrCat("  ", variables_["tracker"], ".");
-
-    MaySetAnnotationVariable(options, "serialize", injector_template,
-                             "OnSerialize(this);\n", &variables_);
-    MaySetAnnotationVariable(options, "deserialize", injector_template,
-                             "OnDeserialize(this);\n", &variables_);
-    // 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.
-    MaySetAnnotationVariable(options, "reflection", injector_template,
-                             "OnGetMetadata();\n", &variables_);
-    MaySetAnnotationVariable(options, "bytesize", injector_template,
-                             "OnByteSize(this);\n", &variables_);
-    MaySetAnnotationVariable(options, "mergefrom", injector_template,
-                             "OnMergeFrom(_this, &from);\n", &variables_);
-  }
-
-  GenerateExtensionAnnotations(descriptor_, options_, &variables_);
-
-  SetUnknownFieldsVariable(descriptor_, options_, &variables_);
 
   // Compute optimized field order to be used for layout and initialization
   // purposes.
@@ -661,8 +657,11 @@
     }
 
     if (IsWeak(field, options_)) {
-      num_weak_fields_++;
-    } else if (!field->real_containing_oneof()) {
+      ++num_weak_fields_;
+      continue;
+    }
+
+    if (!field->real_containing_oneof()) {
       optimized_order_.push_back(field);
     }
   }
@@ -683,8 +682,9 @@
         inlined_string_indices_.resize(descriptor_->field_count(), kNoHasbit);
         // The bitset[0] is for arena dtor tracking. Donating states start from
         // bitset[1];
-        max_inlined_string_index_++;
+        ++max_inlined_string_index_;
       }
+
       inlined_string_indices_[field->index()] = max_inlined_string_index_++;
     }
   }
@@ -697,20 +697,17 @@
     field_generators_.SetInlinedStringIndices(inlined_string_indices_);
   }
 
-  num_required_fields_ = 0;
   for (int i = 0; i < descriptor->field_count(); i++) {
     if (descriptor->field(i)->is_required()) {
       ++num_required_fields_;
     }
   }
 
-  parse_function_generator_.reset(new ParseFunctionGenerator(
+  parse_function_generator_ = std::make_unique<ParseFunctionGenerator>(
       descriptor_, max_has_bit_index_, has_bit_indices_,
-      inlined_string_indices_, options_, scc_analyzer_, variables_));
+      inlined_string_indices_, options_, scc_analyzer_, variables_);
 }
 
-MessageGenerator::~MessageGenerator() = default;
-
 size_t MessageGenerator::HasBitsSize() const {
   return (max_has_bit_index_ + 31) / 32;
 }
@@ -739,24 +736,24 @@
     std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) {
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
     enum_generators->emplace_back(
-        new EnumGenerator(descriptor_->enum_type(i), variables_, options_));
+        std::make_unique<EnumGenerator>(descriptor_->enum_type(i), options_));
     enum_generators_.push_back(enum_generators->back().get());
   }
   for (int i = 0; i < descriptor_->extension_count(); i++) {
-    extension_generators->emplace_back(new ExtensionGenerator(
+    extension_generators->emplace_back(std::make_unique<ExtensionGenerator>(
         descriptor_->extension(i), options_, scc_analyzer_));
     extension_generators_.push_back(extension_generators->back().get());
   }
 }
 
-void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateFieldAccessorDeclarations(io::Printer* p) {
+  Formatter format(p);
   // optimized_fields_ does not contain fields where
   //    field->real_containing_oneof()
   // so we need to iterate over those as well.
   //
   // We place the non-oneof fields in optimized_order_, as that controls the
-  // order of the _has_bits_ entries and we want GDB's pretty printers to be
+  // order of the _has_bits_ entries and we want GDB's pretty ps to be
   // able to infer these indices from the k[FIELDNAME]FieldNumber order.
   std::vector<const FieldDescriptor*> ordered_fields;
   ordered_fields.reserve(descriptor_->field_count());
@@ -776,9 +773,9 @@
     for (auto field : ordered_fields) {
       Formatter::SaveState save(&format);
 
-      std::map<std::string, std::string> vars;
+      absl::flat_hash_map<absl::string_view, std::string> vars;
       SetCommonFieldVariables(field, &vars, options_);
-      format.AddMap(vars);
+      auto v = p->WithVars(std::move(vars));
       format("  ${1$$2$$}$ = $number$,\n", field, FieldConstantName(field));
     }
     format("};\n");
@@ -786,12 +783,7 @@
   for (auto field : ordered_fields) {
     PrintFieldComment(format, field);
 
-    Formatter::SaveState save(&format);
-
-    std::map<std::string, std::string> vars;
-    SetCommonFieldVariables(field, &vars, options_);
-    format.AddMap(vars);
-
+    auto v = p->WithVars(FieldVars(field, options_));
     if (field->is_repeated()) {
       format("$deprecated_attr$int ${1$$name$_size$}$() const$2$\n", field,
              !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
@@ -802,17 +794,13 @@
             "public:\n",
             field);
       }
-    } else if (HasHasMethod(field)) {
-      format("$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field,
-             !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
-      if (!IsFieldStripped(field, options_)) {
+    } else {
+      if (HasHasMethod(field)) {
         format(
-            "private:\n"
-            "bool _internal_has_$name$() const;\n"
-            "public:\n");
+            "$deprecated_attr$bool ${1$has_$name$$}$() const$2$\n", field,
+            !IsFieldStripped(field, options_) ? ";" : " {__builtin_trap();}");
       }
-    } else if (HasPrivateHasMethod(field)) {
-      if (!IsFieldStripped(field, options_)) {
+      if (HasInternalHasMethod(field) && !IsFieldStripped(field, options_)) {
         format(
             "private:\n"
             "bool ${1$_internal_has_$name$$}$() const;\n"
@@ -824,8 +812,7 @@
            !IsFieldStripped(field, options_) ? ";" : "{__builtin_trap();}");
 
     // Generate type-specific accessor declarations.
-    field_generators_.get(field).GenerateAccessorDeclarations(printer);
-
+    field_generators_.get(field).GenerateAccessorDeclarations(p);
     format("\n");
   }
 
@@ -1042,8 +1029,10 @@
 
   for (auto oneof : OneOfRange(descriptor_)) {
     Formatter::SaveState saver(&format);
-    format.Set("oneof_name", oneof->name());
-    format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true));
+    auto v = p->WithVars({
+        {"oneof_name", oneof->name()},
+        {"camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)},
+    });
     format(
         "void ${1$clear_$oneof_name$$}$();\n"
         "$camel_oneof_name$Case $oneof_name$_case() const;\n",
@@ -1052,7 +1041,8 @@
 }
 
 void MessageGenerator::GenerateSingularFieldHasBits(
-    const FieldDescriptor* field, Formatter format) {
+    const FieldDescriptor* field, io::Printer* p) {
+  Formatter format(p);
   if (IsFieldStripped(field, options_)) {
     format(
         "inline bool $classname$::has_$name$() const { "
@@ -1071,13 +1061,11 @@
     int has_bit_index = HasBitIndex(field);
     GOOGLE_CHECK_NE(has_bit_index, kNoHasbit);
 
-    format.Set("has_array_index", has_bit_index / 32);
-    format.Set("has_mask",
-               strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+    auto v = p->WithVars(HasbitVars(has_bit_index));
     format(
-        "inline bool $classname$::_internal_has_$name$() const {\n"
-        "  bool value = "
-        "($has_bits$[$has_array_index$] & 0x$has_mask$u) != 0;\n");
+        "inline bool $classname$::has_$name$() const {\n"
+        "$annotate_has$"
+        "  bool value = ($has_bits$[$has_array_index$] & $has_mask$) != 0;\n");
 
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
         !IsLazy(field, options_, scc_analyzer_)) {
@@ -1089,10 +1077,6 @@
 
     format(
         "  return value;\n"
-        "}\n"
-        "inline bool $classname$::has_$name$() const {\n"
-        "$annotate_has$"
-        "  return _internal_has_$name$();\n"
         "}\n");
   } else if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
     // Message fields have a has_$name$() method.
@@ -1116,12 +1100,14 @@
   }
 }
 
-void MessageGenerator::GenerateOneofHasBits(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  for (auto oneof : OneOfRange(descriptor_)) {
-    format.Set("oneof_name", oneof->name());
-    format.Set("oneof_index", oneof->index());
-    format.Set("cap_oneof_name", ToUpper(oneof->name()));
+void MessageGenerator::GenerateOneofHasBits(io::Printer* p) {
+  Formatter format(p);
+  for (const auto* oneof : OneOfRange(descriptor_)) {
+    auto v = p->WithVars({
+        {"oneof_index", oneof->index()},
+        {"oneof_name", oneof->name()},
+        {"cap_oneof_name", absl::AsciiStrToUpper(oneof->name())},
+    });
     format(
         "inline bool $classname$::has_$oneof_name$() const {\n"
         "  return $oneof_name$_case() != $cap_oneof_name$_NOT_SET;\n"
@@ -1133,7 +1119,9 @@
 }
 
 void MessageGenerator::GenerateOneofMemberHasBits(const FieldDescriptor* field,
-                                                  const Formatter& format) {
+                                                  io::Printer* p) {
+  auto v = p->WithVars(OneofFieldVars(field));
+  Formatter format(p);
   if (IsFieldStripped(field, options_)) {
     if (HasHasMethod(field)) {
       format(
@@ -1148,25 +1136,18 @@
   // Singular field in a oneof
   // N.B.: Without field presence, we do not use has-bits or generate
   // has_$name$() methods, but oneofs still have set_has_$name$().
-  // Oneofs also have has_$name$() but only as a private helper
-  // method, so that generated code is slightly cleaner (vs.  comparing
-  // _oneof_case_[index] against a constant everywhere).
-  //
-  // If has_$name$() is private, there is no need to add an internal accessor.
-  // Only annotate public accessors.
+  // Oneofs also have private _internal_has_$name$() a helper method.
   if (HasHasMethod(field)) {
     format(
-        "inline bool $classname$::_internal_has_$name$() const {\n"
-        "  return $oneof_name$_case() == k$field_name$;\n"
-        "}\n"
         "inline bool $classname$::has_$name$() const {\n"
         "$annotate_has$"
-        "  return _internal_has_$name$();\n"
+        "  return $has_field$;\n"
         "}\n");
-  } else if (HasPrivateHasMethod(field)) {
+  }
+  if (HasInternalHasMethod(field)) {
     format(
         "inline bool $classname$::_internal_has_$name$() const {\n"
-        "  return $oneof_name$_case() == k$field_name$;\n"
+        "  return $has_field$;\n"
         "}\n");
   }
   // set_has_$name$() for oneof fields is always private; hence should not be
@@ -1178,7 +1159,8 @@
 }
 
 void MessageGenerator::GenerateFieldClear(const FieldDescriptor* field,
-                                          bool is_inline, Formatter format) {
+                                          bool is_inline, io::Printer* p) {
+  Formatter format(p);
   if (IsFieldStripped(field, options_)) {
     format("void $classname$::clear_$name$() { __builtin_trap(); }\n");
     return;
@@ -1195,9 +1177,10 @@
   if (field->real_containing_oneof()) {
     // Clear this field only if it is the active field in this oneof,
     // otherwise ignore
-    format("if (_internal_has_$name$()) {\n");
+    auto v = p->WithVars(OneofFieldVars(field));
+    format("if ($has_field$) {\n");
     format.Indent();
-    field_generators_.get(field).GenerateClearingCode(format.printer());
+    field_generators_.get(field).GenerateClearingCode(p);
     format("clear_has_$oneof_name$();\n");
     format.Outdent();
     format("}\n");
@@ -1205,13 +1188,11 @@
     if (ShouldSplit(field, options_)) {
       format("if (IsSplitMessageDefault()) return;\n");
     }
-    field_generators_.get(field).GenerateClearingCode(format.printer());
+    field_generators_.get(field).GenerateClearingCode(p);
     if (HasHasbit(field)) {
       int has_bit_index = HasBitIndex(field);
-      format.Set("has_array_index", has_bit_index / 32);
-      format.Set("has_mask",
-                 strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
-      format("$has_bits$[$has_array_index$] &= ~0x$has_mask$u;\n");
+      auto v = p->WithVars(HasbitVars(has_bit_index));
+      format("$has_bits$[$has_array_index$] &= ~$has_mask$;\n");
     }
   }
   format("$annotate_clear$");
@@ -1219,8 +1200,8 @@
   format("}\n");
 }
 
-void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateFieldAccessorDefinitions(io::Printer* p) {
+  Formatter format(p);
   format("// $classname$\n\n");
 
   for (auto field : FieldRange(descriptor_)) {
@@ -1230,12 +1211,7 @@
       continue;
     }
 
-    std::map<std::string, std::string> vars;
-    SetCommonFieldVariables(field, &vars, options_);
-
-    Formatter::SaveState saver(&format);
-    format.AddMap(vars);
-
+    auto v = p->WithVars(FieldVars(field, options_));
     // Generate has_$name$() or $name$_size().
     if (field->is_repeated()) {
       if (IsFieldStripped(field, options_)) {
@@ -1257,45 +1233,39 @@
                 : "");
       }
     } else if (field->real_containing_oneof()) {
-      format.Set("field_name", UnderscoresToCamelCase(field->name(), true));
-      format.Set("oneof_name", field->containing_oneof()->name());
-      format.Set("oneof_index",
-                 StrCat(field->containing_oneof()->index()));
-      GenerateOneofMemberHasBits(field, format);
+      GenerateOneofMemberHasBits(field, p);
     } else {
       // Singular field.
-      GenerateSingularFieldHasBits(field, format);
+      GenerateSingularFieldHasBits(field, p);
     }
 
     if (!IsCrossFileMaybeMap(field)) {
-      GenerateFieldClear(field, true, format);
+      GenerateFieldClear(field, true, p);
     }
-
     // Generate type-specific accessors.
     if (!IsFieldStripped(field, options_)) {
-      field_generators_.get(field).GenerateInlineAccessorDefinitions(printer);
+      field_generators_.get(field).GenerateInlineAccessorDefinitions(p);
     }
 
     format("\n");
   }
 
   // Generate has_$name$() and clear_has_$name$() functions for oneofs.
-  GenerateOneofHasBits(printer);
+  GenerateOneofHasBits(p);
 }
 
-void MessageGenerator::GenerateClassDefinition(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  format.Set("class_final",
-             ShouldMarkClassAsFinal(descriptor_, options_) ? "final" : "");
+void MessageGenerator::GenerateClassDefinition(io::Printer* p) {
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
+  Formatter format(p);
 
   if (IsMapEntryMessage(descriptor_)) {
-    std::map<std::string, std::string> vars;
+    absl::flat_hash_map<absl::string_view, std::string> vars;
     CollectMapInfo(options_, descriptor_, &vars);
     vars["lite"] =
         HasDescriptorMethods(descriptor_->file(), options_) ? "" : "Lite";
-    format.AddMap(vars);
+    auto v = p->WithVars(std::move(vars));
     format(
-        "class $classname$ : public "
+        "class $classname$ final : public "
         "::$proto_ns$::internal::MapEntry$lite$<$classname$, \n"
         "    $key_cpp$, $val_cpp$,\n"
         "    ::$proto_ns$::internal::WireFormatLite::$key_wire_type$,\n"
@@ -1314,7 +1284,9 @@
         "  static const $classname$* internal_default_instance() { return "
         "reinterpret_cast<const "
         "$classname$*>(&_$classname$_default_instance_); }\n");
-    auto utf8_check = GetUtf8CheckMode(descriptor_->field(0), options_);
+    auto utf8_check = internal::cpp::GetUtf8CheckMode(
+        descriptor_->field(0), GetOptimizeFor(descriptor_->file(), options_) ==
+                                   FileOptions::LITE_RUNTIME);
     if (descriptor_->field(0)->type() == FieldDescriptor::TYPE_STRING &&
         utf8_check != Utf8CheckMode::kNone) {
       if (utf8_check == Utf8CheckMode::kStrict) {
@@ -1386,7 +1358,7 @@
   }
 
   format(
-      "class $dllexport_decl $${1$$classname$$}$$ class_final$ :\n"
+      "class $dllexport_decl $${1$$classname$$}$ final :\n"
       "    public $superclass$ /* @@protoc_insertion_point("
       "class_definition:$full_name$) */ {\n",
       descriptor_);
@@ -1489,7 +1461,7 @@
       format("$1$ = $2$,\n", OneofCaseConstantName(field),  // 1
              field->number());                              // 2
     }
-    format("$1$_NOT_SET = 0,\n", ToUpper(oneof->name()));
+    format("$1$_NOT_SET = 0,\n", absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format(
         "};\n"
@@ -1518,8 +1490,7 @@
           "  return $any_metadata$.PackFrom(GetArena(), message);\n"
           "}\n"
           "bool PackFrom(const ::$proto_ns$::Message& message,\n"
-          "              ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
-          "type_url_prefix) {\n"
+          "              ::absl::string_view type_url_prefix) {\n"
           "  $DCHK$_NE(&message, this);\n"
           "  return $any_metadata$.PackFrom(GetArena(), message, "
           "type_url_prefix);\n"
@@ -1541,8 +1512,7 @@
           "!std::is_convertible<T, const ::$proto_ns$::Message&>"
           "::value>::type>\n"
           "bool PackFrom(const T& message,\n"
-          "              ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
-          "type_url_prefix) {\n"
+          "              ::absl::string_view type_url_prefix) {\n"
           "  return $any_metadata$.PackFrom<T>(GetArena(), message, "
           "type_url_prefix);"
           "}\n"
@@ -1560,8 +1530,7 @@
           "}\n"
           "template <typename T>\n"
           "bool PackFrom(const T& message,\n"
-          "              ::PROTOBUF_NAMESPACE_ID::ConstStringParam "
-          "type_url_prefix) {\n"
+          "              ::absl::string_view type_url_prefix) {\n"
           "  return $any_metadata$.PackFrom(GetArena(), message, "
           "type_url_prefix);\n"
           "}\n"
@@ -1574,8 +1543,7 @@
         "template<typename T> bool Is() const {\n"
         "  return $any_metadata$.Is<T>();\n"
         "}\n"
-        "static bool ParseAnyTypeUrl(::PROTOBUF_NAMESPACE_ID::ConstStringParam "
-        "type_url,\n"
+        "static bool ParseAnyTypeUrl(::absl::string_view type_url,\n"
         "                            std::string* full_type_name);\n");
   }
 
@@ -1612,9 +1580,9 @@
 
   // For instances that derive from Message (rather than MessageLite), some
   // methods are virtual and should be marked as final.
-  format.Set("full_final", HasDescriptorMethods(descriptor_->file(), options_)
-                               ? "final"
-                               : "");
+  auto v2 = p->WithVars(
+      {{"full_final",
+        HasDescriptorMethods(descriptor_->file(), options_) ? "final" : ""}});
 
   if (HasGeneratedMethods(descriptor_->file(), options_)) {
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
@@ -1662,9 +1630,9 @@
           "PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;\n"
           "bool IsInitialized() const final;\n"
           "\n"
-          "size_t ByteSizeLong() const final;\n");
+          "::size_t ByteSizeLong() const final;\n");
 
-      parse_function_generator_->GenerateMethodDecls(printer);
+      parse_function_generator_->GenerateMethodDecls(p);
 
       format(
           "$uint8$* _InternalSerialize(\n"
@@ -1693,11 +1661,9 @@
       // Friend AnyMetadata so that it can call this FullMessageName() method.
       "\nprivate:\n"
       "friend class ::$proto_ns$::internal::AnyMetadata;\n"
-      "static $1$ FullMessageName() {\n"
+      "static ::absl::string_view FullMessageName() {\n"
       "  return \"$full_name$\";\n"
-      "}\n",
-      options_.opensource_runtime ? "::PROTOBUF_NAMESPACE_ID::StringPiece"
-                                  : "::StringPiece");
+      "}\n");
 
   format(
       // TODO(gerbens) Make this private! Currently people are deriving from
@@ -1758,7 +1724,7 @@
     format(
         "private:\n"
         "inline bool IsSplitMessageDefault() const {\n"
-        "  return $split$ == reinterpret_cast<Impl_::Split*>(&$1$);\n"
+        "  return $split$ == reinterpret_cast<const Impl_::Split*>(&$1$);\n"
         "}\n"
         "PROTOBUF_NOINLINE void PrepareSplitMessageForWrite();\n"
         "public:\n",
@@ -1773,8 +1739,9 @@
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     const Descriptor* nested_type = descriptor_->nested_type(i);
     if (!IsMapEntryMessage(nested_type)) {
-      format.Set("nested_full_name", ClassName(nested_type, false));
-      format.Set("nested_name", ResolveKeyword(nested_type->name()));
+      auto v =
+          p->WithVars({{"nested_full_name", ClassName(nested_type, false)},
+                       {"nested_name", ResolveKeyword(nested_type->name())}});
       format("typedef ${1$$nested_full_name$$}$ ${1$$nested_name$$}$;\n",
              nested_type);
     }
@@ -1787,7 +1754,7 @@
   // Import all nested enums and their values into this class's scope with
   // typedefs and constants.
   for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    enum_generators_[i]->GenerateSymbolImports(printer);
+    enum_generators_[i]->GenerateSymbolImports(p);
     format("\n");
   }
 
@@ -1796,11 +1763,11 @@
       "\n");
 
   // Generate accessor methods for all fields.
-  GenerateFieldAccessorDeclarations(printer);
+  GenerateFieldAccessorDeclarations(p);
 
   // Declare extension identifiers.
   for (int i = 0; i < descriptor_->extension_count(); i++) {
-    extension_generators_[i]->GenerateDeclaration(printer);
+    extension_generators_[i]->GenerateDeclaration(p);
   }
 
 
@@ -1835,11 +1802,11 @@
       num_required_fields_ > 1) {
     format(
         "// helper for ByteSizeLong()\n"
-        "size_t RequiredFieldsByteSizeFallback() const;\n\n");
+        "::size_t RequiredFieldsByteSizeFallback() const;\n\n");
   }
 
   if (HasGeneratedMethods(descriptor_->file(), options_)) {
-    parse_function_generator_->GenerateDataDecls(printer);
+    parse_function_generator_->GenerateDataDecls(p);
   }
 
   // Prepare decls for _cached_size_ and _has_bits_.  Their position in the
@@ -1852,7 +1819,7 @@
   const size_t sizeof_has_bits = HasBitsSize();
   const std::string has_bits_decl =
       sizeof_has_bits == 0 ? ""
-                           : StrCat("::$proto_ns$::internal::HasBits<",
+                           : absl::StrCat("::$proto_ns$::internal::HasBits<",
                                           sizeof_has_bits, "> _has_bits_;\n");
 
   format(
@@ -1908,9 +1875,9 @@
   // Emit some private and static members
   for (auto field : optimized_order_) {
     const FieldGenerator& generator = field_generators_.get(field);
-    generator.GenerateStaticMembers(printer);
+    generator.GenerateStaticMembers(p);
     if (!ShouldSplit(field, options_)) {
-      generator.GeneratePrivateMembers(printer);
+      generator.GeneratePrivateMembers(p);
     }
   }
   if (ShouldSplit(descriptor_, options_)) {
@@ -1919,13 +1886,15 @@
     for (auto field : optimized_order_) {
       if (!ShouldSplit(field, options_)) continue;
       const FieldGenerator& generator = field_generators_.get(field);
-      generator.GeneratePrivateMembers(printer);
+      generator.GeneratePrivateMembers(p);
     }
     format.Outdent();
     format(
         "  typedef void InternalArenaConstructable_;\n"
         "  typedef void DestructorSkippable_;\n"
         "};\n"
+        "static_assert(std::is_trivially_copy_constructible<Split>::value);\n"
+        "static_assert(std::is_trivially_destructible<Split>::value);\n"
         "Split* _split_;\n");
   }
 
@@ -1942,14 +1911,14 @@
         camel_oneof_name);
     for (auto field : FieldRange(oneof)) {
       if (!IsFieldStripped(field, options_)) {
-        field_generators_.get(field).GeneratePrivateMembers(printer);
+        field_generators_.get(field).GeneratePrivateMembers(p);
       }
     }
     format.Outdent();
     format("} $1$_;\n", oneof->name());
     for (auto field : FieldRange(oneof)) {
       if (!IsFieldStripped(field, options_)) {
-        field_generators_.get(field).GenerateStaticMembers(printer);
+        field_generators_.get(field).GenerateStaticMembers(p);
       }
     }
   }
@@ -1986,9 +1955,6 @@
   }
 
   if (ShouldSplit(descriptor_, options_)) {
-    format(
-        "static Impl_::Split* CreateSplitMessage("
-        "::$proto_ns$::Arena* arena);\n");
     format("friend struct $1$;\n",
            DefaultInstanceType(descriptor_, options_, /*split=*/true));
   }
@@ -2002,16 +1968,19 @@
   GOOGLE_DCHECK(!need_to_emit_cached_size);
 }  // NOLINT(readability/fn_size)
 
-void MessageGenerator::GenerateInlineMethods(io::Printer* printer) {
+void MessageGenerator::GenerateInlineMethods(io::Printer* p) {
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
   if (IsMapEntryMessage(descriptor_)) return;
-  GenerateFieldAccessorDefinitions(printer);
+  GenerateFieldAccessorDefinitions(p);
 
   // Generate oneof_case() functions.
   for (auto oneof : OneOfRange(descriptor_)) {
-    Formatter format(printer, variables_);
-    format.Set("camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true));
-    format.Set("oneof_name", oneof->name());
-    format.Set("oneof_index", oneof->index());
+    Formatter format(p);
+    auto v = p->WithVars({
+        {"camel_oneof_name", UnderscoresToCamelCase(oneof->name(), true)},
+        {"oneof_name", oneof->name()},
+        {"oneof_index", oneof->index()},
+    });
     format(
         "inline $classname$::$camel_oneof_name$Case $classname$::"
         "${1$$oneof_name$_case$}$() const {\n"
@@ -2022,9 +1991,10 @@
   }
 }
 
-void MessageGenerator::GenerateSchema(io::Printer* printer, int offset,
+void MessageGenerator::GenerateSchema(io::Printer* p, int offset,
                                       int has_offset) {
-  Formatter format(printer, variables_);
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
+  Formatter format(p);
   has_offset = !has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)
                    ? offset + has_offset
                    : -1;
@@ -2036,13 +2006,13 @@
     GOOGLE_DCHECK(!IsMapEntryMessage(descriptor_));
     inlined_string_indices_offset = has_offset + has_bit_indices_.size();
   }
-
   format("{ $1$, $2$, $3$, sizeof($classtype$)},\n", offset, has_offset,
          inlined_string_indices_offset);
 }
 
-void MessageGenerator::GenerateClassMethods(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateClassMethods(io::Printer* p) {
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
+  Formatter format(p);
   if (IsMapEntryMessage(descriptor_)) {
     format(
         "$classname$::$classname$() {}\n"
@@ -2087,7 +2057,7 @@
     }
     format(
         "bool $classname$::ParseAnyTypeUrl(\n"
-        "    ::PROTOBUF_NAMESPACE_ID::ConstStringParam type_url,\n"
+        "    ::absl::string_view type_url,\n"
         "    std::string* full_type_name) {\n"
         "  return ::_pbi::ParseAnyTypeUrl(type_url, full_type_name);\n"
         "}\n"
@@ -2101,10 +2071,17 @@
   if (!has_bit_indices_.empty()) {
     format(
         "using HasBits = "
-        "decltype(std::declval<$classname$>().$has_bits$);\n");
+        "decltype(std::declval<$classname$>().$has_bits$);\n"
+        "static constexpr ::int32_t kHasBitsOffset =\n"
+        "  8 * PROTOBUF_FIELD_OFFSET($classname$, _impl_._has_bits_);\n");
+  }
+  if (descriptor_->real_oneof_decl_count() > 0) {
+    format(
+        "static constexpr ::int32_t kOneofCaseOffset =\n"
+        "  PROTOBUF_FIELD_OFFSET($classtype$, $oneof_case$);\n");
   }
   for (auto field : FieldRange(descriptor_)) {
-    field_generators_.get(field).GenerateInternalAccessorDeclarations(printer);
+    field_generators_.get(field).GenerateInternalAccessorDeclarations(p);
     if (IsFieldStripped(field, options_)) {
       continue;
     }
@@ -2132,8 +2109,7 @@
   format("};\n\n");
   for (auto field : FieldRange(descriptor_)) {
     if (!IsFieldStripped(field, options_)) {
-      field_generators_.get(field).GenerateInternalAccessorDefinitions(
-          printer);
+      field_generators_.get(field).GenerateInternalAccessorDefinitions(p);
     }
   }
 
@@ -2142,54 +2118,49 @@
     if (IsFieldStripped(field, options_)) {
       continue;
     }
-    field_generators_.get(field).GenerateNonInlineAccessorDefinitions(printer);
+    field_generators_.get(field).GenerateNonInlineAccessorDefinitions(p);
     if (IsCrossFileMaybeMap(field)) {
-      Formatter::SaveState saver(&format);
-      std::map<std::string, std::string> vars;
-      SetCommonFieldVariables(field, &vars, options_);
-      if (field->real_containing_oneof()) {
-        SetCommonOneofFieldVariables(field, &vars);
-      }
-      format.AddMap(vars);
-      GenerateFieldClear(field, false, format);
+      auto v1 = p->WithVars(FieldVars(field, options_));
+      auto v2 = p->WithVars(OneofFieldVars(field));
+      GenerateFieldClear(field, false, p);
     }
   }
 
-  GenerateStructors(printer);
+  GenerateStructors(p);
   format("\n");
 
   if (descriptor_->real_oneof_decl_count() > 0) {
-    GenerateOneofClear(printer);
+    GenerateOneofClear(p);
     format("\n");
   }
 
   if (HasGeneratedMethods(descriptor_->file(), options_)) {
-    GenerateClear(printer);
+    GenerateClear(p);
     format("\n");
 
     if (!HasSimpleBaseClass(descriptor_, options_)) {
-      parse_function_generator_->GenerateMethodImpls(printer);
+      parse_function_generator_->GenerateMethodImpls(p);
       format("\n");
 
-      parse_function_generator_->GenerateDataDefinitions(printer);
+      parse_function_generator_->GenerateDataDefinitions(p);
     }
 
-    GenerateSerializeWithCachedSizesToArray(printer);
+    GenerateSerializeWithCachedSizesToArray(p);
     format("\n");
 
-    GenerateByteSize(printer);
+    GenerateByteSize(p);
     format("\n");
 
-    GenerateMergeFrom(printer);
+    GenerateMergeFrom(p);
     format("\n");
 
-    GenerateClassSpecificMergeImpl(printer);
+    GenerateClassSpecificMergeImpl(p);
     format("\n");
 
-    GenerateCopyFrom(printer);
+    GenerateCopyFrom(p);
     format("\n");
 
-    GenerateIsInitialized(printer);
+    GenerateIsInitialized(p);
     format("\n");
   }
 
@@ -2197,14 +2168,19 @@
     format(
         "void $classname$::PrepareSplitMessageForWrite() {\n"
         "  if (IsSplitMessageDefault()) {\n"
-        "    $split$ = CreateSplitMessage(GetArenaForAllocation());\n"
+        "    void* chunk = "
+        "::PROTOBUF_NAMESPACE_ID::internal::CreateSplitMessageGeneric("
+        "GetArenaForAllocation(), &$1$, sizeof(Impl_::Split), this, &$2$);\n"
+        "    $split$ = reinterpret_cast<Impl_::Split*>(chunk);\n"
         "  }\n"
-        "}\n");
+        "}\n",
+        DefaultInstanceName(descriptor_, options_, /*split=*/true),
+        DefaultInstanceName(descriptor_, options_, /*split=*/false));
   }
 
-  GenerateVerify(printer);
+  GenerateVerify(p);
 
-  GenerateSwap(printer);
+  GenerateSwap(p);
   format("\n");
 
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
@@ -2242,9 +2218,9 @@
   }
 }
 
-std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(
-    io::Printer* printer) {
-  Formatter format(printer, variables_);
+std::pair<size_t, size_t> MessageGenerator::GenerateOffsets(io::Printer* p) {
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
+  Formatter format(p);
 
   if (!has_bit_indices_.empty() || IsMapEntryMessage(descriptor_)) {
     format("PROTOBUF_FIELD_OFFSET($classtype$, $has_bits$),\n");
@@ -2274,7 +2250,16 @@
   } else {
     format("~0u,  // no _inlined_string_donated_\n");
   }
-  const int kNumGenericOffsets = 6;  // the number of fixed offsets above
+  if (ShouldSplit(descriptor_, options_)) {
+    format(
+        "PROTOBUF_FIELD_OFFSET($classtype$, $split$),\n"
+        "sizeof($classtype$::Impl_::Split),\n");
+  } else {
+    format(
+        "~0u,  // no _split_\n"
+        "~0u,  // no sizeof(Split)\n");
+  }
+  const int kNumGenericOffsets = 8;  // the number of fixed offsets above
   const size_t offsets = kNumGenericOffsets + descriptor_->field_count() +
                          descriptor_->real_oneof_decl_count();
   size_t entries = offsets;
@@ -2302,12 +2287,17 @@
     // offset of the field, so that the information is available when
     // reflectively accessing the field at run time.
     //
-    // Embed whether the field is eagerly verified lazy or inlined string to the
-    // LSB of the offset.
+    // We embed whether the field is cold to the MSB of the offset, and whether
+    // the field is eagerly verified lazy or inlined string to the LSB of the
+    // offset.
+
+    if (ShouldSplit(field, options_)) {
+      format(" | ::_pbi::kSplitFieldOffsetMask /*split*/");
+    }
     if (IsEagerlyVerifiedLazy(field, options_, scc_analyzer_)) {
-      format(" | 0x1u  // eagerly verified lazy\n");
+      format(" | 0x1u /*eagerly verified lazy*/");
     } else if (IsStringInlined(field, options_)) {
-      format(" | 0x1u  // inlined\n");
+      format(" | 0x1u /*inlined*/");
     }
     format(",\n");
   }
@@ -2328,7 +2318,7 @@
     entries += has_bit_indices_.size();
     for (int i = 0; i < has_bit_indices_.size(); i++) {
       const std::string index =
-          has_bit_indices_[i] >= 0 ? StrCat(has_bit_indices_[i]) : "~0u";
+          has_bit_indices_[i] >= 0 ? absl::StrCat(has_bit_indices_[i]) : "~0u";
       format("$1$,\n", index);
     }
   }
@@ -2337,7 +2327,7 @@
     for (int inlined_string_index : inlined_string_indices_) {
       const std::string index =
           inlined_string_index >= 0
-              ? StrCat(inlined_string_index, ",  // inlined_string_index")
+              ? absl::StrCat(inlined_string_index, ",  // inlined_string_index")
               : "~0u,";
       format("$1$\n", index);
     }
@@ -2346,9 +2336,9 @@
   return std::make_pair(entries, offsets);
 }
 
-void MessageGenerator::GenerateSharedConstructorCode(io::Printer* printer) {
+void MessageGenerator::GenerateSharedConstructorCode(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
 
   format(
       "inline void $classname$::SharedCtor(\n"
@@ -2394,12 +2384,19 @@
       continue;
     }
     put_sep();
-    field_generators_.get(field).GenerateAggregateInitializer(printer);
+    field_generators_.get(field).GenerateAggregateInitializer(p);
   }
   if (ShouldSplit(descriptor_, options_)) {
     put_sep();
-    format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}",
-           DefaultInstanceName(descriptor_, options_, /*split=*/true));
+    // We can't assign the default split to this->split without the const_cast
+    // because the former is a const. The const_cast is safe because we don't
+    // intend to modify the default split through this pointer, and we also
+    // expect the default split to be in the rodata section which is protected
+    // from mutation.
+    format(
+        "decltype($split$){const_cast<Impl_::Split*>"
+        "(reinterpret_cast<const Impl_::Split*>(&$1$))}",
+        DefaultInstanceName(descriptor_, options_, /*split=*/true));
   }
   for (auto oneof : OneOfRange(descriptor_)) {
     put_sep();
@@ -2457,7 +2454,14 @@
     if (ShouldSplit(field, options_)) {
       continue;
     }
-    field_generators_.get(field).GenerateConstructorCode(printer);
+    field_generators_.get(field).GenerateConstructorCode(p);
+  }
+
+  if (ShouldForceAllocationOnConstruction(descriptor_, options_)) {
+    format(
+        "#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n"
+        "$mutable_unknown_fields$;\n"
+        "#endif // PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n");
   }
 
   for (auto oneof : OneOfRange(descriptor_)) {
@@ -2468,49 +2472,11 @@
   format("}\n\n");
 }
 
-void MessageGenerator::GenerateCreateSplitMessage(io::Printer* printer) {
-  Formatter format(printer, variables_);
-  format(
-      "$classname$::Impl_::Split* "
-      "$classname$::CreateSplitMessage(::$proto_ns$::Arena* arena) {\n");
-  format.Indent();
-  const char* field_sep = " ";
-  const auto put_sep = [&] {
-    format("\n$1$ ", field_sep);
-    field_sep = ",";
-  };
-  format(
-      "const size_t size = sizeof(Impl_::Split);\n"
-      "void* chunk = (arena == nullptr) ?\n"
-      "  ::operator new(size) :\n"
-      "  arena->AllocateAligned(size, alignof(Impl_::Split));\n"
-      "Impl_::Split* ptr = reinterpret_cast<Impl_::Split*>(chunk);\n"
-      "new (ptr) Impl_::Split{");
-  format.Indent();
-  for (const FieldDescriptor* field : optimized_order_) {
-    GOOGLE_DCHECK(!IsFieldStripped(field, options_));
-    if (ShouldSplit(field, options_)) {
-      put_sep();
-      field_generators_.get(field).GenerateAggregateInitializer(printer);
-    }
-  }
-  format.Outdent();
-  format("};\n");
-  for (const FieldDescriptor* field : optimized_order_) {
-    GOOGLE_DCHECK(!IsFieldStripped(field, options_));
-    if (ShouldSplit(field, options_)) {
-      field_generators_.get(field).GenerateCreateSplitMessageCode(printer);
-    }
-  }
-  format("return ptr;\n");
-  format.Outdent();
-  format("}\n");
-}
-
-void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* printer) {
+void MessageGenerator::GenerateInitDefaultSplitInstance(io::Printer* p) {
   if (!ShouldSplit(descriptor_, options_)) return;
 
-  Formatter format(printer, variables_);
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
+  Formatter format(p);
   const char* field_sep = " ";
   const auto put_sep = [&] {
     format("\n$1$ ", field_sep);
@@ -2519,15 +2485,14 @@
   for (const auto* field : optimized_order_) {
     if (ShouldSplit(field, options_)) {
       put_sep();
-      field_generators_.get(field).GenerateConstexprAggregateInitializer(
-          printer);
+      field_generators_.get(field).GenerateConstexprAggregateInitializer(p);
     }
   }
 }
 
-void MessageGenerator::GenerateSharedDestructorCode(io::Printer* printer) {
+void MessageGenerator::GenerateSharedDestructorCode(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
 
   format("inline void $classname$::SharedDtor() {\n");
   format.Indent();
@@ -2543,7 +2508,7 @@
     if (ShouldSplit(field, options_)) {
       continue;
     }
-    field_generators_.get(field).GenerateDestructorCode(printer);
+    field_generators_.get(field).GenerateDestructorCode(p);
   }
   if (ShouldSplit(descriptor_, options_)) {
     format("if (!IsSplitMessageDefault()) {\n");
@@ -2551,7 +2516,7 @@
     format("auto* $cached_split_ptr$ = $split$;\n");
     for (auto field : optimized_order_) {
       if (ShouldSplit(field, options_)) {
-        field_generators_.get(field).GenerateDestructorCode(printer);
+        field_generators_.get(field).GenerateDestructorCode(p);
       }
     }
     format("delete $cached_split_ptr$;\n");
@@ -2593,10 +2558,10 @@
   return needs;
 }
 
-void MessageGenerator::GenerateArenaDestructorCode(io::Printer* printer) {
+void MessageGenerator::GenerateArenaDestructorCode(io::Printer* p) {
   GOOGLE_CHECK(NeedsArenaDestructor() > ArenaDtorNeeds::kNone);
 
-  Formatter format(printer, variables_);
+  Formatter format(p);
 
   // Generate the ArenaDtor() method. Track whether any fields actually produced
   // code that needs to be called.
@@ -2614,7 +2579,7 @@
     if (IsFieldStripped(field, options_) || ShouldSplit(field, options_))
       continue;
     const FieldGenerator& fg = field_generators_.get(field);
-    fg.GenerateArenaDestructorCode(printer);
+    fg.GenerateArenaDestructorCode(p);
   }
   if (ShouldSplit(descriptor_, options_)) {
     format("if (!_this->IsSplitMessageDefault()) {\n");
@@ -2623,7 +2588,7 @@
       if (IsFieldStripped(field, options_) || !ShouldSplit(field, options_))
         continue;
       const FieldGenerator& fg = field_generators_.get(field);
-      fg.GenerateArenaDestructorCode(printer);
+      fg.GenerateArenaDestructorCode(p);
     }
     format.Outdent();
     format("}\n");
@@ -2633,7 +2598,7 @@
   for (auto oneof : OneOfRange(descriptor_)) {
     for (auto field : FieldRange(oneof)) {
       if (IsFieldStripped(field, options_)) continue;
-      field_generators_.get(field).GenerateArenaDestructorCode(printer);
+      field_generators_.get(field).GenerateArenaDestructorCode(p);
     }
   }
 
@@ -2641,8 +2606,9 @@
   format("}\n");
 }
 
-void MessageGenerator::GenerateConstexprConstructor(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateConstexprConstructor(io::Printer* p) {
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
+  Formatter format(p);
 
   if (IsMapEntryMessage(descriptor_) || !HasImplData(descriptor_, options_)) {
     format(
@@ -2685,12 +2651,11 @@
       continue;
     }
     put_sep();
-    field_generators_.get(field).GenerateConstexprAggregateInitializer(
-        printer);
+    field_generators_.get(field).GenerateConstexprAggregateInitializer(p);
   }
   if (ShouldSplit(descriptor_, options_)) {
     put_sep();
-    format("/*decltype($split$)*/&$1$._instance",
+    format("/*decltype($split$)*/const_cast<Impl_::Split*>(&$1$._instance)",
            DefaultInstanceName(descriptor_, options_, /*split=*/true));
   }
 
@@ -2725,8 +2690,8 @@
   format("} {}\n");
 }
 
-void MessageGenerator::GenerateCopyConstructorBody(io::Printer* printer) const {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateCopyConstructorBody(io::Printer* p) const {
+  Formatter format(p);
 
   const RunMap runs =
       FindRuns(optimized_order_, [this](const FieldDescriptor* field) {
@@ -2735,20 +2700,14 @@
 
   std::string pod_template =
       "::memcpy(&$first$, &from.$first$,\n"
-      "  static_cast<size_t>(reinterpret_cast<char*>(&$last$) -\n"
+      "  static_cast<::size_t>(reinterpret_cast<char*>(&$last$) -\n"
       "  reinterpret_cast<char*>(&$first$)) + sizeof($last$));\n";
 
-  if (ShouldSplit(descriptor_, options_)) {
-    format("if (!from.IsSplitMessageDefault()) {\n");
-    format.Indent();
-    format("_this->PrepareSplitMessageForWrite();\n");
-    for (auto field : optimized_order_) {
-      if (ShouldSplit(field, options_)) {
-        field_generators_.get(field).GenerateCopyConstructorCode(printer);
-      }
-    }
-    format.Outdent();
-    format("}\n");
+  if (ShouldForceAllocationOnConstruction(descriptor_, options_)) {
+    format(
+        "#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n"
+        "$mutable_unknown_fields$;\n"
+        "#endif // PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION\n");
   }
 
   for (size_t i = 0; i < optimized_order_.size(); ++i) {
@@ -2768,21 +2727,36 @@
       const std::string last_field_name =
           FieldMemberName(optimized_order_[i + run_length - 1], /*cold=*/false);
 
-      format.Set("first", first_field_name);
-      format.Set("last", last_field_name);
-
+      auto v = p->WithVars({
+          {"first", first_field_name},
+          {"last", last_field_name},
+      });
       format(pod_template.c_str());
 
       i += run_length - 1;
       // ++i at the top of the loop.
     } else {
-      field_generators_.get(field).GenerateCopyConstructorCode(printer);
+      field_generators_.get(field).GenerateCopyConstructorCode(p);
     }
   }
+
+  if (ShouldSplit(descriptor_, options_)) {
+    format("if (!from.IsSplitMessageDefault()) {\n");
+    format.Indent();
+    format("_this->PrepareSplitMessageForWrite();\n");
+    // TODO(b/122856539): cache the split pointers.
+    for (auto field : optimized_order_) {
+      if (ShouldSplit(field, options_)) {
+        field_generators_.get(field).GenerateCopyConstructorCode(p);
+      }
+    }
+    format.Outdent();
+    format("}\n");
+  }
 }
 
-void MessageGenerator::GenerateStructors(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateStructors(io::Printer* p) {
+  Formatter format(p);
 
   format(
       "$classname$::$classname$(::$proto_ns$::Arena* arena,\n"
@@ -2803,9 +2777,30 @@
       "  // @@protoc_insertion_point(arena_constructor:$full_name$)\n"
       "}\n");
 
-  std::map<std::string, std::string> vars;
-  SetUnknownFieldsVariable(descriptor_, options_, &vars);
-  format.AddMap(vars);
+  // If the message contains only scalar fields (ints and enums),
+  // then we can copy the entire impl_ section with a single statement.
+  bool copy_construct_impl =
+      !ShouldSplit(descriptor_, options_) &&
+      !HasSimpleBaseClass(descriptor_, options_) &&
+      (descriptor_->extension_range_count() == 0 &&
+       descriptor_->real_oneof_decl_count() == 0 && num_weak_fields_ == 0);
+  for (const auto& field : optimized_order_) {
+    if (!copy_construct_impl) break;
+    if (field->is_repeated() || field->is_extension()) {
+      copy_construct_impl = false;
+    } else if (field->cpp_type() != FieldDescriptor::CPPTYPE_ENUM &&
+               field->cpp_type() != FieldDescriptor::CPPTYPE_INT32 &&
+               field->cpp_type() != FieldDescriptor::CPPTYPE_INT64 &&
+               field->cpp_type() != FieldDescriptor::CPPTYPE_UINT32 &&
+               field->cpp_type() != FieldDescriptor::CPPTYPE_UINT64 &&
+               field->cpp_type() != FieldDescriptor::CPPTYPE_FLOAT &&
+               field->cpp_type() != FieldDescriptor::CPPTYPE_DOUBLE &&
+               field->cpp_type() != FieldDescriptor::CPPTYPE_BOOL) {
+      copy_construct_impl = false;
+    } else {
+      // non-repeated integer fields are fine to copy en masse.
+    }
+  }
 
   // Generate the copy constructor.
   if (UsingImplicitWeakFields(descriptor_->file(), options_)) {
@@ -2818,6 +2813,16 @@
         "  : $classname$() {\n"
         "  MergeFrom(from);\n"
         "}\n");
+  } else if (copy_construct_impl) {
+    format(
+        "$classname$::$classname$(const $classname$& from)\n"
+        "  : $superclass$(), _impl_(from._impl_) {\n"
+        "  _internal_metadata_.MergeFrom<$unknown_fields_type$>(\n"
+        "      from._internal_metadata_);\n");
+    format(
+        "  // @@protoc_insertion_point(copy_constructor:$full_name$)\n"
+        "}\n"
+        "\n");
   } else {
     format(
         "$classname$::$classname$(const $classname$& from)\n"
@@ -2863,12 +2868,14 @@
           continue;
         }
         put_sep();
-        field_generators_.get(field).GenerateCopyAggregateInitializer(printer);
+        field_generators_.get(field).GenerateCopyAggregateInitializer(p);
       }
       if (ShouldSplit(descriptor_, options_)) {
         put_sep();
-        format("decltype($split$){reinterpret_cast<Impl_::Split*>(&$1$)}",
-               DefaultInstanceName(descriptor_, options_, /*split=*/true));
+        format(
+            "decltype($split$){const_cast<Impl_::Split*>"
+            "(reinterpret_cast<const Impl_::Split*>(&$1$))}",
+            DefaultInstanceName(descriptor_, options_, /*split=*/true));
       }
       for (auto oneof : OneOfRange(descriptor_)) {
         put_sep();
@@ -2907,7 +2914,7 @@
           "from.$extensions$);\n");
     }
 
-    GenerateCopyConstructorBody(printer);
+    GenerateCopyConstructorBody(p);
 
     // Copy oneof fields. Oneof field requires oneof case check.
     for (auto oneof : OneOfRange(descriptor_)) {
@@ -2920,7 +2927,7 @@
         format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
         format.Indent();
         if (!IsFieldStripped(field, options_)) {
-          field_generators_.get(field).GenerateMergingCode(printer);
+          field_generators_.get(field).GenerateMergingCode(p);
         }
         format("break;\n");
         format.Outdent();
@@ -2930,7 +2937,7 @@
           "case $1$_NOT_SET: {\n"
           "  break;\n"
           "}\n",
-          ToUpper(oneof->name()));
+          absl::AsciiStrToUpper(oneof->name()));
       format.Outdent();
       format("}\n");
     }
@@ -2943,11 +2950,7 @@
   }
 
   // Generate the shared constructor code.
-  GenerateSharedConstructorCode(printer);
-
-  if (ShouldSplit(descriptor_, options_)) {
-    GenerateCreateSplitMessage(printer);
-  }
+  GenerateSharedConstructorCode(p);
 
   // Generate the destructor.
   if (!HasSimpleBaseClass(descriptor_, options_)) {
@@ -2977,11 +2980,11 @@
   }
 
   // Generate the shared destructor code.
-  GenerateSharedDestructorCode(printer);
+  GenerateSharedDestructorCode(p);
 
   // Generate the arena-specific destructor code.
   if (NeedsArenaDestructor() > ArenaDtorNeeds::kNone) {
-    GenerateArenaDestructorCode(printer);
+    GenerateArenaDestructorCode(p);
   }
 
   if (!HasSimpleBaseClass(descriptor_, options_)) {
@@ -2993,8 +2996,9 @@
   }
 }
 
-void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateSourceInProto2Namespace(io::Printer* p) {
+  auto v = p->WithVars(ClassVars(descriptor_, options_));
+  Formatter format(p);
   format(
       "template<> "
       "PROTOBUF_NOINLINE $classtype$*\n"
@@ -3003,9 +3007,9 @@
       "}\n");
 }
 
-void MessageGenerator::GenerateClear(io::Printer* printer) {
+void MessageGenerator::GenerateClear(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
 
   // The maximum number of bytes we will memset to zero without checking their
   // hasbit to see if a zero-init is necessary.
@@ -3031,7 +3035,7 @@
   // checks all hasbits in the chunk and skips it if none are set.
   int zero_init_bytes = 0;
   for (const auto& field : optimized_order_) {
-    if (CanInitializeByZeroing(field)) {
+    if (CanClearByZeroing(field)) {
       zero_init_bytes += EstimateAlignmentSize(field);
     }
   }
@@ -3044,12 +3048,12 @@
         chunk_count++;
         // This predicate guarantees that there is only a single zero-init
         // (memset) per chunk, and if present it will be at the beginning.
-        bool same = HasByteIndex(a) == HasByteIndex(b) &&
-                    a->is_repeated() == b->is_repeated() &&
-                    ShouldSplit(a, options_) == ShouldSplit(b, options_) &&
-                    (CanInitializeByZeroing(a) == CanInitializeByZeroing(b) ||
-                     (CanInitializeByZeroing(a) &&
-                      (chunk_count == 1 || merge_zero_init)));
+        bool same =
+            HasByteIndex(a) == HasByteIndex(b) &&
+            a->is_repeated() == b->is_repeated() &&
+            ShouldSplit(a, options_) == ShouldSplit(b, options_) &&
+            (CanClearByZeroing(a) == CanClearByZeroing(b) ||
+             (CanClearByZeroing(a) && (chunk_count == 1 || merge_zero_init)));
         if (!same) chunk_count = 0;
         return same;
       });
@@ -3057,17 +3061,28 @@
   ColdChunkSkipper cold_skipper(descriptor_, options_, chunks, has_bit_indices_,
                                 kColdRatio);
   int cached_has_word_index = -1;
-
-  for (int chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
+  bool first_split_chunk_processed = false;
+  for (size_t chunk_index = 0; chunk_index < chunks.size(); chunk_index++) {
     std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
-    cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer);
+    cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", p);
 
     const FieldDescriptor* memset_start = nullptr;
     const FieldDescriptor* memset_end = nullptr;
     bool saw_non_zero_init = false;
-    bool chunk_is_cold = !chunk.empty() && ShouldSplit(chunk.front(), options_);
+    bool chunk_is_split =
+        !chunk.empty() && ShouldSplit(chunk.front(), options_);
+    // All chunks after the first split chunk should also be split.
+    GOOGLE_CHECK(!first_split_chunk_processed || chunk_is_split);
+    if (chunk_is_split && !first_split_chunk_processed) {
+      // Some fields are cleared without checking has_bit. So we add the
+      // condition here to avoid writing to the default split instance.
+      format("if (!IsSplitMessageDefault()) {\n");
+      format.Indent();
+      first_split_chunk_processed = true;
+    }
+
     for (const auto& field : chunk) {
-      if (CanInitializeByZeroing(field)) {
+      if (CanClearByZeroing(field)) {
         GOOGLE_CHECK(!saw_non_zero_init);
         if (!memset_start) memset_start = field;
         memset_end = field;
@@ -3089,7 +3104,7 @@
       // Emit an if() that will let us skip the whole chunk if none are set.
       uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
-          StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
+          absl::StrCat(absl::Hex(chunk_mask, absl::kZeroPad8));
 
       // Check (up to) 8 has_bits at a time if we have more than one field in
       // this chunk.  Due to field layout ordering, we may check
@@ -3105,31 +3120,25 @@
       format.Indent();
     }
 
-    if (chunk_is_cold) {
-      format("if (!IsSplitMessageDefault()) {\n");
-      format.Indent();
-    }
-
     if (memset_start) {
       if (memset_start == memset_end) {
         // For clarity, do not memset a single field.
-        field_generators_.get(memset_start)
-            .GenerateMessageClearingCode(printer);
+        field_generators_.get(memset_start).GenerateMessageClearingCode(p);
       } else {
-        GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_start, options_));
-        GOOGLE_CHECK_EQ(chunk_is_cold, ShouldSplit(memset_end, options_));
+        GOOGLE_CHECK_EQ(chunk_is_split, ShouldSplit(memset_start, options_));
+        GOOGLE_CHECK_EQ(chunk_is_split, ShouldSplit(memset_end, options_));
         format(
-            "::memset(&$1$, 0, static_cast<size_t>(\n"
+            "::memset(&$1$, 0, static_cast<::size_t>(\n"
             "    reinterpret_cast<char*>(&$2$) -\n"
             "    reinterpret_cast<char*>(&$1$)) + sizeof($2$));\n",
-            FieldMemberName(memset_start, chunk_is_cold),
-            FieldMemberName(memset_end, chunk_is_cold));
+            FieldMemberName(memset_start, chunk_is_split),
+            FieldMemberName(memset_end, chunk_is_split));
       }
     }
 
     // Clear all non-zero-initializable fields in the chunk.
     for (const auto& field : chunk) {
-      if (CanInitializeByZeroing(field)) continue;
+      if (CanClearByZeroing(field)) continue;
       // It's faster to just overwrite primitive types, but we should only
       // clear strings and messages if they were set.
       //
@@ -3140,11 +3149,10 @@
            field->cpp_type() == FieldDescriptor::CPPTYPE_STRING);
 
       if (have_enclosing_if) {
-        PrintPresenceCheck(format, field, has_bit_indices_, printer,
-                           &cached_has_word_index);
+        PrintPresenceCheck(field, has_bit_indices_, p, &cached_has_word_index);
       }
 
-      field_generators_.get(field).GenerateMessageClearingCode(printer);
+      field_generators_.get(field).GenerateMessageClearingCode(p);
 
       if (have_enclosing_if) {
         format.Outdent();
@@ -3152,17 +3160,19 @@
       }
     }
 
-    if (chunk_is_cold) {
-      format.Outdent();
-      format("}\n");
-    }
-
     if (have_outer_if) {
       format.Outdent();
       format("}\n");
     }
 
-    if (cold_skipper.OnEndChunk(chunk_index, printer)) {
+    if (chunk_index == chunks.size() - 1) {
+      if (first_split_chunk_processed) {
+        format.Outdent();
+        format("}\n");
+      }
+    }
+
+    if (cold_skipper.OnEndChunk(chunk_index, p)) {
       // Reset here as it may have been updated in just closed if statement.
       cached_has_word_index = -1;
     }
@@ -3184,21 +3194,18 @@
     format("$has_bits$.Clear();\n");
   }
 
-  std::map<std::string, std::string> vars;
-  SetUnknownFieldsVariable(descriptor_, options_, &vars);
-  format.AddMap(vars);
   format("_internal_metadata_.Clear<$unknown_fields_type$>();\n");
 
   format.Outdent();
   format("}\n");
 }
 
-void MessageGenerator::GenerateOneofClear(io::Printer* printer) {
+void MessageGenerator::GenerateOneofClear(io::Printer* p) {
   // Generated function clears the active field and union case (e.g. foo_case_).
   int i = 0;
   for (auto oneof : OneOfRange(descriptor_)) {
-    Formatter format(printer, variables_);
-    format.Set("oneofname", oneof->name());
+    Formatter format(p);
+    auto v = p->WithVars({{"oneofname", oneof->name()}});
 
     format(
         "void $classname$::clear_$oneofname$() {\n"
@@ -3213,7 +3220,7 @@
       if (!IsStringOrMessage(field) || IsFieldStripped(field, options_)) {
         format("// No need to clear\n");
       } else {
-        field_generators_.get(field).GenerateClearingCode(printer);
+        field_generators_.get(field).GenerateClearingCode(p);
       }
       format("break;\n");
       format.Outdent();
@@ -3223,12 +3230,12 @@
         "case $1$_NOT_SET: {\n"
         "  break;\n"
         "}\n",
-        ToUpper(oneof->name()));
+        absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format(
         "}\n"
         "$oneof_case$[$1$] = $2$_NOT_SET;\n",
-        i, ToUpper(oneof->name()));
+        i, absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format(
         "}\n"
@@ -3237,9 +3244,9 @@
   }
 }
 
-void MessageGenerator::GenerateSwap(io::Printer* printer) {
+void MessageGenerator::GenerateSwap(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
 
   format("void $classname$::InternalSwap($classname$* other) {\n");
   format.Indent();
@@ -3252,9 +3259,6 @@
           "\n");
     }
 
-    std::map<std::string, std::string> vars;
-    SetUnknownFieldsVariable(descriptor_, options_, &vars);
-    format.AddMap(vars);
     if (HasNonSplitOptionalString(descriptor_, options_)) {
       format(
           "auto* lhs_arena = GetArenaForAllocation();\n"
@@ -3272,7 +3276,7 @@
     const RunMap runs =
         FindRuns(optimized_order_, [this](const FieldDescriptor* field) {
           return !ShouldSplit(field, options_) &&
-                 CanBeManipulatedAsRawBytes(field, options_, scc_analyzer_);
+                 HasTrivialSwap(field, options_, scc_analyzer_);
         });
 
     for (size_t i = 0; i < optimized_order_.size(); ++i) {
@@ -3293,8 +3297,10 @@
         const std::string last_field_name = FieldMemberName(
             optimized_order_[i + run_length - 1], /*cold=*/false);
 
-        format.Set("first", first_field_name);
-        format.Set("last", last_field_name);
+        auto v = p->WithVars({
+            {"first", first_field_name},
+            {"last", last_field_name},
+        });
 
         format(
             "::PROTOBUF_NAMESPACE_ID::internal::memswap<\n"
@@ -3307,7 +3313,7 @@
         i += run_length - 1;
         // ++i at the top of the loop.
       } else {
-        field_generators_.get(field).GenerateSwappingCode(printer);
+        field_generators_.get(field).GenerateSwappingCode(p);
       }
     }
     if (ShouldSplit(descriptor_, options_)) {
@@ -3344,8 +3350,8 @@
   format("}\n");
 }
 
-void MessageGenerator::GenerateMergeFrom(io::Printer* printer) {
-  Formatter format(printer, variables_);
+void MessageGenerator::GenerateMergeFrom(io::Printer* p) {
+  Formatter format(p);
   if (!HasSimpleBaseClass(descriptor_, options_)) {
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       // We don't override the generalized MergeFrom (aka that which
@@ -3391,10 +3397,10 @@
   }
 }
 
-void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* printer) {
+void MessageGenerator::GenerateClassSpecificMergeImpl(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
   // Generate the class-specific MergeFrom, which avoids the GOOGLE_CHECK and cast.
-  Formatter format(printer, variables_);
+  Formatter format(p);
   if (!HasDescriptorMethods(descriptor_->file(), options_)) {
     // For messages that don't inherit from Message, just implement MergeFrom
     // directly.
@@ -3445,14 +3451,13 @@
     const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
     bool have_outer_if =
         chunk.size() > 1 && HasByteIndex(chunk.front()) != kNoHasbit;
-    cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.",
-                              printer);
+    cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "from.", p);
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
       uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
-          StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
+          absl::StrCat(absl::Hex(chunk_mask, absl::kZeroPad8));
 
       // Check (up to) 8 has_bits at a time if we have more than one field in
       // this chunk.  Due to field layout ordering, we may check
@@ -3476,13 +3481,13 @@
       const FieldGenerator& generator = field_generators_.get(field);
 
       if (field->is_repeated()) {
-        generator.GenerateMergingCode(printer);
+        generator.GenerateMergingCode(p);
       } else if (field->is_optional() && !HasHasbit(field)) {
         // Merge semantics without true field presence: primitive fields are
         // merged only if non-zero (numeric) or non-empty (string).
         bool have_enclosing_if =
-            EmitFieldNonDefaultCondition(printer, "from.", field);
-        generator.GenerateMergingCode(printer);
+            EmitFieldNonDefaultCondition(p, "from.", field);
+        generator.GenerateMergingCode(p);
         if (have_enclosing_if) {
           format.Outdent();
           format("}\n");
@@ -3491,17 +3496,19 @@
                  cached_has_word_index != HasWordIndex(field)) {
         // Check hasbit, not using cached bits.
         GOOGLE_CHECK(HasHasbit(field));
-        format("if (from._internal_has_$1$()) {\n", FieldName(field));
+        auto v = p->WithVars(HasbitVars(HasBitIndex(field)));
+        format(
+            "if ((from.$has_bits$[$has_array_index$] & $has_mask$) != 0) {\n");
         format.Indent();
-        generator.GenerateMergingCode(printer);
+        generator.GenerateMergingCode(p);
         format.Outdent();
         format("}\n");
       } else {
         // Check hasbit, using cached bits.
         GOOGLE_CHECK(HasHasbit(field));
         int has_bit_index = has_bit_indices_[field->index()];
-        const std::string mask = StrCat(
-            strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
+        const std::string mask = absl::StrCat(
+            absl::Hex(1u << (has_bit_index % 32), absl::kZeroPad8));
         format("if (cached_has_bits & 0x$1$u) {\n", mask);
         format.Indent();
 
@@ -3509,9 +3516,9 @@
           // Defer hasbit modification until the end of chunk.
           // This can reduce the number of loads/stores by up to 7 per 8 fields.
           deferred_has_bit_changes = true;
-          generator.GenerateCopyConstructorCode(printer);
+          generator.GenerateCopyConstructorCode(p);
         } else {
-          generator.GenerateMergingCode(printer);
+          generator.GenerateMergingCode(p);
         }
 
         format.Outdent();
@@ -3531,7 +3538,7 @@
       format("}\n");
     }
 
-    if (cold_skipper.OnEndChunk(chunk_index, printer)) {
+    if (cold_skipper.OnEndChunk(chunk_index, p)) {
       // Reset here as it may have been updated in just closed if statement.
       cached_has_word_index = -1;
     }
@@ -3545,7 +3552,7 @@
       format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
       format.Indent();
       if (!IsFieldStripped(field, options_)) {
-        field_generators_.get(field).GenerateMergingCode(printer);
+        field_generators_.get(field).GenerateMergingCode(p);
       }
       format("break;\n");
       format.Outdent();
@@ -3555,7 +3562,7 @@
         "case $1$_NOT_SET: {\n"
         "  break;\n"
         "}\n",
-        ToUpper(oneof->name()));
+        absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format("}\n");
   }
@@ -3582,9 +3589,9 @@
   format("}\n");
 }
 
-void MessageGenerator::GenerateCopyFrom(io::Printer* printer) {
+void MessageGenerator::GenerateCopyFrom(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
   if (HasDescriptorMethods(descriptor_->file(), options_)) {
     // We don't override the generalized CopyFrom (aka that which
     // takes in the Message base class as a parameter); instead we just
@@ -3620,7 +3627,7 @@
     if (HasDescriptorMethods(descriptor_->file(), options_)) {
       format("FailIfCopyFromDescendant(*this, from);\n");
     } else {
-      format("size_t from_size = from.ByteSizeLong();\n");
+      format("::size_t from_size = from.ByteSizeLong();\n");
     }
     format(
         "#endif\n"
@@ -3643,15 +3650,15 @@
   format("}\n");
 }
 
-void MessageGenerator::GenerateVerify(io::Printer* printer) {
+void MessageGenerator::GenerateVerify(io::Printer* p) {
 }
 
 void MessageGenerator::GenerateSerializeOneofFields(
-    io::Printer* printer, const std::vector<const FieldDescriptor*>& fields) {
-  Formatter format(printer, variables_);
+    io::Printer* p, const std::vector<const FieldDescriptor*>& fields) {
+  Formatter format(p);
   GOOGLE_CHECK(!fields.empty());
   if (fields.size() == 1) {
-    GenerateSerializeOneField(printer, fields[0], -1);
+    GenerateSerializeOneField(p, fields[0], -1);
     return;
   }
   // We have multiple mutually exclusive choices.  Emit a switch statement.
@@ -3661,8 +3668,7 @@
   for (auto field : fields) {
     format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
     format.Indent();
-    field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(
-        printer);
+    field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(p);
     format("break;\n");
     format.Outdent();
     format("}\n");
@@ -3674,36 +3680,36 @@
       "}\n");
 }
 
-void MessageGenerator::GenerateSerializeOneField(io::Printer* printer,
+void MessageGenerator::GenerateSerializeOneField(io::Printer* p,
                                                  const FieldDescriptor* field,
                                                  int cached_has_bits_index) {
-  Formatter format(printer, variables_);
+  Formatter format(p);
   if (!field->options().weak()) {
     // For weakfields, PrintFieldComment is called during iteration.
     PrintFieldComment(format, field);
   }
 
+  const FieldGenerator& field_gen = field_generators_.get(field);
+
   bool have_enclosing_if = false;
   if (field->options().weak()) {
   } else if (HasHasbit(field)) {
     // Attempt to use the state of cached_has_bits, if possible.
     int has_bit_index = HasBitIndex(field);
+    auto v = p->WithVars(HasbitVars(has_bit_index));
     if (cached_has_bits_index == has_bit_index / 32) {
-      const std::string mask =
-          StrCat(strings::Hex(1u << (has_bit_index % 32), strings::ZERO_PAD_8));
-
-      format("if (cached_has_bits & 0x$1$u) {\n", mask);
+      format("if (cached_has_bits & $has_mask$) {\n");
     } else {
-      format("if (_internal_has_$1$()) {\n", FieldName(field));
+      field_gen.GenerateIfHasField(p);
     }
 
     format.Indent();
     have_enclosing_if = true;
   } else if (field->is_optional() && !HasHasbit(field)) {
-    have_enclosing_if = EmitFieldNonDefaultCondition(printer, "this->", field);
+    have_enclosing_if = EmitFieldNonDefaultCondition(p, "this->", field);
   }
 
-  field_generators_.get(field).GenerateSerializeWithCachedSizesToArray(printer);
+  field_gen.GenerateSerializeWithCachedSizesToArray(p);
 
   if (have_enclosing_if) {
     format.Outdent();
@@ -3713,21 +3719,20 @@
 }
 
 void MessageGenerator::GenerateSerializeOneExtensionRange(
-    io::Printer* printer, const Descriptor::ExtensionRange* range) {
-  std::map<std::string, std::string> vars = variables_;
-  vars["start"] = StrCat(range->start);
-  vars["end"] = StrCat(range->end);
-  Formatter format(printer, vars);
+    io::Printer* p, const Descriptor::ExtensionRange* range) {
+  absl::flat_hash_map<absl::string_view, std::string> vars = variables_;
+  vars["start"] = absl::StrCat(range->start);
+  vars["end"] = absl::StrCat(range->end);
+  Formatter format(p, vars);
   format("// Extension range [$start$, $end$)\n");
   format(
       "target = $extensions$._InternalSerialize(\n"
       "internal_default_instance(), $start$, $end$, target, stream);\n\n");
 }
 
-void MessageGenerator::GenerateSerializeWithCachedSizesToArray(
-    io::Printer* printer) {
+void MessageGenerator::GenerateSerializeWithCachedSizesToArray(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
     format(
@@ -3738,9 +3743,7 @@
         "  target = $extensions$."
         "InternalSerializeMessageSetWithCachedSizesToArray(\n"  //
         "internal_default_instance(), target, stream);\n");
-    std::map<std::string, std::string> vars;
-    SetUnknownFieldsVariable(descriptor_, options_, &vars);
-    format.AddMap(vars);
+
     format(
         "  target = ::_pbi::"
         "InternalSerializeUnknownMessageSetItemsToArray(\n"
@@ -3766,14 +3769,14 @@
     format.Indent();
   }
 
-  GenerateSerializeWithCachedSizesBody(printer);
+  GenerateSerializeWithCachedSizesBody(p);
 
   if (!ShouldSerializeInOrder(descriptor_, options_)) {
     format.Outdent();
     format("#else  // NDEBUG\n");
     format.Indent();
 
-    GenerateSerializeWithCachedSizesBodyShuffled(printer);
+    GenerateSerializeWithCachedSizesBodyShuffled(p);
 
     format.Outdent();
     format("#endif  // !NDEBUG\n");
@@ -3788,10 +3791,9 @@
       "}\n");
 }
 
-void MessageGenerator::GenerateSerializeWithCachedSizesBody(
-    io::Printer* printer) {
+void MessageGenerator::GenerateSerializeWithCachedSizesBody(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
   // If there are multiple fields in a row from the same oneof then we
   // coalesce them and emit a switch statement.  This is more efficient
   // because it lets the C++ compiler know this is a "at most one can happen"
@@ -3799,9 +3801,9 @@
   // compiler's emitted code might check has_y() even when has_x() is true.
   class LazySerializerEmitter {
    public:
-    LazySerializerEmitter(MessageGenerator* mg, io::Printer* printer)
+    LazySerializerEmitter(MessageGenerator* mg, io::Printer* p)
         : mg_(mg),
-          format_(printer),
+          p_(p),
           eager_(IsProto3(mg->descriptor_->file())),
           cached_has_bit_index_(kNoHasbit) {}
 
@@ -3810,6 +3812,7 @@
     // If conditions allow, try to accumulate a run of fields from the same
     // oneof, and handle them at the next Flush().
     void Emit(const FieldDescriptor* field) {
+      Formatter format(p_);
       if (eager_ || MustFlush(field)) {
         Flush();
       }
@@ -3825,14 +3828,13 @@
             // Reload.
             int new_index = has_bit_index / 32;
 
-            format_("cached_has_bits = _impl_._has_bits_[$1$];\n", new_index);
+            format("cached_has_bits = _impl_._has_bits_[$1$];\n", new_index);
 
             cached_has_bit_index_ = new_index;
           }
         }
 
-        mg_->GenerateSerializeOneField(format_.printer(), field,
-                                       cached_has_bit_index_);
+        mg_->GenerateSerializeOneField(p_, field, cached_has_bit_index_);
       } else {
         v_.push_back(field);
       }
@@ -3846,7 +3848,7 @@
 
     void Flush() {
       if (!v_.empty()) {
-        mg_->GenerateSerializeOneofFields(format_.printer(), v_);
+        mg_->GenerateSerializeOneofFields(p_, v_);
         v_.clear();
       }
     }
@@ -3860,8 +3862,8 @@
     }
 
     MessageGenerator* mg_;
-    Formatter format_;
-    const bool eager_;
+    io::Printer* p_;
+    bool eager_;
     std::vector<const FieldDescriptor*> v_;
 
     // cached_has_bit_index_ maintains that:
@@ -3872,8 +3874,8 @@
 
   class LazyExtensionRangeEmitter {
    public:
-    LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* printer)
-        : mg_(mg), format_(printer) {}
+    LazyExtensionRangeEmitter(MessageGenerator* mg, io::Printer* p)
+        : mg_(mg), p_(p) {}
 
     void AddToRange(const Descriptor::ExtensionRange* range) {
       if (!has_current_range_) {
@@ -3889,15 +3891,14 @@
 
     void Flush() {
       if (has_current_range_) {
-        mg_->GenerateSerializeOneExtensionRange(format_.printer(),
-                                                &current_combined_range_);
+        mg_->GenerateSerializeOneExtensionRange(p_, &current_combined_range_);
       }
       has_current_range_ = false;
     }
 
    private:
     MessageGenerator* mg_;
-    Formatter format_;
+    io::Printer* p_;
     bool has_current_range_ = false;
     Descriptor::ExtensionRange current_combined_range_;
   };
@@ -3947,8 +3948,8 @@
 
   // Merge the fields and the extension ranges, both sorted by field number.
   {
-    LazySerializerEmitter e(this, printer);
-    LazyExtensionRangeEmitter re(this, printer);
+    LazySerializerEmitter e(this, p);
+    LazyExtensionRangeEmitter re(this, p);
     LargestWeakFieldHolder largest_weak_field;
     int i, j;
     for (i = 0, j = 0;
@@ -3978,9 +3979,6 @@
     e.EmitIfNotNull(largest_weak_field.Release());
   }
 
-  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_)) {
@@ -3999,8 +3997,8 @@
 }
 
 void MessageGenerator::GenerateSerializeWithCachedSizesBodyShuffled(
-    io::Printer* printer) {
-  Formatter format(printer, variables_);
+    io::Printer* p) {
+  Formatter format(p);
 
   std::vector<const FieldDescriptor*> ordered_fields =
       SortFieldsByNumber(descriptor_);
@@ -4042,7 +4040,7 @@
     format("case $1$: {\n", index++);
     format.Indent();
 
-    GenerateSerializeOneField(printer, f, -1);
+    GenerateSerializeOneField(p, f, -1);
 
     format("break;\n");
     format.Outdent();
@@ -4053,7 +4051,7 @@
     format("case $1$: {\n", index++);
     format.Indent();
 
-    GenerateSerializeOneExtensionRange(printer, r);
+    GenerateSerializeOneExtensionRange(p, r);
 
     format("break;\n");
     format.Outdent();
@@ -4070,9 +4068,6 @@
   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_)) {
@@ -4106,20 +4101,17 @@
   return masks;
 }
 
-void MessageGenerator::GenerateByteSize(io::Printer* printer) {
+void MessageGenerator::GenerateByteSize(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
 
   if (descriptor_->options().message_set_wire_format()) {
     // Special-case MessageSet.
-    std::map<std::string, std::string> vars;
-    SetUnknownFieldsVariable(descriptor_, options_, &vars);
-    format.AddMap(vars);
     format(
-        "size_t $classname$::ByteSizeLong() const {\n"
+        "::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"
+        "  ::size_t total_size = $extensions$.MessageSetByteSize();\n"
         "  if ($have_unknown_fields$) {\n"
         "    total_size += ::_pbi::\n"
         "        ComputeUnknownMessageSetItemsSize($unknown_fields$);\n"
@@ -4136,20 +4128,19 @@
     // Emit a function (rarely used, we hope) that handles the required fields
     // by checking for each one individually.
     format(
-        "size_t $classname$::RequiredFieldsByteSizeFallback() const {\n"
+        "::size_t $classname$::RequiredFieldsByteSizeFallback() const {\n"
         "// @@protoc_insertion_point(required_fields_byte_size_fallback_start:"
         "$full_name$)\n");
     format.Indent();
-    format("size_t total_size = 0;\n");
+    format("::size_t total_size = 0;\n");
     for (auto field : optimized_order_) {
       if (field->is_required()) {
-        format(
-            "\n"
-            "if (_internal_has_$1$()) {\n",
-            FieldName(field));
+        const FieldGenerator& field_gen = field_generators_.get(field);
+        format("\n");
+        field_gen.GenerateIfHasField(p);
         format.Indent();
         PrintFieldComment(format, field);
-        field_generators_.get(field).GenerateByteSize(printer);
+        field_gen.GenerateByteSize(p);
         format.Outdent();
         format("}\n");
       }
@@ -4162,12 +4153,12 @@
   }
 
   format(
-      "size_t $classname$::ByteSizeLong() const {\n"
+      "::size_t $classname$::ByteSizeLong() const {\n"
       "$annotate_bytesize$"
       "// @@protoc_insertion_point(message_byte_size_start:$full_name$)\n");
   format.Indent();
   format(
-      "size_t total_size = 0;\n"
+      "::size_t total_size = 0;\n"
       "\n");
 
   if (descriptor_->extension_range_count() > 0) {
@@ -4176,10 +4167,6 @@
         "\n");
   }
 
-  std::map<std::string, std::string> vars;
-  SetUnknownFieldsVariable(descriptor_, options_, &vars);
-  format.AddMap(vars);
-
   // Handle required fields (if any).  We expect all of them to be
   // present, so emit one conditional that checks for that.  If they are all
   // present then the fast path executes; otherwise the slow path executes.
@@ -4194,7 +4181,7 @@
     for (auto field : optimized_order_) {
       if (!field->is_required()) continue;
       PrintFieldComment(format, field);
-      field_generators_.get(field).GenerateByteSize(printer);
+      field_generators_.get(field).GenerateByteSize(p);
       format("\n");
     }
     format.Outdent();
@@ -4207,9 +4194,10 @@
     for (auto field : optimized_order_) {
       if (!field->is_required()) continue;
       PrintFieldComment(format, field);
-      format("if (_internal_has_$1$()) {\n", FieldName(field));
+      const FieldGenerator& field_gen = field_generators_.get(field);
+      field_gen.GenerateIfHasField(p);
       format.Indent();
-      field_generators_.get(field).GenerateByteSize(printer);
+      field_gen.GenerateByteSize(p);
       format.Outdent();
       format("}\n");
     }
@@ -4239,13 +4227,13 @@
     const std::vector<const FieldDescriptor*>& chunk = chunks[chunk_index];
     const bool have_outer_if =
         chunk.size() > 1 && HasWordIndex(chunk[0]) != kNoHasbit;
-    cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", printer);
+    cold_skipper.OnStartChunk(chunk_index, cached_has_word_index, "", p);
 
     if (have_outer_if) {
       // Emit an if() that will let us skip the whole chunk if none are set.
       uint32_t chunk_mask = GenChunkMask(chunk, has_bit_indices_);
       std::string chunk_mask_str =
-          StrCat(strings::Hex(chunk_mask, strings::ZERO_PAD_8));
+          absl::StrCat(absl::Hex(chunk_mask, absl::kZeroPad8));
 
       // Check (up to) 8 has_bits at a time if we have more than one field in
       // this chunk.  Due to field layout ordering, we may check
@@ -4274,17 +4262,15 @@
         // No presence check is required.
         need_extra_newline = true;
       } else if (HasHasbit(field)) {
-        PrintPresenceCheck(format, field, has_bit_indices_, printer,
-                           &cached_has_word_index);
+        PrintPresenceCheck(field, has_bit_indices_, p, &cached_has_word_index);
         have_enclosing_if = true;
       } else {
         // Without field presence: field is serialized only if it has a
         // non-default value.
-        have_enclosing_if =
-            EmitFieldNonDefaultCondition(printer, "this->", field);
+        have_enclosing_if = EmitFieldNonDefaultCondition(p, "this->", field);
       }
 
-      generator.GenerateByteSize(printer);
+      generator.GenerateByteSize(p);
 
       if (have_enclosing_if) {
         format.Outdent();
@@ -4302,7 +4288,7 @@
       format("}\n");
     }
 
-    if (cold_skipper.OnEndChunk(chunk_index, printer)) {
+    if (cold_skipper.OnEndChunk(chunk_index, p)) {
       // Reset here as it may have been updated in just closed if statement.
       cached_has_word_index = -1;
     }
@@ -4318,7 +4304,7 @@
       format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
       format.Indent();
       if (!IsFieldStripped(field, options_)) {
-        field_generators_.get(field).GenerateByteSize(printer);
+        field_generators_.get(field).GenerateByteSize(p);
       }
       format("break;\n");
       format.Outdent();
@@ -4328,7 +4314,7 @@
         "case $1$_NOT_SET: {\n"
         "  break;\n"
         "}\n",
-        ToUpper(oneof->name()));
+        absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format("}\n");
   }
@@ -4367,9 +4353,9 @@
   format("}\n");
 }
 
-void MessageGenerator::GenerateIsInitialized(io::Printer* printer) {
+void MessageGenerator::GenerateIsInitialized(io::Printer* p) {
   if (HasSimpleBaseClass(descriptor_, options_)) return;
-  Formatter format(printer, variables_);
+  Formatter format(p);
   format("bool $classname$::IsInitialized() const {\n");
   format.Indent();
 
@@ -4388,7 +4374,7 @@
 
   // Now check that all non-oneof embedded messages are initialized.
   for (auto field : optimized_order_) {
-    field_generators_.get(field).GenerateIsInitialized(printer);
+    field_generators_.get(field).GenerateIsInitialized(p);
   }
   if (num_weak_fields_) {
     // For Weak fields.
@@ -4417,7 +4403,7 @@
       format("case k$1$: {\n", UnderscoresToCamelCase(field->name(), true));
       format.Indent();
       if (!IsFieldStripped(field, options_)) {
-        field_generators_.get(field).GenerateIsInitialized(printer);
+        field_generators_.get(field).GenerateIsInitialized(p);
       }
       format("break;\n");
       format.Outdent();
@@ -4427,7 +4413,7 @@
         "case $1$_NOT_SET: {\n"
         "  break;\n"
         "}\n",
-        ToUpper(oneof->name()));
+        absl::AsciiStrToUpper(oneof->name()));
     format.Outdent();
     format("}\n");
   }
@@ -4443,4 +4429,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/cpp/message.h b/src/google/protobuf/compiler/cpp/message.h
index 5bdfcb3..7e22304 100644
--- a/src/google/protobuf/compiler/cpp/message.h
+++ b/src/google/protobuf/compiler/cpp/message.h
@@ -36,40 +36,38 @@
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_H__
 
 #include <cstdint>
+#include <limits>
 #include <memory>
-#include <set>
 #include <string>
+#include <utility>
+#include <vector>
 
-#include <google/protobuf/compiler/cpp/field.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/message_layout_helper.h>
-#include <google/protobuf/compiler/cpp/options.h>
-#include <google/protobuf/compiler/cpp/parse_function_generator.h>
-
-namespace google {
-namespace protobuf {
-namespace io {
-class Printer;  // printer.h
-}
-}  // namespace protobuf
-}  // namespace google
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/cpp/enum.h"
+#include "google/protobuf/compiler/cpp/extension.h"
+#include "google/protobuf/compiler/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/message_layout_helper.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/compiler/cpp/parse_function_generator.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
-class EnumGenerator;       // enum.h
-class ExtensionGenerator;  // extension.h
-
 class MessageGenerator {
  public:
-  // See generator.cc for the meaning of dllexport_decl.
-  MessageGenerator(const Descriptor* descriptor,
-                   const std::map<std::string, std::string>& vars,
-                   int index_in_file_messages, const Options& options,
-                   MessageSCCAnalyzer* scc_analyzer);
-  ~MessageGenerator();
+  MessageGenerator(
+      const Descriptor* descriptor,
+      const absl::flat_hash_map<absl::string_view, std::string>& ignored,
+      int index_in_file_messages, const Options& options,
+      MessageSCCAnalyzer* scc_analyzer);
+
+  MessageGenerator(const MessageGenerator&) = delete;
+  MessageGenerator& operator=(const MessageGenerator&) = delete;
+
+  ~MessageGenerator() = default;
 
   // Append the two types of nested generators to the corresponding vector.
   void AddGenerators(
@@ -77,95 +75,94 @@
       std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
 
   // Generate definitions for this class and all its nested types.
-  void GenerateClassDefinition(io::Printer* printer);
+  void GenerateClassDefinition(io::Printer* p);
 
   // Generate definitions of inline methods (placed at the end of the header
   // file).
-  void GenerateInlineMethods(io::Printer* printer);
-
-  // Source file stuff.
+  void GenerateInlineMethods(io::Printer* p);
 
   // Generate all non-inline methods for this class.
-  void GenerateClassMethods(io::Printer* printer);
+  void GenerateClassMethods(io::Printer* p);
 
   // Generate source file code that should go outside any namespace.
-  void GenerateSourceInProto2Namespace(io::Printer* printer);
+  void GenerateSourceInProto2Namespace(io::Printer* p);
 
- private:
-  // Generate declarations and definitions of accessors for fields.
-  void GenerateFieldAccessorDeclarations(io::Printer* printer);
-  void GenerateFieldAccessorDefinitions(io::Printer* printer);
+
+  void GenerateInitDefaultSplitInstance(io::Printer* p);
+
+  // Generate the constexpr constructor for constant initialization of the
+  // default instance.
+  void GenerateConstexprConstructor(io::Printer* p);
+
+  void GenerateSchema(io::Printer* p, int offset, int has_offset);
 
   // 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);
+  std::pair<size_t, size_t> GenerateOffsets(io::Printer* p);
+
+  const Descriptor* descriptor() const { return descriptor_; }
+
+ private:
+  // Generate declarations and definitions of accessors for fields.
+  void GenerateFieldAccessorDeclarations(io::Printer* p);
+  void GenerateFieldAccessorDefinitions(io::Printer* p);
 
   // Generate constructors and destructor.
-  void GenerateStructors(io::Printer* printer);
+  void GenerateStructors(io::Printer* p);
 
   // The compiler typically generates multiple copies of each constructor and
   // destructor: http://gcc.gnu.org/bugs.html#nonbugs_cxx
   // Placing common code in a separate method reduces the generated code size.
   //
   // Generate the shared constructor code.
-  void GenerateSharedConstructorCode(io::Printer* printer);
+  void GenerateSharedConstructorCode(io::Printer* p);
   // Generate the shared destructor code.
-  void GenerateSharedDestructorCode(io::Printer* printer);
+  void GenerateSharedDestructorCode(io::Printer* p);
   // 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);
-
-  void GenerateCreateSplitMessage(io::Printer* printer);
-  void GenerateInitDefaultSplitInstance(io::Printer* printer);
+  void GenerateArenaDestructorCode(io::Printer* p);
 
   // Generate standard Message methods.
-  void GenerateClear(io::Printer* printer);
-  void GenerateOneofClear(io::Printer* printer);
-  void GenerateVerify(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 GenerateClassSpecificMergeImpl(io::Printer* printer);
-  void GenerateCopyFrom(io::Printer* printer);
-  void GenerateSwap(io::Printer* printer);
-  void GenerateIsInitialized(io::Printer* printer);
+  void GenerateClear(io::Printer* p);
+  void GenerateOneofClear(io::Printer* p);
+  void GenerateVerify(io::Printer* p);
+  void GenerateSerializeWithCachedSizes(io::Printer* p);
+  void GenerateSerializeWithCachedSizesToArray(io::Printer* p);
+  void GenerateSerializeWithCachedSizesBody(io::Printer* p);
+  void GenerateSerializeWithCachedSizesBodyShuffled(io::Printer* p);
+  void GenerateByteSize(io::Printer* p);
+  void GenerateMergeFrom(io::Printer* p);
+  void GenerateClassSpecificMergeImpl(io::Printer* p);
+  void GenerateCopyFrom(io::Printer* p);
+  void GenerateSwap(io::Printer* p);
+  void GenerateIsInitialized(io::Printer* p);
 
   // Helpers for GenerateSerializeWithCachedSizes().
   //
   // cached_has_bit_index maintains that:
   //   cached_has_bits = _has_bits_[cached_has_bit_index]
   // for cached_has_bit_index >= 0
-  void GenerateSerializeOneField(io::Printer* printer,
-                                 const FieldDescriptor* field,
+  void GenerateSerializeOneField(io::Printer* p, const FieldDescriptor* field,
                                  int cached_has_bits_index);
   // Generate a switch statement to serialize 2+ fields from the same oneof.
   // Or, if fields.size() == 1, just call GenerateSerializeOneField().
   void GenerateSerializeOneofFields(
-      io::Printer* printer, const std::vector<const FieldDescriptor*>& fields);
+      io::Printer* p, const std::vector<const FieldDescriptor*>& fields);
   void GenerateSerializeOneExtensionRange(
-      io::Printer* printer, const Descriptor::ExtensionRange* range);
+      io::Printer* p, const Descriptor::ExtensionRange* range);
 
   // Generates has_foo() functions and variables for singular field has-bits.
   void GenerateSingularFieldHasBits(const FieldDescriptor* field,
-                                    Formatter format);
+                                    io::Printer* p);
   // Generates has_foo() functions and variables for oneof field has-bits.
-  void GenerateOneofHasBits(io::Printer* printer);
+  void GenerateOneofHasBits(io::Printer* p);
   // Generates has_foo_bar() functions for oneof members.
-  void GenerateOneofMemberHasBits(const FieldDescriptor* field,
-                                  const Formatter& format);
+  void GenerateOneofMemberHasBits(const FieldDescriptor* field, io::Printer* p);
   // Generates the clear_foo() method for a field.
   void GenerateFieldClear(const FieldDescriptor* field, bool is_inline,
-                          Formatter format);
+                          io::Printer* p);
 
   // Generates the body of the message's copy constructor.
-  void GenerateCopyConstructorBody(io::Printer* printer) const;
+  void GenerateCopyConstructorBody(io::Printer* p) const;
 
   // Returns the level that this message needs ArenaDtor. If the message has
   // a field that is not arena-exclusive, it needs an ArenaDtor
@@ -181,15 +178,13 @@
 
   size_t HasBitsSize() const;
   size_t InlinedStringDonatedSize() const;
-  int HasBitIndex(const FieldDescriptor* a) const;
-  int HasByteIndex(const FieldDescriptor* a) const;
-  int HasWordIndex(const FieldDescriptor* a) const;
-  bool SameHasByte(const FieldDescriptor* a, const FieldDescriptor* b) const;
+  int HasBitIndex(const FieldDescriptor* field) const;
+  int HasByteIndex(const FieldDescriptor* field) const;
+  int HasWordIndex(const FieldDescriptor* field) const;
   std::vector<uint32_t> RequiredFieldsBitMask() const;
 
   const Descriptor* descriptor_;
   int index_in_file_messages_;
-  std::string classname_;
   Options options_;
   FieldGeneratorMap field_generators_;
   // optimized_order_ is the order we layout the message's fields in the
@@ -199,29 +194,27 @@
   // optimized_order_ excludes oneof fields and weak fields.
   std::vector<const FieldDescriptor*> optimized_order_;
   std::vector<int> has_bit_indices_;
-  int max_has_bit_index_;
+  int max_has_bit_index_ = 0;
 
   // A map from field index to inlined_string index. For non-inlined-string
   // fields, the element is -1. If there is no inlined string in the message,
   // this is empty.
   std::vector<int> inlined_string_indices_;
   // The count of inlined_string fields in the message.
-  int max_inlined_string_index_;
+  int max_inlined_string_index_ = 0;
 
   std::vector<const EnumGenerator*> enum_generators_;
   std::vector<const ExtensionGenerator*> extension_generators_;
-  int num_required_fields_;
-  int num_weak_fields_;
+  int num_required_fields_ = 0;
+  int num_weak_fields_ = 0;
 
   std::unique_ptr<MessageLayoutHelper> message_layout_helper_;
   std::unique_ptr<ParseFunctionGenerator> parse_function_generator_;
 
   MessageSCCAnalyzer* scc_analyzer_;
 
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
 
-  friend class FileGenerator;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/message_field.cc b/src/google/protobuf/compiler/cpp/message_field.cc
index 7e87a07..175313c 100644
--- a/src/google/protobuf/compiler/cpp/message_field.cc
+++ b/src/google/protobuf/compiler/cpp/message_field.cc
@@ -32,13 +32,13 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/message_field.h>
+#include "google/protobuf/compiler/cpp/message_field.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/compiler/cpp/field.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -56,28 +56,34 @@
   }
 }
 
-void SetMessageVariables(const FieldDescriptor* descriptor,
-                         const Options& options, bool implicit_weak,
-                         std::map<std::string, std::string>* variables) {
+void SetMessageVariables(
+    const FieldDescriptor* descriptor, const Options& options,
+    bool implicit_weak,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = FieldMessageTypeName(descriptor, options);
-  (*variables)["casted_member"] = ReinterpretCast(
-      (*variables)["type"] + "*", (*variables)["field"], implicit_weak);
-  (*variables)["casted_member_const"] =
-      ReinterpretCast("const " + (*variables)["type"] + "&",
-                      "*" + (*variables)["field"], implicit_weak);
+  variables->insert(
+      {"casted_member", ReinterpretCast(absl::StrCat((*variables)["type"], "*"),
+                                        (*variables)["field"], implicit_weak)});
+  variables->insert(
+      {"casted_member_const",
+       ReinterpretCast(absl::StrCat("const ", (*variables)["type"], "&"),
+                       absl::StrCat("*", (*variables)["field"]),
+                       implicit_weak)});
   (*variables)["type_default_instance"] =
       QualifiedDefaultInstanceName(descriptor->message_type(), options);
   (*variables)["type_default_instance_ptr"] = ReinterpretCast(
       "const ::PROTOBUF_NAMESPACE_ID::MessageLite*",
       QualifiedDefaultInstancePtr(descriptor->message_type(), options),
       implicit_weak);
-  (*variables)["type_reference_function"] =
-      implicit_weak ? ("  ::" + (*variables)["proto_ns"] +
-                       "::internal::StrongReference(reinterpret_cast<const " +
-                       (*variables)["type"] + "&>(\n" +
-                       (*variables)["type_default_instance"] + "));\n")
-                    : "";
+  variables->insert(
+      {"type_reference_function",
+       implicit_weak
+           ? absl::StrCat("  ::", ProtobufNamespace(options),
+                          "::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.
   (*variables)["release_name"] =
@@ -191,12 +197,19 @@
   } else {
     format("  $field$ = $name$;\n");
   }
+  auto nonempty = [this](const char* fn) {
+    auto var_it = variables_.find(fn);
+    return var_it != variables_.end() && !var_it->second.empty();
+  };
+  if (nonempty("set_hasbit") || nonempty("clear_hasbit")) {
+    format(
+        "  if ($name$) {\n"
+        "    $set_hasbit$\n"
+        "  } else {\n"
+        "    $clear_hasbit$\n"
+        "  }\n");
+  }
   format(
-      "  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"
@@ -343,14 +356,14 @@
     format(
         "::$proto_ns$::MessageLite*\n"
         "$classname$::_Internal::mutable_$name$($classname$* msg) {\n");
-    if (HasHasbit(descriptor_)) {
+    if (internal::cpp::HasHasbit(descriptor_)) {
       format("  msg->$set_hasbit$\n");
     }
     if (descriptor_->real_containing_oneof() == nullptr) {
       format("  if (msg->$field$ == nullptr) {\n");
     } else {
       format(
-          "  if (!msg->_internal_has_$name$()) {\n"
+          "  if (msg->$not_has_field$) {\n"
           "    msg->clear_$oneof_name$();\n"
           "    msg->set_has_$name$();\n");
     }
@@ -376,7 +389,7 @@
   GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
-  if (!HasHasbit(descriptor_)) {
+  if (!internal::cpp::HasHasbit(descriptor_)) {
     // If we don't have has-bits, message presence is indicated only by ptr !=
     // nullptr. Thus on clear, we need to delete the object.
     format(
@@ -394,7 +407,7 @@
   GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
-  if (!HasHasbit(descriptor_)) {
+  if (!internal::cpp::HasHasbit(descriptor_)) {
     // If we don't have has-bits, message presence is indicated only by ptr !=
     // nullptr. Thus on clear, we need to delete the object.
     format(
@@ -450,15 +463,24 @@
   format("delete $field$;\n");
 }
 
+using internal::cpp::HasHasbit;
+
 void MessageFieldGenerator::GenerateCopyConstructorCode(
     io::Printer* printer) const {
   GOOGLE_CHECK(!IsFieldStripped(descriptor_, options_));
 
   Formatter format(printer, variables_);
-  format(
-      "if (from._internal_has_$name$()) {\n"
-      "  _this->$field$ = new $type$(*from.$field$);\n"
-      "}\n");
+  if (HasHasbit(descriptor_)) {
+    format(
+        "if ((from.$has_hasbit$) != 0) {\n"
+        "  _this->$field$ = new $type$(*from.$field$);\n"
+        "}\n");
+  } else {
+    format(
+        "if (from._internal_has_$name$()) {\n"
+        "  _this->$field$ = new $type$(*from.$field$);\n"
+        "}\n");
+  }
 }
 
 void MessageFieldGenerator::GenerateSerializeWithCachedSizesToArray(
@@ -496,10 +518,17 @@
   if (!has_required_fields_) return;
 
   Formatter format(printer, variables_);
-  format(
-      "if (_internal_has_$name$()) {\n"
-      "  if (!$field$->IsInitialized()) return false;\n"
-      "}\n");
+  if (HasHasbit(descriptor_)) {
+    format(
+        "if (($has_hasbit$) != 0) {\n"
+        "  if (!$field$->IsInitialized()) return false;\n"
+        "}\n");
+  } else {
+    format(
+        "if (_internal_has_$name$()) {\n"
+        "  if (!$field$->IsInitialized()) return false;\n"
+        "}\n");
+  }
 }
 
 void MessageFieldGenerator::GenerateConstexprAggregateInitializer(
@@ -577,7 +606,7 @@
       "$annotate_release$"
       "  // @@protoc_insertion_point(field_release:$full_name$)\n"
       "$type_reference_function$"
-      "  if (_internal_has_$name$()) {\n"
+      "  if ($has_field$) {\n"
       "    clear_has_$oneof_name$();\n"
       "    $type$* temp = $casted_member$;\n"
       "    if (GetArenaForAllocation() != nullptr) {\n"
@@ -593,7 +622,7 @@
   format(
       "inline const $type$& $classname$::_internal_$name$() const {\n"
       "$type_reference_function$"
-      "  return _internal_has_$name$()\n"
+      "  return $has_field$\n"
       "      ? $casted_member_const$\n"
       "      : reinterpret_cast< $type$&>($type_default_instance$);\n"
       "}\n"
@@ -607,7 +636,7 @@
       "  // @@protoc_insertion_point(field_unsafe_arena_release"
       ":$full_name$)\n"
       "$type_reference_function$"
-      "  if (_internal_has_$name$()) {\n"
+      "  if ($has_field$) {\n"
       "    clear_has_$oneof_name$();\n"
       "    $type$* temp = $casted_member$;\n"
       "    $field$ = nullptr;\n"
@@ -639,7 +668,7 @@
       "}\n"
       "inline $type$* $classname$::_internal_mutable_$name$() {\n"
       "$type_reference_function$"
-      "  if (!_internal_has_$name$()) {\n"
+      "  if ($not_has_field$) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n");
   if (implicit_weak_field_) {
@@ -703,7 +732,7 @@
 
   Formatter format(printer, variables_);
   format(
-      "if (_internal_has_$name$()) {\n"
+      "if ($has_field$) {\n"
       "  if (!$field$->IsInitialized()) return false;\n"
       "}\n");
 }
diff --git a/src/google/protobuf/compiler/cpp/message_field.h b/src/google/protobuf/compiler/cpp/message_field.h
index 70c42c0..a7708c8 100644
--- a/src/google/protobuf/compiler/cpp/message_field.h
+++ b/src/google/protobuf/compiler/cpp/message_field.h
@@ -35,11 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_FIELD_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/field.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include "google/protobuf/compiler/cpp/field.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
 
 namespace google {
 namespace protobuf {
@@ -51,6 +50,8 @@
   MessageFieldGenerator(const FieldDescriptor* descriptor,
                         const Options& options,
                         MessageSCCAnalyzer* scc_analyzer);
+  MessageFieldGenerator(const MessageFieldGenerator&) = delete;
+  MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
   ~MessageFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -81,9 +82,6 @@
  protected:
   const bool implicit_weak_field_;
   const bool has_required_fields_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFieldGenerator);
 };
 
 class MessageOneofFieldGenerator : public MessageFieldGenerator {
@@ -91,6 +89,9 @@
   MessageOneofFieldGenerator(const FieldDescriptor* descriptor,
                              const Options& options,
                              MessageSCCAnalyzer* scc_analyzer);
+  MessageOneofFieldGenerator(const MessageOneofFieldGenerator&) = delete;
+  MessageOneofFieldGenerator& operator=(const MessageOneofFieldGenerator&) =
+      delete;
   ~MessageOneofFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -106,9 +107,6 @@
   void GenerateDestructorCode(io::Printer* printer) const override;
   void GenerateConstructorCode(io::Printer* printer) const override;
   void GenerateIsInitialized(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageOneofFieldGenerator);
 };
 
 class RepeatedMessageFieldGenerator : public FieldGenerator {
@@ -116,6 +114,9 @@
   RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor,
                                 const Options& options,
                                 MessageSCCAnalyzer* scc_analyzer);
+  RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete;
+  RepeatedMessageFieldGenerator& operator=(
+      const RepeatedMessageFieldGenerator&) = delete;
   ~RepeatedMessageFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -136,8 +137,6 @@
  private:
   const bool implicit_weak_field_;
   const bool has_required_fields_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedMessageFieldGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/message_layout_helper.h b/src/google/protobuf/compiler/cpp/message_layout_helper.h
index a8813a1..7727e67 100644
--- a/src/google/protobuf/compiler/cpp/message_layout_helper.h
+++ b/src/google/protobuf/compiler/cpp/message_layout_helper.h
@@ -35,8 +35,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_MESSAGE_LAYOUT_HELPER_H__
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/options.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/cpp/options.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/cpp/message_size_unittest.cc b/src/google/protobuf/compiler/cpp/message_size_unittest.cc
index 761988b..36eeb92 100644
--- a/src/google/protobuf/compiler/cpp/message_size_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/message_size_unittest.cc
@@ -28,10 +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 <google/protobuf/unittest.pb.h>
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/unittest.pb.h"
 
 namespace google {
 namespace protobuf {
@@ -139,9 +139,9 @@
 
 TEST(GeneratedMessageTest, MoreStringSize) {
   struct MockGenerated : public MockMessageBase {  // 16 bytes
-    int has_bits[1];                               // 4 bytes
     int cached_size;                               // 4 bytes
     MockRepeatedPtrField data;                     // 24 bytes
+    // + 4 bytes padding
   };
   GOOGLE_CHECK_MESSAGE_SIZE(MockGenerated, 48);
   EXPECT_EQ(sizeof(protobuf_unittest::MoreString), sizeof(MockGenerated));
diff --git a/src/google/protobuf/compiler/cpp/metadata_test.cc b/src/google/protobuf/compiler/cpp/metadata_test.cc
index 1ffd357..2a51655 100644
--- a/src/google/protobuf/compiler/cpp/metadata_test.cc
+++ b/src/google/protobuf/compiler/cpp/metadata_test.cc
@@ -30,15 +30,15 @@
 
 #include <memory>
 
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/compiler/cpp/generator.h>
-#include <google/protobuf/compiler/command_line_interface.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/compiler/cpp/generator.h"
+#include "google/protobuf/compiler/command_line_interface.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/compiler/annotation_test_util.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include "google/protobuf/compiler/annotation_test_util.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/cpp/move_unittest.cc b/src/google/protobuf/compiler/cpp/move_unittest.cc
index eb7cd1c..07f0e1f 100644
--- a/src/google/protobuf/compiler/cpp/move_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/move_unittest.cc
@@ -28,10 +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 <google/protobuf/stubs/common.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/unittest.pb.h>
+#include "google/protobuf/stubs/common.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
 
 #if LANG_CXX11
 #include <type_traits>
diff --git a/src/google/protobuf/compiler/cpp/names.h b/src/google/protobuf/compiler/cpp/names.h
index 7404ac5..f4dac4c 100644
--- a/src/google/protobuf/compiler/cpp/names.h
+++ b/src/google/protobuf/compiler/cpp/names.h
@@ -34,7 +34,7 @@
 #include <string>
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -43,10 +43,23 @@
 class EnumDescriptor;
 class EnumValueDescriptor;
 class FieldDescriptor;
+class FileDescriptor;
 
 namespace compiler {
 namespace cpp {
 
+// Returns the fully qualified C++ namespace.
+//
+// For example, if you had:
+//   package foo.bar;
+//   message Baz { message Moo {} }
+// Then the qualified namespace for Moo would be:
+//   ::foo::bar
+std::string Namespace(const FileDescriptor* d);
+std::string Namespace(const Descriptor* d);
+std::string Namespace(const FieldDescriptor* d);
+std::string Namespace(const EnumDescriptor* d);
+
 // Returns the unqualified C++ name.
 //
 // For example, if you had:
@@ -92,6 +105,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CPP_NAMES_H__
diff --git a/src/google/protobuf/compiler/cpp/options.h b/src/google/protobuf/compiler/cpp/options.h
index 5d935e9..affaca3 100644
--- a/src/google/protobuf/compiler/cpp/options.h
+++ b/src/google/protobuf/compiler/cpp/options.h
@@ -33,13 +33,15 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_OPTIONS_H__
 
-#include <set>
 #include <string>
 
+#include "absl/container/flat_hash_set.h"
+
 namespace google {
 namespace protobuf {
 namespace compiler {
 class AccessInfoMap;
+class SplitMap;
 
 namespace cpp {
 
@@ -52,12 +54,13 @@
 
 struct FieldListenerOptions {
   bool inject_field_listener_events = false;
-  std::set<std::string> forbidden_field_listener_events;
+  absl::flat_hash_set<std::string> forbidden_field_listener_events;
 };
 
 // Generator options (see generator.cc for a description of each):
 struct Options {
   const AccessInfoMap* access_info_map = nullptr;
+  const SplitMap* split_map = nullptr;
   std::string dllexport_decl;
   std::string runtime_include_base;
   std::string annotation_pragma_name;
@@ -80,10 +83,10 @@
   bool annotate_accessor = false;
   bool unused_field_stripping = false;
   bool unverified_lazy_message_sets = false;
-  bool unverified_lazy = false;
   bool profile_driven_inline_string = true;
   bool message_owned_arena_trial = false;
   bool force_split = false;
+  bool profile_driven_split = true;
 #ifdef PROTOBUF_STABLE_EXPERIMENTS
   bool force_eagerly_verified_lazy = true;
   bool force_inline_string = true;
diff --git a/src/google/protobuf/compiler/cpp/padding_optimizer.cc b/src/google/protobuf/compiler/cpp/padding_optimizer.cc
index 2091052..d611c34 100644
--- a/src/google/protobuf/compiler/cpp/padding_optimizer.cc
+++ b/src/google/protobuf/compiler/cpp/padding_optimizer.cc
@@ -28,9 +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.
 
-#include <google/protobuf/compiler/cpp/padding_optimizer.h>
+#include "google/protobuf/compiler/cpp/padding_optimizer.h"
 
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include "google/protobuf/compiler/cpp/helpers.h"
 
 namespace google {
 namespace protobuf {
@@ -85,41 +85,11 @@
 
 }  // namespace
 
-// Reorder 'fields' so that if the fields are output into a c++ class in the new
-// order, fields of similar family (see below) are together and within each
-// family, alignment padding is minimized.
-//
-// We try to do this while keeping each field as close as possible to its field
-// number order so that we don't reduce cache locality much for function that
-// access each field in order.  Originally, OptimizePadding used declaration
-// order for its decisions, but generated code minus the serializer/parsers uses
-// the output of OptimizePadding as well (stored in
-// MessageGenerator::optimized_order_).  Since the serializers use field number
-// order, we use that as a tie-breaker.
-//
-// We classify each field into a particular "family" of fields, that we perform
-// the same operation on in our generated functions.
-//
-// REPEATED is placed first, as the C++ compiler automatically initializes
-// these fields in layout order.
-//
-// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
-// calls ArenaStringPtr::Destroy on each.
-//
-// LAZY_MESSAGE is grouped next, as it interferes with the ability to memset
-// non-repeated fields otherwise.
-//
-// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
-// delete on each.  We initialize these fields with a NULL pointer (see
-// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
-// memset.
-//
-// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
-//
-// OTHER these fields are initialized one-by-one.
-void PaddingOptimizer::OptimizeLayout(
-    std::vector<const FieldDescriptor*>* fields, const Options& options,
-    MessageSCCAnalyzer* scc_analyzer) {
+static void OptimizeLayoutHelper(std::vector<const FieldDescriptor*>* fields,
+                                 const Options& options,
+                                 MessageSCCAnalyzer* scc_analyzer) {
+  if (fields->empty()) return;
+
   // The sorted numeric order of Family determines the declaration order in the
   // memory layout.
   enum Family {
@@ -151,7 +121,7 @@
       if (IsLazy(field, options, scc_analyzer)) {
         f = LAZY_MESSAGE;
       }
-    } else if (CanInitializeByZeroing(field)) {
+    } else if (CanInitializeByZeroing(field, options, scc_analyzer)) {
       f = ZERO_INITIALIZABLE;
     }
 
@@ -222,6 +192,61 @@
   }
 }
 
+// Reorder 'fields' so that if the fields are output into a c++ class in the new
+// order, fields of similar family (see below) are together and within each
+// family, alignment padding is minimized.
+//
+// We try to do this while keeping each field as close as possible to its field
+// number order so that we don't reduce cache locality much for function that
+// access each field in order.  Originally, OptimizePadding used declaration
+// order for its decisions, but generated code minus the serializer/parsers uses
+// the output of OptimizePadding as well (stored in
+// MessageGenerator::optimized_order_).  Since the serializers use field number
+// order, we use that as a tie-breaker.
+//
+// We classify each field into a particular "family" of fields, that we perform
+// the same operation on in our generated functions.
+//
+// REPEATED is placed first, as the C++ compiler automatically initializes
+// these fields in layout order.
+//
+// STRING is grouped next, as our Clear/SharedCtor/SharedDtor walks it and
+// calls ArenaStringPtr::Destroy on each.
+//
+// LAZY_MESSAGE is grouped next, as it interferes with the ability to memset
+// non-repeated fields otherwise.
+//
+// MESSAGE is grouped next, as our Clear/SharedDtor code walks it and calls
+// delete on each.  We initialize these fields with a NULL pointer (see
+// MessageFieldGenerator::GenerateConstructorCode), which allows them to be
+// memset.
+//
+// ZERO_INITIALIZABLE is memset in Clear/SharedCtor
+//
+// OTHER these fields are initialized one-by-one.
+//
+// If there are split fields in `fields`, they will be placed at the end. The
+// order within split fields follows the same rule, aka classify and order by
+// "family".
+void PaddingOptimizer::OptimizeLayout(
+    std::vector<const FieldDescriptor*>* fields, const Options& options,
+    MessageSCCAnalyzer* scc_analyzer) {
+  std::vector<const FieldDescriptor*> normal;
+  std::vector<const FieldDescriptor*> split;
+  for (const auto* field : *fields) {
+    if (ShouldSplit(field, options)) {
+      split.push_back(field);
+    } else {
+      normal.push_back(field);
+    }
+  }
+  OptimizeLayoutHelper(&normal, options, scc_analyzer);
+  OptimizeLayoutHelper(&split, options, scc_analyzer);
+  fields->clear();
+  fields->insert(fields->end(), normal.begin(), normal.end());
+  fields->insert(fields->end(), split.begin(), split.end());
+}
+
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/padding_optimizer.h b/src/google/protobuf/compiler/cpp/padding_optimizer.h
index 9c76f38..4f55e64 100644
--- a/src/google/protobuf/compiler/cpp/padding_optimizer.h
+++ b/src/google/protobuf/compiler/cpp/padding_optimizer.h
@@ -35,7 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_PADDING_OPTIMIZER_H__
 
-#include <google/protobuf/compiler/cpp/message_layout_helper.h>
+#include "google/protobuf/compiler/cpp/message_layout_helper.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/cpp/parse_function_generator.cc b/src/google/protobuf/compiler/cpp/parse_function_generator.cc
index 0f1d767..a057570 100644
--- a/src/google/protobuf/compiler/cpp/parse_function_generator.cc
+++ b/src/google/protobuf/compiler/cpp/parse_function_generator.cc
@@ -28,15 +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.
 
-#include <google/protobuf/compiler/cpp/parse_function_generator.h>
+#include "google/protobuf/compiler/cpp/parse_function_generator.h"
 
 #include <algorithm>
 #include <limits>
 #include <string>
 #include <utility>
+#include <vector>
 
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/generated_message_tctable_gen.h"
+#include "google/protobuf/generated_message_tctable_impl.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -44,9 +49,21 @@
 namespace cpp {
 
 namespace {
+using internal::TailCallTableInfo;
+using internal::cpp::Utf8CheckMode;
 using google::protobuf::internal::WireFormat;
 using google::protobuf::internal::WireFormatLite;
 
+bool UseDirectTcParserTable(const FieldDescriptor* field,
+                            const Options& options) {
+  if (field->cpp_type() != field->CPPTYPE_MESSAGE) return false;
+  auto* m = field->message_type();
+  return !m->options().message_set_wire_format() &&
+         m->file()->options().optimize_for() != FileOptions::CODE_SIZE &&
+         !HasSimpleBaseClass(m, options) && !HasTracker(m, options)
+      ;  // NOLINT(whitespace/semicolon)
+}
+
 std::vector<const FieldDescriptor*> GetOrderedFields(
     const Descriptor* descriptor, const Options& options) {
   std::vector<const FieldDescriptor*> ordered_fields;
@@ -66,371 +83,40 @@
   return ctype == FieldOptions::STRING || ctype == FieldOptions::CORD;
 }
 
-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;
-}
-
-std::string FieldParseFunctionName(
-    const TailCallTableInfo::FieldEntryInfo& entry, const Options& options);
-
-bool IsFieldEligibleForFastParsing(
-    const TailCallTableInfo::FieldEntryInfo& entry, const Options& options,
-    MessageSCCAnalyzer* scc_analyzer) {
-  const auto* field = entry.field;
-  // Map, oneof, weak, and lazy fields are not handled on the fast path.
-  if (field->is_map() || field->real_containing_oneof() ||
-      field->options().weak() ||
-      IsImplicitWeakField(field, options, scc_analyzer) ||
-      IsLazy(field, options, scc_analyzer)) {
-    return false;
-  }
-
-  // We will check for a valid auxiliary index range later. However, we might
-  // want to change the value we check for inlined string fields.
-  int aux_idx = entry.aux_idx;
-
-  switch (field->type()) {
-    case FieldDescriptor::TYPE_ENUM:
-      // If enum values are not validated at parse time, then this field can be
-      // handled on the fast path like an int32.
-      if (HasPreservingUnknownEnumSemantics(field)) {
-        break;
-      }
-      if (field->is_repeated() && field->is_packed()) {
-        return false;
-      }
-      break;
-
-      // Some bytes fields can be handled on fast path.
-    case FieldDescriptor::TYPE_STRING:
-    case FieldDescriptor::TYPE_BYTES:
-      if (field->options().ctype() != FieldOptions::STRING) {
-        return false;
-      }
-      if (IsStringInlined(field, options)) {
-        GOOGLE_CHECK(!field->is_repeated());
-        // For inlined strings, the donation state index is stored in the
-        // `aux_idx` field of the fast parsing info. We need to check the range
-        // of that value instead of the auxiliary index.
-        aux_idx = entry.inlined_string_idx;
-      }
-      break;
-
-    default:
-      break;
-  }
-
-  if (HasHasbit(field)) {
-    // The tailcall parser can only update the first 32 hasbits. Fields with
-    // has-bits beyond the first 32 are handled by mini parsing/fallback.
-    GOOGLE_CHECK_GE(entry.hasbit_idx, 0) << field->DebugString();
-    if (entry.hasbit_idx >= 32) return false;
-  }
-
-  // If the field needs auxiliary data, then the aux index is needed. This
-  // must fit in a uint8_t.
-  if (aux_idx > std::numeric_limits<uint8_t>::max()) {
-    return false;
-  }
-
-  // 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
-  //    ^^^^^^^  ^^^^^^^
-  if (field->number() >= 1 << 11) return false;
-
-  return true;
-}
-
-std::vector<TailCallTableInfo::FastFieldInfo> SplitFastFieldsForSize(
-    const std::vector<TailCallTableInfo::FieldEntryInfo>& field_entries,
-    int table_size_log2, const Options& options,
-    MessageSCCAnalyzer* scc_analyzer) {
-  std::vector<TailCallTableInfo::FastFieldInfo> result(1 << table_size_log2);
-  const uint32_t idx_mask = result.size() - 1;
-
-  for (const auto& entry : field_entries) {
-    if (!IsFieldEligibleForFastParsing(entry, options, scc_analyzer)) {
-      continue;
-    }
-
-    const auto* field = entry.field;
-    uint32_t tag = WireFormat::MakeTag(field);
-
-    // Construct the varint-coded tag. If it is more than 7 bits, we need to
-    // shift the high bits and add a continue bit.
-    if (uint32_t hibits = tag & 0xFFFFFF80) {
-      tag = tag + hibits + 128;  // tag = lobits + 2*hibits + 128
-    }
-
-    // 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
-    //   tag: 1nnnnttt 0nnnnnnn
-    //        ^^^^^
-    //         idx (table_size_log2=5)
-    // 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.
-    const uint32_t fast_idx = (tag >> 3) & idx_mask;
-
-    TailCallTableInfo::FastFieldInfo& info = result[fast_idx];
-    if (info.field != nullptr) {
-      // This field entry is already filled.
-      continue;
-    }
-
-    // Fill in this field's entry:
-    GOOGLE_CHECK(info.func_name.empty()) << info.func_name;
-    info.func_name = FieldParseFunctionName(entry, options);
-    info.field = field;
-    info.coded_tag = tag;
-    // If this field does not have presence, then it can set an out-of-bounds
-    // bit (tailcall parsing uses a uint64_t for hasbits, but only stores 32).
-    info.hasbit_idx = HasHasbit(field) ? entry.hasbit_idx : 63;
-    if (IsStringInlined(field, options)) {
-      GOOGLE_CHECK(!field->is_repeated());
-      info.aux_idx = static_cast<uint8_t>(entry.inlined_string_idx);
-    } else {
-      info.aux_idx = static_cast<uint8_t>(entry.aux_idx);
-    }
-  }
-  return result;
-}
-
-// Filter out fields that will be handled by mini parsing.
-std::vector<const FieldDescriptor*> FilterMiniParsedFields(
-    const std::vector<const FieldDescriptor*>& fields, const Options& options,
-    MessageSCCAnalyzer* scc_analyzer) {
-  std::vector<const FieldDescriptor*> generated_fallback_fields;
-
-  for (const auto* field : fields) {
-    bool handled = false;
-    switch (field->type()) {
-      case FieldDescriptor::TYPE_DOUBLE:
-      case FieldDescriptor::TYPE_FLOAT:
-      case FieldDescriptor::TYPE_FIXED32:
-      case FieldDescriptor::TYPE_SFIXED32:
-      case FieldDescriptor::TYPE_FIXED64:
-      case FieldDescriptor::TYPE_SFIXED64:
-      case FieldDescriptor::TYPE_BOOL:
-      case FieldDescriptor::TYPE_UINT32:
-      case FieldDescriptor::TYPE_SINT32:
-      case FieldDescriptor::TYPE_INT32:
-      case FieldDescriptor::TYPE_UINT64:
-      case FieldDescriptor::TYPE_SINT64:
-      case FieldDescriptor::TYPE_INT64:
-        // These are handled by MiniParse, so we don't need any generated
-        // fallback code.
-        handled = true;
-        break;
-
-      case FieldDescriptor::TYPE_ENUM:
-        if (field->is_repeated() && !HasPreservingUnknownEnumSemantics(field)) {
-          // TODO(b/206890171): handle packed repeated closed enums
-          // Non-packed repeated can be handled using tables, but we still
-          // need to generate fallback code for all repeated enums in order to
-          // handle packed encoding. This is because of the lite/full split
-          // when handling invalid enum values in a packed field.
-          handled = false;
-        } else {
-          handled = true;
-        }
-        break;
-
-      case FieldDescriptor::TYPE_BYTES:
-      case FieldDescriptor::TYPE_STRING:
-        if (IsStringInlined(field, options)) {
-          // TODO(b/198211897): support InilnedStringField.
-          handled = false;
-        } else {
-          handled = true;
-        }
-        break;
-
-      case FieldDescriptor::TYPE_MESSAGE:
-      case FieldDescriptor::TYPE_GROUP:
-        // TODO(b/210762816): support remaining field types.
-        if (field->is_map() || IsWeak(field, options) ||
-            IsImplicitWeakField(field, options, scc_analyzer) ||
-            IsLazy(field, options, scc_analyzer)) {
-          handled = false;
-        } else {
-          handled = true;
-        }
-        break;
-
-      default:
-        handled = false;
-        break;
-    }
-    if (!handled) generated_fallback_fields.push_back(field);
-  }
-
-  return generated_fallback_fields;
-}
-
 }  // namespace
 
-TailCallTableInfo::TailCallTableInfo(
-    const Descriptor* descriptor, const Options& options,
-    const std::vector<const FieldDescriptor*>& ordered_fields,
-    const std::vector<int>& has_bit_indices,
-    const std::vector<int>& inlined_string_indices,
-    MessageSCCAnalyzer* scc_analyzer) {
-  int oneof_count = descriptor->real_oneof_decl_count();
-  // If this message has any oneof fields, store the case offset in the first
-  // auxiliary entry.
-  if (oneof_count > 0) {
-    GOOGLE_LOG_IF(DFATAL, ordered_fields.empty())
-        << "Invalid message: " << descriptor->full_name() << " has "
-        << oneof_count << " oneof declarations, but no fields";
-    aux_entries.push_back(StrCat("_fl::Offset{offsetof(",
-                                       ClassName(descriptor),
-                                       ", _impl_._oneof_case_)}"));
+class ParseFunctionGenerator::GeneratedOptionProvider final
+    : public internal::TailCallTableInfo::OptionProvider {
+ public:
+  explicit GeneratedOptionProvider(ParseFunctionGenerator* gen) : gen_(gen) {}
+  TailCallTableInfo::PerFieldOptions GetForField(
+      const FieldDescriptor* field) const final {
+    const auto verify_flag = [&] {
+      if (IsEagerlyVerifiedLazy(field, gen_->options_, gen_->scc_analyzer_))
+        return internal::field_layout::kTvEager;
+      if (IsLazilyVerifiedLazy(field, gen_->options_))
+        return internal::field_layout::kTvLazy;
+      return internal::field_layout::TransformValidation{};
+    };
+    return {verify_flag(),
+            IsStringInlined(field, gen_->options_),
+            IsImplicitWeakField(field, gen_->options_, gen_->scc_analyzer_),
+            UseDirectTcParserTable(field, gen_->options_),
+            GetOptimizeFor(field->file(), gen_->options_) ==
+                FileOptions::LITE_RUNTIME,
+            ShouldSplit(field, gen_->options_)};
   }
 
-  // If this message has any inlined string fields, store the donation state
-  // offset in the second auxiliary entry.
-  if (!inlined_string_indices.empty()) {
-    aux_entries.resize(2);  // pad if necessary
-    aux_entries[1] =
-        StrCat("_fl::Offset{offsetof(", ClassName(descriptor),
-                     ", _impl_._inlined_string_donated_)}");
-  }
-
-  // Fill in mini table entries.
-  for (const FieldDescriptor* field : ordered_fields) {
-    field_entries.push_back(
-        {field, (HasHasbit(field) ? has_bit_indices[field->index()] : -1)});
-    auto& entry = field_entries.back();
-
-    if (field->type() == FieldDescriptor::TYPE_MESSAGE ||
-        field->type() == FieldDescriptor::TYPE_GROUP) {
-      // Message-typed fields have a FieldAux with the default instance pointer.
-      if (field->is_map()) {
-        // TODO(b/205904770): generate aux entries for maps
-      } else if (IsWeak(field, options)) {
-        // Don't generate anything for weak fields. They are handled by the
-        // generated fallback.
-      } else if (IsImplicitWeakField(field, options, scc_analyzer)) {
-        // Implicit weak fields don't need to store a default instance pointer.
-      } else if (IsLazy(field, options, scc_analyzer)) {
-        // Lazy fields are handled by the generated fallback function.
-      } else {
-        field_entries.back().aux_idx = aux_entries.size();
-        const Descriptor* field_type = field->message_type();
-        aux_entries.push_back(StrCat(
-            "reinterpret_cast<const ", QualifiedClassName(field_type, options),
-            "*>(&", QualifiedDefaultInstanceName(field_type, options), ")"));
-      }
-    } else if (field->type() == FieldDescriptor::TYPE_ENUM &&
-               !HasPreservingUnknownEnumSemantics(field)) {
-      // Enum fields which preserve unknown values (proto3 behavior) are
-      // effectively int32 fields with respect to parsing -- i.e., the value
-      // does not need to be validated at parse time.
-      //
-      // Enum fields which do not preserve unknown values (proto2 behavior) use
-      // a FieldAux to store validation information. If the enum values are
-      // sequential (and within a range we can represent), then the FieldAux
-      // entry represents the range using the minimum value (which must fit in
-      // an int16_t) and count (a uint16_t). Otherwise, the entry holds a
-      // pointer to the generated Name_IsValid function.
-
-      entry.aux_idx = aux_entries.size();
-      const EnumDescriptor* enum_type = field->enum_type();
-      GOOGLE_CHECK_GT(enum_type->value_count(), 0) << enum_type->DebugString();
-
-      // Check if the enum values are a single, contiguous range.
-      std::vector<int> enum_values;
-      for (int i = 0, N = enum_type->value_count(); i < N; ++i) {
-        enum_values.push_back(enum_type->value(i)->number());
-      }
-      auto values_begin = enum_values.begin();
-      auto values_end = enum_values.end();
-      std::sort(values_begin, values_end);
-      enum_values.erase(std::unique(values_begin, values_end), values_end);
-
-      if (enum_values.back() - enum_values[0] == enum_values.size() - 1 &&
-          enum_values[0] >= std::numeric_limits<int16_t>::min() &&
-          enum_values[0] <= std::numeric_limits<int16_t>::max() &&
-          enum_values.size() <= std::numeric_limits<uint16_t>::max()) {
-        entry.is_enum_range = true;
-        aux_entries.push_back(
-            StrCat(enum_values[0], ", ", enum_values.size()));
-      } else {
-        entry.is_enum_range = false;
-        aux_entries.push_back(
-            StrCat(QualifiedClassName(enum_type, options), "_IsValid"));
-      }
-    } else if ((field->type() == FieldDescriptor::TYPE_STRING ||
-                field->type() == FieldDescriptor::TYPE_BYTES) &&
-               IsStringInlined(field, options)) {
-      GOOGLE_CHECK(!field->is_repeated());
-      // Inlined strings have an extra marker to represent their donation state.
-      int idx = inlined_string_indices[field->index()];
-      // For mini parsing, the donation state index is stored as an `offset`
-      // auxiliary entry.
-      entry.aux_idx = aux_entries.size();
-      aux_entries.push_back(StrCat("_fl::Offset{", idx, "}"));
-      // For fast table parsing, the donation state index is stored instead of
-      // the aux_idx (this will limit the range to 8 bits).
-      entry.inlined_string_idx = idx;
-    }
-  }
-
-  // Choose the smallest fast table that covers the maximum number of fields.
-  table_size_log2 = 0;  // fallback value
-  int num_fast_fields = -1;
-  for (int try_size_log2 : {0, 1, 2, 3, 4, 5}) {
-    size_t try_size = 1 << try_size_log2;
-    auto split_fields = SplitFastFieldsForSize(field_entries, try_size_log2,
-                                               options, scc_analyzer);
-    GOOGLE_CHECK_EQ(split_fields.size(), try_size);
-    int try_num_fast_fields = 0;
-    for (const auto& info : split_fields) {
-      if (info.field != nullptr) ++try_num_fast_fields;
-    }
-    // Use this size if (and only if) it covers more fields.
-    if (try_num_fast_fields > num_fast_fields) {
-      fast_path_fields = std::move(split_fields);
-      table_size_log2 = try_size_log2;
-      num_fast_fields = try_num_fast_fields;
-    }
-    // The largest table we allow has the same number of entries as the message
-    // has fields, rounded up to the next power of 2 (e.g., a message with 5
-    // fields can have a fast table of size 8). A larger table *might* cover
-    // more fields in certain cases, but a larger table in that case would have
-    // mostly empty entries; so, we cap the size to avoid pathologically sparse
-    // tables.
-    if (try_size > ordered_fields.size()) {
-      break;
-    }
-  }
-
-  // Filter out fields that are handled by MiniParse. We don't need to generate
-  // a fallback for these, which saves code size.
-  fallback_fields = FilterMiniParsedFields(ordered_fields, options,
-                                           scc_analyzer);
-
-  // 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;
-}
+ private:
+  ParseFunctionGenerator* gen_;
+};
 
 ParseFunctionGenerator::ParseFunctionGenerator(
     const Descriptor* descriptor, int max_has_bit_index,
     const std::vector<int>& has_bit_indices,
     const std::vector<int>& inlined_string_indices, const Options& options,
     MessageSCCAnalyzer* scc_analyzer,
-    const std::map<std::string, std::string>& vars)
+    const absl::flat_hash_map<absl::string_view, std::string>& vars)
     : descriptor_(descriptor),
       scc_analyzer_(scc_analyzer),
       options_(options),
@@ -440,10 +126,9 @@
       num_hasbits_(max_has_bit_index) {
   if (should_generate_tctable()) {
     tc_table_info_.reset(new TailCallTableInfo(
-        descriptor_, options_, ordered_fields_, has_bit_indices,
-        inlined_string_indices, scc_analyzer));
+        descriptor_, ordered_fields_, GeneratedOptionProvider(this),
+        has_bit_indices, inlined_string_indices));
   }
-  SetCommonVars(options_, &variables_);
   SetCommonMessageDataVariables(descriptor_, &variables_);
   SetUnknownFieldsVariable(descriptor_, options_, &variables_);
   variables_["classname"] = ClassName(descriptor, false);
@@ -518,6 +203,9 @@
   if (options_.tctable_mode == Options::kTCTableNever) {
     return false;
   }
+  if (HasSimpleBaseClass(descriptor_, options_)) {
+    return false;
+  }
   return true;
 }
 
@@ -536,6 +224,17 @@
       "}\n\n");
 }
 
+static bool NeedsUnknownEnumSupport(const Descriptor* descriptor) {
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    auto* field = descriptor->field(i);
+    if (field->is_repeated() && field->cpp_type() == field->CPPTYPE_ENUM &&
+        !internal::cpp::HasPreservingUnknownEnumSemantics(field)) {
+      return true;
+    }
+  }
+  return false;
+}
+
 void ParseFunctionGenerator::GenerateTailcallFallbackFunction(
     Formatter& format) {
   GOOGLE_CHECK(should_generate_tctable());
@@ -545,11 +244,27 @@
   format.Indent();
   format("auto* typed_msg = static_cast<$classname$*>(msg);\n");
 
+  // If we need a side channel, generate the check to jump to the generic
+  // handler to deal with the side channel data.
+  if (NeedsUnknownEnumSupport(descriptor_)) {
+    format(
+        "if (PROTOBUF_PREDICT_FALSE(\n"
+        "    _pbi::TcParser::MustFallbackToGeneric(PROTOBUF_TC_PARAM_PASS))) "
+        "{\n"
+        "  PROTOBUF_MUSTTAIL return "
+        "::_pbi::TcParser::GenericFallback$1$(PROTOBUF_TC_PARAM_PASS);\n"
+        "}\n",
+        GetOptimizeFor(descriptor_->file(), options_) ==
+                FileOptions::LITE_RUNTIME
+            ? "Lite"
+            : "");
+  }
+
   if (num_hasbits_ > 0) {
     // Sync hasbits
-    format("typed_msg->_impl_._has_bits_[0] = hasbits;\n");
+    format("typed_msg->_impl_._has_bits_[0] |= hasbits;\n");
   }
-  format("uint32_t tag = data.tag();\n");
+  format("::uint32_t tag = data.tag();\n");
 
   format.Set("msg", "typed_msg->");
   format.Set("this", "typed_msg");
@@ -592,6 +307,12 @@
 static NumToEntryTable MakeNumToEntryTable(
     const std::vector<const FieldDescriptor*>& field_descriptors);
 
+static int FieldNameDataSize(const std::vector<uint8_t>& data) {
+  // We add a +1 here to allow for a NUL termination character. It makes the
+  // codegen nicer.
+  return data.empty() ? 0 : data.size() + 1;
+}
+
 void ParseFunctionGenerator::GenerateDataDecls(io::Printer* printer) {
   if (!should_generate_tctable()) {
     return;
@@ -604,10 +325,12 @@
   }
   auto field_num_to_entry_table = MakeNumToEntryTable(ordered_fields_);
   format(
+      "friend class ::$proto_ns$::internal::TcParser;\n"
       "static const ::$proto_ns$::internal::"
       "TcParseTable<$1$, $2$, $3$, $4$, $5$> _table_;\n",
       tc_table_info_->table_size_log2, ordered_fields_.size(),
-      tc_table_info_->aux_entries.size(), CalculateFieldNamesSize(),
+      tc_table_info_->aux_entries.size(),
+      FieldNameDataSize(tc_table_info_->field_name_data),
       field_num_to_entry_table.size16());
   if (should_generate_guarded_tctable()) {
     format.Outdent();
@@ -656,7 +379,7 @@
   format.Indent();
 
   format(
-      "uint32_t tag;\n"
+      "::uint32_t tag;\n"
       "ptr = ::_pbi::ReadTag(ptr, &tag);\n");
   GenerateParseIterationBody(format, descriptor_, ordered_fields_);
 
@@ -761,12 +484,13 @@
   // unknown fields and potentially an extension range.
   auto field_num_to_entry_table = MakeNumToEntryTable(ordered_fields_);
   format(
-      "PROTOBUF_ATTRIBUTE_INIT_PRIORITY1\n"
+      "PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1\n"
       "const ::_pbi::TcParseTable<$1$, $2$, $3$, $4$, $5$> "
       "$classname$::_table_ = "
       "{\n",
       tc_table_info_->table_size_log2, ordered_fields_.size(),
-      tc_table_info_->aux_entries.size(), CalculateFieldNamesSize(),
+      tc_table_info_->aux_entries.size(),
+      FieldNameDataSize(tc_table_info_->field_name_data),
       field_num_to_entry_table.size16());
   {
     auto table_scope = format.ScopedIndent();
@@ -874,19 +598,71 @@
         {
           // aux_entries[]
           auto aux_scope = format.ScopedIndent();
-          for (const std::string& aux_entry : tc_table_info_->aux_entries) {
-            format("{$1$},\n", aux_entry);
+          for (const auto& aux_entry : tc_table_info_->aux_entries) {
+            switch (aux_entry.type) {
+              case TailCallTableInfo::kNothing:
+                format("{},\n");
+                break;
+              case TailCallTableInfo::kInlinedStringDonatedOffset:
+                format(
+                    "{_fl::Offset{offsetof($classname$, "
+                    "_impl_._inlined_string_donated_)}},\n");
+                break;
+              case TailCallTableInfo::kSplitOffset:
+                format(
+                    "{_fl::Offset{offsetof($classname$, _impl_._split_)}},\n");
+                break;
+              case TailCallTableInfo::kSplitSizeof:
+                format("{_fl::Offset{sizeof($classname$::Impl_::Split)}},\n");
+                break;
+              case TailCallTableInfo::kSubMessage:
+                format("{::_pbi::FieldAuxDefaultMessage{}, &$1$},\n",
+                       QualifiedDefaultInstanceName(
+                           aux_entry.field->message_type(), options_));
+                break;
+              case TailCallTableInfo::kSubTable:
+                format("{::_pbi::TcParser::GetTable<$1$>()},\n",
+                       QualifiedClassName(aux_entry.field->message_type(),
+                                          options_));
+                break;
+              case TailCallTableInfo::kSubMessageWeak:
+                format("{::_pbi::FieldAuxDefaultMessage{}, &$1$},\n",
+                       QualifiedDefaultInstancePtr(
+                           aux_entry.field->message_type(), options_));
+                break;
+              case TailCallTableInfo::kMessageVerifyFunc:
+                if (aux_entry.field != nullptr) {
+                  format("{$1$::InternalVerify},\n",
+                         QualifiedClassName(aux_entry.field->message_type(),
+                                            options_));
+                } else {
+                  format("{},\n");
+                }
+                break;
+              case TailCallTableInfo::kEnumRange:
+                format("{$1$, $2$},\n", aux_entry.enum_range.start,
+                       aux_entry.enum_range.size);
+                break;
+              case TailCallTableInfo::kEnumValidator:
+                format(
+                    "{$1$_IsValid},\n",
+                    QualifiedClassName(aux_entry.field->enum_type(), options_));
+                break;
+              case TailCallTableInfo::kNumericOffset:
+                format("{_fl::Offset{$1$}},\n", aux_entry.offset);
+                break;
+            }
           }
         }
         format("}}, {{\n");
       }
     }  // ordered_fields_.empty()
-    {
-      // field_names[]
-      auto field_name_scope = format.ScopedIndent();
-      GenerateFieldNames(format);
-    }
-    format("}},\n");
+      {
+        // field_names[]
+        auto field_name_scope = format.ScopedIndent();
+        GenerateFieldNames(format);
+      }
+      format("}},\n");
   }
   format("};\n\n");  // _table_
 }
@@ -898,145 +674,174 @@
     }
     if (info.func_name.empty()) {
       format("{::_pbi::TcParser::MiniParse, {}},\n");
+    } else if (info.field == nullptr) {
+      // Fast slot that is not associated with a field. Eg end group tags.
+      format("{$1$, {$2$, $3$}},\n", info.func_name, info.coded_tag,
+             info.nonfield_info);
     } else {
-      bool cold = ShouldSplit(info.field, options_);
+      GOOGLE_CHECK(!ShouldSplit(info.field, options_));
+
+      std::string func_name = info.func_name;
+      if (GetOptimizeFor(info.field->file(), options_) == FileOptions::SPEED) {
+        // For 1-byte tags we have a more optimized version of the varint parser
+        // that can hardcode the offset and has bit.
+        if (absl::EndsWith(func_name, "V8S1") ||
+            absl::EndsWith(func_name, "V32S1") ||
+            absl::EndsWith(func_name, "V64S1")) {
+          std::string field_type = absl::EndsWith(func_name, "V8S1") ? "bool"
+                                   : absl::EndsWith(func_name, "V32S1")
+                                       ? "::uint32_t"
+                                       : "::uint64_t";
+          func_name = absl::StrCat(
+              "::_pbi::TcParser::SingularVarintNoZag1<", field_type,
+              ", offsetof(",                                 //
+              ClassName(info.field->containing_type()),      //
+              ", ",                                          //
+              FieldMemberName(info.field, /*split=*/false),  //
+              "), ",                                         //
+              info.hasbit_idx,                               //
+              ">()");
+        }
+      }
+
       format(
           "{$1$,\n"
-          " {$2$, $3$, $4$, PROTOBUF_FIELD_OFFSET($classname$$5$, $6$)}},\n",
-          info.func_name, info.coded_tag, info.hasbit_idx, info.aux_idx,
-          cold ? "::Impl_::Split" : "",
-          cold ? FieldName(info.field) + "_"
-               : FieldMemberName(info.field, /*cold=*/false));
+          " {$2$, $3$, $4$, PROTOBUF_FIELD_OFFSET($classname$, $5$)}},\n",
+          func_name, info.coded_tag, info.hasbit_idx, info.aux_idx,
+          FieldMemberName(info.field, /*split=*/false));
     }
   }
 }
 
 static void FormatFieldKind(Formatter& format,
-                            const TailCallTableInfo::FieldEntryInfo& entry,
-                            const Options& options,
-                            MessageSCCAnalyzer* scc_analyzer) {
-  const FieldDescriptor* field = entry.field;
-  // Spell the field kind in proto language declaration order, starting with
-  // cardinality:
-  format("(::_fl::kFc");
-  if (HasHasbit(field)) {
-    format("Optional");
-  } else if (field->is_repeated()) {
-    format("Repeated");
-  } else if (field->real_containing_oneof()) {
-    format("Oneof");
-  } else {
-    format("Singular");
-  }
+                            const TailCallTableInfo::FieldEntryInfo& entry) {
+  // In here we convert the runtime value of entry.type_card back into a
+  // sequence of literal enum labels. We use the mnenonic labels for nicer
+  // codegen.
+  namespace fl = internal::field_layout;
+  const uint16_t type_card = entry.type_card;
+  const int rep_index = (type_card & fl::kRepMask) >> fl::kRepShift;
+  const int tv_index = (type_card & fl::kTvMask) >> fl::kTvShift;
 
-  // The rest of the type uses convenience aliases:
-  format(" | ::_fl::k");
-  if (field->is_repeated() && field->is_packed()) {
-    format("Packed");
-  }
-  switch (field->type()) {
-    case FieldDescriptor::TYPE_DOUBLE:
-      format("Double");
-      break;
-    case FieldDescriptor::TYPE_FLOAT:
-      format("Float");
-      break;
-    case FieldDescriptor::TYPE_FIXED32:
-      format("Fixed32");
-      break;
-    case FieldDescriptor::TYPE_SFIXED32:
-      format("SFixed32");
-      break;
-    case FieldDescriptor::TYPE_FIXED64:
-      format("Fixed64");
-      break;
-    case FieldDescriptor::TYPE_SFIXED64:
-      format("SFixed64");
-      break;
-    case FieldDescriptor::TYPE_BOOL:
-      format("Bool");
-      break;
-    case FieldDescriptor::TYPE_ENUM:
-      if (HasPreservingUnknownEnumSemantics(field)) {
-        // No validation is required.
-        format("OpenEnum");
-      } else if (entry.is_enum_range) {
-        // Validation is done by range check (start/length in FieldAux).
-        format("EnumRange");
-      } else {
-        // Validation uses the generated _IsValid function.
-        format("Enum");
-      }
-      break;
-    case FieldDescriptor::TYPE_UINT32:
-      format("UInt32");
-      break;
-    case FieldDescriptor::TYPE_SINT32:
-      format("SInt32");
-      break;
-    case FieldDescriptor::TYPE_INT32:
-      format("Int32");
-      break;
-    case FieldDescriptor::TYPE_UINT64:
-      format("UInt64");
-      break;
-    case FieldDescriptor::TYPE_SINT64:
-      format("SInt64");
-      break;
-    case FieldDescriptor::TYPE_INT64:
-      format("Int64");
-      break;
+  format("(");
+  static constexpr const char* kFieldCardNames[] = {"Singular", "Optional",
+                                                    "Repeated", "Oneof"};
+  static_assert((fl::kFcSingular >> fl::kFcShift) == 0, "");
+  static_assert((fl::kFcOptional >> fl::kFcShift) == 1, "");
+  static_assert((fl::kFcRepeated >> fl::kFcShift) == 2, "");
+  static_assert((fl::kFcOneof >> fl::kFcShift) == 3, "");
 
-    case FieldDescriptor::TYPE_BYTES:
-      format("Bytes");
-      break;
-    case FieldDescriptor::TYPE_STRING: {
-      auto mode = GetUtf8CheckMode(field, options);
-      switch (mode) {
-        case Utf8CheckMode::kStrict:
-          format("Utf8String");
-          break;
-        case Utf8CheckMode::kVerify:
-          format("RawString");
-          break;
-        case Utf8CheckMode::kNone:
-          // Treat LITE_RUNTIME strings as bytes.
-          format("Bytes");
-          break;
+  format("::_fl::kFc$1$",
+         kFieldCardNames[(type_card & fl::kFcMask) >> fl::kFcShift]);
+
+#define PROTOBUF_INTERNAL_TYPE_CARD_CASE(x) \
+  case fl::k##x:                            \
+    format(" | ::_fl::k" #x);               \
+    break
+
+  switch (type_card & fl::kFkMask) {
+    case fl::kFkString: {
+      switch (type_card & ~fl::kFcMask & ~fl::kRepMask & ~fl::kSplitMask) {
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bytes);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(RawString);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Utf8String);
         default:
-          GOOGLE_LOG(FATAL) << "Invalid Utf8CheckMode (" << static_cast<int>(mode)
-                     << ") for " << field->DebugString();
+          GOOGLE_LOG(FATAL) << "Unknown type_card: 0x" << type_card;
+      }
+
+      static constexpr const char* kRepNames[] = {"AString", "IString", "Cord",
+                                                  "SPiece", "SString"};
+      static_assert((fl::kRepAString >> fl::kRepShift) == 0, "");
+      static_assert((fl::kRepIString >> fl::kRepShift) == 1, "");
+      static_assert((fl::kRepCord >> fl::kRepShift) == 2, "");
+      static_assert((fl::kRepSPiece >> fl::kRepShift) == 3, "");
+      static_assert((fl::kRepSString >> fl::kRepShift) == 4, "");
+
+      format(" | ::_fl::kRep$1$", kRepNames[rep_index]);
+      break;
+    }
+
+    case fl::kFkMessage: {
+      format(" | ::_fl::kMessage");
+
+      static constexpr const char* kRepNames[] = {nullptr, "Group", "Lazy"};
+      static_assert((fl::kRepGroup >> fl::kRepShift) == 1, "");
+      static_assert((fl::kRepLazy >> fl::kRepShift) == 2, "");
+
+      if (auto* rep = kRepNames[rep_index]) {
+        format(" | ::_fl::kRep$1$", rep);
+      }
+
+      static constexpr const char* kXFormNames[2][4] = {
+          {nullptr, "Default", "Table", "WeakPtr"}, {nullptr, "Eager", "Lazy"}};
+      static_assert((fl::kTvDefault >> fl::kTvShift) == 1, "");
+      static_assert((fl::kTvTable >> fl::kTvShift) == 2, "");
+      static_assert((fl::kTvWeakPtr >> fl::kTvShift) == 3, "");
+      static_assert((fl::kTvEager >> fl::kTvShift) == 1, "");
+      static_assert((fl::kTvLazy >> fl::kTvShift) == 2, "");
+
+      if (auto* xform = kXFormNames[rep_index == 2][tv_index]) {
+        format(" | ::_fl::kTv$1$", xform);
       }
       break;
     }
 
-    case FieldDescriptor::TYPE_GROUP:
-      format("Message | ::_fl::kRepGroup");
+    case fl::kFkMap:
+      format(" | ::_fl::kMap");
       break;
-    case FieldDescriptor::TYPE_MESSAGE:
-      if (field->is_map()) {
-        format("Map");
-      } else {
-        format("Message");
-        if (IsLazy(field, options, scc_analyzer)) {
-          format(" | ::_fl::kRepLazy");
-        } else if (IsImplicitWeakField(field, options, scc_analyzer)) {
-          format(" | ::_fl::kRepIWeak");
-        }
-      }
-      break;
-  }
 
-  // Fill in extra information about string and bytes field representations.
-  if (field->type() == FieldDescriptor::TYPE_BYTES ||
-      field->type() == FieldDescriptor::TYPE_STRING) {
-    if (field->is_repeated()) {
-      format(" | ::_fl::kRepSString");
-    } else {
-      format(" | ::_fl::kRepAString");
+    case fl::kFkNone:
+      break;
+
+    case fl::kFkVarint:
+    case fl::kFkPackedVarint:
+    case fl::kFkFixed:
+    case fl::kFkPackedFixed: {
+      switch (type_card & ~fl::kFcMask & ~fl::kSplitMask) {
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Bool);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Float);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Enum);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(EnumRange);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(OpenEnum);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Fixed64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(UInt64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(SFixed64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Int64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(SInt64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(Double);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedBool);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt32);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFloat);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnum);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedEnumRange);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedOpenEnum);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedFixed64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedUInt64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSFixed64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedInt64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedSInt64);
+        PROTOBUF_INTERNAL_TYPE_CARD_CASE(PackedDouble);
+        default:
+          GOOGLE_LOG(FATAL) << "Unknown type_card: 0x" << type_card;
+      }
     }
   }
 
+  if (type_card & fl::kSplitMask) {
+    format(" | ::_fl::kSplitTrue");
+  }
+
+#undef PROTOBUF_INTERNAL_TYPE_CARD_CASE
+
   format(")");
 }
 
@@ -1051,78 +856,68 @@
       format("/* weak */ 0, 0, 0, 0");
     } else {
       const OneofDescriptor* oneof = field->real_containing_oneof();
-      bool cold = ShouldSplit(field, options_);
-      format("PROTOBUF_FIELD_OFFSET($classname$$1$, $2$), $3$, $4$,\n ",
-             cold ? "::Impl_::Split" : "",
-             cold ? FieldName(field) + "_"
-                  : FieldMemberName(field, /*cold=*/false),
-             (oneof ? oneof->index() : entry.hasbit_idx), entry.aux_idx);
-      FormatFieldKind(format, entry, options_, scc_analyzer_);
+      bool split = ShouldSplit(field, options_);
+      if (split) {
+        format("PROTOBUF_FIELD_OFFSET($classname$::Impl_::Split, $1$), ",
+               FieldName(field) + "_");
+      } else {
+        format("PROTOBUF_FIELD_OFFSET($classname$, $1$), ",
+               FieldMemberName(field, /*cold=*/false));
+      }
+      if (oneof) {
+        format("_Internal::kOneofCaseOffset + $1$, ", 4 * oneof->index());
+      } else if (num_hasbits_ > 0 || IsMapEntryMessage(descriptor_)) {
+        if (entry.hasbit_idx >= 0) {
+          format("_Internal::kHasBitsOffset + $1$, ", entry.hasbit_idx);
+        } else {
+          format("$1$, ", entry.hasbit_idx);
+        }
+      } else {
+        format("0, ");
+      }
+      format("$1$,\n ", entry.aux_idx);
+      FormatFieldKind(format, entry);
     }
     format("},\n");
   }
 }
 
-static constexpr int kMaxNameLength = 255;
-
-int ParseFunctionGenerator::CalculateFieldNamesSize() const {
-  // The full name of the message appears first.
-  int size = std::min(static_cast<int>(descriptor_->full_name().size()),
-                      kMaxNameLength);
-  int lengths_size = 1;
-  for (const auto& entry : tc_table_info_->field_entries) {
-    const FieldDescriptor* field = entry.field;
-    GOOGLE_CHECK_LE(field->name().size(), kMaxNameLength);
-    size += field->name().size();
-    lengths_size += 1;
-  }
-  // align to an 8-byte boundary
-  lengths_size = (lengths_size + 7) & -8;
-  return size + lengths_size + 1;
-}
-
-static void FormatOctal(Formatter& format, int size) {
-  int octal_size = ((size >> 6) & 3) * 100 +  //
-                   ((size >> 3) & 7) * 10 +   //
-                   ((size >> 0) & 7);
-  format("\\$1$", octal_size);
-}
-
 void ParseFunctionGenerator::GenerateFieldNames(Formatter& format) {
-  // First, we output the size of each string, as an unsigned byte. The first
-  // string is the message name.
-  int count = 1;
-  format("\"");
-  FormatOctal(format,
-              std::min(static_cast<int>(descriptor_->full_name().size()), 255));
-  for (const auto& entry : tc_table_info_->field_entries) {
-    FormatOctal(format, entry.field->name().size());
-    ++count;
+  if (tc_table_info_->field_name_data.empty()) {
+    // No names to output.
+    return;
   }
-  while (count & 7) {  // align to an 8-byte boundary
-    format("\\0");
-    ++count;
+
+  // We could just output the bytes directly, but we want it to look better than
+  // that in the source code. Also, it is more efficient for compilation time to
+  // have a literal string than an initializer list of chars.
+
+  const int total_sizes =
+      static_cast<int>(((tc_table_info_->field_entries.size() + 1) + 7) & ~7);
+  const uint8_t* p = tc_table_info_->field_name_data.data();
+  const uint8_t* sizes = p;
+  const uint8_t* sizes_end = sizes + total_sizes;
+
+  // First print all the sizes as octal
+  format("\"");
+  for (int i = 0; i < total_sizes; ++i) {
+    int size = *p++;
+    int octal_size = ((size >> 6) & 3) * 100 +  //
+                     ((size >> 3) & 7) * 10 +   //
+                     ((size >> 0) & 7);
+    format("\\$1$", octal_size);
   }
   format("\"\n");
-  // The message name is stored at the beginning of the string
-  std::string message_name = descriptor_->full_name();
-  if (message_name.size() > kMaxNameLength) {
-    static constexpr int kNameHalfLength = (kMaxNameLength - 3) / 2;
-    message_name = StrCat(
-        message_name.substr(0, kNameHalfLength), "...",
-        message_name.substr(message_name.size() - kNameHalfLength));
-  }
-  format("\"$1$\"\n", message_name);
-  // Then we output the actual field names
-  for (const auto& entry : tc_table_info_->field_entries) {
-    const FieldDescriptor* field = entry.field;
-    format("\"$1$\"\n", field->name());
+
+  // Then print each name in a line of its own
+  for (; sizes < sizes_end; p += *sizes++) {
+    if (*sizes != 0) format("\"$1$\"\n", std::string(p, p + *sizes));
   }
 }
 
 void ParseFunctionGenerator::GenerateArenaString(Formatter& format,
                                                  const FieldDescriptor* field) {
-  if (HasHasbit(field)) {
+  if (internal::cpp::HasHasbit(field)) {
     format("_Internal::set_has_$1$(&$has_bits$);\n", FieldName(field));
   }
   format(
@@ -1184,7 +979,9 @@
   // to verify UTF8 when we already know parsing failed.
   format("CHK_(ptr);\n");
   if (!check_utf8) return;  // return if this is a bytes field
-  auto level = GetUtf8CheckMode(field, options_);
+  auto level = internal::cpp::GetUtf8CheckMode(
+      field,
+      GetOptimizeFor(field->file(), options_) == FileOptions::LITE_RUNTIME);
   switch (level) {
     case Utf8CheckMode::kNone:
       return;
@@ -1198,7 +995,7 @@
   std::string field_name;
   field_name = "nullptr";
   if (HasDescriptorMethods(field->file(), options_)) {
-    field_name = StrCat("\"", field->full_name(), "\"");
+    field_name = absl::StrCat("\"", field->full_name(), "\"");
   }
   format("::_pbi::VerifyUTF8(str, $1$)", field_name);
   switch (level) {
@@ -1219,7 +1016,7 @@
                                                  const FieldDescriptor* field) {
   if (field->is_packable()) {
     if (field->type() == FieldDescriptor::TYPE_ENUM &&
-        !HasPreservingUnknownEnumSemantics(field)) {
+        !internal::cpp::HasPreservingUnknownEnumSemantics(field)) {
       std::string enum_type = QualifiedClassName(field->enum_type(), options_);
       format(
           "ptr = "
@@ -1248,7 +1045,7 @@
           const FieldDescriptor* val = field->message_type()->map_value();
           GOOGLE_CHECK(val);
           if (val->type() == FieldDescriptor::TYPE_ENUM &&
-              !HasPreservingUnknownEnumSemantics(field)) {
+              !internal::cpp::HasPreservingUnknownEnumSemantics(field)) {
             format(
                 "auto object = "
                 "::$proto_ns$::internal::InitEnumParseWrapper<"
@@ -1267,13 +1064,13 @@
             format(
                 "ctx->set_lazy_eager_verify_func($1$);\n",
                 eager_verify
-                    ? StrCat("&", ClassName(field->message_type(), true),
+                    ? absl::StrCat("&", ClassName(field->message_type(), true),
                                    "::InternalVerify")
                     : "nullptr");
           }
           if (field->real_containing_oneof()) {
             format(
-                "if (!$msg$_internal_has_$name$()) {\n"
+                "if ($msg$$1$_case() != k$2$) {\n"
                 "  $msg$clear_$1$();\n"
                 "  $msg$$field$ = ::$proto_ns$::Arena::CreateMessage<\n"
                 "      ::$proto_ns$::internal::LazyField>("
@@ -1281,8 +1078,9 @@
                 "  $msg$set_has_$name$();\n"
                 "}\n"
                 "auto* lazy_field = $msg$$field$;\n",
-                field->containing_oneof()->name());
-          } else if (HasHasbit(field)) {
+                field->containing_oneof()->name(),
+                UnderscoresToCamelCase(field->name(), true));
+          } else if (internal::cpp::HasHasbit(field)) {
             format(
                 "_Internal::set_has_$name$(&$has_bits$);\n"
                 "auto* lazy_field = &$msg$$field$;\n");
@@ -1356,29 +1154,31 @@
       {{"name", FieldName(field)},
        {"primitive_type", PrimitiveTypeName(options_, field->cpp_type())}});
   if (field->is_repeated()) {
-    format.AddMap({{"put_field", StrCat("add_", FieldName(field))},
-                   {"mutable_field", StrCat("add_", FieldName(field))}});
+    format.AddMap({{"put_field", absl::StrCat("add_", FieldName(field))},
+                   {"mutable_field", absl::StrCat("add_", FieldName(field))}});
   } else {
     format.AddMap(
-        {{"put_field", StrCat("set_", FieldName(field))},
-         {"mutable_field", StrCat("mutable_", FieldName(field))}});
+        {{"put_field", absl::StrCat("set_", FieldName(field))},
+         {"mutable_field", absl::StrCat("mutable_", FieldName(field))}});
   }
   uint32_t tag = WireFormatLite::MakeTag(field->number(), wiretype);
   switch (wiretype) {
     case WireFormatLite::WIRETYPE_VARINT: {
-      std::string type = PrimitiveTypeName(options_, field->cpp_type());
       if (field->type() == FieldDescriptor::TYPE_ENUM) {
         format.Set("enum_type",
                    QualifiedClassName(field->enum_type(), options_));
         format(
-            "$uint64$ val = ::$proto_ns$::internal::ReadVarint64(&ptr);\n"
+            "$uint32$ val = ::$proto_ns$::internal::ReadVarint32(&ptr);\n"
             "CHK_(ptr);\n");
-        if (!HasPreservingUnknownEnumSemantics(field)) {
-          format("if (PROTOBUF_PREDICT_TRUE($enum_type$_IsValid(val))) {\n");
+        if (!internal::cpp::HasPreservingUnknownEnumSemantics(field)) {
+          format(
+              "if "
+              "(PROTOBUF_PREDICT_TRUE($enum_type$_IsValid(static_cast<int>(val)"
+              "))) {\n");
           format.Indent();
         }
         format("$msg$_internal_$put_field$(static_cast<$enum_type$>(val));\n");
-        if (!HasPreservingUnknownEnumSemantics(field)) {
+        if (!internal::cpp::HasPreservingUnknownEnumSemantics(field)) {
           format.Outdent();
           format(
               "} else {\n"
@@ -1405,7 +1205,7 @@
               "CHK_(ptr);\n",
               zigzag, size);
         } else {
-          if (HasHasbit(field)) {
+          if (internal::cpp::HasHasbit(field)) {
             format("_Internal::set_has_$name$(&$has_bits$);\n");
           }
           format(
@@ -1424,7 +1224,7 @@
             "::$proto_ns$::internal::UnalignedLoad<$primitive_type$>(ptr));\n"
             "ptr += sizeof($primitive_type$);\n");
       } else {
-        if (HasHasbit(field)) {
+        if (internal::cpp::HasHasbit(field)) {
           format("_Internal::set_has_$name$(&$has_bits$);\n");
         }
         format(
@@ -1599,8 +1399,9 @@
       format.Outdent();
     }
     format(
-        "} else\n"
+        "} else {\n"
         "  goto handle_unusual;\n"
+        "}\n"
         "$next_tag$;\n");
     format.Outdent();
   }  // for loop over ordered fields
@@ -1612,112 +1413,45 @@
   format("}  // switch\n");
 }
 
-namespace {
-
-std::string FieldParseFunctionName(
-    const TailCallTableInfo::FieldEntryInfo& entry, const Options& options) {
-  const FieldDescriptor* field = entry.field;
-  std::string name = "::_pbi::TcParser::Fast";
-
-  switch (field->type()) {
-    case FieldDescriptor::TYPE_FIXED32:
-    case FieldDescriptor::TYPE_SFIXED32:
-    case FieldDescriptor::TYPE_FLOAT:
-      name.append("F32");
-      break;
-
-    case FieldDescriptor::TYPE_FIXED64:
-    case FieldDescriptor::TYPE_SFIXED64:
-    case FieldDescriptor::TYPE_DOUBLE:
-      name.append("F64");
-      break;
-
-    case FieldDescriptor::TYPE_BOOL:
-      name.append("V8");
-      break;
-    case FieldDescriptor::TYPE_INT32:
-    case FieldDescriptor::TYPE_UINT32:
-      name.append("V32");
-      break;
-    case FieldDescriptor::TYPE_INT64:
-    case FieldDescriptor::TYPE_UINT64:
-      name.append("V64");
-      break;
-
-    case FieldDescriptor::TYPE_ENUM:
-      if (HasPreservingUnknownEnumSemantics(field)) {
-        name.append("V32");
-        break;
-      }
-      if (field->is_repeated() && field->is_packed()) {
-        GOOGLE_LOG(DFATAL) << "Enum validation not handled: " << field->DebugString();
-        return "";
-      }
-      name.append(entry.is_enum_range ? "Er" : "Ev");
-      break;
-
-    case FieldDescriptor::TYPE_SINT32:
-      name.append("Z32");
-      break;
-    case FieldDescriptor::TYPE_SINT64:
-      name.append("Z64");
-      break;
-
-    case FieldDescriptor::TYPE_BYTES:
-      name.append("B");
-      if (IsStringInlined(field, options)) {
-        name.append("i");
-      }
-      break;
-    case FieldDescriptor::TYPE_STRING:
-      switch (GetUtf8CheckMode(field, options)) {
-        case Utf8CheckMode::kNone:
-          name.append("B");
-          break;
-        case Utf8CheckMode::kVerify:
-          name.append("S");
-          break;
-        case Utf8CheckMode::kStrict:
-          name.append("U");
-          break;
-        default:
-          GOOGLE_LOG(DFATAL) << "Mode not handled: "
-                      << static_cast<int>(GetUtf8CheckMode(field, options));
-          return "";
-      }
-      if (IsStringInlined(field, options)) {
-        name.append("i");
-      }
-      break;
-
-    case FieldDescriptor::TYPE_MESSAGE:
-      name.append("M");
-      break;
-    case FieldDescriptor::TYPE_GROUP:
-      name.append("G");
-      break;
-
-    default:
-      GOOGLE_LOG(DFATAL) << "Type not handled: " << field->DebugString();
-      return "";
+#if 0
+void PopulateFastFieldEntry(const Descriptor* descriptor,
+                            const TailCallTableInfo::FieldEntryInfo& entry,
+                            const Options& options,
+                            TailCallTableInfo::FastFieldInfo& info) {
+                            .....
+  if (name == "V8S1") {
+    info.func_name = absl::StrCat(
+        "::_pbi::TcParser::SingularVarintNoZag1<bool, offsetof(",  //
+        ClassName(descriptor),                                     //
+        ", ",                                                      //
+        FieldMemberName(field, /*split=*/false),                   //
+        "), ",                                                     //
+        HasHasbit(field) ? entry.hasbit_idx : 63,                  //
+        ">()");
+  } else if (name == "V32S1") {
+    info.func_name = absl::StrCat(
+        "::_pbi::TcParser::SingularVarintNoZag1<::uint32_t, offsetof(",  //
+        ClassName(descriptor),                                           //
+        ", ",                                                            //
+        FieldMemberName(field, /*split=*/false),                         //
+        "), ",                                                           //
+        HasHasbit(field) ? entry.hasbit_idx : 63,                        //
+        ">()");
+  } else if (name == "V64S1") {
+    info.func_name = absl::StrCat(
+        "::_pbi::TcParser::SingularVarintNoZag1<::uint64_t, offsetof(",  //
+        ClassName(descriptor),                                           //
+        ", ",                                                            //
+        FieldMemberName(field, /*split=*/false),                         //
+        "), ",                                                           //
+        HasHasbit(field) ? entry.hasbit_idx : 63,                        //
+        ">()");
+  } else {
+    info.func_name = absl::StrCat("::_pbi::TcParser::Fast", name);
   }
-
-  // The field implementation functions are prefixed by cardinality:
-  //   `S` for optional or implicit fields.
-  //   `R` for non-packed repeated.
-  //   `P` for packed repeated.
-  name.append(field->is_packed()               ? "P"
-              : field->is_repeated()           ? "R"
-              : field->real_containing_oneof() ? "O"
-                                               : "S");
-
-  // Append the tag length. Fast parsing only handles 1- or 2-byte tags.
-  name.append(TagSize(field->number()) == 1 ? "1" : "2");
-
-  return name;
+  info.aux_idx = aux_idx;
 }
-
-}  // namespace
+#endif
 
 }  // namespace cpp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/cpp/parse_function_generator.h b/src/google/protobuf/compiler/cpp/parse_function_generator.h
index 542a15a..0bd9c60 100644
--- a/src/google/protobuf/compiler/cpp/parse_function_generator.h
+++ b/src/google/protobuf/compiler/cpp/parse_function_generator.h
@@ -31,72 +31,32 @@
 #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/io/printer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/options.h>
+#include "google/protobuf/descriptor.h"
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/generated_message_tctable_gen.h"
+#include "google/protobuf/io/printer.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<const FieldDescriptor*>& ordered_fields,
-                    const std::vector<int>& has_bit_indices,
-                    const std::vector<int>& inlined_string_indices,
-                    MessageSCCAnalyzer* scc_analyzer);
-
-  // Fields parsed by the table fast-path.
-  struct FastFieldInfo {
-    std::string func_name;
-    const FieldDescriptor* field;
-    uint16_t coded_tag;
-    uint8_t hasbit_idx;
-    uint8_t aux_idx;
-  };
-  std::vector<FastFieldInfo> fast_path_fields;
-
-  // Fields parsed by mini parsing routines.
-  struct FieldEntryInfo {
-    const FieldDescriptor* field;
-    int hasbit_idx;
-    int inlined_string_idx;
-    uint16_t aux_idx;
-    // True for enums entirely covered by the start/length fields of FieldAux:
-    bool is_enum_range;
-  };
-  std::vector<FieldEntryInfo> field_entries;
-  std::vector<std::string> aux_entries;
-
-  // Fields parsed by generated fallback function.
-  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 std::vector<int>& inlined_string_indices,
-                         const Options& options,
-                         MessageSCCAnalyzer* scc_analyzer,
-                         const std::map<std::string, std::string>& vars);
+  ParseFunctionGenerator(
+      const Descriptor* descriptor, int max_has_bit_index,
+      const std::vector<int>& has_bit_indices,
+      const std::vector<int>& inlined_string_indices, const Options& options,
+      MessageSCCAnalyzer* scc_analyzer,
+      const absl::flat_hash_map<absl::string_view, std::string>& vars);
 
   // Emits class-level method declarations to `printer`:
   void GenerateMethodDecls(io::Printer* printer);
@@ -111,6 +71,8 @@
   void GenerateDataDefinitions(io::Printer* printer);
 
  private:
+  class GeneratedOptionProvider;
+
   // Returns true if tailcall table code should be generated.
   bool should_generate_tctable() const;
 
@@ -134,7 +96,6 @@
   void GenerateTailCallTable(Formatter& format);
   void GenerateFastFieldEntries(Formatter& format);
   void GenerateFieldEntries(Formatter& format);
-  int CalculateFieldNamesSize() const;
   void GenerateFieldNames(Formatter& format);
 
   // Generates parsing code for an `ArenaString` field.
@@ -165,8 +126,8 @@
   const Descriptor* descriptor_;
   MessageSCCAnalyzer* scc_analyzer_;
   const Options& options_;
-  std::map<std::string, std::string> variables_;
-  std::unique_ptr<TailCallTableInfo> tc_table_info_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
+  std::unique_ptr<internal::TailCallTableInfo> tc_table_info_;
   std::vector<int> inlined_string_indices_;
   const std::vector<const FieldDescriptor*> ordered_fields_;
   int num_hasbits_;
diff --git a/src/google/protobuf/compiler/cpp/plugin_unittest.cc b/src/google/protobuf/compiler/cpp/plugin_unittest.cc
index f023dcf..b303bd0 100644
--- a/src/google/protobuf/compiler/cpp/plugin_unittest.cc
+++ b/src/google/protobuf/compiler/cpp/plugin_unittest.cc
@@ -36,14 +36,14 @@
 
 #include <memory>
 
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/compiler/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/googletest.h>
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/compiler/cpp/generator.h"
+#include "google/protobuf/compiler/command_line_interface.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/cpp/primitive_field.cc b/src/google/protobuf/compiler/cpp/primitive_field.cc
index 6c92ede..e672d09 100644
--- a/src/google/protobuf/compiler/cpp/primitive_field.cc
+++ b/src/google/protobuf/compiler/cpp/primitive_field.cc
@@ -32,12 +32,17 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/primitive_field.h>
+#include "google/protobuf/compiler/cpp/primitive_field.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include <string>
+#include <tuple>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -98,9 +103,10 @@
   return -1;
 }
 
-void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           std::map<std::string, std::string>* variables,
-                           const Options& options) {
+void SetPrimitiveVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
   (*variables)["type"] = PrimitiveTypeName(options, descriptor->cpp_type());
   (*variables)["default"] = DefaultValue(options, descriptor);
@@ -108,10 +114,10 @@
   bool cold = ShouldSplit(descriptor, options);
   (*variables)["cached_byte_size_field"] =
       MakeVarintCachedSizeFieldName(descriptor, cold);
-  (*variables)["tag"] = StrCat(internal::WireFormat::MakeTag(descriptor));
+  (*variables)["tag"] = absl::StrCat(internal::WireFormat::MakeTag(descriptor));
   int fixed_size = FixedSize(descriptor->type());
   if (fixed_size != -1) {
-    (*variables)["fixed_size"] = StrCat(fixed_size);
+    (*variables)["fixed_size"] = absl::StrCat(fixed_size);
   }
   (*variables)["wire_format_field_type"] = FieldDescriptorProto_Type_Name(
       static_cast<FieldDescriptorProto_Type>(descriptor->type()));
@@ -139,9 +145,10 @@
 void PrimitiveFieldGenerator::GenerateAccessorDeclarations(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
+  format("$deprecated_attr$$type$ ${1$$name$$}$() const;\n", descriptor_);
+  format("$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n",
+         std::make_tuple(descriptor_, GeneratedCodeInfo::Annotation::SET));
   format(
-      "$deprecated_attr$$type$ ${1$$name$$}$() const;\n"
-      "$deprecated_attr$void ${1$set_$name$$}$($type$ value);\n"
       "private:\n"
       "$type$ ${1$_internal_$name$$}$() const;\n"
       "void ${1$_internal_set_$name$$}$($type$ value);\n"
@@ -263,13 +270,13 @@
   Formatter format(printer, variables_);
   format(
       "inline $type$ $classname$::_internal_$name$() const {\n"
-      "  if (_internal_has_$name$()) {\n"
+      "  if ($has_field$) {\n"
       "    return $field$;\n"
       "  }\n"
       "  return $default$;\n"
       "}\n"
       "inline void $classname$::_internal_set_$name$($type$ value) {\n"
-      "  if (!_internal_has_$name$()) {\n"
+      "  if ($not_has_field$) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "  }\n"
@@ -328,7 +335,9 @@
   format("::$proto_ns$::RepeatedField< $type$ > $name$_;\n");
   if (descriptor_->is_packed() && FixedSize(descriptor_->type()) == -1 &&
       HasGeneratedMethods(descriptor_->file(), options_)) {
-    format("mutable std::atomic<int> $cached_byte_size_name$;\n");
+    format(
+        "mutable ::$proto_ns$::internal::CachedSize "
+        "$cached_byte_size_name$;\n");
   }
 }
 
@@ -433,7 +442,7 @@
       format(
           "{\n"
           "  int byte_size = "
-          "$cached_byte_size_field$.load(std::memory_order_relaxed);\n"
+          "$cached_byte_size_field$.Get();\n"
           "  if (byte_size > 0) {\n"
           "    target = stream->Write$declared_type$Packed(\n"
           "        $number$, _internal_$name$(), byte_size, target);\n"
@@ -465,13 +474,13 @@
   int fixed_size = FixedSize(descriptor_->type());
   if (fixed_size == -1) {
     format(
-        "size_t data_size = ::_pbi::WireFormatLite::\n"
+        "::size_t data_size = ::_pbi::WireFormatLite::\n"
         "  $declared_type$Size(this->$field$);\n");
   } else {
     format(
         "unsigned int count = static_cast<unsigned "
         "int>(this->_internal_$name$_size());\n"
-        "size_t data_size = $fixed_size$UL * count;\n");
+        "::size_t data_size = $fixed_size$UL * count;\n");
   }
 
   if (descriptor_->is_packed()) {
@@ -484,8 +493,7 @@
     if (FixedSize(descriptor_->type()) == -1) {
       format(
           "int cached_size = ::_pbi::ToCachedSize(data_size);\n"
-          "$cached_byte_size_field$.store(cached_size,\n"
-          "                                std::memory_order_relaxed);\n");
+          "$cached_byte_size_field$.Set(cached_size);\n");
     }
     format("total_size += data_size;\n");
   } else {
diff --git a/src/google/protobuf/compiler/cpp/primitive_field.h b/src/google/protobuf/compiler/cpp/primitive_field.h
index bb8a08a..78e717b 100644
--- a/src/google/protobuf/compiler/cpp/primitive_field.h
+++ b/src/google/protobuf/compiler/cpp/primitive_field.h
@@ -35,10 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_PRIMITIVE_FIELD_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/field.h>
+#include "google/protobuf/compiler/cpp/field.h"
 
 namespace google {
 namespace protobuf {
@@ -49,6 +48,8 @@
  public:
   PrimitiveFieldGenerator(const FieldDescriptor* descriptor,
                           const Options& options);
+  PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
+  PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
   ~PrimitiveFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -67,15 +68,15 @@
       io::Printer* printer) const override;
   void GenerateAggregateInitializer(io::Printer* printer) const override;
   void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PrimitiveFieldGenerator);
 };
 
 class PrimitiveOneofFieldGenerator : public PrimitiveFieldGenerator {
  public:
   PrimitiveOneofFieldGenerator(const FieldDescriptor* descriptor,
                                const Options& options);
+  PrimitiveOneofFieldGenerator(const PrimitiveOneofFieldGenerator&) = delete;
+  PrimitiveOneofFieldGenerator& operator=(const PrimitiveOneofFieldGenerator&) =
+      delete;
   ~PrimitiveOneofFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -83,15 +84,16 @@
   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);
 };
 
 class RepeatedPrimitiveFieldGenerator : public FieldGenerator {
  public:
   RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor,
                                   const Options& options);
+  RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) =
+      delete;
+  RepeatedPrimitiveFieldGenerator& operator=(
+      const RepeatedPrimitiveFieldGenerator&) = delete;
   ~RepeatedPrimitiveFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -113,9 +115,6 @@
       io::Printer* printer) const override;
   void GenerateAggregateInitializer(io::Printer* printer) const override;
   void GenerateCopyAggregateInitializer(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedPrimitiveFieldGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/service.cc b/src/google/protobuf/compiler/cpp/service.cc
index 7a0d480..518628a 100644
--- a/src/google/protobuf/compiler/cpp/service.cc
+++ b/src/google/protobuf/compiler/cpp/service.cc
@@ -32,293 +32,279 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/service.h>
+#include "google/protobuf/compiler/cpp/service.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
+#include <string>
+
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
-namespace {
-
-void InitMethodVariables(const MethodDescriptor* method, const Options& options,
-                         Formatter* format) {
-  format->Set("name", method->name());
-  format->Set("input_type", QualifiedClassName(method->input_type(), options));
-  format->Set("output_type",
-              QualifiedClassName(method->output_type(), options));
-}
-
-}  // namespace
-
-ServiceGenerator::ServiceGenerator(
-    const ServiceDescriptor* descriptor,
-    const std::map<std::string, std::string>& vars, const Options& options)
-    : descriptor_(descriptor), vars_(vars), options_(options) {
-  vars_["classname"] = descriptor_->name();
-  vars_["full_name"] = descriptor_->full_name();
-}
-
-ServiceGenerator::~ServiceGenerator() {}
-
 void ServiceGenerator::GenerateDeclarations(io::Printer* printer) {
-  Formatter format(printer, vars_);
-  // Forward-declare the stub type.
-  format(
-      "class $classname$_Stub;\n"
-      "\n");
+  auto vars = printer->WithVars(&vars_);
+  printer->Emit(
+      {
+          {"virts", [&] { GenerateMethodSignatures(kVirtual, printer); }},
+          {"impls", [&] { GenerateMethodSignatures(kNonVirtual, printer); }},
+      },
+      R"cc(
+        class $classname$_Stub;
+        class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {
+         protected:
+          $classname$() = default;
 
-  GenerateInterface(printer);
-  GenerateStubDefinition(printer);
+         public:
+          using Stub = $classname$_Stub;
+
+          $classname$(const $classname$&) = delete;
+          $classname$& operator=(const $classname$&) = delete;
+          virtual ~$classname$() = default;
+
+          static const ::$proto_ns$::ServiceDescriptor* descriptor();
+
+          $virts$;
+
+          // implements Service ----------------------------------------------
+          const ::$proto_ns$::ServiceDescriptor* GetDescriptor() override;
+
+          void CallMethod(const ::$proto_ns$::MethodDescriptor* method,
+                          ::$proto_ns$::RpcController* controller,
+                          const ::$proto_ns$::Message* request,
+                          ::$proto_ns$::Message* response,
+                          ::google::protobuf::Closure* done) override;
+
+          const ::$proto_ns$::Message& GetRequestPrototype(
+              const ::$proto_ns$::MethodDescriptor* method) const override;
+
+          const ::$proto_ns$::Message& GetResponsePrototype(
+              const ::$proto_ns$::MethodDescriptor* method) const override;
+        };
+
+        class $dllexport_decl $$classname$_Stub final : public $classname$ {
+         public:
+          $classname$_Stub(::$proto_ns$::RpcChannel* channel);
+          $classname$_Stub(::$proto_ns$::RpcChannel* channel,
+                           ::$proto_ns$::Service::ChannelOwnership ownership);
+
+          $classname$_Stub(const $classname$_Stub&) = delete;
+          $classname$_Stub& operator=(const $classname$_Stub&) = delete;
+
+          ~$classname$_Stub() override;
+
+          inline ::$proto_ns$::RpcChannel* channel() { return channel_; }
+
+          // implements $classname$ ------------------------------------------
+          $impls$;
+
+         private:
+          ::$proto_ns$::RpcChannel* channel_;
+          bool owns_channel_;
+        };
+      )cc");
 }
 
-void ServiceGenerator::GenerateInterface(io::Printer* printer) {
-  Formatter format(printer, vars_);
-  format(
-      "class $dllexport_decl $$classname$ : public ::$proto_ns$::Service {\n"
-      " protected:\n"
-      "  // This class should be treated as an abstract interface.\n"
-      "  inline $classname$() {};\n"
-      " public:\n"
-      "  virtual ~$classname$();\n");
-  printer->Indent();
-
-  format(
-      "\n"
-      "typedef $classname$_Stub Stub;\n"
-      "\n"
-      "static const ::$proto_ns$::ServiceDescriptor* descriptor();\n"
-      "\n");
-
-  GenerateMethodSignatures(VIRTUAL, printer);
-
-  format(
-      "\n"
-      "// implements Service ----------------------------------------------\n"
-      "\n"
-      "const ::$proto_ns$::ServiceDescriptor* GetDescriptor();\n"
-      "void CallMethod(const ::$proto_ns$::MethodDescriptor* method,\n"
-      "                ::$proto_ns$::RpcController* controller,\n"
-      "                const ::$proto_ns$::Message* request,\n"
-      "                ::$proto_ns$::Message* response,\n"
-      "                ::google::protobuf::Closure* done);\n"
-      "const ::$proto_ns$::Message& GetRequestPrototype(\n"
-      "  const ::$proto_ns$::MethodDescriptor* method) const;\n"
-      "const ::$proto_ns$::Message& GetResponsePrototype(\n"
-      "  const ::$proto_ns$::MethodDescriptor* method) const;\n");
-
-  printer->Outdent();
-  format(
-      "\n"
-      " private:\n"
-      "  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$);\n"
-      "};\n"
-      "\n");
-}
-
-void ServiceGenerator::GenerateStubDefinition(io::Printer* printer) {
-  Formatter format(printer, vars_);
-  format(
-      "class $dllexport_decl $$classname$_Stub : public $classname$ {\n"
-      " public:\n");
-
-  printer->Indent();
-
-  format(
-      "$classname$_Stub(::$proto_ns$::RpcChannel* channel);\n"
-      "$classname$_Stub(::$proto_ns$::RpcChannel* channel,\n"
-      "                 ::$proto_ns$::Service::ChannelOwnership ownership);\n"
-      "~$classname$_Stub();\n"
-      "\n"
-      "inline ::$proto_ns$::RpcChannel* channel() { return channel_; }\n"
-      "\n"
-      "// implements $classname$ ------------------------------------------\n"
-      "\n");
-
-  GenerateMethodSignatures(NON_VIRTUAL, printer);
-
-  printer->Outdent();
-  format(
-      " private:\n"
-      "  ::$proto_ns$::RpcChannel* channel_;\n"
-      "  bool owns_channel_;\n"
-      "  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS($classname$_Stub);\n"
-      "};\n"
-      "\n");
-}
-
-void ServiceGenerator::GenerateMethodSignatures(VirtualOrNon virtual_or_non,
+void ServiceGenerator::GenerateMethodSignatures(VirtualOrNot virtual_or_not,
                                                 io::Printer* printer) {
-  for (int i = 0; i < descriptor_->method_count(); i++) {
+  for (int i = 0; i < descriptor_->method_count(); ++i) {
     const MethodDescriptor* method = descriptor_->method(i);
-    Formatter format(printer, vars_);
-    InitMethodVariables(method, options_, &format);
-    format.Set("virtual", virtual_or_non == VIRTUAL ? "virtual " : "");
-    format(
-        "$virtual$void $name$(::$proto_ns$::RpcController* controller,\n"
-        "                     const $input_type$* request,\n"
-        "                     $output_type$* response,\n"
-        "                     ::google::protobuf::Closure* done);\n");
+
+    printer->Emit(
+        {
+            {"name", method->name()},
+            {"input", QualifiedClassName(method->input_type(), *options_)},
+            {"output", QualifiedClassName(method->output_type(), *options_)},
+            {"virtual", virtual_or_not == kVirtual ? "virtual" : ""},
+            {"override", virtual_or_not != kVirtual ? "override" : ""},
+        },
+        // No cc, clang-format does not format this string well due to the
+        // $ override$ substitution.
+        R"(
+          $virtual $void $name$(::$proto_ns$::RpcController* controller,
+                                const $input$* request,
+                                $output$* response,
+                                ::google::protobuf::Closure* done)$ override$;
+        )");
   }
 }
 
 // ===================================================================
 
 void ServiceGenerator::GenerateImplementation(io::Printer* printer) {
-  Formatter format(printer, vars_);
-  format(
-      "$classname$::~$classname$() {}\n"
-      "\n"
-      "const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {\n"
-      "  "
-      "::$proto_ns$::internal::AssignDescriptors(&$desc_table$);\n"
-      "  return $file_level_service_descriptors$[$1$];\n"
-      "}\n"
-      "\n"
-      "const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {\n"
-      "  return descriptor();\n"
-      "}\n"
-      "\n",
-      index_in_metadata_);
+  auto vars = printer->WithVars(&vars_);
+  printer->Emit(
+      {
+          {"index", index_in_metadata_},
+          {"no_impl_methods", [&] { GenerateNotImplementedMethods(printer); }},
+          {"call_method", [&] { GenerateCallMethod(printer); }},
+          {"get_request", [&] { GenerateGetPrototype(kRequest, printer); }},
+          {"get_response", [&] { GenerateGetPrototype(kResponse, printer); }},
+          {"stub_methods", [&] { GenerateStubMethods(printer); }},
+      },
+      R"cc(
+        const ::$proto_ns$::ServiceDescriptor* $classname$::descriptor() {
+          ::$proto_ns$::internal::AssignDescriptors(&$desc_table$);
+          return $file_level_service_descriptors$[$index$];
+        }
 
-  // Generate methods of the interface.
-  GenerateNotImplementedMethods(printer);
-  GenerateCallMethod(printer);
-  GenerateGetPrototype(REQUEST, printer);
-  GenerateGetPrototype(RESPONSE, printer);
+        const ::$proto_ns$::ServiceDescriptor* $classname$::GetDescriptor() {
+          return descriptor();
+        }
 
-  // Generate stub implementation.
-  format(
-      "$classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel)\n"
-      "  : channel_(channel), owns_channel_(false) {}\n"
-      "$classname$_Stub::$classname$_Stub(\n"
-      "    ::$proto_ns$::RpcChannel* channel,\n"
-      "    ::$proto_ns$::Service::ChannelOwnership ownership)\n"
-      "  : channel_(channel),\n"
-      "    owns_channel_(ownership == "
-      "::$proto_ns$::Service::STUB_OWNS_CHANNEL) "
-      "{}\n"
-      "$classname$_Stub::~$classname$_Stub() {\n"
-      "  if (owns_channel_) delete channel_;\n"
-      "}\n"
-      "\n");
+        $no_impl_methods$;
 
-  GenerateStubMethods(printer);
+        $call_method$;
+
+        $get_request$;
+
+        $get_response$;
+
+        $classname$_Stub::$classname$_Stub(::$proto_ns$::RpcChannel* channel)
+            : channel_(channel), owns_channel_(false) {}
+
+        $classname$_Stub::$classname$_Stub(
+            ::$proto_ns$::RpcChannel* channel,
+            ::$proto_ns$::Service::ChannelOwnership ownership)
+            : channel_(channel),
+              owns_channel_(ownership ==
+                            ::$proto_ns$::Service::STUB_OWNS_CHANNEL) {}
+
+        $classname$_Stub::~$classname$_Stub() {
+          if (owns_channel_) delete channel_;
+        }
+
+        $stub_methods$;
+      )cc");
 }
 
 void ServiceGenerator::GenerateNotImplementedMethods(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->method_count(); i++) {
+  for (int i = 0; i < descriptor_->method_count(); ++i) {
     const MethodDescriptor* method = descriptor_->method(i);
-    Formatter format(printer, vars_);
-    InitMethodVariables(method, options_, &format);
-    format(
-        "void $classname$::$name$(::$proto_ns$::RpcController* controller,\n"
-        "                         const $input_type$*,\n"
-        "                         $output_type$*,\n"
-        "                         ::google::protobuf::Closure* done) {\n"
-        "  controller->SetFailed(\"Method $name$() not implemented.\");\n"
-        "  done->Run();\n"
-        "}\n"
-        "\n");
+
+    printer->Emit(
+        {
+            {"name", method->name()},
+            {"input", QualifiedClassName(method->input_type(), *options_)},
+            {"output", QualifiedClassName(method->output_type(), *options_)},
+        },
+        R"cc(
+          void $classname$::$name$(::$proto_ns$::RpcController* controller,
+                                   const $input$*, $output$*, ::google::protobuf::Closure* done) {
+            controller->SetFailed("Method $name$() not implemented.");
+            done->Run();
+          }
+        )cc");
   }
 }
 
 void ServiceGenerator::GenerateCallMethod(io::Printer* printer) {
-  Formatter format(printer, vars_);
-  format(
-      "void $classname$::CallMethod(const ::$proto_ns$::MethodDescriptor* "
-      "method,\n"
-      "                             ::$proto_ns$::RpcController* controller,\n"
-      "                             const ::$proto_ns$::Message* request,\n"
-      "                             ::$proto_ns$::Message* response,\n"
-      "                             ::google::protobuf::Closure* done) {\n"
-      "  GOOGLE_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$1$]);\n"
-      "  switch(method->index()) {\n",
-      index_in_metadata_);
+  printer->Emit(
+      {
+          {"index", absl::StrCat(index_in_metadata_)},
+          {"cases", [&] { GenerateCallMethodCases(printer); }},
+      },
+      R"cc(
+        void $classname$::CallMethod(
+            const ::$proto_ns$::MethodDescriptor* method,
+            ::$proto_ns$::RpcController* controller,
+            const ::$proto_ns$::Message* request,
+            ::$proto_ns$::Message* response, ::google::protobuf::Closure* done) {
+          GOOGLE_DCHECK_EQ(method->service(), $file_level_service_descriptors$[$index$]);
+          switch (method->index()) {
+            $cases$;
 
-  for (int i = 0; i < descriptor_->method_count(); i++) {
-    const MethodDescriptor* method = descriptor_->method(i);
-    Formatter format_method(printer, vars_);
-    InitMethodVariables(method, options_, &format_method);
-
-    // Note:  down_cast does not work here because it only works on pointers,
-    //   not references.
-    format_method(
-        "    case $1$:\n"
-        "      $name$(controller,\n"
-        "             ::$proto_ns$::internal::DownCast<const $input_type$*>(\n"
-        "                 request),\n"
-        "             ::$proto_ns$::internal::DownCast<$output_type$*>(\n"
-        "                 response),\n"
-        "             done);\n"
-        "      break;\n",
-        i);
-  }
-
-  format(
-      "    default:\n"
-      "      GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
-      "      break;\n"
-      "  }\n"
-      "}\n"
-      "\n");
+            default:
+              GOOGLE_LOG(FATAL) << "Bad method index; this should never happen.";
+              break;
+          }
+        }
+      )cc");
 }
 
 void ServiceGenerator::GenerateGetPrototype(RequestOrResponse which,
                                             io::Printer* printer) {
-  Formatter format(printer, vars_);
-  if (which == REQUEST) {
-    format("const ::$proto_ns$::Message& $classname$::GetRequestPrototype(\n");
-  } else {
-    format("const ::$proto_ns$::Message& $classname$::GetResponsePrototype(\n");
-  }
+  printer->Emit(
+      {
+          {"which", which == kRequest ? "Request" : "Response"},
+          {"which_type", which == kRequest ? "input" : "output"},
+          {"cases",
+           [&] {
+             for (int i = 0; i < descriptor_->method_count(); ++i) {
+               const MethodDescriptor* method = descriptor_->method(i);
+               const Descriptor* type = which == kRequest
+                                            ? method->input_type()
+                                            : method->output_type();
 
-  format(
-      "    const ::$proto_ns$::MethodDescriptor* method) const {\n"
-      "  GOOGLE_DCHECK_EQ(method->service(), descriptor());\n"
-      "  switch(method->index()) {\n");
+               printer->Emit(
+                   {
+                       {"index", absl::StrCat(i)},
+                       {"type", QualifiedClassName(type, *options_)},
+                   },
+                   R"cc(
+                     case $index$:
+                       return $type$::default_instance();
+                   )cc");
+             }
+           }},
+      },
+      R"cc(
+        const ::$proto_ns$::Message& $classname$::Get$which$Prototype(
+            const ::$proto_ns$::MethodDescriptor* method) const {
+          GOOGLE_DCHECK_EQ(method->service(), descriptor());
+          switch (method->index()) {
+            $cases$;
 
-  for (int i = 0; i < descriptor_->method_count(); i++) {
+            default:
+              GOOGLE_LOG(FATAL) << "Bad method index; this should never happen.";
+              return *::$proto_ns$::MessageFactory::generated_factory()
+                          ->GetPrototype(method->$which_type$_type());
+          }
+        }
+      )cc");
+}
+
+void ServiceGenerator::GenerateCallMethodCases(io::Printer* printer) {
+  for (int i = 0; i < descriptor_->method_count(); ++i) {
     const MethodDescriptor* method = descriptor_->method(i);
-    const Descriptor* type =
-        (which == REQUEST) ? method->input_type() : method->output_type();
-
-    format(
-        "    case $1$:\n"
-        "      return $2$::default_instance();\n",
-        i, QualifiedClassName(type, options_));
+    printer->Emit(
+        {
+            {"name", method->name()},
+            {"input", QualifiedClassName(method->input_type(), *options_)},
+            {"output", QualifiedClassName(method->output_type(), *options_)},
+            {"index", absl::StrCat(i)},
+        },
+        R"cc(
+          case $index$:
+            $name$(controller,
+                   ::$proto_ns$::internal::DownCast<const $input$*>(request),
+                   ::$proto_ns$::internal::DownCast<$output$*>(response), done);
+            break;
+        )cc");
   }
-
-  format(
-      "    default:\n"
-      "      GOOGLE_LOG(FATAL) << \"Bad method index; this should never happen.\";\n"
-      "      return *::$proto_ns$::MessageFactory::generated_factory()\n"
-      "          ->GetPrototype(method->$1$_type());\n"
-      "  }\n"
-      "}\n"
-      "\n",
-      which == REQUEST ? "input" : "output");
 }
 
 void ServiceGenerator::GenerateStubMethods(io::Printer* printer) {
-  for (int i = 0; i < descriptor_->method_count(); i++) {
+  for (int i = 0; i < descriptor_->method_count(); ++i) {
     const MethodDescriptor* method = descriptor_->method(i);
-    Formatter format(printer, vars_);
-    InitMethodVariables(method, options_, &format);
-    format(
-        "void $classname$_Stub::$name$(::$proto_ns$::RpcController* "
-        "controller,\n"
-        "                              const $input_type$* request,\n"
-        "                              $output_type$* response,\n"
-        "                              ::google::protobuf::Closure* done) {\n"
-        "  channel_->CallMethod(descriptor()->method($1$),\n"
-        "                       controller, request, response, done);\n"
-        "}\n",
-        i);
+
+    printer->Emit(
+        {
+            {"name", method->name()},
+            {"input", QualifiedClassName(method->input_type(), *options_)},
+            {"output", QualifiedClassName(method->output_type(), *options_)},
+            {"index", absl::StrCat(i)},
+        },
+        R"cc(
+          void $classname$_Stub::$name$(::$proto_ns$::RpcController* controller,
+                                        const $input$* request,
+                                        $output$* response, ::google::protobuf::Closure* done) {
+            channel_->CallMethod(descriptor()->method($index$), controller,
+                                 request, response, done);
+          }
+        )cc");
   }
 }
 
diff --git a/src/google/protobuf/compiler/cpp/service.h b/src/google/protobuf/compiler/cpp/service.h
index b3bd2d7..9e258f2 100644
--- a/src/google/protobuf/compiler/cpp/service.h
+++ b/src/google/protobuf/compiler/cpp/service.h
@@ -35,63 +35,52 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_SERVICE_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/cpp/options.h>
-
-namespace google {
-namespace protobuf {
-namespace io {
-class Printer;  // printer.h
-}
-}  // namespace protobuf
-}  // namespace google
+#include "google/protobuf/descriptor.h"
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/cpp/options.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace cpp {
-
 class ServiceGenerator {
  public:
   // See generator.cc for the meaning of dllexport_decl.
-  explicit ServiceGenerator(const ServiceDescriptor* descriptor,
-                            const std::map<std::string, std::string>& vars,
-                            const Options& options);
-  ~ServiceGenerator();
+  ServiceGenerator(
+      const ServiceDescriptor* descriptor,
+      const absl::flat_hash_map<absl::string_view, std::string>& vars,
+      const Options& options)
+      : descriptor_(descriptor), options_(&options), vars_(vars) {
+    vars_["classname"] = descriptor_->name();
+    vars_["full_name"] = descriptor_->full_name();
+  }
 
-  // Header stuff.
+  ServiceGenerator(const ServiceGenerator&) = delete;
+  ServiceGenerator& operator=(const ServiceGenerator&) = delete;
+  ServiceGenerator(ServiceGenerator&&) = delete;
+  ServiceGenerator& operator=(ServiceGenerator&&) = delete;
+
+  ~ServiceGenerator() = default;
 
   // Generate the class definitions for the service's interface and the
   // stub implementation.
   void GenerateDeclarations(io::Printer* printer);
 
-  // Source file stuff.
-
   // Generate implementations of everything declared by
   // GenerateDeclarations().
   void GenerateImplementation(io::Printer* printer);
 
  private:
-  enum RequestOrResponse { REQUEST, RESPONSE };
-  enum VirtualOrNon { VIRTUAL, NON_VIRTUAL };
-
-  // Header stuff.
-
-  // Generate the service abstract interface.
-  void GenerateInterface(io::Printer* printer);
-
-  // Generate the stub class definition.
-  void GenerateStubDefinition(io::Printer* printer);
+  enum RequestOrResponse { kRequest, kResponse };
+  enum VirtualOrNot { kVirtual, kNonVirtual };
 
   // Prints signatures for all methods in the
-  void GenerateMethodSignatures(VirtualOrNon virtual_or_non,
+  void GenerateMethodSignatures(VirtualOrNot virtual_or_not,
                                 io::Printer* printer);
 
-  // Source file stuff.
-
   // Generate the default implementations of the service methods, which
   // produce a "not implemented" error.
   void GenerateNotImplementedMethods(io::Printer* printer);
@@ -102,19 +91,20 @@
   // Generate the Get{Request,Response}Prototype() methods.
   void GenerateGetPrototype(RequestOrResponse which, io::Printer* printer);
 
+  // Generate the cases in CallMethod().
+  void GenerateCallMethodCases(io::Printer* printer);
+
   // Generate the stub's implementations of the service methods.
   void GenerateStubMethods(io::Printer* printer);
 
   const ServiceDescriptor* descriptor_;
-  std::map<std::string, std::string> vars_;
-  const Options& options_;
+  const Options* options_;
+  absl::flat_hash_map<absl::string_view, std::string> vars_;
 
   int index_in_metadata_;
 
   friend class FileGenerator;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
 };
-
 }  // namespace cpp
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/cpp/string_field.cc b/src/google/protobuf/compiler/cpp/string_field.cc
index 9e7c96d..7c53fa9 100644
--- a/src/google/protobuf/compiler/cpp/string_field.cc
+++ b/src/google/protobuf/compiler/cpp/string_field.cc
@@ -32,13 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/cpp/string_field.h>
+#include "google/protobuf/compiler/cpp/string_field.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/descriptor.pb.h>
+#include <string>
 
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/descriptor.pb.h"
 
 namespace google {
 namespace protobuf {
@@ -47,39 +48,41 @@
 
 namespace {
 
-void SetStringVariables(const FieldDescriptor* descriptor,
-                        std::map<std::string, std::string>* variables,
-                        const Options& options) {
+void SetStringVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    const Options& options) {
   SetCommonFieldVariables(descriptor, variables, options);
 
-  const std::string kNS = "::" + (*variables)["proto_ns"] + "::internal::";
-  const std::string kArenaStringPtr = kNS + "ArenaStringPtr";
 
   (*variables)["default"] = DefaultValue(options, descriptor);
   (*variables)["default_length"] =
-      StrCat(descriptor->default_value_string().length());
+      absl::StrCat(descriptor->default_value_string().length());
   (*variables)["default_variable_name"] = MakeDefaultName(descriptor);
   (*variables)["default_variable_field"] = MakeDefaultFieldName(descriptor);
 
   if (descriptor->default_value_string().empty()) {
-    (*variables)["default_string"] = kNS + "GetEmptyStringAlreadyInited()";
-    (*variables)["default_value"] = "&" + (*variables)["default_string"];
+    const std::string default_string =
+        absl::StrCat("::", ProtobufNamespace(options),
+                     "::internal::GetEmptyStringAlreadyInited()");
+    (*variables)["default_string"] = default_string;
+    (*variables)["default_value"] = absl::StrCat("&", default_string);
     (*variables)["lazy_variable_args"] = "";
   } else {
-    (*variables)["lazy_variable"] =
-        StrCat(QualifiedClassName(descriptor->containing_type(), options),
+    const std::string lazy_variable =
+        absl::StrCat(QualifiedClassName(descriptor->containing_type(), options),
                      "::", MakeDefaultFieldName(descriptor));
+    (*variables)["lazy_variable"] = lazy_variable;
 
-    (*variables)["default_string"] = (*variables)["lazy_variable"] + ".get()";
+    (*variables)["default_string"] = absl::StrCat(lazy_variable, ".get()");
     (*variables)["default_value"] = "nullptr";
-    (*variables)["lazy_variable_args"] = (*variables)["lazy_variable"] + ", ";
+    (*variables)["lazy_variable_args"] = absl::StrCat(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.
   (*variables)["release_name"] =
@@ -89,7 +92,7 @@
   if (options.opensource_runtime) {
     (*variables)["string_piece"] = "::std::string";
   } else {
-    (*variables)["string_piece"] = "::StringPiece";
+    (*variables)["string_piece"] = "::absl::string_view";
   }
 }
 
@@ -286,9 +289,9 @@
       "$maybe_prepare_split_message$"
       "  // @@protoc_insertion_point(field_release:$full_name$)\n");
 
-  if (HasHasbit(descriptor_)) {
+  if (internal::cpp::HasHasbit(descriptor_)) {
     format(
-        "  if (!_internal_has_$name$()) {\n"
+        "  if (($has_hasbit$) == 0) {\n"
         "    return nullptr;\n"
         "  }\n"
         "  $clear_hasbit$\n");
@@ -297,9 +300,7 @@
       if (descriptor_->default_value_string().empty()) {
         format(
             "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
-            "  if ($field$.IsDefault()) {\n"
-            "    $field$.Set(\"\", GetArenaForAllocation());\n"
-            "  }\n"
+            "  $field$.Set(\"\", GetArenaForAllocation());\n"
             "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
       }
       format("  return p;\n");
@@ -315,12 +316,20 @@
   format(
       "}\n"
       "inline void $classname$::set_allocated_$name$(std::string* $name$) {\n"
-      "$maybe_prepare_split_message$"
-      "  if ($name$ != nullptr) {\n"
-      "    $set_hasbit$\n"
-      "  } else {\n"
-      "    $clear_hasbit$\n"
-      "  }\n");
+      "$maybe_prepare_split_message$");
+
+  auto nonempty = [this](const char* fn) {
+    auto var_it = variables_.find(fn);
+    return var_it != variables_.end() && !var_it->second.empty();
+  };
+  if (nonempty("set_hasbit") || nonempty("clear_hasbit")) {
+    format(
+        "  if ($name$ != nullptr) {\n"
+        "    $set_hasbit$\n"
+        "  } else {\n"
+        "    $clear_hasbit$\n"
+        "  }\n");
+  }
   if (!inlined_) {
     format("  $field$.SetAllocated($name$, GetArenaForAllocation());\n");
     if (descriptor_->default_value_string().empty()) {
@@ -377,7 +386,7 @@
   // 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 the default variable.
-  const bool must_be_present = HasHasbit(descriptor_);
+  const bool must_be_present = internal::cpp::HasHasbit(descriptor_);
 
   if (inlined_ && must_be_present) {
     // Calling mutable_$name$() gives us a string reference and sets the has bit
@@ -445,21 +454,6 @@
   }
 }
 
-void StringFieldGenerator::GenerateCreateSplitMessageCode(
-    io::Printer* printer) const {
-  GOOGLE_CHECK(ShouldSplit(descriptor_, options_));
-  GOOGLE_CHECK(!inlined_);
-  Formatter format(printer, variables_);
-  format("ptr->$name$_.InitDefault();\n");
-  if (IsString(descriptor_, options_) &&
-      descriptor_->default_value_string().empty()) {
-    format(
-        "#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING\n"
-        "  ptr->$name$_.Set(\"\", GetArenaForAllocation());\n"
-        "#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING\n");
-  }
-}
-
 void StringFieldGenerator::GenerateCopyConstructorCode(
     io::Printer* printer) const {
   Formatter format(printer, variables_);
@@ -468,8 +462,8 @@
     format("new (&_this->$field$) ::_pbi::InlinedStringField();\n");
   }
 
-  if (HasHasbit(descriptor_)) {
-    format("if (from._internal_has_$name$()) {\n");
+  if (internal::cpp::HasHasbit(descriptor_)) {
+    format("if ((from.$has_hasbit$) != 0) {\n");
   } else {
     format("if (!from._internal_$name$().empty()) {\n");
   }
@@ -554,13 +548,9 @@
     format("/*decltype($field$)*/{nullptr, false}");
     return;
   }
-  if (descriptor_->default_value_string().empty()) {
-    format(
-        "/*decltype($field$)*/{&::_pbi::fixed_address_empty_string, "
-        "::_pbi::ConstantInitialized{}}");
-  } else {
-    format("/*decltype($field$)*/{nullptr, ::_pbi::ConstantInitialized{}}");
-  }
+  format(
+      "/*decltype($field$)*/{&::_pbi::fixed_address_empty_string, "
+      "::_pbi::ConstantInitialized{}}");
 }
 
 void StringFieldGenerator::GenerateAggregateInitializer(
@@ -590,9 +580,6 @@
     const FieldDescriptor* descriptor, const Options& options)
     : StringFieldGenerator(descriptor, options) {
   SetCommonOneofFieldVariables(descriptor, &variables_);
-  variables_["field_name"] = UnderscoresToCamelCase(descriptor->name(), true);
-  variables_["oneof_index"] =
-      StrCat(descriptor->containing_oneof()->index());
 }
 
 StringOneofFieldGenerator::~StringOneofFieldGenerator() {}
@@ -608,7 +595,7 @@
       "}\n"
       "template <typename ArgT0, typename... ArgT>\n"
       "inline void $classname$::set_$name$(ArgT0&& arg0, ArgT... args) {\n"
-      "  if (!_internal_has_$name$()) {\n"
+      "  if ($not_has_field$) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "    $field$.InitDefault();\n"
@@ -625,14 +612,14 @@
       "  return _s;\n"
       "}\n"
       "inline const std::string& $classname$::_internal_$name$() const {\n"
-      "  if (_internal_has_$name$()) {\n"
+      "  if ($has_field$) {\n"
       "    return $field$.Get();\n"
       "  }\n"
       "  return $default_string$;\n"
       "}\n"
       "inline void $classname$::_internal_set_$name$(const std::string& "
       "value) {\n"
-      "  if (!_internal_has_$name$()) {\n"
+      "  if ($not_has_field$) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "    $field$.InitDefault();\n"
@@ -641,7 +628,7 @@
       "}\n");
   format(
       "inline std::string* $classname$::_internal_mutable_$name$() {\n"
-      "  if (!_internal_has_$name$()) {\n"
+      "  if ($not_has_field$) {\n"
       "    clear_$oneof_name$();\n"
       "    set_has_$name$();\n"
       "    $field$.InitDefault();\n"
@@ -652,7 +639,7 @@
       "inline std::string* $classname$::$release_name$() {\n"
       "$annotate_release$"
       "  // @@protoc_insertion_point(field_release:$full_name$)\n"
-      "  if (_internal_has_$name$()) {\n"
+      "  if ($has_field$) {\n"
       "    clear_has_$oneof_name$();\n"
       "    return $field$.Release();\n"
       "  } else {\n"
@@ -737,12 +724,12 @@
   if (!options_.opensource_runtime) {
     format(
         "$deprecated_attr$void ${1$set_$name$$}$(int index, "
-        "StringPiece value);\n",
+        "absl::string_view value);\n",
         descriptor_);
   }
   format(
       "$deprecated_attr$void ${1$set_$name$$}$("
-      "int index, const $pointer_type$* value, size_t size);\n"
+      "int index, const $pointer_type$* value, ::size_t size);\n"
       "$deprecated_attr$std::string* ${1$add_$name$$}$();\n"
       "$deprecated_attr$void ${1$add_$name$$}$(const std::string& value);\n"
       "$deprecated_attr$void ${1$add_$name$$}$(std::string&& value);\n"
@@ -750,12 +737,12 @@
       descriptor_);
   if (!options_.opensource_runtime) {
     format(
-        "$deprecated_attr$void ${1$add_$name$$}$(StringPiece value);\n",
+        "$deprecated_attr$void ${1$add_$name$$}$(absl::string_view value);\n",
         descriptor_);
   }
   format(
       "$deprecated_attr$void ${1$add_$name$$}$(const $pointer_type$* "
-      "value, size_t size)"
+      "value, ::size_t size)"
       ";\n"
       "$deprecated_attr$const ::$proto_ns$::RepeatedPtrField<std::string>& "
       "${1$$name$$}$() "
@@ -824,7 +811,7 @@
       "  // @@protoc_insertion_point(field_set:$full_name$)\n"
       "}\n"
       "inline void $classname$::set_$name$(int index, const char* value) {\n"
-      "  $null_check$"
+      "  $DCHK$(value != nullptr);"
       "  $field$.Mutable(index)->assign(value);\n"
       "$annotate_set$"
       "  // @@protoc_insertion_point(field_set_char:$full_name$)\n"
@@ -832,7 +819,7 @@
   if (!options_.opensource_runtime) {
     format(
         "inline void "
-        "$classname$::set_$name$(int index, StringPiece value) {\n"
+        "$classname$::set_$name$(int index, absl::string_view value) {\n"
         "  $field$.Mutable(index)->assign(value.data(), value.size());\n"
         "$annotate_set$"
         "  // @@protoc_insertion_point(field_set_string_piece:$full_name$)\n"
@@ -841,7 +828,7 @@
   format(
       "inline void "
       "$classname$::set_$name$"
-      "(int index, const $pointer_type$* value, size_t size) {\n"
+      "(int index, const $pointer_type$* value, ::size_t size) {\n"
       "  $field$.Mutable(index)->assign(\n"
       "    reinterpret_cast<const char*>(value), size);\n"
       "$annotate_set$"
@@ -861,14 +848,14 @@
       "  // @@protoc_insertion_point(field_add:$full_name$)\n"
       "}\n"
       "inline void $classname$::add_$name$(const char* value) {\n"
-      "  $null_check$"
+      "  $DCHK$(value != nullptr);"
       "  $field$.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"
+        "inline void $classname$::add_$name$(absl::string_view value) {\n"
         "  $field$.Add()->assign(value.data(), value.size());\n"
         "$annotate_add$"
         "  // @@protoc_insertion_point(field_add_string_piece:$full_name$)\n"
@@ -876,7 +863,7 @@
   }
   format(
       "inline void "
-      "$classname$::add_$name$(const $pointer_type$* value, size_t size) {\n"
+      "$classname$::add_$name$(const $pointer_type$* value, ::size_t size) {\n"
       "  $field$.Add()->assign(reinterpret_cast<const char*>(value), size);\n"
       "$annotate_add$"
       "  // @@protoc_insertion_point(field_add_pointer:$full_name$)\n"
diff --git a/src/google/protobuf/compiler/cpp/string_field.h b/src/google/protobuf/compiler/cpp/string_field.h
index db5f18b..67cfa34 100644
--- a/src/google/protobuf/compiler/cpp/string_field.h
+++ b/src/google/protobuf/compiler/cpp/string_field.h
@@ -35,10 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CPP_STRING_FIELD_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/cpp/field.h>
+#include "google/protobuf/compiler/cpp/field.h"
 
 namespace google {
 namespace protobuf {
@@ -49,6 +48,8 @@
  public:
   StringFieldGenerator(const FieldDescriptor* descriptor,
                        const Options& options);
+  StringFieldGenerator(const StringFieldGenerator&) = delete;
+  StringFieldGenerator& operator=(const StringFieldGenerator&) = delete;
   ~StringFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -63,7 +64,6 @@
   void GenerateMergingCode(io::Printer* printer) const override;
   void GenerateSwappingCode(io::Printer* printer) const override;
   void GenerateConstructorCode(io::Printer* printer) const override;
-  void GenerateCreateSplitMessageCode(io::Printer* printer) const override;
   void GenerateCopyConstructorCode(io::Printer* printer) const override;
   void GenerateDestructorCode(io::Printer* printer) const override;
   void GenerateArenaDestructorCode(io::Printer* printer) const override;
@@ -79,13 +79,15 @@
 
  private:
   bool inlined_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringFieldGenerator);
 };
 
 class StringOneofFieldGenerator : public StringFieldGenerator {
  public:
   StringOneofFieldGenerator(const FieldDescriptor* descriptor,
                             const Options& options);
+  StringOneofFieldGenerator(const StringOneofFieldGenerator&) = delete;
+  StringOneofFieldGenerator& operator=(const StringOneofFieldGenerator&) =
+      delete;
   ~StringOneofFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -97,15 +99,15 @@
   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);
 };
 
 class RepeatedStringFieldGenerator : public FieldGenerator {
  public:
   RepeatedStringFieldGenerator(const FieldDescriptor* descriptor,
                                const Options& options);
+  RepeatedStringFieldGenerator(const RepeatedStringFieldGenerator&) = delete;
+  RepeatedStringFieldGenerator& operator=(const RepeatedStringFieldGenerator&) =
+      delete;
   ~RepeatedStringFieldGenerator() override;
 
   // implements FieldGenerator ---------------------------------------
@@ -123,9 +125,6 @@
   void GenerateSerializeWithCachedSizesToArray(
       io::Printer* printer) const override;
   void GenerateByteSize(io::Printer* printer) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedStringFieldGenerator);
 };
 
 }  // namespace cpp
diff --git a/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto b/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto
index 466a841..ead67b6 100644
--- a/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto
+++ b/src/google/protobuf/compiler/cpp/test_bad_identifiers.proto
@@ -61,7 +61,9 @@
   optional int32 total_size = 6;
   optional int32 tag = 7;
 
-  enum TestEnum { FOO = 0; }
+  enum TestEnum {
+    FOO = 0;
+  }
   message Data1 {
     repeated int32 data = 1;
   }
@@ -91,11 +93,16 @@
   optional int32 already_here = 15;
 
   optional uint32 uint32 = 16;
+  optional uint32 uint32_t = 41;
   optional uint64 uint64 = 17;
+  optional uint32 uint64_t = 42;
   optional string string = 18;
   optional int32 memset = 19;
   optional int32 int32 = 20;
+  optional int32 int32_t = 43;
   optional int64 int64 = 21;
+  optional int64 int64_t = 44;
+  optional int64 size_t = 45;
 
   optional uint32 cached_size = 22;
   optional uint32 extensions = 23;
diff --git a/src/google/protobuf/compiler/cpp/unittest.cc b/src/google/protobuf/compiler/cpp/unittest.cc
index e2730d7..2d03e62 100644
--- a/src/google/protobuf/compiler/cpp/unittest.cc
+++ b/src/google/protobuf/compiler/cpp/unittest.cc
@@ -33,7 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 //
 // To test the code generator, we actually use it to generate code for
-// net/proto2/internal/unittest.proto, then test that.  This means that we
+// third_party/protobuf/unittest.proto, then test that.  This means that we
 // are actually testing the parser and other parts of the system at the same
 // time, and that problems in the generator may show up as compile-time errors
 // rather than unittest failures, which may be surprising.  However, testing
@@ -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/unittest.h>
+#include "google/protobuf/compiler/cpp/unittest.h"
 
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_embed_optimize_for.pb.h>
-#include <google/protobuf/unittest_optimize_for.pb.h>
-#include <google/protobuf/test_util.h>
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_embed_optimize_for.pb.h"
+#include "google/protobuf/unittest_optimize_for.pb.h"
 
 #define MESSAGE_TEST_NAME MessageTest
 #define GENERATED_DESCRIPTOR_TEST_NAME GeneratedDescriptorTest
@@ -59,12 +59,12 @@
 #define HELPERS_TEST_NAME HelpersTest
 #define DESCRIPTOR_INIT_TEST_NAME DescriptorInitializationTest
 
-#define UNITTEST_PROTO_PATH "net/proto2/internal/unittest.proto"
+#define UNITTEST_PROTO_PATH "third_party/protobuf/unittest.proto"
 #define UNITTEST ::protobuf_unittest
 #define UNITTEST_IMPORT ::protobuf_unittest_import
 
 // Must include after the above macros.
-#include <google/protobuf/compiler/cpp/unittest.inc>
+#include "google/protobuf/compiler/cpp/unittest.inc"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/cpp/unittest.inc b/src/google/protobuf/compiler/cpp/unittest.inc
index 0b47176..3499fb5 100644
--- a/src/google/protobuf/compiler/cpp/unittest.inc
+++ b/src/google/protobuf/compiler/cpp/unittest.inc
@@ -33,7 +33,7 @@
 //  Sanjay Ghemawat, Jeff Dean, and others.
 //
 // To test the code generator, we actually use it to generate code for
-// net/proto2/internal/unittest.proto, then test that.  This means that we
+// third_party/protobuf/unittest.proto, then test that.  This means that we
 // are actually testing the parser and other parts of the system at the same
 // time, and that problems in the generator may show up as compile-time errors
 // rather than unittest failures, which may be surprising.  However, testing
@@ -49,37 +49,36 @@
 #include <memory>
 #include <vector>
 
-#include <google/protobuf/compiler/cpp/unittest.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/compiler/cpp/unittest.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
 #ifndef _MSC_VER
 // We exclude this large proto because it's too large for
 // visual studio to compile (report internal errors).
-#include <google/protobuf/unittest_enormous_descriptor.pb.h>
+#include "google/protobuf/unittest_enormous_descriptor.pb.h"
 #endif
-#include <google/protobuf/compiler/cpp/helpers.h>
-#include <google/protobuf/compiler/cpp/test_bad_identifiers.pb.h>
-#include <google/protobuf/unittest_no_generic_services.pb.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/compiler/scc.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/test_util2.h>
-
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/compiler/cpp/helpers.h"
+#include "google/protobuf/unittest_no_generic_services.pb.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/base/casts.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/compiler/cpp/test_bad_identifiers.pb.h"
+#include "google/protobuf/compiler/importer.h"
+#include "google/protobuf/compiler/scc.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/test_util2.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -102,7 +101,7 @@
   // implements ErrorCollector ---------------------------------------
   void AddError(const std::string& filename, int line, int column,
                 const std::string& message) override {
-    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
+    absl::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
                               message);
   }
 };
@@ -602,7 +601,7 @@
 
   TestUtil::SetAllFields(&message1);
 
-  const Message* source = implicit_cast<const Message*>(&message1);
+  const Message* source = absl::implicit_cast<const Message*>(&message1);
   message2.CopyFrom(*source);
 
   TestUtil::ExpectAllFieldsSet(message2);
@@ -664,7 +663,7 @@
   TestUtil::SetAllFields(&message1);
   int size = message1.ByteSizeLong();
   data.resize(size);
-  uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+  uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
   uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
   EXPECT_EQ(size, end - start);
   EXPECT_TRUE(message2.ParseFromString(data));
@@ -678,8 +677,7 @@
   TestUtil::SetPackedFields(&packed_message1);
   int packed_size = packed_message1.ByteSizeLong();
   packed_data.resize(packed_size);
-  uint8_t* start =
-      reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&packed_data));
+  uint8_t* start = reinterpret_cast<uint8_t*>(&packed_data[0]);
   uint8_t* end = packed_message1.SerializeWithCachedSizesToArray(start);
   EXPECT_EQ(packed_size, end - start);
   EXPECT_TRUE(packed_message2.ParseFromString(packed_data));
@@ -696,7 +694,7 @@
   data.resize(size);
   {
     // Allow the output stream to buffer only one byte at a time.
-    io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
     io::CodedOutputStream output_stream(&array_stream);
     message1.SerializeWithCachedSizes(&output_stream);
     EXPECT_FALSE(output_stream.HadError());
@@ -715,7 +713,7 @@
   data.resize(size);
   {
     // Allow the output stream to buffer only one byte at a time.
-    io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
     io::CodedOutputStream output_stream(&array_stream);
     message1.SerializeWithCachedSizes(&output_stream);
     EXPECT_FALSE(output_stream.HadError());
@@ -1822,7 +1820,7 @@
   message1.mutable_foogroup()->set_a(123);
   EXPECT_TRUE(message1.has_foogroup());
 
-  const Message* source = implicit_cast<const Message*>(&message1);
+  const Message* source = absl::implicit_cast<const Message*>(&message1);
   message2.CopyFrom(*source);
 
   EXPECT_TRUE(message2.has_foogroup());
@@ -1841,7 +1839,7 @@
 message1.set_foo_int(123);
 int size = message1.ByteSizeLong();
 data.resize(size);
-uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
 uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
 EXPECT_EQ(size, end - start);
 EXPECT_TRUE(message2.ParseFromString(data));
@@ -1855,7 +1853,7 @@
     message1.set_foo_string("foo");
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
     uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -1870,7 +1868,7 @@
     message1.set_foo_bytes("moo");
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
     uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -1884,7 +1882,7 @@
     message1.set_foo_enum(UNITTEST::TestOneof2::FOO);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
     uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -1898,7 +1896,7 @@
     message1.mutable_foo_message()->set_moo_int(234);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
     uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -1912,7 +1910,7 @@
     message1.mutable_foogroup()->set_a(345);
     int size = message1.ByteSizeLong();
     data.resize(size);
-    uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+    uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
     uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -1937,11 +1935,11 @@
 
 {
   // Allow the output stream to buffer only one byte at a time.
-  io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
-  io::CodedOutputStream output_stream(&array_stream);
-  message1.SerializeWithCachedSizes(&output_stream);
-  EXPECT_FALSE(output_stream.HadError());
-  EXPECT_EQ(size, output_stream.ByteCount());
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
 }
 
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -1958,11 +1956,11 @@
 
     {
       // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
     }
 
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -1980,11 +1978,11 @@
 
     {
       // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
     }
 
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -2001,11 +1999,11 @@
 
     {
       // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
     }
 
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -2022,11 +2020,11 @@
 
     {
       // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
     }
 
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -2043,11 +2041,11 @@
 
     {
       // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
-      io::CodedOutputStream output_stream(&array_stream);
-      message1.SerializeWithCachedSizes(&output_stream);
-      EXPECT_FALSE(output_stream.HadError());
-      EXPECT_EQ(size, output_stream.ByteCount());
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
+    io::CodedOutputStream output_stream(&array_stream);
+    message1.SerializeWithCachedSizes(&output_stream);
+    EXPECT_FALSE(output_stream.HadError());
+    EXPECT_EQ(size, output_stream.ByteCount());
     }
 
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -2223,4 +2221,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/csharp/BUILD.bazel b/src/google/protobuf/compiler/csharp/BUILD.bazel
new file mode 100644
index 0000000..433e0b2
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/BUILD.bazel
@@ -0,0 +1,133 @@
+################################################################################
+# Protocol Buffers Compiler - C# code generator
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "names",
+    hdrs = ["names.h"],
+    srcs = ["names.cc"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/csharp",
+    visibility = ["//visibility:public"],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "csharp",
+    srcs = [
+        "csharp_doc_comment.cc",
+        "csharp_enum.cc",
+        "csharp_enum_field.cc",
+        "csharp_field_base.cc",
+        "csharp_generator.cc",
+        "csharp_helpers.cc",
+        "csharp_map_field.cc",
+        "csharp_message.cc",
+        "csharp_message_field.cc",
+        "csharp_primitive_field.cc",
+        "csharp_reflection_class.cc",
+        "csharp_repeated_enum_field.cc",
+        "csharp_repeated_message_field.cc",
+        "csharp_repeated_primitive_field.cc",
+        "csharp_source_generator_base.cc",
+        "csharp_wrapper_field.cc",
+    ],
+    hdrs = [
+        "csharp_doc_comment.h",
+        "csharp_enum.h",
+        "csharp_enum_field.h",
+        "csharp_field_base.h",
+        "csharp_generator.h",
+        "csharp_helpers.h",
+        "csharp_map_field.h",
+        "csharp_message.h",
+        "csharp_message_field.h",
+        "csharp_options.h",
+        "csharp_primitive_field.h",
+        "csharp_reflection_class.h",
+        "csharp_repeated_enum_field.h",
+        "csharp_repeated_message_field.h",
+        "csharp_repeated_primitive_field.h",
+        "csharp_source_generator_base.h",
+        "csharp_wrapper_field.h",
+    ],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": ["-Wno-overloaded-virtual"],
+    }),
+    include_prefix = "google/protobuf/compiler/csharp",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+    ],
+    deps = [
+        ":names",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "bootstrap_unittest",
+    srcs = ["csharp_bootstrap_unittest.cc"],
+    data = [
+        "//:well_known_type_protos",
+        "//conformance:all_files",
+        "//conformance:conformance_proto",
+        "//csharp:wkt_cs_srcs",
+        "//src/google/protobuf:descriptor_proto_srcs",
+        "//src/google/protobuf:testdata",
+    ],
+    deps = [
+        ":csharp",
+        "//:protobuf",
+        "//src/google/protobuf/compiler:importer",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "generator_unittest",
+    srcs = ["csharp_generator_unittest.cc"],
+    deps = [
+        ":csharp",
+        "//:protobuf",
+        "//src/google/protobuf/compiler:command_line_interface",
+        "//src/google/protobuf/io",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
index 84aacca..b40e0bd 100644
--- a/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_bootstrap_unittest.cc
@@ -37,21 +37,19 @@
 // "generate_descriptor_proto.sh" and add the changed files under
 // csharp/src/ to your changelist.
 
-#include <map>
-
-#include <google/protobuf/compiler/csharp/csharp_generator.h>
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/csharp/csharp_generator.h"
+#include "google/protobuf/compiler/importer.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
 
 namespace google {
 namespace protobuf {
@@ -70,8 +68,8 @@
   // implements ErrorCollector ---------------------------------------
   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);
+    absl::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
+                              message);
   }
 };
 
@@ -104,7 +102,7 @@
   }
 
  private:
-  std::map<std::string, std::unique_ptr<std::string>> files_;
+  absl::flat_hash_map<std::string, std::unique_ptr<std::string>> files_;
 };
 
 class GenerateAndTest {
@@ -178,12 +176,6 @@
                     "WellKnownTypes/Wrappers.cs",
                     "../csharp/src/Google.Protobuf/WellKnownTypes/Wrappers.cs");
 
-  generate_test.SetParameter("");
-  source_tree.MapPath("", TestSourceDir() + "/../conformance");
-  generate_test.Run(importer.Import("conformance.proto"),
-                    "Conformance.cs",
-                    "../csharp/src/Google.Protobuf.Conformance/Conformance.cs");
-
   EXPECT_EQ("", error_collector.text_);
 }
 
diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
index 225d6dc..507b826 100644
--- a/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.cc
@@ -31,10 +31,12 @@
 // Author: kenton@google.com (Kenton Varda)
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -54,10 +56,9 @@
     }
     // XML escaping... no need for apostrophes etc as the whole text is going to be a child
     // node of a summary element, not part of an attribute.
-    comments = StringReplace(comments, "&", "&amp;", true);
-    comments = StringReplace(comments, "<", "&lt;", true);
+    comments = absl::StrReplaceAll(comments, {{"&", "&amp;"}, {"<", "&lt;"}});
     std::vector<std::string> lines;
-    lines = Split(comments, "\n", false);
+    lines = absl::StrSplit(comments, "\n", absl::AllowEmpty());
     // 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.
     printer->Print("/// <summary>\n");
diff --git a/src/google/protobuf/compiler/csharp/csharp_doc_comment.h b/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
index 75eb0ea..40c35ec 100644
--- a/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
+++ b/src/google/protobuf/compiler/csharp/csharp_doc_comment.h
@@ -32,8 +32,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_DOC_COMMENT_H__
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.cc b/src/google/protobuf/compiler/csharp/csharp_enum.cc
index 73679ca..eaeef31 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.cc
@@ -28,19 +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.
 
+#include "google/protobuf/compiler/csharp/csharp_enum.h"
+
 #include <sstream>
+#include <string>
 
-#include <google/protobuf/compiler/code_generator.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/strutil.h>
-
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_enum.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -57,14 +58,20 @@
 
 void EnumGenerator::Generate(io::Printer* printer) {
   WriteEnumDocComment(printer, descriptor_);
+  if (descriptor_->options().deprecated()) {
+    printer->Print("[global::System.ObsoleteAttribute]\n");
+  }
   printer->Print("$access_level$ enum $name$ {\n",
                  "access_level", class_access_level(),
                  "name", descriptor_->name());
   printer->Indent();
-  std::set<std::string> used_names;
-  std::set<int> used_number;
+  absl::flat_hash_set<std::string> used_names;
+  absl::flat_hash_set<int> used_number;
   for (int i = 0; i < descriptor_->value_count(); i++) {
       WriteEnumValueDocComment(printer, descriptor_->value(i));
+      if (descriptor_->value(i)->options().deprecated()) {
+        printer->Print("[global::System.ObsoleteAttribute]\n");
+      }
       std::string original_name = descriptor_->value(i)->name();
       std::string name =
           GetEnumValueName(descriptor_->name(), descriptor_->value(i)->name());
@@ -80,12 +87,12 @@
           printer->Print("[pbr::OriginalName(\"$original_name$\", PreferredAlias = false)] $name$ = $number$,\n",
              "original_name", original_name,
              "name", name,
-             "number", StrCat(number));
+             "number", absl::StrCat(number));
       } else {
           printer->Print("[pbr::OriginalName(\"$original_name$\")] $name$ = $number$,\n",
              "original_name", original_name,
              "name", name,
-             "number", StrCat(number));
+             "number", absl::StrCat(number));
       }
   }
   printer->Outdent();
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum.h b/src/google/protobuf/compiler/csharp/csharp_enum.h
index e409c2e..098102b 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum.h
@@ -33,10 +33,10 @@
 
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_source_generator_base.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
index 55fb60c..065e1cc 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.cc
@@ -28,18 +28,18 @@
 // (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/csharp/csharp_enum_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
-#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_enum_field.h b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
index 0c6b023..c31d55f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_enum_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_ENUM_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_primitive_field.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.cc b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
index 17847e3..158bf71 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.cc
@@ -28,22 +28,24 @@
 // (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/csharp/csharp_field_base.h"
+
 #include <cmath>
 #include <limits>
 #include <sstream>
+#include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_names.h>
+// Must be last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -51,7 +53,7 @@
 namespace csharp {
 
 void FieldGeneratorBase::SetCommonFieldVariables(
-    std::map<std::string, std::string>* variables) {
+    absl::flat_hash_map<absl::string_view, 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,13 +65,13 @@
   uint tag = internal::WireFormat::MakeTag(descriptor_);
   uint8_t tag_array[5];
   io::CodedOutputStream::WriteTagToArray(tag, tag_array);
-  std::string tag_bytes = StrCat(tag_array[0]);
+  std::string tag_bytes = absl::StrCat(tag_array[0]);
   for (int i = 1; i < part_tag_size; i++) {
-    tag_bytes += ", " + StrCat(tag_array[i]);
+    tag_bytes += ", " + absl::StrCat(tag_array[i]);
   }
 
-  (*variables)["tag"] = StrCat(tag);
-  (*variables)["tag_size"] = StrCat(tag_size);
+  (*variables)["tag"] = absl::StrCat(tag);
+  (*variables)["tag_size"] = absl::StrCat(tag_size);
   (*variables)["tag_bytes"] = tag_bytes;
 
   if (descriptor_->type() == FieldDescriptor::Type::TYPE_GROUP) {
@@ -77,12 +79,12 @@
         descriptor_->number(),
         internal::WireFormatLite::WIRETYPE_END_GROUP);
     io::CodedOutputStream::WriteTagToArray(tag, tag_array);
-    tag_bytes = StrCat(tag_array[0]);
+    tag_bytes = absl::StrCat(tag_array[0]);
     for (int i = 1; i < part_tag_size; i++) {
-        tag_bytes += ", " + StrCat(tag_array[i]);
+        tag_bytes += ", " + absl::StrCat(tag_array[i]);
     }
 
-    variables_["end_tag"] = StrCat(tag);
+    variables_["end_tag"] = absl::StrCat(tag);
     variables_["end_tag_bytes"] = tag_bytes;
   }
 
@@ -97,33 +99,46 @@
   (*variables)["capitalized_type_name"] = capitalized_type_name();
   (*variables)["number"] = number();
   if (has_default_value() && !SupportsPresenceApi(descriptor_)) {
-    (*variables)["name_def_message"] =
-      (*variables)["name"] + "_ = " + (*variables)["default_value"];
+    variables->insert({"name_def_message",
+                       absl::StrCat((*variables)["name"],
+                                    "_ = ", (*variables)["default_value"])});
   } else {
-    (*variables)["name_def_message"] = (*variables)["name"] + "_";
+    variables->insert(
+        {"name_def_message", absl::StrCat((*variables)["name"], "_")});
   }
   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"];
+    variables->insert({"has_property_check",
+                       absl::StrCat("Has", (*variables)["property_name"])});
+    variables->insert(
+        {"other_has_property_check",
+         absl::StrCat("other.Has", (*variables)["property_name"])});
+    variables->insert({"has_not_property_check",
+                       absl::StrCat("!", (*variables)["has_property_check"])});
+    variables->insert(
+        {"other_has_not_property_check",
+         absl::StrCat("!", (*variables)["other_has_property_check"])});
     if (presenceIndex_ != -1) {
-      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;
+        const int hasBitsNumber = presenceIndex_ / 32;
+        const int hasBitsMask = 1 << (presenceIndex_ % 32);
+        (*variables)["has_field_check"] = absl::StrCat(
+            "(_hasBits", hasBitsNumber, " & ", hasBitsMask, ") != 0");
+        (*variables)["set_has_field"] =
+            absl::StrCat("_hasBits", hasBitsNumber, " |= ", hasBitsMask);
+        (*variables)["clear_has_field"] =
+            absl::StrCat("_hasBits", hasBitsNumber, " &= ~", hasBitsMask);
     }
   } else {
-    (*variables)["has_property_check"] =
-      (*variables)["property_name"] + " != " + (*variables)["default_value"];
-    (*variables)["other_has_property_check"] = "other." +
-      (*variables)["property_name"] + " != " + (*variables)["default_value"];
+    variables->insert({"has_property_check",
+                       absl::StrCat((*variables)["property_name"],
+                                    " != ", (*variables)["default_value"])});
+    variables->insert({"other_has_property_check",
+                       absl::StrCat("other.", (*variables)["property_name"],
+                                    " != ", (*variables)["default_value"])});
   }
 }
 
 void FieldGeneratorBase::SetCommonOneofFieldVariables(
-    std::map<std::string, std::string>* variables) {
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   (*variables)["oneof_name"] = oneof_name();
   if (SupportsPresenceApi(descriptor_)) {
     (*variables)["has_property_check"] = "Has" + property_name();
@@ -325,7 +340,7 @@
     else
       return "global::System.Text.Encoding.UTF8.GetString(global::System."
              "Convert.FromBase64String(\"" +
-             StringToBase64(descriptor->default_value_string()) + "\"), 0, " + StrCat(descriptor->default_value_string().length()) + ")";
+             StringToBase64(descriptor->default_value_string()) + "\"), 0, " + absl::StrCat(descriptor->default_value_string().length()) + ")";
 }
 
 std::string FieldGeneratorBase::GetBytesDefaultValueInternal(const FieldDescriptor* descriptor) {
@@ -361,7 +376,7 @@
       } else if (std::isnan(value)) {
         return "double.NaN";
       }
-      return StrCat(value) + "D";
+      return absl::StrCat(value) + "D";
     }
     case FieldDescriptor::TYPE_FLOAT: {
       float value = descriptor->default_value_float();
@@ -372,18 +387,18 @@
       } else if (std::isnan(value)) {
         return "float.NaN";
       }
-      return StrCat(value) + "F";
+      return absl::StrCat(value) + "F";
     }
     case FieldDescriptor::TYPE_INT64:
-      return StrCat(descriptor->default_value_int64()) + "L";
+      return absl::StrCat(descriptor->default_value_int64()) + "L";
     case FieldDescriptor::TYPE_UINT64:
-      return StrCat(descriptor->default_value_uint64()) + "UL";
+      return absl::StrCat(descriptor->default_value_uint64()) + "UL";
     case FieldDescriptor::TYPE_INT32:
-      return StrCat(descriptor->default_value_int32());
+      return absl::StrCat(descriptor->default_value_int32());
     case FieldDescriptor::TYPE_FIXED64:
-      return StrCat(descriptor->default_value_uint64()) + "UL";
+      return absl::StrCat(descriptor->default_value_uint64()) + "UL";
     case FieldDescriptor::TYPE_FIXED32:
-      return StrCat(descriptor->default_value_uint32());
+      return absl::StrCat(descriptor->default_value_uint32());
     case FieldDescriptor::TYPE_BOOL:
       if (descriptor->default_value_bool()) {
         return "true";
@@ -395,15 +410,15 @@
     case FieldDescriptor::TYPE_BYTES:
       return GetBytesDefaultValueInternal(descriptor);
     case FieldDescriptor::TYPE_UINT32:
-      return StrCat(descriptor->default_value_uint32());
+      return absl::StrCat(descriptor->default_value_uint32());
     case FieldDescriptor::TYPE_SFIXED32:
-      return StrCat(descriptor->default_value_int32());
+      return absl::StrCat(descriptor->default_value_int32());
     case FieldDescriptor::TYPE_SFIXED64:
-      return StrCat(descriptor->default_value_int64()) + "L";
+      return absl::StrCat(descriptor->default_value_int64()) + "L";
     case FieldDescriptor::TYPE_SINT32:
-      return StrCat(descriptor->default_value_int32());
+      return absl::StrCat(descriptor->default_value_int32());
     case FieldDescriptor::TYPE_SINT64:
-      return StrCat(descriptor->default_value_int64()) + "L";
+      return absl::StrCat(descriptor->default_value_int64()) + "L";
     default:
       GOOGLE_LOG(FATAL)<< "Unknown field type.";
       return "";
@@ -411,7 +426,7 @@
 }
 
 std::string FieldGeneratorBase::number() {
-  return StrCat(descriptor_->number());
+  return absl::StrCat(descriptor_->number());
 }
 
 std::string FieldGeneratorBase::capitalized_type_name() {
@@ -462,3 +477,5 @@
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/csharp/csharp_field_base.h b/src/google/protobuf/compiler/csharp/csharp_field_base.h
index c7b7469..933bbd4 100644
--- a/src/google/protobuf/compiler/csharp/csharp_field_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_field_base.h
@@ -32,12 +32,16 @@
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_FIELD_BASE_H__
 
 #include <string>
-#include <google/protobuf/stubs/strutil.h>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/compiler/csharp/csharp_source_generator_base.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -74,7 +78,7 @@
  protected:
   const FieldDescriptor* descriptor_;
   const int presenceIndex_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
 
   void AddDeprecatedFlag(io::Printer* printer);
   void AddNullCheck(io::Printer* printer);
@@ -82,7 +86,7 @@
 
   void AddPublicMemberAttributes(io::Printer* printer);
   void SetCommonOneofFieldVariables(
-      std::map<std::string, std::string>* variables);
+      absl::flat_hash_map<absl::string_view, std::string>* variables);
 
   std::string oneof_property_name();
   std::string oneof_case_name(); 
@@ -98,7 +102,8 @@
   std::string capitalized_type_name();
 
  private:
-  void SetCommonFieldVariables(std::map<std::string, std::string>* variables);
+  void SetCommonFieldVariables(
+      absl::flat_hash_map<absl::string_view, 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 5ce0651..0152072 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.cc
@@ -28,20 +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/csharp/csharp_generator.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/strutil.h>
-
-#include <google/protobuf/compiler/csharp/csharp_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_names.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
-#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/compiler/csharp/csharp_reflection_class.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator.h b/src/google/protobuf/compiler/csharp/csharp_generator.h
index f41f9b8..ea2746e 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator.h
+++ b/src/google/protobuf/compiler/csharp/csharp_generator.h
@@ -35,9 +35,9 @@
 
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
+#include "google/protobuf/compiler/code_generator.h"
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -65,6 +65,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
index e21eff1..ca4fb9d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_generator_unittest.cc
@@ -30,14 +30,13 @@
 
 #include <memory>
 
-#include <google/protobuf/any.pb.h>
-#include <google/protobuf/compiler/command_line_interface.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/printer.h>
-
+#include "google/protobuf/any.pb.h"
+#include "google/protobuf/compiler/command_line_interface.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
@@ -74,6 +73,22 @@
   EXPECT_FALSE(IsDescriptorOptionMessage(DescriptorProto::descriptor()));
 }
 
+TEST(CSharpIdentifiers, UnderscoresToCamelCase) {
+	EXPECT_EQ("FooBar", UnderscoresToCamelCase("Foo_Bar", true));
+	EXPECT_EQ("fooBar", UnderscoresToCamelCase("FooBar", false));
+	EXPECT_EQ("foo123", UnderscoresToCamelCase("foo_123", false));
+	// remove leading underscores
+	EXPECT_EQ("Foo123", UnderscoresToCamelCase("_Foo_123", true));
+	// this one has slight unexpected output as it capitalises the first
+	// letter after consuming the underscores, but this was the existing
+	// behaviour so I have not changed it
+	EXPECT_EQ("FooBar", UnderscoresToCamelCase("___fooBar", false));
+	// leave a leading underscore for identifiers that would otherwise
+	// be invalid because they would start with a digit
+	EXPECT_EQ("_123Foo", UnderscoresToCamelCase("_123_foo", true));
+	EXPECT_EQ("_123Foo", UnderscoresToCamelCase("___123_foo", true));
+}
+
 }  // namespace
 }  // namespace csharp
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.cc b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
index 73ca868..1ff5444 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.cc
@@ -32,28 +32,32 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+
 #include <algorithm>
 #include <limits>
-#include <vector>
 #include <sstream>
+#include <vector>
 
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_names.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/compiler/csharp/csharp_enum_field.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
+#include "google/protobuf/compiler/csharp/csharp_map_field.h"
+#include "google/protobuf/compiler/csharp/csharp_message_field.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/compiler/csharp/csharp_primitive_field.h"
+#include "google/protobuf/compiler/csharp/csharp_repeated_enum_field.h"
+#include "google/protobuf/compiler/csharp/csharp_repeated_message_field.h"
+#include "google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h"
+#include "google/protobuf/compiler/csharp/csharp_wrapper_field.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/descriptor.pb.h"
 
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
-#include <google/protobuf/compiler/csharp/csharp_enum_field.h>
-#include <google/protobuf/compiler/csharp/csharp_map_field.h>
-#include <google/protobuf/compiler/csharp/csharp_message_field.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
-#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
-#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
-#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
-#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
-#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+// Must be last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -106,84 +110,6 @@
   return (CSharpType) -1;
 }
 
-std::string StripDotProto(const std::string& proto_file) {
-  int lastindex = proto_file.find_last_of(".");
-  return proto_file.substr(0, lastindex);
-}
-
-std::string GetFileNamespace(const FileDescriptor* descriptor) {
-  if (descriptor->options().has_csharp_namespace()) {
-    return descriptor->options().csharp_namespace();
-  }
-  return UnderscoresToCamelCase(descriptor->package(), true, true);
-}
-
-// Returns the Pascal-cased last part of the proto file. For example,
-// input of "google/protobuf/foo_bar.proto" would result in "FooBar".
-std::string GetFileNameBase(const FileDescriptor* descriptor) {
-    std::string proto_file = descriptor->name();
-    int lastslash = proto_file.find_last_of("/");
-    std::string base = proto_file.substr(lastslash + 1);
-    return UnderscoresToPascalCase(StripDotProto(base));
-}
-
-std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
-  // TODO: Detect collisions with existing messages,
-  // and append an underscore if necessary.
-  return GetFileNameBase(descriptor) + "Reflection";
-}
-
-std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) {
-  // TODO: Detect collisions with existing messages,
-  // and append an underscore if necessary.
-  return GetFileNameBase(descriptor) + "Extensions";
-}
-
-// TODO(jtattermusch): can we reuse a utility function?
-std::string UnderscoresToCamelCase(const std::string& input,
-                                   bool cap_next_letter,
-                                   bool preserve_period) {
-  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') {
-      if (cap_next_letter) {
-        result += input[i] + ('A' - 'a');
-      } else {
-        result += input[i];
-      }
-      cap_next_letter = false;
-    } else if ('A' <= input[i] && input[i] <= 'Z') {
-      if (i == 0 && !cap_next_letter) {
-        // Force first letter to lower-case unless explicitly told to
-        // capitalize it.
-        result += input[i] + ('a' - 'A');
-      } else {
-        // Capital letters after the first are left as-is.
-        result += input[i];
-      }
-      cap_next_letter = false;
-    } else if ('0' <= input[i] && input[i] <= '9') {
-      result += input[i];
-      cap_next_letter = true;
-    } else {
-      cap_next_letter = true;
-      if (input[i] == '.' && preserve_period) {
-        result += '.';
-      }
-    }
-  }
-  // Add a trailing "_" if the name should be altered.
-  if (input.size() > 0 && input[input.size() - 1] == '#') {
-    result += '_';
-  }
-  return result;
-}
-
-std::string UnderscoresToPascalCase(const std::string& input) {
-  return UnderscoresToCamelCase(input, true);
-}
-
 // Convert a string which is expected to be SHOUTY_CASE (but may not be *precisely* shouty)
 // into a PascalCase string. Precise rules implemented:
 
@@ -200,18 +126,18 @@
   char previous = '_';
   for (int i = 0; i < input.size(); i++) {
     char current = input[i];
-    if (!ascii_isalnum(current)) {
+    if (!absl::ascii_isalnum(current)) {
       previous = current;
       continue;
     }
-    if (!ascii_isalnum(previous)) {
-      result += ascii_toupper(current);
-    } else if (ascii_isdigit(previous)) {
-      result += ascii_toupper(current);
-    } else if (ascii_islower(previous)) {
+    if (!absl::ascii_isalnum(previous)) {
+      result += absl::ascii_toupper(current);
+    } else if (absl::ascii_isdigit(previous)) {
+      result += absl::ascii_toupper(current);
+    } else if (absl::ascii_islower(previous)) {
       result += current;
     } else {
-      result += ascii_tolower(current);
+      result += absl::ascii_tolower(current);
     }
     previous = current;
   }
@@ -229,7 +155,7 @@
   std::string prefix_to_match = "";
   for (size_t i = 0; i < prefix.size(); i++) {
     if (prefix[i] != '_') {
-      prefix_to_match += ascii_tolower(prefix[i]);
+      prefix_to_match += absl::ascii_tolower(prefix[i]);
     }
   }
 
@@ -242,7 +168,7 @@
     if (value[value_index] == '_') {
       continue;
     }
-    if (ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
+    if (absl::ascii_tolower(value[value_index]) != prefix_to_match[prefix_index++]) {
       // Failed to match the prefix - bail out early.
       return value;
     }
@@ -276,7 +202,7 @@
   std::string result = ShoutyToPascalCase(stripped);
   // Just in case we have an enum name of FOO and a value of FOO_2... make sure the returned
   // string is a valid identifier.
-  if (ascii_isdigit(result[0])) {
+  if (absl::ascii_isdigit(result[0])) {
     result = "_" + result;
   }
   return result;
@@ -320,32 +246,6 @@
   return 0;
 }
 
-std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
-  std::string result = GetFileNamespace(file);
-  if (!result.empty()) {
-    result += '.';
-  }
-  std::string classname;
-  if (file->package().empty()) {
-    classname = name;
-  } else {
-    // Strip the proto package from full_name since we've replaced it with
-    // the C# namespace.
-    classname = name.substr(file->package().size() + 1);
-  }
-  result += StringReplace(classname, ".", ".Types.", true);
-  return "global::" + result;
-}
-
-std::string GetReflectionClassName(const FileDescriptor* descriptor) {
-  std::string result = GetFileNamespace(descriptor);
-  if (!result.empty()) {
-    result += '.';
-  }
-  result += GetReflectionClassUnqualifiedName(descriptor);
-  return "global::" + result;
-}
-
 std::string GetFullExtensionName(const FieldDescriptor* descriptor) {
   if (descriptor->extension_scope()) {
     return GetClassName(descriptor->extension_scope()) + ".Extensions." + GetPropertyName(descriptor);
@@ -355,14 +255,6 @@
   }
 }
 
-std::string GetClassName(const Descriptor* descriptor) {
-  return ToCSharpName(descriptor->full_name(), descriptor->file());
-}
-
-std::string GetClassName(const EnumDescriptor* descriptor) {
-  return ToCSharpName(descriptor->full_name(), descriptor->file());
-}
-
 // Groups are hacky:  The name of the field is just the lower-cased name
 // of the group type.  In C#, though, we would like to retain the original
 // capitalization of the type name.
@@ -379,15 +271,30 @@
 }
 
 std::string GetPropertyName(const FieldDescriptor* descriptor) {
+  // Names of members declared or overridden in the message.
+  static const auto& reserved_member_names = *new absl::flat_hash_set<absl::string_view>({
+    "Types",
+    "Descriptor",
+    "Equals",
+    "ToString",
+    "GetHashCode",
+    "WriteTo",
+    "Clone",
+    "CalculateSize",
+    "MergeFrom",
+    "OnConstruction",
+    "Parser"
+    });
+
   // TODO(jtattermusch): consider introducing csharp_property_name field option
   std::string property_name = UnderscoresToPascalCase(GetFieldName(descriptor));
-  // Avoid either our own type name or reserved names. Note that not all names
-  // are reserved - a field called to_string, write_to etc would still cause a problem.
+  // Avoid either our own type name or reserved names.
   // There are various ways of ending up with naming collisions, but we try to avoid obvious
-  // ones.
+  // ones. In particular, we avoid the names of all the members we generate.
+  // Note that we *don't* add an underscore for MemberwiseClone or GetType. Those generate
+  // warnings, but not errors; changing the name now could be a breaking change.
   if (property_name == descriptor->containing_type()->name()
-      || property_name == "Types"
-      || property_name == "Descriptor") {
+      || reserved_member_names.find(property_name) != reserved_member_names.end()) {
     property_name += "_";
   }
   return property_name;
@@ -400,40 +307,6 @@
   return property_name == "None" ? "None_" : property_name;
 }
 
-std::string GetOutputFile(const FileDescriptor* descriptor,
-                          const std::string file_extension,
-                          const bool generate_directories,
-                          const std::string base_namespace,
-                          std::string* error) {
-  std::string relative_filename = GetFileNameBase(descriptor) + file_extension;
-  if (!generate_directories) {
-    return relative_filename;
-  }
-  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.
-    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.
-    }
-    namespace_suffix = ns.substr(base_namespace.length());
-    if (namespace_suffix.find(".") == 0) {
-      namespace_suffix = namespace_suffix.substr(1);
-    }
-  }
-
-  std::string namespace_dir = StringReplace(namespace_suffix, ".", "/", true);
-  if (!namespace_dir.empty()) {
-    namespace_dir += "/";
-  }
-  return namespace_dir + relative_filename;
-}
-
 // TODO: c&p from Java protoc plugin
 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
 // returns -1.
@@ -597,3 +470,5 @@
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/csharp/csharp_helpers.h b/src/google/protobuf/compiler/csharp/csharp_helpers.h
index 836bd5d..b9aa556 100644
--- a/src/google/protobuf/compiler/csharp/csharp_helpers.h
+++ b/src/google/protobuf/compiler/csharp/csharp_helpers.h
@@ -36,14 +36,15 @@
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
 
 #include <string>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/io/printer.h>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -72,15 +73,6 @@
 // Converts field type to corresponding C# type.
 CSharpType GetCSharpType(FieldDescriptor::Type type);
 
-std::string StripDotProto(const std::string& proto_file);
-
-// Gets unqualified name of the reflection class
-std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
-// Gets unqualified name of the extension class
-std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor);
-
-std::string GetClassName(const EnumDescriptor* descriptor);
-
 std::string GetFieldName(const FieldDescriptor* descriptor);
 
 std::string GetFieldConstantName(const FieldDescriptor* field);
@@ -91,16 +83,6 @@
 
 int GetFixedSize(FieldDescriptor::Type type);
 
-std::string UnderscoresToCamelCase(const std::string& input,
-                                   bool cap_next_letter,
-                                   bool preserve_period);
-
-inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
-  return UnderscoresToCamelCase(input, cap_next_letter, false);
-}
-
-std::string UnderscoresToPascalCase(const std::string& input);
-
 // Note that we wouldn't normally want to export this (we're not expecting
 // it to be used outside libprotoc itself) but this exposes it for testing.
 std::string PROTOC_EXPORT GetEnumValueName(const std::string& enum_name,
@@ -193,6 +175,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_HELPERS_H__
diff --git a/src/google/protobuf/compiler/csharp/csharp_map_field.cc b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
index a13b995..062e3a7 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.cc
@@ -28,18 +28,16 @@
 // (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/csharp/csharp_map_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/strutil.h>
-
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_map_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -88,9 +86,8 @@
 }
 
 void MapFieldGenerator::GenerateMergingCode(io::Printer* printer) {
-  printer->Print(
-      variables_,
-      "$name$_.Add(other.$name$_);\n");
+  printer->Print(variables_,
+                 "$name$_.MergeFrom(other.$name$_);\n");
 }
 
 void MapFieldGenerator::GenerateParsingCode(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 23b3619..c4713d0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_map_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_map_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_MAP_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.cc b/src/google/protobuf/compiler/csharp/csharp_message.cc
index a119bdd..d5c803f 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message.cc
@@ -28,26 +28,28 @@
 // (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 <sstream>
+#include "google/protobuf/compiler/csharp/csharp_message.h"
+
 #include <algorithm>
-#include <map>
+#include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/strutil.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_enum.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
 
-#include <google/protobuf/compiler/csharp/csharp_options.h>
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_enum.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_message.h>
-#include <google/protobuf/compiler/csharp/csharp_names.h>
+// Must be last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -112,7 +114,7 @@
 }
 
 void MessageGenerator::Generate(io::Printer* printer) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["class_name"] = class_name();
   vars["access_level"] = class_access_level();
 
@@ -161,7 +163,7 @@
   for (int i = 0; i < has_bit_field_count_; i++) {
     // don't use arrays since all arrays are heap allocated, saving allocations
     // use ints instead of bytes since bytes lack bitwise operators, saving casts
-    printer->Print("private int _hasBits$i$;\n", "i", StrCat(i));
+    printer->Print("private int _hasBits$i$;\n", "i", absl::StrCat(i));
   }
 
   WriteGeneratedCodeAttributes(printer);
@@ -173,10 +175,10 @@
   // Access the message descriptor via the relevant file descriptor or containing message descriptor.
   if (!descriptor_->containing_type()) {
     vars["descriptor_accessor"] = GetReflectionClassName(descriptor_->file())
-        + ".Descriptor.MessageTypes[" + StrCat(descriptor_->index()) + "]";
+        + ".Descriptor.MessageTypes[" + absl::StrCat(descriptor_->index()) + "]";
   } else {
     vars["descriptor_accessor"] = GetClassName(descriptor_->containing_type())
-        + ".Descriptor.NestedTypes[" + StrCat(descriptor_->index()) + "]";
+        + ".Descriptor.NestedTypes[" + absl::StrCat(descriptor_->index()) + "]";
   }
 
   WriteGeneratedCodeAttributes(printer);
@@ -216,7 +218,7 @@
       "public const int $field_constant_name$ = $index$;\n",
       "field_name", fieldDescriptor->name(),
       "field_constant_name", GetFieldConstantName(fieldDescriptor),
-      "index", StrCat(fieldDescriptor->number()));
+      "index", absl::StrCat(fieldDescriptor->number()));
     std::unique_ptr<FieldGeneratorBase> generator(
         CreateFieldGeneratorInternal(fieldDescriptor));
     generator->GenerateMembers(printer);
@@ -240,7 +242,7 @@
       const FieldDescriptor* field = oneof->field(j);
       printer->Print("$oneof_case_name$ = $index$,\n",
                      "oneof_case_name", GetOneofCaseName(field),
-                     "index", StrCat(field->number()));
+                     "index", absl::StrCat(field->number()));
     }
     printer->Outdent();
     printer->Print("}\n");
@@ -374,7 +376,7 @@
 }
 
 void MessageGenerator::GenerateCloningCode(io::Printer* printer) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   WriteGeneratedCodeAttributes(printer);
   vars["class_name"] = class_name();
     printer->Print(
@@ -382,7 +384,7 @@
     "public $class_name$($class_name$ other) : this() {\n");
   printer->Indent();
   for (int i = 0; i < has_bit_field_count_; i++) {
-    printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", StrCat(i));
+    printer->Print("_hasBits$i$ = other._hasBits$i$;\n", "i", absl::StrCat(i));
   }
   // Clone non-oneof fields first (treating optional proto3 fields as non-oneof)
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -438,32 +440,30 @@
 }
 
 void MessageGenerator::GenerateFrameworkMethods(io::Printer* printer) {
-    std::map<std::string, std::string> vars;
-    vars["class_name"] = class_name();
+  absl::flat_hash_map<absl::string_view, std::string> vars;
+  vars["class_name"] = class_name();
 
-    // Equality
-    WriteGeneratedCodeAttributes(printer);
-    printer->Print(
-        vars,
-        "public override bool Equals(object other) {\n"
-        "  return Equals(other as $class_name$);\n"
-        "}\n\n");
-    WriteGeneratedCodeAttributes(printer);
-    printer->Print(
-        vars,
-        "public bool Equals($class_name$ other) {\n"
-        "  if (ReferenceEquals(other, null)) {\n"
-        "    return false;\n"
-        "  }\n"
-        "  if (ReferenceEquals(other, this)) {\n"
-        "    return true;\n"
-        "  }\n");
-    printer->Indent();
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      std::unique_ptr<FieldGeneratorBase> generator(
-            CreateFieldGeneratorInternal(descriptor_->field(i)));
-        generator->WriteEquals(printer);
-    }
+  // Equality
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print(vars,
+                 "public override bool Equals(object other) {\n"
+                 "  return Equals(other as $class_name$);\n"
+                 "}\n\n");
+  WriteGeneratedCodeAttributes(printer);
+  printer->Print(vars,
+                 "public bool Equals($class_name$ other) {\n"
+                 "  if (ReferenceEquals(other, null)) {\n"
+                 "    return false;\n"
+                 "  }\n"
+                 "  if (ReferenceEquals(other, this)) {\n"
+                 "    return true;\n"
+                 "  }\n");
+  printer->Indent();
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    std::unique_ptr<FieldGeneratorBase> generator(
+        CreateFieldGeneratorInternal(descriptor_->field(i)));
+    generator->WriteEquals(printer);
+  }
     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));
@@ -605,7 +605,7 @@
   // Note:  These are separate from GenerateMessageSerializationMethods()
   //   because they need to be generated even for messages that are optimized
   //   for code size.
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["class_name"] = class_name();
 
   WriteGeneratedCodeAttributes(printer);
@@ -685,7 +685,7 @@
 }
 
 void MessageGenerator::GenerateMainParseLoop(io::Printer* printer, bool use_parse_context) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["maybe_ref_input"] = use_parse_context ? "ref input" : "input";
 
   printer->Print(
@@ -698,7 +698,7 @@
     printer->Print(
         "case $end_tag$:\n"
         "  return;\n",
-        "end_tag", StrCat(end_tag_));
+        "end_tag", absl::StrCat(end_tag_));
   }
   if (has_extension_ranges_) {
     printer->Print(vars,
@@ -727,13 +727,13 @@
       printer->Print(
         "case $packed_tag$:\n",
         "packed_tag",
-        StrCat(
+        absl::StrCat(
             internal::WireFormatLite::MakeTag(
                 field->number(),
                 internal::WireFormatLite::WIRETYPE_LENGTH_DELIMITED)));
     }
 
-    printer->Print("case $tag$: {\n", "tag", StrCat(tag));
+    printer->Print("case $tag$: {\n", "tag", absl::StrCat(tag));
     printer->Indent();
     std::unique_ptr<FieldGeneratorBase> generator(
         CreateFieldGeneratorInternal(field));
@@ -777,3 +777,5 @@
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/csharp/csharp_message.h b/src/google/protobuf/compiler/csharp/csharp_message.h
index d02767e..86025dc 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message.h
@@ -34,9 +34,9 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_source_generator_base.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.cc b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
index 487d01d..1f30bdc 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.cc
@@ -28,21 +28,17 @@
 // (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/csharp/csharp_message_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/strutil.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
-
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_message_field.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_message_field.h b/src/google/protobuf/compiler/csharp/csharp_message_field.h
index e76dfd2..fbbe4c4 100644
--- a/src/google/protobuf/compiler/csharp/csharp_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_message_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_MESSAGE_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
index e7d5116..1467bd3 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.cc
@@ -28,19 +28,18 @@
 // (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/csharp/csharp_primitive_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/strutil.h>
-
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
-#include <google/protobuf/compiler/csharp/csharp_primitive_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -215,7 +214,7 @@
   } else {
     printer->Print(
       "size += $tag_size$ + $fixed_size$;\n",
-      "fixed_size", StrCat(fixedSize),
+      "fixed_size", absl::StrCat(fixedSize),
       "tag_size", variables_["tag_size"]);
   }
   printer->Outdent();
diff --git a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
index 6d495d5..d6fb715 100644
--- a/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_primitive_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_PRIMITIVE_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
index d9ab4b4..c6d6cd0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.cc
@@ -28,23 +28,24 @@
 // (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/csharp/csharp_reflection_class.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/strutil.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/strings/str_join.h"
+#include "google/protobuf/compiler/csharp/csharp_enum.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_message.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
-
-#include <google/protobuf/compiler/csharp/csharp_enum.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
-#include <google/protobuf/compiler/csharp/csharp_message.h>
-#include <google/protobuf/compiler/csharp/csharp_names.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
-#include <google/protobuf/compiler/csharp/csharp_reflection_class.h>
+// Must be last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -213,7 +214,7 @@
     for (int i = 0; i < file_->extension_count(); i++) {
       extensions.push_back(GetFullExtensionName(file_->extension(i)));
     }
-    printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
+    printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", absl::StrJoin(extensions, ", "));
   }
   else {
     printer->Print("null, ");
@@ -265,7 +266,7 @@
       for (int i = 0; i < descriptor->field_count(); i++) {
           fields.push_back(GetPropertyName(descriptor->field(i)));
       }
-      printer->Print("new[]{ \"$fields$\" }, ", "fields", Join(fields, "\", \""));
+      printer->Print("new[]{ \"$fields$\" }, ", "fields", absl::StrJoin(fields, "\", \""));
   }
   else {
       printer->Print("null, ");
@@ -278,7 +279,7 @@
       for (int i = 0; i < descriptor->oneof_decl_count(); i++) {
           oneofs.push_back(UnderscoresToCamelCase(descriptor->oneof_decl(i)->name(), true));
       }
-      printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", Join(oneofs, "\", \""));
+      printer->Print("new[]{ \"$oneofs$\" }, ", "oneofs", absl::StrJoin(oneofs, "\", \""));
   }
   else {
       printer->Print("null, ");
@@ -291,7 +292,7 @@
       for (int i = 0; i < descriptor->enum_type_count(); i++) {
           enums.push_back(GetClassName(descriptor->enum_type(i)));
       }
-      printer->Print("new[]{ typeof($enums$) }, ", "enums", Join(enums, "), typeof("));
+      printer->Print("new[]{ typeof($enums$) }, ", "enums", absl::StrJoin(enums, "), typeof("));
   }
   else {
       printer->Print("null, ");
@@ -303,7 +304,7 @@
     for (int i = 0; i < descriptor->extension_count(); i++) {
       extensions.push_back(GetFullExtensionName(descriptor->extension(i)));
     }
-    printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", Join(extensions, ", "));
+    printer->Print("new pb::Extension[] { $extensions$ }, ", "extensions", absl::StrJoin(extensions, ", "));
   }
   else {
     printer->Print("null, ");
@@ -328,3 +329,5 @@
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
index 9554727..daffb32 100644
--- a/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
+++ b/src/google/protobuf/compiler/csharp/csharp_reflection_class.h
@@ -33,10 +33,10 @@
 
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_source_generator_base.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_source_generator_base.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
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 04bc7bb..1a9fd1d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.cc
@@ -28,18 +28,18 @@
 // (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/csharp/csharp_repeated_enum_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/wire_format.h>
-
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_repeated_enum_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
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 2379f38..08ce992 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_enum_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_ENUM_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
 
 namespace google {
 namespace protobuf {
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 8a93cd1..6ac7e2d 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.cc
@@ -28,19 +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/csharp/csharp_repeated_message_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_repeated_message_field.h>
-#include <google/protobuf/compiler/csharp/csharp_message_field.h>
-#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_message_field.h"
+#include "google/protobuf/compiler/csharp/csharp_wrapper_field.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
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 026efea..f2c935a 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_message_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_MESSAGE_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
 
 namespace google {
 namespace protobuf {
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 0eacf91..df97ccf 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.cc
@@ -28,18 +28,18 @@
 // (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/csharp/csharp_repeated_primitive_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/wire_format.h>
-
-#include <google/protobuf/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
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 bdd12a0..92485a2 100644
--- a/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_repeated_primitive_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_REPEATED_PRIMITIVE_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
 
 namespace google {
 namespace protobuf {
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 7157e6e..f12db82 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.cc
@@ -28,18 +28,18 @@
 // (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/csharp/csharp_source_generator_base.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/compiler/csharp/csharp_source_generator_base.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_names.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
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 17a5269..01b0187 100644
--- a/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
+++ b/src/google/protobuf/compiler/csharp/csharp_source_generator_base.h
@@ -33,8 +33,8 @@
 
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
index e638dd8..2569082 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.cc
@@ -28,18 +28,18 @@
 // (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/csharp/csharp_wrapper_field.h"
+
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.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/compiler/csharp/csharp_doc_comment.h>
-#include <google/protobuf/compiler/csharp/csharp_helpers.h>
-#include <google/protobuf/compiler/csharp/csharp_options.h>
-#include <google/protobuf/compiler/csharp/csharp_wrapper_field.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/csharp/csharp_doc_comment.h"
+#include "google/protobuf/compiler/csharp/csharp_helpers.h"
+#include "google/protobuf/compiler/csharp/csharp_options.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
index cc8a313..6b15aa0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
+++ b/src/google/protobuf/compiler/csharp/csharp_wrapper_field.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_WRAPPER_FIELD_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/csharp/csharp_field_base.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/csharp/csharp_field_base.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/csharp/names.cc b/src/google/protobuf/compiler/csharp/names.cc
new file mode 100644
index 0000000..b4ca408
--- /dev/null
+++ b/src/google/protobuf/compiler/csharp/names.cc
@@ -0,0 +1,225 @@
+// 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.
+
+#include "google/protobuf/compiler/csharp/names.h"
+
+#include <string>
+
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/compiler/csharp/names.h"
+#include "google/protobuf/descriptor.pb.h"
+
+// Must be last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace csharp {
+
+namespace {
+
+std::string StripDotProto(const std::string& proto_file) {
+  int lastindex = proto_file.find_last_of('.');
+  return proto_file.substr(0, lastindex);
+}
+
+// Returns the Pascal-cased last part of the proto file. For example,
+// input of "google/protobuf/foo_bar.proto" would result in "FooBar".
+std::string GetFileNameBase(const FileDescriptor* descriptor) {
+    std::string proto_file = descriptor->name();
+    int lastslash = proto_file.find_last_of('/');
+    std::string base = proto_file.substr(lastslash + 1);
+    return UnderscoresToPascalCase(StripDotProto(base));
+}
+
+std::string ToCSharpName(const std::string& name, const FileDescriptor* file) {
+  std::string result = GetFileNamespace(file);
+  if (!result.empty()) {
+    result += '.';
+  }
+  std::string classname;
+  if (file->package().empty()) {
+    classname = name;
+  } else {
+    // Strip the proto package from full_name since we've replaced it with
+    // the C# namespace.
+    classname = name.substr(file->package().size() + 1);
+  }
+  result += absl::StrReplaceAll(classname, {{".", ".Types."}});
+  return "global::" + result;
+}
+
+}  // namespace
+
+std::string GetFileNamespace(const FileDescriptor* descriptor) {
+  if (descriptor->options().has_csharp_namespace()) {
+    return descriptor->options().csharp_namespace();
+  }
+  return UnderscoresToCamelCase(descriptor->package(), true, true);
+}
+
+std::string GetClassName(const Descriptor* descriptor) {
+  return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+std::string GetClassName(const EnumDescriptor* descriptor) {
+  return ToCSharpName(descriptor->full_name(), descriptor->file());
+}
+
+std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor) {
+  // TODO: Detect collisions with existing messages,
+  // and append an underscore if necessary.
+  return GetFileNameBase(descriptor) + "Reflection";
+}
+
+std::string GetReflectionClassName(const FileDescriptor* descriptor) {
+  std::string result = GetFileNamespace(descriptor);
+  if (!result.empty()) {
+    result += '.';
+  }
+  result += GetReflectionClassUnqualifiedName(descriptor);
+  return "global::" + result;
+}
+
+std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor) {
+  // TODO: Detect collisions with existing messages,
+  // and append an underscore if necessary.
+  return GetFileNameBase(descriptor) + "Extensions";
+}
+
+std::string GetOutputFile(const FileDescriptor* descriptor,
+                          const std::string file_extension,
+                          const bool generate_directories,
+                          const std::string base_namespace,
+                          std::string* error) {
+  std::string relative_filename = GetFileNameBase(descriptor) + file_extension;
+  if (!generate_directories) {
+    return relative_filename;
+  }
+  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.
+    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.
+    }
+    namespace_suffix = ns.substr(base_namespace.length());
+    if (namespace_suffix.find('.') == 0) {
+      namespace_suffix = namespace_suffix.substr(1);
+    }
+  }
+
+  std::string namespace_dir =
+      absl::StrReplaceAll(namespace_suffix, {{".", "/"}});
+  if (!namespace_dir.empty()) {
+    namespace_dir += "/";
+  }
+  return namespace_dir + relative_filename;
+}
+
+std::string UnderscoresToPascalCase(const std::string& input) {
+  return UnderscoresToCamelCase(input, true);
+}
+
+// TODO(jtattermusch): can we reuse a utility function?
+std::string UnderscoresToCamelCase(const std::string& input,
+                                   bool cap_next_letter,
+                                   bool preserve_period) {
+  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') {
+      if (cap_next_letter) {
+        result += input[i] + ('A' - 'a');
+      } else {
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('A' <= input[i] && input[i] <= 'Z') {
+      if (i == 0 && !cap_next_letter) {
+        // Force first letter to lower-case unless explicitly told to
+        // capitalize it.
+        result += input[i] + ('a' - 'A');
+      } else {
+        // Capital letters after the first are left as-is.
+        result += input[i];
+      }
+      cap_next_letter = false;
+    } else if ('0' <= input[i] && input[i] <= '9') {
+      result += input[i];
+      cap_next_letter = true;
+    } else {
+      cap_next_letter = true;
+      if (input[i] == '.' && preserve_period) {
+        result += '.';
+      }
+    }
+  }
+  // Add a trailing "_" if the name should be altered.
+  if (input.size() > 0 && input[input.size() - 1] == '#') {
+    result += '_';
+  }
+
+  // https://github.com/protocolbuffers/protobuf/issues/8101
+  // To avoid generating invalid identifiers - if the input string
+  // starts with _<digit> (or multiple underscores then digit) then
+  // we need to preserve the underscore as an identifier cannot start
+  // with a digit.
+  // This check is being done after the loop rather than before
+  // to handle the case where there are multiple underscores before the
+  // first digit. We let them all be consumed so we can see if we would
+  // start with a digit.
+  // Note: not preserving leading underscores for all otherwise valid identifiers
+  // so as to not break anything that relies on the existing behaviour
+  if (result.size() > 0 && ('0' <= result[0] && result[0] <= '9')
+      && input.size() > 0 && input[0] == '_')
+  {
+      result.insert(0, 1, '_');
+  }
+  return result;
+}
+
+}  // namespace csharp
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/csharp/csharp_names.h b/src/google/protobuf/compiler/csharp/names.h
similarity index 70%
rename from src/google/protobuf/compiler/csharp/csharp_names.h
rename to src/google/protobuf/compiler/csharp/names.h
index 67e53b6..4826ea0 100644
--- a/src/google/protobuf/compiler/csharp/csharp_names.h
+++ b/src/google/protobuf/compiler/csharp/names.h
@@ -39,10 +39,8 @@
 #define GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
 
 #include <string>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/common.h>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -73,9 +71,35 @@
 //   descriptor != NULL
 //
 // Returns:
-//   The fully-qualified name of the C# class that provides
-//   access to the file descriptor. Proto compiler generates
+//   The fully-qualified C# enum class name.
+std::string GetClassName(const EnumDescriptor* descriptor);
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The unqualified name of the C# class that provides access to the file
+//   descriptor. Proto compiler generates
 //   such class for each .proto file processed.
+std::string GetReflectionClassUnqualifiedName(const FileDescriptor* descriptor);
+
+// Gets unqualified name of the extension class
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   The unqualified name of the generated C# extensions class that provide
+//   access to extensions. Proto compiler generates such class for each
+//   .proto file processed that contains extensions.
+std::string GetExtensionClassUnqualifiedName(const FileDescriptor* descriptor);
+
+// Requires:
+//   descriptor != NULL
+//
+// Returns:
+//   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.
 std::string PROTOC_EXPORT
 GetReflectionClassName(const FileDescriptor* descriptor);
 
@@ -99,11 +123,23 @@
                                         const std::string base_namespace,
                                         std::string* error);
 
+std::string UnderscoresToPascalCase(const std::string& input);
+
+// Note that we wouldn't normally want to export this (we're not expecting
+// it to be used outside libprotoc itself) but this exposes it for testing.
+std::string PROTOC_EXPORT UnderscoresToCamelCase(const std::string& input,
+                                   bool cap_next_letter,
+                                   bool preserve_period);
+
+inline std::string UnderscoresToCamelCase(const std::string& input, bool cap_next_letter) {
+  return UnderscoresToCamelCase(input, cap_next_letter, false);
+}
+
 }  // namespace csharp
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_CSHARP_NAMES_H__
diff --git a/src/google/protobuf/compiler/importer.cc b/src/google/protobuf/compiler/importer.cc
index f1e26f8..a2de7e5 100644
--- a/src/google/protobuf/compiler/importer.cc
+++ b/src/google/protobuf/compiler/importer.cc
@@ -32,6 +32,8 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
+#include "google/protobuf/compiler/importer.h"
+
 #ifdef _MSC_VER
 #include <direct.h>
 #else
@@ -44,13 +46,17 @@
 
 #include <algorithm>
 #include <memory>
+#include <vector>
 
-#include <google/protobuf/compiler/importer.h>
-#include <google/protobuf/compiler/parser.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/io_win32.h>
+#include "absl/strings/match.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/compiler/parser.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
 
 #ifdef _WIN32
 #include <ctype.h>
@@ -70,7 +76,7 @@
 // Returns true if the text looks like a Windows-style absolute path, starting
 // with a drive letter.  Example:  "C:\foo".  TODO(kenton):  Share this with
 // copy in command_line_interface.cc?
-static bool IsWindowsAbsolutePath(const std::string& text) {
+static bool IsWindowsAbsolutePath(absl::string_view text) {
 #if defined(_WIN32) || defined(__CYGWIN__)
   return text.size() >= 3 && text[1] == ':' && isalpha(text[0]) &&
          (text[2] == '/' || text[2] == '\\') && text.find_last_of(':') == 1;
@@ -251,10 +257,6 @@
 
 DiskSourceTree::~DiskSourceTree() {}
 
-static inline char LastChar(const std::string& str) {
-  return str[str.size() - 1];
-}
-
 // Given a path, returns an equivalent path with these changes:
 // - On Windows, any backslashes are replaced with forward slashes.
 // - Any instances of the directory "." are removed.
@@ -274,45 +276,38 @@
 //   then if foo/bar is a symbolic link, foo/bar/baz.proto will canonicalize
 //   to a path which does not appear to be under foo, and thus the compiler
 //   will complain that baz.proto is not inside the --proto_path.
-static std::string CanonicalizePath(std::string path) {
+static std::string CanonicalizePath(absl::string_view path) {
 #ifdef _WIN32
   // The Win32 API accepts forward slashes as a path delimiter even though
   // backslashes are standard.  Let's avoid confusion and use only forward
   // slashes.
-  if (HasPrefixString(path, "\\\\")) {
+  std::string path_str;
+  if (absl::StartsWith(path, "\\\\")) {
     // Avoid converting two leading backslashes.
-    path = "\\\\" + StringReplace(path.substr(2), "\\", "/", true);
+    path_str = "\\\\" + absl::StrReplaceAll(path.substr(2), {{"\\", "/"}});
   } else {
-    path = StringReplace(path, "\\", "/", true);
+    path_str = absl::StrReplaceAll(path, {{"\\", "/"}});
   }
+  path = path_str;
 #endif
 
-  std::vector<std::string> canonical_parts;
-  std::vector<std::string> parts = Split(
-      path, "/", true);  // Note:  Removes empty parts.
-  for (const std::string& part : parts) {
+  std::vector<absl::string_view> canonical_parts;
+  if (!path.empty() && path.front() == '/') canonical_parts.push_back("");
+  for (absl::string_view part : absl::StrSplit(path, '/', absl::SkipEmpty())) {
     if (part == ".") {
       // Ignore.
     } else {
       canonical_parts.push_back(part);
     }
   }
-  std::string result = Join(canonical_parts, "/");
-  if (!path.empty() && path[0] == '/') {
-    // Restore leading slash.
-    result = '/' + result;
-  }
-  if (!path.empty() && LastChar(path) == '/' && !result.empty() &&
-      LastChar(result) != '/') {
-    // Restore trailing slash.
-    result += '/';
-  }
-  return result;
+  if (!path.empty() && path.back() == '/') canonical_parts.push_back("");
+
+  return absl::StrJoin(canonical_parts, "/");
 }
 
-static inline bool ContainsParentReference(const std::string& path) {
-  return path == ".." || HasPrefixString(path, "../") ||
-         HasSuffixString(path, "/..") || path.find("/../") != std::string::npos;
+static inline bool ContainsParentReference(absl::string_view path) {
+  return path == ".." || absl::StartsWith(path, "../") ||
+         absl::EndsWith(path, "/..") || absl::StrContains(path, "/../");
 }
 
 // Maps a file from an old location to a new one.  Typically, old_prefix is
@@ -332,28 +327,28 @@
 //   assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
 //   assert(!ApplyMapping("foo/bar", "baz", "qux", &result));
 //   assert(!ApplyMapping("foobar", "foo", "baz", &result));
-static bool ApplyMapping(const std::string& filename,
-                         const std::string& old_prefix,
-                         const std::string& new_prefix, std::string* result) {
+static bool ApplyMapping(absl::string_view filename,
+                         absl::string_view old_prefix,
+                         absl::string_view new_prefix, std::string* result) {
   if (old_prefix.empty()) {
     // old_prefix matches any relative path.
     if (ContainsParentReference(filename)) {
       // We do not allow the file name to use "..".
       return false;
     }
-    if (HasPrefixString(filename, "/") || IsWindowsAbsolutePath(filename)) {
+    if (absl::StartsWith(filename, "/") || IsWindowsAbsolutePath(filename)) {
       // This is an absolute path, so it isn't matched by the empty string.
       return false;
     }
-    result->assign(new_prefix);
+    result->assign(std::string(new_prefix));
     if (!result->empty()) result->push_back('/');
-    result->append(filename);
+    result->append(std::string(filename));
     return true;
-  } else if (HasPrefixString(filename, old_prefix)) {
+  } else if (absl::StartsWith(filename, old_prefix)) {
     // old_prefix is a prefix of the filename.  Is it the whole filename?
     if (filename.size() == old_prefix.size()) {
       // Yep, it's an exact match.
-      *result = new_prefix;
+      *result = std::string(new_prefix);
       return true;
     } else {
       // Not an exact match.  Is the next character a '/'?  Otherwise,
@@ -370,14 +365,14 @@
       if (after_prefix_start != -1) {
         // Yep.  So the prefixes are directories and the filename is a file
         // inside them.
-        std::string after_prefix = filename.substr(after_prefix_start);
+        absl::string_view after_prefix = filename.substr(after_prefix_start);
         if (ContainsParentReference(after_prefix)) {
           // We do not allow the file name to use "..".
           return false;
         }
-        result->assign(new_prefix);
+        result->assign(std::string(new_prefix));
         if (!result->empty()) result->push_back('/');
-        result->append(after_prefix);
+        result->append(std::string(after_prefix));
         return true;
       }
     }
@@ -386,13 +381,14 @@
   return false;
 }
 
-void DiskSourceTree::MapPath(const std::string& virtual_path,
-                             const std::string& disk_path) {
-  mappings_.push_back(Mapping(virtual_path, CanonicalizePath(disk_path)));
+void DiskSourceTree::MapPath(absl::string_view virtual_path,
+                             absl::string_view disk_path) {
+  mappings_.push_back(
+      Mapping(std::string(virtual_path), CanonicalizePath(disk_path)));
 }
 
 DiskSourceTree::DiskFileToVirtualFileResult
-DiskSourceTree::DiskFileToVirtualFile(const std::string& disk_file,
+DiskSourceTree::DiskFileToVirtualFile(absl::string_view disk_file,
                                       std::string* virtual_file,
                                       std::string* shadowing_disk_file) {
   int mapping_index = -1;
@@ -436,14 +432,14 @@
   return SUCCESS;
 }
 
-bool DiskSourceTree::VirtualFileToDiskFile(const std::string& virtual_file,
+bool DiskSourceTree::VirtualFileToDiskFile(absl::string_view virtual_file,
                                            std::string* disk_file) {
   std::unique_ptr<io::ZeroCopyInputStream> stream(
       OpenVirtualFile(virtual_file, disk_file));
   return stream != nullptr;
 }
 
-io::ZeroCopyInputStream* DiskSourceTree::Open(const std::string& filename) {
+io::ZeroCopyInputStream* DiskSourceTree::Open(absl::string_view filename) {
   return OpenVirtualFile(filename, nullptr);
 }
 
@@ -452,7 +448,7 @@
 }
 
 io::ZeroCopyInputStream* DiskSourceTree::OpenVirtualFile(
-    const std::string& virtual_file, std::string* disk_file) {
+    absl::string_view virtual_file, std::string* disk_file) {
   if (virtual_file != CanonicalizePath(virtual_file) ||
       ContainsParentReference(virtual_file)) {
     // We do not allow importing of paths containing things like ".." or
@@ -489,11 +485,11 @@
 }
 
 io::ZeroCopyInputStream* DiskSourceTree::OpenDiskFile(
-    const std::string& filename) {
+    absl::string_view filename) {
   struct stat sb;
   int ret = 0;
   do {
-    ret = stat(filename.c_str(), &sb);
+    ret = stat(std::string(filename).c_str(), &sb);
   } while (ret != 0 && errno == EINTR);
 #if defined(_WIN32)
   if (ret == 0 && sb.st_mode & S_IFDIR) {
@@ -508,7 +504,7 @@
 #endif
   int file_descriptor;
   do {
-    file_descriptor = open(filename.c_str(), O_RDONLY);
+    file_descriptor = open(std::string(filename).c_str(), O_RDONLY);
   } while (file_descriptor < 0 && errno == EINTR);
   if (file_descriptor >= 0) {
     io::FileInputStream* result = new io::FileInputStream(file_descriptor);
diff --git a/src/google/protobuf/compiler/importer.h b/src/google/protobuf/compiler/importer.h
index 2fb88b9..3912f2d 100644
--- a/src/google/protobuf/compiler/importer.h
+++ b/src/google/protobuf/compiler/importer.h
@@ -37,17 +37,16 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
 #define GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
 
-#include <set>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/compiler/parser.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor_database.h>
+#include "google/protobuf/compiler/parser.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor_database.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -159,6 +158,8 @@
 class PROTOBUF_EXPORT Importer {
  public:
   Importer(SourceTree* source_tree, MultiFileErrorCollector* error_collector);
+  Importer(const Importer&) = delete;
+  Importer& operator=(const Importer&) = delete;
   ~Importer();
 
   // Import the given file and build a FileDescriptor representing it.  If
@@ -188,15 +189,15 @@
  private:
   SourceTreeDescriptorDatabase database_;
   DescriptorPool pool_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Importer);
 };
 
 // If the importer encounters problems while trying to import the proto files,
 // it reports them to a MultiFileErrorCollector.
 class PROTOBUF_EXPORT MultiFileErrorCollector {
  public:
-  inline MultiFileErrorCollector() {}
+  MultiFileErrorCollector() {}
+  MultiFileErrorCollector(const MultiFileErrorCollector&) = delete;
+  MultiFileErrorCollector& operator=(const MultiFileErrorCollector&) = delete;
   virtual ~MultiFileErrorCollector();
 
   // Line and column numbers are zero-based.  A line number of -1 indicates
@@ -206,9 +207,6 @@
 
   virtual void AddWarning(const std::string& /* filename */, int /* line */,
                           int /* column */, const std::string& /* message */) {}
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultiFileErrorCollector);
 };
 
 // Abstract interface which represents a directory tree containing proto files.
@@ -217,14 +215,16 @@
 // below.
 class PROTOBUF_EXPORT SourceTree {
  public:
-  inline SourceTree() {}
+  SourceTree() {}
+  SourceTree(const SourceTree&) = delete;
+  SourceTree& operator=(const SourceTree&) = delete;
   virtual ~SourceTree();
 
   // Open the given file and return a stream that reads it, or NULL if not
   // found.  The caller takes ownership of the returned object.  The filename
   // must be a path relative to the root of the source tree and must not
   // contain "." or ".." components.
-  virtual io::ZeroCopyInputStream* Open(const std::string& filename) = 0;
+  virtual io::ZeroCopyInputStream* Open(absl::string_view filename) = 0;
 
   // If Open() returns NULL, calling this method immediately will return an
   // description of the error.
@@ -232,9 +232,6 @@
   // better error reporting.
   // TODO(xiaofeng): change this to a pure virtual function.
   virtual std::string GetLastErrorMessage();
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SourceTree);
 };
 
 // An implementation of SourceTree which loads files from locations on disk.
@@ -243,6 +240,8 @@
 class PROTOBUF_EXPORT DiskSourceTree : public SourceTree {
  public:
   DiskSourceTree();
+  DiskSourceTree(const DiskSourceTree&) = delete;
+  DiskSourceTree& operator=(const DiskSourceTree&) = delete;
   ~DiskSourceTree() override;
 
   // Map a path on disk to a location in the SourceTree.  The path may be
@@ -261,7 +260,7 @@
   //
   // disk_path may be an absolute path or relative to the current directory,
   // just like a path you'd pass to open().
-  void MapPath(const std::string& virtual_path, const std::string& disk_path);
+  void MapPath(absl::string_view virtual_path, absl::string_view disk_path);
 
   // Return type for DiskFileToVirtualFile().
   enum DiskFileToVirtualFileResult {
@@ -292,17 +291,17 @@
   // * NO_MAPPING: Indicates that no mapping was found which contains this
   //   file.
   DiskFileToVirtualFileResult DiskFileToVirtualFile(
-      const std::string& disk_file, std::string* virtual_file,
+      absl::string_view disk_file, std::string* virtual_file,
       std::string* shadowing_disk_file);
 
   // Given a virtual path, find the path to the file on disk.
   // Return true and update disk_file with the on-disk path if the file exists.
   // Return false and leave disk_file untouched if the file doesn't exist.
-  bool VirtualFileToDiskFile(const std::string& virtual_file,
+  bool VirtualFileToDiskFile(absl::string_view virtual_file,
                              std::string* disk_file);
 
   // implements SourceTree -------------------------------------------
-  io::ZeroCopyInputStream* Open(const std::string& filename) override;
+  io::ZeroCopyInputStream* Open(absl::string_view filename) override;
 
   std::string GetLastErrorMessage() override;
 
@@ -311,28 +310,26 @@
     std::string virtual_path;
     std::string disk_path;
 
-    inline Mapping(const std::string& virtual_path_param,
-                   const std::string& disk_path_param)
-        : virtual_path(virtual_path_param), disk_path(disk_path_param) {}
+    inline Mapping(std::string virtual_path_param, std::string disk_path_param)
+        : virtual_path(std::move(virtual_path_param)),
+          disk_path(std::move(disk_path_param)) {}
   };
   std::vector<Mapping> mappings_;
   std::string last_error_message_;
 
   // Like Open(), but returns the on-disk path in disk_file if disk_file is
   // non-NULL and the file could be successfully opened.
-  io::ZeroCopyInputStream* OpenVirtualFile(const std::string& virtual_file,
+  io::ZeroCopyInputStream* OpenVirtualFile(absl::string_view virtual_file,
                                            std::string* disk_file);
 
   // Like Open() but given the actual on-disk path.
-  io::ZeroCopyInputStream* OpenDiskFile(const std::string& filename);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DiskSourceTree);
+  io::ZeroCopyInputStream* OpenDiskFile(absl::string_view filename);
 };
 
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_IMPORTER_H__
diff --git a/src/google/protobuf/compiler/importer_unittest.cc b/src/google/protobuf/compiler/importer_unittest.cc
index d2810ad..8099ca2 100644
--- a/src/google/protobuf/compiler/importer_unittest.cc
+++ b/src/google/protobuf/compiler/importer_unittest.cc
@@ -32,23 +32,22 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/importer.h>
+#include "google/protobuf/compiler/importer.h"
 
 #include <memory>
-#include <unordered_map>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/status/status.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
 
 namespace google {
 namespace protobuf {
@@ -74,13 +73,13 @@
   // implements ErrorCollector ---------------------------------------
   void AddError(const std::string& filename, int line, int column,
                 const std::string& message) override {
-    strings::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
+    absl::SubstituteAndAppend(&text_, "$0:$1:$2: $3\n", filename, line, column,
                               message);
   }
 
   void AddWarning(const std::string& filename, int line, int column,
                   const std::string& message) override {
-    strings::SubstituteAndAppend(&warning_text_, "$0:$1:$2: $3\n", filename, line,
+    absl::SubstituteAndAppend(&warning_text_, "$0:$1:$2: $3\n", filename, line,
                               column, message);
   }
 };
@@ -93,24 +92,22 @@
   MockSourceTree() {}
   ~MockSourceTree() override {}
 
-  void AddFile(const std::string& name, const char* contents) {
+  void AddFile(absl::string_view name, const char* contents) {
     files_[name] = contents;
   }
 
   // implements SourceTree -------------------------------------------
-  io::ZeroCopyInputStream* Open(const std::string& filename) override {
-    const char* contents = FindPtrOrNull(files_, filename);
-    if (contents == nullptr) {
-      return nullptr;
-    } else {
-      return new io::ArrayInputStream(contents, strlen(contents));
-    }
+  io::ZeroCopyInputStream* Open(absl::string_view filename) override {
+    auto it = files_.find(filename);
+    if (it == files_.end()) return nullptr;
+    return new io::ArrayInputStream(it->second,
+                                    static_cast<int>(strlen(it->second)));
   }
 
   std::string GetLastErrorMessage() override { return "File not found."; }
 
  private:
-  std::unordered_map<std::string, const char*> files_;
+  absl::flat_hash_map<std::string, const char*> files_;
 };
 
 // ===================================================================
diff --git a/src/google/protobuf/compiler/java/BUILD.bazel b/src/google/protobuf/compiler/java/BUILD.bazel
new file mode 100644
index 0000000..b93a423
--- /dev/null
+++ b/src/google/protobuf/compiler/java/BUILD.bazel
@@ -0,0 +1,172 @@
+################################################################################
+# Protocol Buffers Compiler - Java code generator
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "names",
+    hdrs = ["names.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/java",
+    visibility = ["//visibility:public"],
+    deps = [
+        ":names_internal",
+        "//src/google/protobuf:protobuf_nowkt",
+    ],
+)
+
+cc_library(
+    name = "names_internal",
+    srcs = [
+        "helpers.cc",
+        "name_resolver.cc",
+        "names.cc",
+    ],
+    hdrs = [
+        "helpers.h",
+        "name_resolver.h",
+        "names.h",
+        "options.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/java",
+    visibility = ["//pkg:__pkg__"],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/container:flat_hash_set",
+    ],
+)
+
+cc_library(
+    name = "java",
+    srcs = [
+        "context.cc",
+        "doc_comment.cc",
+        "enum.cc",
+        "enum_field.cc",
+        "enum_field_lite.cc",
+        "enum_lite.cc",
+        "extension.cc",
+        "extension_lite.cc",
+        "field.cc",
+        "file.cc",
+        "generator.cc",
+        "generator_factory.cc",
+        "kotlin_generator.cc",
+        "map_field.cc",
+        "map_field_lite.cc",
+        "message.cc",
+        "message_builder.cc",
+        "message_builder_lite.cc",
+        "message_field.cc",
+        "message_field_lite.cc",
+        "message_lite.cc",
+        "message_serialization.cc",
+        "primitive_field.cc",
+        "primitive_field_lite.cc",
+        "service.cc",
+        "shared_code_generator.cc",
+        "string_field.cc",
+        "string_field_lite.cc",
+    ],
+    hdrs = [
+        "context.h",
+        "doc_comment.h",
+        "enum.h",
+        "enum_field.h",
+        "enum_field_lite.h",
+        "enum_lite.h",
+        "extension.h",
+        "extension_lite.h",
+        "field.h",
+        "file.h",
+        "generator.h",
+        "generator_factory.h",
+        "kotlin_generator.h",
+        "map_field.h",
+        "map_field_lite.h",
+        "message.h",
+        "message_builder.h",
+        "message_builder_lite.h",
+        "message_field.h",
+        "message_field_lite.h",
+        "message_lite.h",
+        "message_serialization.h",
+        "primitive_field.h",
+        "primitive_field_lite.h",
+        "service.h",
+        "shared_code_generator.h",
+        "string_field.h",
+        "string_field_lite.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/java",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+    ],
+    deps = [
+        ":names",
+        ":names_internal",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/container:btree",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "doc_comment_unittest",
+    srcs = ["doc_comment_unittest.cc"],
+    data = [
+        "//:well_known_type_protos",
+        "//conformance:conformance_proto",
+        "//src/google/protobuf:descriptor_proto_srcs",
+    ],
+    deps = [
+        ":java",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "plugin_unittest",
+    srcs = ["plugin_unittest.cc"],
+    deps = [
+        ":java",
+        "//:protobuf",
+        "//src/google/protobuf/compiler:command_line_interface",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs:lite",
+        "//src/google/protobuf/testing",
+        "@com_google_absl//absl/strings",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/java/context.cc b/src/google/protobuf/compiler/java/context.cc
index cdc0d44..5d16ffb 100644
--- a/src/google/protobuf/compiler/java/context.cc
+++ b/src/google/protobuf/compiler/java/context.cc
@@ -28,14 +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.
 
-#include <google/protobuf/compiler/java/context.h>
+#include "google/protobuf/compiler/java/context.h"
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/field.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/stubs/map_util.h>
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/field.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
@@ -43,7 +42,7 @@
 namespace java {
 
 Context::Context(const FileDescriptor* file, const Options& options)
-    : name_resolver_(new ClassNameResolver), options_(options) {
+    : name_resolver_(new ClassNameResolver(options)), options_(options) {
   InitializeFieldGeneratorInfo(file);
 }
 
@@ -131,10 +130,10 @@
   std::vector<std::string> conflict_reason(fields.size());
   for (int i = 0; i < fields.size(); ++i) {
     const FieldDescriptor* field = fields[i];
-    const std::string& name = UnderscoresToCapitalizedCamelCase(field);
+    const std::string& name = CapitalizedFieldName(field);
     for (int j = i + 1; j < fields.size(); ++j) {
       const FieldDescriptor* other = fields[j];
-      const std::string& other_name = UnderscoresToCapitalizedCamelCase(other);
+      const std::string& other_name = CapitalizedFieldName(other);
       if (name == other_name) {
         is_conflict[i] = is_conflict[j] = true;
         conflict_reason[i] = conflict_reason[j] =
@@ -155,12 +154,12 @@
     const FieldDescriptor* field = fields[i];
     FieldGeneratorInfo info;
     info.name = CamelCaseFieldName(field);
-    info.capitalized_name = UnderscoresToCapitalizedCamelCase(field);
+    info.capitalized_name = CapitalizedFieldName(field);
     // For fields conflicting with some other fields, we append the field
     // number to their field names in generated code to avoid conflicts.
     if (is_conflict[i]) {
-      info.name += StrCat(field->number());
-      info.capitalized_name += StrCat(field->number());
+      info.name += absl::StrCat(field->number());
+      info.capitalized_name += absl::StrCat(field->number());
       info.disambiguated_reason = conflict_reason[i];
     }
     field_generator_info_map_[field] = info;
@@ -169,24 +168,22 @@
 
 const FieldGeneratorInfo* Context::GetFieldGeneratorInfo(
     const FieldDescriptor* field) const {
-  const FieldGeneratorInfo* result =
-      FindOrNull(field_generator_info_map_, field);
-  if (result == NULL) {
+  auto it = field_generator_info_map_.find(field);
+  if (it == field_generator_info_map_.end()) {
     GOOGLE_LOG(FATAL) << "Can not find FieldGeneratorInfo for field: "
                << field->full_name();
   }
-  return result;
+  return &it->second;
 }
 
 const OneofGeneratorInfo* Context::GetOneofGeneratorInfo(
     const OneofDescriptor* oneof) const {
-  const OneofGeneratorInfo* result =
-      FindOrNull(oneof_generator_info_map_, oneof);
-  if (result == NULL) {
+  auto it = oneof_generator_info_map_.find(oneof);
+  if (it == oneof_generator_info_map_.end()) {
     GOOGLE_LOG(FATAL) << "Can not find OneofGeneratorInfo for oneof: "
                << oneof->name();
   }
-  return result;
+  return &it->second;
 }
 
 // Does this message class have generated parsing, serialization, and other
diff --git a/src/google/protobuf/compiler/java/context.h b/src/google/protobuf/compiler/java/context.h
index c224ab7..2291cfa 100644
--- a/src/google/protobuf/compiler/java/context.h
+++ b/src/google/protobuf/compiler/java/context.h
@@ -31,12 +31,13 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_CONTEXT_H__
 
-#include <map>
 #include <memory>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/java/options.h>
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/options.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -65,6 +66,8 @@
 class Context {
  public:
   Context(const FileDescriptor* file, const Options& options);
+  Context(const Context&) = delete;
+  Context& operator=(const Context&) = delete;
   ~Context();
 
   // Get the name resolver associated with this context. The resolver
@@ -97,14 +100,27 @@
       const std::vector<const FieldDescriptor*>& fields);
 
   std::unique_ptr<ClassNameResolver> name_resolver_;
-  std::map<const FieldDescriptor*, FieldGeneratorInfo>
+  absl::flat_hash_map<const FieldDescriptor*, FieldGeneratorInfo>
       field_generator_info_map_;
-  std::map<const OneofDescriptor*, OneofGeneratorInfo>
+  absl::flat_hash_map<const OneofDescriptor*, OneofGeneratorInfo>
       oneof_generator_info_map_;
   Options options_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Context);
 };
 
+template <typename Descriptor>
+void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer,
+                                   Descriptor* descriptor, bool immutable,
+                                   const std::string& suffix = "") {
+  if (IsOwnFile(descriptor, immutable)) {
+    PrintGeneratedAnnotation(printer, '$',
+                             context->options().annotate_code
+                                 ? AnnotationFileName(descriptor, suffix)
+                                 : "",
+                             context->options());
+  }
+}
+
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/java/doc_comment.cc b/src/google/protobuf/compiler/java/doc_comment.cc
index 066bff6..496d59d 100644
--- a/src/google/protobuf/compiler/java/doc_comment.cc
+++ b/src/google/protobuf/compiler/java/doc_comment.cc
@@ -32,13 +32,14 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/doc_comment.h>
+#include "google/protobuf/compiler/java/doc_comment.h"
 
 #include <vector>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/str_split.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -103,26 +104,65 @@
   return result;
 }
 
+static std::string EscapeKdoc(const std::string& input) {
+  std::string result;
+  result.reserve(input.size() * 2);
+
+  char prev = 'a';
+
+  for (char c : input) {
+    switch (c) {
+      case '*':
+        // Avoid "/*".
+        if (prev == '/') {
+          result.append("&#42;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      case '/':
+        // Avoid "*/".
+        if (prev == '*') {
+          result.append("&#47;");
+        } else {
+          result.push_back(c);
+        }
+        break;
+      default:
+        result.push_back(c);
+        break;
+    }
+
+    prev = c;
+  }
+
+  return result;
+}
+
 static void WriteDocCommentBodyForLocation(io::Printer* printer,
-                                           const SourceLocation& location) {
+                                           const SourceLocation& location,
+                                           const bool kdoc) {
   std::string comments = location.leading_comments.empty()
                              ? location.trailing_comments
                              : location.leading_comments;
   if (!comments.empty()) {
-    // TODO(kenton):  Ideally we should parse the comment text as Markdown and
-    //   write it back as HTML, but this requires a Markdown parser.  For now
-    //   we just use <pre> to get fixed-width text formatting.
+    if (kdoc) {
+      comments = EscapeKdoc(comments);
+    } else {
+      comments = EscapeJavadoc(comments);
+    }
 
-    // If the comment itself contains block comment start or end markers,
-    // HTML-escape them so that they don't accidentally close the doc comment.
-    comments = EscapeJavadoc(comments);
-
-    std::vector<std::string> lines = Split(comments, "\n");
+    std::vector<std::string> lines = absl::StrSplit(comments, "\n");
     while (!lines.empty() && lines.back().empty()) {
       lines.pop_back();
     }
 
-    printer->Print(" * <pre>\n");
+    if (kdoc) {
+      printer->Print(" * ```\n");
+    } else {
+      printer->Print(" * <pre>\n");
+    }
+
     for (int i = 0; i < lines.size(); i++) {
       // Most lines should start with a space.  Watch out for lines that start
       // with a /, since putting that right after the leading asterisk will
@@ -133,18 +173,23 @@
         printer->Print(" *$line$\n", "line", lines[i]);
       }
     }
-    printer->Print(
-        " * </pre>\n"
-        " *\n");
+
+    if (kdoc) {
+      printer->Print(" * ```\n");
+    } else {
+      printer->Print(" * </pre>\n");
+    }
+    printer->Print(" *\n");
   }
 }
 
 template <typename DescriptorType>
 static void WriteDocCommentBody(io::Printer* printer,
-                                const DescriptorType* descriptor) {
+                                const DescriptorType* descriptor,
+                                const bool kdoc) {
   SourceLocation location;
   if (descriptor->GetSourceLocation(&location)) {
-    WriteDocCommentBodyForLocation(printer, location);
+    WriteDocCommentBodyForLocation(printer, location, kdoc);
   }
 }
 
@@ -164,16 +209,36 @@
   return result;
 }
 
-void WriteMessageDocComment(io::Printer* printer, const Descriptor* message) {
-  printer->Print("/**\n");
-  WriteDocCommentBody(printer, message);
-  printer->Print(
-      " * Protobuf type {@code $fullname$}\n"
-      " */\n",
-      "fullname", EscapeJavadoc(message->full_name()));
+static void WriteDebugString(io::Printer* printer, const FieldDescriptor* field,
+                      const bool kdoc) {
+  if (kdoc) {
+    printer->Print(" * `$def$`\n", "def",
+                   EscapeKdoc(FirstLineOf(field->DebugString())));
+  } else {
+    printer->Print(" * <code>$def$</code>\n", "def",
+                   EscapeJavadoc(FirstLineOf(field->DebugString())));
+  }
 }
 
-void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field) {
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message,
+                            const bool kdoc) {
+  printer->Print("/**\n");
+  WriteDocCommentBody(printer, message, kdoc);
+  if (kdoc) {
+    printer->Print(
+        " * Protobuf type `$fullname$`\n"
+        " */\n",
+        "fullname", EscapeKdoc(message->full_name()));
+  } else {
+    printer->Print(
+        " * Protobuf type {@code $fullname$}\n"
+        " */\n",
+        "fullname", EscapeJavadoc(message->full_name()));
+  }
+}
+
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+                          const bool kdoc) {
   // We start the comment with the main body based on the comments from the
   // .proto file (if present). We then continue with the field declaration,
   // e.g.:
@@ -181,9 +246,14 @@
   // And then we end with the javadoc tags if applicable.
   // If the field is a group, the debug string might end with {.
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, field);
-  printer->Print(" * <code>$def$</code>\n", "def",
-                 EscapeJavadoc(FirstLineOf(field->DebugString())));
+  WriteDocCommentBody(printer, field, kdoc);
+  if (kdoc) {
+    printer->Print(" * `$def$`\n", "def",
+                   EscapeKdoc(FirstLineOf(field->DebugString())));
+  } else {
+    printer->Print(" * <code>$def$</code>\n", "def",
+                   EscapeJavadoc(FirstLineOf(field->DebugString())));
+  }
   printer->Print(" */\n");
 }
 
@@ -214,12 +284,11 @@
 void WriteFieldAccessorDocComment(io::Printer* printer,
                                   const FieldDescriptor* field,
                                   const FieldAccessorType type,
-                                  const bool builder) {
+                                  const bool builder, const bool kdoc) {
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, field);
-  printer->Print(" * <code>$def$</code>\n", "def",
-                 EscapeJavadoc(FirstLineOf(field->DebugString())));
-  WriteDeprecatedJavadoc(printer, field, type);
+  WriteDocCommentBody(printer, field, kdoc);
+  WriteDebugString(printer, field, kdoc);
+  if (!kdoc) WriteDeprecatedJavadoc(printer, field, type);
   switch (type) {
     case HAZZER:
       printer->Print(" * @return Whether the $name$ field is set.\n", "name",
@@ -273,12 +342,12 @@
 void WriteFieldEnumValueAccessorDocComment(io::Printer* printer,
                                            const FieldDescriptor* field,
                                            const FieldAccessorType type,
-                                           const bool builder) {
+                                           const bool builder,
+                                           const bool kdoc) {
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, field);
-  printer->Print(" * <code>$def$</code>\n", "def",
-                 EscapeJavadoc(FirstLineOf(field->DebugString())));
-  WriteDeprecatedJavadoc(printer, field, type);
+  WriteDocCommentBody(printer, field, kdoc);
+  WriteDebugString(printer, field, kdoc);
+  if (!kdoc) WriteDeprecatedJavadoc(printer, field, type);
   switch (type) {
     case HAZZER:
       // Should never happen
@@ -343,12 +412,12 @@
 void WriteFieldStringBytesAccessorDocComment(io::Printer* printer,
                                              const FieldDescriptor* field,
                                              const FieldAccessorType type,
-                                             const bool builder) {
+                                             const bool builder,
+                                             const bool kdoc) {
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, field);
-  printer->Print(" * <code>$def$</code>\n", "def",
-                 EscapeJavadoc(FirstLineOf(field->DebugString())));
-  WriteDeprecatedJavadoc(printer, field, type);
+  WriteDocCommentBody(printer, field, kdoc);
+  WriteDebugString(printer, field, kdoc);
+  if (!kdoc) WriteDeprecatedJavadoc(printer, field, type);
   switch (type) {
     case HAZZER:
       // Should never happen
@@ -399,19 +468,28 @@
 
 // Enum
 
-void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_) {
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+                         const bool kdoc) {
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, enum_);
-  printer->Print(
-      " * Protobuf enum {@code $fullname$}\n"
-      " */\n",
-      "fullname", EscapeJavadoc(enum_->full_name()));
+  WriteDocCommentBody(printer, enum_, kdoc);
+  if (kdoc) {
+    printer->Print(
+        " * Protobuf enum `$fullname$`\n"
+        " */\n",
+        "fullname", EscapeKdoc(enum_->full_name()));
+  } else {
+    printer->Print(
+        " * Protobuf enum {@code $fullname$}\n"
+        " */\n",
+        "fullname", EscapeJavadoc(enum_->full_name()));
+  }
 }
 
 void WriteEnumValueDocComment(io::Printer* printer,
                               const EnumValueDescriptor* value) {
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, value);
+  WriteDocCommentBody(printer, value, /* kdoc */ false);
+
   printer->Print(
       " * <code>$def$</code>\n"
       " */\n",
@@ -421,7 +499,7 @@
 void WriteServiceDocComment(io::Printer* printer,
                             const ServiceDescriptor* service) {
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, service);
+  WriteDocCommentBody(printer, service, /* kdoc */ false);
   printer->Print(
       " * Protobuf service {@code $fullname$}\n"
       " */\n",
@@ -431,7 +509,7 @@
 void WriteMethodDocComment(io::Printer* printer,
                            const MethodDescriptor* method) {
   printer->Print("/**\n");
-  WriteDocCommentBody(printer, method);
+  WriteDocCommentBody(printer, method, /* kdoc */ false);
   printer->Print(
       " * <code>$def$</code>\n"
       " */\n",
diff --git a/src/google/protobuf/compiler/java/doc_comment.h b/src/google/protobuf/compiler/java/doc_comment.h
index 7f68778..de8e6bf 100644
--- a/src/google/protobuf/compiler/java/doc_comment.h
+++ b/src/google/protobuf/compiler/java/doc_comment.h
@@ -35,10 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
 
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -67,21 +67,27 @@
   LIST_MULTI_ADDER
 };
 
-void WriteMessageDocComment(io::Printer* printer, const Descriptor* message);
-void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field);
+void WriteMessageDocComment(io::Printer* printer, const Descriptor* message,
+                            const bool kdoc = false);
+void WriteFieldDocComment(io::Printer* printer, const FieldDescriptor* field,
+                          const bool kdoc = false);
 void WriteFieldAccessorDocComment(io::Printer* printer,
                                   const FieldDescriptor* field,
                                   const FieldAccessorType type,
-                                  const bool builder = false);
+                                  const bool builder = false,
+                                  const bool kdoc = false);
 void WriteFieldEnumValueAccessorDocComment(io::Printer* printer,
                                            const FieldDescriptor* field,
                                            const FieldAccessorType type,
-                                           const bool builder = false);
+                                           const bool builder = false,
+                                           const bool kdoc = false);
 void WriteFieldStringBytesAccessorDocComment(io::Printer* printer,
                                              const FieldDescriptor* field,
                                              const FieldAccessorType type,
-                                             const bool builder = false);
-void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_);
+                                             const bool builder = false,
+                                             const bool kdoc = false);
+void WriteEnumDocComment(io::Printer* printer, const EnumDescriptor* enum_,
+                         const bool kdoc = false);
 void WriteEnumValueDocComment(io::Printer* printer,
                               const EnumValueDescriptor* value);
 void WriteServiceDocComment(io::Printer* printer,
@@ -90,6 +96,7 @@
                            const MethodDescriptor* method);
 
 // Exposed for testing only.
+// Also called by proto1-Java code generator.
 PROTOC_EXPORT std::string EscapeJavadoc(const std::string& input);
 
 }  // namespace java
@@ -97,6 +104,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_DOC_COMMENT_H__
diff --git a/src/google/protobuf/compiler/java/doc_comment_unittest.cc b/src/google/protobuf/compiler/java/doc_comment_unittest.cc
index 3fcdf07..687b25f 100644
--- a/src/google/protobuf/compiler/java/doc_comment_unittest.cc
+++ b/src/google/protobuf/compiler/java/doc_comment_unittest.cc
@@ -30,7 +30,7 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <google/protobuf/compiler/java/doc_comment.h>
+#include "google/protobuf/compiler/java/doc_comment.h"
 
 #include <gtest/gtest.h>
 
diff --git a/src/google/protobuf/compiler/java/enum.cc b/src/google/protobuf/compiler/java/enum.cc
index 0cab93c..84c99e6 100644
--- a/src/google/protobuf/compiler/java/enum.cc
+++ b/src/google/protobuf/compiler/java/enum.cc
@@ -32,21 +32,21 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/enum.h>
+#include "google/protobuf/compiler/java/enum.h"
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -80,6 +80,10 @@
 void EnumGenerator::Generate(io::Printer* printer) {
   WriteEnumDocComment(printer, descriptor_);
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_, immutable_api_);
+
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
+  }
   printer->Print(
       "$deprecation$public enum $classname$\n"
       "    implements com.google.protobuf.ProtocolMessageEnum {\n",
@@ -99,10 +103,10 @@
   }
 
   for (int i = 0; i < canonical_values_.size(); i++) {
-    std::map<std::string, std::string> vars;
+    absl::flat_hash_map<absl::string_view, std::string> vars;
     vars["name"] = canonical_values_[i]->name();
-    vars["index"] = StrCat(canonical_values_[i]->index());
-    vars["number"] = StrCat(canonical_values_[i]->number());
+    vars["index"] = absl::StrCat(canonical_values_[i]->index());
+    vars["number"] = absl::StrCat(canonical_values_[i]->number());
     WriteEnumValueDocComment(printer, canonical_values_[i]);
     if (canonical_values_[i]->options().deprecated()) {
       printer->Print("@java.lang.Deprecated\n");
@@ -131,7 +135,7 @@
   // -----------------------------------------------------------------
 
   for (int i = 0; i < aliases_.size(); i++) {
-    std::map<std::string, std::string> vars;
+    absl::flat_hash_map<absl::string_view, std::string> vars;
     vars["classname"] = descriptor_->name();
     vars["name"] = aliases_[i].value->name();
     vars["canonical_name"] = aliases_[i].canonical_value->name();
@@ -142,9 +146,9 @@
   }
 
   for (int i = 0; i < descriptor_->value_count(); i++) {
-    std::map<std::string, std::string> vars;
+    absl::flat_hash_map<absl::string_view, std::string> vars;
     vars["name"] = descriptor_->value(i)->name();
-    vars["number"] = StrCat(descriptor_->value(i)->number());
+    vars["number"] = absl::StrCat(descriptor_->value(i)->number());
     vars["{"] = "";
     vars["}"] = "";
     vars["deprecation"] = descriptor_->value(i)->options().deprecated()
@@ -181,23 +185,32 @@
   printer->Print(
       "  return value;\n"
       "}\n"
-      "\n"
+      "\n");
+  if (context_->options().opensource_runtime) {
+    printer->Print(
+        "/**\n"
+        " * @param value The numeric wire value of the corresponding enum "
+        "entry.\n"
+        " * @return The enum associated with the given numeric wire value.\n"
+        " * @deprecated Use {@link #forNumber(int)} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "public static $classname$ valueOf(int value) {\n"
+        "  return forNumber(value);\n"
+        "}\n"
+        "\n",
+        "classname", descriptor_->name());
+  }
+  printer->Print(
       "/**\n"
       " * @param value The numeric wire value of the corresponding enum "
       "entry.\n"
       " * @return The enum associated with the given numeric wire value.\n"
-      " * @deprecated Use {@link #forNumber(int)} instead.\n"
-      " */\n"
-      "@java.lang.Deprecated\n"
-      "public static $classname$ valueOf(int value) {\n"
-      "  return forNumber(value);\n"
-      "}\n"
-      "\n"
-      "/**\n"
-      " * @param value The numeric wire value of the corresponding enum "
-      "entry.\n"
-      " * @return The enum associated with the given numeric wire value.\n"
-      " */\n"
+      " */\n");
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoMethodMayReturnNull\n");
+  }
+  printer->Print(
       "public static $classname$ forNumber(int value) {\n"
       "  switch (value) {\n",
       "classname", descriptor_->name());
@@ -207,7 +220,7 @@
   for (int i = 0; i < canonical_values_.size(); i++) {
     printer->Print("case $number$: return $name$;\n", "name",
                    canonical_values_[i]->name(), "number",
-                   StrCat(canonical_values_[i]->number()));
+                   absl::StrCat(canonical_values_[i]->number()));
   }
 
   printer->Outdent();
@@ -277,7 +290,7 @@
           "  return $file$.getDescriptor().getEnumTypes().get($index$);\n",
           "file",
           name_resolver_->GetClassName(descriptor_->file(), immutable_api_),
-          "index", StrCat(descriptor_->index()));
+          "index", absl::StrCat(descriptor_->index()));
     } else {
       printer->Print(
           "  return $parent$.$descriptor$.getEnumTypes().get($index$);\n",
@@ -290,7 +303,7 @@
                   .no_standard_descriptor_accessor()
               ? "getDefaultInstance().getDescriptorForType()"
               : "getDescriptor()",
-          "index", StrCat(descriptor_->index()));
+          "index", absl::StrCat(descriptor_->index()));
     }
 
     printer->Print(
@@ -394,4 +407,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/enum.h b/src/google/protobuf/compiler/java/enum.h
index 0a2c363..ae85b0c 100644
--- a/src/google/protobuf/compiler/java/enum.h
+++ b/src/google/protobuf/compiler/java/enum.h
@@ -37,7 +37,8 @@
 
 #include <string>
 #include <vector>
-#include <google/protobuf/descriptor.h>
+
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +63,8 @@
  public:
   EnumGenerator(const EnumDescriptor* descriptor, bool immutable_api,
                 Context* context);
+  EnumGenerator(const EnumGenerator&) = delete;
+  EnumGenerator& operator=(const EnumGenerator&) = delete;
   ~EnumGenerator();
 
   void Generate(io::Printer* printer);
@@ -88,8 +91,6 @@
   ClassNameResolver* name_resolver_;
 
   bool CanUseEnumValues();
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/enum_field.cc b/src/google/protobuf/compiler/java/enum_field.cc
index e64ee5b..f28fde7 100644
--- a/src/google/protobuf/compiler/java/enum_field.cc
+++ b/src/google/protobuf/compiler/java/enum_field.cc
@@ -35,18 +35,18 @@
 #include "google/protobuf/compiler/java/enum_field.h"
 
 #include <cstdint>
-#include <map>
 #include <string>
 
 #include "google/protobuf/stubs/logging.h"
 #include "google/protobuf/stubs/common.h"
-#include "google/protobuf/io/printer.h"
-#include "google/protobuf/wire_format.h"
-#include "google/protobuf/stubs/strutil.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
 #include "google/protobuf/compiler/java/context.h"
 #include "google/protobuf/compiler/java/doc_comment.h"
 #include "google/protobuf/compiler/java/helpers.h"
 #include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
 #include "google/protobuf/port_def.inc"
@@ -61,21 +61,22 @@
 void SetEnumVariables(
     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
     const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
-    std::map<std::string, std::string>* variables,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
     Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->enum_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])});
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->enum_type());
-  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default"] =
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
   (*variables)["default_number"] =
-      StrCat(descriptor->default_value_enum()->number());
-  (*variables)["tag"] = StrCat(
+      absl::StrCat(descriptor->default_value_enum()->number());
+  (*variables)["tag"] = absl::StrCat(
       static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
-  (*variables)["tag_size"] = StrCat(
+  (*variables)["tag_size"] = absl::StrCat(
       internal::WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // by the proto compiler
@@ -84,7 +85,7 @@
   variables->insert(
       {"kt_deprecation",
        descriptor->options().deprecated()
-           ? StrCat("@kotlin.Deprecated(message = \"Field ",
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
                           (*variables)["name"], " is deprecated\") ")
            : ""});
   if (HasHasbit(descriptor)) {
@@ -100,7 +101,7 @@
     (*variables)["set_has_field_bit_message"] = "";
     (*variables)["set_has_field_bit_to_local"] = "";
     variables->insert({"is_field_present_message",
-                       StrCat((*variables)["name"], "_ != ",
+                       absl::StrCat((*variables)["name"], "_ != ",
                                     (*variables)["default"], ".getNumber()")});
   }
 
@@ -121,7 +122,7 @@
 
   if (SupportUnknownEnumValue(descriptor->file())) {
     variables->insert(
-        {"unknown", StrCat((*variables)["type"], ".UNRECOGNIZED")});
+        {"unknown", absl::StrCat((*variables)["type"], ".UNRECOGNIZED")});
   } else {
     variables->insert({"unknown", (*variables)["default"]});
   }
@@ -275,7 +276,7 @@
 
 void ImmutableEnumFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -285,15 +286,28 @@
                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
                  "  }\n");
 
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(
+        variables_,
+        "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n"
+        "  @JvmName(\"${$get$kt_capitalized_name$Value$}$\")\n"
+        "  get() = $kt_dsl_builder$.${$get$capitalized_name$Value$}$()\n"
+        "  @JvmName(\"${$set$kt_capitalized_name$Value$}$\")\n"
+        "  set(value) {\n"
+        "    $kt_dsl_builder$.${$set$capitalized_name$Value$}$(value)\n"
+        "  }\n");
+  }
+
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
   if (HasHazzer(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                                 /* builder */ false, /* kdoc */ true);
     printer->Print(
         variables_,
         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -976,7 +990,6 @@
                  "}\n"
                  "input.popLimit(oldLimit);\n");
 }
-
 void RepeatedImmutableEnumFieldGenerator::GenerateSerializationCode(
     io::Printer* printer) const {
   if (descriptor_->is_packed()) {
@@ -1057,7 +1070,7 @@
       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -1068,7 +1081,7 @@
                  "  )\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -1079,7 +1092,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -1091,7 +1104,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
@@ -1102,7 +1115,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1115,7 +1128,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1127,7 +1140,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
diff --git a/src/google/protobuf/compiler/java/enum_field.h b/src/google/protobuf/compiler/java/enum_field.h
index 8f0a5c3..ed3d08a 100644
--- a/src/google/protobuf/compiler/java/enum_field.h
+++ b/src/google/protobuf/compiler/java/enum_field.h
@@ -35,9 +35,9 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_H__
 
-#include <map>
 #include <string>
 
+#include "absl/container/flat_hash_map.h"
 #include "google/protobuf/compiler/java/field.h"
 
 namespace google {
@@ -94,7 +94,7 @@
   const FieldDescriptor* descriptor_;
   int message_bit_index_;
   int builder_bit_index_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   ClassNameResolver* name_resolver_;
 };
 
diff --git a/src/google/protobuf/compiler/java/enum_field_lite.cc b/src/google/protobuf/compiler/java/enum_field_lite.cc
index e80b938..348d97b 100644
--- a/src/google/protobuf/compiler/java/enum_field_lite.cc
+++ b/src/google/protobuf/compiler/java/enum_field_lite.cc
@@ -32,24 +32,25 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/enum_field_lite.h>
+#include "google/protobuf/compiler/java/enum_field_lite.h"
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -65,36 +66,45 @@
 #endif  // !PROTOBUF_EXPERIMENT
 }
 
-void SetEnumVariables(const FieldDescriptor* descriptor, int messageBitIndex,
-                      int builderBitIndex, const FieldGeneratorInfo* info,
-                      ClassNameResolver* name_resolver,
-                      std::map<std::string, std::string>* variables) {
+void SetEnumVariables(
+    const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+    const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->enum_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])});
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->enum_type());
-  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default"] =
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
   (*variables)["default_number"] =
-      StrCat(descriptor->default_value_enum()->number());
-  (*variables)["tag"] = StrCat(
+      absl::StrCat(descriptor->default_value_enum()->number());
+  (*variables)["tag"] = absl::StrCat(
       static_cast<int32_t>(internal::WireFormat::MakeTag(descriptor)));
-  (*variables)["tag_size"] = StrCat(
+  (*variables)["tag_size"] = absl::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->insert(
+      {"kt_deprecation",
+       descriptor->options().deprecated()
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
+                          (*variables)["name"], " is deprecated\") ")
+           : ""});
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
   if (HasHasbit(descriptor)) {
+    if (!context->options().opensource_runtime) {
+      (*variables)["bit_field_id"] = absl::StrCat(messageBitIndex / 32);
+      (*variables)["bit_field_name"] = GetBitFieldNameForBit(messageBitIndex);
+      (*variables)["bit_field_mask"] =
+          absl::StrCat(1 << (messageBitIndex % 32));
+    }
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
 
@@ -109,9 +119,9 @@
     (*variables)["set_has_field_bit_message"] = "";
     (*variables)["clear_has_field_bit_message"] = "";
 
-    (*variables)["is_field_present_message"] =
-        (*variables)["name"] + "_ != " + (*variables)["default"] +
-        ".getNumber()";
+    variables->insert({"is_field_present_message",
+                       absl::StrCat((*variables)["name"], "_ != ",
+                                    (*variables)["default"], ".getNumber()")});
   }
 
   (*variables)["get_has_field_bit_from_local"] =
@@ -120,14 +130,18 @@
       GenerateSetBitToLocal(messageBitIndex);
 
   if (SupportUnknownEnumValue(descriptor->file())) {
-    (*variables)["unknown"] = (*variables)["type"] + ".UNRECOGNIZED";
+    variables->insert(
+        {"unknown", absl::StrCat((*variables)["type"], ".UNRECOGNIZED")});
   } else {
-    (*variables)["unknown"] = (*variables)["default"];
+    variables->insert({"unknown", (*variables)["default"]});
   }
 
   // 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";
+  // Calls to Annotate() use variable ranges to know which text to annotate.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 }  // namespace
@@ -142,7 +156,7 @@
       name_resolver_(context->GetNameResolver()) {
   SetEnumVariables(descriptor, messageBitIndex, 0,
                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
-                   &variables_);
+                   &variables_, context);
 }
 
 ImmutableEnumFieldLiteGenerator::~ImmutableEnumFieldLiteGenerator() {}
@@ -156,19 +170,37 @@
   if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
-                   "$deprecation$boolean has$capitalized_name$();\n");
+                   "$deprecation$boolean ${$has$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, GETTER);
     printer->Print(variables_,
-                   "$deprecation$int get$capitalized_name$Value();\n");
+                   "$deprecation$int ${$get$capitalized_name$Value$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
-  printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+  printer->Print(variables_,
+                 "$deprecation$$type$ ${$get$capitalized_name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableEnumFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        variables_,
+        "@com.google.protobuf.ProtoField(\n"
+        "  fieldNumber=$number$,\n"
+        "  type=com.google.protobuf.FieldType.$annotation_field_type$,\n"
+        "  isRequired=$required$)\n");
+    if (HasHazzer(descriptor_)) {
+      printer->Print(variables_,
+                     "@com.google.protobuf.ProtoPresenceCheckedField(\n"
+                     "  presenceBitsId=$bit_field_id$,\n"
+                     "  mask=$bit_field_mask$)\n");
+    }
+  }
   printer->Print(variables_, "private int $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
   if (HasHazzer(descriptor_)) {
@@ -286,7 +318,7 @@
 
 void ImmutableEnumFieldLiteGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -296,15 +328,28 @@
                  "    $kt_dsl_builder$.${$set$capitalized_name$$}$(value)\n"
                  "  }\n");
 
+  if (SupportUnknownEnumValue(descriptor_->file())) {
+    printer->Print(
+        variables_,
+        "$kt_deprecation$public var $kt_name$Value: kotlin.Int\n"
+        "  @JvmName(\"${$get$kt_capitalized_name$Value$}$\")\n"
+        "  get() = $kt_dsl_builder$.${$get$capitalized_name$Value$}$()\n"
+        "  @JvmName(\"${$set$kt_capitalized_name$Value$}$\")\n"
+        "  set(value) {\n"
+        "    $kt_dsl_builder$.${$set$capitalized_name$Value$}$(value)\n"
+        "  }\n");
+  }
+
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
   if (HasHazzer(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                                 /* builder */ false, /* kdoc */ true);
     printer->Print(
         variables_,
         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -501,7 +546,7 @@
       name_resolver_(context->GetNameResolver()) {
   SetEnumVariables(descriptor, messageBitIndex, 0,
                    context->GetFieldGeneratorInfo(descriptor), name_resolver_,
-                   &variables_);
+                   &variables_, context);
 }
 
 RepeatedImmutableEnumFieldLiteGenerator::
@@ -514,29 +559,43 @@
 void RepeatedImmutableEnumFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
-  printer->Print(
-      variables_,
-      "$deprecation$java.util.List<$type$> get$capitalized_name$List();\n");
+  printer->Print(variables_,
+                 "$deprecation$java.util.List<$type$> "
+                 "${$get$capitalized_name$List$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
   printer->Print(variables_,
-                 "$deprecation$int get$capitalized_name$Count();\n");
+                 "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
-  printer->Print(variables_,
-                 "$deprecation$$type$ get$capitalized_name$(int index);\n");
+  printer->Print(
+      variables_,
+      "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
   if (SupportUnknownEnumValue(descriptor_->file())) {
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_, LIST_GETTER);
     printer->Print(variables_,
                    "$deprecation$java.util.List<java.lang.Integer>\n"
-                   "get$capitalized_name$ValueList();\n");
+                   "${$get$capitalized_name$ValueList$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
     WriteFieldEnumValueAccessorDocComment(printer, descriptor_,
                                           LIST_INDEXED_GETTER);
-    printer->Print(variables_,
-                   "$deprecation$int get$capitalized_name$Value(int index);\n");
+    printer->Print(
+        variables_,
+        "$deprecation$int ${$get$capitalized_name$Value$}$(int index);\n");
+    printer->Annotate("{", "}", descriptor_);
   }
 }
 
 void RepeatedImmutableEnumFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        variables_,
+        "@com.google.protobuf.ProtoField(\n"
+        "  fieldNumber=$number$,\n"
+        "  type=com.google.protobuf.FieldType.$annotation_field_type$)\n");
+  }
   printer->Print(
       variables_,
       "private com.google.protobuf.Internal.IntList $name$_;\n"
@@ -793,6 +852,7 @@
     printer->Print(variables_,
                    "$deprecation$public Builder "
                    "${$add$capitalized_name$Value$}$(int value) {\n"
+                   "  copyOnWrite();\n"
                    "  instance.add$capitalized_name$Value(value);\n"
                    "  return this;\n"
                    "}\n");
@@ -830,7 +890,7 @@
       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$ public val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -841,7 +901,7 @@
                  "  )\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -852,7 +912,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -864,7 +924,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
@@ -875,7 +935,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -888,7 +948,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -900,7 +960,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
@@ -920,4 +980,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/enum_field_lite.h b/src/google/protobuf/compiler/java/enum_field_lite.h
index 492b268..d51ef34 100644
--- a/src/google/protobuf/compiler/java/enum_field_lite.h
+++ b/src/google/protobuf/compiler/java/enum_field_lite.h
@@ -36,10 +36,10 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_ENUM_FIELD_LITE_H__
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,10 @@
   explicit ImmutableEnumFieldLiteGenerator(const FieldDescriptor* descriptor,
                                            int messageBitIndex,
                                            Context* context);
+  ImmutableEnumFieldLiteGenerator(const ImmutableEnumFieldLiteGenerator&) =
+      delete;
+  ImmutableEnumFieldLiteGenerator& operator=(
+      const ImmutableEnumFieldLiteGenerator&) = delete;
   ~ImmutableEnumFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
@@ -79,13 +83,10 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   const int messageBitIndex_;
   Context* context_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumFieldLiteGenerator);
 };
 
 class ImmutableEnumOneofFieldLiteGenerator
@@ -93,15 +94,16 @@
  public:
   ImmutableEnumOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
                                        int messageBitIndex, Context* context);
+  ImmutableEnumOneofFieldLiteGenerator(
+      const ImmutableEnumOneofFieldLiteGenerator&) = delete;
+  ImmutableEnumOneofFieldLiteGenerator& operator=(
+      const ImmutableEnumOneofFieldLiteGenerator&) = delete;
   ~ImmutableEnumOneofFieldLiteGenerator() override;
 
   void GenerateMembers(io::Printer* printer) const override;
   void GenerateBuilderMembers(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
                          std::vector<uint16_t>* output) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableEnumOneofFieldLiteGenerator);
 };
 
 class RepeatedImmutableEnumFieldLiteGenerator
@@ -109,6 +111,10 @@
  public:
   explicit RepeatedImmutableEnumFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  RepeatedImmutableEnumFieldLiteGenerator(
+      const RepeatedImmutableEnumFieldLiteGenerator&) = delete;
+  RepeatedImmutableEnumFieldLiteGenerator& operator=(
+      const RepeatedImmutableEnumFieldLiteGenerator&) = delete;
   ~RepeatedImmutableEnumFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
@@ -125,11 +131,9 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   Context* context_;
   ClassNameResolver* name_resolver_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableEnumFieldLiteGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/enum_lite.cc b/src/google/protobuf/compiler/java/enum_lite.cc
index 4387090..5d10a68 100644
--- a/src/google/protobuf/compiler/java/enum_lite.cc
+++ b/src/google/protobuf/compiler/java/enum_lite.cc
@@ -32,19 +32,18 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/enum_lite.h>
+#include "google/protobuf/compiler/java/enum_lite.h"
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/map_util.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -87,9 +86,9 @@
   printer->Indent();
 
   for (int i = 0; i < canonical_values_.size(); i++) {
-    std::map<std::string, std::string> vars;
+    absl::flat_hash_map<absl::string_view, std::string> vars;
     vars["name"] = canonical_values_[i]->name();
-    vars["number"] = StrCat(canonical_values_[i]->number());
+    vars["number"] = absl::StrCat(canonical_values_[i]->number());
     WriteEnumValueDocComment(printer, canonical_values_[i]);
     if (canonical_values_[i]->options().deprecated()) {
       printer->Print("@java.lang.Deprecated\n");
@@ -110,7 +109,7 @@
   // -----------------------------------------------------------------
 
   for (int i = 0; i < aliases_.size(); i++) {
-    std::map<std::string, std::string> vars;
+    absl::flat_hash_map<absl::string_view, std::string> vars;
     vars["classname"] = descriptor_->name();
     vars["name"] = aliases_[i].value->name();
     vars["canonical_name"] = aliases_[i].canonical_value->name();
@@ -121,9 +120,9 @@
   }
 
   for (int i = 0; i < descriptor_->value_count(); i++) {
-    std::map<std::string, std::string> vars;
+    absl::flat_hash_map<absl::string_view, std::string> vars;
     vars["name"] = descriptor_->value(i)->name();
-    vars["number"] = StrCat(descriptor_->value(i)->number());
+    vars["number"] = absl::StrCat(descriptor_->value(i)->number());
     vars["{"] = "";
     vars["}"] = "";
     vars["deprecation"] = descriptor_->value(i)->options().deprecated()
@@ -153,17 +152,26 @@
   printer->Print(
       "  return value;\n"
       "}\n"
-      "\n"
-      "/**\n"
-      " * @param value The number of the enum to look for.\n"
-      " * @return The enum associated with the given number.\n"
-      " * @deprecated Use {@link #forNumber(int)} instead.\n"
-      " */\n"
-      "@java.lang.Deprecated\n"
-      "public static $classname$ valueOf(int value) {\n"
-      "  return forNumber(value);\n"
-      "}\n"
-      "\n"
+      "\n");
+  if (context_->options().opensource_runtime) {
+    printer->Print(
+        "/**\n"
+        " * @param value The number of the enum to look for.\n"
+        " * @return The enum associated with the given number.\n"
+        " * @deprecated Use {@link #forNumber(int)} instead.\n"
+        " */\n"
+        "@java.lang.Deprecated\n"
+        "public static $classname$ valueOf(int value) {\n"
+        "  return forNumber(value);\n"
+        "}\n"
+        "\n",
+        "classname", descriptor_->name());
+  }
+
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoMethodMayReturnNull\n");
+  }
+  printer->Print(
       "public static $classname$ forNumber(int value) {\n"
       "  switch (value) {\n",
       "classname", descriptor_->name());
@@ -173,7 +181,7 @@
   for (int i = 0; i < canonical_values_.size(); i++) {
     printer->Print("case $number$: return $name$;\n", "name",
                    canonical_values_[i]->name(), "number",
-                   StrCat(canonical_values_[i]->number()));
+                   absl::StrCat(canonical_values_[i]->number()));
   }
 
   printer->Outdent();
@@ -212,6 +220,35 @@
       "      };\n"
       "\n",
       "classname", descriptor_->name());
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        "/**\n"
+        " * Override of toString that prints the number and name.\n"
+        " * This is primarily intended as a developer aid.\n"
+        " *\n"
+        " * <p>NOTE: This implementation is liable to change in the future,\n"
+        " * and should not be relied on in code.\n"
+        " */\n"
+        "@java.lang.Override\n"
+        "public java.lang.String toString() {\n"
+        "  StringBuilder result = new StringBuilder(\"<\");\n"
+        "  result.append(getClass().getName()).append('@')\n"
+        "      .append(java.lang.Integer.toHexString(\n"
+        "        java.lang.System.identityHashCode(this)));\n");
+    if (SupportUnknownEnumValue(descriptor_->file())) {
+      printer->Print(
+          "  if (this != UNRECOGNIZED) {\n"
+          "    result.append(\" number=\").append(getNumber());\n"
+          "  }\n");
+    } else {
+      printer->Print("  result.append(\" number=\").append(getNumber());\n");
+    }
+    printer->Print(
+        "  return result.append(\" name=\")\n"
+        "      .append(name()).append('>').toString();\n"
+        "}\n"
+        "\n");
+  }
 
   printer->Print(
       "private final int value;\n\n"
diff --git a/src/google/protobuf/compiler/java/enum_lite.h b/src/google/protobuf/compiler/java/enum_lite.h
index 50f3fe7..309d539 100644
--- a/src/google/protobuf/compiler/java/enum_lite.h
+++ b/src/google/protobuf/compiler/java/enum_lite.h
@@ -37,7 +37,8 @@
 
 #include <string>
 #include <vector>
-#include <google/protobuf/descriptor.h>
+
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +63,8 @@
  public:
   EnumLiteGenerator(const EnumDescriptor* descriptor, bool immutable_api,
                     Context* context);
+  EnumLiteGenerator(const EnumLiteGenerator&) = delete;
+  EnumLiteGenerator& operator=(const EnumLiteGenerator&) = delete;
   ~EnumLiteGenerator();
 
   void Generate(io::Printer* printer);
@@ -86,8 +89,6 @@
 
   Context* context_;
   ClassNameResolver* name_resolver_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumLiteGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/extension.cc b/src/google/protobuf/compiler/java/extension.cc
index 8b93eb1..b553b45 100644
--- a/src/google/protobuf/compiler/java/extension.cc
+++ b/src/google/protobuf/compiler/java/extension.cc
@@ -32,17 +32,18 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/extension.h>
+#include "google/protobuf/compiler/java/extension.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -51,7 +52,9 @@
 
 ImmutableExtensionGenerator::ImmutableExtensionGenerator(
     const FieldDescriptor* descriptor, Context* context)
-    : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+    : descriptor_(descriptor),
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   if (descriptor_->extension_scope() != NULL) {
     scope_ =
         name_resolver_->GetImmutableClassName(descriptor_->extension_scope());
@@ -66,18 +69,20 @@
 void ExtensionGenerator::InitTemplateVars(
     const FieldDescriptor* descriptor, const std::string& scope, bool immutable,
     ClassNameResolver* name_resolver,
-    std::map<std::string, std::string>* vars_pointer) {
-  std::map<std::string, std::string>& vars = *vars_pointer;
+    absl::flat_hash_map<absl::string_view, std::string>* vars_pointer,
+    Context* context) {
+  absl::flat_hash_map<absl::string_view, std::string>& vars = *vars_pointer;
   vars["scope"] = scope;
   vars["name"] = UnderscoresToCamelCaseCheckReserved(descriptor);
   vars["containing_type"] =
       name_resolver->GetClassName(descriptor->containing_type(), immutable);
-  vars["number"] = StrCat(descriptor->number());
+  vars["number"] = absl::StrCat(descriptor->number());
   vars["constant_name"] = FieldConstantName(descriptor);
-  vars["index"] = StrCat(descriptor->index());
+  vars["index"] = absl::StrCat(descriptor->index());
   vars["default"] = descriptor->is_repeated()
                         ? ""
-                        : DefaultValue(descriptor, immutable, name_resolver);
+                        : DefaultValue(descriptor, immutable, name_resolver,
+                                       context->options());
   vars["type_constant"] = FieldTypeName(GetType(descriptor));
   vars["packed"] = descriptor->is_packed() ? "true" : "false";
   vars["enum_map"] = "null";
@@ -113,10 +118,10 @@
 }
 
 void ImmutableExtensionGenerator::Generate(io::Printer* printer) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   const bool kUseImmutableNames = true;
   InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
-                   &vars);
+                   &vars, context_);
   printer->Print(vars, "public static final int $constant_name$ = $number$;\n");
 
   WriteFieldDocComment(printer, descriptor_);
@@ -156,7 +161,7 @@
     printer->Print(
         "$name$.internalInit(descriptor.getExtensions().get($index$));\n",
         "name", UnderscoresToCamelCaseCheckReserved(descriptor_), "index",
-        StrCat(descriptor_->index()));
+        absl::StrCat(descriptor_->index()));
     bytecode_estimate += 21;
   }
   return bytecode_estimate;
@@ -174,4 +179,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/extension.h b/src/google/protobuf/compiler/java/extension.h
index 318cfa4..ad5709c 100644
--- a/src/google/protobuf/compiler/java/extension.h
+++ b/src/google/protobuf/compiler/java/extension.h
@@ -35,10 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -66,6 +66,8 @@
 class ExtensionGenerator {
  public:
   explicit ExtensionGenerator() {}
+  ExtensionGenerator(const ExtensionGenerator&) = delete;
+  ExtensionGenerator& operator=(const ExtensionGenerator&) = delete;
   virtual ~ExtensionGenerator() {}
 
   virtual void Generate(io::Printer* printer) = 0;
@@ -82,16 +84,17 @@
   static void InitTemplateVars(
       const FieldDescriptor* descriptor, const std::string& scope,
       bool immutable, ClassNameResolver* name_resolver,
-      std::map<std::string, std::string>* vars_pointer);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionGenerator);
+      absl::flat_hash_map<absl::string_view, std::string>* vars_pointer,
+      Context* context);
 };
 
 class ImmutableExtensionGenerator : public ExtensionGenerator {
  public:
   explicit ImmutableExtensionGenerator(const FieldDescriptor* descriptor,
                                        Context* context);
+  ImmutableExtensionGenerator(const ImmutableExtensionGenerator&) = delete;
+  ImmutableExtensionGenerator& operator=(const ImmutableExtensionGenerator&) =
+      delete;
   ~ImmutableExtensionGenerator() override;
 
   void Generate(io::Printer* printer) override;
@@ -102,9 +105,7 @@
   const FieldDescriptor* descriptor_;
   ClassNameResolver* name_resolver_;
   std::string scope_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionGenerator);
+  Context* context_;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/extension_lite.cc b/src/google/protobuf/compiler/java/extension_lite.cc
index bffb1d6..592679b 100644
--- a/src/google/protobuf/compiler/java/extension_lite.cc
+++ b/src/google/protobuf/compiler/java/extension_lite.cc
@@ -28,17 +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/java/extension_lite.h>
+#include "google/protobuf/compiler/java/extension_lite.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include <string>
+
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -47,7 +49,9 @@
 
 ImmutableExtensionLiteGenerator::ImmutableExtensionLiteGenerator(
     const FieldDescriptor* descriptor, Context* context)
-    : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+    : descriptor_(descriptor),
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   if (descriptor_->extension_scope() != NULL) {
     scope_ =
         name_resolver_->GetImmutableClassName(descriptor_->extension_scope());
@@ -59,10 +63,10 @@
 ImmutableExtensionLiteGenerator::~ImmutableExtensionLiteGenerator() {}
 
 void ImmutableExtensionLiteGenerator::Generate(io::Printer* printer) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   const bool kUseImmutableNames = true;
   InitTemplateVars(descriptor_, scope_, kUseImmutableNames, name_resolver_,
-                   &vars);
+                   &vars, context_);
   printer->Print(vars, "public static final int $constant_name$ = $number$;\n");
 
   WriteFieldDocComment(printer, descriptor_);
@@ -117,4 +121,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/extension_lite.h b/src/google/protobuf/compiler/java/extension_lite.h
index 264230c..da5612a 100644
--- a/src/google/protobuf/compiler/java/extension_lite.h
+++ b/src/google/protobuf/compiler/java/extension_lite.h
@@ -31,11 +31,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_EXTENSION_LITE_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/java/extension.h>
+#include "google/protobuf/compiler/java/extension.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -49,6 +48,10 @@
  public:
   explicit ImmutableExtensionLiteGenerator(const FieldDescriptor* descriptor,
                                            Context* context);
+  ImmutableExtensionLiteGenerator(const ImmutableExtensionLiteGenerator&) =
+      delete;
+  ImmutableExtensionLiteGenerator& operator=(
+      const ImmutableExtensionLiteGenerator&) = delete;
   ~ImmutableExtensionLiteGenerator() override;
 
   void Generate(io::Printer* printer) override;
@@ -63,8 +66,7 @@
   const FieldDescriptor* descriptor_;
   ClassNameResolver* name_resolver_;
   std::string scope_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableExtensionLiteGenerator);
+  Context* context_;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/field.cc b/src/google/protobuf/compiler/java/field.cc
index 3dd528f..3967ec4 100644
--- a/src/google/protobuf/compiler/java/field.cc
+++ b/src/google/protobuf/compiler/java/field.cc
@@ -32,27 +32,29 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 #include <memory>
+#include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/enum_field.h>
-#include <google/protobuf/compiler/java/enum_field_lite.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/map_field.h>
-#include <google/protobuf/compiler/java/map_field_lite.h>
-#include <google/protobuf/compiler/java/message_field.h>
-#include <google/protobuf/compiler/java/message_field_lite.h>
-#include <google/protobuf/compiler/java/primitive_field.h>
-#include <google/protobuf/compiler/java/primitive_field_lite.h>
-#include <google/protobuf/compiler/java/string_field.h>
-#include <google/protobuf/compiler/java/string_field_lite.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/enum_field.h"
+#include "google/protobuf/compiler/java/enum_field_lite.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/map_field.h"
+#include "google/protobuf/compiler/java/map_field_lite.h"
+#include "google/protobuf/compiler/java/message_field.h"
+#include "google/protobuf/compiler/java/message_field_lite.h"
+#include "google/protobuf/compiler/java/primitive_field.h"
+#include "google/protobuf/compiler/java/primitive_field_lite.h"
+#include "google/protobuf/compiler/java/string_field.h"
+#include "google/protobuf/compiler/java/string_field_lite.h"
+#include "google/protobuf/io/printer.h"
 
 
 namespace google {
@@ -241,16 +243,16 @@
 FieldGeneratorMap<ImmutableFieldLiteGenerator>::~FieldGeneratorMap() {}
 
 
-void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             const FieldGeneratorInfo* info,
-                             std::map<std::string, std::string>* variables) {
+void SetCommonFieldVariables(
+    const FieldDescriptor* descriptor, const FieldGeneratorInfo* info,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   (*variables)["field_name"] = descriptor->name();
   (*variables)["name"] = info->name;
   (*variables)["classname"] = descriptor->containing_type()->name();
   (*variables)["capitalized_name"] = info->capitalized_name;
   (*variables)["disambiguated_reason"] = info->disambiguated_reason;
   (*variables)["constant_name"] = FieldConstantName(descriptor);
-  (*variables)["number"] = StrCat(descriptor->number());
+  (*variables)["number"] = absl::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
@@ -273,31 +275,32 @@
     (*variables)["annotation_field_type"] =
         std::string(FieldTypeName(descriptor->type())) + "_LIST";
     if (descriptor->is_packed()) {
-      (*variables)["annotation_field_type"] =
-          (*variables)["annotation_field_type"] + "_PACKED";
+      variables->insert(
+          {"annotation_field_type",
+           absl::StrCat((*variables)["annotation_field_type"], "_PACKED")});
     }
   }
 }
 
-void SetCommonOneofVariables(const FieldDescriptor* descriptor,
-                             const OneofGeneratorInfo* info,
-                             std::map<std::string, std::string>* variables) {
+void SetCommonOneofVariables(
+    const FieldDescriptor* descriptor, const OneofGeneratorInfo* info,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   (*variables)["oneof_name"] = info->name;
   (*variables)["oneof_capitalized_name"] = info->capitalized_name;
   (*variables)["oneof_index"] =
-      StrCat(descriptor->containing_oneof()->index());
+      absl::StrCat(descriptor->containing_oneof()->index());
   (*variables)["oneof_stored_type"] = GetOneofStoredType(descriptor);
   (*variables)["set_oneof_case_message"] =
-      info->name + "Case_ = " + StrCat(descriptor->number());
+      info->name + "Case_ = " + absl::StrCat(descriptor->number());
   (*variables)["clear_oneof_case_message"] = info->name + "Case_ = 0";
   (*variables)["has_oneof_case_message"] =
-      info->name + "Case_ == " + StrCat(descriptor->number());
+      info->name + "Case_ == " + absl::StrCat(descriptor->number());
 }
 
-void PrintExtraFieldInfo(const std::map<std::string, std::string>& variables,
-                         io::Printer* printer) {
-  const std::map<std::string, std::string>::const_iterator it =
-      variables.find("disambiguated_reason");
+void PrintExtraFieldInfo(
+    const absl::flat_hash_map<absl::string_view, std::string>& variables,
+    io::Printer* printer) {
+  auto it = variables.find("disambiguated_reason");
   if (it != variables.end() && !it->second.empty()) {
     printer->Print(
         variables,
diff --git a/src/google/protobuf/compiler/java/field.h b/src/google/protobuf/compiler/java/field.h
index 7f82316..98ecb87 100644
--- a/src/google/protobuf/compiler/java/field.h
+++ b/src/google/protobuf/compiler/java/field.h
@@ -36,13 +36,14 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_FIELD_H__
 
 #include <cstdint>
-#include <map>
 #include <memory>
 #include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -66,6 +67,8 @@
 class ImmutableFieldGenerator {
  public:
   ImmutableFieldGenerator() {}
+  ImmutableFieldGenerator(const ImmutableFieldGenerator&) = delete;
+  ImmutableFieldGenerator& operator=(const ImmutableFieldGenerator&) = delete;
   virtual ~ImmutableFieldGenerator();
 
   virtual int GetMessageBitIndex() const = 0;
@@ -91,14 +94,14 @@
   virtual void GenerateHashCode(io::Printer* printer) const = 0;
 
   virtual std::string GetBoxedType() const = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldGenerator);
 };
 
 class ImmutableFieldLiteGenerator {
  public:
   ImmutableFieldLiteGenerator() {}
+  ImmutableFieldLiteGenerator(const ImmutableFieldLiteGenerator&) = delete;
+  ImmutableFieldLiteGenerator& operator=(const ImmutableFieldLiteGenerator&) =
+      delete;
   virtual ~ImmutableFieldLiteGenerator();
 
   virtual int GetNumBitsForMessage() const = 0;
@@ -111,9 +114,6 @@
   virtual void GenerateKotlinDslMembers(io::Printer* printer) const = 0;
 
   virtual std::string GetBoxedType() const = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableFieldLiteGenerator);
 };
 
 
@@ -122,6 +122,8 @@
 class FieldGeneratorMap {
  public:
   explicit FieldGeneratorMap(const Descriptor* descriptor, Context* context);
+  FieldGeneratorMap(const FieldGeneratorMap&) = delete;
+  FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete;
   ~FieldGeneratorMap();
 
   const FieldGeneratorType& get(const FieldDescriptor* field) const;
@@ -129,8 +131,6 @@
  private:
   const Descriptor* descriptor_;
   std::vector<std::unique_ptr<FieldGeneratorType>> field_generators_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldGeneratorMap);
 };
 
 template <typename FieldGeneratorType>
@@ -171,18 +171,19 @@
 };
 
 // Set some common variables used in variable FieldGenerators.
-void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             const FieldGeneratorInfo* info,
-                             std::map<std::string, std::string>* variables);
+void SetCommonFieldVariables(
+    const FieldDescriptor* descriptor, const FieldGeneratorInfo* info,
+    absl::flat_hash_map<absl::string_view, std::string>* variables);
 
 // Set some common oneof variables used in OneofFieldGenerators.
-void SetCommonOneofVariables(const FieldDescriptor* descriptor,
-                             const OneofGeneratorInfo* info,
-                             std::map<std::string, std::string>* variables);
+void SetCommonOneofVariables(
+    const FieldDescriptor* descriptor, const OneofGeneratorInfo* info,
+    absl::flat_hash_map<absl::string_view, std::string>* variables);
 
 // Print useful comments before a field's accessors.
-void PrintExtraFieldInfo(const std::map<std::string, std::string>& variables,
-                         io::Printer* printer);
+void PrintExtraFieldInfo(
+    const absl::flat_hash_map<absl::string_view, std::string>& variables,
+    io::Printer* printer);
 
 }  // namespace java
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/java/file.cc b/src/google/protobuf/compiler/java/file.cc
index cf27703..2a381cf 100644
--- a/src/google/protobuf/compiler/java/file.cc
+++ b/src/google/protobuf/compiler/java/file.cc
@@ -32,30 +32,31 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/file.h>
+#include "google/protobuf/compiler/java/file.h"
 
 #include <memory>
-#include <set>
+#include <vector>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/enum.h>
-#include <google/protobuf/compiler/java/enum_lite.h>
-#include <google/protobuf/compiler/java/extension.h>
-#include <google/protobuf/compiler/java/generator_factory.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/message.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/compiler/java/service.h>
-#include <google/protobuf/compiler/java/shared_code_generator.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/container/btree_set.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/enum.h"
+#include "google/protobuf/compiler/java/enum_lite.h"
+#include "google/protobuf/compiler/java/extension.h"
+#include "google/protobuf/compiler/java/generator_factory.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/message.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/compiler/java/service.h"
+#include "google/protobuf/compiler/java/shared_code_generator.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -76,8 +77,8 @@
   }
 };
 
-typedef std::set<const FieldDescriptor*, FieldDescriptorCompare>
-    FieldDescriptorSet;
+using FieldDescriptorSet =
+    absl::btree_set<const FieldDescriptor*, FieldDescriptorCompare>;
 
 // Recursively searches the given message to collect extensions.
 // Returns true if all the extensions can be recognized. The extensions will be
@@ -175,10 +176,10 @@
 
   if ((*bytecode_estimate) > bytesPerMethod) {
     ++(*method_num);
-    printer->Print(chain_statement, "method_num", StrCat(*method_num));
+    printer->Print(chain_statement, "method_num", absl::StrCat(*method_num));
     printer->Outdent();
     printer->Print("}\n");
-    printer->Print(method_decl, "method_num", StrCat(*method_num));
+    printer->Print(method_decl, "method_num", absl::StrCat(*method_num));
     printer->Indent();
     *bytecode_estimate = 0;
   }
@@ -188,7 +189,7 @@
 FileGenerator::FileGenerator(const FileDescriptor* file, const Options& options,
                              bool immutable_api)
     : file_(file),
-      java_package_(FileJavaPackage(file, immutable_api)),
+      java_package_(FileJavaPackage(file, immutable_api, options)),
       message_generators_(file->message_type_count()),
       extension_generators_(file->extension_count()),
       context_(new Context(file, options)),
@@ -196,7 +197,7 @@
       options_(options),
       immutable_api_(immutable_api) {
   classname_ = name_resolver_->GetFileClassName(file, immutable_api);
-  generator_factory_.reset(new ImmutableGeneratorFactory(context_.get()));
+    generator_factory_.reset(new ImmutableGeneratorFactory(context_.get()));
   for (int i = 0; i < file_->message_type_count(); ++i) {
     message_generators_[i].reset(
         generator_factory_->NewMessageGenerator(file_->message_type(i)));
@@ -271,8 +272,12 @@
         "package", java_package_);
   }
   PrintGeneratedAnnotation(
-      printer, '$', options_.annotate_code ? classname_ + ".java.pb.meta" : "");
+      printer, '$', options_.annotate_code ? classname_ + ".java.pb.meta" : "",
+      options_);
 
+  if (!options_.opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
+  }
   printer->Print(
       "$deprecation$public final class $classname$ {\n"
       "  private $ctor$() {}\n",
@@ -401,11 +406,14 @@
       "    descriptor;\n"
       "static {\n",
       // TODO(dweis): Mark this as final.
-      "final", "");
+      "final", options_.opensource_runtime ? "" : "final");
   printer->Indent();
 
-  SharedCodeGenerator shared_code_generator(file_, options_);
-  shared_code_generator.GenerateDescriptors(printer);
+  if (options_.opensource_runtime) {
+    SharedCodeGenerator shared_code_generator(file_, options_);
+    shared_code_generator.GenerateDescriptors(printer);
+  } else {
+  }
 
   int bytecode_estimate = 0;
   int method_num = 0;
@@ -449,16 +457,16 @@
   FieldDescriptorSet extensions;
   CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
 
-  if (extensions.size() > 0) {
+  if (!extensions.empty()) {
     // Must construct an ExtensionRegistry containing all existing extensions
     // and use it to parse the descriptor data again to recognize extensions.
     printer->Print(
         "com.google.protobuf.ExtensionRegistry registry =\n"
         "    com.google.protobuf.ExtensionRegistry.newInstance();\n");
     FieldDescriptorSet::iterator it;
-    for (it = extensions.begin(); it != extensions.end(); it++) {
+    for (const FieldDescriptor* field : extensions) {
       std::unique_ptr<ExtensionGenerator> generator(
-          generator_factory_->NewExtensionGenerator(*it));
+          generator_factory_->NewExtensionGenerator(field));
       bytecode_estimate += generator->GenerateRegistrationCode(printer);
       MaybeRestartJavaMethod(
           printer, &bytecode_estimate, &method_num,
@@ -499,8 +507,8 @@
 
   printer->Print(
       "descriptor = $immutable_package$.$descriptor_classname$.descriptor;\n",
-      "immutable_package", FileJavaPackage(file_, true), "descriptor_classname",
-      name_resolver_->GetDescriptorClassName(file_));
+      "immutable_package", FileJavaPackage(file_, true, options_),
+      "descriptor_classname", name_resolver_->GetDescriptorClassName(file_));
 
   for (int i = 0; i < file_->message_type_count(); i++) {
     message_generators_[i]->GenerateStaticVariableInitializers(printer);
@@ -518,7 +526,7 @@
   FieldDescriptorSet extensions;
   CollectExtensions(file_proto, *file_->pool(), &extensions, file_data);
 
-  if (extensions.size() > 0) {
+  if (!extensions.empty()) {
     // Try to load immutable messages' outer class. Its initialization code
     // will take care of interpreting custom options.
     printer->Print(
@@ -539,15 +547,14 @@
         "com.google.protobuf.ExtensionRegistry registry =\n"
         "    com.google.protobuf.ExtensionRegistry.newInstance();\n"
         "com.google.protobuf.MessageLite defaultExtensionInstance = null;\n");
-    FieldDescriptorSet::iterator it;
-    for (it = extensions.begin(); it != extensions.end(); it++) {
-      const FieldDescriptor* field = *it;
+
+    for (const FieldDescriptor* field : extensions) {
       std::string scope;
       if (field->extension_scope() != NULL) {
         scope = name_resolver_->GetMutableClassName(field->extension_scope()) +
                 ".getDescriptor()";
       } else {
-        scope = FileJavaPackage(field->file(), true) + "." +
+        scope = FileJavaPackage(field->file(), true, options_) + "." +
                 name_resolver_->GetDescriptorClassName(field->file()) +
                 ".descriptor";
       }
@@ -560,11 +567,11 @@
             "      $scope$.getExtensions().get($index$),\n"
             "      (com.google.protobuf.Message) defaultExtensionInstance);\n"
             "}\n",
-            "scope", scope, "index", StrCat(field->index()), "class",
+            "scope", scope, "index", absl::StrCat(field->index()), "class",
             name_resolver_->GetImmutableClassName(field->message_type()));
       } else {
         printer->Print("registry.add($scope$.getExtensions().get($index$));\n",
-                       "scope", scope, "index", StrCat(field->index()));
+                       "scope", scope, "index", absl::StrCat(field->index()));
       }
     }
     printer->Print(
@@ -682,6 +689,23 @@
   return name_resolver_->GetFileClassName(file_, immutable_api_, true);
 }
 
+void FileGenerator::GenerateKotlin(io::Printer* printer) {
+  printer->Print(
+      "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+      "// source: $filename$\n"
+      "\n",
+      "filename", file_->name());
+  printer->Print(
+      "// Generated files should ignore deprecation warnings\n"
+      "@file:Suppress(\"DEPRECATION\")\n");
+  if (!java_package_.empty()) {
+    printer->Print(
+        "package $package$;\n"
+        "\n",
+        "package", EscapeKotlinKeywords(java_package_));
+  }
+}
+
 void FileGenerator::GenerateKotlinSiblings(
     const std::string& package_dir, GeneratorContext* context,
     std::vector<std::string>* file_list,
@@ -704,15 +728,18 @@
         options_.annotate_code ? &annotation_collector : nullptr);
 
     printer.Print(
-        "//Generated by the protocol buffer compiler. DO NOT EDIT!\n"
+        "// Generated by the protocol buffer compiler. DO NOT EDIT!\n"
         "// source: $filename$\n"
         "\n",
         "filename", descriptor->file()->name());
+    printer.Print(
+        "// Generated files should ignore deprecation warnings\n"
+        "@file:Suppress(\"DEPRECATION\")\n");
     if (!java_package_.empty()) {
       printer.Print(
           "package $package$;\n"
           "\n",
-          "package", java_package_);
+          "package", EscapeKotlinKeywords(java_package_));
     }
 
     generator->GenerateKotlinMembers(&printer);
@@ -736,4 +763,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/file.h b/src/google/protobuf/compiler/java/file.h
index b2e0373..862242f 100644
--- a/src/google/protobuf/compiler/java/file.h
+++ b/src/google/protobuf/compiler/java/file.h
@@ -39,8 +39,8 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/java/options.h>
+#include "google/protobuf/compiler/java/options.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -70,6 +70,8 @@
  public:
   FileGenerator(const FileDescriptor* file, const Options& options,
                 bool immutable_api = true);
+  FileGenerator(const FileGenerator&) = delete;
+  FileGenerator& operator=(const FileGenerator&) = delete;
   ~FileGenerator();
 
   // Checks for problems that would otherwise lead to cryptic compile errors.
@@ -80,6 +82,7 @@
   void Generate(io::Printer* printer);
 
   std::string GetKotlinClassname();
+  void GenerateKotlin(io::Printer* printer);
   void GenerateKotlinSiblings(const std::string& package_dir,
                               GeneratorContext* generator_context,
                               std::vector<std::string>* file_list,
@@ -114,8 +117,6 @@
   ClassNameResolver* name_resolver_;
   const Options options_;
   bool immutable_api_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/generator.cc b/src/google/protobuf/compiler/java/generator.cc
index 85e3991..9f019be 100644
--- a/src/google/protobuf/compiler/java/generator.cc
+++ b/src/google/protobuf/compiler/java/generator.cc
@@ -32,23 +32,19 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/generator.h>
+#include "google/protobuf/compiler/java/generator.h"
 
 
 #include <memory>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/compiler/java/file.h>
-#include <google/protobuf/compiler/java/generator_factory.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/compiler/java/options.h>
-#include <google/protobuf/compiler/java/shared_code_generator.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/str_format.h"
+#include "google/protobuf/compiler/java/file.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/compiler/java/options.h"
+#include "google/protobuf/compiler/java/shared_code_generator.h"
+#include "google/protobuf/descriptor.pb.h"
 
-#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -74,6 +70,8 @@
   ParseGeneratorParameter(parameter, &options);
   Options file_options;
 
+  file_options.opensource_runtime = opensource_runtime_;
+
   for (int i = 0; i < options.size(); i++) {
     if (options[i].first == "output_list_file") {
       file_options.output_list_file = options[i].second;
diff --git a/src/google/protobuf/compiler/java/generator.h b/src/google/protobuf/compiler/java/generator.h
index bbc7170..fdb4bb7 100644
--- a/src/google/protobuf/compiler/java/generator.h
+++ b/src/google/protobuf/compiler/java/generator.h
@@ -38,10 +38,11 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
 
 #include <string>
-#include <google/protobuf/compiler/code_generator.h>
+
+#include "google/protobuf/compiler/code_generator.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -55,6 +56,8 @@
 class PROTOC_EXPORT JavaGenerator : public CodeGenerator {
  public:
   JavaGenerator();
+  JavaGenerator(const JavaGenerator&) = delete;
+  JavaGenerator& operator=(const JavaGenerator&) = delete;
   ~JavaGenerator() override;
 
   // implements CodeGenerator ----------------------------------------
@@ -63,8 +66,12 @@
 
   uint64_t GetSupportedFeatures() const override;
 
+  void set_opensource_runtime(bool opensource) {
+    opensource_runtime_ = opensource;
+  }
+
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JavaGenerator);
+  bool opensource_runtime_ = PROTO2_IS_OSS;
 };
 
 }  // namespace java
@@ -72,6 +79,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/java/generator_factory.cc b/src/google/protobuf/compiler/java/generator_factory.cc
index dd526ba..86baf0b 100644
--- a/src/google/protobuf/compiler/java/generator_factory.cc
+++ b/src/google/protobuf/compiler/java/generator_factory.cc
@@ -30,17 +30,17 @@
 
 // Author: liujisi@google.com (Pherl Liu)
 
-#include <google/protobuf/compiler/java/generator_factory.h>
+#include "google/protobuf/compiler/java/generator_factory.h"
 
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/enum_field.h>
-#include <google/protobuf/compiler/java/extension.h>
-#include <google/protobuf/compiler/java/extension_lite.h>
-#include <google/protobuf/compiler/java/field.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/message.h>
-#include <google/protobuf/compiler/java/message_lite.h>
-#include <google/protobuf/compiler/java/service.h>
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/enum_field.h"
+#include "google/protobuf/compiler/java/extension.h"
+#include "google/protobuf/compiler/java/extension_lite.h"
+#include "google/protobuf/compiler/java/field.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/message.h"
+#include "google/protobuf/compiler/java/message_lite.h"
+#include "google/protobuf/compiler/java/service.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/java/generator_factory.h b/src/google/protobuf/compiler/java/generator_factory.h
index 807bca3..b2fb054 100644
--- a/src/google/protobuf/compiler/java/generator_factory.h
+++ b/src/google/protobuf/compiler/java/generator_factory.h
@@ -33,7 +33,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_GENERATOR_FACTORY_H__
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -59,6 +59,8 @@
 class GeneratorFactory {
  public:
   GeneratorFactory();
+  GeneratorFactory(const GeneratorFactory&) = delete;
+  GeneratorFactory& operator=(const GeneratorFactory&) = delete;
   virtual ~GeneratorFactory();
 
   virtual MessageGenerator* NewMessageGenerator(
@@ -69,15 +71,15 @@
 
   virtual ServiceGenerator* NewServiceGenerator(
       const ServiceDescriptor* descriptor) const = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GeneratorFactory);
 };
 
 // Factory that creates generators for immutable-default messages.
 class ImmutableGeneratorFactory : public GeneratorFactory {
  public:
   ImmutableGeneratorFactory(Context* context);
+  ImmutableGeneratorFactory(const ImmutableGeneratorFactory&) = delete;
+  ImmutableGeneratorFactory& operator=(const ImmutableGeneratorFactory&) =
+      delete;
   ~ImmutableGeneratorFactory() override;
 
   MessageGenerator* NewMessageGenerator(
@@ -91,7 +93,6 @@
 
  private:
   Context* context_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableGeneratorFactory);
 };
 
 
diff --git a/src/google/protobuf/compiler/java/helpers.cc b/src/google/protobuf/compiler/java/helpers.cc
index 15ee8f5..dd688db 100644
--- a/src/google/protobuf/compiler/java/helpers.cc
+++ b/src/google/protobuf/compiler/java/helpers.cc
@@ -32,25 +32,29 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/helpers.h>
+#include "google/protobuf/compiler/java/helpers.h"
 
 #include <algorithm>
 #include <cstdint>
 #include <limits>
-#include <unordered_set>
 #include <vector>
 
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/compiler/java/names.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/hash.h>  // for hash<T *>
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -65,78 +69,9 @@
 const char kThinSeparator[] =
     "// -------------------------------------------------------------------\n";
 
-namespace {
-
-const char* kDefaultPackage = "";
-
-// Names that should be avoided (in UpperCamelCase format).
-// Using them will cause the compiler to generate accessors whose names
-// collide with methods defined in base classes.
-// Keep this list in sync with specialFieldNames in
-// java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java
-const char* kForbiddenWordList[] = {
-    // java.lang.Object:
-    "Class",
-    // com.google.protobuf.MessageLiteOrBuilder:
-    "DefaultInstanceForType",
-    // com.google.protobuf.MessageLite:
-    "ParserForType",
-    "SerializedSize",
-    // com.google.protobuf.MessageOrBuilder:
-    "AllFields",
-    "DescriptorForType",
-    "InitializationErrorString",
-    "UnknownFields",
-    // obsolete. kept for backwards compatibility of generated code
-    "CachedSize",
-};
-
-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",
-        "enum",       "extends",      "final",     "finally",    "float",
-        "for",        "goto",         "if",        "implements", "import",
-        "instanceof", "int",          "interface", "long",       "native",
-        "new",        "package",      "private",   "protected",  "public",
-        "return",     "short",        "static",    "strictfp",   "super",
-        "switch",     "synchronized", "this",      "throw",      "throws",
-        "transient",  "try",          "void",      "volatile",   "while",
-    });
-
-bool IsForbidden(const std::string& field_name) {
-  for (int i = 0; i < GOOGLE_ARRAYSIZE(kForbiddenWordList); ++i) {
-    if (UnderscoresToCamelCase(field_name, true) == kForbiddenWordList[i]) {
-      return true;
-    }
-  }
-  return false;
-}
-
-std::string FieldName(const FieldDescriptor* field) {
-  std::string field_name;
-  // Groups are hacky:  The name of the field is just the lower-cased name
-  // of the group type.  In Java, though, we would like to retain the original
-  // capitalization of the type name.
-  if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
-    field_name = field->message_type()->name();
-  } else {
-    field_name = field->name();
-  }
-  if (IsForbidden(field_name)) {
-    // Append a trailing "#" to indicate that the name should be decorated to
-    // avoid collision with other names.
-    field_name += "#";
-  }
-  return field_name;
-}
-
-
-}  // namespace
-
 void PrintGeneratedAnnotation(io::Printer* printer, char delimiter,
-                              const std::string& annotation_file) {
+                              const std::string& annotation_file,
+                              Options options) {
   if (annotation_file.empty()) {
     return;
   }
@@ -149,14 +84,13 @@
   printer->Print(ptemplate.c_str(), "annotation_file", annotation_file);
 }
 
-void PrintEnumVerifierLogic(io::Printer* printer,
-                            const FieldDescriptor* descriptor,
-                            const std::map<std::string, std::string>& variables,
-                            const char* var_name,
-                            const char* terminating_string, bool enforce_lite) {
+void PrintEnumVerifierLogic(
+    io::Printer* printer, const FieldDescriptor* descriptor,
+    const absl::flat_hash_map<absl::string_view, std::string>& variables,
+    const char* var_name, const char* terminating_string, bool enforce_lite) {
   std::string enum_verifier_string =
-      enforce_lite ? StrCat(var_name, ".internalGetVerifier()")
-                   : StrCat(
+      enforce_lite ? absl::StrCat(var_name, ".internalGetVerifier()")
+                   : absl::StrCat(
                          "new com.google.protobuf.Internal.EnumVerifier() {\n"
                          "        @java.lang.Override\n"
                          "        public boolean isInRange(int number) {\n"
@@ -167,7 +101,7 @@
                          "      }");
   printer->Print(
       variables,
-      StrCat(enum_verifier_string, terminating_string).c_str());
+      absl::StrCat(enum_verifier_string, terminating_string).c_str());
 }
 
 std::string UnderscoresToCamelCase(const std::string& input,
@@ -216,7 +150,7 @@
     if (i == '_') {
       capitalize_next = true;
     } else if (capitalize_next) {
-      result.push_back(ToUpperCh(i));
+      result.push_back(absl::ascii_toupper(i));
       capitalize_next = false;
     } else {
       result.push_back(i);
@@ -225,62 +159,43 @@
 
   // Lower-case the first letter.
   if (lower_first && !result.empty()) {
-    result[0] = ToLowerCh(result[0]);
+    result[0] = absl::ascii_tolower(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);
-}
-
-std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
-  return UnderscoresToCamelCase(FieldName(field), true);
-}
-
-std::string CapitalizedFieldName(const FieldDescriptor* field) {
-  return UnderscoresToCapitalizedCamelCase(field);
-}
-
-std::string UnderscoresToCamelCase(const MethodDescriptor* method) {
-  return UnderscoresToCamelCase(method->name(), false);
-}
-
-std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) {
-  std::string name = UnderscoresToCamelCase(field);
-  if (kReservedNames->find(name) != kReservedNames->end()) {
-    return name + "_";
-  }
-  return 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",
-    });
+bool IsForbiddenKotlin(absl::string_view field_name) {
+  static const auto& kKotlinForbiddenNames =
+      *new absl::flat_hash_set<absl::string_view>({
+          "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",
+      });
 
-bool IsForbiddenKotlin(const std::string& field_name) {
-  return kKotlinForbiddenNames->find(field_name) !=
-         kKotlinForbiddenNames->end();
+  return kKotlinForbiddenNames.contains(field_name);
+}
+
+std::string EscapeKotlinKeywords(std::string name) {
+  std::vector<std::string> escaped_packages;
+  std::vector<std::string> packages = absl::StrSplit(name, "."); // NOLINT
+  for (const std::string& package : packages) {
+    if (IsForbiddenKotlin(package)) {
+      escaped_packages.push_back("`" + package + "`");
+    } else {
+      escaped_packages.push_back(package);
+    }
+  }
+  return absl::StrJoin(escaped_packages, ".");
 }
 
 std::string UniqueFileScopeIdentifier(const Descriptor* descriptor) {
-  return "static_" + StringReplace(descriptor->full_name(), ".", "_", true);
+  return "static_" + absl::StrReplaceAll(descriptor->full_name(), {{".", "_"}});
 }
 
 std::string CamelCaseFieldName(const FieldDescriptor* field) {
@@ -292,57 +207,15 @@
 }
 
 std::string FileClassName(const FileDescriptor* file, bool immutable) {
-  ClassNameResolver name_resolver;
-  return name_resolver.GetFileClassName(file, immutable);
-}
-
-std::string FileJavaPackage(const FileDescriptor* file, bool immutable) {
-  std::string result;
-
-  if (file->options().has_java_package()) {
-    result = file->options().java_package();
-  } else {
-    result = kDefaultPackage;
-    if (!file->package().empty()) {
-      if (!result.empty()) result += '.';
-      result += file->package();
-    }
-  }
-
-  return result;
-}
-
-std::string FileJavaPackage(const FileDescriptor* file) {
-  return FileJavaPackage(file, true /* immutable */);
+  return ClassNameResolver().GetFileClassName(file, immutable);
 }
 
 std::string JavaPackageToDir(std::string package_name) {
-  std::string package_dir = StringReplace(package_name, ".", "/", true);
+  std::string package_dir = absl::StrReplaceAll(package_name, {{".", "/"}});
   if (!package_dir.empty()) package_dir += "/";
   return package_dir;
 }
 
-std::string ClassName(const Descriptor* descriptor) {
-  ClassNameResolver name_resolver;
-  return name_resolver.GetClassName(descriptor, true);
-}
-
-std::string ClassName(const EnumDescriptor* descriptor) {
-  ClassNameResolver name_resolver;
-  return name_resolver.GetClassName(descriptor, true);
-}
-
-std::string ClassName(const ServiceDescriptor* descriptor) {
-  ClassNameResolver name_resolver;
-  return name_resolver.GetClassName(descriptor, true);
-}
-
-std::string ClassName(const FileDescriptor* descriptor) {
-  ClassNameResolver name_resolver;
-  return name_resolver.GetClassName(descriptor, true);
-}
-
-
 std::string ExtraMessageInterfaces(const Descriptor* descriptor) {
   std::string interfaces = "// @@protoc_insertion_point(message_implements:" +
                            descriptor->full_name() + ")";
@@ -364,7 +237,7 @@
 
 std::string FieldConstantName(const FieldDescriptor* field) {
   std::string name = field->name() + "_FIELD_NUMBER";
-  ToUpper(&name);
+  absl::AsciiStrToUpper(&name);
   return name;
 }
 
@@ -519,7 +392,7 @@
     case JAVATYPE_ENUM:
       return "java.lang.Integer";
     case JAVATYPE_MESSAGE:
-      return ClassName(field->message_type());
+      return ClassNameResolver().GetClassName(field->message_type(), true);
     default:
       return BoxedPrimitiveTypeName(javaType);
   }
@@ -582,19 +455,19 @@
 }
 
 std::string DefaultValue(const FieldDescriptor* field, bool immutable,
-                         ClassNameResolver* name_resolver) {
+                         ClassNameResolver* name_resolver, Options options) {
   // Switch on CppType since we need to know which default_value_* method
   // of FieldDescriptor to call.
   switch (field->cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
-      return StrCat(field->default_value_int32());
+      return absl::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_t>(field->default_value_uint32()));
+      return absl::StrCat(static_cast<int32_t>(field->default_value_uint32()));
     case FieldDescriptor::CPPTYPE_INT64:
-      return StrCat(field->default_value_int64()) + "L";
+      return absl::StrCat(field->default_value_int64()) + "L";
     case FieldDescriptor::CPPTYPE_UINT64:
-      return StrCat(static_cast<int64_t>(field->default_value_uint64())) +
+      return absl::StrCat(static_cast<int64_t>(field->default_value_uint64())) +
              "L";
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field->default_value_double();
@@ -605,7 +478,7 @@
       } else if (value != value) {
         return "Double.NaN";
       } else {
-        return SimpleDtoa(value) + "D";
+        return io::SimpleDtoa(value) + "D";
       }
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
@@ -617,7 +490,7 @@
       } else if (value != value) {
         return "Float.NaN";
       } else {
-        return SimpleFtoa(value) + "F";
+        return io::SimpleFtoa(value) + "F";
       }
     }
     case FieldDescriptor::CPPTYPE_BOOL:
@@ -626,21 +499,21 @@
       if (GetType(field) == FieldDescriptor::TYPE_BYTES) {
         if (field->has_default_value()) {
           // See comments in Internal.java for gory details.
-          return strings::Substitute(
+          return absl::Substitute(
               "com.google.protobuf.Internal.bytesDefaultValue(\"$0\")",
-              CEscape(field->default_value_string()));
+              absl::CEscape(field->default_value_string()));
         } else {
           return "com.google.protobuf.ByteString.EMPTY";
         }
       } else {
         if (AllAscii(field->default_value_string())) {
           // All chars are ASCII.  In this case CEscape() works fine.
-          return "\"" + CEscape(field->default_value_string()) + "\"";
+          return "\"" + absl::CEscape(field->default_value_string()) + "\"";
         } else {
           // See comments in Internal.java for gory details.
-          return strings::Substitute(
+          return absl::Substitute(
               "com.google.protobuf.Internal.stringDefaultValue(\"$0\")",
-              CEscape(field->default_value_string()));
+              absl::CEscape(field->default_value_string()));
         }
       }
 
@@ -713,7 +586,7 @@
 
 std::string GetBitFieldName(int index) {
   std::string varName = "bitField";
-  varName += StrCat(index);
+  varName += absl::StrCat(index);
   varName += "_";
   return varName;
 }
@@ -806,7 +679,8 @@
   return false;
 }
 
-const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable) {
+const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable,
+                               Options options) {
   switch (GetType(field)) {
     case FieldDescriptor::TYPE_INT32:
       return "Int32";
@@ -923,7 +797,7 @@
 // already_seen is used to avoid checking the same type multiple times
 // (and also to protect against recursion).
 bool HasRequiredFields(const Descriptor* type,
-                       std::unordered_set<const Descriptor*>* already_seen) {
+                       absl::flat_hash_set<const Descriptor*>* already_seen) {
   if (already_seen->count(type) > 0) {
     // The type is already in cache.  This means that either:
     // a. The type has no required fields.
@@ -958,7 +832,7 @@
 }
 
 bool HasRequiredFields(const Descriptor* type) {
-  std::unordered_set<const Descriptor*> already_seen;
+  absl::flat_hash_set<const Descriptor*> already_seen;
   return HasRequiredFields(type, &already_seen);
 }
 
@@ -1103,7 +977,7 @@
   } else if (code >= 0x20 && code <= 0x7f) {
     output->push_back(static_cast<char>(code));
   } else {
-    output->append(StringPrintf("\\u%04x", code));
+    output->append(absl::StrFormat("\\u%04x", code));
   }
 }
 
@@ -1112,4 +986,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/helpers.h b/src/google/protobuf/compiler/java/helpers.h
index 9f1a557..79f1785 100644
--- a/src/google/protobuf/compiler/java/helpers.h
+++ b/src/google/protobuf/compiler/java/helpers.h
@@ -38,10 +38,15 @@
 #include <cstdint>
 #include <string>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/compiler/java/names.h"
+#include "google/protobuf/compiler/java/options.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+
+// Must be last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -53,7 +58,7 @@
 extern const char kThickSeparator[];
 extern const char kThinSeparator[];
 
-bool IsForbiddenKotlin(const std::string& field_name);
+bool IsForbiddenKotlin(absl::string_view 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
@@ -64,39 +69,20 @@
 // annotation_file should be generated from the filename of the source file
 // being annotated (which in turn must be a Java identifier plus ".java").
 void PrintGeneratedAnnotation(io::Printer* printer, char delimiter = '$',
-                              const std::string& annotation_file = "");
+                              const std::string& annotation_file = "",
+                              Options options = {});
 
 // If a GeneratedMessageLite contains non-lite enums, then its verifier
 // must be instantiated inline, rather than retrieved from the enum class.
-void PrintEnumVerifierLogic(io::Printer* printer,
-                            const FieldDescriptor* descriptor,
-                            const std::map<std::string, std::string>& variables,
-                            const char* var_name,
-                            const char* terminating_string, bool enforce_lite);
+void PrintEnumVerifierLogic(
+    io::Printer* printer, const FieldDescriptor* descriptor,
+    const absl::flat_hash_map<absl::string_view, std::string>& variables,
+    const char* var_name, const char* terminating_string, bool enforce_lite);
 
 // 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
-// "fooBarBaz" or "FooBarBaz", respectively.
-std::string UnderscoresToCamelCase(const FieldDescriptor* field);
-std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field);
-
-// Similar, but for method names.  (Typically, this merely has the effect
-// of lower-casing the first letter of the name.)
-std::string UnderscoresToCamelCase(const MethodDescriptor* method);
-
-// Same as UnderscoresToCamelCase, but checks for reserved keywords
-std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field);
-
 // Similar to UnderscoresToCamelCase, but guarantees that the result is a
 // complete Java identifier by adding a _ if needed.
 std::string CamelCaseFieldName(const FieldDescriptor* field);
@@ -113,11 +99,15 @@
 std::string FileClassName(const FileDescriptor* file, bool immutable = true);
 
 // Returns the file's Java package name.
-std::string FileJavaPackage(const FileDescriptor* file, bool immutable);
+std::string FileJavaPackage(const FileDescriptor* file, bool immutable,
+                            Options options = {});
 
 // Returns output directory for the given package name.
 std::string JavaPackageToDir(std::string package_name);
 
+// Returns the name with Kotlin keywords enclosed in backticks
+std::string EscapeKotlinKeywords(std::string name);
+
 // 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);
@@ -198,18 +188,6 @@
   return descriptor->name() + suffix + ".java.pb.meta";
 }
 
-template <typename Descriptor>
-void MaybePrintGeneratedAnnotation(Context* context, io::Printer* printer,
-                                   Descriptor* descriptor, bool immutable,
-                                   const std::string& suffix = "") {
-  if (IsOwnFile(descriptor, immutable)) {
-    PrintGeneratedAnnotation(printer, '$',
-                             context->options().annotate_code
-                                 ? AnnotationFileName(descriptor, suffix)
-                                 : "");
-  }
-}
-
 // Get the unqualified name that should be used for a field's field
 // number constant.
 std::string FieldConstantName(const FieldDescriptor* field);
@@ -251,10 +229,12 @@
 
 class ClassNameResolver;
 std::string DefaultValue(const FieldDescriptor* field, bool immutable,
-                         ClassNameResolver* name_resolver);
+                         ClassNameResolver* name_resolver,
+                         Options options = {});
 inline std::string ImmutableDefaultValue(const FieldDescriptor* field,
-                                         ClassNameResolver* name_resolver) {
-  return DefaultValue(field, true, name_resolver);
+                                         ClassNameResolver* name_resolver,
+                                         Options options = {}) {
+  return DefaultValue(field, true, name_resolver, options);
 }
 bool IsDefaultValueJavaDefault(const FieldDescriptor* field);
 bool IsByteStringWithCustomDefaultValue(const FieldDescriptor* field);
@@ -333,7 +313,8 @@
 
 // Returns the capitalized name for calling relative functions in
 // CodedInputStream
-const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable);
+const char* GetCapitalizedType(const FieldDescriptor* field, bool immutable,
+                               Options options);
 
 // For encodings with fixed sizes, returns that size in bytes.  Otherwise
 // returns -1.
@@ -471,4 +452,5 @@
 }  // namespace protobuf
 }  // namespace google
 
+#include "google/protobuf/port_undef.inc"
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_HELPERS_H__
diff --git a/src/google/protobuf/compiler/java/java_generator.h b/src/google/protobuf/compiler/java/java_generator.h
index 294b1bd..45d30a5 100644
--- a/src/google/protobuf/compiler/java/java_generator.h
+++ b/src/google/protobuf/compiler/java/java_generator.h
@@ -1,6 +1,36 @@
+// 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_JAVA_JAVA_GENERATOR_H_
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_JAVA_GENERATOR_H_
 
-#include <google/protobuf/compiler/java/generator.h>
+#include "google/protobuf/compiler/java/generator.h"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_JAVA_GENERATOR_H_
diff --git a/src/google/protobuf/compiler/java/kotlin_generator.cc b/src/google/protobuf/compiler/java/kotlin_generator.cc
index 1af548a..685b1e8 100644
--- a/src/google/protobuf/compiler/java/kotlin_generator.cc
+++ b/src/google/protobuf/compiler/java/kotlin_generator.cc
@@ -28,13 +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.
 
-#include <google/protobuf/compiler/java/kotlin_generator.h>
+#include "google/protobuf/compiler/java/kotlin_generator.h"
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/java/file.h>
-#include <google/protobuf/compiler/java/generator.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/options.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/java/file.h"
+#include "google/protobuf/compiler/java/generator.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/options.h"
 
 namespace google {
 namespace protobuf {
@@ -119,6 +119,8 @@
       output.get(), '$',
       file_options.annotate_code ? &annotation_collector : nullptr);
 
+  file_generator->GenerateKotlin(&printer);
+
   file_generator->GenerateKotlinSiblings(package_dir, context, &all_files,
                                          &all_annotations);
 
diff --git a/src/google/protobuf/compiler/java/kotlin_generator.h b/src/google/protobuf/compiler/java/kotlin_generator.h
index ccd9688..312b653 100644
--- a/src/google/protobuf/compiler/java/kotlin_generator.h
+++ b/src/google/protobuf/compiler/java/kotlin_generator.h
@@ -35,10 +35,10 @@
 
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
+#include "google/protobuf/compiler/code_generator.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -52,6 +52,8 @@
 class PROTOC_EXPORT KotlinGenerator : public CodeGenerator {
  public:
   KotlinGenerator();
+  KotlinGenerator(const KotlinGenerator&) = delete;
+  KotlinGenerator& operator=(const KotlinGenerator&) = delete;
   ~KotlinGenerator() override;
 
   // implements CodeGenerator ----------------------------------------
@@ -59,9 +61,6 @@
                 GeneratorContext* context, std::string* error) const override;
 
   uint64_t GetSupportedFeatures() const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(KotlinGenerator);
 };
 
 }  // namespace java
@@ -69,6 +68,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_KOTLIN_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/java/map_field.cc b/src/google/protobuf/compiler/java/map_field.cc
index 777f107..603d2b9 100644
--- a/src/google/protobuf/compiler/java/map_field.cc
+++ b/src/google/protobuf/compiler/java/map_field.cc
@@ -30,11 +30,12 @@
 
 #include "google/protobuf/compiler/java/map_field.h"
 
-#include "google/protobuf/io/printer.h"
+#include "absl/strings/str_cat.h"
 #include "google/protobuf/compiler/java/context.h"
 #include "google/protobuf/compiler/java/doc_comment.h"
 #include "google/protobuf/compiler/java/helpers.h"
 #include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be last.
 #include "google/protobuf/port_def.inc"
@@ -91,7 +92,7 @@
 void SetMessageVariables(
     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
     const FieldGeneratorInfo* info, Context* context,
-    std::map<std::string, std::string>* variables) {
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
   ClassNameResolver* name_resolver = context->GetNameResolver();
 
@@ -102,7 +103,12 @@
   const JavaType keyJavaType = GetJavaType(key);
   const JavaType valueJavaType = GetJavaType(value);
 
-  std::string pass_through_nullness = "/* nullable */\n";
+  // The code that generates the open-source version appears not to understand
+  // #else, so we have an #ifndef instead.
+  std::string pass_through_nullness =
+      context->options().opensource_runtime
+          ? "/* nullable */\n"
+          : "@com.google.protobuf.Internal.ProtoPassThroughNullness ";
 
   (*variables)["key_type"] = TypeName(key, name_resolver, false);
   std::string boxed_key_type = TypeName(key, name_resolver, true);
@@ -113,7 +119,8 @@
   (*variables)["short_key_type"] =
       boxed_key_type.substr(boxed_key_type.rfind('.') + 1);
   (*variables)["key_wire_type"] = WireType(key);
-  (*variables)["key_default_value"] = DefaultValue(key, true, name_resolver);
+  (*variables)["key_default_value"] =
+      DefaultValue(key, true, name_resolver, context->options());
   (*variables)["key_null_check"] =
       IsReferenceType(keyJavaType)
           ? "if (key == null) { throw new NullPointerException(\"map key\"); }"
@@ -131,40 +138,41 @@
     (*variables)["boxed_value_type"] = "java.lang.Integer";
     (*variables)["value_wire_type"] = WireType(value);
     (*variables)["value_default_value"] =
-        DefaultValue(value, true, name_resolver) + ".getNumber()";
+        DefaultValue(value, true, name_resolver, context->options()) +
+        ".getNumber()";
 
     (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
 
     variables->insert(
         {"value_enum_type_pass_through_nullness",
-         StrCat(pass_through_nullness, (*variables)["value_enum_type"])});
+         absl::StrCat(pass_through_nullness, (*variables)["value_enum_type"])});
 
     if (SupportUnknownEnumValue(descriptor->file())) {
       // Map unknown values to a special UNRECOGNIZED value if supported.
       variables->insert(
           {"unrecognized_value",
-           StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")});
+           absl::StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")});
     } else {
       // Map unknown values to the default value if we don't have UNRECOGNIZED.
       (*variables)["unrecognized_value"] =
-          DefaultValue(value, true, name_resolver);
+          DefaultValue(value, true, name_resolver, context->options());
     }
   } else {
     (*variables)["value_type"] = TypeName(value, name_resolver, false);
 
     variables->insert(
         {"value_type_pass_through_nullness",
-         StrCat(
+         absl::StrCat(
              (IsReferenceType(valueJavaType) ? pass_through_nullness : ""),
              (*variables)["value_type"])});
 
     (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
     (*variables)["value_wire_type"] = WireType(value);
     (*variables)["value_default_value"] =
-        DefaultValue(value, true, name_resolver);
+        DefaultValue(value, true, name_resolver, context->options());
   }
   variables->insert(
-      {"type_parameters", StrCat((*variables)["boxed_key_type"], ", ",
+      {"type_parameters", absl::StrCat((*variables)["boxed_key_type"], ", ",
                                        (*variables)["boxed_value_type"])});
   // TODO(birdo): Add @deprecated javadoc when generating javadoc is supported
   // by the proto compiler
@@ -173,13 +181,13 @@
   variables->insert(
       {"kt_deprecation",
        descriptor->options().deprecated()
-           ? StrCat("@kotlin.Deprecated(message = \"Field ",
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
                           (*variables)["name"], " is deprecated\") ")
            : ""});
   (*variables)["on_changed"] = "onChanged();";
 
   variables->insert(
-      {"default_entry", StrCat((*variables)["capitalized_name"],
+      {"default_entry", absl::StrCat((*variables)["capitalized_name"],
                                      "DefaultEntryHolder.defaultEntry")});
   variables->insert({"map_field_parameter", (*variables)["default_entry"]});
   (*variables)["descriptor"] =
@@ -237,14 +245,16 @@
                  "    $key_type$ key);\n");
   printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Deprecated\n"
-                   "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-                   "${$get$capitalized_name$$}$();\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(variables_,
+                     "/**\n"
+                     " * Use {@link #get$capitalized_name$Map()} instead.\n"
+                     " */\n"
+                     "@java.lang.Deprecated\n"
+                     "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+                     "${$get$capitalized_name$$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
@@ -295,14 +305,16 @@
       printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Deprecated\n"
-                   "java.util.Map<$type_parameters$>\n"
-                   "${$get$capitalized_name$$}$();\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(variables_,
+                     "/**\n"
+                     " * Use {@link #get$capitalized_name$Map()} instead.\n"
+                     " */\n"
+                     "@java.lang.Deprecated\n"
+                     "java.util.Map<$type_parameters$>\n"
+                     "${$get$capitalized_name$$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "$deprecation$java.util.Map<$type_parameters$>\n"
@@ -423,19 +435,22 @@
   printer->Annotate("{", "}", descriptor_);
 
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
-    printer->Print(
-        variables_,
-        "/**\n"
-        " * Use alternate mutation accessors instead.\n"
-        " */\n"
-        "@java.lang.Deprecated\n"
-        "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-        "    ${$getMutable$capitalized_name$$}$() {\n"
-        "  $set_has_field_bit_builder$\n"
-        "  return internalGetAdapted$capitalized_name$Map(\n"
-        "       internalGetMutable$capitalized_name$().getMutableMap());\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use alternate mutation accessors instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+          "    ${$getMutable$capitalized_name$$}$() {\n"
+          "  $set_has_field_bit_builder$\n"
+          "  return internalGetAdapted$capitalized_name$Map(\n"
+          "       internalGetMutable$capitalized_name$().getMutableMap());\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
+
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
@@ -464,18 +479,21 @@
     printer->Annotate("{", "}", descriptor_);
 
     if (SupportUnknownEnumValue(descriptor_->file())) {
-      printer->Print(
-          variables_,
-          "/**\n"
-          " * Use alternate mutation accessors instead.\n"
-          " */\n"
-          "@java.lang.Deprecated\n"
-          "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
-          "${$getMutable$capitalized_name$Value$}$() {\n"
-          "  $set_has_field_bit_builder$\n"
-          "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
-          "}\n");
-      printer->Annotate("{", "}", descriptor_);
+      if (context_->options().opensource_runtime) {
+        printer->Print(
+            variables_,
+            "/**\n"
+            " * Use alternate mutation accessors instead.\n"
+            " */\n"
+            "@java.lang.Deprecated\n"
+            "public java.util.Map<$boxed_key_type$, $boxed_value_type$>\n"
+            "${$getMutable$capitalized_name$Value$}$() {\n"
+            "  $set_has_field_bit_builder$\n"
+            "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+            "}\n");
+        printer->Annotate("{", "}", descriptor_);
+      }
+
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(
           variables_,
@@ -504,18 +522,21 @@
       printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    printer->Print(
-        variables_,
-        "/**\n"
-        " * Use alternate mutation accessors instead.\n"
-        " */\n"
-        "@java.lang.Deprecated\n"
-        "public java.util.Map<$type_parameters$>\n"
-        "    ${$getMutable$capitalized_name$$}$() {\n"
-        "  $set_has_field_bit_builder$\n"
-        "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
-        "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use alternate mutation accessors instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "public java.util.Map<$type_parameters$>\n"
+          "    ${$getMutable$capitalized_name$$}$() {\n"
+          "  $set_has_field_bit_builder$\n"
+          "  return internalGetMutable$capitalized_name$().getMutableMap();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
+
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "$deprecation$public Builder ${$put$capitalized_name$$}$(\n"
@@ -565,17 +586,21 @@
   printer->Annotate("{", "}", descriptor_);
 
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Override\n"
-                   "@java.lang.Deprecated\n"
-                   "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-                   "${$get$capitalized_name$$}$() {\n"
-                   "  return get$capitalized_name$Map();\n"
-                   "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use {@link #get$capitalized_name$Map()} instead.\n"
+          " */\n"
+          "@java.lang.Override\n"
+          "@java.lang.Deprecated\n"
+          "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+          "${$get$capitalized_name$$}$() {\n"
+          "  return get$capitalized_name$Map();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
+
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "@java.lang.Override\n"
@@ -674,17 +699,19 @@
       printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Override\n"
-                   "@java.lang.Deprecated\n"
-                   "public java.util.Map<$type_parameters$> "
-                   "${$get$capitalized_name$$}$() {\n"
-                   "  return get$capitalized_name$Map();\n"
-                   "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(variables_,
+                     "/**\n"
+                     " * Use {@link #get$capitalized_name$Map()} instead.\n"
+                     " */\n"
+                     "@java.lang.Override\n"
+                     "@java.lang.Deprecated\n"
+                     "public java.util.Map<$type_parameters$> "
+                     "${$get$capitalized_name$$}$() {\n"
+                     "  return get$capitalized_name$Map();\n"
+                     "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "@java.lang.Override\n"
@@ -738,7 +765,7 @@
       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "$kt_deprecation$ public val $kt_name$: "
@@ -750,7 +777,7 @@
       "    $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
       "  )\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@JvmName(\"put$kt_capitalized_name$\")\n"
@@ -760,7 +787,7 @@
       "     $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -772,7 +799,7 @@
       "     put(key, value)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -783,7 +810,7 @@
       "     $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -795,7 +822,7 @@
       "     $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
diff --git a/src/google/protobuf/compiler/java/map_field.h b/src/google/protobuf/compiler/java/map_field.h
index d54a28b..5454ea0 100644
--- a/src/google/protobuf/compiler/java/map_field.h
+++ b/src/google/protobuf/compiler/java/map_field.h
@@ -72,7 +72,7 @@
   const FieldDescriptor* descriptor_;
   int message_bit_index_;
   int builder_bit_index_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   ClassNameResolver* name_resolver_;
   Context* context_;
   void GenerateMapGetters(io::Printer* printer) const;
diff --git a/src/google/protobuf/compiler/java/map_field_lite.cc b/src/google/protobuf/compiler/java/map_field_lite.cc
index ed6f8f3..b2b5b77 100644
--- a/src/google/protobuf/compiler/java/map_field_lite.cc
+++ b/src/google/protobuf/compiler/java/map_field_lite.cc
@@ -28,18 +28,18 @@
 // (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/map_field_lite.h>
+#include "google/protobuf/compiler/java/map_field_lite.h"
 
 #include <cstdint>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -90,10 +90,10 @@
          std::string(FieldTypeName(field->type()));
 }
 
-void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
-                         int builderBitIndex, const FieldGeneratorInfo* info,
-                         Context* context,
-                         std::map<std::string, std::string>* variables) {
+void SetMessageVariables(
+    const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+    const FieldGeneratorInfo* info, Context* context,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   ClassNameResolver* name_resolver = context->GetNameResolver();
@@ -104,14 +104,18 @@
   const JavaType keyJavaType = GetJavaType(key);
   const JavaType valueJavaType = GetJavaType(value);
 
-  std::string pass_through_nullness = "/* nullable */\n";
+  std::string pass_through_nullness =
+      context->options().opensource_runtime
+          ? "/* nullable */\n"
+          : "@com.google.protobuf.Internal.ProtoPassThroughNullness ";
 
   (*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);
+  (*variables)["key_default_value"] =
+      DefaultValue(key, true, name_resolver, context->options());
   // We use `x.getClass()` as a null check because it generates less bytecode
   // than an `if (x == null) { throw ... }` statement.
   (*variables)["key_null_check"] =
@@ -126,51 +130,63 @@
   if (GetJavaType(value) == JAVATYPE_ENUM) {
     // We store enums as Integers internally.
     (*variables)["value_type"] = "int";
+    (*variables)["value_type_pass_through_nullness"] = "int";
     (*variables)["boxed_value_type"] = "java.lang.Integer";
     (*variables)["value_wire_type"] = WireType(value);
     (*variables)["value_default_value"] =
-        DefaultValue(value, true, name_resolver) + ".getNumber()";
+        DefaultValue(value, true, name_resolver, context->options()) +
+        ".getNumber()";
 
     (*variables)["value_enum_type"] = TypeName(value, name_resolver, false);
 
-    (*variables)["value_enum_type_pass_through_nullness"] =
-        pass_through_nullness + (*variables)["value_enum_type"];
+    variables->insert(
+        {"value_enum_type_pass_through_nullness",
+         absl::StrCat(pass_through_nullness, (*variables)["value_enum_type"])});
 
     if (SupportUnknownEnumValue(descriptor->file())) {
       // Map unknown values to a special UNRECOGNIZED value if supported.
-      (*variables)["unrecognized_value"] =
-          (*variables)["value_enum_type"] + ".UNRECOGNIZED";
+      variables->insert(
+          {"unrecognized_value",
+           absl::StrCat((*variables)["value_enum_type"], ".UNRECOGNIZED")});
     } else {
       // Map unknown values to the default value if we don't have UNRECOGNIZED.
       (*variables)["unrecognized_value"] =
-          DefaultValue(value, true, name_resolver);
+          DefaultValue(value, true, name_resolver, context->options());
     }
   } else {
     (*variables)["value_type"] = TypeName(value, name_resolver, false);
 
-    (*variables)["value_type_pass_through_nullness"] =
-        (IsReferenceType(valueJavaType) ? pass_through_nullness : "") +
-        (*variables)["value_type"];
+    variables->insert(
+        {"value_type_pass_through_nullness",
+         absl::StrCat(
+             (IsReferenceType(valueJavaType) ? pass_through_nullness : ""),
+             (*variables)["value_type"])});
 
     (*variables)["boxed_value_type"] = TypeName(value, name_resolver, true);
     (*variables)["value_wire_type"] = WireType(value);
     (*variables)["value_default_value"] =
-        DefaultValue(value, true, name_resolver);
+        DefaultValue(value, true, name_resolver, context->options());
   }
-  (*variables)["type_parameters"] =
-      (*variables)["boxed_key_type"] + ", " + (*variables)["boxed_value_type"];
+  variables->insert(
+      {"type_parameters", absl::StrCat((*variables)["boxed_key_type"], ", ",
+                                       (*variables)["boxed_value_type"])});
   // 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->insert(
+      {"kt_deprecation",
+       descriptor->options().deprecated()
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
+                          (*variables)["name"], " is deprecated\") ")
+           : ""});
 
-  (*variables)["default_entry"] =
-      (*variables)["capitalized_name"] + "DefaultEntryHolder.defaultEntry";
+  variables->insert(
+      {"default_entry", absl::StrCat((*variables)["capitalized_name"],
+                                     "DefaultEntryHolder.defaultEntry")});
+  // { and } variables are used as delimiters when emitting annotations.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 }  // namespace
@@ -201,14 +217,16 @@
                  "    $key_type$ key);\n");
   printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Deprecated\n"
-                   "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-                   "${$get$capitalized_name$$}$();\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(variables_,
+                     "/**\n"
+                     " * Use {@link #get$capitalized_name$Map()} instead.\n"
+                     " */\n"
+                     "@java.lang.Deprecated\n"
+                     "java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+                     "${$get$capitalized_name$$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
@@ -247,9 +265,10 @@
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
                      "$deprecation$\n"
-                     "$value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+                     "$value_type_pass_through_nullness$ "
+                     "${$get$capitalized_name$ValueOrDefault$}$(\n"
                      "    $key_type$ key,\n"
-                     "    $value_type$ defaultValue);\n");
+                     "    $value_type_pass_through_nullness$ defaultValue);\n");
       printer->Annotate("{", "}", descriptor_);
       WriteFieldDocComment(printer, descriptor_);
       printer->Print(variables_,
@@ -259,14 +278,16 @@
       printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Deprecated\n"
-                   "java.util.Map<$type_parameters$>\n"
-                   "${$get$capitalized_name$$}$();\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(variables_,
+                     "/**\n"
+                     " * Use {@link #get$capitalized_name$Map()} instead.\n"
+                     " */\n"
+                     "@java.lang.Deprecated\n"
+                     "java.util.Map<$type_parameters$>\n"
+                     "${$get$capitalized_name$$}$();\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "$deprecation$java.util.Map<$type_parameters$>\n"
@@ -303,6 +324,12 @@
       "              $value_wire_type$,\n"
       "              $value_default_value$);\n"
       "}\n");
+  if (!context_->options().opensource_runtime) {
+    printer->Print(variables_,
+                   "@com.google.protobuf.ProtoField(\n"
+                   "  fieldNumber=$number$,\n"
+                   "  type=com.google.protobuf.FieldType.MAP)\n");
+  }
   printer->Print(variables_,
                  "private com.google.protobuf.MapFieldLite<\n"
                  "    $type_parameters$> $name$_ =\n"
@@ -344,16 +371,19 @@
         "        com.google.protobuf.Internal.MapAdapter.newEnumConverter(\n"
         "            $value_enum_type$.internalGetValueMap(),\n"
         "            $unrecognized_value$);\n");
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Deprecated\n"
-                   "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-                   "${$get$capitalized_name$$}$() {\n"
-                   "  return get$capitalized_name$Map();\n"
-                   "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use {@link #get$capitalized_name$Map()} instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+          "${$get$capitalized_name$$}$() {\n"
+          "  return get$capitalized_name$Map();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(
         variables_,
@@ -373,9 +403,10 @@
         variables_,
         "@java.lang.Override\n"
         "$deprecation$\n"
-        "public $value_enum_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "public $value_enum_type_pass_through_nullness$ "
+        "${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
-        "    $value_enum_type$ defaultValue) {\n"
+        "    $value_enum_type_pass_through_nullness$ defaultValue) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
         "      internalGet$capitalized_name$();\n"
@@ -429,9 +460,10 @@
           variables_,
           "@java.lang.Override\n"
           "$deprecation$\n"
-          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+          "public $value_type_pass_through_nullness$ "
+          "${$get$capitalized_name$ValueOrDefault$}$(\n"
           "    $key_type$ key,\n"
-          "    $value_type$ defaultValue) {\n"
+          "    $value_type_pass_through_nullness$ defaultValue) {\n"
           "  $key_null_check$\n"
           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
           "      internalGet$capitalized_name$();\n"
@@ -456,17 +488,19 @@
       printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Override\n"
-                   "@java.lang.Deprecated\n"
-                   "public java.util.Map<$type_parameters$> "
-                   "${$get$capitalized_name$$}$() {\n"
-                   "  return get$capitalized_name$Map();\n"
-                   "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(variables_,
+                     "/**\n"
+                     " * Use {@link #get$capitalized_name$Map()} instead.\n"
+                     " */\n"
+                     "@java.lang.Override\n"
+                     "@java.lang.Deprecated\n"
+                     "public java.util.Map<$type_parameters$> "
+                     "${$get$capitalized_name$$}$() {\n"
+                     "  return get$capitalized_name$Map();\n"
+                     "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "@java.lang.Override\n"
@@ -482,9 +516,10 @@
         variables_,
         "@java.lang.Override\n"
         "$deprecation$\n"
-        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "public $value_type_pass_through_nullness$ "
+        "${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
-        "    $value_type$ defaultValue) {\n"
+        "    $value_type_pass_through_nullness$ defaultValue) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$type_parameters$> map =\n"
         "      internalGet$capitalized_name$();\n"
@@ -596,16 +631,19 @@
                  "}\n");
   printer->Annotate("{", "}", descriptor_);
   if (GetJavaType(ValueField(descriptor_)) == JAVATYPE_ENUM) {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Deprecated\n"
-                   "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
-                   "${$get$capitalized_name$$}$() {\n"
-                   "  return get$capitalized_name$Map();\n"
-                   "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(
+          variables_,
+          "/**\n"
+          " * Use {@link #get$capitalized_name$Map()} instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "public java.util.Map<$boxed_key_type$, $value_enum_type$>\n"
+          "${$get$capitalized_name$$}$() {\n"
+          "  return get$capitalized_name$Map();\n"
+          "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "@java.lang.Override\n"
@@ -701,9 +739,10 @@
           variables_,
           "@java.lang.Override\n"
           "$deprecation$\n"
-          "public $value_type$ ${$get$capitalized_name$ValueOrDefault$}$(\n"
+          "public $value_type_pass_through_nullness$ "
+          "${$get$capitalized_name$ValueOrDefault$}$(\n"
           "    $key_type$ key,\n"
-          "    $value_type$ defaultValue) {\n"
+          "    $value_type_pass_through_nullness$ defaultValue) {\n"
           "  $key_null_check$\n"
           "  java.util.Map<$boxed_key_type$, $boxed_value_type$> map =\n"
           "      instance.get$capitalized_name$ValueMap();\n"
@@ -750,17 +789,19 @@
       printer->Annotate("{", "}", descriptor_);
     }
   } else {
-    printer->Print(variables_,
-                   "/**\n"
-                   " * Use {@link #get$capitalized_name$Map()} instead.\n"
-                   " */\n"
-                   "@java.lang.Override\n"
-                   "@java.lang.Deprecated\n"
-                   "public java.util.Map<$type_parameters$> "
-                   "${$get$capitalized_name$$}$() {\n"
-                   "  return get$capitalized_name$Map();\n"
-                   "}\n");
-    printer->Annotate("{", "}", descriptor_);
+    if (context_->options().opensource_runtime) {
+      printer->Print(variables_,
+                     "/**\n"
+                     " * Use {@link #get$capitalized_name$Map()} instead.\n"
+                     " */\n"
+                     "@java.lang.Override\n"
+                     "@java.lang.Deprecated\n"
+                     "public java.util.Map<$type_parameters$> "
+                     "${$get$capitalized_name$$}$() {\n"
+                     "  return get$capitalized_name$Map();\n"
+                     "}\n");
+      printer->Annotate("{", "}", descriptor_);
+    }
     WriteFieldDocComment(printer, descriptor_);
     printer->Print(variables_,
                    "@java.lang.Override\n"
@@ -776,9 +817,10 @@
         variables_,
         "@java.lang.Override\n"
         "$deprecation$\n"
-        "public $value_type$ ${$get$capitalized_name$OrDefault$}$(\n"
+        "public $value_type_pass_through_nullness$ "
+        "${$get$capitalized_name$OrDefault$}$(\n"
         "    $key_type$ key,\n"
-        "    $value_type$ defaultValue) {\n"
+        "    $value_type_pass_through_nullness$ defaultValue) {\n"
         "  $key_null_check$\n"
         "  java.util.Map<$type_parameters$> map =\n"
         "      instance.get$capitalized_name$Map();\n"
@@ -841,7 +883,7 @@
       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "$kt_deprecation$ public val $kt_name$: "
@@ -853,7 +895,7 @@
       "    $kt_dsl_builder$.${$get$capitalized_name$Map$}$()\n"
       "  )\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@JvmName(\"put$kt_capitalized_name$\")\n"
@@ -863,7 +905,7 @@
       "     $kt_dsl_builder$.${$put$capitalized_name$$}$(key, value)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -875,7 +917,7 @@
       "     put(key, value)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -886,7 +928,7 @@
       "     $kt_dsl_builder$.${$remove$capitalized_name$$}$(key)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -898,7 +940,7 @@
       "     $kt_dsl_builder$.${$putAll$capitalized_name$$}$(map)\n"
       "   }\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -924,4 +966,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/map_field_lite.h b/src/google/protobuf/compiler/java/map_field_lite.h
index 964f098..ccb2bc4 100644
--- a/src/google/protobuf/compiler/java/map_field_lite.h
+++ b/src/google/protobuf/compiler/java/map_field_lite.h
@@ -33,7 +33,7 @@
 
 #include <cstdint>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -61,7 +61,7 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   Context* context_;
   ClassNameResolver* name_resolver_;
 };
diff --git a/src/google/protobuf/compiler/java/message.cc b/src/google/protobuf/compiler/java/message.cc
index a29d9a7..2d51b25 100644
--- a/src/google/protobuf/compiler/java/message.cc
+++ b/src/google/protobuf/compiler/java/message.cc
@@ -32,33 +32,34 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/message.h>
+#include "google/protobuf/compiler/java/message.h"
 
 #include <algorithm>
 #include <cstdint>
-#include <map>
 #include <memory>
 #include <vector>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/enum.h>
-#include <google/protobuf/compiler/java/extension.h>
-#include <google/protobuf/compiler/java/generator_factory.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/message_builder.h>
-#include <google/protobuf/compiler/java/message_builder_lite.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/enum.h"
+#include "google/protobuf/compiler/java/extension.h"
+#include "google/protobuf/compiler/java/generator_factory.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/message_builder.h"
+#include "google/protobuf/compiler/java/message_builder_lite.h"
+#include "google/protobuf/compiler/java/message_serialization.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -83,7 +84,8 @@
     : descriptor_(descriptor) {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (IsRealOneof(descriptor_->field(i))) {
-      oneofs_.insert(descriptor_->field(i)->containing_oneof());
+      const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof();
+      GOOGLE_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof);
     }
   }
 }
@@ -113,9 +115,9 @@
   // the outermost class in the file.  This way, they will be initialized in
   // a deterministic order.
 
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
-  vars["index"] = StrCat(descriptor_->index());
+  vars["index"] = absl::StrCat(descriptor_->index());
   vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
   if (descriptor_->containing_type() != NULL) {
     vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
@@ -157,9 +159,9 @@
 int ImmutableMessageGenerator::GenerateStaticVariableInitializers(
     io::Printer* printer) {
   int bytecode_estimate = 0;
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
-  vars["index"] = StrCat(descriptor_->index());
+  vars["index"] = absl::StrCat(descriptor_->index());
   vars["classname"] = name_resolver_->GetImmutableClassName(descriptor_);
   if (descriptor_->containing_type() != NULL) {
     vars["parent"] = UniqueFileScopeIdentifier(descriptor_->containing_type());
@@ -194,7 +196,7 @@
 
 void ImmutableMessageGenerator::GenerateFieldAccessorTable(
     io::Printer* printer, int* bytecode_estimate) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["identifier"] = UniqueFileScopeIdentifier(descriptor_);
   if (MultipleJavaFiles(descriptor_->file(), /* immutable = */ true)) {
     // We can only make these package-private since the classes that use them
@@ -261,6 +263,9 @@
 void ImmutableMessageGenerator::GenerateInterface(io::Printer* printer) {
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
                                 /* immutable = */ true, "OrBuilder");
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
+  }
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
         "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
@@ -290,13 +295,14 @@
     field_generators_.get(descriptor_->field(i))
         .GenerateInterfaceMembers(printer);
   }
-  for (auto oneof : oneofs_) {
+  for (auto& kv : oneofs_) {
     printer->Print(
         "\n"
-        "public $classname$.$oneof_capitalized_name$Case "
+        "$classname$.$oneof_capitalized_name$Case "
         "get$oneof_capitalized_name$Case();\n",
         "oneof_capitalized_name",
-        context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname",
+        context_->GetOneofGeneratorInfo(kv.second)->capitalized_name,
+        "classname",
         context_->GetNameResolver()->GetImmutableClassName(descriptor_));
   }
   printer->Outdent();
@@ -309,7 +315,7 @@
 void ImmutableMessageGenerator::Generate(io::Printer* printer) {
   bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
 
-  std::map<std::string, std::string> variables;
+  absl::flat_hash_map<absl::string_view, std::string> variables;
   variables["static"] = is_own_file ? "" : "static ";
   variables["classname"] = descriptor_->name();
   variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
@@ -320,6 +326,10 @@
   WriteMessageDocComment(printer, descriptor_);
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
                                 /* immutable = */ true);
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
+  }
+
   // The builder_type stores the super type name of the nested Builder class.
   std::string builder_type;
   if (descriptor_->extension_range_count() > 0) {
@@ -333,7 +343,7 @@
         "      $classname$> implements\n"
         "    $extra_interfaces$\n"
         "    $classname$OrBuilder {\n");
-    builder_type = strings::Substitute(
+    builder_type = absl::Substitute(
         "com.google.protobuf.GeneratedMessage$1.ExtendableBuilder<$0, ?>",
         name_resolver_->GetImmutableClassName(descriptor_),
         GeneratedCodeVersionSuffix());
@@ -347,7 +357,7 @@
                    "    $extra_interfaces$\n"
                    "    $classname$OrBuilder {\n");
     builder_type =
-        strings::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>",
+        absl::Substitute("com.google.protobuf.GeneratedMessage$0.Builder<?>",
                          GeneratedCodeVersionSuffix());
   }
   printer->Print("private static final long serialVersionUID = 0L;\n");
@@ -380,14 +390,6 @@
                  "}\n"
                  "\n");
 
-  // TODO(b/248149118): Remove this superfluous override.
-  printer->Print(
-      "@java.lang.Override\n"
-      "public final com.google.protobuf.UnknownFieldSet\n"
-      "getUnknownFields() {\n"
-      "  return this.unknownFields;\n"
-      "}\n");
-
   GenerateDescriptorMethods(printer);
 
   // Nested types
@@ -417,59 +419,69 @@
   }
 
   // oneof
-  std::map<std::string, std::string> vars;
-  for (auto oneof : oneofs_) {
+  absl::flat_hash_map<absl::string_view, std::string> vars;
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
     vars["oneof_capitalized_name"] =
         context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
-    vars["oneof_index"] = StrCat((oneof)->index());
+    vars["oneof_index"] = absl::StrCat((oneof)->index());
+    vars["{"] = "";
+    vars["}"] = "";
     // oneofCase_ and oneof_
     printer->Print(vars,
                    "private int $oneof_name$Case_ = 0;\n"
+                   "@SuppressWarnings(\"serial\")\n"
                    "private java.lang.Object $oneof_name$_;\n");
     // OneofCase enum
     printer->Print(
         vars,
-        "public enum $oneof_capitalized_name$Case\n"
+        "public enum ${$$oneof_capitalized_name$Case$}$\n"
         // TODO(dweis): Remove EnumLite when we want to break compatibility with
         // 3.x users
         "    implements com.google.protobuf.Internal.EnumLite,\n"
         "        com.google.protobuf.AbstractMessage.InternalOneOfEnum {\n");
+    printer->Annotate("{", "}", oneof);
     printer->Indent();
     for (int j = 0; j < (oneof)->field_count(); j++) {
       const FieldDescriptor* field = (oneof)->field(j);
       printer->Print(
           "$deprecation$$field_name$($field_number$),\n", "deprecation",
           field->options().deprecated() ? "@java.lang.Deprecated " : "",
-          "field_name", ToUpper(field->name()), "field_number",
-          StrCat(field->number()));
+          "field_name", absl::AsciiStrToUpper(field->name()), "field_number",
+          absl::StrCat(field->number()));
+      printer->Annotate("field_name", field);
     }
     printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
-                   ToUpper(vars["oneof_name"]));
+                   absl::AsciiStrToUpper(vars["oneof_name"]));
     printer->Print(vars,
                    "private final int value;\n"
                    "private $oneof_capitalized_name$Case(int value) {\n"
                    "  this.value = value;\n"
                    "}\n");
+    if (context_->options().opensource_runtime) {
+      printer->Print(
+          vars,
+          "/**\n"
+          " * @param value The number of the enum to look for.\n"
+          " * @return The enum associated with the given number.\n"
+          " * @deprecated Use {@link #forNumber(int)} instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+          "  return forNumber(value);\n"
+          "}\n"
+          "\n");
+    }
     printer->Print(
         vars,
-        "/**\n"
-        " * @param value The number of the enum to look for.\n"
-        " * @return The enum associated with the given number.\n"
-        " * @deprecated Use {@link #forNumber(int)} instead.\n"
-        " */\n"
-        "@java.lang.Deprecated\n"
-        "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
-        "  return forNumber(value);\n"
-        "}\n"
-        "\n"
         "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
         "  switch (value) {\n");
     for (int j = 0; j < (oneof)->field_count(); j++) {
       const FieldDescriptor* field = (oneof)->field(j);
       printer->Print("    case $field_number$: return $field_name$;\n",
-                     "field_number", StrCat(field->number()),
-                     "field_name", ToUpper(field->name()));
+                     "field_number", absl::StrCat(field->number()),
+                     "field_name", absl::AsciiStrToUpper(field->name()));
     }
     printer->Print(
         "    case 0: return $cap_oneof_name$_NOT_SET;\n"
@@ -479,17 +491,18 @@
         "public int getNumber() {\n"
         "  return this.value;\n"
         "}\n",
-        "cap_oneof_name", ToUpper(vars["oneof_name"]));
+        "cap_oneof_name", absl::AsciiStrToUpper(vars["oneof_name"]));
     printer->Outdent();
     printer->Print("};\n\n");
     // oneofCase()
     printer->Print(vars,
                    "public $oneof_capitalized_name$Case\n"
-                   "get$oneof_capitalized_name$Case() {\n"
+                   "${$get$oneof_capitalized_name$Case$}$() {\n"
                    "  return $oneof_capitalized_name$Case.forNumber(\n"
                    "      $oneof_name$Case_);\n"
                    "}\n"
                    "\n");
+    printer->Annotate("{", "}", oneof);
   }
 
   if (IsAnyMessage(descriptor_)) {
@@ -500,7 +513,7 @@
   for (int i = 0; i < descriptor_->field_count(); i++) {
     printer->Print("public static final int $constant_name$ = $number$;\n",
                    "constant_name", FieldConstantName(descriptor_->field(i)),
-                   "number", StrCat(descriptor_->field(i)->number()));
+                   "number", absl::StrCat(descriptor_->field(i)->number()));
     printer->Annotate("constant_name", descriptor_->field(i));
     field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
     printer->Print("\n");
@@ -580,13 +593,6 @@
   std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
       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));
-  }
-  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
-            ExtensionRangeOrdering());
   printer->Print(
       "@java.lang.Override\n"
       "public void writeTo(com.google.protobuf.CodedOutputStream output)\n"
@@ -621,19 +627,8 @@
     }
   }
 
-  // Merge the fields and the extension ranges, both sorted by field number.
-  for (int i = 0, j = 0;
-       i < descriptor_->field_count() || j < sorted_extensions.size();) {
-    if (i == descriptor_->field_count()) {
-      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
-    } else if (j == sorted_extensions.size()) {
-      GenerateSerializeOneField(printer, sorted_fields[i++]);
-    } else if (sorted_fields[i]->number() < sorted_extensions[j]->start) {
-      GenerateSerializeOneField(printer, sorted_fields[i++]);
-    } else {
-      GenerateSerializeOneExtensionRange(printer, sorted_extensions[j++]);
-    }
-  }
+  GenerateSerializeFieldsAndExtensions(printer, field_generators_, descriptor_,
+                                       sorted_fields.get());
 
   if (descriptor_->options().message_set_wire_format()) {
     printer->Print("getUnknownFields().writeAsMessageSetTo(output);\n");
@@ -764,17 +759,6 @@
       GeneratedCodeVersionSuffix());
 }
 
-void ImmutableMessageGenerator::GenerateSerializeOneField(
-    io::Printer* printer, const FieldDescriptor* field) {
-  field_generators_.get(field).GenerateSerializationCode(printer);
-}
-
-void ImmutableMessageGenerator::GenerateSerializeOneExtensionRange(
-    io::Printer* printer, const Descriptor::ExtensionRange* range) {
-  printer->Print("extensionWriter.writeUntil($end$, output);\n", "end",
-                 StrCat(range->end));
-}
-
 // ===================================================================
 
 void ImmutableMessageGenerator::GenerateBuilder(io::Printer* printer) {
@@ -846,7 +830,7 @@
       printer->Print(
           "case $number$:\n"
           "  return internalGet$capitalized_name$();\n",
-          "number", StrCat(field->number()), "capitalized_name",
+          "number", absl::StrCat(field->number()), "capitalized_name",
           info->capitalized_name);
     }
     printer->Print(
@@ -1004,6 +988,10 @@
   printer->Print(
       "@java.lang.Override\n"
       "public boolean equals(");
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        "@com.google.protobuf.Internal.ProtoMethodAcceptsNullParameter\n");
+  }
   printer->Print("final java.lang.Object obj) {\n");
   printer->Indent();
   printer->Print(
@@ -1011,6 +999,8 @@
       " return true;\n"
       "}\n"
       "if (!(obj instanceof $classname$)) {\n"
+      // don't simply return false because mutable and immutable types
+      // can be equal
       "  return super.equals(obj);\n"
       "}\n"
       "$classname$ other = ($classname$) obj;\n"
@@ -1038,7 +1028,8 @@
   }
 
   // Compare oneofs.
-  for (auto oneof : oneofs_) {
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     printer->Print(
         "if (!get$oneof_capitalized_name$Case().equals("
         "other.get$oneof_capitalized_name$Case())) return false;\n",
@@ -1050,7 +1041,7 @@
     for (int j = 0; j < (oneof)->field_count(); j++) {
       const FieldDescriptor* field = (oneof)->field(j);
       printer->Print("case $field_number$:\n", "field_number",
-                     StrCat(field->number()));
+                     absl::StrCat(field->number()));
       printer->Indent();
       field_generators_.get(field).GenerateEqualsCode(printer);
       printer->Print("break;\n");
@@ -1118,14 +1109,15 @@
   }
 
   // hashCode oneofs.
-  for (auto oneof : oneofs_) {
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     printer->Print("switch ($oneof_name$Case_) {\n", "oneof_name",
                    context_->GetOneofGeneratorInfo(oneof)->name);
     printer->Indent();
     for (int j = 0; j < (oneof)->field_count(); j++) {
       const FieldDescriptor* field = (oneof)->field(j);
       printer->Print("case $field_number$:\n", "field_number",
-                     StrCat(field->number()));
+                     absl::StrCat(field->number()));
       printer->Indent();
       field_generators_.get(field).GenerateHashCode(printer);
       printer->Print("break;\n");
@@ -1273,7 +1265,8 @@
       "  @kotlin.jvm.JvmSynthetic\n"
       "  @kotlin.PublishedApi\n"
       "  internal fun _build(): $message$ = _builder.build()\n",
-      "message", name_resolver_->GetClassName(descriptor_, true));
+      "message",
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)));
 
   printer->Indent();
 
@@ -1283,7 +1276,8 @@
         .GenerateKotlinDslMembers(printer);
   }
 
-  for (auto oneof : oneofs_) {
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     printer->Print(
         "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
         "  @JvmName(\"get$oneof_capitalized_name$Case\")\n"
@@ -1294,7 +1288,7 @@
         "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
         "oneof_capitalized_name",
         context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
-        name_resolver_->GetClassName(descriptor_, true));
+        EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)));
   }
 
   if (descriptor_->extension_range_count() > 0) {
@@ -1307,8 +1301,15 @@
 
 void ImmutableMessageGenerator::GenerateKotlinMembers(
     io::Printer* printer) const {
+  printer->Print("@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n",
+                 "camelcase_name",
+                 name_resolver_->GetKotlinFactoryName(descriptor_));
+
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.errorprone.annotations.CheckReturnValue\n");
+  }
+
   printer->Print(
-      "@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n"
       "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> "
       "kotlin.Unit): "
       "$message$ "
@@ -1316,9 +1317,13 @@
       "  $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));
+      "message_kt",
+      EscapeKotlinKeywords(
+          name_resolver_->GetKotlinExtensionsClassName(descriptor_)),
+      "message",
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)));
 
+  WriteMessageDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print("public object $name$Kt {\n", "name", descriptor_->name());
   printer->Indent();
   GenerateKotlinDsl(printer);
@@ -1333,15 +1338,22 @@
 
 void ImmutableMessageGenerator::GenerateTopLevelKotlinMembers(
     io::Printer* printer) const {
+  printer->Print("@kotlin.jvm.JvmSynthetic\n");
+
+  if (context_->options().opensource_runtime) {
+    printer->Print("@com.google.errorprone.annotations.CheckReturnValue\n");
+  }
+
   printer->Print(
-      "@kotlin.jvm.JvmSynthetic\n"
       "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> "
-      "kotlin.Unit): "
-      "$message$ =\n"
+      "kotlin.Unit): $message$ =\n"
       "  $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
       "}._build()\n\n",
-      "message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
-      name_resolver_->GetKotlinExtensionsClassName(descriptor_));
+      "message",
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)),
+      "message_kt",
+      EscapeKotlinKeywords(
+          name_resolver_->GetKotlinExtensionsClassName(descriptor_)));
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     if (IsMapEntry(descriptor_->nested_type(i))) continue;
@@ -1352,25 +1364,30 @@
   GenerateKotlinOrNull(printer);
 }
 
-void ImmutableMessageGenerator::GenerateKotlinOrNull(io::Printer* printer) const {
+void ImmutableMessageGenerator::GenerateKotlinOrNull(
+    io::Printer* printer) const {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     const FieldDescriptor* field = descriptor_->field(i);
     if (field->has_presence() && GetJavaType(field) == JAVATYPE_MESSAGE) {
       printer->Print(
-          "public val $full_classname$OrBuilder.$camelcase_name$OrNull: $full_name$?\n"
+          "public val $full_classname$OrBuilder.$camelcase_name$OrNull: "
+          "$full_name$?\n"
           "  get() = if (has$name$()) get$name$() else null\n\n",
-          "full_classname", name_resolver_->GetClassName(descriptor_, true),
+          "full_classname",
+          EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)),
           "camelcase_name", context_->GetFieldGeneratorInfo(field)->name,
           "full_name",
-          name_resolver_->GetImmutableClassName(field->message_type()), "name",
-          context_->GetFieldGeneratorInfo(field)->capitalized_name);
+          EscapeKotlinKeywords(
+              name_resolver_->GetImmutableClassName(field->message_type())),
+          "name", context_->GetFieldGeneratorInfo(field)->capitalized_name);
     }
   }
 }
 
 void ImmutableMessageGenerator::GenerateKotlinExtensions(
     io::Printer* printer) const {
-  std::string message_name = name_resolver_->GetClassName(descriptor_, true);
+  std::string message_name =
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true));
 
   printer->Print(
       "@Suppress(\"UNCHECKED_CAST\")\n"
@@ -1379,7 +1396,7 @@
       "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"
+      "kotlin.collections.List<*>>) as T\n"
       "  } else {\n"
       "    _builder.getExtension(extension)\n"
       "  }\n"
@@ -1392,7 +1409,8 @@
       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
       "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
       "public operator fun <E : kotlin.Any> get(\n"
-      "  extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, "
+      "kotlin.collections.List<E>>\n"
       "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
       "  return com.google.protobuf.kotlin.ExtensionList(extension, "
       "_builder.getExtension(extension))\n"
@@ -1419,8 +1437,7 @@
 
   printer->Print(
       "@kotlin.jvm.JvmSynthetic\n"
-      "@kotlin.PublishedApi\n"
-      "internal fun <T : kotlin.Any> setExtension(extension: "
+      "public fun <T : kotlin.Any> setExtension(extension: "
       "com.google.protobuf.ExtensionLite<$message$, T>, "
       "value: T) {\n"
       "  _builder.setExtension(extension, value)\n"
@@ -1453,7 +1470,7 @@
   printer->Print(
       "@kotlin.jvm.JvmSynthetic\n"
       "@Suppress(\"NOTHING_TO_INLINE\")\n"
-      "inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
+      "public inline operator fun <T : com.google.protobuf.MessageLite> set(\n"
       "  extension: com.google.protobuf.ExtensionLite<$message$, T>,\n"
       "  value: T\n"
       ") {\n"
@@ -1569,12 +1586,19 @@
       "      defaultInstance.getDescriptorForType().getFullName());\n"
       "}\n"
       "\n"
+      "public boolean isSameTypeAs(com.google.protobuf.Message message) {\n"
+      "  return getTypeNameFromTypeUrl(getTypeUrl()).equals(\n"
+      "      message.getDescriptorForType().getFullName());\n"
+      "}\n"
+      "\n"
+      "@SuppressWarnings(\"serial\")\n"
       "private volatile com.google.protobuf.Message cachedUnpackValue;\n"
       "\n"
       "@java.lang.SuppressWarnings(\"unchecked\")\n"
       "public <T extends com.google.protobuf.Message> T unpack(\n"
       "    java.lang.Class<T> clazz)\n"
-      "    throws com.google.protobuf.InvalidProtocolBufferException {\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n");
+  printer->Print(
       "  boolean invalidClazz = false;\n"
       "  if (cachedUnpackValue != null) {\n"
       "    if (cachedUnpackValue.getClass() == clazz) {\n"
@@ -1592,7 +1616,30 @@
       "      .parseFrom(getValue());\n"
       "  cachedUnpackValue = result;\n"
       "  return result;\n"
-      "}\n");
+      "}\n"
+      "\n"
+      "@java.lang.SuppressWarnings(\"unchecked\")\n"
+      "public <T extends com.google.protobuf.Message> T unpackSameTypeAs("
+      "T message)\n"
+      "    throws com.google.protobuf.InvalidProtocolBufferException {\n");
+  printer->Print(
+      "  boolean invalidValue = false;\n"
+      "  if (cachedUnpackValue != null) {\n"
+      "    if (cachedUnpackValue.getClass() == message.getClass()) {\n"
+      "      return (T) cachedUnpackValue;\n"
+      "    }\n"
+      "    invalidValue = true;\n"
+      "  }\n"
+      "  if (invalidValue || !isSameTypeAs(message)) {\n"
+      "    throw new com.google.protobuf.InvalidProtocolBufferException(\n"
+      "        \"Type of the Any message does not match the given "
+      "exemplar.\");\n"
+      "  }\n"
+      "  T result = (T) message.getParserForType().parseFrom(getValue());\n"
+      "  cachedUnpackValue = result;\n"
+      "  return result;\n"
+      "}\n"
+      "\n");
 }
 
 }  // namespace java
@@ -1600,4 +1647,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/message.h b/src/google/protobuf/compiler/java/message.h
index 2dbd0dd..a122c83 100644
--- a/src/google/protobuf/compiler/java/message.h
+++ b/src/google/protobuf/compiler/java/message.h
@@ -35,10 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "absl/container/btree_map.h"
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -64,6 +64,8 @@
 class MessageGenerator {
  public:
   explicit MessageGenerator(const Descriptor* descriptor);
+  MessageGenerator(const MessageGenerator&) = delete;
+  MessageGenerator& operator=(const MessageGenerator&) = delete;
   virtual ~MessageGenerator();
 
   // All static variables have to be declared at the top-level of the file
@@ -92,15 +94,15 @@
 
  protected:
   const Descriptor* descriptor_;
-  std::set<const OneofDescriptor*> oneofs_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageGenerator);
+  absl::btree_map<int, const OneofDescriptor*> oneofs_;
 };
 
 class ImmutableMessageGenerator : public MessageGenerator {
  public:
   ImmutableMessageGenerator(const Descriptor* descriptor, Context* context);
+  ImmutableMessageGenerator(const ImmutableMessageGenerator&) = delete;
+  ImmutableMessageGenerator& operator=(const ImmutableMessageGenerator&) =
+      delete;
   ~ImmutableMessageGenerator() override;
 
   void Generate(io::Printer* printer) override;
@@ -123,10 +125,6 @@
 
   void GenerateMessageSerializationMethods(io::Printer* printer);
   void GenerateParseFromMethods(io::Printer* printer);
-  void GenerateSerializeOneField(io::Printer* printer,
-                                 const FieldDescriptor* field);
-  void GenerateSerializeOneExtensionRange(
-      io::Printer* printer, const Descriptor::ExtensionRange* range);
 
   void GenerateBuilder(io::Printer* printer);
   void GenerateIsInitialized(io::Printer* printer);
@@ -143,8 +141,6 @@
   Context* context_;
   ClassNameResolver* name_resolver_;
   FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/message_builder.cc b/src/google/protobuf/compiler/java/message_builder.cc
index 32ad668..945cf9d 100644
--- a/src/google/protobuf/compiler/java/message_builder.cc
+++ b/src/google/protobuf/compiler/java/message_builder.cc
@@ -35,16 +35,14 @@
 #include "google/protobuf/compiler/java/message_builder.h"
 
 #include <algorithm>
-#include <map>
 #include <memory>
 #include <set>
 #include <vector>
 
-#include "google/protobuf/io/coded_stream.h"
-#include "google/protobuf/io/printer.h"
-#include "google/protobuf/wire_format.h"
-#include "google/protobuf/stubs/strutil.h"
-#include "google/protobuf/stubs/substitute.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/substitute.h"
 #include "google/protobuf/compiler/java/context.h"
 #include "google/protobuf/compiler/java/doc_comment.h"
 #include "google/protobuf/compiler/java/enum.h"
@@ -53,6 +51,9 @@
 #include "google/protobuf/compiler/java/helpers.h"
 #include "google/protobuf/compiler/java/name_resolver.h"
 #include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
 #include "google/protobuf/port_def.inc"
@@ -85,7 +86,8 @@
          "generate lite messages.";
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (IsRealOneof(descriptor_->field(i))) {
-      oneofs_.insert(descriptor_->field(i)->containing_oneof());
+      const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof();
+      GOOGLE_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof);
     }
   }
 }
@@ -126,12 +128,13 @@
   }
 
   // oneof
-  std::map<std::string, std::string> vars;
-  for (auto oneof : oneofs_) {
+  absl::flat_hash_map<absl::string_view, std::string> vars;
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
     vars["oneof_capitalized_name"] =
         context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
-    vars["oneof_index"] = StrCat(oneof->index());
+    vars["oneof_index"] = absl::StrCat(oneof->index());
     // oneofCase_ and oneof_
     printer->Print(vars,
                    "private int $oneof_name$Case_ = 0;\n"
@@ -171,24 +174,26 @@
         .GenerateBuilderMembers(printer);
   }
 
-  // Override methods declared in GeneratedMessage to return the concrete
-  // generated type so callsites won't depend on GeneratedMessage. This
-  // is needed to keep binary compatibility when we change generated code
-  // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
-  // we changed all generated code to subclass GeneratedMessageV3).
-  printer->Print(
-      "@java.lang.Override\n"
-      "public final Builder setUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return super.setUnknownFields(unknownFields);\n"
-      "}\n"
-      "\n"
-      "@java.lang.Override\n"
-      "public final Builder mergeUnknownFields(\n"
-      "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
-      "  return super.mergeUnknownFields(unknownFields);\n"
-      "}\n"
-      "\n");
+  if (context_->options().opensource_runtime) {
+    // Override methods declared in GeneratedMessage to return the concrete
+    // generated type so callsites won't depend on GeneratedMessage. This
+    // is needed to keep binary compatibility when we change generated code
+    // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
+    // we changed all generated code to subclass GeneratedMessageV3).
+    printer->Print(
+        "@java.lang.Override\n"
+        "public final Builder setUnknownFields(\n"
+        "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+        "  return super.setUnknownFields(unknownFields);\n"
+        "}\n"
+        "\n"
+        "@java.lang.Override\n"
+        "public final Builder mergeUnknownFields(\n"
+        "    final com.google.protobuf.UnknownFieldSet unknownFields) {\n"
+        "  return super.mergeUnknownFields(unknownFields);\n"
+        "}\n"
+        "\n");
+  }
 
   printer->Print(
       "\n"
@@ -234,7 +239,7 @@
       printer->Print(
           "case $number$:\n"
           "  return internalGet$capitalized_name$();\n",
-          "number", StrCat(field->number()), "capitalized_name",
+          "number", absl::StrCat(field->number()), "capitalized_name",
           info->capitalized_name);
     }
     printer->Print(
@@ -259,7 +264,7 @@
       printer->Print(
           "case $number$:\n"
           "  return internalGetMutable$capitalized_name$();\n",
-          "number", StrCat(field->number()), "capitalized_name",
+          "number", absl::StrCat(field->number()), "capitalized_name",
           info->capitalized_name);
     }
     printer->Print(
@@ -366,11 +371,11 @@
         .GenerateBuilderClearCode(printer);
   }
 
-  for (auto oneof : oneofs_) {
+  for (auto& kv : oneofs_) {
     printer->Print(
         "$oneof_name$Case_ = 0;\n"
         "$oneof_name$_ = null;\n",
-        "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
+        "oneof_name", context_->GetOneofGeneratorInfo(kv.second)->name);
   }
 
   printer->Outdent();
@@ -413,77 +418,6 @@
 
   GenerateBuildPartial(printer);
 
-  // Override methods declared in GeneratedMessage to return the concrete
-  // generated type so callsites won't depend on GeneratedMessage. This
-  // is needed to keep binary compatibility when we change generated code
-  // to subclass a different GeneratedMessage class (e.g., in v3.0.0 release
-  // we changed all generated code to subclass GeneratedMessageV3).
-  printer->Print(
-      "@java.lang.Override\n"
-      "public Builder clone() {\n"
-      "  return super.clone();\n"
-      "}\n"
-      "@java.lang.Override\n"
-      "public Builder setField(\n"
-      "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
-      "    java.lang.Object value) {\n"
-      "  return super.setField(field, value);\n"
-      "}\n"
-      "@java.lang.Override\n"
-      "public Builder clearField(\n"
-      "    com.google.protobuf.Descriptors.FieldDescriptor field) {\n"
-      "  return super.clearField(field);\n"
-      "}\n"
-      "@java.lang.Override\n"
-      "public Builder clearOneof(\n"
-      "    com.google.protobuf.Descriptors.OneofDescriptor oneof) {\n"
-      "  return super.clearOneof(oneof);\n"
-      "}\n"
-      "@java.lang.Override\n"
-      "public Builder setRepeatedField(\n"
-      "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
-      "    int index, java.lang.Object value) {\n"
-      "  return super.setRepeatedField(field, index, value);\n"
-      "}\n"
-      "@java.lang.Override\n"
-      "public Builder addRepeatedField(\n"
-      "    com.google.protobuf.Descriptors.FieldDescriptor field,\n"
-      "    java.lang.Object value) {\n"
-      "  return super.addRepeatedField(field, value);\n"
-      "}\n");
-
-  if (descriptor_->extension_range_count() > 0) {
-    printer->Print(
-        "@java.lang.Override\n"
-        "public <Type> Builder setExtension(\n"
-        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
-        "        $classname$, Type> extension,\n"
-        "    Type value) {\n"
-        "  return super.setExtension(extension, value);\n"
-        "}\n"
-        "@java.lang.Override\n"
-        "public <Type> Builder setExtension(\n"
-        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
-        "        $classname$, java.util.List<Type>> extension,\n"
-        "    int index, Type value) {\n"
-        "  return super.setExtension(extension, index, value);\n"
-        "}\n"
-        "@java.lang.Override\n"
-        "public <Type> Builder addExtension(\n"
-        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
-        "        $classname$, java.util.List<Type>> extension,\n"
-        "    Type value) {\n"
-        "  return super.addExtension(extension, value);\n"
-        "}\n"
-        "@java.lang.Override\n"
-        "public <Type> Builder clearExtension(\n"
-        "    com.google.protobuf.GeneratedMessage.GeneratedExtension<\n"
-        "        $classname$, ?> extension) {\n"
-        "  return super.clearExtension(extension);\n"
-        "}\n",
-        "classname", name_resolver_->GetImmutableClassName(descriptor_));
-  }
-
   // -----------------------------------------------------------------
 
   if (context_->HasGeneratedMethods(descriptor_)) {
@@ -516,7 +450,8 @@
     }
 
     // Merge oneof fields.
-    for (auto oneof : oneofs_) {
+    for (auto& kv : oneofs_) {
+      const OneofDescriptor* oneof = kv.second;
       printer->Print("switch (other.get$oneof_capitalized_name$Case()) {\n",
                      "oneof_capitalized_name",
                      context_->GetOneofGeneratorInfo(oneof)->capitalized_name);
@@ -524,7 +459,7 @@
       for (int j = 0; j < oneof->field_count(); j++) {
         const FieldDescriptor* field = oneof->field(j);
         printer->Print("case $field_name$: {\n", "field_name",
-                       ToUpper(field->name()));
+                       absl::AsciiStrToUpper(field->name()));
         printer->Indent();
         field_generators_.get(field).GenerateMergingCode(printer);
         printer->Print("break;\n");
@@ -536,7 +471,7 @@
           "  break;\n"
           "}\n",
           "cap_oneof_name",
-          ToUpper(context_->GetOneofGeneratorInfo(oneof)->name));
+          absl::AsciiStrToUpper(context_->GetOneofGeneratorInfo(oneof)->name));
       printer->Outdent();
       printer->Print("}\n");
     }
@@ -585,7 +520,7 @@
     for (int i = 0; i < totalBuilderInts; ++i) {
       printer->Print(
           "if ($bit_field_name$ != 0) { buildPartial$piece$(result); }\n",
-          "bit_field_name", GetBitFieldName(i), "piece", StrCat(i));
+          "bit_field_name", GetBitFieldName(i), "piece", absl::StrCat(i));
     }
   }
 
@@ -631,7 +566,8 @@
                    "classname",
                    name_resolver_->GetImmutableClassName(descriptor_));
     printer->Indent();
-    for (auto oneof : oneofs_) {
+    for (auto& kv : oneofs_) {
+      const OneofDescriptor* oneof = kv.second;
       printer->Print(
           "result.$oneof_name$Case_ = $oneof_name$Case_;\n"
           "result.$oneof_name$_ = this.$oneof_name$_;\n",
@@ -656,7 +592,7 @@
       "private void buildPartial$piece$($classname$ result) {\n"
       "  int from_$bit_field_name$ = $bit_field_name$;\n",
       "classname", name_resolver_->GetImmutableClassName(descriptor_), "piece",
-      StrCat(piece), "bit_field_name", GetBitFieldName(piece));
+      absl::StrCat(piece), "bit_field_name", GetBitFieldName(piece));
   printer->Indent();
   std::set<int> declared_to_bitfields;
 
@@ -775,7 +711,7 @@
     io::Printer* printer, const FieldDescriptor* field) {
   uint32_t tag = WireFormatLite::MakeTag(
       field->number(), WireFormat::WireTypeForFieldType(field->type()));
-  std::string tagString = StrCat(static_cast<int32_t>(tag));
+  std::string tagString = absl::StrCat(static_cast<int32_t>(tag));
   printer->Print("case $tag$: {\n", "tag", tagString);
   printer->Indent();
 
@@ -794,7 +730,7 @@
   // packed version of this field regardless of field->options().packed().
   uint32_t tag = WireFormatLite::MakeTag(
       field->number(), WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
-  std::string tagString = StrCat(static_cast<int32_t>(tag));
+  std::string tagString = absl::StrCat(static_cast<int32_t>(tag));
   printer->Print("case $tag$: {\n", "tag", tagString);
   printer->Indent();
 
diff --git a/src/google/protobuf/compiler/java/message_builder.h b/src/google/protobuf/compiler/java/message_builder.h
index 4b1cc7e..efafd36 100644
--- a/src/google/protobuf/compiler/java/message_builder.h
+++ b/src/google/protobuf/compiler/java/message_builder.h
@@ -35,10 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "absl/container/btree_map.h"
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +63,8 @@
  public:
   explicit MessageBuilderGenerator(const Descriptor* descriptor,
                                    Context* context);
+  MessageBuilderGenerator(const MessageBuilderGenerator&) = delete;
+  MessageBuilderGenerator& operator=(const MessageBuilderGenerator&) = delete;
   virtual ~MessageBuilderGenerator();
 
   virtual void Generate(io::Printer* printer);
@@ -87,9 +89,7 @@
   Context* context_;
   ClassNameResolver* name_resolver_;
   FieldGeneratorMap<ImmutableFieldGenerator> field_generators_;
-  std::set<const OneofDescriptor*> oneofs_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderGenerator);
+  absl::btree_map<int, const OneofDescriptor*> oneofs_;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/message_builder_lite.cc b/src/google/protobuf/compiler/java/message_builder_lite.cc
index 526f949..ab4378e 100644
--- a/src/google/protobuf/compiler/java/message_builder_lite.cc
+++ b/src/google/protobuf/compiler/java/message_builder_lite.cc
@@ -32,29 +32,30 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/message_builder_lite.h>
+#include "google/protobuf/compiler/java/message_builder_lite.h"
 
 #include <algorithm>
-#include <map>
 #include <memory>
+#include <string>
 #include <vector>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/enum.h>
-#include <google/protobuf/compiler/java/extension.h>
-#include <google/protobuf/compiler/java/generator_factory.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/enum.h"
+#include "google/protobuf/compiler/java/extension.h"
+#include "google/protobuf/compiler/java/generator_factory.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -72,7 +73,8 @@
          "generate non-lite messages.";
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (IsRealOneof(descriptor_->field(i))) {
-      oneofs_.insert(descriptor_->field(i)->containing_oneof());
+      const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof();
+      GOOGLE_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof);
     }
   }
 }
@@ -81,41 +83,51 @@
 
 void MessageBuilderLiteGenerator::Generate(io::Printer* printer) {
   WriteMessageDocComment(printer, descriptor_);
+  absl::flat_hash_map<absl::string_view, std::string> vars = {
+      {"{", ""},
+      {"}", ""},
+      {"classname", name_resolver_->GetImmutableClassName(descriptor_)},
+      {"extra_interfaces", ExtraBuilderInterfaces(descriptor_)},
+      {"extendible",
+       descriptor_->extension_range_count() > 0 ? "Extendable" : ""},
+  };
   printer->Print(
-      "public static final class Builder extends\n"
+      vars,
+      "public static final class ${$Builder$}$ extends\n"
       "    com.google.protobuf.GeneratedMessageLite.$extendible$Builder<\n"
       "      $classname$, Builder> implements\n"
       "    $extra_interfaces$\n"
-      "    $classname$OrBuilder {\n",
-      "classname", name_resolver_->GetImmutableClassName(descriptor_),
-      "extra_interfaces", ExtraBuilderInterfaces(descriptor_), "extendible",
-      descriptor_->extension_range_count() > 0 ? "Extendable" : "");
+      "    $classname$OrBuilder {\n");
+  printer->Annotate("{", "}", descriptor_);
   printer->Indent();
 
   GenerateCommonBuilderMethods(printer);
 
   // oneof
-  std::map<std::string, std::string> vars;
-  for (auto oneof : oneofs_) {
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
     vars["oneof_capitalized_name"] =
         context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
-    vars["oneof_index"] = StrCat(oneof->index());
+    vars["oneof_index"] = absl::StrCat(oneof->index());
 
     // oneofCase() and clearOneof()
     printer->Print(vars,
                    "@java.lang.Override\n"
                    "public $oneof_capitalized_name$Case\n"
-                   "    get$oneof_capitalized_name$Case() {\n"
+                   "    ${$get$oneof_capitalized_name$Case$}$() {\n"
                    "  return instance.get$oneof_capitalized_name$Case();\n"
-                   "}\n"
+                   "}\n");
+    printer->Annotate("{", "}", oneof);
+    printer->Print(vars,
                    "\n"
-                   "public Builder clear$oneof_capitalized_name$() {\n"
+                   "public Builder ${$clear$oneof_capitalized_name$$}$() {\n"
                    "  copyOnWrite();\n"
                    "  instance.clear$oneof_capitalized_name$();\n"
                    "  return this;\n"
                    "}\n"
                    "\n");
+    printer->Annotate("{", "}", oneof);
   }
 
   for (int i = 0; i < descriptor_->field_count(); i++) {
@@ -153,4 +165,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/message_builder_lite.h b/src/google/protobuf/compiler/java/message_builder_lite.h
index 0d895fc..a0d0e15 100644
--- a/src/google/protobuf/compiler/java/message_builder_lite.h
+++ b/src/google/protobuf/compiler/java/message_builder_lite.h
@@ -35,10 +35,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_BUILDER_LITE_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "absl/container/btree_map.h"
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +63,9 @@
  public:
   explicit MessageBuilderLiteGenerator(const Descriptor* descriptor,
                                        Context* context);
+  MessageBuilderLiteGenerator(const MessageBuilderLiteGenerator&) = delete;
+  MessageBuilderLiteGenerator& operator=(const MessageBuilderLiteGenerator&) =
+      delete;
   virtual ~MessageBuilderLiteGenerator();
 
   virtual void Generate(io::Printer* printer);
@@ -74,9 +77,7 @@
   Context* context_;
   ClassNameResolver* name_resolver_;
   FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
-  std::set<const OneofDescriptor*> oneofs_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageBuilderLiteGenerator);
+  absl::btree_map<int, const OneofDescriptor*> oneofs_;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/message_field.cc b/src/google/protobuf/compiler/java/message_field.cc
index 5093be4..7ce013f 100644
--- a/src/google/protobuf/compiler/java/message_field.cc
+++ b/src/google/protobuf/compiler/java/message_field.cc
@@ -34,16 +34,15 @@
 
 #include "google/protobuf/compiler/java/message_field.h"
 
-#include <map>
 #include <string>
 
-#include "google/protobuf/io/printer.h"
-#include "google/protobuf/wire_format.h"
-#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_cat.h"
 #include "google/protobuf/compiler/java/context.h"
 #include "google/protobuf/compiler/java/doc_comment.h"
 #include "google/protobuf/compiler/java/helpers.h"
 #include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
 #include "google/protobuf/port_def.inc"
@@ -59,13 +58,13 @@
 void SetMessageVariables(
     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
     const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
-    std::map<std::string, std::string>* variables,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
     Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])});
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
@@ -78,14 +77,16 @@
   variables->insert(
       {"kt_deprecation",
        descriptor->options().deprecated()
-           ? StrCat("@kotlin.Deprecated(message = \"Field ",
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
                           (*variables)["name"], " is deprecated\") ")
            : ""});
   (*variables)["on_changed"] = "onChanged();";
   (*variables)["ver"] = GeneratedCodeVersionSuffix();
   (*variables)["get_parser"] =
-      ExposePublicParser(descriptor->message_type()->file()) ? "PARSER"
-                                                             : "parser()";
+      ExposePublicParser(descriptor->message_type()->file()) &&
+              context->options().opensource_runtime
+          ? "PARSER"
+          : "parser()";
 
   if (HasHasbit(descriptor)) {
     // For singular messages and builders, one bit is used for the hasField bit.
@@ -99,7 +100,7 @@
   } else {
     (*variables)["set_has_field_bit_to_local"] = "";
     variables->insert({"is_field_present_message",
-                       StrCat((*variables)["name"], "_ != null")});
+                       absl::StrCat((*variables)["name"], "_ != null")});
   }
 
   // For repeated builders, one bit is used for whether the array is immutable.
@@ -383,7 +384,7 @@
 
 void ImmutableMessageFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -394,13 +395,14 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
-  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -1363,7 +1365,7 @@
       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$ public val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -1374,7 +1376,7 @@
                  "  )\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -1385,7 +1387,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -1397,7 +1399,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
@@ -1408,7 +1410,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1421,7 +1423,7 @@
       "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1433,7 +1435,7 @@
       "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
diff --git a/src/google/protobuf/compiler/java/message_field.h b/src/google/protobuf/compiler/java/message_field.h
index f16062f..acefb36 100644
--- a/src/google/protobuf/compiler/java/message_field.h
+++ b/src/google/protobuf/compiler/java/message_field.h
@@ -35,7 +35,6 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_H__
 
-#include <map>
 #include <string>
 
 #include "google/protobuf/compiler/java/field.h"
@@ -96,7 +95,7 @@
   const FieldDescriptor* descriptor_;
   int message_bit_index_;
   int builder_bit_index_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   ClassNameResolver* name_resolver_;
   Context* context_;
 
diff --git a/src/google/protobuf/compiler/java/message_field_lite.cc b/src/google/protobuf/compiler/java/message_field_lite.cc
index da96790..c0c2a1d 100644
--- a/src/google/protobuf/compiler/java/message_field_lite.cc
+++ b/src/google/protobuf/compiler/java/message_field_lite.cc
@@ -32,22 +32,21 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/message_field_lite.h>
+#include "google/protobuf/compiler/java/message_field_lite.h"
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -56,15 +55,16 @@
 
 namespace {
 
-void SetMessageVariables(const FieldDescriptor* descriptor, int messageBitIndex,
-                         int builderBitIndex, const FieldGeneratorInfo* info,
-                         ClassNameResolver* name_resolver,
-                         std::map<std::string, std::string>* variables) {
+void SetMessageVariables(
+    const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+    const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["type"] =
       name_resolver->GetImmutableClassName(descriptor->message_type());
-  (*variables)["kt_type"] = (*variables)["type"];
+  variables->insert({"kt_type", EscapeKotlinKeywords((*variables)["type"])});
   (*variables)["mutable_type"] =
       name_resolver->GetMutableClassName(descriptor->message_type());
   (*variables)["group_or_message"] =
@@ -74,11 +74,12 @@
   // 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->insert(
+      {"kt_deprecation",
+       descriptor->options().deprecated()
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
+                          (*variables)["name"], " is deprecated\") ")
+           : ""});
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
   if (HasHasbit(descriptor)) {
@@ -96,8 +97,8 @@
     (*variables)["set_has_field_bit_message"] = "";
     (*variables)["clear_has_field_bit_message"] = "";
 
-    (*variables)["is_field_present_message"] =
-        (*variables)["name"] + "_ != null";
+    variables->insert({"is_field_present_message",
+                       absl::StrCat((*variables)["name"], "_ != null")});
   }
 
   (*variables)["get_has_field_bit_from_local"] =
@@ -108,6 +109,9 @@
   // 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";
+  // Annotations often use { and } to determine ranges.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 }  // namespace
@@ -118,10 +122,11 @@
     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
     : descriptor_(descriptor),
       messageBitIndex_(messageBitIndex),
-      name_resolver_(context->GetNameResolver()) {
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   SetMessageVariables(descriptor, messageBitIndex, 0,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      name_resolver_, &variables_, context);
 }
 
 ImmutableMessageFieldLiteGenerator::~ImmutableMessageFieldLiteGenerator() {}
@@ -137,9 +142,13 @@
 void ImmutableMessageFieldLiteGenerator::GenerateInterfaceMembers(
     io::Printer* printer) const {
   WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
-  printer->Print(variables_, "$deprecation$boolean has$capitalized_name$();\n");
+  printer->Print(variables_,
+                 "$deprecation$boolean ${$has$capitalized_name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
-  printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+  printer->Print(variables_,
+                 "$deprecation$$type$ ${$get$capitalized_name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableMessageFieldLiteGenerator::GenerateMembers(
@@ -288,7 +297,7 @@
 
 void ImmutableMessageFieldLiteGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -299,13 +308,14 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
-  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+  WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -495,10 +505,12 @@
     RepeatedImmutableMessageFieldLiteGenerator(
         const FieldDescriptor* descriptor, int messageBitIndex,
         Context* context)
-    : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+    : descriptor_(descriptor),
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   SetMessageVariables(descriptor, messageBitIndex, 0,
                       context->GetFieldGeneratorInfo(descriptor),
-                      name_resolver_, &variables_);
+                      name_resolver_, &variables_, context);
 }
 
 RepeatedImmutableMessageFieldLiteGenerator::
@@ -517,17 +529,28 @@
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
                  "$deprecation$java.util.List<$type$> \n"
-                 "    get$capitalized_name$List();\n");
+                 "    ${$get$capitalized_name$List$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
+  WriteFieldDocComment(printer, descriptor_);
+  printer->Print(
+      variables_,
+      "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldDocComment(printer, descriptor_);
   printer->Print(variables_,
-                 "$deprecation$$type$ get$capitalized_name$(int index);\n");
-  WriteFieldDocComment(printer, descriptor_);
-  printer->Print(variables_,
-                 "$deprecation$int get$capitalized_name$Count();\n");
+                 "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableMessageFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        variables_,
+        "@com.google.protobuf.ProtoField(\n"
+        "  fieldNumber=$number$,\n"
+        "  type=com.google.protobuf.FieldType.$annotation_field_type$)\n");
+  }
   printer->Print(
       variables_,
       "private com.google.protobuf.Internal.ProtobufList<$type$> $name$_;\n");
@@ -809,7 +832,7 @@
       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$ public val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -820,7 +843,7 @@
                  "  )\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -831,7 +854,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -843,7 +866,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
@@ -854,7 +877,7 @@
                  "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -867,7 +890,7 @@
       "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -879,7 +902,7 @@
       "}\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
@@ -895,4 +918,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/message_field_lite.h b/src/google/protobuf/compiler/java/message_field_lite.h
index 4253acc..01328d2 100644
--- a/src/google/protobuf/compiler/java/message_field_lite.h
+++ b/src/google/protobuf/compiler/java/message_field_lite.h
@@ -36,10 +36,9 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_FIELD_LITE_H__
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +61,10 @@
   explicit ImmutableMessageFieldLiteGenerator(const FieldDescriptor* descriptor,
                                               int messageBitIndex,
                                               Context* context);
+  ImmutableMessageFieldLiteGenerator(
+      const ImmutableMessageFieldLiteGenerator&) = delete;
+  ImmutableMessageFieldLiteGenerator& operator=(
+      const ImmutableMessageFieldLiteGenerator&) = delete;
   ~ImmutableMessageFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
@@ -79,12 +82,12 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   const int messageBitIndex_;
   ClassNameResolver* name_resolver_;
+  Context* context_;
 
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageFieldLiteGenerator);
   void GenerateKotlinOrNull(io::Printer* printer) const;
 };
 
@@ -94,6 +97,10 @@
   ImmutableMessageOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
                                           int messageBitIndex,
                                           Context* context);
+  ImmutableMessageOneofFieldLiteGenerator(
+      const ImmutableMessageOneofFieldLiteGenerator&) = delete;
+  ImmutableMessageOneofFieldLiteGenerator& operator=(
+      const ImmutableMessageOneofFieldLiteGenerator&) = delete;
   ~ImmutableMessageOneofFieldLiteGenerator() override;
 
   void GenerateMembers(io::Printer* printer) const override;
@@ -101,8 +108,6 @@
   void GenerateFieldInfo(io::Printer* printer,
                          std::vector<uint16_t>* output) const override;
 
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageOneofFieldLiteGenerator);
 };
 
 class RepeatedImmutableMessageFieldLiteGenerator
@@ -110,6 +115,10 @@
  public:
   explicit RepeatedImmutableMessageFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  RepeatedImmutableMessageFieldLiteGenerator(
+      const RepeatedImmutableMessageFieldLiteGenerator&) = delete;
+  RepeatedImmutableMessageFieldLiteGenerator& operator=(
+      const RepeatedImmutableMessageFieldLiteGenerator&) = delete;
   ~RepeatedImmutableMessageFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
@@ -126,11 +135,9 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableMessageFieldLiteGenerator);
+  Context* context_;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/message_lite.cc b/src/google/protobuf/compiler/java/message_lite.cc
index 9a85734..d6e480f 100644
--- a/src/google/protobuf/compiler/java/message_lite.cc
+++ b/src/google/protobuf/compiler/java/message_lite.cc
@@ -32,32 +32,34 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/message_lite.h>
+#include "google/protobuf/compiler/java/message_lite.h"
 
 #include <algorithm>
 #include <cstdint>
-#include <map>
 #include <memory>
+#include <string>
 #include <vector>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/enum_lite.h>
-#include <google/protobuf/compiler/java/extension_lite.h>
-#include <google/protobuf/compiler/java/generator_factory.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/message_builder.h>
-#include <google/protobuf/compiler/java/message_builder_lite.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/enum_lite.h"
+#include "google/protobuf/compiler/java/extension_lite.h"
+#include "google/protobuf/compiler/java/generator_factory.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/message_builder.h"
+#include "google/protobuf/compiler/java/message_builder_lite.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -79,7 +81,8 @@
          "generate non-lite messages.";
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (IsRealOneof(descriptor_->field(i))) {
-      oneofs_.insert(descriptor_->field(i)->containing_oneof());
+      const OneofDescriptor* oneof = descriptor_->field(i)->containing_oneof();
+      GOOGLE_CHECK(oneofs_.emplace(oneof->index(), oneof).first->second == oneof);
     }
   }
 }
@@ -114,26 +117,33 @@
 void ImmutableMessageLiteGenerator::GenerateInterface(io::Printer* printer) {
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
                                 /* immutable = */ true, "OrBuilder");
+
+  absl::flat_hash_map<absl::string_view, std::string> variables = {
+      {"{", ""},
+      {"}", ""},
+      {"deprecation",
+       descriptor_->options().deprecated() ? "@java.lang.Deprecated " : ""},
+      {"extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_)},
+      {"classname", descriptor_->name()},
+  };
+
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
+  }
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
+        variables,
         "$deprecation$public interface ${$$classname$OrBuilder$}$ extends \n"
         "    $extra_interfaces$\n"
         "     com.google.protobuf.GeneratedMessageLite.\n"
         "          ExtendableMessageOrBuilder<\n"
-        "              $classname$, $classname$.Builder> {\n",
-        "deprecation",
-        descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
-        "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
-        "classname", descriptor_->name(), "{", "", "}", "");
+        "              $classname$, $classname$.Builder> {\n");
   } else {
     printer->Print(
+        variables,
         "$deprecation$public interface ${$$classname$OrBuilder$}$ extends\n"
         "    $extra_interfaces$\n"
-        "    com.google.protobuf.MessageLiteOrBuilder {\n",
-        "deprecation",
-        descriptor_->options().deprecated() ? "@java.lang.Deprecated " : "",
-        "extra_interfaces", ExtraMessageOrBuilderInterfaces(descriptor_),
-        "classname", descriptor_->name(), "{", "", "}", "");
+        "    com.google.protobuf.MessageLiteOrBuilder {\n");
   }
   printer->Annotate("{", "}", descriptor_);
 
@@ -143,14 +153,17 @@
     field_generators_.get(descriptor_->field(i))
         .GenerateInterfaceMembers(printer);
   }
-  for (auto oneof : oneofs_) {
-    printer->Print(
-        "\n"
-        "public $classname$.$oneof_capitalized_name$Case "
-        "get$oneof_capitalized_name$Case();\n",
-        "oneof_capitalized_name",
-        context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "classname",
-        context_->GetNameResolver()->GetImmutableClassName(descriptor_));
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
+    variables["oneof_capitalized_name"] =
+        context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
+    variables["classname"] =
+        context_->GetNameResolver()->GetImmutableClassName(descriptor_);
+    printer->Print(variables,
+                   "\n"
+                   "public ${$$classname$.$oneof_capitalized_name$Case$}$ "
+                   "get$oneof_capitalized_name$Case();\n");
+    printer->Annotate("{", "}", oneof);
   }
   printer->Outdent();
 
@@ -162,7 +175,8 @@
 void ImmutableMessageLiteGenerator::Generate(io::Printer* printer) {
   bool is_own_file = IsOwnFile(descriptor_, /* immutable = */ true);
 
-  std::map<std::string, std::string> variables;
+  absl::flat_hash_map<absl::string_view, std::string> variables = {{"{", ""},
+                                                                   {"}", ""}};
   variables["static"] = is_own_file ? " " : " static ";
   variables["classname"] = descriptor_->name();
   variables["extra_interfaces"] = ExtraMessageInterfaces(descriptor_);
@@ -179,18 +193,18 @@
   if (descriptor_->extension_range_count() > 0) {
     printer->Print(
         variables,
-        "$deprecation$public $static$final class $classname$ extends\n"
+        "$deprecation$public $static$final class ${$$classname$$}$ extends\n"
         "    com.google.protobuf.GeneratedMessageLite.ExtendableMessage<\n"
         "      $classname$, $classname$.Builder> implements\n"
         "    $extra_interfaces$\n"
         "    $classname$OrBuilder {\n");
-    builder_type = strings::Substitute(
+    builder_type = absl::Substitute(
         "com.google.protobuf.GeneratedMessageLite.ExtendableBuilder<$0, ?>",
         name_resolver_->GetImmutableClassName(descriptor_));
   } else {
     printer->Print(
         variables,
-        "$deprecation$public $static$final class $classname$ extends\n"
+        "$deprecation$public $static$final class ${$$classname$$}$ extends\n"
         "    com.google.protobuf.GeneratedMessageLite<\n"
         "        $classname$, $classname$.Builder> implements\n"
         "    $extra_interfaces$\n"
@@ -198,6 +212,7 @@
 
     builder_type = "com.google.protobuf.GeneratedMessageLite.Builder";
   }
+  printer->Annotate("{", "}", descriptor_);
   printer->Indent();
 
   GenerateConstructor(printer);
@@ -230,49 +245,59 @@
   }
 
   // oneof
-  std::map<std::string, std::string> vars;
-  for (auto oneof : oneofs_) {
+  absl::flat_hash_map<absl::string_view, std::string> vars = {{"{", ""},
+                                                              {"}", ""}};
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     vars["oneof_name"] = context_->GetOneofGeneratorInfo(oneof)->name;
     vars["oneof_capitalized_name"] =
         context_->GetOneofGeneratorInfo(oneof)->capitalized_name;
-    vars["oneof_index"] = StrCat((oneof)->index());
-    // oneofCase_ and oneof_
-    printer->Print(vars,
-                   "private int $oneof_name$Case_ = 0;\n"
-                   "private java.lang.Object $oneof_name$_;\n");
+    vars["oneof_index"] = absl::StrCat((oneof)->index());
+    if (context_->options().opensource_runtime) {
+      // oneofCase_ and oneof_
+      printer->Print(vars,
+                     "private int $oneof_name$Case_ = 0;\n"
+                     "private java.lang.Object $oneof_name$_;\n");
+    }
     // OneofCase enum
-    printer->Print(vars, "public enum $oneof_capitalized_name$Case {\n");
+    printer->Print(vars, "public enum ${$$oneof_capitalized_name$Case$}$ {\n");
+    printer->Annotate("{", "}", oneof);
     printer->Indent();
     for (int j = 0; j < (oneof)->field_count(); j++) {
       const FieldDescriptor* field = (oneof)->field(j);
       printer->Print("$field_name$($field_number$),\n", "field_name",
-                     ToUpper(field->name()), "field_number",
-                     StrCat(field->number()));
+                     absl::AsciiStrToUpper(field->name()), "field_number",
+                     absl::StrCat(field->number()));
+      printer->Annotate("field_name", field);
     }
     printer->Print("$cap_oneof_name$_NOT_SET(0);\n", "cap_oneof_name",
-                   ToUpper(vars["oneof_name"]));
+                   absl::AsciiStrToUpper(vars["oneof_name"]));
     printer->Print(vars,
                    "private final int value;\n"
                    "private $oneof_capitalized_name$Case(int value) {\n"
                    "  this.value = value;\n"
                    "}\n");
+    if (context_->options().opensource_runtime) {
+      printer->Print(
+          vars,
+          "/**\n"
+          " * @deprecated Use {@link #forNumber(int)} instead.\n"
+          " */\n"
+          "@java.lang.Deprecated\n"
+          "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
+          "  return forNumber(value);\n"
+          "}\n"
+          "\n");
+    }
     printer->Print(
         vars,
-        "/**\n"
-        " * @deprecated Use {@link #forNumber(int)} instead.\n"
-        " */\n"
-        "@java.lang.Deprecated\n"
-        "public static $oneof_capitalized_name$Case valueOf(int value) {\n"
-        "  return forNumber(value);\n"
-        "}\n"
-        "\n"
         "public static $oneof_capitalized_name$Case forNumber(int value) {\n"
         "  switch (value) {\n");
     for (int j = 0; j < (oneof)->field_count(); j++) {
       const FieldDescriptor* field = (oneof)->field(j);
       printer->Print("    case $field_number$: return $field_name$;\n",
-                     "field_number", StrCat(field->number()),
-                     "field_name", ToUpper(field->name()));
+                     "field_number", absl::StrCat(field->number()),
+                     "field_name", absl::AsciiStrToUpper(field->name()));
     }
     printer->Print(
         "    case 0: return $cap_oneof_name$_NOT_SET;\n"
@@ -284,30 +309,34 @@
         "public int getNumber() {\n"
         "  return this.value;\n"
         "}\n",
-        "cap_oneof_name", ToUpper(vars["oneof_name"]));
+        "cap_oneof_name", absl::AsciiStrToUpper(vars["oneof_name"]));
     printer->Outdent();
     printer->Print("};\n\n");
     // oneofCase()
     printer->Print(vars,
                    "@java.lang.Override\n"
                    "public $oneof_capitalized_name$Case\n"
-                   "get$oneof_capitalized_name$Case() {\n"
+                   "${$get$oneof_capitalized_name$Case$}$() {\n"
                    "  return $oneof_capitalized_name$Case.forNumber(\n"
                    "      $oneof_name$Case_);\n"
-                   "}\n"
+                   "}\n");
+    printer->Annotate("{", "}", oneof);
+    printer->Print(vars,
                    "\n"
-                   "private void clear$oneof_capitalized_name$() {\n"
+                   "private void ${$clear$oneof_capitalized_name$$}$() {\n"
                    "  $oneof_name$Case_ = 0;\n"
                    "  $oneof_name$_ = null;\n"
                    "}\n"
                    "\n");
+    printer->Annotate("{", "}", oneof);
   }
 
   // Fields
   for (int i = 0; i < descriptor_->field_count(); i++) {
     printer->Print("public static final int $constant_name$ = $number$;\n",
                    "constant_name", FieldConstantName(descriptor_->field(i)),
-                   "number", StrCat(descriptor_->field(i)->number()));
+                   "number", absl::StrCat(descriptor_->field(i)->number()));
+    printer->Annotate("constant_name", descriptor_->field(i));
     field_generators_.get(descriptor_->field(i)).GenerateMembers(printer);
     printer->Print("\n");
   }
@@ -496,11 +525,11 @@
 
     // Record the number of oneofs.
     WriteIntToUtf16CharSequence(oneofs_.size(), &chars);
-    for (auto oneof : oneofs_) {
+    for (auto& kv : oneofs_) {
       printer->Print(
           "\"$oneof_name$_\",\n"
           "\"$oneof_name$Case_\",\n",
-          "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name);
+          "oneof_name", context_->GetOneofGeneratorInfo(kv.second)->name);
     }
 
     // Integers for bit fields.
@@ -747,7 +776,8 @@
       "  @kotlin.jvm.JvmSynthetic\n"
       "  @kotlin.PublishedApi\n"
       "  internal fun _build(): $message$ = _builder.build()\n",
-      "message", name_resolver_->GetClassName(descriptor_, true));
+      "message",
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)));
 
   printer->Indent();
 
@@ -757,7 +787,8 @@
         .GenerateKotlinDslMembers(printer);
   }
 
-  for (auto oneof : oneofs_) {
+  for (auto& kv : oneofs_) {
+    const OneofDescriptor* oneof = kv.second;
     printer->Print(
         "public val $oneof_name$Case: $message$.$oneof_capitalized_name$Case\n"
         "  @JvmName(\"get$oneof_capitalized_name$Case\")\n"
@@ -768,7 +799,7 @@
         "oneof_name", context_->GetOneofGeneratorInfo(oneof)->name,
         "oneof_capitalized_name",
         context_->GetOneofGeneratorInfo(oneof)->capitalized_name, "message",
-        name_resolver_->GetClassName(descriptor_, true));
+        EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)));
   }
 
   if (descriptor_->extension_range_count() > 0) {
@@ -781,17 +812,26 @@
 
 void ImmutableMessageLiteGenerator::GenerateKotlinMembers(
     io::Printer* printer) const {
+  printer->Print("@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n",
+                 "camelcase_name",
+                 name_resolver_->GetKotlinFactoryName(descriptor_));
+
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.errorprone.annotations.CheckReturnValue\n");
+  }
   printer->Print(
-      "@kotlin.jvm.JvmName(\"-initialize$camelcase_name$\")\n"
       "public inline fun $camelcase_name$(block: $message_kt$.Dsl.() -> "
-      "kotlin.Unit): "
-      "$message$ =\n"
+      "kotlin.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));
+      "message_kt",
+      EscapeKotlinKeywords(
+          name_resolver_->GetKotlinExtensionsClassName(descriptor_)),
+      "message",
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)));
 
+  WriteMessageDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print("public object $name$Kt {\n", "name", descriptor_->name());
   printer->Indent();
   GenerateKotlinDsl(printer);
@@ -806,14 +846,19 @@
 
 void ImmutableMessageLiteGenerator::GenerateTopLevelKotlinMembers(
     io::Printer* printer) const {
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.errorprone.annotations.CheckReturnValue\n");
+  }
   printer->Print(
       "public inline fun $message$.copy(block: $message_kt$.Dsl.() -> "
-      "kotlin.Unit): "
-      "$message$ =\n"
+      "kotlin.Unit): $message$ =\n"
       "  $message_kt$.Dsl._create(this.toBuilder()).apply { block() "
       "}._build()\n\n",
-      "message", name_resolver_->GetClassName(descriptor_, true), "message_kt",
-      name_resolver_->GetKotlinExtensionsClassName(descriptor_));
+      "message",
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)),
+      "message_kt",
+      EscapeKotlinKeywords(
+          name_resolver_->GetKotlinExtensionsClassName(descriptor_)));
 
   for (int i = 0; i < descriptor_->nested_type_count(); i++) {
     if (IsMapEntry(descriptor_->nested_type(i))) continue;
@@ -833,18 +878,21 @@
           "public val $full_classname$OrBuilder.$camelcase_name$OrNull: "
           "$full_name$?\n"
           "  get() = if (has$name$()) get$name$() else null\n\n",
-          "full_classname", name_resolver_->GetClassName(descriptor_, true),
+          "full_classname",
+          EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true)),
           "camelcase_name", context_->GetFieldGeneratorInfo(field)->name,
           "full_name",
-          name_resolver_->GetImmutableClassName(field->message_type()), "name",
-          context_->GetFieldGeneratorInfo(field)->capitalized_name);
+          EscapeKotlinKeywords(
+              name_resolver_->GetImmutableClassName(field->message_type())),
+          "name", context_->GetFieldGeneratorInfo(field)->capitalized_name);
     }
   }
 }
 
 void ImmutableMessageLiteGenerator::GenerateKotlinExtensions(
     io::Printer* printer) const {
-  std::string message_name = name_resolver_->GetClassName(descriptor_, true);
+  std::string message_name =
+      EscapeKotlinKeywords(name_resolver_->GetClassName(descriptor_, true));
 
   printer->Print(
       "@Suppress(\"UNCHECKED_CAST\")\n"
@@ -853,7 +901,7 @@
       "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"
+      "kotlin.collections.List<*>>) as T\n"
       "  } else {\n"
       "    _builder.getExtension(extension)\n"
       "  }\n"
@@ -866,7 +914,8 @@
       "(com.google.protobuf.kotlin.OnlyForUseByGeneratedProtoCode::class)\n"
       "@kotlin.jvm.JvmName(\"-getRepeatedExtension\")\n"
       "public operator fun <E : kotlin.Any> get(\n"
-      "  extension: com.google.protobuf.ExtensionLite<$message$, List<E>>\n"
+      "  extension: com.google.protobuf.ExtensionLite<$message$, "
+      "kotlin.collections.List<E>>\n"
       "): com.google.protobuf.kotlin.ExtensionList<E, $message$> {\n"
       "  return com.google.protobuf.kotlin.ExtensionList(extension, "
       "_builder.getExtension(extension))\n"
@@ -893,8 +942,7 @@
 
   printer->Print(
       "@kotlin.jvm.JvmSynthetic\n"
-      "@kotlin.PublishedApi\n"
-      "internal fun <T : kotlin.Any> setExtension(extension: "
+      "public fun <T : kotlin.Any> setExtension(extension: "
       "com.google.protobuf.ExtensionLite<$message$, T>, "
       "value: T) {\n"
       "  _builder.setExtension(extension, value)\n"
@@ -1000,4 +1048,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/message_lite.h b/src/google/protobuf/compiler/java/message_lite.h
index d1e4b68..2794040 100644
--- a/src/google/protobuf/compiler/java/message_lite.h
+++ b/src/google/protobuf/compiler/java/message_lite.h
@@ -35,8 +35,8 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_LITE_H__
 
-#include <google/protobuf/compiler/java/field.h>
-#include <google/protobuf/compiler/java/message.h>
+#include "google/protobuf/compiler/java/field.h"
+#include "google/protobuf/compiler/java/message.h"
 
 namespace google {
 namespace protobuf {
@@ -46,6 +46,9 @@
 class ImmutableMessageLiteGenerator : public MessageGenerator {
  public:
   ImmutableMessageLiteGenerator(const Descriptor* descriptor, Context* context);
+  ImmutableMessageLiteGenerator(const ImmutableMessageLiteGenerator&) = delete;
+  ImmutableMessageLiteGenerator& operator=(
+      const ImmutableMessageLiteGenerator&) = delete;
   ~ImmutableMessageLiteGenerator() override;
 
   void Generate(io::Printer* printer) override;
@@ -73,8 +76,6 @@
   Context* context_;
   ClassNameResolver* name_resolver_;
   FieldGeneratorMap<ImmutableFieldLiteGenerator> field_generators_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableMessageLiteGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/compiler/java/message_serialization.cc
similarity index 76%
copy from src/google/protobuf/util/internal/error_listener.cc
copy to src/google/protobuf/compiler/java/message_serialization.cc
index 538307b..fb258b8 100644
--- a/src/google/protobuf/util/internal/error_listener.cc
+++ b/src/google/protobuf/compiler/java/message_serialization.cc
@@ -28,15 +28,24 @@
 // (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/util/internal/error_listener.h>
+#include "google/protobuf/compiler/java/message_serialization.h"
+
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace converter {
+namespace compiler {
+namespace java {
 
+void GenerateSerializeExtensionRange(io::Printer* printer,
+                                     const Descriptor::ExtensionRange* range) {
+  printer->Print("extensionWriter.writeUntil($end$, output);\n", "end",
+                 absl::StrCat(range->end));
+}
 
-}  // namespace converter
-}  // namespace util
+}  // namespace java
+}  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/compiler/java/message_serialization.h b/src/google/protobuf/compiler/java/message_serialization.h
new file mode 100644
index 0000000..3b7c846
--- /dev/null
+++ b/src/google/protobuf/compiler/java/message_serialization.h
@@ -0,0 +1,103 @@
+// 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_JAVA_MESSAGE_SERIALIZATION_H__
+#define GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__
+
+#include <algorithm>
+#include <cstddef>
+#include <vector>
+
+#include "google/protobuf/compiler/java/field.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+// Generates code to serialize a single extension range.
+void GenerateSerializeExtensionRange(io::Printer* printer,
+                                     const Descriptor::ExtensionRange* range);
+
+// Generates code to serialize all fields and extension ranges for the specified
+// message descriptor, sorting serialization calls in increasing order by field
+// number.
+//
+// Templatized to support different field generator implementations.
+template <typename FieldGenerator>
+void GenerateSerializeFieldsAndExtensions(
+    io::Printer* printer,
+    const FieldGeneratorMap<FieldGenerator>& field_generators,
+    const Descriptor* descriptor, const FieldDescriptor** sorted_fields) {
+  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(),
+            ExtensionRangeOrdering());
+
+  std::size_t range_idx = 0;
+
+  // Merge the fields and the extension ranges, both sorted by field number.
+  for (int i = 0; i < descriptor->field_count(); ++i) {
+    const FieldDescriptor* field = sorted_fields[i];
+
+    // Collapse all extension ranges up until the next field. This leads to
+    // shorter and more efficient codegen for messages containing a large
+    // number of extension ranges without fields in between them.
+    const Descriptor::ExtensionRange* range = nullptr;
+    while (range_idx < sorted_extensions.size() &&
+           sorted_extensions[range_idx]->end <= field->number()) {
+      range = sorted_extensions[range_idx++];
+    }
+
+    if (range != nullptr) {
+      GenerateSerializeExtensionRange(printer, range);
+    }
+    field_generators.get(field).GenerateSerializationCode(printer);
+  }
+
+  // After serializing all fields, serialize any remaining extensions via a
+  // single writeUntil call.
+  if (range_idx < sorted_extensions.size()) {
+    GenerateSerializeExtensionRange(printer, sorted_extensions.back());
+  }
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_MESSAGE_SERIALIZATION_H__
diff --git a/src/google/protobuf/compiler/java/message_serialization_unittest.cc b/src/google/protobuf/compiler/java/message_serialization_unittest.cc
new file mode 100644
index 0000000..2ef7309
--- /dev/null
+++ b/src/google/protobuf/compiler/java/message_serialization_unittest.cc
@@ -0,0 +1,125 @@
+// 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 <cstddef>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include <gmock/gmock.h>
+#include "google/protobuf/testing/googletest.h"
+#include <gtest/gtest.h>
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/compiler/command_line_interface.h"
+#include "google/protobuf/compiler/java/generator.h"
+#include "google/protobuf/test_util2.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+namespace {
+
+using ::testing::ElementsAre;
+
+// Generates Java code for the specified Java proto, returning the compiler's
+// exit status.
+int CompileJavaProto(std::string proto_file_name) {
+  JavaGenerator java_generator;
+
+  CommandLineInterface cli;
+  cli.RegisterGenerator("--java_out", &java_generator, /*help_text=*/"");
+
+  std::string proto_path = absl::StrCat(
+      "--proto_path=",
+      TestUtil::GetTestDataPath("third_party/protobuf/compiler/java"));
+  std::string java_out = absl::StrCat("--java_out=", TestTempDir());
+
+  const char* argv[] = {
+      "protoc",
+      proto_path.c_str(),
+      java_out.c_str(),
+      proto_file_name.c_str(),
+  };
+
+  return cli.Run(4, argv);
+}
+
+TEST(MessageSerializationTest, CollapseAdjacentExtensionRanges) {
+  GOOGLE_CHECK_EQ(CompileJavaProto("message_serialization_unittest.proto"), 0);
+
+  std::string java_source;
+  GOOGLE_CHECK_OK(File::GetContents(
+      // Open-source codebase does not support file::JoinPath, so we manually
+      // concatenate instead.
+      absl::StrCat(TestTempDir(),
+                   "/TestMessageWithManyExtensionRanges.java"),
+      &java_source, true));
+
+  // Open-source codebase does not support constexpr absl::string_view.
+  static constexpr const char kWriteUntilCall[] = "extensionWriter.writeUntil(";
+
+  std::vector<std::string> range_ends;
+
+  // Open-source codebase does not have absl::StrSplit overload taking a single
+  // char delimiter.
+  //
+  // NOLINTNEXTLINE(abseil-faster-strsplit-delimiter)
+  for (const auto& line : absl::StrSplit(java_source, "\n")) {
+    // Extract end position from writeUntil call. (Open-source codebase does not
+    // support RE2.)
+    std::size_t write_until_pos = line.find(kWriteUntilCall);
+    if (write_until_pos == std::string::npos) {
+      continue;
+    }
+    write_until_pos += (sizeof(kWriteUntilCall) - 1);
+
+    std::size_t comma_pos = line.find(',', write_until_pos);
+    if (comma_pos == std::string::npos) {
+      continue;
+    }
+
+    range_ends.push_back(
+        std::string(line.substr(write_until_pos, comma_pos - write_until_pos)));
+  }
+
+  EXPECT_THAT(range_ends, ElementsAre("3", "13", "43"));
+}
+
+}  // namespace
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/stubs/once.h b/src/google/protobuf/compiler/java/message_serialization_unittest.proto
similarity index 71%
copy from src/google/protobuf/stubs/once.h
copy to src/google/protobuf/compiler/java/message_serialization_unittest.proto
index 070d36d..9cfdf42 100644
--- a/src/google/protobuf/stubs/once.h
+++ b/src/google/protobuf/compiler/java/message_serialization_unittest.proto
@@ -28,28 +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.
 
-#ifndef GOOGLE_PROTOBUF_STUBS_ONCE_H__
-#define GOOGLE_PROTOBUF_STUBS_ONCE_H__
+syntax = "proto2";
 
-#include <mutex>
-#include <utility>
+package protobuf_unittest;
 
-#include <google/protobuf/port_def.inc>
+option java_multiple_files = true;
+option java_package = "";
 
-namespace google {
-namespace protobuf {
-namespace internal {
+// Each batch of extension ranges not separated by a non-extension field should
+// be serialized using a single ExtensionWriter#writeUntil call.
+message TestMessageWithManyExtensionRanges {
+  // First extension range: ends at field number 3 (exclusive)
+  extensions 1 to 2;
 
-using once_flag = std::once_flag;
-template <typename... Args>
-void call_once(Args&&... args ) {
-  std::call_once(std::forward<Args>(args)...);
+  optional int32 foo = 3;
+  optional int32 bar = 5;
+
+  // Second extension range: ends at field number 13 (exclusive)
+  extensions 6;
+  extensions 8;
+  extensions 10 to 12;
+
+  optional int32 baz = 23;
+
+  // Third extension range: ends at field number 43 (exclusive)
+  extensions 42;
 }
-
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_ONCE_H__
diff --git a/src/google/protobuf/compiler/java/name_resolver.cc b/src/google/protobuf/compiler/java/name_resolver.cc
index 06a637e..32f35ad 100644
--- a/src/google/protobuf/compiler/java/name_resolver.cc
+++ b/src/google/protobuf/compiler/java/name_resolver.cc
@@ -28,18 +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.
 
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "google/protobuf/compiler/java/name_resolver.h"
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/names.h>
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/names.h"
+
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -108,7 +110,7 @@
 
 // Return true if a and b are equals (case insensitive).
 NameEquality CheckNameEquality(const std::string& a, const std::string& b) {
-  if (ToUpper(a) == ToUpper(b)) {
+  if (absl::AsciiStrToUpper(a) == absl::AsciiStrToUpper(b)) {
     if (a == b) {
       return NameEquality::EXACT_EQUAL;
     }
@@ -141,10 +143,6 @@
 
 }  // namespace
 
-ClassNameResolver::ClassNameResolver() {}
-
-ClassNameResolver::~ClassNameResolver() {}
-
 std::string ClassNameResolver::GetFileDefaultImmutableClassName(
     const FileDescriptor* file) {
   std::string basename;
@@ -217,8 +215,12 @@
 }
 
 std::string ClassNameResolver::GetDescriptorClassName(
-    const FileDescriptor* descriptor) {
-  return GetFileImmutableClassName(descriptor);
+    const FileDescriptor* file) {
+  if (options_.opensource_runtime) {
+    return GetFileImmutableClassName(file);
+  } else {
+    return GetFileImmutableClassName(file) + "InternalDescriptors";
+  }
 }
 
 std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor,
@@ -228,7 +230,7 @@
 
 std::string ClassNameResolver::GetClassName(const FileDescriptor* descriptor,
                                             bool immutable, bool kotlin) {
-  std::string result = FileJavaPackage(descriptor, immutable);
+  std::string result = FileJavaPackage(descriptor, immutable, options_);
   if (!result.empty()) result += '.';
   result += GetFileClassName(descriptor, immutable, kotlin);
   return result;
@@ -248,7 +250,7 @@
     bool immutable, bool is_own_file, bool kotlin) {
   std::string result;
   if (is_own_file) {
-    result = FileJavaPackage(file, immutable);
+    result = FileJavaPackage(file, immutable, options_);
   } else {
     result = GetClassName(file, immutable, kotlin);
   }
@@ -308,13 +310,13 @@
     bool immutable, bool kotlin) {
   std::string result;
   if (MultipleJavaFiles(file, immutable)) {
-    result = FileJavaPackage(file, immutable);
+    result = FileJavaPackage(file, immutable, options_);
     if (!result.empty()) result += '.';
   } else {
     result = GetClassName(file, immutable, kotlin);
     if (!result.empty()) result += '$';
   }
-  result += StringReplace(name_without_package, ".", "$", true);
+  result += absl::StrReplaceAll(name_without_package, {{".", "$"}});
   return result;
 }
 
@@ -372,7 +374,7 @@
 
 std::string ClassNameResolver::GetDowngradedClassName(
     const Descriptor* descriptor) {
-  return FileJavaPackage(descriptor->file()) + "." +
+  return FileJavaPackage(descriptor->file(), true, options_) + "." +
          GetDowngradedFileClassName(descriptor->file()) + "." +
          ClassNameWithoutPackage(descriptor, false);
 }
@@ -382,4 +384,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/name_resolver.h b/src/google/protobuf/compiler/java/name_resolver.h
index 103cace..7e8a75c 100644
--- a/src/google/protobuf/compiler/java/name_resolver.h
+++ b/src/google/protobuf/compiler/java/name_resolver.h
@@ -31,13 +31,16 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__
 
-#include <map>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/java/options.h"
+#include "google/protobuf/port.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -58,8 +61,11 @@
 // Thread-safety note: This class is *not* thread-safe.
 class ClassNameResolver {
  public:
-  ClassNameResolver();
-  ~ClassNameResolver();
+  explicit ClassNameResolver(const Options& options = {}) : options_(options) {}
+  ~ClassNameResolver() = default;
+
+  ClassNameResolver(const ClassNameResolver&) = delete;
+  ClassNameResolver& operator=(const ClassNameResolver&) = delete;
 
   // Gets the unqualified outer class name for the file.
   std::string GetFileClassName(const FileDescriptor* file, bool immutable);
@@ -135,6 +141,8 @@
                                const FileDescriptor* file, bool immutable,
                                bool is_own_file, bool kotlin);
 
+  Options options_;
+
  private:
   // Get the Java Class style full name of a message.
   std::string GetJavaClassFullName(const std::string& name_without_package,
@@ -143,10 +151,8 @@
                                    const FileDescriptor* file, bool immutable,
                                    bool kotlin);
   // Caches the result to provide better performance.
-  std::map<const FileDescriptor*, std::string>
+  absl::flat_hash_map<const FileDescriptor*, std::string>
       file_immutable_outer_class_names_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ClassNameResolver);
 };
 
 }  // namespace java
@@ -154,6 +160,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_NAME_RESOLVER_H__
diff --git a/src/google/protobuf/compiler/java/names.cc b/src/google/protobuf/compiler/java/names.cc
new file mode 100644
index 0000000..f4f0858
--- /dev/null
+++ b/src/google/protobuf/compiler/java/names.cc
@@ -0,0 +1,193 @@
+// 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.
+
+#include "google/protobuf/compiler/java/names.h"
+
+#include <string>
+
+#include "absl/container/flat_hash_set.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/compiler/java/names.h"
+#include "google/protobuf/compiler/java/options.h"
+#include "google/protobuf/descriptor.pb.h"
+
+// Must be last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace java {
+
+namespace {
+
+const char* DefaultPackage(Options options) {
+  return options.opensource_runtime ? "" : "com.google.protos";
+}
+
+bool IsReservedName(absl::string_view name) {
+  static const auto& kReservedNames =
+      *new absl::flat_hash_set<absl::string_view>({
+          "abstract",   "assert",       "boolean",   "break",      "byte",
+          "case",       "catch",        "char",      "class",      "const",
+          "continue",   "default",      "do",        "double",     "else",
+          "enum",       "extends",      "final",     "finally",    "float",
+          "for",        "goto",         "if",        "implements", "import",
+          "instanceof", "int",          "interface", "long",       "native",
+          "new",        "package",      "private",   "protected",  "public",
+          "return",     "short",        "static",    "strictfp",   "super",
+          "switch",     "synchronized", "this",      "throw",      "throws",
+          "transient",  "try",          "void",      "volatile",   "while",
+      });
+  return kReservedNames.contains(name);
+}
+
+bool IsForbidden(const std::string& field_name) {
+  // Names that should be avoided (in UpperCamelCase format).
+  // Using them will cause the compiler to generate accessors whose names
+  // collide with methods defined in base classes.
+  // Keep this list in sync with specialFieldNames in
+  // java/core/src/main/java/com/google/protobuf/DescriptorMessageInfoFactory.java
+  static const auto& kForbiddenNames =
+      *new absl::flat_hash_set<absl::string_view>({
+        // java.lang.Object:
+          "Class",
+          // com.google.protobuf.MessageLiteOrBuilder:
+          "DefaultInstanceForType",
+          // com.google.protobuf.MessageLite:
+          "ParserForType",
+          "SerializedSize",
+          // com.google.protobuf.MessageOrBuilder:
+          "AllFields",
+          "DescriptorForType",
+          "InitializationErrorString",
+          "UnknownFields",
+          // obsolete. kept for backwards compatibility of generated code
+          "CachedSize",
+      });
+  return kForbiddenNames.contains(UnderscoresToCamelCase(field_name, true));
+}
+
+std::string FieldName(const FieldDescriptor* field) {
+  std::string field_name;
+  // Groups are hacky:  The name of the field is just the lower-cased name
+  // of the group type.  In Java, though, we would like to retain the original
+  // capitalization of the type name.
+  if (GetType(field) == FieldDescriptor::TYPE_GROUP) {
+    field_name = field->message_type()->name();
+  } else {
+    field_name = field->name();
+  }
+  if (IsForbidden(field_name)) {
+    // Append a trailing "#" to indicate that the name should be decorated to
+    // avoid collision with other names.
+    field_name += "#";
+  }
+  return field_name;
+}
+
+}  // namespace
+
+std::string ClassName(const Descriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+std::string ClassName(const EnumDescriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+std::string ClassName(const ServiceDescriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+std::string ClassName(const FileDescriptor* descriptor) {
+  ClassNameResolver name_resolver;
+  return name_resolver.GetClassName(descriptor, true);
+}
+
+std::string FileJavaPackage(const FileDescriptor* file, bool immutable,
+                            Options options) {
+  std::string result;
+
+  if (file->options().has_java_package()) {
+    result = file->options().java_package();
+  } else {
+    result = DefaultPackage(options);
+    if (!file->package().empty()) {
+      if (!result.empty()) result += '.';
+      result += file->package();
+    }
+  }
+
+  return result;
+}
+
+std::string FileJavaPackage(const FileDescriptor* file, Options options) {
+  return FileJavaPackage(file, true /* immutable */, options);
+}
+
+std::string CapitalizedFieldName(const FieldDescriptor* field) {
+  return UnderscoresToCamelCase(FieldName(field), true);
+}
+
+std::string UnderscoresToCamelCase(const FieldDescriptor* field) {
+  return UnderscoresToCamelCase(FieldName(field), false);
+}
+
+std::string UnderscoresToCapitalizedCamelCase(const FieldDescriptor* field) {
+  return UnderscoresToCamelCase(FieldName(field), true);
+}
+
+std::string UnderscoresToCamelCase(const MethodDescriptor* method) {
+  return UnderscoresToCamelCase(method->name(), false);
+}
+
+std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field) {
+  std::string name = UnderscoresToCamelCase(field);
+  if (IsReservedName(name)) {
+    return name + "_";
+  }
+  return name;
+}
+
+}  // namespace java
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/names.h b/src/google/protobuf/compiler/java/names.h
index 313ace4..5c55bb3 100644
--- a/src/google/protobuf/compiler/java/names.h
+++ b/src/google/protobuf/compiler/java/names.h
@@ -40,6 +40,12 @@
 
 #include <string>
 
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/compiler/java/options.h"
+
+// Must be last.
+#include "google/protobuf/port_def.inc"
+
 namespace google {
 namespace protobuf {
 
@@ -85,7 +91,8 @@
 //
 // Returns:
 //   Java package name.
-std::string FileJavaPackage(const FileDescriptor* descriptor);
+std::string FileJavaPackage(const FileDescriptor* descriptor,
+                            Options options = {});
 
 // Requires:
 //   descriptor != NULL
@@ -93,8 +100,36 @@
 //   Capitalized camel case name field name.
 std::string CapitalizedFieldName(const FieldDescriptor* descriptor);
 
+// Returns:
+//   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);
+// Requires:
+//   field != NULL
+// Returns:
+//   Converts the field's name to camel-case, e.g. "foo_bar_baz" becomes
+//   "fooBarBaz" or "FooBarBaz", respectively.
+std::string UnderscoresToCamelCase(const FieldDescriptor* field);
+
+// Requires:
+//   method != NULL
+// Returns:
+//   Similar, but for method names.  (Typically, this merely has the effect
+//   of lower-casing the first letter of the name.)
+std::string UnderscoresToCamelCase(const MethodDescriptor* method);
+
+// Requires:
+//   field != NULL
+// Returns:
+//   Same as UnderscoresToCamelCase, but checks for reserved keywords
+std::string UnderscoresToCamelCaseCheckReserved(const FieldDescriptor* field);
+
+
 }  // namespace java
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#include "google/protobuf/port_undef.inc"
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_NAMES_H__
diff --git a/src/google/protobuf/compiler/java/options.h b/src/google/protobuf/compiler/java/options.h
index 6c29be1..79d90fd 100644
--- a/src/google/protobuf/compiler/java/options.h
+++ b/src/google/protobuf/compiler/java/options.h
@@ -33,6 +33,8 @@
 
 #include <string>
 
+#include "google/protobuf/port_def.inc"
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -54,6 +56,7 @@
   // When set, the protoc will generate the current files and all the transitive
   // dependencies as lite runtime.
   bool enforce_lite;
+  bool opensource_runtime = PROTO2_IS_OSS;
   // If true, we should build .meta files and emit @Generated annotations into
   // generated code.
   bool annotate_code;
@@ -70,4 +73,5 @@
 }  // namespace protobuf
 }  // namespace google
 
+#include "google/protobuf/port_undef.inc"
 #endif  // GOOGLE_PROTOBUF_COMPILER_JAVA_OPTIONS_H__
diff --git a/src/google/protobuf/compiler/java/plugin_unittest.cc b/src/google/protobuf/compiler/java/plugin_unittest.cc
index 8135f86..467d1fe 100644
--- a/src/google/protobuf/compiler/java/plugin_unittest.cc
+++ b/src/google/protobuf/compiler/java/plugin_unittest.cc
@@ -33,15 +33,15 @@
 #include <memory>
 #include <string>
 
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/compiler/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/stubs/strutil.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "absl/strings/str_split.h"
+#include "google/protobuf/compiler/command_line_interface.h"
+#include "google/protobuf/compiler/java/generator.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
@@ -114,7 +114,7 @@
   std::string output;
   GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/Test.java", &output,
                              true));
-  std::vector<std::string> lines = Split(output, "\n");
+  std::vector<std::string> lines = absl::StrSplit(output, "\n");
   bool found_generated_annotation = false;
   bool found_do_not_edit = false;
   for (const auto& line : lines) {
diff --git a/src/google/protobuf/compiler/java/primitive_field.cc b/src/google/protobuf/compiler/java/primitive_field.cc
index 2e3b8ea..50e0637 100644
--- a/src/google/protobuf/compiler/java/primitive_field.cc
+++ b/src/google/protobuf/compiler/java/primitive_field.cc
@@ -35,18 +35,17 @@
 #include "google/protobuf/compiler/java/primitive_field.h"
 
 #include <cstdint>
-#include <map>
 #include <string>
 
 #include "google/protobuf/stubs/logging.h"
 #include "google/protobuf/stubs/common.h"
-#include "google/protobuf/io/printer.h"
-#include "google/protobuf/wire_format.h"
-#include "google/protobuf/stubs/strutil.h"
+#include "absl/strings/str_cat.h"
 #include "google/protobuf/compiler/java/context.h"
 #include "google/protobuf/compiler/java/doc_comment.h"
 #include "google/protobuf/compiler/java/helpers.h"
 #include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -60,7 +59,7 @@
 void SetPrimitiveVariables(
     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
     const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
-    std::map<std::string, std::string>* variables,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
     Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
   JavaType javaType = GetJavaType(descriptor);
@@ -77,47 +76,49 @@
     std::string capitalized_type = UnderscoresToCamelCase(
         PrimitiveTypeName(javaType), /*cap_first_letter=*/true);
     (*variables)["field_list_type"] =
-        StrCat("com.google.protobuf.Internal.", capitalized_type, "List");
+        absl::StrCat("com.google.protobuf.Internal.", capitalized_type, "List");
     (*variables)["empty_list"] =
-        StrCat("empty", capitalized_type, "List()");
+        absl::StrCat("empty", capitalized_type, "List()");
     (*variables)["create_list"] =
-        StrCat("new", capitalized_type, "List()");
+        absl::StrCat("new", capitalized_type, "List()");
     (*variables)["mutable_copy_list"] =
-        StrCat("mutableCopy(", name, "_)");
+        absl::StrCat("mutableCopy(", name, "_)");
     (*variables)["name_make_immutable"] =
-        StrCat(name, "_.makeImmutable()");
+        absl::StrCat(name, "_.makeImmutable()");
     (*variables)["repeated_get"] =
-        StrCat(name, "_.get", capitalized_type);
+        absl::StrCat(name, "_.get", capitalized_type);
     (*variables)["repeated_add"] =
-        StrCat(name, "_.add", capitalized_type);
+        absl::StrCat(name, "_.add", capitalized_type);
     (*variables)["repeated_set"] =
-        StrCat(name, "_.set", capitalized_type);
+        absl::StrCat(name, "_.set", capitalized_type);
   } else {
     std::string boxed_type = (*variables)["boxed_type"];
     (*variables)["field_list_type"] =
-        StrCat("java.util.List<", boxed_type, ">");
+        absl::StrCat("java.util.List<", boxed_type, ">");
     (*variables)["create_list"] =
-        StrCat("new java.util.ArrayList<", boxed_type, ">()");
+        absl::StrCat("new java.util.ArrayList<", boxed_type, ">()");
     (*variables)["mutable_copy_list"] =
-        StrCat("new java.util.ArrayList<", boxed_type, ">(", name, "_)");
+        absl::StrCat("new java.util.ArrayList<", boxed_type, ">(", name, "_)");
     (*variables)["empty_list"] = "java.util.Collections.emptyList()";
-    (*variables)["name_make_immutable"] = StrCat(
+    (*variables)["name_make_immutable"] = absl::StrCat(
         name, "_ = java.util.Collections.unmodifiableList(", name, "_)");
-    (*variables)["repeated_get"] = StrCat(name, "_.get");
-    (*variables)["repeated_add"] = StrCat(name, "_.add");
-    (*variables)["repeated_set"] = StrCat(name, "_.set");
+    (*variables)["repeated_get"] = absl::StrCat(name, "_.get");
+    (*variables)["repeated_add"] = absl::StrCat(name, "_.add");
+    (*variables)["repeated_set"] = absl::StrCat(name, "_.set");
   }
 
-  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default"] =
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
   (*variables)["default_init"] =
       IsDefaultValueJavaDefault(descriptor)
           ? ""
-          : ("= " + ImmutableDefaultValue(descriptor, name_resolver));
-  (*variables)["capitalized_type"] =
-      GetCapitalizedType(descriptor, /* immutable = */ true);
+          : ("= " + ImmutableDefaultValue(descriptor, name_resolver,
+                                          context->options()));
+  (*variables)["capitalized_type"] = GetCapitalizedType(
+      descriptor, /* immutable = */ true, context->options());
   (*variables)["tag"] =
-      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
-  (*variables)["tag_size"] = StrCat(
+      absl::StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+  (*variables)["tag_size"] = absl::StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   if (IsReferenceType(GetJavaType(descriptor))) {
     (*variables)["null_check"] =
@@ -131,12 +132,12 @@
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
   (*variables)["kt_deprecation"] =
       descriptor->options().deprecated()
-          ? StrCat("@kotlin.Deprecated(message = \"Field ", name,
+          ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", name,
                          " is deprecated\") ")
           : "";
   int fixed_size = FixedSize(GetType(descriptor));
   if (fixed_size != -1) {
-    (*variables)["fixed_size"] = StrCat(fixed_size);
+    (*variables)["fixed_size"] = absl::StrCat(fixed_size);
   }
   (*variables)["on_changed"] = "onChanged();";
 
@@ -152,20 +153,20 @@
     switch (descriptor->type()) {
       case FieldDescriptor::TYPE_BYTES:
         (*variables)["is_field_present_message"] =
-            StrCat("!", name, "_.isEmpty()");
+            absl::StrCat("!", name, "_.isEmpty()");
         break;
       case FieldDescriptor::TYPE_FLOAT:
         (*variables)["is_field_present_message"] =
-            StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0");
+            absl::StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0");
         break;
       case FieldDescriptor::TYPE_DOUBLE:
-        (*variables)["is_field_present_message"] = StrCat(
+        (*variables)["is_field_present_message"] = absl::StrCat(
             "java.lang.Double.doubleToRawLongBits(", name, "_) != 0");
         break;
       default:
         variables->insert(
             {"is_field_present_message",
-             StrCat(name, "_ != ", (*variables)["default"])});
+             absl::StrCat(name, "_ != ", (*variables)["default"])});
         break;
     }
   }
@@ -314,7 +315,7 @@
 
 void ImmutablePrimitiveFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public var $kt_name$: $kt_type$\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -325,14 +326,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
   if (HasHazzer(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                                 /* builder */ false, /* kdoc */ true);
     printer->Print(
         variables_,
         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -833,7 +835,7 @@
       "public class ${$$kt_capitalized_name$Proxy$}$ private constructor()"
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$ public val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -844,7 +846,7 @@
                  "  )\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -855,7 +857,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -867,7 +869,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
@@ -878,7 +880,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -891,7 +893,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -903,7 +905,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
diff --git a/src/google/protobuf/compiler/java/primitive_field.h b/src/google/protobuf/compiler/java/primitive_field.h
index 9d95655..7e98686 100644
--- a/src/google/protobuf/compiler/java/primitive_field.h
+++ b/src/google/protobuf/compiler/java/primitive_field.h
@@ -35,7 +35,6 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_H__
 
-#include <map>
 #include <string>
 
 #include "google/protobuf/compiler/java/field.h"
@@ -96,7 +95,7 @@
   const FieldDescriptor* descriptor_;
   int message_bit_index_;
   int builder_bit_index_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   ClassNameResolver* name_resolver_;
 };
 
diff --git a/src/google/protobuf/compiler/java/primitive_field_lite.cc b/src/google/protobuf/compiler/java/primitive_field_lite.cc
index 28c23d5..badc0d8 100644
--- a/src/google/protobuf/compiler/java/primitive_field_lite.cc
+++ b/src/google/protobuf/compiler/java/primitive_field_lite.cc
@@ -32,21 +32,20 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/primitive_field_lite.h>
+#include "google/protobuf/compiler/java/primitive_field_lite.h"
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -65,65 +64,70 @@
 #endif  // !PROTOBUF_EXPERIMENT
 }
 
-void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           int messageBitIndex, int builderBitIndex,
-                           const FieldGeneratorInfo* info,
-                           ClassNameResolver* name_resolver,
-                           std::map<std::string, std::string>* variables) {
+void SetPrimitiveVariables(
+    const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+    const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
   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->insert({"field_type", (*variables)["type"]});
+  (*variables)["default"] =
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
+  (*variables)["capitalized_type"] = GetCapitalizedType(
+      descriptor, /* immutable = */ true, context->options());
   (*variables)["tag"] =
-      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
-  (*variables)["tag_size"] = StrCat(
+      absl::StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+  (*variables)["tag_size"] = absl::StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
 
   std::string capitalized_type = UnderscoresToCamelCase(
       PrimitiveTypeName(javaType), true /* cap_next_letter */);
+  std::string name = (*variables)["name"];
   switch (javaType) {
     case JAVATYPE_INT:
     case JAVATYPE_LONG:
     case JAVATYPE_FLOAT:
     case JAVATYPE_DOUBLE:
     case JAVATYPE_BOOLEAN:
-      (*variables)["field_list_type"] =
-          "com.google.protobuf.Internal." + capitalized_type + "List";
-      (*variables)["empty_list"] = "empty" + capitalized_type + "List()";
+      (*variables)["field_list_type"] = absl::StrCat(
+          "com.google.protobuf.Internal.", capitalized_type, "List");
+      (*variables)["empty_list"] =
+          absl::StrCat("empty", capitalized_type, "List()");
       (*variables)["make_name_unmodifiable"] =
-          (*variables)["name"] + "_.makeImmutable()";
+          absl::StrCat(name, "_.makeImmutable()");
       (*variables)["repeated_get"] =
-          (*variables)["name"] + "_.get" + capitalized_type;
+          absl::StrCat(name, "_.get", capitalized_type);
       (*variables)["repeated_add"] =
-          (*variables)["name"] + "_.add" + capitalized_type;
+          absl::StrCat(name, "_.add", capitalized_type);
       (*variables)["repeated_set"] =
-          (*variables)["name"] + "_.set" + capitalized_type;
+          absl::StrCat(name, "_.set", capitalized_type);
       (*variables)["visit_type"] = capitalized_type;
-      (*variables)["visit_type_list"] = "visit" + capitalized_type + "List";
+      (*variables)["visit_type_list"] =
+          absl::StrCat("visit", capitalized_type, "List");
       break;
     default:
-      (*variables)["field_list_type"] =
-          "com.google.protobuf.Internal.ProtobufList<" +
-          (*variables)["boxed_type"] + ">";
+      variables->insert(
+          {"field_list_type",
+           absl::StrCat("com.google.protobuf.Internal.ProtobufList<",
+                        (*variables)["boxed_type"], ">")});
       (*variables)["empty_list"] = "emptyProtobufList()";
       (*variables)["make_name_unmodifiable"] =
-          (*variables)["name"] + "_.makeImmutable()";
-      (*variables)["repeated_get"] = (*variables)["name"] + "_.get";
-      (*variables)["repeated_add"] = (*variables)["name"] + "_.add";
-      (*variables)["repeated_set"] = (*variables)["name"] + "_.set";
+          absl::StrCat(name, "_.makeImmutable()");
+      (*variables)["repeated_get"] = absl::StrCat(name, "_.get");
+      (*variables)["repeated_add"] = absl::StrCat(name, "_.add");
+      (*variables)["repeated_set"] = absl::StrCat(name, "_.set");
       (*variables)["visit_type"] = "ByteString";
       (*variables)["visit_type_list"] = "visitList";
   }
 
   if (javaType == JAVATYPE_BYTES) {
     (*variables)["bytes_default"] =
-        ToUpper((*variables)["name"]) + "_DEFAULT_VALUE";
+        absl::AsciiStrToUpper(name) + "_DEFAULT_VALUE";
   }
 
   if (IsReferenceType(javaType)) {
@@ -140,12 +144,12 @@
       descriptor->options().deprecated() ? "@java.lang.Deprecated " : "";
   (*variables)["kt_deprecation"] =
       descriptor->options().deprecated()
-          ? "@kotlin.Deprecated(message = \"Field " + (*variables)["name"] +
-                " is deprecated\") "
+          ? absl::StrCat("@kotlin.Deprecated(message = \"Field ", name,
+                         " is deprecated\") ")
           : "";
   int fixed_size = FixedSize(GetType(descriptor));
   if (fixed_size != -1) {
-    (*variables)["fixed_size"] = StrCat(fixed_size);
+    (*variables)["fixed_size"] = absl::StrCat(fixed_size);
   }
 
   if (HasHasbit(descriptor)) {
@@ -166,21 +170,20 @@
     switch (descriptor->type()) {
       case FieldDescriptor::TYPE_BYTES:
         (*variables)["is_field_present_message"] =
-            "!" + (*variables)["name"] + "_.isEmpty()";
+            absl::StrCat("!", name, "_.isEmpty()");
         break;
       case FieldDescriptor::TYPE_FLOAT:
         (*variables)["is_field_present_message"] =
-            "java.lang.Float.floatToRawIntBits(" + (*variables)["name"] +
-            "_) != 0";
+            absl::StrCat("java.lang.Float.floatToRawIntBits(", name, "_) != 0");
         break;
       case FieldDescriptor::TYPE_DOUBLE:
-        (*variables)["is_field_present_message"] =
-            "java.lang.Double.doubleToRawLongBits(" + (*variables)["name"] +
-            "_) != 0";
+        (*variables)["is_field_present_message"] = absl::StrCat(
+            "java.lang.Double.doubleToRawLongBits(", name, "_) != 0");
         break;
       default:
-        (*variables)["is_field_present_message"] =
-            (*variables)["name"] + "_ != " + (*variables)["default"];
+        variables->insert(
+            {"is_field_present_message",
+             absl::StrCat(name, "_ != " + (*variables)["default"])});
         break;
     }
   }
@@ -189,6 +192,9 @@
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
       GenerateSetBitToLocal(messageBitIndex);
+  // Annotations often use { and } variables to denote ranges.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 }  // namespace
@@ -199,10 +205,11 @@
     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
     : descriptor_(descriptor),
       messageBitIndex_(messageBitIndex),
+      context_(context),
       name_resolver_(context->GetNameResolver()) {
   SetPrimitiveVariables(descriptor, messageBitIndex, 0,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 ImmutablePrimitiveFieldLiteGenerator::~ImmutablePrimitiveFieldLiteGenerator() {}
@@ -219,7 +226,9 @@
                    "$deprecation$boolean has$capitalized_name$();\n");
   }
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
-  printer->Print(variables_, "$deprecation$$type$ get$capitalized_name$();\n");
+  printer->Print(variables_,
+                 "$deprecation$$type$ ${$get$capitalized_name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
@@ -231,6 +240,20 @@
         variables_,
         "private static final $field_type$ $bytes_default$ = $default$;\n");
   }
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        variables_,
+        "@com.google.protobuf.ProtoField(\n"
+        "  fieldNumber=$number$,\n"
+        "  type=com.google.protobuf.FieldType.$annotation_field_type$,\n"
+        "  isRequired=$required$)\n");
+    if (HasHazzer(descriptor_)) {
+      printer->Print(variables_,
+                     "@com.google.protobuf.ProtoPresenceCheckedField(\n"
+                     "  presenceBitsId=$bit_field_id$,\n"
+                     "  mask=$bit_field_mask$)\n");
+    }
+  }
   printer->Print(variables_, "private $field_type$ $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
   if (HasHazzer(descriptor_)) {
@@ -334,14 +357,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
   if (HasHazzer(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                                 /* builder */ false, /* kdoc */ true);
     printer->Print(
         variables_,
         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -492,7 +516,7 @@
       name_resolver_(context->GetNameResolver()) {
   SetPrimitiveVariables(descriptor, messageBitIndex, 0,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 RepeatedImmutablePrimitiveFieldLiteGenerator::
@@ -507,13 +531,17 @@
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
   printer->Print(variables_,
                  "$deprecation$java.util.List<$boxed_type$> "
-                 "get$capitalized_name$List();\n");
+                 "${$get$capitalized_name$List$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
   printer->Print(variables_,
-                 "$deprecation$int get$capitalized_name$Count();\n");
+                 "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
-  printer->Print(variables_,
-                 "$deprecation$$type$ get$capitalized_name$(int index);\n");
+  printer->Print(
+      variables_,
+      "$deprecation$$type$ ${$get$capitalized_name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutablePrimitiveFieldLiteGenerator::GenerateMembers(
@@ -685,7 +713,7 @@
                  "  )\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -696,7 +724,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -708,7 +736,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"addAll$kt_capitalized_name$\")\n"
@@ -719,7 +747,7 @@
                  "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -732,7 +760,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -744,7 +772,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
diff --git a/src/google/protobuf/compiler/java/primitive_field_lite.h b/src/google/protobuf/compiler/java/primitive_field_lite.h
index 2da0cd8..aa8ba76 100644
--- a/src/google/protobuf/compiler/java/primitive_field_lite.h
+++ b/src/google/protobuf/compiler/java/primitive_field_lite.h
@@ -36,10 +36,9 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_PRIMITIVE_FIELD_LITE_H__
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +61,10 @@
  public:
   explicit ImmutablePrimitiveFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  ImmutablePrimitiveFieldLiteGenerator(
+      const ImmutablePrimitiveFieldLiteGenerator&) = delete;
+  ImmutablePrimitiveFieldLiteGenerator& operator=(
+      const ImmutablePrimitiveFieldLiteGenerator&) = delete;
   ~ImmutablePrimitiveFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
@@ -79,12 +82,10 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   const int messageBitIndex_;
+  Context* context_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveFieldLiteGenerator);
 };
 
 class ImmutablePrimitiveOneofFieldLiteGenerator
@@ -93,6 +94,10 @@
   ImmutablePrimitiveOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
                                             int messageBitIndex,
                                             Context* context);
+  ImmutablePrimitiveOneofFieldLiteGenerator(
+      const ImmutablePrimitiveOneofFieldLiteGenerator&) = delete;
+  ImmutablePrimitiveOneofFieldLiteGenerator& operator=(
+      const ImmutablePrimitiveOneofFieldLiteGenerator&) = delete;
   ~ImmutablePrimitiveOneofFieldLiteGenerator() override;
 
   void GenerateMembers(io::Printer* printer) const override;
@@ -100,9 +105,6 @@
 
   void GenerateFieldInfo(io::Printer* printer,
                          std::vector<uint16_t>* output) const override;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutablePrimitiveOneofFieldLiteGenerator);
 };
 
 class RepeatedImmutablePrimitiveFieldLiteGenerator
@@ -110,6 +112,10 @@
  public:
   explicit RepeatedImmutablePrimitiveFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  RepeatedImmutablePrimitiveFieldLiteGenerator(
+      const RepeatedImmutablePrimitiveFieldLiteGenerator&) = delete;
+  RepeatedImmutablePrimitiveFieldLiteGenerator& operator=(
+      const RepeatedImmutablePrimitiveFieldLiteGenerator&) = delete;
   ~RepeatedImmutablePrimitiveFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
@@ -126,11 +132,9 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   Context* context_;
   ClassNameResolver* name_resolver_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutablePrimitiveFieldLiteGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/service.cc b/src/google/protobuf/compiler/java/service.cc
index 9e20620..ed77ae2 100644
--- a/src/google/protobuf/compiler/java/service.cc
+++ b/src/google/protobuf/compiler/java/service.cc
@@ -32,17 +32,17 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/service.h>
+#include "google/protobuf/compiler/java/service.h"
 
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
 
 // Must be last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -68,6 +68,10 @@
   WriteServiceDocComment(printer, descriptor_);
   MaybePrintGeneratedAnnotation(context_, printer, descriptor_,
                                 /* immutable = */ true);
+  if (!context_->options().opensource_runtime) {
+    printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
+  }
+
   printer->Print(
       "public $static$ abstract class $classname$\n"
       "    implements com.google.protobuf.Service {\n",
@@ -92,7 +96,7 @@
       "  return $file$.getDescriptor().getServices().get($index$);\n"
       "}\n",
       "file", name_resolver_->GetImmutableClassName(descriptor_->file()),
-      "index", StrCat(descriptor_->index()));
+      "index", absl::StrCat(descriptor_->index()));
   GenerateGetDescriptorForType(printer);
 
   // Generate more stuff.
@@ -211,8 +215,8 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    std::map<std::string, std::string> vars;
-    vars["index"] = StrCat(i);
+    absl::flat_hash_map<absl::string_view, std::string> vars;
+    vars["index"] = absl::StrCat(i);
     vars["method"] = UnderscoresToCamelCase(method);
     vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
     vars["output"] = GetOutput(method);
@@ -258,8 +262,8 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    std::map<std::string, std::string> vars;
-    vars["index"] = StrCat(i);
+    absl::flat_hash_map<absl::string_view, std::string> vars;
+    vars["index"] = absl::StrCat(i);
     vars["method"] = UnderscoresToCamelCase(method);
     vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
     vars["output"] = GetOutput(method);
@@ -303,8 +307,8 @@
 
   for (int i = 0; i < descriptor_->method_count(); i++) {
     const MethodDescriptor* method = descriptor_->method(i);
-    std::map<std::string, std::string> vars;
-    vars["index"] = StrCat(i);
+    absl::flat_hash_map<absl::string_view, std::string> vars;
+    vars["index"] = absl::StrCat(i);
     vars["type"] =
         (which == REQUEST)
             ? name_resolver_->GetImmutableClassName(method->input_type())
@@ -358,8 +362,8 @@
     printer->Print(" {\n");
     printer->Indent();
 
-    std::map<std::string, std::string> vars;
-    vars["index"] = StrCat(i);
+    absl::flat_hash_map<absl::string_view, std::string> vars;
+    vars["index"] = absl::StrCat(i);
     vars["output"] = GetOutput(method);
     printer->Print(vars,
                    "channel.callMethod(\n"
@@ -422,8 +426,8 @@
     printer->Print(" {\n");
     printer->Indent();
 
-    std::map<std::string, std::string> vars;
-    vars["index"] = StrCat(i);
+    absl::flat_hash_map<absl::string_view, std::string> vars;
+    vars["index"] = absl::StrCat(i);
     vars["output"] = GetOutput(method);
     printer->Print(vars,
                    "return ($output$) channel.callBlockingMethod(\n"
@@ -445,7 +449,7 @@
 void ImmutableServiceGenerator::GenerateMethodSignature(
     io::Printer* printer, const MethodDescriptor* method,
     IsAbstract is_abstract) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["name"] = UnderscoresToCamelCase(method);
   vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
   vars["output"] = GetOutput(method);
@@ -459,7 +463,7 @@
 
 void ImmutableServiceGenerator::GenerateBlockingMethodSignature(
     io::Printer* printer, const MethodDescriptor* method) {
-  std::map<std::string, std::string> vars;
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["method"] = UnderscoresToCamelCase(method);
   vars["input"] = name_resolver_->GetImmutableClassName(method->input_type());
   vars["output"] = GetOutput(method);
@@ -476,4 +480,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/java/service.h b/src/google/protobuf/compiler/java/service.h
index 9cb9021..98f9b23 100644
--- a/src/google/protobuf/compiler/java/service.h
+++ b/src/google/protobuf/compiler/java/service.h
@@ -35,8 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_SERVICE_H__
 
-#include <map>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 namespace google {
 namespace protobuf {
@@ -60,6 +59,8 @@
 class ServiceGenerator {
  public:
   explicit ServiceGenerator(const ServiceDescriptor* descriptor);
+  ServiceGenerator(const ServiceGenerator&) = delete;
+  ServiceGenerator& operator=(const ServiceGenerator&) = delete;
   virtual ~ServiceGenerator();
 
   virtual void Generate(io::Printer* printer) = 0;
@@ -69,15 +70,15 @@
 
  protected:
   const ServiceDescriptor* descriptor_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceGenerator);
 };
 
 class ImmutableServiceGenerator : public ServiceGenerator {
  public:
   ImmutableServiceGenerator(const ServiceDescriptor* descriptor,
                             Context* context);
+  ImmutableServiceGenerator(const ImmutableServiceGenerator&) = delete;
+  ImmutableServiceGenerator& operator=(const ImmutableServiceGenerator&) =
+      delete;
   ~ImmutableServiceGenerator() override;
 
   void Generate(io::Printer* printer) override;
@@ -128,7 +129,6 @@
 
   Context* context_;
   ClassNameResolver* name_resolver_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableServiceGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/shared_code_generator.cc b/src/google/protobuf/compiler/java/shared_code_generator.cc
index 39b96ee..cc3ea6b 100644
--- a/src/google/protobuf/compiler/java/shared_code_generator.cc
+++ b/src/google/protobuf/compiler/java/shared_code_generator.cc
@@ -30,19 +30,19 @@
 
 // Author: xiaofeng@google.com (Feng Xiao)
 
-#include <google/protobuf/compiler/java/shared_code_generator.h>
+#include "google/protobuf/compiler/java/shared_code_generator.h"
 
 #include <memory>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
-#include <google/protobuf/compiler/java/names.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/escaping.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/compiler/java/names.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"
 
 namespace google {
 namespace protobuf {
@@ -51,14 +51,16 @@
 
 SharedCodeGenerator::SharedCodeGenerator(const FileDescriptor* file,
                                          const Options& options)
-    : name_resolver_(new ClassNameResolver), file_(file), options_(options) {}
+    : name_resolver_(new ClassNameResolver(options)),
+      file_(file),
+      options_(options) {}
 
 SharedCodeGenerator::~SharedCodeGenerator() {}
 
 void SharedCodeGenerator::Generate(
     GeneratorContext* context, std::vector<std::string>* file_list,
     std::vector<std::string>* annotation_file_list) {
-  std::string java_package = FileJavaPackage(file_);
+  std::string java_package = FileJavaPackage(file_, true, options_);
   std::string package_dir = JavaPackageToDir(java_package);
 
   if (HasDescriptorMethods(file_, options_.enforce_lite)) {
@@ -87,7 +89,12 @@
           "package", java_package);
     }
     PrintGeneratedAnnotation(printer.get(), '$',
-                             options_.annotate_code ? info_relative_path : "");
+                             options_.annotate_code ? info_relative_path : "",
+                             options_);
+
+    if (!options_.opensource_runtime) {
+      printer->Print("@com.google.protobuf.Internal.ProtoNonnullApi\n");
+    }
     printer->Print(
         "public final class $classname$ {\n"
         "  public static com.google.protobuf.Descriptors.FileDescriptor\n"
@@ -152,7 +159,7 @@
       }
     }
     printer->Print("\"$data$\"", "data",
-                   CEscape(file_data.substr(i, kBytesPerLine)));
+                   absl::CEscape(file_data.substr(i, kBytesPerLine)));
   }
 
   printer->Outdent();
@@ -163,7 +170,7 @@
   std::vector<std::pair<std::string, std::string> > dependencies;
   for (int i = 0; i < file_->dependency_count(); i++) {
     std::string filename = file_->dependency(i)->name();
-    std::string package = FileJavaPackage(file_->dependency(i));
+    std::string package = FileJavaPackage(file_->dependency(i), true, options_);
     std::string classname =
         name_resolver_->GetDescriptorClassName(file_->dependency(i));
     std::string full_name;
@@ -180,13 +187,15 @@
   printer->Print(
       "descriptor = com.google.protobuf.Descriptors.FileDescriptor\n"
       "  .internalBuildGeneratedFileFrom(descriptorData,\n");
-  printer->Print(
-      "    new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
+  if (options_.opensource_runtime) {
+    printer->Print(
+        "    new com.google.protobuf.Descriptors.FileDescriptor[] {\n");
 
-  for (int i = 0; i < dependencies.size(); i++) {
-    const std::string& dependency = dependencies[i].second;
-    printer->Print("      $dependency$.getDescriptor(),\n", "dependency",
-                   dependency);
+    for (int i = 0; i < dependencies.size(); i++) {
+      const std::string& dependency = dependencies[i].second;
+      printer->Print("      $dependency$.getDescriptor(),\n", "dependency",
+                     dependency);
+    }
   }
 
   printer->Print("    });\n");
diff --git a/src/google/protobuf/compiler/java/shared_code_generator.h b/src/google/protobuf/compiler/java/shared_code_generator.h
index b1f6eb3..fdb4f0e 100644
--- a/src/google/protobuf/compiler/java/shared_code_generator.h
+++ b/src/google/protobuf/compiler/java/shared_code_generator.h
@@ -39,8 +39,8 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/java/options.h>
+#include "google/protobuf/compiler/java/options.h"
+#include "google/protobuf/port.h"
 
 namespace google {
 namespace protobuf {
@@ -67,6 +67,8 @@
 class SharedCodeGenerator {
  public:
   SharedCodeGenerator(const FileDescriptor* file, const Options& options);
+  SharedCodeGenerator(const SharedCodeGenerator&) = delete;
+  SharedCodeGenerator& operator=(const SharedCodeGenerator&) = delete;
   ~SharedCodeGenerator();
 
   void Generate(GeneratorContext* generator_context,
@@ -79,7 +81,6 @@
   std::unique_ptr<ClassNameResolver> name_resolver_;
   const FileDescriptor* file_;
   const Options options_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SharedCodeGenerator);
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/java/string_field.cc b/src/google/protobuf/compiler/java/string_field.cc
index 5f20792..c267219 100644
--- a/src/google/protobuf/compiler/java/string_field.cc
+++ b/src/google/protobuf/compiler/java/string_field.cc
@@ -36,18 +36,18 @@
 #include "google/protobuf/compiler/java/string_field.h"
 
 #include <cstdint>
-#include <map>
 #include <string>
 
 #include "google/protobuf/stubs/logging.h"
 #include "google/protobuf/stubs/common.h"
-#include "google/protobuf/io/printer.h"
-#include "google/protobuf/wire_format.h"
-#include "google/protobuf/stubs/strutil.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
 #include "google/protobuf/compiler/java/context.h"
 #include "google/protobuf/compiler/java/doc_comment.h"
 #include "google/protobuf/compiler/java/helpers.h"
 #include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -62,19 +62,21 @@
 void SetPrimitiveVariables(
     const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
     const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
-    std::map<std::string, std::string>* variables,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
     Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["empty_list"] = "com.google.protobuf.LazyStringArrayList.EMPTY";
 
-  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default"] =
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
   (*variables)["default_init"] =
-      "= " + ImmutableDefaultValue(descriptor, name_resolver);
+      "= " +
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
   (*variables)["capitalized_type"] = "String";
   (*variables)["tag"] =
-      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
-  (*variables)["tag_size"] = StrCat(
+      absl::StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+  (*variables)["tag_size"] = absl::StrCat(
       WireFormat::TagSize(descriptor->number(), GetType(descriptor)));
   (*variables)["null_check"] =
       "if (value == null) { throw new NullPointerException(); }";
@@ -94,7 +96,7 @@
   variables->insert(
       {"kt_deprecation",
        descriptor->options().deprecated()
-           ? StrCat("@kotlin.Deprecated(message = \"Field ",
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
                           (*variables)["name"], " is deprecated\") ")
            : ""});
   (*variables)["on_changed"] = "onChanged();";
@@ -116,7 +118,7 @@
     (*variables)["set_has_field_bit_message"] = "";
 
     variables->insert({"is_field_present_message",
-                       StrCat("!", (*variables)["isStringEmpty"], "(",
+                       absl::StrCat("!", (*variables)["isStringEmpty"], "(",
                                     (*variables)["name"], "_)")});
   }
 
@@ -381,7 +383,7 @@
 
 void ImmutableStringFieldGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public var $kt_name$: kotlin.String\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -392,14 +394,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
   if (HasHazzer(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                                 /* builder */ false, /* kdoc */ true);
     printer->Print(
         variables_,
         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -963,7 +966,8 @@
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
   // property for List<String>
-  WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public val $kt_name$: "
                  "com.google.protobuf.kotlin.DslList"
@@ -975,7 +979,7 @@
 
   // List<String>.add(String)
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -987,7 +991,7 @@
 
   // List<String> += String
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -1000,7 +1004,7 @@
 
   // List<String>.addAll(Iterable<String>)
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1013,7 +1017,7 @@
 
   // List<String> += Iterable<String>
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1027,7 +1031,7 @@
 
   // List<String>[Int] = String
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -1039,7 +1043,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
diff --git a/src/google/protobuf/compiler/java/string_field.h b/src/google/protobuf/compiler/java/string_field.h
index 814ebf2..96f53b9 100644
--- a/src/google/protobuf/compiler/java/string_field.h
+++ b/src/google/protobuf/compiler/java/string_field.h
@@ -36,7 +36,6 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_H__
 
-#include <map>
 #include <string>
 
 #include "google/protobuf/compiler/java/field.h"
@@ -95,7 +94,7 @@
   const FieldDescriptor* descriptor_;
   int message_bit_index_;
   int builder_bit_index_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   ClassNameResolver* name_resolver_;
 };
 
diff --git a/src/google/protobuf/compiler/java/string_field_lite.cc b/src/google/protobuf/compiler/java/string_field_lite.cc
index 49f6891..e2c6cb4 100644
--- a/src/google/protobuf/compiler/java/string_field_lite.cc
+++ b/src/google/protobuf/compiler/java/string_field_lite.cc
@@ -33,21 +33,20 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/java/string_field_lite.h>
+#include "google/protobuf/compiler/java/string_field_lite.h"
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/java/context.h>
-#include <google/protobuf/compiler/java/doc_comment.h>
-#include <google/protobuf/compiler/java/helpers.h>
-#include <google/protobuf/compiler/java/name_resolver.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/java/context.h"
+#include "google/protobuf/compiler/java/doc_comment.h"
+#include "google/protobuf/compiler/java/helpers.h"
+#include "google/protobuf/compiler/java/name_resolver.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -59,23 +58,25 @@
 
 namespace {
 
-void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           int messageBitIndex, int builderBitIndex,
-                           const FieldGeneratorInfo* info,
-                           ClassNameResolver* name_resolver,
-                           std::map<std::string, std::string>* variables) {
+void SetPrimitiveVariables(
+    const FieldDescriptor* descriptor, int messageBitIndex, int builderBitIndex,
+    const FieldGeneratorInfo* info, ClassNameResolver* name_resolver,
+    absl::flat_hash_map<absl::string_view, std::string>* variables,
+    Context* context) {
   SetCommonFieldVariables(descriptor, info, variables);
 
   (*variables)["empty_list"] =
       "com.google.protobuf.GeneratedMessageLite.emptyProtobufList()";
 
-  (*variables)["default"] = ImmutableDefaultValue(descriptor, name_resolver);
+  (*variables)["default"] =
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
   (*variables)["default_init"] =
-      "= " + ImmutableDefaultValue(descriptor, name_resolver);
+      "= " +
+      ImmutableDefaultValue(descriptor, name_resolver, context->options());
   (*variables)["capitalized_type"] = "java.lang.String";
   (*variables)["tag"] =
-      StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
-  (*variables)["tag_size"] = StrCat(
+      absl::StrCat(static_cast<int32_t>(WireFormat::MakeTag(descriptor)));
+  (*variables)["tag_size"] = absl::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.
@@ -86,14 +87,24 @@
   // 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->insert(
+      {"kt_deprecation",
+       descriptor->options().deprecated()
+           ? absl::StrCat("@kotlin.Deprecated(message = \"Field ",
+                          (*variables)["name"], " is deprecated\") ")
+           : ""});
   (*variables)["required"] = descriptor->is_required() ? "true" : "false";
+  if (!context->options().opensource_runtime) {
+    (*variables)["enforce_utf8"] = CheckUtf8(descriptor) ? "true" : "false";
+  }
 
   if (HasHasbit(descriptor)) {
+    if (!context->options().opensource_runtime) {
+      (*variables)["bit_field_id"] = absl::StrCat(messageBitIndex / 32);
+      (*variables)["bit_field_name"] = GetBitFieldNameForBit(messageBitIndex);
+      (*variables)["bit_field_mask"] =
+          absl::StrCat(1 << (messageBitIndex % 32));
+    }
     // For singular messages and builders, one bit is used for the hasField bit.
     (*variables)["get_has_field_bit_message"] = GenerateGetBit(messageBitIndex);
 
@@ -108,14 +119,17 @@
     (*variables)["set_has_field_bit_message"] = "";
     (*variables)["clear_has_field_bit_message"] = "";
 
-    (*variables)["is_field_present_message"] =
-        "!" + (*variables)["name"] + "_.isEmpty()";
+    variables->insert({"is_field_present_message",
+                       absl::StrCat("!", (*variables)["name"], "_.isEmpty()")});
   }
 
   (*variables)["get_has_field_bit_from_local"] =
       GenerateGetBitFromLocal(builderBitIndex);
   (*variables)["set_has_field_bit_to_local"] =
       GenerateSetBitToLocal(messageBitIndex);
+  // Annotations often use { and } variables to denote text ranges.
+  (*variables)["{"] = "";
+  (*variables)["}"] = "";
 }
 
 }  // namespace
@@ -126,10 +140,11 @@
     const FieldDescriptor* descriptor, int messageBitIndex, Context* context)
     : descriptor_(descriptor),
       messageBitIndex_(messageBitIndex),
-      name_resolver_(context->GetNameResolver()) {
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   SetPrimitiveVariables(descriptor, messageBitIndex, 0,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 ImmutableStringFieldLiteGenerator::~ImmutableStringFieldLiteGenerator() {}
@@ -168,19 +183,38 @@
   if (HasHazzer(descriptor_)) {
     WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
     printer->Print(variables_,
-                   "$deprecation$boolean has$capitalized_name$();\n");
+                   "$deprecation$boolean ${$has$capitalized_name$$}$();\n");
+    printer->Annotate("{", "}", descriptor_);
   }
   WriteFieldAccessorDocComment(printer, descriptor_, GETTER);
-  printer->Print(variables_,
-                 "$deprecation$java.lang.String get$capitalized_name$();\n");
+  printer->Print(
+      variables_,
+      "$deprecation$java.lang.String ${$get$capitalized_name$$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldStringBytesAccessorDocComment(printer, descriptor_, GETTER);
   printer->Print(variables_,
                  "$deprecation$com.google.protobuf.ByteString\n"
-                 "    get$capitalized_name$Bytes();\n");
+                 "    ${$get$capitalized_name$Bytes$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void ImmutableStringFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        variables_,
+        "@com.google.protobuf.ProtoField(\n"
+        "  fieldNumber=$number$,\n"
+        "  type=com.google.protobuf.FieldType.$annotation_field_type$,\n"
+        "  isRequired=$required$,\n"
+        "  isEnforceUtf8=$enforce_utf8$)\n");
+    if (HasHazzer(descriptor_)) {
+      printer->Print(variables_,
+                     "@com.google.protobuf.ProtoPresenceCheckedField(\n"
+                     "  presenceBitsId=$bit_field_id$,\n"
+                     "  mask=$bit_field_mask$)\n");
+    }
+  }
   printer->Print(variables_, "private java.lang.String $name$_;\n");
   PrintExtraFieldInfo(variables_, printer);
 
@@ -311,7 +345,7 @@
 
 void ImmutableStringFieldLiteGenerator::GenerateKotlinDslMembers(
     io::Printer* printer) const {
-  WriteFieldDocComment(printer, descriptor_);
+  WriteFieldDocComment(printer, descriptor_, /* kdoc */ true);
   printer->Print(variables_,
                  "$kt_deprecation$public var $kt_name$: kotlin.String\n"
                  "  @JvmName(\"${$get$kt_capitalized_name$$}$\")\n"
@@ -322,14 +356,15 @@
                  "  }\n");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "public fun ${$clear$kt_capitalized_name$$}$() {\n"
                  "  $kt_dsl_builder$.${$clear$capitalized_name$$}$()\n"
                  "}\n");
 
   if (HasHazzer(descriptor_)) {
-    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER);
+    WriteFieldAccessorDocComment(printer, descriptor_, HAZZER,
+                                 /* builder */ false, /* kdoc */ true);
     printer->Print(
         variables_,
         "public fun ${$has$kt_capitalized_name$$}$(): kotlin.Boolean {\n"
@@ -519,10 +554,12 @@
     RepeatedImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
                                               int messageBitIndex,
                                               Context* context)
-    : descriptor_(descriptor), name_resolver_(context->GetNameResolver()) {
+    : descriptor_(descriptor),
+      name_resolver_(context->GetNameResolver()),
+      context_(context) {
   SetPrimitiveVariables(descriptor, messageBitIndex, 0,
                         context->GetFieldGeneratorInfo(descriptor),
-                        name_resolver_, &variables_);
+                        name_resolver_, &variables_, context);
 }
 
 RepeatedImmutableStringFieldLiteGenerator::
@@ -537,22 +574,34 @@
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
   printer->Print(variables_,
                  "$deprecation$java.util.List<java.lang.String>\n"
-                 "    get$capitalized_name$List();\n");
+                 "    ${$get$capitalized_name$List$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_COUNT);
   printer->Print(variables_,
-                 "$deprecation$int get$capitalized_name$Count();\n");
+                 "$deprecation$int ${$get$capitalized_name$Count$}$();\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
-  printer->Print(
-      variables_,
-      "$deprecation$java.lang.String get$capitalized_name$(int index);\n");
+  printer->Print(variables_,
+                 "$deprecation$java.lang.String "
+                 "${$get$capitalized_name$$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_GETTER);
   printer->Print(variables_,
                  "$deprecation$com.google.protobuf.ByteString\n"
-                 "    get$capitalized_name$Bytes(int index);\n");
+                 "    ${$get$capitalized_name$Bytes$}$(int index);\n");
+  printer->Annotate("{", "}", descriptor_);
 }
 
 void RepeatedImmutableStringFieldLiteGenerator::GenerateMembers(
     io::Printer* printer) const {
+  if (!context_->options().opensource_runtime) {
+    printer->Print(
+        variables_,
+        "@com.google.protobuf.ProtoField(\n"
+        "  fieldNumber=$number$,\n"
+        "  type=com.google.protobuf.FieldType.$annotation_field_type$,\n"
+        "  isEnforceUtf8=$enforce_utf8$)\n");
+  }
   printer->Print(
       variables_,
       "private com.google.protobuf.Internal.ProtobufList<java.lang.String> "
@@ -752,7 +801,8 @@
       " : com.google.protobuf.kotlin.DslProxy()\n");
 
   // property for List<String>
-  WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER);
+  WriteFieldAccessorDocComment(printer, descriptor_, LIST_GETTER,
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "$kt_deprecation$public val $kt_name$: "
@@ -766,7 +816,7 @@
 
   // List<String>.add(String)
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"add$kt_capitalized_name$\")\n"
@@ -778,7 +828,7 @@
 
   // List<String> += String
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"plusAssign$kt_capitalized_name$\")\n"
@@ -791,7 +841,7 @@
 
   // List<String>.addAll(Iterable<String>)
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -804,7 +854,7 @@
 
   // List<String> += Iterable<String>
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_MULTI_ADDER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -818,7 +868,7 @@
 
   // List<String>[Int] = String
   WriteFieldAccessorDocComment(printer, descriptor_, LIST_INDEXED_SETTER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(
       variables_,
       "@kotlin.jvm.JvmSynthetic\n"
@@ -830,7 +880,7 @@
       "}");
 
   WriteFieldAccessorDocComment(printer, descriptor_, CLEARER,
-                               /* builder */ false);
+                               /* builder */ false, /* kdoc */ true);
   printer->Print(variables_,
                  "@kotlin.jvm.JvmSynthetic\n"
                  "@kotlin.jvm.JvmName(\"clear$kt_capitalized_name$\")\n"
diff --git a/src/google/protobuf/compiler/java/string_field_lite.h b/src/google/protobuf/compiler/java/string_field_lite.h
index b6ad1ea..6fa9636 100644
--- a/src/google/protobuf/compiler/java/string_field_lite.h
+++ b/src/google/protobuf/compiler/java/string_field_lite.h
@@ -37,10 +37,9 @@
 #define GOOGLE_PROTOBUF_COMPILER_JAVA_STRING_FIELD_LITE_H__
 
 #include <cstdint>
-#include <map>
 #include <string>
 
-#include <google/protobuf/compiler/java/field.h>
+#include "google/protobuf/compiler/java/field.h"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +62,10 @@
   explicit ImmutableStringFieldLiteGenerator(const FieldDescriptor* descriptor,
                                              int messageBitIndex,
                                              Context* context);
+  ImmutableStringFieldLiteGenerator(const ImmutableStringFieldLiteGenerator&) =
+      delete;
+  ImmutableStringFieldLiteGenerator& operator=(
+      const ImmutableStringFieldLiteGenerator&) = delete;
   ~ImmutableStringFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator
@@ -80,12 +83,10 @@
 
  protected:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   const int messageBitIndex_;
   ClassNameResolver* name_resolver_;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringFieldLiteGenerator);
+  Context* context_;
 };
 
 class ImmutableStringOneofFieldLiteGenerator
@@ -93,6 +94,10 @@
  public:
   ImmutableStringOneofFieldLiteGenerator(const FieldDescriptor* descriptor,
                                          int messageBitIndex, Context* context);
+  ImmutableStringOneofFieldLiteGenerator(
+      const ImmutableStringOneofFieldLiteGenerator&) = delete;
+  ImmutableStringOneofFieldLiteGenerator& operator=(
+      const ImmutableStringOneofFieldLiteGenerator&) = delete;
   ~ImmutableStringOneofFieldLiteGenerator() override;
 
  private:
@@ -100,8 +105,6 @@
   void GenerateBuilderMembers(io::Printer* printer) const override;
   void GenerateFieldInfo(io::Printer* printer,
                          std::vector<uint16_t>* output) const override;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImmutableStringOneofFieldLiteGenerator);
 };
 
 class RepeatedImmutableStringFieldLiteGenerator
@@ -109,6 +112,10 @@
  public:
   explicit RepeatedImmutableStringFieldLiteGenerator(
       const FieldDescriptor* descriptor, int messageBitIndex, Context* context);
+  RepeatedImmutableStringFieldLiteGenerator(
+      const RepeatedImmutableStringFieldLiteGenerator&) = delete;
+  RepeatedImmutableStringFieldLiteGenerator& operator=(
+      const RepeatedImmutableStringFieldLiteGenerator&) = delete;
   ~RepeatedImmutableStringFieldLiteGenerator() override;
 
   // implements ImmutableFieldLiteGenerator ------------------------------------
@@ -125,10 +132,9 @@
 
  private:
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
   ClassNameResolver* name_resolver_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RepeatedImmutableStringFieldLiteGenerator);
+  Context* context_;
 };
 
 }  // namespace java
diff --git a/src/google/protobuf/compiler/main.cc b/src/google/protobuf/compiler/main.cc
index 3960946..dfce4fb 100644
--- a/src/google/protobuf/compiler/main.cc
+++ b/src/google/protobuf/compiler/main.cc
@@ -28,19 +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/cpp/generator.h>
-#include <google/protobuf/compiler/java/generator.h>
-#include <google/protobuf/compiler/java/kotlin_generator.h>
-#include <google/protobuf/compiler/command_line_interface.h>
-#include <google/protobuf/compiler/csharp/csharp_generator.h>
-#include <google/protobuf/compiler/objectivec/objectivec_generator.h>
-#include <google/protobuf/compiler/php/php_generator.h>
-#include <google/protobuf/compiler/python/generator.h>
-#include <google/protobuf/compiler/python/pyi_generator.h>
-#include <google/protobuf/compiler/ruby/ruby_generator.h>
+#include "google/protobuf/compiler/command_line_interface.h"
+#include "google/protobuf/compiler/cpp/generator.h"
+#include "google/protobuf/compiler/csharp/csharp_generator.h"
+#include "google/protobuf/compiler/java/generator.h"
+#include "google/protobuf/compiler/java/kotlin_generator.h"
+#include "google/protobuf/compiler/objectivec/generator.h"
+#include "google/protobuf/compiler/php/php_generator.h"
+#include "google/protobuf/compiler/python/generator.h"
+#include "google/protobuf/compiler/python/pyi_generator.h"
+#include "google/protobuf/compiler/ruby/ruby_generator.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -66,6 +66,10 @@
   cli.RegisterGenerator("--java_out", "--java_opt", &java_generator,
                         "Generate Java source file.");
 
+#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
+  java_generator.set_opensource_runtime(true);
+#endif
+
   // Proto2 Kotlin
   java::KotlinGenerator kt_generator;
   cli.RegisterGenerator("--kotlin_out", "--kotlin_opt", &kt_generator,
@@ -76,6 +80,11 @@
   python::Generator py_generator;
   cli.RegisterGenerator("--python_out", "--python_opt", &py_generator,
                         "Generate Python source file.");
+
+#ifdef GOOGLE_PROTOBUF_RUNTIME_INCLUDE_BASE
+  py_generator.set_opensource_runtime(true);
+#endif
+
   // Python pyi
   python::PyiGenerator pyi_generator;
   cli.RegisterGenerator("--pyi_out", &pyi_generator,
diff --git a/src/google/protobuf/compiler/mock_code_generator.cc b/src/google/protobuf/compiler/mock_code_generator.cc
index 4d04511..a4cc9e6 100644
--- a/src/google/protobuf/compiler/mock_code_generator.cc
+++ b/src/google/protobuf/compiler/mock_code_generator.cc
@@ -30,7 +30,7 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <google/protobuf/compiler/mock_code_generator.h>
+#include "google/protobuf/compiler/mock_code_generator.h"
 
 #include <stdlib.h>
 
@@ -39,21 +39,23 @@
 #include <memory>
 #include <vector>
 
-#include <google/protobuf/stubs/strutil.h>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/compiler/plugin.pb.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/compiler/plugin.pb.h"
+#include "google/protobuf/descriptor.pb.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/text_format.h>
+#include "absl/strings/str_join.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/text_format.h"
 
 #ifdef major
 #undef major
@@ -74,7 +76,7 @@
   for (size_t i = 0; i < all_files.size(); i++) {
     names.push_back(all_files[i]->name());
   }
-  return Join(names, ",");
+  return absl::StrJoin(names, ",");
 }
 
 static const char* kFirstInsertionPointName = "first_mock_insertion_point";
@@ -109,7 +111,7 @@
                         &content, true));
 
   std::vector<std::string> lines =
-      Split(content, "\n", true);
+      absl::StrSplit(content, "\n", absl::SkipEmpty());
 
   while (!lines.empty() && lines.back().empty()) {
     lines.pop_back();
@@ -120,7 +122,7 @@
 
   std::vector<std::string> insertion_list;
   if (!insertions.empty()) {
-    insertion_list = Split(insertions, ",", true);
+    insertion_list = absl::StrSplit(insertions, ",", absl::SkipEmpty());
   }
 
   EXPECT_EQ(lines.size(), 3 + insertion_list.size() * 2);
@@ -205,8 +207,8 @@
                                  std::string* error) const {
   bool annotate = false;
   for (int i = 0; i < file->message_type_count(); i++) {
-    if (HasPrefixString(file->message_type(i)->name(), "MockCodeGenerator_")) {
-      std::string command = StripPrefixString(
+    if (absl::StartsWith(file->message_type(i)->name(), "MockCodeGenerator_")) {
+      absl::string_view command = absl::StripPrefix(
           file->message_type(i)->name(), "MockCodeGenerator_");
       if (command == "Error") {
         *error = "Saw message type MockCodeGenerator_Error.";
@@ -249,12 +251,12 @@
     }
   }
 
-  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);
+  bool insert_endlines = absl::StartsWith(parameter, "insert_endlines=");
+  if (insert_endlines || absl::StartsWith(parameter, "insert=")) {
+    std::vector<std::string> insert_into = absl::StrSplit(
+        absl::StripPrefix(parameter,
+                          insert_endlines ? "insert_endlines=" : "insert="),
+        ',', absl::SkipEmpty());
 
     for (size_t i = 0; i < insert_into.size(); i++) {
       {
@@ -262,7 +264,7 @@
         std::string content =
             GetOutputFileContent(name_, "first_insert", file, context);
         if (insert_endlines) {
-          GlobalReplaceSubstring(",", ",\n", &content);
+          absl::StrReplaceAll({{",", ",\n"}}, &content);
         }
         if (annotate) {
           auto* annotation = info.add_annotation();
@@ -287,7 +289,7 @@
         std::string content =
             GetOutputFileContent(name_, "second_insert", file, context);
         if (insert_endlines) {
-          GlobalReplaceSubstring(",", ",\n", &content);
+          absl::StrReplaceAll({{",", ",\n"}}, &content);
         }
         if (annotate) {
           auto* annotation = info.add_annotation();
@@ -375,7 +377,7 @@
     const std::string& generator_name, const std::string& parameter,
     const std::string& file, const std::string& parsed_file_list,
     const std::string& first_message_name) {
-  return strings::Substitute("$0: $1, $2, $3, $4\n", generator_name, parameter,
+  return absl::Substitute("$0: $1, $2, $3, $4\n", generator_name, parameter,
                           file, first_message_name, parsed_file_list);
 }
 
diff --git a/src/google/protobuf/compiler/mock_code_generator.h b/src/google/protobuf/compiler/mock_code_generator.h
index 45d735a..f91b7bc 100644
--- a/src/google/protobuf/compiler/mock_code_generator.h
+++ b/src/google/protobuf/compiler/mock_code_generator.h
@@ -36,7 +36,7 @@
 #include <cstdint>
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
+#include "google/protobuf/compiler/code_generator.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/objectivec/BUILD.bazel b/src/google/protobuf/compiler/objectivec/BUILD.bazel
new file mode 100644
index 0000000..e0de9eb
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/BUILD.bazel
@@ -0,0 +1,154 @@
+################################################################################
+# Protocol Buffers Compiler - ObjC code generator
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "names",
+    hdrs = ["names.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/objectivec",
+    visibility = ["//visibility:public"],
+    deps = [
+        ":names_internal",
+    ],
+)
+
+cc_library(
+    name = "names_internal",
+    srcs = [
+        "names.cc",
+    ],
+    hdrs = [
+        "names.h",
+        "nsobject_methods.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/objectivec",
+    visibility = ["//pkg:__pkg__"],
+    deps = [
+        ":line_consumer",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/container:flat_hash_set",
+    ],
+)
+
+cc_library(
+    name = "line_consumer",
+    srcs = ["line_consumer.cc"],
+    hdrs = ["line_consumer.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/objectivec",
+    visibility = ["//pkg:__pkg__"],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+    ],
+)
+
+cc_library(
+    name = "objectivec",
+    srcs = [
+        "enum.cc",
+        "enum_field.cc",
+        "extension.cc",
+        "field.cc",
+        "file.cc",
+        "generator.cc",
+        "helpers.cc",
+        "import_writer.cc",
+        "map_field.cc",
+        "message.cc",
+        "message_field.cc",
+        "oneof.cc",
+        "primitive_field.cc",
+        "text_format_decode_data.cc",
+    ],
+    hdrs = [
+        "enum.h",
+        "enum_field.h",
+        "extension.h",
+        "field.h",
+        "file.h",
+        "generator.h",
+        "helpers.h",
+        "import_writer.h",
+        "map_field.h",
+        "message.h",
+        "message_field.h",
+        "oneof.h",
+        "options.h",
+        "primitive_field.h",
+        "text_format_decode_data.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/objectivec",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+    ],
+    deps = [
+        ":line_consumer",
+        ":names",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/container:btree",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "line_consumer_unittest",
+    srcs = ["line_consumer_unittest.cc"],
+    deps = [
+        ":line_consumer",
+        "//src/google/protobuf/io",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "names_unittest",
+    srcs = ["names_unittest.cc"],
+    deps = [
+        ":names",
+        "//src/google/protobuf/io",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "text_format_decode_data_unittest",
+    srcs = ["text_format_decode_data_unittest.cc"],
+    deps = [
+        ":objectivec",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc b/src/google/protobuf/compiler/objectivec/enum.cc
similarity index 68%
rename from src/google/protobuf/compiler/objectivec/objectivec_enum.cc
rename to src/google/protobuf/compiler/objectivec/enum.cc
index ea8f394..6f9fbda 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.cc
+++ b/src/google/protobuf/compiler/objectivec/enum.cc
@@ -28,23 +28,38 @@
 // (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 <map>
+#include "google/protobuf/compiler/objectivec/enum.h"
+
+#include <algorithm>
+#include <limits>
 #include <string>
 
-#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <algorithm> // std::find()
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace objectivec {
+namespace {
+std::string SafelyPrintIntToCode(int v) {
+  if (v == std::numeric_limits<int>::min()) {
+    // Some compilers try to parse -2147483648 as two tokens and then get spicy
+    // about the fact that +2147483648 cannot be represented as an int.
+    return absl::StrCat(v + 1, " - 1");
+  } else {
+    return absl::StrCat(v);
+  }
+}
+}  // namespace
 
 EnumGenerator::EnumGenerator(const EnumDescriptor* descriptor)
-    : descriptor_(descriptor),
-      name_(EnumName(descriptor_)) {
+    : descriptor_(descriptor), name_(EnumName(descriptor_)) {
   // Track the names for the enum values, and if an alias overlaps a base
   // value, skip making a name for it. Likewise if two alias overlap, the
   // first one wins.
@@ -54,7 +69,7 @@
   // compile error is just fine.
   // The values are still tracked to support the reflection apis and
   // TextFormat handing since they are different there.
-  std::set<std::string> value_names;
+  absl::flat_hash_set<std::string> value_names;
 
   for (int i = 0; i < descriptor_->value_count(); i++) {
     const EnumValueDescriptor* value = descriptor_->value(i);
@@ -65,20 +80,15 @@
       base_values_.push_back(value);
       value_names.insert(EnumValueName(value));
     } else {
-      std::string value_name(EnumValueName(value));
-      if (value_names.find(value_name) != value_names.end()) {
+      if (!value_names.insert(EnumValueName(value)).second) {
         alias_values_to_skip_.insert(value);
-      } else {
-        value_names.insert(value_name);
       }
     }
     all_values_.push_back(value);
   }
 }
 
-EnumGenerator::~EnumGenerator() {}
-
-void EnumGenerator::GenerateHeader(io::Printer* printer) {
+void EnumGenerator::GenerateHeader(io::Printer* printer) const {
   std::string enum_comments;
   SourceLocation location;
   if (descriptor_->GetSourceLocation(&location)) {
@@ -106,45 +116,49 @@
   // doesn't have to bother with the `enum_extensibility` attribute, as the
   // default will be what is needed.
 
-  printer->Print("$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
-                 "comments", enum_comments,
-                 "deprecated_attribute", GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()),
-                 "name", name_);
+  printer->Print(
+      "$comments$typedef$deprecated_attribute$ GPB_ENUM($name$) {\n",
+      "comments", enum_comments, "deprecated_attribute",
+      GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file()), "name",
+      name_);
   printer->Indent();
 
-  if (HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+  if (!descriptor_->is_closed()) {
     // Include the unknown value.
     printer->Print(
-      "/**\n"
-      " * Value used if any message's field encounters a value that is not defined\n"
-      " * by this enum. The message will also have C functions to get/set the rawValue\n"
-      " * of the field.\n"
-      " **/\n"
-      "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
-      "name", name_);
+        // clang-format off
+        "/**\n"
+        " * Value used if any message's field encounters a value that is not defined\n"
+        " * by this enum. The message will also have C functions to get/set the rawValue\n"
+        " * of the field.\n"
+        " **/\n"
+        "$name$_GPBUnrecognizedEnumeratorValue = kGPBUnrecognizedEnumeratorValue,\n",
+        // clang-format on
+        "name", name_);
   }
   for (int i = 0; i < all_values_.size(); i++) {
-    if (alias_values_to_skip_.find(all_values_[i]) != alias_values_to_skip_.end()) {
+    if (alias_values_to_skip_.find(all_values_[i]) !=
+        alias_values_to_skip_.end()) {
       continue;
     }
     if (all_values_[i]->GetSourceLocation(&location)) {
-      std::string comments = BuildCommentsString(location, true).c_str();
+      std::string comments = BuildCommentsString(location, true);
       if (comments.length() > 0) {
         if (i > 0) {
           printer->Print("\n");
         }
-        printer->Print(comments.c_str());
+        printer->Print(comments);
       }
     }
 
-    printer->Print(
-        "$name$$deprecated_attribute$ = $value$,\n",
-        "name", EnumValueName(all_values_[i]),
-        "deprecated_attribute", GetOptionalDeprecatedAttribute(all_values_[i]),
-        "value", StrCat(all_values_[i]->number()));
+    printer->Print("$name$$deprecated_attribute$ = $value$,\n", "name",
+                   EnumValueName(all_values_[i]), "deprecated_attribute",
+                   GetOptionalDeprecatedAttribute(all_values_[i]), "value",
+                   SafelyPrintIntToCode(all_values_[i]->number()));
   }
   printer->Outdent();
   printer->Print(
+      // clang-format off
       "};\n"
       "\n"
       "GPBEnumDescriptor *$name$_EnumDescriptor(void);\n"
@@ -154,11 +168,12 @@
       " * the time this source was generated.\n"
       " **/\n"
       "BOOL $name$_IsValidValue(int32_t value);\n"
+      // clang-format on
       "\n",
       "name", name_);
 }
 
-void EnumGenerator::GenerateSource(io::Printer* printer) {
+void EnumGenerator::GenerateSource(io::Printer* printer) const {
   printer->Print(
       "#pragma mark - Enum $name$\n"
       "\n",
@@ -184,38 +199,46 @@
   }
 
   printer->Print(
+      // clang-format off
       "GPBEnumDescriptor *$name$_EnumDescriptor(void) {\n"
       "  static _Atomic(GPBEnumDescriptor*) descriptor = nil;\n"
       "  if (!descriptor) {\n",
+      // clang-format on
       "name", name_);
 
   static const int kBytesPerLine = 40;  // allow for escaping
-  printer->Print(
-      "    static const char *valueNames =");
+  printer->Print("    static const char *valueNames =");
   for (int i = 0; i < text_blob.size(); i += kBytesPerLine) {
     printer->Print(
-        "\n        \"$data$\"",
-        "data", EscapeTrigraphs(CEscape(text_blob.substr(i, kBytesPerLine))));
+        "\n        \"$data$\"", "data",
+        EscapeTrigraphs(absl::CEscape(text_blob.substr(i, kBytesPerLine))));
   }
   printer->Print(
       ";\n"
       "    static const int32_t values[] = {\n");
   for (int i = 0; i < all_values_.size(); i++) {
-    printer->Print("        $name$,\n",  "name", EnumValueName(all_values_[i]));
+    printer->Print("        $name$,\n", "name", EnumValueName(all_values_[i]));
   }
   printer->Print("    };\n");
 
   if (text_format_decode_data.num_entries() == 0) {
     printer->Print(
+        // clang-format off
         "    GPBEnumDescriptor *worker =\n"
         "        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
         "                                       valueNames:valueNames\n"
         "                                           values:values\n"
         "                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
-        "                                     enumVerifier:$name$_IsValidValue];\n",
-        "name", name_);
-    } else {
-      printer->Print(
+        "                                     enumVerifier:$name$_IsValidValue\n"
+        "                                            flags:$flags$];\n",
+        // clang-format on
+        "name", name_, "flags",
+        (descriptor_->is_closed()
+             ? "GPBEnumDescriptorInitializationFlag_IsClosed"
+             : "GPBEnumDescriptorInitializationFlag_None"));
+  } else {
+    printer->Print(
+        // clang-format off
         "    static const char *extraTextFormatInfo = \"$extraTextFormatInfo$\";\n"
         "    GPBEnumDescriptor *worker =\n"
         "        [GPBEnumDescriptor allocDescriptorForName:GPBNSStringifySymbol($name$)\n"
@@ -223,36 +246,46 @@
         "                                           values:values\n"
         "                                            count:(uint32_t)(sizeof(values) / sizeof(int32_t))\n"
         "                                     enumVerifier:$name$_IsValidValue\n"
+        "                                            flags:$flags$\n"
         "                              extraTextFormatInfo:extraTextFormatInfo];\n",
-        "name", name_,
-        "extraTextFormatInfo", CEscape(text_format_decode_data.Data()));
-    }
-    printer->Print(
-      "    GPBEnumDescriptor *expected = nil;\n"
-      "    if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n"
-      "      [worker release];\n"
-      "    }\n"
-      "  }\n"
-      "  return descriptor;\n"
-      "}\n\n");
+        // clang-format on
+        "name", name_, "flags",
+        (descriptor_->is_closed()
+             ? "GPBEnumDescriptorInitializationFlag_IsClosed"
+             : "GPBEnumDescriptorInitializationFlag_None"),
+        "extraTextFormatInfo", absl::CEscape(text_format_decode_data.Data()));
+  }
+  // clang-format off
+  printer->Print(
+    "    GPBEnumDescriptor *expected = nil;\n"
+    "    if (!atomic_compare_exchange_strong(&descriptor, &expected, worker)) {\n"
+    "      [worker release];\n"
+    "    }\n"
+    "  }\n"
+    "  return descriptor;\n"
+    "}\n\n");
+  // clang-format on
 
   printer->Print(
+      // clang-format off
       "BOOL $name$_IsValidValue(int32_t value__) {\n"
       "  switch (value__) {\n",
+      // clang-format on
       "name", name_);
 
   for (int i = 0; i < base_values_.size(); i++) {
-    printer->Print(
-        "    case $name$:\n",
-        "name", EnumValueName(base_values_[i]));
+    printer->Print("    case $name$:\n", "name",
+                   EnumValueName(base_values_[i]));
   }
 
+  // clang-format off
   printer->Print(
       "      return YES;\n"
       "    default:\n"
       "      return NO;\n"
       "  }\n"
       "}\n\n");
+  // clang-format on
 }
 }  // namespace objectivec
 }  // namespace compiler
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum.h b/src/google/protobuf/compiler/objectivec/enum.h
similarity index 88%
rename from src/google/protobuf/compiler/objectivec/objectivec_enum.h
rename to src/google/protobuf/compiler/objectivec/enum.h
index 1d5741a..61338c8 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum.h
+++ b/src/google/protobuf/compiler/objectivec/enum.h
@@ -32,10 +32,11 @@
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_H__
 
 #include <string>
-#include <set>
 #include <vector>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+
+#include "absl/container/flat_hash_set.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -45,13 +46,13 @@
 class EnumGenerator {
  public:
   explicit EnumGenerator(const EnumDescriptor* descriptor);
-  ~EnumGenerator();
+  ~EnumGenerator() = default;
 
   EnumGenerator(const EnumGenerator&) = delete;
   EnumGenerator& operator=(const EnumGenerator&) = delete;
 
-  void GenerateHeader(io::Printer* printer);
-  void GenerateSource(io::Printer* printer);
+  void GenerateHeader(io::Printer* printer) const;
+  void GenerateSource(io::Printer* printer) const;
 
   const std::string& name() const { return name_; }
 
@@ -59,7 +60,7 @@
   const EnumDescriptor* descriptor_;
   std::vector<const EnumValueDescriptor*> base_values_;
   std::vector<const EnumValueDescriptor*> all_values_;
-  std::set<const EnumValueDescriptor*> alias_values_to_skip_;
+  absl::flat_hash_set<const EnumValueDescriptor*> alias_values_to_skip_;
   const std::string name_;
 };
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc b/src/google/protobuf/compiler/objectivec/enum_field.cc
similarity index 76%
rename from src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
rename to src/google/protobuf/compiler/objectivec/enum_field.cc
index 6e0d69b..7e425c7 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.cc
+++ b/src/google/protobuf/compiler/objectivec/enum_field.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.
 
-#include <map>
+#include "google/protobuf/compiler/objectivec/enum_field.h"
+
 #include <string>
 
-#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/printer.h>
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -42,22 +44,24 @@
 
 namespace {
 
-void SetEnumVariables(const FieldDescriptor* descriptor,
-                      std::map<std::string, std::string>* variables) {
-  std::string type = EnumName(descriptor->enum_type());
+void SetEnumVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
+  const std::string type = EnumName(descriptor->enum_type());
+  const std::string enum_desc_func = absl::StrCat(type, "_EnumDescriptor");
   (*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
   // the forward declaration of the enums.
   if (!descriptor->is_repeated() &&
       (descriptor->file() != descriptor->enum_type()->file())) {
-    (*variables)["property_type"] = "enum " + type;
+    (*variables)["property_type"] = absl::StrCat("enum ", type);
   }
-  (*variables)["enum_verifier"] = type + "_IsValidValue";
-  (*variables)["enum_desc_func"] = type + "_EnumDescriptor";
+  (*variables)["enum_verifier"] = absl::StrCat(type, "_IsValidValue");
+  (*variables)["enum_desc_func"] = enum_desc_func;
 
   (*variables)["dataTypeSpecific_name"] = "enumDescFunc";
-  (*variables)["dataTypeSpecific_value"] = (*variables)["enum_desc_func"];
+  (*variables)["dataTypeSpecific_value"] = enum_desc_func;
 
   const Descriptor* msg_descriptor = descriptor->containing_type();
   (*variables)["owning_message_class"] = ClassName(msg_descriptor);
@@ -69,14 +73,13 @@
   SetEnumVariables(descriptor, &variables_);
 }
 
-EnumFieldGenerator::~EnumFieldGenerator() {}
-
 void EnumFieldGenerator::GenerateCFunctionDeclarations(
     io::Printer* printer) const {
-  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) {
+  if (descriptor_->enum_type()->is_closed()) {
     return;
   }
 
+  // clang-format off
   printer->Print(
       variables_,
       "/**\n"
@@ -91,12 +94,16 @@
       " **/\n"
       "void Set$owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message, int32_t value);\n"
       "\n");
+  // clang-format on
 }
 
 void EnumFieldGenerator::GenerateCFunctionImplementations(
     io::Printer* printer) const {
-  if (!HasPreservingUnknownEnumSemantics(descriptor_->file())) return;
+  if (descriptor_->enum_type()->is_closed()) {
+    return;
+  }
 
+  // clang-format off
   printer->Print(
       variables_,
       "int32_t $owning_message_class$_$capitalized_name$_RawValue($owning_message_class$ *message) {\n"
@@ -111,13 +118,14 @@
       "  GPBSetMessageRawEnumField(message, field, value);\n"
       "}\n"
       "\n");
+  // clang-format on
 }
 
 void EnumFieldGenerator::DetermineForwardDeclarations(
-    std::set<std::string>* fwd_decls,
+    absl::btree_set<std::string>* fwd_decls,
     bool include_external_types) const {
-  SingleFieldGenerator::DetermineForwardDeclarations(
-      fwd_decls, include_external_types);
+  SingleFieldGenerator::DetermineForwardDeclarations(fwd_decls,
+                                                     include_external_types);
   // If it is an enum defined in a different file (and not a WKT), 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.
@@ -126,7 +134,7 @@
       !IsProtobufLibraryBundledProtoFile(descriptor_->enum_type()->file())) {
     // Enum name is already in "storage_type".
     const std::string& name = variable("storage_type");
-    fwd_decls->insert("GPB_ENUM_FWD_DECLARE(" + name + ")");
+    fwd_decls->insert(absl::StrCat("GPB_ENUM_FWD_DECLARE(", name, ");"));
   }
 }
 
@@ -137,14 +145,16 @@
   variables_["array_storage_type"] = "GPBEnumArray";
 }
 
-RepeatedEnumFieldGenerator::~RepeatedEnumFieldGenerator() {}
-
-void RepeatedEnumFieldGenerator::FinishInitialization(void) {
+void RepeatedEnumFieldGenerator::FinishInitialization() {
   RepeatedFieldGenerator::FinishInitialization();
-  variables_["array_comment"] =
-      "// |" + variables_["name"] + "| contains |" + variables_["storage_type"] + "|\n";
+  variables_["array_comment"] = "// |" + variables_["name"] + "| contains |" +
+                                variables_["storage_type"] + "|\n";
 }
 
+// NOTE: RepeatedEnumFieldGenerator::DetermineForwardDeclarations isn't needed
+// because `GPBEnumArray` isn't generic (like `NSArray` would be for messages)
+// and thus doesn't reference the type in the header.
+
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h b/src/google/protobuf/compiler/objectivec/enum_field.h
similarity index 82%
rename from src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
rename to src/google/protobuf/compiler/objectivec/enum_field.h
index f0d685c..96dd280 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_enum_field.h
+++ b/src/google/protobuf/compiler/objectivec/enum_field.h
@@ -31,9 +31,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ENUM_FIELD_H__
 
-#include <map>
 #include <string>
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+#include "absl/container/btree_set.h"
+#include "google/protobuf/compiler/objectivec/field.h"
 
 namespace google {
 namespace protobuf {
@@ -47,28 +48,25 @@
   EnumFieldGenerator& operator=(const EnumFieldGenerator&) = delete;
 
  public:
-  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,
-      bool include_external_types) const override;
+  void GenerateCFunctionDeclarations(io::Printer* printer) const override;
+  void GenerateCFunctionImplementations(io::Printer* printer) const override;
+  void DetermineForwardDeclarations(absl::btree_set<std::string>* fwd_decls,
+                                    bool include_external_types) const override;
 
  protected:
   explicit EnumFieldGenerator(const FieldDescriptor* descriptor);
-  virtual ~EnumFieldGenerator();
+  ~EnumFieldGenerator() override = default;
 };
 
 class RepeatedEnumFieldGenerator : public RepeatedFieldGenerator {
   friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
 
  public:
-  virtual void FinishInitialization() override;
+  void FinishInitialization() override;
 
  protected:
   explicit RepeatedEnumFieldGenerator(const FieldDescriptor* descriptor);
-  virtual ~RepeatedEnumFieldGenerator();
+  ~RepeatedEnumFieldGenerator() override = default;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc b/src/google/protobuf/compiler/objectivec/extension.cc
similarity index 73%
rename from src/google/protobuf/compiler/objectivec/objectivec_extension.cc
rename to src/google/protobuf/compiler/objectivec/extension.cc
index 9cebcb2..d70b9a4 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.cc
+++ b/src/google/protobuf/compiler/objectivec/extension.cc
@@ -28,13 +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.
 
-#include <iostream>
+#include "google/protobuf/compiler/objectivec/extension.h"
 
-#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
+#include <iostream>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -50,16 +57,14 @@
     // 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 errors.
     std::cerr << "error: Extension is a map<>!"
-         << " That used to be blocked by the compiler." << std::endl;
+              << " That used to be blocked by the compiler." << std::endl;
     std::cerr.flush();
     abort();
   }
 }
 
-ExtensionGenerator::~ExtensionGenerator() {}
-
-void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) {
-  std::map<std::string, std::string> vars;
+void ExtensionGenerator::GenerateMembersHeader(io::Printer* printer) const {
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["method_name"] = method_name_;
   if (IsRetainedName(method_name_)) {
     vars["storage_attribute"] = " NS_RETURNS_NOT_RETAINED";
@@ -74,19 +79,23 @@
   }
   // Unlike normal message fields, check if the file for the extension was
   // deprecated.
-  vars["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file());
-  printer->Print(vars,
-                 "$comments$"
-                 "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n");
+  vars["deprecated_attribute"] =
+      GetOptionalDeprecatedAttribute(descriptor_, descriptor_->file());
+  // clang-format off
+  printer->Print(
+      vars,
+      "$comments$"
+      "+ (GPBExtensionDescriptor *)$method_name$$storage_attribute$$deprecated_attribute$;\n");
+  // clang-format on
 }
 
 void ExtensionGenerator::GenerateStaticVariablesInitialization(
-    io::Printer* printer) {
-  std::map<std::string, std::string> vars;
+    io::Printer* printer) const {
+  absl::flat_hash_map<absl::string_view, std::string> vars;
   vars["root_class_and_method_name"] = root_class_and_method_name_;
   const std::string containing_type = ClassName(descriptor_->containing_type());
   vars["extended_type"] = ObjCClass(containing_type);
-  vars["number"] = StrCat(descriptor_->number());
+  vars["number"] = absl::StrCat(descriptor_->number());
 
   std::vector<std::string> options;
   if (descriptor_->is_repeated()) options.push_back("GPBExtensionRepeated");
@@ -115,26 +124,29 @@
 
   if (objc_type == OBJECTIVECTYPE_ENUM) {
     vars["enum_desc_func_name"] =
-         EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
+        EnumName(descriptor_->enum_type()) + "_EnumDescriptor";
   } else {
     vars["enum_desc_func_name"] = "NULL";
   }
 
-  printer->Print(vars,
-                 "{\n"
-                 "  .defaultValue.$default_name$ = $default$,\n"
-                 "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
-                 "  .extendedClass.clazz = $extended_type$,\n"
-                 "  .messageOrGroupClass.clazz = $type$,\n"
-                 "  .enumDescriptorFunc = $enum_desc_func_name$,\n"
-                 "  .fieldNumber = $number$,\n"
-                 "  .dataType = $extension_type$,\n"
-                 "  .options = $options$,\n"
-                 "},\n");
+  // clang-format off
+  printer->Print(
+      vars,
+      "{\n"
+      "  .defaultValue.$default_name$ = $default$,\n"
+      "  .singletonName = GPBStringifySymbol($root_class_and_method_name$),\n"
+      "  .extendedClass.clazz = $extended_type$,\n"
+      "  .messageOrGroupClass.clazz = $type$,\n"
+      "  .enumDescriptorFunc = $enum_desc_func_name$,\n"
+      "  .fieldNumber = $number$,\n"
+      "  .dataType = $extension_type$,\n"
+      "  .options = $options$,\n"
+      "},\n");
+  // clang-format on
 }
 
 void ExtensionGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<std::string>* fwd_decls) {
+    absl::btree_set<std::string>* fwd_decls) const {
   std::string extended_type = ClassName(descriptor_->containing_type());
   fwd_decls->insert(ObjCClassDeclaration(extended_type));
   ObjectiveCType objc_type = GetObjectiveCType(descriptor_);
@@ -144,10 +156,13 @@
   }
 }
 
-void ExtensionGenerator::GenerateRegistrationSource(io::Printer* printer) {
+void ExtensionGenerator::GenerateRegistrationSource(
+    io::Printer* printer) const {
+  // clang-format off
   printer->Print(
       "[registry addExtension:$root_class_and_method_name$];\n",
       "root_class_and_method_name", root_class_and_method_name_);
+  // clang-format on
 }
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_extension.h b/src/google/protobuf/compiler/objectivec/extension.h
similarity index 86%
rename from src/google/protobuf/compiler/objectivec/objectivec_extension.h
rename to src/google/protobuf/compiler/objectivec/extension.h
index d412f4a..c174e95 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_extension.h
+++ b/src/google/protobuf/compiler/objectivec/extension.h
@@ -31,8 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_EXTENSION_H__
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include <string>
+
+#include "absl/container/btree_set.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -43,15 +46,16 @@
  public:
   ExtensionGenerator(const std::string& root_class_name,
                      const FieldDescriptor* descriptor);
-  ~ExtensionGenerator();
+  ~ExtensionGenerator() = default;
 
   ExtensionGenerator(const ExtensionGenerator&) = delete;
   ExtensionGenerator& operator=(const ExtensionGenerator&) = delete;
 
-  void GenerateMembersHeader(io::Printer* printer);
-  void GenerateStaticVariablesInitialization(io::Printer* printer);
-  void GenerateRegistrationSource(io::Printer* printer);
-  void DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls);
+  void GenerateMembersHeader(io::Printer* printer) const;
+  void GenerateStaticVariablesInitialization(io::Printer* printer) const;
+  void GenerateRegistrationSource(io::Printer* printer) const;
+  void DetermineObjectiveCClassDefinitions(
+      absl::btree_set<std::string>* fwd_decls) const;
 
  private:
   std::string method_name_;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.cc b/src/google/protobuf/compiler/objectivec/field.cc
similarity index 75%
rename from src/google/protobuf/compiler/objectivec/objectivec_field.cc
rename to src/google/protobuf/compiler/objectivec/field.cc
index 004ea19..bf4c1f3 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.cc
+++ b/src/google/protobuf/compiler/objectivec/field.cc
@@ -28,16 +28,22 @@
 // (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 <iostream>
+#include "google/protobuf/compiler/objectivec/field.h"
 
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/compiler/objectivec/objectivec_enum_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
+#include <iostream>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/objectivec/enum_field.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/map_field.h"
+#include "google/protobuf/compiler/objectivec/message_field.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/compiler/objectivec/primitive_field.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -46,8 +52,9 @@
 
 namespace {
 
-void SetCommonFieldVariables(const FieldDescriptor* descriptor,
-                             std::map<std::string, std::string>* variables) {
+void SetCommonFieldVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   std::string camel_case_name = FieldName(descriptor);
   std::string raw_field_name;
   if (descriptor->type() == FieldDescriptor::TYPE_GROUP) {
@@ -74,9 +81,10 @@
   (*variables)["raw_field_name"] = raw_field_name;
   (*variables)["field_number_name"] =
       classname + "_FieldNumber_" + capitalized_name;
-  (*variables)["field_number"] = StrCat(descriptor->number());
+  (*variables)["field_number"] = absl::StrCat(descriptor->number());
   (*variables)["field_type"] = GetCapitalizedType(descriptor);
-  (*variables)["deprecated_attribute"] = GetOptionalDeprecatedAttribute(descriptor);
+  (*variables)["deprecated_attribute"] =
+      GetOptionalDeprecatedAttribute(descriptor);
   std::vector<std::string> field_flags;
   if (descriptor->is_repeated()) field_flags.push_back("GPBFieldRepeated");
   if (descriptor->is_required()) field_flags.push_back("GPBFieldRequired");
@@ -89,6 +97,9 @@
   if (needs_custom_name) field_flags.push_back("GPBFieldTextFormatNameCustom");
   if (descriptor->type() == FieldDescriptor::TYPE_ENUM) {
     field_flags.push_back("GPBFieldHasEnumDescriptor");
+    if (descriptor->enum_type()->is_closed()) {
+      field_flags.push_back("GPBFieldClosedEnum");
+    }
   }
   // It will clear on a zero value if...
   //  - not repeated/map
@@ -107,18 +118,63 @@
   (*variables)["dataTypeSpecific_name"] = "clazz";
   (*variables)["dataTypeSpecific_value"] = "Nil";
 
-  (*variables)["storage_offset_value"] =
-      "(uint32_t)offsetof(" + classname + "__storage_, " + camel_case_name + ")";
+  (*variables)["storage_offset_value"] = "(uint32_t)offsetof(" + classname +
+                                         "__storage_, " + camel_case_name + ")";
   (*variables)["storage_offset_comment"] = "";
 
   // Clear some common things so they can be set just when needed.
   (*variables)["storage_attribute"] = "";
 }
 
+bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
+  // Repeated fields don't have defaults.
+  if (field->is_repeated()) {
+    return false;
+  }
+
+  // As much as checking field->has_default_value() seems useful, it isn't
+  // because of enums. proto2 syntax allows the first item in an enum (the
+  // default) to be non zero. So checking field->has_default_value() would
+  // result in missing this non zero default.  See MessageWithOneBasedEnum in
+  // objectivec/Tests/unittest_objc.proto for a test Message to confirm this.
+
+  // Some proto file set the default to the zero value, so make sure the value
+  // isn't the zero case.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return field->default_value_int32() != 0;
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return field->default_value_uint32() != 0U;
+    case FieldDescriptor::CPPTYPE_INT64:
+      return field->default_value_int64() != 0LL;
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return field->default_value_uint64() != 0ULL;
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return field->default_value_double() != 0.0;
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return field->default_value_float() != 0.0f;
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool();
+    case FieldDescriptor::CPPTYPE_STRING: {
+      const std::string& default_string = field->default_value_string();
+      return default_string.length() != 0;
+    }
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return field->default_value_enum()->number() != 0;
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return false;
+  }
+
+  // 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 false;
+}
+
 }  // namespace
 
 FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field) {
-  FieldGenerator* result = NULL;
+  FieldGenerator* result = nullptr;
   if (field->is_repeated()) {
     switch (GetObjectiveCType(field)) {
       case OBJECTIVECTYPE_MESSAGE: {
@@ -163,16 +219,11 @@
   SetCommonFieldVariables(descriptor, &variables_);
 }
 
-FieldGenerator::~FieldGenerator() {}
-
 void FieldGenerator::GenerateFieldNumberConstant(io::Printer* printer) const {
-  printer->Print(
-      variables_,
-      "$field_number_name$ = $field_number$,\n");
+  printer->Print(variables_, "$field_number_name$ = $field_number$,\n");
 }
 
-void FieldGenerator::GenerateCFunctionDeclarations(
-    io::Printer* printer) const {
+void FieldGenerator::GenerateCFunctionDeclarations(io::Printer* printer) const {
   // Nothing
 }
 
@@ -182,20 +233,21 @@
 }
 
 void FieldGenerator::DetermineForwardDeclarations(
-    std::set<std::string>* fwd_decls,
+    absl::btree_set<std::string>* fwd_decls,
     bool include_external_types) const {
   // Nothing
 }
 
 void FieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<std::string>* fwd_decls) const {
+    absl::btree_set<std::string>* fwd_decls) const {
   // Nothing
 }
 
-void FieldGenerator::GenerateFieldDescription(
-    io::Printer* printer, bool include_default) const {
+void FieldGenerator::GenerateFieldDescription(io::Printer* printer,
+                                              bool include_default) const {
   // Printed in the same order as the structure decl.
   if (include_default) {
+    // clang-format off
     printer->Print(
         variables_,
         "{\n"
@@ -208,7 +260,9 @@
         "  .core.flags = $fieldflags$,\n"
         "  .core.dataType = GPBDataType$field_type$,\n"
         "},\n");
+    // clang-format on
   } else {
+    // clang-format off
     printer->Print(
         variables_,
         "{\n"
@@ -220,43 +274,41 @@
         "  .flags = $fieldflags$,\n"
         "  .dataType = GPBDataType$field_type$,\n"
         "},\n");
+    // clang-format on
   }
 }
 
 void FieldGenerator::SetRuntimeHasBit(int has_index) {
-  variables_["has_index"] = StrCat(has_index);
+  variables_["has_index"] = absl::StrCat(has_index);
 }
 
-void FieldGenerator::SetNoHasBit(void) {
-  variables_["has_index"] = "GPBNoHasBit";
-}
+void FieldGenerator::SetNoHasBit() { variables_["has_index"] = "GPBNoHasBit"; }
 
-int FieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
-  return 0;
-}
+int FieldGenerator::ExtraRuntimeHasBitsNeeded() const { return 0; }
 
 void FieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
   // 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 errors.
-  std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()." << std::endl;
+  std::cerr << "Error: should have overridden SetExtraRuntimeHasBitsBase()."
+            << std::endl;
   std::cerr.flush();
   abort();
 }
 
 void FieldGenerator::SetOneofIndexBase(int index_base) {
   const OneofDescriptor* oneof = descriptor_->real_containing_oneof();
-  if (oneof != NULL) {
+  if (oneof != nullptr) {
     int index = oneof->index() + index_base;
     // Flip the sign to mark it as a oneof.
-    variables_["has_index"] = StrCat(-index);
+    variables_["has_index"] = absl::StrCat(-index);
   }
 }
 
-bool FieldGenerator::WantsHasProperty(void) const {
+bool FieldGenerator::WantsHasProperty() const {
   return descriptor_->has_presence() && !descriptor_->real_containing_oneof();
 }
 
-void FieldGenerator::FinishInitialization(void) {
+void FieldGenerator::FinishInitialization() {
   // If "property_type" wasn't set, make it "storage_type".
   if ((variables_.find("property_type") == variables_.end()) &&
       (variables_.find("storage_type") != variables_.end())) {
@@ -269,8 +321,6 @@
   // Nothing
 }
 
-SingleFieldGenerator::~SingleFieldGenerator() {}
-
 void SingleFieldGenerator::GenerateFieldStorageDeclaration(
     io::Printer* printer) const {
   printer->Print(variables_, "$storage_type$ $name$;\n");
@@ -279,15 +329,19 @@
 void SingleFieldGenerator::GeneratePropertyDeclaration(
     io::Printer* printer) const {
   printer->Print(variables_, "$comments$");
+  // clang-format off
   printer->Print(
       variables_,
-      "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n"
-      "\n");
+      "@property(nonatomic, readwrite) $property_type$ $name$$deprecated_attribute$;\n");
+  // clang-format on
   if (WantsHasProperty()) {
+    // clang-format off
     printer->Print(
         variables_,
         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
+    // clang-format on
   }
+  printer->Print("\n");
 }
 
 void SingleFieldGenerator::GeneratePropertyImplementation(
@@ -299,7 +353,7 @@
   }
 }
 
-bool SingleFieldGenerator::RuntimeUsesHasBit(void) const {
+bool SingleFieldGenerator::RuntimeUsesHasBit() const {
   if (descriptor_->real_containing_oneof()) {
     // The oneof tracks what is set instead.
     return false;
@@ -315,8 +369,6 @@
   }
 }
 
-ObjCObjFieldGenerator::~ObjCObjFieldGenerator() {}
-
 void ObjCObjFieldGenerator::GenerateFieldStorageDeclaration(
     io::Printer* printer) const {
   printer->Print(variables_, "$storage_type$ *$name$;\n");
@@ -324,26 +376,30 @@
 
 void ObjCObjFieldGenerator::GeneratePropertyDeclaration(
     io::Printer* printer) const {
-
   // Differs from SingleFieldGenerator::GeneratePropertyDeclaration() in that
   // it uses pointers and deals with Objective C's rules around storage name
   // conventions (init*, new*, etc.)
 
   printer->Print(variables_, "$comments$");
+  // clang-format off
   printer->Print(
       variables_,
       "@property(nonatomic, readwrite, $property_storage_attribute$, null_resettable) $property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n");
+  // clang-format on
   if (WantsHasProperty()) {
+    // clang-format off
     printer->Print(
         variables_,
         "/** Test to see if @c $name$ has been set. */\n"
         "@property(nonatomic, readwrite) BOOL has$capitalized_name$$deprecated_attribute$;\n");
+    // clang-format on
   }
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
     printer->Print(variables_,
-                   "- ($property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
+                   "- ($property_type$ *)$name$ "
+                   "GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
   }
   printer->Print("\n");
 }
@@ -355,9 +411,7 @@
   variables_["array_comment"] = "";
 }
 
-RepeatedFieldGenerator::~RepeatedFieldGenerator() {}
-
-void RepeatedFieldGenerator::FinishInitialization(void) {
+void RepeatedFieldGenerator::FinishInitialization() {
   FieldGenerator::FinishInitialization();
   if (variables_.find("array_property_type") == variables_.end()) {
     variables_["array_property_type"] = variable("array_storage_type");
@@ -376,30 +430,33 @@
 
 void RepeatedFieldGenerator::GeneratePropertyDeclaration(
     io::Printer* printer) const {
-
   // Repeated fields don't need the has* properties, but they do expose a
   // *Count (to check without autocreation).  So for the field property we need
   // the same logic as ObjCObjFieldGenerator::GeneratePropertyDeclaration() for
   // dealing with needing Objective C's rules around storage name conventions
   // (init*, new*, etc.)
 
+  // clang-format off
   printer->Print(
       variables_,
       "$comments$"
       "$array_comment$"
       "@property(nonatomic, readwrite, strong, null_resettable) $array_property_type$ *$name$$storage_attribute$$deprecated_attribute$;\n"
-      "/** The number of items in @c $name$ without causing the array to be created. */\n"
+      "/** The number of items in @c $name$ without causing the container to be created. */\n"
       "@property(nonatomic, readonly) NSUInteger $name$_Count$deprecated_attribute$;\n");
+  // clang-format on
   if (IsInitName(variables_.find("name")->second)) {
     // If property name starts with init we need to annotate it to get past ARC.
     // http://stackoverflow.com/questions/18723226/how-do-i-annotate-an-objective-c-property-with-an-objc-method-family/18723227#18723227
+    // clang-format off
     printer->Print(variables_,
                    "- ($array_property_type$ *)$name$ GPB_METHOD_FAMILY_NONE$deprecated_attribute$;\n");
+    // clang-format on
   }
   printer->Print("\n");
 }
 
-bool RepeatedFieldGenerator::RuntimeUsesHasBit(void) const {
+bool RepeatedFieldGenerator::RuntimeUsesHasBit() const {
   return false;  // The array (or map/dict) having anything is what is used.
 }
 
@@ -409,8 +466,7 @@
       extension_generators_(descriptor->extension_count()) {
   // Construct all the FieldGenerators.
   for (int i = 0; i < descriptor->field_count(); i++) {
-    field_generators_[i].reset(
-        FieldGenerator::Make(descriptor->field(i)));
+    field_generators_[i].reset(FieldGenerator::Make(descriptor->field(i)));
   }
   for (int i = 0; i < descriptor->extension_count(); i++) {
     extension_generators_[i].reset(
@@ -418,8 +474,6 @@
   }
 }
 
-FieldGeneratorMap::~FieldGeneratorMap() {}
-
 const FieldGenerator& FieldGeneratorMap::get(
     const FieldDescriptor* field) const {
   GOOGLE_CHECK_EQ(field->containing_type(), descriptor_);
@@ -430,7 +484,7 @@
   return *extension_generators_[index];
 }
 
-int FieldGeneratorMap::CalculateHasBits(void) {
+int FieldGeneratorMap::CalculateHasBits() {
   int total_bits = 0;
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (field_generators_[i]->RuntimeUsesHasBit()) {
@@ -454,7 +508,7 @@
   }
 }
 
-bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault(void) const {
+bool FieldGeneratorMap::DoesAnyFieldHaveNonZeroDefault() const {
   for (int i = 0; i < descriptor_->field_count(); i++) {
     if (HasNonZeroDefaultValue(descriptor_->field(i))) {
       return true;
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_field.h b/src/google/protobuf/compiler/objectivec/field.h
similarity index 75%
rename from src/google/protobuf/compiler/objectivec/objectivec_field.h
rename to src/google/protobuf/compiler/objectivec/field.h
index 759ef80..8cc1d5a 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_field.h
+++ b/src/google/protobuf/compiler/objectivec/field.h
@@ -31,10 +31,15 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FIELD_H__
 
-#include <map>
+#include <memory>
 #include <string>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+#include <vector>
+
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/match.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -45,7 +50,7 @@
  public:
   static FieldGenerator* Make(const FieldDescriptor* field);
 
-  virtual ~FieldGenerator();
+  virtual ~FieldGenerator() = default;
 
   FieldGenerator(const FieldGenerator&) = delete;
   FieldGenerator& operator=(const FieldGenerator&) = delete;
@@ -64,21 +69,21 @@
 
   // Exposed for subclasses, should always call it on the parent class also.
   virtual void DetermineForwardDeclarations(
-      std::set<std::string>* fwd_decls,
+      absl::btree_set<std::string>* fwd_decls,
       bool include_external_types) const;
   virtual void DetermineObjectiveCClassDefinitions(
-      std::set<std::string>* fwd_decls) const;
+      absl::btree_set<std::string>* fwd_decls) const;
 
   // Used during generation, not intended to be extended by subclasses.
-  void GenerateFieldDescription(
-      io::Printer* printer, bool include_default) const;
+  void GenerateFieldDescription(io::Printer* printer,
+                                bool include_default) const;
   void GenerateFieldNumberConstant(io::Printer* printer) const;
 
   // Exposed to get and set the has bits information.
-  virtual bool RuntimeUsesHasBit(void) const = 0;
+  virtual bool RuntimeUsesHasBit() const = 0;
   void SetRuntimeHasBit(int has_index);
-  void SetNoHasBit(void);
-  virtual int ExtraRuntimeHasBitsNeeded(void) const;
+  void SetNoHasBit();
+  virtual int ExtraRuntimeHasBitsNeeded() const;
   virtual void SetExtraRuntimeHasBitsBase(int index_base);
   void SetOneofIndexBase(int index_base);
 
@@ -88,8 +93,7 @@
 
   bool needs_textformat_name_support() const {
     const std::string& field_flags = variable("fieldflags");
-    return field_flags.find("GPBFieldTextFormatNameCustom") !=
-           std::string::npos;
+    return absl::StrContains(field_flags, "GPBFieldTextFormatNameCustom");
   }
   std::string generated_objc_name() const { return variable("name"); }
   std::string raw_field_name() const { return variable("raw_field_name"); }
@@ -97,26 +101,26 @@
  protected:
   explicit FieldGenerator(const FieldDescriptor* descriptor);
 
-  virtual void FinishInitialization(void);
-  bool WantsHasProperty(void) const;
+  virtual void FinishInitialization();
+  bool WantsHasProperty() const;
 
   const FieldDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
 };
 
 class SingleFieldGenerator : public FieldGenerator {
  public:
-  virtual ~SingleFieldGenerator();
+  ~SingleFieldGenerator() override = default;
 
   SingleFieldGenerator(const SingleFieldGenerator&) = delete;
   SingleFieldGenerator& operator=(const SingleFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
-  virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
+  void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+  void GeneratePropertyDeclaration(io::Printer* printer) const override;
 
-  virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
+  void GeneratePropertyImplementation(io::Printer* printer) const override;
 
-  virtual bool RuntimeUsesHasBit(void) const override;
+  bool RuntimeUsesHasBit() const override;
 
  protected:
   explicit SingleFieldGenerator(const FieldDescriptor* descriptor);
@@ -125,13 +129,13 @@
 // Subclass with common support for when the field ends up as an ObjC Object.
 class ObjCObjFieldGenerator : public SingleFieldGenerator {
  public:
-  virtual ~ObjCObjFieldGenerator();
+  ~ObjCObjFieldGenerator() override = default;
 
   ObjCObjFieldGenerator(const ObjCObjFieldGenerator&) = delete;
   ObjCObjFieldGenerator& operator=(const ObjCObjFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
-  virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
+  void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+  void GeneratePropertyDeclaration(io::Printer* printer) const override;
 
  protected:
   explicit ObjCObjFieldGenerator(const FieldDescriptor* descriptor);
@@ -139,28 +143,28 @@
 
 class RepeatedFieldGenerator : public ObjCObjFieldGenerator {
  public:
-  virtual ~RepeatedFieldGenerator();
+  ~RepeatedFieldGenerator() override = default;
 
   RepeatedFieldGenerator(const RepeatedFieldGenerator&) = delete;
   RepeatedFieldGenerator& operator=(const RepeatedFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
-  virtual void GeneratePropertyDeclaration(io::Printer* printer) const override;
+  void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+  void GeneratePropertyDeclaration(io::Printer* printer) const override;
 
-  virtual void GeneratePropertyImplementation(io::Printer* printer) const override;
+  void GeneratePropertyImplementation(io::Printer* printer) const override;
 
-  virtual bool RuntimeUsesHasBit(void) const override;
+  bool RuntimeUsesHasBit() const override;
 
  protected:
   explicit RepeatedFieldGenerator(const FieldDescriptor* descriptor);
-  virtual void FinishInitialization(void) override;
+  void FinishInitialization() override;
 };
 
 // Convenience class which constructs FieldGenerators for a Descriptor.
 class FieldGeneratorMap {
  public:
   explicit FieldGeneratorMap(const Descriptor* descriptor);
-  ~FieldGeneratorMap();
+  ~FieldGeneratorMap() = default;
 
   FieldGeneratorMap(const FieldGeneratorMap&) = delete;
   FieldGeneratorMap& operator=(const FieldGeneratorMap&) = delete;
@@ -169,12 +173,12 @@
   const FieldGenerator& get_extension(int index) const;
 
   // Assigns the has bits and returns the number of bits needed.
-  int CalculateHasBits(void);
+  int CalculateHasBits();
 
   void SetOneofIndexBase(int index_base);
 
   // Check if any field of this message has a non zero default.
-  bool DoesAnyFieldHaveNonZeroDefault(void) const;
+  bool DoesAnyFieldHaveNonZeroDefault() const;
 
  private:
   const Descriptor* descriptor_;
diff --git a/src/google/protobuf/compiler/objectivec/file.cc b/src/google/protobuf/compiler/objectivec/file.cc
new file mode 100644
index 0000000..2d7b5bb
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/file.cc
@@ -0,0 +1,656 @@
+// 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/objectivec/file.h"
+
+#include <algorithm>
+#include <functional>
+#include <iostream>
+#include <iterator>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "google/protobuf/compiler/objectivec/enum.h"
+#include "google/protobuf/compiler/objectivec/extension.h"
+#include "google/protobuf/compiler/objectivec/import_writer.h"
+#include "google/protobuf/compiler/objectivec/message.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/io/printer.h"
+
+// 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 errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+// This is also found in GPBBootstrap.h, and needs to be kept in sync.
+const int32_t GOOGLE_PROTOBUF_OBJC_VERSION = 30005;
+
+const char* kHeaderExtension = ".pbobjc.h";
+
+// Checks if a message contains any extension definitions (on the message or
+// a nested message under it).
+bool MessageContainsExtensions(const Descriptor* message) {
+  if (message->extension_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < message->nested_type_count(); i++) {
+    if (MessageContainsExtensions(message->nested_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+// Checks if the file contains any extensions definitions (at the root or
+// nested under a message).
+bool FileContainsExtensions(const FileDescriptor* file) {
+  if (file->extension_count() > 0) {
+    return true;
+  }
+  for (int i = 0; i < file->message_type_count(); i++) {
+    if (MessageContainsExtensions(file->message_type(i))) {
+      return true;
+    }
+  }
+  return false;
+}
+
+bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) {
+  for (int i = 0; i < file->dependency_count(); i++) {
+    if (dep == file->dependency(i)) {
+      return true;
+    }
+  }
+  return false;
+}
+
+struct FileDescriptorsOrderedByName {
+  inline bool operator()(const FileDescriptor* a,
+                         const FileDescriptor* b) const {
+    return a->name() < b->name();
+  }
+};
+
+void MakeDescriptors(
+    const Descriptor* descriptor, const std::string& root_classname,
+    std::vector<std::unique_ptr<EnumGenerator>>* enum_generators,
+    std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators,
+    std::vector<std::unique_ptr<MessageGenerator>>* message_generators) {
+  for (int i = 0; i < descriptor->enum_type_count(); i++) {
+    enum_generators->emplace_back(
+        std::make_unique<EnumGenerator>(descriptor->enum_type(i)));
+  }
+  for (int i = 0; i < descriptor->nested_type_count(); i++) {
+    message_generators->emplace_back(std::make_unique<MessageGenerator>(
+        root_classname, descriptor->nested_type(i)));
+    message_generators->back()->AddExtensionGenerators(extension_generators);
+    MakeDescriptors(descriptor->nested_type(i), root_classname, enum_generators,
+                    extension_generators, message_generators);
+  }
+}
+
+}  // namespace
+
+const FileGenerator::CommonState::MinDepsEntry&
+FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal(
+    const FileDescriptor* file) {
+  auto it = deps_info_cache.find(file);
+  if (it != deps_info_cache.end()) {
+    return it->second;
+  }
+
+  absl::flat_hash_set<const FileDescriptor*> min_deps_collector;
+  absl::flat_hash_set<const FileDescriptor*> transitive_deps_collector;
+  absl::flat_hash_set<const FileDescriptor*> to_prune;
+  for (int i = 0; i < file->dependency_count(); i++) {
+    const FileDescriptor* dep = file->dependency(i);
+    MinDepsEntry dep_info =
+        CollectMinimalFileDepsContainingExtensionsInternal(dep);
+
+    // Everything the dep covered, this file will also cover.
+    transitive_deps_collector.insert(dep_info.transitive_deps.begin(),
+                                     dep_info.transitive_deps.end());
+    // Prune everything from the dep's covered list in case another dep lists it
+    // as a min dep.
+    to_prune.insert(dep_info.transitive_deps.begin(),
+                    dep_info.transitive_deps.end());
+
+    // Does the dep have any extensions...
+    if (dep_info.has_extensions) {
+      // Yes -> Add this file, prune its min_deps and add them to the covered
+      // deps.
+      min_deps_collector.insert(dep);
+      to_prune.insert(dep_info.min_deps.begin(), dep_info.min_deps.end());
+      transitive_deps_collector.insert(dep_info.min_deps.begin(),
+                                       dep_info.min_deps.end());
+    } else {
+      // No -> Just use its min_deps.
+      min_deps_collector.insert(dep_info.min_deps.begin(),
+                                dep_info.min_deps.end());
+    }
+  }
+
+  const bool file_has_exts = FileContainsExtensions(file);
+
+  // Fast path: if nothing to prune or there was only one dep, the prune work is
+  // a waste, skip it.
+  if (to_prune.empty() || file->dependency_count() == 1) {
+    return deps_info_cache
+        .insert(
+            {file,
+             {file_has_exts, min_deps_collector, transitive_deps_collector}})
+        .first->second;
+  }
+
+  absl::flat_hash_set<const FileDescriptor*> min_deps;
+  std::copy_if(min_deps_collector.begin(), min_deps_collector.end(),
+               std::inserter(min_deps, min_deps.end()),
+               [&](const FileDescriptor* value) {
+                 return to_prune.find(value) == to_prune.end();
+               });
+  return deps_info_cache
+      .insert({file, {file_has_exts, min_deps, transitive_deps_collector}})
+      .first->second;
+}
+
+// Collect the deps of the given file that contain extensions. This can be used
+// to create the chain of roots that need to be wired together.
+//
+// NOTE: If any changes are made to this and the supporting functions, you will
+// need to manually validate what the generated code is for the test files:
+//   objectivec/Tests/unittest_extension_chain_*.proto
+// There are comments about what the expected code should be line and limited
+// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports
+// specifically).
+std::vector<const FileDescriptor*>
+FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensions(
+    const FileDescriptor* file) {
+  absl::flat_hash_set<const FileDescriptor*> min_deps =
+      CollectMinimalFileDepsContainingExtensionsInternal(file).min_deps;
+  // Sort the list since pointer order isn't stable across runs.
+  std::vector<const FileDescriptor*> result(min_deps.begin(), min_deps.end());
+  std::sort(result.begin(), result.end(), FileDescriptorsOrderedByName());
+  return result;
+}
+
+FileGenerator::FileGenerator(const FileDescriptor* file,
+                             const GenerationOptions& generation_options,
+                             CommonState& common_state)
+    : file_(file),
+      generation_options_(generation_options),
+      common_state_(&common_state),
+      root_class_name_(FileClassName(file)),
+      is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)) {
+  for (int i = 0; i < file_->enum_type_count(); i++) {
+    enum_generators_.emplace_back(
+        std::make_unique<EnumGenerator>(file_->enum_type(i)));
+  }
+  for (int i = 0; i < file_->extension_count(); i++) {
+    extension_generators_.push_back(std::make_unique<ExtensionGenerator>(
+        root_class_name_, file_->extension(i)));
+  }
+  for (int i = 0; i < file_->message_type_count(); i++) {
+    message_generators_.emplace_back(std::make_unique<MessageGenerator>(
+        root_class_name_, file_->message_type(i)));
+    message_generators_.back()->AddExtensionGenerators(&extension_generators_);
+    MakeDescriptors(file_->message_type(i), root_class_name_, &enum_generators_,
+                    &extension_generators_, &message_generators_);
+  }
+}
+
+void FileGenerator::GenerateHeader(io::Printer* p) const {
+  GenerateFile(p, GeneratedFileType::kHeader, [&] {
+    p->Print("CF_EXTERN_C_BEGIN\n\n");
+
+    absl::btree_set<std::string> fwd_decls;
+    for (const auto& generator : message_generators_) {
+      generator->DetermineForwardDeclarations(&fwd_decls,
+                                              /* include_external_types = */
+                                              HeadersUseForwardDeclarations());
+    }
+    if (!fwd_decls.empty()) {
+      p->Print("$fwd_decls$\n\n", "fwd_decls", absl::StrJoin(fwd_decls, "\n"));
+    }
+
+    p->Print("NS_ASSUME_NONNULL_BEGIN\n\n");
+
+    for (const auto& generator : enum_generators_) {
+      generator->GenerateHeader(p);
+    }
+
+    // For extensions to chain together, the Root gets created even if there
+    // are no extensions.
+    p->Print(
+        // clang-format off
+        "#pragma mark - $root_class_name$\n"
+        "\n"
+        "/**\n"
+        " * Exposes the extension registry for this file.\n"
+        " *\n"
+        " * The base class provides:\n"
+        " * @code\n"
+        " *   + (GPBExtensionRegistry *)extensionRegistry;\n"
+        " * @endcode\n"
+        " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
+        " * this file and all files that it depends on.\n"
+        " **/\n"
+        "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n"
+        "@end\n"
+        "\n",
+        // clang-format on
+        "root_class_name", root_class_name_);
+
+    // The dynamic methods block is only needed if there are extensions that are
+    // file level scoped (not message scoped). The first
+    // file_->extension_count() of extension_generators_ are the file scoped
+    // ones.
+    if (file_->extension_count()) {
+      p->Print("@interface $root_class_name$ (DynamicMethods)\n",
+               "root_class_name", root_class_name_);
+
+      for (int i = 0; i < file_->extension_count(); i++) {
+        extension_generators_[i]->GenerateMembersHeader(p);
+      }
+
+      p->Print("@end\n\n");
+    }  // file_->extension_count()
+
+    for (const auto& generator : message_generators_) {
+      generator->GenerateMessageHeader(p);
+    }
+
+    // clang-format off
+    p->Print(
+      "NS_ASSUME_NONNULL_END\n"
+      "\n"
+      "CF_EXTERN_C_END\n");
+    // clang-format on
+  });
+}
+
+void FileGenerator::GenerateSource(io::Printer* p) const {
+  std::vector<const FileDescriptor*> deps_with_extensions =
+      common_state_->CollectMinimalFileDepsContainingExtensions(file_);
+
+  // If any indirect dependency provided extensions, it needs to be directly
+  // imported so it can get merged into the root's extensions registry.
+  // See the Note by CollectMinimalFileDepsContainingExtensions before
+  // changing this.
+  std::vector<const FileDescriptor*> extra_files;
+  for (auto& dep : deps_with_extensions) {
+    if (!IsDirectDependency(dep, file_)) {
+      extra_files.push_back(dep);
+    }
+  }
+
+  absl::btree_set<std::string> fwd_decls;
+  for (const auto& generator : message_generators_) {
+    generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
+  }
+  for (const auto& generator : extension_generators_) {
+    generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
+  }
+
+  std::vector<std::string> ignored_warnings;
+  // The generated code for oneof's uses direct ivar access, suppress the
+  // warning in case developer turn that on in the context they compile the
+  // generated code.
+  for (const auto& generator : message_generators_) {
+    if (generator->IncludesOneOfDefinition()) {
+      ignored_warnings.push_back("direct-ivar-access");
+      break;
+    }
+  }
+  if (!fwd_decls.empty()) {
+    ignored_warnings.push_back("dollar-in-identifier-extension");
+  }
+
+  GenerateFile(
+      p, GeneratedFileType::kSource, ignored_warnings, extra_files, [&] {
+        if (!fwd_decls.empty()) {
+          p->Print(
+              // clang-format off
+              "#pragma mark - Objective C Class declarations\n"
+              "// Forward declarations of Objective C classes that we can use as\n"
+              "// static values in struct initializers.\n"
+              "// We don't use [Foo class] because it is not a static value.\n"
+              "$fwd_decls$\n"
+              "\n",
+              // clang-format on
+              "fwd_decls", absl::StrJoin(fwd_decls, "\n"));
+        }
+
+        PrintRootImplementation(p, deps_with_extensions);
+        PrintFileDescriptorImplementation(p);
+
+        for (const auto& generator : enum_generators_) {
+          generator->GenerateSource(p);
+        }
+        for (const auto& generator : message_generators_) {
+          generator->GenerateSource(p);
+        }
+      });
+}
+
+void FileGenerator::GenerateFile(
+    io::Printer* p, GeneratedFileType file_type,
+    const std::vector<std::string>& ignored_warnings,
+    const std::vector<const FileDescriptor*>& extra_files_to_import,
+    std::function<void()> body) const {
+  ImportWriter import_writer(
+      generation_options_.generate_for_named_framework,
+      generation_options_.named_framework_to_proto_path_mappings_path,
+      generation_options_.runtime_import_prefix,
+      /* for_bundled_proto = */ is_bundled_proto_);
+  const std::string header_extension(kHeaderExtension);
+
+  switch (file_type) {
+    case GeneratedFileType::kHeader:
+      // Generated files bundled with the library get minimal imports,
+      // everything else gets the wrapper so everything is usable.
+      if (is_bundled_proto_) {
+        import_writer.AddRuntimeImport("GPBDescriptor.h");
+        import_writer.AddRuntimeImport("GPBMessage.h");
+        import_writer.AddRuntimeImport("GPBRootObject.h");
+      } else {
+        import_writer.AddRuntimeImport("GPBProtocolBuffers.h");
+      }
+      if (HeadersUseForwardDeclarations()) {
+        // #import any headers for "public imports" in the proto file.
+        for (int i = 0; i < file_->public_dependency_count(); i++) {
+          import_writer.AddFile(file_->public_dependency(i), header_extension);
+        }
+      } else {
+        for (int i = 0; i < file_->dependency_count(); i++) {
+          import_writer.AddFile(file_->dependency(i), header_extension);
+        }
+      }
+      break;
+    case GeneratedFileType::kSource:
+      import_writer.AddRuntimeImport("GPBProtocolBuffers_RuntimeSupport.h");
+      import_writer.AddFile(file_, header_extension);
+      if (HeadersUseForwardDeclarations()) {
+        // #import the headers for anything that a plain dependency of this
+        // proto file (that means they were just an include, not a "public"
+        // include).
+        absl::flat_hash_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());
+        }
+        for (int i = 0; i < file_->dependency_count(); i++) {
+          const FileDescriptor* dep = file_->dependency(i);
+          if (!public_import_names.contains(dep->name())) {
+            import_writer.AddFile(dep, header_extension);
+          }
+        }
+      }
+      break;
+  }
+
+  for (const auto& dep : extra_files_to_import) {
+    import_writer.AddFile(dep, header_extension);
+  }
+
+  p->Print(
+      "// Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "// $clangfmt$ off\n"
+      "// source: $filename$\n"
+      "\n",
+      "filename", file_->name(), "clangfmt", "clang-format");
+
+  import_writer.PrintRuntimeImports(
+      p, /* default_cpp_symbol = */ !is_bundled_proto_);
+
+  p->Print("\n");
+
+  if (file_type == GeneratedFileType::kHeader) {
+    // Add some verification that the generated code matches the source the
+    // code is being compiled with.
+    // NOTE: This captures the raw numeric values at the time the generator was
+    // compiled, since that will be the versions for the ObjC runtime at that
+    // time.  The constants in the generated code will then get their values at
+    // at compile time (so checking against the headers being used to compile).
+    p->Print(
+        // clang-format off
+        "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
+        "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
+        "#endif\n"
+        "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n"
+        "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
+        "#endif\n"
+        "\n",
+        // clang-format on
+        "google_protobuf_objc_version",
+        absl::StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
+  }
+
+  // Enum implementation uses atomic in the generated code, so add
+  // the system import as needed.
+  if (file_type == GeneratedFileType::kSource && !enum_generators_.empty()) {
+    p->Print("#import <stdatomic.h>\n\n");
+  }
+
+  import_writer.PrintFileImports(p);
+
+  // clang-format off
+  p->Print(
+      "// @@protoc_insertion_point(imports)\n"
+      "\n"
+      "#pragma clang diagnostic push\n"
+      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
+  // clang-format on
+  for (const auto& warning : ignored_warnings) {
+    p->Print("#pragma clang diagnostic ignored \"-W$warning$\"\n", "warning",
+             warning);
+  }
+  p->Print("\n");
+
+  body();
+
+  p->Print(
+      "\n"
+      "#pragma clang diagnostic pop\n"
+      "\n"
+      "// @@protoc_insertion_point(global_scope)\n"
+      "\n"
+      "// $clangfmt$ on\n",
+      "clangfmt", "clang-format");
+}
+
+void FileGenerator::PrintRootImplementation(
+    io::Printer* p,
+    const std::vector<const FileDescriptor*>& deps_with_extensions) const {
+  p->Print(
+      // clang-format off
+      "#pragma mark - $root_class_name$\n"
+      "\n"
+      "@implementation $root_class_name$\n"
+      "\n",
+      // clang-format on
+      "root_class_name", root_class_name_);
+
+  // If there were any extensions or this file has any dependencies, output a
+  // registry to override to create the file specific registry.
+  if (extension_generators_.empty() && deps_with_extensions.empty()) {
+    if (file_->dependency_count() == 0) {
+      // clang-format off
+      p->Print(
+          "// No extensions in the file and no imports, so no need to generate\n"
+          "// +extensionRegistry.\n");
+      // clang-format on
+    } else {
+      // clang-format off
+      p->Print(
+          "// No extensions in the file and none of the imports (direct or indirect)\n"
+          "// defined extensions, so no need to generate +extensionRegistry.\n");
+      // clang-format on
+    }
+  } else {
+    PrintRootExtensionRegistryImplementation(p, deps_with_extensions);
+  }
+
+  p->Print("\n@end\n\n");
+}
+
+void FileGenerator::PrintRootExtensionRegistryImplementation(
+    io::Printer* p,
+    const std::vector<const FileDescriptor*>& deps_with_extensions) const {
+  // clang-format off
+  p->Print(
+      "+ (GPBExtensionRegistry*)extensionRegistry {\n"
+      "  // This is called by +initialize so there is no need to worry\n"
+      "  // about thread safety and initialization of registry.\n"
+      "  static GPBExtensionRegistry* registry = nil;\n"
+      "  if (!registry) {\n"
+      "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
+      "    registry = [[GPBExtensionRegistry alloc] init];\n");
+  // clang-format on
+
+  p->Indent();
+  p->Indent();
+
+  if (!extension_generators_.empty()) {
+    p->Print("static GPBExtensionDescription descriptions[] = {\n");
+    p->Indent();
+    for (const auto& generator : extension_generators_) {
+      generator->GenerateStaticVariablesInitialization(p);
+    }
+    p->Outdent();
+    // clang-format off
+    p->Print(
+        "};\n"
+        "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
+        "  GPBExtensionDescriptor *extension =\n"
+        "      [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n"
+        "                                                     usesClassRefs:YES];\n"
+        "  [registry addExtension:extension];\n"
+        "  [self globallyRegisterExtension:extension];\n"
+        "  [extension release];\n"
+        "}\n");
+    // clang-format on
+  }
+
+  if (deps_with_extensions.empty()) {
+    // clang-format off
+    p->Print(
+        "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
+        "// them to this registry.\n");
+    // clang-format on
+  } else {
+    // clang-format off
+    p->Print(
+        "// Merge in the imports (direct or indirect) that defined extensions.\n");
+    // clang-format on
+    for (const auto& dep : deps_with_extensions) {
+      const std::string root_class_name(FileClassName((dep)));
+      p->Print("[registry addExtensions:[$dependency$ extensionRegistry]];\n",
+               "dependency", root_class_name);
+    }
+  }
+
+  p->Outdent();
+  p->Outdent();
+
+  // clang-format off
+    p->Print(
+        "  }\n"
+        "  return registry;\n"
+        "}\n");
+  // clang-format on
+}
+
+void FileGenerator::PrintFileDescriptorImplementation(io::Printer* p) const {
+  // File descriptor only needed if there are messages to use it.
+  if (message_generators_.empty()) {
+    return;
+  }
+
+  const std::string objc_prefix(FileClassPrefix(file_));
+  absl::flat_hash_map<absl::string_view, std::string> vars;
+  vars["root_class_name"] = root_class_name_;
+  vars["package"] = file_->package();
+  switch (file_->syntax()) {
+    case FileDescriptor::SYNTAX_UNKNOWN:
+      vars["syntax"] = "GPBFileSyntaxUnknown";
+      break;
+    case FileDescriptor::SYNTAX_PROTO2:
+      vars["syntax"] = "GPBFileSyntaxProto2";
+      break;
+    case FileDescriptor::SYNTAX_PROTO3:
+      vars["syntax"] = "GPBFileSyntaxProto3";
+      break;
+  }
+  if (objc_prefix.empty()) {
+    vars["prefix_arg"] = "";
+  } else {
+    vars["prefix_arg"] = absl::StrCat(
+        "                                                 objcPrefix:@\"",
+        objc_prefix, "\"\n");
+  }
+
+  // clang-format off
+  p->Print(
+      vars,
+      "#pragma mark - $root_class_name$_FileDescriptor\n"
+      "\n"
+      "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
+      "  // This is called by +initialize so there is no need to worry\n"
+      "  // about thread safety of the singleton.\n"
+      "  static GPBFileDescriptor *descriptor = NULL;\n"
+      "  if (!descriptor) {\n"
+      "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
+      "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
+      "$prefix_arg$"
+      "                                                     syntax:$syntax$];\n"
+      "  }\n"
+      "  return descriptor;\n"
+      "}\n"
+      "\n");
+  // clang-format on
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/file.h b/src/google/protobuf/compiler/objectivec/file.h
new file mode 100644
index 0000000..f6d3879
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/file.h
@@ -0,0 +1,130 @@
+// 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_OBJECTIVEC_FILE_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
+
+#include <functional>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "google/protobuf/compiler/objectivec/enum.h"
+#include "google/protobuf/compiler/objectivec/extension.h"
+#include "google/protobuf/compiler/objectivec/message.h"
+#include "google/protobuf/compiler/objectivec/options.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+class FileGenerator {
+ public:
+  // Wrapper for some common state that is shared between file generations to
+  // improve performance when more than one file is generated at a time.
+  struct CommonState {
+    CommonState() = default;
+
+    std::vector<const FileDescriptor*>
+    CollectMinimalFileDepsContainingExtensions(const FileDescriptor* file);
+
+   private:
+    struct MinDepsEntry {
+      bool has_extensions;
+      // The minimal dependencies that cover all the dependencies with
+      // extensions.
+      absl::flat_hash_set<const FileDescriptor*> min_deps;
+      absl::flat_hash_set<const FileDescriptor*> transitive_deps;
+    };
+    const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal(
+        const FileDescriptor* file);
+    absl::flat_hash_map<const FileDescriptor*, MinDepsEntry> deps_info_cache;
+  };
+
+  FileGenerator(const FileDescriptor* file,
+                const GenerationOptions& generation_options,
+                CommonState& common_state);
+  ~FileGenerator() = default;
+
+  FileGenerator(const FileGenerator&) = delete;
+  FileGenerator& operator=(const FileGenerator&) = delete;
+
+  void GenerateHeader(io::Printer* p) const;
+  void GenerateSource(io::Printer* p) const;
+
+  enum class GeneratedFileType : int { kHeader, kSource };
+
+  void GenerateFile(io::Printer* p, GeneratedFileType file_type,
+                    const std::vector<std::string>& ignored_warnings,
+                    const std::vector<const FileDescriptor*>& extra_files,
+                    std::function<void()> body) const;
+  void GenerateFile(io::Printer* p, GeneratedFileType file_type,
+                    std::function<void()> body) const {
+    GenerateFile(p, file_type, {}, {}, body);
+  }
+
+  void PrintRootImplementation(
+      io::Printer* p,
+      const std::vector<const FileDescriptor*>& deps_with_extensions) const;
+  void PrintRootExtensionRegistryImplementation(
+      io::Printer* p,
+      const std::vector<const FileDescriptor*>& deps_with_extensions) const;
+  void PrintFileDescriptorImplementation(io::Printer* p) const;
+
+  bool HeadersUseForwardDeclarations() const {
+    // The bundled protos (WKTs) don't make use of forward declarations.
+    return !is_bundled_proto_ &&
+           generation_options_.headers_use_forward_declarations;
+  }
+
+ private:
+  const FileDescriptor* file_;
+  const GenerationOptions& generation_options_;
+  mutable CommonState* common_state_;
+  const std::string root_class_name_;
+  const bool is_bundled_proto_;
+
+  std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
+  std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
+  // The first file_->extension_count() are the extensions at file level scope.
+  std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc b/src/google/protobuf/compiler/objectivec/generator.cc
similarity index 83%
rename from src/google/protobuf/compiler/objectivec/objectivec_generator.cc
rename to src/google/protobuf/compiler/objectivec/generator.cc
index 9dccf14..aeb4da8 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.cc
+++ b/src/google/protobuf/compiler/objectivec/generator.cc
@@ -28,16 +28,24 @@
 // (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/objectivec/generator.h"
+
 #include <fstream>
 #include <iostream>
+#include <memory>
 #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>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/strutil.h>
+#include <utility>
+#include <vector>
+
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/strip.h"
+#include "google/protobuf/compiler/objectivec/file.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
@@ -51,7 +59,7 @@
 // invalid, `result` is unchanged.
 bool StringToBool(const std::string& value, bool* result) {
   std::string upper_value(value);
-  UpperString(&upper_value);
+  absl::AsciiStrToUpper(&upper_value);
   if (upper_value == "NO") {
     *result = false;
     return true;
@@ -66,13 +74,7 @@
 
 }  // namespace
 
-ObjectiveCGenerator::ObjectiveCGenerator() {}
-
-ObjectiveCGenerator::~ObjectiveCGenerator() {}
-
-bool ObjectiveCGenerator::HasGenerateAll() const {
-  return true;
-}
+bool ObjectiveCGenerator::HasGenerateAll() const { return true; }
 
 bool ObjectiveCGenerator::Generate(const FileDescriptor* file,
                                    const std::string& parameter,
@@ -92,14 +94,15 @@
   // options along with their values. If the option appears multiple times, only
   // the last value will be considered.
   //
-  // e.g. protoc ... --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework
+  // e.g. protoc ...
+  // --objc_opt=expected_prefixes=file.txt,generate_for_named_framework=MyFramework
 
   Options validation_options;
-  FileGenerator::GenerationOptions generation_options;
+  GenerationOptions generation_options;
 
   std::vector<std::pair<std::string, std::string> > options;
   ParseGeneratorParameter(parameter, &options);
-  for (int i = 0; i < options.size(); i++) {
+  for (size_t i = 0; i < options.size(); i++) {
     if (options[i].first == "expected_prefixes_path") {
       // Path to find a file containing the expected prefixes
       // (objc_class_prefix "PREFIX") for proto packages (package NAME). The
@@ -122,8 +125,8 @@
       // 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.
-      for (StringPiece split_piece : Split(
-               options[i].second, ";", true)) {
+      for (absl::string_view split_piece :
+           absl::StrSplit(options[i].second, ';', absl::SkipEmpty())) {
         validation_options.expected_prefixes_suppressions.push_back(
             std::string(split_piece));
       }
@@ -137,7 +140,8 @@
       // Default is "no".
       if (!StringToBool(options[i].second,
                         &validation_options.prefixes_must_be_registered)) {
-        *error = "error: Unknown value for prefixes_must_be_registered: " + options[i].second;
+        *error = "error: Unknown value for prefixes_must_be_registered: " +
+                 options[i].second;
         return false;
       }
     } else if (options[i].first == "require_prefixes") {
@@ -149,7 +153,8 @@
       // Default is "no".
       if (!StringToBool(options[i].second,
                         &validation_options.require_prefixes)) {
-        *error = "error: Unknown value for require_prefixes: " + options[i].second;
+        *error =
+            "error: Unknown value for require_prefixes: " + options[i].second;
         return false;
       }
     } else if (options[i].first == "generate_for_named_framework") {
@@ -162,7 +167,8 @@
       // the "default" framework name used for everything that wasn't mapped by
       // the mapping file.
       generation_options.generate_for_named_framework = options[i].second;
-    } else if (options[i].first == "named_framework_to_proto_path_mappings_path") {
+    } else if (options[i].first ==
+               "named_framework_to_proto_path_mappings_path") {
       // Path to find a file containing the list of framework names and proto
       // files. The generator uses this to decide if a proto file
       // referenced should use a framework style import vs. a user level import
@@ -183,17 +189,20 @@
       // 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;
+      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, "/");
+      generation_options.runtime_import_prefix =
+          std::string(absl::StripSuffix(options[i].second, "/"));
     } else if (options[i].first == "package_to_prefix_mappings_path") {
       // Path to use for when loading the objc class prefix mappings to use.
-      // The `objc_class_prefix` file option is always honored first if one is present.
-      // This option also has precedent over the use_package_as_prefix option.
+      // The `objc_class_prefix` file option is always honored first if one is
+      // present. This option also has precedent over the use_package_as_prefix
+      // option.
       //
       // The format of the file is:
       //   - An entry is a line of "package=prefix".
@@ -230,10 +239,15 @@
       //   - A comment can go on a line after a expected package/prefix pair.
       //     (i.e. - "some.proto.package # comment")
       SetProtoPackagePrefixExceptionList(options[i].second);
+    } else if (options[i].first == "package_as_prefix_forced_prefix") {
+      // String to use as the prefix when deriving a prefix from the package
+      // name. So this only applies when use_package_as_prefix is also used.
+      SetForcedPackagePrefix(options[i].second);
     } else if (options[i].first == "headers_use_forward_declarations") {
       if (!StringToBool(options[i].second,
                         &generation_options.headers_use_forward_declarations)) {
-        *error = "error: Unknown value for headers_use_forward_declarations: " + options[i].second;
+        *error = "error: Unknown value for headers_use_forward_declarations: " +
+                 options[i].second;
         return false;
       }
     } else {
@@ -246,9 +260,9 @@
 
   // 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) {
+  bool headers_only = getenv("GPB_OBJC_HEADERS_ONLY") != nullptr;
+  absl::flat_hash_set<std::string> skip_impls;
+  if (getenv("GPB_OBJC_SKIP_IMPLS_FILE") != nullptr) {
     std::ifstream skip_file(getenv("GPB_OBJC_SKIP_IMPLS_FILE"));
     if (skip_file.is_open()) {
       std::string line;
@@ -272,7 +286,7 @@
   FileGenerator::CommonState state;
   for (int i = 0; i < files.size(); i++) {
     const FileDescriptor* file = files[i];
-    FileGenerator file_generator(file, generation_options, state);
+    const FileGenerator file_generator(file, generation_options, state);
     std::string filepath = FilePath(file);
 
     // Generate header.
@@ -281,6 +295,11 @@
           context->Open(filepath + ".pbobjc.h"));
       io::Printer printer(output.get(), '$');
       file_generator.GenerateHeader(&printer);
+      if (printer.failed()) {
+        *error = absl::StrCat("error: internal error generating a header: ",
+                              file->name());
+        return false;
+      }
     }
 
     // Generate m file.
@@ -289,6 +308,12 @@
           context->Open(filepath + ".pbobjc.m"));
       io::Printer printer(output.get(), '$');
       file_generator.GenerateSource(&printer);
+      if (printer.failed()) {
+        *error =
+            absl::StrCat("error: internal error generating an implementation:",
+                         file->name());
+        return false;
+      }
     }
   }
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_generator.h b/src/google/protobuf/compiler/objectivec/generator.h
similarity index 91%
rename from src/google/protobuf/compiler/objectivec/objectivec_generator.h
rename to src/google/protobuf/compiler/objectivec/generator.h
index 1dbc666..490bbff7d 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_generator.h
+++ b/src/google/protobuf/compiler/objectivec/generator.h
@@ -34,10 +34,13 @@
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
 
 #include <string>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/descriptor.h>
+#include <vector>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+
+// Must be included last
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -50,8 +53,8 @@
 // CodeGenerator with the CommandLineInterface in your main() function.
 class PROTOC_EXPORT ObjectiveCGenerator : public CodeGenerator {
  public:
-  ObjectiveCGenerator();
-  ~ObjectiveCGenerator();
+  ObjectiveCGenerator() = default;
+  ~ObjectiveCGenerator() override = default;
 
   ObjectiveCGenerator(const ObjectiveCGenerator&) = delete;
   ObjectiveCGenerator& operator=(const ObjectiveCGenerator&) = delete;
@@ -74,6 +77,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/objectivec/helpers.cc b/src/google/protobuf/compiler/objectivec/helpers.cc
new file mode 100644
index 0000000..2c376d7
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/helpers.cc
@@ -0,0 +1,395 @@
+// 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/objectivec/helpers.h"
+
+#include <string>
+#include <vector>
+
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/stubs/common.h"
+
+// 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 errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+std::string EscapeTrigraphs(absl::string_view to_escape) {
+  return absl::StrReplaceAll(to_escape, {{"?", "\\?"}});
+}
+
+namespace {
+
+std::string GetZeroEnumNameForFlagType(const FlagType flag_type) {
+  switch (flag_type) {
+    case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+      return "GPBDescriptorInitializationFlag_None";
+    case FLAGTYPE_EXTENSION:
+      return "GPBExtensionNone";
+    case FLAGTYPE_FIELD:
+      return "GPBFieldNone";
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      return "0";
+  }
+}
+
+std::string GetEnumNameForFlagType(const FlagType flag_type) {
+  switch (flag_type) {
+    case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
+      return "GPBDescriptorInitializationFlags";
+    case FLAGTYPE_EXTENSION:
+      return "GPBExtensionOptions";
+    case FLAGTYPE_FIELD:
+      return "GPBFieldFlags";
+    default:
+      GOOGLE_LOG(FATAL) << "Can't get here.";
+      return std::string();
+  }
+}
+
+std::string HandleExtremeFloatingPoint(std::string val, bool add_float_suffix) {
+  if (val == "nan") {
+    return "NAN";
+  } else if (val == "inf") {
+    return "INFINITY";
+  } else if (val == "-inf") {
+    return "-INFINITY";
+  } else {
+    // float strings with ., e or E need to have f appended
+    if (add_float_suffix &&
+        (absl::StrContains(val, '.') || absl::StrContains(val, 'e') ||
+         absl::StrContains(val, 'E'))) {
+      val += "f";
+    }
+    return val;
+  }
+}
+
+}  // namespace
+
+std::string GetCapitalizedType(const FieldDescriptor* field) {
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_INT32:
+      return "Int32";
+    case FieldDescriptor::TYPE_UINT32:
+      return "UInt32";
+    case FieldDescriptor::TYPE_SINT32:
+      return "SInt32";
+    case FieldDescriptor::TYPE_FIXED32:
+      return "Fixed32";
+    case FieldDescriptor::TYPE_SFIXED32:
+      return "SFixed32";
+    case FieldDescriptor::TYPE_INT64:
+      return "Int64";
+    case FieldDescriptor::TYPE_UINT64:
+      return "UInt64";
+    case FieldDescriptor::TYPE_SINT64:
+      return "SInt64";
+    case FieldDescriptor::TYPE_FIXED64:
+      return "Fixed64";
+    case FieldDescriptor::TYPE_SFIXED64:
+      return "SFixed64";
+    case FieldDescriptor::TYPE_FLOAT:
+      return "Float";
+    case FieldDescriptor::TYPE_DOUBLE:
+      return "Double";
+    case FieldDescriptor::TYPE_BOOL:
+      return "Bool";
+    case FieldDescriptor::TYPE_STRING:
+      return "String";
+    case FieldDescriptor::TYPE_BYTES:
+      return "Bytes";
+    case FieldDescriptor::TYPE_ENUM:
+      return "Enum";
+    case FieldDescriptor::TYPE_GROUP:
+      return "Group";
+    case FieldDescriptor::TYPE_MESSAGE:
+      return "Message";
+  }
+
+  // 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 std::string();
+}
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
+  switch (field_type) {
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_SFIXED32:
+      return OBJECTIVECTYPE_INT32;
+
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_FIXED32:
+      return OBJECTIVECTYPE_UINT32;
+
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_SFIXED64:
+      return OBJECTIVECTYPE_INT64;
+
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_FIXED64:
+      return OBJECTIVECTYPE_UINT64;
+
+    case FieldDescriptor::TYPE_FLOAT:
+      return OBJECTIVECTYPE_FLOAT;
+
+    case FieldDescriptor::TYPE_DOUBLE:
+      return OBJECTIVECTYPE_DOUBLE;
+
+    case FieldDescriptor::TYPE_BOOL:
+      return OBJECTIVECTYPE_BOOLEAN;
+
+    case FieldDescriptor::TYPE_STRING:
+      return OBJECTIVECTYPE_STRING;
+
+    case FieldDescriptor::TYPE_BYTES:
+      return OBJECTIVECTYPE_DATA;
+
+    case FieldDescriptor::TYPE_ENUM:
+      return OBJECTIVECTYPE_ENUM;
+
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+      return OBJECTIVECTYPE_MESSAGE;
+  }
+
+  // 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 OBJECTIVECTYPE_INT32;
+}
+
+std::string GPBGenericValueFieldName(const FieldDescriptor* field) {
+  // Returns the field within the GPBGenericValue union to use for the given
+  // field.
+  if (field->is_repeated()) {
+    return "valueMessage";
+  }
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      return "valueInt32";
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return "valueUInt32";
+    case FieldDescriptor::CPPTYPE_INT64:
+      return "valueInt64";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return "valueUInt64";
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return "valueFloat";
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return "valueDouble";
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return "valueBool";
+    case FieldDescriptor::CPPTYPE_STRING:
+      if (field->type() == FieldDescriptor::TYPE_BYTES) {
+        return "valueData";
+      } else {
+        return "valueString";
+      }
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return "valueEnum";
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return "valueMessage";
+  }
+
+  // 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 std::string();
+}
+
+std::string DefaultValue(const FieldDescriptor* field) {
+  // Repeated fields don't have defaults.
+  if (field->is_repeated()) {
+    return "nil";
+  }
+
+  // Switch on cpp_type since we need to know which default_value_* method
+  // of FieldDescriptor to call.
+  switch (field->cpp_type()) {
+    case FieldDescriptor::CPPTYPE_INT32:
+      // gcc and llvm reject the decimal form of kint32min and kint64min.
+      if (field->default_value_int32() == INT_MIN) {
+        return "-0x80000000";
+      }
+      return absl::StrCat(field->default_value_int32());
+    case FieldDescriptor::CPPTYPE_UINT32:
+      return absl::StrCat(field->default_value_uint32()) + "U";
+    case FieldDescriptor::CPPTYPE_INT64:
+      // gcc and llvm reject the decimal form of kint32min and kint64min.
+      if (field->default_value_int64() == LLONG_MIN) {
+        return "-0x8000000000000000LL";
+      }
+      return absl::StrCat(field->default_value_int64()) + "LL";
+    case FieldDescriptor::CPPTYPE_UINT64:
+      return absl::StrCat(field->default_value_uint64()) + "ULL";
+    case FieldDescriptor::CPPTYPE_DOUBLE:
+      return HandleExtremeFloatingPoint(
+          io::SimpleDtoa(field->default_value_double()), false);
+    case FieldDescriptor::CPPTYPE_FLOAT:
+      return HandleExtremeFloatingPoint(
+          io::SimpleFtoa(field->default_value_float()), true);
+    case FieldDescriptor::CPPTYPE_BOOL:
+      return field->default_value_bool() ? "YES" : "NO";
+    case FieldDescriptor::CPPTYPE_STRING: {
+      const bool has_default_value = field->has_default_value();
+      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
+        // default for both strings and data.
+        return "nil";
+      }
+      if (field->type() == FieldDescriptor::TYPE_BYTES) {
+        // We want constant fields in our data structures so we can
+        // declare them as static. To achieve this we cheat and stuff
+        // a escaped c string (prefixed with a length) into the data
+        // field, and cast it to an (NSData*) so it will compile.
+        // The runtime library knows how to handle it.
+
+        // Must convert to a standard byte order for packing length into
+        // a cstring.
+        uint32_t length = ghtonl(default_string.length());
+        std::string bytes((const char*)&length, sizeof(length));
+        bytes.append(default_string);
+        return "(NSData*)\"" + EscapeTrigraphs(absl::CEscape(bytes)) + "\"";
+      } else {
+        return "@\"" + EscapeTrigraphs(absl::CEscape(default_string)) + "\"";
+      }
+    }
+    case FieldDescriptor::CPPTYPE_ENUM:
+      return EnumValueName(field->default_value_enum());
+    case FieldDescriptor::CPPTYPE_MESSAGE:
+      return "nil";
+  }
+
+  // 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 std::string();
+}
+
+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];
+  }
+  std::string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
+  for (size_t i = 0; i != strings.size(); ++i) {
+    if (i > 0) {
+      string.append(" | ");
+    }
+    string.append(strings[i]);
+  }
+  string.append(")");
+  return string;
+}
+
+std::string ObjCClass(const std::string& class_name) {
+  return std::string("GPBObjCClass(") + class_name + ")";
+}
+
+std::string ObjCClassDeclaration(const std::string& class_name) {
+  return std::string("GPBObjCClassDeclaration(") + class_name + ");";
+}
+
+std::string BuildCommentsString(const SourceLocation& location,
+                                bool prefer_single_line) {
+  const std::string& comments = location.leading_comments.empty()
+                                    ? location.trailing_comments
+                                    : location.leading_comments;
+  std::vector<std::string> lines;
+  lines = absl::StrSplit(comments, '\n', absl::AllowEmpty());
+  while (!lines.empty() && lines.back().empty()) {
+    lines.pop_back();
+  }
+  // If there are no comments, just return an empty string.
+  if (lines.empty()) {
+    return "";
+  }
+
+  std::string prefix;
+  std::string suffix;
+  std::string final_comments;
+  std::string epilogue;
+
+  bool add_leading_space = false;
+
+  if (prefer_single_line && lines.size() == 1) {
+    prefix = "/** ";
+    suffix = " */\n";
+  } else {
+    prefix = "* ";
+    suffix = "\n";
+    final_comments += "/**\n";
+    epilogue = " **/\n";
+    add_leading_space = true;
+  }
+
+  for (size_t i = 0; i < lines.size(); i++) {
+    std::string line = absl::StrReplaceAll(
+        absl::StripPrefix(lines[i], " "),
+        {// HeaderDoc and appledoc use '\' and '@' for markers; escape them.
+         {"\\", "\\\\"},
+         {"@", "\\@"},
+         // Decouple / from * to not have inline comments inside comments.
+         {"/*", "/\\*"},
+         {"*/", "*\\/"}});
+    line = prefix + line;
+    absl::StripAsciiWhitespace(&line);
+    // If not a one line, need to add the first space before *, as
+    // absl::StripAsciiWhitespace would have removed it.
+    line = (add_leading_space ? " " : "") + line;
+    final_comments += line + suffix;
+  }
+  final_comments += epilogue;
+  return final_comments;
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/helpers.h b/src/google/protobuf/compiler/objectivec/helpers.h
new file mode 100644
index 0000000..76766b2
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/helpers.h
@@ -0,0 +1,161 @@
+// 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.
+
+// Helper functions for generating ObjectiveC code.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
+
+#include <string>
+#include <vector>
+
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// Escape C++ trigraphs by escaping question marks to "\?".
+std::string EscapeTrigraphs(absl::string_view to_escape);
+
+enum ObjectiveCType {
+  OBJECTIVECTYPE_INT32,
+  OBJECTIVECTYPE_UINT32,
+  OBJECTIVECTYPE_INT64,
+  OBJECTIVECTYPE_UINT64,
+  OBJECTIVECTYPE_FLOAT,
+  OBJECTIVECTYPE_DOUBLE,
+  OBJECTIVECTYPE_BOOLEAN,
+  OBJECTIVECTYPE_STRING,
+  OBJECTIVECTYPE_DATA,
+  OBJECTIVECTYPE_ENUM,
+  OBJECTIVECTYPE_MESSAGE
+};
+
+enum FlagType {
+  FLAGTYPE_DESCRIPTOR_INITIALIZATION,
+  FLAGTYPE_EXTENSION,
+  FLAGTYPE_FIELD
+};
+
+std::string GetCapitalizedType(const FieldDescriptor* field);
+
+ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type);
+
+inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) {
+  return GetObjectiveCType(field->type());
+}
+
+inline bool IsPrimitiveType(const FieldDescriptor* field) {
+  ObjectiveCType type = GetObjectiveCType(field);
+  switch (type) {
+    case OBJECTIVECTYPE_INT32:
+    case OBJECTIVECTYPE_UINT32:
+    case OBJECTIVECTYPE_INT64:
+    case OBJECTIVECTYPE_UINT64:
+    case OBJECTIVECTYPE_FLOAT:
+    case OBJECTIVECTYPE_DOUBLE:
+    case OBJECTIVECTYPE_BOOLEAN:
+    case OBJECTIVECTYPE_ENUM:
+      return true;
+      break;
+    default:
+      return false;
+  }
+}
+
+inline bool IsReferenceType(const FieldDescriptor* field) {
+  return !IsPrimitiveType(field);
+}
+
+std::string GPBGenericValueFieldName(const FieldDescriptor* field);
+std::string DefaultValue(const FieldDescriptor* field);
+
+std::string BuildFlagsString(const FlagType type,
+                             const std::vector<std::string>& strings);
+
+// Returns a symbol that can be used in C code to refer to an Objective C
+// class without initializing the class.
+std::string ObjCClass(const std::string& class_name);
+
+// Declares an Objective C class without initializing the class so that it can
+// be refrerred to by ObjCClass.
+std::string ObjCClassDeclaration(const std::string& class_name);
+
+// Builds HeaderDoc/appledoc style comments out of the comments in the .proto
+// file.
+std::string BuildCommentsString(const SourceLocation& location,
+                                bool prefer_single_line);
+
+template <class TDescriptor>
+std::string GetOptionalDeprecatedAttribute(const TDescriptor* descriptor,
+                                           const FileDescriptor* file = nullptr,
+                                           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
+  // field or enum value with when the file is deprecated.
+  bool isFileLevelDeprecation = false;
+  if (!isDeprecated && file) {
+    isFileLevelDeprecation = file->options().deprecated();
+    isDeprecated = isFileLevelDeprecation;
+  }
+  if (isDeprecated) {
+    std::string message;
+    const FileDescriptor* sourceFile = descriptor->file();
+    if (isFileLevelDeprecation) {
+      message = sourceFile->name() + " is deprecated.";
+    } else {
+      message = descriptor->full_name() + " is deprecated (see " +
+                sourceFile->name() + ").";
+    }
+
+    std::string result = std::string("GPB_DEPRECATED_MSG(\"") + message + "\")";
+    if (preSpace) {
+      result.insert(0, " ");
+    }
+    if (postNewline) {
+      result.append("\n");
+    }
+    return result;
+  } else {
+    return "";
+  }
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
diff --git a/src/google/protobuf/compiler/objectivec/import_writer.cc b/src/google/protobuf/compiler/objectivec/import_writer.cc
new file mode 100644
index 0000000..63a8a04
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/import_writer.cc
@@ -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.
+
+#include "google/protobuf/compiler/objectivec/import_writer.h"
+
+#include <iostream>
+#include <ostream>
+#include <string>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/match.h"
+#include "google/protobuf/compiler/objectivec/line_consumer.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/io/printer.h"
+
+// 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 errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+class ProtoFrameworkCollector : public LineConsumer {
+ public:
+  explicit ProtoFrameworkCollector(
+      absl::flat_hash_map<std::string, std::string>*
+          inout_proto_file_to_framework_name)
+      : map_(inout_proto_file_to_framework_name) {}
+
+  bool ConsumeLine(absl::string_view line, std::string* out_error) override;
+
+ private:
+  absl::flat_hash_map<std::string, std::string>* map_;
+};
+
+bool ProtoFrameworkCollector::ConsumeLine(absl::string_view line,
+                                          std::string* out_error) {
+  int offset = line.find(':');
+  if (offset == absl::string_view::npos) {
+    *out_error = absl::StrCat(
+        "Framework/proto file mapping line without colon sign: '", line, "'.");
+    return false;
+  }
+  absl::string_view framework_name =
+      absl::StripAsciiWhitespace(line.substr(0, offset));
+  absl::string_view proto_file_list =
+      absl::StripAsciiWhitespace(line.substr(offset + 1));
+
+  int start = 0;
+  while (start < proto_file_list.length()) {
+    offset = proto_file_list.find(',', start);
+    if (offset == absl::string_view::npos) {
+      offset = proto_file_list.length();
+    }
+
+    absl::string_view proto_file = absl::StripAsciiWhitespace(
+        proto_file_list.substr(start, offset - start));
+    if (!proto_file.empty()) {
+      auto existing_entry = map_->find(proto_file);
+      if (existing_entry != map_->end()) {
+        std::cerr << "warning: duplicate proto file reference, replacing "
+                     "framework entry for '"
+                  << proto_file << "' with '" << framework_name << "' (was '"
+                  << existing_entry->second << "')." << std::endl;
+        std::cerr.flush();
+      }
+
+      if (absl::StrContains(proto_file, ' ')) {
+        std::cerr << "note: framework mapping file had a proto file with a "
+                     "space in, hopefully that isn't a missing comma: '"
+                  << proto_file << "'" << std::endl;
+        std::cerr.flush();
+      }
+
+      (*map_)[proto_file] = std::string(framework_name);
+    }
+
+    start = offset + 1;
+  }
+
+  return true;
+}
+
+}  // namespace
+
+ImportWriter::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 for_bundled_proto)
+    : 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),
+      for_bundled_proto_(for_bundled_proto),
+      need_to_parse_mapping_file_(true) {}
+
+void ImportWriter::AddFile(const FileDescriptor* file,
+                           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 (for_bundled_proto_) {
+      const std::string header_name =
+          "GPB" + FilePathBasename(file) + header_extension;
+      protobuf_imports_.push_back(header_name);
+    }
+    return;
+  }
+
+  // Lazy parse any mappings.
+  if (need_to_parse_mapping_file_) {
+    ParseFrameworkMappings();
+  }
+
+  auto proto_lookup = proto_file_to_framework_name_.find(file->name());
+  if (proto_lookup != proto_file_to_framework_name_.end()) {
+    other_framework_imports_.push_back(
+        proto_lookup->second + "/" + FilePathBasename(file) + header_extension);
+    return;
+  }
+
+  if (!generate_for_named_framework_.empty()) {
+    other_framework_imports_.push_back(generate_for_named_framework_ + "/" +
+                                       FilePathBasename(file) +
+                                       header_extension);
+    return;
+  }
+
+  other_imports_.push_back(FilePath(file) + header_extension);
+}
+
+void ImportWriter::AddRuntimeImport(const std::string& header_name) {
+  protobuf_imports_.push_back(header_name);
+}
+
+void ImportWriter::PrintFileImports(io::Printer* p) const {
+  if (!other_framework_imports_.empty()) {
+    for (const auto& header : other_framework_imports_) {
+      p->Print("#import <$header$>\n", "header", header);
+    }
+  }
+
+  if (!other_imports_.empty()) {
+    if (!other_framework_imports_.empty()) {
+      p->Print("\n");
+    }
+
+    for (const auto& header : other_imports_) {
+      p->Print("#import \"$header$\"\n", "header", header);
+    }
+  }
+}
+
+void ImportWriter::PrintRuntimeImports(io::Printer* p,
+                                       bool default_cpp_symbol) const {
+  // Given an override, use that.
+  if (!runtime_import_prefix_.empty()) {
+    for (const auto& header : protobuf_imports_) {
+      p->Print("#import \"$import_prefix$/$header$\"\n", "header", header,
+               "import_prefix", runtime_import_prefix_);
+    }
+    return;
+  }
+
+  // If bundled, no need to do the framework support below.
+  if (for_bundled_proto_) {
+    GOOGLE_DCHECK(!default_cpp_symbol);
+    for (const auto& header : protobuf_imports_) {
+      p->Print("#import \"$header$\"\n", "header", header);
+    }
+    return;
+  }
+
+  const std::string cpp_symbol(
+      ProtobufFrameworkImportSymbol(ProtobufLibraryFrameworkName));
+
+  if (default_cpp_symbol) {
+    p->Print(
+        // clang-format off
+        "// 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",
+        // clang-format on
+        "cpp_symbol", cpp_symbol);
+  }
+
+  p->Print("#if $cpp_symbol$\n", "cpp_symbol", cpp_symbol);
+  for (const auto& header : protobuf_imports_) {
+    p->Print(" #import <$framework_name$/$header$>\n", "framework_name",
+             ProtobufLibraryFrameworkName, "header", header);
+  }
+  p->Print("#else\n");
+  for (const auto& header : protobuf_imports_) {
+    p->Print(" #import \"$header$\"\n", "header", header);
+  }
+  p->Print("#endif\n");
+}
+
+void ImportWriter::ParseFrameworkMappings() {
+  need_to_parse_mapping_file_ = false;
+  if (named_framework_to_proto_path_mappings_path_.empty()) {
+    return;  // Nothing to do.
+  }
+
+  ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
+  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_ << " : "
+              << parse_error << std::endl;
+    std::cerr.flush();
+  }
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/import_writer.h b/src/google/protobuf/compiler/objectivec/import_writer.h
new file mode 100644
index 0000000..9f5e0a0
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/import_writer.h
@@ -0,0 +1,82 @@
+// 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_OBJECTIVEC_IMPORT_WRITER_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__
+
+#include <string>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// Helper class for parsing framework import mappings and generating
+// import statements.
+class ImportWriter {
+ public:
+  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 for_bundled_proto);
+  ~ImportWriter() = default;
+
+  void AddFile(const FileDescriptor* file, const std::string& header_extension);
+  void AddRuntimeImport(const std::string& header_name);
+
+  void PrintFileImports(io::Printer* p) const;
+  void PrintRuntimeImports(io::Printer* p, bool default_cpp_symbol) const;
+
+ private:
+  void ParseFrameworkMappings();
+
+  const std::string generate_for_named_framework_;
+  const std::string named_framework_to_proto_path_mappings_path_;
+  const std::string runtime_import_prefix_;
+  absl::flat_hash_map<std::string, std::string> proto_file_to_framework_name_;
+  bool for_bundled_proto_;
+  bool need_to_parse_mapping_file_;
+
+  std::vector<std::string> protobuf_imports_;
+  std::vector<std::string> other_framework_imports_;
+  std::vector<std::string> other_imports_;
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_IMPORT_WRITER_H__
diff --git a/src/google/protobuf/compiler/objectivec/line_consumer.cc b/src/google/protobuf/compiler/objectivec/line_consumer.cc
new file mode 100644
index 0000000..a62a7b9
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/line_consumer.cc
@@ -0,0 +1,212 @@
+// 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 _MSC_VER
+#include <unistd.h>
+#endif
+#include <errno.h>
+#include <fcntl.h>
+#include <stdlib.h>
+
+#include <climits>
+#include <fstream>
+#include <iostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/objectivec/line_consumer.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+
+#ifdef _WIN32
+#include "google/protobuf/io/io_win32.h"
+#endif
+
+// 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 errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// <io.h> is transitively included in this file. Import the functions explicitly
+// in this port namespace to avoid ambiguous definition.
+namespace posix {
+#ifdef _WIN32
+using google::protobuf::io::win32::open;
+#else   // !_WIN32
+using ::open;
+#endif  // _WIN32
+}  // namespace posix
+
+namespace {
+
+bool ascii_isnewline(char c) { return c == '\n' || c == '\r'; }
+
+bool ReadLine(absl::string_view* input, absl::string_view* line) {
+  for (int len = 0; len < input->size(); ++len) {
+    if (ascii_isnewline((*input)[len])) {
+      *line = absl::string_view(input->data(), len);
+      ++len;  // advance over the newline
+      *input = absl::string_view(input->data() + len, input->size() - len);
+      return true;
+    }
+  }
+  return false;  // Ran out of input with no newline.
+}
+
+void RemoveComment(absl::string_view* input) {
+  int offset = input->find('#');
+  if (offset != absl::string_view::npos) {
+    input->remove_suffix(input->length() - offset);
+  }
+}
+
+class Parser {
+ public:
+  explicit Parser(LineConsumer* line_consumer)
+      : line_consumer_(line_consumer), line_(0) {}
+
+  // Feeds in some input, parse what it can, returning success/failure. Calling
+  // again after an error is undefined.
+  bool ParseChunk(absl::string_view chunk, std::string* out_error);
+
+  // Should be called to finish parsing (after all input has been provided via
+  // successful calls to ParseChunk(), calling after a ParseChunk() failure is
+  // undefined). Returns success/failure.
+  bool Finish(std::string* out_error);
+
+  int last_line() const { return line_; }
+
+ private:
+  LineConsumer* line_consumer_;
+  int line_;
+  std::string leftover_;
+};
+
+bool Parser::ParseChunk(absl::string_view chunk, std::string* out_error) {
+  absl::string_view full_chunk;
+  if (!leftover_.empty()) {
+    leftover_ += std::string(chunk);
+    full_chunk = absl::string_view(leftover_);
+  } else {
+    full_chunk = chunk;
+  }
+
+  absl::string_view line;
+  while (ReadLine(&full_chunk, &line)) {
+    ++line_;
+    RemoveComment(&line);
+    line = absl::StripAsciiWhitespace(line);
+    if (!line.empty() && !line_consumer_->ConsumeLine(line, out_error)) {
+      if (out_error->empty()) {
+        *out_error = "ConsumeLine failed without setting an error.";
+      }
+      leftover_.clear();
+      return false;
+    }
+  }
+
+  if (full_chunk.empty()) {
+    leftover_.clear();
+  } else {
+    leftover_ = std::string(full_chunk);
+  }
+  return true;
+}
+
+bool Parser::Finish(std::string* out_error) {
+  // If there is still something to go, flush it with a newline.
+  if (!leftover_.empty() && !ParseChunk("\n", out_error)) {
+    return false;
+  }
+  // This really should never fail if ParseChunk succeeded, but check to be
+  // sure.
+  if (!leftover_.empty()) {
+    *out_error = "ParseSimple Internal error: finished with pending data.";
+    return false;
+  }
+  return true;
+}
+
+}  // namespace
+
+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 =
+        absl::StrCat("error: Unable to open \"", path, "\", ", strerror(errno));
+    return false;
+  }
+  io::FileInputStream file_stream(fd);
+  file_stream.SetCloseOnDelete(true);
+
+  return ParseSimpleStream(file_stream, path, line_consumer, out_error);
+}
+
+bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
+                       const std::string& stream_name,
+                       LineConsumer* line_consumer, std::string* out_error) {
+  std::string local_error;
+  Parser parser(line_consumer);
+  const void* buf;
+  int buf_len;
+  while (input_stream.Next(&buf, &buf_len)) {
+    if (buf_len == 0) {
+      continue;
+    }
+
+    if (!parser.ParseChunk(
+            absl::string_view(static_cast<const char*>(buf), buf_len),
+            &local_error)) {
+      *out_error = absl::StrCat("error: ", stream_name, " Line ",
+                                parser.last_line(), ", ", local_error);
+      return false;
+    }
+  }
+  if (!parser.Finish(&local_error)) {
+    *out_error = absl::StrCat("error: ", stream_name, " Line ",
+                              parser.last_line(), ", ", local_error);
+    return false;
+  }
+  return true;
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/line_consumer.h
similarity index 62%
copy from src/google/protobuf/compiler/objectivec/objectivec_oneof.h
copy to src/google/protobuf/compiler/objectivec/line_consumer.h
index 034f07f..0b63f34 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+++ b/src/google/protobuf/compiler/objectivec/line_consumer.h
@@ -28,49 +28,47 @@
 // (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_OBJECTIVEC_ONEOF_H__
-#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_LINE_CONSUMER_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_LINE_CONSUMER_H__
 
 #include <string>
-#include <set>
 #include <vector>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+
+#include "google/protobuf/io/zero_copy_stream.h"
+
+// Must be included last
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace objectivec {
 
-class OneofGenerator {
+// TODO(b/250947994): PROTOC_EXPORT is only used to allow the CMake build to
+// find/link these in the unittest, this is not public api.
+
+// Helper for parsing simple files.
+class PROTOC_EXPORT LineConsumer {
  public:
-  explicit OneofGenerator(const OneofDescriptor* descriptor);
-  ~OneofGenerator();
-
-  OneofGenerator(const OneofGenerator&) = delete;
-  OneofGenerator& operator=(const OneofGenerator&) = delete;
-
-  void SetOneofIndexBase(int index_base);
-
-  void GenerateCaseEnum(io::Printer* printer);
-
-  void GeneratePublicCasePropertyDeclaration(io::Printer* printer);
-  void GenerateClearFunctionDeclaration(io::Printer* printer);
-
-  void GeneratePropertyImplementation(io::Printer* printer);
-  void GenerateClearFunctionImplementation(io::Printer* printer);
-
-  std::string DescriptorName(void) const;
-  std::string HasIndexAsString(void) const;
-
- private:
-  const OneofDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  LineConsumer() = default;
+  virtual ~LineConsumer() = default;
+  virtual bool ConsumeLine(absl::string_view line, std::string* out_error) = 0;
 };
 
+bool PROTOC_EXPORT ParseSimpleFile(const std::string& path,
+                                   LineConsumer* line_consumer,
+                                   std::string* out_error);
+
+bool PROTOC_EXPORT ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
+                                     const std::string& stream_name,
+                                     LineConsumer* line_consumer,
+                                     std::string* out_error);
+
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
 
-#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_LINE_CONSUMER_H__
diff --git a/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc b/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc
new file mode 100644
index 0000000..d346c3f
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/line_consumer_unittest.cc
@@ -0,0 +1,183 @@
+// 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 "google/protobuf/compiler/objectivec/line_consumer.h"
+
+#include <string>
+#include <tuple>
+#include <utility>
+#include <vector>
+
+#include <gtest/gtest.h>
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+namespace {
+
+class TestLineCollector : public LineConsumer {
+ public:
+  explicit TestLineCollector(std::vector<std::string>* inout_lines,
+                             const std::string* reject_line = nullptr,
+                             bool skip_msg = false)
+      : lines_(inout_lines), reject_(reject_line), skip_msg_(skip_msg) {}
+
+  bool ConsumeLine(absl::string_view line, std::string* out_error) override {
+    if (reject_ && *reject_ == line) {
+      if (!skip_msg_) {
+        *out_error = std::string("Rejected '") + *reject_ + "'";
+      }
+      return false;
+    }
+    if (lines_) {
+      lines_->emplace_back(line);
+    }
+    return true;
+  }
+
+ private:
+  std::vector<std::string>* lines_;
+  const std::string* reject_;
+  bool skip_msg_;
+};
+
+const int kBlockSizes[] = {-1, 1, 2, 5, 64};
+const int kBlockSizeCount = ABSL_ARRAYSIZE(kBlockSizes);
+
+TEST(ObjCHelper, ParseSimple_BasicsSuccess) {
+  const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
+      {"", {}},
+      {"a", {"a"}},
+      {"a c", {"a c"}},
+      {" a c ", {"a c"}},
+      {"\ta c ", {"a c"}},
+      {"abc\n", {"abc"}},
+      {"abc\nd f", {"abc", "d f"}},
+      {"\n abc \n def \n\n", {"abc", "def"}},
+  };
+
+  for (const auto& test : tests) {
+    for (int i = 0; i < kBlockSizeCount; i++) {
+      io::ArrayInputStream input(test.first.data(), test.first.size(),
+                                 kBlockSizes[i]);
+      std::string err_str;
+      std::vector<std::string> lines;
+      TestLineCollector collector(&lines);
+      EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+      EXPECT_EQ(lines, test.second);
+      EXPECT_TRUE(err_str.empty());
+    }
+  }
+}
+
+TEST(ObjCHelper, ParseSimple_DropsComments) {
+  const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
+      {"# nothing", {}},
+      {"#", {}},
+      {"##", {}},
+      {"\n# nothing\n", {}},
+      {"a # same line", {"a"}},
+      {"a # same line\n", {"a"}},
+      {"a\n# line\nc", {"a", "c"}},
+      {"# n o t # h i n g #", {}},
+      {"## n o # t h i n g #", {}},
+      {"a# n o t # h i n g #", {"a"}},
+      {"a\n## n o # t h i n g #", {"a"}},
+  };
+
+  for (const auto& test : tests) {
+    for (int i = 0; i < kBlockSizeCount; i++) {
+      io::ArrayInputStream input(test.first.data(), test.first.size(),
+                                 kBlockSizes[i]);
+      std::string err_str;
+      std::vector<std::string> lines;
+      TestLineCollector collector(&lines);
+      EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+      EXPECT_EQ(lines, test.second);
+      EXPECT_TRUE(err_str.empty());
+    }
+  }
+}
+
+TEST(ObjCHelper, ParseSimple_RejectLines) {
+  const std::vector<std::tuple<std::string, std::string, int>> tests = {
+      std::make_tuple("a\nb\nc", "a", 1),
+      std::make_tuple("a\nb\nc", "b", 2),
+      std::make_tuple("a\nb\nc", "c", 3),
+      std::make_tuple("a\nb\nc\n", "c", 3),
+  };
+
+  for (const auto& test : tests) {
+    for (int i = 0; i < kBlockSizeCount; i++) {
+      io::ArrayInputStream input(std::get<0>(test).data(),
+                                 std::get<0>(test).size(), kBlockSizes[i]);
+      std::string err_str;
+      TestLineCollector collector(nullptr, &std::get<1>(test));
+      EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+      std::string expected_err =
+          absl::StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '",
+                       std::get<1>(test), "'");
+      EXPECT_EQ(err_str, expected_err);
+    }
+  }
+}
+
+TEST(ObjCHelper, ParseSimple_RejectLinesNoMessage) {
+  const std::vector<std::tuple<std::string, std::string, int>> tests = {
+      std::make_tuple("a\nb\nc", "a", 1),
+      std::make_tuple("a\nb\nc", "b", 2),
+      std::make_tuple("a\nb\nc", "c", 3),
+      std::make_tuple("a\nb\nc\n", "c", 3),
+  };
+
+  for (const auto& test : tests) {
+    for (int i = 0; i < kBlockSizeCount; i++) {
+      io::ArrayInputStream input(std::get<0>(test).data(),
+                                 std::get<0>(test).size(), kBlockSizes[i]);
+      std::string err_str;
+      TestLineCollector collector(nullptr, &std::get<1>(test),
+                                  true /* skip msg */);
+      EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
+      std::string expected_err =
+          absl::StrCat("error: dummy Line ", std::get<2>(test),
+                       ", ConsumeLine failed without setting an error.");
+      EXPECT_EQ(err_str, expected_err);
+    }
+  }
+}
+
+}  // namespace
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc b/src/google/protobuf/compiler/objectivec/map_field.cc
similarity index 75%
rename from src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
rename to src/google/protobuf/compiler/objectivec/map_field.cc
index 99d7581..a9c73fd 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.cc
+++ b/src/google/protobuf/compiler/objectivec/map_field.cc
@@ -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.
 
-#include <map>
-#include <string>
+#include "google/protobuf/compiler/objectivec/map_field.h"
 
-#include <google/protobuf/compiler/objectivec/objectivec_map_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/printer.h>
+#include <string>
+#include <vector>
+
+#include "absl/container/btree_set.h"
+#include "absl/strings/match.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/names.h"
 
 namespace google {
 namespace protobuf {
@@ -76,15 +79,14 @@
   // 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 NULL;
+  return nullptr;
 }
 
 }  // namespace
 
 MapFieldGenerator::MapFieldGenerator(const FieldDescriptor* descriptor)
     : RepeatedFieldGenerator(descriptor) {
-  const FieldDescriptor* key_descriptor =
-      descriptor->message_type()->map_key();
+  const FieldDescriptor* key_descriptor = descriptor->message_type()->map_key();
   const FieldDescriptor* value_descriptor =
       descriptor->message_type()->map_value();
   value_field_generator_.reset(FieldGenerator::Make(value_descriptor));
@@ -98,19 +100,21 @@
   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") !=
-      std::string::npos) {
+  if (absl::StrContains(variables_["fieldflags"],
+                        "GPBFieldTextFormatNameCustom")) {
     field_flags.push_back("GPBFieldTextFormatNameCustom");
   }
   // Pull over some info from the value's flags.
   const std::string& value_field_flags =
       value_field_generator_->variable("fieldflags");
-  if (value_field_flags.find("GPBFieldHasDefaultValue") != std::string::npos) {
+  if (absl::StrContains(value_field_flags, "GPBFieldHasDefaultValue")) {
     field_flags.push_back("GPBFieldHasDefaultValue");
   }
-  if (value_field_flags.find("GPBFieldHasEnumDescriptor") !=
-      std::string::npos) {
+  if (absl::StrContains(value_field_flags, "GPBFieldHasEnumDescriptor")) {
     field_flags.push_back("GPBFieldHasEnumDescriptor");
+    if (absl::StrContains(value_field_flags, "GPBFieldClosedEnum")) {
+      field_flags.push_back("GPBFieldClosedEnum");
+    }
   }
 
   variables_["fieldflags"] = BuildFlagsString(FLAGTYPE_FIELD, field_flags);
@@ -134,8 +138,8 @@
     variables_["array_storage_type"] = class_name;
     if (value_is_object_type) {
       variables_["array_property_type"] =
-          class_name + "<" +
-          value_field_generator_->variable("storage_type") + "*>";
+          class_name + "<" + value_field_generator_->variable("storage_type") +
+          "*>";
     }
   }
 
@@ -145,9 +149,7 @@
       value_field_generator_->variable("dataTypeSpecific_value");
 }
 
-MapFieldGenerator::~MapFieldGenerator() {}
-
-void MapFieldGenerator::FinishInitialization(void) {
+void MapFieldGenerator::FinishInitialization() {
   RepeatedFieldGenerator::FinishInitialization();
   // Use the array_comment support in RepeatedFieldGenerator to output what the
   // values in the map are.
@@ -155,38 +157,48 @@
       descriptor_->message_type()->map_value();
   if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_ENUM) {
     variables_["array_comment"] =
-        "// |" + variables_["name"] + "| values are |" + value_field_generator_->variable("storage_type") + "|\n";
+        "// |" + variables_["name"] + "| values are |" +
+        value_field_generator_->variable("storage_type") + "|\n";
   }
 }
 
 void MapFieldGenerator::DetermineForwardDeclarations(
-    std::set<std::string>* fwd_decls,
+    absl::btree_set<std::string>* fwd_decls,
     bool include_external_types) const {
-  RepeatedFieldGenerator::DetermineForwardDeclarations(
-      fwd_decls, include_external_types);
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls,
+                                                       include_external_types);
   const FieldDescriptor* value_descriptor =
       descriptor_->message_type()->map_value();
+  // NOTE: Maps with values of enums don't have to worry about adding the
+  // forward declaration because `GPB*EnumDictionary` isn't generic to the
+  // specific enum (like say `NSDictionary<String, MyMessage>`) and thus doesn't
+  // reference the type in the header.
+  if (GetObjectiveCType(value_descriptor) != OBJECTIVECTYPE_MESSAGE) {
+    return;
+  }
+
+  const Descriptor* value_msg_descriptor = value_descriptor->message_type();
+
   // Within a file there is no requirement on the order of the messages, so
   // local references need a forward declaration. External files (not WKTs),
   // need one when requested.
-  if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE &&
-      ((include_external_types &&
-        !IsProtobufLibraryBundledProtoFile(value_descriptor->file())) ||
-       descriptor_->file() == value_descriptor->file())) {
+  if ((include_external_types &&
+       !IsProtobufLibraryBundledProtoFile(value_msg_descriptor->file())) ||
+      descriptor_->file() == value_msg_descriptor->file()) {
     const std::string& value_storage_type =
         value_field_generator_->variable("storage_type");
-    fwd_decls->insert("@class " + value_storage_type);
+    fwd_decls->insert(absl::StrCat("@class ", value_storage_type, ";"));
   }
 }
 
 void MapFieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<std::string>* fwd_decls) const {
+    absl::btree_set<std::string>* fwd_decls) const {
   // Class name is already in "storage_type".
   const FieldDescriptor* value_descriptor =
       descriptor_->message_type()->map_value();
   if (GetObjectiveCType(value_descriptor) == OBJECTIVECTYPE_MESSAGE) {
-    fwd_decls->insert(ObjCClassDeclaration(
-        value_field_generator_->variable("storage_type")));
+    fwd_decls->insert(
+        ObjCClassDeclaration(value_field_generator_->variable("storage_type")));
   }
 }
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h b/src/google/protobuf/compiler/objectivec/map_field.h
similarity index 84%
rename from src/google/protobuf/compiler/objectivec/objectivec_map_field.h
rename to src/google/protobuf/compiler/objectivec/map_field.h
index d9aa387..ee11354 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_map_field.h
+++ b/src/google/protobuf/compiler/objectivec/map_field.h
@@ -31,9 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MAP_FIELD_H__
 
-#include <map>
+#include <memory>
 #include <string>
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+#include "absl/container/btree_set.h"
+#include "google/protobuf/compiler/objectivec/field.h"
 
 namespace google {
 namespace protobuf {
@@ -44,20 +46,19 @@
   friend FieldGenerator* FieldGenerator::Make(const FieldDescriptor* field);
 
  public:
-  virtual void FinishInitialization(void) override;
+  void FinishInitialization() override;
 
   MapFieldGenerator(const MapFieldGenerator&) = delete;
   MapFieldGenerator& operator=(const MapFieldGenerator&) = delete;
 
  protected:
   explicit MapFieldGenerator(const FieldDescriptor* descriptor);
-  virtual ~MapFieldGenerator();
+  ~MapFieldGenerator() override = default;
 
-  virtual void DetermineObjectiveCClassDefinitions(
-      std::set<std::string>* fwd_decls) const override;
-  virtual void DetermineForwardDeclarations(
-      std::set<std::string>* fwd_decls,
-      bool include_external_types) const override;
+  void DetermineObjectiveCClassDefinitions(
+      absl::btree_set<std::string>* fwd_decls) const override;
+  void DetermineForwardDeclarations(absl::btree_set<std::string>* fwd_decls,
+                                    bool include_external_types) const override;
 
  private:
   std::unique_ptr<FieldGenerator> value_field_generator_;
diff --git a/src/google/protobuf/compiler/objectivec/message.cc b/src/google/protobuf/compiler/objectivec/message.cc
new file mode 100644
index 0000000..7a52b40
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/message.cc
@@ -0,0 +1,587 @@
+// 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/objectivec/message.h"
+
+#include <algorithm>
+#include <iostream>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/objectivec/extension.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/compiler/objectivec/oneof.h"
+#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+bool IsMapEntryMessage(const Descriptor* descriptor) {
+  return descriptor->options().map_entry();
+}
+
+struct FieldOrderingByNumber {
+  inline bool operator()(const FieldDescriptor* a,
+                         const FieldDescriptor* b) const {
+    return a->number() < b->number();
+  }
+};
+
+int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
+  // The first item in the object structure is our uint32[] for has bits.
+  // We then want to order things to make the instances as small as
+  // possible. So we follow the has bits with:
+  //   1. Anything always 4 bytes - float, *32, enums
+  //   2. Anything that is always a pointer (they will be 8 bytes on 64 bit
+  //      builds and 4 bytes on 32bit builds.
+  //   3. Anything always 8 bytes - double, *64
+  //
+  // NOTE: Bools aren't listed, they were stored in the has bits.
+  //
+  // Why? Using 64bit builds as an example, this means worse case, we have
+  // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
+  // are wasted before the 4 byte values. Then if we have an odd number of
+  // those 4 byte values, the 8 byte values will be pushed down by 32bits to
+  // keep them aligned. But the structure will end 8 byte aligned, so no
+  // waste on the end. If you did the reverse order, you could waste 4 bytes
+  // before the first 8 byte value (after the has array), then a single
+  // bool on the end would need 7 bytes of padding to make the overall
+  // structure 8 byte aligned; so 11 bytes, wasted total.
+
+  // Anything repeated is a GPB*Array/NSArray, so pointer.
+  if (descriptor->is_repeated()) {
+    return 3;
+  }
+
+  switch (descriptor->type()) {
+    // All always 8 bytes.
+    case FieldDescriptor::TYPE_DOUBLE:
+    case FieldDescriptor::TYPE_INT64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_UINT64:
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_FIXED64:
+      return 4;
+
+    // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
+    // depending on the build architecture.
+    case FieldDescriptor::TYPE_GROUP:
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      return 3;
+
+    // All always 4 bytes (enums are int32s).
+    case FieldDescriptor::TYPE_FLOAT:
+    case FieldDescriptor::TYPE_INT32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_UINT32:
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_ENUM:
+      return 2;
+
+    // 0 bytes. Stored in the has bits.
+    case FieldDescriptor::TYPE_BOOL:
+      return 99;  // End of the list (doesn't really matter).
+  }
+
+  // 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 0;
+}
+
+struct FieldOrderingByStorageSize {
+  inline bool operator()(const FieldDescriptor* a,
+                         const FieldDescriptor* b) const {
+    // Order by grouping.
+    const int order_group_a = OrderGroupForFieldDescriptor(a);
+    const int order_group_b = OrderGroupForFieldDescriptor(b);
+    if (order_group_a != order_group_b) {
+      return order_group_a < order_group_b;
+    }
+    // Within the group, order by field number (provides stable ordering).
+    return a->number() < b->number();
+  }
+};
+
+struct ExtensionRangeOrdering {
+  bool operator()(const Descriptor::ExtensionRange* a,
+                  const Descriptor::ExtensionRange* b) const {
+    return a->start < b->start;
+  }
+};
+
+// Sort the fields of the given Descriptor by number into a new[]'d array
+// and return it.
+const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
+  const FieldDescriptor** fields =
+      new const FieldDescriptor*[descriptor->field_count()];
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields[i] = descriptor->field(i);
+  }
+  std::sort(fields, fields + descriptor->field_count(),
+            FieldOrderingByNumber());
+  return fields;
+}
+
+// Sort the fields of the given Descriptor by storage size into a new[]'d
+// array and return it.
+const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
+  const FieldDescriptor** fields =
+      new const FieldDescriptor*[descriptor->field_count()];
+  for (int i = 0; i < descriptor->field_count(); i++) {
+    fields[i] = descriptor->field(i);
+  }
+  std::sort(fields, fields + descriptor->field_count(),
+            FieldOrderingByStorageSize());
+  return fields;
+}
+
+}  // namespace
+
+MessageGenerator::MessageGenerator(const std::string& root_classname,
+                                   const Descriptor* descriptor)
+    : root_classname_(root_classname),
+      descriptor_(descriptor),
+      field_generators_(descriptor),
+      class_name_(ClassName(descriptor_)),
+      deprecated_attribute_(GetOptionalDeprecatedAttribute(
+          descriptor, descriptor->file(), false, true)) {
+  for (int i = 0; i < descriptor_->real_oneof_decl_count(); i++) {
+    oneof_generators_.push_back(
+        std::make_unique<OneofGenerator>(descriptor_->oneof_decl(i)));
+  }
+
+  // Assign has bits:
+  // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
+  //    who needs has bits and assigning them.
+  // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
+  //    index that groups all the elements in the oneof.
+  size_t num_has_bits = field_generators_.CalculateHasBits();
+  size_t sizeof_has_storage = (num_has_bits + 31) / 32;
+  if (sizeof_has_storage == 0) {
+    // In the case where no field needs has bits, don't let the _has_storage_
+    // end up as zero length (zero length arrays are sort of a grey area
+    // since it has to be at the start of the struct). This also ensures a
+    // field with only oneofs keeps the required negative indices they need.
+    sizeof_has_storage = 1;
+  }
+  // Tell all the fields the oneof base.
+  for (const auto& generator : oneof_generators_) {
+    generator->SetOneofIndexBase(sizeof_has_storage);
+  }
+  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 += oneof_generators_.size();
+
+  sizeof_has_storage_ = sizeof_has_storage;
+}
+
+void MessageGenerator::AddExtensionGenerators(
+    std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators) {
+  for (int i = 0; i < descriptor_->extension_count(); i++) {
+    extension_generators->push_back(std::make_unique<ExtensionGenerator>(
+        class_name_, descriptor_->extension(i)));
+    extension_generators_.push_back(extension_generators->back().get());
+  }
+}
+
+void MessageGenerator::DetermineForwardDeclarations(
+    absl::btree_set<std::string>* fwd_decls,
+    bool include_external_types) const {
+  if (IsMapEntryMessage(descriptor_)) {
+    return;
+  }
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+    field_generators_.get(fieldDescriptor)
+        .DetermineForwardDeclarations(fwd_decls, include_external_types);
+  }
+}
+
+void MessageGenerator::DetermineObjectiveCClassDefinitions(
+    absl::btree_set<std::string>* fwd_decls) const {
+  if (!IsMapEntryMessage(descriptor_)) {
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
+      field_generators_.get(fieldDescriptor)
+          .DetermineObjectiveCClassDefinitions(fwd_decls);
+    }
+  }
+
+  const Descriptor* containing_descriptor = descriptor_->containing_type();
+  if (containing_descriptor != nullptr) {
+    std::string containing_class = ClassName(containing_descriptor);
+    fwd_decls->insert(ObjCClassDeclaration(containing_class));
+  }
+}
+
+void MessageGenerator::GenerateMessageHeader(io::Printer* printer) const {
+  // This a a map entry message, just recurse and do nothing directly.
+  if (IsMapEntryMessage(descriptor_)) {
+    return;
+  }
+
+  printer->Print(
+      // clang-format off
+      "#pragma mark - $classname$\n"
+      "\n",
+      // clang-format on
+      "classname", class_name_);
+
+  if (descriptor_->field_count()) {
+    std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+        SortFieldsByNumber(descriptor_));
+
+    printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n", "classname",
+                   class_name_);
+    printer->Indent();
+
+    for (int i = 0; i < descriptor_->field_count(); i++) {
+      field_generators_.get(sorted_fields[i])
+          .GenerateFieldNumberConstant(printer);
+    }
+
+    printer->Outdent();
+    printer->Print("};\n\n");
+  }
+
+  for (const auto& generator : oneof_generators_) {
+    generator->GenerateCaseEnum(printer);
+  }
+
+  std::string message_comments;
+  SourceLocation location;
+  if (descriptor_->GetSourceLocation(&location)) {
+    message_comments = BuildCommentsString(location, false);
+  } else {
+    message_comments = "";
+  }
+
+  printer->Print(
+      // clang-format off
+      "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
+      // clang-format on
+      "classname", class_name_, "deprecated_attribute", deprecated_attribute_,
+      "comments", message_comments);
+
+  std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    const FieldDescriptor* field = descriptor_->field(i);
+    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(
+            printer);
+      }
+    }
+    field_generators_.get(field).GeneratePropertyDeclaration(printer);
+  }
+
+  printer->Print("@end\n\n");
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateCFunctionDeclarations(printer);
+  }
+
+  if (!oneof_generators_.empty()) {
+    for (const auto& generator : oneof_generators_) {
+      generator->GenerateClearFunctionDeclaration(printer);
+    }
+    printer->Print("\n");
+  }
+
+  if (descriptor_->extension_count() > 0) {
+    printer->Print("@interface $classname$ (DynamicMethods)\n\n", "classname",
+                   class_name_);
+    for (const auto generator : extension_generators_) {
+      generator->GenerateMembersHeader(printer);
+    }
+    printer->Print("@end\n\n");
+  }
+}
+
+void MessageGenerator::GenerateSource(io::Printer* printer) const {
+  if (IsMapEntryMessage(descriptor_)) {
+    return;
+  }
+  printer->Print(
+      // clang-format off
+      "#pragma mark - $classname$\n"
+      "\n",
+      // clang-format on
+      "classname", class_name_);
+
+  if (!deprecated_attribute_.empty()) {
+    // No warnings when compiling the impl of this deprecated class.
+    // clang-format off
+    printer->Print(
+        "#pragma clang diagnostic push\n"
+        "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
+        "\n");
+    // clang-format on
+  }
+
+  printer->Print("@implementation $classname$\n\n", "classname", class_name_);
+
+  for (const auto& generator : oneof_generators_) {
+    generator->GeneratePropertyImplementation(printer);
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GeneratePropertyImplementation(printer);
+  }
+
+  std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
+      SortFieldsByNumber(descriptor_));
+  std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
+      SortFieldsByStorageSize(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));
+  }
+
+  std::sort(sorted_extensions.begin(), sorted_extensions.end(),
+            ExtensionRangeOrdering());
+
+  printer->Print(
+      // clang-format off
+      "\n"
+      "typedef struct $classname$__storage_ {\n"
+      "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
+      // clang-format on
+      "classname", class_name_, "sizeof_has_storage",
+      absl::StrCat(sizeof_has_storage_));
+  printer->Indent();
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(size_order_fields[i])
+        .GenerateFieldStorageDeclaration(printer);
+  }
+  printer->Outdent();
+
+  printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
+
+  // clang-format off
+  printer->Print(
+      "// This method is threadsafe because it is initially called\n"
+      "// in +initialize for each subclass.\n"
+      "+ (GPBDescriptor *)descriptor {\n"
+      "  static GPBDescriptor *descriptor = nil;\n"
+      "  if (!descriptor) {\n");
+  // clang-format on
+
+  TextFormatDecodeData text_format_decode_data;
+  bool has_fields = descriptor_->field_count() > 0;
+  bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
+  std::string field_description_type;
+  if (need_defaults) {
+    field_description_type = "GPBMessageFieldDescriptionWithDefault";
+  } else {
+    field_description_type = "GPBMessageFieldDescription";
+  }
+  if (has_fields) {
+    printer->Indent();
+    printer->Indent();
+    printer->Print("static $field_description_type$ fields[] = {\n",
+                   "field_description_type", field_description_type);
+    printer->Indent();
+    for (int i = 0; i < descriptor_->field_count(); ++i) {
+      const FieldGenerator& field_generator =
+          field_generators_.get(sorted_fields[i]);
+      field_generator.GenerateFieldDescription(printer, need_defaults);
+      if (field_generator.needs_textformat_name_support()) {
+        text_format_decode_data.AddString(sorted_fields[i]->number(),
+                                          field_generator.generated_objc_name(),
+                                          field_generator.raw_field_name());
+      }
+    }
+    printer->Outdent();
+    printer->Print("};\n");
+    printer->Outdent();
+    printer->Outdent();
+  }
+
+  absl::flat_hash_map<absl::string_view, std::string> vars;
+  vars["classname"] = class_name_;
+  vars["rootclassname"] = root_classname_;
+  vars["fields"] = has_fields ? "fields" : "NULL";
+  if (has_fields) {
+    vars["fields_count"] = absl::StrCat("(uint32_t)(sizeof(fields) / sizeof(",
+                                        field_description_type, "))");
+  } else {
+    vars["fields_count"] = "0";
+  }
+
+  std::vector<std::string> init_flags;
+  init_flags.push_back("GPBDescriptorInitializationFlag_UsesClassRefs");
+  init_flags.push_back("GPBDescriptorInitializationFlag_Proto3OptionalKnown");
+  init_flags.push_back(
+      "GPBDescriptorInitializationFlag_ClosedEnumSupportKnown");
+  if (need_defaults) {
+    init_flags.push_back("GPBDescriptorInitializationFlag_FieldsWithDefault");
+  }
+  if (descriptor_->options().message_set_wire_format()) {
+    init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
+  }
+  vars["init_flags"] =
+      BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION, init_flags);
+
+  // clang-format off
+  printer->Print(
+      vars,
+      "    GPBDescriptor *localDescriptor =\n"
+      "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
+      "                                     rootClass:[$rootclassname$ class]\n"
+      "                                          file:$rootclassname$_FileDescriptor()\n"
+      "                                        fields:$fields$\n"
+      "                                    fieldCount:$fields_count$\n"
+      "                                   storageSize:sizeof($classname$__storage_)\n"
+      "                                         flags:$init_flags$];\n");
+  // clang-format on
+  if (!oneof_generators_.empty()) {
+    printer->Print("    static const char *oneofs[] = {\n");
+    for (const auto& generator : oneof_generators_) {
+      printer->Print("      \"$name$\",\n", "name",
+                     generator->DescriptorName());
+    }
+    printer->Print(
+        // clang-format off
+        "    };\n"
+        "    [localDescriptor setupOneofs:oneofs\n"
+        "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
+        "                   firstHasIndex:$first_has_index$];\n",
+        // clang-format on
+        "first_has_index", oneof_generators_[0]->HasIndexAsString());
+  }
+  if (text_format_decode_data.num_entries() != 0) {
+    const std::string text_format_data_str(text_format_decode_data.Data());
+    // clang-format off
+    printer->Print(
+        "#if !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n"
+        "    static const char *extraTextFormatInfo =");
+    // clang-format on
+    static const int kBytesPerLine = 40;  // allow for escaping
+    for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
+      printer->Print("\n        \"$data$\"", "data",
+                     EscapeTrigraphs(absl::CEscape(
+                         text_format_data_str.substr(i, kBytesPerLine))));
+    }
+    // clang-format off
+    printer->Print(
+        ";\n"
+        "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
+        "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
+    // clang-format on
+  }
+  if (!sorted_extensions.empty()) {
+    printer->Print("    static const GPBExtensionRange ranges[] = {\n");
+    for (int i = 0; i < sorted_extensions.size(); i++) {
+      printer->Print("      { .start = $start$, .end = $end$ },\n", "start",
+                     absl::StrCat(sorted_extensions[i]->start), "end",
+                     absl::StrCat(sorted_extensions[i]->end));
+    }
+    // clang-format off
+    printer->Print(
+        "    };\n"
+        "    [localDescriptor setupExtensionRanges:ranges\n"
+        "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
+    // clang-format on
+  }
+  if (descriptor_->containing_type() != nullptr) {
+    std::string containing_class = ClassName(descriptor_->containing_type());
+    std::string parent_class_ref = ObjCClass(containing_class);
+    printer->Print(
+        // clang-format off
+        "    [localDescriptor setupContainingMessageClass:$parent_class_ref$];\n",
+        // clang-format on
+        "parent_class_ref", parent_class_ref);
+  }
+  std::string suffix_added;
+  ClassName(descriptor_, &suffix_added);
+  if (!suffix_added.empty()) {
+    printer->Print(
+        "    [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
+        "suffix", suffix_added);
+  }
+  // clang-format off
+  printer->Print(
+      "    #if defined(DEBUG) && DEBUG\n"
+      "      NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
+      "    #endif  // DEBUG\n"
+      "    descriptor = localDescriptor;\n"
+      "  }\n"
+      "  return descriptor;\n"
+      "}\n\n"
+      "@end\n\n");
+  // clang-format on
+
+  if (!deprecated_attribute_.empty()) {
+    // clang-format off
+    printer->Print(
+        "#pragma clang diagnostic pop\n"
+        "\n");
+    // clang-format on
+  }
+
+  for (int i = 0; i < descriptor_->field_count(); i++) {
+    field_generators_.get(descriptor_->field(i))
+        .GenerateCFunctionImplementations(printer);
+  }
+
+  for (const auto& generator : oneof_generators_) {
+    generator->GenerateClearFunctionImplementation(printer);
+  }
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.h b/src/google/protobuf/compiler/objectivec/message.h
similarity index 65%
rename from src/google/protobuf/compiler/objectivec/objectivec_message.h
rename to src/google/protobuf/compiler/objectivec/message.h
index 9d14430..32ec4de 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.h
+++ b/src/google/protobuf/compiler/objectivec/message.h
@@ -31,13 +31,16 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_H__
 
+#include <cstddef>
+#include <memory>
 #include <string>
-#include <set>
 #include <vector>
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+
+#include "absl/container/btree_set.h"
+#include "google/protobuf/compiler/objectivec/field.h"
+#include "google/protobuf/compiler/objectivec/oneof.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -45,50 +48,38 @@
 namespace objectivec {
 
 class ExtensionGenerator;
-class EnumGenerator;
 
 class MessageGenerator {
  public:
   MessageGenerator(const std::string& root_classname,
                    const Descriptor* descriptor);
-  ~MessageGenerator();
+  ~MessageGenerator() = default;
 
   MessageGenerator(const MessageGenerator&) = delete;
   MessageGenerator& operator=(const MessageGenerator&) = delete;
 
-  void GenerateStaticVariablesInitialization(io::Printer* printer);
-  void GenerateEnumHeader(io::Printer* printer);
-  void GenerateMessageHeader(io::Printer* printer);
-  void GenerateSource(io::Printer* printer);
-  void GenerateExtensionRegistrationSource(io::Printer* printer);
-  void DetermineObjectiveCClassDefinitions(std::set<std::string>* fwd_decls);
-  void DetermineForwardDeclarations(std::set<std::string>* fwd_decls,
-                                    bool include_external_types);
+  void AddExtensionGenerators(
+      std::vector<std::unique_ptr<ExtensionGenerator>>* extension_generators);
+
+  void GenerateMessageHeader(io::Printer* printer) const;
+  void GenerateSource(io::Printer* printer) const;
+  void DetermineObjectiveCClassDefinitions(
+      absl::btree_set<std::string>* fwd_decls) const;
+  void DetermineForwardDeclarations(absl::btree_set<std::string>* fwd_decls,
+                                    bool include_external_types) const;
 
   // Checks if the message or a nested message includes a oneof definition.
-  bool IncludesOneOfDefinition() const;
+  bool IncludesOneOfDefinition() const { return !oneof_generators_.empty(); }
 
  private:
-  void GenerateParseFromMethodsHeader(io::Printer* printer);
-
-  void GenerateSerializeOneFieldSource(io::Printer* printer,
-                                       const FieldDescriptor* field);
-  void GenerateSerializeOneExtensionRangeSource(
-      io::Printer* printer, const Descriptor::ExtensionRange* range);
-
-  void GenerateMessageDescriptionSource(io::Printer* printer);
-  void GenerateDescriptionOneFieldSource(io::Printer* printer,
-                                         const FieldDescriptor* field);
-
   const std::string root_classname_;
   const Descriptor* descriptor_;
   FieldGeneratorMap field_generators_;
   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_;
+  std::vector<const ExtensionGenerator*> extension_generators_;
   std::vector<std::unique_ptr<OneofGenerator>> oneof_generators_;
+  size_t sizeof_has_storage_;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc b/src/google/protobuf/compiler/objectivec/message_field.cc
similarity index 75%
rename from src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
rename to src/google/protobuf/compiler/objectivec/message_field.cc
index 2ff0b44..8da2f82 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.cc
+++ b/src/google/protobuf/compiler/objectivec/message_field.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.
 
-#include <map>
+#include "google/protobuf/compiler/objectivec/message_field.h"
+
 #include <string>
 
-#include <google/protobuf/compiler/objectivec/objectivec_message_field.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/printer.h>
+#include "absl/container/btree_set.h"
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/names.h"
 
 namespace google {
 namespace protobuf {
@@ -42,8 +44,9 @@
 
 namespace {
 
-void SetMessageVariables(const FieldDescriptor* descriptor,
-                         std::map<std::string, std::string>* variables) {
+void SetMessageVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   const std::string& message_type = ClassName(descriptor->message_type());
   const std::string& containing_class =
       ClassName(descriptor->containing_type());
@@ -62,26 +65,24 @@
   SetMessageVariables(descriptor, &variables_);
 }
 
-MessageFieldGenerator::~MessageFieldGenerator() {}
-
 void MessageFieldGenerator::DetermineForwardDeclarations(
-    std::set<std::string>* fwd_decls,
+    absl::btree_set<std::string>* fwd_decls,
     bool include_external_types) const {
-  ObjCObjFieldGenerator::DetermineForwardDeclarations(
-      fwd_decls, include_external_types);
+  ObjCObjFieldGenerator::DetermineForwardDeclarations(fwd_decls,
+                                                      include_external_types);
   // Within a file there is no requirement on the order of the messages, so
   // local references need a forward declaration. External files (not WKTs),
   // need one when requested.
-  if ((include_external_types &&
-       !IsProtobufLibraryBundledProtoFile(descriptor_->message_type()->file())) ||
+  if ((include_external_types && !IsProtobufLibraryBundledProtoFile(
+                                     descriptor_->message_type()->file())) ||
       descriptor_->file() == descriptor_->message_type()->file()) {
     // Class name is already in "storage_type".
-    fwd_decls->insert("@class " + variable("storage_type"));
+    fwd_decls->insert(absl::StrCat("@class ", variable("storage_type"), ";"));
   }
 }
 
 void MessageFieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<std::string>* fwd_decls) const {
+    absl::btree_set<std::string>* fwd_decls) const {
   fwd_decls->insert(ObjCClassDeclaration(variable("storage_type")));
 }
 
@@ -94,26 +95,24 @@
       "NSMutableArray<" + variables_["storage_type"] + "*>";
 }
 
-RepeatedMessageFieldGenerator::~RepeatedMessageFieldGenerator() {}
-
 void RepeatedMessageFieldGenerator::DetermineForwardDeclarations(
-    std::set<std::string>* fwd_decls,
+    absl::btree_set<std::string>* fwd_decls,
     bool include_external_types) const {
-  RepeatedFieldGenerator::DetermineForwardDeclarations(
-      fwd_decls, include_external_types);
+  RepeatedFieldGenerator::DetermineForwardDeclarations(fwd_decls,
+                                                       include_external_types);
   // Within a file there is no requirement on the order of the messages, so
   // local references need a forward declaration. External files (not WKTs),
   // need one when requested.
-  if ((include_external_types &&
-       !IsProtobufLibraryBundledProtoFile(descriptor_->message_type()->file())) ||
+  if ((include_external_types && !IsProtobufLibraryBundledProtoFile(
+                                     descriptor_->message_type()->file())) ||
       descriptor_->file() == descriptor_->message_type()->file()) {
     // Class name is already in "storage_type".
-    fwd_decls->insert("@class " + variable("storage_type"));
+    fwd_decls->insert(absl::StrCat("@class ", variable("storage_type"), ";"));
   }
 }
 
 void RepeatedMessageFieldGenerator::DetermineObjectiveCClassDefinitions(
-    std::set<std::string>* fwd_decls) const {
+    absl::btree_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/message_field.h
similarity index 77%
rename from src/google/protobuf/compiler/objectivec/objectivec_message_field.h
rename to src/google/protobuf/compiler/objectivec/message_field.h
index 49a84fb..40028a0 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_message_field.h
+++ b/src/google/protobuf/compiler/objectivec/message_field.h
@@ -31,9 +31,10 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_MESSAGE_FIELD_H__
 
-#include <map>
 #include <string>
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+
+#include "absl/container/btree_set.h"
+#include "google/protobuf/compiler/objectivec/field.h"
 
 namespace google {
 namespace protobuf {
@@ -45,18 +46,16 @@
 
  protected:
   explicit MessageFieldGenerator(const FieldDescriptor* descriptor);
+  ~MessageFieldGenerator() override = default;
 
   MessageFieldGenerator(const MessageFieldGenerator&) = delete;
   MessageFieldGenerator& operator=(const MessageFieldGenerator&) = delete;
 
-  virtual ~MessageFieldGenerator();
-
  public:
-  virtual void DetermineForwardDeclarations(
-      std::set<std::string>* fwd_decls,
-      bool include_external_types) const override;
-  virtual void DetermineObjectiveCClassDefinitions(
-      std::set<std::string>* fwd_decls) const override;
+  void DetermineForwardDeclarations(absl::btree_set<std::string>* fwd_decls,
+                                    bool include_external_types) const override;
+  void DetermineObjectiveCClassDefinitions(
+      absl::btree_set<std::string>* fwd_decls) const override;
 };
 
 class RepeatedMessageFieldGenerator : public RepeatedFieldGenerator {
@@ -64,17 +63,17 @@
 
  protected:
   explicit RepeatedMessageFieldGenerator(const FieldDescriptor* descriptor);
-  virtual ~RepeatedMessageFieldGenerator();
+  ~RepeatedMessageFieldGenerator() override = default;
 
   RepeatedMessageFieldGenerator(const RepeatedMessageFieldGenerator&) = delete;
-  RepeatedMessageFieldGenerator operator=(const RepeatedMessageFieldGenerator&) = delete;
+  RepeatedMessageFieldGenerator operator=(
+      const RepeatedMessageFieldGenerator&) = delete;
 
  public:
-  virtual void DetermineForwardDeclarations(
-      std::set<std::string>* fwd_decls,
-      bool include_external_types) const override;
-  virtual void DetermineObjectiveCClassDefinitions(
-      std::set<std::string>* fwd_decls) const override;
+  void DetermineForwardDeclarations(absl::btree_set<std::string>* fwd_decls,
+                                    bool include_external_types) const override;
+  void DetermineObjectiveCClassDefinitions(
+      absl::btree_set<std::string>* fwd_decls) const override;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/compiler/objectivec/method_dump.sh b/src/google/protobuf/compiler/objectivec/method_dump.sh
index 193825d..332d42a 100755
--- a/src/google/protobuf/compiler/objectivec/method_dump.sh
+++ b/src/google/protobuf/compiler/objectivec/method_dump.sh
@@ -1,7 +1,7 @@
 #!/bin/bash
 
-# Updates objectivec_nsobject_methods.h by generating a list of all of the properties
-# and methods on NSObject that Protobufs should not overload from iOS and macOS combined.
+# Updates nsobject_methods.h by generating a list of all of the properties and
+# methods on NSObject that Protobufs should not overload from iOS and macOS combined.
 #
 # The rules:
 #   - No property should ever be overloaded.
@@ -82,9 +82,9 @@
     for (NSString *item in array) {
       // Some items with _ in them get returned in quotes, so do not add more.
       if ([item hasPrefix:@"\""]) {
-        printf("\t%s,\n", item.UTF8String);
+        printf("    %s,\n", item.UTF8String);
       } else {
-        printf("\t\"%s\",\n", item.UTF8String);
+        printf("    \"%s\",\n", item.UTF8String);
       }
     }
   }
@@ -110,7 +110,7 @@
 )
 
 # Check to make sure we are updating the correct file.
-if [[ ! -e "objectivec_nsobject_methods.h" ]]; then
+if [[ ! -e "nsobject_methods.h" ]]; then
   echo "error: Must be run in the src/google/protobuf/compiler/objectivec directory"
   exit 1
 fi
@@ -154,7 +154,7 @@
 # Check for differences. Turn off error checking because we expect diff to fail when
 # there are no differences.
 set +e
-diff_out=$(diff -I "^//.*$" "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h)
+diff_out=$(diff -I "^//.*$" "$temp_dir"/methods_sorted.txt nsobject_methods.h)
 removed_methods=$(echo "$diff_out" | grep '^>.*$')
 set -e
 if [[ -n "$removed_methods" ]]; then
@@ -168,12 +168,12 @@
   echo "$removed_methods"
   echo ""
   echo "New Version: $temp_dir/methods_sorted.txt"
-  echo "Old Version: objectivec_nsobject_methods.h"
+  echo "Old Version: nsobject_methods.h"
   exit 1
 fi
 if [[ -n "$diff_out" ]]; then
   echo "Added Methods:"
   echo "$(echo "$diff_out" | grep '^<.*$' | sed -e 's/^< "\(.*\)",$/  \1/')"
 fi;
-cp "$temp_dir"/methods_sorted.txt objectivec_nsobject_methods.h
+cp "$temp_dir"/methods_sorted.txt nsobject_methods.h
 rm -rf "$temp_dir"
diff --git a/src/google/protobuf/compiler/objectivec/names.cc b/src/google/protobuf/compiler/objectivec/names.cc
new file mode 100644
index 0000000..2e1c45c
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/names.cc
@@ -0,0 +1,1246 @@
+// 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/objectivec/names.h"
+
+#include <algorithm>
+#include <climits>
+#include <fstream>
+#include <iostream>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/compiler/objectivec/line_consumer.h"
+#include "google/protobuf/compiler/objectivec/nsobject_methods.h"
+#include "google/protobuf/descriptor.pb.h"
+
+// 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 errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+bool BoolFromEnvVar(const char* env_var, bool default_value) {
+  const char* value = getenv(env_var);
+  if (value) {
+    return std::string("YES") == absl::AsciiStrToUpper(value);
+  }
+  return default_value;
+}
+
+class SimpleLineCollector : public LineConsumer {
+ public:
+  explicit SimpleLineCollector(absl::flat_hash_set<std::string>* inout_set)
+      : set_(inout_set) {}
+
+  bool ConsumeLine(absl::string_view line, std::string* out_error) override {
+    set_->insert(std::string(line));
+    return true;
+  }
+
+ private:
+  absl::flat_hash_set<std::string>* set_;
+};
+
+class PackageToPrefixesCollector : public LineConsumer {
+ public:
+  PackageToPrefixesCollector(const std::string& usage,
+                             absl::flat_hash_map<std::string, std::string>*
+                                 inout_package_to_prefix_map)
+      : usage_(usage), prefix_map_(inout_package_to_prefix_map) {}
+
+  bool ConsumeLine(absl::string_view line, std::string* out_error) override;
+
+ private:
+  const std::string usage_;
+  absl::flat_hash_map<std::string, std::string>* prefix_map_;
+};
+
+class PrefixModeStorage {
+ public:
+  PrefixModeStorage();
+
+  std::string package_to_prefix_mappings_path() const {
+    return package_to_prefix_mappings_path_;
+  }
+  void set_package_to_prefix_mappings_path(const std::string& path) {
+    package_to_prefix_mappings_path_ = path;
+    package_to_prefix_map_.clear();
+  }
+
+  std::string prefix_from_proto_package_mappings(const FileDescriptor* file);
+
+  bool use_package_name() const { return use_package_name_; }
+  void set_use_package_name(bool on_or_off) { use_package_name_ = on_or_off; }
+
+  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);
+
+  // When using a proto package as the prefix, this should be added as the
+  // prefix in front of it.
+  const std::string& forced_package_prefix() const { return forced_prefix_; }
+  void set_forced_package_prefix(const std::string& prefix) {
+    forced_prefix_ = prefix;
+  }
+
+ private:
+  bool use_package_name_;
+  absl::flat_hash_map<std::string, std::string> package_to_prefix_map_;
+  std::string package_to_prefix_mappings_path_;
+  std::string exception_path_;
+  std::string forced_prefix_;
+  absl::flat_hash_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.
+
+  use_package_name_ = BoolFromEnvVar("GPB_OBJC_USE_PACKAGE_AS_PREFIX", false);
+
+  const char* exception_path =
+      getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH");
+  if (exception_path) {
+    exception_path_ = exception_path;
+  }
+
+  const char* prefix = getenv("GPB_OBJC_USE_PACKAGE_AS_PREFIX_PREFIX");
+  if (prefix) {
+    forced_prefix_ = prefix;
+  }
+}
+
+constexpr absl::string_view kNoPackagePrefix = "no_package:";
+
+std::string PrefixModeStorage::prefix_from_proto_package_mappings(
+    const FileDescriptor* file) {
+  if (!file) {
+    return "";
+  }
+
+  if (package_to_prefix_map_.empty() &&
+      !package_to_prefix_mappings_path_.empty()) {
+    std::string error_str;
+    // Re use the same collector as we use for expected_prefixes_path since the
+    // file format is the same.
+    PackageToPrefixesCollector collector("Package to prefixes",
+                                         &package_to_prefix_map_);
+    if (!ParseSimpleFile(package_to_prefix_mappings_path_, &collector,
+                         &error_str)) {
+      if (error_str.empty()) {
+        error_str = absl::StrCat("protoc:0: warning: Failed to parse ",
+                                 "prefix to proto package mappings file: ",
+                                 package_to_prefix_mappings_path_);
+      }
+      std::cerr << error_str << std::endl;
+      std::cerr.flush();
+      package_to_prefix_map_.clear();
+    }
+  }
+
+  const std::string package = file->package();
+  // For files without packages, the can be registered as "no_package:PATH",
+  // allowing the expected prefixes file.
+  const std::string lookup_key =
+      package.empty() ? absl::StrCat(kNoPackagePrefix, file->name()) : package;
+
+  auto prefix_lookup = package_to_prefix_map_.find(lookup_key);
+
+  if (prefix_lookup != package_to_prefix_map_.end()) {
+    return prefix_lookup->second;
+  }
+
+  return "";
+}
+
+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 = *new PrefixModeStorage();
+
+}  // namespace
+
+std::string GetPackageToPrefixMappingsPath() {
+  return g_prefix_mode.package_to_prefix_mappings_path();
+}
+
+void SetPackageToPrefixMappingsPath(const std::string& file_path) {
+  g_prefix_mode.set_package_to_prefix_mappings_path(file_path);
+}
+
+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);
+}
+
+std::string GetForcedPackagePrefix() {
+  return g_prefix_mode.forced_package_prefix();
+}
+
+void SetForcedPackagePrefix(const std::string& prefix) {
+  g_prefix_mode.set_forced_package_prefix(prefix);
+}
+
+namespace {
+
+const char* const kUpperSegmentsList[] = {"url", "http", "https"};
+
+const absl::flat_hash_set<absl::string_view>& UpperSegments() {
+  static const auto* words = [] {
+    auto* words = new absl::flat_hash_set<absl::string_view>();
+
+    for (const auto word : kUpperSegmentsList) {
+      words->emplace(word);
+    }
+    return words;
+  }();
+  return *words;
+}
+
+// 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.
+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;
+  bool last_char_was_upper = false;
+  for (int i = 0; i < input.size(); i++) {
+    char c = input[i];
+    if (absl::ascii_isdigit(c)) {
+      if (!last_char_was_number) {
+        values.push_back(current);
+        current = "";
+      }
+      current += c;
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+      last_char_was_number = true;
+    } else if (absl::ascii_islower(c)) {
+      // lowercase letter can follow a lowercase or uppercase letter
+      if (!last_char_was_lower && !last_char_was_upper) {
+        values.push_back(current);
+        current = "";
+      }
+      current += c;  // already lower
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+      last_char_was_lower = true;
+    } else if (absl::ascii_isupper(c)) {
+      if (!last_char_was_upper) {
+        values.push_back(current);
+        current = "";
+      }
+      current += absl::ascii_tolower(c);
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+      last_char_was_upper = true;
+    } else {
+      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
+    }
+  }
+  values.push_back(current);
+
+  std::string result;
+  bool first_segment_forces_upper = false;
+  for (auto& value : values) {
+    bool all_upper = (UpperSegments().count(value) > 0);
+    if (all_upper && (result.length() == 0)) {
+      first_segment_forces_upper = true;
+    }
+    if (all_upper) {
+      absl::AsciiStrToUpper(&value);
+    } else {
+      value[0] = absl::ascii_toupper(value[0]);
+    }
+    result += value;
+  }
+  if ((result.length() != 0) && !first_capitalized &&
+      !first_segment_forces_upper) {
+    result[0] = absl::ascii_tolower(result[0]);
+  }
+  return result;
+}
+
+const char* const kReservedWordList[] = {
+    // Note NSObject Methods:
+    // These are brought in from nsobject_methods.h that is generated
+    // using method_dump.sh. See kNSObjectMethods below.
+
+    // Objective C "keywords" that aren't in C
+    // From
+    // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
+    // with some others added on.
+    "id",
+    "_cmd",
+    "super",
+    "in",
+    "out",
+    "inout",
+    "bycopy",
+    "byref",
+    "oneway",
+    "self",
+    "instancetype",
+    "nullable",
+    "nonnull",
+    "nil",
+    "Nil",
+    "YES",
+    "NO",
+    "weak",
+
+    // C/C++ keywords (Incl C++ 0x11)
+    // From http://en.cppreference.com/w/cpp/keywords
+    "and",
+    "and_eq",
+    "alignas",
+    "alignof",
+    "asm",
+    "auto",
+    "bitand",
+    "bitor",
+    "bool",
+    "break",
+    "case",
+    "catch",
+    "char",
+    "char16_t",
+    "char32_t",
+    "class",
+    "compl",
+    "const",
+    "constexpr",
+    "const_cast",
+    "continue",
+    "decltype",
+    "default",
+    "delete",
+    "double",
+    "dynamic_cast",
+    "else",
+    "enum",
+    "explicit",
+    "export",
+    "extern ",
+    "false",
+    "float",
+    "for",
+    "friend",
+    "goto",
+    "if",
+    "inline",
+    "int",
+    "long",
+    "mutable",
+    "namespace",
+    "new",
+    "noexcept",
+    "not",
+    "not_eq",
+    "nullptr",
+    "operator",
+    "or",
+    "or_eq",
+    "private",
+    "protected",
+    "public",
+    "register",
+    "reinterpret_cast",
+    "return",
+    "short",
+    "signed",
+    "sizeof",
+    "static",
+    "static_assert",
+    "static_cast",
+    "struct",
+    "switch",
+    "template",
+    "this",
+    "thread_local",
+    "throw",
+    "true",
+    "try",
+    "typedef",
+    "typeid",
+    "typename",
+    "union",
+    "unsigned",
+    "using",
+    "virtual",
+    "void",
+    "volatile",
+    "wchar_t",
+    "while",
+    "xor",
+    "xor_eq",
+
+    // C99 keywords
+    // From
+    // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
+    "restrict",
+
+    // GCC/Clang extension
+    "typeof",
+
+    // 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",
+
+    // GPBMessage Methods
+    // Only need to add instance methods that may conflict with
+    // method declared in protos. The main cases are methods
+    // that take no arguments, or setFoo:/hasFoo: type methods.
+    "clear",
+    "data",
+    "delimitedData",
+    "descriptor",
+    "extensionRegistry",
+    "extensionsCurrentlySet",
+    "initialized",
+    "isInitialized",
+    "serializedSize",
+    "sortedExtensionsInUse",
+    "unknownFields",
+
+    // MacTypes.h names
+    "Fixed",
+    "Fract",
+    "Size",
+    "LogicalAddress",
+    "PhysicalAddress",
+    "ByteCount",
+    "ByteOffset",
+    "Duration",
+    "AbsoluteTime",
+    "OptionBits",
+    "ItemCount",
+    "PBVersion",
+    "ScriptCode",
+    "LangCode",
+    "RegionCode",
+    "OSType",
+    "ProcessSerialNumber",
+    "Point",
+    "Rect",
+    "FixedPoint",
+    "FixedRect",
+    "Style",
+    "StyleParameter",
+    "StyleField",
+    "TimeScale",
+    "TimeBase",
+    "TimeRecord",
+};
+
+const absl::flat_hash_set<absl::string_view>& ReservedWords() {
+  static const auto* words = [] {
+    auto* words = new absl::flat_hash_set<absl::string_view>();
+
+    for (const auto word : kReservedWordList) {
+      words->emplace(word);
+    }
+    return words;
+  }();
+  return *words;
+}
+
+const absl::flat_hash_set<absl::string_view>& NSObjectMethods() {
+  static const auto* words = [] {
+    auto* words = new absl::flat_hash_set<absl::string_view>();
+
+    for (const auto word : kNSObjectMethodsList) {
+      words->emplace(word);
+    }
+    return words;
+  }();
+  return *words;
+}
+
+// returns true is input starts with __ or _[A-Z] which are reserved identifiers
+// in C/ C++. All calls should go through UnderscoresToCamelCase before getting
+// here 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 std::string& input) {
+  if (input.length() > 2) {
+    if (input.at(0) == '_') {
+      if (isupper(input.at(1)) || input.at(1) == '_') {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+std::string SanitizeNameForObjC(const std::string& prefix,
+                                const std::string& input,
+                                const std::string& extension,
+                                std::string* out_suffix_added) {
+  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
+  // b) Isn't equivalent to the prefix or
+  // c) Has the prefix, but the letter after the prefix is lowercase
+  if (absl::StartsWith(input, prefix)) {
+    if (input.length() == prefix.length() ||
+        !absl::ascii_isupper(input[prefix.length()])) {
+      sanitized = prefix + input;
+    } else {
+      sanitized = input;
+    }
+  } else {
+    sanitized = prefix + input;
+  }
+  if (IsReservedCIdentifier(sanitized) ||
+      (ReservedWords().count(sanitized) > 0) ||
+      (NSObjectMethods().count(sanitized) > 0)) {
+    if (out_suffix_added) *out_suffix_added = extension;
+    return sanitized + extension;
+  }
+  if (out_suffix_added) out_suffix_added->clear();
+  return sanitized;
+}
+
+std::string NameFromFieldDescriptor(const FieldDescriptor* field) {
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    return field->message_type()->name();
+  } else {
+    return field->name();
+  }
+}
+
+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 = "";
+    }
+    if (basename) {
+      *basename = path;
+    }
+  } else {
+    if (directory) {
+      *directory = path.substr(0, last_slash);
+    }
+    if (basename) {
+      *basename = path.substr(last_slash + 1);
+    }
+  }
+}
+
+bool IsSpecialNamePrefix(const std::string& name,
+                         const std::vector<std::string>& special_names) {
+  for (const auto& special_name : special_names) {
+    const size_t length = special_name.length();
+    if (name.compare(0, length, special_name) == 0) {
+      if (name.length() > length) {
+        // If name is longer than the special_name that it matches the next
+        // character must be not lower case (newton vs newTon vs new_ton).
+        return !absl::ascii_islower(name[length]);
+      } else {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+void MaybeUnQuote(absl::string_view* input) {
+  if ((input->length() >= 2) &&
+      ((*input->data() == '\'' || *input->data() == '"')) &&
+      ((*input)[input->length() - 1] == *input->data())) {
+    input->remove_prefix(1);
+    input->remove_suffix(1);
+  }
+}
+
+}  // namespace
+
+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 std::vector<std::string>* retained_names =
+      new std::vector<std::string>({"new", "alloc", "copy", "mutableCopy"});
+  return IsSpecialNamePrefix(name, *retained_names);
+}
+
+bool IsInitName(const std::string& name) {
+  static const std::vector<std::string>* init_names =
+      new std::vector<std::string>({"init"});
+  return IsSpecialNamePrefix(name, *init_names);
+}
+
+bool IsCreateName(const std::string& name) {
+  // List of segments from
+  // https://developer.apple.com/library/archive/documentation/CoreFoundation/Conceptual/CFMemoryMgmt/Concepts/Ownership.html#//apple_ref/doc/uid/20001148-103029
+  static const std::vector<std::string>* create_names =
+      new std::vector<std::string>({"Create", "Copy"});
+
+  for (const auto& create_name : *create_names) {
+    const size_t length = create_name.length();
+    size_t pos = name.find(create_name);
+    if (pos != std::string::npos) {
+      // The above docs don't actually call out anything about the characters
+      // before the special words. So it's not clear if something like
+      // "FOOCreate" would or would not match the "The Create Rule", but by not
+      // checking, and claiming it does match, then callers will annotate with
+      // `cf_returns_not_retained` which will ensure things work as desired.
+      //
+      // The footnote here is the docs do have a passing reference to "NoCopy",
+      // but again, not looking for that and just returning `true` will cause
+      // callers to annotate the api as not being a Create Rule function.
+
+      // If name is longer than the create_names[i] that it matches the next
+      // character must be not lower case (Copyright vs CopyFoo vs Copy_Foo).
+      if (name.length() > pos + length) {
+        return !absl::ascii_islower(name[pos + length]);
+      } else {
+        return true;
+      }
+    }
+  }
+  return false;
+}
+
+std::string BaseFileName(const FileDescriptor* file) {
+  std::string basename;
+  PathSplit(file->name(), nullptr, &basename);
+  return basename;
+}
+
+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 is specified in an prefix to proto mappings file then use
+  // that.
+  std::string objc_class_prefix =
+      g_prefix_mode.prefix_from_proto_package_mappings(file);
+  if (!objc_class_prefix.empty()) {
+    return objc_class_prefix;
+  }
+
+  // If package prefix isn't enabled, done.
+  if (!g_prefix_mode.use_package_name()) {
+    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 =
+      absl::StrSplit(file->package(), '.', absl::SkipEmpty());
+  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 g_prefix_mode.forced_package_prefix() + result;
+}
+
+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 + "/";
+  }
+  basename = StripProto(basename);
+
+  // CamelCase to be more ObjC friendly.
+  basename = UnderscoresToCamelCase(basename, true);
+
+  output += basename;
+  return output;
+}
+
+std::string FilePathBasename(const FileDescriptor* file) {
+  std::string output;
+  std::string basename;
+  std::string directory;
+  PathSplit(file->name(), &directory, &basename);
+  basename = StripProto(basename);
+
+  // CamelCase to be more ObjC friendly.
+  output = UnderscoresToCamelCase(basename, true);
+
+  return output;
+}
+
+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", nullptr);
+}
+
+std::string ClassNameWorker(const Descriptor* descriptor) {
+  std::string name;
+  if (descriptor->containing_type() != nullptr) {
+    name = ClassNameWorker(descriptor->containing_type());
+    name += "_";
+  }
+  return name + descriptor->name();
+}
+
+std::string ClassNameWorker(const EnumDescriptor* descriptor) {
+  std::string name;
+  if (descriptor->containing_type() != nullptr) {
+    name = ClassNameWorker(descriptor->containing_type());
+    name += "_";
+  }
+  return name + descriptor->name();
+}
+
+std::string ClassName(const Descriptor* descriptor) {
+  return ClassName(descriptor, nullptr);
+}
+
+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 std::string prefix = FileClassPrefix(descriptor->file());
+  const std::string name = ClassNameWorker(descriptor);
+  return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added);
+}
+
+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 {
+  //        message Size {...}
+  //        enum Mumble {...}
+  //      ...
+  //      }
+  //    yields Fixed_Class, Fixed_Size.
+  const std::string prefix = FileClassPrefix(descriptor->file());
+  const std::string name = ClassNameWorker(descriptor);
+  return SanitizeNameForObjC(prefix, name, "_Enum", nullptr);
+}
+
+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 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", nullptr);
+}
+
+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.
+  // The "short name" is intended to be the final leaf, the value name; but
+  // you can't simply send that off to sanitize as that could result in it
+  // getting modified when the full name didn't.  For example enum
+  // "StorageModes" has a value "retain".  So the full name is
+  // "StorageModes_Retain", but if we sanitize "retain" it would become
+  // "RetainValue".
+  // 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 std::string class_name = EnumName(descriptor->type());
+  const std::string long_name_prefix = class_name + "_";
+  const std::string long_name = EnumValueName(descriptor);
+  return std::string(absl::StripPrefix(long_name, long_name_prefix));
+}
+
+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 && absl::ascii_isupper(c)) {
+      result += '_';
+    }
+    result += absl::ascii_toupper(c);
+  }
+  return result;
+}
+
+std::string ExtensionMethodName(const FieldDescriptor* descriptor) {
+  const std::string name = NameFromFieldDescriptor(descriptor);
+  const std::string result = UnderscoresToCamelCase(name, false);
+  return SanitizeNameForObjC("", result, "_Extension", nullptr);
+}
+
+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";
+  } else {
+    // If it wasn't repeated, but ends in "Array", force on the _p suffix.
+    if (absl::EndsWith(result, "Array")) {
+      result += "_p";
+    }
+  }
+  return SanitizeNameForObjC("", result, "_p", nullptr);
+}
+
+std::string FieldNameCapitalized(const FieldDescriptor* field) {
+  // Want the same suffix handling, so upcase the first letter of the other
+  // name.
+  std::string result = FieldName(field);
+  if (result.length() > 0) {
+    result[0] = absl::ascii_toupper(result[0]);
+  }
+  return result;
+}
+
+std::string OneofEnumName(const OneofDescriptor* descriptor) {
+  const Descriptor* fieldDescriptor = descriptor->containing_type();
+  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;
+}
+
+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;
+}
+
+std::string OneofNameCapitalized(const OneofDescriptor* descriptor) {
+  // Use the common handling and then up-case the first letter.
+  std::string result = OneofName(descriptor);
+  if (result.length() > 0) {
+    result[0] = absl::ascii_toupper(result[0]);
+  }
+  return result;
+}
+
+std::string UnCamelCaseFieldName(const std::string& name,
+                                 const FieldDescriptor* field) {
+  absl::string_view worker(name);
+  if (absl::EndsWith(worker, "_p")) {
+    worker = absl::StripSuffix(worker, "_p");
+  }
+  if (field->is_repeated() && absl::EndsWith(worker, "Array")) {
+    worker = absl::StripSuffix(worker, "Array");
+  }
+  if (field->type() == FieldDescriptor::TYPE_GROUP) {
+    if (worker.length() > 0) {
+      if (absl::ascii_islower(worker[0])) {
+        std::string copy(worker);
+        copy[0] = absl::ascii_toupper(worker[0]);
+        return copy;
+      }
+    }
+    return std::string(worker);
+  } else {
+    std::string result;
+    for (int i = 0; i < worker.size(); i++) {
+      char c = worker[i];
+      if (absl::ascii_isupper(c)) {
+        if (i > 0) {
+          result += '_';
+        }
+        result += absl::ascii_tolower(c);
+      } else {
+        result += c;
+      }
+    }
+    return result;
+  }
+}
+
+// Making these a generator option for folks that don't use CocoaPods, but do
+// want to put the library in a framework is an interesting question. The
+// problem is it means changing sources shipped with the library to actually
+// use a different value; so it isn't as simple as a option.
+const char* const ProtobufLibraryFrameworkName = "Protobuf";
+
+std::string ProtobufFrameworkImportSymbol(const std::string& framework_name) {
+  // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS
+  return absl::StrCat("GPB_USE_", absl::AsciiStrToUpper(framework_name),
+                      "_FRAMEWORK_IMPORTS");
+}
+
+bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) {
+  // 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 std::string name = file->name();
+  if (name == "google/protobuf/any.proto" ||
+      name == "google/protobuf/api.proto" ||
+      name == "google/protobuf/duration.proto" ||
+      name == "google/protobuf/empty.proto" ||
+      name == "google/protobuf/field_mask.proto" ||
+      name == "google/protobuf/source_context.proto" ||
+      name == "google/protobuf/struct.proto" ||
+      name == "google/protobuf/timestamp.proto" ||
+      name == "google/protobuf/type.proto" ||
+      name == "google/protobuf/wrappers.proto") {
+    return true;
+  }
+  return false;
+}
+
+namespace {
+
+bool PackageToPrefixesCollector::ConsumeLine(absl::string_view line,
+                                             std::string* out_error) {
+  int offset = line.find('=');
+  if (offset == absl::string_view::npos) {
+    *out_error =
+        absl::StrCat(usage_, " file line without equal sign: '", line, "'.");
+    return false;
+  }
+  absl::string_view package =
+      absl::StripAsciiWhitespace(line.substr(0, offset));
+  absl::string_view prefix =
+      absl::StripAsciiWhitespace(line.substr(offset + 1));
+  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_)[std::string(package)] = std::string(prefix);
+  return true;
+}
+
+bool LoadExpectedPackagePrefixes(
+    const std::string& expected_prefixes_path,
+    absl::flat_hash_map<std::string, std::string>* prefix_map,
+    std::string* out_error) {
+  if (expected_prefixes_path.empty()) {
+    return true;
+  }
+
+  PackageToPrefixesCollector collector("Expected prefixes", prefix_map);
+  return ParseSimpleFile(expected_prefixes_path, &collector, out_error);
+}
+
+bool ValidateObjCClassPrefix(
+    const FileDescriptor* file, const std::string& expected_prefixes_path,
+    const absl::flat_hash_map<std::string, std::string>&
+        expected_package_prefixes,
+    bool prefixes_must_be_registered, bool require_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();
+  // For files without packages, the can be registered as "no_package:PATH",
+  // allowing the expected prefixes file.
+  const std::string lookup_key =
+      package.empty() ? absl::StrCat(kNoPackagePrefix, file->name()) : 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).
+  auto package_match = expected_package_prefixes.find(lookup_key);
+  if (package_match != expected_package_prefixes.end()) {
+    // There was an entry, and...
+    if (has_prefix && package_match->second == prefix) {
+      // ...it matches.  All good, out of here!
+      return true;
+    } else {
+      // ...it didn't match!
+      *out_error = "error: Expected 'option objc_class_prefix = \"" +
+                   package_match->second + "\";'";
+      if (!package.empty()) {
+        *out_error += " for package '" + package + "'";
+      }
+      *out_error += " in '" + file->name() + "'";
+      if (has_prefix) {
+        *out_error += "; but found '" + prefix + "' instead";
+      }
+      *out_error += ".";
+      return false;
+    }
+  }
+
+  // If there was no prefix option, we're done at this point.
+  if (!has_prefix) {
+    if (require_prefixes) {
+      *out_error = "error: '" + file->name() +
+                   "' does not have a required 'option" +
+                   " objc_class_prefix'.";
+      return false;
+    }
+    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 (auto i = expected_package_prefixes.begin();
+         i != expected_package_prefixes.end(); ++i) {
+      if (i->second == prefix) {
+        other_package_for_prefix = i->first;
+        // Stop on the first real package listing, if it was a no_package file
+        // specific entry, keep looking to try and find a package one.
+        if (!absl::StartsWith(other_package_for_prefix, kNoPackagePrefix)) {
+          break;
+        }
+      }
+    }
+
+    // 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 ";
+      if (absl::StartsWith(other_package_for_prefix, kNoPackagePrefix)) {
+        absl::StrAppend(
+            out_error, "file '",
+            absl::StripPrefix(other_package_for_prefix, kNoPackagePrefix),
+            "'.");
+      } else {
+        absl::StrAppend(out_error, "'package ",
+                        other_package_for_prefix + ";'.");
+      }
+      absl::StrAppend(out_error, " It can only be reused by adding '",
+                      lookup_key, " = ", prefix,
+                      "' to the expected prefixes file (",
+                      expected_prefixes_path, ").");
+      return false;  // Only report first usage of the prefix.
+    }
+  }  // !prefix.empty() && have_expected_prefix_file
+
+  // 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 (!prefix.empty() && !absl::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.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 << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
+              << prefix << "\";' in '" << file->name() << "';"
+              << " Apple recommends they should be at least 3 characters long."
+              << std::endl;
+    std::cerr.flush();
+  }
+
+  // Check: Error/Warning - If the given package/prefix pair wasn't expected,
+  // issue a error/warning to added to the file.
+  if (have_expected_prefix_file) {
+    if (prefixes_must_be_registered) {
+      *out_error =
+          "error: '" + file->name() + "' has 'option objc_class_prefix = \"" +
+          prefix + "\";', but it is not registered. Add '" + lookup_key +
+          " = " + (prefix.empty() ? "\"\"" : prefix) +
+          "' to the expected prefixes file (" + expected_prefixes_path + ").";
+      return false;
+    }
+
+    std::cerr
+        << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
+        << prefix << "\";' in '" << file->name() << "'; consider adding '"
+        << lookup_key << " = " << (prefix.empty() ? "\"\"" : prefix)
+        << "' to the expected prefixes file (" << expected_prefixes_path << ")."
+        << std::endl;
+    std::cerr.flush();
+  }
+
+  return true;
+}
+
+}  // namespace
+
+Options::Options() {
+  // While there are generator options, also support env variables to help with
+  // build systems where it isn't as easy to hook in for add the generation
+  // options when invoking protoc.
+  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
+  if (file_path) {
+    expected_prefixes_path = file_path;
+  }
+  const char* suppressions =
+      getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
+  if (suppressions) {
+    expected_prefixes_suppressions =
+        absl::StrSplit(suppressions, ';', absl::SkipEmpty());
+  }
+  prefixes_must_be_registered =
+      BoolFromEnvVar("GPB_OBJC_PREFIXES_MUST_BE_REGISTERED", false);
+  require_prefixes = BoolFromEnvVar("GPB_OBJC_REQUIRE_PREFIXES", false);
+}
+
+bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
+                               std::string* out_error) {
+  // Options's ctor load from the environment.
+  Options options;
+  return ValidateObjCClassPrefixes(files, options, out_error);
+}
+
+bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
+                               const Options& validation_options,
+                               std::string* out_error) {
+  // Allow a '-' as the path for the expected prefixes to completely disable
+  // even the most basic of checks.
+  if (validation_options.expected_prefixes_path == "-") {
+    return true;
+  }
+
+  // Load the expected package prefixes, if available, to validate against.
+  absl::flat_hash_map<std::string, std::string> expected_package_prefixes;
+  if (!LoadExpectedPackagePrefixes(validation_options.expected_prefixes_path,
+                                   &expected_package_prefixes, out_error)) {
+    return false;
+  }
+
+  for (auto file : files) {
+    bool should_skip =
+        (std::find(validation_options.expected_prefixes_suppressions.begin(),
+                   validation_options.expected_prefixes_suppressions.end(),
+                   file->name()) !=
+         validation_options.expected_prefixes_suppressions.end());
+    if (should_skip) {
+      continue;
+    }
+
+    bool is_valid =
+        ValidateObjCClassPrefix(file, validation_options.expected_prefixes_path,
+                                expected_package_prefixes,
+                                validation_options.prefixes_must_be_registered,
+                                validation_options.require_prefixes, out_error);
+    if (!is_valid) {
+      return false;
+    }
+  }
+  return true;
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/names.h b/src/google/protobuf/compiler/objectivec/names.h
new file mode 100644
index 0000000..a6f792e
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/names.h
@@ -0,0 +1,179 @@
+// 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.
+
+// Helper functions for generating ObjectiveC code.
+
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_NAMES_H__
+
+#include <string>
+#include <vector>
+
+#include "google/protobuf/descriptor.h"
+
+// Must be included last
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// Get/Set the path to a file to load for objc class prefix lookups.
+PROTOC_EXPORT std::string GetPackageToPrefixMappingsPath();
+PROTOC_EXPORT void SetPackageToPrefixMappingsPath(const std::string& file_path);
+// 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.
+PROTOC_EXPORT bool UseProtoPackageAsDefaultPrefix();
+PROTOC_EXPORT void SetUseProtoPackageAsDefaultPrefix(bool on_or_off);
+// Get/Set the path to a file to load as exceptions when
+// `UseProtoPackageAsDefaultPrefix()` is `true`. An empty string means there
+// should be no exceptions.
+PROTOC_EXPORT std::string GetProtoPackagePrefixExceptionList();
+PROTOC_EXPORT void SetProtoPackagePrefixExceptionList(
+    const std::string& file_path);
+// Get/Set a prefix to add before the prefix generated from the package name.
+// This is only used when UseProtoPackageAsDefaultPrefix() is True.
+PROTOC_EXPORT std::string GetForcedPackagePrefix();
+PROTOC_EXPORT void SetForcedPackagePrefix(const std::string& prefix);
+
+// Returns true if the name requires a ns_returns_not_retained attribute applied
+// to it.
+PROTOC_EXPORT bool IsRetainedName(const std::string& name);
+
+// Returns true if the name starts with "init" and will need to have special
+// handling under ARC.
+PROTOC_EXPORT bool IsInitName(const std::string& name);
+
+// Returns true if the name requires a cf_returns_not_retained attribute applied
+// to it.
+PROTOC_EXPORT bool IsCreateName(const std::string& name);
+
+// Gets the objc_class_prefix or the prefix made from the proto package.
+PROTOC_EXPORT std::string 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.
+PROTOC_EXPORT std::string FilePath(const FileDescriptor* file);
+
+// Just like FilePath(), but without the directory part.
+PROTOC_EXPORT std::string 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
+PROTOC_EXPORT std::string FileClassName(const FileDescriptor* file);
+
+// These return the fully-qualified class name corresponding to the given
+// descriptor.
+PROTOC_EXPORT std::string ClassName(const Descriptor* descriptor);
+PROTOC_EXPORT std::string ClassName(const Descriptor* descriptor,
+                                    std::string* out_suffix_added);
+PROTOC_EXPORT std::string EnumName(const EnumDescriptor* descriptor);
+
+// Returns the fully-qualified name of the enum value corresponding to the
+// the descriptor.
+PROTOC_EXPORT std::string EnumValueName(const EnumValueDescriptor* descriptor);
+
+// Returns the name of the enum value corresponding to the descriptor.
+PROTOC_EXPORT std::string EnumValueShortName(
+    const EnumValueDescriptor* descriptor);
+
+// Reverse what an enum does.
+PROTOC_EXPORT std::string UnCamelCaseEnumShortName(const std::string& name);
+
+// Returns the name to use for the extension (used as the method off the file's
+// Root class).
+PROTOC_EXPORT std::string ExtensionMethodName(
+    const FieldDescriptor* descriptor);
+
+// Returns the transformed field name.
+PROTOC_EXPORT std::string FieldName(const FieldDescriptor* field);
+PROTOC_EXPORT std::string FieldNameCapitalized(const FieldDescriptor* field);
+
+// Returns the transformed oneof name.
+PROTOC_EXPORT std::string OneofEnumName(const OneofDescriptor* descriptor);
+PROTOC_EXPORT std::string OneofName(const OneofDescriptor* descriptor);
+PROTOC_EXPORT std::string OneofNameCapitalized(
+    const OneofDescriptor* descriptor);
+
+// Reverse of the above.
+PROTOC_EXPORT std::string UnCamelCaseFieldName(const std::string& name,
+                                               const FieldDescriptor* field);
+
+// 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.
+PROTOC_EXPORT std::string ProtobufFrameworkImportSymbol(
+    const std::string& framework_name);
+
+// ---------------------------------------------------------------------------
+
+// These aren't really "naming" related, but can be useful for something
+// building on top of ObjC Protos to be able to share the knowledge/enforcement.
+
+// Checks if the file is one of the proto's bundled with the library.
+PROTOC_EXPORT bool IsProtobufLibraryBundledProtoFile(
+    const FileDescriptor* file);
+
+// Generator Prefix Validation Options (see generator.cc for a
+// description of each):
+struct Options {
+  Options();
+  std::string expected_prefixes_path;
+  std::vector<std::string> expected_prefixes_suppressions;
+  bool prefixes_must_be_registered;
+  bool require_prefixes;
+};
+
+// 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.
+PROTOC_EXPORT bool ValidateObjCClassPrefixes(
+    const std::vector<const FileDescriptor*>& files,
+    const Options& validation_options, std::string* out_error);
+// Same was the other ValidateObjCClassPrefixes() calls, but the options all
+// come from the environment variables.
+PROTOC_EXPORT bool ValidateObjCClassPrefixes(
+    const std::vector<const FileDescriptor*>& files, std::string* out_error);
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_NAMES_H__
diff --git a/src/google/protobuf/compiler/objectivec/names_unittest.cc b/src/google/protobuf/compiler/objectivec/names_unittest.cc
new file mode 100644
index 0000000..1771e17
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/names_unittest.cc
@@ -0,0 +1,137 @@
+// 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 "google/protobuf/compiler/objectivec/names.h"
+
+#include <gtest/gtest.h>
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+namespace {
+
+TEST(ObjCHelper, IsRetainedName) {
+  EXPECT_TRUE(IsRetainedName("new"));
+  EXPECT_TRUE(IsRetainedName("alloc"));
+  EXPECT_TRUE(IsRetainedName("copy"));
+  EXPECT_TRUE(IsRetainedName("mutableCopy"));
+  EXPECT_TRUE(IsRetainedName("newFoo"));
+  EXPECT_TRUE(IsRetainedName("allocFoo"));
+  EXPECT_TRUE(IsRetainedName("copyFoo"));
+  EXPECT_TRUE(IsRetainedName("mutableCopyFoo"));
+  EXPECT_TRUE(IsRetainedName("new_foo"));
+  EXPECT_TRUE(IsRetainedName("alloc_foo"));
+  EXPECT_TRUE(IsRetainedName("copy_foo"));
+  EXPECT_TRUE(IsRetainedName("mutableCopy_foo"));
+
+  EXPECT_FALSE(IsRetainedName(""));
+  EXPECT_FALSE(IsRetainedName("ne"));
+  EXPECT_FALSE(IsRetainedName("all"));
+  EXPECT_FALSE(IsRetainedName("co"));
+  EXPECT_FALSE(IsRetainedName("mutable"));
+  EXPECT_FALSE(IsRetainedName("New"));
+  EXPECT_FALSE(IsRetainedName("Alloc"));
+  EXPECT_FALSE(IsRetainedName("Copy"));
+  EXPECT_FALSE(IsRetainedName("MutableCopy"));
+  EXPECT_FALSE(IsRetainedName("newer"));
+  EXPECT_FALSE(IsRetainedName("alloced"));
+  EXPECT_FALSE(IsRetainedName("copying"));
+  EXPECT_FALSE(IsRetainedName("mutableCopying"));
+
+  EXPECT_FALSE(IsRetainedName("init"));
+  EXPECT_FALSE(IsRetainedName("Create"));
+  EXPECT_FALSE(IsRetainedName("Copy"));
+}
+
+TEST(ObjCHelper, IsInitName) {
+  EXPECT_TRUE(IsInitName("init"));
+  EXPECT_TRUE(IsInitName("initFoo"));
+  EXPECT_TRUE(IsInitName("init_foo"));
+
+  EXPECT_FALSE(IsInitName(""));
+  EXPECT_FALSE(IsInitName("in"));
+  EXPECT_FALSE(IsInitName("Init"));
+  EXPECT_FALSE(IsInitName("inIt"));
+  EXPECT_FALSE(IsInitName("initial"));
+  EXPECT_FALSE(IsInitName("initiAl"));
+  EXPECT_FALSE(IsInitName("fooInit"));
+  EXPECT_FALSE(IsInitName("foo_init"));
+
+  EXPECT_FALSE(IsInitName("new"));
+  EXPECT_FALSE(IsInitName("alloc"));
+  EXPECT_FALSE(IsInitName("copy"));
+  EXPECT_FALSE(IsInitName("mutableCopy"));
+  EXPECT_FALSE(IsInitName("Create"));
+  EXPECT_FALSE(IsInitName("Copy"));
+}
+
+TEST(ObjCHelper, IsCreateName) {
+  EXPECT_TRUE(IsCreateName("Create"));
+  EXPECT_TRUE(IsCreateName("Copy"));
+  EXPECT_TRUE(IsCreateName("CreateFoo"));
+  EXPECT_TRUE(IsCreateName("CopyFoo"));
+  EXPECT_TRUE(IsCreateName("Create_foo"));
+  EXPECT_TRUE(IsCreateName("Copy_foo"));
+  EXPECT_TRUE(IsCreateName("ReCreate"));
+  EXPECT_TRUE(IsCreateName("ReCopy"));
+  EXPECT_TRUE(IsCreateName("FOOCreate"));
+  EXPECT_TRUE(IsCreateName("FOOCopy"));
+  EXPECT_TRUE(IsCreateName("CreateWithCopy"));
+
+  EXPECT_FALSE(IsCreateName(""));
+  EXPECT_FALSE(IsCreateName("Crea"));
+  EXPECT_FALSE(IsCreateName("Co"));
+  EXPECT_FALSE(IsCreateName("create"));
+  EXPECT_FALSE(IsCreateName("recreate"));
+  EXPECT_FALSE(IsCreateName("recopy"));
+  EXPECT_FALSE(IsCreateName("ReCreated"));
+  EXPECT_FALSE(IsCreateName("ReCopying"));
+
+  EXPECT_FALSE(IsCreateName("init"));
+  EXPECT_FALSE(IsCreateName("new"));
+  EXPECT_FALSE(IsCreateName("alloc"));
+  EXPECT_FALSE(IsCreateName("copy"));
+  EXPECT_TRUE(IsCreateName("mutableCopy"));
+}
+
+// TODO(thomasvl): Should probably add some unittests for all the special cases
+// of name mangling (class name, field name, enum names).  Rather than doing
+// this with an ObjC test in the objectivec directory, we should be able to
+// use src/google/protobuf/compiler/importer* (like other tests) to support a
+// virtual file system to feed in protos, once we have the Descriptor tree, the
+// tests could use the helper methods for generating names and validate the
+// right things are happening.
+
+}  // namespace
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/nsobject_methods.h b/src/google/protobuf/compiler/objectivec/nsobject_methods.h
new file mode 100644
index 0000000..7a1b9ef
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/nsobject_methods.h
@@ -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.
+
+// NSObject methods
+// Autogenerated by method_dump.sh. Do not edit by hand.
+// Date: Thu Nov  1 14:12:16 PDT 2018
+// macOS: MacOSX10.14.sdk
+// iOS: iPhoneSimulator12.1.sdk
+
+const char* const kNSObjectMethodsList[] = {
+    "CAMLType",
+    "CA_copyRenderValue",
+    "CA_prepareRenderValue",
+    "NS_copyCGImage",
+    "NS_tiledLayerVisibleRect",
+    "___tryRetain_OA",
+    "__autorelease_OA",
+    "__dealloc_zombie",
+    "__release_OA",
+    "__retain_OA",
+    "_accessibilityFinalize",
+    "_accessibilityIsTableViewDescendant",
+    "_accessibilityUIElementSpecifier",
+    "_accessibilityUseConvenienceAPI",
+    "_allowsDirectEncoding",
+    "_asScriptTerminologyNameArray",
+    "_asScriptTerminologyNameString",
+    "_bindingAdaptor",
+    "_cfTypeID",
+    "_copyDescription",
+    "_destroyObserverList",
+    "_didEndKeyValueObserving",
+    "_implicitObservationInfo",
+    "_internalAccessibilityAttributedHint",
+    "_internalAccessibilityAttributedLabel",
+    "_internalAccessibilityAttributedValue",
+    "_isAXConnector",
+    "_isAccessibilityContainerSectionCandidate",
+    "_isAccessibilityContentNavigatorSectionCandidate",
+    "_isAccessibilityContentSectionCandidate",
+    "_isAccessibilityTopLevelNavigatorSectionCandidate",
+    "_isDeallocating",
+    "_isKVOA",
+    "_isToManyChangeInformation",
+    "_ivarDescription",
+    "_localClassNameForClass",
+    "_methodDescription",
+    "_observerStorage",
+    "_overrideUseFastBlockObservers",
+    "_propertyDescription",
+    "_releaseBindingAdaptor",
+    "_scriptingCount",
+    "_scriptingCountNonrecursively",
+    "_scriptingDebugDescription",
+    "_scriptingExists",
+    "_scriptingShouldCheckObjectIndexes",
+    "_shortMethodDescription",
+    "_shouldSearchChildrenForSection",
+    "_traitStorageList",
+    "_tryRetain",
+    "_ui_descriptionBuilder",
+    "_uikit_variesByTraitCollections",
+    "_web_description",
+    "_webkit_invokeOnMainThread",
+    "_willBeginKeyValueObserving",
+    "accessibilityActivate",
+    "accessibilityActivationPoint",
+    "accessibilityAllowsOverriddenAttributesWhenIgnored",
+    "accessibilityAssistiveTechnologyFocusedIdentifiers",
+    "accessibilityAttributedHint",
+    "accessibilityAttributedLabel",
+    "accessibilityAttributedValue",
+    "accessibilityContainer",
+    "accessibilityContainerType",
+    "accessibilityCustomActions",
+    "accessibilityCustomRotors",
+    "accessibilityDecrement",
+    "accessibilityDragSourceDescriptors",
+    "accessibilityDropPointDescriptors",
+    "accessibilityElementCount",
+    "accessibilityElementDidBecomeFocused",
+    "accessibilityElementDidLoseFocus",
+    "accessibilityElementIsFocused",
+    "accessibilityElements",
+    "accessibilityElementsHidden",
+    "accessibilityFrame",
+    "accessibilityHeaderElements",
+    "accessibilityHint",
+    "accessibilityIdentification",
+    "accessibilityIdentifier",
+    "accessibilityIncrement",
+    "accessibilityLabel",
+    "accessibilityLanguage",
+    "accessibilityLocalizedStringKey",
+    "accessibilityNavigationStyle",
+    "accessibilityOverriddenAttributes",
+    "accessibilityParameterizedAttributeNames",
+    "accessibilityPath",
+    "accessibilityPerformEscape",
+    "accessibilityPerformMagicTap",
+    "accessibilityPresenterProcessIdentifier",
+    "accessibilityShouldUseUniqueId",
+    "accessibilitySupportsNotifications",
+    "accessibilitySupportsOverriddenAttributes",
+    "accessibilityTemporaryChildren",
+    "accessibilityTraits",
+    "accessibilityValue",
+    "accessibilityViewIsModal",
+    "accessibilityVisibleArea",
+    "allPropertyKeys",
+    "allowsWeakReference",
+    "attributeKeys",
+    "autoContentAccessingProxy",
+    "autorelease",
+    "awakeFromNib",
+    "boolValueSafe",
+    "bs_encoded",
+    "bs_isPlistableType",
+    "bs_secureEncoded",
+    "cl_json_serializeKey",
+    "class",
+    "classCode",
+    "classDescription",
+    "classForArchiver",
+    "classForCoder",
+    "classForKeyedArchiver",
+    "classForPortCoder",
+    "className",
+    "clearProperties",
+    "copy",
+    "dealloc",
+    "debugDescription",
+    "defaultAccessibilityTraits",
+    "description",
+    "doubleValueSafe",
+    "entityName",
+    "exposedBindings",
+    "finalize",
+    "finishObserving",
+    "flushKeyBindings",
+    "hash",
+    "init",
+    "int64ValueSafe",
+    "isAccessibilityElement",
+    "isAccessibilityElementByDefault",
+    "isElementAccessibilityExposedToInterfaceBuilder",
+    "isFault",
+    "isNSArray__",
+    "isNSCFConstantString__",
+    "isNSData__",
+    "isNSDate__",
+    "isNSDictionary__",
+    "isNSNumber__",
+    "isNSObject__",
+    "isNSOrderedSet__",
+    "isNSSet__",
+    "isNSString__",
+    "isNSTimeZone__",
+    "isNSValue__",
+    "isProxy",
+    "mutableCopy",
+    "nilValueForKey",
+    "objectSpecifier",
+    "observationInfo",
+    "pep_onDetachedThread",
+    "pep_onMainThread",
+    "pep_onMainThreadIfNecessary",
+    "prepareForInterfaceBuilder",
+    "release",
+    "releaseOnMainThread",
+    "retain",
+    "retainCount",
+    "retainWeakReference",
+    "scriptingProperties",
+    "self",
+    "shouldGroupAccessibilityChildren",
+    "storedAccessibilityActivationPoint",
+    "storedAccessibilityContainerType",
+    "storedAccessibilityElementsHidden",
+    "storedAccessibilityFrame",
+    "storedAccessibilityNavigationStyle",
+    "storedAccessibilityTraits",
+    "storedAccessibilityViewIsModal",
+    "storedIsAccessibilityElement",
+    "storedShouldGroupAccessibilityChildren",
+    "stringValueSafe",
+    "superclass",
+    "toManyRelationshipKeys",
+    "toOneRelationshipKeys",
+    "traitStorageList",
+    "un_safeBoolValue",
+    "userInterfaceItemIdentifier",
+    "utf8ValueSafe",
+    "valuesForKeysWithDictionary",
+    "zone",
+    // Protocol: CAAnimatableValue
+    // Protocol: CARenderValue
+    // Protocol: NSObject
+    // Protocol: ROCKRemoteInvocationInterface
+};
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.cc b/src/google/protobuf/compiler/objectivec/objectivec_file.cc
deleted file mode 100644
index 50b4285..0000000
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.cc
+++ /dev/null
@@ -1,681 +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 <google/protobuf/compiler/objectivec/objectivec_file.h>
-#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
-#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/compiler/objectivec/objectivec_message.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <algorithm> // std::find()
-#include <iostream>
-#include <sstream>
-
-// 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 errors.
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace objectivec {
-
-namespace {
-
-// This is also found in GPBBootstrap.h, and needs to be kept in sync.
-const int32_t GOOGLE_PROTOBUF_OBJC_VERSION = 30004;
-
-const char* kHeaderExtension = ".pbobjc.h";
-
-std::string BundledFileName(const FileDescriptor* file) {
-  return "GPB" + FilePathBasename(file) + kHeaderExtension;
-}
-
-// Checks if a message contains any enums definitions (on the message or
-// a nested message under it).
-bool MessageContainsEnums(const Descriptor* message) {
-  if (message->enum_type_count() > 0) {
-    return true;
-  }
-  for (int i = 0; i < message->nested_type_count(); i++) {
-    if (MessageContainsEnums(message->nested_type(i))) {
-      return true;
-    }
-  }
-  return false;
-}
-
-// Checks if a message contains any extension definitions (on the message or
-// a nested message under it).
-bool MessageContainsExtensions(const Descriptor* message) {
-  if (message->extension_count() > 0) {
-    return true;
-  }
-  for (int i = 0; i < message->nested_type_count(); i++) {
-    if (MessageContainsExtensions(message->nested_type(i))) {
-      return true;
-    }
-  }
-  return false;
-}
-
-// Checks if the file contains any enum definitions (at the root or
-// nested under a message).
-bool FileContainsEnums(const FileDescriptor* file) {
-  if (file->enum_type_count() > 0) {
-    return true;
-  }
-  for (int i = 0; i < file->message_type_count(); i++) {
-    if (MessageContainsEnums(file->message_type(i))) {
-      return true;
-    }
-  }
-  return false;
-}
-
-// Checks if the file contains any extensions definitions (at the root or
-// nested under a message).
-bool FileContainsExtensions(const FileDescriptor* file) {
-  if (file->extension_count() > 0) {
-    return true;
-  }
-  for (int i = 0; i < file->message_type_count(); i++) {
-    if (MessageContainsExtensions(file->message_type(i))) {
-      return true;
-    }
-  }
-  return false;
-}
-
-bool IsDirectDependency(const FileDescriptor* dep, const FileDescriptor* file) {
-  for (int i = 0; i < file->dependency_count(); i++) {
-    if (dep == file->dependency(i)) {
-      return true;
-    }
-  }
-  return false;
-}
-
-struct FileDescriptorsOrderedByName {
-  inline bool operator()(const FileDescriptor* a,
-                         const FileDescriptor* b) const {
-    return a->name() < b->name();
-  }
-};
-
-}  // namespace
-
-FileGenerator::CommonState::CommonState() { }
-
-const FileGenerator::CommonState::MinDepsEntry&
-FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensionsInternal(
-    const FileDescriptor* file) {
-  auto it = deps_info_cache_.find(file);
-  if (it != deps_info_cache_.end()) {
-    return it->second;
-  }
-
-  std::set<const FileDescriptor*> min_deps_collector;
-  std::set<const FileDescriptor*> covered_deps_collector;
-  std::set<const FileDescriptor*> to_prune;
-  for (int i = 0; i < file->dependency_count(); i++) {
-    const FileDescriptor* dep = file->dependency(i);
-    MinDepsEntry dep_info =
-        CollectMinimalFileDepsContainingExtensionsInternal(dep);
-
-    // Everything the dep covered, this file will also cover.
-    covered_deps_collector.insert(dep_info.covered_deps.begin(), dep_info.covered_deps.end());
-    // Prune everything from the dep's covered list in case another dep lists it
-    // as a min dep.
-    to_prune.insert(dep_info.covered_deps.begin(), dep_info.covered_deps.end());
-
-    // Does the dep have any extensions...
-    if (dep_info.has_extensions) {
-      // Yes -> Add this file, prune its min_deps and add them to the covered deps.
-      min_deps_collector.insert(dep);
-      to_prune.insert(dep_info.min_deps.begin(), dep_info.min_deps.end());
-      covered_deps_collector.insert(dep_info.min_deps.begin(), dep_info.min_deps.end());
-    } else {
-      // No -> Just use its min_deps.
-      min_deps_collector.insert(dep_info.min_deps.begin(), dep_info.min_deps.end());
-    }
-  }
-
-  const bool file_has_exts = FileContainsExtensions(file);
-
-  // Fast path: if nothing to prune or there was only one dep, the prune work is
-  // a waste, skip it.
-  if (to_prune.empty() || file->dependency_count() == 1) {
-    return deps_info_cache_.insert(
-        {file, {file_has_exts, min_deps_collector, covered_deps_collector}}).first->second;
-  }
-
-  std::set<const FileDescriptor*> min_deps;
-  std::copy_if(min_deps_collector.begin(), min_deps_collector.end(),
-               std::inserter(min_deps, min_deps.end()),
-               [&](const FileDescriptor* value){
-    return to_prune.find(value) == to_prune.end();
-  });
-  return deps_info_cache_.insert(
-      {file, {file_has_exts, min_deps, covered_deps_collector}}).first->second;
-}
-
-// Collect the deps of the given file that contain extensions. This can be used to
-// create the chain of roots that need to be wired together.
-//
-// NOTE: If any changes are made to this and the supporting functions, you will
-// need to manually validate what the generated code is for the test files:
-//   objectivec/Tests/unittest_extension_chain_*.proto
-// There are comments about what the expected code should be line and limited
-// testing objectivec/Tests/GPBUnittestProtos2.m around compilation (#imports
-// specifically).
-const std::vector<const FileDescriptor*>
-FileGenerator::CommonState::CollectMinimalFileDepsContainingExtensions(
-    const FileDescriptor* file) {
-  std::set<const FileDescriptor*> min_deps =
-    CollectMinimalFileDepsContainingExtensionsInternal(file).min_deps;
-  // Sort the list since pointer order isn't stable across runs.
-  std::vector<const FileDescriptor*> result(min_deps.begin(), min_deps.end());
-  std::sort(result.begin(), result.end(), FileDescriptorsOrderedByName());
-  return result;
-}
-
-FileGenerator::FileGenerator(const FileDescriptor* file,
-                             const GenerationOptions& generation_options,
-                             CommonState& common_state)
-    : file_(file),
-      generation_options_(generation_options),
-      common_state_(common_state),
-      root_class_name_(FileClassName(file)),
-      is_bundled_proto_(IsProtobufLibraryBundledProtoFile(file)) {
-  for (int i = 0; i < file_->enum_type_count(); 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 =
-        new MessageGenerator(root_class_name_, file_->message_type(i));
-    message_generators_.emplace_back(generator);
-  }
-  for (int i = 0; i < file_->extension_count(); i++) {
-    ExtensionGenerator* generator =
-        new ExtensionGenerator(root_class_name_, file_->extension(i));
-    extension_generators_.emplace_back(generator);
-  }
-}
-
-FileGenerator::~FileGenerator() {}
-
-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.push_back("GPBDescriptor.h");
-    headers.push_back("GPBMessage.h");
-    headers.push_back("GPBRootObject.h");
-    for (int i = 0; i < file_->dependency_count(); i++) {
-      const std::string header_name = BundledFileName(file_->dependency(i));
-      headers.push_back(header_name);
-    }
-  } else {
-    headers.push_back("GPBProtocolBuffers.h");
-  }
-  PrintFileRuntimePreamble(printer, headers);
-
-  // Add some verification that the generated code matches the source the
-  // code is being compiled with.
-  // NOTE: This captures the raw numeric values at the time the generator was
-  // compiled, since that will be the versions for the ObjC runtime at that
-  // time.  The constants in the generated code will then get their values at
-  // at compile time (so checking against the headers being used to compile).
-  printer->Print(
-      "#if GOOGLE_PROTOBUF_OBJC_VERSION < $google_protobuf_objc_version$\n"
-      "#error This file was generated by a newer version of protoc which is incompatible with your Protocol Buffer library sources.\n"
-      "#endif\n"
-      "#if $google_protobuf_objc_version$ < GOOGLE_PROTOBUF_OBJC_MIN_SUPPORTED_VERSION\n"
-      "#error This file was generated by an older version of protoc which is incompatible with your Protocol Buffer library sources.\n"
-      "#endif\n"
-      "\n",
-      "google_protobuf_objc_version", StrCat(GOOGLE_PROTOBUF_OBJC_VERSION));
-
-  // The bundled protos (WKTs) don't use of forward declarations.
-  bool headers_use_forward_declarations =
-      generation_options_.headers_use_forward_declarations && !is_bundled_proto_;
-
-  {
-    ImportWriter import_writer(
-        generation_options_.generate_for_named_framework,
-        generation_options_.named_framework_to_proto_path_mappings_path,
-        generation_options_.runtime_import_prefix,
-        /* include_wkt_imports = */ false);
-    const std::string header_extension(kHeaderExtension);
-    if (headers_use_forward_declarations) {
-      // #import any headers for "public imports" in the proto file.
-      for (int i = 0; i < file_->public_dependency_count(); i++) {
-        import_writer.AddFile(file_->public_dependency(i), header_extension);
-      }
-    } else {
-      for (int i = 0; i < file_->dependency_count(); i++) {
-        import_writer.AddFile(file_->dependency(i), header_extension);
-      }
-    }
-    import_writer.Print(printer);
-  }
-
-  // Note:
-  //  deprecated-declarations suppression is only needed if some place in this
-  //    proto file is something deprecated or if it references something from
-  //    another file that is deprecated.
-  printer->Print(
-      "// @@protoc_insertion_point(imports)\n"
-      "\n"
-      "#pragma clang diagnostic push\n"
-      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n"
-      "\n"
-      "CF_EXTERN_C_BEGIN\n"
-      "\n");
-
-  std::set<std::string> fwd_decls;
-  for (const auto& generator : message_generators_) {
-    generator->DetermineForwardDeclarations(
-        &fwd_decls,
-        /* include_external_types = */ headers_use_forward_declarations);
-  }
-  for (std::set<std::string>::const_iterator i(fwd_decls.begin());
-       i != fwd_decls.end(); ++i) {
-    printer->Print("$value$;\n", "value", *i);
-  }
-  if (fwd_decls.begin() != fwd_decls.end()) {
-    printer->Print("\n");
-  }
-
-  printer->Print(
-      "NS_ASSUME_NONNULL_BEGIN\n"
-      "\n");
-
-  // need to write out all enums first
-  for (const auto& generator : enum_generators_) {
-    generator->GenerateHeader(printer);
-  }
-
-  for (const auto& generator : message_generators_) {
-    generator->GenerateEnumHeader(printer);
-  }
-
-  // For extensions to chain together, the Root gets created even if there
-  // are no extensions.
-  printer->Print(
-      "#pragma mark - $root_class_name$\n"
-      "\n"
-      "/**\n"
-      " * Exposes the extension registry for this file.\n"
-      " *\n"
-      " * The base class provides:\n"
-      " * @code\n"
-      " *   + (GPBExtensionRegistry *)extensionRegistry;\n"
-      " * @endcode\n"
-      " * which is a @c GPBExtensionRegistry that includes all the extensions defined by\n"
-      " * this file and all files that it depends on.\n"
-      " **/\n"
-      "GPB_FINAL @interface $root_class_name$ : GPBRootObject\n"
-      "@end\n"
-      "\n",
-      "root_class_name", root_class_name_);
-
-  if (!extension_generators_.empty()) {
-    // The dynamic methods block is only needed if there are extensions.
-    printer->Print(
-        "@interface $root_class_name$ (DynamicMethods)\n",
-        "root_class_name", root_class_name_);
-
-    for (const auto& generator : extension_generators_) {
-      generator->GenerateMembersHeader(printer);
-    }
-
-    printer->Print("@end\n\n");
-  }  // !extension_generators_.empty()
-
-  for (const auto& generator : message_generators_) {
-    generator->GenerateMessageHeader(printer);
-  }
-
-  printer->Print(
-      "NS_ASSUME_NONNULL_END\n"
-      "\n"
-      "CF_EXTERN_C_END\n"
-      "\n"
-      "#pragma clang diagnostic pop\n"
-      "\n"
-      "// @@protoc_insertion_point(global_scope)\n");
-}
-
-void FileGenerator::GenerateSource(io::Printer* printer) {
-  // #import the runtime support.
-  std::vector<std::string> headers;
-  headers.push_back("GPBProtocolBuffers_RuntimeSupport.h");
-  if (is_bundled_proto_) {
-    headers.push_back(BundledFileName(file_));
-  }
-  PrintFileRuntimePreamble(printer, headers);
-
-  // Enums use atomic in the generated code, so add the system import as needed.
-  if (FileContainsEnums(file_)) {
-    printer->Print(
-        "#import <stdatomic.h>\n"
-        "\n");
-  }
-
-  std::vector<const FileDescriptor*> deps_with_extensions =
-    common_state_.CollectMinimalFileDepsContainingExtensions(file_);
-
-  // The bundled protos (WKTs) don't use of forward declarations.
-  bool headers_use_forward_declarations =
-      generation_options_.headers_use_forward_declarations && !is_bundled_proto_;
-
-  {
-    ImportWriter import_writer(
-        generation_options_.generate_for_named_framework,
-        generation_options_.named_framework_to_proto_path_mappings_path,
-        generation_options_.runtime_import_prefix,
-        /* include_wkt_imports = */ false);
-    const std::string header_extension(kHeaderExtension);
-
-    // #import the header for this proto file.
-    import_writer.AddFile(file_, header_extension);
-
-    if (headers_use_forward_declarations) {
-      // #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<std::string> public_import_names;
-      for (int i = 0; i < file_->public_dependency_count(); i++) {
-        public_import_names.insert(file_->public_dependency(i)->name());
-      }
-      for (int i = 0; i < file_->dependency_count(); i++) {
-        const FileDescriptor *dep = file_->dependency(i);
-        bool public_import = (public_import_names.count(dep->name()) != 0);
-        if (!public_import) {
-          import_writer.AddFile(dep, header_extension);
-        }
-      }
-    }
-
-    // If any indirect dependency provided extensions, it needs to be directly
-    // 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 =
-             deps_with_extensions.begin();
-         iter != deps_with_extensions.end(); ++iter) {
-      if (!IsDirectDependency(*iter, file_)) {
-        import_writer.AddFile(*iter, header_extension);
-      }
-    }
-
-    import_writer.Print(printer);
-  }
-
-  bool includes_oneof = false;
-  for (const auto& generator : message_generators_) {
-    if (generator->IncludesOneOfDefinition()) {
-      includes_oneof = true;
-      break;
-    }
-  }
-
-  std::set<std::string> fwd_decls;
-  for (const auto& generator : message_generators_) {
-    generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
-  }
-  for (const auto& generator : extension_generators_) {
-    generator->DetermineObjectiveCClassDefinitions(&fwd_decls);
-  }
-
-  // Note:
-  //  deprecated-declarations suppression is only needed if some place in this
-  //    proto file is something deprecated or if it references something from
-  //    another file that is deprecated.
-  //  dollar-in-identifier-extension is needed because we use references to
-  //    objc class names that have $ in identifiers.
-  printer->Print(
-      "// @@protoc_insertion_point(imports)\n"
-      "\n"
-      "#pragma clang diagnostic push\n"
-      "#pragma clang diagnostic ignored \"-Wdeprecated-declarations\"\n");
-  if (includes_oneof) {
-    // The generated code for oneof's uses direct ivar access, suppress 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");
-  }
-  if (!fwd_decls.empty()) {
-    printer->Print(
-      "#pragma clang diagnostic ignored \"-Wdollar-in-identifier-extension\"\n");
-  }
-  printer->Print(
-      "\n");
-  if (!fwd_decls.empty()) {
-    printer->Print(
-        "#pragma mark - Objective C Class declarations\n"
-        "// Forward declarations of Objective C classes that we can use as\n"
-        "// static values in struct initializers.\n"
-        "// We don't use [Foo class] because it is not a static value.\n");
-  }
-  for (const auto& i : fwd_decls) {
-    printer->Print("$value$\n", "value", i);
-  }
-  if (!fwd_decls.empty()) {
-    printer->Print("\n");
-  }
-  printer->Print(
-      "#pragma mark - $root_class_name$\n"
-      "\n"
-      "@implementation $root_class_name$\n\n",
-      "root_class_name", root_class_name_);
-
-  const bool file_contains_extensions = FileContainsExtensions(file_);
-
-  // If there were any extensions or this file has any dependencies, output
-  // a registry to override to create the file specific registry.
-  if (file_contains_extensions || !deps_with_extensions.empty()) {
-    printer->Print(
-        "+ (GPBExtensionRegistry*)extensionRegistry {\n"
-        "  // This is called by +initialize so there is no need to worry\n"
-        "  // about thread safety and initialization of registry.\n"
-        "  static GPBExtensionRegistry* registry = nil;\n"
-        "  if (!registry) {\n"
-        "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n"
-        "    registry = [[GPBExtensionRegistry alloc] init];\n");
-
-    printer->Indent();
-    printer->Indent();
-
-    if (file_contains_extensions) {
-      printer->Print(
-          "static GPBExtensionDescription descriptions[] = {\n");
-      printer->Indent();
-      for (const auto& generator : extension_generators_) {
-        generator->GenerateStaticVariablesInitialization(printer);
-      }
-      for (const auto& generator : message_generators_) {
-        generator->GenerateStaticVariablesInitialization(printer);
-      }
-      printer->Outdent();
-      printer->Print(
-          "};\n"
-          "for (size_t i = 0; i < sizeof(descriptions) / sizeof(descriptions[0]); ++i) {\n"
-          "  GPBExtensionDescriptor *extension =\n"
-          "      [[GPBExtensionDescriptor alloc] initWithExtensionDescription:&descriptions[i]\n"
-          "                                                     usesClassRefs:YES];\n"
-          "  [registry addExtension:extension];\n"
-          "  [self globallyRegisterExtension:extension];\n"
-          "  [extension release];\n"
-          "}\n");
-    }
-
-    if (deps_with_extensions.empty()) {
-      printer->Print(
-          "// None of the imports (direct or indirect) defined extensions, so no need to add\n"
-          "// them to this registry.\n");
-    } else {
-      printer->Print(
-          "// Merge in the imports (direct or indirect) that defined extensions.\n");
-      for (std::vector<const FileDescriptor*>::iterator iter =
-               deps_with_extensions.begin();
-           iter != deps_with_extensions.end(); ++iter) {
-        const std::string root_class_name(FileClassName((*iter)));
-        printer->Print(
-            "[registry addExtensions:[$dependency$ extensionRegistry]];\n",
-            "dependency", root_class_name);
-      }
-    }
-
-    printer->Outdent();
-    printer->Outdent();
-
-    printer->Print(
-        "  }\n"
-        "  return registry;\n"
-        "}\n");
-  } else {
-    if (file_->dependency_count() > 0) {
-      printer->Print(
-          "// No extensions in the file and none of the imports (direct or indirect)\n"
-          "// defined extensions, so no need to generate +extensionRegistry.\n");
-    } else {
-      printer->Print(
-          "// No extensions in the file and no imports, so no need to generate\n"
-          "// +extensionRegistry.\n");
-    }
-  }
-
-  printer->Print("\n@end\n\n");
-
-  // File descriptor only needed if there are messages to use it.
-  if (!message_generators_.empty()) {
-    std::map<std::string, std::string> vars;
-    vars["root_class_name"] = root_class_name_;
-    vars["package"] = file_->package();
-    vars["objc_prefix"] = FileClassPrefix(file_);
-    switch (file_->syntax()) {
-      case FileDescriptor::SYNTAX_UNKNOWN:
-        vars["syntax"] = "GPBFileSyntaxUnknown";
-        break;
-      case FileDescriptor::SYNTAX_PROTO2:
-        vars["syntax"] = "GPBFileSyntaxProto2";
-        break;
-      case FileDescriptor::SYNTAX_PROTO3:
-        vars["syntax"] = "GPBFileSyntaxProto3";
-        break;
-    }
-    printer->Print(vars,
-        "#pragma mark - $root_class_name$_FileDescriptor\n"
-        "\n"
-        "static GPBFileDescriptor *$root_class_name$_FileDescriptor(void) {\n"
-        "  // This is called by +initialize so there is no need to worry\n"
-        "  // about thread safety of the singleton.\n"
-        "  static GPBFileDescriptor *descriptor = NULL;\n"
-        "  if (!descriptor) {\n"
-        "    GPB_DEBUG_CHECK_RUNTIME_VERSIONS();\n");
-    if (!vars["objc_prefix"].empty()) {
-      printer->Print(
-          vars,
-          "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
-          "                                                 objcPrefix:@\"$objc_prefix$\"\n"
-          "                                                     syntax:$syntax$];\n");
-    } else {
-      printer->Print(
-          vars,
-          "    descriptor = [[GPBFileDescriptor alloc] initWithPackage:@\"$package$\"\n"
-          "                                                     syntax:$syntax$];\n");
-    }
-    printer->Print(
-        "  }\n"
-        "  return descriptor;\n"
-        "}\n"
-        "\n");
-  }
-
-  for (const auto& generator : enum_generators_) {
-    generator->GenerateSource(printer);
-  }
-  for (const auto& generator : message_generators_) {
-    generator->GenerateSource(printer);
-  }
-
-  printer->Print(
-    "\n"
-    "#pragma clang diagnostic pop\n"
-    "\n"
-    "// @@protoc_insertion_point(global_scope)\n");
-}
-
-// Helper to print the import of the runtime support at the top of generated
-// 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::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());
-
-  if (is_bundled_proto_) {
-    // This is basically a clone of ImportWriter::PrintRuntimeImports() but
-    // without the CPP symbol gate, since within the bundled files, that isn't
-    // needed.
-    std::string import_prefix = generation_options_.runtime_import_prefix;
-    if (!import_prefix.empty()) {
-      import_prefix += "/";
-    }
-    for (const auto& header : headers_to_import) {
-      printer->Print(
-          "#import \"$import_prefix$$header$\"\n",
-          "import_prefix", import_prefix,
-          "header", header);
-    }
-  } else {
-    ImportWriter::PrintRuntimeImports(
-        printer, headers_to_import, generation_options_.runtime_import_prefix, true);
-  }
-
-  printer->Print("\n");
-}
-
-}  // namespace objectivec
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_file.h b/src/google/protobuf/compiler/objectivec/objectivec_file.h
deleted file mode 100644
index ef49cf8..0000000
--- a/src/google/protobuf/compiler/objectivec/objectivec_file.h
+++ /dev/null
@@ -1,115 +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_COMPILER_OBJECTIVEC_FILE_H__
-#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
-
-#include <map>
-#include <set>
-#include <string>
-#include <vector>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace objectivec {
-
-class EnumGenerator;
-class ExtensionGenerator;
-class MessageGenerator;
-
-class FileGenerator {
- public:
-  struct GenerationOptions {
-    GenerationOptions()
-      // TODO(thomasvl): Eventually flip this default to false for better
-      // interop with Swift if proto usages span modules made from ObjC sources.
-      : headers_use_forward_declarations(true) {}
-    std::string generate_for_named_framework;
-    std::string named_framework_to_proto_path_mappings_path;
-    std::string runtime_import_prefix;
-    bool headers_use_forward_declarations;
-  };
-
-  // Wrapper for some common state that is shared between file generations to
-  // improve performance when more than one file is generated at a time.
-  struct CommonState {
-    CommonState();
-
-    const std::vector<const FileDescriptor*>
-    CollectMinimalFileDepsContainingExtensions(const FileDescriptor* file);
-
-   private:
-    struct MinDepsEntry {
-      bool has_extensions;
-      std::set<const FileDescriptor*> min_deps;
-      // `covered_deps` are the transtive deps of `min_deps_w_exts` that also
-      // have extensions.
-      std::set<const FileDescriptor*> covered_deps;
-    };
-    const MinDepsEntry& CollectMinimalFileDepsContainingExtensionsInternal(const FileDescriptor* file);
-    std::map<const FileDescriptor*, MinDepsEntry> deps_info_cache_;
-  };
-
-  FileGenerator(const FileDescriptor* file,
-                const GenerationOptions& generation_options,
-                CommonState& common_state);
-  ~FileGenerator();
-
-  FileGenerator(const FileGenerator&) = delete;
-  FileGenerator& operator=(const FileGenerator&) = delete;
-
-  void GenerateSource(io::Printer* printer);
-  void GenerateHeader(io::Printer* printer);
-
- private:
-  const FileDescriptor* file_;
-  const GenerationOptions& generation_options_;
-  CommonState& common_state_;
-  std::string root_class_name_;
-  bool is_bundled_proto_;
-
-  std::vector<std::unique_ptr<EnumGenerator>> enum_generators_;
-  std::vector<std::unique_ptr<MessageGenerator>> message_generators_;
-  std::vector<std::unique_ptr<ExtensionGenerator>> extension_generators_;
-
-  void PrintFileRuntimePreamble(
-      io::Printer* printer,
-      const std::vector<std::string>& headers_to_import) const;
-};
-
-}  // namespace objectivec
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_FILE_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc b/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
deleted file mode 100644
index b15f580..0000000
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.cc
+++ /dev/null
@@ -1,2043 +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 _MSC_VER
-#include <unistd.h>
-#endif
-#include <climits>
-#include <errno.h>
-#include <fcntl.h>
-#include <fstream>
-#include <iostream>
-#include <sstream>
-#include <stdlib.h>
-#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>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
-
-// 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 errors.
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace objectivec {
-
-// <io.h> is transitively included in this file. Import the functions explicitly
-// in this port namespace to avoid ambiguous definition.
-namespace posix {
-#ifdef _WIN32
-using ::google::protobuf::io::win32::open;
-#else
-using ::open;
-#endif
-}  // namespace port
-
-namespace {
-
-bool BoolFromEnvVar(const char* env_var, bool default_value) {
-  const char* value = getenv(env_var);
-  if (value) {
-    return std::string("YES") == ToUpper(value);
-  }
-  return default_value;
-}
-
-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 PackageToPrefixesCollector : public LineConsumer {
- public:
-  PackageToPrefixesCollector(const std::string &usage,
-                             std::map<std::string, std::string>* inout_package_to_prefix_map)
-      : usage_(usage), prefix_map_(inout_package_to_prefix_map) {}
-
-  virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override;
-
- private:
-  const std::string usage_;
-  std::map<std::string, std::string>* prefix_map_;
-};
-
-class PrefixModeStorage {
- public:
-  PrefixModeStorage();
-
-  const std::string package_to_prefix_mappings_path() const { return package_to_prefix_mappings_path_; }
-  void set_package_to_prefix_mappings_path(const std::string& path) {
-    package_to_prefix_mappings_path_ = path;
-    package_to_prefix_map_.clear();
-  }
-
-  std::string prefix_from_proto_package_mappings(const FileDescriptor* file);
-
-  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);
-
-  // When using a proto package as the prefix, this should be added as the
-  // prefix in front of it.
-  const std::string& forced_package_prefix() const { return forced_prefix_; }
-
- private:
-  bool use_package_name_;
-  std::map<std::string, std::string> package_to_prefix_map_;
-  std::string package_to_prefix_mappings_path_;
-  std::string exception_path_;
-  std::string forced_prefix_;
-  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.
-
-  use_package_name_ = BoolFromEnvVar("GPB_OBJC_USE_PACKAGE_AS_PREFIX", false);
-
-  const char* exception_path = getenv("GPB_OBJC_PACKAGE_PREFIX_EXCEPTIONS_PATH");
-  if (exception_path) {
-    exception_path_ = exception_path;
-  }
-
-  // This one is a not expected to be common, so it doesn't get a generation
-  // option, just the env var.
-  const char* prefix = getenv("GPB_OBJC_USE_PACKAGE_AS_PREFIX_PREFIX");
-  if (prefix) {
-    forced_prefix_ = prefix;
-  }
-}
-
-std::string PrefixModeStorage::prefix_from_proto_package_mappings(const FileDescriptor* file) {
-  if (!file) {
-    return "";
-  }
-
-  if (package_to_prefix_map_.empty() && !package_to_prefix_mappings_path_.empty()) {
-    std::string error_str;
-    // Re use the same collector as we use for expected_prefixes_path since the file
-    // format is the same.
-    PackageToPrefixesCollector collector("Package to prefixes", &package_to_prefix_map_);
-    if (!ParseSimpleFile(package_to_prefix_mappings_path_, &collector, &error_str)) {
-      if (error_str.empty()) {
-        error_str = std::string("protoc:0: warning: Failed to parse")
-           + std::string(" prefix to proto package mappings file: ")
-           + package_to_prefix_mappings_path_;
-      }
-      std::cerr << error_str << std::endl;
-      std::cerr.flush();
-      package_to_prefix_map_.clear();
-    }
-  }
-
-  const std::string package = file->package();
-  // For files without packages, the can be registered as "no_package:PATH",
-  // allowing the expected prefixes file.
-  static const std::string no_package_prefix("no_package:");
-  const std::string lookup_key = package.empty() ? no_package_prefix + file->name() : package;
-
-  std::map<std::string, std::string>::const_iterator prefix_lookup =
-      package_to_prefix_map_.find(lookup_key);
-
-  if (prefix_lookup != package_to_prefix_map_.end()) {
-    return prefix_lookup->second;
-  }  
-
-  return "";
-}
-
-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
-
-std::string GetPackageToPrefixMappingsPath() {
-  return g_prefix_mode.package_to_prefix_mappings_path();
-}
-
-void SetPackageToPrefixMappingsPath(const std::string& file_path) {
-  g_prefix_mode.set_package_to_prefix_mappings_path(file_path);
-}
-
-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() {
-  // While there are generator options, also support env variables to help with
-  // build systems where it isn't as easy to hook in for add the generation
-  // options when invoking protoc.
-  const char* file_path = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES");
-  if (file_path) {
-    expected_prefixes_path = file_path;
-  }
-  const char* suppressions = getenv("GPB_OBJC_EXPECTED_PACKAGE_PREFIXES_SUPPRESSIONS");
-  if (suppressions) {
-    expected_prefixes_suppressions =
-        Split(suppressions, ";", true);
-  }
-  prefixes_must_be_registered =
-      BoolFromEnvVar("GPB_OBJC_PREFIXES_MUST_BE_REGISTERED", false);
-  require_prefixes = BoolFromEnvVar("GPB_OBJC_REQUIRE_PREFIXES", false);
-}
-
-namespace {
-
-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]);
-  }
-  return result;
-}
-
-const char* const kUpperSegmentsList[] = {"url", "http", "https"};
-
-std::unordered_set<std::string> kUpperSegments =
-    MakeWordsMap(kUpperSegmentsList, GOOGLE_ARRAYSIZE(kUpperSegmentsList));
-
-bool ascii_isnewline(char c) {
-  return c == '\n' || c == '\r';
-}
-
-// 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.
-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;
-  bool last_char_was_upper = false;
-  for (int i = 0; i < input.size(); i++) {
-    char c = input[i];
-    if (ascii_isdigit(c)) {
-      if (!last_char_was_number) {
-        values.push_back(current);
-        current = "";
-      }
-      current += c;
-      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
-      last_char_was_number = true;
-    } else if (ascii_islower(c)) {
-      // lowercase letter can follow a lowercase or uppercase letter
-      if (!last_char_was_lower && !last_char_was_upper) {
-        values.push_back(current);
-        current = "";
-      }
-      current += c;  // already lower
-      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
-      last_char_was_lower = true;
-    } else if (ascii_isupper(c)) {
-      if (!last_char_was_upper) {
-        values.push_back(current);
-        current = "";
-      }
-      current += ascii_tolower(c);
-      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
-      last_char_was_upper = true;
-    } else {
-      last_char_was_number = last_char_was_lower = last_char_was_upper = false;
-    }
-  }
-  values.push_back(current);
-
-  std::string result;
-  bool first_segment_forces_upper = false;
-  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;
-    }
-    for (int j = 0; j < value.length(); j++) {
-      if (j == 0 || all_upper) {
-        value[j] = ascii_toupper(value[j]);
-      } else {
-        // Nothing, already in lower.
-      }
-    }
-    result += value;
-  }
-  if ((result.length() != 0) &&
-      !first_capitalized &&
-      !first_segment_forces_upper) {
-    result[0] = ascii_tolower(result[0]);
-  }
-  return result;
-}
-
-const char* const kReservedWordList[] = {
-  // Note NSObject Methods:
-  // These are brought in from objectivec_nsobject_methods.h that is generated
-  // using method_dump.sh. See kNSObjectMethods below.
-
-  // Objective C "keywords" that aren't in C
-  // From
-  // http://stackoverflow.com/questions/1873630/reserved-keywords-in-objective-c
-  // with some others added on.
-  "id", "_cmd", "super", "in", "out", "inout", "bycopy", "byref", "oneway",
-  "self", "instancetype", "nullable", "nonnull", "nil", "Nil",
-  "YES", "NO", "weak",
-
-  // C/C++ keywords (Incl C++ 0x11)
-  // From http://en.cppreference.com/w/cpp/keywords
-  "and", "and_eq", "alignas", "alignof", "asm", "auto", "bitand", "bitor",
-  "bool", "break", "case", "catch", "char", "char16_t", "char32_t", "class",
-  "compl", "const", "constexpr", "const_cast", "continue", "decltype",
-  "default", "delete", "double", "dynamic_cast", "else", "enum", "explicit",
-  "export", "extern ", "false", "float", "for", "friend", "goto", "if",
-  "inline", "int", "long", "mutable", "namespace", "new", "noexcept", "not",
-  "not_eq", "nullptr", "operator", "or", "or_eq", "private", "protected",
-  "public", "register", "reinterpret_cast", "return", "short", "signed",
-  "sizeof", "static", "static_assert", "static_cast", "struct", "switch",
-  "template", "this", "thread_local", "throw", "true", "try", "typedef",
-  "typeid", "typename", "union", "unsigned", "using", "virtual", "void",
-  "volatile", "wchar_t", "while", "xor", "xor_eq",
-
-  // C99 keywords
-  // From
-  // http://publib.boulder.ibm.com/infocenter/lnxpcomp/v8v101/index.jsp?topic=%2Fcom.ibm.xlcpp8l.doc%2Flanguage%2Fref%2Fkeyw.htm
-  "restrict",
-
-  // GCC/Clang extension
-  "typeof",
-
-  // 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",
-
-  // GPBMessage Methods
-  // Only need to add instance methods that may conflict with
-  // method declared in protos. The main cases are methods
-  // that take no arguments, or setFoo:/hasFoo: type methods.
-  "clear", "data", "delimitedData", "descriptor", "extensionRegistry",
-  "extensionsCurrentlySet", "initialized", "isInitialized", "serializedSize",
-  "sortedExtensionsInUse", "unknownFields",
-
-  // MacTypes.h names
-  "Fixed", "Fract", "Size", "LogicalAddress", "PhysicalAddress", "ByteCount",
-  "ByteOffset", "Duration", "AbsoluteTime", "OptionBits", "ItemCount",
-  "PBVersion", "ScriptCode", "LangCode", "RegionCode", "OSType",
-  "ProcessSerialNumber", "Point", "Rect", "FixedPoint", "FixedRect", "Style",
-  "StyleParameter", "StyleField", "TimeScale", "TimeBase", "TimeRecord",
-};
-
-// returns true is input starts with __ or _[A-Z] which are reserved identifiers
-// in C/ C++. All calls should go through UnderscoresToCamelCase before getting here
-// 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 std::string& input) {
-  if (input.length() > 2) {
-    if (input.at(0) == '_') {
-      if (isupper(input.at(1)) || input.at(1) == '_') {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-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<std::string> kNSObjectMethods =
-      MakeWordsMap(kNSObjectMethodsList, GOOGLE_ARRAYSIZE(kNSObjectMethodsList));
-  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
-  // b) Isn't equivalent to the prefix or
-  // c) Has the prefix, but the letter after the prefix is lowercase
-  if (HasPrefixString(input, prefix)) {
-    if (input.length() == prefix.length() || !ascii_isupper(input[prefix.length()])) {
-      sanitized = prefix + input;
-    } else {
-      sanitized = input;
-    }
-  } else {
-    sanitized = prefix + input;
-  }
-  if (IsReservedCIdentifier(sanitized) ||
-      (kReservedWords.count(sanitized) > 0) ||
-      (kNSObjectMethods.count(sanitized) > 0)) {
-    if (out_suffix_added) *out_suffix_added = extension;
-    return sanitized + extension;
-  }
-  if (out_suffix_added) out_suffix_added->clear();
-  return sanitized;
-}
-
-std::string NameFromFieldDescriptor(const FieldDescriptor* field) {
-  if (field->type() == FieldDescriptor::TYPE_GROUP) {
-    return field->message_type()->name();
-  } else {
-    return field->name();
-  }
-}
-
-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 = "";
-    }
-    if (basename) {
-      *basename = path;
-    }
-  } else {
-    if (directory) {
-      *directory = path.substr(0, last_slash);
-    }
-    if (basename) {
-      *basename = path.substr(last_slash + 1);
-    }
-  }
-}
-
-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();
-    if (name.compare(0, length, special_names[i]) == 0) {
-      if (name.length() > length) {
-        // If name is longer than the retained_name[i] that it matches
-        // the next character must be not lower case (newton vs newTon vs
-        // new_ton).
-        return !ascii_islower(name[length]);
-      } else {
-        return true;
-      }
-    }
-  }
-  return false;
-}
-
-std::string GetZeroEnumNameForFlagType(const FlagType flag_type) {
-  switch(flag_type) {
-    case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
-      return "GPBDescriptorInitializationFlag_None";
-    case FLAGTYPE_EXTENSION:
-      return "GPBExtensionNone";
-    case FLAGTYPE_FIELD:
-      return "GPBFieldNone";
-    default:
-      GOOGLE_LOG(FATAL) << "Can't get here.";
-      return "0";
-  }
-}
-
-std::string GetEnumNameForFlagType(const FlagType flag_type) {
-  switch(flag_type) {
-    case FLAGTYPE_DESCRIPTOR_INITIALIZATION:
-      return "GPBDescriptorInitializationFlags";
-    case FLAGTYPE_EXTENSION:
-      return "GPBExtensionOptions";
-    case FLAGTYPE_FIELD:
-      return "GPBFieldFlags";
-    default:
-      GOOGLE_LOG(FATAL) << "Can't get here.";
-      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 \?
-std::string EscapeTrigraphs(const std::string& to_escape) {
-  return StringReplace(to_escape, "?", "\\?", true);
-}
-
-void TrimWhitespace(StringPiece* input) {
-  while (!input->empty() && ascii_isspace(*input->data())) {
-    input->remove_prefix(1);
-  }
-  while (!input->empty() && ascii_isspace((*input)[input->length() - 1])) {
-    input->remove_suffix(1);
-  }
-}
-
-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 std::string retained_names[] = {"new", "alloc", "copy",
-                                               "mutableCopy"};
-  return IsSpecialName(name, retained_names,
-                       sizeof(retained_names) / sizeof(retained_names[0]));
-}
-
-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]));
-}
-
-std::string BaseFileName(const FileDescriptor* file) {
-  std::string basename;
-  PathSplit(file->name(), NULL, &basename);
-  return basename;
-}
-
-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 is specified in an prefix to proto mappings file then use that.
-  std::string objc_class_prefix = g_prefix_mode.prefix_from_proto_package_mappings(file);
-  if (!objc_class_prefix.empty()) {
-    return objc_class_prefix;
-  }
-
-  // If package prefix isn't enabled, done.
-  if (!g_prefix_mode.use_package_name()) {
-    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 g_prefix_mode.forced_package_prefix() + result;
-}
-
-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 + "/";
-  }
-  basename = StripProto(basename);
-
-  // CamelCase to be more ObjC friendly.
-  basename = UnderscoresToCamelCase(basename, true);
-
-  output += basename;
-  return output;
-}
-
-std::string FilePathBasename(const FileDescriptor* file) {
-  std::string output;
-  std::string basename;
-  std::string directory;
-  PathSplit(file->name(), &directory, &basename);
-  basename = StripProto(basename);
-
-  // CamelCase to be more ObjC friendly.
-  output = UnderscoresToCamelCase(basename, true);
-
-  return output;
-}
-
-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);
-}
-
-std::string ClassNameWorker(const Descriptor* descriptor) {
-  std::string name;
-  if (descriptor->containing_type() != NULL) {
-    name = ClassNameWorker(descriptor->containing_type());
-    name += "_";
-  }
-  return name + descriptor->name();
-}
-
-std::string ClassNameWorker(const EnumDescriptor* descriptor) {
-  std::string name;
-  if (descriptor->containing_type() != NULL) {
-    name = ClassNameWorker(descriptor->containing_type());
-    name += "_";
-  }
-  return name + descriptor->name();
-}
-
-std::string ClassName(const Descriptor* descriptor) {
-  return ClassName(descriptor, NULL);
-}
-
-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 std::string prefix = FileClassPrefix(descriptor->file());
-  const std::string name = ClassNameWorker(descriptor);
-  return SanitizeNameForObjC(prefix, name, "_Class", out_suffix_added);
-}
-
-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 {
-  //        message Size {...}
-  //        enum Mumble {...}
-  //      ...
-  //      }
-  //    yields Fixed_Class, Fixed_Size.
-  const std::string prefix = FileClassPrefix(descriptor->file());
-  const std::string name = ClassNameWorker(descriptor);
-  return SanitizeNameForObjC(prefix, name, "_Enum", NULL);
-}
-
-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 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);
-}
-
-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.
-  // The "short name" is intended to be the final leaf, the value name; but
-  // you can't simply send that off to sanitize as that could result in it
-  // getting modified when the full name didn't.  For example enum
-  // "StorageModes" has a value "retain".  So the full name is
-  // "StorageModes_Retain", but if we sanitize "retain" it would become
-  // "RetainValue".
-  // 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 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);
-}
-
-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)) {
-      result += '_';
-    }
-    result += ascii_toupper(c);
-  }
-  return result;
-}
-
-std::string ExtensionMethodName(const FieldDescriptor* descriptor) {
-  const std::string name = NameFromFieldDescriptor(descriptor);
-  const std::string result = UnderscoresToCamelCase(name, false);
-  return SanitizeNameForObjC("", result, "_Extension", NULL);
-}
-
-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";
-  } else {
-    // If it wasn't repeated, but ends in "Array", force on the _p suffix.
-    if (HasSuffixString(result, "Array")) {
-      result += "_p";
-    }
-  }
-  return SanitizeNameForObjC("", result, "_p", NULL);
-}
-
-std::string FieldNameCapitalized(const FieldDescriptor* field) {
-  // Want the same suffix handling, so upcase the first letter of the other
-  // name.
-  std::string result = FieldName(field);
-  if (result.length() > 0) {
-    result[0] = ascii_toupper(result[0]);
-  }
-  return result;
-}
-
-std::string OneofEnumName(const OneofDescriptor* descriptor) {
-  const Descriptor* fieldDescriptor = descriptor->containing_type();
-  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;
-}
-
-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;
-}
-
-std::string OneofNameCapitalized(const OneofDescriptor* descriptor) {
-  // Use the common handling and then up-case the first letter.
-  std::string result = OneofName(descriptor);
-  if (result.length() > 0) {
-    result[0] = ascii_toupper(result[0]);
-  }
-  return result;
-}
-
-std::string ObjCClass(const std::string& class_name) {
-  return std::string("GPBObjCClass(") + class_name + ")";
-}
-
-std::string ObjCClassDeclaration(const std::string& class_name) {
-  return std::string("GPBObjCClassDeclaration(") + class_name + ");";
-}
-
-std::string UnCamelCaseFieldName(const std::string& name, const FieldDescriptor* field) {
-  std::string worker(name);
-  if (HasSuffixString(worker, "_p")) {
-    worker = StripSuffixString(worker, "_p");
-  }
-  if (field->is_repeated() && HasSuffixString(worker, "Array")) {
-    worker = StripSuffixString(worker, "Array");
-  }
-  if (field->type() == FieldDescriptor::TYPE_GROUP) {
-    if (worker.length() > 0) {
-      if (ascii_islower(worker[0])) {
-        worker[0] = ascii_toupper(worker[0]);
-      }
-    }
-    return worker;
-  } else {
-    std::string result;
-    for (int i = 0; i < worker.size(); i++) {
-      char c = worker[i];
-      if (ascii_isupper(c)) {
-        if (i > 0) {
-          result += '_';
-        }
-        result += ascii_tolower(c);
-      } else {
-        result += c;
-      }
-    }
-    return result;
-  }
-}
-
-std::string GetCapitalizedType(const FieldDescriptor* field) {
-  switch (field->type()) {
-    case FieldDescriptor::TYPE_INT32:
-      return "Int32";
-    case FieldDescriptor::TYPE_UINT32:
-      return "UInt32";
-    case FieldDescriptor::TYPE_SINT32:
-      return "SInt32";
-    case FieldDescriptor::TYPE_FIXED32:
-      return "Fixed32";
-    case FieldDescriptor::TYPE_SFIXED32:
-      return "SFixed32";
-    case FieldDescriptor::TYPE_INT64:
-      return "Int64";
-    case FieldDescriptor::TYPE_UINT64:
-      return "UInt64";
-    case FieldDescriptor::TYPE_SINT64:
-      return "SInt64";
-    case FieldDescriptor::TYPE_FIXED64:
-      return "Fixed64";
-    case FieldDescriptor::TYPE_SFIXED64:
-      return "SFixed64";
-    case FieldDescriptor::TYPE_FLOAT:
-      return "Float";
-    case FieldDescriptor::TYPE_DOUBLE:
-      return "Double";
-    case FieldDescriptor::TYPE_BOOL:
-      return "Bool";
-    case FieldDescriptor::TYPE_STRING:
-      return "String";
-    case FieldDescriptor::TYPE_BYTES:
-      return "Bytes";
-    case FieldDescriptor::TYPE_ENUM:
-      return "Enum";
-    case FieldDescriptor::TYPE_GROUP:
-      return "Group";
-    case FieldDescriptor::TYPE_MESSAGE:
-      return "Message";
-  }
-
-  // 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 std::string();
-}
-
-ObjectiveCType GetObjectiveCType(FieldDescriptor::Type field_type) {
-  switch (field_type) {
-    case FieldDescriptor::TYPE_INT32:
-    case FieldDescriptor::TYPE_SINT32:
-    case FieldDescriptor::TYPE_SFIXED32:
-      return OBJECTIVECTYPE_INT32;
-
-    case FieldDescriptor::TYPE_UINT32:
-    case FieldDescriptor::TYPE_FIXED32:
-      return OBJECTIVECTYPE_UINT32;
-
-    case FieldDescriptor::TYPE_INT64:
-    case FieldDescriptor::TYPE_SINT64:
-    case FieldDescriptor::TYPE_SFIXED64:
-      return OBJECTIVECTYPE_INT64;
-
-    case FieldDescriptor::TYPE_UINT64:
-    case FieldDescriptor::TYPE_FIXED64:
-      return OBJECTIVECTYPE_UINT64;
-
-    case FieldDescriptor::TYPE_FLOAT:
-      return OBJECTIVECTYPE_FLOAT;
-
-    case FieldDescriptor::TYPE_DOUBLE:
-      return OBJECTIVECTYPE_DOUBLE;
-
-    case FieldDescriptor::TYPE_BOOL:
-      return OBJECTIVECTYPE_BOOLEAN;
-
-    case FieldDescriptor::TYPE_STRING:
-      return OBJECTIVECTYPE_STRING;
-
-    case FieldDescriptor::TYPE_BYTES:
-      return OBJECTIVECTYPE_DATA;
-
-    case FieldDescriptor::TYPE_ENUM:
-      return OBJECTIVECTYPE_ENUM;
-
-    case FieldDescriptor::TYPE_GROUP:
-    case FieldDescriptor::TYPE_MESSAGE:
-      return OBJECTIVECTYPE_MESSAGE;
-  }
-
-  // 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 OBJECTIVECTYPE_INT32;
-}
-
-bool IsPrimitiveType(const FieldDescriptor* field) {
-  ObjectiveCType type = GetObjectiveCType(field);
-  switch (type) {
-    case OBJECTIVECTYPE_INT32:
-    case OBJECTIVECTYPE_UINT32:
-    case OBJECTIVECTYPE_INT64:
-    case OBJECTIVECTYPE_UINT64:
-    case OBJECTIVECTYPE_FLOAT:
-    case OBJECTIVECTYPE_DOUBLE:
-    case OBJECTIVECTYPE_BOOLEAN:
-    case OBJECTIVECTYPE_ENUM:
-      return true;
-      break;
-    default:
-      return false;
-  }
-}
-
-bool IsReferenceType(const FieldDescriptor* field) {
-  return !IsPrimitiveType(field);
-}
-
-static std::string HandleExtremeFloatingPoint(std::string val,
-                                              bool add_float_suffix) {
-  if (val == "nan") {
-    return "NAN";
-  } else if (val == "inf") {
-    return "INFINITY";
-  } else if (val == "-inf") {
-    return "-INFINITY";
-  } else {
-    // float strings with ., e or E need to have f appended
-    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;
-  }
-}
-
-std::string GPBGenericValueFieldName(const FieldDescriptor* field) {
-  // Returns the field within the GPBGenericValue union to use for the given
-  // field.
-  if (field->is_repeated()) {
-      return "valueMessage";
-  }
-  switch (field->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_INT32:
-      return "valueInt32";
-    case FieldDescriptor::CPPTYPE_UINT32:
-      return "valueUInt32";
-    case FieldDescriptor::CPPTYPE_INT64:
-      return "valueInt64";
-    case FieldDescriptor::CPPTYPE_UINT64:
-      return "valueUInt64";
-    case FieldDescriptor::CPPTYPE_FLOAT:
-      return "valueFloat";
-    case FieldDescriptor::CPPTYPE_DOUBLE:
-      return "valueDouble";
-    case FieldDescriptor::CPPTYPE_BOOL:
-      return "valueBool";
-    case FieldDescriptor::CPPTYPE_STRING:
-      if (field->type() == FieldDescriptor::TYPE_BYTES) {
-        return "valueData";
-      } else {
-        return "valueString";
-      }
-    case FieldDescriptor::CPPTYPE_ENUM:
-      return "valueEnum";
-    case FieldDescriptor::CPPTYPE_MESSAGE:
-      return "valueMessage";
-  }
-
-  // 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 std::string();
-}
-
-
-std::string DefaultValue(const FieldDescriptor* field) {
-  // Repeated fields don't have defaults.
-  if (field->is_repeated()) {
-    return "nil";
-  }
-
-  // Switch on cpp_type since we need to know which default_value_* method
-  // of FieldDescriptor to call.
-  switch (field->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_INT32:
-      // gcc and llvm reject the decimal form of kint32min and kint64min.
-      if (field->default_value_int32() == INT_MIN) {
-        return "-0x80000000";
-      }
-      return StrCat(field->default_value_int32());
-    case FieldDescriptor::CPPTYPE_UINT32:
-      return StrCat(field->default_value_uint32()) + "U";
-    case FieldDescriptor::CPPTYPE_INT64:
-      // gcc and llvm reject the decimal form of kint32min and kint64min.
-      if (field->default_value_int64() == LLONG_MIN) {
-        return "-0x8000000000000000LL";
-      }
-      return StrCat(field->default_value_int64()) + "LL";
-    case FieldDescriptor::CPPTYPE_UINT64:
-      return StrCat(field->default_value_uint64()) + "ULL";
-    case FieldDescriptor::CPPTYPE_DOUBLE:
-      return HandleExtremeFloatingPoint(
-          SimpleDtoa(field->default_value_double()), false);
-    case FieldDescriptor::CPPTYPE_FLOAT:
-      return HandleExtremeFloatingPoint(
-          SimpleFtoa(field->default_value_float()), true);
-    case FieldDescriptor::CPPTYPE_BOOL:
-      return field->default_value_bool() ? "YES" : "NO";
-    case FieldDescriptor::CPPTYPE_STRING: {
-      const bool has_default_value = field->has_default_value();
-      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
-        // default for both strings and data.
-        return "nil";
-      }
-      if (field->type() == FieldDescriptor::TYPE_BYTES) {
-        // We want constant fields in our data structures so we can
-        // declare them as static. To achieve this we cheat and stuff
-        // a escaped c string (prefixed with a length) into the data
-        // field, and cast it to an (NSData*) so it will compile.
-        // The runtime library knows how to handle it.
-
-        // Must convert to a standard byte order for packing length into
-        // a cstring.
-        uint32_t length = ghtonl(default_string.length());
-        std::string bytes((const char*)&length, sizeof(length));
-        bytes.append(default_string);
-        return "(NSData*)\"" + EscapeTrigraphs(CEscape(bytes)) + "\"";
-      } else {
-        return "@\"" + EscapeTrigraphs(CEscape(default_string)) + "\"";
-      }
-    }
-    case FieldDescriptor::CPPTYPE_ENUM:
-      return EnumValueName(field->default_value_enum());
-    case FieldDescriptor::CPPTYPE_MESSAGE:
-      return "nil";
-  }
-
-  // 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 std::string();
-}
-
-bool HasNonZeroDefaultValue(const FieldDescriptor* field) {
-  // Repeated fields don't have defaults.
-  if (field->is_repeated()) {
-    return false;
-  }
-
-  // As much as checking field->has_default_value() seems useful, it isn't
-  // because of enums. proto2 syntax allows the first item in an enum (the
-  // default) to be non zero. So checking field->has_default_value() would
-  // result in missing this non zero default.  See MessageWithOneBasedEnum in
-  // objectivec/Tests/unittest_objc.proto for a test Message to confirm this.
-
-  // Some proto file set the default to the zero value, so make sure the value
-  // isn't the zero case.
-  switch (field->cpp_type()) {
-    case FieldDescriptor::CPPTYPE_INT32:
-      return field->default_value_int32() != 0;
-    case FieldDescriptor::CPPTYPE_UINT32:
-      return field->default_value_uint32() != 0U;
-    case FieldDescriptor::CPPTYPE_INT64:
-      return field->default_value_int64() != 0LL;
-    case FieldDescriptor::CPPTYPE_UINT64:
-      return field->default_value_uint64() != 0ULL;
-    case FieldDescriptor::CPPTYPE_DOUBLE:
-      return field->default_value_double() != 0.0;
-    case FieldDescriptor::CPPTYPE_FLOAT:
-      return field->default_value_float() != 0.0f;
-    case FieldDescriptor::CPPTYPE_BOOL:
-      return field->default_value_bool();
-    case FieldDescriptor::CPPTYPE_STRING: {
-      const std::string& default_string = field->default_value_string();
-      return default_string.length() != 0;
-    }
-    case FieldDescriptor::CPPTYPE_ENUM:
-      return field->default_value_enum()->number() != 0;
-    case FieldDescriptor::CPPTYPE_MESSAGE:
-      return false;
-  }
-
-  // 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 false;
-}
-
-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];
-  }
-  std::string string("(" + GetEnumNameForFlagType(flag_type) + ")(");
-  for (size_t i = 0; i != strings.size(); ++i) {
-    if (i > 0) {
-      string.append(" | ");
-    }
-    string.append(strings[i]);
-  }
-  string.append(")");
-  return string;
-}
-
-std::string BuildCommentsString(const SourceLocation& location,
-                           bool prefer_single_line) {
-  const std::string& comments = location.leading_comments.empty()
-                               ? location.trailing_comments
-                               : location.leading_comments;
-  std::vector<std::string> lines;
-  lines = Split(comments, "\n", false);
-  while (!lines.empty() && lines.back().empty()) {
-    lines.pop_back();
-  }
-  // If there are no comments, just return an empty string.
-  if (lines.empty()) {
-    return "";
-  }
-
-  std::string prefix;
-  std::string suffix;
-  std::string final_comments;
-  std::string epilogue;
-
-  bool add_leading_space = false;
-
-  if (prefer_single_line && lines.size() == 1) {
-    prefix = "/** ";
-    suffix = " */\n";
-  } else {
-    prefix = "* ";
-    suffix = "\n";
-    final_comments += "/**\n";
-    epilogue = " **/\n";
-    add_leading_space = true;
-  }
-
-  for (int i = 0; i < lines.size(); i++) {
-    std::string line = StripPrefixString(lines[i], " ");
-    // HeaderDoc and appledoc use '\' and '@' for markers; escape them.
-    line = StringReplace(line, "\\", "\\\\", true);
-    line = StringReplace(line, "@", "\\@", true);
-    // Decouple / from * to not have inline comments inside comments.
-    line = StringReplace(line, "/*", "/\\*", true);
-    line = StringReplace(line, "*/", "*\\/", true);
-    line = prefix + line;
-    StripWhitespace(&line);
-    // If not a one line, need to add the first space before *, as
-    // StripWhitespace would have removed it.
-    line = (add_leading_space ? " " : "") + line;
-    final_comments += line + suffix;
-  }
-  final_comments += epilogue;
-  return final_comments;
-}
-
-// Making these a generator option for folks that don't use CocoaPods, but do
-// want to put the library in a framework is an interesting question. The
-// problem is it means changing sources shipped with the library to actually
-// use a different value; so it isn't as simple as a option.
-const char* const ProtobufLibraryFrameworkName = "Protobuf";
-
-std::string ProtobufFrameworkImportSymbol(const std::string& framework_name) {
-  // GPB_USE_[framework_name]_FRAMEWORK_IMPORTS
-  std::string result = std::string("GPB_USE_");
-  result += ToUpper(framework_name);
-  result += "_FRAMEWORK_IMPORTS";
-  return result;
-}
-
-bool IsProtobufLibraryBundledProtoFile(const FileDescriptor* file) {
-  // 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 std::string name = file->name();
-  if (name == "google/protobuf/any.proto" ||
-      name == "google/protobuf/api.proto" ||
-      name == "google/protobuf/duration.proto" ||
-      name == "google/protobuf/empty.proto" ||
-      name == "google/protobuf/field_mask.proto" ||
-      name == "google/protobuf/source_context.proto" ||
-      name == "google/protobuf/struct.proto" ||
-      name == "google/protobuf/timestamp.proto" ||
-      name == "google/protobuf/type.proto" ||
-      name == "google/protobuf/wrappers.proto") {
-    return true;
-  }
-  return false;
-}
-
-bool ReadLine(StringPiece* input, StringPiece* line) {
-  for (int len = 0; len < input->size(); ++len) {
-    if (ascii_isnewline((*input)[len])) {
-      *line = StringPiece(input->data(), len);
-      ++len;  // advance over the newline
-      *input = StringPiece(input->data() + len, input->size() - len);
-      return true;
-    }
-  }
-  return false;  // Ran out of input with no newline.
-}
-
-void RemoveComment(StringPiece* input) {
-  int offset = input->find('#');
-  if (offset != StringPiece::npos) {
-    input->remove_suffix(input->length() - offset);
-  }
-}
-
-namespace {
-
-bool PackageToPrefixesCollector::ConsumeLine(
-    const StringPiece& line, std::string* out_error) {
-  int offset = line.find('=');
-  if (offset == StringPiece::npos) {
-    *out_error = usage_ + " file line without equal sign: '" + StrCat(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_)[std::string(package)] = std::string(prefix);
-  return true;
-}
-
-bool LoadExpectedPackagePrefixes(const std::string& expected_prefixes_path,
-                                 std::map<std::string, std::string>* prefix_map,
-                                 std::string* out_error) {
-  if (expected_prefixes_path.empty()) {
-    return true;
-  }
-
-  PackageToPrefixesCollector collector("Expected prefixes", prefix_map);
-  return ParseSimpleFile(
-      expected_prefixes_path, &collector, out_error);
-}
-
-bool ValidateObjCClassPrefix(
-    const FileDescriptor* file, const std::string& expected_prefixes_path,
-    const std::map<std::string, std::string>& expected_package_prefixes,
-    bool prefixes_must_be_registered, bool require_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();
-  // For files without packages, the can be registered as "no_package:PATH",
-  // allowing the expected prefixes file.
-  static const std::string no_package_prefix("no_package:");
-  const std::string lookup_key =
-      package.empty() ? no_package_prefix + file->name() : 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<std::string, std::string>::const_iterator package_match =
-      expected_package_prefixes.find(lookup_key);
-  if (package_match != expected_package_prefixes.end()) {
-    // There was an entry, and...
-    if (has_prefix && package_match->second == prefix) {
-      // ...it matches.  All good, out of here!
-      return true;
-    } else {
-      // ...it didn't match!
-      *out_error = "error: Expected 'option objc_class_prefix = \"" +
-                   package_match->second + "\";'";
-      if (!package.empty()) {
-        *out_error += " for package '" + package + "'";
-      }
-      *out_error += " in '" + file->name() + "'";
-      if (has_prefix) {
-        *out_error += "; but found '" + prefix + "' instead";
-      }
-      *out_error += ".";
-      return false;
-    }
-  }
-
-  // If there was no prefix option, we're done at this point.
-  if (!has_prefix) {
-    if (require_prefixes) {
-      *out_error =
-        "error: '" + file->name() + "' does not have a required 'option" +
-        " objc_class_prefix'.";
-      return false;
-    }
-    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;
-        // Stop on the first real package listing, if it was a no_package file
-        // specific entry, keep looking to try and find a package one.
-        if (!HasPrefixString(other_package_for_prefix, no_package_prefix)) {
-          break;
-        }
-      }
-    }
-
-    // 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 ";
-      if (HasPrefixString(other_package_for_prefix, no_package_prefix)) {
-        *out_error += "file '" +
-          StripPrefixString(other_package_for_prefix, no_package_prefix) +
-          "'.";
-      } else {
-        *out_error += "'package " + other_package_for_prefix + ";'.";
-      }
-      *out_error +=
-        " It can only be reused by adding '" + lookup_key + " = " + prefix +
-        "' to the expected prefixes file (" + expected_prefixes_path + ").";
-      return false;  // Only report first usage of the prefix.
-    }
-  } // !prefix.empty() && have_expected_prefix_file
-
-  // 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 (!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.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
-         << "protoc:0: warning: Invalid 'option objc_class_prefix = \""
-         << prefix << "\";' in '" << file->name() << "';"
-         << " Apple recommends they should be at least 3 characters long."
-         << std::endl;
-    std::cerr.flush();
-  }
-
-  // Check: Error/Warning - If the given package/prefix pair wasn't expected,
-  // issue a error/warning to added to the file.
-  if (have_expected_prefix_file) {
-    if (prefixes_must_be_registered) {
-      *out_error =
-        "error: '" + file->name() + "' has 'option objc_class_prefix = \"" +
-        prefix + "\";', but it is not registered. Add '" + lookup_key + " = " +
-        (prefix.empty() ? "\"\"" : prefix) +
-        "' to the expected prefixes file (" + expected_prefixes_path + ").";
-      return false;
-    }
-
-    std::cerr
-         << "protoc:0: warning: Found unexpected 'option objc_class_prefix = \""
-         << prefix << "\";' in '" << file->name() << "'; consider adding '"
-         << lookup_key << " = " << (prefix.empty() ? "\"\"" : prefix)
-         << "' to the expected prefixes file (" << expected_prefixes_path
-         << ")." << std::endl;
-    std::cerr.flush();
-  }
-
-  return true;
-}
-
-}  // namespace
-
-bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
-                               std::string* out_error) {
-    // Options's ctor load from the environment.
-    Options options;
-    return ValidateObjCClassPrefixes(files, options, out_error);
-}
-
-bool ValidateObjCClassPrefixes(const std::vector<const FileDescriptor*>& files,
-                               const Options& generation_options,
-                               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<std::string, std::string> expected_package_prefixes;
-  if (!LoadExpectedPackagePrefixes(generation_options.expected_prefixes_path,
-                                   &expected_package_prefixes,
-                                   out_error)) {
-    return false;
-  }
-
-  for (int i = 0; i < files.size(); i++) {
-    bool should_skip =
-      (std::find(generation_options.expected_prefixes_suppressions.begin(),
-                 generation_options.expected_prefixes_suppressions.end(),
-                 files[i]->name())
-          != generation_options.expected_prefixes_suppressions.end());
-    if (should_skip) {
-      continue;
-    }
-
-    bool is_valid =
-        ValidateObjCClassPrefix(files[i],
-                                generation_options.expected_prefixes_path,
-                                expected_package_prefixes,
-                                generation_options.prefixes_must_be_registered,
-                                generation_options.require_prefixes,
-                                out_error);
-    if (!is_valid) {
-      return false;
-    }
-  }
-  return true;
-}
-
-TextFormatDecodeData::TextFormatDecodeData() { }
-
-TextFormatDecodeData::~TextFormatDecodeData() { }
-
-void TextFormatDecodeData::AddString(int32_t key,
-                                     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) {
-      std::cerr << "error: duplicate key (" << key
-           << ") making TextFormat data, input: \"" << input_for_decode
-           << "\", desired: \"" << desired_output << "\"." << std::endl;
-      std::cerr.flush();
-      abort();
-    }
-  }
-
-  const std::string& data = TextFormatDecodeData::DecodeDataForString(
-      input_for_decode, desired_output);
-  entries_.push_back(DataEntry(key, data));
-}
-
-std::string TextFormatDecodeData::Data() const {
-  std::ostringstream data_stringstream;
-
-  if (num_entries() > 0) {
-    io::OstreamOutputStream data_outputstream(&data_stringstream);
-    io::CodedOutputStream output_stream(&data_outputstream);
-
-    output_stream.WriteVarint32(num_entries());
-    for (std::vector<DataEntry>::const_iterator i = entries_.begin();
-         i != entries_.end(); ++i) {
-      output_stream.WriteVarint32(i->first);
-      output_stream.WriteString(i->second);
-    }
-  }
-
-  data_stringstream.flush();
-  return data_stringstream.str();
-}
-
-namespace {
-
-// Helper to build up the decode data for a string.
-class DecodeDataBuilder {
- public:
-  DecodeDataBuilder() { Reset(); }
-
-  bool AddCharacter(const char desired, const char input);
-  void AddUnderscore() {
-    Push();
-    need_underscore_ = true;
-  }
-  std::string Finish() {
-    Push();
-    return decode_data_;
-  }
-
- private:
-  static constexpr uint8_t kAddUnderscore = 0x80;
-
-  static constexpr uint8_t kOpAsIs = 0x00;
-  static constexpr uint8_t kOpFirstUpper = 0x40;
-  static constexpr uint8_t kOpFirstLower = 0x20;
-  static constexpr uint8_t kOpAllUpper = 0x60;
-
-  static constexpr int kMaxSegmentLen = 0x1f;
-
-  void AddChar(const char desired) {
-    ++segment_len_;
-    is_all_upper_ &= ascii_isupper(desired);
-  }
-
-  void Push() {
-    uint8_t op = (op_ | segment_len_);
-    if (need_underscore_) op |= kAddUnderscore;
-    if (op != 0) {
-      decode_data_ += (char)op;
-    }
-    Reset();
-  }
-
-  bool AddFirst(const char desired, const char input) {
-    if (desired == input) {
-      op_ = kOpAsIs;
-    } else if (desired == ascii_toupper(input)) {
-      op_ = kOpFirstUpper;
-    } else if (desired == ascii_tolower(input)) {
-      op_ = kOpFirstLower;
-    } else {
-      // Can't be transformed to match.
-      return false;
-    }
-    AddChar(desired);
-    return true;
-  }
-
-  void Reset() {
-    need_underscore_ = false;
-    op_ = 0;
-    segment_len_ = 0;
-    is_all_upper_ = true;
-  }
-
-  bool need_underscore_;
-  bool is_all_upper_;
-  uint8_t op_;
-  int segment_len_;
-
-  std::string decode_data_;
-};
-
-bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
-  // If we've hit the max size, push to start a new segment.
-  if (segment_len_ == kMaxSegmentLen) {
-    Push();
-  }
-  if (segment_len_ == 0) {
-    return AddFirst(desired, input);
-  }
-
-  // Desired and input match...
-  if (desired == input) {
-    // If we aren't transforming it, or we're upper casing it and it is
-    // supposed to be uppercase; just add it to the segment.
-    if ((op_ != kOpAllUpper) || ascii_isupper(desired)) {
-      AddChar(desired);
-      return true;
-    }
-
-    // Add the current segment, and start the next one.
-    Push();
-    return AddFirst(desired, input);
-  }
-
-  // If we need to uppercase, and everything so far has been uppercase,
-  // promote op to AllUpper.
-  if ((desired == ascii_toupper(input)) && is_all_upper_) {
-    op_ = kOpAllUpper;
-    AddChar(desired);
-    return true;
-  }
-
-  // Give up, push and start a new segment.
-  Push();
-  return AddFirst(desired, input);
-}
-
-// If decode data can't be generated, a directive for the raw string
-// is used instead.
-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.
-  return result;
-}
-
-}  // namespace
-
-// static
-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 << "\"."
-         << std::endl;
-    std::cerr.flush();
-    abort();
-  }
-  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;
-    std::cerr.flush();
-    abort();
-  }
-
-  DecodeDataBuilder builder;
-
-  // Walk the output building it from the input.
-  int x = 0;
-  for (int y = 0; y < desired_output.size(); y++) {
-    const char d = desired_output[y];
-    if (d == '_') {
-      builder.AddUnderscore();
-      continue;
-    }
-
-    if (x >= input_for_decode.size()) {
-      // Out of input, no way to encode it, just return a full decode.
-      return DirectDecodeString(desired_output);
-    }
-    if (builder.AddCharacter(d, input_for_decode[x])) {
-      ++x;  // Consumed one input
-    } else {
-      // Couldn't transform for the next character, just return a full decode.
-      return DirectDecodeString(desired_output);
-    }
-  }
-
-  if (x != input_for_decode.size()) {
-    // Extra input (suffix from name sanitizing?), just return a full decode.
-    return DirectDecodeString(desired_output);
-  }
-
-  // Add the end marker.
-  return builder.Finish() + (char)'\0';
-}
-
-namespace {
-
-class Parser {
- public:
-  Parser(LineConsumer* line_consumer)
-      : line_consumer_(line_consumer), line_(0) {}
-
-  // Feeds in some input, parse what it can, returning success/failure. Calling
-  // again after an error is undefined.
-  bool ParseChunk(StringPiece chunk, std::string* out_error);
-
-  // Should be called to finish parsing (after all input has been provided via
-  // successful calls to ParseChunk(), calling after a ParseChunk() failure is
-  // undefined). Returns success/failure.
-  bool Finish(std::string* out_error);
-
-  int last_line() const { return line_; }
-
- private:
-  LineConsumer* line_consumer_;
-  int line_;
-  std::string leftover_;
-};
-
-bool Parser::ParseChunk(StringPiece chunk, std::string* out_error) {
-  StringPiece full_chunk;
-  if (!leftover_.empty()) {
-    leftover_ += std::string(chunk);
-    full_chunk = StringPiece(leftover_);
-  } else {
-    full_chunk = chunk;
-  }
-
-  StringPiece line;
-  while (ReadLine(&full_chunk, &line)) {
-    ++line_;
-    RemoveComment(&line);
-    TrimWhitespace(&line);
-    if (!line.empty() && !line_consumer_->ConsumeLine(line, out_error)) {
-      if (out_error->empty()) {
-        *out_error = "ConsumeLine failed without setting an error.";
-      }
-      leftover_.clear();
-      return false;
-    }
-  }
-
-  if (full_chunk.empty()) {
-    leftover_.clear();
-  } else {
-    leftover_ = std::string(full_chunk);
-  }
-  return true;
-}
-
-bool Parser::Finish(std::string* out_error) {
-  // If there is still something to go, flush it with a newline.
-  if (!leftover_.empty() && !ParseChunk("\n", out_error)) {
-    return false;
-  }
-  // This really should never fail if ParseChunk succeeded, but check to be sure.
-  if (!leftover_.empty()) {
-    *out_error = "ParseSimple Internal error: finished with pending data.";
-    return false;
-  }
-  return true;
-}
-
-std::string FullErrorString(const std::string& name, int line_num, const std::string& msg) {
-  return std::string("error: ") + name + " Line " + StrCat(line_num) + ", " + msg;
-}
-
-}  // namespace
-
-LineConsumer::LineConsumer() {}
-
-LineConsumer::~LineConsumer() {}
-
-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 = std::string("error: Unable to open \"") + path + "\", " +
-                 strerror(errno);
-    return false;
-  }
-  io::FileInputStream file_stream(fd);
-  file_stream.SetCloseOnDelete(true);
-
-  return ParseSimpleStream(file_stream, path, line_consumer, out_error);
-}
-
-bool ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
-                       const std::string& stream_name,
-                       LineConsumer* line_consumer,
-                       std::string* out_error) {
-  std::string local_error;
-  Parser parser(line_consumer);
-  const void* buf;
-  int buf_len;
-  while (input_stream.Next(&buf, &buf_len)) {
-    if (buf_len == 0) {
-      continue;
-    }
-
-    if (!parser.ParseChunk(StringPiece(static_cast<const char*>(buf), buf_len),
-                           &local_error)) {
-      *out_error = FullErrorString(stream_name, parser.last_line(), local_error);
-      return false;
-    }
-  }
-  if (!parser.Finish(&local_error)) {
-    *out_error = FullErrorString(stream_name, parser.last_line(), local_error);
-    return false;
-  }
-  return true;
-}
-
-ImportWriter::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)
-    : 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) {}
-
-ImportWriter::~ImportWriter() {}
-
-void ImportWriter::AddFile(const FileDescriptor* file,
-                           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 std::string header_name =
-          "GPB" + FilePathBasename(file) + header_extension;
-      protobuf_imports_.push_back(header_name);
-    }
-    return;
-  }
-
-  // Lazy parse any mappings.
-  if (need_to_parse_mapping_file_) {
-    ParseFrameworkMappings();
-  }
-
-  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(
-        proto_lookup->second + "/" +
-        FilePathBasename(file) + header_extension);
-    return;
-  }
-
-  if (!generate_for_named_framework_.empty()) {
-    other_framework_imports_.push_back(
-        generate_for_named_framework_ + "/" +
-        FilePathBasename(file) + header_extension);
-    return;
-  }
-
-  other_imports_.push_back(FilePath(file) + header_extension);
-}
-
-void ImportWriter::Print(io::Printer* printer) const {
-  bool add_blank_line = false;
-
-  if (!protobuf_imports_.empty()) {
-    PrintRuntimeImports(printer, protobuf_imports_, runtime_import_prefix_);
-    add_blank_line = true;
-  }
-
-  if (!other_framework_imports_.empty()) {
-    if (add_blank_line) {
-      printer->Print("\n");
-    }
-
-    for (std::vector<std::string>::const_iterator iter =
-             other_framework_imports_.begin();
-         iter != other_framework_imports_.end(); ++iter) {
-      printer->Print(
-          "#import <$header$>\n",
-          "header", *iter);
-    }
-
-    add_blank_line = true;
-  }
-
-  if (!other_imports_.empty()) {
-    if (add_blank_line) {
-      printer->Print("\n");
-    }
-
-    for (std::vector<std::string>::const_iterator iter = other_imports_.begin();
-         iter != other_imports_.end(); ++iter) {
-      printer->Print(
-          "#import \"$header$\"\n",
-          "header", *iter);
-    }
-  }
-}
-
-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()) {
-    return;  // Nothing to do.
-  }
-
-  ProtoFrameworkCollector collector(&proto_file_to_framework_name_);
-  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_
-         << " : " << parse_error << std::endl;
-    std::cerr.flush();
-  }
-}
-
-bool ImportWriter::ProtoFrameworkCollector::ConsumeLine(
-    const StringPiece& line, std::string* out_error) {
-  int offset = line.find(':');
-  if (offset == StringPiece::npos) {
-    *out_error =
-        std::string("Framework/proto file mapping line without colon sign: '") +
-        std::string(line) + "'.";
-    return false;
-  }
-  StringPiece framework_name = line.substr(0, offset);
-  StringPiece proto_file_list = line.substr(offset + 1);
-  TrimWhitespace(&framework_name);
-
-  int start = 0;
-  while (start < proto_file_list.length()) {
-    offset = proto_file_list.find(',', start);
-    if (offset == StringPiece::npos) {
-      offset = proto_file_list.length();
-    }
-
-    StringPiece proto_file = proto_file_list.substr(start, offset - start);
-    TrimWhitespace(&proto_file);
-    if (!proto_file.empty()) {
-      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 '"
-                  << std::string(proto_file) << "' with '" << std::string(framework_name)
-                  << "' (was '" << existing_entry->second << "')." << std::endl;
-        std::cerr.flush();
-      }
-
-      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: '"
-                  << std::string(proto_file) << "'" << std::endl;
-        std::cerr.flush();
-      }
-
-      (*map_)[std::string(proto_file)] = std::string(framework_name);
-    }
-
-    start = offset + 1;
-  }
-
-  return true;
-}
-
-}  // namespace objectivec
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h b/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
deleted file mode 100644
index d21fed2..0000000
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers.h
+++ /dev/null
@@ -1,353 +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.
-
-// Helper functions for generating ObjectiveC code.
-
-#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
-#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
-
-#include <string>
-#include <vector>
-
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace objectivec {
-
-// Get/Set the path to a file to load for objc class prefix lookups.
-std::string PROTOC_EXPORT GetPackageToPrefixMappingsPath();
-void PROTOC_EXPORT SetPackageToPrefixMappingsPath(
-    const std::string& file_path);
-// 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
-// `UseProtoPackageAsDefaultPrefix()` is `true`. An empty string means there
-// should be no exceptions.
-std::string PROTOC_EXPORT GetProtoPackagePrefixExceptionList();
-void PROTOC_EXPORT SetProtoPackagePrefixExceptionList(
-    const std::string& file_path);
-
-// Generator Prefix Validation Options (see objectivec_generator.cc for a
-// description of each):
-struct Options {
-  Options();
-  std::string expected_prefixes_path;
-  std::vector<std::string> expected_prefixes_suppressions;
-  bool prefixes_must_be_registered;
-  bool require_prefixes;
-};
-
-// Escape C++ trigraphs by escaping question marks to "\?".
-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 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 std::string& name);
-
-// 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.
-std::string PROTOC_EXPORT FilePath(const FileDescriptor* file);
-
-// Just like FilePath(), but without the directory part.
-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
-std::string PROTOC_EXPORT FileClassName(const FileDescriptor* file);
-
-// These return the fully-qualified class name corresponding to the given
-// 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.
-std::string PROTOC_EXPORT EnumValueName(const EnumValueDescriptor* descriptor);
-
-// Returns the name of the enum value corresponding to the descriptor.
-std::string PROTOC_EXPORT EnumValueShortName(const EnumValueDescriptor* descriptor);
-
-// Reverse what an enum does.
-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).
-std::string PROTOC_EXPORT ExtensionMethodName(const FieldDescriptor* descriptor);
-
-// Returns the transformed field name.
-std::string PROTOC_EXPORT FieldName(const FieldDescriptor* field);
-std::string PROTOC_EXPORT FieldNameCapitalized(const FieldDescriptor* field);
-
-// Returns the transformed oneof name.
-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.
-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.
-std::string PROTOC_EXPORT ObjCClassDeclaration(const std::string& class_name);
-
-inline bool HasPreservingUnknownEnumSemantics(const FileDescriptor* file) {
-  return file->syntax() == FileDescriptor::SYNTAX_PROTO3;
-}
-
-inline bool IsMapEntryMessage(const Descriptor* descriptor) {
-  return descriptor->options().map_entry();
-}
-
-// Reverse of the above.
-std::string PROTOC_EXPORT UnCamelCaseFieldName(const std::string& name,
-                                               const FieldDescriptor* field);
-
-enum ObjectiveCType {
-  OBJECTIVECTYPE_INT32,
-  OBJECTIVECTYPE_UINT32,
-  OBJECTIVECTYPE_INT64,
-  OBJECTIVECTYPE_UINT64,
-  OBJECTIVECTYPE_FLOAT,
-  OBJECTIVECTYPE_DOUBLE,
-  OBJECTIVECTYPE_BOOLEAN,
-  OBJECTIVECTYPE_STRING,
-  OBJECTIVECTYPE_DATA,
-  OBJECTIVECTYPE_ENUM,
-  OBJECTIVECTYPE_MESSAGE
-};
-
-enum FlagType {
-  FLAGTYPE_DESCRIPTOR_INITIALIZATION,
-  FLAGTYPE_EXTENSION,
-  FLAGTYPE_FIELD
-};
-
-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
-  // field or enum value with when the file is deprecated.
-  bool isFileLevelDeprecation = false;
-  if (!isDeprecated && file) {
-    isFileLevelDeprecation = file->options().deprecated();
-    isDeprecated = isFileLevelDeprecation;
-  }
-  if (isDeprecated) {
-    std::string message;
-    const FileDescriptor* sourceFile = descriptor->file();
-    if (isFileLevelDeprecation) {
-      message = sourceFile->name() + " is deprecated.";
-    } else {
-      message = descriptor->full_name() + " is deprecated (see " +
-                sourceFile->name() + ").";
-    }
-
-    std::string result = std::string("GPB_DEPRECATED_MSG(\"") + message + "\")";
-    if (preSpace) {
-      result.insert(0, " ");
-    }
-    if (postNewline) {
-      result.append("\n");
-    }
-    return result;
-  } else {
-    return "";
-  }
-}
-
-std::string PROTOC_EXPORT GetCapitalizedType(const FieldDescriptor* field);
-
-ObjectiveCType PROTOC_EXPORT
-GetObjectiveCType(FieldDescriptor::Type field_type);
-
-inline ObjectiveCType GetObjectiveCType(const FieldDescriptor* field) {
-  return GetObjectiveCType(field->type());
-}
-
-bool PROTOC_EXPORT IsPrimitiveType(const FieldDescriptor* field);
-bool PROTOC_EXPORT IsReferenceType(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);
-
-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.
-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.
-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
-IsProtobufLibraryBundledProtoFile(const FileDescriptor* file);
-
-// 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& validation_options, std::string* out_error);
-// Same was the other ValidateObjCClassPrefixes() calls, but the options all
-// come from the environment variables.
-bool PROTOC_EXPORT ValidateObjCClassPrefixes(
-    const std::vector<const FileDescriptor*>& files, std::string* out_error);
-
-// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
-// the input into the expected output.
-class PROTOC_EXPORT TextFormatDecodeData {
- public:
-  TextFormatDecodeData();
-  ~TextFormatDecodeData();
-
-  TextFormatDecodeData(const TextFormatDecodeData&) = delete;
-  TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete;
-
-  void AddString(int32_t key, const std::string& input_for_decode,
-                 const std::string& desired_output);
-  size_t num_entries() const { return entries_.size(); }
-  std::string Data() const;
-
-  static std::string DecodeDataForString(const std::string& input_for_decode,
-                                         const std::string& desired_output);
-
- private:
-  typedef std::pair<int32_t, std::string> DataEntry;
-  std::vector<DataEntry> entries_;
-};
-
-// Helper for parsing simple files.
-class PROTOC_EXPORT LineConsumer {
- public:
-  LineConsumer();
-  virtual ~LineConsumer();
-  virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) = 0;
-};
-
-bool PROTOC_EXPORT ParseSimpleFile(const std::string& path,
-                                   LineConsumer* line_consumer,
-                                   std::string* out_error);
-
-bool PROTOC_EXPORT ParseSimpleStream(io::ZeroCopyInputStream& input_stream,
-                                     const std::string& stream_name,
-                                     LineConsumer* line_consumer,
-                                     std::string* out_error);
-
-// Helper class for parsing framework import mappings and generating
-// import statements.
-class PROTOC_EXPORT ImportWriter {
- public:
-  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 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<std::string, std::string>* inout_proto_file_to_framework_name)
-        : map_(inout_proto_file_to_framework_name) {}
-
-    virtual bool ConsumeLine(const StringPiece& line, std::string* out_error) override;
-
-   private:
-    std::map<std::string, std::string>* map_;
-  };
-
-  void ParseFrameworkMappings();
-
-  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<std::string, std::string> proto_file_to_framework_name_;
-  bool need_to_parse_mapping_file_;
-
-  std::vector<std::string> protobuf_imports_;
-  std::vector<std::string> other_framework_imports_;
-  std::vector<std::string> other_imports_;
-};
-
-}  // namespace objectivec
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_HELPERS_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_message.cc b/src/google/protobuf/compiler/objectivec/objectivec_message.cc
deleted file mode 100644
index 4ebb75c..0000000
--- a/src/google/protobuf/compiler/objectivec/objectivec_message.cc
+++ /dev/null
@@ -1,633 +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 <algorithm>
-#include <iostream>
-#include <sstream>
-
-#include <google/protobuf/compiler/objectivec/objectivec_message.h>
-#include <google/protobuf/compiler/objectivec/objectivec_enum.h>
-#include <google/protobuf/compiler/objectivec/objectivec_extension.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.pb.h>
-
-namespace google {
-namespace protobuf {
-namespace compiler {
-namespace objectivec {
-
-namespace {
-struct FieldOrderingByNumber {
-  inline bool operator()(const FieldDescriptor* a,
-                         const FieldDescriptor* b) const {
-    return a->number() < b->number();
-  }
-};
-
-int OrderGroupForFieldDescriptor(const FieldDescriptor* descriptor) {
-  // The first item in the object structure is our uint32[] for has bits.
-  // We then want to order things to make the instances as small as
-  // possible. So we follow the has bits with:
-  //   1. Anything always 4 bytes - float, *32, enums
-  //   2. Anything that is always a pointer (they will be 8 bytes on 64 bit
-  //      builds and 4 bytes on 32bit builds.
-  //   3. Anything always 8 bytes - double, *64
-  //
-  // NOTE: Bools aren't listed, they were stored in the has bits.
-  //
-  // Why? Using 64bit builds as an example, this means worse case, we have
-  // enough bools that we overflow 1 byte from 4 byte alignment, so 3 bytes
-  // are wasted before the 4 byte values. Then if we have an odd number of
-  // those 4 byte values, the 8 byte values will be pushed down by 32bits to
-  // keep them aligned. But the structure will end 8 byte aligned, so no
-  // waste on the end. If you did the reverse order, you could waste 4 bytes
-  // before the first 8 byte value (after the has array), then a single
-  // bool on the end would need 7 bytes of padding to make the overall
-  // structure 8 byte aligned; so 11 bytes, wasted total.
-
-  // Anything repeated is a GPB*Array/NSArray, so pointer.
-  if (descriptor->is_repeated()) {
-    return 3;
-  }
-
-  switch (descriptor->type()) {
-    // All always 8 bytes.
-    case FieldDescriptor::TYPE_DOUBLE:
-    case FieldDescriptor::TYPE_INT64:
-    case FieldDescriptor::TYPE_SINT64:
-    case FieldDescriptor::TYPE_UINT64:
-    case FieldDescriptor::TYPE_SFIXED64:
-    case FieldDescriptor::TYPE_FIXED64:
-      return 4;
-
-    // Pointers (string and bytes are NSString and NSData); 8 or 4 bytes
-    // depending on the build architecture.
-    case FieldDescriptor::TYPE_GROUP:
-    case FieldDescriptor::TYPE_MESSAGE:
-    case FieldDescriptor::TYPE_STRING:
-    case FieldDescriptor::TYPE_BYTES:
-      return 3;
-
-    // All always 4 bytes (enums are int32s).
-    case FieldDescriptor::TYPE_FLOAT:
-    case FieldDescriptor::TYPE_INT32:
-    case FieldDescriptor::TYPE_SINT32:
-    case FieldDescriptor::TYPE_UINT32:
-    case FieldDescriptor::TYPE_SFIXED32:
-    case FieldDescriptor::TYPE_FIXED32:
-    case FieldDescriptor::TYPE_ENUM:
-      return 2;
-
-    // 0 bytes. Stored in the has bits.
-    case FieldDescriptor::TYPE_BOOL:
-      return 99;  // End of the list (doesn't really matter).
-  }
-
-  // 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 0;
-}
-
-struct FieldOrderingByStorageSize {
-  inline bool operator()(const FieldDescriptor* a,
-                         const FieldDescriptor* b) const {
-    // Order by grouping.
-    const int order_group_a = OrderGroupForFieldDescriptor(a);
-    const int order_group_b = OrderGroupForFieldDescriptor(b);
-    if (order_group_a != order_group_b) {
-      return order_group_a < order_group_b;
-    }
-    // Within the group, order by field number (provides stable ordering).
-    return a->number() < b->number();
-  }
-};
-
-struct ExtensionRangeOrdering {
-  bool operator()(const Descriptor::ExtensionRange* a,
-                  const Descriptor::ExtensionRange* b) const {
-    return a->start < b->start;
-  }
-};
-
-// Sort the fields of the given Descriptor by number into a new[]'d array
-// and return it.
-const FieldDescriptor** SortFieldsByNumber(const Descriptor* descriptor) {
-  const FieldDescriptor** fields =
-      new const FieldDescriptor* [descriptor->field_count()];
-  for (int i = 0; i < descriptor->field_count(); i++) {
-    fields[i] = descriptor->field(i);
-  }
-  std::sort(fields, fields + descriptor->field_count(), FieldOrderingByNumber());
-  return fields;
-}
-
-// Sort the fields of the given Descriptor by storage size into a new[]'d
-// array and return it.
-const FieldDescriptor** SortFieldsByStorageSize(const Descriptor* descriptor) {
-  const FieldDescriptor** fields =
-      new const FieldDescriptor* [descriptor->field_count()];
-  for (int i = 0; i < descriptor->field_count(); i++) {
-    fields[i] = descriptor->field(i);
-  }
-  std::sort(fields, fields + descriptor->field_count(),
-       FieldOrderingByStorageSize());
-  return fields;
-}
-}  // namespace
-
-MessageGenerator::MessageGenerator(const std::string& root_classname,
-                                   const Descriptor* descriptor)
-    : root_classname_(root_classname),
-      descriptor_(descriptor),
-      field_generators_(descriptor),
-      class_name_(ClassName(descriptor_)),
-      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_->real_oneof_decl_count(); i++) {
-    OneofGenerator* generator = new OneofGenerator(descriptor_->oneof_decl(i));
-    oneof_generators_.emplace_back(generator);
-  }
-
-  for (int i = 0; i < descriptor_->enum_type_count(); i++) {
-    EnumGenerator* generator = new EnumGenerator(descriptor_->enum_type(i));
-    enum_generators_.emplace_back(generator);
-  }
-
-  for (int i = 0; i < descriptor_->nested_type_count(); i++) {
-    MessageGenerator* generator =
-        new MessageGenerator(root_classname_,
-                             descriptor_->nested_type(i));
-    nested_message_generators_.emplace_back(generator);
-  }
-}
-
-MessageGenerator::~MessageGenerator() {}
-
-void MessageGenerator::GenerateStaticVariablesInitialization(
-    io::Printer* printer) {
-  for (const auto& generator : extension_generators_) {
-    generator->GenerateStaticVariablesInitialization(printer);
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    generator->GenerateStaticVariablesInitialization(printer);
-  }
-}
-
-void MessageGenerator::DetermineForwardDeclarations(
-    std::set<std::string>* fwd_decls,
-    bool include_external_types) {
-  if (!IsMapEntryMessage(descriptor_)) {
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      const FieldDescriptor* fieldDescriptor = descriptor_->field(i);
-      field_generators_.get(fieldDescriptor)
-          .DetermineForwardDeclarations(fwd_decls, include_external_types);
-    }
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    generator->DetermineForwardDeclarations(fwd_decls, include_external_types);
-  }
-}
-
-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);
-      field_generators_.get(fieldDescriptor)
-          .DetermineObjectiveCClassDefinitions(fwd_decls);
-    }
-  }
-
-  for (const auto& generator : extension_generators_) {
-    generator->DetermineObjectiveCClassDefinitions(fwd_decls);
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    generator->DetermineObjectiveCClassDefinitions(fwd_decls);
-  }
-
-  const Descriptor* containing_descriptor = descriptor_->containing_type();
-  if (containing_descriptor != NULL) {
-    std::string containing_class = ClassName(containing_descriptor);
-    fwd_decls->insert(ObjCClassDeclaration(containing_class));
-  }
-}
-
-bool MessageGenerator::IncludesOneOfDefinition() const {
-  if (!oneof_generators_.empty()) {
-    return true;
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    if (generator->IncludesOneOfDefinition()) {
-      return true;
-    }
-  }
-
-  return false;
-}
-
-void MessageGenerator::GenerateEnumHeader(io::Printer* printer) {
-  for (const auto& generator : enum_generators_) {
-    generator->GenerateHeader(printer);
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    generator->GenerateEnumHeader(printer);
-  }
-}
-
-void MessageGenerator::GenerateExtensionRegistrationSource(
-    io::Printer* printer) {
-  for (const auto& generator : extension_generators_) {
-    generator->GenerateRegistrationSource(printer);
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    generator->GenerateExtensionRegistrationSource(printer);
-  }
-}
-
-void MessageGenerator::GenerateMessageHeader(io::Printer* printer) {
-  // This a a map entry message, just recurse and do nothing directly.
-  if (IsMapEntryMessage(descriptor_)) {
-    for (const auto& generator : nested_message_generators_) {
-      generator->GenerateMessageHeader(printer);
-    }
-    return;
-  }
-
-  printer->Print(
-      "#pragma mark - $classname$\n"
-      "\n",
-      "classname", class_name_);
-
-  if (descriptor_->field_count()) {
-    std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
-        SortFieldsByNumber(descriptor_));
-
-    printer->Print("typedef GPB_ENUM($classname$_FieldNumber) {\n",
-                   "classname", class_name_);
-    printer->Indent();
-
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      field_generators_.get(sorted_fields[i])
-          .GenerateFieldNumberConstant(printer);
-    }
-
-    printer->Outdent();
-    printer->Print("};\n\n");
-  }
-
-  for (const auto& generator : oneof_generators_) {
-    generator->GenerateCaseEnum(printer);
-  }
-
-  std::string message_comments;
-  SourceLocation location;
-  if (descriptor_->GetSourceLocation(&location)) {
-    message_comments = BuildCommentsString(location, false);
-  } else {
-    message_comments = "";
-  }
-
-  printer->Print(
-      "$comments$$deprecated_attribute$GPB_FINAL @interface $classname$ : GPBMessage\n\n",
-      "classname", class_name_,
-      "deprecated_attribute", deprecated_attribute_,
-      "comments", message_comments);
-
-  std::vector<char> seen_oneofs(oneof_generators_.size(), 0);
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    const FieldDescriptor* field = descriptor_->field(i);
-    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(
-            printer);
-      }
-    }
-    field_generators_.get(field).GeneratePropertyDeclaration(printer);
-  }
-
-  printer->Print("@end\n\n");
-
-  for (int i = 0; i < descriptor_->field_count(); i++) {
-    field_generators_.get(descriptor_->field(i))
-        .GenerateCFunctionDeclarations(printer);
-  }
-
-  if (!oneof_generators_.empty()) {
-    for (const auto& generator : oneof_generators_) {
-      generator->GenerateClearFunctionDeclaration(printer);
-    }
-    printer->Print("\n");
-  }
-
-  if (descriptor_->extension_count() > 0) {
-    printer->Print("@interface $classname$ (DynamicMethods)\n\n",
-                   "classname", class_name_);
-    for (const auto& generator : extension_generators_) {
-      generator->GenerateMembersHeader(printer);
-    }
-    printer->Print("@end\n\n");
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    generator->GenerateMessageHeader(printer);
-  }
-}
-
-void MessageGenerator::GenerateSource(io::Printer* printer) {
-  if (!IsMapEntryMessage(descriptor_)) {
-    printer->Print(
-        "#pragma mark - $classname$\n"
-        "\n",
-        "classname", class_name_);
-
-    if (!deprecated_attribute_.empty()) {
-      // No warnings when compiling the impl of this deprecated class.
-      printer->Print(
-          "#pragma clang diagnostic push\n"
-          "#pragma clang diagnostic ignored \"-Wdeprecated-implementations\"\n"
-          "\n");
-    }
-
-    printer->Print("@implementation $classname$\n\n",
-                   "classname", class_name_);
-
-    for (const auto& generator : oneof_generators_) {
-      generator->GeneratePropertyImplementation(printer);
-    }
-
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      field_generators_.get(descriptor_->field(i))
-          .GeneratePropertyImplementation(printer);
-    }
-
-    std::unique_ptr<const FieldDescriptor*[]> sorted_fields(
-        SortFieldsByNumber(descriptor_));
-    std::unique_ptr<const FieldDescriptor*[]> size_order_fields(
-        SortFieldsByStorageSize(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));
-    }
-
-    std::sort(sorted_extensions.begin(), sorted_extensions.end(),
-         ExtensionRangeOrdering());
-
-    // Assign has bits:
-    // 1. FieldGeneratorMap::CalculateHasBits() loops through the fields seeing
-    //    who needs has bits and assigning them.
-    // 2. FieldGenerator::SetOneofIndexBase() overrides has_bit with a negative
-    //    index that groups all the elements in the oneof.
-    size_t num_has_bits = field_generators_.CalculateHasBits();
-    size_t sizeof_has_storage = (num_has_bits + 31) / 32;
-    if (sizeof_has_storage == 0) {
-      // In the case where no field needs has bits, don't let the _has_storage_
-      // end up as zero length (zero length arrays are sort of a grey area
-      // since it has to be at the start of the struct). This also ensures a
-      // field with only oneofs keeps the required negative indices they need.
-      sizeof_has_storage = 1;
-    }
-    // Tell all the fields the oneof base.
-    for (const auto& generator : oneof_generators_) {
-      generator->SetOneofIndexBase(sizeof_has_storage);
-    }
-    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 += oneof_generators_.size();
-
-    printer->Print(
-        "\n"
-        "typedef struct $classname$__storage_ {\n"
-        "  uint32_t _has_storage_[$sizeof_has_storage$];\n",
-        "classname", class_name_,
-        "sizeof_has_storage", StrCat(sizeof_has_storage));
-    printer->Indent();
-
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      field_generators_.get(size_order_fields[i])
-          .GenerateFieldStorageDeclaration(printer);
-    }
-    printer->Outdent();
-
-    printer->Print("} $classname$__storage_;\n\n", "classname", class_name_);
-
-
-    printer->Print(
-        "// This method is threadsafe because it is initially called\n"
-        "// in +initialize for each subclass.\n"
-        "+ (GPBDescriptor *)descriptor {\n"
-        "  static GPBDescriptor *descriptor = nil;\n"
-        "  if (!descriptor) {\n");
-
-    TextFormatDecodeData text_format_decode_data;
-    bool has_fields = descriptor_->field_count() > 0;
-    bool need_defaults = field_generators_.DoesAnyFieldHaveNonZeroDefault();
-    std::string field_description_type;
-    if (need_defaults) {
-      field_description_type = "GPBMessageFieldDescriptionWithDefault";
-    } else {
-      field_description_type = "GPBMessageFieldDescription";
-    }
-    if (has_fields) {
-      printer->Indent();
-      printer->Indent();
-      printer->Print(
-          "static $field_description_type$ fields[] = {\n",
-          "field_description_type", field_description_type);
-      printer->Indent();
-      for (int i = 0; i < descriptor_->field_count(); ++i) {
-        const FieldGenerator& field_generator =
-            field_generators_.get(sorted_fields[i]);
-        field_generator.GenerateFieldDescription(printer, need_defaults);
-        if (field_generator.needs_textformat_name_support()) {
-          text_format_decode_data.AddString(sorted_fields[i]->number(),
-                                            field_generator.generated_objc_name(),
-                                            field_generator.raw_field_name());
-        }
-      }
-      printer->Outdent();
-      printer->Print(
-          "};\n");
-      printer->Outdent();
-      printer->Outdent();
-    }
-
-    std::map<std::string, std::string> vars;
-    vars["classname"] = class_name_;
-    vars["rootclassname"] = root_classname_;
-    vars["fields"] = has_fields ? "fields" : "NULL";
-    if (has_fields) {
-      vars["fields_count"] =
-          "(uint32_t)(sizeof(fields) / sizeof(" + field_description_type + "))";
-    } else {
-      vars["fields_count"] = "0";
-    }
-
-    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");
-    }
-    if (descriptor_->options().message_set_wire_format()) {
-      init_flags.push_back("GPBDescriptorInitializationFlag_WireFormat");
-    }
-    vars["init_flags"] = BuildFlagsString(FLAGTYPE_DESCRIPTOR_INITIALIZATION,
-                                          init_flags);
-
-    printer->Print(
-        vars,
-        "    GPBDescriptor *localDescriptor =\n"
-        "        [GPBDescriptor allocDescriptorForClass:[$classname$ class]\n"
-        "                                     rootClass:[$rootclassname$ class]\n"
-        "                                          file:$rootclassname$_FileDescriptor()\n"
-        "                                        fields:$fields$\n"
-        "                                    fieldCount:$fields_count$\n"
-        "                                   storageSize:sizeof($classname$__storage_)\n"
-        "                                         flags:$init_flags$];\n");
-    if (!oneof_generators_.empty()) {
-      printer->Print(
-          "    static const char *oneofs[] = {\n");
-      for (const auto& generator : oneof_generators_) {
-        printer->Print("      \"$name$\",\n", "name",
-                       generator->DescriptorName());
-      }
-      printer->Print(
-          "    };\n"
-          "    [localDescriptor setupOneofs:oneofs\n"
-          "                           count:(uint32_t)(sizeof(oneofs) / sizeof(char*))\n"
-          "                   firstHasIndex:$first_has_index$];\n",
-          "first_has_index", oneof_generators_[0]->HasIndexAsString());
-    }
-    if (text_format_decode_data.num_entries() != 0) {
-      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 =");
-      static const int kBytesPerLine = 40;  // allow for escaping
-      for (int i = 0; i < text_format_data_str.size(); i += kBytesPerLine) {
-        printer->Print(
-            "\n        \"$data$\"",
-            "data", EscapeTrigraphs(
-                CEscape(text_format_data_str.substr(i, kBytesPerLine))));
-      }
-      printer->Print(
-          ";\n"
-          "    [localDescriptor setupExtraTextInfo:extraTextFormatInfo];\n"
-          "#endif  // !GPBOBJC_SKIP_MESSAGE_TEXTFORMAT_EXTRAS\n");
-    }
-    if (!sorted_extensions.empty()) {
-      printer->Print(
-          "    static const GPBExtensionRange ranges[] = {\n");
-      for (int i = 0; i < sorted_extensions.size(); i++) {
-        printer->Print("      { .start = $start$, .end = $end$ },\n",
-                       "start", StrCat(sorted_extensions[i]->start),
-                       "end", StrCat(sorted_extensions[i]->end));
-      }
-      printer->Print(
-          "    };\n"
-          "    [localDescriptor setupExtensionRanges:ranges\n"
-          "                                    count:(uint32_t)(sizeof(ranges) / sizeof(GPBExtensionRange))];\n");
-    }
-    if (descriptor_->containing_type() != NULL) {
-      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);
-    }
-    std::string suffix_added;
-    ClassName(descriptor_, &suffix_added);
-    if (!suffix_added.empty()) {
-      printer->Print(
-          "    [localDescriptor setupMessageClassNameSuffix:@\"$suffix$\"];\n",
-          "suffix", suffix_added);
-    }
-    printer->Print(
-        "    #if defined(DEBUG) && DEBUG\n"
-        "      NSAssert(descriptor == nil, @\"Startup recursed!\");\n"
-        "    #endif  // DEBUG\n"
-        "    descriptor = localDescriptor;\n"
-        "  }\n"
-        "  return descriptor;\n"
-        "}\n\n"
-        "@end\n\n");
-
-    if (!deprecated_attribute_.empty()) {
-      printer->Print(
-          "#pragma clang diagnostic pop\n"
-          "\n");
-    }
-
-    for (int i = 0; i < descriptor_->field_count(); i++) {
-      field_generators_.get(descriptor_->field(i))
-          .GenerateCFunctionImplementations(printer);
-    }
-
-    for (const auto& generator : oneof_generators_) {
-      generator->GenerateClearFunctionImplementation(printer);
-    }
-  }
-
-  for (const auto& generator : enum_generators_) {
-    generator->GenerateSource(printer);
-  }
-
-  for (const auto& generator : nested_message_generators_) {
-    generator->GenerateSource(printer);
-  }
-}
-
-}  // namespace objectivec
-}  // namespace compiler
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h b/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h
deleted file mode 100644
index 1633046..0000000
--- a/src/google/protobuf/compiler/objectivec/objectivec_nsobject_methods.h
+++ /dev/null
@@ -1,197 +0,0 @@
-// NSObject methods
-// Autogenerated by method_dump.sh. Do not edit by hand.
-// Date: Thu Nov  1 14:12:16 PDT 2018
-// macOS: MacOSX10.14.sdk
-// iOS: iPhoneSimulator12.1.sdk
-
-const char* const kNSObjectMethodsList[] = {
-	"CAMLType",
-	"CA_copyRenderValue",
-	"CA_prepareRenderValue",
-	"NS_copyCGImage",
-	"NS_tiledLayerVisibleRect",
-	"___tryRetain_OA",
-	"__autorelease_OA",
-	"__dealloc_zombie",
-	"__release_OA",
-	"__retain_OA",
-	"_accessibilityFinalize",
-	"_accessibilityIsTableViewDescendant",
-	"_accessibilityUIElementSpecifier",
-	"_accessibilityUseConvenienceAPI",
-	"_allowsDirectEncoding",
-	"_asScriptTerminologyNameArray",
-	"_asScriptTerminologyNameString",
-	"_bindingAdaptor",
-	"_cfTypeID",
-	"_copyDescription",
-	"_destroyObserverList",
-	"_didEndKeyValueObserving",
-	"_implicitObservationInfo",
-	"_internalAccessibilityAttributedHint",
-	"_internalAccessibilityAttributedLabel",
-	"_internalAccessibilityAttributedValue",
-	"_isAXConnector",
-	"_isAccessibilityContainerSectionCandidate",
-	"_isAccessibilityContentNavigatorSectionCandidate",
-	"_isAccessibilityContentSectionCandidate",
-	"_isAccessibilityTopLevelNavigatorSectionCandidate",
-	"_isDeallocating",
-	"_isKVOA",
-	"_isToManyChangeInformation",
-	"_ivarDescription",
-	"_localClassNameForClass",
-	"_methodDescription",
-	"_observerStorage",
-	"_overrideUseFastBlockObservers",
-	"_propertyDescription",
-	"_releaseBindingAdaptor",
-	"_scriptingCount",
-	"_scriptingCountNonrecursively",
-	"_scriptingDebugDescription",
-	"_scriptingExists",
-	"_scriptingShouldCheckObjectIndexes",
-	"_shortMethodDescription",
-	"_shouldSearchChildrenForSection",
-	"_traitStorageList",
-	"_tryRetain",
-	"_ui_descriptionBuilder",
-	"_uikit_variesByTraitCollections",
-	"_web_description",
-	"_webkit_invokeOnMainThread",
-	"_willBeginKeyValueObserving",
-	"accessibilityActivate",
-	"accessibilityActivationPoint",
-	"accessibilityAllowsOverriddenAttributesWhenIgnored",
-	"accessibilityAssistiveTechnologyFocusedIdentifiers",
-	"accessibilityAttributedHint",
-	"accessibilityAttributedLabel",
-	"accessibilityAttributedValue",
-	"accessibilityContainer",
-	"accessibilityContainerType",
-	"accessibilityCustomActions",
-	"accessibilityCustomRotors",
-	"accessibilityDecrement",
-	"accessibilityDragSourceDescriptors",
-	"accessibilityDropPointDescriptors",
-	"accessibilityElementCount",
-	"accessibilityElementDidBecomeFocused",
-	"accessibilityElementDidLoseFocus",
-	"accessibilityElementIsFocused",
-	"accessibilityElements",
-	"accessibilityElementsHidden",
-	"accessibilityFrame",
-	"accessibilityHeaderElements",
-	"accessibilityHint",
-	"accessibilityIdentification",
-	"accessibilityIdentifier",
-	"accessibilityIncrement",
-	"accessibilityLabel",
-	"accessibilityLanguage",
-	"accessibilityLocalizedStringKey",
-	"accessibilityNavigationStyle",
-	"accessibilityOverriddenAttributes",
-	"accessibilityParameterizedAttributeNames",
-	"accessibilityPath",
-	"accessibilityPerformEscape",
-	"accessibilityPerformMagicTap",
-	"accessibilityPresenterProcessIdentifier",
-	"accessibilityShouldUseUniqueId",
-	"accessibilitySupportsNotifications",
-	"accessibilitySupportsOverriddenAttributes",
-	"accessibilityTemporaryChildren",
-	"accessibilityTraits",
-	"accessibilityValue",
-	"accessibilityViewIsModal",
-	"accessibilityVisibleArea",
-	"allPropertyKeys",
-	"allowsWeakReference",
-	"attributeKeys",
-	"autoContentAccessingProxy",
-	"autorelease",
-	"awakeFromNib",
-	"boolValueSafe",
-	"bs_encoded",
-	"bs_isPlistableType",
-	"bs_secureEncoded",
-	"cl_json_serializeKey",
-	"class",
-	"classCode",
-	"classDescription",
-	"classForArchiver",
-	"classForCoder",
-	"classForKeyedArchiver",
-	"classForPortCoder",
-	"className",
-	"clearProperties",
-	"copy",
-	"dealloc",
-	"debugDescription",
-	"defaultAccessibilityTraits",
-	"description",
-	"doubleValueSafe",
-	"entityName",
-	"exposedBindings",
-	"finalize",
-	"finishObserving",
-	"flushKeyBindings",
-	"hash",
-	"init",
-	"int64ValueSafe",
-	"isAccessibilityElement",
-	"isAccessibilityElementByDefault",
-	"isElementAccessibilityExposedToInterfaceBuilder",
-	"isFault",
-	"isNSArray__",
-	"isNSCFConstantString__",
-	"isNSData__",
-	"isNSDate__",
-	"isNSDictionary__",
-	"isNSNumber__",
-	"isNSObject__",
-	"isNSOrderedSet__",
-	"isNSSet__",
-	"isNSString__",
-	"isNSTimeZone__",
-	"isNSValue__",
-	"isProxy",
-	"mutableCopy",
-	"nilValueForKey",
-	"objectSpecifier",
-	"observationInfo",
-	"pep_onDetachedThread",
-	"pep_onMainThread",
-	"pep_onMainThreadIfNecessary",
-	"prepareForInterfaceBuilder",
-	"release",
-	"releaseOnMainThread",
-	"retain",
-	"retainCount",
-	"retainWeakReference",
-	"scriptingProperties",
-	"self",
-	"shouldGroupAccessibilityChildren",
-	"storedAccessibilityActivationPoint",
-	"storedAccessibilityContainerType",
-	"storedAccessibilityElementsHidden",
-	"storedAccessibilityFrame",
-	"storedAccessibilityNavigationStyle",
-	"storedAccessibilityTraits",
-	"storedAccessibilityViewIsModal",
-	"storedIsAccessibilityElement",
-	"storedShouldGroupAccessibilityChildren",
-	"stringValueSafe",
-	"superclass",
-	"toManyRelationshipKeys",
-	"toOneRelationshipKeys",
-	"traitStorageList",
-	"un_safeBoolValue",
-	"userInterfaceItemIdentifier",
-	"utf8ValueSafe",
-	"valuesForKeysWithDictionary",
-	"zone",
-// Protocol: CAAnimatableValue
-// Protocol: CARenderValue
-// Protocol: NSObject
-// Protocol: ROCKRemoteInvocationInterface
-};
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc b/src/google/protobuf/compiler/objectivec/oneof.cc
similarity index 72%
rename from src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
rename to src/google/protobuf/compiler/objectivec/oneof.cc
index 1bef293..99b2149 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.cc
+++ b/src/google/protobuf/compiler/objectivec/oneof.cc
@@ -28,13 +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.
 
-#include <map>
+#include "google/protobuf/compiler/objectivec/oneof.h"
+
 #include <string>
 
-#include <google/protobuf/compiler/objectivec/objectivec_oneof.h>
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/compiler/objectivec/names.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -46,7 +47,7 @@
   variables_["enum_name"] = OneofEnumName(descriptor_);
   variables_["name"] = OneofName(descriptor_);
   variables_["capitalized_name"] = OneofNameCapitalized(descriptor_);
-  variables_["raw_index"] = StrCat(descriptor_->index());
+  variables_["raw_index"] = absl::StrCat(descriptor_->index());
   const Descriptor* msg_descriptor = descriptor_->containing_type();
   variables_["owning_message_class"] = ClassName(msg_descriptor);
 
@@ -60,63 +61,63 @@
   variables_["comments"] = comments;
 }
 
-OneofGenerator::~OneofGenerator() {}
-
 void OneofGenerator::SetOneofIndexBase(int index_base) {
   int index = descriptor_->index() + index_base;
   // Flip the sign to mark it as a oneof.
-  variables_["index"] = StrCat(-index);
+  variables_["index"] = absl::StrCat(-index);
 }
 
-void OneofGenerator::GenerateCaseEnum(io::Printer* printer) {
-  printer->Print(
-      variables_,
-      "typedef GPB_ENUM($enum_name$) {\n");
+void OneofGenerator::GenerateCaseEnum(io::Printer* printer) const {
+  printer->Print(variables_, "typedef GPB_ENUM($enum_name$) {\n");
   printer->Indent();
-  printer->Print(
-      variables_,
-      "$enum_name$_GPBUnsetOneOfCase = 0,\n");
-  std::string enum_name = variables_["enum_name"];
+  printer->Print(variables_, "$enum_name$_GPBUnsetOneOfCase = 0,\n");
+  std::string enum_name = variables_.find("enum_name")->second;
   for (int j = 0; j < descriptor_->field_count(); j++) {
     const FieldDescriptor* field = descriptor_->field(j);
     std::string field_name = FieldNameCapitalized(field);
-    printer->Print(
-        "$enum_name$_$field_name$ = $field_number$,\n",
-        "enum_name", enum_name,
-        "field_name", field_name,
-        "field_number", StrCat(field->number()));
+    printer->Print("$enum_name$_$field_name$ = $field_number$,\n", "enum_name",
+                   enum_name, "field_name", field_name, "field_number",
+                   absl::StrCat(field->number()));
   }
   printer->Outdent();
+  // clang-format off
   printer->Print(
       "};\n"
       "\n");
+  // clang-format on
 }
 
 void OneofGenerator::GeneratePublicCasePropertyDeclaration(
-    io::Printer* printer) {
+    io::Printer* printer) const {
+  // clang-format off
   printer->Print(
       variables_,
       "$comments$"
       "@property(nonatomic, readonly) $enum_name$ $name$OneOfCase;\n"
       "\n");
+  // clang-format on
 }
 
-void OneofGenerator::GenerateClearFunctionDeclaration(io::Printer* printer) {
+void OneofGenerator::GenerateClearFunctionDeclaration(
+    io::Printer* printer) const {
+  // clang-format off
   printer->Print(
       variables_,
       "/**\n"
       " * Clears whatever value was set for the oneof '$name$'.\n"
       " **/\n"
       "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message);\n");
+  // clang-format on
 }
 
-void OneofGenerator::GeneratePropertyImplementation(io::Printer* printer) {
-  printer->Print(
-      variables_,
-      "@dynamic $name$OneOfCase;\n");
+void OneofGenerator::GeneratePropertyImplementation(
+    io::Printer* printer) const {
+  printer->Print(variables_, "@dynamic $name$OneOfCase;\n");
 }
 
-void OneofGenerator::GenerateClearFunctionImplementation(io::Printer* printer) {
+void OneofGenerator::GenerateClearFunctionImplementation(
+    io::Printer* printer) const {
+  // clang-format off
   printer->Print(
       variables_,
       "void $owning_message_class$_Clear$capitalized_name$OneOfCase($owning_message_class$ *message) {\n"
@@ -124,13 +125,14 @@
       "  GPBOneofDescriptor *oneof = [descriptor.oneofs objectAtIndex:$raw_index$];\n"
       "  GPBClearOneof(message, oneof);\n"
       "}\n");
+  // clang-format on
 }
 
-std::string OneofGenerator::DescriptorName(void) const {
+std::string OneofGenerator::DescriptorName() const {
   return variables_.find("name")->second;
 }
 
-std::string OneofGenerator::HasIndexAsString(void) const {
+std::string OneofGenerator::HasIndexAsString() const {
   return variables_.find("index")->second;
 }
 
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h b/src/google/protobuf/compiler/objectivec/oneof.h
similarity index 83%
rename from src/google/protobuf/compiler/objectivec/objectivec_oneof.h
rename to src/google/protobuf/compiler/objectivec/oneof.h
index 034f07f..398a962 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_oneof.h
+++ b/src/google/protobuf/compiler/objectivec/oneof.h
@@ -32,10 +32,11 @@
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_ONEOF_H__
 
 #include <string>
-#include <set>
 #include <vector>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/printer.h>
+
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
@@ -45,27 +46,27 @@
 class OneofGenerator {
  public:
   explicit OneofGenerator(const OneofDescriptor* descriptor);
-  ~OneofGenerator();
+  ~OneofGenerator() = default;
 
   OneofGenerator(const OneofGenerator&) = delete;
   OneofGenerator& operator=(const OneofGenerator&) = delete;
 
   void SetOneofIndexBase(int index_base);
 
-  void GenerateCaseEnum(io::Printer* printer);
+  void GenerateCaseEnum(io::Printer* printer) const;
 
-  void GeneratePublicCasePropertyDeclaration(io::Printer* printer);
-  void GenerateClearFunctionDeclaration(io::Printer* printer);
+  void GeneratePublicCasePropertyDeclaration(io::Printer* printer) const;
+  void GenerateClearFunctionDeclaration(io::Printer* printer) const;
 
-  void GeneratePropertyImplementation(io::Printer* printer);
-  void GenerateClearFunctionImplementation(io::Printer* printer);
+  void GeneratePropertyImplementation(io::Printer* printer) const;
+  void GenerateClearFunctionImplementation(io::Printer* printer) const;
 
-  std::string DescriptorName(void) const;
-  std::string HasIndexAsString(void) const;
+  std::string DescriptorName() const;
+  std::string HasIndexAsString() const;
 
  private:
   const OneofDescriptor* descriptor_;
-  std::map<std::string, std::string> variables_;
+  absl::flat_hash_map<absl::string_view, std::string> variables_;
 };
 
 }  // namespace objectivec
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/compiler/objectivec/options.h
similarity index 70%
copy from src/google/protobuf/util/internal/error_listener.cc
copy to src/google/protobuf/compiler/objectivec/options.h
index 538307b..388d1ca 100644
--- a/src/google/protobuf/util/internal/error_listener.cc
+++ b/src/google/protobuf/compiler/objectivec/options.h
@@ -28,15 +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.
 
-#include <google/protobuf/util/internal/error_listener.h>
+#ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_OPTIONS_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_OPTIONS_H__
+
+#include <string>
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace converter {
+namespace compiler {
+namespace objectivec {
 
+// Generation options, documented within generator.cc.
+struct GenerationOptions {
+  std::string generate_for_named_framework;
+  std::string named_framework_to_proto_path_mappings_path;
+  std::string runtime_import_prefix;
+  // TODO(thomasvl): Eventually flip this default to false for better interop
+  // with Swift if proto usages span modules made from ObjC sources.
+  bool headers_use_forward_declarations = true;
+};
 
-}  // namespace converter
-}  // namespace util
+}  // namespace objectivec
+}  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_OPTIONS_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc b/src/google/protobuf/compiler/objectivec/primitive_field.cc
similarity index 84%
rename from src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
rename to src/google/protobuf/compiler/objectivec/primitive_field.cc
index 1fefde5..fa89d2c 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.cc
+++ b/src/google/protobuf/compiler/objectivec/primitive_field.cc
@@ -28,22 +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.
 
-#include <map>
+#include "google/protobuf/compiler/objectivec/primitive_field.h"
+
 #include <string>
 
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/compiler/objectivec/objectivec_primitive_field.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/compiler/objectivec/helpers.h"
+#include "google/protobuf/io/printer.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace objectivec {
 
-using internal::WireFormat;
-using internal::WireFormatLite;
-
 namespace {
 
 const char* PrimitiveTypeName(const FieldDescriptor* descriptor) {
@@ -70,13 +68,13 @@
     case OBJECTIVECTYPE_ENUM:
       return "int32_t";
     case OBJECTIVECTYPE_MESSAGE:
-      return NULL;  // Messages go through objectivec_message_field.cc|h.
+      return nullptr;  // Messages go through message_field.cc|h.
   }
 
   // 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 NULL;
+  return nullptr;
 }
 
 const char* PrimitiveArrayTypeName(const FieldDescriptor* descriptor) {
@@ -103,18 +101,19 @@
     case OBJECTIVECTYPE_ENUM:
       return "Enum";
     case OBJECTIVECTYPE_MESSAGE:
-      // Want NSArray (but goes through objectivec_message_field.cc|h).
+      // Want NSArray (but goes through message_field.cc|h).
       return "";
   }
 
   // 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 NULL;
+  return nullptr;
 }
 
-void SetPrimitiveVariables(const FieldDescriptor* descriptor,
-                           std::map<std::string, std::string>* variables) {
+void SetPrimitiveVariables(
+    const FieldDescriptor* descriptor,
+    absl::flat_hash_map<absl::string_view, std::string>* variables) {
   std::string primitive_name = PrimitiveTypeName(descriptor);
   (*variables)["type"] = primitive_name;
   (*variables)["storage_type"] = primitive_name;
@@ -128,8 +127,6 @@
   SetPrimitiveVariables(descriptor, &variables_);
 }
 
-PrimitiveFieldGenerator::~PrimitiveFieldGenerator() {}
-
 void PrimitiveFieldGenerator::GenerateFieldStorageDeclaration(
     io::Printer* printer) const {
   if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
@@ -139,7 +136,7 @@
   }
 }
 
-int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded(void) const {
+int PrimitiveFieldGenerator::ExtraRuntimeHasBitsNeeded() const {
   if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
     // Reserve a bit for the storage of the boolean.
     return 1;
@@ -147,10 +144,10 @@
   return 0;
 }
 
-void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int has_base) {
+void PrimitiveFieldGenerator::SetExtraRuntimeHasBitsBase(int index_base) {
   if (GetObjectiveCType(descriptor_) == OBJECTIVECTYPE_BOOLEAN) {
     // Set into the offset the has bit to use for the actual value.
-    variables_["storage_offset_value"] = StrCat(has_base);
+    variables_["storage_offset_value"] = absl::StrCat(index_base);
     variables_["storage_offset_comment"] =
         "  // Stored in _has_storage_ to save space.";
   }
@@ -163,8 +160,6 @@
   variables_["property_storage_attribute"] = "copy";
 }
 
-PrimitiveObjFieldGenerator::~PrimitiveObjFieldGenerator() {}
-
 RepeatedPrimitiveFieldGenerator::RepeatedPrimitiveFieldGenerator(
     const FieldDescriptor* descriptor)
     : RepeatedFieldGenerator(descriptor) {
@@ -180,8 +175,6 @@
   }
 }
 
-RepeatedPrimitiveFieldGenerator::~RepeatedPrimitiveFieldGenerator() {}
-
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h b/src/google/protobuf/compiler/objectivec/primitive_field.h
similarity index 88%
rename from src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
rename to src/google/protobuf/compiler/objectivec/primitive_field.h
index 06a1528..e691605 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_primitive_field.h
+++ b/src/google/protobuf/compiler/objectivec/primitive_field.h
@@ -31,7 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
 #define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_PRIMITIVE_FIELD_H__
 
-#include <google/protobuf/compiler/objectivec/objectivec_field.h>
+#include "google/protobuf/compiler/objectivec/field.h"
 
 namespace google {
 namespace protobuf {
@@ -43,15 +43,15 @@
 
  protected:
   explicit PrimitiveFieldGenerator(const FieldDescriptor* descriptor);
-  virtual ~PrimitiveFieldGenerator();
+  ~PrimitiveFieldGenerator() override = default;
 
   PrimitiveFieldGenerator(const PrimitiveFieldGenerator&) = delete;
   PrimitiveFieldGenerator& operator=(const PrimitiveFieldGenerator&) = delete;
 
-  virtual void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
+  void GenerateFieldStorageDeclaration(io::Printer* printer) const override;
 
-  virtual int ExtraRuntimeHasBitsNeeded(void) const override;
-  virtual void SetExtraRuntimeHasBitsBase(int index_base) override;
+  int ExtraRuntimeHasBitsNeeded() const override;
+  void SetExtraRuntimeHasBitsBase(int index_base) override;
 };
 
 class PrimitiveObjFieldGenerator : public ObjCObjFieldGenerator {
@@ -59,7 +59,7 @@
 
  protected:
   explicit PrimitiveObjFieldGenerator(const FieldDescriptor* descriptor);
-  virtual ~PrimitiveObjFieldGenerator();
+  ~PrimitiveObjFieldGenerator() override = default;
 
   PrimitiveObjFieldGenerator(const PrimitiveObjFieldGenerator&) = delete;
   PrimitiveObjFieldGenerator& operator=(const PrimitiveObjFieldGenerator&) =
@@ -71,7 +71,7 @@
 
  protected:
   explicit RepeatedPrimitiveFieldGenerator(const FieldDescriptor* descriptor);
-  virtual ~RepeatedPrimitiveFieldGenerator();
+  ~RepeatedPrimitiveFieldGenerator() override = default;
 
   RepeatedPrimitiveFieldGenerator(const RepeatedPrimitiveFieldGenerator&) =
       delete;
diff --git a/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc b/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc
new file mode 100644
index 0000000..df1c153
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/text_format_decode_data.cc
@@ -0,0 +1,266 @@
+// 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/objectivec/text_format_decode_data.h"
+
+#include <iostream>
+#include <ostream>
+#include <sstream>
+#include <string>
+#include <vector>
+
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/match.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+
+// 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 errors.
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+namespace {
+
+// Helper to build up the decode data for a string.
+class DecodeDataBuilder {
+ public:
+  DecodeDataBuilder() { Reset(); }
+
+  bool AddCharacter(const char desired, const char input);
+  void AddUnderscore() {
+    Push();
+    need_underscore_ = true;
+  }
+  std::string Finish() {
+    Push();
+    return decode_data_;
+  }
+
+ private:
+  static constexpr uint8_t kAddUnderscore = 0x80;
+
+  static constexpr uint8_t kOpAsIs = 0x00;
+  static constexpr uint8_t kOpFirstUpper = 0x40;
+  static constexpr uint8_t kOpFirstLower = 0x20;
+  static constexpr uint8_t kOpAllUpper = 0x60;
+
+  static constexpr int kMaxSegmentLen = 0x1f;
+
+  void AddChar(const char desired) {
+    ++segment_len_;
+    is_all_upper_ &= absl::ascii_isupper(desired);
+  }
+
+  void Push() {
+    uint8_t op = (op_ | segment_len_);
+    if (need_underscore_) op |= kAddUnderscore;
+    if (op != 0) {
+      decode_data_ += (char)op;
+    }
+    Reset();
+  }
+
+  bool AddFirst(const char desired, const char input) {
+    if (desired == input) {
+      op_ = kOpAsIs;
+    } else if (desired == absl::ascii_toupper(input)) {
+      op_ = kOpFirstUpper;
+    } else if (desired == absl::ascii_tolower(input)) {
+      op_ = kOpFirstLower;
+    } else {
+      // Can't be transformed to match.
+      return false;
+    }
+    AddChar(desired);
+    return true;
+  }
+
+  void Reset() {
+    need_underscore_ = false;
+    op_ = 0;
+    segment_len_ = 0;
+    is_all_upper_ = true;
+  }
+
+  bool need_underscore_;
+  bool is_all_upper_;
+  uint8_t op_;
+  int segment_len_;
+
+  std::string decode_data_;
+};
+
+bool DecodeDataBuilder::AddCharacter(const char desired, const char input) {
+  // If we've hit the max size, push to start a new segment.
+  if (segment_len_ == kMaxSegmentLen) {
+    Push();
+  }
+  if (segment_len_ == 0) {
+    return AddFirst(desired, input);
+  }
+
+  // Desired and input match...
+  if (desired == input) {
+    // If we aren't transforming it, or we're upper casing it and it is
+    // supposed to be uppercase; just add it to the segment.
+    if ((op_ != kOpAllUpper) || absl::ascii_isupper(desired)) {
+      AddChar(desired);
+      return true;
+    }
+
+    // Add the current segment, and start the next one.
+    Push();
+    return AddFirst(desired, input);
+  }
+
+  // If we need to uppercase, and everything so far has been uppercase,
+  // promote op to AllUpper.
+  if ((desired == absl::ascii_toupper(input)) && is_all_upper_) {
+    op_ = kOpAllUpper;
+    AddChar(desired);
+    return true;
+  }
+
+  // Give up, push and start a new segment.
+  Push();
+  return AddFirst(desired, input);
+}
+
+// If decode data can't be generated, a directive for the raw string
+// is used instead.
+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.
+  return result;
+}
+
+}  // namespace
+
+void TextFormatDecodeData::AddString(int32_t key,
+                                     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) {
+      std::cerr << "error: duplicate key (" << key
+                << ") making TextFormat data, input: \"" << input_for_decode
+                << "\", desired: \"" << desired_output << "\"." << std::endl;
+      std::cerr.flush();
+      abort();
+    }
+  }
+
+  const std::string& data = TextFormatDecodeData::DecodeDataForString(
+      input_for_decode, desired_output);
+  entries_.push_back(DataEntry(key, data));
+}
+
+std::string TextFormatDecodeData::Data() const {
+  std::ostringstream data_stringstream;
+
+  if (num_entries() > 0) {
+    io::OstreamOutputStream data_outputstream(&data_stringstream);
+    io::CodedOutputStream output_stream(&data_outputstream);
+
+    output_stream.WriteVarint32(num_entries());
+    for (std::vector<DataEntry>::const_iterator i = entries_.begin();
+         i != entries_.end(); ++i) {
+      output_stream.WriteVarint32(i->first);
+      output_stream.WriteString(i->second);
+    }
+  }
+
+  data_stringstream.flush();
+  return data_stringstream.str();
+}
+
+// static
+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
+              << "\"." << std::endl;
+    std::cerr.flush();
+    abort();
+  }
+  if ((absl::StrContains(input_for_decode, '\0')) ||
+      (absl::StrContains(desired_output, '\0'))) {
+    std::cerr
+        << "error: got a null char in a string for making TextFormat data,"
+        << " input: \"" << absl::CEscape(input_for_decode) << "\", desired: \""
+        << absl::CEscape(desired_output) << "\"." << std::endl;
+    std::cerr.flush();
+    abort();
+  }
+
+  DecodeDataBuilder builder;
+
+  // Walk the output building it from the input.
+  int x = 0;
+  for (int y = 0; y < desired_output.size(); y++) {
+    const char d = desired_output[y];
+    if (d == '_') {
+      builder.AddUnderscore();
+      continue;
+    }
+
+    if (x >= input_for_decode.size()) {
+      // Out of input, no way to encode it, just return a full decode.
+      return DirectDecodeString(desired_output);
+    }
+    if (builder.AddCharacter(d, input_for_decode[x])) {
+      ++x;  // Consumed one input
+    } else {
+      // Couldn't transform for the next character, just return a full decode.
+      return DirectDecodeString(desired_output);
+    }
+  }
+
+  if (x != input_for_decode.size()) {
+    // Extra input (suffix from name sanitizing?), just return a full decode.
+    return DirectDecodeString(desired_output);
+  }
+
+  // Add the end marker.
+  return builder.Finish() + (char)'\0';
+}
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/objectivec/text_format_decode_data.h b/src/google/protobuf/compiler/objectivec/text_format_decode_data.h
new file mode 100644
index 0000000..ab5b493
--- /dev/null
+++ b/src/google/protobuf/compiler/objectivec/text_format_decode_data.h
@@ -0,0 +1,79 @@
+// 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_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__
+#define GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__
+
+#include <string>
+#include <utility>
+#include <vector>
+
+// Must be included last
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace objectivec {
+
+// TODO(b/250947994): PROTOC_EXPORT is only used to allow the CMake build to
+// find/link these in the unittest, this is not public api.
+
+// Generate decode data needed for ObjC's GPBDecodeTextFormatName() to transform
+// the input into the expected output.
+class PROTOC_EXPORT TextFormatDecodeData {
+ public:
+  TextFormatDecodeData() = default;
+  ~TextFormatDecodeData() = default;
+
+  TextFormatDecodeData(const TextFormatDecodeData&) = delete;
+  TextFormatDecodeData& operator=(const TextFormatDecodeData&) = delete;
+
+  void AddString(int32_t key, const std::string& input_for_decode,
+                 const std::string& desired_output);
+  size_t num_entries() const { return entries_.size(); }
+  std::string Data() const;
+
+  static std::string DecodeDataForString(const std::string& input_for_decode,
+                                         const std::string& desired_output);
+
+ private:
+  typedef std::pair<int32_t, std::string> DataEntry;
+  std::vector<DataEntry> entries_;
+};
+
+}  // namespace objectivec
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_OBJECTIVEC_TEXT_FORMAT_DECODE_DATA_H__
diff --git a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc b/src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc
similarity index 67%
rename from src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
rename to src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc
index 7ae6a92..2891bcd 100644
--- a/src/google/protobuf/compiler/objectivec/objectivec_helpers_unittest.cc
+++ b/src/google/protobuf/compiler/objectivec/text_format_decode_data_unittest.cc
@@ -28,10 +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.
 
-#include <google/protobuf/compiler/objectivec/objectivec_helpers.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include "google/protobuf/compiler/objectivec/text_format_decode_data.h"
+
+#include <string>
+
 #include <gtest/gtest.h>
 
+// Must be included last
+#include "google/protobuf/port_def.inc"
+
 namespace google {
 namespace protobuf {
 namespace compiler {
@@ -101,10 +106,12 @@
 
   // Long name so multiple decode ops are needed.
 
+  // clang-format off
   input_for_decode =
       "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000";
   desired_output_for_decode =
       "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000";
+  // clang-format on
   expected = std::string("\x04\xA5\xA4\xA2\xBF\x1F\x0E\x84\x0", 9);
   result = TextFormatDecodeData::DecodeDataForString(input_for_decode,
                                                      desired_output_for_decode);
@@ -154,11 +161,13 @@
   EXPECT_EQ(4, decode_data.num_entries());
 
   uint8_t expected_data[] = {
+      // clang-format off
       0x4,
       0x1, 0x0, 'z', 'b', 'c', 'd', 'e', 'f', 'g', 'h', 'I', 'J', 0x0,
       0x3, 0x0, 'a', 'b', 'c', 'd', 'e', 'z', 'g', 'h', 'I', 'J', 0x0,
       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,
+      // clang-format on
   };
   std::string expected((const char*)expected_data, sizeof(expected_data));
 
@@ -172,12 +181,15 @@
   decode_data.AddString(3, "abcdefghIJ", "_AbcdefghIJ");
   decode_data.AddString(2, "abcdefghIJ", "Abcd_EfghIJ");
   decode_data.AddString(4, "abcdefghIJ", "ABCD__EfghI_j");
+  // clang-format off
   decode_data.AddString(1000,
                         "longFieldNameIsLooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong1000",
                         "long_field_name_is_looooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooooong_1000");
+  // clang-format on
 
   EXPECT_EQ(5, decode_data.num_entries());
 
+  // clang-format off
   uint8_t expected_data[] = {
       0x5,
       // All as is (00 op)
@@ -196,12 +208,12 @@
       //   underscore, as is + 3 (00 op)
       0xE8, 0x07, 0x04, 0xA5, 0xA4, 0xA2, 0xBF, 0x1F, 0x0E, 0x84, 0x0,
   };
+  // clang-format on
   std::string expected((const char*)expected_data, sizeof(expected_data));
 
   EXPECT_EQ(expected, decode_data.Data());
 }
 
-
 // Death tests do not work on Windows as of yet.
 #ifdef PROTOBUF_HAS_DEATH_TEST
 TEST(ObjCHelperDeathTest, TextFormatDecodeData_Failures) {
@@ -242,143 +254,10 @@
 }
 #endif  // PROTOBUF_HAS_DEATH_TEST
 
-class TestLineCollector : public LineConsumer {
- public:
-  TestLineCollector(std::vector<std::string>* inout_lines,
-                    const std::string* reject_line = nullptr,
-                    bool skip_msg = false)
-    : lines_(inout_lines), reject_(reject_line), skip_msg_(skip_msg) {}
-
-  bool ConsumeLine(const StringPiece& line, std::string* out_error) override {
-    if (reject_ && *reject_ == line) {
-      if (!skip_msg_) {
-        *out_error = std::string("Rejected '") + *reject_ + "'";
-      }
-      return false;
-    }
-    if (lines_) {
-      lines_->emplace_back(line);
-    }
-    return true;
-  }
-
- private:
-  std::vector<std::string>* lines_;
-  const std::string* reject_;
-  bool skip_msg_;
-};
-
-const int kBlockSizes[] = {-1, 1, 2, 5, 64};
-const int kBlockSizeCount = GOOGLE_ARRAYSIZE(kBlockSizes);
-
-TEST(ObjCHelper, ParseSimple_BasicsSuccess) {
-  const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
-    {"", {}},
-    {"a", {"a"}},
-    {"a c", {"a c"}},
-    {" a c ", {"a c"}},
-    {"\ta c ", {"a c"}},
-    {"abc\n", {"abc"}},
-    {"abc\nd f", {"abc", "d f"}},
-    {"\n abc \n def \n\n", {"abc", "def"}},
-  };
-
-  for (const auto& test : tests) {
-    for (int i = 0; i < kBlockSizeCount; i++) {
-      io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]);
-      std::string err_str;
-      std::vector<std::string> lines;
-      TestLineCollector collector(&lines);
-      EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
-      EXPECT_EQ(lines, test.second);
-      EXPECT_TRUE(err_str.empty());
-    }
-  }
-}
-
-TEST(ObjCHelper, ParseSimple_DropsComments) {
-  const std::vector<std::pair<std::string, std::vector<std::string>>> tests = {
-    {"# nothing", {}},
-    {"#", {}},
-    {"##", {}},
-    {"\n# nothing\n", {}},
-    {"a # same line", {"a"}},
-    {"a # same line\n", {"a"}},
-    {"a\n# line\nc", {"a", "c"}},
-    {"# n o t # h i n g #", {}},
-    {"## n o # t h i n g #", {}},
-    {"a# n o t # h i n g #", {"a"}},
-    {"a\n## n o # t h i n g #", {"a"}},
-  };
-
-  for (const auto& test : tests) {
-    for (int i = 0; i < kBlockSizeCount; i++) {
-      io::ArrayInputStream input(test.first.data(), test.first.size(), kBlockSizes[i]);
-      std::string err_str;
-      std::vector<std::string> lines;
-      TestLineCollector collector(&lines);
-      EXPECT_TRUE(ParseSimpleStream(input, "dummy", &collector, &err_str));
-      EXPECT_EQ(lines, test.second);
-      EXPECT_TRUE(err_str.empty());
-    }
-  }
-}
-
-TEST(ObjCHelper, ParseSimple_RejectLines) {
-  const std::vector<std::tuple<std::string, std::string, int>> tests = {
-    std::make_tuple("a\nb\nc", "a", 1),
-    std::make_tuple("a\nb\nc", "b", 2),
-    std::make_tuple("a\nb\nc", "c", 3),
-    std::make_tuple("a\nb\nc\n", "c", 3),
-  };
-
-  for (const auto& test : tests) {
-    for (int i = 0; i < kBlockSizeCount; i++) {
-      io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(),
-                                 kBlockSizes[i]);
-      std::string err_str;
-      TestLineCollector collector(nullptr, &std::get<1>(test));
-      EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
-      std::string expected_err =
-        StrCat("error: dummy Line ", std::get<2>(test), ", Rejected '", std::get<1>(test), "'");
-      EXPECT_EQ(err_str, expected_err);
-    }
-  }
-}
-
-TEST(ObjCHelper, ParseSimple_RejectLinesNoMessage) {
-  const std::vector<std::tuple<std::string, std::string, int>> tests = {
-    std::make_tuple("a\nb\nc", "a", 1),
-    std::make_tuple("a\nb\nc", "b", 2),
-    std::make_tuple("a\nb\nc", "c", 3),
-    std::make_tuple("a\nb\nc\n", "c", 3),
-  };
-
-  for (const auto& test : tests) {
-    for (int i = 0; i < kBlockSizeCount; i++) {
-      io::ArrayInputStream input(std::get<0>(test).data(), std::get<0>(test).size(),
-                                 kBlockSizes[i]);
-      std::string err_str;
-      TestLineCollector collector(nullptr, &std::get<1>(test), true /* skip msg */);
-      EXPECT_FALSE(ParseSimpleStream(input, "dummy", &collector, &err_str));
-      std::string expected_err =
-        StrCat("error: dummy Line ", std::get<2>(test),
-               ", ConsumeLine failed without setting an error.");
-      EXPECT_EQ(err_str, expected_err);
-    }
-  }
-}
-
-// TODO(thomasvl): Should probably add some unittests for all the special cases
-// of name mangling (class name, field name, enum names).  Rather than doing
-// this with an ObjC test in the objectivec directory, we should be able to
-// use src/google/protobuf/compiler/importer* (like other tests) to support a
-// virtual file system to feed in protos, once we have the Descriptor tree, the
-// tests could use the helper methods for generating names and validate the
-// right things are happening.
-
 }  // namespace
 }  // namespace objectivec
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/parser.cc b/src/google/protobuf/compiler/parser.cc
index 5bd37d1..49ae6bd 100644
--- a/src/google/protobuf/compiler/parser.cc
+++ b/src/google/protobuf/compiler/parser.cc
@@ -34,35 +34,42 @@
 //
 // Recursive descent FTW.
 
-#include <google/protobuf/compiler/parser.h>
+#include "google/protobuf/compiler/parser.h"
 
 #include <float.h>
 
 #include <cstdint>
 #include <limits>
-#include <unordered_map>
-#include <unordered_set>
+#include <string>
+#include <tuple>
+#include <utility>
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/base/casts.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
-
-using internal::WireFormat;
-
 namespace {
 
-typedef std::unordered_map<std::string, FieldDescriptorProto::Type> TypeNameMap;
+using ::google::protobuf::internal::DownCast;
+
+using TypeNameMap =
+    absl::flat_hash_map<absl::string_view, FieldDescriptorProto::Type>;
 
 const TypeNameMap& GetTypeNameTable() {
   static auto* table = new auto([]() {
@@ -286,6 +293,16 @@
   }
 }
 
+bool Parser::TryConsumeInteger64(uint64_t max_value, uint64_t* output) {
+  if (LookingAtType(io::Tokenizer::TYPE_INTEGER) &&
+      io::Tokenizer::ParseInteger(input_->current().text, max_value,
+                                  output)) {
+    input_->Next();
+    return true;
+  }
+  return false;
+}
+
 bool Parser::ConsumeNumber(double* output, const char* error) {
   if (LookingAtType(io::Tokenizer::TYPE_FLOAT)) {
     *output = io::Tokenizer::ParseFloat(input_->current().text);
@@ -294,13 +311,19 @@
   } else if (LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
     // Also accept integers.
     uint64_t value = 0;
-    if (!io::Tokenizer::ParseInteger(input_->current().text,
+    if (io::Tokenizer::ParseInteger(input_->current().text,
                                      std::numeric_limits<uint64_t>::max(),
                                      &value)) {
+      *output = value;
+    } else if (input_->current().text[0] == '0') {
+      // octal or hexadecimal; don't bother parsing as float
+      AddError("Integer out of range.");
+      // We still return true because we did, in fact, parse a number.
+    } else if (!io::Tokenizer::TryParseFloat(input_->current().text, output)) {
+      // out of int range, and not valid float? 🤷
       AddError("Integer out of range.");
       // We still return true because we did, in fact, parse a number.
     }
-    *output = value;
     input_->Next();
     return true;
   } else if (LookingAt("inf")) {
@@ -387,13 +410,16 @@
   AddError(input_->current().line, input_->current().column, error);
 }
 
-void Parser::AddWarning(const std::string& warning) {
+void Parser::AddWarning(int line, int column, const std::string& warning) {
   if (error_collector_ != nullptr) {
-    error_collector_->AddWarning(input_->current().line,
-                                 input_->current().column, warning);
+    error_collector_->AddWarning(line, column, warning);
   }
 }
 
+void Parser::AddWarning(const std::string& warning) {
+  AddWarning(input_->current().line, input_->current().column, warning);
+}
+
 // -------------------------------------------------------------------
 
 Parser::LocationRecorder::LocationRecorder(Parser* parser)
@@ -572,7 +598,7 @@
     return false;
   }
 
-  std::set<int> used_values;
+  absl::flat_hash_set<int> used_values;
   bool has_duplicates = false;
   for (int i = 0; i < proto->value_size(); ++i) {
     const EnumValueDescriptorProto& enum_value = proto->value(i);
@@ -634,14 +660,17 @@
     root_location.RecordLegacyLocation(file,
                                        DescriptorPool::ErrorCollector::OTHER);
 
-    if (require_syntax_identifier_ || LookingAt("syntax")) {
+    if (require_syntax_identifier_ || LookingAt("syntax")
+    ) {
       if (!ParseSyntaxIdentifier(root_location)) {
         // Don't attempt to parse the file if we didn't recognize the syntax
         // identifier.
         return false;
       }
       // Store the syntax into the file.
-      if (file != nullptr) file->set_syntax(syntax_identifier_);
+      if (file != nullptr) {
+        file->set_syntax(syntax_identifier_);
+      }
     } else if (!stop_after_syntax_identifier_) {
       GOOGLE_LOG(WARNING) << "No syntax specified for the proto file: " << file->name()
                    << ". Please use 'syntax = \"proto2\";' "
@@ -678,9 +707,10 @@
 bool Parser::ParseSyntaxIdentifier(const LocationRecorder& parent) {
   LocationRecorder syntax_location(parent,
                                    FileDescriptorProto::kSyntaxFieldNumber);
-  DO(Consume(
-      "syntax",
-      "File must begin with a syntax statement, e.g. 'syntax = \"proto2\";'."));
+    DO(Consume("syntax",
+               "File must begin with a syntax statement, e.g. 'syntax = "
+               "\"proto2\";'."));
+
   DO(Consume("="));
   io::Tokenizer::Token syntax_token = input_->current();
   std::string syntax;
@@ -688,7 +718,6 @@
   DO(ConsumeEndOfDeclaration(";", &syntax_location));
 
   syntax_identifier_ = syntax;
-
   if (syntax != "proto2" && syntax != "proto3" &&
       !stop_after_syntax_identifier_) {
     AddError(syntax_token.line, syntax_token.column,
@@ -772,7 +801,7 @@
     //
     // We have to make sure the oneof names don't conflict with any other
     // field or oneof.
-    std::unordered_set<std::string> names;
+    absl::flat_hash_set<std::string> names;
     for (const auto& field : message->field()) {
       names.insert(field.name());
     }
@@ -797,7 +826,7 @@
         names.insert(oneof_name);
         field.set_oneof_index(message->oneof_decl_size());
         OneofDescriptorProto* oneof = message->add_oneof_decl();
-        oneof->set_name(oneof_name);
+        oneof->set_name(std::move(oneof_name));
       }
     }
   }
@@ -1084,7 +1113,7 @@
       AddError(name_token.line, name_token.column,
                "Group names must start with a capital letter.");
     }
-    LowerString(field->mutable_name());
+    absl::AsciiStrToLower(field->mutable_name());
 
     field->set_type_name(group->name());
     if (LookingAt("{")) {
@@ -1283,7 +1312,7 @@
       DO(ConsumeInteger64(max_value, &value,
                           "Expected integer for field default value."));
       // And stringify it again.
-      default_value->append(StrCat(value));
+      default_value->append(absl::StrCat(value));
       break;
     }
 
@@ -1306,24 +1335,24 @@
       DO(ConsumeInteger64(max_value, &value,
                           "Expected integer for field default value."));
       // And stringify it again.
-      default_value->append(StrCat(value));
+      default_value->append(absl::StrCat(value));
       break;
     }
 
     case FieldDescriptorProto::TYPE_FLOAT:
-    case FieldDescriptorProto::TYPE_DOUBLE:
+    case FieldDescriptorProto::TYPE_DOUBLE: {
       // These types can be negative.
       if (TryConsume("-")) {
         default_value->append("-");
       }
       // Parse the integer because we have to convert hex integers to decimal
       // floats.
-      double value;
+      double value = 0.0;
       DO(ConsumeNumber(&value, "Expected number."));
       // And stringify it again.
-      default_value->append(SimpleDtoa(value));
+      default_value->append(io::SimpleDtoa(value));
       break;
-
+    }
     case FieldDescriptorProto::TYPE_BOOL:
       if (TryConsume("true")) {
         default_value->assign("true");
@@ -1346,7 +1375,7 @@
 
     case FieldDescriptorProto::TYPE_BYTES:
       DO(ConsumeString(default_value, "Expected string."));
-      *default_value = CEscape(*default_value);
+      *default_value = absl::CEscape(*default_value);
       break;
 
     case FieldDescriptorProto::TYPE_ENUM:
@@ -1474,7 +1503,7 @@
   }
 
   UninterpretedOption* uninterpreted_option =
-      down_cast<UninterpretedOption*>(options->GetReflection()->AddMessage(
+      DownCast<UninterpretedOption*>(options->GetReflection()->AddMessage(
           options, uninterpreted_option_field));
 
   // Parse dot-separated name.
@@ -1546,23 +1575,26 @@
             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_t>(0 - value));
-        } else {
-          value_location.AddPath(
-              UninterpretedOption::kPositiveIntValueFieldNumber);
-          uninterpreted_option->set_positive_int_value(value);
+        if (TryConsumeInteger64(max_value, &value)) {
+          if (is_negative) {
+            value_location.AddPath(
+                UninterpretedOption::kNegativeIntValueFieldNumber);
+            uninterpreted_option->set_negative_int_value(
+                static_cast<int64_t>(0 - value));
+          } else {
+            value_location.AddPath(
+                UninterpretedOption::kPositiveIntValueFieldNumber);
+            uninterpreted_option->set_positive_int_value(value);
+          }
+          break;
         }
-        break;
+        // value too large for an integer; fall through below to treat as floating point
+        ABSL_FALLTHROUGH_INTENDED;
       }
 
       case io::Tokenizer::TYPE_FLOAT: {
         value_location.AddPath(UninterpretedOption::kDoubleValueFieldNumber);
-        double value;
+        double value = 0.0;
         DO(ConsumeNumber(&value, "Expected number."));
         uninterpreted_option->set_double_value(is_negative ? -value : value);
         break;
@@ -1723,11 +1755,23 @@
   }
 }
 
+bool Parser::ParseReservedName(std::string* name, const char* error_message) {
+  // Capture the position of the token, in case we have to report an
+  // error after it is consumed.
+  int line = input_->current().line;
+  int col = input_->current().column;
+  DO(ConsumeString(name, error_message));
+  if (!io::Tokenizer::IsIdentifier(*name)) {
+    AddWarning(line, col, absl::StrFormat("Reserved name \"%s\" is not a valid identifier.", *name));
+  }
+  return true;
+}
+
 bool Parser::ParseReservedNames(DescriptorProto* message,
                                 const LocationRecorder& parent_location) {
   do {
     LocationRecorder location(parent_location, message->reserved_name_size());
-    DO(ConsumeString(message->add_reserved_name(), "Expected field name."));
+    DO(ParseReservedName(message->add_reserved_name(), "Expected field name."));
   } while (TryConsume(","));
   DO(ConsumeEndOfDeclaration(";", &parent_location));
   return true;
@@ -1782,42 +1826,42 @@
   return true;
 }
 
-bool Parser::ParseReserved(EnumDescriptorProto* message,
-                           const LocationRecorder& message_location) {
+bool Parser::ParseReserved(EnumDescriptorProto* proto,
+                           const LocationRecorder& enum_location) {
   io::Tokenizer::Token start_token = input_->current();
   // Parse the declaration.
   DO(Consume("reserved"));
   if (LookingAtType(io::Tokenizer::TYPE_STRING)) {
-    LocationRecorder location(message_location,
+    LocationRecorder location(enum_location,
                               EnumDescriptorProto::kReservedNameFieldNumber);
     location.StartAt(start_token);
-    return ParseReservedNames(message, location);
+    return ParseReservedNames(proto, location);
   } else {
-    LocationRecorder location(message_location,
+    LocationRecorder location(enum_location,
                               EnumDescriptorProto::kReservedRangeFieldNumber);
     location.StartAt(start_token);
-    return ParseReservedNumbers(message, location);
+    return ParseReservedNumbers(proto, location);
   }
 }
 
-bool Parser::ParseReservedNames(EnumDescriptorProto* message,
+bool Parser::ParseReservedNames(EnumDescriptorProto* proto,
                                 const LocationRecorder& parent_location) {
   do {
-    LocationRecorder location(parent_location, message->reserved_name_size());
-    DO(ConsumeString(message->add_reserved_name(), "Expected enum value."));
+    LocationRecorder location(parent_location, proto->reserved_name_size());
+    DO(ParseReservedName(proto->add_reserved_name(), "Expected enum value."));
   } while (TryConsume(","));
   DO(ConsumeEndOfDeclaration(";", &parent_location));
   return true;
 }
 
-bool Parser::ParseReservedNumbers(EnumDescriptorProto* message,
+bool Parser::ParseReservedNumbers(EnumDescriptorProto* proto,
                                   const LocationRecorder& parent_location) {
   bool first = true;
   do {
-    LocationRecorder location(parent_location, message->reserved_range_size());
+    LocationRecorder location(parent_location, proto->reserved_range_size());
 
     EnumDescriptorProto::EnumReservedRange* range =
-        message->add_reserved_range();
+        proto->add_reserved_range();
     int start, end;
     io::Tokenizer::Token start_token;
     {
@@ -2395,33 +2439,27 @@
     const Message* descriptor,
     DescriptorPool::ErrorCollector::ErrorLocation location, int* line,
     int* column) const {
-  const std::pair<int, int>* result =
-      FindOrNull(location_map_, std::make_pair(descriptor, location));
-  if (result == nullptr) {
+  auto it = location_map_.find({descriptor, location});
+  if (it == location_map_.end()) {
     *line = -1;
     *column = 0;
     return false;
-  } else {
-    *line = result->first;
-    *column = result->second;
-    return true;
   }
+  std::tie(*line, *column) = it->second;
+  return true;
 }
 
 bool SourceLocationTable::FindImport(const Message* descriptor,
                                      const std::string& name, int* line,
                                      int* column) const {
-  const std::pair<int, int>* result =
-      FindOrNull(import_location_map_, std::make_pair(descriptor, name));
-  if (result == nullptr) {
+  auto it = import_location_map_.find({descriptor, name});
+  if (it == import_location_map_.end()) {
     *line = -1;
     *column = 0;
     return false;
-  } else {
-    *line = result->first;
-    *column = result->second;
-    return true;
   }
+  std::tie(*line, *column) = it->second;
+  return true;
 }
 
 void SourceLocationTable::Add(
diff --git a/src/google/protobuf/compiler/parser.h b/src/google/protobuf/compiler/parser.h
index d4eb763..80cc396 100644
--- a/src/google/protobuf/compiler/parser.h
+++ b/src/google/protobuf/compiler/parser.h
@@ -38,17 +38,17 @@
 #define GOOGLE_PROTOBUF_COMPILER_PARSER_H__
 
 #include <cstdint>
-#include <map>
 #include <string>
 #include <utility>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/repeated_field.h>
+#include "absl/container/flat_hash_map.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/repeated_field.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -71,6 +71,8 @@
 class PROTOBUF_EXPORT Parser {
  public:
   Parser();
+  Parser(const Parser&) = delete;
+  Parser& operator=(const Parser&) = delete;
   ~Parser();
 
   // Parse the entire input and construct a FileDescriptorProto representing
@@ -178,6 +180,9 @@
   // is greater than max_value, an error will be reported.
   bool ConsumeInteger64(uint64_t max_value, uint64_t* output,
                         const char* error);
+  // Try to consume a 64-bit integer and store its value in "output".  No
+  // error is reported on failure, allowing caller to consume token another way.
+  bool TryConsumeInteger64(uint64_t max_value, uint64_t* output);
   // 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);
@@ -211,6 +216,9 @@
   // of the current token.
   void AddError(const std::string& error);
 
+  // Invokes error_collector_->AddWarning(), if error_collector_ is not NULL.
+  void AddWarning(int line, int column, const std::string& warning);
+
   // Invokes error_collector_->AddWarning() with the line and column number
   // of the current token.
   void AddWarning(const std::string& warning);
@@ -392,6 +400,7 @@
                      const LocationRecorder& message_location);
   bool ParseReservedNames(DescriptorProto* message,
                           const LocationRecorder& parent_location);
+  bool ParseReservedName(std::string* name, const char* error_message);
   bool ParseReservedNumbers(DescriptorProto* message,
                             const LocationRecorder& parent_location);
   bool ParseReserved(EnumDescriptorProto* message,
@@ -545,8 +554,6 @@
   // the next element (See SourceCodeInfo.Location in descriptor.proto), when
   // ConsumeEndOfDeclaration() is called.
   std::vector<std::string> upcoming_detached_comments_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Parser);
 };
 
 // A table mapping (descriptor, ErrorLocation) pairs -- as reported by
@@ -584,12 +591,12 @@
   void Clear();
 
  private:
-  typedef std::map<
+  using LocationMap = absl::flat_hash_map<
       std::pair<const Message*, DescriptorPool::ErrorCollector::ErrorLocation>,
-      std::pair<int, int> >
-      LocationMap;
+      std::pair<int, int>>;
   LocationMap location_map_;
-  std::map<std::pair<const Message*, std::string>, std::pair<int, int> >
+  absl::flat_hash_map<std::pair<const Message*, std::string>,
+                      std::pair<int, int>>
       import_location_map_;
 };
 
@@ -597,6 +604,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_PARSER_H__
diff --git a/src/google/protobuf/compiler/parser_unittest.cc b/src/google/protobuf/compiler/parser_unittest.cc
index 2d681d9..91789f7 100644
--- a/src/google/protobuf/compiler/parser_unittest.cc
+++ b/src/google/protobuf/compiler/parser_unittest.cc
@@ -32,26 +32,27 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/compiler/parser.h>
+#include "google/protobuf/compiler/parser.h"
 
 #include <algorithm>
 #include <map>
 #include <memory>
 #include <vector>
 
-#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>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/any.pb.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/stubs/map_util.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/test_util2.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_custom_options.pb.h"
+#include "google/protobuf/unittest_import.pb.h"
+#include "google/protobuf/unittest_import_public.pb.h"
+#include "google/protobuf/wire_format.h"
 
 namespace google {
 namespace protobuf {
@@ -69,11 +70,11 @@
 
   // implements ErrorCollector ---------------------------------------
   void AddWarning(int line, int column, const std::string& message) override {
-    strings::SubstituteAndAppend(&warning_, "$0:$1: $2\n", line, column, message);
+    absl::SubstituteAndAppend(&warning_, "$0:$1: $2\n", line, column, message);
   }
 
   void AddError(int line, int column, const std::string& message) override {
-    strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message);
+    absl::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message);
   }
 };
 
@@ -147,6 +148,16 @@
     EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
   }
 
+  // Parse the text and expect that the given warnings are reported.
+  void ExpectHasWarnings(const char* text, const char* expected_warnings) {
+    SetupParser(text);
+    FileDescriptorProto file;
+    ASSERT_TRUE(parser_->Parse(input_.get(), &file));
+    EXPECT_EQ(io::Tokenizer::TYPE_END, input_->current().type);
+    ASSERT_EQ("", error_collector_.text_);
+    EXPECT_EQ(expected_warnings, error_collector_.warning_);
+  }
+
   // Same as above but does not expect that the parser parses the complete
   // input.
   void ExpectHasEarlyExitErrors(const char* text, const char* expected_errors) {
@@ -264,6 +275,7 @@
                   "song_name_1.") != std::string::npos);
 }
 
+
 // ===================================================================
 
 typedef ParserTest ParseMessageTest;
@@ -591,6 +603,56 @@
       "}");
 }
 
+TEST_F(ParseMessageTest, FieldOptionsSupportLargeDecimalLiteral) {
+  // decimal integer literal > uint64 max
+  ExpectParsesTo(
+      "import \"google/protobuf/descriptor.proto\";\n"
+      "extend google.protobuf.FieldOptions {\n"
+      "  optional double f = 10101;\n"
+      "}\n"
+      "message TestMessage {\n"
+      "  optional double a = 1 [default = 18446744073709551616];\n"
+      "  optional double b = 2 [default = -18446744073709551616];\n"
+      "  optional double c = 3 [(f) = 18446744073709551616];\n"
+      "  optional double d = 4 [(f) = -18446744073709551616];\n"
+      "}\n",
+
+      "dependency: \"google/protobuf/descriptor.proto\""
+      "extension {"
+      "  name: \"f\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 10101"
+      "  extendee: \"google.protobuf.FieldOptions\""
+      "}"
+      "message_type {"
+      "  name: \"TestMessage\""
+      "  field {"
+      "    name: \"a\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 1"
+      "    default_value: \"1.8446744073709552e+19\""
+      "  }"
+      "  field {"
+      "    name: \"b\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 2"
+      "    default_value: \"-1.8446744073709552e+19\""
+      "  }"
+      "  field {"
+      "    name: \"c\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 3"
+      "    options{"
+      "      uninterpreted_option{"
+      "        name{ name_part: \"f\" is_extension: true }"
+      "        double_value: 1.8446744073709552e+19"
+      "      }"
+      "    }"
+      "  }"
+      "  field {"
+      "    name: \"d\" label: LABEL_OPTIONAL type: TYPE_DOUBLE number: 4"
+      "    options{"
+      "      uninterpreted_option{"
+      "        name{ name_part: \"f\" is_extension: true }"
+      "        double_value: -1.8446744073709552e+19"
+      "      }"
+      "    }"
+      "  }"
+      "}");
+}
+
 TEST_F(ParseMessageTest, Oneof) {
   ExpectParsesTo(
       "message TestMessage {\n"
@@ -1674,6 +1736,17 @@
       "2:11: Expected enum value or number range.\n");
 }
 
+TEST_F(ParseErrorTest, EnumReservedInvalidIdentifier) {
+  ExpectHasWarnings(
+      R"pb(
+      enum TestEnum {
+        FOO = 1;
+        reserved "foo bar";
+      }
+      )pb",
+      "3:17: Reserved name \"foo bar\" is not a valid identifier.\n");
+}
+
 // -------------------------------------------------------------------
 // Reserved field number errors
 
@@ -1701,6 +1774,16 @@
       "1:11: Expected field name or number range.\n");
 }
 
+TEST_F(ParseErrorTest, ReservedInvalidIdentifier) {
+  ExpectHasWarnings(
+      R"pb(
+      message Foo {
+        reserved "foo bar";
+      }
+      )pb",
+      "2:17: Reserved name \"foo bar\" is not a valid identifier.\n");
+}
+
 TEST_F(ParseErrorTest, ReservedNegativeNumber) {
   ExpectHasErrors(
       "message Foo {\n"
@@ -1890,6 +1973,22 @@
       "2:32: Enum type \"Baz\" has no value named \"NO_SUCH_VALUE\".\n");
 }
 
+TEST_F(ParserValidationErrorTest, FieldDefaultIntegerOutOfRange) {
+  ExpectHasErrors(
+      "message Foo {\n"
+      "  optional double bar = 1 [default = 0x10000000000000000];\n"
+      "}\n",
+      "1:37: Integer out of range.\n");
+}
+
+TEST_F(ParserValidationErrorTest, FieldOptionOutOfRange) {
+  ExpectHasErrors(
+      "message Foo {\n"
+      "  optional double bar = 1 [foo = 0x10000000000000000];\n"
+      "}\n",
+      "1:33: Integer out of range.\n");
+}
+
 TEST_F(ParserValidationErrorTest, FileOptionNameError) {
   ExpectHasValidationErrors(
       "option foo = 5;",
@@ -2224,7 +2323,7 @@
   // need to link to a FileDecriptor, then output back to a proto. We'll
   // also need to give it the same name as the original.
   parsed.set_name(
-      TestUtil::MaybeTranslatePath("net/proto2/internal/unittest.proto"));
+      TestUtil::MaybeTranslatePath("third_party/protobuf/unittest.proto"));
   // We need the imported dependency before we can build our parsed proto
   const FileDescriptor* public_import =
       protobuf_unittest_import::PublicImportMessage::descriptor()->file();
@@ -2401,7 +2500,7 @@
     const std::string debug_string =
         descriptor->DebugStringWithOptions(debug_string_options);
 
-    for (int i = 0; i < GOOGLE_ARRAYSIZE(expected_comments); ++i) {
+    for (int i = 0; i < ABSL_ARRAYSIZE(expected_comments); ++i) {
       std::string::size_type found_pos =
           debug_string.find(expected_comments[i]);
       EXPECT_TRUE(found_pos != std::string::npos)
@@ -2677,8 +2776,8 @@
         return true;
       }
     } else {
-      std::pair<int, int> start_pos = FindOrDie(markers_, start_marker);
-      std::pair<int, int> end_pos = FindOrDie(markers_, end_marker);
+      std::pair<int, int> start_pos = markers_.at(start_marker);
+      std::pair<int, int> end_pos = markers_.at(end_marker);
 
       RepeatedField<int> expected_span;
       expected_span.Add(start_pos.first);
@@ -2709,7 +2808,7 @@
           } else {
             EXPECT_EQ(
                 expected_leading_detached_comments,
-                Join(iter->second->leading_detached_comments(), "\n"));
+                absl::StrJoin(iter->second->leading_detached_comments(), "\n"));
           }
 
           spans_.erase(iter);
@@ -2745,7 +2844,7 @@
 
   typedef std::multimap<SpanKey, const SourceCodeInfo::Location*> SpanMap;
   SpanMap spans_;
-  std::map<char, std::pair<int, int> > markers_;
+  absl::flat_hash_map<char, std::pair<int, int>> markers_;
   std::string text_without_markers_;
 
   void ExtractMarkers(const char* text) {
diff --git a/src/google/protobuf/compiler/php/BUILD.bazel b/src/google/protobuf/compiler/php/BUILD.bazel
new file mode 100644
index 0000000..3f8376f
--- /dev/null
+++ b/src/google/protobuf/compiler/php/BUILD.bazel
@@ -0,0 +1,59 @@
+################################################################################
+# Protocol Buffers Compiler - PHP code generator
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "names",
+    hdrs = ["names.h"],
+    srcs = ["names.cc"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/php",
+    visibility = ["//visibility:public"],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "php",
+    srcs = ["php_generator.cc"],
+    hdrs = ["php_generator.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/php",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+    ],
+    deps = [
+        ":names",
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/php/names.cc b/src/google/protobuf/compiler/php/names.cc
new file mode 100644
index 0000000..20e169e
--- /dev/null
+++ b/src/google/protobuf/compiler/php/names.cc
@@ -0,0 +1,144 @@
+// 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/php/names.h"
+
+#include <string>
+
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/plugin.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+
+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",
+    "global",       "goto",       "if",           "implements", "include",
+    "include_once", "instanceof", "insteadof",    "interface",  "isset",
+    "list",         "match",      "namespace",    "new",        "or",
+    "parent",       "print",      "private",      "protected",  "public",
+    "readonly",     "require",    "require_once", "return",     "self",
+    "static",       "switch",     "throw",        "trait",      "try",
+    "unset",        "use",        "var",          "while",      "xor",
+    "yield",        "int",        "float",        "bool",       "string",
+    "true",         "false",      "null",         "void",       "iterable"};
+const int kReservedNamesSize = 80;
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace php {
+
+bool IsReservedName(absl::string_view name) {
+  std::string lower(name);
+  std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
+  for (int i = 0; i < kReservedNamesSize; i++) {
+    if (lower == kReservedNames[i]) {
+      return true;
+    }
+  }
+  return false;
+}
+
+std::string ReservedNamePrefix(const std::string& classname,
+                               const FileDescriptor* file) {
+  if (IsReservedName(classname)) {
+    if (file->package() == "google.protobuf") {
+      return "GPB";
+    } else {
+      return "PB";
+    }
+  }
+
+  return "";
+}
+
+namespace {
+
+template <typename DescriptorType>
+std::string ClassNamePrefixImpl(const std::string& classname,
+                                const DescriptorType* desc) {
+  const std::string& prefix = (desc->file()->options()).php_class_prefix();
+  if (!prefix.empty()) {
+    return prefix;
+  }
+
+  return ReservedNamePrefix(classname, desc->file());
+}
+
+template <typename DescriptorType>
+std::string GeneratedClassNameImpl(const DescriptorType* desc) {
+  std::string classname = ClassNamePrefixImpl(desc->name(), desc) + desc->name();
+  const Descriptor* containing = desc->containing_type();
+  while (containing != NULL) {
+    classname = ClassNamePrefixImpl(containing->name(), desc) + containing->name()
+       + '\\' + classname;
+    containing = containing->containing_type();
+  }
+  return classname;
+}
+
+std::string GeneratedClassNameImpl(const ServiceDescriptor* desc) {
+  std::string classname = desc->name();
+  return ClassNamePrefixImpl(classname, desc) + classname;
+}
+
+}  // namespace
+
+std::string ClassNamePrefix(const std::string& classname,
+                            const Descriptor* desc) {
+  return ClassNamePrefixImpl(classname, desc);
+}
+std::string ClassNamePrefix(const std::string& classname,
+                            const EnumDescriptor* desc) {
+  return ClassNamePrefixImpl(classname, desc);
+}
+
+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);
+}
+
+}  // namespace php
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/compiler/php/names.h b/src/google/protobuf/compiler/php/names.h
new file mode 100644
index 0000000..cf4f942
--- /dev/null
+++ b/src/google/protobuf/compiler/php/names.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 GOOGLE_PROTOBUF_COMPILER_PHP_NAMES_H__
+#define GOOGLE_PROTOBUF_COMPILER_PHP_NAMES_H__
+
+#include "google/protobuf/descriptor.h"
+
+#include <string>
+
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace compiler {
+namespace php {
+
+// Whether or not a name is reserved.
+PROTOC_EXPORT bool IsReservedName(absl::string_view name);
+
+// A prefix to stick in front of reserved names to avoid clashes.
+PROTOC_EXPORT std::string ReservedNamePrefix(const std::string& classname,
+                                             const FileDescriptor* file);
+
+// A prefix to stick in front of all class names.
+PROTOC_EXPORT std::string ClassNamePrefix(const std::string& classname,
+                                          const Descriptor* desc);
+PROTOC_EXPORT std::string ClassNamePrefix(const std::string& classname,
+                                          const EnumDescriptor* desc);
+
+// To skip reserved keywords in php, some generated classname are prefixed.
+// Other code generators may need following API to figure out the actual
+// classname.
+PROTOC_EXPORT std::string GeneratedClassName(const Descriptor* desc);
+PROTOC_EXPORT std::string GeneratedClassName(const EnumDescriptor* desc);
+PROTOC_EXPORT std::string GeneratedClassName(const ServiceDescriptor* desc);
+
+}  // namespace php
+}  // namespace compiler
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_COMPILER_PHP_NAMES_H__
diff --git a/src/google/protobuf/compiler/php/php_generator.cc b/src/google/protobuf/compiler/php/php_generator.cc
index f3aa92f..5501c98 100644
--- a/src/google/protobuf/compiler/php/php_generator.cc
+++ b/src/google/protobuf/compiler/php/php_generator.cc
@@ -28,48 +28,36 @@
 // (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/php/php_generator.h>
-
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/plugin.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/strutil.h>
+#include "google/protobuf/compiler/php/php_generator.h"
 
 #include <sstream>
+#include <string>
 
-const std::string kDescriptorFile = "google/protobuf/descriptor.proto";
-const std::string kEmptyFile = "google/protobuf/empty.proto";
-const std::string kEmptyMetadataFile = "GPBMetadata/Google/Protobuf/GPBEmpty.php";
-const std::string kDescriptorMetadataFile =
+#include "google/protobuf/compiler/code_generator.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.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"
+
+constexpr absl::string_view kDescriptorFile =
+    "google/protobuf/descriptor.proto";
+constexpr absl::string_view kEmptyFile = "google/protobuf/empty.proto";
+constexpr absl::string_view kEmptyMetadataFile =
+    "GPBMetadata/Google/Protobuf/GPBEmpty.php";
+constexpr absl::string_view kDescriptorMetadataFile =
     "GPBMetadata/Google/Protobuf/Internal/Descriptor.php";
-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",
-    "finally",      "fn",         "for",          "foreach",    "function",
-    "global",       "goto",       "if",           "implements", "include",
-    "include_once", "instanceof", "insteadof",    "interface",  "isset",
-    "list",         "match",      "namespace",    "new",        "or",
-    "parent",       "print",      "private",      "protected",  "public",
-    "readonly",     "require",    "require_once", "return",     "self",
-    "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", "parent",
-    "self", "readonly"
-};
-const int kReservedNamesSize = 80;
+constexpr absl::string_view kDescriptorPackageName =
+    "Google\\Protobuf\\Internal";
+constexpr absl::string_view kValidConstantNames[] = {
+    "int",  "float", "bool",     "string", "true", "false",
+    "null", "void",  "iterable", "parent", "self", "readonly"};
 const int kValidConstantNamesSize = 12;
 const int kFieldSetter = 1;
 const int kFieldGetter = 2;
@@ -84,7 +72,7 @@
   bool is_descriptor = false;
   bool aggregate_metadata = false;
   bool gen_c_wkt = false;
-  std::set<std::string> aggregate_metadata_prefixes;
+  absl::flat_hash_set<std::string> aggregate_metadata_prefixes;
 };
 
 namespace {
@@ -121,68 +109,19 @@
 void GenerateServiceMethodDocComment(io::Printer* printer,
                               const MethodDescriptor* method);
 
-std::string ReservedNamePrefix(const std::string& classname,
-                                const FileDescriptor* file) {
-  bool is_reserved = false;
-
-  std::string lower = classname;
-  std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
-
-  for (int i = 0; i < kReservedNamesSize; i++) {
-    if (lower == kReservedNames[i]) {
-      is_reserved = true;
-      break;
-    }
-  }
-
-  if (is_reserved) {
-    if (file->package() == "google.protobuf") {
-      return "GPB";
-    } else {
-      return "PB";
-    }
-  }
-
-  return "";
-}
-
 template <typename DescriptorType>
 std::string DescriptorFullName(const DescriptorType* desc, bool is_internal) {
+  absl::string_view full_name = desc->full_name();
   if (is_internal) {
-    return StringReplace(desc->full_name(),
-                         "google.protobuf",
-                         "google.protobuf.internal", false);
-  } else {
-    return desc->full_name();
+    constexpr absl::string_view replace = "google.protobuf";
+    size_t index = full_name.find(replace);
+    if (index != std::string::npos) {
+      return absl::StrCat(full_name.substr(0, index),
+                          "google.protobuf.internal",
+                          full_name.substr(index + replace.size()));
+    }
   }
-}
-
-template <typename DescriptorType>
-std::string ClassNamePrefix(const std::string& classname,
-                            const DescriptorType* desc) {
-  const std::string& prefix = (desc->file()->options()).php_class_prefix();
-  if (!prefix.empty()) {
-    return prefix;
-  }
-
-  return ReservedNamePrefix(classname, desc->file());
-}
-
-template <typename DescriptorType>
-std::string GeneratedClassNameImpl(const DescriptorType* desc) {
-  std::string classname = ClassNamePrefix(desc->name(), desc) + desc->name();
-  const Descriptor* containing = desc->containing_type();
-  while (containing != NULL) {
-    classname = ClassNamePrefix(containing->name(), desc) + containing->name()
-       + '\\' + classname;
-    containing = containing->containing_type();
-  }
-  return classname;
-}
-
-std::string GeneratedClassNameImpl(const ServiceDescriptor* desc) {
-  std::string classname = desc->name();
-  return ClassNamePrefix(classname, desc) + classname;
+  return std::string(full_name);
 }
 
 template <typename DescriptorType>
@@ -196,31 +135,13 @@
   return ClassNamePrefix(classname, desc) + classname;
 }
 
-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]) {
-      return "PB";
-    }
-  }
-
-  return "";
-}
-
 std::string ConstantNamePrefix(const std::string& classname) {
   bool is_reserved = false;
 
   std::string lower = classname;
   std::transform(lower.begin(), lower.end(), lower.begin(), ::tolower);
 
-  for (int i = 0; i < kReservedNamesSize; i++) {
-    if (lower == kReservedNames[i]) {
-      is_reserved = true;
-      break;
-    }
-  }
+  is_reserved = IsReservedName(lower);
 
   for (int i = 0; i < kValidConstantNamesSize; i++) {
     if (lower == kValidConstantNames[i]) {
@@ -255,7 +176,7 @@
 
 template <typename DescriptorType>
 std::string FullClassName(const DescriptorType* desc, const Options& options) {
-  std::string classname = GeneratedClassNameImpl(desc);
+  std::string classname = GeneratedClassName(desc);
   std::string php_namespace = RootPhpNamespace(desc, options);
   if (!php_namespace.empty()) {
     return php_namespace + "\\" + classname;
@@ -281,9 +202,14 @@
   return classname;
 }
 
+std::string PhpNamePrefix(const std::string& classname) {
+  if (IsReservedName(classname)) return "PB";
+  return "";
+}
+
 std::string PhpName(const std::string& full_name, const Options& options) {
   if (options.is_descriptor) {
-    return kDescriptorPackageName;
+    return std::string(kDescriptorPackageName);
   }
 
   std::string segment;
@@ -294,7 +220,7 @@
       segment += full_name[i] + ('A' - 'a');
       cap_next_letter = false;
     } else if (full_name[i] == '.') {
-      result += ClassNamePrefix(segment) + segment + '\\';
+      result += PhpNamePrefix(segment) + segment + '\\';
       segment = "";
       cap_next_letter = true;
     } else {
@@ -302,7 +228,7 @@
       cap_next_letter = false;
     }
   }
-  result += ClassNamePrefix(segment) + segment;
+  result += PhpNamePrefix(segment) + segment;
   return result;
 }
 
@@ -334,22 +260,22 @@
                                       const Options& options) {
   const std::string& proto_file = file->name();
   int start_index = 0;
-  int first_index = proto_file.find_first_of("/", start_index);
+  int first_index = proto_file.find_first_of('/', start_index);
   std::string result = "";
   std::string segment = "";
 
   if (proto_file == kEmptyFile) {
-    return kEmptyMetadataFile;
+    return std::string(kEmptyMetadataFile);
   }
   if (options.is_descriptor) {
-    return kDescriptorMetadataFile;
+    return std::string(kDescriptorMetadataFile);
   }
 
   // Append directory name.
   std::string file_no_suffix;
-  int lastindex = proto_file.find_last_of(".");
+  int lastindex = proto_file.find_last_of('.');
   if (proto_file == kEmptyFile) {
-    return kEmptyMetadataFile;
+    return std::string(kEmptyMetadataFile);
   } else {
     file_no_suffix = proto_file.substr(0, lastindex);
   }
@@ -371,12 +297,12 @@
           file_no_suffix.substr(start_index, first_index - start_index), true);
       result += ReservedNamePrefix(segment, file) + segment + "/";
       start_index = first_index + 1;
-      first_index = file_no_suffix.find_first_of("/", start_index);
+      first_index = file_no_suffix.find_first_of('/', start_index);
     }
   }
 
   // Append file name.
-  int file_name_start = file_no_suffix.find_last_of("/");
+  int file_name_start = file_no_suffix.find_last_of('/');
   if (file_name_start == std::string::npos) {
     file_name_start = 0;
   } else {
@@ -503,7 +429,7 @@
   }
   if (field->is_repeated()) {
     // accommodate for edge case with multiple types.
-    size_t start_pos = type.find("|");
+    size_t start_pos = type.find('|');
     if (start_pos != std::string::npos) {
       type.replace(start_pos, 1, ">|array<");
     }
@@ -763,8 +689,8 @@
         "$arr = GPBUtil::checkMapField($var, "
         "\\Google\\Protobuf\\Internal\\GPBType::^key_type^, "
         "\\Google\\Protobuf\\Internal\\GPBType::^value_type^",
-        "key_type", ToUpper(key->type_name()),
-        "value_type", ToUpper(value->type_name()));
+        "key_type", absl::AsciiStrToUpper(key->type_name()),
+        "value_type", absl::AsciiStrToUpper(value->type_name()));
     if (value->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       printer->Print(
           ", \\^class_name^);\n",
@@ -782,7 +708,7 @@
     printer->Print(
         "$arr = GPBUtil::checkRepeatedField($var, "
         "\\Google\\Protobuf\\Internal\\GPBType::^type^",
-        "type", ToUpper(field->type_name()));
+        "type", absl::AsciiStrToUpper(field->type_name()));
     if (field->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
       printer->Print(
           ", \\^class_name^);\n",
@@ -912,9 +838,9 @@
           "->map('^field^', \\Google\\Protobuf\\Internal\\GPBType::^key^, "
           "\\Google\\Protobuf\\Internal\\GPBType::^value^, ^number^^other^)\n",
           "field", field->name(),
-          "key", ToUpper(key->type_name()),
-          "value", ToUpper(val->type_name()),
-          "number", StrCat(field->number()),
+          "key", absl::AsciiStrToUpper(key->type_name()),
+          "value", absl::AsciiStrToUpper(val->type_name()),
+          "number", absl::StrCat(field->number()),
           "other", EnumOrMessageSuffix(val, true));
     } else if (!field->real_containing_oneof()) {
       printer->Print(
@@ -922,8 +848,8 @@
           "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
           "field", field->name(),
           "label", LabelForField(field),
-          "type", ToUpper(field->type_name()),
-          "number", StrCat(field->number()),
+          "type", absl::AsciiStrToUpper(field->type_name()),
+          "number", absl::StrCat(field->number()),
           "other", EnumOrMessageSuffix(field, true));
     }
   }
@@ -940,8 +866,8 @@
           "->value('^field^', "
           "\\Google\\Protobuf\\Internal\\GPBType::^type^, ^number^^other^)\n",
           "field", field->name(),
-          "type", ToUpper(field->type_name()),
-          "number", StrCat(field->number()),
+          "type", absl::AsciiStrToUpper(field->type_name()),
+          "number", absl::StrCat(field->number()),
           "other", EnumOrMessageSuffix(field, true));
     }
     printer->Print("->finish()\n");
@@ -1068,9 +994,10 @@
 
 static void AnalyzeDependencyForFile(
     const FileDescriptor* file,
-    std::set<const FileDescriptor*>* nodes_without_dependency,
-    std::map<const FileDescriptor*, std::set<const FileDescriptor*>>* deps,
-    std::map<const FileDescriptor*, int>* dependency_count) {
+    absl::flat_hash_set<const FileDescriptor*>* nodes_without_dependency,
+    absl::flat_hash_map<const FileDescriptor*,
+                        absl::flat_hash_set<const FileDescriptor*>>* deps,
+    absl::flat_hash_map<const FileDescriptor*, int>* dependency_count) {
   int count = file->dependency_count();
   for (int i = 0; i < file->dependency_count(); i++) {
       const FileDescriptor* dependency = file->dependency(i);
@@ -1090,7 +1017,7 @@
         continue;
       }
       if (deps->find(dependency) == deps->end()) {
-        (*deps)[dependency] = std::set<const FileDescriptor*>();
+        (*deps)[dependency] = {};
       }
       (*deps)[dependency].insert(file);
       AnalyzeDependencyForFile(
@@ -1106,7 +1033,7 @@
     has_aggregate_metadata_prefix = true;
   } else {
     for (const auto& prefix : options.aggregate_metadata_prefixes) {
-      if (HasPrefixString(file->package(), prefix)) {
+      if (absl::StartsWith(file->package(), prefix)) {
         has_aggregate_metadata_prefix = true;
         break;
       }
@@ -1126,9 +1053,11 @@
       "}\n");
 
   // Sort files according to dependency
-  std::map<const FileDescriptor*, std::set<const FileDescriptor*>> deps;
-  std::map<const FileDescriptor*, int> dependency_count;
-  std::set<const FileDescriptor*> nodes_without_dependency;
+  absl::flat_hash_map<const FileDescriptor*,
+                      absl::flat_hash_set<const FileDescriptor*>>
+      deps;
+  absl::flat_hash_map<const FileDescriptor*, int> dependency_count;
+  absl::flat_hash_set<const FileDescriptor*> nodes_without_dependency;
   FileDescriptorSet sorted_file_set;
 
   AnalyzeDependencyForFile(
@@ -1235,7 +1164,7 @@
 }
 
 std::string FilenameToClassname(const std::string& filename) {
-  int lastindex = filename.find_last_of(".");
+  int lastindex = filename.find_last_of('.');
   std::string result = filename.substr(0, lastindex);
   for (int i = 0; i < result.size(); i++) {
     if (result[i] == '/') {
@@ -1255,7 +1184,7 @@
   GenerateHead(file, &printer);
 
   std::string fullname = FilenameToClassname(filename);
-  int lastindex = fullname.find_last_of("\\");
+  int lastindex = fullname.find_last_of('\\');
 
   if (lastindex != std::string::npos) {
     printer.Print(
@@ -1310,7 +1239,7 @@
   Outdent(&printer);
   printer.Print("}\n");
   printer.Print("class_exists(^new^::class);\n",
-      "new", GeneratedClassNameImpl(desc));
+      "new", GeneratedClassName(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, options),
@@ -1367,7 +1296,7 @@
   GenerateHead(file, &printer);
 
   std::string fullname = FilenameToClassname(filename);
-  int lastindex = fullname.find_last_of("\\");
+  int lastindex = fullname.find_last_of('\\');
 
   if (lastindex != std::string::npos) {
     printer.Print(
@@ -1467,7 +1396,7 @@
   Outdent(&printer);
   printer.Print("}\n\n");
 
-  // write legacy file for backwards compatibility with nested messages and enums
+  // write legacy alias for backwards compatibility with nested messages and enums
   if (en->containing_type() != NULL) {
     printer.Print(
         "// Adding a class alias for backwards compatibility with the previous class name.\n");
@@ -1475,7 +1404,6 @@
         "class_alias(^new^::class, \\^old^::class);\n\n",
         "new", fullname,
         "old", LegacyFullClassName(en, options));
-    LegacyGenerateClassFile(file, en, options, generator_context);
   }
 
   // Write legacy file for backwards compatibility with "readonly" keywword
@@ -1509,7 +1437,7 @@
   GenerateHead(file, &printer);
 
   std::string fullname = FilenameToClassname(filename);
-  int lastindex = fullname.find_last_of("\\");
+  int lastindex = fullname.find_last_of('\\');
 
   if (lastindex != std::string::npos) {
     printer.Print(
@@ -1595,7 +1523,7 @@
   Outdent(&printer);
   printer.Print("}\n\n");
 
-  // write legacy file for backwards compatibility with nested messages and enums
+  // write legacy alias for backwards compatibility with nested messages and enums
   if (message->containing_type() != NULL) {
     printer.Print(
         "// Adding a class alias for backwards compatibility with the previous class name.\n");
@@ -1603,7 +1531,6 @@
         "class_alias(^new^::class, \\^old^::class);\n\n",
         "new", fullname,
         "old", LegacyFullClassName(message, options));
-    LegacyGenerateClassFile(file, message, options, generator_context);
   }
 
   // Write legacy file for backwards compatibility with "readonly" keywword
@@ -1640,7 +1567,7 @@
   GenerateHead(file, &printer);
 
   std::string fullname = FilenameToClassname(filename);
-  int lastindex = fullname.find_last_of("\\");
+  int lastindex = fullname.find_last_of('\\');
 
   if (!file->options().php_namespace().empty() ||
       (!file->options().has_php_namespace() && !file->package().empty()) ||
@@ -1751,7 +1678,7 @@
     // HTML-escape them so that they don't accidentally close the doc comment.
     comments = EscapePhpdoc(comments);
 
-    std::vector<std::string> lines = Split(comments, "\n", true);
+    std::vector<std::string> lines = absl::StrSplit(comments, "\n", absl::SkipEmpty());
     while (!lines.empty() && lines.back().empty()) {
       lines.pop_back();
     }
@@ -1950,17 +1877,13 @@
 }
 
 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;
+  return absl::StrReplaceAll(file->name(), {{".", "_"}, {"/", "_"}});
 }
 
 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);
+  std::string c_name = absl::StrReplaceAll(desc->full_name(), {{".", "_"}});
+  std::string php_name =
+      absl::StrReplaceAll(FullClassName(desc, Options()), {{"\\", "\\\\"}});
   printer->Print(
       "/* $c_name$ */\n"
       "\n"
@@ -2043,10 +1966,9 @@
 }
 
 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);
+  std::string c_name = absl::StrReplaceAll(message->full_name(), {{".", "_"}});
+  std::string php_name =
+      absl::StrReplaceAll(FullClassName(message, Options()), {{"\\", "\\\\"}});
   printer->Print(
       "/* $c_name$ */\n"
       "\n"
@@ -2196,8 +2118,7 @@
 }
 
 void GenerateEnumCInit(const EnumDescriptor* desc, io::Printer* printer) {
-  std::string c_name = desc->full_name();
-  c_name = StringReplace(c_name, ".", "_", true);
+  std::string c_name = absl::StrReplaceAll(desc->full_name(), {{".", "_"}});
 
   printer->Print(
       "  $c_name$_ModuleInit();\n",
@@ -2205,8 +2126,7 @@
 }
 
 void GenerateCInit(const Descriptor* message, io::Printer* printer) {
-  std::string c_name = message->full_name();
-  c_name = StringReplace(c_name, ".", "_", true);
+  std::string c_name = absl::StrReplaceAll(message->full_name(), {{".", "_"}});
 
   printer->Print(
       "  $c_name$_ModuleInit();\n",
@@ -2248,8 +2168,9 @@
     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);
+        absl::StrReplaceAll(metadata_classname, {{"\\", "_"}});
+    metadata_classname =
+        absl::StrReplaceAll(metadata_classname, {{"\\", "\\\\"}});
     FileDescriptorProto file_proto;
     file->CopyTo(&file_proto);
     std::string serialized;
@@ -2267,7 +2188,7 @@
 
     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("'$ch$', ", "ch", absl::CEscape(serialized.substr(i, 1)));
       }
       printer.Print("\n");
     }
@@ -2330,7 +2251,7 @@
     std::string metadata_filename = GeneratedMetadataFileName(file, Options());
     std::string metadata_classname = FilenameToClassname(metadata_filename);
     std::string metadata_c_name =
-        StringReplace(metadata_classname, "\\", "_", true);
+        absl::StrReplaceAll(metadata_classname, {{"\\", "_"}});
     printer.Print(
         "  $metadata_c_name$_ModuleInit();\n",
         "metadata_c_name", metadata_c_name);
@@ -2348,18 +2269,6 @@
 
 }  // 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,
@@ -2394,11 +2303,11 @@
                             std::string* error) const {
   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")) {
+  for (const auto& option : absl::StrSplit(parameter, ",", absl::SkipEmpty())) {
+    const std::vector<std::string> option_pair = absl::StrSplit(option, "=", absl::SkipEmpty());
+    if (absl::StartsWith(option_pair[0], "aggregate_metadata")) {
       options.aggregate_metadata = true;
-      for (const auto& prefix : Split(option_pair[1], "#", false)) {
+      for (const auto& prefix : absl::StrSplit(option_pair[1], "#", absl::AllowEmpty())) {
         options.aggregate_metadata_prefixes.emplace(prefix);
         GOOGLE_LOG(INFO) << prefix;
       }
diff --git a/src/google/protobuf/compiler/php/php_generator.h b/src/google/protobuf/compiler/php/php_generator.h
index 17cb59c..2729b4a 100644
--- a/src/google/protobuf/compiler/php/php_generator.h
+++ b/src/google/protobuf/compiler/php/php_generator.h
@@ -31,12 +31,13 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
 #define GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/php/names.h"
+#include "google/protobuf/descriptor.h"
 
 #include <string>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -70,13 +71,6 @@
       std::string* error) const;
 };
 
-// To skip reserved keywords in php, some generated classname are prefixed.
-// Other code generators may need following API to figure out the actual
-// classname.
-PROTOC_EXPORT std::string GeneratedClassName(const Descriptor* desc);
-PROTOC_EXPORT std::string GeneratedClassName(const EnumDescriptor* desc);
-PROTOC_EXPORT std::string GeneratedClassName(const ServiceDescriptor* desc);
-
 inline bool IsWrapperType(const FieldDescriptor* descriptor) {
   return descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE &&
       descriptor->message_type()->file()->name() == "google/protobuf/wrappers.proto";
@@ -87,6 +81,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_PHP_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/plugin.cc b/src/google/protobuf/compiler/plugin.cc
index 0a32384..76f4f27 100644
--- a/src/google/protobuf/compiler/plugin.cc
+++ b/src/google/protobuf/compiler/plugin.cc
@@ -30,25 +30,23 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <google/protobuf/compiler/plugin.h>
+#include "google/protobuf/compiler/plugin.h"
 
 #include <iostream>
-#include <set>
-
 #ifdef _WIN32
 #include <fcntl.h>
 #else
 #include <unistd.h>
 #endif
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/compiler/plugin.pb.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/compiler/plugin.pb.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
 
 
 namespace google {
diff --git a/src/google/protobuf/compiler/plugin.h b/src/google/protobuf/compiler/plugin.h
index 611713e..388f51a 100644
--- a/src/google/protobuf/compiler/plugin.h
+++ b/src/google/protobuf/compiler/plugin.h
@@ -65,7 +65,7 @@
 #include <string>
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -91,6 +91,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_PLUGIN_H__
diff --git a/src/google/protobuf/compiler/plugin.pb.cc b/src/google/protobuf/compiler/plugin.pb.cc
index 8f8d83f..f77a0e3 100644
--- a/src/google/protobuf/compiler/plugin.pb.cc
+++ b/src/google/protobuf/compiler/plugin.pb.cc
@@ -1,25 +1,23 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/compiler/plugin.proto
 
-#include <google/protobuf/compiler/plugin.pb.h>
+#include "google/protobuf/compiler/plugin.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
 PROTOBUF_CONSTEXPR Version::Version(
@@ -31,14 +29,15 @@
   , /*decltype(_impl_.minor_)*/0
   , /*decltype(_impl_.patch_)*/0} {}
 struct VersionDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR VersionDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR VersionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~VersionDefaultTypeInternal() {}
   union {
     Version _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 VersionDefaultTypeInternal _Version_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 VersionDefaultTypeInternal _Version_default_instance_;
 PROTOBUF_CONSTEXPR CodeGeneratorRequest::CodeGeneratorRequest(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -48,14 +47,15 @@
   , /*decltype(_impl_.parameter_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.compiler_version_)*/nullptr} {}
 struct CodeGeneratorRequestDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR CodeGeneratorRequestDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR CodeGeneratorRequestDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~CodeGeneratorRequestDefaultTypeInternal() {}
   union {
     CodeGeneratorRequest _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorRequestDefaultTypeInternal _CodeGeneratorRequest_default_instance_;
 PROTOBUF_CONSTEXPR CodeGeneratorResponse_File::CodeGeneratorResponse_File(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -65,146 +65,180 @@
   , /*decltype(_impl_.content_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.generated_code_info_)*/nullptr} {}
 struct CodeGeneratorResponse_FileDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR CodeGeneratorResponse_FileDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR CodeGeneratorResponse_FileDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~CodeGeneratorResponse_FileDefaultTypeInternal() {}
   union {
     CodeGeneratorResponse_File _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponse_FileDefaultTypeInternal _CodeGeneratorResponse_File_default_instance_;
 PROTOBUF_CONSTEXPR CodeGeneratorResponse::CodeGeneratorResponse(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}
   , /*decltype(_impl_.file_)*/{}
   , /*decltype(_impl_.error_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
-  , /*decltype(_impl_.supported_features_)*/uint64_t{0u}} {}
+  , /*decltype(_impl_.supported_features_)*/::uint64_t{0u}} {}
 struct CodeGeneratorResponseDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR CodeGeneratorResponseDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR CodeGeneratorResponseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~CodeGeneratorResponseDefaultTypeInternal() {}
   union {
     CodeGeneratorResponse _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 CodeGeneratorResponseDefaultTypeInternal _CodeGeneratorResponse_default_instance_;
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fcompiler_2fplugin_2eproto[4];
 static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto[1];
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.major_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.minor_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.patch_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.suffix_),
-  1,
-  2,
-  3,
-  0,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.file_to_generate_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.parameter_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.proto_file_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.compiler_version_),
-  ~0u,
-  0,
-  ~0u,
-  1,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.insertion_point_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.content_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.generated_code_info_),
-  0,
-  1,
-  2,
-  3,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.error_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.supported_features_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.file_),
-  0,
-  1,
-  ~0u,
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.major_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.minor_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.patch_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::Version, _impl_.suffix_),
+    1,
+    2,
+    3,
+    0,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.file_to_generate_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.parameter_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.proto_file_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest, _impl_.compiler_version_),
+    ~0u,
+    0,
+    ~0u,
+    1,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.insertion_point_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.content_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File, _impl_.generated_code_info_),
+    0,
+    1,
+    2,
+    3,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.error_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.supported_features_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse, _impl_.file_),
+    0,
+    1,
+    ~0u,
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, 10, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::Version)},
-  { 14, 24, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)},
-  { 28, 38, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)},
-  { 42, 51, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, 12, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::Version)},
+        { 16, 28, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest)},
+        { 32, 44, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File)},
+        { 48, 59, -1, sizeof(::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::compiler::_Version_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorRequest_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_File_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::compiler::_CodeGeneratorResponse_default_instance_._instance,
 };
-
-const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
-  "\n%google/protobuf/compiler/plugin.proto\022"
-  "\030google.protobuf.compiler\032 google/protob"
-  "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030"
-  "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s"
-  "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020"
-  "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001("
-  "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf."
-  "FileDescriptorProto\022;\n\020compiler_version\030"
-  "\003 \001(\0132!.google.protobuf.compiler.Version"
-  "\"\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\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\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 ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] = {
-  &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
+const char descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+    "\n%google/protobuf/compiler/plugin.proto\022"
+    "\030google.protobuf.compiler\032 google/protob"
+    "uf/descriptor.proto\"F\n\007Version\022\r\n\005major\030"
+    "\001 \001(\005\022\r\n\005minor\030\002 \001(\005\022\r\n\005patch\030\003 \001(\005\022\016\n\006s"
+    "uffix\030\004 \001(\t\"\272\001\n\024CodeGeneratorRequest\022\030\n\020"
+    "file_to_generate\030\001 \003(\t\022\021\n\tparameter\030\002 \001("
+    "\t\0228\n\nproto_file\030\017 \003(\0132$.google.protobuf."
+    "FileDescriptorProto\022;\n\020compiler_version\030"
+    "\003 \001(\0132!.google.protobuf.compiler.Version"
+    "\"\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\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\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once;
+static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_deps[1] =
+    {
+        &::descriptor_table_google_2fprotobuf_2fdescriptor_2eproto,
+};
+static ::absl::once_flag descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto = {
-    false, false, 773, descriptor_table_protodef_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fcompiler_2fplugin_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fcompiler_2fplugin_2eproto(&descriptor_table_google_2fprotobuf_2fcompiler_2fplugin_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::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() {
@@ -220,20 +254,24 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_NONE;
 constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::FEATURE_PROTO3_OPTIONAL;
 constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MIN;
 constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse::Feature_MAX;
 constexpr int CodeGeneratorResponse::Feature_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 // ===================================================================
 
 class Version::_Internal {
  public:
   using HasBits = decltype(std::declval<Version>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(Version, _impl_._has_bits_);
   static void set_has_major(HasBits* has_bits) {
     (*has_bits)[0] |= 2u;
   }
@@ -270,12 +308,12 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.suffix_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_suffix()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.suffix_.Set(from._internal_suffix(), 
       _this->GetArenaForAllocation());
   }
   ::memcpy(&_impl_.major_, &from._impl_.major_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.patch_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.patch_) -
     reinterpret_cast<char*>(&_impl_.major_)) + sizeof(_impl_.patch_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.Version)
 }
@@ -318,7 +356,7 @@
 
 void Version::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.Version)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -327,7 +365,7 @@
     _impl_.suffix_.ClearNonDefaultToEmpty();
   }
   if (cached_has_bits & 0x0000000eu) {
-    ::memset(&_impl_.major_, 0, static_cast<size_t>(
+    ::memset(&_impl_.major_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.patch_) -
         reinterpret_cast<char*>(&_impl_.major_)) + sizeof(_impl_.patch_));
   }
@@ -336,50 +374,55 @@
 }
 
 const char* Version::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional int32 major = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_major(&has_bits);
           _impl_.major_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 minor = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_minor(&has_bits);
           _impl_.minor_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 patch = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _Internal::set_has_patch(&has_bits);
           _impl_.patch_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string suffix = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           auto str = _internal_mutable_suffix();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.Version.suffix");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -405,10 +448,11 @@
 #undef CHK_
 }
 
-uint8_t* Version::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Version::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.Version)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -448,11 +492,12 @@
   return target;
 }
 
-size_t Version::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version)
-  size_t total_size = 0;
+::size_t Version::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.Version)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -494,9 +539,10 @@
 void Version::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Version*>(&to_msg);
   auto& from = static_cast<const Version&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.Version)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -548,16 +594,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Version::GetMetadata() const {
+
   return ::_pbi::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]);
 }
-
 // ===================================================================
 
 class CodeGeneratorRequest::_Internal {
  public:
   using HasBits = decltype(std::declval<CodeGeneratorRequest>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(CodeGeneratorRequest, _impl_._has_bits_);
   static void set_has_parameter(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -596,11 +644,11 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.parameter_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_parameter()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.parameter_.Set(from._internal_parameter(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_compiler_version()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.compiler_version_ = new ::PROTOBUF_NAMESPACE_ID::compiler::Version(*from._impl_.compiler_version_);
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorRequest)
@@ -647,7 +695,7 @@
 
 void CodeGeneratorRequest::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorRequest)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -668,15 +716,16 @@
 }
 
 const char* CodeGeneratorRequest::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated string file_to_generate = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -688,32 +737,35 @@
             #endif  // !NDEBUG
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string parameter = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_parameter();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorRequest.parameter");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.compiler.Version compiler_version = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr = ctx->ParseMessage(_internal_mutable_compiler_version(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.FileDescriptorProto proto_file = 15;
       case 15:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 122)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -721,8 +773,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -748,10 +801,11 @@
 #undef CHK_
 }
 
-uint8_t* CodeGeneratorRequest::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* CodeGeneratorRequest::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorRequest)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated string file_to_generate = 1;
@@ -798,11 +852,12 @@
   return target;
 }
 
-size_t CodeGeneratorRequest::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest)
-  size_t total_size = 0;
+::size_t CodeGeneratorRequest::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorRequest)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -851,9 +906,10 @@
 void CodeGeneratorRequest::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<CodeGeneratorRequest*>(&to_msg);
   auto& from = static_cast<const CodeGeneratorRequest&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorRequest)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.file_to_generate_.MergeFrom(from._impl_.file_to_generate_);
@@ -900,16 +956,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorRequest::GetMetadata() const {
+
   return ::_pbi::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]);
 }
-
 // ===================================================================
 
 class CodeGeneratorResponse_File::_Internal {
  public:
   using HasBits = decltype(std::declval<CodeGeneratorResponse_File>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse_File, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -955,7 +1013,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
@@ -963,7 +1021,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.insertion_point_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_insertion_point()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.insertion_point_.Set(from._internal_insertion_point(), 
       _this->GetArenaForAllocation());
   }
@@ -971,11 +1029,11 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.content_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_content()) {
+  if ((from._impl_._has_bits_[0] & 0x00000004u) != 0) {
     _this->_impl_.content_.Set(from._internal_content(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_generated_code_info()) {
+  if ((from._impl_._has_bits_[0] & 0x00000008u) != 0) {
     _this->_impl_.generated_code_info_ = new ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo(*from._impl_.generated_code_info_);
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.compiler.CodeGeneratorResponse.File)
@@ -1030,7 +1088,7 @@
 
 void CodeGeneratorResponse_File::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse.File)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1055,55 +1113,60 @@
 }
 
 const char* CodeGeneratorResponse_File::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string insertion_point = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_insertion_point();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string content = 15;
       case 15:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 122)) {
           auto str = _internal_mutable_content();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.File.content");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
       case 16:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 130)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 130)) {
           ptr = ctx->ParseMessage(_internal_mutable_generated_code_info(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1129,10 +1192,11 @@
 #undef CHK_
 }
 
-uint8_t* CodeGeneratorResponse_File::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* CodeGeneratorResponse_File::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse.File)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -1181,11 +1245,12 @@
   return target;
 }
 
-size_t CodeGeneratorResponse_File::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File)
-  size_t total_size = 0;
+::size_t CodeGeneratorResponse_File::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse.File)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1233,9 +1298,10 @@
 void CodeGeneratorResponse_File::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<CodeGeneratorResponse_File*>(&to_msg);
   auto& from = static_cast<const CodeGeneratorResponse_File&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse.File)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -1290,16 +1356,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse_File::GetMetadata() const {
+
   return ::_pbi::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]);
 }
-
 // ===================================================================
 
 class CodeGeneratorResponse::_Internal {
  public:
   using HasBits = decltype(std::declval<CodeGeneratorResponse>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(CodeGeneratorResponse, _impl_._has_bits_);
   static void set_has_error(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -1329,7 +1397,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.error_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_error()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.error_.Set(from._internal_error(), 
       _this->GetArenaForAllocation());
   }
@@ -1346,7 +1414,7 @@
     , /*decltype(_impl_._cached_size_)*/{}
     , decltype(_impl_.file_){arena}
     , decltype(_impl_.error_){}
-    , decltype(_impl_.supported_features_){uint64_t{0u}}
+    , decltype(_impl_.supported_features_){::uint64_t{0u}}
   };
   _impl_.error_.InitDefault();
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -1375,7 +1443,7 @@
 
 void CodeGeneratorResponse::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.compiler.CodeGeneratorResponse)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1384,42 +1452,45 @@
   if (cached_has_bits & 0x00000001u) {
     _impl_.error_.ClearNonDefaultToEmpty();
   }
-  _impl_.supported_features_ = uint64_t{0u};
+  _impl_.supported_features_ = ::uint64_t{0u};
   _impl_._has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* CodeGeneratorResponse::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string error = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_error();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.compiler.CodeGeneratorResponse.error");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional uint64 supported_features = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_supported_features(&has_bits);
           _impl_.supported_features_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.compiler.CodeGeneratorResponse.File file = 15;
       case 15:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 122)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 122)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1427,8 +1498,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<122>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1454,10 +1526,11 @@
 #undef CHK_
 }
 
-uint8_t* CodeGeneratorResponse::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* CodeGeneratorResponse::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.compiler.CodeGeneratorResponse)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -1493,11 +1566,12 @@
   return target;
 }
 
-size_t CodeGeneratorResponse::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse)
-  size_t total_size = 0;
+::size_t CodeGeneratorResponse::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.compiler.CodeGeneratorResponse)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1536,9 +1610,10 @@
 void CodeGeneratorResponse::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<CodeGeneratorResponse*>(&to_msg);
   auto& from = static_cast<const CodeGeneratorResponse&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.compiler.CodeGeneratorResponse)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.file_.MergeFrom(from._impl_.file_);
@@ -1581,11 +1656,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata CodeGeneratorResponse::GetMetadata() const {
+
   return ::_pbi::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
@@ -1607,6 +1682,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/compiler/plugin.pb.h b/src/google/protobuf/compiler/plugin.pb.h
index fd6773b..c4fda8c 100644
--- a/src/google/protobuf/compiler/plugin.pb.h
+++ b/src/google/protobuf/compiler/plugin.pb.h
@@ -1,46 +1,51 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/compiler/plugin.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/generated_enum_reflection.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/descriptor.pb.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/generated_enum_reflection.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/descriptor.pb.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fcompiler_2fplugin_2eproto PROTOC_EXPORT
 #ifdef major
 #undef major
-#endif
+#endif  // major
 #ifdef minor
 #undef minor
-#endif
+#endif  // minor
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -49,9 +54,10 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOC_EXPORT TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOC_EXPORT extern 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;
@@ -67,41 +73,52 @@
 struct VersionDefaultTypeInternal;
 PROTOC_EXPORT extern VersionDefaultTypeInternal _Version_default_instance_;
 }  // namespace compiler
+template <>
+PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest>(Arena*);
+template <>
+PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse>(Arena*);
+template <>
+PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File>(Arena*);
+template <>
+PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::Version>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorRequest>(Arena*);
-template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse>(Arena*);
-template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File>(Arena*);
-template<> PROTOC_EXPORT ::PROTOBUF_NAMESPACE_ID::compiler::Version* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::compiler::Version>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 namespace compiler {
-
 enum CodeGeneratorResponse_Feature : int {
   CodeGeneratorResponse_Feature_FEATURE_NONE = 0,
-  CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL = 1
+  CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL = 1,
 };
-PROTOC_EXPORT bool CodeGeneratorResponse_Feature_IsValid(int value);
-constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = CodeGeneratorResponse_Feature_FEATURE_NONE;
-constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL;
-constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = CodeGeneratorResponse_Feature_Feature_MAX + 1;
 
-PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CodeGeneratorResponse_Feature_descriptor();
-template<typename T>
-inline const std::string& CodeGeneratorResponse_Feature_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, CodeGeneratorResponse_Feature>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function CodeGeneratorResponse_Feature_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    CodeGeneratorResponse_Feature_descriptor(), enum_t_value);
+PROTOC_EXPORT bool CodeGeneratorResponse_Feature_IsValid(int value);
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MIN = static_cast<CodeGeneratorResponse_Feature>(0);
+constexpr CodeGeneratorResponse_Feature CodeGeneratorResponse_Feature_Feature_MAX = static_cast<CodeGeneratorResponse_Feature>(1);
+constexpr int CodeGeneratorResponse_Feature_Feature_ARRAYSIZE = 1 + 1;
+PROTOC_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+CodeGeneratorResponse_Feature_descriptor();
+template <typename T>
+const std::string& CodeGeneratorResponse_Feature_Name(T value) {
+  static_assert(std::is_same<T, CodeGeneratorResponse_Feature>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to Feature_Name().");
+  return CodeGeneratorResponse_Feature_Name(static_cast<CodeGeneratorResponse_Feature>(value));
 }
-inline bool CodeGeneratorResponse_Feature_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, CodeGeneratorResponse_Feature* value) {
+template <>
+inline const std::string& CodeGeneratorResponse_Feature_Name(CodeGeneratorResponse_Feature value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<CodeGeneratorResponse_Feature_descriptor,
+                                                 0, 1>(
+      static_cast<int>(value));
+}
+inline bool CodeGeneratorResponse_Feature_Parse(absl::string_view name, CodeGeneratorResponse_Feature* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<CodeGeneratorResponse_Feature>(
-    CodeGeneratorResponse_Feature_descriptor(), name, value);
+      CodeGeneratorResponse_Feature_descriptor(), name, value);
 }
+
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOC_EXPORT Version final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.Version) */ {
  public:
@@ -198,10 +215,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -212,7 +229,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.compiler.Version";
   }
   protected:
@@ -237,9 +254,6 @@
   };
   // optional string suffix = 4;
   bool has_suffix() const;
-  private:
-  bool _internal_has_suffix() const;
-  public:
   void clear_suffix();
   const std::string& suffix() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -255,41 +269,32 @@
 
   // optional int32 major = 1;
   bool has_major() const;
-  private:
-  bool _internal_has_major() const;
-  public:
   void clear_major();
-  int32_t major() const;
-  void set_major(int32_t value);
+  ::int32_t major() const;
+  void set_major(::int32_t value);
   private:
-  int32_t _internal_major() const;
-  void _internal_set_major(int32_t value);
+  ::int32_t _internal_major() const;
+  void _internal_set_major(::int32_t value);
   public:
 
   // optional int32 minor = 2;
   bool has_minor() const;
-  private:
-  bool _internal_has_minor() const;
-  public:
   void clear_minor();
-  int32_t minor() const;
-  void set_minor(int32_t value);
+  ::int32_t minor() const;
+  void set_minor(::int32_t value);
   private:
-  int32_t _internal_minor() const;
-  void _internal_set_minor(int32_t value);
+  ::int32_t _internal_minor() const;
+  void _internal_set_minor(::int32_t value);
   public:
 
   // optional int32 patch = 3;
   bool has_patch() const;
-  private:
-  bool _internal_has_patch() const;
-  public:
   void clear_patch();
-  int32_t patch() const;
-  void set_patch(int32_t value);
+  ::int32_t patch() const;
+  void set_patch(::int32_t value);
   private:
-  int32_t _internal_patch() const;
-  void _internal_set_patch(int32_t value);
+  ::int32_t _internal_patch() const;
+  void _internal_set_patch(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.Version)
@@ -303,14 +308,13 @@
     ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr suffix_;
-    int32_t major_;
-    int32_t minor_;
-    int32_t patch_;
+    ::int32_t major_;
+    ::int32_t minor_;
+    ::int32_t patch_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOC_EXPORT CodeGeneratorRequest final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorRequest) */ {
@@ -408,10 +412,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -422,7 +426,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.compiler.CodeGeneratorRequest";
   }
   protected:
@@ -456,12 +460,12 @@
   void set_file_to_generate(int index, const std::string& value);
   void set_file_to_generate(int index, std::string&& value);
   void set_file_to_generate(int index, const char* value);
-  void set_file_to_generate(int index, const char* value, size_t size);
+  void set_file_to_generate(int index, const char* value, ::size_t size);
   std::string* add_file_to_generate();
   void add_file_to_generate(const std::string& value);
   void add_file_to_generate(std::string&& value);
   void add_file_to_generate(const char* value);
-  void add_file_to_generate(const char* value, size_t size);
+  void add_file_to_generate(const char* value, ::size_t size);
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& file_to_generate() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_file_to_generate();
   private:
@@ -489,9 +493,6 @@
 
   // optional string parameter = 2;
   bool has_parameter() const;
-  private:
-  bool _internal_has_parameter() const;
-  public:
   void clear_parameter();
   const std::string& parameter() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -507,9 +508,6 @@
 
   // optional .google.protobuf.compiler.Version compiler_version = 3;
   bool has_compiler_version() const;
-  private:
-  bool _internal_has_compiler_version() const;
-  public:
   void clear_compiler_version();
   const ::PROTOBUF_NAMESPACE_ID::compiler::Version& compiler_version() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::compiler::Version* release_compiler_version();
@@ -540,8 +538,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOC_EXPORT CodeGeneratorResponse_File final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse.File) */ {
@@ -639,10 +636,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -653,7 +650,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.compiler.CodeGeneratorResponse.File";
   }
   protected:
@@ -678,9 +675,6 @@
   };
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -696,9 +690,6 @@
 
   // optional string insertion_point = 2;
   bool has_insertion_point() const;
-  private:
-  bool _internal_has_insertion_point() const;
-  public:
   void clear_insertion_point();
   const std::string& insertion_point() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -714,9 +705,6 @@
 
   // optional string content = 15;
   bool has_content() const;
-  private:
-  bool _internal_has_content() const;
-  public:
   void clear_content();
   const std::string& content() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -732,9 +720,6 @@
 
   // 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_NODISCARD ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* release_generated_code_info();
@@ -765,8 +750,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOC_EXPORT CodeGeneratorResponse final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.compiler.CodeGeneratorResponse) */ {
@@ -864,10 +848,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -878,7 +862,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.compiler.CodeGeneratorResponse";
   }
   protected:
@@ -895,33 +879,23 @@
 
   typedef CodeGeneratorResponse_File File;
 
-  typedef CodeGeneratorResponse_Feature Feature;
-  static constexpr Feature FEATURE_NONE =
-    CodeGeneratorResponse_Feature_FEATURE_NONE;
-  static constexpr Feature FEATURE_PROTO3_OPTIONAL =
-    CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL;
+  using Feature = CodeGeneratorResponse_Feature;
+  static constexpr Feature FEATURE_NONE = CodeGeneratorResponse_Feature_FEATURE_NONE;
+  static constexpr Feature FEATURE_PROTO3_OPTIONAL = CodeGeneratorResponse_Feature_FEATURE_PROTO3_OPTIONAL;
   static inline bool Feature_IsValid(int value) {
     return CodeGeneratorResponse_Feature_IsValid(value);
   }
-  static constexpr Feature Feature_MIN =
-    CodeGeneratorResponse_Feature_Feature_MIN;
-  static constexpr Feature Feature_MAX =
-    CodeGeneratorResponse_Feature_Feature_MAX;
-  static constexpr int Feature_ARRAYSIZE =
-    CodeGeneratorResponse_Feature_Feature_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  Feature_descriptor() {
+  static constexpr Feature Feature_MIN = CodeGeneratorResponse_Feature_Feature_MIN;
+  static constexpr Feature Feature_MAX = CodeGeneratorResponse_Feature_Feature_MAX;
+  static constexpr int Feature_ARRAYSIZE = CodeGeneratorResponse_Feature_Feature_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Feature_descriptor() {
     return CodeGeneratorResponse_Feature_descriptor();
   }
-  template<typename T>
-  static inline const std::string& Feature_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, Feature>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function Feature_Name.");
-    return CodeGeneratorResponse_Feature_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& Feature_Name(T value) {
+    return CodeGeneratorResponse_Feature_Name(value);
   }
-  static inline bool Feature_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      Feature* value) {
+  static inline bool Feature_Parse(absl::string_view name, Feature* value) {
     return CodeGeneratorResponse_Feature_Parse(name, value);
   }
 
@@ -952,9 +926,6 @@
 
   // optional string error = 1;
   bool has_error() const;
-  private:
-  bool _internal_has_error() const;
-  public:
   void clear_error();
   const std::string& error() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -970,15 +941,12 @@
 
   // optional uint64 supported_features = 2;
   bool has_supported_features() const;
-  private:
-  bool _internal_has_supported_features() const;
-  public:
   void clear_supported_features();
-  uint64_t supported_features() const;
-  void set_supported_features(uint64_t value);
+  ::uint64_t supported_features() const;
+  void set_supported_features(::uint64_t value);
   private:
-  uint64_t _internal_supported_features() const;
-  void _internal_set_supported_features(uint64_t value);
+  ::uint64_t _internal_supported_features() const;
+  void _internal_set_supported_features(::uint64_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.compiler.CodeGeneratorResponse)
@@ -993,7 +961,7 @@
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
     ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_File > file_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr error_;
-    uint64_t supported_features_;
+    ::uint64_t supported_features_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fcompiler_2fplugin_2eproto;
@@ -1001,106 +969,99 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // Version
 
 // optional int32 major = 1;
-inline bool Version::_internal_has_major() const {
+inline bool Version::has_major() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool Version::has_major() const {
-  return _internal_has_major();
-}
 inline void Version::clear_major() {
   _impl_.major_ = 0;
   _impl_._has_bits_[0] &= ~0x00000002u;
 }
-inline int32_t Version::_internal_major() const {
+inline ::int32_t Version::_internal_major() const {
   return _impl_.major_;
 }
-inline int32_t Version::major() const {
+inline ::int32_t Version::major() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.major)
   return _internal_major();
 }
-inline void Version::_internal_set_major(int32_t value) {
+inline void Version::_internal_set_major(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000002u;
   _impl_.major_ = value;
 }
-inline void Version::set_major(int32_t value) {
+inline void Version::set_major(::int32_t value) {
   _internal_set_major(value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.major)
 }
 
 // optional int32 minor = 2;
-inline bool Version::_internal_has_minor() const {
+inline bool Version::has_minor() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool Version::has_minor() const {
-  return _internal_has_minor();
-}
 inline void Version::clear_minor() {
   _impl_.minor_ = 0;
   _impl_._has_bits_[0] &= ~0x00000004u;
 }
-inline int32_t Version::_internal_minor() const {
+inline ::int32_t Version::_internal_minor() const {
   return _impl_.minor_;
 }
-inline int32_t Version::minor() const {
+inline ::int32_t Version::minor() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.minor)
   return _internal_minor();
 }
-inline void Version::_internal_set_minor(int32_t value) {
+inline void Version::_internal_set_minor(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000004u;
   _impl_.minor_ = value;
 }
-inline void Version::set_minor(int32_t value) {
+inline void Version::set_minor(::int32_t value) {
   _internal_set_minor(value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.minor)
 }
 
 // optional int32 patch = 3;
-inline bool Version::_internal_has_patch() const {
+inline bool Version::has_patch() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   return value;
 }
-inline bool Version::has_patch() const {
-  return _internal_has_patch();
-}
 inline void Version::clear_patch() {
   _impl_.patch_ = 0;
   _impl_._has_bits_[0] &= ~0x00000008u;
 }
-inline int32_t Version::_internal_patch() const {
+inline ::int32_t Version::_internal_patch() const {
   return _impl_.patch_;
 }
-inline int32_t Version::patch() const {
+inline ::int32_t Version::patch() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.Version.patch)
   return _internal_patch();
 }
-inline void Version::_internal_set_patch(int32_t value) {
+inline void Version::_internal_set_patch(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000008u;
   _impl_.patch_ = value;
 }
-inline void Version::set_patch(int32_t value) {
+inline void Version::set_patch(::int32_t value) {
   _internal_set_patch(value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.Version.patch)
 }
 
 // optional string suffix = 4;
-inline bool Version::_internal_has_suffix() const {
+inline bool Version::has_suffix() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool Version::has_suffix() const {
-  return _internal_has_suffix();
-}
 inline void Version::clear_suffix() {
   _impl_.suffix_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -1134,15 +1095,13 @@
 }
 inline std::string* Version::release_suffix() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.Version.suffix)
-  if (!_internal_has_suffix()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.suffix_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.suffix_.IsDefault()) {
-    _impl_.suffix_.Set("", GetArenaForAllocation());
-  }
+  _impl_.suffix_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -1200,11 +1159,10 @@
   // @@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);
-  _impl_.file_to_generate_.Mutable(index)->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.file_to_generate_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
-inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, size_t size) {
+inline void CodeGeneratorRequest::set_file_to_generate(int index, const char* value, ::size_t size) {
   _impl_.file_to_generate_.Mutable(index)->assign(
     reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
@@ -1221,11 +1179,10 @@
   // @@protoc_insertion_point(field_add:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
 inline void CodeGeneratorRequest::add_file_to_generate(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.file_to_generate_.Add()->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.file_to_generate_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
-inline void CodeGeneratorRequest::add_file_to_generate(const char* value, size_t size) {
+inline void CodeGeneratorRequest::add_file_to_generate(const char* value, ::size_t size) {
   _impl_.file_to_generate_.Add()->assign(reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_add_pointer:google.protobuf.compiler.CodeGeneratorRequest.file_to_generate)
 }
@@ -1241,13 +1198,10 @@
 }
 
 // optional string parameter = 2;
-inline bool CodeGeneratorRequest::_internal_has_parameter() const {
+inline bool CodeGeneratorRequest::has_parameter() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool CodeGeneratorRequest::has_parameter() const {
-  return _internal_has_parameter();
-}
 inline void CodeGeneratorRequest::clear_parameter() {
   _impl_.parameter_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -1281,15 +1235,13 @@
 }
 inline std::string* CodeGeneratorRequest::release_parameter() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorRequest.parameter)
-  if (!_internal_has_parameter()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.parameter_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.parameter_.IsDefault()) {
-    _impl_.parameter_.Set("", GetArenaForAllocation());
-  }
+  _impl_.parameter_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -1346,14 +1298,11 @@
 }
 
 // optional .google.protobuf.compiler.Version compiler_version = 3;
-inline bool CodeGeneratorRequest::_internal_has_compiler_version() const {
+inline bool CodeGeneratorRequest::has_compiler_version() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.compiler_version_ != nullptr);
   return value;
 }
-inline bool CodeGeneratorRequest::has_compiler_version() const {
-  return _internal_has_compiler_version();
-}
 inline void CodeGeneratorRequest::clear_compiler_version() {
   if (_impl_.compiler_version_ != nullptr) _impl_.compiler_version_->Clear();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -1440,13 +1389,10 @@
 // CodeGeneratorResponse_File
 
 // optional string name = 1;
-inline bool CodeGeneratorResponse_File::_internal_has_name() const {
+inline bool CodeGeneratorResponse_File::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool CodeGeneratorResponse_File::has_name() const {
-  return _internal_has_name();
-}
 inline void CodeGeneratorResponse_File::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -1480,15 +1426,13 @@
 }
 inline std::string* CodeGeneratorResponse_File::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -1508,13 +1452,10 @@
 }
 
 // optional string insertion_point = 2;
-inline bool CodeGeneratorResponse_File::_internal_has_insertion_point() const {
+inline bool CodeGeneratorResponse_File::has_insertion_point() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool CodeGeneratorResponse_File::has_insertion_point() const {
-  return _internal_has_insertion_point();
-}
 inline void CodeGeneratorResponse_File::clear_insertion_point() {
   _impl_.insertion_point_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -1548,15 +1489,13 @@
 }
 inline std::string* CodeGeneratorResponse_File::release_insertion_point() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.insertion_point)
-  if (!_internal_has_insertion_point()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000002u;
   auto* p = _impl_.insertion_point_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.insertion_point_.IsDefault()) {
-    _impl_.insertion_point_.Set("", GetArenaForAllocation());
-  }
+  _impl_.insertion_point_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -1576,13 +1515,10 @@
 }
 
 // optional string content = 15;
-inline bool CodeGeneratorResponse_File::_internal_has_content() const {
+inline bool CodeGeneratorResponse_File::has_content() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool CodeGeneratorResponse_File::has_content() const {
-  return _internal_has_content();
-}
 inline void CodeGeneratorResponse_File::clear_content() {
   _impl_.content_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -1616,15 +1552,13 @@
 }
 inline std::string* CodeGeneratorResponse_File::release_content() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.File.content)
-  if (!_internal_has_content()) {
+  if ((_impl_._has_bits_[0] & 0x00000004u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000004u;
   auto* p = _impl_.content_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.content_.IsDefault()) {
-    _impl_.content_.Set("", GetArenaForAllocation());
-  }
+  _impl_.content_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -1644,14 +1578,11 @@
 }
 
 // optional .google.protobuf.GeneratedCodeInfo generated_code_info = 16;
-inline bool CodeGeneratorResponse_File::_internal_has_generated_code_info() const {
+inline bool CodeGeneratorResponse_File::has_generated_code_info() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.generated_code_info_ != nullptr);
   return value;
 }
-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 = _impl_.generated_code_info_;
   return p != nullptr ? *p : reinterpret_cast<const ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo&>(
@@ -1735,13 +1666,10 @@
 // CodeGeneratorResponse
 
 // optional string error = 1;
-inline bool CodeGeneratorResponse::_internal_has_error() const {
+inline bool CodeGeneratorResponse::has_error() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool CodeGeneratorResponse::has_error() const {
-  return _internal_has_error();
-}
 inline void CodeGeneratorResponse::clear_error() {
   _impl_.error_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -1775,15 +1703,13 @@
 }
 inline std::string* CodeGeneratorResponse::release_error() {
   // @@protoc_insertion_point(field_release:google.protobuf.compiler.CodeGeneratorResponse.error)
-  if (!_internal_has_error()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.error_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.error_.IsDefault()) {
-    _impl_.error_.Set("", GetArenaForAllocation());
-  }
+  _impl_.error_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -1803,29 +1729,26 @@
 }
 
 // optional uint64 supported_features = 2;
-inline bool CodeGeneratorResponse::_internal_has_supported_features() const {
+inline bool CodeGeneratorResponse::has_supported_features() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool CodeGeneratorResponse::has_supported_features() const {
-  return _internal_has_supported_features();
-}
 inline void CodeGeneratorResponse::clear_supported_features() {
-  _impl_.supported_features_ = uint64_t{0u};
+  _impl_.supported_features_ = ::uint64_t{0u};
   _impl_._has_bits_[0] &= ~0x00000002u;
 }
-inline uint64_t CodeGeneratorResponse::_internal_supported_features() const {
+inline ::uint64_t CodeGeneratorResponse::_internal_supported_features() const {
   return _impl_.supported_features_;
 }
-inline uint64_t CodeGeneratorResponse::supported_features() const {
+inline ::uint64_t CodeGeneratorResponse::supported_features() const {
   // @@protoc_insertion_point(field_get:google.protobuf.compiler.CodeGeneratorResponse.supported_features)
   return _internal_supported_features();
 }
-inline void CodeGeneratorResponse::_internal_set_supported_features(uint64_t value) {
+inline void CodeGeneratorResponse::_internal_set_supported_features(::uint64_t value) {
   _impl_._has_bits_[0] |= 0x00000002u;
   _impl_.supported_features_ = value;
 }
-inline void CodeGeneratorResponse::set_supported_features(uint64_t value) {
+inline void CodeGeneratorResponse::set_supported_features(::uint64_t value) {
   _internal_set_supported_features(value);
   // @@protoc_insertion_point(field_set:google.protobuf.compiler.CodeGeneratorResponse.supported_features)
 }
@@ -1871,25 +1794,20 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
 
 // @@protoc_insertion_point(namespace_scope)
-
 }  // namespace compiler
 PROTOBUF_NAMESPACE_CLOSE
 
+
 PROTOBUF_NAMESPACE_OPEN
 
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature>() {
   return ::PROTOBUF_NAMESPACE_ID::compiler::CodeGeneratorResponse_Feature_descriptor();
 }
 
@@ -1897,5 +1815,6 @@
 
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fcompiler_2fplugin_2eproto_2epb_2eh
diff --git a/src/google/protobuf/compiler/plugin.proto b/src/google/protobuf/compiler/plugin.proto
index 9242aac..b233bce 100644
--- a/src/google/protobuf/compiler/plugin.proto
+++ b/src/google/protobuf/compiler/plugin.proto
@@ -30,9 +30,6 @@
 
 // Author: kenton@google.com (Kenton Varda)
 //
-// WARNING:  The plugin interface is currently EXPERIMENTAL and is subject to
-//   change.
-//
 // protoc (aka the Protocol Compiler) can be extended via plugins.  A plugin is
 // just a program that reads a CodeGeneratorRequest from stdin and writes a
 // CodeGeneratorResponse to stdout.
@@ -92,7 +89,6 @@
 
   // The version number of protocol compiler.
   optional Version compiler_version = 3;
-
 }
 
 // The plugin writes an encoded CodeGeneratorResponse to stdout.
diff --git a/src/google/protobuf/compiler/python/BUILD.bazel b/src/google/protobuf/compiler/python/BUILD.bazel
new file mode 100644
index 0000000..933d063
--- /dev/null
+++ b/src/google/protobuf/compiler/python/BUILD.bazel
@@ -0,0 +1,69 @@
+################################################################################
+# Protocol Buffers Compiler - Python code generator
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "python",
+    srcs = [
+        "generator.cc",
+        "helpers.cc",
+        "pyi_generator.cc",
+    ],
+    hdrs = [
+        "generator.h",
+        "helpers.h",
+        "pyi_generator.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/python",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+        "@com_github_grpc_grpc//tools/distrib/python/grpcio_tools:__subpackages__",
+    ],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/synchronization",
+    ],
+)
+
+cc_test(
+    name = "plugin_unittest",
+    srcs = ["plugin_unittest.cc"],
+    copts = COPTS,
+    deps = [
+        ":python",
+        "//src/google/protobuf/compiler:command_line_interface",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/testing",
+        "@com_google_absl//absl/strings",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/python/generator.cc b/src/google/protobuf/compiler/python/generator.cc
index d8d6d74..f8a33cc 100644
--- a/src/google/protobuf/compiler/python/generator.cc
+++ b/src/google/protobuf/compiler/python/generator.cc
@@ -42,27 +42,33 @@
 // performance-minded Python code leverage the fast C++ implementation
 // directly.
 
-#include <google/protobuf/compiler/python/generator.h>
+#include "google/protobuf/compiler/python/generator.h"
 
 #include <algorithm>
 #include <limits>
-#include <map>
 #include <memory>
 #include <string>
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/compiler/python/helpers.h>
-#include <google/protobuf/compiler/python/pyi_generator.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/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/compiler/python/helpers.h"
+#include "google/protobuf/compiler/python/pyi_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
@@ -79,8 +85,8 @@
   // We can't have dots in the module name, so we replace each with _dot_.
   // But that could lead to a collision between a.b and a_dot_b, so we also
   // duplicate each underscore.
-  GlobalReplaceSubstring("_", "__", &module_name);
-  GlobalReplaceSubstring(".", "_dot_", &module_name);
+  absl::StrReplaceAll({{"_", "__"}}, &module_name);
+  absl::StrReplaceAll({{".", "_dot_"}}, &module_name);
   return module_name;
 }
 
@@ -90,29 +96,7 @@
 // in proto2/public/reflection.py.
 const char kDescriptorKey[] = "DESCRIPTOR";
 
-
-// file output by this generator.
-void PrintTopBoilerplate(io::Printer* printer, const FileDescriptor* file,
-                         bool descriptor_proto) {
-  // TODO(robinson): Allow parameterization of Python version?
-  printer->Print(
-      "# -*- coding: utf-8 -*-\n"
-      "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
-      "# source: $filename$\n"
-      "\"\"\"Generated protocol buffer code.\"\"\"\n",
-      "filename", file->name());
-  printer->Print(
-      "from google.protobuf.internal import builder as _builder\n"
-      "from google.protobuf import descriptor as _descriptor\n"
-      "from google.protobuf import descriptor_pool as "
-      "_descriptor_pool\n"
-      "from google.protobuf import symbol_database as "
-      "_symbol_database\n");
-
-  printer->Print("# @@protoc_insertion_point(imports)\n\n");
-  printer->Print("_sym_db = _symbol_database.Default()\n");
-  printer->Print("\n\n");
-}
+const char kThirdPartyPrefix[] = "google3.third_party.py.";
 
 // Returns a Python literal giving the default value for a field.
 // If the field specifies no explicit default value, we'll return
@@ -131,13 +115,13 @@
 
   switch (field.cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
-      return StrCat(field.default_value_int32());
+      return absl::StrCat(field.default_value_int32());
     case FieldDescriptor::CPPTYPE_UINT32:
-      return StrCat(field.default_value_uint32());
+      return absl::StrCat(field.default_value_uint32());
     case FieldDescriptor::CPPTYPE_INT64:
-      return StrCat(field.default_value_int64());
+      return absl::StrCat(field.default_value_int64());
     case FieldDescriptor::CPPTYPE_UINT64:
-      return StrCat(field.default_value_uint64());
+      return absl::StrCat(field.default_value_uint64());
     case FieldDescriptor::CPPTYPE_DOUBLE: {
       double value = field.default_value_double();
       if (value == std::numeric_limits<double>::infinity()) {
@@ -151,7 +135,7 @@
         // infinity * 0 = nan
         return "(1e10000 * 0)";
       } else {
-        return "float(" + SimpleDtoa(value) + ")";
+        return "float(" + io::SimpleDtoa(value) + ")";
       }
     }
     case FieldDescriptor::CPPTYPE_FLOAT: {
@@ -167,15 +151,15 @@
         // infinity - infinity = nan
         return "(1e10000 * 0)";
       } else {
-        return "float(" + SimpleFtoa(value) + ")";
+        return "float(" + io::SimpleFtoa(value) + ")";
       }
     }
     case FieldDescriptor::CPPTYPE_BOOL:
       return field.default_value_bool() ? "True" : "False";
     case FieldDescriptor::CPPTYPE_ENUM:
-      return StrCat(field.default_value_enum()->number());
+      return absl::StrCat(field.default_value_enum()->number());
     case FieldDescriptor::CPPTYPE_STRING:
-      return "b\"" + CEscape(field.default_value_string()) +
+      return "b\"" + absl::CEscape(field.default_value_string()) +
              (field.type() != FieldDescriptor::TYPE_STRING
                   ? "\""
                   : "\".decode('utf-8')");
@@ -212,26 +196,42 @@
   return CodeGenerator::Feature::FEATURE_PROTO3_OPTIONAL;
 }
 
+GeneratorOptions Generator::ParseParameter(const std::string& parameter,
+                                           std::string* error) const {
+  GeneratorOptions options;
+
+  std::vector<std::pair<std::string, std::string> > option_pairs;
+  ParseGeneratorParameter(parameter, &option_pairs);
+
+  for (const std::pair<std::string, std::string>& option : option_pairs) {
+    if (!opensource_runtime_ &&
+        option.first == "no_enforce_api_compatibility") {
+      // TODO(b/241584880): remove this legacy option, it has no effect.
+    } else if (!opensource_runtime_ && option.first == "bootstrap") {
+      options.bootstrap = true;
+    } else if (option.first == "pyi_out") {
+      options.generate_pyi = true;
+    } else if (option.first == "annotate_code") {
+      options.annotate_pyi = true;
+    } else {
+      *error = "Unknown generator option: " + option.first;
+    }
+  }
+  return options;
+}
+
 bool Generator::Generate(const FileDescriptor* file,
                          const std::string& parameter,
                          GeneratorContext* context, std::string* error) const {
   // -----------------------------------------------------------------
-  // parse generator options
-  bool cpp_generated_lib_linked = false;
+  GeneratorOptions options = ParseParameter(parameter, error);
+  if (!error->empty()) return false;
 
-  std::vector<std::pair<std::string, std::string> > options;
-  ParseGeneratorParameter(parameter, &options);
-
-  for (int i = 0; i < options.size(); i++) {
-    if (options[i].first == "cpp_generated_lib_linked") {
-      cpp_generated_lib_linked = true;
-    } else if (options[i].first == "pyi_out") {
-      python::PyiGenerator pyi_generator;
-      if (!pyi_generator.Generate(file, "", context, error)) {
-        return false;
-      }
-    } else {
-      *error = "Unknown generator option: " + options[i].first;
+  // Generate pyi typing information
+  if (options.generate_pyi) {
+    python::PyiGenerator pyi_generator;
+    std::string pyi_options = options.annotate_pyi ? "annotate_code" : "";
+    if (!pyi_generator.Generate(file, pyi_options, context, error)) {
       return false;
     }
   }
@@ -243,75 +243,106 @@
   // TODO(kenton):  The proper thing to do would be to allocate any state on
   //   the stack and use that, so that the Generator class itself does not need
   //   to have any mutable members.  Then it is implicitly thread-safe.
-  MutexLock lock(&mutex_);
+  absl::MutexLock lock(&mutex_);
   file_ = file;
 
   std::string filename = GetFileName(file, ".py");
-  pure_python_workable_ = !cpp_generated_lib_linked;
-  if (HasPrefixString(file->name(), "google/protobuf/")) {
-    pure_python_workable_ = true;
-  }
 
   FileDescriptorProto fdp;
   file_->CopyTo(&fdp);
   fdp.SerializeToString(&file_descriptor_serialized_);
 
+  if (!opensource_runtime_ && GeneratingDescriptorProto()) {
+    std::string bootstrap_filename =
+        "net/proto2/python/internal/descriptor_pb2.py";
+    if (options.bootstrap) {
+      filename = bootstrap_filename;
+    } else {
+      std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
+      io::Printer printer(output.get(), '$');
+      printer.Print(
+          "from $internal_package$ import descriptor_pb2\n"
+          "\n",
+          "internal_package", InternalPackage());
+
+      // For static checkers, we need to explicitly assign to the symbols we
+      // publicly export.
+      for (int i = 0; i < file_->message_type_count(); i++) {
+        const Descriptor* message = file_->message_type(i);
+        printer.Print("$name$ = descriptor_pb2.$name$\n", "name",
+                      message->name());
+      }
+
+      // Sadly some clients access our internal variables (starting with "_").
+      // To support them, we iterate over *all* symbols to expose even the
+      // private ones.  Statically type-checked code should (especially) never
+      // use these, so we don't worry about making them available to pytype
+      // checks.
+      printer.Print(
+          "\n"
+          "globals().update(descriptor_pb2.__dict__)\n"
+          "\n");
+
+      printer.Print(
+          "# @@protoc_insertion_point(module_scope)\n"
+          "\n");
+      return true;
+    }
+  }
 
   std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   GOOGLE_CHECK(output.get());
   io::Printer printer(output.get(), '$');
   printer_ = &printer;
 
-  PrintTopBoilerplate(printer_, file_, GeneratingDescriptorProto());
-  if (pure_python_workable_) {
-    PrintImports();
-  }
+  PrintTopBoilerplate();
+  PrintImports();
   PrintFileDescriptor();
-  if (pure_python_workable_) {
-    if (GeneratingDescriptorProto()) {
-      printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
-      printer_->Indent();
-      // Create enums before message descriptors
-      PrintAllNestedEnumsInFile();
-      PrintMessageDescriptors();
-      FixForeignFieldsInDescriptors();
-      printer_->Outdent();
-      printer_->Print("else:\n");
-      printer_->Indent();
-    }
-    // Find the message descriptors first and then use the message
-    // descriptor to find enums.
-    printer_->Print(
-        "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())\n");
-    if (GeneratingDescriptorProto()) {
-      printer_->Outdent();
-    }
+  if (GeneratingDescriptorProto()) {
+    printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
+    printer_->Indent();
+    // Create enums before message descriptors
+    PrintAllNestedEnumsInFile();
+    PrintMessageDescriptors();
+    FixForeignFieldsInDescriptors();
+    printer_->Outdent();
+    printer_->Print("else:\n");
+    printer_->Indent();
+  }
+  // Find the message descriptors first and then use the message
+  // descriptor to find enums.
+  printer_->Print(
+      "_builder.BuildMessageAndEnumDescriptors(DESCRIPTOR, globals())\n");
+  if (GeneratingDescriptorProto()) {
+    printer_->Outdent();
   }
   std::string module_name = ModuleName(file->name());
+  if (!opensource_runtime_) {
+    module_name =
+        std::string(absl::StripPrefix(module_name, kThirdPartyPrefix));
+  }
   printer_->Print(
       "_builder.BuildTopDescriptorsAndMessages(DESCRIPTOR, '$module_name$', "
       "globals())\n",
       "module_name", module_name);
-  if (pure_python_workable_) {
-    printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
-    printer_->Indent();
+  printer.Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
+  printer_->Indent();
 
-    // We have to fix up the extensions after the message classes themselves,
-    // since they need to call static RegisterExtension() methods on these
-    // classes.
-    FixForeignFieldsInExtensions();
-    // Descriptor options may have custom extensions. These custom options
-    // can only be successfully parsed after we register corresponding
-    // extensions. Therefore we parse all options again here to recognize
-    // custom options that may be unknown when we define the descriptors.
-    // This does not apply to services because they are not used by extensions.
-    FixAllDescriptorOptions();
+  // We have to fix up the extensions after the message classes themselves,
+  // since they need to call static RegisterExtension() methods on these
+  // classes.
+  FixForeignFieldsInExtensions();
+  // Descriptor options may have custom extensions. These custom options
+  // can only be successfully parsed after we register corresponding
+  // extensions. Therefore we parse all options again here to recognize
+  // custom options that may be unknown when we define the descriptors.
+  // This does not apply to services because they are not used by extensions.
+  FixAllDescriptorOptions();
 
-    // Set serialized_start and serialized_end.
-    SetSerializedPbInterval();
+  // Set serialized_start and serialized_end.
+  SetSerializedPbInterval();
 
-    printer_->Outdent();
-  }
+  printer_->Outdent();
   if (HasGenericServices(file)) {
     printer_->Print(
         "_builder.BuildServices(DESCRIPTOR, '$module_name$', globals())\n",
@@ -323,6 +354,34 @@
   return !printer.failed();
 }
 
+// file output by this generator.
+void Generator::PrintTopBoilerplate() const {
+  // TODO(robinson): Allow parameterization of Python version?
+  printer_->Print(
+      "# -*- coding: utf-8 -*-\n"
+      "# Generated by the protocol buffer compiler.  DO NOT EDIT!\n"
+      "# source: $filename$\n"
+      "\"\"\"Generated protocol buffer code.\"\"\"\n",
+      "filename", file_->name());
+  if (!opensource_runtime_) {
+    // This import is needed so that compatibility proto1 compiler output
+    // inserted at protoc_insertion_point can refer to other protos like
+    // google3.a.b.c. Code generated by proto2 compiler doesn't do it, and
+    // instead uses aliases assigned when importing modules.
+    printer_->Print("import google3\n");
+  }
+  printer_->Print(
+      "from $internal_package$ import builder as _builder\n"
+      "from $public_package$ import descriptor as _descriptor\n"
+      "from $public_package$ import descriptor_pool as _descriptor_pool\n"
+      "from $public_package$ import symbol_database as _symbol_database\n",
+      "internal_package", InternalPackage(), "public_package", PublicPackage());
+
+  printer_->Print("# @@protoc_insertion_point(imports)\n\n");
+  printer_->Print("_sym_db = _symbol_database.Default()\n");
+  printer_->Print("\n\n");
+}
+
 // Prints Python imports for all modules imported by |file|.
 void Generator::PrintImports() const {
   for (int i = 0; i < file_->dependency_count(); ++i) {
@@ -330,6 +389,10 @@
 
     std::string module_name = ModuleName(filename);
     std::string module_alias = ModuleAlias(filename);
+    if (!opensource_runtime_) {
+      module_name =
+          std::string(absl::StripPrefix(module_name, kThirdPartyPrefix));
+    }
     if (ContainsPythonKeyword(module_name)) {
       // If the module path contains a Python keyword, we have to quote the
       // module name and import it using importlib. Otherwise the usual kind of
@@ -360,6 +423,10 @@
   // Print public imports.
   for (int i = 0; i < file_->public_dependency_count(); ++i) {
     std::string module_name = ModuleName(file_->public_dependency(i)->name());
+    if (!opensource_runtime_) {
+      module_name =
+          std::string(absl::StripPrefix(module_name, kThirdPartyPrefix));
+    }
     printer_->Print("from $module$ import *\n", "module", module_name);
   }
   printer_->Print("\n");
@@ -367,13 +434,13 @@
 
 // Prints the single file descriptor for this file.
 void Generator::PrintFileDescriptor() const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["name"] = file_->name();
   m["package"] = file_->package();
   m["syntax"] = StringifySyntax(file_->syntax());
   m["options"] = OptionsValue(file_->options().SerializeAsString());
-  m["serialized_descriptor"] = strings::CHexEscape(file_descriptor_serialized_);
+  m["serialized_descriptor"] = absl::CHexEscape(file_descriptor_serialized_);
   if (GeneratingDescriptorProto()) {
     printer_->Print("if _descriptor._USE_C_DESCRIPTORS == False:\n");
     printer_->Indent();
@@ -389,30 +456,26 @@
         "  create_key=_descriptor._internal_create_key,\n";
     printer_->Print(m, file_descriptor_template);
     printer_->Indent();
-    if (pure_python_workable_) {
-      printer_->Print("serialized_pb=b'$value$'\n", "value",
-                      strings::CHexEscape(file_descriptor_serialized_));
-      if (file_->dependency_count() != 0) {
-        printer_->Print(",\ndependencies=[");
-        for (int i = 0; i < file_->dependency_count(); ++i) {
-          std::string module_alias = ModuleAlias(file_->dependency(i)->name());
-          printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
-                          module_alias);
-        }
-        printer_->Print("]");
+    printer_->Print("serialized_pb=b'$value$'\n", "value",
+                    absl::CHexEscape(file_descriptor_serialized_));
+    if (file_->dependency_count() != 0) {
+      printer_->Print(",\ndependencies=[");
+      for (int i = 0; i < file_->dependency_count(); ++i) {
+        std::string module_alias = ModuleAlias(file_->dependency(i)->name());
+        printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+                        module_alias);
       }
-      if (file_->public_dependency_count() > 0) {
-        printer_->Print(",\npublic_dependencies=[");
-        for (int i = 0; i < file_->public_dependency_count(); ++i) {
-          std::string module_alias =
-              ModuleAlias(file_->public_dependency(i)->name());
-          printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
-                          module_alias);
-        }
-        printer_->Print("]");
+      printer_->Print("]");
+    }
+    if (file_->public_dependency_count() > 0) {
+      printer_->Print(",\npublic_dependencies=[");
+      for (int i = 0; i < file_->public_dependency_count(); ++i) {
+        std::string module_alias =
+            ModuleAlias(file_->public_dependency(i)->name());
+        printer_->Print("$module_alias$.DESCRIPTOR,", "module_alias",
+                        module_alias);
       }
-    } else {
-      printer_->Print("serialized_pb=''\n");
+      printer_->Print("]");
     }
 
     // TODO(falk): Also print options and fix the message_type, enum_type,
@@ -446,7 +509,7 @@
 // enum name to a Python EnumDescriptor object equivalent to
 // enum_descriptor.
 void Generator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   std::string module_level_descriptor_name =
       ModuleLevelDescriptorName(enum_descriptor);
   m["descriptor_name"] = module_level_descriptor_name;
@@ -467,11 +530,9 @@
   printer_->Indent();
   printer_->Indent();
 
-  if (pure_python_workable_) {
-    for (int i = 0; i < enum_descriptor.value_count(); ++i) {
-      PrintEnumValueDescriptor(*enum_descriptor.value(i));
-      printer_->Print(",\n");
-    }
+  for (int i = 0; i < enum_descriptor.value_count(); ++i) {
+    PrintEnumValueDescriptor(*enum_descriptor.value(i));
+    printer_->Print(",\n");
   }
 
   printer_->Outdent();
@@ -482,10 +543,8 @@
   EnumDescriptorProto edp;
   printer_->Outdent();
   printer_->Print(")\n");
-  if (pure_python_workable_) {
-    printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name",
-                    module_level_descriptor_name);
-  }
+  printer_->Print("_sym_db.RegisterEnumDescriptor($name$)\n", "name",
+                  module_level_descriptor_name);
   printer_->Print("\n");
 }
 
@@ -525,7 +584,7 @@
 
 void Generator::PrintServiceDescriptor(
     const ServiceDescriptor& descriptor) const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["service_name"] = ModuleLevelServiceDescriptorName(descriptor);
   m["name"] = descriptor.name();
   m["file"] = kDescriptorKey;
@@ -535,13 +594,13 @@
 void Generator::PrintDescriptorKeyAndModuleName(
     const ServiceDescriptor& descriptor) const {
   std::string name = ModuleLevelServiceDescriptorName(descriptor);
-  if (!pure_python_workable_) {
-    name = "_descriptor.ServiceDescriptor(full_name='" +
-           descriptor.full_name() + "')";
-  }
   printer_->Print("$descriptor_key$ = $descriptor_name$,\n", "descriptor_key",
                   kDescriptorKey, "descriptor_name", name);
   std::string module_name = ModuleName(file_->name());
+  if (!opensource_runtime_) {
+    module_name =
+        std::string(absl::StripPrefix(module_name, kThirdPartyPrefix));
+  }
   printer_->Print("__module__ = '$module_name$'\n", "module_name", module_name);
 }
 
@@ -575,7 +634,7 @@
 //
 // Mutually recursive with PrintNestedDescriptors().
 void Generator::PrintDescriptor(const Descriptor& message_descriptor) const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["name"] = message_descriptor.name();
   m["full_name"] = message_descriptor.full_name();
   m["file"] = kDescriptorKey;
@@ -634,8 +693,8 @@
   for (int i = 0; i < message_descriptor.extension_range_count(); ++i) {
     const Descriptor::ExtensionRange* range =
         message_descriptor.extension_range(i);
-    printer_->Print("($start$, $end$), ", "start", StrCat(range->start),
-                    "end", StrCat(range->end));
+    printer_->Print("($start$, $end$), ", "start", absl::StrCat(range->start),
+                    "end", absl::StrCat(range->end));
   }
   printer_->Print("],\n");
   printer_->Print("oneofs=[\n");
@@ -645,7 +704,7 @@
     m.clear();
     m["name"] = desc->name();
     m["full_name"] = desc->full_name();
-    m["index"] = StrCat(desc->index());
+    m["index"] = absl::StrCat(desc->index());
     options_string = OptionsValue(desc->options().SerializeAsString());
     if (options_string == "None") {
       m["serialized_options"] = "";
@@ -726,16 +785,15 @@
   to_register->push_back(qualified_name);
 
   PrintNestedMessages(message_descriptor, qualified_name, to_register);
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["descriptor_key"] = kDescriptorKey;
-  if (pure_python_workable_) {
-    m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
-  } else {
-    m["descriptor_name"] = "_descriptor.Descriptor(full_name='" +
-                           message_descriptor.full_name() + "')";
-  }
+  m["descriptor_name"] = ModuleLevelDescriptorName(message_descriptor);
   printer_->Print(m, "'$descriptor_key$' : $descriptor_name$,\n");
   std::string module_name = ModuleName(file_->name());
+  if (!opensource_runtime_) {
+    module_name =
+        std::string(absl::StripPrefix(module_name, kThirdPartyPrefix));
+  }
   printer_->Print("'__module__' : '$module_name$'\n", "module_name",
                   module_name);
   printer_->Print("# @@protoc_insertion_point(class_scope:$full_name$)\n",
@@ -782,7 +840,7 @@
     FixContainingTypeInDescriptor(enum_descriptor, &descriptor);
   }
   for (int i = 0; i < descriptor.oneof_decl_count(); ++i) {
-    std::map<std::string, std::string> m;
+    absl::flat_hash_map<absl::string_view, std::string> m;
     const OneofDescriptor* oneof = descriptor.oneof_decl(i);
     m["descriptor_name"] = ModuleLevelDescriptorName(descriptor);
     m["oneof_name"] = oneof->name();
@@ -801,7 +859,7 @@
 }
 
 void Generator::AddMessageToFileDescriptor(const Descriptor& descriptor) const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["message_name"] = descriptor.name();
   m["message_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
@@ -813,7 +871,7 @@
 
 void Generator::AddServiceToFileDescriptor(
     const ServiceDescriptor& descriptor) const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["service_name"] = descriptor.name();
   m["service_descriptor_name"] = ModuleLevelServiceDescriptorName(descriptor);
@@ -825,7 +883,7 @@
 
 void Generator::AddEnumToFileDescriptor(
     const EnumDescriptor& descriptor) const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["enum_name"] = descriptor.name();
   m["enum_descriptor_name"] = ModuleLevelDescriptorName(descriptor);
@@ -837,7 +895,7 @@
 
 void Generator::AddExtensionToFileDescriptor(
     const FieldDescriptor& descriptor) const {
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["descriptor_name"] = kDescriptorKey;
   m["field_name"] = descriptor.name();
   m["resolved_name"] = ResolveKeyword(descriptor.name());
@@ -861,7 +919,7 @@
     const std::string& python_dict_name) const {
   const std::string field_referencing_expression =
       FieldReferencingExpression(containing_type, field, python_dict_name);
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["field_ref"] = field_referencing_expression;
   const Descriptor* foreign_message_type = field.message_type();
   if (foreign_message_type) {
@@ -894,7 +952,7 @@
   if (!containing_type) {
     return ResolveKeyword(field.name());
   }
-  return strings::Substitute("$0.$1['$2']",
+  return absl::Substitute("$0.$1['$2']",
                           ModuleLevelDescriptorName(*containing_type),
                           python_dict_name, field.name());
 }
@@ -957,7 +1015,7 @@
     const FieldDescriptor& extension_field) const {
   GOOGLE_CHECK(extension_field.is_extension());
 
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   // Confusingly, for FieldDescriptors that happen to be extensions,
   // containing_type() means "extended type."
   // On the other hand, extension_scope() will give us what we normally
@@ -989,10 +1047,10 @@
   // More circular references.  ::sigh::
   std::string options_string;
   descriptor.options().SerializeToString(&options_string);
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["name"] = descriptor.name();
-  m["index"] = StrCat(descriptor.index());
-  m["number"] = StrCat(descriptor.number());
+  m["index"] = absl::StrCat(descriptor.index());
+  m["number"] = absl::StrCat(descriptor.number());
   m["options"] = OptionsValue(options_string);
   printer_->Print(m,
                   "_descriptor.EnumValueDescriptor(\n"
@@ -1008,7 +1066,7 @@
   if (serialized_options.length() == 0 || GeneratingDescriptorProto()) {
     return "None";
   } else {
-    return "b'" + CEscape(serialized_options) + "'";
+    return "b'" + absl::CEscape(serialized_options) + "'";
   }
 }
 
@@ -1017,14 +1075,14 @@
                                      bool is_extension) const {
   std::string options_string;
   field.options().SerializeToString(&options_string);
-  std::map<std::string, std::string> m;
+  absl::flat_hash_map<absl::string_view, std::string> m;
   m["name"] = field.name();
   m["full_name"] = field.full_name();
-  m["index"] = StrCat(field.index());
-  m["number"] = StrCat(field.number());
-  m["type"] = StrCat(field.type());
-  m["cpp_type"] = StrCat(field.cpp_type());
-  m["label"] = StrCat(field.label());
+  m["index"] = absl::StrCat(field.index());
+  m["number"] = absl::StrCat(field.number());
+  m["type"] = absl::StrCat(field.type());
+  m["cpp_type"] = absl::StrCat(field.cpp_type());
+  m["label"] = absl::StrCat(field.label());
   m["has_default_value"] = field.has_default_value() ? "True" : "False";
   m["default_value"] = StringifyDefaultValue(field);
   m["is_extension"] = is_extension ? "True" : "False";
@@ -1106,7 +1164,7 @@
   // The C++ implementation doesn't guard against this either.  Leaving
   // it for now...
   std::string name = NamePrefixedWithNestedTypes(descriptor, "_");
-  ToUpper(&name);
+  absl::AsciiStrToUpper(&name);
   // Module-private for now.  Easy to make public later; almost impossible
   // to make private later.
   name = "_" + name;
@@ -1136,7 +1194,7 @@
 std::string Generator::ModuleLevelServiceDescriptorName(
     const ServiceDescriptor& descriptor) const {
   std::string name = descriptor.name();
-  ToUpper(&name);
+  absl::AsciiStrToUpper(&name);
   name = "_" + name;
   if (descriptor.file() != file_) {
     name = ModuleAlias(descriptor.file()->name()) + "." + name;
@@ -1144,6 +1202,16 @@
   return name;
 }
 
+std::string Generator::PublicPackage() const {
+  return opensource_runtime_ ? "google.protobuf"
+                             : "google3.net.google.protobuf.python.public";
+}
+
+std::string Generator::InternalPackage() const {
+  return opensource_runtime_ ? "google.protobuf.internal"
+                             : "google3.net.google.protobuf.python.internal";
+}
+
 // Prints standard constructor arguments serialized_start and serialized_end.
 // Args:
 //   descriptor: The cpp descriptor to have a serialized reference.
@@ -1165,8 +1233,8 @@
   printer_->Print(
       "$name$._serialized_start=$serialized_start$\n"
       "$name$._serialized_end=$serialized_end$\n",
-      "name", name, "serialized_start", StrCat(offset), "serialized_end",
-      StrCat(offset + sp.size()));
+      "name", name, "serialized_start", absl::StrCat(offset), "serialized_end",
+      absl::StrCat(offset + sp.size()));
 }
 
 namespace {
@@ -1256,7 +1324,7 @@
 void Generator::FixOptionsForOneof(const OneofDescriptor& oneof) const {
   std::string oneof_options = OptionsValue(oneof.options().SerializeAsString());
   if (oneof_options != "None") {
-    std::string oneof_name = strings::Substitute(
+    std::string oneof_name = absl::Substitute(
         "$0.$1['$2']", ModuleLevelDescriptorName(*oneof.containing_type()),
         "oneofs_by_name", oneof.name());
     PrintDescriptorOptionsFixingCode(oneof_name, oneof_options, printer_);
@@ -1278,7 +1346,7 @@
         OptionsValue(value_descriptor.options().SerializeAsString());
     if (value_options != "None") {
       PrintDescriptorOptionsFixingCode(
-          StringPrintf("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
+          absl::StrFormat("%s.values_by_name[\"%s\"]", descriptor_name.c_str(),
                           value_descriptor.name().c_str()),
           value_options, printer_);
     }
diff --git a/src/google/protobuf/compiler/python/generator.h b/src/google/protobuf/compiler/python/generator.h
index f1fecbc..3fa946d 100644
--- a/src/google/protobuf/compiler/python/generator.h
+++ b/src/google/protobuf/compiler/python/generator.h
@@ -37,11 +37,11 @@
 
 #include <string>
 
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/compiler/code_generator.h>
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/compiler/code_generator.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -64,9 +64,18 @@
 // If you create your own protocol compiler binary and you want it to support
 // Python output, you can do so by registering an instance of this
 // CodeGenerator with the CommandLineInterface in your main() function.
+
+struct GeneratorOptions {
+  bool generate_pyi = false;
+  bool annotate_pyi = false;
+  bool bootstrap = false;
+};
+
 class PROTOC_EXPORT Generator : public CodeGenerator {
  public:
   Generator();
+  Generator(const Generator&) = delete;
+  Generator& operator=(const Generator&) = delete;
   ~Generator() override;
 
   // CodeGenerator methods.
@@ -76,7 +85,13 @@
 
   uint64_t GetSupportedFeatures() const override;
 
+  void set_opensource_runtime(bool opensource) {
+    opensource_runtime_ = opensource;
+  }
+
  private:
+  GeneratorOptions ParseParameter(const std::string& parameter,
+                                  std::string* error) const;
   void PrintImports() const;
   void PrintFileDescriptor() const;
   void PrintAllNestedEnumsInFile() const;
@@ -128,6 +143,7 @@
       const FieldDescriptor& extension_field) const;
   void FixForeignFieldsInNestedExtensions(const Descriptor& descriptor) const;
 
+  void PrintTopBoilerplate() const;
   void PrintServices() const;
   void PrintServiceDescriptors() const;
   void PrintServiceDescriptor(const ServiceDescriptor& descriptor) const;
@@ -145,6 +161,8 @@
   std::string ModuleLevelMessageName(const Descriptor& descriptor) const;
   std::string ModuleLevelServiceDescriptorName(
       const ServiceDescriptor& descriptor) const;
+  std::string PublicPackage() const;
+  std::string InternalPackage() const;
 
   template <typename DescriptorT, typename DescriptorProtoT>
   void PrintSerializedPbInterval(const DescriptorT& descriptor,
@@ -166,13 +184,12 @@
 
   // Very coarse-grained lock to ensure that Generate() is reentrant.
   // Guards file_, printer_ and file_descriptor_serialized_.
-  mutable Mutex mutex_;
+  mutable absl::Mutex mutex_;
   mutable const FileDescriptor* file_;  // Set in Generate().  Under mutex_.
   mutable std::string file_descriptor_serialized_;
   mutable io::Printer* printer_;  // Set in Generate().  Under mutex_.
-  mutable bool pure_python_workable_;
 
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Generator);
+  bool opensource_runtime_ = true;
 };
 
 }  // namespace python
@@ -180,6 +197,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_PYTHON_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/python/helpers.cc b/src/google/protobuf/compiler/python/helpers.cc
index e4d3c13..e58ed9c 100644
--- a/src/google/protobuf/compiler/python/helpers.cc
+++ b/src/google/protobuf/compiler/python/helpers.cc
@@ -28,14 +28,18 @@
 // (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/python/helpers.h>
+#include "google/protobuf/compiler/python/helpers.h"
 
 #include <algorithm>
 
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "absl/strings/escaping.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/strip.h"
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
 
 namespace google {
 namespace protobuf {
@@ -45,8 +49,7 @@
 // Returns the Python module name expected for a given .proto filename.
 std::string ModuleName(const std::string& filename) {
   std::string basename = StripProto(filename);
-  ReplaceCharacters(&basename, "-", '_');
-  ReplaceCharacters(&basename, "/", '.');
+  absl::StrReplaceAll({{"-", "_"}, {"/", "."}}, &basename);
   return basename + "_pb2";
 }
 
@@ -68,7 +71,7 @@
     kKeywords + (sizeof(kKeywords) / sizeof(kKeywords[0]));
 
 bool ContainsPythonKeyword(const std::string& module_name) {
-  std::vector<std::string> tokens = Split(module_name, ".");
+  std::vector<std::string> tokens = absl::StrSplit(module_name, ".");
   for (int i = 0; i < static_cast<int>(tokens.size()); ++i) {
     if (std::find(kKeywords, kKeywordsEnd, tokens[i]) != kKeywordsEnd) {
       return true;
@@ -92,7 +95,7 @@
                         const std::string& suffix) {
   std::string module_name = ModuleName(file_des->name());
   std::string filename = module_name;
-  ReplaceCharacters(&filename, ".", '/');
+  absl::StrReplaceAll({{".", "/"}}, &filename);
   filename += suffix;
   return filename;
 }
@@ -101,6 +104,12 @@
   return file->service_count() > 0 && file->options().py_generic_services();
 }
 
+std::string GeneratedCodeToBase64(const GeneratedCodeInfo& annotations) {
+  std::string result;
+  absl::Base64Escape(annotations.SerializeAsString(), &result);
+  return result;
+}
+
 template <typename DescriptorT>
 std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
                                         const std::string& separator) {
diff --git a/src/google/protobuf/compiler/python/helpers.h b/src/google/protobuf/compiler/python/helpers.h
index a68ceb1..3741fbb 100644
--- a/src/google/protobuf/compiler/python/helpers.h
+++ b/src/google/protobuf/compiler/python/helpers.h
@@ -33,14 +33,15 @@
 
 #include <string>
 
-#include <google/protobuf/descriptor.h>
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace python {
 
-
 std::string ModuleName(const std::string& filename);
 std::string StrippedModuleName(const std::string& filename);
 bool ContainsPythonKeyword(const std::string& module_name);
@@ -49,6 +50,7 @@
 std::string GetFileName(const FileDescriptor* file_des,
                         const std::string& suffix);
 bool HasGenericServices(const FileDescriptor* file);
+std::string GeneratedCodeToBase64(const GeneratedCodeInfo& annotations);
 
 template <typename DescriptorT>
 std::string NamePrefixedWithNestedTypes(const DescriptorT& descriptor,
diff --git a/src/google/protobuf/compiler/python/plugin_unittest.cc b/src/google/protobuf/compiler/python/plugin_unittest.cc
index 7f9589b..b613f2d 100644
--- a/src/google/protobuf/compiler/python/plugin_unittest.cc
+++ b/src/google/protobuf/compiler/python/plugin_unittest.cc
@@ -33,15 +33,15 @@
 #include <memory>
 #include <string>
 
-#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/generator.h>
-#include <google/protobuf/io/printer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/testing/googletest.h>
+#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/generator.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "absl/strings/str_split.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
@@ -107,7 +107,7 @@
   std::string output;
   GOOGLE_CHECK_OK(File::GetContents(TestTempDir() + "/test1_pb2.py", &output,
                              true));
-  std::vector<std::string> lines = Split(output, "\n");
+  std::vector<std::string> lines = absl::StrSplit(output, "\n");
   std::string expected_import = "import test2_pb2";
   bool found_expected_import = false;
   for (int i = 0; i < lines.size(); ++i) {
diff --git a/src/google/protobuf/compiler/python/pyi_generator.cc b/src/google/protobuf/compiler/python/pyi_generator.cc
index 1ccc9a2..607a054 100644
--- a/src/google/protobuf/compiler/python/pyi_generator.cc
+++ b/src/google/protobuf/compiler/python/pyi_generator.cc
@@ -28,61 +28,58 @@
 // (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/python/pyi_generator.h>
+#include "google/protobuf/compiler/python/pyi_generator.h"
 
 #include <string>
+#include <utility>
 
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/compiler/python/helpers.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 "absl/container/flat_hash_set.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/compiler/python/helpers.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"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 namespace python {
 
-template <typename DescriptorT>
-struct SortByName {
-  bool operator()(const DescriptorT* l, const DescriptorT* r) const {
-    return l->name() < r->name();
-  }
-};
-
 PyiGenerator::PyiGenerator() : file_(nullptr) {}
 
 PyiGenerator::~PyiGenerator() {}
 
-void PyiGenerator::PrintItemMap(
-    const std::map<std::string, std::string>& item_map) const {
-  for (const auto& entry : item_map) {
-    printer_->Print("$key$: $value$\n", "key", entry.first, "value",
-                    entry.second);
-  }
-}
-
 template <typename DescriptorT>
-std::string PyiGenerator::ModuleLevelName(
-    const DescriptorT& descriptor,
-    const std::map<std::string, std::string>& import_map) const {
+std::string PyiGenerator::ModuleLevelName(const DescriptorT& descriptor) const {
   std::string name = NamePrefixedWithNestedTypes(descriptor, ".");
   if (descriptor.file() != file_) {
     std::string module_alias;
     std::string filename = descriptor.file()->name();
-    if (import_map.find(filename) == import_map.end()) {
+    if (import_map_.find(filename) == import_map_.end()) {
       std::string module_name = ModuleName(descriptor.file()->name());
-      std::vector<std::string> tokens = Split(module_name, ".");
+      std::vector<std::string> tokens = absl::StrSplit(module_name, ".");
       module_alias = "_" + tokens.back();
     } else {
-      module_alias = import_map.at(filename);
+      module_alias = import_map_.at(filename);
     }
     name = module_alias + "." + name;
   }
   return name;
 }
 
+std::string PyiGenerator::PublicPackage() const {
+  return opensource_runtime_ ? "google.protobuf"
+                             : "google3.net.google.protobuf.python.public";
+}
+
+std::string PyiGenerator::InternalPackage() const {
+  return opensource_runtime_ ? "google.protobuf.internal"
+                             : "google3.net.google.protobuf.python.internal";
+}
+
 struct ImportModules {
   bool has_repeated = false;    // _containers
   bool has_iterable = false;    // typing.Iterable
@@ -156,41 +153,40 @@
 
 void PyiGenerator::PrintImportForDescriptor(
     const FileDescriptor& desc,
-    std::map<std::string, std::string>* import_map,
-    std::set<std::string>* seen_aliases) const {
+    absl::flat_hash_set<std::string>* seen_aliases) const {
   const std::string& filename = desc.name();
-  std::string module_name = StrippedModuleName(filename);
+  std::string module_name_owned = StrippedModuleName(filename);
+  absl::string_view module_name(module_name_owned);
   size_t last_dot_pos = module_name.rfind('.');
   std::string import_statement;
   if (last_dot_pos == std::string::npos) {
-    import_statement = "import " + module_name;
+    import_statement = absl::StrCat("import ", module_name);
   } else {
-    import_statement = "from " + module_name.substr(0, last_dot_pos) +
-                       " import " + module_name.substr(last_dot_pos + 1);
+    import_statement =
+        absl::StrCat("from ", module_name.substr(0, last_dot_pos), " import ",
+                     module_name.substr(last_dot_pos + 1));
     module_name = module_name.substr(last_dot_pos + 1);
   }
-  std::string alias = "_" + module_name;
+  std::string alias = absl::StrCat("_", module_name);
   // Generate a unique alias by adding _1 suffixes until we get an unused alias.
   while (seen_aliases->find(alias) != seen_aliases->end()) {
     alias = alias + "_1";
   }
   printer_->Print("$statement$ as $alias$\n", "statement",
                   import_statement, "alias", alias);
-  (*import_map)[filename] = alias;
+  import_map_[filename] = alias;
   seen_aliases->insert(alias);
 }
 
-void PyiGenerator::PrintImports(
-    std::map<std::string, std::string>* item_map,
-    std::map<std::string, std::string>* import_map) const {
+void PyiGenerator::PrintImports() const {
   // Prints imported dependent _pb2 files.
-  std::set<std::string> seen_aliases;
+  absl::flat_hash_set<std::string> seen_aliases;
   for (int i = 0; i < file_->dependency_count(); ++i) {
     const FileDescriptor* dep = file_->dependency(i);
-    PrintImportForDescriptor(*dep, import_map, &seen_aliases);
+    PrintImportForDescriptor(*dep, &seen_aliases);
     for (int j = 0; j < dep->public_dependency_count(); ++j) {
       PrintImportForDescriptor(
-          *dep->public_dependency(j), import_map, &seen_aliases);
+          *dep->public_dependency(j), &seen_aliases);
     }
   }
 
@@ -202,6 +198,10 @@
   if (file_->enum_type_count() > 0) {
     import_modules.has_enums = true;
   }
+  if (!opensource_runtime_ && file_->service_count() > 0) {
+    import_modules.has_optional = true;
+    import_modules.has_union = true;
+  }
   for (int i = 0; i < file_->message_type_count(); i++) {
     CheckImportModules(file_->message_type(i), &import_modules);
   }
@@ -210,37 +210,50 @@
   // required in the proto file.
   if (import_modules.has_repeated) {
     printer_->Print(
-        "from google.protobuf.internal import containers as "
-        "_containers\n");
+        "from $internal_package$ import containers as _containers\n",
+        "internal_package", InternalPackage());
   }
   if (import_modules.has_enums) {
     printer_->Print(
-        "from google.protobuf.internal import enum_type_wrapper"
-        " as _enum_type_wrapper\n");
+        "from $internal_package$ import enum_type_wrapper as "
+        "_enum_type_wrapper\n",
+        "internal_package", InternalPackage());
   }
   if (import_modules.has_extendable) {
     printer_->Print(
-        "from google.protobuf.internal import python_message"
-        " as _python_message\n");
+        "from $internal_package$ import python_message as _python_message\n",
+        "internal_package", InternalPackage());
   }
   if (import_modules.has_well_known_type) {
     printer_->Print(
-        "from google.protobuf.internal import well_known_types"
-        " as _well_known_types\n");
+        "from $internal_package$ import well_known_types as "
+        "_well_known_types\n",
+        "internal_package", InternalPackage());
   }
-  printer_->Print(
-      "from google.protobuf import"
-      " descriptor as _descriptor\n");
+  printer_->Print("from $public_package$ import descriptor as _descriptor\n",
+                  "public_package", PublicPackage());
   if (import_modules.has_messages) {
-    printer_->Print(
-        "from google.protobuf import message as _message\n");
+    printer_->Print("from $public_package$ import message as _message\n",
+                    "public_package", PublicPackage());
   }
-  if (HasGenericServices(file_)) {
-    printer_->Print(
-        "from google.protobuf import service as"
-        " _service\n");
+  if (opensource_runtime_) {
+    if (HasGenericServices(file_)) {
+      printer_->Print("from $public_package$ import service as _service\n",
+                      "public_package", PublicPackage());
+    }
+  } else {
+    if (file_->service_count() > 0) {
+      printer_->Print(
+          "from google3.net.rpc.python import proto_python_api_2_stub as "
+          "_proto_python_api_2_stub\n"
+          "from google3.net.rpc.python import pywraprpc as _pywraprpc\n"
+          "from google3.net.rpc.python import rpcserver as _rpcserver\n");
+    }
   }
   printer_->Print("from typing import ");
+  if (!opensource_runtime_ && file_->service_count() > 0) {
+    printer_->Print("Any as _Any, ");
+  }
   printer_->Print("ClassVar as _ClassVar");
   if (import_modules.has_iterable) {
     printer_->Print(", Iterable as _Iterable");
@@ -254,7 +267,7 @@
   if (import_modules.has_union) {
     printer_->Print(", Union as _Union");
   }
-  printer_->Print("\n\n");
+  printer_->Print("\n");
 
   // Public imports
   for (int i = 0; i < file_->public_dependency_count(); ++i) {
@@ -272,17 +285,16 @@
                       module_name, "enum_class",
                       public_dep->enum_type(i)->name());
     }
-    // Enum values for public imports
-    for (int i = 0; i < public_dep->enum_type_count(); ++i) {
-      const EnumDescriptor* enum_descriptor = public_dep->enum_type(i);
-      for (int j = 0; j < enum_descriptor->value_count(); ++j) {
-        (*item_map)[enum_descriptor->value(j)->name()] =
-            ModuleLevelName(*enum_descriptor, *import_map);
-      }
-    }
-    // Top level extensions for public imports
-    AddExtensions(*public_dep, item_map);
   }
+printer_->Print("\n");
+}
+
+// Annotate wrapper for debugging purposes
+// Print a message after Annotate to see what is annotated.
+template <typename DescriptorT>
+void PyiGenerator::Annotate(const std::string& label,
+                            const DescriptorT* descriptor) const {
+printer_->Annotate(label.c_str(), descriptor);
 }
 
 void PyiGenerator::PrintEnum(const EnumDescriptor& enum_descriptor) const {
@@ -291,22 +303,31 @@
       "class $enum_name$(int, metaclass=_enum_type_wrapper.EnumTypeWrapper):\n"
       "    __slots__ = []\n",
       "enum_name", enum_name);
+  Annotate("enum_name", &enum_descriptor);
+  printer_->Indent();
+  PrintEnumValues(enum_descriptor, /* is_classvar = */ true);
+  printer_->Outdent();
 }
 
-// Adds enum value to item map which will be ordered and printed later.
-void PyiGenerator::AddEnumValue(
-    const EnumDescriptor& enum_descriptor,
-    std::map<std::string, std::string>* item_map,
-    const std::map<std::string, std::string>& import_map) const {
+void PyiGenerator::PrintEnumValues(const EnumDescriptor& enum_descriptor,
+                                   bool is_classvar) const {
   // enum values
-  std::string module_enum_name = ModuleLevelName(enum_descriptor, import_map);
+  std::string module_enum_name = ModuleLevelName(enum_descriptor);
   for (int j = 0; j < enum_descriptor.value_count(); ++j) {
     const EnumValueDescriptor* value_descriptor = enum_descriptor.value(j);
-    (*item_map)[value_descriptor->name()] = module_enum_name;
+    if (is_classvar) {
+      printer_->Print("$name$: _ClassVar[$module_enum_name$]\n", "name",
+                      value_descriptor->name(), "module_enum_name",
+                      module_enum_name);
+    } else {
+      printer_->Print("$name$: $module_enum_name$\n", "name",
+                      value_descriptor->name(), "module_enum_name",
+                      module_enum_name);
+    }
+    Annotate("name", value_descriptor);
   }
 }
 
-// Prints top level enums
 void PyiGenerator::PrintTopLevelEnums() const {
   for (int i = 0; i < file_->enum_type_count(); ++i) {
     printer_->Print("\n");
@@ -314,25 +335,23 @@
   }
 }
 
-// Add top level extensions to item_map which will be ordered and
-// printed later.
 template <typename DescriptorT>
-void PyiGenerator::AddExtensions(
-    const DescriptorT& descriptor,
-    std::map<std::string, std::string>* item_map) const {
+void PyiGenerator::PrintExtensions(const DescriptorT& descriptor) const {
   for (int i = 0; i < descriptor.extension_count(); ++i) {
     const FieldDescriptor* extension_field = descriptor.extension(i);
     std::string constant_name = extension_field->name() + "_FIELD_NUMBER";
-    ToUpper(&constant_name);
-    (*item_map)[constant_name] = "_ClassVar[int]";
-    (*item_map)[extension_field->name()] = "_descriptor.FieldDescriptor";
+    absl::AsciiStrToUpper(&constant_name);
+    printer_->Print("$constant_name$: _ClassVar[int]\n",
+                    "constant_name", constant_name);
+    printer_->Print("$name$: _descriptor.FieldDescriptor\n",
+                    "name", extension_field->name());
+    Annotate("name", extension_field);
   }
 }
 
 // Returns the string format of a field's cpp_type
 std::string PyiGenerator::GetFieldType(
-    const FieldDescriptor& field_des, const Descriptor& containing_des,
-    const std::map<std::string, std::string>& import_map) const {
+    const FieldDescriptor& field_des, const Descriptor& containing_des) const {
   switch (field_des.cpp_type()) {
     case FieldDescriptor::CPPTYPE_INT32:
     case FieldDescriptor::CPPTYPE_UINT32:
@@ -345,7 +364,7 @@
     case FieldDescriptor::CPPTYPE_BOOL:
       return "bool";
     case FieldDescriptor::CPPTYPE_ENUM:
-      return ModuleLevelName(*field_des.enum_type(), import_map);
+      return ModuleLevelName(*field_des.enum_type());
     case FieldDescriptor::CPPTYPE_STRING:
       if (field_des.type() == FieldDescriptor::TYPE_STRING) {
         return "str";
@@ -356,7 +375,7 @@
       // If the field is inside a nested message and the nested message has the
       // same name as a top-level message, then we need to prefix the field type
       // with the module name for disambiguation.
-      std::string name = ModuleLevelName(*field_des.message_type(), import_map);
+      std::string name = ModuleLevelName(*field_des.message_type());
       if ((containing_des.containing_type() != nullptr &&
            name == containing_des.name())) {
         std::string module = ModuleName(field_des.file()->name());
@@ -371,8 +390,7 @@
 }
 
 void PyiGenerator::PrintMessage(
-    const Descriptor& message_descriptor, bool is_nested,
-    const std::map<std::string, std::string>& import_map) const {
+    const Descriptor& message_descriptor, bool is_nested) const {
   if (!is_nested) {
     printer_->Print("\n");
   }
@@ -387,20 +405,14 @@
   }
   printer_->Print("class $class_name$(_message.Message$extra_base$):\n",
                   "class_name", class_name, "extra_base", extra_base);
+  Annotate("class_name", &message_descriptor);
   printer_->Indent();
-  printer_->Indent();
-
-  std::vector<const FieldDescriptor*> fields;
-  fields.reserve(message_descriptor.field_count());
-  for (int i = 0; i < message_descriptor.field_count(); ++i) {
-    fields.push_back(message_descriptor.field(i));
-  }
-  std::sort(fields.begin(), fields.end(), SortByName<FieldDescriptor>());
 
   // Prints slots
   printer_->Print("__slots__ = [", "class_name", class_name);
   bool first_item = true;
-  for (const auto& field_des : fields) {
+  for (int i = 0; i < message_descriptor.field_count(); ++i) {
+    const FieldDescriptor* field_des = message_descriptor.field(i);
     if (IsPythonKeyword(field_des->name())) {
       continue;
     }
@@ -413,48 +425,34 @@
   }
   printer_->Print("]\n");
 
-  std::map<std::string, std::string> item_map;
   // Prints Extensions for extendable messages
   if (message_descriptor.extension_range_count() > 0) {
-    item_map["Extensions"] = "_python_message._ExtensionDict";
+    printer_->Print("Extensions: _python_message._ExtensionDict\n");
   }
 
   // Prints nested enums
-  std::vector<const EnumDescriptor*> nested_enums;
-  nested_enums.reserve(message_descriptor.enum_type_count());
   for (int i = 0; i < message_descriptor.enum_type_count(); ++i) {
-    nested_enums.push_back(message_descriptor.enum_type(i));
-  }
-  std::sort(nested_enums.begin(), nested_enums.end(),
-            SortByName<EnumDescriptor>());
-
-  for (const auto& entry : nested_enums) {
-    PrintEnum(*entry);
-    // Adds enum value to item_map which will be ordered and printed later
-    AddEnumValue(*entry, &item_map, import_map);
+    PrintEnum(*message_descriptor.enum_type(i));
+    PrintEnumValues(*message_descriptor.enum_type(i));
   }
 
   // Prints nested messages
-  std::vector<const Descriptor*> nested_messages;
-  nested_messages.reserve(message_descriptor.nested_type_count());
   for (int i = 0; i < message_descriptor.nested_type_count(); ++i) {
-    nested_messages.push_back(message_descriptor.nested_type(i));
-  }
-  std::sort(nested_messages.begin(), nested_messages.end(),
-            SortByName<Descriptor>());
-
-  for (const auto& entry : nested_messages) {
-    PrintMessage(*entry, true, import_map);
+    PrintMessage(*message_descriptor.nested_type(i), true);
   }
 
-  // Adds extensions to item_map which will be ordered and printed later
-  AddExtensions(message_descriptor, &item_map);
+  PrintExtensions(message_descriptor);
 
-  // Adds field number and field descriptor to item_map
+  // Prints field number
   for (int i = 0; i < message_descriptor.field_count(); ++i) {
     const FieldDescriptor& field_des = *message_descriptor.field(i);
-    item_map[ToUpper(field_des.name()) + "_FIELD_NUMBER"] =
-        "_ClassVar[int]";
+    printer_->Print(
+      "$field_number_name$: _ClassVar[int]\n", "field_number_name",
+      absl::AsciiStrToUpper(field_des.name()) + "_FIELD_NUMBER");
+  }
+  // Prints field name and type
+  for (int i = 0; i < message_descriptor.field_count(); ++i) {
+    const FieldDescriptor& field_des = *message_descriptor.field(i);
     if (IsPythonKeyword(field_des.name())) {
       continue;
     }
@@ -465,27 +463,26 @@
       field_type = (value_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
                         ? "_containers.MessageMap["
                         : "_containers.ScalarMap[");
-      field_type += GetFieldType(*key_des, message_descriptor, import_map);
+      field_type += GetFieldType(*key_des, message_descriptor);
       field_type += ", ";
-      field_type += GetFieldType(*value_des, message_descriptor, import_map);
+      field_type += GetFieldType(*value_des, message_descriptor);
     } else {
       if (field_des.is_repeated()) {
         field_type = (field_des.cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE
                           ? "_containers.RepeatedCompositeFieldContainer["
                           : "_containers.RepeatedScalarFieldContainer[");
       }
-      field_type += GetFieldType(field_des, message_descriptor, import_map);
+      field_type += GetFieldType(field_des, message_descriptor);
     }
 
     if (field_des.is_repeated()) {
       field_type += "]";
     }
-    item_map[field_des.name()] = field_type;
+    printer_->Print("$name$: $type$\n",
+                    "name", field_des.name(), "type", field_type);
+    Annotate("name", &field_des);
   }
 
-  // Prints all items in item_map
-  PrintItemMap(item_map);
-
   // Prints __init__
   printer_->Print("def __init__(self");
   bool has_key_words = false;
@@ -505,6 +502,7 @@
     }
     is_first = false;
     printer_->Print(", $field_name$: ", "field_name", field_name);
+    Annotate("field_name", field_des);
     if (field_des->is_repeated() ||
         field_des->cpp_type() != FieldDescriptor::CPPTYPE_BOOL) {
       printer_->Print("_Optional[");
@@ -513,9 +511,9 @@
       const Descriptor* map_entry = field_des->message_type();
       printer_->Print(
           "_Mapping[$key_type$, $value_type$]", "key_type",
-          GetFieldType(*map_entry->field(0), message_descriptor, import_map),
+          GetFieldType(*map_entry->field(0), message_descriptor),
           "value_type",
-          GetFieldType(*map_entry->field(1), message_descriptor, import_map));
+          GetFieldType(*map_entry->field(1), message_descriptor));
     } else {
       if (field_des->is_repeated()) {
         printer_->Print("_Iterable[");
@@ -523,15 +521,15 @@
       if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
         printer_->Print(
             "_Union[$type_name$, _Mapping]", "type_name",
-            GetFieldType(*field_des, message_descriptor, import_map));
+            GetFieldType(*field_des, message_descriptor));
       } else {
         if (field_des->cpp_type() == FieldDescriptor::CPPTYPE_ENUM) {
           printer_->Print("_Union[$type_name$, str]", "type_name",
-                          ModuleLevelName(*field_des->enum_type(), import_map));
+                          ModuleLevelName(*field_des->enum_type()));
         } else {
           printer_->Print(
               "$type_name$", "type_name",
-              GetFieldType(*field_des, message_descriptor, import_map));
+              GetFieldType(*field_des, message_descriptor));
         }
       }
       if (field_des->is_repeated()) {
@@ -548,83 +546,92 @@
     printer_->Print(", **kwargs");
   }
   printer_->Print(") -> None: ...\n");
-
-  printer_->Outdent();
   printer_->Outdent();
 }
 
-void PyiGenerator::PrintMessages(
-    const std::map<std::string, std::string>& import_map) const {
+void PyiGenerator::PrintMessages() const {
   // Deterministically order the descriptors.
-  std::vector<const Descriptor*> messages;
-  messages.reserve(file_->message_type_count());
   for (int i = 0; i < file_->message_type_count(); ++i) {
-    messages.push_back(file_->message_type(i));
-  }
-  std::sort(messages.begin(), messages.end(), SortByName<Descriptor>());
-
-  for (const auto& entry : messages) {
-    PrintMessage(*entry, false, import_map);
+    PrintMessage(*file_->message_type(i), false);
   }
 }
 
 void PyiGenerator::PrintServices() const {
-  std::vector<const ServiceDescriptor*> services;
-  services.reserve(file_->service_count());
-  for (int i = 0; i < file_->service_count(); ++i) {
-    services.push_back(file_->service(i));
-  }
-  std::sort(services.begin(), services.end(), SortByName<ServiceDescriptor>());
-
   // Prints $Service$ and $Service$_Stub classes
-  for (const auto& entry : services) {
+  for (int i = 0; i < file_->service_count(); ++i) {
     printer_->Print("\n");
     printer_->Print(
         "class $service_name$(_service.service): ...\n\n"
         "class $service_name$_Stub($service_name$): ...\n",
-        "service_name", entry->name());
+        "service_name", file_->service(i)->name());
   }
 }
 
+
 bool PyiGenerator::Generate(const FileDescriptor* file,
                             const std::string& parameter,
                             GeneratorContext* context,
                             std::string* error) const {
-  MutexLock lock(&mutex_);
+  absl::MutexLock lock(&mutex_);
+  import_map_.clear();
   // Calculate file name.
   file_ = file;
-  std::string filename =
-      parameter.empty() ? GetFileName(file, ".pyi") : parameter;
+  // In google3, devtools/python/blaze/pytype/pytype_impl.bzl uses --pyi_out to
+  // directly set the output file name.
+  std::vector<std::pair<std::string, std::string> > options;
+  ParseGeneratorParameter(parameter, &options);
+
+  std::string filename;
+  bool annotate_code = false;
+  for (const std::pair<std::string, std::string>& option : options) {
+    if (option.first == "annotate_code") {
+      annotate_code = true;
+    } else if (absl::EndsWith(option.first, ".pyi")) {
+      filename = option.first;
+    } else {
+      *error = "Unknown generator option: " + option.first;
+      return false;
+    }
+  }
+
+  if (filename.empty()) {
+    filename = GetFileName(file, ".pyi");
+  }
 
   std::unique_ptr<io::ZeroCopyOutputStream> output(context->Open(filename));
   GOOGLE_CHECK(output.get());
-  io::Printer printer(output.get(), '$');
+  GeneratedCodeInfo annotations;
+  io::AnnotationProtoCollector<GeneratedCodeInfo> annotation_collector(
+      &annotations);
+  io::Printer::Options printer_opt(
+      '$', annotate_code ? &annotation_collector : nullptr);
+  printer_opt.spaces_per_indent = 4;
+  io::Printer printer(output.get(), printer_opt);
   printer_ = &printer;
 
-  // item map will store "DESCRIPTOR", top level extensions, top level enum
-  // values. The items will be sorted and printed later.
-  std::map<std::string, std::string> item_map;
+  PrintImports();
+  printer_->Print("DESCRIPTOR: _descriptor.FileDescriptor\n");
 
-  // Adds "DESCRIPTOR" into item_map.
-  item_map["DESCRIPTOR"] = "_descriptor.FileDescriptor";
-
-  // import_map will be a mapping from filename to module alias, e.g.
-  // "google3/foo/bar.py" -> "_bar"
-  std::map<std::string, std::string> import_map;
-
-  PrintImports(&item_map, &import_map);
-  // Adds top level enum values to item_map.
-  for (int i = 0; i < file_->enum_type_count(); ++i) {
-    AddEnumValue(*file_->enum_type(i), &item_map, import_map);
+  // Prints extensions and enums from imports.
+  for (int i = 0; i < file_->public_dependency_count(); ++i) {
+    const FileDescriptor* public_dep = file_->public_dependency(i);
+    PrintExtensions(*public_dep);
+    for (int i = 0; i < public_dep->enum_type_count(); ++i) {
+      const EnumDescriptor* enum_descriptor = public_dep->enum_type(i);
+      PrintEnumValues(*enum_descriptor);
+    }
   }
-  // Adds top level extensions to item_map.
-  AddExtensions(*file_, &item_map);
-  // Prints item map
-  PrintItemMap(item_map);
 
-  PrintMessages(import_map);
   PrintTopLevelEnums();
-  if (HasGenericServices(file)) {
+  // Prints top level enum values
+  for (int i = 0; i < file_->enum_type_count(); ++i) {
+    PrintEnumValues(*file_->enum_type(i));
+  }
+  // Prints top level Extensions
+  PrintExtensions(*file_);
+  PrintMessages();
+
+  if (opensource_runtime_ && HasGenericServices(file)) {
     PrintServices();
   }
   return true;
diff --git a/src/google/protobuf/compiler/python/pyi_generator.h b/src/google/protobuf/compiler/python/pyi_generator.h
index 9611ed4..fca8654 100644
--- a/src/google/protobuf/compiler/python/pyi_generator.h
+++ b/src/google/protobuf/compiler/python/pyi_generator.h
@@ -35,15 +35,15 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__
 #define GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__
 
-#include <map>
-#include <set>
 #include <string>
 
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/compiler/code_generator.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/compiler/code_generator.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +63,8 @@
 class PROTOC_EXPORT PyiGenerator : public google::protobuf::compiler::CodeGenerator {
  public:
   PyiGenerator();
+  PyiGenerator(const PyiGenerator&) = delete;
+  PyiGenerator& operator=(const PyiGenerator&) = delete;
   ~PyiGenerator() override;
 
   // CodeGenerator methods.
@@ -75,39 +77,38 @@
                 std::string* error) const override;
 
  private:
-  void PrintImportForDescriptor(const FileDescriptor& desc,
-                                std::map<std::string, std::string>* import_map,
-                                std::set<std::string>* seen_aliases) const;
-  void PrintImports(std::map<std::string, std::string>* item_map,
-                    std::map<std::string, std::string>* import_map) const;
-  void PrintEnum(const EnumDescriptor& enum_descriptor) const;
-  void AddEnumValue(const EnumDescriptor& enum_descriptor,
-                    std::map<std::string, std::string>* item_map,
-                    const std::map<std::string, std::string>& import_map) const;
+  void PrintImportForDescriptor(
+      const FileDescriptor& desc,
+      absl::flat_hash_set<std::string>* seen_aliases) const;
+  template <typename DescriptorT>
+  void Annotate(const std::string& label, const DescriptorT* descriptor) const;
+  void PrintImports() const;
   void PrintTopLevelEnums() const;
+  void PrintEnum(const EnumDescriptor& enum_descriptor) const;
+  void PrintEnumValues(const EnumDescriptor& enum_descriptor,
+                       bool is_classvar = false) const;
   template <typename DescriptorT>
-  void AddExtensions(const DescriptorT& descriptor,
-                     std::map<std::string, std::string>* item_map) const;
-  void PrintMessages(
-      const std::map<std::string, std::string>& import_map) const;
-  void PrintMessage(const Descriptor& message_descriptor, bool is_nested,
-                    const std::map<std::string, std::string>& import_map) const;
+  void PrintExtensions(const DescriptorT& descriptor) const;
+  void PrintMessages() const;
+  void PrintMessage(const Descriptor& message_descriptor, bool is_nested) const;
   void PrintServices() const;
-  void PrintItemMap(const std::map<std::string, std::string>& item_map) const;
   std::string GetFieldType(
-      const FieldDescriptor& field_des, const Descriptor& containing_des,
-      const std::map<std::string, std::string>& import_map) const;
+      const FieldDescriptor& field_des, const Descriptor& containing_des) const;
   template <typename DescriptorT>
-  std::string ModuleLevelName(
-      const DescriptorT& descriptor,
-      const std::map<std::string, std::string>& import_map) const;
+  std::string ModuleLevelName(const DescriptorT& descriptor) const;
+  std::string PublicPackage() const;
+  std::string InternalPackage() const;
+
+  bool opensource_runtime_ = true;
 
   // Very coarse-grained lock to ensure that Generate() is reentrant.
-  // Guards file_ and printer_.
-  mutable Mutex mutex_;
+  // Guards file_, printer_, and import_map_.
+  mutable absl::Mutex mutex_;
   mutable const FileDescriptor* file_;  // Set in Generate().  Under mutex_.
   mutable io::Printer* printer_;        // Set in Generate().  Under mutex_.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(PyiGenerator);
+  // import_map will be a mapping from filename to module alias, e.g.
+  // "google3/foo/bar.py" -> "_bar"
+  mutable absl::flat_hash_map<std::string, std::string> import_map_;
 };
 
 }  // namespace python
@@ -115,6 +116,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_PYTHON_PYI_GENERATOR_H__
diff --git a/src/google/protobuf/compiler/python/python_generator.h b/src/google/protobuf/compiler/python/python_generator.h
index 21d48cd..a46cf5e 100644
--- a/src/google/protobuf/compiler/python/python_generator.h
+++ b/src/google/protobuf/compiler/python/python_generator.h
@@ -1,6 +1,36 @@
+// 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_PYTHON_PYTHON_GENERATOR_H_
 #define GOOGLE_PROTOBUF_COMPILER_PYTHON_PYTHON_GENERATOR_H_
 
-#include <google/protobuf/compiler/python/generator.h>
+#include "google/protobuf/compiler/python/generator.h"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_PYTHON_PYTHON_GENERATOR_H_
diff --git a/src/google/protobuf/compiler/ruby/BUILD.bazel b/src/google/protobuf/compiler/ruby/BUILD.bazel
new file mode 100644
index 0000000..7abfeb6
--- /dev/null
+++ b/src/google/protobuf/compiler/ruby/BUILD.bazel
@@ -0,0 +1,70 @@
+################################################################################
+# Protocol Buffers Compiler - Ruby code generator
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "ruby",
+    srcs = ["ruby_generator.cc"],
+    hdrs = ["ruby_generator.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/compiler/ruby",
+    visibility = [
+        "//pkg:__pkg__",
+        "//src/google/protobuf/compiler:__pkg__",
+    ],
+    deps = [
+        "//src/google/protobuf:protobuf_nowkt",
+        "//src/google/protobuf/compiler:code_generator",
+    ],
+)
+
+cc_test(
+    name = "generator_unittest",
+    srcs = ["ruby_generator_unittest.cc"],
+    data = [
+        "ruby_generated_code.proto",
+        "ruby_generated_code_pb.rb",
+        "ruby_generated_code_proto2.proto",
+        "ruby_generated_code_proto2_import.proto",
+        "ruby_generated_code_proto2_pb.rb",
+        "ruby_generated_pkg_explicit.proto",
+        "ruby_generated_pkg_explicit_legacy.proto",
+        "ruby_generated_pkg_explicit_legacy_pb.rb",
+        "ruby_generated_pkg_explicit_pb.rb",
+        "ruby_generated_pkg_implicit.proto",
+        "ruby_generated_pkg_implicit_pb.rb",
+        "//src/google/protobuf:testdata",
+    ],
+    deps = [
+        ":ruby",
+        "//src/google/protobuf/compiler:command_line_interface",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//src/google/protobuf/compiler:__pkg__"],
+)
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code.proto b/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
index 70ec9f1..56173c2 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_code.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 package A.B.C;
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto
index ea7f783..cd4955d 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2.proto
@@ -1,3 +1,33 @@
+// 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";
 
 package A.B.C;
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto
index 9ec0738..9fc1719 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_code_proto2_import.proto
@@ -1,3 +1,33 @@
+// 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";
 
 package A.B.C;
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto
index 8d7c948..153cec6 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 package one.two.a_three;
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto
index 7a0d260..6515634 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_explicit_legacy.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 package one.two.a_three.and;
diff --git a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto
index 544db64..23eaa43 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto
+++ b/src/google/protobuf/compiler/ruby/ruby_generated_pkg_implicit.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 package one.two.a_three;
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.cc b/src/google/protobuf/compiler/ruby/ruby_generator.cc
index d4a53d5..be643d8 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.cc
@@ -28,17 +28,17 @@
 // (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/ruby/ruby_generator.h"
+
 #include <iomanip>
 #include <sstream>
 
-#include <google/protobuf/compiler/code_generator.h>
-#include <google/protobuf/compiler/plugin.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/compiler/ruby/ruby_generator.h>
+#include "google/protobuf/compiler/code_generator.h"
+#include "google/protobuf/compiler/plugin.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"
 
 namespace google {
 namespace protobuf {
@@ -68,7 +68,7 @@
 }
 
 std::string GetRequireName(const std::string& proto_file) {
-  int lastindex = proto_file.find_last_of(".");
+  int lastindex = proto_file.find_last_of('.');
   return proto_file.substr(0, lastindex) + "_pb";
 }
 
@@ -421,7 +421,7 @@
     //    -> A.B.C
     if (package_name.find("::") != std::string::npos) {
       need_change_to_module = false;
-    } else if (package_name.find(".") != std::string::npos) {
+    } else if (package_name.find('.') != std::string::npos) {
       GOOGLE_LOG(WARNING) << "ruby_package option should be in the form of:"
                           << " 'A::B::C' and not 'A.B.C'";
     }
diff --git a/src/google/protobuf/compiler/ruby/ruby_generator.h b/src/google/protobuf/compiler/ruby/ruby_generator.h
index 647bb83..a6881ff 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator.h
+++ b/src/google/protobuf/compiler/ruby/ruby_generator.h
@@ -35,9 +35,9 @@
 
 #include <string>
 
-#include <google/protobuf/compiler/code_generator.h>
+#include "google/protobuf/compiler/code_generator.h"
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -62,6 +62,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 c3ce1d3..31d3770 100644
--- a/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
+++ b/src/google/protobuf/compiler/ruby/ruby_generator_unittest.cc
@@ -28,17 +28,17 @@
 // (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 <memory>
+#include "google/protobuf/compiler/ruby/ruby_generator.h"
+
 #include <list>
+#include <memory>
 
-#include <google/protobuf/compiler/ruby/ruby_generator.h>
-#include <google/protobuf/compiler/command_line_interface.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/printer.h>
-
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/testing/file.h>
+#include "google/protobuf/compiler/command_line_interface.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/scc.h b/src/google/protobuf/compiler/scc.h
index 7b95689..c9a112a 100644
--- a/src/google/protobuf/compiler/scc.h
+++ b/src/google/protobuf/compiler/scc.h
@@ -31,14 +31,17 @@
 #ifndef GOOGLE_PROTOBUF_COMPILER_SCC_H__
 #define GOOGLE_PROTOBUF_COMPILER_SCC_H__
 
-#include <map>
+#include <memory>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/memory/memory.h"
+#include "google/protobuf/descriptor.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -64,10 +67,15 @@
 class PROTOC_EXPORT SCCAnalyzer {
  public:
   explicit SCCAnalyzer() : index_(0) {}
+  SCCAnalyzer(const SCCAnalyzer&) = delete;
+  SCCAnalyzer& operator=(const SCCAnalyzer&) = delete;
 
   const SCC* GetSCC(const Descriptor* descriptor) {
-    if (cache_.count(descriptor)) return cache_[descriptor].scc;
-    return DFS(descriptor).scc;
+    auto it = cache_.find(descriptor);
+    if (it == cache_.end()) {
+      return DFS(descriptor).scc;
+    }
+    return it->second->scc;
   }
 
  private:
@@ -77,7 +85,7 @@
     int lowlink;
   };
 
-  std::map<const Descriptor*, NodeData> cache_;
+  absl::flat_hash_map<const Descriptor*, std::unique_ptr<NodeData>> cache_;
   std::vector<const Descriptor*> stack_;
   int index_;
   std::vector<std::unique_ptr<SCC>> garbage_bin_;
@@ -89,24 +97,25 @@
 
   // Tarjan's Strongly Connected Components algo
   NodeData DFS(const Descriptor* descriptor) {
-    // Must not have visited already.
-    GOOGLE_DCHECK_EQ(cache_.count(descriptor), 0);
-
     // Mark visited by inserting in map.
-    NodeData& result = cache_[descriptor];
+    auto ins = cache_.try_emplace(descriptor, absl::make_unique<NodeData>());
+    // Must not have visited already.
+    GOOGLE_DCHECK(ins.second);
+    NodeData& result = *ins.first->second;
     // Initialize data structures.
     result.index = result.lowlink = index_++;
     stack_.push_back(descriptor);
 
     // Recurse the fields / nodes in graph
-    for (auto dep : DepsGenerator()(descriptor)) {
+    for (const auto* dep : DepsGenerator()(descriptor)) {
       GOOGLE_CHECK(dep);
-      if (cache_.count(dep) == 0) {
+      auto it = cache_.find(dep);
+      if (it == cache_.end()) {
         // unexplored node
         NodeData child_data = DFS(dep);
         result.lowlink = std::min(result.lowlink, child_data.lowlink);
       } else {
-        NodeData child_data = cache_[dep];
+        NodeData& child_data = *it->second;
         if (child_data.scc == nullptr) {
           // Still in the stack_ so we found a back edge
           result.lowlink = std::min(result.lowlink, child_data.index);
@@ -121,7 +130,7 @@
         scc->descriptors.push_back(scc_desc);
         // Remove from stack
         stack_.pop_back();
-        cache_[scc_desc].scc = scc;
+        cache_[scc_desc]->scc = scc;
 
         if (scc_desc == descriptor) break;
       }
@@ -139,7 +148,7 @@
 
   // Add the SCC's that are children of this SCC to its children.
   void AddChildren(SCC* scc) {
-    std::set<const SCC*> seen;
+    absl::flat_hash_set<const SCC*> seen;
     for (auto descriptor : scc->descriptors) {
       for (auto child_msg : DepsGenerator()(descriptor)) {
         GOOGLE_CHECK(child_msg);
@@ -151,15 +160,12 @@
       }
     }
   }
-
-  // This is necessary for compiler bug in msvc2015.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SCCAnalyzer);
 };
 
 }  // namespace compiler
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_SCC_H__
diff --git a/src/google/protobuf/compiler/subprocess.cc b/src/google/protobuf/compiler/subprocess.cc
index 6f547db..ae1f5dd 100644
--- a/src/google/protobuf/compiler/subprocess.cc
+++ b/src/google/protobuf/compiler/subprocess.cc
@@ -30,7 +30,7 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <google/protobuf/compiler/subprocess.h>
+#include "google/protobuf/compiler/subprocess.h"
 
 #include <algorithm>
 #include <cstring>
@@ -43,26 +43,17 @@
 #include <sys/wait.h>
 #endif
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/io/io_win32.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/message.h"
 
 namespace google {
 namespace protobuf {
 namespace compiler {
 
-namespace {
-char* portable_strdup(const char* s) {
-  char* ns = (char*)malloc(strlen(s) + 1);
-  if (ns != nullptr) {
-    strcpy(ns, s);
-  }
-  return ns;
-}
-}  // namespace
-
 #ifdef _WIN32
 
 static void CloseHandleOrDie(HANDLE handle) {
@@ -273,12 +264,12 @@
   child_handle_ = nullptr;
 
   if (exit_code != 0) {
-    *error = strings::Substitute("Plugin failed with status code $0.", exit_code);
+    *error = absl::Substitute("Plugin failed with status code $0.", exit_code);
     return false;
   }
 
   if (!output->ParseFromString(output_data)) {
-    *error = "Plugin output is unparseable: " + CEscape(output_data);
+    *error = "Plugin output is unparseable: " + absl::CEscape(output_data);
     return false;
   }
 
@@ -317,6 +308,16 @@
   }
 }
 
+namespace {
+char* portable_strdup(const char* s) {
+  char* ns = (char*)malloc(strlen(s) + 1);
+  if (ns != nullptr) {
+    strcpy(ns, s);
+  }
+  return ns;
+}
+}  // namespace
+
 void Subprocess::Start(const std::string& program, SearchMode search_mode) {
   // Note that we assume that there are no other threads, thus we don't have to
   // do crazy stuff like using socket pairs or avoiding libc locks.
@@ -471,12 +472,12 @@
     if (WEXITSTATUS(status) != 0) {
       int error_code = WEXITSTATUS(status);
       *error =
-          strings::Substitute("Plugin failed with status code $0.", error_code);
+          absl::Substitute("Plugin failed with status code $0.", error_code);
       return false;
     }
   } else if (WIFSIGNALED(status)) {
     int signal = WTERMSIG(status);
-    *error = strings::Substitute("Plugin killed by signal $0.", signal);
+    *error = absl::Substitute("Plugin killed by signal $0.", signal);
     return false;
   } else {
     *error = "Neither WEXITSTATUS nor WTERMSIG is true?";
@@ -484,7 +485,7 @@
   }
 
   if (!output->ParseFromString(output_data)) {
-    *error = "Plugin output is unparseable: " + CEscape(output_data);
+    *error = "Plugin output is unparseable: " + absl::CEscape(output_data);
     return false;
   }
 
diff --git a/src/google/protobuf/compiler/subprocess.h b/src/google/protobuf/compiler/subprocess.h
index 5cb784d..b6bf282 100644
--- a/src/google/protobuf/compiler/subprocess.h
+++ b/src/google/protobuf/compiler/subprocess.h
@@ -42,12 +42,12 @@
 #include <sys/types.h>
 #include <unistd.h>
 #endif  // !_WIN32
-#include <google/protobuf/stubs/common.h>
-
 #include <string>
 
+#include "google/protobuf/port.h"
+
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -109,6 +109,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMPILER_SUBPROCESS_H__
diff --git a/src/google/protobuf/compiler/test_plugin.cc b/src/google/protobuf/compiler/test_plugin.cc
index 2556078..2ed1e3d 100644
--- a/src/google/protobuf/compiler/test_plugin.cc
+++ b/src/google/protobuf/compiler/test_plugin.cc
@@ -37,8 +37,8 @@
 
 #include <string>
 
-#include <google/protobuf/compiler/mock_code_generator.h>
-#include <google/protobuf/compiler/plugin.h>
+#include "google/protobuf/compiler/mock_code_generator.h"
+#include "google/protobuf/compiler/plugin.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/zip_writer.cc b/src/google/protobuf/compiler/zip_writer.cc
index 72e1d71..73b9ef5 100644
--- a/src/google/protobuf/compiler/zip_writer.cc
+++ b/src/google/protobuf/compiler/zip_writer.cc
@@ -33,11 +33,11 @@
 //
 // Based on http://www.pkware.com/documents/casestudies/APPNOTE.TXT
 
-#include <google/protobuf/compiler/zip_writer.h>
+#include "google/protobuf/compiler/zip_writer.h"
 
 #include <cstdint>
 
-#include <google/protobuf/io/coded_stream.h>
+#include "google/protobuf/io/coded_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/compiler/zip_writer.h b/src/google/protobuf/compiler/zip_writer.h
index 5d7f69a..89717c7 100644
--- a/src/google/protobuf/compiler/zip_writer.h
+++ b/src/google/protobuf/compiler/zip_writer.h
@@ -35,8 +35,8 @@
 #include <cstdint>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/zero_copy_stream.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/descriptor.cc b/src/google/protobuf/descriptor.cc
index 5f3427d..701abfa 100644
--- a/src/google/protobuf/descriptor.cc
+++ b/src/google/protobuf/descriptor.cc
@@ -32,10 +32,11 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 
 #include <algorithm>
 #include <array>
+#include <cstdlib>
 #include <functional>
 #include <limits>
 #include <map>
@@ -44,53 +45,46 @@
 #include <sstream>
 #include <string>
 #include <type_traits>
-#include <unordered_map>
-#include <unordered_set>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/once.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>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/descriptor_database.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/io/strtod.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/hash.h>
-
-#undef PACKAGE  // autoheader #defines this.  :(
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/base/dynamic_annotations.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/hash/hash.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/substitute.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/any.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/descriptor_database.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/unknown_field_set.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
-
 namespace {
+using ::google::protobuf::internal::DownCast;
+
 const int kPackageLimit = 100;
 
-// Note:  I distrust ctype.h due to locales.
-char ToUpper(char ch) {
-  return (ch >= 'a' && ch <= 'z') ? (ch - 'a' + 'A') : ch;
-}
-
-char ToLower(char ch) {
-  return (ch >= 'A' && ch <= 'Z') ? (ch - 'A' + 'a') : ch;
-}
 
 std::string ToCamelCase(const std::string& input, bool lower_first) {
   bool capitalize_next = !lower_first;
@@ -101,7 +95,7 @@
     if (character == '_') {
       capitalize_next = true;
     } else if (capitalize_next) {
-      result.push_back(ToUpper(character));
+      result.push_back(absl::ascii_toupper(character));
       capitalize_next = false;
     } else {
       result.push_back(character);
@@ -110,7 +104,7 @@
 
   // Lower-case the first letter.
   if (lower_first && !result.empty()) {
-    result[0] = ToLower(result[0]);
+    result[0] = absl::ascii_tolower(result[0]);
   }
 
   return result;
@@ -125,7 +119,7 @@
     if (character == '_') {
       capitalize_next = true;
     } else if (capitalize_next) {
-      result.push_back(ToUpper(character));
+      result.push_back(absl::ascii_toupper(character));
       capitalize_next = false;
     } else {
       result.push_back(character);
@@ -430,13 +424,13 @@
     }
 
     std::string lowercase_name = name;
-    LowerString(&lowercase_name);
+    absl::AsciiStrToLower(&lowercase_name);
 
     std::string camelcase_name = ToCamelCase(name, /* lower_first = */ true);
     std::string json_name =
         opt_json_name != nullptr ? *opt_json_name : ToJsonName(name);
 
-    StringPiece all_names[] = {name, lowercase_name, camelcase_name,
+    absl::string_view all_names[] = {name, lowercase_name, camelcase_name,
                                      json_name};
     std::sort(all_names, all_names + 4);
     int unique =
@@ -457,7 +451,7 @@
     GOOGLE_CHECK(has_allocated());
 
     std::string full_name =
-        scope.empty() ? name : StrCat(scope, ".", name);
+        scope.empty() ? name : absl::StrCat(scope, ".", name);
 
     // Fast path for snake_case names, which follow the style guide.
     if (opt_json_name == nullptr) {
@@ -494,7 +488,7 @@
     FieldNamesResult result{nullptr, 0, 0, 0};
 
     std::string lowercase_name = name;
-    LowerString(&lowercase_name);
+    absl::AsciiStrToLower(&lowercase_name);
     result.lowercase_index = push_name(std::move(lowercase_name));
     result.camelcase_index =
         push_name(ToCamelCase(name, /* lower_first = */ true));
@@ -575,7 +569,6 @@
     METHOD,
     FULL_PACKAGE,
     SUB_PACKAGE,
-    QUERY_KEY
   };
 
   Symbol() {
@@ -641,35 +634,6 @@
                : nullptr;
   }
 
-  // Not a real symbol.
-  // Only used for heterogeneous lookups and never actually inserted in the
-  // tables.
-  // TODO(b/215557658): If we templetize QueryKey on the expected object type we
-  // can skip the switches for the eq function altogether.
-  struct QueryKey : internal::SymbolBase {
-    StringPiece name;
-    const void* parent;
-    int field_number;
-
-    // Adaptor functions to look like a Symbol to the comparators.
-    StringPiece full_name() const { return name; }
-    std::pair<const void*, int> parent_number_key() const {
-      return {parent, field_number};
-    }
-    std::pair<const void*, StringPiece> parent_name_key() const {
-      return {parent, name};
-    }
-  };
-  // This constructor is implicit to allow for non-transparent lookups when
-  // necessary.
-  // For transparent lookup cases we query directly with the object without the
-  // type erasure layer.
-  Symbol(QueryKey& value) : ptr_(&value) {  // NOLINT
-    value.symbol_type_ = QUERY_KEY;
-  }
-  const QueryKey* query_key() const {
-    return type() == QUERY_KEY ? static_cast<const QueryKey*>(ptr_) : nullptr;
-  }
 #undef DEFINE_MEMBERS
 
   Type type() const { return static_cast<Type>(ptr_->symbol_type_); }
@@ -707,7 +671,7 @@
     }
   }
 
-  StringPiece full_name() const {
+  absl::string_view full_name() const {
     switch (type()) {
       case MESSAGE:
         return descriptor()->full_name();
@@ -726,17 +690,15 @@
       case FULL_PACKAGE:
         return file_descriptor()->package();
       case SUB_PACKAGE:
-        return StringPiece(sub_package_file_descriptor()->file->package())
+        return absl::string_view(sub_package_file_descriptor()->file->package())
             .substr(0, sub_package_file_descriptor()->name_size);
-      case QUERY_KEY:
-        return query_key()->full_name();
       default:
         GOOGLE_CHECK(false);
     }
     return "";
   }
 
-  std::pair<const void*, StringPiece> parent_name_key() const {
+  std::pair<const void*, absl::string_view> parent_name_key() const {
     const auto or_file = [&](const void* p) { return p ? p : GetFile(); };
     switch (type()) {
       case MESSAGE:
@@ -763,24 +725,6 @@
         return {GetFile(), service_descriptor()->name()};
       case METHOD:
         return {method_descriptor()->service(), method_descriptor()->name()};
-      case QUERY_KEY:
-        return query_key()->parent_name_key();
-      default:
-        GOOGLE_CHECK(false);
-    }
-    return {};
-  }
-
-  std::pair<const void*, int> parent_number_key() const {
-    switch (type()) {
-      case FIELD:
-        return {field_descriptor()->containing_type(),
-                field_descriptor()->number()};
-      case ENUM_VALUE:
-        return {enum_value_descriptor()->type(),
-                enum_value_descriptor()->number()};
-      case QUERY_KEY:
-        return query_key()->parent_number_key();
       default:
         GOOGLE_CHECK(false);
     }
@@ -894,9 +838,9 @@
       next_upper = true;
     } else {
       if (next_upper) {
-        result.push_back(ToUpper(character));
+        result.push_back(absl::ascii_toupper(character));
       } else {
-        result.push_back(ToLower(character));
+        result.push_back(absl::ascii_tolower(character));
       }
       next_upper = false;
     }
@@ -908,18 +852,18 @@
 // Class to remove an enum prefix from enum values.
 class PrefixRemover {
  public:
-  PrefixRemover(StringPiece prefix) {
+  PrefixRemover(absl::string_view prefix) {
     // Strip underscores and lower-case the prefix.
     for (char character : prefix) {
       if (character != '_') {
-        prefix_ += ascii_tolower(character);
+        prefix_ += absl::ascii_tolower(character);
       }
     }
   }
 
   // Tries to remove the enum prefix from this enum value.
   // If this is not possible, returns the input verbatim.
-  std::string MaybeRemove(StringPiece str) {
+  std::string MaybeRemove(absl::string_view str) {
     // We can't just lowercase and strip str and look for a prefix.
     // We need to properly recognize the difference between:
     //
@@ -938,7 +882,7 @@
         continue;
       }
 
-      if (ascii_tolower(str[i]) != prefix_[j++]) {
+      if (absl::ascii_tolower(str[i]) != prefix_[j++]) {
         return std::string(str);
       }
     }
@@ -975,60 +919,16 @@
 // hash-maps for each object.
 //
 // The keys to these hash-maps are (parent, name) or (parent, number) pairs.
-
-typedef std::pair<const void*, StringPiece> PointerStringPair;
-
-typedef std::pair<const Descriptor*, int> DescriptorIntPair;
-
-#define HASH_MAP std::unordered_map
-#define HASH_SET std::unordered_set
-#define HASH_FXN hash
-
-template <typename PairType>
-struct PointerIntegerPairHash {
-  size_t operator()(const PairType& p) const {
-    static const size_t prime1 = 16777499;
-    static const size_t prime2 = 16777619;
-    return reinterpret_cast<size_t>(p.first) * prime1 ^
-           static_cast<size_t>(p.second) * prime2;
-  }
-
-#ifdef _MSC_VER
-  // Used only by MSVC and platforms where hash_map is not available.
-  static const size_t bucket_size = 4;
-  static const size_t min_buckets = 8;
-#endif
-  inline bool operator()(const PairType& a, const PairType& b) const {
-    return a < b;
-  }
+struct FullNameQuery {
+  absl::string_view query;
+  absl::string_view full_name() const { return query; }
 };
-
-struct PointerStringPairHash {
-  size_t operator()(const PointerStringPair& p) const {
-    static const size_t prime = 16777619;
-    hash<StringPiece> string_hash;
-    return reinterpret_cast<size_t>(p.first) * prime ^
-           static_cast<size_t>(string_hash(p.second));
-  }
-
-#ifdef _MSC_VER
-  // Used only by MSVC and platforms where hash_map is not available.
-  static const size_t bucket_size = 4;
-  static const size_t min_buckets = 8;
-#endif
-  inline bool operator()(const PointerStringPair& a,
-                         const PointerStringPair& b) const {
-    return a < b;
-  }
-};
-
-
 struct SymbolByFullNameHash {
   using is_transparent = void;
 
   template <typename T>
   size_t operator()(const T& s) const {
-    return HASH_FXN<StringPiece>{}(s.full_name());
+    return absl::HashOf(s.full_name());
   }
 };
 struct SymbolByFullNameEq {
@@ -1040,14 +940,20 @@
   }
 };
 using SymbolsByNameSet =
-    HASH_SET<Symbol, SymbolByFullNameHash, SymbolByFullNameEq>;
+    absl::flat_hash_set<Symbol, SymbolByFullNameHash, SymbolByFullNameEq>;
 
+struct ParentNameQuery {
+  std::pair<const void*, absl::string_view> query;
+  std::pair<const void*, absl::string_view> parent_name_key() const {
+    return query;
+  }
+};
 struct SymbolByParentHash {
   using is_transparent = void;
 
   template <typename T>
   size_t operator()(const T& s) const {
-    return PointerStringPairHash{}(s.parent_name_key());
+    return absl::HashOf(s.parent_name_key());
   }
 };
 struct SymbolByParentEq {
@@ -1059,52 +965,94 @@
   }
 };
 using SymbolsByParentSet =
-    HASH_SET<Symbol, SymbolByParentHash, SymbolByParentEq>;
+    absl::flat_hash_set<Symbol, SymbolByParentHash, SymbolByParentEq>;
 
-typedef HASH_MAP<StringPiece, const FileDescriptor*,
-                 HASH_FXN<StringPiece>>
-    FilesByNameMap;
+struct FilesByNameHash {
+  using is_transparent = void;
 
-typedef HASH_MAP<PointerStringPair, const FieldDescriptor*,
-                 PointerStringPairHash>
-    FieldsByNameMap;
+  size_t operator()(absl::string_view name) const { return absl::HashOf(name); }
 
-struct FieldsByNumberHash {
+  size_t operator()(const FileDescriptor* file) const {
+    return absl::HashOf(file->name());
+  }
+};
+
+struct FilesByNameEq {
+  using is_transparent = void;
+
+  bool operator()(absl::string_view lhs, absl::string_view rhs) const {
+    return lhs == rhs;
+  }
+  bool operator()(absl::string_view lhs, const FileDescriptor* rhs) const {
+    return lhs == rhs->name();
+  }
+  bool operator()(const FileDescriptor* lhs, absl::string_view rhs) const {
+    return lhs->name() == rhs;
+  }
+  bool operator()(const FileDescriptor* lhs, const FileDescriptor* rhs) const {
+    return lhs == rhs || lhs->name() == rhs->name();
+  }
+};
+using FilesByNameSet =
+    absl::flat_hash_set<const FileDescriptor*, FilesByNameHash, FilesByNameEq>;
+
+using FieldsByNameMap =
+    absl::flat_hash_map<std::pair<const void*, absl::string_view>,
+                        const FieldDescriptor*>;
+
+struct ParentNumberQuery {
+  std::pair<const void*, int> query;
+};
+std::pair<const void*, int> ObjectToParentNumber(const FieldDescriptor* field) {
+  return {field->containing_type(), field->number()};
+}
+std::pair<const void*, int> ObjectToParentNumber(
+    const EnumValueDescriptor* enum_value) {
+  return {enum_value->type(), enum_value->number()};
+}
+std::pair<const void*, int> ObjectToParentNumber(ParentNumberQuery query) {
+  return query.query;
+}
+struct ParentNumberHash {
   using is_transparent = void;
 
   template <typename T>
-  size_t operator()(const T& s) const {
-    return PointerIntegerPairHash<std::pair<const void*, int>>{}(
-        s.parent_number_key());
+  size_t operator()(const T& t) const {
+    return absl::HashOf(ObjectToParentNumber(t));
   }
 };
-struct FieldsByNumberEq {
+struct ParentNumberEq {
   using is_transparent = void;
 
   template <typename T, typename U>
   bool operator()(const T& a, const U& b) const {
-    return a.parent_number_key() == b.parent_number_key();
+    return ObjectToParentNumber(a) == ObjectToParentNumber(b);
   }
 };
-using FieldsByNumberSet =
-    HASH_SET<Symbol, FieldsByNumberHash, FieldsByNumberEq>;
-using EnumValuesByNumberSet = FieldsByNumberSet;
+using FieldsByNumberSet = absl::flat_hash_set<const FieldDescriptor*,
+                                              ParentNumberHash, ParentNumberEq>;
+using EnumValuesByNumberSet =
+    absl::flat_hash_set<const EnumValueDescriptor*, ParentNumberHash,
+                        ParentNumberEq>;
 
 // This is a map rather than a hash-map, since we use it to iterate
 // through all the extensions that extend a given Descriptor, and an
 // ordered data structure that implements lower_bound is convenient
 // for that.
-typedef std::map<DescriptorIntPair, const FieldDescriptor*>
-    ExtensionsGroupedByDescriptorMap;
-typedef HASH_MAP<std::string, const SourceCodeInfo_Location*>
-    LocationsByPathMap;
+using ExtensionsGroupedByDescriptorMap =
+    std::map<std::pair<const Descriptor*, int>, const FieldDescriptor*>;
+using LocationsByPathMap =
+    absl::flat_hash_map<std::string, const SourceCodeInfo_Location*>;
 
-std::set<std::string>* NewAllowedProto3Extendee() {
-  auto allowed_proto3_extendees = new std::set<std::string>;
+absl::flat_hash_set<std::string>* NewAllowedProto3Extendee() {
   const char* kOptionNames[] = {
       "FileOptions",   "MessageOptions",   "FieldOptions",
       "EnumOptions",   "EnumValueOptions", "ServiceOptions",
       "MethodOptions", "OneofOptions",     "ExtensionRangeOptions"};
+  auto allowed_proto3_extendees = new absl::flat_hash_set<std::string>();
+  allowed_proto3_extendees->reserve(sizeof(kOptionNames) /
+                                    sizeof(kOptionNames[0]));
+
   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
@@ -1113,7 +1061,7 @@
                                      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." + option_name);
+    allowed_proto3_extendees->insert(std::string("proto2.") + option_name);
   }
   return allowed_proto3_extendees;
 }
@@ -1151,16 +1099,19 @@
   // Finding items.
 
   // Returns a null Symbol (symbol.IsNull() is true) if not found.
+  // TODO(sbenza): All callers to this function know the type they are looking
+  // for. If we propagate that information statically we can make the query
+  // faster.
   inline Symbol FindNestedSymbol(const void* parent,
-                                 StringPiece name) const;
+                                 absl::string_view name) const;
 
   // These return nullptr if not found.
   inline const FieldDescriptor* FindFieldByNumber(const Descriptor* parent,
                                                   int number) const;
   inline const FieldDescriptor* FindFieldByLowercaseName(
-      const void* parent, StringPiece lowercase_name) const;
+      const void* parent, absl::string_view lowercase_name) const;
   inline const FieldDescriptor* FindFieldByCamelcaseName(
-      const void* parent, StringPiece camelcase_name) const;
+      const void* parent, absl::string_view 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.
@@ -1178,7 +1129,7 @@
   bool AddEnumValueByNumber(EnumValueDescriptor* value);
 
   // Populates p->first->locations_by_path_ from p->second.
-  // Unusual signature dictated by internal::call_once.
+  // Unusual signature dictated by absl::call_once.
   static void BuildLocationsByPath(
       std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p);
 
@@ -1203,8 +1154,8 @@
   void FieldsByCamelcaseNamesLazyInitInternal() const;
 
   SymbolsByParentSet symbols_by_parent_;
-  mutable internal::once_flag fields_by_lowercase_name_once_;
-  mutable internal::once_flag fields_by_camelcase_name_once_;
+  mutable absl::once_flag fields_by_lowercase_name_once_;
+  mutable absl::once_flag fields_by_camelcase_name_once_;
   // Make these fields atomic to avoid race conditions with
   // GetEstimatedOwnedMemoryBytesSize. Once the pointer is set the map won't
   // change anymore.
@@ -1216,12 +1167,12 @@
       PROTOBUF_GUARDED_BY(unknown_enum_values_mu_);
 
   // Populated on first request to save space, hence constness games.
-  mutable internal::once_flag locations_by_path_once_;
+  mutable absl::once_flag locations_by_path_once_;
   mutable LocationsByPathMap locations_by_path_;
 
   // Mutex to protect the unknown-enum-value map due to dynamic
   // EnumValueDescriptor creation on unknown values.
-  mutable internal::WrappedMutex unknown_enum_values_mu_;
+  mutable absl::Mutex unknown_enum_values_mu_;
 };
 
 namespace internal {
@@ -1303,39 +1254,39 @@
   // execution of the current public API call, but for compatibility with
   // legacy clients, this is cleared at the beginning of each public API call.
   // Not used when fallback_database_ == nullptr.
-  HASH_SET<std::string> known_bad_files_;
+  absl::flat_hash_set<std::string> known_bad_files_;
 
   // A set of symbols which we have tried to load from the fallback database
   // and encountered errors. We will not attempt to load them again during
   // execution of the current public API call, but for compatibility with
   // legacy clients, this is cleared at the beginning of each public API call.
-  HASH_SET<std::string> known_bad_symbols_;
+  absl::flat_hash_set<std::string> known_bad_symbols_;
 
   // The set of descriptors for which we've already loaded the full
   // set of extensions numbers from fallback_database_.
-  HASH_SET<const Descriptor*> extensions_loaded_from_db_;
+  absl::flat_hash_set<const Descriptor*> extensions_loaded_from_db_;
 
   // Maps type name to Descriptor::WellKnownType.  This is logically global
   // and const, but we make it a member here to simplify its construction and
   // destruction.  This only has 20-ish entries and is one per DescriptorPool,
   // so the overhead is small.
-  HASH_MAP<std::string, Descriptor::WellKnownType> well_known_types_;
+  absl::flat_hash_map<std::string, Descriptor::WellKnownType> well_known_types_;
 
   // -----------------------------------------------------------------
   // Finding items.
 
   // Find symbols.  This returns a null Symbol (symbol.IsNull() is true)
   // if not found.
-  inline Symbol FindSymbol(StringPiece key) const;
+  inline Symbol FindSymbol(absl::string_view 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, StringPiece name);
+  Symbol FindByNameHelper(const DescriptorPool* pool, absl::string_view name);
 
   // These return nullptr if not found.
-  inline const FileDescriptor* FindFile(StringPiece key) const;
+  inline const FileDescriptor* FindFile(absl::string_view key) const;
   inline const FieldDescriptor* FindExtension(const Descriptor* extendee,
                                               int number) const;
   inline void FindAllExtensions(const Descriptor* extendee,
@@ -1394,7 +1345,7 @@
       flat_allocs_;
 
   SymbolsByNameSet symbols_by_name_;
-  FilesByNameMap files_by_name_;
+  FilesByNameSet files_by_name_;
   ExtensionsGroupedByDescriptorMap extensions_;
 
   struct CheckPoint {
@@ -1418,7 +1369,7 @@
   std::vector<CheckPoint> checkpoints_;
   std::vector<Symbol> symbols_after_checkpoint_;
   std::vector<const FileDescriptor*> files_after_checkpoint_;
-  std::vector<DescriptorIntPair> extensions_after_checkpoint_;
+  std::vector<std::pair<const Descriptor*, int>> extensions_after_checkpoint_;
 };
 
 DescriptorPool::Tables::Tables() {
@@ -1483,7 +1434,7 @@
   }
   for (size_t i = checkpoint.pending_files_before_checkpoint;
        i < files_after_checkpoint_.size(); i++) {
-    files_by_name_.erase(files_after_checkpoint_[i]->name());
+    files_by_name_.erase(files_after_checkpoint_[i]);
   }
   for (size_t i = checkpoint.pending_extensions_before_checkpoint;
        i < extensions_after_checkpoint_.size(); i++) {
@@ -1503,33 +1454,28 @@
 
 // -------------------------------------------------------------------
 
-inline Symbol DescriptorPool::Tables::FindSymbol(StringPiece key) const {
-  Symbol::QueryKey name;
-  name.name = key;
-  auto it = symbols_by_name_.find(name);
+inline Symbol DescriptorPool::Tables::FindSymbol(absl::string_view key) const {
+  auto it = symbols_by_name_.find(FullNameQuery{key});
   return it == symbols_by_name_.end() ? Symbol() : *it;
 }
 
 inline Symbol FileDescriptorTables::FindNestedSymbol(
-    const void* parent, StringPiece name) const {
-  Symbol::QueryKey query;
-  query.name = name;
-  query.parent = parent;
-  auto it = symbols_by_parent_.find(query);
+    const void* parent, absl::string_view name) const {
+  auto it = symbols_by_parent_.find(ParentNameQuery{{parent, name}});
   return it == symbols_by_parent_.end() ? Symbol() : *it;
 }
 
 Symbol DescriptorPool::Tables::FindByNameHelper(const DescriptorPool* pool,
-                                                StringPiece name) {
+                                                absl::string_view name) {
   if (pool->mutex_ != nullptr) {
     // Fast path: the Symbol is already cached.  This is just a hash lookup.
-    ReaderMutexLock lock(pool->mutex_);
+    absl::ReaderMutexLock lock(pool->mutex_);
     if (known_bad_symbols_.empty() && known_bad_files_.empty()) {
       Symbol result = FindSymbol(name);
       if (!result.IsNull()) return result;
     }
   }
-  MutexLockMaybe lock(pool->mutex_);
+  absl::MutexLockMaybe lock(pool->mutex_);
   if (pool->fallback_database_ != nullptr) {
     known_bad_symbols_.clear();
     known_bad_files_.clear();
@@ -1552,8 +1498,10 @@
 }
 
 inline const FileDescriptor* DescriptorPool::Tables::FindFile(
-    StringPiece key) const {
-  return FindPtrOrNull(files_by_name_, key);
+    absl::string_view key) const {
+  auto it = files_by_name_.find(key);
+  if (it == files_by_name_.end()) return nullptr;
+  return *it;
 }
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByNumber(
@@ -1565,12 +1513,8 @@
     return parent->field(number - 1);
   }
 
-  Symbol::QueryKey query;
-  query.parent = parent;
-  query.field_number = number;
-
-  auto it = fields_by_number_.find(query);
-  return it == fields_by_number_.end() ? nullptr : it->field_descriptor();
+  auto it = fields_by_number_.find(ParentNumberQuery{{parent, number}});
+  return it == fields_by_number_.end() ? nullptr : *it;
 }
 
 const void* FileDescriptorTables::FindParentForFieldsByMap(
@@ -1603,13 +1547,15 @@
 }
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByLowercaseName(
-    const void* parent, StringPiece lowercase_name) const {
-  internal::call_once(
-      fields_by_lowercase_name_once_,
-      &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic, this);
-  return FindPtrOrNull(
-      *fields_by_lowercase_name_.load(std::memory_order_acquire),
-      PointerStringPair(parent, lowercase_name));
+    const void* parent, absl::string_view lowercase_name) const {
+  absl::call_once(fields_by_lowercase_name_once_,
+                  &FileDescriptorTables::FieldsByLowercaseNamesLazyInitStatic,
+                  this);
+  const auto* fields =
+      fields_by_lowercase_name_.load(std::memory_order_acquire);
+  auto it = fields->find({parent, lowercase_name});
+  if (it == fields->end()) return nullptr;
+  return it->second;
 }
 
 void FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic(
@@ -1629,13 +1575,14 @@
 }
 
 inline const FieldDescriptor* FileDescriptorTables::FindFieldByCamelcaseName(
-    const void* parent, StringPiece camelcase_name) const {
-  internal::call_once(
-      fields_by_camelcase_name_once_,
-      FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic, this);
-  return FindPtrOrNull(
-      *fields_by_camelcase_name_.load(std::memory_order_acquire),
-      PointerStringPair(parent, camelcase_name));
+    const void* parent, absl::string_view camelcase_name) const {
+  absl::call_once(fields_by_camelcase_name_once_,
+                  FileDescriptorTables::FieldsByCamelcaseNamesLazyInitStatic,
+                  this);
+  auto* fields = fields_by_camelcase_name_.load(std::memory_order_acquire);
+  auto it = fields->find({parent, camelcase_name});
+  if (it == fields->end()) return nullptr;
+  return it->second;
 }
 
 inline const EnumValueDescriptor* FileDescriptorTables::FindEnumValueByNumber(
@@ -1648,13 +1595,8 @@
     return parent->value(number - base);
   }
 
-  Symbol::QueryKey query;
-  query.parent = parent;
-  query.field_number = number;
-
-  auto it = enum_values_by_number_.find(query);
-  return it == enum_values_by_number_.end() ? nullptr
-                                            : it->enum_value_descriptor();
+  auto it = enum_values_by_number_.find(ParentNumberQuery{{parent, number}});
+  return it == enum_values_by_number_.end() ? nullptr : *it;
 }
 
 inline const EnumValueDescriptor*
@@ -1668,34 +1610,30 @@
     }
   }
 
-  Symbol::QueryKey query;
-  query.parent = parent;
-  query.field_number = number;
+  const ParentNumberQuery query{{parent, number}};
 
   // Second try, with reader lock held on unknown enum values: common case.
   {
-    ReaderMutexLock l(&unknown_enum_values_mu_);
+    absl::ReaderMutexLock l(&unknown_enum_values_mu_);
     auto it = unknown_enum_values_by_number_.find(query);
-    if (it != unknown_enum_values_by_number_.end() &&
-        it->enum_value_descriptor() != nullptr) {
-      return it->enum_value_descriptor();
+    if (it != unknown_enum_values_by_number_.end()) {
+      return *it;
     }
   }
   // If not found, try again with writer lock held, and create new descriptor if
   // necessary.
   {
-    WriterMutexLock l(&unknown_enum_values_mu_);
+    absl::WriterMutexLock l(&unknown_enum_values_mu_);
     auto it = unknown_enum_values_by_number_.find(query);
-    if (it != unknown_enum_values_by_number_.end() &&
-        it->enum_value_descriptor() != nullptr) {
-      return it->enum_value_descriptor();
+    if (it != unknown_enum_values_by_number_.end()) {
+      return *it;
     }
 
     // Create an EnumValueDescriptor dynamically. We don't insert it into the
     // EnumDescriptor (it's not a part of the enum as originally defined), but
     // we do insert it into the table so that we can return the same pointer
     // later.
-    std::string enum_value_name = StringPrintf(
+    std::string enum_value_name = absl::StrFormat(
         "UNKNOWN_ENUM_VALUE_%s_%d", parent->name().c_str(), number);
     auto* pool = DescriptorPool::generated_pool();
     auto* tables = const_cast<DescriptorPool::Tables*>(pool->tables_.get());
@@ -1705,24 +1643,26 @@
 
     {
       // Must lock the pool because we will do allocations in the shared arena.
-      MutexLockMaybe l2(pool->mutex_);
+      absl::MutexLockMaybe l2(pool->mutex_);
       alloc.FinalizePlanning(tables);
     }
     EnumValueDescriptor* result = alloc.AllocateArray<EnumValueDescriptor>(1);
     result->all_names_ = alloc.AllocateStrings(
         enum_value_name,
-        StrCat(parent->full_name(), ".", enum_value_name));
+        absl::StrCat(parent->full_name(), ".", enum_value_name));
     result->number_ = number;
     result->type_ = parent;
     result->options_ = &EnumValueOptions::default_instance();
-    unknown_enum_values_by_number_.insert(Symbol::EnumValue(result, 0));
+    unknown_enum_values_by_number_.insert(result);
     return result;
   }
 }
 
 inline const FieldDescriptor* DescriptorPool::Tables::FindExtension(
     const Descriptor* extendee, int number) const {
-  return FindPtrOrNull(extensions_, std::make_pair(extendee, number));
+  auto it = extensions_.find({extendee, number});
+  if (it == extensions_.end()) return nullptr;
+  return it->second;
 }
 
 inline void DescriptorPool::Tables::FindAllExtensions(
@@ -1757,7 +1697,7 @@
 }
 
 bool DescriptorPool::Tables::AddFile(const FileDescriptor* file) {
-  if (InsertIfNotPresent(&files_by_name_, file->name(), file)) {
+  if (files_by_name_.insert(file).second) {
     files_after_checkpoint_.push_back(file);
     return true;
   } else {
@@ -1780,7 +1720,7 @@
     return field->containing_type()->field(field->number() - 1) == field;
   }
 
-  return fields_by_number_.insert(Symbol(field)).second;
+  return fields_by_number_.insert(field).second;
 }
 
 bool FileDescriptorTables::AddEnumValueByNumber(EnumValueDescriptor* value) {
@@ -1790,13 +1730,14 @@
       value->number() <=
           static_cast<int64_t>(base) + value->type()->sequential_value_limit_)
     return true;
-  return enum_values_by_number_.insert(Symbol::EnumValue(value, 0)).second;
+  return enum_values_by_number_.insert(value).second;
 }
 
 bool DescriptorPool::Tables::AddExtension(const FieldDescriptor* field) {
-  DescriptorIntPair key(field->containing_type(), field->number());
-  if (InsertIfNotPresent(&extensions_, key, field)) {
-    extensions_after_checkpoint_.push_back(key);
+  auto it_inserted =
+      extensions_.insert({{field->containing_type(), field->number()}, field});
+  if (it_inserted.second) {
+    extensions_after_checkpoint_.push_back(it_inserted.first->first);
     return true;
   } else {
     return false;
@@ -1842,7 +1783,7 @@
     std::pair<const FileDescriptorTables*, const SourceCodeInfo*>* p) {
   for (int i = 0, len = p->second->location_size(); i < len; ++i) {
     const SourceCodeInfo_Location* loc = &p->second->location().Get(i);
-    p->first->locations_by_path_[Join(loc->path(), ",")] = loc;
+    p->first->locations_by_path_[absl::StrJoin(loc->path(), ",")] = loc;
   }
 }
 
@@ -1850,9 +1791,11 @@
     const std::vector<int>& path, const SourceCodeInfo* info) const {
   std::pair<const FileDescriptorTables*, const SourceCodeInfo*> p(
       std::make_pair(this, info));
-  internal::call_once(locations_by_path_once_,
-                      FileDescriptorTables::BuildLocationsByPath, &p);
-  return FindPtrOrNull(locations_by_path_, Join(path, ","));
+  absl::call_once(locations_by_path_once_,
+                  FileDescriptorTables::BuildLocationsByPath, &p);
+  auto it = locations_by_path_.find(absl::StrJoin(path, ","));
+  if (it == locations_by_path_.end()) return nullptr;
+  return it->second;
 }
 
 // ===================================================================
@@ -1874,7 +1817,7 @@
 
 DescriptorPool::DescriptorPool(DescriptorDatabase* fallback_database,
                                ErrorCollector* error_collector)
-    : mutex_(new internal::WrappedMutex),
+    : mutex_(new absl::Mutex),
       fallback_database_(fallback_database),
       default_error_collector_(error_collector),
       underlay_(nullptr),
@@ -1908,7 +1851,7 @@
   enforce_dependencies_ = false;
 }
 
-void DescriptorPool::AddUnusedImportTrackFile(ConstStringParam file_name,
+void DescriptorPool::AddUnusedImportTrackFile(absl::string_view file_name,
                                               bool is_error) {
   unused_import_track_files_[std::string(file_name)] = is_error;
 }
@@ -1917,8 +1860,8 @@
   unused_import_track_files_.clear();
 }
 
-bool DescriptorPool::InternalIsFileLoaded(ConstStringParam filename) const {
-  MutexLockMaybe lock(mutex_);
+bool DescriptorPool::InternalIsFileLoaded(absl::string_view filename) const {
+  absl::MutexLockMaybe lock(mutex_);
   return tables_->FindFile(filename) != nullptr;
 }
 
@@ -1994,8 +1937,8 @@
 //   there's nothing more important to do (read: never).
 
 const FileDescriptor* DescriptorPool::FindFileByName(
-    ConstStringParam name) const {
-  MutexLockMaybe lock(mutex_);
+    absl::string_view name) const {
+  absl::MutexLockMaybe lock(mutex_);
   if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
@@ -2014,8 +1957,8 @@
 }
 
 const FileDescriptor* DescriptorPool::FindFileContainingSymbol(
-    ConstStringParam symbol_name) const {
-  MutexLockMaybe lock(mutex_);
+    absl::string_view symbol_name) const {
+  absl::MutexLockMaybe lock(mutex_);
   if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
@@ -2035,12 +1978,12 @@
 }
 
 const Descriptor* DescriptorPool::FindMessageTypeByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   return tables_->FindByNameHelper(this, name).descriptor();
 }
 
 const FieldDescriptor* DescriptorPool::FindFieldByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   if (const FieldDescriptor* field =
           tables_->FindByNameHelper(this, name).field_descriptor()) {
     if (!field->is_extension()) {
@@ -2051,7 +1994,7 @@
 }
 
 const FieldDescriptor* DescriptorPool::FindExtensionByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   if (const FieldDescriptor* field =
           tables_->FindByNameHelper(this, name).field_descriptor()) {
     if (field->is_extension()) {
@@ -2062,27 +2005,27 @@
 }
 
 const OneofDescriptor* DescriptorPool::FindOneofByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   return tables_->FindByNameHelper(this, name).oneof_descriptor();
 }
 
 const EnumDescriptor* DescriptorPool::FindEnumTypeByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   return tables_->FindByNameHelper(this, name).enum_descriptor();
 }
 
 const EnumValueDescriptor* DescriptorPool::FindEnumValueByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   return tables_->FindByNameHelper(this, name).enum_value_descriptor();
 }
 
 const ServiceDescriptor* DescriptorPool::FindServiceByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   return tables_->FindByNameHelper(this, name).service_descriptor();
 }
 
 const MethodDescriptor* DescriptorPool::FindMethodByName(
-    ConstStringParam name) const {
+    absl::string_view name) const {
   return tables_->FindByNameHelper(this, name).method_descriptor();
 }
 
@@ -2092,13 +2035,13 @@
   // A faster path to reduce lock contention in finding extensions, assuming
   // most extensions will be cache hit.
   if (mutex_ != nullptr) {
-    ReaderMutexLock lock(mutex_);
+    absl::ReaderMutexLock lock(mutex_);
     const FieldDescriptor* result = tables_->FindExtension(extendee, number);
     if (result != nullptr) {
       return result;
     }
   }
-  MutexLockMaybe lock(mutex_);
+  absl::MutexLockMaybe lock(mutex_);
   if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
@@ -2138,7 +2081,7 @@
 }
 
 const FieldDescriptor* DescriptorPool::FindExtensionByPrintableName(
-    const Descriptor* extendee, ConstStringParam printable_name) const {
+    const Descriptor* extendee, absl::string_view printable_name) const {
   if (extendee->extension_range_count() == 0) return nullptr;
   const FieldDescriptor* result = FindExtensionByName(printable_name);
   if (result != nullptr && result->containing_type() == extendee) {
@@ -2167,7 +2110,7 @@
 void DescriptorPool::FindAllExtensions(
     const Descriptor* extendee,
     std::vector<const FieldDescriptor*>* out) const {
-  MutexLockMaybe lock(mutex_);
+  absl::MutexLockMaybe lock(mutex_);
   if (fallback_database_ != nullptr) {
     tables_->known_bad_symbols_.clear();
     tables_->known_bad_files_.clear();
@@ -2208,7 +2151,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindFieldByLowercaseName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByLowercaseName(this, key);
   if (result == nullptr || result->is_extension()) {
@@ -2219,7 +2162,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindFieldByCamelcaseName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByCamelcaseName(this, key);
   if (result == nullptr || result->is_extension()) {
@@ -2229,25 +2172,27 @@
   }
 }
 
-const FieldDescriptor* Descriptor::FindFieldByName(ConstStringParam key) const {
+const FieldDescriptor* Descriptor::FindFieldByName(
+    absl::string_view key) const {
   const FieldDescriptor* field =
       file()->tables_->FindNestedSymbol(this, key).field_descriptor();
   return field != nullptr && !field->is_extension() ? field : nullptr;
 }
 
-const OneofDescriptor* Descriptor::FindOneofByName(ConstStringParam key) const {
+const OneofDescriptor* Descriptor::FindOneofByName(
+    absl::string_view key) const {
   return file()->tables_->FindNestedSymbol(this, key).oneof_descriptor();
 }
 
 const FieldDescriptor* Descriptor::FindExtensionByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* field =
       file()->tables_->FindNestedSymbol(this, key).field_descriptor();
   return field != nullptr && field->is_extension() ? field : nullptr;
 }
 
 const FieldDescriptor* Descriptor::FindExtensionByLowercaseName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByLowercaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
@@ -2258,7 +2203,7 @@
 }
 
 const FieldDescriptor* Descriptor::FindExtensionByCamelcaseName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* result =
       file()->tables_->FindFieldByCamelcaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
@@ -2268,17 +2213,18 @@
   }
 }
 
-const Descriptor* Descriptor::FindNestedTypeByName(ConstStringParam key) const {
+const Descriptor* Descriptor::FindNestedTypeByName(
+    absl::string_view key) const {
   return file()->tables_->FindNestedSymbol(this, key).descriptor();
 }
 
 const EnumDescriptor* Descriptor::FindEnumTypeByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return file()->tables_->FindNestedSymbol(this, key).enum_descriptor();
 }
 
 const EnumValueDescriptor* Descriptor::FindEnumValueByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
 }
 
@@ -2295,7 +2241,7 @@
 }
 
 const EnumValueDescriptor* EnumDescriptor::FindValueByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return file()->tables_->FindNestedSymbol(this, key).enum_value_descriptor();
 }
 
@@ -2309,39 +2255,39 @@
 }
 
 const MethodDescriptor* ServiceDescriptor::FindMethodByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return file()->tables_->FindNestedSymbol(this, key).method_descriptor();
 }
 
 const Descriptor* FileDescriptor::FindMessageTypeByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return tables_->FindNestedSymbol(this, key).descriptor();
 }
 
 const EnumDescriptor* FileDescriptor::FindEnumTypeByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return tables_->FindNestedSymbol(this, key).enum_descriptor();
 }
 
 const EnumValueDescriptor* FileDescriptor::FindEnumValueByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return tables_->FindNestedSymbol(this, key).enum_value_descriptor();
 }
 
 const ServiceDescriptor* FileDescriptor::FindServiceByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   return tables_->FindNestedSymbol(this, key).service_descriptor();
 }
 
 const FieldDescriptor* FileDescriptor::FindExtensionByName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* field =
       tables_->FindNestedSymbol(this, key).field_descriptor();
   return field != nullptr && field->is_extension() ? field : nullptr;
 }
 
 const FieldDescriptor* FileDescriptor::FindExtensionByLowercaseName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* result = tables_->FindFieldByLowercaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
     return nullptr;
@@ -2351,7 +2297,7 @@
 }
 
 const FieldDescriptor* FileDescriptor::FindExtensionByCamelcaseName(
-    ConstStringParam key) const {
+    absl::string_view key) const {
   const FieldDescriptor* result = tables_->FindFieldByCamelcaseName(this, key);
   if (result == nullptr || !result->is_extension()) {
     return nullptr;
@@ -2408,7 +2354,7 @@
 // -------------------------------------------------------------------
 
 bool DescriptorPool::TryFindFileInFallbackDatabase(
-    StringPiece name) const {
+    absl::string_view name) const {
   if (fallback_database_ == nullptr) return false;
 
   auto name_string = std::string(name);
@@ -2423,7 +2369,7 @@
   return true;
 }
 
-bool DescriptorPool::IsSubSymbolOfBuiltType(StringPiece name) const {
+bool DescriptorPool::IsSubSymbolOfBuiltType(absl::string_view name) const {
   auto prefix = std::string(name);
   for (;;) {
     std::string::size_type dot_pos = prefix.find_last_of('.');
@@ -2446,7 +2392,7 @@
 }
 
 bool DescriptorPool::TryFindSymbolInFallbackDatabase(
-    StringPiece name) const {
+    absl::string_view name) const {
   if (fallback_database_ == nullptr) return false;
 
   auto name_string = std::string(name);
@@ -2523,25 +2469,25 @@
   GOOGLE_CHECK(has_default_value()) << "No default value";
   switch (cpp_type()) {
     case CPPTYPE_INT32:
-      return StrCat(default_value_int32_t());
+      return absl::StrCat(default_value_int32_t());
     case CPPTYPE_INT64:
-      return StrCat(default_value_int64_t());
+      return absl::StrCat(default_value_int64_t());
     case CPPTYPE_UINT32:
-      return StrCat(default_value_uint32_t());
+      return absl::StrCat(default_value_uint32_t());
     case CPPTYPE_UINT64:
-      return StrCat(default_value_uint64_t());
+      return absl::StrCat(default_value_uint64_t());
     case CPPTYPE_FLOAT:
-      return SimpleFtoa(default_value_float());
+      return io::SimpleFtoa(default_value_float());
     case CPPTYPE_DOUBLE:
-      return SimpleDtoa(default_value_double());
+      return io::SimpleDtoa(default_value_double());
     case CPPTYPE_BOOL:
       return default_value_bool() ? "true" : "false";
     case CPPTYPE_STRING:
       if (quote_string_type) {
-        return "\"" + CEscape(default_value_string()) + "\"";
+        return "\"" + absl::CEscape(default_value_string()) + "\"";
       } else {
         if (type() == TYPE_BYTES) {
-          return CEscape(default_value_string());
+          return absl::CEscape(default_value_string());
         } else {
           return default_value_string();
         }
@@ -2559,10 +2505,7 @@
 // CopyTo methods ====================================================
 
 void FileDescriptor::CopyTo(FileDescriptorProto* proto) const {
-  proto->set_name(name());
-  if (!package().empty()) proto->set_package(package());
-  // TODO(liujisi): Also populate when syntax="proto2".
-  if (syntax() == SYNTAX_PROTO3) proto->set_syntax(SyntaxName(syntax()));
+  CopyHeadingTo(proto);
 
   for (int i = 0; i < dependency_count(); i++) {
     proto->add_dependency(dependency(i)->name());
@@ -2588,9 +2531,21 @@
   for (int i = 0; i < extension_count(); i++) {
     extension(i)->CopyTo(proto->add_extension());
   }
+}
 
+void FileDescriptor::CopyHeadingTo(FileDescriptorProto* proto) const {
+  proto->set_name(name());
+  if (!package().empty()) {
+    proto->set_package(package());
+  }
+
+  // TODO(liujisi): Also populate when syntax="proto2".
+  if (syntax() == SYNTAX_PROTO3
+  ) {
+    proto->set_syntax(SyntaxName(syntax()));
+  }
   if (&options() != &FileOptions::default_instance()) {
-    proto->mutable_options()->CopyFrom(options());
+    *proto->mutable_options() = options();
   }
 }
 
@@ -2680,9 +2635,9 @@
   // Some compilers do not allow static_cast directly between two enum types,
   // so we must cast to int first.
   proto->set_label(static_cast<FieldDescriptorProto::Label>(
-      implicit_cast<int>(label())));
+      absl::implicit_cast<int>(label())));
   proto->set_type(static_cast<FieldDescriptorProto::Type>(
-      implicit_cast<int>(type())));
+      absl::implicit_cast<int>(type())));
 
   if (is_extension()) {
     if (!containing_type()->is_unqualified_placeholder_) {
@@ -2889,7 +2844,7 @@
                             const DescriptorPool* pool, std::string* output) {
   std::vector<std::string> all_options;
   if (RetrieveOptions(depth, options, pool, &all_options)) {
-    output->append(Join(all_options, ", "));
+    output->append(absl::StrJoin(all_options, ", "));
   }
   return !all_options.empty();
 }
@@ -2901,7 +2856,7 @@
   std::vector<std::string> all_options;
   if (RetrieveOptions(depth, options, pool, &all_options)) {
     for (const std::string& option : all_options) {
-      strings::SubstituteAndAppend(output, "$0option $1;\n", prefix, option);
+      absl::SubstituteAndAppend(output, "$0option $1;\n", prefix, option);
     }
   }
   return !all_options.empty();
@@ -2952,11 +2907,11 @@
   // the DebugString() output.
   std::string FormatComment(const std::string& comment_text) {
     std::string stripped_comment = comment_text;
-    StripWhitespace(&stripped_comment);
-    std::vector<std::string> lines = Split(stripped_comment, "\n");
+    absl::StripAsciiWhitespace(&stripped_comment);
+    std::vector<std::string> lines = absl::StrSplit(stripped_comment, "\n");
     std::string output;
     for (const std::string& line : lines) {
-      strings::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
+      absl::SubstituteAndAppend(&output, "$0// $1\n", prefix_, line);
     }
     return output;
   }
@@ -2985,7 +2940,7 @@
     SourceLocationCommentPrinter syntax_comment(this, path, "",
                                                 debug_string_options);
     syntax_comment.AddPreComment(&contents);
-    strings::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
+    absl::SubstituteAndAppend(&contents, "syntax = \"$0\";\n\n",
                               SyntaxName(syntax()));
     syntax_comment.AddPostComment(&contents);
   }
@@ -2993,22 +2948,20 @@
   SourceLocationCommentPrinter comment_printer(this, "", debug_string_options);
   comment_printer.AddPreComment(&contents);
 
-  std::set<int> public_dependencies;
-  std::set<int> weak_dependencies;
-  public_dependencies.insert(public_dependencies_,
-                             public_dependencies_ + public_dependency_count_);
-  weak_dependencies.insert(weak_dependencies_,
-                           weak_dependencies_ + weak_dependency_count_);
+  absl::flat_hash_set<int> public_dependencies(
+      public_dependencies_, public_dependencies_ + public_dependency_count_);
+  absl::flat_hash_set<int> weak_dependencies(
+      weak_dependencies_, weak_dependencies_ + weak_dependency_count_);
 
   for (int i = 0; i < dependency_count(); i++) {
-    if (public_dependencies.count(i) > 0) {
-      strings::SubstituteAndAppend(&contents, "import public \"$0\";\n",
+    if (public_dependencies.contains(i)) {
+      absl::SubstituteAndAppend(&contents, "import public \"$0\";\n",
                                 dependency(i)->name());
-    } else if (weak_dependencies.count(i) > 0) {
-      strings::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
+    } else if (weak_dependencies.contains(i)) {
+      absl::SubstituteAndAppend(&contents, "import weak \"$0\";\n",
                                 dependency(i)->name());
     } else {
-      strings::SubstituteAndAppend(&contents, "import \"$0\";\n",
+      absl::SubstituteAndAppend(&contents, "import \"$0\";\n",
                                 dependency(i)->name());
     }
   }
@@ -3019,7 +2972,7 @@
     SourceLocationCommentPrinter package_comment(this, path, "",
                                                  debug_string_options);
     package_comment.AddPreComment(&contents);
-    strings::SubstituteAndAppend(&contents, "package $0;\n\n", package());
+    absl::SubstituteAndAppend(&contents, "package $0;\n\n", package());
     package_comment.AddPostComment(&contents);
   }
 
@@ -3034,7 +2987,7 @@
 
   // Find all the 'group' type extensions; we will not output their nested
   // definitions (those will be done with their group field descriptor).
-  std::set<const Descriptor*> groups;
+  absl::flat_hash_set<const Descriptor*> groups;
   for (int i = 0; i < extension_count(); i++) {
     if (extension(i)->type() == FieldDescriptor::TYPE_GROUP) {
       groups.insert(extension(i)->message_type());
@@ -3042,7 +2995,7 @@
   }
 
   for (int i = 0; i < message_type_count(); i++) {
-    if (groups.count(message_type(i)) == 0) {
+    if (!groups.contains(message_type(i))) {
       message_type(i)->DebugString(0, &contents, debug_string_options,
                                    /* include_opening_clause */ true);
       contents.append("\n");
@@ -3059,7 +3012,7 @@
     if (extension(i)->containing_type() != containing_type) {
       if (i > 0) contents.append("}\n\n");
       containing_type = extension(i)->containing_type();
-      strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
+      absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
                                 containing_type->full_name());
     }
     extension(i)->DebugString(1, &contents, debug_string_options);
@@ -3098,7 +3051,7 @@
   comment_printer.AddPreComment(contents);
 
   if (include_opening_clause) {
-    strings::SubstituteAndAppend(contents, "$0message $1", prefix, name());
+    absl::SubstituteAndAppend(contents, "$0message $1", prefix, name());
   }
   contents->append(" {\n");
 
@@ -3107,7 +3060,7 @@
   // Find all the 'group' types for fields and extensions; we will not output
   // their nested definitions (those will be done with their group field
   // descriptor).
-  std::set<const Descriptor*> groups;
+  absl::flat_hash_set<const Descriptor*> groups;
   for (int i = 0; i < field_count(); i++) {
     if (field(i)->type() == FieldDescriptor::TYPE_GROUP) {
       groups.insert(field(i)->message_type());
@@ -3120,7 +3073,7 @@
   }
 
   for (int i = 0; i < nested_type_count(); i++) {
-    if (groups.count(nested_type(i)) == 0) {
+    if (!groups.contains(nested_type(i))) {
       nested_type(i)->DebugString(depth, contents, debug_string_options,
                                   /* include_opening_clause */ true);
     }
@@ -3139,7 +3092,7 @@
   }
 
   for (int i = 0; i < extension_range_count(); i++) {
-    strings::SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n", prefix,
+    absl::SubstituteAndAppend(contents, "$0  extensions $1 to $2;\n", prefix,
                               extension_range(i)->start,
                               extension_range(i)->end - 1);
   }
@@ -3148,26 +3101,26 @@
   const Descriptor* containing_type = nullptr;
   for (int i = 0; i < extension_count(); i++) {
     if (extension(i)->containing_type() != containing_type) {
-      if (i > 0) strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
+      if (i > 0) absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
       containing_type = extension(i)->containing_type();
-      strings::SubstituteAndAppend(contents, "$0  extend .$1 {\n", prefix,
+      absl::SubstituteAndAppend(contents, "$0  extend .$1 {\n", prefix,
                                 containing_type->full_name());
     }
     extension(i)->DebugString(depth + 1, contents, debug_string_options);
   }
   if (extension_count() > 0)
-    strings::SubstituteAndAppend(contents, "$0  }\n", prefix);
+    absl::SubstituteAndAppend(contents, "$0  }\n", prefix);
 
   if (reserved_range_count() > 0) {
-    strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
+    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
     for (int i = 0; i < reserved_range_count(); i++) {
       const Descriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start + 1) {
-        strings::SubstituteAndAppend(contents, "$0, ", range->start);
+        absl::SubstituteAndAppend(contents, "$0, ", range->start);
       } else if (range->end > FieldDescriptor::kMaxNumber) {
-        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
+        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
-        strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
+        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end - 1);
       }
     }
@@ -3175,15 +3128,15 @@
   }
 
   if (reserved_name_count() > 0) {
-    strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
+    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
     for (int i = 0; i < reserved_name_count(); i++) {
-      strings::SubstituteAndAppend(contents, "\"$0\", ",
-                                CEscape(reserved_name(i)));
+      absl::SubstituteAndAppend(contents, "\"$0\", ",
+                                absl::CEscape(reserved_name(i)));
     }
     contents->replace(contents->size() - 2, 2, ";\n");
   }
 
-  strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
   comment_printer.AddPostComment(contents);
 }
 
@@ -3197,7 +3150,7 @@
   std::string contents;
   int depth = 0;
   if (is_extension()) {
-    strings::SubstituteAndAppend(&contents, "extend .$0 {\n",
+    absl::SubstituteAndAppend(&contents, "extend .$0 {\n",
                               containing_type()->full_name());
     depth = 1;
   }
@@ -3228,7 +3181,7 @@
 
   // Special case map fields.
   if (is_map()) {
-    strings::SubstituteAndAppend(
+    absl::SubstituteAndAppend(
         &field_type, "map<$0, $1>",
         message_type()->field(0)->FieldTypeNameDebugString(),
         message_type()->field(1)->FieldTypeNameDebugString());
@@ -3236,7 +3189,7 @@
     field_type = FieldTypeNameDebugString();
   }
 
-  std::string label = StrCat(kLabelToName[this->label()], " ");
+  std::string label = absl::StrCat(kLabelToName[this->label()], " ");
 
   // Label is omitted for maps, oneof, and plain proto3 fields.
   if (is_map() || real_containing_oneof() ||
@@ -3248,14 +3201,14 @@
                                                debug_string_options);
   comment_printer.AddPreComment(contents);
 
-  strings::SubstituteAndAppend(
+  absl::SubstituteAndAppend(
       contents, "$0$1$2 $3 = $4", prefix, label, field_type,
       type() == TYPE_GROUP ? message_type()->name() : name(), number());
 
   bool bracketed = false;
   if (has_default_value()) {
     bracketed = true;
-    strings::SubstituteAndAppend(contents, " [default = $0",
+    absl::SubstituteAndAppend(contents, " [default = $0",
                               DefaultValueAsString(true));
   }
   if (has_json_name_) {
@@ -3266,7 +3219,7 @@
       contents->append(", ");
     }
     contents->append("json_name = \"");
-    contents->append(CEscape(json_name()));
+    contents->append(absl::CEscape(json_name()));
     contents->append("\"");
   }
 
@@ -3316,7 +3269,7 @@
   SourceLocationCommentPrinter comment_printer(this, prefix,
                                                debug_string_options);
   comment_printer.AddPreComment(contents);
-  strings::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
+  absl::SubstituteAndAppend(contents, "$0oneof $1 {", prefix, name());
 
   FormatLineOptions(depth, options(), containing_type()->file()->pool(),
                     contents);
@@ -3328,7 +3281,7 @@
     for (int i = 0; i < field_count(); i++) {
       field(i)->DebugString(depth, contents, debug_string_options);
     }
-    strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+    absl::SubstituteAndAppend(contents, "$0}\n", prefix);
   }
   comment_printer.AddPostComment(contents);
 }
@@ -3355,7 +3308,7 @@
                                                debug_string_options);
   comment_printer.AddPreComment(contents);
 
-  strings::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name());
+  absl::SubstituteAndAppend(contents, "$0enum $1 {\n", prefix, name());
 
   FormatLineOptions(depth, options(), file()->pool(), contents);
 
@@ -3364,15 +3317,15 @@
   }
 
   if (reserved_range_count() > 0) {
-    strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
+    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
     for (int i = 0; i < reserved_range_count(); i++) {
       const EnumDescriptor::ReservedRange* range = reserved_range(i);
       if (range->end == range->start) {
-        strings::SubstituteAndAppend(contents, "$0, ", range->start);
+        absl::SubstituteAndAppend(contents, "$0, ", range->start);
       } else if (range->end == INT_MAX) {
-        strings::SubstituteAndAppend(contents, "$0 to max, ", range->start);
+        absl::SubstituteAndAppend(contents, "$0 to max, ", range->start);
       } else {
-        strings::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
+        absl::SubstituteAndAppend(contents, "$0 to $1, ", range->start,
                                   range->end);
       }
     }
@@ -3380,15 +3333,15 @@
   }
 
   if (reserved_name_count() > 0) {
-    strings::SubstituteAndAppend(contents, "$0  reserved ", prefix);
+    absl::SubstituteAndAppend(contents, "$0  reserved ", prefix);
     for (int i = 0; i < reserved_name_count(); i++) {
-      strings::SubstituteAndAppend(contents, "\"$0\", ",
-                                CEscape(reserved_name(i)));
+      absl::SubstituteAndAppend(contents, "\"$0\", ",
+                                absl::CEscape(reserved_name(i)));
     }
     contents->replace(contents->size() - 2, 2, ";\n");
   }
 
-  strings::SubstituteAndAppend(contents, "$0}\n", prefix);
+  absl::SubstituteAndAppend(contents, "$0}\n", prefix);
 
   comment_printer.AddPostComment(contents);
 }
@@ -3414,12 +3367,12 @@
                                                debug_string_options);
   comment_printer.AddPreComment(contents);
 
-  strings::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number());
+  absl::SubstituteAndAppend(contents, "$0$1 = $2", prefix, name(), number());
 
   std::string formatted_options;
   if (FormatBracketedOptions(depth, options(), type()->file()->pool(),
                              &formatted_options)) {
-    strings::SubstituteAndAppend(contents, " [$0]", formatted_options);
+    absl::SubstituteAndAppend(contents, " [$0]", formatted_options);
   }
   contents->append(";\n");
 
@@ -3445,7 +3398,7 @@
                                                debug_string_options);
   comment_printer.AddPreComment(contents);
 
-  strings::SubstituteAndAppend(contents, "service $0 {\n", name());
+  absl::SubstituteAndAppend(contents, "service $0 {\n", name());
 
   FormatLineOptions(1, options(), file()->pool(), contents);
 
@@ -3480,7 +3433,7 @@
                                                debug_string_options);
   comment_printer.AddPreComment(contents);
 
-  strings::SubstituteAndAppend(
+  absl::SubstituteAndAppend(
       contents, "$0rpc $1($4.$2) returns ($5.$3)", prefix, name(),
       input_type()->full_name(), output_type()->full_name(),
       client_streaming() ? "stream " : "", server_streaming() ? "stream " : "");
@@ -3488,7 +3441,7 @@
   std::string formatted_options;
   if (FormatLineOptions(depth, options(), service()->file()->pool(),
                         &formatted_options)) {
-    strings::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options,
+    absl::SubstituteAndAppend(contents, " {\n$0$1}\n", formatted_options,
                               prefix);
   } else {
     contents->append(";\n");
@@ -3698,7 +3651,7 @@
   std::string filename_;
   FileDescriptor* file_;
   FileDescriptorTables* file_tables_;
-  std::set<const FileDescriptor*> dependencies_;
+  absl::flat_hash_set<const FileDescriptor*> dependencies_;
 
   struct MessageHints {
     int fields_to_suggest = 0;
@@ -3721,11 +3674,11 @@
     }
   };
 
-  std::unordered_map<const Descriptor*, MessageHints> message_hints_;
+  absl::flat_hash_map<const Descriptor*, MessageHints> message_hints_;
 
   // unused_dependency_ is used to record the unused imported files.
   // Note: public import is not considered.
-  std::set<const FileDescriptor*> unused_dependency_;
+  absl::flat_hash_set<const FileDescriptor*> unused_dependency_;
 
   // If LookupSymbol() finds a symbol that is in a file which is not a declared
   // dependency of this file, it will fail, but will set
@@ -3949,6 +3902,8 @@
     // specified builder, which must not be nullptr. We don't take ownership of
     // the builder.
     explicit OptionInterpreter(DescriptorBuilder* builder);
+    OptionInterpreter(const OptionInterpreter&) = delete;
+    OptionInterpreter& operator=(const OptionInterpreter&) = delete;
 
     ~OptionInterpreter();
 
@@ -4065,8 +4020,6 @@
     // Factory used to create the dynamic messages we need to parse
     // any aggregate option values we encounter.
     DynamicMessageFactory dynamic_factory_;
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OptionInterpreter);
   };
 
   // Work-around for broken compilers:  According to the C++ standard,
@@ -4259,7 +4212,7 @@
 
 bool DescriptorBuilder::IsInPackage(const FileDescriptor* file,
                                     const std::string& package_name) {
-  return HasPrefixString(file->package(), package_name) &&
+  return absl::StartsWith(file->package(), package_name) &&
          (file->package().size() == package_name.size() ||
           file->package()[package_name.size()] == '.');
 }
@@ -4275,7 +4228,7 @@
     const DescriptorPool* pool, const std::string& name, bool build_it) {
   // If we are looking at an underlay, we must lock its mutex_, since we are
   // accessing the underlay's tables_ directly.
-  MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
+  absl::MutexLockMaybe lock((pool == pool_) ? nullptr : pool->mutex_);
 
   Symbol result = pool->tables_->FindSymbol(name);
   if (result.IsNull() && pool->underlay_ != nullptr) {
@@ -4305,7 +4258,7 @@
   // Only find symbols which were defined in this file or one of its
   // dependencies.
   const FileDescriptor* file = result.GetFile();
-  if (file == file_ || dependencies_.count(file) > 0) {
+  if (file == file_ || dependencies_.contains(file)) {
     unused_dependency_.erase(file);
   }
   return result;
@@ -4324,7 +4277,7 @@
   // Only find symbols which were defined in this file or one of its
   // dependencies.
   const FileDescriptor* file = result.GetFile();
-  if (file == file_ || dependencies_.count(file) > 0) {
+  if (file == file_ || dependencies_.contains(file)) {
     return result;
   }
 
@@ -4337,11 +4290,9 @@
     // dependency also defines the same package.  We can't really rule out this
     // symbol unless none of the dependencies define it.
     if (IsInPackage(file_, name)) return result;
-    for (std::set<const FileDescriptor*>::const_iterator it =
-             dependencies_.begin();
-         it != dependencies_.end(); ++it) {
+    for (const auto* dep : dependencies_) {
       // Note:  A dependency may be nullptr if it was not found or had errors.
-      if (*it != nullptr && IsInPackage(*it, name)) return result;
+      if (dep != nullptr && IsInPackage(dep, name)) return result;
     }
   }
 
@@ -4439,7 +4390,7 @@
   return result;
 }
 
-static bool ValidateQualifiedName(StringPiece name) {
+static bool ValidateQualifiedName(absl::string_view name) {
   bool last_was_period = false;
 
   for (char character : name) {
@@ -4459,20 +4410,20 @@
   return !name.empty() && !last_was_period;
 }
 
-Symbol DescriptorPool::NewPlaceholder(StringPiece name,
+Symbol DescriptorPool::NewPlaceholder(absl::string_view name,
                                       PlaceholderType placeholder_type) const {
-  MutexLockMaybe lock(mutex_);
+  absl::MutexLockMaybe lock(mutex_);
   return NewPlaceholderWithMutexHeld(name, placeholder_type);
 }
 
 Symbol DescriptorPool::NewPlaceholderWithMutexHeld(
-    StringPiece name, PlaceholderType placeholder_type) const {
+    absl::string_view name, PlaceholderType placeholder_type) const {
   if (mutex_) {
     mutex_->AssertHeld();
   }
   // Compute names.
-  StringPiece placeholder_full_name;
-  StringPiece placeholder_name;
+  absl::string_view placeholder_full_name;
+  absl::string_view placeholder_name;
   const std::string* placeholder_package;
 
   if (!ValidateQualifiedName(name)) return Symbol();
@@ -4512,7 +4463,7 @@
   }
 
   FileDescriptor* placeholder_file = NewPlaceholderFileWithMutexHeld(
-      StrCat(placeholder_full_name, ".placeholder.proto"), alloc);
+      absl::StrCat(placeholder_full_name, ".placeholder.proto"), alloc);
   placeholder_file->package_ = placeholder_package;
 
   if (placeholder_type == PLACEHOLDER_ENUM) {
@@ -4581,8 +4532,8 @@
 }
 
 FileDescriptor* DescriptorPool::NewPlaceholderFile(
-    StringPiece name) const {
-  MutexLockMaybe lock(mutex_);
+    absl::string_view name) const {
+  absl::MutexLockMaybe lock(mutex_);
   internal::FlatAllocator alloc;
   alloc.PlanArray<FileDescriptor>(1);
   alloc.PlanArray<std::string>(1);
@@ -4592,7 +4543,7 @@
 }
 
 FileDescriptor* DescriptorPool::NewPlaceholderFileWithMutexHeld(
-    StringPiece name, internal::FlatAllocator& alloc) const {
+    absl::string_view name, internal::FlatAllocator& alloc) const {
   if (mutex_) {
     mutex_->AssertHeld();
   }
@@ -4982,7 +4933,8 @@
                                internal::FlatAllocator& alloc) {
   alloc.PlanArray<FileDescriptor>(1);
   alloc.PlanArray<FileDescriptorTables>(1);
-  alloc.PlanArray<std::string>(2);  // name + package
+  alloc.PlanArray<std::string>(2
+  );  // name + package
   if (proto.has_options()) alloc.PlanArray<FileOptions>(1);
   if (proto.has_source_code_info()) alloc.PlanArray<SourceCodeInfo>(1);
 
@@ -5151,13 +5103,13 @@
   }
 
   // Make sure all dependencies are loaded.
-  std::set<std::string> seen_dependencies;
+  absl::flat_hash_set<absl::string_view> seen_dependencies;
   result->dependency_count_ = proto.dependency_size();
   result->dependencies_ =
       alloc.AllocateArray<const FileDescriptor*>(proto.dependency_size());
   result->dependencies_once_ = nullptr;
   unused_dependency_.clear();
-  std::set<int> weak_deps;
+  absl::flat_hash_set<int> weak_deps;
   for (int i = 0; i < proto.weak_dependency_size(); ++i) {
     weak_deps.insert(proto.weak_dependency(i));
   }
@@ -5183,7 +5135,7 @@
     if (dependency == nullptr) {
       if (!pool_->lazily_build_dependencies_) {
         if (pool_->allow_unknown_ ||
-            (!pool_->enforce_weak_ && weak_deps.find(i) != weak_deps.end())) {
+            (!pool_->enforce_weak_ && weak_deps.contains(i))) {
           internal::FlatAllocator lazy_dep_alloc;
           lazy_dep_alloc.PlanArray<FileDescriptor>(1);
           lazy_dep_alloc.PlanArray<std::string>(1);
@@ -5220,8 +5172,8 @@
     }
 
     void* data = tables_->AllocateBytes(
-        static_cast<int>(sizeof(internal::once_flag) + total_char_size));
-    result->dependencies_once_ = ::new (data) internal::once_flag{};
+        static_cast<int>(sizeof(absl::once_flag)) + total_char_size);
+    result->dependencies_once_ = ::new (data) absl::once_flag{};
     char* name_data = reinterpret_cast<char*>(result->dependencies_once_ + 1);
 
     for (int i = 0; i < proto.dependency_size(); i++) {
@@ -5358,7 +5310,7 @@
     return alloc.AllocateStrings(proto_name, proto_name);
   } else {
     return alloc.AllocateStrings(proto_name,
-                                 StrCat(scope, ".", proto_name));
+                                 absl::StrCat(scope, ".", proto_name));
   }
 }
 
@@ -5452,7 +5404,7 @@
       if (range1.end() > range2.start() && range2.end() > range1.start()) {
         AddError(result->full_name(), proto.reserved_range(i),
                  DescriptorPool::ErrorCollector::NUMBER,
-                 strings::Substitute("Reserved range $0 to $1 overlaps with "
+                 absl::Substitute("Reserved range $0 to $1 overlaps with "
                                   "already-defined range $2 to $3.",
                                   range2.start(), range2.end() - 1,
                                   range1.start(), range1.end() - 1));
@@ -5460,14 +5412,12 @@
     }
   }
 
-  HASH_SET<std::string> reserved_name_set;
+  absl::flat_hash_set<std::string> reserved_name_set;
   for (int i = 0; i < proto.reserved_name_size(); i++) {
     const std::string& name = proto.reserved_name(i);
-    if (reserved_name_set.find(name) == reserved_name_set.end()) {
-      reserved_name_set.insert(name);
-    } else {
+    if (!reserved_name_set.insert(name).second) {
       AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
-               strings::Substitute("Field name \"$0\" is reserved multiple times.",
+               absl::Substitute("Field name \"$0\" is reserved multiple times.",
                                 name));
     }
   }
@@ -5483,7 +5433,7 @@
         AddError(
             field->full_name(), proto.extension_range(j),
             DescriptorPool::ErrorCollector::NUMBER,
-            strings::Substitute(
+            absl::Substitute(
                 "Extension range $0 to $1 includes field \"$2\" ($3).",
                 range->start, range->end - 1, field->name(), field->number()));
       }
@@ -5495,7 +5445,7 @@
             proto.reserved_range(j), DescriptorPool::ErrorCollector::NUMBER);
         AddError(field->full_name(), proto.reserved_range(j),
                  DescriptorPool::ErrorCollector::NUMBER,
-                 strings::Substitute("Field \"$0\" uses reserved number $1.",
+                 absl::Substitute("Field \"$0\" uses reserved number $1.",
                                   field->name(), field->number()));
       }
     }
@@ -5503,7 +5453,7 @@
       AddError(
           field->full_name(), proto.field(i),
           DescriptorPool::ErrorCollector::NAME,
-          strings::Substitute("Field name \"$0\" is reserved.", field->name()));
+          absl::Substitute("Field name \"$0\" is reserved.", field->name()));
     }
 
   }
@@ -5517,7 +5467,7 @@
       if (range1->end > range2->start && range2->end > range1->start) {
         AddError(result->full_name(), proto.extension_range(i),
                  DescriptorPool::ErrorCollector::NUMBER,
-                 strings::Substitute("Extension range $0 to $1 overlaps with "
+                 absl::Substitute("Extension range $0 to $1 overlaps with "
                                   "reserved range $2 to $3.",
                                   range1->start, range1->end - 1, range2->start,
                                   range2->end - 1));
@@ -5528,7 +5478,7 @@
       if (range1->end > range2->start && range2->end > range1->start) {
         AddError(result->full_name(), proto.extension_range(i),
                  DescriptorPool::ErrorCollector::NUMBER,
-                 strings::Substitute("Extension range $0 to $1 overlaps with "
+                 absl::Substitute("Extension range $0 to $1 overlaps with "
                                   "already-defined range $2 to $3.",
                                   range2->start, range2->end - 1, range1->start,
                                   range1->end - 1));
@@ -5576,9 +5526,9 @@
   // Some compilers do not allow static_cast directly between two enum types,
   // so we must cast to int first.
   result->type_ = static_cast<FieldDescriptor::Type>(
-      implicit_cast<int>(proto.type()));
+      absl::implicit_cast<int>(proto.type()));
   result->label_ = static_cast<FieldDescriptor::Label>(
-      implicit_cast<int>(proto.label()));
+      absl::implicit_cast<int>(proto.label()));
 
   if (result->label_ == FieldDescriptor::LABEL_REQUIRED) {
     // An extension cannot have a required field (b/13365836).
@@ -5612,19 +5562,23 @@
       switch (result->cpp_type()) {
         case FieldDescriptor::CPPTYPE_INT32:
           result->default_value_int32_t_ =
-              strtol(proto.default_value().c_str(), &end_pos, 0);
+              std::strtol(proto.default_value().c_str(), &end_pos, 0);
           break;
         case FieldDescriptor::CPPTYPE_INT64:
+          static_assert(sizeof(int64_t) == sizeof(long long),
+                        "sizeof int64_t is not sizeof long long");
           result->default_value_int64_t_ =
-              strto64(proto.default_value().c_str(), &end_pos, 0);
+              std::strtoll(proto.default_value().c_str(), &end_pos, 0);
           break;
         case FieldDescriptor::CPPTYPE_UINT32:
           result->default_value_uint32_t_ =
-              strtoul(proto.default_value().c_str(), &end_pos, 0);
+              std::strtoul(proto.default_value().c_str(), &end_pos, 0);
           break;
         case FieldDescriptor::CPPTYPE_UINT64:
+          static_assert(sizeof(uint64_t) == sizeof(unsigned long long),
+                        "sizeof uint64_t is not sizeof unsigned long long");
           result->default_value_uint64_t_ =
-              strtou64(proto.default_value().c_str(), &end_pos, 0);
+              std::strtoull(proto.default_value().c_str(), &end_pos, 0);
           break;
         case FieldDescriptor::CPPTYPE_FLOAT:
           if (proto.default_value() == "inf") {
@@ -5673,8 +5627,9 @@
           break;
         case FieldDescriptor::CPPTYPE_STRING:
           if (result->type() == FieldDescriptor::TYPE_BYTES) {
-            result->default_value_string_ = alloc.AllocateStrings(
-                UnescapeCEscapeString(proto.default_value()));
+            std::string value;
+            absl::CUnescape(proto.default_value(), &value);
+            result->default_value_string_ = alloc.AllocateStrings(value);
           } else {
             result->default_value_string_ =
                 alloc.AllocateStrings(proto.default_value());
@@ -5755,14 +5710,14 @@
     message_hints_[parent].RequestHintOnFieldNumbers(
         proto, DescriptorPool::ErrorCollector::NUMBER);
     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
-             strings::Substitute("Field numbers cannot be greater than $0.",
+             absl::Substitute("Field numbers cannot be greater than $0.",
                               FieldDescriptor::kMaxNumber));
   } else if (result->number() >= FieldDescriptor::kFirstReservedNumber &&
              result->number() <= FieldDescriptor::kLastReservedNumber) {
     message_hints_[parent].RequestHintOnFieldNumbers(
         proto, DescriptorPool::ErrorCollector::NUMBER);
     AddError(result->full_name(), proto, DescriptorPool::ErrorCollector::NUMBER,
-             strings::Substitute(
+             absl::Substitute(
                  "Field numbers $0 through $1 are reserved for the protocol "
                  "buffer library implementation.",
                  FieldDescriptor::kFirstReservedNumber,
@@ -5797,7 +5752,7 @@
           proto.oneof_index() >= parent->oneof_decl_count()) {
         AddError(result->full_name(), proto,
                  DescriptorPool::ErrorCollector::TYPE,
-                 strings::Substitute("FieldDescriptorProto.oneof_index $0 is "
+                 absl::Substitute("FieldDescriptorProto.oneof_index $0 is "
                                   "out of range for type \"$1\".",
                                   proto.oneof_index(), parent->name()));
       } else {
@@ -6046,7 +6001,7 @@
       if (range1.end() >= range2.start() && range2.end() >= range1.start()) {
         AddError(result->full_name(), proto.reserved_range(i),
                  DescriptorPool::ErrorCollector::NUMBER,
-                 strings::Substitute("Reserved range $0 to $1 overlaps with "
+                 absl::Substitute("Reserved range $0 to $1 overlaps with "
                                   "already-defined range $2 to $3.",
                                   range2.start(), range2.end(), range1.start(),
                                   range1.end()));
@@ -6054,14 +6009,14 @@
     }
   }
 
-  HASH_SET<std::string> reserved_name_set;
+  absl::flat_hash_set<std::string> reserved_name_set;
   for (int i = 0; i < proto.reserved_name_size(); i++) {
     const std::string& name = proto.reserved_name(i);
     if (reserved_name_set.find(name) == reserved_name_set.end()) {
       reserved_name_set.insert(name);
     } else {
       AddError(name, proto, DescriptorPool::ErrorCollector::NAME,
-               strings::Substitute("Enum value \"$0\" is reserved multiple times.",
+               absl::Substitute("Enum value \"$0\" is reserved multiple times.",
                                 name));
     }
   }
@@ -6073,7 +6028,7 @@
       if (range->start <= value->number() && value->number() <= range->end) {
         AddError(value->full_name(), proto.reserved_range(j),
                  DescriptorPool::ErrorCollector::NUMBER,
-                 strings::Substitute("Enum value \"$0\" uses reserved number $1.",
+                 absl::Substitute("Enum value \"$0\" uses reserved number $1.",
                                   value->name(), value->number()));
       }
     }
@@ -6081,7 +6036,7 @@
       AddError(
           value->full_name(), proto.value(i),
           DescriptorPool::ErrorCollector::NAME,
-          strings::Substitute("Enum value \"$0\" is reserved.", value->name()));
+          absl::Substitute("Enum value \"$0\" is reserved.", value->name()));
     }
   }
 }
@@ -6279,7 +6234,7 @@
           message->field(i - 1)->containing_oneof() != oneof_decl) {
         AddError(message->full_name() + "." + message->field(i - 1)->name(),
                  proto.field(i - 1), DescriptorPool::ErrorCollector::TYPE,
-                 strings::Substitute(
+                 absl::Substitute(
                      "Fields in the same oneof must be defined consecutively. "
                      "\"$0\" cannot be defined before the completion of the "
                      "\"$1\" oneof definition.",
@@ -6399,7 +6354,7 @@
       if (!skip_check) {
         AddError(field->full_name(), proto,
                  DescriptorPool::ErrorCollector::NUMBER,
-                 strings::Substitute("\"$0\" does not declare $1 as an "
+                 absl::Substitute("\"$0\" does not declare $1 as an "
                                   "extension number.",
                                   field->containing_type()->full_name(),
                                   field->number()));
@@ -6449,8 +6404,9 @@
         int name_sizes = static_cast<int>(name.size() + 1 +
                                           proto.default_value().size() + 1);
 
-        field->type_once_ = ::new (tables_->AllocateBytes(static_cast<int>(
-            sizeof(internal::once_flag) + name_sizes))) internal::once_flag{};
+        field->type_once_ = ::new (tables_->AllocateBytes(
+            static_cast<int>(sizeof(absl::once_flag)) + name_sizes))
+            absl::once_flag{};
         char* names = reinterpret_cast<char*>(field->type_once_ + 1);
 
         memcpy(names, name.c_str(), name.size() + 1);
@@ -6589,14 +6545,14 @@
     if (field->is_extension()) {
       AddError(field->full_name(), proto,
                DescriptorPool::ErrorCollector::NUMBER,
-               strings::Substitute("Extension number $0 has already been used "
+               absl::Substitute("Extension number $0 has already been used "
                                 "in \"$1\" by extension \"$2\".",
                                 field->number(), containing_type_name,
                                 conflicting_field->full_name()));
     } else {
       AddError(field->full_name(), proto,
                DescriptorPool::ErrorCollector::NUMBER,
-               strings::Substitute("Field number $0 has already been used in "
+               absl::Substitute("Field number $0 has already been used in "
                                 "\"$1\" by field \"$2\".",
                                 field->number(), containing_type_name,
                                 conflicting_field->name()));
@@ -6610,7 +6566,7 @@
             field->containing_type() == nullptr
                 ? "unknown"
                 : field->containing_type()->full_name();
-        std::string error_msg = strings::Substitute(
+        std::string error_msg = absl::Substitute(
             "Extension number $0 has already been used in \"$1\" by extension "
             "\"$2\" defined in $3.",
             field->number(), containing_type_name,
@@ -6708,8 +6664,9 @@
   for (int message_index = 0; message_index < file->message_type_count();
        message_index++) {
     const Descriptor* message = &file->message_types_[message_index];
-    auto* hints = FindOrNull(message_hints_, message);
-    if (!hints) continue;
+    auto hints_it = message_hints_.find(message);
+    if (hints_it == message_hints_.end()) continue;
+    auto* hints = &hints_it->second;
     constexpr int kMaxSuggestions = 3;
     int fields_to_suggest = std::min(kMaxSuggestions, hints->fields_to_suggest);
     if (fields_to_suggest <= 0) continue;
@@ -6951,7 +6908,7 @@
     if (message->extension_range(i)->end > max_extension_range + 1) {
       AddError(message->full_name(), proto.extension_range(i),
                DescriptorPool::ErrorCollector::NUMBER,
-               strings::Substitute("Extension numbers cannot be greater than $0.",
+               absl::Substitute("Extension numbers cannot be greater than $0.",
                                 max_extension_range));
     }
 
@@ -7309,7 +7266,7 @@
           *original_options, original_uninterpreted_options_field);
   for (int i = 0; i < num_uninterpreted_options; ++i) {
     src_path.push_back(i);
-    uninterpreted_option_ = down_cast<const UninterpretedOption*>(
+    uninterpreted_option_ = DownCast<const UninterpretedOption*>(
         &original_options->GetReflection()->GetRepeatedMessage(
             *original_options, original_uninterpreted_options_field, i));
     if (!InterpretSingleOption(options, src_path,
@@ -7729,6 +7686,27 @@
   return true;
 }
 
+namespace {
+// Helpers for method below
+
+template <typename T> std::string ValueOutOfRange(
+    absl::string_view type_name, absl::string_view option_name) {
+  return absl::StrFormat(
+    "Value out of range, %d to %d, for %s option \"%s\".", \
+    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
+    type_name, option_name);
+}
+
+template <typename T> std::string ValueMustBeInt(
+    absl::string_view type_name, absl::string_view option_name) {
+  return absl::StrFormat(
+    "Value must be integer, from %d to %d, for %s option \"%s\".", \
+    std::numeric_limits<T>::min(), std::numeric_limits<T>::max(),
+    type_name, option_name);
+}
+
+} // namespace
+
 bool DescriptorBuilder::OptionInterpreter::SetOptionValue(
     const FieldDescriptor* option_field, UnknownFieldSet* unknown_fields) {
   // We switch on the CppType to validate.
@@ -7737,8 +7715,7 @@
       if (uninterpreted_option_->has_positive_int_value()) {
         if (uninterpreted_option_->positive_int_value() >
             static_cast<uint64_t>(std::numeric_limits<int32_t>::max())) {
-          return AddValueError("Value out of range for int32 option \"" +
-                               option_field->full_name() + "\".");
+          return AddValueError(ValueOutOfRange<int32_t>("int32", option_field->full_name()));
         } else {
           SetInt32(option_field->number(),
                    uninterpreted_option_->positive_int_value(),
@@ -7747,16 +7724,14 @@
       } else if (uninterpreted_option_->has_negative_int_value()) {
         if (uninterpreted_option_->negative_int_value() <
             static_cast<int64_t>(std::numeric_limits<int32_t>::min())) {
-          return AddValueError("Value out of range for int32 option \"" +
-                               option_field->full_name() + "\".");
+          return AddValueError(ValueOutOfRange<int32_t>("int32", option_field->full_name()));
         } else {
           SetInt32(option_field->number(),
                    uninterpreted_option_->negative_int_value(),
                    option_field->type(), unknown_fields);
         }
       } else {
-        return AddValueError("Value must be integer for int32 option \"" +
-                             option_field->full_name() + "\".");
+        return AddValueError(ValueMustBeInt<int32_t>("int32", option_field->full_name()));
       }
       break;
 
@@ -7764,8 +7739,7 @@
       if (uninterpreted_option_->has_positive_int_value()) {
         if (uninterpreted_option_->positive_int_value() >
             static_cast<uint64_t>(std::numeric_limits<int64_t>::max())) {
-          return AddValueError("Value out of range for int64 option \"" +
-                               option_field->full_name() + "\".");
+          return AddValueError(ValueOutOfRange<int64_t>("int64", option_field->full_name()));
         } else {
           SetInt64(option_field->number(),
                    uninterpreted_option_->positive_int_value(),
@@ -7776,8 +7750,7 @@
                  uninterpreted_option_->negative_int_value(),
                  option_field->type(), unknown_fields);
       } else {
-        return AddValueError("Value must be integer for int64 option \"" +
-                             option_field->full_name() + "\".");
+        return AddValueError(ValueMustBeInt<int64_t>("int64", option_field->full_name()));
       }
       break;
 
@@ -7785,18 +7758,14 @@
       if (uninterpreted_option_->has_positive_int_value()) {
         if (uninterpreted_option_->positive_int_value() >
             std::numeric_limits<uint32_t>::max()) {
-          return AddValueError("Value out of range for uint32 option \"" +
-                               option_field->name() + "\".");
+          return AddValueError(ValueOutOfRange<uint32_t>("uint32", option_field->full_name()));
         } else {
           SetUInt32(option_field->number(),
                     uninterpreted_option_->positive_int_value(),
                     option_field->type(), unknown_fields);
         }
       } else {
-        return AddValueError(
-            "Value must be non-negative integer for uint32 "
-            "option \"" +
-            option_field->full_name() + "\".");
+        return AddValueError(ValueMustBeInt<uint32_t>("uint32", option_field->full_name()));
       }
       break;
 
@@ -7806,10 +7775,7 @@
                   uninterpreted_option_->positive_int_value(),
                   option_field->type(), unknown_fields);
       } else {
-        return AddValueError(
-            "Value must be non-negative integer for uint64 "
-            "option \"" +
-            option_field->full_name() + "\".");
+        return AddValueError(ValueMustBeInt<uint64_t>("uint64", option_field->full_name()));
       }
       break;
 
@@ -8154,22 +8120,20 @@
     auto itr = pool_->unused_import_track_files_.find(proto.name());
     bool is_error =
         itr != pool_->unused_import_track_files_.end() && itr->second;
-    for (std::set<const FileDescriptor*>::const_iterator it =
-             unused_dependency_.begin();
-         it != unused_dependency_.end(); ++it) {
-      std::string error_message = "Import " + (*it)->name() + " is unused.";
+    for (const auto* unused : unused_dependency_) {
+      std::string error_message = "Import " + unused->name() + " is unused.";
       if (is_error) {
-        AddError((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
+        AddError(unused->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
                  error_message);
       } else {
-        AddWarning((*it)->name(), proto, DescriptorPool::ErrorCollector::IMPORT,
-                   error_message);
+        AddWarning(unused->name(), proto,
+                   DescriptorPool::ErrorCollector::IMPORT, error_message);
       }
     }
   }
 }
 
-Symbol DescriptorPool::CrossLinkOnDemandHelper(StringPiece name,
+Symbol DescriptorPool::CrossLinkOnDemandHelper(absl::string_view name,
                                                bool expecting_enum) const {
   (void)expecting_enum;  // Parameter is used by Google-internal code.
   auto lookup_name = std::string(name);
@@ -8231,11 +8195,11 @@
 }
 
 // message_type(), enum_type(), default_value_enum(), and type()
-// all share the same internal::call_once init path to do lazy
+// all share the same absl::call_once init path to do lazy
 // import building and cross linking of a field of a message.
 const Descriptor* FieldDescriptor::message_type() const {
   if (type_once_) {
-    internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
+    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
   }
   return type_ == TYPE_MESSAGE || type_ == TYPE_GROUP
              ? type_descriptor_.message_type
@@ -8244,14 +8208,14 @@
 
 const EnumDescriptor* FieldDescriptor::enum_type() const {
   if (type_once_) {
-    internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
+    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
   }
   return type_ == TYPE_ENUM ? type_descriptor_.enum_type : nullptr;
 }
 
 const EnumValueDescriptor* FieldDescriptor::default_value_enum() const {
   if (type_once_) {
-    internal::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
+    absl::call_once(*type_once_, FieldDescriptor::TypeOnceInit, this);
   }
   return default_value_enum_;
 }
@@ -8284,9 +8248,9 @@
 const FileDescriptor* FileDescriptor::dependency(int index) const {
   if (dependencies_once_) {
     // Do once init for all indices, as it's unlikely only a single index would
-    // be called, and saves on internal::call_once allocations.
-    internal::call_once(*dependencies_once_,
-                        FileDescriptor::DependenciesOnceInit, this);
+    // be called, and saves on absl::call_once allocations.
+    absl::call_once(*dependencies_once_, FileDescriptor::DependenciesOnceInit,
+                    this);
   }
   return dependencies_[index];
 }
@@ -8305,7 +8269,7 @@
   descriptor_ = descriptor;
 }
 
-void LazyDescriptor::SetLazy(StringPiece name,
+void LazyDescriptor::SetLazy(absl::string_view name,
                              const FileDescriptor* file) {
   // verify Init() has been called and Set hasn't been called yet.
   GOOGLE_CHECK(!descriptor_);
@@ -8314,7 +8278,7 @@
   GOOGLE_CHECK(file->pool_->lazily_build_dependencies_);
   GOOGLE_CHECK(!file->finished_building_);
   once_ = ::new (file->pool_->tables_->AllocateBytes(static_cast<int>(
-      sizeof(internal::once_flag) + name.size() + 1))) internal::once_flag{};
+      sizeof(absl::once_flag) + name.size() + 1))) absl::once_flag{};
   char* lazy_name = reinterpret_cast<char*>(once_ + 1);
   memcpy(lazy_name, name.data(), name.size());
   lazy_name[name.size()] = 0;
@@ -8322,7 +8286,7 @@
 
 void LazyDescriptor::Once(const ServiceDescriptor* service) {
   if (once_) {
-    internal::call_once(*once_, [&] {
+    absl::call_once(*once_, [&] {
       auto* file = service->file();
       GOOGLE_CHECK(file->finished_building_);
       const char* lazy_name = reinterpret_cast<const char*>(once_ + 1);
@@ -8332,9 +8296,51 @@
   }
 }
 
+namespace cpp {
+bool HasPreservingUnknownEnumSemantics(const FieldDescriptor* field) {
+  return field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
+bool HasHasbit(const FieldDescriptor* field) {
+  // This predicate includes proto3 message fields only if they have "optional".
+  //   Foo submsg1 = 1;           // HasHasbit() == false
+  //   optional Foo submsg2 = 2;  // HasHasbit() == true
+  // This is slightly odd, as adding "optional" to a singular proto3 field does
+  // not change the semantics or API. However whenever any field in a message
+  // has a hasbit, it forces reflection to include hasbit offsets for *all*
+  // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
+  // causing a sudden size regression for ~all proto3 messages, we give proto3
+  // message fields a hasbit only if "optional" is present. If the user is
+  // explicitly writing "optional", it is likely they are writing it on
+  // primitive fields also.
+  return (field->has_optional_keyword() || field->is_required()) &&
+         !field->options().weak();
+}
+
+static bool FieldEnforceUtf8(const FieldDescriptor* field) {
+  return true;
+}
+
+static bool FileUtf8Verification(const FileDescriptor* file) {
+  return true;
+}
+
+// Which level of UTF-8 enforcemant is placed on this file.
+Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field, bool is_lite) {
+  if (field->file()->syntax() == FileDescriptor::SYNTAX_PROTO3 &&
+      FieldEnforceUtf8(field)) {
+    return Utf8CheckMode::kStrict;
+  } else if (!is_lite && FileUtf8Verification(field->file())) {
+    return Utf8CheckMode::kVerify;
+  } else {
+    return Utf8CheckMode::kNone;
+  }
+}
+
+}  // namespace cpp
 }  // namespace internal
 
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/descriptor.h b/src/google/protobuf/descriptor.h
index 6e536e5..5a8b5f3 100644
--- a/src/google/protobuf/descriptor.h
+++ b/src/google/protobuf/descriptor.h
@@ -54,27 +54,26 @@
 #ifndef GOOGLE_PROTOBUF_DESCRIPTOR_H__
 #define GOOGLE_PROTOBUF_DESCRIPTOR_H__
 
-
 #include <atomic>
+#include <cstdint>
+#include <iterator>
 #include <map>
 #include <memory>
 #include <set>
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/port.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/port.h"
+#include "absl/base/call_once.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/port.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
-
-// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
-#ifdef TYPE_BOOL
-#undef TYPE_BOOL
-#endif  // TYPE_BOOL
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #define PROTOBUF_EXPORT
@@ -220,7 +219,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(StringPiece name, const FileDescriptor* file);
+  void SetLazy(absl::string_view 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,
@@ -235,7 +234,7 @@
 
   const Descriptor* descriptor_;
   // The once_ flag is followed by a NUL terminated string for the type name.
-  internal::once_flag* once_;
+  absl::once_flag* once_;
 };
 
 class PROTOBUF_EXPORT SymbolBase {
@@ -261,6 +260,10 @@
 class PROTOBUF_EXPORT Descriptor : private internal::SymbolBase {
  public:
   typedef DescriptorProto Proto;
+#ifndef SWIG
+  Descriptor(const Descriptor&) = delete;
+  Descriptor& operator=(const Descriptor&) = delete;
+#endif
 
   // The name of the message type, not including its scope.
   const std::string& name() const;
@@ -349,20 +352,20 @@
   // exists.
   const FieldDescriptor* FindFieldByNumber(int number) const;
   // Looks up a field by name.  Returns nullptr if no such field exists.
-  const FieldDescriptor* FindFieldByName(ConstStringParam name) const;
+  const FieldDescriptor* FindFieldByName(absl::string_view 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(
-      ConstStringParam lowercase_name) const;
+      absl::string_view 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(
-      ConstStringParam camelcase_name) const;
+      absl::string_view camelcase_name) const;
 
   // The number of oneofs in this message type.
   int oneof_decl_count() const;
@@ -375,7 +378,7 @@
   const OneofDescriptor* oneof_decl(int index) const;
 
   // Looks up a oneof by name.  Returns nullptr if no such oneof exists.
-  const OneofDescriptor* FindOneofByName(ConstStringParam name) const;
+  const OneofDescriptor* FindOneofByName(absl::string_view name) const;
 
   // Nested type stuff -----------------------------------------------
 
@@ -387,7 +390,7 @@
 
   // Looks up a nested type by name.  Returns nullptr if no such nested type
   // exists.
-  const Descriptor* FindNestedTypeByName(ConstStringParam name) const;
+  const Descriptor* FindNestedTypeByName(absl::string_view name) const;
 
   // Enum stuff ------------------------------------------------------
 
@@ -399,11 +402,11 @@
 
   // Looks up an enum type by name.  Returns nullptr if no such enum type
   // exists.
-  const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const;
+  const EnumDescriptor* FindEnumTypeByName(absl::string_view 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(ConstStringParam name) const;
+  const EnumValueDescriptor* FindEnumValueByName(absl::string_view name) const;
 
   // Extensions ------------------------------------------------------
 
@@ -467,17 +470,17 @@
 
   // Looks up a named extension (which extends some *other* message type)
   // defined within this message type's scope.
-  const FieldDescriptor* FindExtensionByName(ConstStringParam name) const;
+  const FieldDescriptor* FindExtensionByName(absl::string_view name) const;
 
   // Similar to FindFieldByLowercaseName(), but finds extensions defined within
   // this message type's scope.
   const FieldDescriptor* FindExtensionByLowercaseName(
-      ConstStringParam name) const;
+      absl::string_view name) const;
 
   // Similar to FindFieldByCamelcaseName(), but finds extensions defined within
   // this message type's scope.
   const FieldDescriptor* FindExtensionByCamelcaseName(
-      ConstStringParam name) const;
+      absl::string_view name) const;
 
   // Reserved fields -------------------------------------------------
 
@@ -507,7 +510,7 @@
   const std::string& reserved_name(int index) const;
 
   // Returns true if the field name is reserved.
-  bool IsReservedName(ConstStringParam name) const;
+  bool IsReservedName(absl::string_view name) const;
 
   // Source Location ---------------------------------------------------
 
@@ -609,7 +612,6 @@
   friend class OneofDescriptor;
   friend class MethodDescriptor;
   friend class FileDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Descriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(Descriptor, 136);
@@ -628,6 +630,11 @@
  public:
   typedef FieldDescriptorProto Proto;
 
+#ifndef SWIG
+  FieldDescriptor(const FieldDescriptor&) = delete;
+  FieldDescriptor& operator=(const FieldDescriptor&) = delete;
+#endif
+
   // Identifies a field type.  0 is reserved for errors.  The order is weird
   // for historical reasons.  Types 12 and up are new in proto2.
   enum Type {
@@ -754,6 +761,10 @@
   // Reflection::HasField() is semantically meaningful.
   bool has_presence() const;
 
+  // Returns true if this TYPE_STRING-typed field requires UTF-8 validation on
+  // parse.
+  bool requires_utf8_validation() const;
+
   // Index of this field within the message's field array, or the file or
   // extension scope's extensions array.
   int index() const;
@@ -941,7 +952,7 @@
 
   // The once_flag is followed by a NUL terminated string for the type name and
   // enum default value (or empty string if no default enum).
-  internal::once_flag* type_once_;
+  absl::once_flag* type_once_;
   static void TypeOnceInit(const FieldDescriptor* to_init);
   void InternalTypeOnceInit() const;
   const Descriptor* containing_type_;
@@ -986,7 +997,6 @@
   friend class FileDescriptor;
   friend class Descriptor;
   friend class OneofDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FieldDescriptor, 72);
@@ -996,6 +1006,11 @@
  public:
   typedef OneofDescriptorProto Proto;
 
+#ifndef SWIG
+  OneofDescriptor(const OneofDescriptor&) = delete;
+  OneofDescriptor& operator=(const OneofDescriptor&) = delete;
+#endif
+
   const std::string& name() const;       // Name of this oneof.
   const std::string& full_name() const;  // Fully-qualified name of the oneof.
 
@@ -1067,7 +1082,6 @@
   OneofDescriptor() {}
   friend class DescriptorBuilder;
   friend class Descriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OneofDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(OneofDescriptor, 40);
@@ -1079,6 +1093,11 @@
  public:
   typedef EnumDescriptorProto Proto;
 
+#ifndef SWIG
+  EnumDescriptor(const EnumDescriptor&) = delete;
+  EnumDescriptor& operator=(const EnumDescriptor&) = delete;
+#endif
+
   // The name of this enum type in the containing scope.
   const std::string& name() const;
 
@@ -1099,7 +1118,7 @@
   const EnumValueDescriptor* value(int index) const;
 
   // Looks up a value by name.  Returns nullptr if no such value exists.
-  const EnumValueDescriptor* FindValueByName(ConstStringParam name) const;
+  const EnumValueDescriptor* FindValueByName(absl::string_view 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;
@@ -1128,6 +1147,13 @@
   // with AllowUnknownDependencies() set.
   bool is_placeholder() const;
 
+  // Returns true whether this is a "closed" enum, meaning that it:
+  // - Has a fixed set of named values.
+  // - Encountering values not in this set causes them to be treated as unknown
+  //   fields.
+  // - The first value (i.e., the default) may be nonzero.
+  bool is_closed() const;
+
   // Reserved fields -------------------------------------------------
 
   // A range of reserved field numbers.
@@ -1157,7 +1183,7 @@
   const std::string& reserved_name(int index) const;
 
   // Returns true if the field name is reserved.
-  bool IsReservedName(ConstStringParam name) const;
+  bool IsReservedName(absl::string_view name) const;
 
   // Source Location ---------------------------------------------------
 
@@ -1238,7 +1264,6 @@
   friend class FileDescriptor;
   friend class DescriptorPool;
   friend class Reflection;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(EnumDescriptor, 72);
@@ -1253,6 +1278,11 @@
  public:
   typedef EnumValueDescriptorProto Proto;
 
+#ifndef SWIG
+  EnumValueDescriptor(const EnumValueDescriptor&) = delete;
+  EnumValueDescriptor& operator=(const EnumValueDescriptor&) = delete;
+#endif
+
   const std::string& name() const;  // Name of this enum constant.
   int index() const;                // Index within the enums's Descriptor.
   int number() const;               // Numeric value of this enum constant.
@@ -1323,7 +1353,6 @@
   friend class DescriptorPool;
   friend class FileDescriptorTables;
   friend class Reflection;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EnumValueDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(EnumValueDescriptor, 32);
@@ -1334,6 +1363,11 @@
  public:
   typedef ServiceDescriptorProto Proto;
 
+#ifndef SWIG
+  ServiceDescriptor(const ServiceDescriptor&) = delete;
+  ServiceDescriptor& operator=(const ServiceDescriptor&) = delete;
+#endif
+
   // The name of the service, not including its containing scope.
   const std::string& name() const;
   // The fully-qualified name of the service, scope delimited by periods.
@@ -1357,7 +1391,7 @@
   const MethodDescriptor* method(int index) const;
 
   // Look up a MethodDescriptor by name.
-  const MethodDescriptor* FindMethodByName(ConstStringParam name) const;
+  const MethodDescriptor* FindMethodByName(absl::string_view name) const;
 
   // See Descriptor::CopyTo().
   void CopyTo(ServiceDescriptorProto* proto) const;
@@ -1406,7 +1440,6 @@
   friend class DescriptorBuilder;
   friend class FileDescriptor;
   friend class MethodDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ServiceDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(ServiceDescriptor, 48);
@@ -1419,6 +1452,11 @@
  public:
   typedef MethodDescriptorProto Proto;
 
+#ifndef SWIG
+  MethodDescriptor(const MethodDescriptor&) = delete;
+  MethodDescriptor& operator=(const MethodDescriptor&) = delete;
+#endif
+
   // Name of this method, not including containing scope.
   const std::string& name() const;
   // The fully-qualified name of the method, scope delimited by periods.
@@ -1495,7 +1533,6 @@
   MethodDescriptor() {}
   friend class DescriptorBuilder;
   friend class ServiceDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MethodDescriptor);
 };
 
 PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(MethodDescriptor, 64);
@@ -1507,6 +1544,11 @@
  public:
   typedef FileDescriptorProto Proto;
 
+#ifndef SWIG
+  FileDescriptor(const FileDescriptor&) = delete;
+  FileDescriptor& operator=(const FileDescriptor&) = delete;
+#endif
+
   // The filename, relative to the source tree.
   // e.g. "foo/bar/baz.proto"
   const std::string& name() const;
@@ -1574,7 +1616,11 @@
   const FileOptions& options() const;
 
   // Syntax of this file.
-  enum Syntax {
+  enum Syntax
+#ifndef SWIG
+      : int
+#endif  // !SWIG
+  {
     SYNTAX_UNKNOWN = 0,
     SYNTAX_PROTO2 = 2,
     SYNTAX_PROTO3 = 3,
@@ -1584,25 +1630,25 @@
 
   // Find a top-level message type by name (not full_name).  Returns nullptr if
   // not found.
-  const Descriptor* FindMessageTypeByName(ConstStringParam name) const;
+  const Descriptor* FindMessageTypeByName(absl::string_view name) const;
   // Find a top-level enum type by name.  Returns nullptr if not found.
-  const EnumDescriptor* FindEnumTypeByName(ConstStringParam name) const;
+  const EnumDescriptor* FindEnumTypeByName(absl::string_view name) const;
   // Find an enum value defined in any top-level enum by name.  Returns nullptr
   // if not found.
-  const EnumValueDescriptor* FindEnumValueByName(ConstStringParam name) const;
+  const EnumValueDescriptor* FindEnumValueByName(absl::string_view name) const;
   // Find a service definition by name.  Returns nullptr if not found.
-  const ServiceDescriptor* FindServiceByName(ConstStringParam name) const;
+  const ServiceDescriptor* FindServiceByName(absl::string_view name) const;
   // Find a top-level extension definition by name.  Returns nullptr if not
   // found.
-  const FieldDescriptor* FindExtensionByName(ConstStringParam name) const;
+  const FieldDescriptor* FindExtensionByName(absl::string_view name) const;
   // Similar to FindExtensionByName(), but searches by lowercased-name.  See
   // Descriptor::FindFieldByLowercaseName().
   const FieldDescriptor* FindExtensionByLowercaseName(
-      ConstStringParam name) const;
+      absl::string_view name) const;
   // Similar to FindExtensionByName(), but searches by camelcased-name.  See
   // Descriptor::FindFieldByCamelcaseName().
   const FieldDescriptor* FindExtensionByCamelcaseName(
-      ConstStringParam name) const;
+      absl::string_view name) const;
 
   // See Descriptor::CopyTo().
   // Notes:
@@ -1615,6 +1661,9 @@
   // Fill the json_name field of FieldDescriptorProto for all fields. Can only
   // be called after CopyTo().
   void CopyJsonNameTo(FileDescriptorProto* proto) const;
+  // Fills in the file-level settings of this file (e.g. syntax, package,
+  // file options) to `proto`.
+  void CopyHeadingTo(FileDescriptorProto* proto) const;
 
   // See Descriptor::DebugString().
   std::string DebugString() const;
@@ -1660,7 +1709,7 @@
   // dependencies_once_ contain a once_flag followed by N NUL terminated
   // strings. Dependencies that do not need to be loaded will be empty. ie just
   // {'\0'}
-  internal::once_flag* dependencies_once_;
+  absl::once_flag* dependencies_once_;
   static void DependenciesOnceInit(const FileDescriptor* to_init);
   void InternalDependenciesOnceInit() const;
 
@@ -1699,10 +1748,9 @@
   friend class EnumValueDescriptor;
   friend class MethodDescriptor;
   friend class ServiceDescriptor;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileDescriptor);
 };
 
-PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FileDescriptor, 144);
+PROTOBUF_INTERNAL_CHECK_CLASS_SIZE(FileDescriptor, 152);
 
 // ===================================================================
 
@@ -1762,6 +1810,10 @@
   explicit DescriptorPool(DescriptorDatabase* fallback_database,
                           ErrorCollector* error_collector = nullptr);
 
+#ifndef SWIG
+  DescriptorPool(const DescriptorPool&) = delete;
+  DescriptorPool& operator=(const DescriptorPool&) = delete;
+#endif
   ~DescriptorPool();
 
   // Get a pointer to the generated pool.  Generated protocol message classes
@@ -1772,28 +1824,28 @@
 
   // Find a FileDescriptor in the pool by file name.  Returns nullptr if not
   // found.
-  const FileDescriptor* FindFileByName(ConstStringParam name) const;
+  const FileDescriptor* FindFileByName(absl::string_view 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(
-      ConstStringParam symbol_name) const;
+      absl::string_view 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(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;
+  const Descriptor* FindMessageTypeByName(absl::string_view name) const;
+  const FieldDescriptor* FindFieldByName(absl::string_view name) const;
+  const FieldDescriptor* FindExtensionByName(absl::string_view name) const;
+  const OneofDescriptor* FindOneofByName(absl::string_view name) const;
+  const EnumDescriptor* FindEnumTypeByName(absl::string_view name) const;
+  const EnumValueDescriptor* FindEnumValueByName(absl::string_view name) const;
+  const ServiceDescriptor* FindServiceByName(absl::string_view name) const;
+  const MethodDescriptor* FindMethodByName(absl::string_view 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.
@@ -1806,7 +1858,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, ConstStringParam printable_name) const;
+      const Descriptor* extendee, absl::string_view printable_name) const;
 
   // Finds extensions of extendee. The extensions will be appended to
   // out in an undefined order. Only extensions defined directly in
@@ -1824,6 +1876,10 @@
   class PROTOBUF_EXPORT ErrorCollector {
    public:
     inline ErrorCollector() {}
+#ifndef SWIG
+    ErrorCollector(const ErrorCollector&) = delete;
+    ErrorCollector& operator=(const ErrorCollector&) = delete;
+#endif
     virtual ~ErrorCollector();
 
     // These constants specify what exact part of the construct is broken.
@@ -1864,9 +1920,6 @@
         ErrorLocation /*location*/,     // One of the location constants, above.
         const std::string& /*message*/  // Human-readable error message.
     ) {}
-
-   private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
   };
 
   // Convert the FileDescriptorProto to real descriptors and place them in
@@ -1979,11 +2032,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(ConstStringParam filename) const;
+  bool InternalIsFileLoaded(absl::string_view 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(ConstStringParam file_name,
+  void AddUnusedImportTrackFile(absl::string_view file_name,
                                 bool is_error = false);
   void ClearUnusedImportTrackFiles();
 
@@ -2001,14 +2054,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(StringPiece name) const;
+  bool IsSubSymbolOfBuiltType(absl::string_view 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(StringPiece name) const;
-  bool TryFindSymbolInFallbackDatabase(StringPiece name) const;
+  bool TryFindFileInFallbackDatabase(absl::string_view name) const;
+  bool TryFindSymbolInFallbackDatabase(absl::string_view name) const;
   bool TryFindExtensionInFallbackDatabase(const Descriptor* containing_type,
                                           int field_number) const;
 
@@ -2029,13 +2082,13 @@
   // 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(StringPiece name,
+  Symbol CrossLinkOnDemandHelper(absl::string_view name,
                                  bool expecting_enum) const;
 
   // Create a placeholder FileDescriptor of the specified name
-  FileDescriptor* NewPlaceholderFile(StringPiece name) const;
+  FileDescriptor* NewPlaceholderFile(absl::string_view name) const;
   FileDescriptor* NewPlaceholderFileWithMutexHeld(
-      StringPiece name, internal::FlatAllocator& alloc) const;
+      absl::string_view name, internal::FlatAllocator& alloc) const;
 
   enum PlaceholderType {
     PLACEHOLDER_MESSAGE,
@@ -2043,14 +2096,14 @@
     PLACEHOLDER_EXTENDABLE_MESSAGE
   };
   // Create a placeholder Descriptor of the specified name
-  Symbol NewPlaceholder(StringPiece name,
+  Symbol NewPlaceholder(absl::string_view name,
                         PlaceholderType placeholder_type) const;
-  Symbol NewPlaceholderWithMutexHeld(StringPiece name,
+  Symbol NewPlaceholderWithMutexHeld(absl::string_view name,
                                      PlaceholderType placeholder_type) const;
 
   // If fallback_database_ is nullptr, this is nullptr.  Otherwise, this is a
   // mutex which must be locked while accessing tables_.
-  internal::WrappedMutex* mutex_;
+  absl::Mutex* mutex_;
 
   // See constructor.
   DescriptorDatabase* fallback_database_;
@@ -2071,8 +2124,6 @@
   // Set of files to track for unused imports. The bool value when true means
   // unused imports are treated as errors (and as warnings when false).
   std::map<std::string, bool> unused_import_track_files_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPool);
 };
 
 
@@ -2163,6 +2214,10 @@
                                const EnumDescriptor::ReservedRange*)
 PROTOBUF_DEFINE_ACCESSOR(EnumDescriptor, reserved_name_count, int)
 
+inline bool EnumDescriptor::is_closed() const {
+  return file()->syntax() != FileDescriptor::SYNTAX_PROTO3;
+}
+
 PROTOBUF_DEFINE_NAME_ACCESSOR(EnumValueDescriptor)
 PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, number, int)
 PROTOBUF_DEFINE_ACCESSOR(EnumValueDescriptor, type, const EnumDescriptor*)
@@ -2219,9 +2274,9 @@
   return FindReservedRangeContainingNumber(number) != nullptr;
 }
 
-inline bool Descriptor::IsReservedName(ConstStringParam name) const {
+inline bool Descriptor::IsReservedName(absl::string_view name) const {
   for (int i = 0; i < reserved_name_count(); i++) {
-    if (name == static_cast<ConstStringParam>(reserved_name(i))) {
+    if (name == static_cast<absl::string_view>(reserved_name(i))) {
       return true;
     }
   }
@@ -2238,9 +2293,9 @@
   return FindReservedRangeContainingNumber(number) != nullptr;
 }
 
-inline bool EnumDescriptor::IsReservedName(ConstStringParam name) const {
+inline bool EnumDescriptor::IsReservedName(absl::string_view name) const {
   for (int i = 0; i < reserved_name_count(); i++) {
-    if (name == static_cast<ConstStringParam>(reserved_name(i))) {
+    if (name == static_cast<absl::string_view>(reserved_name(i))) {
       return true;
     }
   }
@@ -2285,7 +2340,7 @@
 
 inline FieldDescriptor::Type FieldDescriptor::type() const {
   if (type_once_) {
-    internal::call_once(*type_once_, &FieldDescriptor::TypeOnceInit, this);
+    absl::call_once(*type_once_, &FieldDescriptor::TypeOnceInit, this);
   }
   return static_cast<Type>(type_);
 }
@@ -2327,6 +2382,11 @@
          file()->syntax() == FileDescriptor::SYNTAX_PROTO2;
 }
 
+inline bool FieldDescriptor::requires_utf8_validation() const {
+  return type() == TYPE_STRING &&
+         file()->syntax() == FileDescriptor::SYNTAX_PROTO3;
+}
+
 // To save space, index() is computed by looking at the descriptor's position
 // in the parent's array of children.
 inline int FieldDescriptor::index() const {
@@ -2431,10 +2491,79 @@
   return static_cast<Syntax>(syntax_);
 }
 
+namespace internal {
+
+// FieldRange(desc) provides an iterable range for the fields of a
+// descriptor type, appropriate for range-for loops.
+
+template <typename T>
+struct FieldRangeImpl;
+
+template <typename T>
+FieldRangeImpl<T> FieldRange(const T* desc) {
+  return {desc};
+}
+
+template <typename T>
+struct FieldRangeImpl {
+  struct Iterator {
+    using iterator_category = std::forward_iterator_tag;
+    using value_type = const FieldDescriptor*;
+    using difference_type = int;
+
+    value_type operator*() { return descriptor->field(idx); }
+
+    friend bool operator==(const Iterator& a, const Iterator& b) {
+      GOOGLE_DCHECK(a.descriptor == b.descriptor);
+      return a.idx == b.idx;
+    }
+    friend bool operator!=(const Iterator& a, const Iterator& b) {
+      return !(a == b);
+    }
+
+    Iterator& operator++() {
+      idx++;
+      return *this;
+    }
+
+    int idx;
+    const T* descriptor;
+  };
+
+  Iterator begin() const { return {0, descriptor}; }
+  Iterator end() const { return {descriptor->field_count(), descriptor}; }
+
+  const T* descriptor;
+};
+
+// The context for these functions under `cpp` is "for the C++ implementation".
+// In particular, questions like "does this field have a has bit?" have a
+// different answer depending on the language.
+namespace cpp {
+// Returns true if 'enum' semantics are such that unknown values are preserved
+// in the enum field itself, rather than going to the UnknownFieldSet.
+PROTOBUF_EXPORT bool HasPreservingUnknownEnumSemantics(
+    const FieldDescriptor* field);
+
+PROTOBUF_EXPORT bool HasHasbit(const FieldDescriptor* field);
+
+#ifndef SWIG
+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.
+};
+PROTOBUF_EXPORT Utf8CheckMode GetUtf8CheckMode(const FieldDescriptor* field,
+                                               bool is_lite);
+#endif  // !SWIG
+
+}  // namespace cpp
+}  // namespace internal
+
 }  // namespace protobuf
 }  // namespace google
 
 #undef PROTOBUF_INTERNAL_CHECK_CLASS_SIZE
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_DESCRIPTOR_H__
diff --git a/src/google/protobuf/descriptor.pb.cc b/src/google/protobuf/descriptor.pb.cc
index d3bfb46..6b750b1 100644
--- a/src/google/protobuf/descriptor.pb.cc
+++ b/src/google/protobuf/descriptor.pb.cc
@@ -1,39 +1,38 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/descriptor.proto
 
-#include <google/protobuf/descriptor.pb.h>
+#include "google/protobuf/descriptor.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR FileDescriptorSet::FileDescriptorSet(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.file_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct FileDescriptorSetDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FileDescriptorSetDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FileDescriptorSetDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FileDescriptorSetDefaultTypeInternal() {}
   union {
     FileDescriptorSet _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileDescriptorSetDefaultTypeInternal _FileDescriptorSet_default_instance_;
 PROTOBUF_CONSTEXPR FileDescriptorProto::FileDescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -48,17 +47,19 @@
   , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.package_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.syntax_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
+  , /*decltype(_impl_.edition_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.options_)*/nullptr
   , /*decltype(_impl_.source_code_info_)*/nullptr} {}
 struct FileDescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FileDescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FileDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FileDescriptorProtoDefaultTypeInternal() {}
   union {
     FileDescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileDescriptorProtoDefaultTypeInternal _FileDescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRange::DescriptorProto_ExtensionRange(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -67,14 +68,15 @@
   , /*decltype(_impl_.start_)*/0
   , /*decltype(_impl_.end_)*/0} {}
 struct DescriptorProto_ExtensionRangeDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRangeDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR DescriptorProto_ExtensionRangeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~DescriptorProto_ExtensionRangeDefaultTypeInternal() {}
   union {
     DescriptorProto_ExtensionRange _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProto_ExtensionRangeDefaultTypeInternal _DescriptorProto_ExtensionRange_default_instance_;
 PROTOBUF_CONSTEXPR DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -82,14 +84,15 @@
   , /*decltype(_impl_.start_)*/0
   , /*decltype(_impl_.end_)*/0} {}
 struct DescriptorProto_ReservedRangeDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR DescriptorProto_ReservedRangeDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR DescriptorProto_ReservedRangeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~DescriptorProto_ReservedRangeDefaultTypeInternal() {}
   union {
     DescriptorProto_ReservedRange _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProto_ReservedRangeDefaultTypeInternal _DescriptorProto_ReservedRange_default_instance_;
 PROTOBUF_CONSTEXPR DescriptorProto::DescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -105,28 +108,30 @@
   , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.options_)*/nullptr} {}
 struct DescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR DescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR DescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~DescriptorProtoDefaultTypeInternal() {}
   union {
     DescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DescriptorProtoDefaultTypeInternal _DescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR ExtensionRangeOptions::ExtensionRangeOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
   , /*decltype(_impl_.uninterpreted_option_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct ExtensionRangeOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR ExtensionRangeOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR ExtensionRangeOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~ExtensionRangeOptionsDefaultTypeInternal() {}
   union {
     ExtensionRangeOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ExtensionRangeOptionsDefaultTypeInternal _ExtensionRangeOptions_default_instance_;
 PROTOBUF_CONSTEXPR FieldDescriptorProto::FieldDescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -143,14 +148,15 @@
   , /*decltype(_impl_.label_)*/1
   , /*decltype(_impl_.type_)*/1} {}
 struct FieldDescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FieldDescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FieldDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FieldDescriptorProtoDefaultTypeInternal() {}
   union {
     FieldDescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldDescriptorProtoDefaultTypeInternal _FieldDescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR OneofDescriptorProto::OneofDescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -158,14 +164,15 @@
   , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.options_)*/nullptr} {}
 struct OneofDescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR OneofDescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR OneofDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~OneofDescriptorProtoDefaultTypeInternal() {}
   union {
     OneofDescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OneofDescriptorProtoDefaultTypeInternal _OneofDescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -173,14 +180,15 @@
   , /*decltype(_impl_.start_)*/0
   , /*decltype(_impl_.end_)*/0} {}
 struct EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal() {}
   union {
     EnumDescriptorProto_EnumReservedRange _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDescriptorProto_EnumReservedRangeDefaultTypeInternal _EnumDescriptorProto_EnumReservedRange_default_instance_;
 PROTOBUF_CONSTEXPR EnumDescriptorProto::EnumDescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -191,14 +199,15 @@
   , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.options_)*/nullptr} {}
 struct EnumDescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EnumDescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EnumDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EnumDescriptorProtoDefaultTypeInternal() {}
   union {
     EnumDescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDescriptorProtoDefaultTypeInternal _EnumDescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR EnumValueDescriptorProto::EnumValueDescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -207,14 +216,15 @@
   , /*decltype(_impl_.options_)*/nullptr
   , /*decltype(_impl_.number_)*/0} {}
 struct EnumValueDescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EnumValueDescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EnumValueDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EnumValueDescriptorProtoDefaultTypeInternal() {}
   union {
     EnumValueDescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueDescriptorProtoDefaultTypeInternal _EnumValueDescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR ServiceDescriptorProto::ServiceDescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -223,14 +233,15 @@
   , /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.options_)*/nullptr} {}
 struct ServiceDescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR ServiceDescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR ServiceDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~ServiceDescriptorProtoDefaultTypeInternal() {}
   union {
     ServiceDescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ServiceDescriptorProtoDefaultTypeInternal _ServiceDescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR MethodDescriptorProto::MethodDescriptorProto(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -242,14 +253,15 @@
   , /*decltype(_impl_.client_streaming_)*/false
   , /*decltype(_impl_.server_streaming_)*/false} {}
 struct MethodDescriptorProtoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR MethodDescriptorProtoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR MethodDescriptorProtoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~MethodDescriptorProtoDefaultTypeInternal() {}
   union {
     MethodDescriptorProto _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodDescriptorProtoDefaultTypeInternal _MethodDescriptorProto_default_instance_;
 PROTOBUF_CONSTEXPR FileOptions::FileOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
@@ -277,14 +289,15 @@
   , /*decltype(_impl_.optimize_for_)*/1
   , /*decltype(_impl_.cc_enable_arenas_)*/true} {}
 struct FileOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FileOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FileOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FileOptionsDefaultTypeInternal() {}
   union {
     FileOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FileOptionsDefaultTypeInternal _FileOptions_default_instance_;
 PROTOBUF_CONSTEXPR MessageOptions::MessageOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
@@ -296,14 +309,15 @@
   , /*decltype(_impl_.deprecated_)*/false
   , /*decltype(_impl_.map_entry_)*/false} {}
 struct MessageOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR MessageOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR MessageOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~MessageOptionsDefaultTypeInternal() {}
   union {
     MessageOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MessageOptionsDefaultTypeInternal _MessageOptions_default_instance_;
 PROTOBUF_CONSTEXPR FieldOptions::FieldOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
@@ -318,28 +332,30 @@
   , /*decltype(_impl_.deprecated_)*/false
   , /*decltype(_impl_.weak_)*/false} {}
 struct FieldOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FieldOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FieldOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FieldOptionsDefaultTypeInternal() {}
   union {
     FieldOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldOptionsDefaultTypeInternal _FieldOptions_default_instance_;
 PROTOBUF_CONSTEXPR OneofOptions::OneofOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
   , /*decltype(_impl_.uninterpreted_option_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct OneofOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR OneofOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR OneofOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~OneofOptionsDefaultTypeInternal() {}
   union {
     OneofOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OneofOptionsDefaultTypeInternal _OneofOptions_default_instance_;
 PROTOBUF_CONSTEXPR EnumOptions::EnumOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
@@ -349,14 +365,15 @@
   , /*decltype(_impl_.allow_alias_)*/false
   , /*decltype(_impl_.deprecated_)*/false} {}
 struct EnumOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EnumOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EnumOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EnumOptionsDefaultTypeInternal() {}
   union {
     EnumOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumOptionsDefaultTypeInternal _EnumOptions_default_instance_;
 PROTOBUF_CONSTEXPR EnumValueOptions::EnumValueOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
@@ -365,14 +382,15 @@
   , /*decltype(_impl_.uninterpreted_option_)*/{}
   , /*decltype(_impl_.deprecated_)*/false} {}
 struct EnumValueOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EnumValueOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EnumValueOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EnumValueOptionsDefaultTypeInternal() {}
   union {
     EnumValueOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueOptionsDefaultTypeInternal _EnumValueOptions_default_instance_;
 PROTOBUF_CONSTEXPR ServiceOptions::ServiceOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
@@ -381,14 +399,15 @@
   , /*decltype(_impl_.uninterpreted_option_)*/{}
   , /*decltype(_impl_.deprecated_)*/false} {}
 struct ServiceOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR ServiceOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR ServiceOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~ServiceOptionsDefaultTypeInternal() {}
   union {
     ServiceOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ServiceOptionsDefaultTypeInternal _ServiceOptions_default_instance_;
 PROTOBUF_CONSTEXPR MethodOptions::MethodOptions(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._extensions_)*/{}
@@ -398,14 +417,15 @@
   , /*decltype(_impl_.deprecated_)*/false
   , /*decltype(_impl_.idempotency_level_)*/0} {}
 struct MethodOptionsDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR MethodOptionsDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR MethodOptionsDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~MethodOptionsDefaultTypeInternal() {}
   union {
     MethodOptions _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 MethodOptionsDefaultTypeInternal _MethodOptions_default_instance_;
 PROTOBUF_CONSTEXPR UninterpretedOption_NamePart::UninterpretedOption_NamePart(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -413,14 +433,15 @@
   , /*decltype(_impl_.name_part_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.is_extension_)*/false} {}
 struct UninterpretedOption_NamePartDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR UninterpretedOption_NamePartDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR UninterpretedOption_NamePartDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~UninterpretedOption_NamePartDefaultTypeInternal() {}
   union {
     UninterpretedOption_NamePart _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
 PROTOBUF_CONSTEXPR UninterpretedOption::UninterpretedOption(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -429,18 +450,19 @@
   , /*decltype(_impl_.identifier_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.string_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.aggregate_value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
-  , /*decltype(_impl_.positive_int_value_)*/uint64_t{0u}
-  , /*decltype(_impl_.negative_int_value_)*/int64_t{0}
+  , /*decltype(_impl_.positive_int_value_)*/::uint64_t{0u}
+  , /*decltype(_impl_.negative_int_value_)*/::int64_t{0}
   , /*decltype(_impl_.double_value_)*/0} {}
 struct UninterpretedOptionDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR UninterpretedOptionDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR UninterpretedOptionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~UninterpretedOptionDefaultTypeInternal() {}
   union {
     UninterpretedOption _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UninterpretedOptionDefaultTypeInternal _UninterpretedOption_default_instance_;
 PROTOBUF_CONSTEXPR SourceCodeInfo_Location::SourceCodeInfo_Location(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -453,27 +475,29 @@
   , /*decltype(_impl_.leading_comments_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.trailing_comments_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}} {}
 struct SourceCodeInfo_LocationDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR SourceCodeInfo_LocationDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR SourceCodeInfo_LocationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~SourceCodeInfo_LocationDefaultTypeInternal() {}
   union {
     SourceCodeInfo_Location _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceCodeInfo_LocationDefaultTypeInternal _SourceCodeInfo_Location_default_instance_;
 PROTOBUF_CONSTEXPR SourceCodeInfo::SourceCodeInfo(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.location_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct SourceCodeInfoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR SourceCodeInfoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR SourceCodeInfoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~SourceCodeInfoDefaultTypeInternal() {}
   union {
     SourceCodeInfo _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceCodeInfoDefaultTypeInternal _SourceCodeInfo_default_instance_;
 PROTOBUF_CONSTEXPR GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_._has_bits_)*/{}
@@ -482,674 +506,762 @@
   , /*decltype(_impl_._path_cached_byte_size_)*/{0}
   , /*decltype(_impl_.source_file_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.begin_)*/0
-  , /*decltype(_impl_.end_)*/0} {}
+  , /*decltype(_impl_.end_)*/0
+  , /*decltype(_impl_.semantic_)*/0} {}
 struct GeneratedCodeInfo_AnnotationDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR GeneratedCodeInfo_AnnotationDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR GeneratedCodeInfo_AnnotationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~GeneratedCodeInfo_AnnotationDefaultTypeInternal() {}
   union {
     GeneratedCodeInfo_Annotation _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GeneratedCodeInfo_AnnotationDefaultTypeInternal _GeneratedCodeInfo_Annotation_default_instance_;
 PROTOBUF_CONSTEXPR GeneratedCodeInfo::GeneratedCodeInfo(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.annotation_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct GeneratedCodeInfoDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR GeneratedCodeInfoDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR GeneratedCodeInfoDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~GeneratedCodeInfoDefaultTypeInternal() {}
   union {
     GeneratedCodeInfo _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 GeneratedCodeInfoDefaultTypeInternal _GeneratedCodeInfo_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[27];
-static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[6];
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _impl_.file_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.package_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.dependency_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.public_dependency_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.weak_dependency_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.message_type_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.enum_type_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.service_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.extension_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.source_code_info_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.syntax_),
-  0,
-  1,
-  ~0u,
-  ~0u,
-  ~0u,
-  ~0u,
-  ~0u,
-  ~0u,
-  ~0u,
-  3,
-  4,
-  2,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.start_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.end_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.options_),
-  1,
-  2,
-  0,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_.start_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_.end_),
-  0,
-  1,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.field_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.extension_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.nested_type_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.enum_type_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.extension_range_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.oneof_decl_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.reserved_range_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.reserved_name_),
-  0,
-  ~0u,
-  ~0u,
-  ~0u,
-  ~0u,
-  ~0u,
-  ~0u,
-  1,
-  ~0u,
-  ~0u,
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _impl_.uninterpreted_option_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.number_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.label_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.type_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.type_name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.extendee_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.default_value_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.oneof_index_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.json_name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.proto3_optional_),
-  0,
-  6,
-  9,
-  10,
-  2,
-  1,
-  3,
-  7,
-  4,
-  5,
-  8,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_.options_),
-  0,
-  1,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_.start_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_.end_),
-  0,
-  1,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.value_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.reserved_range_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.reserved_name_),
-  0,
-  ~0u,
-  1,
-  ~0u,
-  ~0u,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.number_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.options_),
-  0,
-  2,
-  1,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.method_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.options_),
-  0,
-  ~0u,
-  1,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.input_type_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.output_type_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.client_streaming_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.server_streaming_),
-  0,
-  1,
-  2,
-  3,
-  4,
-  5,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_package_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_outer_classname_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_multiple_files_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_generate_equals_and_hash_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_string_check_utf8_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.optimize_for_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.go_package_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.cc_generic_services_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_generic_services_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.py_generic_services_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_generic_services_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.deprecated_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.cc_enable_arenas_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.objc_class_prefix_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.csharp_namespace_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.swift_prefix_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_class_prefix_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_namespace_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_metadata_namespace_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.ruby_package_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.uninterpreted_option_),
-  0,
-  1,
-  10,
-  11,
-  12,
-  18,
-  2,
-  13,
-  14,
-  15,
-  16,
-  17,
-  19,
-  3,
-  4,
-  5,
-  6,
-  7,
-  8,
-  9,
-  ~0u,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.message_set_wire_format_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.no_standard_descriptor_accessor_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.deprecated_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.map_entry_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.uninterpreted_option_),
-  0,
-  1,
-  2,
-  3,
-  ~0u,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.ctype_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.packed_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.jstype_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.lazy_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.unverified_lazy_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.deprecated_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.weak_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.uninterpreted_option_),
-  0,
-  2,
-  1,
-  3,
-  4,
-  5,
-  6,
-  ~0u,
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _impl_.uninterpreted_option_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.allow_alias_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.deprecated_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.uninterpreted_option_),
-  0,
-  1,
-  ~0u,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_.deprecated_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_.uninterpreted_option_),
-  0,
-  ~0u,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_.deprecated_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_.uninterpreted_option_),
-  0,
-  ~0u,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _internal_metadata_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_._extensions_),
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.deprecated_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.idempotency_level_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.uninterpreted_option_),
-  0,
-  1,
-  ~0u,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_.name_part_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_.is_extension_),
-  0,
-  1,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.identifier_value_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.positive_int_value_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.negative_int_value_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.double_value_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.string_value_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.aggregate_value_),
-  ~0u,
-  0,
-  3,
-  4,
-  5,
-  1,
-  2,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.path_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.span_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.leading_comments_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.trailing_comments_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.leading_detached_comments_),
-  ~0u,
-  ~0u,
-  0,
-  1,
-  ~0u,
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _impl_.location_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_._has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.path_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.source_file_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.begin_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.end_),
-  ~0u,
-  0,
-  1,
-  2,
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _impl_.annotation_),
+static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[7];
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fdescriptor_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet, _impl_.file_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.package_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.dependency_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.public_dependency_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.weak_dependency_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.message_type_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.enum_type_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.service_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.extension_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.source_code_info_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.syntax_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto, _impl_.edition_),
+    0,
+    1,
+    ~0u,
+    ~0u,
+    ~0u,
+    ~0u,
+    ~0u,
+    ~0u,
+    ~0u,
+    4,
+    5,
+    2,
+    3,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.start_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.end_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange, _impl_.options_),
+    1,
+    2,
+    0,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_.start_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange, _impl_.end_),
+    0,
+    1,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.field_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.extension_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.nested_type_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.enum_type_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.extension_range_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.oneof_decl_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.reserved_range_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DescriptorProto, _impl_.reserved_name_),
+    0,
+    ~0u,
+    ~0u,
+    ~0u,
+    ~0u,
+    ~0u,
+    ~0u,
+    1,
+    ~0u,
+    ~0u,
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions, _impl_.uninterpreted_option_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.number_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.label_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.type_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.type_name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.extendee_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.default_value_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.oneof_index_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.json_name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto, _impl_.proto3_optional_),
+    0,
+    6,
+    9,
+    10,
+    2,
+    1,
+    3,
+    7,
+    4,
+    5,
+    8,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto, _impl_.options_),
+    0,
+    1,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_.start_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange, _impl_.end_),
+    0,
+    1,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.value_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.reserved_range_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto, _impl_.reserved_name_),
+    0,
+    ~0u,
+    1,
+    ~0u,
+    ~0u,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.number_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto, _impl_.options_),
+    0,
+    2,
+    1,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.method_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto, _impl_.options_),
+    0,
+    ~0u,
+    1,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.input_type_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.output_type_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.client_streaming_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto, _impl_.server_streaming_),
+    0,
+    1,
+    2,
+    3,
+    4,
+    5,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_package_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_outer_classname_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_multiple_files_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_generate_equals_and_hash_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_string_check_utf8_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.optimize_for_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.go_package_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.cc_generic_services_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.java_generic_services_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.py_generic_services_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_generic_services_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.deprecated_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.cc_enable_arenas_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.objc_class_prefix_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.csharp_namespace_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.swift_prefix_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_class_prefix_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_namespace_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.php_metadata_namespace_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.ruby_package_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FileOptions, _impl_.uninterpreted_option_),
+    0,
+    1,
+    10,
+    11,
+    12,
+    18,
+    2,
+    13,
+    14,
+    15,
+    16,
+    17,
+    19,
+    3,
+    4,
+    5,
+    6,
+    7,
+    8,
+    9,
+    ~0u,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.message_set_wire_format_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.no_standard_descriptor_accessor_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.deprecated_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.map_entry_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MessageOptions, _impl_.uninterpreted_option_),
+    0,
+    1,
+    2,
+    3,
+    ~0u,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.ctype_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.packed_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.jstype_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.lazy_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.unverified_lazy_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.deprecated_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.weak_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldOptions, _impl_.uninterpreted_option_),
+    0,
+    2,
+    1,
+    3,
+    4,
+    5,
+    6,
+    ~0u,
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::OneofOptions, _impl_.uninterpreted_option_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.allow_alias_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.deprecated_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumOptions, _impl_.uninterpreted_option_),
+    0,
+    1,
+    ~0u,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_.deprecated_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValueOptions, _impl_.uninterpreted_option_),
+    0,
+    ~0u,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_.deprecated_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ServiceOptions, _impl_.uninterpreted_option_),
+    0,
+    ~0u,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _internal_metadata_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_._extensions_),
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.deprecated_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.idempotency_level_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::MethodOptions, _impl_.uninterpreted_option_),
+    0,
+    1,
+    ~0u,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_.name_part_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart, _impl_.is_extension_),
+    0,
+    1,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.identifier_value_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.positive_int_value_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.negative_int_value_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.double_value_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.string_value_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UninterpretedOption, _impl_.aggregate_value_),
+    ~0u,
+    0,
+    3,
+    4,
+    5,
+    1,
+    2,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.path_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.span_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.leading_comments_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.trailing_comments_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location, _impl_.leading_detached_comments_),
+    ~0u,
+    ~0u,
+    0,
+    1,
+    ~0u,
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo, _impl_.location_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_._has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.path_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.source_file_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.begin_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.end_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation, _impl_.semantic_),
+    ~0u,
+    0,
+    1,
+    2,
+    3,
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo, _impl_.annotation_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet)},
-  { 7, 25, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto)},
-  { 37, 46, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)},
-  { 49, 57, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)},
-  { 59, 75, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto)},
-  { 85, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)},
-  { 92, 109, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)},
-  { 120, 128, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)},
-  { 130, 138, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)},
-  { 140, 151, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)},
-  { 156, 165, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)},
-  { 168, 177, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)},
-  { 180, 192, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)},
-  { 198, 225, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileOptions)},
-  { 246, 257, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MessageOptions)},
-  { 262, 276, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldOptions)},
-  { 284, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofOptions)},
-  { 291, 300, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumOptions)},
-  { 303, 311, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueOptions)},
-  { 313, 321, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceOptions)},
-  { 323, 332, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodOptions)},
-  { 335, 343, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)},
-  { 345, 358, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption)},
-  { 365, 376, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)},
-  { 381, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo)},
-  { 388, 398, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)},
-  { 402, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorSet)},
+        { 9, 30, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileDescriptorProto)},
+        { 43, 54, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange)},
+        { 57, 67, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange)},
+        { 69, 87, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DescriptorProto)},
+        { 97, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions)},
+        { 106, 125, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto)},
+        { 136, 146, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto)},
+        { 148, 158, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange)},
+        { 160, 173, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto)},
+        { 178, 189, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto)},
+        { 192, 203, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto)},
+        { 206, 220, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto)},
+        { 226, 255, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FileOptions)},
+        { 276, 289, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MessageOptions)},
+        { 294, 310, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldOptions)},
+        { 318, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::OneofOptions)},
+        { 327, 338, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumOptions)},
+        { 341, 351, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValueOptions)},
+        { 353, 363, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ServiceOptions)},
+        { 365, 376, -1, sizeof(::PROTOBUF_NAMESPACE_ID::MethodOptions)},
+        { 379, 389, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart)},
+        { 391, 406, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UninterpretedOption)},
+        { 413, 426, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location)},
+        { 431, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceCodeInfo)},
+        { 440, 453, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation)},
+        { 458, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_FileDescriptorSet_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_ReservedRange_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_EnumReservedRange_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_UninterpretedOption_NamePart_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_UninterpretedOption_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_Location_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_Annotation_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_FileDescriptorSet_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_FileDescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_ExtensionRange_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_ReservedRange_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_DescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_ExtensionRangeOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_FieldDescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_OneofDescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_EnumReservedRange_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_EnumDescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_EnumValueDescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_ServiceDescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_MethodDescriptorProto_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_FileOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_MessageOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_FieldOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_OneofOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_EnumOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_EnumValueOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_ServiceOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_MethodOptions_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_UninterpretedOption_NamePart_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_UninterpretedOption_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_Location_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_SourceCodeInfo_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_Annotation_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_GeneratedCodeInfo_default_instance_._instance,
 };
-
-const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
-  "\n google/protobuf/descriptor.proto\022\017goog"
-  "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
-  "\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
-  "roto\"\333\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
-  "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
-  "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen"
-  "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog"
-  "le.protobuf.DescriptorProto\0227\n\tenum_type"
-  "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP"
-  "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf."
-  "ServiceDescriptorProto\0228\n\textension\030\007 \003("
-  "\0132%.google.protobuf.FieldDescriptorProto"
-  "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File"
-  "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog"
-  "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001"
-  "(\t\"\251\005\n\017DescriptorProto\022\014\n\004name\030\001 \001(\t\0224\n\005"
-  "field\030\002 \003(\0132%.google.protobuf.FieldDescr"
-  "iptorProto\0228\n\textension\030\006 \003(\0132%.google.p"
-  "rotobuf.FieldDescriptorProto\0225\n\013nested_t"
-  "ype\030\003 \003(\0132 .google.protobuf.DescriptorPr"
-  "oto\0227\n\tenum_type\030\004 \003(\0132$.google.protobuf"
-  ".EnumDescriptorProto\022H\n\017extension_range\030"
-  "\005 \003(\0132/.google.protobuf.DescriptorProto."
-  "ExtensionRange\0229\n\noneof_decl\030\010 \003(\0132%.goo"
-  "gle.protobuf.OneofDescriptorProto\0220\n\007opt"
-  "ions\030\007 \001(\0132\037.google.protobuf.MessageOpti"
-  "ons\022F\n\016reserved_range\030\t \003(\0132..google.pro"
-  "tobuf.DescriptorProto.ReservedRange\022\025\n\rr"
-  "eserved_name\030\n \003(\t\032e\n\016ExtensionRange\022\r\n\005"
-  "start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\0227\n\007options\030\003 \001("
-  "\0132&.google.protobuf.ExtensionRangeOption"
-  "s\032+\n\rReservedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end"
-  "\030\002 \001(\005\"g\n\025ExtensionRangeOptions\022C\n\024unint"
-  "erpreted_option\030\347\007 \003(\0132$.google.protobuf"
-  ".UninterpretedOption*\t\010\350\007\020\200\200\200\200\002\"\325\005\n\024Fiel"
-  "dDescriptorProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number"
-  "\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+.google.protobuf."
-  "FieldDescriptorProto.Label\0228\n\004type\030\005 \001(\016"
-  "2*.google.protobuf.FieldDescriptorProto."
-  "Type\022\021\n\ttype_name\030\006 \001(\t\022\020\n\010extendee\030\002 \001("
-  "\t\022\025\n\rdefault_value\030\007 \001(\t\022\023\n\013oneof_index\030"
-  "\t \001(\005\022\021\n\tjson_name\030\n \001(\t\022.\n\007options\030\010 \001("
-  "\0132\035.google.protobuf.FieldOptions\022\027\n\017prot"
-  "o3_optional\030\021 \001(\010\"\266\002\n\004Type\022\017\n\013TYPE_DOUBL"
-  "E\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT64\020\003\022\017\n\013T"
-  "YPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014TYPE_FIX"
-  "ED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE_BOOL\020\010\022"
-  "\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n\022\020\n\014TYPE"
-  "_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TYPE_UINT3"
-  "2\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXED32\020\017\022\021\n"
-  "\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020\021\022\017\n\013TYP"
-  "E_SINT64\020\022\"C\n\005Label\022\022\n\016LABEL_OPTIONAL\020\001\022"
-  "\022\n\016LABEL_REQUIRED\020\002\022\022\n\016LABEL_REPEATED\020\003\""
-  "T\n\024OneofDescriptorProto\022\014\n\004name\030\001 \001(\t\022.\n"
-  "\007options\030\002 \001(\0132\035.google.protobuf.OneofOp"
-  "tions\"\244\002\n\023EnumDescriptorProto\022\014\n\004name\030\001 "
-  "\001(\t\0228\n\005value\030\002 \003(\0132).google.protobuf.Enu"
-  "mValueDescriptorProto\022-\n\007options\030\003 \001(\0132\034"
-  ".google.protobuf.EnumOptions\022N\n\016reserved"
-  "_range\030\004 \003(\01326.google.protobuf.EnumDescr"
-  "iptorProto.EnumReservedRange\022\025\n\rreserved"
-  "_name\030\005 \003(\t\032/\n\021EnumReservedRange\022\r\n\005star"
-  "t\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"l\n\030EnumValueDescrip"
-  "torProto\022\014\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\0222"
-  "\n\007options\030\003 \001(\0132!.google.protobuf.EnumVa"
-  "lueOptions\"\220\001\n\026ServiceDescriptorProto\022\014\n"
-  "\004name\030\001 \001(\t\0226\n\006method\030\002 \003(\0132&.google.pro"
-  "tobuf.MethodDescriptorProto\0220\n\007options\030\003"
-  " \001(\0132\037.google.protobuf.ServiceOptions\"\301\001"
-  "\n\025MethodDescriptorProto\022\014\n\004name\030\001 \001(\t\022\022\n"
-  "\ninput_type\030\002 \001(\t\022\023\n\013output_type\030\003 \001(\t\022/"
-  "\n\007options\030\004 \001(\0132\036.google.protobuf.Method"
-  "Options\022\037\n\020client_streaming\030\005 \001(\010:\005false"
-  "\022\037\n\020server_streaming\030\006 \001(\010:\005false\"\245\006\n\013Fi"
-  "leOptions\022\024\n\014java_package\030\001 \001(\t\022\034\n\024java_"
-  "outer_classname\030\010 \001(\t\022\"\n\023java_multiple_f"
-  "iles\030\n \001(\010:\005false\022)\n\035java_generate_equal"
-  "s_and_hash\030\024 \001(\010B\002\030\001\022%\n\026java_string_chec"
-  "k_utf8\030\033 \001(\010:\005false\022F\n\014optimize_for\030\t \001("
-  "\0162).google.protobuf.FileOptions.Optimize"
-  "Mode:\005SPEED\022\022\n\ngo_package\030\013 \001(\t\022\"\n\023cc_ge"
-  "neric_services\030\020 \001(\010:\005false\022$\n\025java_gene"
-  "ric_services\030\021 \001(\010:\005false\022\"\n\023py_generic_"
-  "services\030\022 \001(\010:\005false\022#\n\024php_generic_ser"
-  "vices\030* \001(\010:\005false\022\031\n\ndeprecated\030\027 \001(\010:\005"
-  "false\022\036\n\020cc_enable_arenas\030\037 \001(\010:\004true\022\031\n"
-  "\021objc_class_prefix\030$ \001(\t\022\030\n\020csharp_names"
-  "pace\030% \001(\t\022\024\n\014swift_prefix\030\' \001(\t\022\030\n\020php_"
-  "class_prefix\030( \001(\t\022\025\n\rphp_namespace\030) \001("
-  "\t\022\036\n\026php_metadata_namespace\030, \001(\t\022\024\n\014rub"
-  "y_package\030- \001(\t\022C\n\024uninterpreted_option\030"
-  "\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"
-  "\'\"\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\004\020\005"
-  "J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020\n\"\276\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\036\n\017unverified_lazy\030\017 \001(\010:\005false\022\031\n\nd"
-  "eprecated\030\003 \001(\010:\005false\022\023\n\004weak\030\n \001(\010:\005fa"
-  "lse\022C\n\024uninterpreted_option\030\347\007 \003(\0132$.goo"
-  "gle.protobuf.UninterpretedOption\"/\n\005CTyp"
-  "e\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001\022\020\n\014STRING_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\014One"
-  "ofOptions\022C\n\024uninterpreted_option\030\347\007 \003(\013"
-  "2$.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\ndeprecated\030\003 \001(\010:\005false\022C\n\024uni"
-  "nterpreted_option\030\347\007 \003(\0132$.google.protob"
-  "uf.UninterpretedOption*\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\""
-  "}\n\020EnumValueOptions\022\031\n\ndeprecated\030\001 \001(\010:"
-  "\005false\022C\n\024uninterpreted_option\030\347\007 \003(\0132$."
-  "google.protobuf.UninterpretedOption*\t\010\350\007"
-  "\020\200\200\200\200\002\"{\n\016ServiceOptions\022\031\n\ndeprecated\030!"
-  " \001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003"
-  "(\0132$.google.protobuf.UninterpretedOption"
-  "*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodOptions\022\031\n\ndepreca"
-  "ted\030! \001(\010:\005false\022_\n\021idempotency_level\030\" "
-  "\001(\0162/.google.protobuf.MethodOptions.Idem"
-  "potencyLevel:\023IDEMPOTENCY_UNKNOWN\022C\n\024uni"
-  "nterpreted_option\030\347\007 \003(\0132$.google.protob"
-  "uf.UninterpretedOption\"P\n\020IdempotencyLev"
-  "el\022\027\n\023IDEMPOTENCY_UNKNOWN\020\000\022\023\n\017NO_SIDE_E"
-  "FFECTS\020\001\022\016\n\nIDEMPOTENT\020\002*\t\010\350\007\020\200\200\200\200\002\"\236\002\n\023"
-  "UninterpretedOption\022;\n\004name\030\002 \003(\0132-.goog"
-  "le.protobuf.UninterpretedOption.NamePart"
-  "\022\030\n\020identifier_value\030\003 \001(\t\022\032\n\022positive_i"
-  "nt_value\030\004 \001(\004\022\032\n\022negative_int_value\030\005 \001"
-  "(\003\022\024\n\014double_value\030\006 \001(\001\022\024\n\014string_value"
-  "\030\007 \001(\014\022\027\n\017aggregate_value\030\010 \001(\t\0323\n\010NameP"
-  "art\022\021\n\tname_part\030\001 \002(\t\022\024\n\014is_extension\030\002"
-  " \002(\010\"\325\001\n\016SourceCodeInfo\022:\n\010location\030\001 \003("
-  "\0132(.google.protobuf.SourceCodeInfo.Locat"
-  "ion\032\206\001\n\010Location\022\020\n\004path\030\001 \003(\005B\002\020\001\022\020\n\004sp"
-  "an\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_det"
-  "ached_comments\030\006 \003(\t\"\247\001\n\021GeneratedCodeIn"
-  "fo\022A\n\nannotation\030\001 \003(\0132-.google.protobuf"
-  ".GeneratedCodeInfo.Annotation\032O\n\nAnnotat"
-  "ion\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.go"
-  "ogle.protobufB\020DescriptorProtosH\001Z-googl"
-  "e.golang.org/protobuf/types/descriptorpb"
-  "\370\001\001\242\002\003GPB\252\002\032Google.Protobuf.Reflection"
-  ;
-static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once;
+const char descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+    "\n google/protobuf/descriptor.proto\022\017goog"
+    "le.protobuf\"G\n\021FileDescriptorSet\0222\n\004file"
+    "\030\001 \003(\0132$.google.protobuf.FileDescriptorP"
+    "roto\"\354\003\n\023FileDescriptorProto\022\014\n\004name\030\001 \001"
+    "(\t\022\017\n\007package\030\002 \001(\t\022\022\n\ndependency\030\003 \003(\t\022"
+    "\031\n\021public_dependency\030\n \003(\005\022\027\n\017weak_depen"
+    "dency\030\013 \003(\005\0226\n\014message_type\030\004 \003(\0132 .goog"
+    "le.protobuf.DescriptorProto\0227\n\tenum_type"
+    "\030\005 \003(\0132$.google.protobuf.EnumDescriptorP"
+    "roto\0228\n\007service\030\006 \003(\0132\'.google.protobuf."
+    "ServiceDescriptorProto\0228\n\textension\030\007 \003("
+    "\0132%.google.protobuf.FieldDescriptorProto"
+    "\022-\n\007options\030\010 \001(\0132\034.google.protobuf.File"
+    "Options\0229\n\020source_code_info\030\t \001(\0132\037.goog"
+    "le.protobuf.SourceCodeInfo\022\016\n\006syntax\030\014 \001"
+    "(\t\022\017\n\007edition\030\r \001(\t\"\251\005\n\017DescriptorProto\022"
+    "\014\n\004name\030\001 \001(\t\0224\n\005field\030\002 \003(\0132%.google.pr"
+    "otobuf.FieldDescriptorProto\0228\n\textension"
+    "\030\006 \003(\0132%.google.protobuf.FieldDescriptor"
+    "Proto\0225\n\013nested_type\030\003 \003(\0132 .google.prot"
+    "obuf.DescriptorProto\0227\n\tenum_type\030\004 \003(\0132"
+    "$.google.protobuf.EnumDescriptorProto\022H\n"
+    "\017extension_range\030\005 \003(\0132/.google.protobuf"
+    ".DescriptorProto.ExtensionRange\0229\n\noneof"
+    "_decl\030\010 \003(\0132%.google.protobuf.OneofDescr"
+    "iptorProto\0220\n\007options\030\007 \001(\0132\037.google.pro"
+    "tobuf.MessageOptions\022F\n\016reserved_range\030\t"
+    " \003(\0132..google.protobuf.DescriptorProto.R"
+    "eservedRange\022\025\n\rreserved_name\030\n \003(\t\032e\n\016E"
+    "xtensionRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001("
+    "\005\0227\n\007options\030\003 \001(\0132&.google.protobuf.Ext"
+    "ensionRangeOptions\032+\n\rReservedRange\022\r\n\005s"
+    "tart\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"g\n\025ExtensionRang"
+    "eOptions\022C\n\024uninterpreted_option\030\347\007 \003(\0132"
+    "$.google.protobuf.UninterpretedOption*\t\010"
+    "\350\007\020\200\200\200\200\002\"\325\005\n\024FieldDescriptorProto\022\014\n\004nam"
+    "e\030\001 \001(\t\022\016\n\006number\030\003 \001(\005\022:\n\005label\030\004 \001(\0162+"
+    ".google.protobuf.FieldDescriptorProto.La"
+    "bel\0228\n\004type\030\005 \001(\0162*.google.protobuf.Fiel"
+    "dDescriptorProto.Type\022\021\n\ttype_name\030\006 \001(\t"
+    "\022\020\n\010extendee\030\002 \001(\t\022\025\n\rdefault_value\030\007 \001("
+    "\t\022\023\n\013oneof_index\030\t \001(\005\022\021\n\tjson_name\030\n \001("
+    "\t\022.\n\007options\030\010 \001(\0132\035.google.protobuf.Fie"
+    "ldOptions\022\027\n\017proto3_optional\030\021 \001(\010\"\266\002\n\004T"
+    "ype\022\017\n\013TYPE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\n"
+    "TYPE_INT64\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_IN"
+    "T32\020\005\022\020\n\014TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020"
+    "\007\022\r\n\tTYPE_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYP"
+    "E_GROUP\020\n\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTE"
+    "S\020\014\022\017\n\013TYPE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rT"
+    "YPE_SFIXED32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYP"
+    "E_SINT32\020\021\022\017\n\013TYPE_SINT64\020\022\"C\n\005Label\022\022\n\016"
+    "LABEL_OPTIONAL\020\001\022\022\n\016LABEL_REQUIRED\020\002\022\022\n\016"
+    "LABEL_REPEATED\020\003\"T\n\024OneofDescriptorProto"
+    "\022\014\n\004name\030\001 \001(\t\022.\n\007options\030\002 \001(\0132\035.google"
+    ".protobuf.OneofOptions\"\244\002\n\023EnumDescripto"
+    "rProto\022\014\n\004name\030\001 \001(\t\0228\n\005value\030\002 \003(\0132).go"
+    "ogle.protobuf.EnumValueDescriptorProto\022-"
+    "\n\007options\030\003 \001(\0132\034.google.protobuf.EnumOp"
+    "tions\022N\n\016reserved_range\030\004 \003(\01326.google.p"
+    "rotobuf.EnumDescriptorProto.EnumReserved"
+    "Range\022\025\n\rreserved_name\030\005 \003(\t\032/\n\021EnumRese"
+    "rvedRange\022\r\n\005start\030\001 \001(\005\022\013\n\003end\030\002 \001(\005\"l\n"
+    "\030EnumValueDescriptorProto\022\014\n\004name\030\001 \001(\t\022"
+    "\016\n\006number\030\002 \001(\005\0222\n\007options\030\003 \001(\0132!.googl"
+    "e.protobuf.EnumValueOptions\"\220\001\n\026ServiceD"
+    "escriptorProto\022\014\n\004name\030\001 \001(\t\0226\n\006method\030\002"
+    " \003(\0132&.google.protobuf.MethodDescriptorP"
+    "roto\0220\n\007options\030\003 \001(\0132\037.google.protobuf."
+    "ServiceOptions\"\301\001\n\025MethodDescriptorProto"
+    "\022\014\n\004name\030\001 \001(\t\022\022\n\ninput_type\030\002 \001(\t\022\023\n\013ou"
+    "tput_type\030\003 \001(\t\022/\n\007options\030\004 \001(\0132\036.googl"
+    "e.protobuf.MethodOptions\022\037\n\020client_strea"
+    "ming\030\005 \001(\010:\005false\022\037\n\020server_streaming\030\006 "
+    "\001(\010:\005false\"\245\006\n\013FileOptions\022\024\n\014java_packa"
+    "ge\030\001 \001(\t\022\034\n\024java_outer_classname\030\010 \001(\t\022\""
+    "\n\023java_multiple_files\030\n \001(\010:\005false\022)\n\035ja"
+    "va_generate_equals_and_hash\030\024 \001(\010B\002\030\001\022%\n"
+    "\026java_string_check_utf8\030\033 \001(\010:\005false\022F\n\014"
+    "optimize_for\030\t \001(\0162).google.protobuf.Fil"
+    "eOptions.OptimizeMode:\005SPEED\022\022\n\ngo_packa"
+    "ge\030\013 \001(\t\022\"\n\023cc_generic_services\030\020 \001(\010:\005f"
+    "alse\022$\n\025java_generic_services\030\021 \001(\010:\005fal"
+    "se\022\"\n\023py_generic_services\030\022 \001(\010:\005false\022#"
+    "\n\024php_generic_services\030* \001(\010:\005false\022\031\n\nd"
+    "eprecated\030\027 \001(\010:\005false\022\036\n\020cc_enable_aren"
+    "as\030\037 \001(\010:\004true\022\031\n\021objc_class_prefix\030$ \001("
+    "\t\022\030\n\020csharp_namespace\030% \001(\t\022\024\n\014swift_pre"
+    "fix\030\' \001(\t\022\030\n\020php_class_prefix\030( \001(\t\022\025\n\rp"
+    "hp_namespace\030) \001(\t\022\036\n\026php_metadata_names"
+    "pace\030, \001(\t\022\024\n\014ruby_package\030- \001(\t\022C\n\024unin"
+    "terpreted_option\030\347\007 \003(\0132$.google.protobu"
+    "f.UninterpretedOption\":\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\'\"\204\002\n\016MessageOptions\022&\n"
+    "\027message_set_wire_format\030\001 \001(\010:\005false\022.\n"
+    "\037no_standard_descriptor_accessor\030\002 \001(\010:\005"
+    "false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022\021\n\tmap_"
+    "entry\030\007 \001(\010\022C\n\024uninterpreted_option\030\347\007 \003"
+    "(\0132$.google.protobuf.UninterpretedOption"
+    "*\t\010\350\007\020\200\200\200\200\002J\004\010\004\020\005J\004\010\005\020\006J\004\010\006\020\007J\004\010\010\020\tJ\004\010\t\020"
+    "\n\"\276\003\n\014FieldOptions\022:\n\005ctype\030\001 \001(\0162#.goog"
+    "le.protobuf.FieldOptions.CType:\006STRING\022\016"
+    "\n\006packed\030\002 \001(\010\022\?\n\006jstype\030\006 \001(\0162$.google."
+    "protobuf.FieldOptions.JSType:\tJS_NORMAL\022"
+    "\023\n\004lazy\030\005 \001(\010:\005false\022\036\n\017unverified_lazy\030"
+    "\017 \001(\010:\005false\022\031\n\ndeprecated\030\003 \001(\010:\005false\022"
+    "\023\n\004weak\030\n \001(\010:\005false\022C\n\024uninterpreted_op"
+    "tion\030\347\007 \003(\0132$.google.protobuf.Uninterpre"
+    "tedOption\"/\n\005CType\022\n\n\006STRING\020\000\022\010\n\004CORD\020\001"
+    "\022\020\n\014STRING_PIECE\020\002\"5\n\006JSType\022\r\n\tJS_NORMA"
+    "L\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\024uninterpre"
+    "ted_option\030\347\007 \003(\0132$.google.protobuf.Unin"
+    "terpretedOption*\t\010\350\007\020\200\200\200\200\002\"\223\001\n\013EnumOptio"
+    "ns\022\023\n\013allow_alias\030\002 \001(\010\022\031\n\ndeprecated\030\003 "
+    "\001(\010:\005false\022C\n\024uninterpreted_option\030\347\007 \003("
+    "\0132$.google.protobuf.UninterpretedOption*"
+    "\t\010\350\007\020\200\200\200\200\002J\004\010\005\020\006\"}\n\020EnumValueOptions\022\031\n\n"
+    "deprecated\030\001 \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\002\"{\n\016ServiceOption"
+    "s\022\031\n\ndeprecated\030! \001(\010:\005false\022C\n\024uninterp"
+    "reted_option\030\347\007 \003(\0132$.google.protobuf.Un"
+    "interpretedOption*\t\010\350\007\020\200\200\200\200\002\"\255\002\n\rMethodO"
+    "ptions\022\031\n\ndeprecated\030! \001(\010:\005false\022_\n\021ide"
+    "mpotency_level\030\" \001(\0162/.google.protobuf.M"
+    "ethodOptions.IdempotencyLevel:\023IDEMPOTEN"
+    "CY_UNKNOWN\022C\n\024uninterpreted_option\030\347\007 \003("
+    "\0132$.google.protobuf.UninterpretedOption\""
+    "P\n\020IdempotencyLevel\022\027\n\023IDEMPOTENCY_UNKNO"
+    "WN\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\023UninterpretedOption\022;\n\004"
+    "name\030\002 \003(\0132-.google.protobuf.Uninterpret"
+    "edOption.NamePart\022\030\n\020identifier_value\030\003 "
+    "\001(\t\022\032\n\022positive_int_value\030\004 \001(\004\022\032\n\022negat"
+    "ive_int_value\030\005 \001(\003\022\024\n\014double_value\030\006 \001("
+    "\001\022\024\n\014string_value\030\007 \001(\014\022\027\n\017aggregate_val"
+    "ue\030\010 \001(\t\0323\n\010NamePart\022\021\n\tname_part\030\001 \002(\t\022"
+    "\024\n\014is_extension\030\002 \002(\010\"\325\001\n\016SourceCodeInfo"
+    "\022:\n\010location\030\001 \003(\0132(.google.protobuf.Sou"
+    "rceCodeInfo.Location\032\206\001\n\010Location\022\020\n\004pat"
+    "h\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_comments\030\006 \003(\t\"\234\002"
+    "\n\021GeneratedCodeInfo\022A\n\nannotation\030\001 \003(\0132"
+    "-.google.protobuf.GeneratedCodeInfo.Anno"
+    "tation\032\303\001\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\003e"
+    "nd\030\004 \001(\005\022H\n\010semantic\030\005 \001(\01626.google.prot"
+    "obuf.GeneratedCodeInfo.Annotation.Semant"
+    "ic\"(\n\010Semantic\022\010\n\004NONE\020\000\022\007\n\003SET\020\001\022\t\n\005ALI"
+    "AS\020\002B~\n\023com.google.protobufB\020DescriptorP"
+    "rotosH\001Z-google.golang.org/protobuf/type"
+    "s/descriptorpb\370\001\001\242\002\003GPB\252\002\032Google.Protobu"
+    "f.Reflection"
+};
+static ::absl::once_flag descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fdescriptor_2eproto = {
-    false, false, 6078, descriptor_table_protodef_google_2fprotobuf_2fdescriptor_2eproto,
+    false,
+    false,
+    6212,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fdescriptor_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fdescriptor_2eproto(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::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);
@@ -1180,8 +1292,9 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_DOUBLE;
 constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_FLOAT;
 constexpr FieldDescriptorProto_Type FieldDescriptorProto::TYPE_INT64;
@@ -1203,7 +1316,9 @@
 constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MIN;
 constexpr FieldDescriptorProto_Type FieldDescriptorProto::Type_MAX;
 constexpr int FieldDescriptorProto::Type_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Label_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
   return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[1];
@@ -1218,15 +1333,18 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_OPTIONAL;
 constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REQUIRED;
 constexpr FieldDescriptorProto_Label FieldDescriptorProto::LABEL_REPEATED;
 constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MIN;
 constexpr FieldDescriptorProto_Label FieldDescriptorProto::Label_MAX;
 constexpr int FieldDescriptorProto::Label_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FileOptions_OptimizeMode_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
   return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[2];
@@ -1241,15 +1359,18 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr FileOptions_OptimizeMode FileOptions::SPEED;
 constexpr FileOptions_OptimizeMode FileOptions::CODE_SIZE;
 constexpr FileOptions_OptimizeMode FileOptions::LITE_RUNTIME;
 constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MIN;
 constexpr FileOptions_OptimizeMode FileOptions::OptimizeMode_MAX;
 constexpr int FileOptions::OptimizeMode_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_CType_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
   return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[3];
@@ -1264,15 +1385,18 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr FieldOptions_CType FieldOptions::STRING;
 constexpr FieldOptions_CType FieldOptions::CORD;
 constexpr FieldOptions_CType FieldOptions::STRING_PIECE;
 constexpr FieldOptions_CType FieldOptions::CType_MIN;
 constexpr FieldOptions_CType FieldOptions::CType_MAX;
 constexpr int FieldOptions::CType_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_JSType_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
   return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[4];
@@ -1287,15 +1411,18 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr FieldOptions_JSType FieldOptions::JS_NORMAL;
 constexpr FieldOptions_JSType FieldOptions::JS_STRING;
 constexpr FieldOptions_JSType FieldOptions::JS_NUMBER;
 constexpr FieldOptions_JSType FieldOptions::JSType_MIN;
 constexpr FieldOptions_JSType FieldOptions::JSType_MAX;
 constexpr int FieldOptions::JSType_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
   return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[5];
@@ -1310,16 +1437,44 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENCY_UNKNOWN;
 constexpr MethodOptions_IdempotencyLevel MethodOptions::NO_SIDE_EFFECTS;
 constexpr MethodOptions_IdempotencyLevel MethodOptions::IDEMPOTENT;
 constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MIN;
 constexpr MethodOptions_IdempotencyLevel MethodOptions::IdempotencyLevel_MAX;
 constexpr int MethodOptions::IdempotencyLevel_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* GeneratedCodeInfo_Annotation_Semantic_descriptor() {
+  ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2fdescriptor_2eproto);
+  return file_level_enum_descriptors_google_2fprotobuf_2fdescriptor_2eproto[6];
+}
+bool GeneratedCodeInfo_Annotation_Semantic_IsValid(int value) {
+  switch (value) {
+    case 0:
+    case 1:
+    case 2:
+      return true;
+    default:
+      return false;
+  }
+}
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::NONE;
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::SET;
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::ALIAS;
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::Semantic_MIN;
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::Semantic_MAX;
+constexpr int GeneratedCodeInfo_Annotation::Semantic_ARRAYSIZE;
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 // ===================================================================
 
 class FileDescriptorSet::_Internal {
@@ -1373,7 +1528,7 @@
 
 void FileDescriptorSet::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorSet)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1382,14 +1537,15 @@
 }
 
 const char* FileDescriptorSet::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated .google.protobuf.FileDescriptorProto file = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1397,8 +1553,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1423,10 +1580,11 @@
 #undef CHK_
 }
 
-uint8_t* FileDescriptorSet::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* FileDescriptorSet::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorSet)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -1445,11 +1603,12 @@
   return target;
 }
 
-size_t FileDescriptorSet::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet)
-  size_t total_size = 0;
+::size_t FileDescriptorSet::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorSet)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1473,9 +1632,10 @@
 void FileDescriptorSet::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<FileDescriptorSet*>(&to_msg);
   auto& from = static_cast<const FileDescriptorSet&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorSet)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.file_.MergeFrom(from._impl_.file_);
@@ -1502,16 +1662,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorSet::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[0]);
 }
-
 // ===================================================================
 
 class FileDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<FileDescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -1520,15 +1682,18 @@
   }
   static const ::PROTOBUF_NAMESPACE_ID::FileOptions& options(const FileDescriptorProto* msg);
   static void set_has_options(HasBits* has_bits) {
-    (*has_bits)[0] |= 8u;
+    (*has_bits)[0] |= 16u;
   }
   static const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info(const FileDescriptorProto* msg);
   static void set_has_source_code_info(HasBits* has_bits) {
-    (*has_bits)[0] |= 16u;
+    (*has_bits)[0] |= 32u;
   }
   static void set_has_syntax(HasBits* has_bits) {
     (*has_bits)[0] |= 4u;
   }
+  static void set_has_edition(HasBits* has_bits) {
+    (*has_bits)[0] |= 8u;
+  }
 };
 
 const ::PROTOBUF_NAMESPACE_ID::FileOptions&
@@ -1561,6 +1726,7 @@
     , decltype(_impl_.name_){}
     , decltype(_impl_.package_){}
     , decltype(_impl_.syntax_){}
+    , decltype(_impl_.edition_){}
     , decltype(_impl_.options_){nullptr}
     , decltype(_impl_.source_code_info_){nullptr}};
 
@@ -1569,7 +1735,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
@@ -1577,7 +1743,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.package_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_package()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.package_.Set(from._internal_package(), 
       _this->GetArenaForAllocation());
   }
@@ -1585,14 +1751,22 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.syntax_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_syntax()) {
+  if ((from._impl_._has_bits_[0] & 0x00000004u) != 0) {
     _this->_impl_.syntax_.Set(from._internal_syntax(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  _impl_.edition_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+    _impl_.edition_.Set("", GetArenaForAllocation());
+  #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  if ((from._impl_._has_bits_[0] & 0x00000008u) != 0) {
+    _this->_impl_.edition_.Set(from._internal_edition(), 
+      _this->GetArenaForAllocation());
+  }
+  if ((from._impl_._has_bits_[0] & 0x00000010u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::FileOptions(*from._impl_.options_);
   }
-  if (from._internal_has_source_code_info()) {
+  if ((from._impl_._has_bits_[0] & 0x00000020u) != 0) {
     _this->_impl_.source_code_info_ = new ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo(*from._impl_.source_code_info_);
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileDescriptorProto)
@@ -1615,6 +1789,7 @@
     , decltype(_impl_.name_){}
     , decltype(_impl_.package_){}
     , decltype(_impl_.syntax_){}
+    , decltype(_impl_.edition_){}
     , decltype(_impl_.options_){nullptr}
     , decltype(_impl_.source_code_info_){nullptr}
   };
@@ -1630,6 +1805,10 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.syntax_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  _impl_.edition_.InitDefault();
+  #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+    _impl_.edition_.Set("", GetArenaForAllocation());
+  #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
 }
 
 FileDescriptorProto::~FileDescriptorProto() {
@@ -1653,6 +1832,7 @@
   _impl_.name_.Destroy();
   _impl_.package_.Destroy();
   _impl_.syntax_.Destroy();
+  _impl_.edition_.Destroy();
   if (this != internal_default_instance()) delete _impl_.options_;
   if (this != internal_default_instance()) delete _impl_.source_code_info_;
 }
@@ -1663,7 +1843,7 @@
 
 void FileDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1675,7 +1855,7 @@
   _impl_.public_dependency_.Clear();
   _impl_.weak_dependency_.Clear();
   cached_has_bits = _impl_._has_bits_[0];
-  if (cached_has_bits & 0x0000001fu) {
+  if (cached_has_bits & 0x0000003fu) {
     if (cached_has_bits & 0x00000001u) {
       _impl_.name_.ClearNonDefaultToEmpty();
     }
@@ -1686,10 +1866,13 @@
       _impl_.syntax_.ClearNonDefaultToEmpty();
     }
     if (cached_has_bits & 0x00000008u) {
+      _impl_.edition_.ClearNonDefaultToEmpty();
+    }
+    if (cached_has_bits & 0x00000010u) {
       GOOGLE_DCHECK(_impl_.options_ != nullptr);
       _impl_.options_->Clear();
     }
-    if (cached_has_bits & 0x00000010u) {
+    if (cached_has_bits & 0x00000020u) {
       GOOGLE_DCHECK(_impl_.source_code_info_ != nullptr);
       _impl_.source_code_info_->Clear();
     }
@@ -1699,39 +1882,42 @@
 }
 
 const char* FileDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string package = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_package();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.package");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated string dependency = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1743,12 +1929,13 @@
             #endif  // !NDEBUG
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.DescriptorProto message_type = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1756,12 +1943,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 42)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1769,12 +1957,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.ServiceDescriptorProto service = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1782,12 +1971,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.FieldDescriptorProto extension = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1795,28 +1985,31 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<58>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.FileOptions options = 8;
       case 8:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 66)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
       case 9:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 74)) {
           ptr = ctx->ParseMessage(_internal_mutable_source_code_info(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated int32 public_dependency = 10;
       case 10:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 80)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1824,15 +2017,16 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<80>(ptr));
-        } else if (static_cast<uint8_t>(tag) == 82) {
+        } else if (static_cast<::uint8_t>(tag) == 82) {
           ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_public_dependency(), ptr, ctx);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated int32 weak_dependency = 11;
       case 11:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 88)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 88)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1840,23 +2034,38 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<88>(ptr));
-        } else if (static_cast<uint8_t>(tag) == 90) {
+        } else if (static_cast<::uint8_t>(tag) == 90) {
           ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_weak_dependency(), ptr, ctx);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string syntax = 12;
       case 12:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 98)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 98)) {
           auto str = _internal_mutable_syntax();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.syntax");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
+        continue;
+      // optional string edition = 13;
+      case 13:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 106)) {
+          auto str = _internal_mutable_edition();
+          ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
+          CHK_(ptr);
+          #ifndef NDEBUG
+          ::_pbi::VerifyUTF8(str, "google.protobuf.FileDescriptorProto.edition");
+          #endif  // !NDEBUG
+        } else {
+          goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1882,10 +2091,11 @@
 #undef CHK_
 }
 
-uint8_t* FileDescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* FileDescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -1952,14 +2162,14 @@
   }
 
   // optional .google.protobuf.FileOptions options = 8;
-  if (cached_has_bits & 0x00000008u) {
+  if (cached_has_bits & 0x00000010u) {
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(8, _Internal::options(this),
         _Internal::options(this).GetCachedSize(), target, stream);
   }
 
   // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
-  if (cached_has_bits & 0x00000010u) {
+  if (cached_has_bits & 0x00000020u) {
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(9, _Internal::source_code_info(this),
         _Internal::source_code_info(this).GetCachedSize(), target, stream);
@@ -1987,6 +2197,16 @@
         12, this->_internal_syntax(), target);
   }
 
+  // optional string edition = 13;
+  if (cached_has_bits & 0x00000008u) {
+    ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::VerifyUTF8StringNamedField(
+      this->_internal_edition().data(), static_cast<int>(this->_internal_edition().length()),
+      ::PROTOBUF_NAMESPACE_ID::internal::WireFormat::SERIALIZE,
+      "google.protobuf.FileDescriptorProto.edition");
+    target = stream->WriteStringMaybeAliased(
+        13, this->_internal_edition(), target);
+  }
+
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
     target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
         _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
@@ -1995,11 +2215,12 @@
   return target;
 }
 
-size_t FileDescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto)
-  size_t total_size = 0;
+::size_t FileDescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileDescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -2041,7 +2262,7 @@
 
   // repeated int32 public_dependency = 10;
   {
-    size_t data_size = ::_pbi::WireFormatLite::
+    ::size_t data_size = ::_pbi::WireFormatLite::
       Int32Size(this->_impl_.public_dependency_);
     total_size += 1 *
                   ::_pbi::FromIntSize(this->_internal_public_dependency_size());
@@ -2050,7 +2271,7 @@
 
   // repeated int32 weak_dependency = 11;
   {
-    size_t data_size = ::_pbi::WireFormatLite::
+    ::size_t data_size = ::_pbi::WireFormatLite::
       Int32Size(this->_impl_.weak_dependency_);
     total_size += 1 *
                   ::_pbi::FromIntSize(this->_internal_weak_dependency_size());
@@ -2058,7 +2279,7 @@
   }
 
   cached_has_bits = _impl_._has_bits_[0];
-  if (cached_has_bits & 0x0000001fu) {
+  if (cached_has_bits & 0x0000003fu) {
     // optional string name = 1;
     if (cached_has_bits & 0x00000001u) {
       total_size += 1 +
@@ -2080,15 +2301,22 @@
           this->_internal_syntax());
     }
 
-    // optional .google.protobuf.FileOptions options = 8;
+    // optional string edition = 13;
     if (cached_has_bits & 0x00000008u) {
       total_size += 1 +
+        ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
+          this->_internal_edition());
+    }
+
+    // optional .google.protobuf.FileOptions options = 8;
+    if (cached_has_bits & 0x00000010u) {
+      total_size += 1 +
         ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
           *_impl_.options_);
     }
 
     // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
-    if (cached_has_bits & 0x00000010u) {
+    if (cached_has_bits & 0x00000020u) {
       total_size += 1 +
         ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::MessageSize(
           *_impl_.source_code_info_);
@@ -2108,9 +2336,10 @@
 void FileDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<FileDescriptorProto*>(&to_msg);
   auto& from = static_cast<const FileDescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileDescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.dependency_.MergeFrom(from._impl_.dependency_);
@@ -2121,7 +2350,7 @@
   _this->_impl_.public_dependency_.MergeFrom(from._impl_.public_dependency_);
   _this->_impl_.weak_dependency_.MergeFrom(from._impl_.weak_dependency_);
   cached_has_bits = from._impl_._has_bits_[0];
-  if (cached_has_bits & 0x0000001fu) {
+  if (cached_has_bits & 0x0000003fu) {
     if (cached_has_bits & 0x00000001u) {
       _this->_internal_set_name(from._internal_name());
     }
@@ -2132,10 +2361,13 @@
       _this->_internal_set_syntax(from._internal_syntax());
     }
     if (cached_has_bits & 0x00000008u) {
+      _this->_internal_set_edition(from._internal_edition());
+    }
+    if (cached_has_bits & 0x00000010u) {
       _this->_internal_mutable_options()->::PROTOBUF_NAMESPACE_ID::FileOptions::MergeFrom(
           from._internal_options());
     }
-    if (cached_has_bits & 0x00000010u) {
+    if (cached_has_bits & 0x00000020u) {
       _this->_internal_mutable_source_code_info()->::PROTOBUF_NAMESPACE_ID::SourceCodeInfo::MergeFrom(
           from._internal_source_code_info());
     }
@@ -2159,7 +2391,7 @@
     return false;
   if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.extension_))
     return false;
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000010u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -2190,6 +2422,10 @@
       &_impl_.syntax_, lhs_arena,
       &other->_impl_.syntax_, rhs_arena
   );
+  ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr::InternalSwap(
+      &_impl_.edition_, lhs_arena,
+      &other->_impl_.edition_, rhs_arena
+  );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
       PROTOBUF_FIELD_OFFSET(FileDescriptorProto, _impl_.source_code_info_)
       + sizeof(FileDescriptorProto::_impl_.source_code_info_)
@@ -2199,16 +2435,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileDescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[1]);
 }
-
 // ===================================================================
 
 class DescriptorProto_ExtensionRange::_Internal {
  public:
   using HasBits = decltype(std::declval<DescriptorProto_ExtensionRange>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(DescriptorProto_ExtensionRange, _impl_._has_bits_);
   static void set_has_start(HasBits* has_bits) {
     (*has_bits)[0] |= 2u;
   }
@@ -2242,11 +2480,11 @@
     , decltype(_impl_.end_){}};
 
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions(*from._impl_.options_);
   }
   ::memcpy(&_impl_.start_, &from._impl_.start_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.end_) -
     reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ExtensionRange)
 }
@@ -2284,7 +2522,7 @@
 
 void DescriptorProto_ExtensionRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ExtensionRange)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -2294,7 +2532,7 @@
     _impl_.options_->Clear();
   }
   if (cached_has_bits & 0x00000006u) {
-    ::memset(&_impl_.start_, 0, static_cast<size_t>(
+    ::memset(&_impl_.start_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.end_) -
         reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_));
   }
@@ -2303,37 +2541,41 @@
 }
 
 const char* DescriptorProto_ExtensionRange::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_start(&has_bits);
           _impl_.start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 end = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_end(&has_bits);
           _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.ExtensionRangeOptions options = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -2359,10 +2601,11 @@
 #undef CHK_
 }
 
-uint8_t* DescriptorProto_ExtensionRange::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* DescriptorProto_ExtensionRange::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ExtensionRange)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -2393,11 +2636,12 @@
   return target;
 }
 
-size_t DescriptorProto_ExtensionRange::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange)
-  size_t total_size = 0;
+::size_t DescriptorProto_ExtensionRange::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ExtensionRange)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -2434,9 +2678,10 @@
 void DescriptorProto_ExtensionRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<DescriptorProto_ExtensionRange*>(&to_msg);
   auto& from = static_cast<const DescriptorProto_ExtensionRange&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ExtensionRange)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -2464,7 +2709,7 @@
 }
 
 bool DescriptorProto_ExtensionRange::IsInitialized() const {
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -2483,16 +2728,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ExtensionRange::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[2]);
 }
-
 // ===================================================================
 
 class DescriptorProto_ReservedRange::_Internal {
  public:
   using HasBits = decltype(std::declval<DescriptorProto_ReservedRange>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(DescriptorProto_ReservedRange, _impl_._has_bits_);
   static void set_has_start(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -2508,18 +2755,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.DescriptorProto.ReservedRange)
 }
 DescriptorProto_ReservedRange::DescriptorProto_ReservedRange(const DescriptorProto_ReservedRange& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  DescriptorProto_ReservedRange* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_._has_bits_){from._impl_._has_bits_}
-    , /*decltype(_impl_._cached_size_)*/{}
-    , decltype(_impl_.start_){}
-    , decltype(_impl_.end_){}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  ::memcpy(&_impl_.start_, &from._impl_.start_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) -
-    reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_));
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto.ReservedRange)
 }
 
@@ -2554,13 +2792,13 @@
 
 void DescriptorProto_ReservedRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto.ReservedRange)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
   if (cached_has_bits & 0x00000003u) {
-    ::memset(&_impl_.start_, 0, static_cast<size_t>(
+    ::memset(&_impl_.start_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.end_) -
         reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_));
   }
@@ -2569,29 +2807,32 @@
 }
 
 const char* DescriptorProto_ReservedRange::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_start(&has_bits);
           _impl_.start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 end = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_end(&has_bits);
           _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -2617,10 +2858,11 @@
 #undef CHK_
 }
 
-uint8_t* DescriptorProto_ReservedRange::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* DescriptorProto_ReservedRange::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto.ReservedRange)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -2644,11 +2886,12 @@
   return target;
 }
 
-size_t DescriptorProto_ReservedRange::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange)
-  size_t total_size = 0;
+::size_t DescriptorProto_ReservedRange::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto.ReservedRange)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -2678,9 +2921,10 @@
 void DescriptorProto_ReservedRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<DescriptorProto_ReservedRange*>(&to_msg);
   auto& from = static_cast<const DescriptorProto_ReservedRange&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto.ReservedRange)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -2720,16 +2964,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto_ReservedRange::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[3]);
 }
-
 // ===================================================================
 
 class DescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<DescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(DescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -2771,11 +3017,11 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::MessageOptions(*from._impl_.options_);
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DescriptorProto)
@@ -2834,7 +3080,7 @@
 
 void DescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -2861,27 +3107,29 @@
 }
 
 const char* DescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.DescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.FieldDescriptorProto field = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2889,12 +3137,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.DescriptorProto nested_type = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2902,12 +3151,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.EnumDescriptorProto enum_type = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2915,12 +3165,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.DescriptorProto.ExtensionRange extension_range = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 42)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2928,12 +3179,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.FieldDescriptorProto extension = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2941,20 +3193,22 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.MessageOptions options = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.OneofDescriptorProto oneof_decl = 8;
       case 8:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 66)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2962,12 +3216,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<66>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.DescriptorProto.ReservedRange reserved_range = 9;
       case 9:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 74)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2975,12 +3230,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<74>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated string reserved_name = 10;
       case 10:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 82)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 82)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -2992,8 +3248,9 @@
             #endif  // !NDEBUG
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<82>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -3019,10 +3276,11 @@
 #undef CHK_
 }
 
-uint8_t* DescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* DescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -3117,11 +3375,12 @@
   return target;
 }
 
-size_t DescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto)
-  size_t total_size = 0;
+::size_t DescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -3212,9 +3471,10 @@
 void DescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<DescriptorProto*>(&to_msg);
   auto& from = static_cast<const DescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.field_.MergeFrom(from._impl_.field_);
@@ -3258,7 +3518,7 @@
     return false;
   if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.oneof_decl_))
     return false;
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -3286,11 +3546,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[4]);
 }
-
 // ===================================================================
 
 class ExtensionRangeOptions::_Internal {
@@ -3348,7 +3608,7 @@
 
 void ExtensionRangeOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ExtensionRangeOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -3358,14 +3618,15 @@
 }
 
 const char* ExtensionRangeOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -3373,8 +3634,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -3404,10 +3666,11 @@
 #undef CHK_
 }
 
-uint8_t* ExtensionRangeOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* ExtensionRangeOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ExtensionRangeOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
@@ -3430,13 +3693,14 @@
   return target;
 }
 
-size_t ExtensionRangeOptions::ByteSizeLong() const {
+::size_t ExtensionRangeOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ExtensionRangeOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -3460,9 +3724,10 @@
 void ExtensionRangeOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<ExtensionRangeOptions*>(&to_msg);
   auto& from = static_cast<const ExtensionRangeOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ExtensionRangeOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
@@ -3495,16 +3760,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ExtensionRangeOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[5]);
 }
-
 // ===================================================================
 
 class FieldDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<FieldDescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -3574,7 +3841,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
@@ -3582,7 +3849,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.extendee_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_extendee()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.extendee_.Set(from._internal_extendee(), 
       _this->GetArenaForAllocation());
   }
@@ -3590,7 +3857,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.type_name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_type_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000004u) != 0) {
     _this->_impl_.type_name_.Set(from._internal_type_name(), 
       _this->GetArenaForAllocation());
   }
@@ -3598,7 +3865,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.default_value_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_default_value()) {
+  if ((from._impl_._has_bits_[0] & 0x00000008u) != 0) {
     _this->_impl_.default_value_.Set(from._internal_default_value(), 
       _this->GetArenaForAllocation());
   }
@@ -3606,15 +3873,15 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.json_name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_json_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000010u) != 0) {
     _this->_impl_.json_name_.Set(from._internal_json_name(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000020u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::FieldOptions(*from._impl_.options_);
   }
   ::memcpy(&_impl_.number_, &from._impl_.number_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.type_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.type_) -
     reinterpret_cast<char*>(&_impl_.number_)) + sizeof(_impl_.type_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldDescriptorProto)
 }
@@ -3685,7 +3952,7 @@
 
 void FieldDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -3712,7 +3979,7 @@
     }
   }
   if (cached_has_bits & 0x000000c0u) {
-    ::memset(&_impl_.number_, 0, static_cast<size_t>(
+    ::memset(&_impl_.number_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.oneof_index_) -
         reinterpret_cast<char*>(&_impl_.number_)) + sizeof(_impl_.oneof_index_));
   }
@@ -3726,132 +3993,144 @@
 }
 
 const char* FieldDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string extendee = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_extendee();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.extendee");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 number = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _Internal::set_has_number(&has_bits);
           _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 32)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_IsValid(val))) {
+          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_IsValid(static_cast<int>(val)))) {
             _internal_set_label(static_cast<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label>(val));
           } else {
             ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(4, val, mutable_unknown_fields());
           }
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 40)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_IsValid(val))) {
+          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_IsValid(static_cast<int>(val)))) {
             _internal_set_type(static_cast<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type>(val));
           } else {
             ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(5, val, mutable_unknown_fields());
           }
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string type_name = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           auto str = _internal_mutable_type_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.type_name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string default_value = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           auto str = _internal_mutable_default_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.default_value");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.FieldOptions options = 8;
       case 8:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 66)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 oneof_index = 9;
       case 9:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 72)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 72)) {
           _Internal::set_has_oneof_index(&has_bits);
           _impl_.oneof_index_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string json_name = 10;
       case 10:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 82)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 82)) {
           auto str = _internal_mutable_json_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FieldDescriptorProto.json_name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool proto3_optional = 17;
       case 17:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 136)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 136)) {
           _Internal::set_has_proto3_optional(&has_bits);
           _impl_.proto3_optional_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -3877,10 +4156,11 @@
 #undef CHK_
 }
 
-uint8_t* FieldDescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* FieldDescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -3981,11 +4261,12 @@
   return target;
 }
 
-size_t FieldDescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto)
-  size_t total_size = 0;
+::size_t FieldDescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldDescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -4076,9 +4357,10 @@
 void FieldDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<FieldDescriptorProto*>(&to_msg);
   auto& from = static_cast<const FieldDescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldDescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -4133,7 +4415,7 @@
 }
 
 bool FieldDescriptorProto::IsInitialized() const {
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000020u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -4166,26 +4448,26 @@
       &other->_impl_.json_name_, rhs_arena
   );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
-      PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.proto3_optional_)
-      + sizeof(FieldDescriptorProto::_impl_.proto3_optional_)
+      PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.type_)
+      + sizeof(FieldDescriptorProto::_impl_.type_)
       - PROTOBUF_FIELD_OFFSET(FieldDescriptorProto, _impl_.options_)>(
           reinterpret_cast<char*>(&_impl_.options_),
           reinterpret_cast<char*>(&other->_impl_.options_));
-  swap(_impl_.label_, other->_impl_.label_);
-  swap(_impl_.type_, other->_impl_.type_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldDescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[6]);
 }
-
 // ===================================================================
 
 class OneofDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<OneofDescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(OneofDescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -4219,11 +4501,11 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::OneofOptions(*from._impl_.options_);
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.OneofDescriptorProto)
@@ -4266,7 +4548,7 @@
 
 void OneofDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -4285,31 +4567,34 @@
 }
 
 const char* OneofDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.OneofDescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.OneofOptions options = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -4335,10 +4620,11 @@
 #undef CHK_
 }
 
-uint8_t* OneofDescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* OneofDescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -4367,11 +4653,12 @@
   return target;
 }
 
-size_t OneofDescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto)
-  size_t total_size = 0;
+::size_t OneofDescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofDescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -4405,9 +4692,10 @@
 void OneofDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<OneofDescriptorProto*>(&to_msg);
   auto& from = static_cast<const OneofDescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofDescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -4431,7 +4719,7 @@
 }
 
 bool OneofDescriptorProto::IsInitialized() const {
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -4451,16 +4739,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata OneofDescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[7]);
 }
-
 // ===================================================================
 
 class EnumDescriptorProto_EnumReservedRange::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumDescriptorProto_EnumReservedRange>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(EnumDescriptorProto_EnumReservedRange, _impl_._has_bits_);
   static void set_has_start(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -4476,18 +4766,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange)
 }
 EnumDescriptorProto_EnumReservedRange::EnumDescriptorProto_EnumReservedRange(const EnumDescriptorProto_EnumReservedRange& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  EnumDescriptorProto_EnumReservedRange* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_._has_bits_){from._impl_._has_bits_}
-    , /*decltype(_impl_._cached_size_)*/{}
-    , decltype(_impl_.start_){}
-    , decltype(_impl_.end_){}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  ::memcpy(&_impl_.start_, &from._impl_.start_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) -
-    reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_));
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto.EnumReservedRange)
 }
 
@@ -4522,13 +4803,13 @@
 
 void EnumDescriptorProto_EnumReservedRange::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
   if (cached_has_bits & 0x00000003u) {
-    ::memset(&_impl_.start_, 0, static_cast<size_t>(
+    ::memset(&_impl_.start_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.end_) -
         reinterpret_cast<char*>(&_impl_.start_)) + sizeof(_impl_.end_));
   }
@@ -4537,29 +4818,32 @@
 }
 
 const char* EnumDescriptorProto_EnumReservedRange::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional int32 start = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_start(&has_bits);
           _impl_.start_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 end = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_end(&has_bits);
           _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -4585,10 +4869,11 @@
 #undef CHK_
 }
 
-uint8_t* EnumDescriptorProto_EnumReservedRange::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* EnumDescriptorProto_EnumReservedRange::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -4612,11 +4897,12 @@
   return target;
 }
 
-size_t EnumDescriptorProto_EnumReservedRange::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
-  size_t total_size = 0;
+::size_t EnumDescriptorProto_EnumReservedRange::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -4646,9 +4932,10 @@
 void EnumDescriptorProto_EnumReservedRange::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<EnumDescriptorProto_EnumReservedRange*>(&to_msg);
   auto& from = static_cast<const EnumDescriptorProto_EnumReservedRange&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto.EnumReservedRange)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -4688,16 +4975,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto_EnumReservedRange::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[8]);
 }
-
 // ===================================================================
 
 class EnumDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumDescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(EnumDescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -4734,11 +5023,11 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::EnumOptions(*from._impl_.options_);
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumDescriptorProto)
@@ -4787,7 +5076,7 @@
 
 void EnumDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -4809,27 +5098,29 @@
 }
 
 const char* EnumDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.EnumDescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.EnumValueDescriptorProto value = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -4837,20 +5128,22 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.EnumOptions options = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.EnumDescriptorProto.EnumReservedRange reserved_range = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -4858,12 +5151,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated string reserved_name = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 42)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -4875,8 +5169,9 @@
             #endif  // !NDEBUG
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<42>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -4902,10 +5197,11 @@
 #undef CHK_
 }
 
-uint8_t* EnumDescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* EnumDescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -4960,11 +5256,12 @@
   return target;
 }
 
-size_t EnumDescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto)
-  size_t total_size = 0;
+::size_t EnumDescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumDescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -5020,9 +5317,10 @@
 void EnumDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<EnumDescriptorProto*>(&to_msg);
   auto& from = static_cast<const EnumDescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumDescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.value_.MergeFrom(from._impl_.value_);
@@ -5051,7 +5349,7 @@
 bool EnumDescriptorProto::IsInitialized() const {
   if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.value_))
     return false;
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -5074,16 +5372,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumDescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[9]);
 }
-
 // ===================================================================
 
 class EnumValueDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumValueDescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(EnumValueDescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -5121,11 +5421,11 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::EnumValueOptions(*from._impl_.options_);
   }
   _this->_impl_.number_ = from._impl_.number_;
@@ -5170,7 +5470,7 @@
 
 void EnumValueDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -5190,40 +5490,44 @@
 }
 
 const char* EnumValueDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.EnumValueDescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 number = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_number(&has_bits);
           _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.EnumValueOptions options = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -5249,10 +5553,11 @@
 #undef CHK_
 }
 
-uint8_t* EnumValueDescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* EnumValueDescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -5287,11 +5592,12 @@
   return target;
 }
 
-size_t EnumValueDescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto)
-  size_t total_size = 0;
+::size_t EnumValueDescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueDescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -5330,9 +5636,10 @@
 void EnumValueDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<EnumValueDescriptorProto*>(&to_msg);
   auto& from = static_cast<const EnumValueDescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueDescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -5360,7 +5667,7 @@
 }
 
 bool EnumValueDescriptorProto::IsInitialized() const {
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -5385,16 +5692,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValueDescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[10]);
 }
-
 // ===================================================================
 
 class ServiceDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<ServiceDescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(ServiceDescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -5429,11 +5738,11 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::ServiceOptions(*from._impl_.options_);
   }
   // @@protoc_insertion_point(copy_constructor:google.protobuf.ServiceDescriptorProto)
@@ -5478,7 +5787,7 @@
 
 void ServiceDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -5498,27 +5807,29 @@
 }
 
 const char* ServiceDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.ServiceDescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.MethodDescriptorProto method = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -5526,16 +5837,18 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.ServiceOptions options = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -5561,10 +5874,11 @@
 #undef CHK_
 }
 
-uint8_t* ServiceDescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* ServiceDescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -5601,11 +5915,12 @@
   return target;
 }
 
-size_t ServiceDescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto)
-  size_t total_size = 0;
+::size_t ServiceDescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceDescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -5646,9 +5961,10 @@
 void ServiceDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<ServiceDescriptorProto*>(&to_msg);
   auto& from = static_cast<const ServiceDescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceDescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.method_.MergeFrom(from._impl_.method_);
@@ -5675,7 +5991,7 @@
 bool ServiceDescriptorProto::IsInitialized() const {
   if (!::PROTOBUF_NAMESPACE_ID::internal::AllAreInitialized(_impl_.method_))
     return false;
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -5696,16 +6012,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ServiceDescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[11]);
 }
-
 // ===================================================================
 
 class MethodDescriptorProto::_Internal {
  public:
   using HasBits = decltype(std::declval<MethodDescriptorProto>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(MethodDescriptorProto, _impl_._has_bits_);
   static void set_has_name(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -5755,7 +6073,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_.Set(from._internal_name(), 
       _this->GetArenaForAllocation());
   }
@@ -5763,7 +6081,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.input_type_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_input_type()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.input_type_.Set(from._internal_input_type(), 
       _this->GetArenaForAllocation());
   }
@@ -5771,15 +6089,15 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.output_type_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_output_type()) {
+  if ((from._impl_._has_bits_[0] & 0x00000004u) != 0) {
     _this->_impl_.output_type_.Set(from._internal_output_type(), 
       _this->GetArenaForAllocation());
   }
-  if (from._internal_has_options()) {
+  if ((from._impl_._has_bits_[0] & 0x00000008u) != 0) {
     _this->_impl_.options_ = new ::PROTOBUF_NAMESPACE_ID::MethodOptions(*from._impl_.options_);
   }
   ::memcpy(&_impl_.client_streaming_, &from._impl_.client_streaming_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.server_streaming_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.server_streaming_) -
     reinterpret_cast<char*>(&_impl_.client_streaming_)) + sizeof(_impl_.server_streaming_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodDescriptorProto)
 }
@@ -5835,7 +6153,7 @@
 
 void MethodDescriptorProto::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -5855,7 +6173,7 @@
       _impl_.options_->Clear();
     }
   }
-  ::memset(&_impl_.client_streaming_, 0, static_cast<size_t>(
+  ::memset(&_impl_.client_streaming_, 0, static_cast<::size_t>(
       reinterpret_cast<char*>(&_impl_.server_streaming_) -
       reinterpret_cast<char*>(&_impl_.client_streaming_)) + sizeof(_impl_.server_streaming_));
   _impl_._has_bits_.Clear();
@@ -5863,73 +6181,80 @@
 }
 
 const char* MethodDescriptorProto::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.name");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string input_type = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_input_type();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.input_type");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string output_type = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           auto str = _internal_mutable_output_type();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.MethodDescriptorProto.output_type");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.MethodOptions options = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           ptr = ctx->ParseMessage(_internal_mutable_options(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool client_streaming = 5 [default = false];
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 40)) {
           _Internal::set_has_client_streaming(&has_bits);
           _impl_.client_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool server_streaming = 6 [default = false];
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 48)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 48)) {
           _Internal::set_has_server_streaming(&has_bits);
           _impl_.server_streaming_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -5955,10 +6280,11 @@
 #undef CHK_
 }
 
-uint8_t* MethodDescriptorProto::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* MethodDescriptorProto::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodDescriptorProto)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -6019,11 +6345,12 @@
   return target;
 }
 
-size_t MethodDescriptorProto::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto)
-  size_t total_size = 0;
+::size_t MethodDescriptorProto::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodDescriptorProto)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -6081,9 +6408,10 @@
 void MethodDescriptorProto::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<MethodDescriptorProto*>(&to_msg);
   auto& from = static_cast<const MethodDescriptorProto&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodDescriptorProto)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -6120,7 +6448,7 @@
 }
 
 bool MethodDescriptorProto::IsInitialized() const {
-  if (_internal_has_options()) {
+  if ((_impl_._has_bits_[0] & 0x00000008u) != 0) {
     if (!_impl_.options_->IsInitialized()) return false;
   }
   return true;
@@ -6153,16 +6481,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MethodDescriptorProto::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[12]);
 }
-
 // ===================================================================
 
 class FileOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<FileOptions>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(FileOptions, _impl_._has_bits_);
   static void set_has_java_package(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -6266,7 +6596,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.java_package_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_java_package()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.java_package_.Set(from._internal_java_package(), 
       _this->GetArenaForAllocation());
   }
@@ -6274,7 +6604,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.java_outer_classname_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_java_outer_classname()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.java_outer_classname_.Set(from._internal_java_outer_classname(), 
       _this->GetArenaForAllocation());
   }
@@ -6282,7 +6612,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.go_package_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_go_package()) {
+  if ((from._impl_._has_bits_[0] & 0x00000004u) != 0) {
     _this->_impl_.go_package_.Set(from._internal_go_package(), 
       _this->GetArenaForAllocation());
   }
@@ -6290,7 +6620,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.objc_class_prefix_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_objc_class_prefix()) {
+  if ((from._impl_._has_bits_[0] & 0x00000008u) != 0) {
     _this->_impl_.objc_class_prefix_.Set(from._internal_objc_class_prefix(), 
       _this->GetArenaForAllocation());
   }
@@ -6298,7 +6628,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.csharp_namespace_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_csharp_namespace()) {
+  if ((from._impl_._has_bits_[0] & 0x00000010u) != 0) {
     _this->_impl_.csharp_namespace_.Set(from._internal_csharp_namespace(), 
       _this->GetArenaForAllocation());
   }
@@ -6306,7 +6636,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.swift_prefix_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_swift_prefix()) {
+  if ((from._impl_._has_bits_[0] & 0x00000020u) != 0) {
     _this->_impl_.swift_prefix_.Set(from._internal_swift_prefix(), 
       _this->GetArenaForAllocation());
   }
@@ -6314,7 +6644,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.php_class_prefix_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_php_class_prefix()) {
+  if ((from._impl_._has_bits_[0] & 0x00000040u) != 0) {
     _this->_impl_.php_class_prefix_.Set(from._internal_php_class_prefix(), 
       _this->GetArenaForAllocation());
   }
@@ -6322,7 +6652,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.php_namespace_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_php_namespace()) {
+  if ((from._impl_._has_bits_[0] & 0x00000080u) != 0) {
     _this->_impl_.php_namespace_.Set(from._internal_php_namespace(), 
       _this->GetArenaForAllocation());
   }
@@ -6330,7 +6660,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.php_metadata_namespace_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_php_metadata_namespace()) {
+  if ((from._impl_._has_bits_[0] & 0x00000100u) != 0) {
     _this->_impl_.php_metadata_namespace_.Set(from._internal_php_metadata_namespace(), 
       _this->GetArenaForAllocation());
   }
@@ -6338,12 +6668,12 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.ruby_package_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_ruby_package()) {
+  if ((from._impl_._has_bits_[0] & 0x00000200u) != 0) {
     _this->_impl_.ruby_package_.Set(from._internal_ruby_package(), 
       _this->GetArenaForAllocation());
   }
   ::memcpy(&_impl_.java_multiple_files_, &from._impl_.java_multiple_files_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.cc_enable_arenas_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.cc_enable_arenas_) -
     reinterpret_cast<char*>(&_impl_.java_multiple_files_)) + sizeof(_impl_.cc_enable_arenas_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FileOptions)
 }
@@ -6451,7 +6781,7 @@
 
 void FileOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FileOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -6493,12 +6823,12 @@
     }
   }
   if (cached_has_bits & 0x0000fc00u) {
-    ::memset(&_impl_.java_multiple_files_, 0, static_cast<size_t>(
+    ::memset(&_impl_.java_multiple_files_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.py_generic_services_) -
         reinterpret_cast<char*>(&_impl_.java_multiple_files_)) + sizeof(_impl_.py_generic_services_));
   }
   if (cached_has_bits & 0x000f0000u) {
-    ::memset(&_impl_.php_generic_services_, 0, static_cast<size_t>(
+    ::memset(&_impl_.php_generic_services_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.deprecated_) -
         reinterpret_cast<char*>(&_impl_.php_generic_services_)) + sizeof(_impl_.deprecated_));
     _impl_.optimize_for_ = 1;
@@ -6509,229 +6839,250 @@
 }
 
 const char* FileOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional string java_package = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_java_package();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.java_package");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string java_outer_classname = 8;
       case 8:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 66)) {
           auto str = _internal_mutable_java_outer_classname();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.java_outer_classname");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
       case 9:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 72)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 72)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_IsValid(val))) {
+          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_IsValid(static_cast<int>(val)))) {
             _internal_set_optimize_for(static_cast<::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode>(val));
           } else {
             ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(9, val, mutable_unknown_fields());
           }
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool java_multiple_files = 10 [default = false];
       case 10:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 80)) {
           _Internal::set_has_java_multiple_files(&has_bits);
           _impl_.java_multiple_files_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string go_package = 11;
       case 11:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 90)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 90)) {
           auto str = _internal_mutable_go_package();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.go_package");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool cc_generic_services = 16 [default = false];
       case 16:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 128)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 128)) {
           _Internal::set_has_cc_generic_services(&has_bits);
           _impl_.cc_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool java_generic_services = 17 [default = false];
       case 17:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 136)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 136)) {
           _Internal::set_has_java_generic_services(&has_bits);
           _impl_.java_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool py_generic_services = 18 [default = false];
       case 18:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 144)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 144)) {
           _Internal::set_has_py_generic_services(&has_bits);
           _impl_.py_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
       case 20:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 160)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 160)) {
           _Internal::set_has_java_generate_equals_and_hash(&has_bits);
           _impl_.java_generate_equals_and_hash_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool deprecated = 23 [default = false];
       case 23:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 184)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 184)) {
           _Internal::set_has_deprecated(&has_bits);
           _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool java_string_check_utf8 = 27 [default = false];
       case 27:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 216)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 216)) {
           _Internal::set_has_java_string_check_utf8(&has_bits);
           _impl_.java_string_check_utf8_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool cc_enable_arenas = 31 [default = true];
       case 31:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 248)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 248)) {
           _Internal::set_has_cc_enable_arenas(&has_bits);
           _impl_.cc_enable_arenas_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string objc_class_prefix = 36;
       case 36:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           auto str = _internal_mutable_objc_class_prefix();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.objc_class_prefix");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string csharp_namespace = 37;
       case 37:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 42)) {
           auto str = _internal_mutable_csharp_namespace();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.csharp_namespace");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string swift_prefix = 39;
       case 39:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           auto str = _internal_mutable_swift_prefix();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.swift_prefix");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string php_class_prefix = 40;
       case 40:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 66)) {
           auto str = _internal_mutable_php_class_prefix();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.php_class_prefix");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string php_namespace = 41;
       case 41:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 74)) {
           auto str = _internal_mutable_php_namespace();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.php_namespace");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool php_generic_services = 42 [default = false];
       case 42:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 80)) {
           _Internal::set_has_php_generic_services(&has_bits);
           _impl_.php_generic_services_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string php_metadata_namespace = 44;
       case 44:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 98)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 98)) {
           auto str = _internal_mutable_php_metadata_namespace();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.php_metadata_namespace");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string ruby_package = 45;
       case 45:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 106)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 106)) {
           auto str = _internal_mutable_ruby_package();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.FileOptions.ruby_package");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -6739,8 +7090,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -6771,10 +7123,11 @@
 #undef CHK_
 }
 
-uint8_t* FileOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* FileOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FileOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -6959,13 +7312,14 @@
   return target;
 }
 
-size_t FileOptions::ByteSizeLong() const {
+::size_t FileOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FileOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -7117,9 +7471,10 @@
 void FileOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<FileOptions*>(&to_msg);
   auto& from = static_cast<const FileOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FileOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
@@ -7262,26 +7617,26 @@
       &other->_impl_.ruby_package_, rhs_arena
   );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
-      PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.deprecated_)
-      + sizeof(FileOptions::_impl_.deprecated_)
+      PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.cc_enable_arenas_)
+      + sizeof(FileOptions::_impl_.cc_enable_arenas_)
       - PROTOBUF_FIELD_OFFSET(FileOptions, _impl_.java_multiple_files_)>(
           reinterpret_cast<char*>(&_impl_.java_multiple_files_),
           reinterpret_cast<char*>(&other->_impl_.java_multiple_files_));
-  swap(_impl_.optimize_for_, other->_impl_.optimize_for_);
-  swap(_impl_.cc_enable_arenas_, other->_impl_.cc_enable_arenas_);
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FileOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[13]);
 }
-
 // ===================================================================
 
 class MessageOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<MessageOptions>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(MessageOptions, _impl_._has_bits_);
   static void set_has_message_set_wire_format(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -7318,7 +7673,7 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_);
   ::memcpy(&_impl_.message_set_wire_format_, &from._impl_.message_set_wire_format_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.map_entry_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.map_entry_) -
     reinterpret_cast<char*>(&_impl_.message_set_wire_format_)) + sizeof(_impl_.map_entry_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MessageOptions)
 }
@@ -7360,13 +7715,13 @@
 
 void MessageOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MessageOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   _impl_._extensions_.Clear();
   _impl_.uninterpreted_option_.Clear();
-  ::memset(&_impl_.message_set_wire_format_, 0, static_cast<size_t>(
+  ::memset(&_impl_.message_set_wire_format_, 0, static_cast<::size_t>(
       reinterpret_cast<char*>(&_impl_.map_entry_) -
       reinterpret_cast<char*>(&_impl_.message_set_wire_format_)) + sizeof(_impl_.map_entry_));
   _impl_._has_bits_.Clear();
@@ -7374,51 +7729,56 @@
 }
 
 const char* MessageOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional bool message_set_wire_format = 1 [default = false];
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_message_set_wire_format(&has_bits);
           _impl_.message_set_wire_format_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool no_standard_descriptor_accessor = 2 [default = false];
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_no_standard_descriptor_accessor(&has_bits);
           _impl_.no_standard_descriptor_accessor_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool deprecated = 3 [default = false];
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _Internal::set_has_deprecated(&has_bits);
           _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool map_entry = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 56)) {
           _Internal::set_has_map_entry(&has_bits);
           _impl_.map_entry_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -7426,8 +7786,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -7458,10 +7819,11 @@
 #undef CHK_
 }
 
-uint8_t* MessageOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* MessageOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MessageOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -7509,13 +7871,14 @@
   return target;
 }
 
-size_t MessageOptions::ByteSizeLong() const {
+::size_t MessageOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MessageOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -7562,9 +7925,10 @@
 void MessageOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<MessageOptions*>(&to_msg);
   auto& from = static_cast<const MessageOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MessageOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
@@ -7620,16 +7984,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MessageOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[14]);
 }
-
 // ===================================================================
 
 class FieldOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<FieldOptions>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(FieldOptions, _impl_._has_bits_);
   static void set_has_ctype(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -7678,7 +8044,7 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_);
   ::memcpy(&_impl_.ctype_, &from._impl_.ctype_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.weak_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.weak_) -
     reinterpret_cast<char*>(&_impl_.ctype_)) + sizeof(_impl_.weak_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FieldOptions)
 }
@@ -7723,7 +8089,7 @@
 
 void FieldOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -7731,7 +8097,7 @@
   _impl_.uninterpreted_option_.Clear();
   cached_has_bits = _impl_._has_bits_[0];
   if (cached_has_bits & 0x0000007fu) {
-    ::memset(&_impl_.ctype_, 0, static_cast<size_t>(
+    ::memset(&_impl_.ctype_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.weak_) -
         reinterpret_cast<char*>(&_impl_.ctype_)) + sizeof(_impl_.weak_));
   }
@@ -7740,86 +8106,94 @@
 }
 
 const char* FieldOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType_IsValid(val))) {
+          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType_IsValid(static_cast<int>(val)))) {
             _internal_set_ctype(static_cast<::PROTOBUF_NAMESPACE_ID::FieldOptions_CType>(val));
           } else {
             ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(1, val, mutable_unknown_fields());
           }
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool packed = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_packed(&has_bits);
           _impl_.packed_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool deprecated = 3 [default = false];
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _Internal::set_has_deprecated(&has_bits);
           _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool lazy = 5 [default = false];
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 40)) {
           _Internal::set_has_lazy(&has_bits);
           _impl_.lazy_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 48)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 48)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_IsValid(val))) {
+          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_IsValid(static_cast<int>(val)))) {
             _internal_set_jstype(static_cast<::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType>(val));
           } else {
             ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(6, val, mutable_unknown_fields());
           }
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool weak = 10 [default = false];
       case 10:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 80)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 80)) {
           _Internal::set_has_weak(&has_bits);
           _impl_.weak_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool unverified_lazy = 15 [default = false];
       case 15:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 120)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 120)) {
           _Internal::set_has_unverified_lazy(&has_bits);
           _impl_.unverified_lazy_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -7827,8 +8201,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -7859,10 +8234,11 @@
 #undef CHK_
 }
 
-uint8_t* FieldOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* FieldOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -7930,13 +8306,14 @@
   return target;
 }
 
-size_t FieldOptions::ByteSizeLong() const {
+::size_t FieldOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -8000,9 +8377,10 @@
 void FieldOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<FieldOptions*>(&to_msg);
   auto& from = static_cast<const FieldOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
@@ -8067,11 +8445,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[15]);
 }
-
 // ===================================================================
 
 class OneofOptions::_Internal {
@@ -8129,7 +8507,7 @@
 
 void OneofOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.OneofOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -8139,14 +8517,15 @@
 }
 
 const char* OneofOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -8154,8 +8533,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -8185,10 +8565,11 @@
 #undef CHK_
 }
 
-uint8_t* OneofOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* OneofOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.OneofOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
@@ -8211,13 +8592,14 @@
   return target;
 }
 
-size_t OneofOptions::ByteSizeLong() const {
+::size_t OneofOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.OneofOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -8241,9 +8623,10 @@
 void OneofOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<OneofOptions*>(&to_msg);
   auto& from = static_cast<const OneofOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.OneofOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
@@ -8276,16 +8659,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata OneofOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[16]);
 }
-
 // ===================================================================
 
 class EnumOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumOptions>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(EnumOptions, _impl_._has_bits_);
   static void set_has_allow_alias(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -8314,7 +8699,7 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_);
   ::memcpy(&_impl_.allow_alias_, &from._impl_.allow_alias_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.deprecated_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.deprecated_) -
     reinterpret_cast<char*>(&_impl_.allow_alias_)) + sizeof(_impl_.deprecated_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.EnumOptions)
 }
@@ -8354,13 +8739,13 @@
 
 void EnumOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   _impl_._extensions_.Clear();
   _impl_.uninterpreted_option_.Clear();
-  ::memset(&_impl_.allow_alias_, 0, static_cast<size_t>(
+  ::memset(&_impl_.allow_alias_, 0, static_cast<::size_t>(
       reinterpret_cast<char*>(&_impl_.deprecated_) -
       reinterpret_cast<char*>(&_impl_.allow_alias_)) + sizeof(_impl_.deprecated_));
   _impl_._has_bits_.Clear();
@@ -8368,33 +8753,36 @@
 }
 
 const char* EnumOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional bool allow_alias = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_allow_alias(&has_bits);
           _impl_.allow_alias_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bool deprecated = 3 [default = false];
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _Internal::set_has_deprecated(&has_bits);
           _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -8402,8 +8790,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -8434,10 +8823,11 @@
 #undef CHK_
 }
 
-uint8_t* EnumOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* EnumOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -8473,13 +8863,14 @@
   return target;
 }
 
-size_t EnumOptions::ByteSizeLong() const {
+::size_t EnumOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -8516,9 +8907,10 @@
 void EnumOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<EnumOptions*>(&to_msg);
   auto& from = static_cast<const EnumOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
@@ -8568,16 +8960,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[17]);
 }
-
 // ===================================================================
 
 class EnumValueOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<EnumValueOptions>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(EnumValueOptions, _impl_._has_bits_);
   static void set_has_deprecated(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -8639,7 +9033,7 @@
 
 void EnumValueOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValueOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -8651,24 +9045,26 @@
 }
 
 const char* EnumValueOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional bool deprecated = 1 [default = false];
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_deprecated(&has_bits);
           _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -8676,8 +9072,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -8708,10 +9105,11 @@
 #undef CHK_
 }
 
-uint8_t* EnumValueOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* EnumValueOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValueOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -8741,13 +9139,14 @@
   return target;
 }
 
-size_t EnumValueOptions::ByteSizeLong() const {
+::size_t EnumValueOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValueOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -8777,13 +9176,14 @@
 void EnumValueOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<EnumValueOptions*>(&to_msg);
   auto& from = static_cast<const EnumValueOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValueOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
-  if (from._internal_has_deprecated()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_internal_set_deprecated(from._internal_deprecated());
   }
   _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_);
@@ -8817,16 +9217,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValueOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[18]);
 }
-
 // ===================================================================
 
 class ServiceOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<ServiceOptions>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(ServiceOptions, _impl_._has_bits_);
   static void set_has_deprecated(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -8888,7 +9290,7 @@
 
 void ServiceOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ServiceOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -8900,24 +9302,26 @@
 }
 
 const char* ServiceOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_deprecated(&has_bits);
           _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -8925,8 +9329,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -8957,10 +9362,11 @@
 #undef CHK_
 }
 
-uint8_t* ServiceOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* ServiceOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ServiceOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -8990,13 +9396,14 @@
   return target;
 }
 
-size_t ServiceOptions::ByteSizeLong() const {
+::size_t ServiceOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.ServiceOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -9026,13 +9433,14 @@
 void ServiceOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<ServiceOptions*>(&to_msg);
   auto& from = static_cast<const ServiceOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ServiceOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
-  if (from._internal_has_deprecated()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_internal_set_deprecated(from._internal_deprecated());
   }
   _this->_impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_);
@@ -9066,16 +9474,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ServiceOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[19]);
 }
-
 // ===================================================================
 
 class MethodOptions::_Internal {
  public:
   using HasBits = decltype(std::declval<MethodOptions>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(MethodOptions, _impl_._has_bits_);
   static void set_has_deprecated(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -9104,7 +9514,7 @@
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _impl_._extensions_.MergeFrom(internal_default_instance(), from._impl_._extensions_);
   ::memcpy(&_impl_.deprecated_, &from._impl_.deprecated_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.idempotency_level_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.idempotency_level_) -
     reinterpret_cast<char*>(&_impl_.deprecated_)) + sizeof(_impl_.idempotency_level_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.MethodOptions)
 }
@@ -9144,7 +9554,7 @@
 
 void MethodOptions::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.MethodOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -9152,7 +9562,7 @@
   _impl_.uninterpreted_option_.Clear();
   cached_has_bits = _impl_._has_bits_[0];
   if (cached_has_bits & 0x00000003u) {
-    ::memset(&_impl_.deprecated_, 0, static_cast<size_t>(
+    ::memset(&_impl_.deprecated_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.idempotency_level_) -
         reinterpret_cast<char*>(&_impl_.deprecated_)) + sizeof(_impl_.idempotency_level_));
   }
@@ -9161,37 +9571,40 @@
 }
 
 const char* MethodOptions::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // optional bool deprecated = 33 [default = false];
       case 33:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _Internal::set_has_deprecated(&has_bits);
           _impl_.deprecated_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];
       case 34:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_IsValid(val))) {
+          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_IsValid(static_cast<int>(val)))) {
             _internal_set_idempotency_level(static_cast<::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel>(val));
           } else {
             ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(34, val, mutable_unknown_fields());
           }
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.UninterpretedOption uninterpreted_option = 999;
       case 999:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           ptr -= 2;
           do {
             ptr += 2;
@@ -9199,8 +9612,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<7994>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -9231,10 +9645,11 @@
 #undef CHK_
 }
 
-uint8_t* MethodOptions::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* MethodOptions::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.MethodOptions)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -9271,13 +9686,14 @@
   return target;
 }
 
-size_t MethodOptions::ByteSizeLong() const {
+::size_t MethodOptions::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.MethodOptions)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   total_size += _impl_._extensions_.ByteSize();
 
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -9315,9 +9731,10 @@
 void MethodOptions::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<MethodOptions*>(&to_msg);
   auto& from = static_cast<const MethodOptions&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.MethodOptions)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.uninterpreted_option_.MergeFrom(from._impl_.uninterpreted_option_);
@@ -9367,16 +9784,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata MethodOptions::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[20]);
 }
-
 // ===================================================================
 
 class UninterpretedOption_NamePart::_Internal {
  public:
   using HasBits = decltype(std::declval<UninterpretedOption_NamePart>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(UninterpretedOption_NamePart, _impl_._has_bits_);
   static void set_has_name_part(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -9408,7 +9827,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.name_part_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_name_part()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.name_part_.Set(from._internal_name_part(), 
       _this->GetArenaForAllocation());
   }
@@ -9452,7 +9871,7 @@
 
 void UninterpretedOption_NamePart::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption.NamePart)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -9466,32 +9885,35 @@
 }
 
 const char* UninterpretedOption_NamePart::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // required string name_part = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name_part();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.UninterpretedOption.NamePart.name_part");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // required bool is_extension = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _Internal::set_has_is_extension(&has_bits);
           _impl_.is_extension_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -9517,10 +9939,11 @@
 #undef CHK_
 }
 
-uint8_t* UninterpretedOption_NamePart::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* UninterpretedOption_NamePart::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption.NamePart)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = _impl_._has_bits_[0];
@@ -9548,27 +9971,28 @@
   return target;
 }
 
-size_t UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const {
+::size_t UninterpretedOption_NamePart::RequiredFieldsByteSizeFallback() const {
 // @@protoc_insertion_point(required_fields_byte_size_fallback_start:google.protobuf.UninterpretedOption.NamePart)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
-  if (_internal_has_name_part()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) != 0) {
     // required string name_part = 1;
     total_size += 1 +
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::StringSize(
         this->_internal_name_part());
   }
 
-  if (_internal_has_is_extension()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) != 0) {
     // required bool is_extension = 2;
     total_size += 1 + 1;
   }
 
   return total_size;
 }
-size_t UninterpretedOption_NamePart::ByteSizeLong() const {
+::size_t UninterpretedOption_NamePart::ByteSizeLong() const {
+
 // @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption.NamePart)
-  size_t total_size = 0;
+  ::size_t total_size = 0;
 
   if (((_impl_._has_bits_[0] & 0x00000003) ^ 0x00000003) == 0) {  // All required fields are present.
     // required string name_part = 1;
@@ -9582,7 +10006,7 @@
   } else {
     total_size += RequiredFieldsByteSizeFallback();
   }
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -9599,9 +10023,10 @@
 void UninterpretedOption_NamePart::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<UninterpretedOption_NamePart*>(&to_msg);
   auto& from = static_cast<const UninterpretedOption_NamePart&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption.NamePart)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   cached_has_bits = from._impl_._has_bits_[0];
@@ -9643,16 +10068,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption_NamePart::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[21]);
 }
-
 // ===================================================================
 
 class UninterpretedOption::_Internal {
  public:
   using HasBits = decltype(std::declval<UninterpretedOption>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(UninterpretedOption, _impl_._has_bits_);
   static void set_has_identifier_value(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -9698,7 +10125,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.identifier_value_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_identifier_value()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.identifier_value_.Set(from._internal_identifier_value(), 
       _this->GetArenaForAllocation());
   }
@@ -9706,7 +10133,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.string_value_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_string_value()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.string_value_.Set(from._internal_string_value(), 
       _this->GetArenaForAllocation());
   }
@@ -9714,12 +10141,12 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.aggregate_value_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_aggregate_value()) {
+  if ((from._impl_._has_bits_[0] & 0x00000004u) != 0) {
     _this->_impl_.aggregate_value_.Set(from._internal_aggregate_value(), 
       _this->GetArenaForAllocation());
   }
   ::memcpy(&_impl_.positive_int_value_, &from._impl_.positive_int_value_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.double_value_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.double_value_) -
     reinterpret_cast<char*>(&_impl_.positive_int_value_)) + sizeof(_impl_.double_value_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UninterpretedOption)
 }
@@ -9735,8 +10162,8 @@
     , decltype(_impl_.identifier_value_){}
     , decltype(_impl_.string_value_){}
     , decltype(_impl_.aggregate_value_){}
-    , decltype(_impl_.positive_int_value_){uint64_t{0u}}
-    , decltype(_impl_.negative_int_value_){int64_t{0}}
+    , decltype(_impl_.positive_int_value_){::uint64_t{0u}}
+    , decltype(_impl_.negative_int_value_){::int64_t{0}}
     , decltype(_impl_.double_value_){0}
   };
   _impl_.identifier_value_.InitDefault();
@@ -9776,7 +10203,7 @@
 
 void UninterpretedOption::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UninterpretedOption)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -9794,7 +10221,7 @@
     }
   }
   if (cached_has_bits & 0x00000038u) {
-    ::memset(&_impl_.positive_int_value_, 0, static_cast<size_t>(
+    ::memset(&_impl_.positive_int_value_, 0, static_cast<::size_t>(
         reinterpret_cast<char*>(&_impl_.double_value_) -
         reinterpret_cast<char*>(&_impl_.positive_int_value_)) + sizeof(_impl_.double_value_));
   }
@@ -9803,15 +10230,16 @@
 }
 
 const char* UninterpretedOption::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -9819,68 +10247,75 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string identifier_value = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           auto str = _internal_mutable_identifier_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.UninterpretedOption.identifier_value");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional uint64 positive_int_value = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 32)) {
           _Internal::set_has_positive_int_value(&has_bits);
           _impl_.positive_int_value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int64 negative_int_value = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 40)) {
           _Internal::set_has_negative_int_value(&has_bits);
           _impl_.negative_int_value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional double double_value = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 49)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 49)) {
           _Internal::set_has_double_value(&has_bits);
           _impl_.double_value_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr);
           ptr += sizeof(double);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional bytes string_value = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 58)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 58)) {
           auto str = _internal_mutable_string_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string aggregate_value = 8;
       case 8:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 66)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 66)) {
           auto str = _internal_mutable_aggregate_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.UninterpretedOption.aggregate_value");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -9906,10 +10341,11 @@
 #undef CHK_
 }
 
-uint8_t* UninterpretedOption::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* UninterpretedOption::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UninterpretedOption)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.UninterpretedOption.NamePart name = 2;
@@ -9973,11 +10409,12 @@
   return target;
 }
 
-size_t UninterpretedOption::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption)
-  size_t total_size = 0;
+::size_t UninterpretedOption::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UninterpretedOption)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -10040,9 +10477,10 @@
 void UninterpretedOption::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<UninterpretedOption*>(&to_msg);
   auto& from = static_cast<const UninterpretedOption&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UninterpretedOption)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.name_.MergeFrom(from._impl_.name_);
@@ -10112,16 +10550,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UninterpretedOption::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[22]);
 }
-
 // ===================================================================
 
 class SourceCodeInfo_Location::_Internal {
  public:
   using HasBits = decltype(std::declval<SourceCodeInfo_Location>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(SourceCodeInfo_Location, _impl_._has_bits_);
   static void set_has_leading_comments(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -10155,7 +10595,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.leading_comments_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_leading_comments()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.leading_comments_.Set(from._internal_leading_comments(), 
       _this->GetArenaForAllocation());
   }
@@ -10163,7 +10603,7 @@
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.trailing_comments_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_trailing_comments()) {
+  if ((from._impl_._has_bits_[0] & 0x00000002u) != 0) {
     _this->_impl_.trailing_comments_.Set(from._internal_trailing_comments(), 
       _this->GetArenaForAllocation());
   }
@@ -10219,7 +10659,7 @@
 
 void SourceCodeInfo_Location::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo.Location)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -10240,61 +10680,66 @@
 }
 
 const char* SourceCodeInfo_Location::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_path(), ptr, ctx);
           CHK_(ptr);
-        } else if (static_cast<uint8_t>(tag) == 8) {
+        } else if (static_cast<::uint8_t>(tag) == 8) {
           _internal_add_path(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr));
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated int32 span = 2 [packed = true];
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_span(), ptr, ctx);
           CHK_(ptr);
-        } else if (static_cast<uint8_t>(tag) == 16) {
+        } else if (static_cast<::uint8_t>(tag) == 16) {
           _internal_add_span(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr));
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string leading_comments = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           auto str = _internal_mutable_leading_comments();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.leading_comments");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string trailing_comments = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           auto str = _internal_mutable_trailing_comments();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.SourceCodeInfo.Location.trailing_comments");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated string leading_detached_comments = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -10306,8 +10751,9 @@
             #endif  // !NDEBUG
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<50>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -10333,15 +10779,16 @@
 #undef CHK_
 }
 
-uint8_t* SourceCodeInfo_Location::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* SourceCodeInfo_Location::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo.Location)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated int32 path = 1 [packed = true];
   {
-    int byte_size = _impl_._path_cached_byte_size_.load(std::memory_order_relaxed);
+    int byte_size = _impl_._path_cached_byte_size_.Get();
     if (byte_size > 0) {
       target = stream->WriteInt32Packed(
           1, _internal_path(), byte_size, target);
@@ -10350,7 +10797,7 @@
 
   // repeated int32 span = 2 [packed = true];
   {
-    int byte_size = _impl_._span_cached_byte_size_.load(std::memory_order_relaxed);
+    int byte_size = _impl_._span_cached_byte_size_.Get();
     if (byte_size > 0) {
       target = stream->WriteInt32Packed(
           2, _internal_span(), byte_size, target);
@@ -10396,39 +10843,38 @@
   return target;
 }
 
-size_t SourceCodeInfo_Location::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location)
-  size_t total_size = 0;
+::size_t SourceCodeInfo_Location::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo.Location)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   // repeated int32 path = 1 [packed = true];
   {
-    size_t data_size = ::_pbi::WireFormatLite::
+    ::size_t data_size = ::_pbi::WireFormatLite::
       Int32Size(this->_impl_.path_);
     if (data_size > 0) {
       total_size += 1 +
-        ::_pbi::WireFormatLite::Int32Size(static_cast<int32_t>(data_size));
+        ::_pbi::WireFormatLite::Int32Size(static_cast<::int32_t>(data_size));
     }
     int cached_size = ::_pbi::ToCachedSize(data_size);
-    _impl_._path_cached_byte_size_.store(cached_size,
-                                    std::memory_order_relaxed);
+    _impl_._path_cached_byte_size_.Set(cached_size);
     total_size += data_size;
   }
 
   // repeated int32 span = 2 [packed = true];
   {
-    size_t data_size = ::_pbi::WireFormatLite::
+    ::size_t data_size = ::_pbi::WireFormatLite::
       Int32Size(this->_impl_.span_);
     if (data_size > 0) {
       total_size += 1 +
-        ::_pbi::WireFormatLite::Int32Size(static_cast<int32_t>(data_size));
+        ::_pbi::WireFormatLite::Int32Size(static_cast<::int32_t>(data_size));
     }
     int cached_size = ::_pbi::ToCachedSize(data_size);
-    _impl_._span_cached_byte_size_.store(cached_size,
-                                    std::memory_order_relaxed);
+    _impl_._span_cached_byte_size_.Set(cached_size);
     total_size += data_size;
   }
 
@@ -10470,9 +10916,10 @@
 void SourceCodeInfo_Location::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<SourceCodeInfo_Location*>(&to_msg);
   auto& from = static_cast<const SourceCodeInfo_Location&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo.Location)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.path_.MergeFrom(from._impl_.path_);
@@ -10521,11 +10968,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo_Location::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[23]);
 }
-
 // ===================================================================
 
 class SourceCodeInfo::_Internal {
@@ -10579,7 +11026,7 @@
 
 void SourceCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceCodeInfo)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -10588,14 +11035,15 @@
 }
 
 const char* SourceCodeInfo::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -10603,8 +11051,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -10629,10 +11078,11 @@
 #undef CHK_
 }
 
-uint8_t* SourceCodeInfo::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* SourceCodeInfo::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceCodeInfo)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.SourceCodeInfo.Location location = 1;
@@ -10651,11 +11101,12 @@
   return target;
 }
 
-size_t SourceCodeInfo::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo)
-  size_t total_size = 0;
+::size_t SourceCodeInfo::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceCodeInfo)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -10679,9 +11130,10 @@
 void SourceCodeInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<SourceCodeInfo*>(&to_msg);
   auto& from = static_cast<const SourceCodeInfo&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceCodeInfo)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.location_.MergeFrom(from._impl_.location_);
@@ -10706,16 +11158,18 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceCodeInfo::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[24]);
 }
-
 // ===================================================================
 
 class GeneratedCodeInfo_Annotation::_Internal {
  public:
   using HasBits = decltype(std::declval<GeneratedCodeInfo_Annotation>()._impl_._has_bits_);
+  static constexpr ::int32_t kHasBitsOffset =
+    8 * PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_._has_bits_);
   static void set_has_source_file(HasBits* has_bits) {
     (*has_bits)[0] |= 1u;
   }
@@ -10725,6 +11179,9 @@
   static void set_has_end(HasBits* has_bits) {
     (*has_bits)[0] |= 4u;
   }
+  static void set_has_semantic(HasBits* has_bits) {
+    (*has_bits)[0] |= 8u;
+  }
 };
 
 GeneratedCodeInfo_Annotation::GeneratedCodeInfo_Annotation(::PROTOBUF_NAMESPACE_ID::Arena* arena,
@@ -10743,20 +11200,21 @@
     , /*decltype(_impl_._path_cached_byte_size_)*/{0}
     , decltype(_impl_.source_file_){}
     , decltype(_impl_.begin_){}
-    , decltype(_impl_.end_){}};
+    , decltype(_impl_.end_){}
+    , decltype(_impl_.semantic_){}};
 
   _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
   _impl_.source_file_.InitDefault();
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
     _impl_.source_file_.Set("", GetArenaForAllocation());
   #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (from._internal_has_source_file()) {
+  if ((from._impl_._has_bits_[0] & 0x00000001u) != 0) {
     _this->_impl_.source_file_.Set(from._internal_source_file(), 
       _this->GetArenaForAllocation());
   }
   ::memcpy(&_impl_.begin_, &from._impl_.begin_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.end_) -
-    reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.end_));
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.semantic_) -
+    reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.semantic_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.GeneratedCodeInfo.Annotation)
 }
 
@@ -10772,6 +11230,7 @@
     , decltype(_impl_.source_file_){}
     , decltype(_impl_.begin_){0}
     , decltype(_impl_.end_){0}
+    , decltype(_impl_.semantic_){0}
   };
   _impl_.source_file_.InitDefault();
   #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
@@ -10800,7 +11259,7 @@
 
 void GeneratedCodeInfo_Annotation::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo.Annotation)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -10809,62 +11268,81 @@
   if (cached_has_bits & 0x00000001u) {
     _impl_.source_file_.ClearNonDefaultToEmpty();
   }
-  if (cached_has_bits & 0x00000006u) {
-    ::memset(&_impl_.begin_, 0, static_cast<size_t>(
-        reinterpret_cast<char*>(&_impl_.end_) -
-        reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.end_));
+  if (cached_has_bits & 0x0000000eu) {
+    ::memset(&_impl_.begin_, 0, static_cast<::size_t>(
+        reinterpret_cast<char*>(&_impl_.semantic_) -
+        reinterpret_cast<char*>(&_impl_.begin_)) + sizeof(_impl_.semantic_));
   }
   _impl_._has_bits_.Clear();
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* GeneratedCodeInfo_Annotation::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   _Internal::HasBits has_bits{};
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated int32 path = 1 [packed = true];
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr = ::PROTOBUF_NAMESPACE_ID::internal::PackedInt32Parser(_internal_mutable_path(), ptr, ctx);
           CHK_(ptr);
-        } else if (static_cast<uint8_t>(tag) == 8) {
+        } else if (static_cast<::uint8_t>(tag) == 8) {
           _internal_add_path(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr));
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional string source_file = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           auto str = _internal_mutable_source_file();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           #ifndef NDEBUG
           ::_pbi::VerifyUTF8(str, "google.protobuf.GeneratedCodeInfo.Annotation.source_file");
           #endif  // !NDEBUG
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 begin = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _Internal::set_has_begin(&has_bits);
           _impl_.begin_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // optional int32 end = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 32)) {
           _Internal::set_has_end(&has_bits);
           _impl_.end_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
+        continue;
+      // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
+      case 5:
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 40)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
+          CHK_(ptr);
+          if (PROTOBUF_PREDICT_TRUE(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic_IsValid(static_cast<int>(val)))) {
+            _internal_set_semantic(static_cast<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic>(val));
+          } else {
+            ::PROTOBUF_NAMESPACE_ID::internal::WriteVarint(5, val, mutable_unknown_fields());
+          }
+        } else {
+          goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -10890,15 +11368,16 @@
 #undef CHK_
 }
 
-uint8_t* GeneratedCodeInfo_Annotation::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* GeneratedCodeInfo_Annotation::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo.Annotation)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated int32 path = 1 [packed = true];
   {
-    int byte_size = _impl_._path_cached_byte_size_.load(std::memory_order_relaxed);
+    int byte_size = _impl_._path_cached_byte_size_.Get();
     if (byte_size > 0) {
       target = stream->WriteInt32Packed(
           1, _internal_path(), byte_size, target);
@@ -10928,6 +11407,13 @@
     target = ::_pbi::WireFormatLite::WriteInt32ToArray(4, this->_internal_end(), target);
   }
 
+  // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
+  if (cached_has_bits & 0x00000008u) {
+    target = stream->EnsureSpace(target);
+    target = ::_pbi::WireFormatLite::WriteEnumToArray(
+      5, this->_internal_semantic(), target);
+  }
+
   if (PROTOBUF_PREDICT_FALSE(_internal_metadata_.have_unknown_fields())) {
     target = ::_pbi::WireFormat::InternalSerializeUnknownFieldsToArray(
         _internal_metadata_.unknown_fields<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(::PROTOBUF_NAMESPACE_ID::UnknownFieldSet::default_instance), target, stream);
@@ -10936,30 +11422,30 @@
   return target;
 }
 
-size_t GeneratedCodeInfo_Annotation::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation)
-  size_t total_size = 0;
+::size_t GeneratedCodeInfo_Annotation::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo.Annotation)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   // repeated int32 path = 1 [packed = true];
   {
-    size_t data_size = ::_pbi::WireFormatLite::
+    ::size_t data_size = ::_pbi::WireFormatLite::
       Int32Size(this->_impl_.path_);
     if (data_size > 0) {
       total_size += 1 +
-        ::_pbi::WireFormatLite::Int32Size(static_cast<int32_t>(data_size));
+        ::_pbi::WireFormatLite::Int32Size(static_cast<::int32_t>(data_size));
     }
     int cached_size = ::_pbi::ToCachedSize(data_size);
-    _impl_._path_cached_byte_size_.store(cached_size,
-                                    std::memory_order_relaxed);
+    _impl_._path_cached_byte_size_.Set(cached_size);
     total_size += data_size;
   }
 
   cached_has_bits = _impl_._has_bits_[0];
-  if (cached_has_bits & 0x00000007u) {
+  if (cached_has_bits & 0x0000000fu) {
     // optional string source_file = 2;
     if (cached_has_bits & 0x00000001u) {
       total_size += 1 +
@@ -10977,6 +11463,12 @@
       total_size += ::_pbi::WireFormatLite::Int32SizePlusOne(this->_internal_end());
     }
 
+    // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
+    if (cached_has_bits & 0x00000008u) {
+      total_size += 1 +
+        ::_pbi::WireFormatLite::EnumSize(this->_internal_semantic());
+    }
+
   }
   return MaybeComputeUnknownFieldsSize(total_size, &_impl_._cached_size_);
 }
@@ -10991,14 +11483,15 @@
 void GeneratedCodeInfo_Annotation::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<GeneratedCodeInfo_Annotation*>(&to_msg);
   auto& from = static_cast<const GeneratedCodeInfo_Annotation&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo.Annotation)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.path_.MergeFrom(from._impl_.path_);
   cached_has_bits = from._impl_._has_bits_[0];
-  if (cached_has_bits & 0x00000007u) {
+  if (cached_has_bits & 0x0000000fu) {
     if (cached_has_bits & 0x00000001u) {
       _this->_internal_set_source_file(from._internal_source_file());
     }
@@ -11008,6 +11501,9 @@
     if (cached_has_bits & 0x00000004u) {
       _this->_impl_.end_ = from._impl_.end_;
     }
+    if (cached_has_bits & 0x00000008u) {
+      _this->_impl_.semantic_ = from._impl_.semantic_;
+    }
     _this->_impl_._has_bits_[0] |= cached_has_bits;
   }
   _this->_internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
@@ -11036,19 +11532,19 @@
       &other->_impl_.source_file_, rhs_arena
   );
   ::PROTOBUF_NAMESPACE_ID::internal::memswap<
-      PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.end_)
-      + sizeof(GeneratedCodeInfo_Annotation::_impl_.end_)
+      PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.semantic_)
+      + sizeof(GeneratedCodeInfo_Annotation::_impl_.semantic_)
       - PROTOBUF_FIELD_OFFSET(GeneratedCodeInfo_Annotation, _impl_.begin_)>(
           reinterpret_cast<char*>(&_impl_.begin_),
           reinterpret_cast<char*>(&other->_impl_.begin_));
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo_Annotation::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_getter, &descriptor_table_google_2fprotobuf_2fdescriptor_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fdescriptor_2eproto[25]);
 }
-
 // ===================================================================
 
 class GeneratedCodeInfo::_Internal {
@@ -11102,7 +11598,7 @@
 
 void GeneratedCodeInfo::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.GeneratedCodeInfo)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -11111,14 +11607,15 @@
 }
 
 const char* GeneratedCodeInfo::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -11126,8 +11623,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -11152,10 +11650,11 @@
 #undef CHK_
 }
 
-uint8_t* GeneratedCodeInfo::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* GeneratedCodeInfo::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.GeneratedCodeInfo)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.GeneratedCodeInfo.Annotation annotation = 1;
@@ -11174,11 +11673,12 @@
   return target;
 }
 
-size_t GeneratedCodeInfo::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo)
-  size_t total_size = 0;
+::size_t GeneratedCodeInfo::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.GeneratedCodeInfo)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -11202,9 +11702,10 @@
 void GeneratedCodeInfo::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<GeneratedCodeInfo*>(&to_msg);
   auto& from = static_cast<const GeneratedCodeInfo&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.GeneratedCodeInfo)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.annotation_.MergeFrom(from._impl_.annotation_);
@@ -11229,11 +11730,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata GeneratedCodeInfo::GetMetadata() const {
+
   return ::_pbi::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
@@ -11346,6 +11847,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/descriptor.pb.h b/src/google/protobuf/descriptor.pb.h
index cb83348..40413f1 100644
--- a/src/google/protobuf/descriptor.pb.h
+++ b/src/google/protobuf/descriptor.pb.h
@@ -1,39 +1,44 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/descriptor.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/generated_enum_reflection.h>
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/generated_enum_reflection.h"
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fdescriptor_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -42,9 +47,10 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fdescriptor_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct DescriptorProtoDefaultTypeInternal;
@@ -127,38 +133,63 @@
 class UninterpretedOption_NamePart;
 struct UninterpretedOption_NamePartDefaultTypeInternal;
 PROTOBUF_EXPORT extern UninterpretedOption_NamePartDefaultTypeInternal _UninterpretedOption_NamePart_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValueOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileDescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileDescriptorSet* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileDescriptorSet>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MessageOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MessageOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MethodOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MethodOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::OneofOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::OneofOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ServiceOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ServiceOptions>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UninterpretedOption>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto_ExtensionRange>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DescriptorProto_ReservedRange>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto_EnumReservedRange>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValueDescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValueOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileDescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileDescriptorSet* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileDescriptorSet>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FileOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MessageOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MessageOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MethodDescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::MethodOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::MethodOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::OneofDescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::OneofOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::OneofOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ServiceOptions* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ServiceOptions>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo_Location>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UninterpretedOption* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UninterpretedOption>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UninterpretedOption_NamePart>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
 
+PROTOBUF_NAMESPACE_OPEN
 enum FieldDescriptorProto_Type : int {
   FieldDescriptorProto_Type_TYPE_DOUBLE = 1,
   FieldDescriptorProto_Type_TYPE_FLOAT = 2,
@@ -177,149 +208,212 @@
   FieldDescriptorProto_Type_TYPE_SFIXED32 = 15,
   FieldDescriptorProto_Type_TYPE_SFIXED64 = 16,
   FieldDescriptorProto_Type_TYPE_SINT32 = 17,
-  FieldDescriptorProto_Type_TYPE_SINT64 = 18
+  FieldDescriptorProto_Type_TYPE_SINT64 = 18,
 };
-PROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value);
-constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = FieldDescriptorProto_Type_TYPE_DOUBLE;
-constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = FieldDescriptorProto_Type_TYPE_SINT64;
-constexpr int FieldDescriptorProto_Type_Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Type_descriptor();
-template<typename T>
-inline const std::string& FieldDescriptorProto_Type_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, FieldDescriptorProto_Type>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function FieldDescriptorProto_Type_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    FieldDescriptorProto_Type_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool FieldDescriptorProto_Type_IsValid(int value);
+constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MIN = static_cast<FieldDescriptorProto_Type>(1);
+constexpr FieldDescriptorProto_Type FieldDescriptorProto_Type_Type_MAX = static_cast<FieldDescriptorProto_Type>(18);
+constexpr int FieldDescriptorProto_Type_Type_ARRAYSIZE = 18 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+FieldDescriptorProto_Type_descriptor();
+template <typename T>
+const std::string& FieldDescriptorProto_Type_Name(T value) {
+  static_assert(std::is_same<T, FieldDescriptorProto_Type>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to Type_Name().");
+  return FieldDescriptorProto_Type_Name(static_cast<FieldDescriptorProto_Type>(value));
 }
-inline bool FieldDescriptorProto_Type_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Type* value) {
+template <>
+inline const std::string& FieldDescriptorProto_Type_Name(FieldDescriptorProto_Type value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<FieldDescriptorProto_Type_descriptor,
+                                                 1, 18>(
+      static_cast<int>(value));
+}
+inline bool FieldDescriptorProto_Type_Parse(absl::string_view name, FieldDescriptorProto_Type* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Type>(
-    FieldDescriptorProto_Type_descriptor(), name, value);
+      FieldDescriptorProto_Type_descriptor(), name, value);
 }
 enum FieldDescriptorProto_Label : int {
   FieldDescriptorProto_Label_LABEL_OPTIONAL = 1,
   FieldDescriptorProto_Label_LABEL_REQUIRED = 2,
-  FieldDescriptorProto_Label_LABEL_REPEATED = 3
+  FieldDescriptorProto_Label_LABEL_REPEATED = 3,
 };
-PROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value);
-constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = FieldDescriptorProto_Label_LABEL_OPTIONAL;
-constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = FieldDescriptorProto_Label_LABEL_REPEATED;
-constexpr int FieldDescriptorProto_Label_Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldDescriptorProto_Label_descriptor();
-template<typename T>
-inline const std::string& FieldDescriptorProto_Label_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, FieldDescriptorProto_Label>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function FieldDescriptorProto_Label_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    FieldDescriptorProto_Label_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool FieldDescriptorProto_Label_IsValid(int value);
+constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MIN = static_cast<FieldDescriptorProto_Label>(1);
+constexpr FieldDescriptorProto_Label FieldDescriptorProto_Label_Label_MAX = static_cast<FieldDescriptorProto_Label>(3);
+constexpr int FieldDescriptorProto_Label_Label_ARRAYSIZE = 3 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+FieldDescriptorProto_Label_descriptor();
+template <typename T>
+const std::string& FieldDescriptorProto_Label_Name(T value) {
+  static_assert(std::is_same<T, FieldDescriptorProto_Label>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to Label_Name().");
+  return FieldDescriptorProto_Label_Name(static_cast<FieldDescriptorProto_Label>(value));
 }
-inline bool FieldDescriptorProto_Label_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldDescriptorProto_Label* value) {
+template <>
+inline const std::string& FieldDescriptorProto_Label_Name(FieldDescriptorProto_Label value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<FieldDescriptorProto_Label_descriptor,
+                                                 1, 3>(
+      static_cast<int>(value));
+}
+inline bool FieldDescriptorProto_Label_Parse(absl::string_view name, FieldDescriptorProto_Label* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldDescriptorProto_Label>(
-    FieldDescriptorProto_Label_descriptor(), name, value);
+      FieldDescriptorProto_Label_descriptor(), name, value);
 }
 enum FileOptions_OptimizeMode : int {
   FileOptions_OptimizeMode_SPEED = 1,
   FileOptions_OptimizeMode_CODE_SIZE = 2,
-  FileOptions_OptimizeMode_LITE_RUNTIME = 3
+  FileOptions_OptimizeMode_LITE_RUNTIME = 3,
 };
-PROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
-constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = FileOptions_OptimizeMode_SPEED;
-constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = FileOptions_OptimizeMode_LITE_RUNTIME;
-constexpr int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FileOptions_OptimizeMode_descriptor();
-template<typename T>
-inline const std::string& FileOptions_OptimizeMode_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, FileOptions_OptimizeMode>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function FileOptions_OptimizeMode_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    FileOptions_OptimizeMode_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool FileOptions_OptimizeMode_IsValid(int value);
+constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MIN = static_cast<FileOptions_OptimizeMode>(1);
+constexpr FileOptions_OptimizeMode FileOptions_OptimizeMode_OptimizeMode_MAX = static_cast<FileOptions_OptimizeMode>(3);
+constexpr int FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE = 3 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+FileOptions_OptimizeMode_descriptor();
+template <typename T>
+const std::string& FileOptions_OptimizeMode_Name(T value) {
+  static_assert(std::is_same<T, FileOptions_OptimizeMode>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to OptimizeMode_Name().");
+  return FileOptions_OptimizeMode_Name(static_cast<FileOptions_OptimizeMode>(value));
 }
-inline bool FileOptions_OptimizeMode_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FileOptions_OptimizeMode* value) {
+template <>
+inline const std::string& FileOptions_OptimizeMode_Name(FileOptions_OptimizeMode value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<FileOptions_OptimizeMode_descriptor,
+                                                 1, 3>(
+      static_cast<int>(value));
+}
+inline bool FileOptions_OptimizeMode_Parse(absl::string_view name, FileOptions_OptimizeMode* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FileOptions_OptimizeMode>(
-    FileOptions_OptimizeMode_descriptor(), name, value);
+      FileOptions_OptimizeMode_descriptor(), name, value);
 }
 enum FieldOptions_CType : int {
   FieldOptions_CType_STRING = 0,
   FieldOptions_CType_CORD = 1,
-  FieldOptions_CType_STRING_PIECE = 2
+  FieldOptions_CType_STRING_PIECE = 2,
 };
-PROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
-constexpr FieldOptions_CType FieldOptions_CType_CType_MIN = FieldOptions_CType_STRING;
-constexpr FieldOptions_CType FieldOptions_CType_CType_MAX = FieldOptions_CType_STRING_PIECE;
-constexpr int FieldOptions_CType_CType_ARRAYSIZE = FieldOptions_CType_CType_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_CType_descriptor();
-template<typename T>
-inline const std::string& FieldOptions_CType_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, FieldOptions_CType>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function FieldOptions_CType_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    FieldOptions_CType_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool FieldOptions_CType_IsValid(int value);
+constexpr FieldOptions_CType FieldOptions_CType_CType_MIN = static_cast<FieldOptions_CType>(0);
+constexpr FieldOptions_CType FieldOptions_CType_CType_MAX = static_cast<FieldOptions_CType>(2);
+constexpr int FieldOptions_CType_CType_ARRAYSIZE = 2 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+FieldOptions_CType_descriptor();
+template <typename T>
+const std::string& FieldOptions_CType_Name(T value) {
+  static_assert(std::is_same<T, FieldOptions_CType>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to CType_Name().");
+  return FieldOptions_CType_Name(static_cast<FieldOptions_CType>(value));
 }
-inline bool FieldOptions_CType_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_CType* value) {
+template <>
+inline const std::string& FieldOptions_CType_Name(FieldOptions_CType value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<FieldOptions_CType_descriptor,
+                                                 0, 2>(
+      static_cast<int>(value));
+}
+inline bool FieldOptions_CType_Parse(absl::string_view name, FieldOptions_CType* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_CType>(
-    FieldOptions_CType_descriptor(), name, value);
+      FieldOptions_CType_descriptor(), name, value);
 }
 enum FieldOptions_JSType : int {
   FieldOptions_JSType_JS_NORMAL = 0,
   FieldOptions_JSType_JS_STRING = 1,
-  FieldOptions_JSType_JS_NUMBER = 2
+  FieldOptions_JSType_JS_NUMBER = 2,
 };
-PROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value);
-constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MIN = FieldOptions_JSType_JS_NORMAL;
-constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MAX = FieldOptions_JSType_JS_NUMBER;
-constexpr int FieldOptions_JSType_JSType_ARRAYSIZE = FieldOptions_JSType_JSType_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* FieldOptions_JSType_descriptor();
-template<typename T>
-inline const std::string& FieldOptions_JSType_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, FieldOptions_JSType>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function FieldOptions_JSType_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    FieldOptions_JSType_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool FieldOptions_JSType_IsValid(int value);
+constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MIN = static_cast<FieldOptions_JSType>(0);
+constexpr FieldOptions_JSType FieldOptions_JSType_JSType_MAX = static_cast<FieldOptions_JSType>(2);
+constexpr int FieldOptions_JSType_JSType_ARRAYSIZE = 2 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+FieldOptions_JSType_descriptor();
+template <typename T>
+const std::string& FieldOptions_JSType_Name(T value) {
+  static_assert(std::is_same<T, FieldOptions_JSType>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to JSType_Name().");
+  return FieldOptions_JSType_Name(static_cast<FieldOptions_JSType>(value));
 }
-inline bool FieldOptions_JSType_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, FieldOptions_JSType* value) {
+template <>
+inline const std::string& FieldOptions_JSType_Name(FieldOptions_JSType value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<FieldOptions_JSType_descriptor,
+                                                 0, 2>(
+      static_cast<int>(value));
+}
+inline bool FieldOptions_JSType_Parse(absl::string_view name, FieldOptions_JSType* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<FieldOptions_JSType>(
-    FieldOptions_JSType_descriptor(), name, value);
+      FieldOptions_JSType_descriptor(), name, value);
 }
 enum MethodOptions_IdempotencyLevel : int {
   MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN = 0,
   MethodOptions_IdempotencyLevel_NO_SIDE_EFFECTS = 1,
-  MethodOptions_IdempotencyLevel_IDEMPOTENT = 2
+  MethodOptions_IdempotencyLevel_IDEMPOTENT = 2,
 };
-PROTOBUF_EXPORT bool MethodOptions_IdempotencyLevel_IsValid(int value);
-constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN = MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN;
-constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX = MethodOptions_IdempotencyLevel_IDEMPOTENT;
-constexpr int MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE = MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* MethodOptions_IdempotencyLevel_descriptor();
-template<typename T>
-inline const std::string& MethodOptions_IdempotencyLevel_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, MethodOptions_IdempotencyLevel>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function MethodOptions_IdempotencyLevel_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    MethodOptions_IdempotencyLevel_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool MethodOptions_IdempotencyLevel_IsValid(int value);
+constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN = static_cast<MethodOptions_IdempotencyLevel>(0);
+constexpr MethodOptions_IdempotencyLevel MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX = static_cast<MethodOptions_IdempotencyLevel>(2);
+constexpr int MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE = 2 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+MethodOptions_IdempotencyLevel_descriptor();
+template <typename T>
+const std::string& MethodOptions_IdempotencyLevel_Name(T value) {
+  static_assert(std::is_same<T, MethodOptions_IdempotencyLevel>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to IdempotencyLevel_Name().");
+  return MethodOptions_IdempotencyLevel_Name(static_cast<MethodOptions_IdempotencyLevel>(value));
 }
-inline bool MethodOptions_IdempotencyLevel_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, MethodOptions_IdempotencyLevel* value) {
+template <>
+inline const std::string& MethodOptions_IdempotencyLevel_Name(MethodOptions_IdempotencyLevel value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<MethodOptions_IdempotencyLevel_descriptor,
+                                                 0, 2>(
+      static_cast<int>(value));
+}
+inline bool MethodOptions_IdempotencyLevel_Parse(absl::string_view name, MethodOptions_IdempotencyLevel* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<MethodOptions_IdempotencyLevel>(
-    MethodOptions_IdempotencyLevel_descriptor(), name, value);
+      MethodOptions_IdempotencyLevel_descriptor(), name, value);
 }
+enum GeneratedCodeInfo_Annotation_Semantic : int {
+  GeneratedCodeInfo_Annotation_Semantic_NONE = 0,
+  GeneratedCodeInfo_Annotation_Semantic_SET = 1,
+  GeneratedCodeInfo_Annotation_Semantic_ALIAS = 2,
+};
+
+PROTOBUF_EXPORT bool GeneratedCodeInfo_Annotation_Semantic_IsValid(int value);
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation_Semantic_Semantic_MIN = static_cast<GeneratedCodeInfo_Annotation_Semantic>(0);
+constexpr GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation_Semantic_Semantic_MAX = static_cast<GeneratedCodeInfo_Annotation_Semantic>(2);
+constexpr int GeneratedCodeInfo_Annotation_Semantic_Semantic_ARRAYSIZE = 2 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+GeneratedCodeInfo_Annotation_Semantic_descriptor();
+template <typename T>
+const std::string& GeneratedCodeInfo_Annotation_Semantic_Name(T value) {
+  static_assert(std::is_same<T, GeneratedCodeInfo_Annotation_Semantic>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to Semantic_Name().");
+  return GeneratedCodeInfo_Annotation_Semantic_Name(static_cast<GeneratedCodeInfo_Annotation_Semantic>(value));
+}
+template <>
+inline const std::string& GeneratedCodeInfo_Annotation_Semantic_Name(GeneratedCodeInfo_Annotation_Semantic value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<GeneratedCodeInfo_Annotation_Semantic_descriptor,
+                                                 0, 2>(
+      static_cast<int>(value));
+}
+inline bool GeneratedCodeInfo_Annotation_Semantic_Parse(absl::string_view name, GeneratedCodeInfo_Annotation_Semantic* value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<GeneratedCodeInfo_Annotation_Semantic>(
+      GeneratedCodeInfo_Annotation_Semantic_descriptor(), name, value);
+}
+
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT FileDescriptorSet final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorSet) */ {
  public:
@@ -416,10 +510,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -430,7 +524,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.FileDescriptorSet";
   }
   protected:
@@ -481,8 +575,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT FileDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileDescriptorProto) */ {
@@ -580,10 +673,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -594,7 +687,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.FileDescriptorProto";
   }
   protected:
@@ -622,6 +715,7 @@
     kNameFieldNumber = 1,
     kPackageFieldNumber = 2,
     kSyntaxFieldNumber = 12,
+    kEditionFieldNumber = 13,
     kOptionsFieldNumber = 8,
     kSourceCodeInfoFieldNumber = 9,
   };
@@ -636,12 +730,12 @@
   void set_dependency(int index, const std::string& value);
   void set_dependency(int index, std::string&& value);
   void set_dependency(int index, const char* value);
-  void set_dependency(int index, const char* value, size_t size);
+  void set_dependency(int index, const char* value, ::size_t size);
   std::string* add_dependency();
   void add_dependency(const std::string& value);
   void add_dependency(std::string&& value);
   void add_dependency(const char* value);
-  void add_dependency(const char* value, size_t size);
+  void add_dependency(const char* value, ::size_t size);
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& dependency() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_dependency();
   private:
@@ -728,19 +822,19 @@
   public:
   void clear_public_dependency();
   private:
-  int32_t _internal_public_dependency(int index) const;
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t _internal_public_dependency(int index) const;
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       _internal_public_dependency() const;
-  void _internal_add_public_dependency(int32_t value);
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  void _internal_add_public_dependency(::int32_t value);
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       _internal_mutable_public_dependency();
   public:
-  int32_t public_dependency(int index) const;
-  void set_public_dependency(int index, int32_t value);
-  void add_public_dependency(int32_t value);
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t public_dependency(int index) const;
+  void set_public_dependency(int index, ::int32_t value);
+  void add_public_dependency(::int32_t value);
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       public_dependency() const;
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       mutable_public_dependency();
 
   // repeated int32 weak_dependency = 11;
@@ -750,26 +844,23 @@
   public:
   void clear_weak_dependency();
   private:
-  int32_t _internal_weak_dependency(int index) const;
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t _internal_weak_dependency(int index) const;
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       _internal_weak_dependency() const;
-  void _internal_add_weak_dependency(int32_t value);
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  void _internal_add_weak_dependency(::int32_t value);
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       _internal_mutable_weak_dependency();
   public:
-  int32_t weak_dependency(int index) const;
-  void set_weak_dependency(int index, int32_t value);
-  void add_weak_dependency(int32_t value);
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t weak_dependency(int index) const;
+  void set_weak_dependency(int index, ::int32_t value);
+  void add_weak_dependency(::int32_t value);
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       weak_dependency() const;
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       mutable_weak_dependency();
 
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -785,9 +876,6 @@
 
   // optional string package = 2;
   bool has_package() const;
-  private:
-  bool _internal_has_package() const;
-  public:
   void clear_package();
   const std::string& package() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -803,9 +891,6 @@
 
   // optional string syntax = 12;
   bool has_syntax() const;
-  private:
-  bool _internal_has_syntax() const;
-  public:
   void clear_syntax();
   const std::string& syntax() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -819,11 +904,23 @@
   std::string* _internal_mutable_syntax();
   public:
 
+  // optional string edition = 13;
+  bool has_edition() const;
+  void clear_edition();
+  const std::string& edition() const;
+  template <typename ArgT0 = const std::string&, typename... ArgT>
+  void set_edition(ArgT0&& arg0, ArgT... args);
+  std::string* mutable_edition();
+  PROTOBUF_NODISCARD std::string* release_edition();
+  void set_allocated_edition(std::string* edition);
+  private:
+  const std::string& _internal_edition() const;
+  inline PROTOBUF_ALWAYS_INLINE void _internal_set_edition(const std::string& value);
+  std::string* _internal_mutable_edition();
+  public:
+
   // optional .google.protobuf.FileOptions options = 8;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::FileOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::FileOptions* release_options();
@@ -839,9 +936,6 @@
 
   // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
   bool has_source_code_info() const;
-  private:
-  bool _internal_has_source_code_info() const;
-  public:
   void clear_source_code_info();
   const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& source_code_info() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* release_source_code_info();
@@ -870,18 +964,18 @@
     ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::EnumDescriptorProto > enum_type_;
     ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::ServiceDescriptorProto > service_;
     ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto > extension_;
-    ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > public_dependency_;
-    ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > weak_dependency_;
+    ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t > public_dependency_;
+    ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t > weak_dependency_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr package_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr syntax_;
+    ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr edition_;
     ::PROTOBUF_NAMESPACE_ID::FileOptions* options_;
     ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* source_code_info_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT DescriptorProto_ExtensionRange final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ExtensionRange) */ {
@@ -979,10 +1073,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -993,7 +1087,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.DescriptorProto.ExtensionRange";
   }
   protected:
@@ -1017,9 +1111,6 @@
   };
   // optional .google.protobuf.ExtensionRangeOptions options = 3;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* release_options();
@@ -1035,28 +1126,22 @@
 
   // optional int32 start = 1;
   bool has_start() const;
-  private:
-  bool _internal_has_start() const;
-  public:
   void clear_start();
-  int32_t start() const;
-  void set_start(int32_t value);
+  ::int32_t start() const;
+  void set_start(::int32_t value);
   private:
-  int32_t _internal_start() const;
-  void _internal_set_start(int32_t value);
+  ::int32_t _internal_start() const;
+  void _internal_set_start(::int32_t value);
   public:
 
   // optional int32 end = 2;
   bool has_end() const;
-  private:
-  bool _internal_has_end() const;
-  public:
   void clear_end();
-  int32_t end() const;
-  void set_end(int32_t value);
+  ::int32_t end() const;
+  void set_end(::int32_t value);
   private:
-  int32_t _internal_end() const;
-  void _internal_set_end(int32_t value);
+  ::int32_t _internal_end() const;
+  void _internal_set_end(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ExtensionRange)
@@ -1070,13 +1155,12 @@
     ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
     ::PROTOBUF_NAMESPACE_ID::ExtensionRangeOptions* options_;
-    int32_t start_;
-    int32_t end_;
+    ::int32_t start_;
+    ::int32_t end_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT DescriptorProto_ReservedRange final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto.ReservedRange) */ {
@@ -1174,10 +1258,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1188,7 +1272,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.DescriptorProto.ReservedRange";
   }
   protected:
@@ -1211,28 +1295,22 @@
   };
   // optional int32 start = 1;
   bool has_start() const;
-  private:
-  bool _internal_has_start() const;
-  public:
   void clear_start();
-  int32_t start() const;
-  void set_start(int32_t value);
+  ::int32_t start() const;
+  void set_start(::int32_t value);
   private:
-  int32_t _internal_start() const;
-  void _internal_set_start(int32_t value);
+  ::int32_t _internal_start() const;
+  void _internal_set_start(::int32_t value);
   public:
 
   // optional int32 end = 2;
   bool has_end() const;
-  private:
-  bool _internal_has_end() const;
-  public:
   void clear_end();
-  int32_t end() const;
-  void set_end(int32_t value);
+  ::int32_t end() const;
+  void set_end(::int32_t value);
   private:
-  int32_t _internal_end() const;
-  void _internal_set_end(int32_t value);
+  ::int32_t _internal_end() const;
+  void _internal_set_end(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.DescriptorProto.ReservedRange)
@@ -1245,13 +1323,12 @@
   struct Impl_ {
     ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
-    int32_t start_;
-    int32_t end_;
+    ::int32_t start_;
+    ::int32_t end_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT DescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DescriptorProto) */ {
@@ -1349,10 +1426,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1363,7 +1440,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.DescriptorProto";
   }
   protected:
@@ -1532,12 +1609,12 @@
   void set_reserved_name(int index, const std::string& value);
   void set_reserved_name(int index, std::string&& value);
   void set_reserved_name(int index, const char* value);
-  void set_reserved_name(int index, const char* value, size_t size);
+  void set_reserved_name(int index, const char* value, ::size_t size);
   std::string* add_reserved_name();
   void add_reserved_name(const std::string& value);
   void add_reserved_name(std::string&& value);
   void add_reserved_name(const char* value);
-  void add_reserved_name(const char* value, size_t size);
+  void add_reserved_name(const char* value, ::size_t size);
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& reserved_name() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_reserved_name();
   private:
@@ -1547,9 +1624,6 @@
 
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -1565,9 +1639,6 @@
 
   // optional .google.protobuf.MessageOptions options = 7;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::MessageOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::MessageOptions* release_options();
@@ -1604,8 +1675,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT ExtensionRangeOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ExtensionRangeOptions) */ {
@@ -1703,10 +1773,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1717,7 +1787,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.ExtensionRangeOptions";
   }
   protected:
@@ -1960,8 +2030,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT FieldDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldDescriptorProto) */ {
@@ -2059,10 +2128,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -2073,7 +2142,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.FieldDescriptorProto";
   }
   protected:
@@ -2088,97 +2157,60 @@
 
   // nested types ----------------------------------------------------
 
-  typedef FieldDescriptorProto_Type Type;
-  static constexpr Type TYPE_DOUBLE =
-    FieldDescriptorProto_Type_TYPE_DOUBLE;
-  static constexpr Type TYPE_FLOAT =
-    FieldDescriptorProto_Type_TYPE_FLOAT;
-  static constexpr Type TYPE_INT64 =
-    FieldDescriptorProto_Type_TYPE_INT64;
-  static constexpr Type TYPE_UINT64 =
-    FieldDescriptorProto_Type_TYPE_UINT64;
-  static constexpr Type TYPE_INT32 =
-    FieldDescriptorProto_Type_TYPE_INT32;
-  static constexpr Type TYPE_FIXED64 =
-    FieldDescriptorProto_Type_TYPE_FIXED64;
-  static constexpr Type TYPE_FIXED32 =
-    FieldDescriptorProto_Type_TYPE_FIXED32;
-  static constexpr Type TYPE_BOOL =
-    FieldDescriptorProto_Type_TYPE_BOOL;
-  static constexpr Type TYPE_STRING =
-    FieldDescriptorProto_Type_TYPE_STRING;
-  static constexpr Type TYPE_GROUP =
-    FieldDescriptorProto_Type_TYPE_GROUP;
-  static constexpr Type TYPE_MESSAGE =
-    FieldDescriptorProto_Type_TYPE_MESSAGE;
-  static constexpr Type TYPE_BYTES =
-    FieldDescriptorProto_Type_TYPE_BYTES;
-  static constexpr Type TYPE_UINT32 =
-    FieldDescriptorProto_Type_TYPE_UINT32;
-  static constexpr Type TYPE_ENUM =
-    FieldDescriptorProto_Type_TYPE_ENUM;
-  static constexpr Type TYPE_SFIXED32 =
-    FieldDescriptorProto_Type_TYPE_SFIXED32;
-  static constexpr Type TYPE_SFIXED64 =
-    FieldDescriptorProto_Type_TYPE_SFIXED64;
-  static constexpr Type TYPE_SINT32 =
-    FieldDescriptorProto_Type_TYPE_SINT32;
-  static constexpr Type TYPE_SINT64 =
-    FieldDescriptorProto_Type_TYPE_SINT64;
+  using Type = FieldDescriptorProto_Type;
+  static constexpr Type TYPE_DOUBLE = FieldDescriptorProto_Type_TYPE_DOUBLE;
+  static constexpr Type TYPE_FLOAT = FieldDescriptorProto_Type_TYPE_FLOAT;
+  static constexpr Type TYPE_INT64 = FieldDescriptorProto_Type_TYPE_INT64;
+  static constexpr Type TYPE_UINT64 = FieldDescriptorProto_Type_TYPE_UINT64;
+  static constexpr Type TYPE_INT32 = FieldDescriptorProto_Type_TYPE_INT32;
+  static constexpr Type TYPE_FIXED64 = FieldDescriptorProto_Type_TYPE_FIXED64;
+  static constexpr Type TYPE_FIXED32 = FieldDescriptorProto_Type_TYPE_FIXED32;
+  static constexpr Type TYPE_BOOL = FieldDescriptorProto_Type_TYPE_BOOL;
+  static constexpr Type TYPE_STRING = FieldDescriptorProto_Type_TYPE_STRING;
+  static constexpr Type TYPE_GROUP = FieldDescriptorProto_Type_TYPE_GROUP;
+  static constexpr Type TYPE_MESSAGE = FieldDescriptorProto_Type_TYPE_MESSAGE;
+  static constexpr Type TYPE_BYTES = FieldDescriptorProto_Type_TYPE_BYTES;
+  static constexpr Type TYPE_UINT32 = FieldDescriptorProto_Type_TYPE_UINT32;
+  static constexpr Type TYPE_ENUM = FieldDescriptorProto_Type_TYPE_ENUM;
+  static constexpr Type TYPE_SFIXED32 = FieldDescriptorProto_Type_TYPE_SFIXED32;
+  static constexpr Type TYPE_SFIXED64 = FieldDescriptorProto_Type_TYPE_SFIXED64;
+  static constexpr Type TYPE_SINT32 = FieldDescriptorProto_Type_TYPE_SINT32;
+  static constexpr Type TYPE_SINT64 = FieldDescriptorProto_Type_TYPE_SINT64;
   static inline bool Type_IsValid(int value) {
     return FieldDescriptorProto_Type_IsValid(value);
   }
-  static constexpr Type Type_MIN =
-    FieldDescriptorProto_Type_Type_MIN;
-  static constexpr Type Type_MAX =
-    FieldDescriptorProto_Type_Type_MAX;
-  static constexpr int Type_ARRAYSIZE =
-    FieldDescriptorProto_Type_Type_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  Type_descriptor() {
+  static constexpr Type Type_MIN = FieldDescriptorProto_Type_Type_MIN;
+  static constexpr Type Type_MAX = FieldDescriptorProto_Type_Type_MAX;
+  static constexpr int Type_ARRAYSIZE = FieldDescriptorProto_Type_Type_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Type_descriptor() {
     return FieldDescriptorProto_Type_descriptor();
   }
-  template<typename T>
-  static inline const std::string& Type_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, Type>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function Type_Name.");
-    return FieldDescriptorProto_Type_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& Type_Name(T value) {
+    return FieldDescriptorProto_Type_Name(value);
   }
-  static inline bool Type_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      Type* value) {
+  static inline bool Type_Parse(absl::string_view name, Type* value) {
     return FieldDescriptorProto_Type_Parse(name, value);
   }
 
-  typedef FieldDescriptorProto_Label Label;
-  static constexpr Label LABEL_OPTIONAL =
-    FieldDescriptorProto_Label_LABEL_OPTIONAL;
-  static constexpr Label LABEL_REQUIRED =
-    FieldDescriptorProto_Label_LABEL_REQUIRED;
-  static constexpr Label LABEL_REPEATED =
-    FieldDescriptorProto_Label_LABEL_REPEATED;
+  using Label = FieldDescriptorProto_Label;
+  static constexpr Label LABEL_OPTIONAL = FieldDescriptorProto_Label_LABEL_OPTIONAL;
+  static constexpr Label LABEL_REQUIRED = FieldDescriptorProto_Label_LABEL_REQUIRED;
+  static constexpr Label LABEL_REPEATED = FieldDescriptorProto_Label_LABEL_REPEATED;
   static inline bool Label_IsValid(int value) {
     return FieldDescriptorProto_Label_IsValid(value);
   }
-  static constexpr Label Label_MIN =
-    FieldDescriptorProto_Label_Label_MIN;
-  static constexpr Label Label_MAX =
-    FieldDescriptorProto_Label_Label_MAX;
-  static constexpr int Label_ARRAYSIZE =
-    FieldDescriptorProto_Label_Label_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  Label_descriptor() {
+  static constexpr Label Label_MIN = FieldDescriptorProto_Label_Label_MIN;
+  static constexpr Label Label_MAX = FieldDescriptorProto_Label_Label_MAX;
+  static constexpr int Label_ARRAYSIZE = FieldDescriptorProto_Label_Label_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Label_descriptor() {
     return FieldDescriptorProto_Label_descriptor();
   }
-  template<typename T>
-  static inline const std::string& Label_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, Label>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function Label_Name.");
-    return FieldDescriptorProto_Label_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& Label_Name(T value) {
+    return FieldDescriptorProto_Label_Name(value);
   }
-  static inline bool Label_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      Label* value) {
+  static inline bool Label_Parse(absl::string_view name, Label* value) {
     return FieldDescriptorProto_Label_Parse(name, value);
   }
 
@@ -2199,9 +2231,6 @@
   };
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -2217,9 +2246,6 @@
 
   // optional string extendee = 2;
   bool has_extendee() const;
-  private:
-  bool _internal_has_extendee() const;
-  public:
   void clear_extendee();
   const std::string& extendee() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -2235,9 +2261,6 @@
 
   // optional string type_name = 6;
   bool has_type_name() const;
-  private:
-  bool _internal_has_type_name() const;
-  public:
   void clear_type_name();
   const std::string& type_name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -2253,9 +2276,6 @@
 
   // optional string default_value = 7;
   bool has_default_value() const;
-  private:
-  bool _internal_has_default_value() const;
-  public:
   void clear_default_value();
   const std::string& default_value() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -2271,9 +2291,6 @@
 
   // optional string json_name = 10;
   bool has_json_name() const;
-  private:
-  bool _internal_has_json_name() const;
-  public:
   void clear_json_name();
   const std::string& json_name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -2289,9 +2306,6 @@
 
   // optional .google.protobuf.FieldOptions options = 8;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::FieldOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::FieldOptions* release_options();
@@ -2307,35 +2321,26 @@
 
   // optional int32 number = 3;
   bool has_number() const;
-  private:
-  bool _internal_has_number() const;
-  public:
   void clear_number();
-  int32_t number() const;
-  void set_number(int32_t value);
+  ::int32_t number() const;
+  void set_number(::int32_t value);
   private:
-  int32_t _internal_number() const;
-  void _internal_set_number(int32_t value);
+  ::int32_t _internal_number() const;
+  void _internal_set_number(::int32_t value);
   public:
 
   // optional int32 oneof_index = 9;
   bool has_oneof_index() const;
-  private:
-  bool _internal_has_oneof_index() const;
-  public:
   void clear_oneof_index();
-  int32_t oneof_index() const;
-  void set_oneof_index(int32_t value);
+  ::int32_t oneof_index() const;
+  void set_oneof_index(::int32_t value);
   private:
-  int32_t _internal_oneof_index() const;
-  void _internal_set_oneof_index(int32_t value);
+  ::int32_t _internal_oneof_index() const;
+  void _internal_set_oneof_index(::int32_t value);
   public:
 
   // optional bool proto3_optional = 17;
   bool has_proto3_optional() const;
-  private:
-  bool _internal_has_proto3_optional() const;
-  public:
   void clear_proto3_optional();
   bool proto3_optional() const;
   void set_proto3_optional(bool value);
@@ -2346,9 +2351,6 @@
 
   // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
   bool has_label() const;
-  private:
-  bool _internal_has_label() const;
-  public:
   void clear_label();
   ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label label() const;
   void set_label(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label value);
@@ -2359,9 +2361,6 @@
 
   // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
   bool has_type() const;
-  private:
-  bool _internal_has_type() const;
-  public:
   void clear_type();
   ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type type() const;
   void set_type(::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type value);
@@ -2386,16 +2385,15 @@
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr default_value_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr json_name_;
     ::PROTOBUF_NAMESPACE_ID::FieldOptions* options_;
-    int32_t number_;
-    int32_t oneof_index_;
+    ::int32_t number_;
+    ::int32_t oneof_index_;
     bool proto3_optional_;
     int label_;
     int type_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT OneofDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofDescriptorProto) */ {
@@ -2493,10 +2491,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -2507,7 +2505,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.OneofDescriptorProto";
   }
   protected:
@@ -2530,9 +2528,6 @@
   };
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -2548,9 +2543,6 @@
 
   // optional .google.protobuf.OneofOptions options = 2;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::OneofOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::OneofOptions* release_options();
@@ -2579,8 +2571,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT EnumDescriptorProto_EnumReservedRange final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto.EnumReservedRange) */ {
@@ -2678,10 +2669,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -2692,7 +2683,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.EnumDescriptorProto.EnumReservedRange";
   }
   protected:
@@ -2715,28 +2706,22 @@
   };
   // optional int32 start = 1;
   bool has_start() const;
-  private:
-  bool _internal_has_start() const;
-  public:
   void clear_start();
-  int32_t start() const;
-  void set_start(int32_t value);
+  ::int32_t start() const;
+  void set_start(::int32_t value);
   private:
-  int32_t _internal_start() const;
-  void _internal_set_start(int32_t value);
+  ::int32_t _internal_start() const;
+  void _internal_set_start(::int32_t value);
   public:
 
   // optional int32 end = 2;
   bool has_end() const;
-  private:
-  bool _internal_has_end() const;
-  public:
   void clear_end();
-  int32_t end() const;
-  void set_end(int32_t value);
+  ::int32_t end() const;
+  void set_end(::int32_t value);
   private:
-  int32_t _internal_end() const;
-  void _internal_set_end(int32_t value);
+  ::int32_t _internal_end() const;
+  void _internal_set_end(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumDescriptorProto.EnumReservedRange)
@@ -2749,13 +2734,12 @@
   struct Impl_ {
     ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
-    int32_t start_;
-    int32_t end_;
+    ::int32_t start_;
+    ::int32_t end_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT EnumDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumDescriptorProto) */ {
@@ -2853,10 +2837,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -2867,7 +2851,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.EnumDescriptorProto";
   }
   protected:
@@ -2940,12 +2924,12 @@
   void set_reserved_name(int index, const std::string& value);
   void set_reserved_name(int index, std::string&& value);
   void set_reserved_name(int index, const char* value);
-  void set_reserved_name(int index, const char* value, size_t size);
+  void set_reserved_name(int index, const char* value, ::size_t size);
   std::string* add_reserved_name();
   void add_reserved_name(const std::string& value);
   void add_reserved_name(std::string&& value);
   void add_reserved_name(const char* value);
-  void add_reserved_name(const char* value, size_t size);
+  void add_reserved_name(const char* value, ::size_t size);
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& reserved_name() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_reserved_name();
   private:
@@ -2955,9 +2939,6 @@
 
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -2973,9 +2954,6 @@
 
   // optional .google.protobuf.EnumOptions options = 3;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::EnumOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::EnumOptions* release_options();
@@ -3007,8 +2985,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT EnumValueDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueDescriptorProto) */ {
@@ -3106,10 +3083,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -3120,7 +3097,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.EnumValueDescriptorProto";
   }
   protected:
@@ -3144,9 +3121,6 @@
   };
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3162,9 +3136,6 @@
 
   // optional .google.protobuf.EnumValueOptions options = 3;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::EnumValueOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* release_options();
@@ -3180,15 +3151,12 @@
 
   // optional int32 number = 2;
   bool has_number() const;
-  private:
-  bool _internal_has_number() const;
-  public:
   void clear_number();
-  int32_t number() const;
-  void set_number(int32_t value);
+  ::int32_t number() const;
+  void set_number(::int32_t value);
   private:
-  int32_t _internal_number() const;
-  void _internal_set_number(int32_t value);
+  ::int32_t _internal_number() const;
+  void _internal_set_number(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValueDescriptorProto)
@@ -3203,12 +3171,11 @@
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
     ::PROTOBUF_NAMESPACE_ID::EnumValueOptions* options_;
-    int32_t number_;
+    ::int32_t number_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT ServiceDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceDescriptorProto) */ {
@@ -3306,10 +3273,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -3320,7 +3287,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.ServiceDescriptorProto";
   }
   protected:
@@ -3362,9 +3329,6 @@
 
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3380,9 +3344,6 @@
 
   // optional .google.protobuf.ServiceOptions options = 3;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::ServiceOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::ServiceOptions* release_options();
@@ -3412,8 +3373,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT MethodDescriptorProto final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodDescriptorProto) */ {
@@ -3511,10 +3471,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -3525,7 +3485,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.MethodDescriptorProto";
   }
   protected:
@@ -3552,9 +3512,6 @@
   };
   // optional string name = 1;
   bool has_name() const;
-  private:
-  bool _internal_has_name() const;
-  public:
   void clear_name();
   const std::string& name() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3570,9 +3527,6 @@
 
   // optional string input_type = 2;
   bool has_input_type() const;
-  private:
-  bool _internal_has_input_type() const;
-  public:
   void clear_input_type();
   const std::string& input_type() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3588,9 +3542,6 @@
 
   // optional string output_type = 3;
   bool has_output_type() const;
-  private:
-  bool _internal_has_output_type() const;
-  public:
   void clear_output_type();
   const std::string& output_type() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3606,9 +3557,6 @@
 
   // optional .google.protobuf.MethodOptions options = 4;
   bool has_options() const;
-  private:
-  bool _internal_has_options() const;
-  public:
   void clear_options();
   const ::PROTOBUF_NAMESPACE_ID::MethodOptions& options() const;
   PROTOBUF_NODISCARD ::PROTOBUF_NAMESPACE_ID::MethodOptions* release_options();
@@ -3624,9 +3572,6 @@
 
   // optional bool client_streaming = 5 [default = false];
   bool has_client_streaming() const;
-  private:
-  bool _internal_has_client_streaming() const;
-  public:
   void clear_client_streaming();
   bool client_streaming() const;
   void set_client_streaming(bool value);
@@ -3637,9 +3582,6 @@
 
   // optional bool server_streaming = 6 [default = false];
   bool has_server_streaming() const;
-  private:
-  bool _internal_has_server_streaming() const;
-  public:
   void clear_server_streaming();
   bool server_streaming() const;
   void set_server_streaming(bool value);
@@ -3667,8 +3609,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT FileOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FileOptions) */ {
@@ -3766,10 +3707,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -3780,7 +3721,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.FileOptions";
   }
   protected:
@@ -3795,35 +3736,24 @@
 
   // nested types ----------------------------------------------------
 
-  typedef FileOptions_OptimizeMode OptimizeMode;
-  static constexpr OptimizeMode SPEED =
-    FileOptions_OptimizeMode_SPEED;
-  static constexpr OptimizeMode CODE_SIZE =
-    FileOptions_OptimizeMode_CODE_SIZE;
-  static constexpr OptimizeMode LITE_RUNTIME =
-    FileOptions_OptimizeMode_LITE_RUNTIME;
+  using OptimizeMode = FileOptions_OptimizeMode;
+  static constexpr OptimizeMode SPEED = FileOptions_OptimizeMode_SPEED;
+  static constexpr OptimizeMode CODE_SIZE = FileOptions_OptimizeMode_CODE_SIZE;
+  static constexpr OptimizeMode LITE_RUNTIME = FileOptions_OptimizeMode_LITE_RUNTIME;
   static inline bool OptimizeMode_IsValid(int value) {
     return FileOptions_OptimizeMode_IsValid(value);
   }
-  static constexpr OptimizeMode OptimizeMode_MIN =
-    FileOptions_OptimizeMode_OptimizeMode_MIN;
-  static constexpr OptimizeMode OptimizeMode_MAX =
-    FileOptions_OptimizeMode_OptimizeMode_MAX;
-  static constexpr int OptimizeMode_ARRAYSIZE =
-    FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  OptimizeMode_descriptor() {
+  static constexpr OptimizeMode OptimizeMode_MIN = FileOptions_OptimizeMode_OptimizeMode_MIN;
+  static constexpr OptimizeMode OptimizeMode_MAX = FileOptions_OptimizeMode_OptimizeMode_MAX;
+  static constexpr int OptimizeMode_ARRAYSIZE = FileOptions_OptimizeMode_OptimizeMode_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* OptimizeMode_descriptor() {
     return FileOptions_OptimizeMode_descriptor();
   }
-  template<typename T>
-  static inline const std::string& OptimizeMode_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, OptimizeMode>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function OptimizeMode_Name.");
-    return FileOptions_OptimizeMode_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& OptimizeMode_Name(T value) {
+    return FileOptions_OptimizeMode_Name(value);
   }
-  static inline bool OptimizeMode_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      OptimizeMode* value) {
+  static inline bool OptimizeMode_Parse(absl::string_view name, OptimizeMode* value) {
     return FileOptions_OptimizeMode_Parse(name, value);
   }
 
@@ -3872,9 +3802,6 @@
 
   // optional string java_package = 1;
   bool has_java_package() const;
-  private:
-  bool _internal_has_java_package() const;
-  public:
   void clear_java_package();
   const std::string& java_package() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3890,9 +3817,6 @@
 
   // optional string java_outer_classname = 8;
   bool has_java_outer_classname() const;
-  private:
-  bool _internal_has_java_outer_classname() const;
-  public:
   void clear_java_outer_classname();
   const std::string& java_outer_classname() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3908,9 +3832,6 @@
 
   // optional string go_package = 11;
   bool has_go_package() const;
-  private:
-  bool _internal_has_go_package() const;
-  public:
   void clear_go_package();
   const std::string& go_package() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3926,9 +3847,6 @@
 
   // optional string objc_class_prefix = 36;
   bool has_objc_class_prefix() const;
-  private:
-  bool _internal_has_objc_class_prefix() const;
-  public:
   void clear_objc_class_prefix();
   const std::string& objc_class_prefix() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3944,9 +3862,6 @@
 
   // optional string csharp_namespace = 37;
   bool has_csharp_namespace() const;
-  private:
-  bool _internal_has_csharp_namespace() const;
-  public:
   void clear_csharp_namespace();
   const std::string& csharp_namespace() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3962,9 +3877,6 @@
 
   // optional string swift_prefix = 39;
   bool has_swift_prefix() const;
-  private:
-  bool _internal_has_swift_prefix() const;
-  public:
   void clear_swift_prefix();
   const std::string& swift_prefix() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3980,9 +3892,6 @@
 
   // optional string php_class_prefix = 40;
   bool has_php_class_prefix() const;
-  private:
-  bool _internal_has_php_class_prefix() const;
-  public:
   void clear_php_class_prefix();
   const std::string& php_class_prefix() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -3998,9 +3907,6 @@
 
   // optional string php_namespace = 41;
   bool has_php_namespace() const;
-  private:
-  bool _internal_has_php_namespace() const;
-  public:
   void clear_php_namespace();
   const std::string& php_namespace() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -4016,9 +3922,6 @@
 
   // optional string php_metadata_namespace = 44;
   bool has_php_metadata_namespace() const;
-  private:
-  bool _internal_has_php_metadata_namespace() const;
-  public:
   void clear_php_metadata_namespace();
   const std::string& php_metadata_namespace() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -4034,9 +3937,6 @@
 
   // optional string ruby_package = 45;
   bool has_ruby_package() const;
-  private:
-  bool _internal_has_ruby_package() const;
-  public:
   void clear_ruby_package();
   const std::string& ruby_package() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -4052,9 +3952,6 @@
 
   // optional bool java_multiple_files = 10 [default = false];
   bool has_java_multiple_files() const;
-  private:
-  bool _internal_has_java_multiple_files() const;
-  public:
   void clear_java_multiple_files();
   bool java_multiple_files() const;
   void set_java_multiple_files(bool value);
@@ -4065,9 +3962,6 @@
 
   // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
   PROTOBUF_DEPRECATED bool has_java_generate_equals_and_hash() const;
-  private:
-  bool _internal_has_java_generate_equals_and_hash() const;
-  public:
   PROTOBUF_DEPRECATED void clear_java_generate_equals_and_hash();
   PROTOBUF_DEPRECATED bool java_generate_equals_and_hash() const;
   PROTOBUF_DEPRECATED void set_java_generate_equals_and_hash(bool value);
@@ -4078,9 +3972,6 @@
 
   // optional bool java_string_check_utf8 = 27 [default = false];
   bool has_java_string_check_utf8() const;
-  private:
-  bool _internal_has_java_string_check_utf8() const;
-  public:
   void clear_java_string_check_utf8();
   bool java_string_check_utf8() const;
   void set_java_string_check_utf8(bool value);
@@ -4091,9 +3982,6 @@
 
   // optional bool cc_generic_services = 16 [default = false];
   bool has_cc_generic_services() const;
-  private:
-  bool _internal_has_cc_generic_services() const;
-  public:
   void clear_cc_generic_services();
   bool cc_generic_services() const;
   void set_cc_generic_services(bool value);
@@ -4104,9 +3992,6 @@
 
   // optional bool java_generic_services = 17 [default = false];
   bool has_java_generic_services() const;
-  private:
-  bool _internal_has_java_generic_services() const;
-  public:
   void clear_java_generic_services();
   bool java_generic_services() const;
   void set_java_generic_services(bool value);
@@ -4117,9 +4002,6 @@
 
   // optional bool py_generic_services = 18 [default = false];
   bool has_py_generic_services() const;
-  private:
-  bool _internal_has_py_generic_services() const;
-  public:
   void clear_py_generic_services();
   bool py_generic_services() const;
   void set_py_generic_services(bool value);
@@ -4130,9 +4012,6 @@
 
   // optional bool php_generic_services = 42 [default = false];
   bool has_php_generic_services() const;
-  private:
-  bool _internal_has_php_generic_services() const;
-  public:
   void clear_php_generic_services();
   bool php_generic_services() const;
   void set_php_generic_services(bool value);
@@ -4143,9 +4022,6 @@
 
   // optional bool deprecated = 23 [default = false];
   bool has_deprecated() const;
-  private:
-  bool _internal_has_deprecated() const;
-  public:
   void clear_deprecated();
   bool deprecated() const;
   void set_deprecated(bool value);
@@ -4156,9 +4032,6 @@
 
   // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
   bool has_optimize_for() const;
-  private:
-  bool _internal_has_optimize_for() const;
-  public:
   void clear_optimize_for();
   ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode optimize_for() const;
   void set_optimize_for(::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode value);
@@ -4169,9 +4042,6 @@
 
   // optional bool cc_enable_arenas = 31 [default = true];
   bool has_cc_enable_arenas() const;
-  private:
-  bool _internal_has_cc_enable_arenas() const;
-  public:
   void clear_cc_enable_arenas();
   bool cc_enable_arenas() const;
   void set_cc_enable_arenas(bool value);
@@ -4406,8 +4276,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT MessageOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MessageOptions) */ {
@@ -4505,10 +4374,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -4519,7 +4388,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.MessageOptions";
   }
   protected:
@@ -4563,9 +4432,6 @@
 
   // optional bool message_set_wire_format = 1 [default = false];
   bool has_message_set_wire_format() const;
-  private:
-  bool _internal_has_message_set_wire_format() const;
-  public:
   void clear_message_set_wire_format();
   bool message_set_wire_format() const;
   void set_message_set_wire_format(bool value);
@@ -4576,9 +4442,6 @@
 
   // optional bool no_standard_descriptor_accessor = 2 [default = false];
   bool has_no_standard_descriptor_accessor() const;
-  private:
-  bool _internal_has_no_standard_descriptor_accessor() const;
-  public:
   void clear_no_standard_descriptor_accessor();
   bool no_standard_descriptor_accessor() const;
   void set_no_standard_descriptor_accessor(bool value);
@@ -4589,9 +4452,6 @@
 
   // optional bool deprecated = 3 [default = false];
   bool has_deprecated() const;
-  private:
-  bool _internal_has_deprecated() const;
-  public:
   void clear_deprecated();
   bool deprecated() const;
   void set_deprecated(bool value);
@@ -4602,9 +4462,6 @@
 
   // optional bool map_entry = 7;
   bool has_map_entry() const;
-  private:
-  bool _internal_has_map_entry() const;
-  public:
   void clear_map_entry();
   bool map_entry() const;
   void set_map_entry(bool value);
@@ -4823,8 +4680,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT FieldOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldOptions) */ {
@@ -4922,10 +4778,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -4936,7 +4792,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.FieldOptions";
   }
   protected:
@@ -4951,67 +4807,45 @@
 
   // nested types ----------------------------------------------------
 
-  typedef FieldOptions_CType CType;
-  static constexpr CType STRING =
-    FieldOptions_CType_STRING;
-  static constexpr CType CORD =
-    FieldOptions_CType_CORD;
-  static constexpr CType STRING_PIECE =
-    FieldOptions_CType_STRING_PIECE;
+  using CType = FieldOptions_CType;
+  static constexpr CType STRING = FieldOptions_CType_STRING;
+  static constexpr CType CORD = FieldOptions_CType_CORD;
+  static constexpr CType STRING_PIECE = FieldOptions_CType_STRING_PIECE;
   static inline bool CType_IsValid(int value) {
     return FieldOptions_CType_IsValid(value);
   }
-  static constexpr CType CType_MIN =
-    FieldOptions_CType_CType_MIN;
-  static constexpr CType CType_MAX =
-    FieldOptions_CType_CType_MAX;
-  static constexpr int CType_ARRAYSIZE =
-    FieldOptions_CType_CType_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  CType_descriptor() {
+  static constexpr CType CType_MIN = FieldOptions_CType_CType_MIN;
+  static constexpr CType CType_MAX = FieldOptions_CType_CType_MAX;
+  static constexpr int CType_ARRAYSIZE = FieldOptions_CType_CType_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* CType_descriptor() {
     return FieldOptions_CType_descriptor();
   }
-  template<typename T>
-  static inline const std::string& CType_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, CType>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function CType_Name.");
-    return FieldOptions_CType_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& CType_Name(T value) {
+    return FieldOptions_CType_Name(value);
   }
-  static inline bool CType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      CType* value) {
+  static inline bool CType_Parse(absl::string_view name, CType* value) {
     return FieldOptions_CType_Parse(name, value);
   }
 
-  typedef FieldOptions_JSType JSType;
-  static constexpr JSType JS_NORMAL =
-    FieldOptions_JSType_JS_NORMAL;
-  static constexpr JSType JS_STRING =
-    FieldOptions_JSType_JS_STRING;
-  static constexpr JSType JS_NUMBER =
-    FieldOptions_JSType_JS_NUMBER;
+  using JSType = FieldOptions_JSType;
+  static constexpr JSType JS_NORMAL = FieldOptions_JSType_JS_NORMAL;
+  static constexpr JSType JS_STRING = FieldOptions_JSType_JS_STRING;
+  static constexpr JSType JS_NUMBER = FieldOptions_JSType_JS_NUMBER;
   static inline bool JSType_IsValid(int value) {
     return FieldOptions_JSType_IsValid(value);
   }
-  static constexpr JSType JSType_MIN =
-    FieldOptions_JSType_JSType_MIN;
-  static constexpr JSType JSType_MAX =
-    FieldOptions_JSType_JSType_MAX;
-  static constexpr int JSType_ARRAYSIZE =
-    FieldOptions_JSType_JSType_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  JSType_descriptor() {
+  static constexpr JSType JSType_MIN = FieldOptions_JSType_JSType_MIN;
+  static constexpr JSType JSType_MAX = FieldOptions_JSType_JSType_MAX;
+  static constexpr int JSType_ARRAYSIZE = FieldOptions_JSType_JSType_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* JSType_descriptor() {
     return FieldOptions_JSType_descriptor();
   }
-  template<typename T>
-  static inline const std::string& JSType_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, JSType>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function JSType_Name.");
-    return FieldOptions_JSType_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& JSType_Name(T value) {
+    return FieldOptions_JSType_Name(value);
   }
-  static inline bool JSType_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      JSType* value) {
+  static inline bool JSType_Parse(absl::string_view name, JSType* value) {
     return FieldOptions_JSType_Parse(name, value);
   }
 
@@ -5047,9 +4881,6 @@
 
   // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
   bool has_ctype() const;
-  private:
-  bool _internal_has_ctype() const;
-  public:
   void clear_ctype();
   ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType ctype() const;
   void set_ctype(::PROTOBUF_NAMESPACE_ID::FieldOptions_CType value);
@@ -5060,9 +4891,6 @@
 
   // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
   bool has_jstype() const;
-  private:
-  bool _internal_has_jstype() const;
-  public:
   void clear_jstype();
   ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType jstype() const;
   void set_jstype(::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType value);
@@ -5073,9 +4901,6 @@
 
   // optional bool packed = 2;
   bool has_packed() const;
-  private:
-  bool _internal_has_packed() const;
-  public:
   void clear_packed();
   bool packed() const;
   void set_packed(bool value);
@@ -5086,9 +4911,6 @@
 
   // optional bool lazy = 5 [default = false];
   bool has_lazy() const;
-  private:
-  bool _internal_has_lazy() const;
-  public:
   void clear_lazy();
   bool lazy() const;
   void set_lazy(bool value);
@@ -5099,9 +4921,6 @@
 
   // optional bool unverified_lazy = 15 [default = false];
   bool has_unverified_lazy() const;
-  private:
-  bool _internal_has_unverified_lazy() const;
-  public:
   void clear_unverified_lazy();
   bool unverified_lazy() const;
   void set_unverified_lazy(bool value);
@@ -5112,9 +4931,6 @@
 
   // optional bool deprecated = 3 [default = false];
   bool has_deprecated() const;
-  private:
-  bool _internal_has_deprecated() const;
-  public:
   void clear_deprecated();
   bool deprecated() const;
   void set_deprecated(bool value);
@@ -5125,9 +4941,6 @@
 
   // optional bool weak = 10 [default = false];
   bool has_weak() const;
-  private:
-  bool _internal_has_weak() const;
-  public:
   void clear_weak();
   bool weak() const;
   void set_weak(bool value);
@@ -5349,8 +5162,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT OneofOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.OneofOptions) */ {
@@ -5448,10 +5260,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -5462,7 +5274,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.OneofOptions";
   }
   protected:
@@ -5705,8 +5517,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT EnumOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumOptions) */ {
@@ -5804,10 +5615,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -5818,7 +5629,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.EnumOptions";
   }
   protected:
@@ -5860,9 +5671,6 @@
 
   // optional bool allow_alias = 2;
   bool has_allow_alias() const;
-  private:
-  bool _internal_has_allow_alias() const;
-  public:
   void clear_allow_alias();
   bool allow_alias() const;
   void set_allow_alias(bool value);
@@ -5873,9 +5681,6 @@
 
   // optional bool deprecated = 3 [default = false];
   bool has_deprecated() const;
-  private:
-  bool _internal_has_deprecated() const;
-  public:
   void clear_deprecated();
   bool deprecated() const;
   void set_deprecated(bool value);
@@ -6092,8 +5897,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT EnumValueOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValueOptions) */ {
@@ -6191,10 +5995,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -6205,7 +6009,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.EnumValueOptions";
   }
   protected:
@@ -6246,9 +6050,6 @@
 
   // optional bool deprecated = 1 [default = false];
   bool has_deprecated() const;
-  private:
-  bool _internal_has_deprecated() const;
-  public:
   void clear_deprecated();
   bool deprecated() const;
   void set_deprecated(bool value);
@@ -6464,8 +6265,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT ServiceOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ServiceOptions) */ {
@@ -6563,10 +6363,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -6577,7 +6377,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.ServiceOptions";
   }
   protected:
@@ -6618,9 +6418,6 @@
 
   // optional bool deprecated = 33 [default = false];
   bool has_deprecated() const;
-  private:
-  bool _internal_has_deprecated() const;
-  public:
   void clear_deprecated();
   bool deprecated() const;
   void set_deprecated(bool value);
@@ -6836,8 +6633,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT MethodOptions final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.MethodOptions) */ {
@@ -6935,10 +6731,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -6949,7 +6745,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.MethodOptions";
   }
   protected:
@@ -6964,35 +6760,24 @@
 
   // nested types ----------------------------------------------------
 
-  typedef MethodOptions_IdempotencyLevel IdempotencyLevel;
-  static constexpr IdempotencyLevel IDEMPOTENCY_UNKNOWN =
-    MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN;
-  static constexpr IdempotencyLevel NO_SIDE_EFFECTS =
-    MethodOptions_IdempotencyLevel_NO_SIDE_EFFECTS;
-  static constexpr IdempotencyLevel IDEMPOTENT =
-    MethodOptions_IdempotencyLevel_IDEMPOTENT;
+  using IdempotencyLevel = MethodOptions_IdempotencyLevel;
+  static constexpr IdempotencyLevel IDEMPOTENCY_UNKNOWN = MethodOptions_IdempotencyLevel_IDEMPOTENCY_UNKNOWN;
+  static constexpr IdempotencyLevel NO_SIDE_EFFECTS = MethodOptions_IdempotencyLevel_NO_SIDE_EFFECTS;
+  static constexpr IdempotencyLevel IDEMPOTENT = MethodOptions_IdempotencyLevel_IDEMPOTENT;
   static inline bool IdempotencyLevel_IsValid(int value) {
     return MethodOptions_IdempotencyLevel_IsValid(value);
   }
-  static constexpr IdempotencyLevel IdempotencyLevel_MIN =
-    MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN;
-  static constexpr IdempotencyLevel IdempotencyLevel_MAX =
-    MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX;
-  static constexpr int IdempotencyLevel_ARRAYSIZE =
-    MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  IdempotencyLevel_descriptor() {
+  static constexpr IdempotencyLevel IdempotencyLevel_MIN = MethodOptions_IdempotencyLevel_IdempotencyLevel_MIN;
+  static constexpr IdempotencyLevel IdempotencyLevel_MAX = MethodOptions_IdempotencyLevel_IdempotencyLevel_MAX;
+  static constexpr int IdempotencyLevel_ARRAYSIZE = MethodOptions_IdempotencyLevel_IdempotencyLevel_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* IdempotencyLevel_descriptor() {
     return MethodOptions_IdempotencyLevel_descriptor();
   }
-  template<typename T>
-  static inline const std::string& IdempotencyLevel_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, IdempotencyLevel>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function IdempotencyLevel_Name.");
-    return MethodOptions_IdempotencyLevel_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& IdempotencyLevel_Name(T value) {
+    return MethodOptions_IdempotencyLevel_Name(value);
   }
-  static inline bool IdempotencyLevel_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      IdempotencyLevel* value) {
+  static inline bool IdempotencyLevel_Parse(absl::string_view name, IdempotencyLevel* value) {
     return MethodOptions_IdempotencyLevel_Parse(name, value);
   }
 
@@ -7023,9 +6808,6 @@
 
   // optional bool deprecated = 33 [default = false];
   bool has_deprecated() const;
-  private:
-  bool _internal_has_deprecated() const;
-  public:
   void clear_deprecated();
   bool deprecated() const;
   void set_deprecated(bool value);
@@ -7036,9 +6818,6 @@
 
   // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];
   bool has_idempotency_level() const;
-  private:
-  bool _internal_has_idempotency_level() const;
-  public:
   void clear_idempotency_level();
   ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel idempotency_level() const;
   void set_idempotency_level(::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel value);
@@ -7255,8 +7034,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT UninterpretedOption_NamePart final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption.NamePart) */ {
@@ -7354,10 +7132,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -7368,7 +7146,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.UninterpretedOption.NamePart";
   }
   protected:
@@ -7391,9 +7169,6 @@
   };
   // required string name_part = 1;
   bool has_name_part() const;
-  private:
-  bool _internal_has_name_part() const;
-  public:
   void clear_name_part();
   const std::string& name_part() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -7409,9 +7184,6 @@
 
   // required bool is_extension = 2;
   bool has_is_extension() const;
-  private:
-  bool _internal_has_is_extension() const;
-  public:
   void clear_is_extension();
   bool is_extension() const;
   void set_is_extension(bool value);
@@ -7425,7 +7197,7 @@
   class _Internal;
 
   // helper for ByteSizeLong()
-  size_t RequiredFieldsByteSizeFallback() const;
+  ::size_t RequiredFieldsByteSizeFallback() const;
 
   template <typename T> friend class ::PROTOBUF_NAMESPACE_ID::Arena::InternalHelper;
   typedef void InternalArenaConstructable_;
@@ -7438,8 +7210,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT UninterpretedOption final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UninterpretedOption) */ {
@@ -7537,10 +7308,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -7551,7 +7322,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.UninterpretedOption";
   }
   protected:
@@ -7599,9 +7370,6 @@
 
   // optional string identifier_value = 3;
   bool has_identifier_value() const;
-  private:
-  bool _internal_has_identifier_value() const;
-  public:
   void clear_identifier_value();
   const std::string& identifier_value() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -7617,9 +7385,6 @@
 
   // optional bytes string_value = 7;
   bool has_string_value() const;
-  private:
-  bool _internal_has_string_value() const;
-  public:
   void clear_string_value();
   const std::string& string_value() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -7635,9 +7400,6 @@
 
   // optional string aggregate_value = 8;
   bool has_aggregate_value() const;
-  private:
-  bool _internal_has_aggregate_value() const;
-  public:
   void clear_aggregate_value();
   const std::string& aggregate_value() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -7653,35 +7415,26 @@
 
   // optional uint64 positive_int_value = 4;
   bool has_positive_int_value() const;
-  private:
-  bool _internal_has_positive_int_value() const;
-  public:
   void clear_positive_int_value();
-  uint64_t positive_int_value() const;
-  void set_positive_int_value(uint64_t value);
+  ::uint64_t positive_int_value() const;
+  void set_positive_int_value(::uint64_t value);
   private:
-  uint64_t _internal_positive_int_value() const;
-  void _internal_set_positive_int_value(uint64_t value);
+  ::uint64_t _internal_positive_int_value() const;
+  void _internal_set_positive_int_value(::uint64_t value);
   public:
 
   // optional int64 negative_int_value = 5;
   bool has_negative_int_value() const;
-  private:
-  bool _internal_has_negative_int_value() const;
-  public:
   void clear_negative_int_value();
-  int64_t negative_int_value() const;
-  void set_negative_int_value(int64_t value);
+  ::int64_t negative_int_value() const;
+  void set_negative_int_value(::int64_t value);
   private:
-  int64_t _internal_negative_int_value() const;
-  void _internal_set_negative_int_value(int64_t value);
+  ::int64_t _internal_negative_int_value() const;
+  void _internal_set_negative_int_value(::int64_t value);
   public:
 
   // optional double double_value = 6;
   bool has_double_value() const;
-  private:
-  bool _internal_has_double_value() const;
-  public:
   void clear_double_value();
   double double_value() const;
   void set_double_value(double value);
@@ -7704,14 +7457,13 @@
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr identifier_value_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr string_value_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr aggregate_value_;
-    uint64_t positive_int_value_;
-    int64_t negative_int_value_;
+    ::uint64_t positive_int_value_;
+    ::int64_t negative_int_value_;
     double double_value_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT SourceCodeInfo_Location final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo.Location) */ {
@@ -7809,10 +7561,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -7823,7 +7575,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.SourceCodeInfo.Location";
   }
   protected:
@@ -7854,19 +7606,19 @@
   public:
   void clear_path();
   private:
-  int32_t _internal_path(int index) const;
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t _internal_path(int index) const;
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       _internal_path() const;
-  void _internal_add_path(int32_t value);
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  void _internal_add_path(::int32_t value);
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       _internal_mutable_path();
   public:
-  int32_t path(int index) const;
-  void set_path(int index, int32_t value);
-  void add_path(int32_t value);
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t path(int index) const;
+  void set_path(int index, ::int32_t value);
+  void add_path(::int32_t value);
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       path() const;
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       mutable_path();
 
   // repeated int32 span = 2 [packed = true];
@@ -7876,19 +7628,19 @@
   public:
   void clear_span();
   private:
-  int32_t _internal_span(int index) const;
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t _internal_span(int index) const;
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       _internal_span() const;
-  void _internal_add_span(int32_t value);
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  void _internal_add_span(::int32_t value);
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       _internal_mutable_span();
   public:
-  int32_t span(int index) const;
-  void set_span(int index, int32_t value);
-  void add_span(int32_t value);
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t span(int index) const;
+  void set_span(int index, ::int32_t value);
+  void add_span(::int32_t value);
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       span() const;
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       mutable_span();
 
   // repeated string leading_detached_comments = 6;
@@ -7902,12 +7654,12 @@
   void set_leading_detached_comments(int index, const std::string& value);
   void set_leading_detached_comments(int index, std::string&& value);
   void set_leading_detached_comments(int index, const char* value);
-  void set_leading_detached_comments(int index, const char* value, size_t size);
+  void set_leading_detached_comments(int index, const char* value, ::size_t size);
   std::string* add_leading_detached_comments();
   void add_leading_detached_comments(const std::string& value);
   void add_leading_detached_comments(std::string&& value);
   void add_leading_detached_comments(const char* value);
-  void add_leading_detached_comments(const char* value, size_t size);
+  void add_leading_detached_comments(const char* value, ::size_t size);
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& leading_detached_comments() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_leading_detached_comments();
   private:
@@ -7917,9 +7669,6 @@
 
   // optional string leading_comments = 3;
   bool has_leading_comments() const;
-  private:
-  bool _internal_has_leading_comments() const;
-  public:
   void clear_leading_comments();
   const std::string& leading_comments() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -7935,9 +7684,6 @@
 
   // optional string trailing_comments = 4;
   bool has_trailing_comments() const;
-  private:
-  bool _internal_has_trailing_comments() const;
-  public:
   void clear_trailing_comments();
   const std::string& trailing_comments() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -7961,18 +7707,17 @@
   struct Impl_ {
     ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
-    ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > path_;
-    mutable std::atomic<int> _path_cached_byte_size_;
-    ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > span_;
-    mutable std::atomic<int> _span_cached_byte_size_;
+    ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t > path_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _path_cached_byte_size_;
+    ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t > span_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _span_cached_byte_size_;
     ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string> leading_detached_comments_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr leading_comments_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr trailing_comments_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT SourceCodeInfo final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceCodeInfo) */ {
@@ -8070,10 +7815,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -8084,7 +7829,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.SourceCodeInfo";
   }
   protected:
@@ -8137,8 +7882,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT GeneratedCodeInfo_Annotation final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo.Annotation) */ {
@@ -8236,10 +7980,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -8250,7 +7994,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.GeneratedCodeInfo.Annotation";
   }
   protected:
@@ -8265,6 +8009,27 @@
 
   // nested types ----------------------------------------------------
 
+  using Semantic = GeneratedCodeInfo_Annotation_Semantic;
+  static constexpr Semantic NONE = GeneratedCodeInfo_Annotation_Semantic_NONE;
+  static constexpr Semantic SET = GeneratedCodeInfo_Annotation_Semantic_SET;
+  static constexpr Semantic ALIAS = GeneratedCodeInfo_Annotation_Semantic_ALIAS;
+  static inline bool Semantic_IsValid(int value) {
+    return GeneratedCodeInfo_Annotation_Semantic_IsValid(value);
+  }
+  static constexpr Semantic Semantic_MIN = GeneratedCodeInfo_Annotation_Semantic_Semantic_MIN;
+  static constexpr Semantic Semantic_MAX = GeneratedCodeInfo_Annotation_Semantic_Semantic_MAX;
+  static constexpr int Semantic_ARRAYSIZE = GeneratedCodeInfo_Annotation_Semantic_Semantic_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Semantic_descriptor() {
+    return GeneratedCodeInfo_Annotation_Semantic_descriptor();
+  }
+  template <typename T>
+  static inline const std::string& Semantic_Name(T value) {
+    return GeneratedCodeInfo_Annotation_Semantic_Name(value);
+  }
+  static inline bool Semantic_Parse(absl::string_view name, Semantic* value) {
+    return GeneratedCodeInfo_Annotation_Semantic_Parse(name, value);
+  }
+
   // accessors -------------------------------------------------------
 
   enum : int {
@@ -8272,6 +8037,7 @@
     kSourceFileFieldNumber = 2,
     kBeginFieldNumber = 3,
     kEndFieldNumber = 4,
+    kSemanticFieldNumber = 5,
   };
   // repeated int32 path = 1 [packed = true];
   int path_size() const;
@@ -8280,26 +8046,23 @@
   public:
   void clear_path();
   private:
-  int32_t _internal_path(int index) const;
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t _internal_path(int index) const;
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       _internal_path() const;
-  void _internal_add_path(int32_t value);
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  void _internal_add_path(::int32_t value);
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       _internal_mutable_path();
   public:
-  int32_t path(int index) const;
-  void set_path(int index, int32_t value);
-  void add_path(int32_t value);
-  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+  ::int32_t path(int index) const;
+  void set_path(int index, ::int32_t value);
+  void add_path(::int32_t value);
+  const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
       path() const;
-  ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+  ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
       mutable_path();
 
   // optional string source_file = 2;
   bool has_source_file() const;
-  private:
-  bool _internal_has_source_file() const;
-  public:
   void clear_source_file();
   const std::string& source_file() const;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -8315,28 +8078,32 @@
 
   // optional int32 begin = 3;
   bool has_begin() const;
-  private:
-  bool _internal_has_begin() const;
-  public:
   void clear_begin();
-  int32_t begin() const;
-  void set_begin(int32_t value);
+  ::int32_t begin() const;
+  void set_begin(::int32_t value);
   private:
-  int32_t _internal_begin() const;
-  void _internal_set_begin(int32_t value);
+  ::int32_t _internal_begin() const;
+  void _internal_set_begin(::int32_t value);
   public:
 
   // optional int32 end = 4;
   bool has_end() const;
-  private:
-  bool _internal_has_end() const;
-  public:
   void clear_end();
-  int32_t end() const;
-  void set_end(int32_t value);
+  ::int32_t end() const;
+  void set_end(::int32_t value);
   private:
-  int32_t _internal_end() const;
-  void _internal_set_end(int32_t value);
+  ::int32_t _internal_end() const;
+  void _internal_set_end(::int32_t value);
+  public:
+
+  // optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
+  bool has_semantic() const;
+  void clear_semantic();
+  ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic semantic() const;
+  void set_semantic(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic value);
+  private:
+  ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic _internal_semantic() const;
+  void _internal_set_semantic(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.GeneratedCodeInfo.Annotation)
@@ -8349,16 +8116,16 @@
   struct Impl_ {
     ::PROTOBUF_NAMESPACE_ID::internal::HasBits<1> _has_bits_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
-    ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t > path_;
-    mutable std::atomic<int> _path_cached_byte_size_;
+    ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t > path_;
+    mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _path_cached_byte_size_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr source_file_;
-    int32_t begin_;
-    int32_t end_;
+    ::int32_t begin_;
+    ::int32_t end_;
+    int semantic_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fdescriptor_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT GeneratedCodeInfo final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.GeneratedCodeInfo) */ {
@@ -8456,10 +8223,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -8470,7 +8237,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.GeneratedCodeInfo";
   }
   protected:
@@ -8527,12 +8294,17 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // FileDescriptorSet
 
 // repeated .google.protobuf.FileDescriptorProto file = 1;
@@ -8580,13 +8352,10 @@
 // FileDescriptorProto
 
 // optional string name = 1;
-inline bool FileDescriptorProto::_internal_has_name() const {
+inline bool FileDescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool FileDescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void FileDescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -8620,15 +8389,13 @@
 }
 inline std::string* FileDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -8648,13 +8415,10 @@
 }
 
 // optional string package = 2;
-inline bool FileDescriptorProto::_internal_has_package() const {
+inline bool FileDescriptorProto::has_package() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool FileDescriptorProto::has_package() const {
-  return _internal_has_package();
-}
 inline void FileDescriptorProto::clear_package() {
   _impl_.package_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -8688,15 +8452,13 @@
 }
 inline std::string* FileDescriptorProto::release_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.package)
-  if (!_internal_has_package()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000002u;
   auto* p = _impl_.package_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.package_.IsDefault()) {
-    _impl_.package_.Set("", GetArenaForAllocation());
-  }
+  _impl_.package_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -8750,11 +8512,10 @@
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.dependency)
 }
 inline void FileDescriptorProto::set_dependency(int index, const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.dependency_.Mutable(index)->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.dependency_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.FileDescriptorProto.dependency)
 }
-inline void FileDescriptorProto::set_dependency(int index, const char* value, size_t size) {
+inline void FileDescriptorProto::set_dependency(int index, const char* value, ::size_t size) {
   _impl_.dependency_.Mutable(index)->assign(
     reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.FileDescriptorProto.dependency)
@@ -8771,11 +8532,10 @@
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.dependency)
 }
 inline void FileDescriptorProto::add_dependency(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.dependency_.Add()->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.dependency_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.FileDescriptorProto.dependency)
 }
-inline void FileDescriptorProto::add_dependency(const char* value, size_t size) {
+inline void FileDescriptorProto::add_dependency(const char* value, ::size_t size) {
   _impl_.dependency_.Add()->assign(reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_add_pointer:google.protobuf.FileDescriptorProto.dependency)
 }
@@ -8800,38 +8560,38 @@
 inline void FileDescriptorProto::clear_public_dependency() {
   _impl_.public_dependency_.Clear();
 }
-inline int32_t FileDescriptorProto::_internal_public_dependency(int index) const {
+inline ::int32_t FileDescriptorProto::_internal_public_dependency(int index) const {
   return _impl_.public_dependency_.Get(index);
 }
-inline int32_t FileDescriptorProto::public_dependency(int index) const {
+inline ::int32_t FileDescriptorProto::public_dependency(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.public_dependency)
   return _internal_public_dependency(index);
 }
-inline void FileDescriptorProto::set_public_dependency(int index, int32_t value) {
+inline void FileDescriptorProto::set_public_dependency(int index, ::int32_t value) {
   _impl_.public_dependency_.Set(index, value);
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.public_dependency)
 }
-inline void FileDescriptorProto::_internal_add_public_dependency(int32_t value) {
+inline void FileDescriptorProto::_internal_add_public_dependency(::int32_t value) {
   _impl_.public_dependency_.Add(value);
 }
-inline void FileDescriptorProto::add_public_dependency(int32_t value) {
+inline void FileDescriptorProto::add_public_dependency(::int32_t value) {
   _internal_add_public_dependency(value);
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.public_dependency)
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 FileDescriptorProto::_internal_public_dependency() const {
   return _impl_.public_dependency_;
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 FileDescriptorProto::public_dependency() const {
   // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.public_dependency)
   return _internal_public_dependency();
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 FileDescriptorProto::_internal_mutable_public_dependency() {
   return &_impl_.public_dependency_;
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 FileDescriptorProto::mutable_public_dependency() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.public_dependency)
   return _internal_mutable_public_dependency();
@@ -8847,38 +8607,38 @@
 inline void FileDescriptorProto::clear_weak_dependency() {
   _impl_.weak_dependency_.Clear();
 }
-inline int32_t FileDescriptorProto::_internal_weak_dependency(int index) const {
+inline ::int32_t FileDescriptorProto::_internal_weak_dependency(int index) const {
   return _impl_.weak_dependency_.Get(index);
 }
-inline int32_t FileDescriptorProto::weak_dependency(int index) const {
+inline ::int32_t FileDescriptorProto::weak_dependency(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.weak_dependency)
   return _internal_weak_dependency(index);
 }
-inline void FileDescriptorProto::set_weak_dependency(int index, int32_t value) {
+inline void FileDescriptorProto::set_weak_dependency(int index, ::int32_t value) {
   _impl_.weak_dependency_.Set(index, value);
   // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.weak_dependency)
 }
-inline void FileDescriptorProto::_internal_add_weak_dependency(int32_t value) {
+inline void FileDescriptorProto::_internal_add_weak_dependency(::int32_t value) {
   _impl_.weak_dependency_.Add(value);
 }
-inline void FileDescriptorProto::add_weak_dependency(int32_t value) {
+inline void FileDescriptorProto::add_weak_dependency(::int32_t value) {
   _internal_add_weak_dependency(value);
   // @@protoc_insertion_point(field_add:google.protobuf.FileDescriptorProto.weak_dependency)
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 FileDescriptorProto::_internal_weak_dependency() const {
   return _impl_.weak_dependency_;
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 FileDescriptorProto::weak_dependency() const {
   // @@protoc_insertion_point(field_list:google.protobuf.FileDescriptorProto.weak_dependency)
   return _internal_weak_dependency();
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 FileDescriptorProto::_internal_mutable_weak_dependency() {
   return &_impl_.weak_dependency_;
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 FileDescriptorProto::mutable_weak_dependency() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.FileDescriptorProto.weak_dependency)
   return _internal_mutable_weak_dependency();
@@ -9045,17 +8805,14 @@
 }
 
 // optional .google.protobuf.FileOptions options = 8;
-inline bool FileDescriptorProto::_internal_has_options() const {
-  bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
+inline bool FileDescriptorProto::has_options() const {
+  bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool FileDescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void FileDescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
-  _impl_._has_bits_[0] &= ~0x00000008u;
+  _impl_._has_bits_[0] &= ~0x00000010u;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::FileOptions& FileDescriptorProto::_internal_options() const {
   const ::PROTOBUF_NAMESPACE_ID::FileOptions* p = _impl_.options_;
@@ -9073,14 +8830,14 @@
   }
   _impl_.options_ = options;
   if (options) {
-    _impl_._has_bits_[0] |= 0x00000008u;
+    _impl_._has_bits_[0] |= 0x00000010u;
   } else {
-    _impl_._has_bits_[0] &= ~0x00000008u;
+    _impl_._has_bits_[0] &= ~0x00000010u;
   }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.options)
 }
 inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::release_options() {
-  _impl_._has_bits_[0] &= ~0x00000008u;
+  _impl_._has_bits_[0] &= ~0x00000010u;
   ::PROTOBUF_NAMESPACE_ID::FileOptions* temp = _impl_.options_;
   _impl_.options_ = nullptr;
 #ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
@@ -9096,13 +8853,13 @@
 }
 inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::unsafe_arena_release_options() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.options)
-  _impl_._has_bits_[0] &= ~0x00000008u;
+  _impl_._has_bits_[0] &= ~0x00000010u;
   ::PROTOBUF_NAMESPACE_ID::FileOptions* temp = _impl_.options_;
   _impl_.options_ = nullptr;
   return temp;
 }
 inline ::PROTOBUF_NAMESPACE_ID::FileOptions* FileDescriptorProto::_internal_mutable_options() {
-  _impl_._has_bits_[0] |= 0x00000008u;
+  _impl_._has_bits_[0] |= 0x00000010u;
   if (_impl_.options_ == nullptr) {
     auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FileOptions>(GetArenaForAllocation());
     _impl_.options_ = p;
@@ -9126,26 +8883,23 @@
       options = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, options, submessage_arena);
     }
-    _impl_._has_bits_[0] |= 0x00000008u;
+    _impl_._has_bits_[0] |= 0x00000010u;
   } else {
-    _impl_._has_bits_[0] &= ~0x00000008u;
+    _impl_._has_bits_[0] &= ~0x00000010u;
   }
   _impl_.options_ = options;
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.options)
 }
 
 // optional .google.protobuf.SourceCodeInfo source_code_info = 9;
-inline bool FileDescriptorProto::_internal_has_source_code_info() const {
-  bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
+inline bool FileDescriptorProto::has_source_code_info() const {
+  bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.source_code_info_ != nullptr);
   return value;
 }
-inline bool FileDescriptorProto::has_source_code_info() const {
-  return _internal_has_source_code_info();
-}
 inline void FileDescriptorProto::clear_source_code_info() {
   if (_impl_.source_code_info_ != nullptr) _impl_.source_code_info_->Clear();
-  _impl_._has_bits_[0] &= ~0x00000010u;
+  _impl_._has_bits_[0] &= ~0x00000020u;
 }
 inline const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo& FileDescriptorProto::_internal_source_code_info() const {
   const ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* p = _impl_.source_code_info_;
@@ -9163,14 +8917,14 @@
   }
   _impl_.source_code_info_ = source_code_info;
   if (source_code_info) {
-    _impl_._has_bits_[0] |= 0x00000010u;
+    _impl_._has_bits_[0] |= 0x00000020u;
   } else {
-    _impl_._has_bits_[0] &= ~0x00000010u;
+    _impl_._has_bits_[0] &= ~0x00000020u;
   }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
 }
 inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::release_source_code_info() {
-  _impl_._has_bits_[0] &= ~0x00000010u;
+  _impl_._has_bits_[0] &= ~0x00000020u;
   ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = _impl_.source_code_info_;
   _impl_.source_code_info_ = nullptr;
 #ifdef PROTOBUF_FORCE_COPY_IN_RELEASE
@@ -9186,13 +8940,13 @@
 }
 inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::unsafe_arena_release_source_code_info() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.source_code_info)
-  _impl_._has_bits_[0] &= ~0x00000010u;
+  _impl_._has_bits_[0] &= ~0x00000020u;
   ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* temp = _impl_.source_code_info_;
   _impl_.source_code_info_ = nullptr;
   return temp;
 }
 inline ::PROTOBUF_NAMESPACE_ID::SourceCodeInfo* FileDescriptorProto::_internal_mutable_source_code_info() {
-  _impl_._has_bits_[0] |= 0x00000010u;
+  _impl_._has_bits_[0] |= 0x00000020u;
   if (_impl_.source_code_info_ == nullptr) {
     auto* p = CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceCodeInfo>(GetArenaForAllocation());
     _impl_.source_code_info_ = p;
@@ -9216,22 +8970,19 @@
       source_code_info = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_code_info, submessage_arena);
     }
-    _impl_._has_bits_[0] |= 0x00000010u;
+    _impl_._has_bits_[0] |= 0x00000020u;
   } else {
-    _impl_._has_bits_[0] &= ~0x00000010u;
+    _impl_._has_bits_[0] &= ~0x00000020u;
   }
   _impl_.source_code_info_ = source_code_info;
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.source_code_info)
 }
 
 // optional string syntax = 12;
-inline bool FileDescriptorProto::_internal_has_syntax() const {
+inline bool FileDescriptorProto::has_syntax() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool FileDescriptorProto::has_syntax() const {
-  return _internal_has_syntax();
-}
 inline void FileDescriptorProto::clear_syntax() {
   _impl_.syntax_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -9265,15 +9016,13 @@
 }
 inline std::string* FileDescriptorProto::release_syntax() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.syntax)
-  if (!_internal_has_syntax()) {
+  if ((_impl_._has_bits_[0] & 0x00000004u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000004u;
   auto* p = _impl_.syntax_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.syntax_.IsDefault()) {
-    _impl_.syntax_.Set("", GetArenaForAllocation());
-  }
+  _impl_.syntax_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -9292,75 +9041,129 @@
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.syntax)
 }
 
+// optional string edition = 13;
+inline bool FileDescriptorProto::has_edition() const {
+  bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
+  return value;
+}
+inline void FileDescriptorProto::clear_edition() {
+  _impl_.edition_.ClearToEmpty();
+  _impl_._has_bits_[0] &= ~0x00000008u;
+}
+inline const std::string& FileDescriptorProto::edition() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.FileDescriptorProto.edition)
+  return _internal_edition();
+}
+template <typename ArgT0, typename... ArgT>
+inline PROTOBUF_ALWAYS_INLINE
+void FileDescriptorProto::set_edition(ArgT0&& arg0, ArgT... args) {
+ _impl_._has_bits_[0] |= 0x00000008u;
+ _impl_.edition_.Set(static_cast<ArgT0 &&>(arg0), args..., GetArenaForAllocation());
+  // @@protoc_insertion_point(field_set:google.protobuf.FileDescriptorProto.edition)
+}
+inline std::string* FileDescriptorProto::mutable_edition() {
+  std::string* _s = _internal_mutable_edition();
+  // @@protoc_insertion_point(field_mutable:google.protobuf.FileDescriptorProto.edition)
+  return _s;
+}
+inline const std::string& FileDescriptorProto::_internal_edition() const {
+  return _impl_.edition_.Get();
+}
+inline void FileDescriptorProto::_internal_set_edition(const std::string& value) {
+  _impl_._has_bits_[0] |= 0x00000008u;
+  _impl_.edition_.Set(value, GetArenaForAllocation());
+}
+inline std::string* FileDescriptorProto::_internal_mutable_edition() {
+  _impl_._has_bits_[0] |= 0x00000008u;
+  return _impl_.edition_.Mutable(GetArenaForAllocation());
+}
+inline std::string* FileDescriptorProto::release_edition() {
+  // @@protoc_insertion_point(field_release:google.protobuf.FileDescriptorProto.edition)
+  if ((_impl_._has_bits_[0] & 0x00000008u) == 0) {
+    return nullptr;
+  }
+  _impl_._has_bits_[0] &= ~0x00000008u;
+  auto* p = _impl_.edition_.Release();
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  _impl_.edition_.Set("", GetArenaForAllocation());
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  return p;
+}
+inline void FileDescriptorProto::set_allocated_edition(std::string* edition) {
+  if (edition != nullptr) {
+    _impl_._has_bits_[0] |= 0x00000008u;
+  } else {
+    _impl_._has_bits_[0] &= ~0x00000008u;
+  }
+  _impl_.edition_.SetAllocated(edition, GetArenaForAllocation());
+#ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  if (_impl_.edition_.IsDefault()) {
+    _impl_.edition_.Set("", GetArenaForAllocation());
+  }
+#endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
+  // @@protoc_insertion_point(field_set_allocated:google.protobuf.FileDescriptorProto.edition)
+}
+
 // -------------------------------------------------------------------
 
 // DescriptorProto_ExtensionRange
 
 // optional int32 start = 1;
-inline bool DescriptorProto_ExtensionRange::_internal_has_start() const {
+inline bool DescriptorProto_ExtensionRange::has_start() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool DescriptorProto_ExtensionRange::has_start() const {
-  return _internal_has_start();
-}
 inline void DescriptorProto_ExtensionRange::clear_start() {
   _impl_.start_ = 0;
   _impl_._has_bits_[0] &= ~0x00000002u;
 }
-inline int32_t DescriptorProto_ExtensionRange::_internal_start() const {
+inline ::int32_t DescriptorProto_ExtensionRange::_internal_start() const {
   return _impl_.start_;
 }
-inline int32_t DescriptorProto_ExtensionRange::start() const {
+inline ::int32_t DescriptorProto_ExtensionRange::start() const {
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.start)
   return _internal_start();
 }
-inline void DescriptorProto_ExtensionRange::_internal_set_start(int32_t value) {
+inline void DescriptorProto_ExtensionRange::_internal_set_start(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000002u;
   _impl_.start_ = value;
 }
-inline void DescriptorProto_ExtensionRange::set_start(int32_t value) {
+inline void DescriptorProto_ExtensionRange::set_start(::int32_t value) {
   _internal_set_start(value);
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.start)
 }
 
 // optional int32 end = 2;
-inline bool DescriptorProto_ExtensionRange::_internal_has_end() const {
+inline bool DescriptorProto_ExtensionRange::has_end() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool DescriptorProto_ExtensionRange::has_end() const {
-  return _internal_has_end();
-}
 inline void DescriptorProto_ExtensionRange::clear_end() {
   _impl_.end_ = 0;
   _impl_._has_bits_[0] &= ~0x00000004u;
 }
-inline int32_t DescriptorProto_ExtensionRange::_internal_end() const {
+inline ::int32_t DescriptorProto_ExtensionRange::_internal_end() const {
   return _impl_.end_;
 }
-inline int32_t DescriptorProto_ExtensionRange::end() const {
+inline ::int32_t DescriptorProto_ExtensionRange::end() const {
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ExtensionRange.end)
   return _internal_end();
 }
-inline void DescriptorProto_ExtensionRange::_internal_set_end(int32_t value) {
+inline void DescriptorProto_ExtensionRange::_internal_set_end(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000004u;
   _impl_.end_ = value;
 }
-inline void DescriptorProto_ExtensionRange::set_end(int32_t value) {
+inline void DescriptorProto_ExtensionRange::set_end(::int32_t value) {
   _internal_set_end(value);
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ExtensionRange.end)
 }
 
 // optional .google.protobuf.ExtensionRangeOptions options = 3;
-inline bool DescriptorProto_ExtensionRange::_internal_has_options() const {
+inline bool DescriptorProto_ExtensionRange::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool DescriptorProto_ExtensionRange::has_options() const {
-  return _internal_has_options();
-}
 inline void DescriptorProto_ExtensionRange::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -9447,57 +9250,51 @@
 // DescriptorProto_ReservedRange
 
 // optional int32 start = 1;
-inline bool DescriptorProto_ReservedRange::_internal_has_start() const {
+inline bool DescriptorProto_ReservedRange::has_start() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool DescriptorProto_ReservedRange::has_start() const {
-  return _internal_has_start();
-}
 inline void DescriptorProto_ReservedRange::clear_start() {
   _impl_.start_ = 0;
   _impl_._has_bits_[0] &= ~0x00000001u;
 }
-inline int32_t DescriptorProto_ReservedRange::_internal_start() const {
+inline ::int32_t DescriptorProto_ReservedRange::_internal_start() const {
   return _impl_.start_;
 }
-inline int32_t DescriptorProto_ReservedRange::start() const {
+inline ::int32_t DescriptorProto_ReservedRange::start() const {
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.start)
   return _internal_start();
 }
-inline void DescriptorProto_ReservedRange::_internal_set_start(int32_t value) {
+inline void DescriptorProto_ReservedRange::_internal_set_start(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000001u;
   _impl_.start_ = value;
 }
-inline void DescriptorProto_ReservedRange::set_start(int32_t value) {
+inline void DescriptorProto_ReservedRange::set_start(::int32_t value) {
   _internal_set_start(value);
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.start)
 }
 
 // optional int32 end = 2;
-inline bool DescriptorProto_ReservedRange::_internal_has_end() const {
+inline bool DescriptorProto_ReservedRange::has_end() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool DescriptorProto_ReservedRange::has_end() const {
-  return _internal_has_end();
-}
 inline void DescriptorProto_ReservedRange::clear_end() {
   _impl_.end_ = 0;
   _impl_._has_bits_[0] &= ~0x00000002u;
 }
-inline int32_t DescriptorProto_ReservedRange::_internal_end() const {
+inline ::int32_t DescriptorProto_ReservedRange::_internal_end() const {
   return _impl_.end_;
 }
-inline int32_t DescriptorProto_ReservedRange::end() const {
+inline ::int32_t DescriptorProto_ReservedRange::end() const {
   // @@protoc_insertion_point(field_get:google.protobuf.DescriptorProto.ReservedRange.end)
   return _internal_end();
 }
-inline void DescriptorProto_ReservedRange::_internal_set_end(int32_t value) {
+inline void DescriptorProto_ReservedRange::_internal_set_end(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000002u;
   _impl_.end_ = value;
 }
-inline void DescriptorProto_ReservedRange::set_end(int32_t value) {
+inline void DescriptorProto_ReservedRange::set_end(::int32_t value) {
   _internal_set_end(value);
   // @@protoc_insertion_point(field_set:google.protobuf.DescriptorProto.ReservedRange.end)
 }
@@ -9507,13 +9304,10 @@
 // DescriptorProto
 
 // optional string name = 1;
-inline bool DescriptorProto::_internal_has_name() const {
+inline bool DescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool DescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void DescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -9547,15 +9341,13 @@
 }
 inline std::string* DescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.DescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -9815,14 +9607,11 @@
 }
 
 // optional .google.protobuf.MessageOptions options = 7;
-inline bool DescriptorProto::_internal_has_options() const {
+inline bool DescriptorProto::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool DescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void DescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -9979,11 +9768,10 @@
   // @@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);
-  _impl_.reserved_name_.Mutable(index)->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.reserved_name_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.DescriptorProto.reserved_name)
 }
-inline void DescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+inline void DescriptorProto::set_reserved_name(int index, const char* value, ::size_t size) {
   _impl_.reserved_name_.Mutable(index)->assign(
     reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.DescriptorProto.reserved_name)
@@ -10000,11 +9788,10 @@
   // @@protoc_insertion_point(field_add:google.protobuf.DescriptorProto.reserved_name)
 }
 inline void DescriptorProto::add_reserved_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.reserved_name_.Add()->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.reserved_name_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.DescriptorProto.reserved_name)
 }
-inline void DescriptorProto::add_reserved_name(const char* value, size_t size) {
+inline void DescriptorProto::add_reserved_name(const char* value, ::size_t size) {
   _impl_.reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_add_pointer:google.protobuf.DescriptorProto.reserved_name)
 }
@@ -10068,13 +9855,10 @@
 // FieldDescriptorProto
 
 // optional string name = 1;
-inline bool FieldDescriptorProto::_internal_has_name() const {
+inline bool FieldDescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void FieldDescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -10108,15 +9892,13 @@
 }
 inline std::string* FieldDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -10136,41 +9918,35 @@
 }
 
 // optional int32 number = 3;
-inline bool FieldDescriptorProto::_internal_has_number() const {
+inline bool FieldDescriptorProto::has_number() const {
   bool value = (_impl_._has_bits_[0] & 0x00000040u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_number() const {
-  return _internal_has_number();
-}
 inline void FieldDescriptorProto::clear_number() {
   _impl_.number_ = 0;
   _impl_._has_bits_[0] &= ~0x00000040u;
 }
-inline int32_t FieldDescriptorProto::_internal_number() const {
+inline ::int32_t FieldDescriptorProto::_internal_number() const {
   return _impl_.number_;
 }
-inline int32_t FieldDescriptorProto::number() const {
+inline ::int32_t FieldDescriptorProto::number() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.number)
   return _internal_number();
 }
-inline void FieldDescriptorProto::_internal_set_number(int32_t value) {
+inline void FieldDescriptorProto::_internal_set_number(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000040u;
   _impl_.number_ = value;
 }
-inline void FieldDescriptorProto::set_number(int32_t value) {
+inline void FieldDescriptorProto::set_number(::int32_t value) {
   _internal_set_number(value);
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.number)
 }
 
 // optional .google.protobuf.FieldDescriptorProto.Label label = 4;
-inline bool FieldDescriptorProto::_internal_has_label() const {
+inline bool FieldDescriptorProto::has_label() const {
   bool value = (_impl_._has_bits_[0] & 0x00000200u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_label() const {
-  return _internal_has_label();
-}
 inline void FieldDescriptorProto::clear_label() {
   _impl_.label_ = 1;
   _impl_._has_bits_[0] &= ~0x00000200u;
@@ -10193,13 +9969,10 @@
 }
 
 // optional .google.protobuf.FieldDescriptorProto.Type type = 5;
-inline bool FieldDescriptorProto::_internal_has_type() const {
+inline bool FieldDescriptorProto::has_type() const {
   bool value = (_impl_._has_bits_[0] & 0x00000400u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_type() const {
-  return _internal_has_type();
-}
 inline void FieldDescriptorProto::clear_type() {
   _impl_.type_ = 1;
   _impl_._has_bits_[0] &= ~0x00000400u;
@@ -10222,13 +9995,10 @@
 }
 
 // optional string type_name = 6;
-inline bool FieldDescriptorProto::_internal_has_type_name() const {
+inline bool FieldDescriptorProto::has_type_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_type_name() const {
-  return _internal_has_type_name();
-}
 inline void FieldDescriptorProto::clear_type_name() {
   _impl_.type_name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -10262,15 +10032,13 @@
 }
 inline std::string* FieldDescriptorProto::release_type_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.type_name)
-  if (!_internal_has_type_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000004u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000004u;
   auto* p = _impl_.type_name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.type_name_.IsDefault()) {
-    _impl_.type_name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.type_name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -10290,13 +10058,10 @@
 }
 
 // optional string extendee = 2;
-inline bool FieldDescriptorProto::_internal_has_extendee() const {
+inline bool FieldDescriptorProto::has_extendee() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_extendee() const {
-  return _internal_has_extendee();
-}
 inline void FieldDescriptorProto::clear_extendee() {
   _impl_.extendee_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -10330,15 +10095,13 @@
 }
 inline std::string* FieldDescriptorProto::release_extendee() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.extendee)
-  if (!_internal_has_extendee()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000002u;
   auto* p = _impl_.extendee_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.extendee_.IsDefault()) {
-    _impl_.extendee_.Set("", GetArenaForAllocation());
-  }
+  _impl_.extendee_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -10358,13 +10121,10 @@
 }
 
 // optional string default_value = 7;
-inline bool FieldDescriptorProto::_internal_has_default_value() const {
+inline bool FieldDescriptorProto::has_default_value() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_default_value() const {
-  return _internal_has_default_value();
-}
 inline void FieldDescriptorProto::clear_default_value() {
   _impl_.default_value_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000008u;
@@ -10398,15 +10158,13 @@
 }
 inline std::string* FieldDescriptorProto::release_default_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.default_value)
-  if (!_internal_has_default_value()) {
+  if ((_impl_._has_bits_[0] & 0x00000008u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000008u;
   auto* p = _impl_.default_value_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.default_value_.IsDefault()) {
-    _impl_.default_value_.Set("", GetArenaForAllocation());
-  }
+  _impl_.default_value_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -10426,41 +10184,35 @@
 }
 
 // optional int32 oneof_index = 9;
-inline bool FieldDescriptorProto::_internal_has_oneof_index() const {
+inline bool FieldDescriptorProto::has_oneof_index() const {
   bool value = (_impl_._has_bits_[0] & 0x00000080u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_oneof_index() const {
-  return _internal_has_oneof_index();
-}
 inline void FieldDescriptorProto::clear_oneof_index() {
   _impl_.oneof_index_ = 0;
   _impl_._has_bits_[0] &= ~0x00000080u;
 }
-inline int32_t FieldDescriptorProto::_internal_oneof_index() const {
+inline ::int32_t FieldDescriptorProto::_internal_oneof_index() const {
   return _impl_.oneof_index_;
 }
-inline int32_t FieldDescriptorProto::oneof_index() const {
+inline ::int32_t FieldDescriptorProto::oneof_index() const {
   // @@protoc_insertion_point(field_get:google.protobuf.FieldDescriptorProto.oneof_index)
   return _internal_oneof_index();
 }
-inline void FieldDescriptorProto::_internal_set_oneof_index(int32_t value) {
+inline void FieldDescriptorProto::_internal_set_oneof_index(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000080u;
   _impl_.oneof_index_ = value;
 }
-inline void FieldDescriptorProto::set_oneof_index(int32_t value) {
+inline void FieldDescriptorProto::set_oneof_index(::int32_t value) {
   _internal_set_oneof_index(value);
   // @@protoc_insertion_point(field_set:google.protobuf.FieldDescriptorProto.oneof_index)
 }
 
 // optional string json_name = 10;
-inline bool FieldDescriptorProto::_internal_has_json_name() const {
+inline bool FieldDescriptorProto::has_json_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_json_name() const {
-  return _internal_has_json_name();
-}
 inline void FieldDescriptorProto::clear_json_name() {
   _impl_.json_name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000010u;
@@ -10494,15 +10246,13 @@
 }
 inline std::string* FieldDescriptorProto::release_json_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.FieldDescriptorProto.json_name)
-  if (!_internal_has_json_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000010u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000010u;
   auto* p = _impl_.json_name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.json_name_.IsDefault()) {
-    _impl_.json_name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.json_name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -10522,14 +10272,11 @@
 }
 
 // optional .google.protobuf.FieldOptions options = 8;
-inline bool FieldDescriptorProto::_internal_has_options() const {
+inline bool FieldDescriptorProto::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool FieldDescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void FieldDescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000020u;
@@ -10612,13 +10359,10 @@
 }
 
 // optional bool proto3_optional = 17;
-inline bool FieldDescriptorProto::_internal_has_proto3_optional() const {
+inline bool FieldDescriptorProto::has_proto3_optional() const {
   bool value = (_impl_._has_bits_[0] & 0x00000100u) != 0;
   return value;
 }
-inline bool FieldDescriptorProto::has_proto3_optional() const {
-  return _internal_has_proto3_optional();
-}
 inline void FieldDescriptorProto::clear_proto3_optional() {
   _impl_.proto3_optional_ = false;
   _impl_._has_bits_[0] &= ~0x00000100u;
@@ -10644,13 +10388,10 @@
 // OneofDescriptorProto
 
 // optional string name = 1;
-inline bool OneofDescriptorProto::_internal_has_name() const {
+inline bool OneofDescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool OneofDescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void OneofDescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -10684,15 +10425,13 @@
 }
 inline std::string* OneofDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.OneofDescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -10712,14 +10451,11 @@
 }
 
 // optional .google.protobuf.OneofOptions options = 2;
-inline bool OneofDescriptorProto::_internal_has_options() const {
+inline bool OneofDescriptorProto::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool OneofDescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void OneofDescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -10806,57 +10542,51 @@
 // EnumDescriptorProto_EnumReservedRange
 
 // optional int32 start = 1;
-inline bool EnumDescriptorProto_EnumReservedRange::_internal_has_start() const {
+inline bool EnumDescriptorProto_EnumReservedRange::has_start() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool EnumDescriptorProto_EnumReservedRange::has_start() const {
-  return _internal_has_start();
-}
 inline void EnumDescriptorProto_EnumReservedRange::clear_start() {
   _impl_.start_ = 0;
   _impl_._has_bits_[0] &= ~0x00000001u;
 }
-inline int32_t EnumDescriptorProto_EnumReservedRange::_internal_start() const {
+inline ::int32_t EnumDescriptorProto_EnumReservedRange::_internal_start() const {
   return _impl_.start_;
 }
-inline int32_t EnumDescriptorProto_EnumReservedRange::start() const {
+inline ::int32_t EnumDescriptorProto_EnumReservedRange::start() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.EnumReservedRange.start)
   return _internal_start();
 }
-inline void EnumDescriptorProto_EnumReservedRange::_internal_set_start(int32_t value) {
+inline void EnumDescriptorProto_EnumReservedRange::_internal_set_start(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000001u;
   _impl_.start_ = value;
 }
-inline void EnumDescriptorProto_EnumReservedRange::set_start(int32_t value) {
+inline void EnumDescriptorProto_EnumReservedRange::set_start(::int32_t value) {
   _internal_set_start(value);
   // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.EnumReservedRange.start)
 }
 
 // optional int32 end = 2;
-inline bool EnumDescriptorProto_EnumReservedRange::_internal_has_end() const {
+inline bool EnumDescriptorProto_EnumReservedRange::has_end() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool EnumDescriptorProto_EnumReservedRange::has_end() const {
-  return _internal_has_end();
-}
 inline void EnumDescriptorProto_EnumReservedRange::clear_end() {
   _impl_.end_ = 0;
   _impl_._has_bits_[0] &= ~0x00000002u;
 }
-inline int32_t EnumDescriptorProto_EnumReservedRange::_internal_end() const {
+inline ::int32_t EnumDescriptorProto_EnumReservedRange::_internal_end() const {
   return _impl_.end_;
 }
-inline int32_t EnumDescriptorProto_EnumReservedRange::end() const {
+inline ::int32_t EnumDescriptorProto_EnumReservedRange::end() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumDescriptorProto.EnumReservedRange.end)
   return _internal_end();
 }
-inline void EnumDescriptorProto_EnumReservedRange::_internal_set_end(int32_t value) {
+inline void EnumDescriptorProto_EnumReservedRange::_internal_set_end(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000002u;
   _impl_.end_ = value;
 }
-inline void EnumDescriptorProto_EnumReservedRange::set_end(int32_t value) {
+inline void EnumDescriptorProto_EnumReservedRange::set_end(::int32_t value) {
   _internal_set_end(value);
   // @@protoc_insertion_point(field_set:google.protobuf.EnumDescriptorProto.EnumReservedRange.end)
 }
@@ -10866,13 +10596,10 @@
 // EnumDescriptorProto
 
 // optional string name = 1;
-inline bool EnumDescriptorProto::_internal_has_name() const {
+inline bool EnumDescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool EnumDescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void EnumDescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -10906,15 +10633,13 @@
 }
 inline std::string* EnumDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.EnumDescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -10974,14 +10699,11 @@
 }
 
 // optional .google.protobuf.EnumOptions options = 3;
-inline bool EnumDescriptorProto::_internal_has_options() const {
+inline bool EnumDescriptorProto::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool EnumDescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void EnumDescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -11138,11 +10860,10 @@
   // @@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);
-  _impl_.reserved_name_.Mutable(index)->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.reserved_name_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.EnumDescriptorProto.reserved_name)
 }
-inline void EnumDescriptorProto::set_reserved_name(int index, const char* value, size_t size) {
+inline void EnumDescriptorProto::set_reserved_name(int index, const char* value, ::size_t size) {
   _impl_.reserved_name_.Mutable(index)->assign(
     reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.EnumDescriptorProto.reserved_name)
@@ -11159,11 +10880,10 @@
   // @@protoc_insertion_point(field_add:google.protobuf.EnumDescriptorProto.reserved_name)
 }
 inline void EnumDescriptorProto::add_reserved_name(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.reserved_name_.Add()->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.reserved_name_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.EnumDescriptorProto.reserved_name)
 }
-inline void EnumDescriptorProto::add_reserved_name(const char* value, size_t size) {
+inline void EnumDescriptorProto::add_reserved_name(const char* value, ::size_t size) {
   _impl_.reserved_name_.Add()->assign(reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_add_pointer:google.protobuf.EnumDescriptorProto.reserved_name)
 }
@@ -11183,13 +10903,10 @@
 // EnumValueDescriptorProto
 
 // optional string name = 1;
-inline bool EnumValueDescriptorProto::_internal_has_name() const {
+inline bool EnumValueDescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool EnumValueDescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void EnumValueDescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -11223,15 +10940,13 @@
 }
 inline std::string* EnumValueDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.EnumValueDescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -11251,42 +10966,36 @@
 }
 
 // optional int32 number = 2;
-inline bool EnumValueDescriptorProto::_internal_has_number() const {
+inline bool EnumValueDescriptorProto::has_number() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool EnumValueDescriptorProto::has_number() const {
-  return _internal_has_number();
-}
 inline void EnumValueDescriptorProto::clear_number() {
   _impl_.number_ = 0;
   _impl_._has_bits_[0] &= ~0x00000004u;
 }
-inline int32_t EnumValueDescriptorProto::_internal_number() const {
+inline ::int32_t EnumValueDescriptorProto::_internal_number() const {
   return _impl_.number_;
 }
-inline int32_t EnumValueDescriptorProto::number() const {
+inline ::int32_t EnumValueDescriptorProto::number() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValueDescriptorProto.number)
   return _internal_number();
 }
-inline void EnumValueDescriptorProto::_internal_set_number(int32_t value) {
+inline void EnumValueDescriptorProto::_internal_set_number(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000004u;
   _impl_.number_ = value;
 }
-inline void EnumValueDescriptorProto::set_number(int32_t value) {
+inline void EnumValueDescriptorProto::set_number(::int32_t value) {
   _internal_set_number(value);
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValueDescriptorProto.number)
 }
 
 // optional .google.protobuf.EnumValueOptions options = 3;
-inline bool EnumValueDescriptorProto::_internal_has_options() const {
+inline bool EnumValueDescriptorProto::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool EnumValueDescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void EnumValueDescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -11373,13 +11082,10 @@
 // ServiceDescriptorProto
 
 // optional string name = 1;
-inline bool ServiceDescriptorProto::_internal_has_name() const {
+inline bool ServiceDescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool ServiceDescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void ServiceDescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -11413,15 +11119,13 @@
 }
 inline std::string* ServiceDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.ServiceDescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -11481,14 +11185,11 @@
 }
 
 // optional .google.protobuf.ServiceOptions options = 3;
-inline bool ServiceDescriptorProto::_internal_has_options() const {
+inline bool ServiceDescriptorProto::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool ServiceDescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void ServiceDescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -11575,13 +11276,10 @@
 // MethodDescriptorProto
 
 // optional string name = 1;
-inline bool MethodDescriptorProto::_internal_has_name() const {
+inline bool MethodDescriptorProto::has_name() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool MethodDescriptorProto::has_name() const {
-  return _internal_has_name();
-}
 inline void MethodDescriptorProto::clear_name() {
   _impl_.name_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -11615,15 +11313,13 @@
 }
 inline std::string* MethodDescriptorProto::release_name() {
   // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.name)
-  if (!_internal_has_name()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_.IsDefault()) {
-    _impl_.name_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -11643,13 +11339,10 @@
 }
 
 // optional string input_type = 2;
-inline bool MethodDescriptorProto::_internal_has_input_type() const {
+inline bool MethodDescriptorProto::has_input_type() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool MethodDescriptorProto::has_input_type() const {
-  return _internal_has_input_type();
-}
 inline void MethodDescriptorProto::clear_input_type() {
   _impl_.input_type_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -11683,15 +11376,13 @@
 }
 inline std::string* MethodDescriptorProto::release_input_type() {
   // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.input_type)
-  if (!_internal_has_input_type()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000002u;
   auto* p = _impl_.input_type_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.input_type_.IsDefault()) {
-    _impl_.input_type_.Set("", GetArenaForAllocation());
-  }
+  _impl_.input_type_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -11711,13 +11402,10 @@
 }
 
 // optional string output_type = 3;
-inline bool MethodDescriptorProto::_internal_has_output_type() const {
+inline bool MethodDescriptorProto::has_output_type() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool MethodDescriptorProto::has_output_type() const {
-  return _internal_has_output_type();
-}
 inline void MethodDescriptorProto::clear_output_type() {
   _impl_.output_type_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -11751,15 +11439,13 @@
 }
 inline std::string* MethodDescriptorProto::release_output_type() {
   // @@protoc_insertion_point(field_release:google.protobuf.MethodDescriptorProto.output_type)
-  if (!_internal_has_output_type()) {
+  if ((_impl_._has_bits_[0] & 0x00000004u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000004u;
   auto* p = _impl_.output_type_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.output_type_.IsDefault()) {
-    _impl_.output_type_.Set("", GetArenaForAllocation());
-  }
+  _impl_.output_type_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -11779,14 +11465,11 @@
 }
 
 // optional .google.protobuf.MethodOptions options = 4;
-inline bool MethodDescriptorProto::_internal_has_options() const {
+inline bool MethodDescriptorProto::has_options() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   PROTOBUF_ASSUME(!value || _impl_.options_ != nullptr);
   return value;
 }
-inline bool MethodDescriptorProto::has_options() const {
-  return _internal_has_options();
-}
 inline void MethodDescriptorProto::clear_options() {
   if (_impl_.options_ != nullptr) _impl_.options_->Clear();
   _impl_._has_bits_[0] &= ~0x00000008u;
@@ -11869,13 +11552,10 @@
 }
 
 // optional bool client_streaming = 5 [default = false];
-inline bool MethodDescriptorProto::_internal_has_client_streaming() const {
+inline bool MethodDescriptorProto::has_client_streaming() const {
   bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
   return value;
 }
-inline bool MethodDescriptorProto::has_client_streaming() const {
-  return _internal_has_client_streaming();
-}
 inline void MethodDescriptorProto::clear_client_streaming() {
   _impl_.client_streaming_ = false;
   _impl_._has_bits_[0] &= ~0x00000010u;
@@ -11897,13 +11577,10 @@
 }
 
 // optional bool server_streaming = 6 [default = false];
-inline bool MethodDescriptorProto::_internal_has_server_streaming() const {
+inline bool MethodDescriptorProto::has_server_streaming() const {
   bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0;
   return value;
 }
-inline bool MethodDescriptorProto::has_server_streaming() const {
-  return _internal_has_server_streaming();
-}
 inline void MethodDescriptorProto::clear_server_streaming() {
   _impl_.server_streaming_ = false;
   _impl_._has_bits_[0] &= ~0x00000020u;
@@ -11929,13 +11606,10 @@
 // FileOptions
 
 // optional string java_package = 1;
-inline bool FileOptions::_internal_has_java_package() const {
+inline bool FileOptions::has_java_package() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool FileOptions::has_java_package() const {
-  return _internal_has_java_package();
-}
 inline void FileOptions::clear_java_package() {
   _impl_.java_package_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -11969,15 +11643,13 @@
 }
 inline std::string* FileOptions::release_java_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_package)
-  if (!_internal_has_java_package()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.java_package_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.java_package_.IsDefault()) {
-    _impl_.java_package_.Set("", GetArenaForAllocation());
-  }
+  _impl_.java_package_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -11997,13 +11669,10 @@
 }
 
 // optional string java_outer_classname = 8;
-inline bool FileOptions::_internal_has_java_outer_classname() const {
+inline bool FileOptions::has_java_outer_classname() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool FileOptions::has_java_outer_classname() const {
-  return _internal_has_java_outer_classname();
-}
 inline void FileOptions::clear_java_outer_classname() {
   _impl_.java_outer_classname_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -12037,15 +11706,13 @@
 }
 inline std::string* FileOptions::release_java_outer_classname() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.java_outer_classname)
-  if (!_internal_has_java_outer_classname()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000002u;
   auto* p = _impl_.java_outer_classname_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.java_outer_classname_.IsDefault()) {
-    _impl_.java_outer_classname_.Set("", GetArenaForAllocation());
-  }
+  _impl_.java_outer_classname_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12065,13 +11732,10 @@
 }
 
 // optional bool java_multiple_files = 10 [default = false];
-inline bool FileOptions::_internal_has_java_multiple_files() const {
+inline bool FileOptions::has_java_multiple_files() const {
   bool value = (_impl_._has_bits_[0] & 0x00000400u) != 0;
   return value;
 }
-inline bool FileOptions::has_java_multiple_files() const {
-  return _internal_has_java_multiple_files();
-}
 inline void FileOptions::clear_java_multiple_files() {
   _impl_.java_multiple_files_ = false;
   _impl_._has_bits_[0] &= ~0x00000400u;
@@ -12093,13 +11757,10 @@
 }
 
 // optional bool java_generate_equals_and_hash = 20 [deprecated = true];
-inline bool FileOptions::_internal_has_java_generate_equals_and_hash() const {
+inline bool FileOptions::has_java_generate_equals_and_hash() const {
   bool value = (_impl_._has_bits_[0] & 0x00000800u) != 0;
   return value;
 }
-inline bool FileOptions::has_java_generate_equals_and_hash() const {
-  return _internal_has_java_generate_equals_and_hash();
-}
 inline void FileOptions::clear_java_generate_equals_and_hash() {
   _impl_.java_generate_equals_and_hash_ = false;
   _impl_._has_bits_[0] &= ~0x00000800u;
@@ -12121,13 +11782,10 @@
 }
 
 // optional bool java_string_check_utf8 = 27 [default = false];
-inline bool FileOptions::_internal_has_java_string_check_utf8() const {
+inline bool FileOptions::has_java_string_check_utf8() const {
   bool value = (_impl_._has_bits_[0] & 0x00001000u) != 0;
   return value;
 }
-inline bool FileOptions::has_java_string_check_utf8() const {
-  return _internal_has_java_string_check_utf8();
-}
 inline void FileOptions::clear_java_string_check_utf8() {
   _impl_.java_string_check_utf8_ = false;
   _impl_._has_bits_[0] &= ~0x00001000u;
@@ -12149,13 +11807,10 @@
 }
 
 // optional .google.protobuf.FileOptions.OptimizeMode optimize_for = 9 [default = SPEED];
-inline bool FileOptions::_internal_has_optimize_for() const {
+inline bool FileOptions::has_optimize_for() const {
   bool value = (_impl_._has_bits_[0] & 0x00040000u) != 0;
   return value;
 }
-inline bool FileOptions::has_optimize_for() const {
-  return _internal_has_optimize_for();
-}
 inline void FileOptions::clear_optimize_for() {
   _impl_.optimize_for_ = 1;
   _impl_._has_bits_[0] &= ~0x00040000u;
@@ -12178,13 +11833,10 @@
 }
 
 // optional string go_package = 11;
-inline bool FileOptions::_internal_has_go_package() const {
+inline bool FileOptions::has_go_package() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool FileOptions::has_go_package() const {
-  return _internal_has_go_package();
-}
 inline void FileOptions::clear_go_package() {
   _impl_.go_package_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -12218,15 +11870,13 @@
 }
 inline std::string* FileOptions::release_go_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.go_package)
-  if (!_internal_has_go_package()) {
+  if ((_impl_._has_bits_[0] & 0x00000004u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000004u;
   auto* p = _impl_.go_package_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.go_package_.IsDefault()) {
-    _impl_.go_package_.Set("", GetArenaForAllocation());
-  }
+  _impl_.go_package_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12246,13 +11896,10 @@
 }
 
 // optional bool cc_generic_services = 16 [default = false];
-inline bool FileOptions::_internal_has_cc_generic_services() const {
+inline bool FileOptions::has_cc_generic_services() const {
   bool value = (_impl_._has_bits_[0] & 0x00002000u) != 0;
   return value;
 }
-inline bool FileOptions::has_cc_generic_services() const {
-  return _internal_has_cc_generic_services();
-}
 inline void FileOptions::clear_cc_generic_services() {
   _impl_.cc_generic_services_ = false;
   _impl_._has_bits_[0] &= ~0x00002000u;
@@ -12274,13 +11921,10 @@
 }
 
 // optional bool java_generic_services = 17 [default = false];
-inline bool FileOptions::_internal_has_java_generic_services() const {
+inline bool FileOptions::has_java_generic_services() const {
   bool value = (_impl_._has_bits_[0] & 0x00004000u) != 0;
   return value;
 }
-inline bool FileOptions::has_java_generic_services() const {
-  return _internal_has_java_generic_services();
-}
 inline void FileOptions::clear_java_generic_services() {
   _impl_.java_generic_services_ = false;
   _impl_._has_bits_[0] &= ~0x00004000u;
@@ -12302,13 +11946,10 @@
 }
 
 // optional bool py_generic_services = 18 [default = false];
-inline bool FileOptions::_internal_has_py_generic_services() const {
+inline bool FileOptions::has_py_generic_services() const {
   bool value = (_impl_._has_bits_[0] & 0x00008000u) != 0;
   return value;
 }
-inline bool FileOptions::has_py_generic_services() const {
-  return _internal_has_py_generic_services();
-}
 inline void FileOptions::clear_py_generic_services() {
   _impl_.py_generic_services_ = false;
   _impl_._has_bits_[0] &= ~0x00008000u;
@@ -12330,13 +11971,10 @@
 }
 
 // optional bool php_generic_services = 42 [default = false];
-inline bool FileOptions::_internal_has_php_generic_services() const {
+inline bool FileOptions::has_php_generic_services() const {
   bool value = (_impl_._has_bits_[0] & 0x00010000u) != 0;
   return value;
 }
-inline bool FileOptions::has_php_generic_services() const {
-  return _internal_has_php_generic_services();
-}
 inline void FileOptions::clear_php_generic_services() {
   _impl_.php_generic_services_ = false;
   _impl_._has_bits_[0] &= ~0x00010000u;
@@ -12358,13 +11996,10 @@
 }
 
 // optional bool deprecated = 23 [default = false];
-inline bool FileOptions::_internal_has_deprecated() const {
+inline bool FileOptions::has_deprecated() const {
   bool value = (_impl_._has_bits_[0] & 0x00020000u) != 0;
   return value;
 }
-inline bool FileOptions::has_deprecated() const {
-  return _internal_has_deprecated();
-}
 inline void FileOptions::clear_deprecated() {
   _impl_.deprecated_ = false;
   _impl_._has_bits_[0] &= ~0x00020000u;
@@ -12386,13 +12021,10 @@
 }
 
 // optional bool cc_enable_arenas = 31 [default = true];
-inline bool FileOptions::_internal_has_cc_enable_arenas() const {
+inline bool FileOptions::has_cc_enable_arenas() const {
   bool value = (_impl_._has_bits_[0] & 0x00080000u) != 0;
   return value;
 }
-inline bool FileOptions::has_cc_enable_arenas() const {
-  return _internal_has_cc_enable_arenas();
-}
 inline void FileOptions::clear_cc_enable_arenas() {
   _impl_.cc_enable_arenas_ = true;
   _impl_._has_bits_[0] &= ~0x00080000u;
@@ -12414,13 +12046,10 @@
 }
 
 // optional string objc_class_prefix = 36;
-inline bool FileOptions::_internal_has_objc_class_prefix() const {
+inline bool FileOptions::has_objc_class_prefix() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   return value;
 }
-inline bool FileOptions::has_objc_class_prefix() const {
-  return _internal_has_objc_class_prefix();
-}
 inline void FileOptions::clear_objc_class_prefix() {
   _impl_.objc_class_prefix_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000008u;
@@ -12454,15 +12083,13 @@
 }
 inline std::string* FileOptions::release_objc_class_prefix() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.objc_class_prefix)
-  if (!_internal_has_objc_class_prefix()) {
+  if ((_impl_._has_bits_[0] & 0x00000008u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000008u;
   auto* p = _impl_.objc_class_prefix_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.objc_class_prefix_.IsDefault()) {
-    _impl_.objc_class_prefix_.Set("", GetArenaForAllocation());
-  }
+  _impl_.objc_class_prefix_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12482,13 +12109,10 @@
 }
 
 // optional string csharp_namespace = 37;
-inline bool FileOptions::_internal_has_csharp_namespace() const {
+inline bool FileOptions::has_csharp_namespace() const {
   bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
   return value;
 }
-inline bool FileOptions::has_csharp_namespace() const {
-  return _internal_has_csharp_namespace();
-}
 inline void FileOptions::clear_csharp_namespace() {
   _impl_.csharp_namespace_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000010u;
@@ -12522,15 +12146,13 @@
 }
 inline std::string* FileOptions::release_csharp_namespace() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.csharp_namespace)
-  if (!_internal_has_csharp_namespace()) {
+  if ((_impl_._has_bits_[0] & 0x00000010u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000010u;
   auto* p = _impl_.csharp_namespace_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.csharp_namespace_.IsDefault()) {
-    _impl_.csharp_namespace_.Set("", GetArenaForAllocation());
-  }
+  _impl_.csharp_namespace_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12550,13 +12172,10 @@
 }
 
 // optional string swift_prefix = 39;
-inline bool FileOptions::_internal_has_swift_prefix() const {
+inline bool FileOptions::has_swift_prefix() const {
   bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0;
   return value;
 }
-inline bool FileOptions::has_swift_prefix() const {
-  return _internal_has_swift_prefix();
-}
 inline void FileOptions::clear_swift_prefix() {
   _impl_.swift_prefix_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000020u;
@@ -12590,15 +12209,13 @@
 }
 inline std::string* FileOptions::release_swift_prefix() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.swift_prefix)
-  if (!_internal_has_swift_prefix()) {
+  if ((_impl_._has_bits_[0] & 0x00000020u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000020u;
   auto* p = _impl_.swift_prefix_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.swift_prefix_.IsDefault()) {
-    _impl_.swift_prefix_.Set("", GetArenaForAllocation());
-  }
+  _impl_.swift_prefix_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12618,13 +12235,10 @@
 }
 
 // optional string php_class_prefix = 40;
-inline bool FileOptions::_internal_has_php_class_prefix() const {
+inline bool FileOptions::has_php_class_prefix() const {
   bool value = (_impl_._has_bits_[0] & 0x00000040u) != 0;
   return value;
 }
-inline bool FileOptions::has_php_class_prefix() const {
-  return _internal_has_php_class_prefix();
-}
 inline void FileOptions::clear_php_class_prefix() {
   _impl_.php_class_prefix_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000040u;
@@ -12658,15 +12272,13 @@
 }
 inline std::string* FileOptions::release_php_class_prefix() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_class_prefix)
-  if (!_internal_has_php_class_prefix()) {
+  if ((_impl_._has_bits_[0] & 0x00000040u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000040u;
   auto* p = _impl_.php_class_prefix_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.php_class_prefix_.IsDefault()) {
-    _impl_.php_class_prefix_.Set("", GetArenaForAllocation());
-  }
+  _impl_.php_class_prefix_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12686,13 +12298,10 @@
 }
 
 // optional string php_namespace = 41;
-inline bool FileOptions::_internal_has_php_namespace() const {
+inline bool FileOptions::has_php_namespace() const {
   bool value = (_impl_._has_bits_[0] & 0x00000080u) != 0;
   return value;
 }
-inline bool FileOptions::has_php_namespace() const {
-  return _internal_has_php_namespace();
-}
 inline void FileOptions::clear_php_namespace() {
   _impl_.php_namespace_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000080u;
@@ -12726,15 +12335,13 @@
 }
 inline std::string* FileOptions::release_php_namespace() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_namespace)
-  if (!_internal_has_php_namespace()) {
+  if ((_impl_._has_bits_[0] & 0x00000080u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000080u;
   auto* p = _impl_.php_namespace_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.php_namespace_.IsDefault()) {
-    _impl_.php_namespace_.Set("", GetArenaForAllocation());
-  }
+  _impl_.php_namespace_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12754,13 +12361,10 @@
 }
 
 // optional string php_metadata_namespace = 44;
-inline bool FileOptions::_internal_has_php_metadata_namespace() const {
+inline bool FileOptions::has_php_metadata_namespace() const {
   bool value = (_impl_._has_bits_[0] & 0x00000100u) != 0;
   return value;
 }
-inline bool FileOptions::has_php_metadata_namespace() const {
-  return _internal_has_php_metadata_namespace();
-}
 inline void FileOptions::clear_php_metadata_namespace() {
   _impl_.php_metadata_namespace_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000100u;
@@ -12794,15 +12398,13 @@
 }
 inline std::string* FileOptions::release_php_metadata_namespace() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.php_metadata_namespace)
-  if (!_internal_has_php_metadata_namespace()) {
+  if ((_impl_._has_bits_[0] & 0x00000100u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000100u;
   auto* p = _impl_.php_metadata_namespace_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.php_metadata_namespace_.IsDefault()) {
-    _impl_.php_metadata_namespace_.Set("", GetArenaForAllocation());
-  }
+  _impl_.php_metadata_namespace_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12822,13 +12424,10 @@
 }
 
 // optional string ruby_package = 45;
-inline bool FileOptions::_internal_has_ruby_package() const {
+inline bool FileOptions::has_ruby_package() const {
   bool value = (_impl_._has_bits_[0] & 0x00000200u) != 0;
   return value;
 }
-inline bool FileOptions::has_ruby_package() const {
-  return _internal_has_ruby_package();
-}
 inline void FileOptions::clear_ruby_package() {
   _impl_.ruby_package_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000200u;
@@ -12862,15 +12461,13 @@
 }
 inline std::string* FileOptions::release_ruby_package() {
   // @@protoc_insertion_point(field_release:google.protobuf.FileOptions.ruby_package)
-  if (!_internal_has_ruby_package()) {
+  if ((_impl_._has_bits_[0] & 0x00000200u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000200u;
   auto* p = _impl_.ruby_package_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.ruby_package_.IsDefault()) {
-    _impl_.ruby_package_.Set("", GetArenaForAllocation());
-  }
+  _impl_.ruby_package_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -12934,13 +12531,10 @@
 // MessageOptions
 
 // optional bool message_set_wire_format = 1 [default = false];
-inline bool MessageOptions::_internal_has_message_set_wire_format() const {
+inline bool MessageOptions::has_message_set_wire_format() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool MessageOptions::has_message_set_wire_format() const {
-  return _internal_has_message_set_wire_format();
-}
 inline void MessageOptions::clear_message_set_wire_format() {
   _impl_.message_set_wire_format_ = false;
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -12962,13 +12556,10 @@
 }
 
 // optional bool no_standard_descriptor_accessor = 2 [default = false];
-inline bool MessageOptions::_internal_has_no_standard_descriptor_accessor() const {
+inline bool MessageOptions::has_no_standard_descriptor_accessor() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool MessageOptions::has_no_standard_descriptor_accessor() const {
-  return _internal_has_no_standard_descriptor_accessor();
-}
 inline void MessageOptions::clear_no_standard_descriptor_accessor() {
   _impl_.no_standard_descriptor_accessor_ = false;
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -12990,13 +12581,10 @@
 }
 
 // optional bool deprecated = 3 [default = false];
-inline bool MessageOptions::_internal_has_deprecated() const {
+inline bool MessageOptions::has_deprecated() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool MessageOptions::has_deprecated() const {
-  return _internal_has_deprecated();
-}
 inline void MessageOptions::clear_deprecated() {
   _impl_.deprecated_ = false;
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -13018,13 +12606,10 @@
 }
 
 // optional bool map_entry = 7;
-inline bool MessageOptions::_internal_has_map_entry() const {
+inline bool MessageOptions::has_map_entry() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   return value;
 }
-inline bool MessageOptions::has_map_entry() const {
-  return _internal_has_map_entry();
-}
 inline void MessageOptions::clear_map_entry() {
   _impl_.map_entry_ = false;
   _impl_._has_bits_[0] &= ~0x00000008u;
@@ -13090,13 +12675,10 @@
 // FieldOptions
 
 // optional .google.protobuf.FieldOptions.CType ctype = 1 [default = STRING];
-inline bool FieldOptions::_internal_has_ctype() const {
+inline bool FieldOptions::has_ctype() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool FieldOptions::has_ctype() const {
-  return _internal_has_ctype();
-}
 inline void FieldOptions::clear_ctype() {
   _impl_.ctype_ = 0;
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -13119,13 +12701,10 @@
 }
 
 // optional bool packed = 2;
-inline bool FieldOptions::_internal_has_packed() const {
+inline bool FieldOptions::has_packed() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool FieldOptions::has_packed() const {
-  return _internal_has_packed();
-}
 inline void FieldOptions::clear_packed() {
   _impl_.packed_ = false;
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -13147,13 +12726,10 @@
 }
 
 // optional .google.protobuf.FieldOptions.JSType jstype = 6 [default = JS_NORMAL];
-inline bool FieldOptions::_internal_has_jstype() const {
+inline bool FieldOptions::has_jstype() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool FieldOptions::has_jstype() const {
-  return _internal_has_jstype();
-}
 inline void FieldOptions::clear_jstype() {
   _impl_.jstype_ = 0;
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -13176,13 +12752,10 @@
 }
 
 // optional bool lazy = 5 [default = false];
-inline bool FieldOptions::_internal_has_lazy() const {
+inline bool FieldOptions::has_lazy() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   return value;
 }
-inline bool FieldOptions::has_lazy() const {
-  return _internal_has_lazy();
-}
 inline void FieldOptions::clear_lazy() {
   _impl_.lazy_ = false;
   _impl_._has_bits_[0] &= ~0x00000008u;
@@ -13204,13 +12777,10 @@
 }
 
 // optional bool unverified_lazy = 15 [default = false];
-inline bool FieldOptions::_internal_has_unverified_lazy() const {
+inline bool FieldOptions::has_unverified_lazy() const {
   bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
   return value;
 }
-inline bool FieldOptions::has_unverified_lazy() const {
-  return _internal_has_unverified_lazy();
-}
 inline void FieldOptions::clear_unverified_lazy() {
   _impl_.unverified_lazy_ = false;
   _impl_._has_bits_[0] &= ~0x00000010u;
@@ -13232,13 +12802,10 @@
 }
 
 // optional bool deprecated = 3 [default = false];
-inline bool FieldOptions::_internal_has_deprecated() const {
+inline bool FieldOptions::has_deprecated() const {
   bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0;
   return value;
 }
-inline bool FieldOptions::has_deprecated() const {
-  return _internal_has_deprecated();
-}
 inline void FieldOptions::clear_deprecated() {
   _impl_.deprecated_ = false;
   _impl_._has_bits_[0] &= ~0x00000020u;
@@ -13260,13 +12827,10 @@
 }
 
 // optional bool weak = 10 [default = false];
-inline bool FieldOptions::_internal_has_weak() const {
+inline bool FieldOptions::has_weak() const {
   bool value = (_impl_._has_bits_[0] & 0x00000040u) != 0;
   return value;
 }
-inline bool FieldOptions::has_weak() const {
-  return _internal_has_weak();
-}
 inline void FieldOptions::clear_weak() {
   _impl_.weak_ = false;
   _impl_._has_bits_[0] &= ~0x00000040u;
@@ -13376,13 +12940,10 @@
 // EnumOptions
 
 // optional bool allow_alias = 2;
-inline bool EnumOptions::_internal_has_allow_alias() const {
+inline bool EnumOptions::has_allow_alias() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool EnumOptions::has_allow_alias() const {
-  return _internal_has_allow_alias();
-}
 inline void EnumOptions::clear_allow_alias() {
   _impl_.allow_alias_ = false;
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -13404,13 +12965,10 @@
 }
 
 // optional bool deprecated = 3 [default = false];
-inline bool EnumOptions::_internal_has_deprecated() const {
+inline bool EnumOptions::has_deprecated() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool EnumOptions::has_deprecated() const {
-  return _internal_has_deprecated();
-}
 inline void EnumOptions::clear_deprecated() {
   _impl_.deprecated_ = false;
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -13476,13 +13034,10 @@
 // EnumValueOptions
 
 // optional bool deprecated = 1 [default = false];
-inline bool EnumValueOptions::_internal_has_deprecated() const {
+inline bool EnumValueOptions::has_deprecated() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool EnumValueOptions::has_deprecated() const {
-  return _internal_has_deprecated();
-}
 inline void EnumValueOptions::clear_deprecated() {
   _impl_.deprecated_ = false;
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -13548,13 +13103,10 @@
 // ServiceOptions
 
 // optional bool deprecated = 33 [default = false];
-inline bool ServiceOptions::_internal_has_deprecated() const {
+inline bool ServiceOptions::has_deprecated() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool ServiceOptions::has_deprecated() const {
-  return _internal_has_deprecated();
-}
 inline void ServiceOptions::clear_deprecated() {
   _impl_.deprecated_ = false;
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -13620,13 +13172,10 @@
 // MethodOptions
 
 // optional bool deprecated = 33 [default = false];
-inline bool MethodOptions::_internal_has_deprecated() const {
+inline bool MethodOptions::has_deprecated() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool MethodOptions::has_deprecated() const {
-  return _internal_has_deprecated();
-}
 inline void MethodOptions::clear_deprecated() {
   _impl_.deprecated_ = false;
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -13648,13 +13197,10 @@
 }
 
 // optional .google.protobuf.MethodOptions.IdempotencyLevel idempotency_level = 34 [default = IDEMPOTENCY_UNKNOWN];
-inline bool MethodOptions::_internal_has_idempotency_level() const {
+inline bool MethodOptions::has_idempotency_level() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool MethodOptions::has_idempotency_level() const {
-  return _internal_has_idempotency_level();
-}
 inline void MethodOptions::clear_idempotency_level() {
   _impl_.idempotency_level_ = 0;
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -13721,13 +13267,10 @@
 // UninterpretedOption_NamePart
 
 // required string name_part = 1;
-inline bool UninterpretedOption_NamePart::_internal_has_name_part() const {
+inline bool UninterpretedOption_NamePart::has_name_part() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool UninterpretedOption_NamePart::has_name_part() const {
-  return _internal_has_name_part();
-}
 inline void UninterpretedOption_NamePart::clear_name_part() {
   _impl_.name_part_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -13761,15 +13304,13 @@
 }
 inline std::string* UninterpretedOption_NamePart::release_name_part() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.NamePart.name_part)
-  if (!_internal_has_name_part()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.name_part_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.name_part_.IsDefault()) {
-    _impl_.name_part_.Set("", GetArenaForAllocation());
-  }
+  _impl_.name_part_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -13789,13 +13330,10 @@
 }
 
 // required bool is_extension = 2;
-inline bool UninterpretedOption_NamePart::_internal_has_is_extension() const {
+inline bool UninterpretedOption_NamePart::has_is_extension() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool UninterpretedOption_NamePart::has_is_extension() const {
-  return _internal_has_is_extension();
-}
 inline void UninterpretedOption_NamePart::clear_is_extension() {
   _impl_.is_extension_ = false;
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -13861,13 +13399,10 @@
 }
 
 // optional string identifier_value = 3;
-inline bool UninterpretedOption::_internal_has_identifier_value() const {
+inline bool UninterpretedOption::has_identifier_value() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool UninterpretedOption::has_identifier_value() const {
-  return _internal_has_identifier_value();
-}
 inline void UninterpretedOption::clear_identifier_value() {
   _impl_.identifier_value_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -13901,15 +13436,13 @@
 }
 inline std::string* UninterpretedOption::release_identifier_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.identifier_value)
-  if (!_internal_has_identifier_value()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.identifier_value_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.identifier_value_.IsDefault()) {
-    _impl_.identifier_value_.Set("", GetArenaForAllocation());
-  }
+  _impl_.identifier_value_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -13929,69 +13462,60 @@
 }
 
 // optional uint64 positive_int_value = 4;
-inline bool UninterpretedOption::_internal_has_positive_int_value() const {
+inline bool UninterpretedOption::has_positive_int_value() const {
   bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
   return value;
 }
-inline bool UninterpretedOption::has_positive_int_value() const {
-  return _internal_has_positive_int_value();
-}
 inline void UninterpretedOption::clear_positive_int_value() {
-  _impl_.positive_int_value_ = uint64_t{0u};
+  _impl_.positive_int_value_ = ::uint64_t{0u};
   _impl_._has_bits_[0] &= ~0x00000008u;
 }
-inline uint64_t UninterpretedOption::_internal_positive_int_value() const {
+inline ::uint64_t UninterpretedOption::_internal_positive_int_value() const {
   return _impl_.positive_int_value_;
 }
-inline uint64_t UninterpretedOption::positive_int_value() const {
+inline ::uint64_t UninterpretedOption::positive_int_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.positive_int_value)
   return _internal_positive_int_value();
 }
-inline void UninterpretedOption::_internal_set_positive_int_value(uint64_t value) {
+inline void UninterpretedOption::_internal_set_positive_int_value(::uint64_t value) {
   _impl_._has_bits_[0] |= 0x00000008u;
   _impl_.positive_int_value_ = value;
 }
-inline void UninterpretedOption::set_positive_int_value(uint64_t value) {
+inline void UninterpretedOption::set_positive_int_value(::uint64_t value) {
   _internal_set_positive_int_value(value);
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.positive_int_value)
 }
 
 // optional int64 negative_int_value = 5;
-inline bool UninterpretedOption::_internal_has_negative_int_value() const {
+inline bool UninterpretedOption::has_negative_int_value() const {
   bool value = (_impl_._has_bits_[0] & 0x00000010u) != 0;
   return value;
 }
-inline bool UninterpretedOption::has_negative_int_value() const {
-  return _internal_has_negative_int_value();
-}
 inline void UninterpretedOption::clear_negative_int_value() {
-  _impl_.negative_int_value_ = int64_t{0};
+  _impl_.negative_int_value_ = ::int64_t{0};
   _impl_._has_bits_[0] &= ~0x00000010u;
 }
-inline int64_t UninterpretedOption::_internal_negative_int_value() const {
+inline ::int64_t UninterpretedOption::_internal_negative_int_value() const {
   return _impl_.negative_int_value_;
 }
-inline int64_t UninterpretedOption::negative_int_value() const {
+inline ::int64_t UninterpretedOption::negative_int_value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UninterpretedOption.negative_int_value)
   return _internal_negative_int_value();
 }
-inline void UninterpretedOption::_internal_set_negative_int_value(int64_t value) {
+inline void UninterpretedOption::_internal_set_negative_int_value(::int64_t value) {
   _impl_._has_bits_[0] |= 0x00000010u;
   _impl_.negative_int_value_ = value;
 }
-inline void UninterpretedOption::set_negative_int_value(int64_t value) {
+inline void UninterpretedOption::set_negative_int_value(::int64_t value) {
   _internal_set_negative_int_value(value);
   // @@protoc_insertion_point(field_set:google.protobuf.UninterpretedOption.negative_int_value)
 }
 
 // optional double double_value = 6;
-inline bool UninterpretedOption::_internal_has_double_value() const {
+inline bool UninterpretedOption::has_double_value() const {
   bool value = (_impl_._has_bits_[0] & 0x00000020u) != 0;
   return value;
 }
-inline bool UninterpretedOption::has_double_value() const {
-  return _internal_has_double_value();
-}
 inline void UninterpretedOption::clear_double_value() {
   _impl_.double_value_ = 0;
   _impl_._has_bits_[0] &= ~0x00000020u;
@@ -14013,13 +13537,10 @@
 }
 
 // optional bytes string_value = 7;
-inline bool UninterpretedOption::_internal_has_string_value() const {
+inline bool UninterpretedOption::has_string_value() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool UninterpretedOption::has_string_value() const {
-  return _internal_has_string_value();
-}
 inline void UninterpretedOption::clear_string_value() {
   _impl_.string_value_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -14053,15 +13574,13 @@
 }
 inline std::string* UninterpretedOption::release_string_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.string_value)
-  if (!_internal_has_string_value()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000002u;
   auto* p = _impl_.string_value_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.string_value_.IsDefault()) {
-    _impl_.string_value_.Set("", GetArenaForAllocation());
-  }
+  _impl_.string_value_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -14081,13 +13600,10 @@
 }
 
 // optional string aggregate_value = 8;
-inline bool UninterpretedOption::_internal_has_aggregate_value() const {
+inline bool UninterpretedOption::has_aggregate_value() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool UninterpretedOption::has_aggregate_value() const {
-  return _internal_has_aggregate_value();
-}
 inline void UninterpretedOption::clear_aggregate_value() {
   _impl_.aggregate_value_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000004u;
@@ -14121,15 +13637,13 @@
 }
 inline std::string* UninterpretedOption::release_aggregate_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.UninterpretedOption.aggregate_value)
-  if (!_internal_has_aggregate_value()) {
+  if ((_impl_._has_bits_[0] & 0x00000004u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000004u;
   auto* p = _impl_.aggregate_value_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.aggregate_value_.IsDefault()) {
-    _impl_.aggregate_value_.Set("", GetArenaForAllocation());
-  }
+  _impl_.aggregate_value_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -14162,38 +13676,38 @@
 inline void SourceCodeInfo_Location::clear_path() {
   _impl_.path_.Clear();
 }
-inline int32_t SourceCodeInfo_Location::_internal_path(int index) const {
+inline ::int32_t SourceCodeInfo_Location::_internal_path(int index) const {
   return _impl_.path_.Get(index);
 }
-inline int32_t SourceCodeInfo_Location::path(int index) const {
+inline ::int32_t SourceCodeInfo_Location::path(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.path)
   return _internal_path(index);
 }
-inline void SourceCodeInfo_Location::set_path(int index, int32_t value) {
+inline void SourceCodeInfo_Location::set_path(int index, ::int32_t value) {
   _impl_.path_.Set(index, value);
   // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.path)
 }
-inline void SourceCodeInfo_Location::_internal_add_path(int32_t value) {
+inline void SourceCodeInfo_Location::_internal_add_path(::int32_t value) {
   _impl_.path_.Add(value);
 }
-inline void SourceCodeInfo_Location::add_path(int32_t value) {
+inline void SourceCodeInfo_Location::add_path(::int32_t value) {
   _internal_add_path(value);
   // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.path)
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 SourceCodeInfo_Location::_internal_path() const {
   return _impl_.path_;
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 SourceCodeInfo_Location::path() const {
   // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.path)
   return _internal_path();
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 SourceCodeInfo_Location::_internal_mutable_path() {
   return &_impl_.path_;
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 SourceCodeInfo_Location::mutable_path() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.path)
   return _internal_mutable_path();
@@ -14209,51 +13723,48 @@
 inline void SourceCodeInfo_Location::clear_span() {
   _impl_.span_.Clear();
 }
-inline int32_t SourceCodeInfo_Location::_internal_span(int index) const {
+inline ::int32_t SourceCodeInfo_Location::_internal_span(int index) const {
   return _impl_.span_.Get(index);
 }
-inline int32_t SourceCodeInfo_Location::span(int index) const {
+inline ::int32_t SourceCodeInfo_Location::span(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.SourceCodeInfo.Location.span)
   return _internal_span(index);
 }
-inline void SourceCodeInfo_Location::set_span(int index, int32_t value) {
+inline void SourceCodeInfo_Location::set_span(int index, ::int32_t value) {
   _impl_.span_.Set(index, value);
   // @@protoc_insertion_point(field_set:google.protobuf.SourceCodeInfo.Location.span)
 }
-inline void SourceCodeInfo_Location::_internal_add_span(int32_t value) {
+inline void SourceCodeInfo_Location::_internal_add_span(::int32_t value) {
   _impl_.span_.Add(value);
 }
-inline void SourceCodeInfo_Location::add_span(int32_t value) {
+inline void SourceCodeInfo_Location::add_span(::int32_t value) {
   _internal_add_span(value);
   // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.span)
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 SourceCodeInfo_Location::_internal_span() const {
   return _impl_.span_;
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 SourceCodeInfo_Location::span() const {
   // @@protoc_insertion_point(field_list:google.protobuf.SourceCodeInfo.Location.span)
   return _internal_span();
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 SourceCodeInfo_Location::_internal_mutable_span() {
   return &_impl_.span_;
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 SourceCodeInfo_Location::mutable_span() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.SourceCodeInfo.Location.span)
   return _internal_mutable_span();
 }
 
 // optional string leading_comments = 3;
-inline bool SourceCodeInfo_Location::_internal_has_leading_comments() const {
+inline bool SourceCodeInfo_Location::has_leading_comments() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool SourceCodeInfo_Location::has_leading_comments() const {
-  return _internal_has_leading_comments();
-}
 inline void SourceCodeInfo_Location::clear_leading_comments() {
   _impl_.leading_comments_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -14287,15 +13798,13 @@
 }
 inline std::string* SourceCodeInfo_Location::release_leading_comments() {
   // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.leading_comments)
-  if (!_internal_has_leading_comments()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.leading_comments_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.leading_comments_.IsDefault()) {
-    _impl_.leading_comments_.Set("", GetArenaForAllocation());
-  }
+  _impl_.leading_comments_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -14315,13 +13824,10 @@
 }
 
 // optional string trailing_comments = 4;
-inline bool SourceCodeInfo_Location::_internal_has_trailing_comments() const {
+inline bool SourceCodeInfo_Location::has_trailing_comments() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool SourceCodeInfo_Location::has_trailing_comments() const {
-  return _internal_has_trailing_comments();
-}
 inline void SourceCodeInfo_Location::clear_trailing_comments() {
   _impl_.trailing_comments_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000002u;
@@ -14355,15 +13861,13 @@
 }
 inline std::string* SourceCodeInfo_Location::release_trailing_comments() {
   // @@protoc_insertion_point(field_release:google.protobuf.SourceCodeInfo.Location.trailing_comments)
-  if (!_internal_has_trailing_comments()) {
+  if ((_impl_._has_bits_[0] & 0x00000002u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000002u;
   auto* p = _impl_.trailing_comments_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.trailing_comments_.IsDefault()) {
-    _impl_.trailing_comments_.Set("", GetArenaForAllocation());
-  }
+  _impl_.trailing_comments_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -14417,11 +13921,10 @@
   // @@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);
-  _impl_.leading_detached_comments_.Mutable(index)->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.leading_detached_comments_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
 }
-inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, size_t size) {
+inline void SourceCodeInfo_Location::set_leading_detached_comments(int index, const char* value, ::size_t size) {
   _impl_.leading_detached_comments_.Mutable(index)->assign(
     reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
@@ -14438,11 +13941,10 @@
   // @@protoc_insertion_point(field_add:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
 }
 inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.leading_detached_comments_.Add()->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.leading_detached_comments_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
 }
-inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, size_t size) {
+inline void SourceCodeInfo_Location::add_leading_detached_comments(const char* value, ::size_t size) {
   _impl_.leading_detached_comments_.Add()->assign(reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_add_pointer:google.protobuf.SourceCodeInfo.Location.leading_detached_comments)
 }
@@ -14515,51 +14017,48 @@
 inline void GeneratedCodeInfo_Annotation::clear_path() {
   _impl_.path_.Clear();
 }
-inline int32_t GeneratedCodeInfo_Annotation::_internal_path(int index) const {
+inline ::int32_t GeneratedCodeInfo_Annotation::_internal_path(int index) const {
   return _impl_.path_.Get(index);
 }
-inline int32_t GeneratedCodeInfo_Annotation::path(int index) const {
+inline ::int32_t GeneratedCodeInfo_Annotation::path(int index) const {
   // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.path)
   return _internal_path(index);
 }
-inline void GeneratedCodeInfo_Annotation::set_path(int index, int32_t value) {
+inline void GeneratedCodeInfo_Annotation::set_path(int index, ::int32_t value) {
   _impl_.path_.Set(index, value);
   // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.path)
 }
-inline void GeneratedCodeInfo_Annotation::_internal_add_path(int32_t value) {
+inline void GeneratedCodeInfo_Annotation::_internal_add_path(::int32_t value) {
   _impl_.path_.Add(value);
 }
-inline void GeneratedCodeInfo_Annotation::add_path(int32_t value) {
+inline void GeneratedCodeInfo_Annotation::add_path(::int32_t value) {
   _internal_add_path(value);
   // @@protoc_insertion_point(field_add:google.protobuf.GeneratedCodeInfo.Annotation.path)
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 GeneratedCodeInfo_Annotation::_internal_path() const {
   return _impl_.path_;
 }
-inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >&
+inline const ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >&
 GeneratedCodeInfo_Annotation::path() const {
   // @@protoc_insertion_point(field_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
   return _internal_path();
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 GeneratedCodeInfo_Annotation::_internal_mutable_path() {
   return &_impl_.path_;
 }
-inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< int32_t >*
+inline ::PROTOBUF_NAMESPACE_ID::RepeatedField< ::int32_t >*
 GeneratedCodeInfo_Annotation::mutable_path() {
   // @@protoc_insertion_point(field_mutable_list:google.protobuf.GeneratedCodeInfo.Annotation.path)
   return _internal_mutable_path();
 }
 
 // optional string source_file = 2;
-inline bool GeneratedCodeInfo_Annotation::_internal_has_source_file() const {
+inline bool GeneratedCodeInfo_Annotation::has_source_file() const {
   bool value = (_impl_._has_bits_[0] & 0x00000001u) != 0;
   return value;
 }
-inline bool GeneratedCodeInfo_Annotation::has_source_file() const {
-  return _internal_has_source_file();
-}
 inline void GeneratedCodeInfo_Annotation::clear_source_file() {
   _impl_.source_file_.ClearToEmpty();
   _impl_._has_bits_[0] &= ~0x00000001u;
@@ -14593,15 +14092,13 @@
 }
 inline std::string* GeneratedCodeInfo_Annotation::release_source_file() {
   // @@protoc_insertion_point(field_release:google.protobuf.GeneratedCodeInfo.Annotation.source_file)
-  if (!_internal_has_source_file()) {
+  if ((_impl_._has_bits_[0] & 0x00000001u) == 0) {
     return nullptr;
   }
   _impl_._has_bits_[0] &= ~0x00000001u;
   auto* p = _impl_.source_file_.Release();
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
-  if (_impl_.source_file_.IsDefault()) {
-    _impl_.source_file_.Set("", GetArenaForAllocation());
-  }
+  _impl_.source_file_.Set("", GetArenaForAllocation());
 #endif // PROTOBUF_FORCE_COPY_DEFAULT_STRING
   return p;
 }
@@ -14621,61 +14118,81 @@
 }
 
 // optional int32 begin = 3;
-inline bool GeneratedCodeInfo_Annotation::_internal_has_begin() const {
+inline bool GeneratedCodeInfo_Annotation::has_begin() const {
   bool value = (_impl_._has_bits_[0] & 0x00000002u) != 0;
   return value;
 }
-inline bool GeneratedCodeInfo_Annotation::has_begin() const {
-  return _internal_has_begin();
-}
 inline void GeneratedCodeInfo_Annotation::clear_begin() {
   _impl_.begin_ = 0;
   _impl_._has_bits_[0] &= ~0x00000002u;
 }
-inline int32_t GeneratedCodeInfo_Annotation::_internal_begin() const {
+inline ::int32_t GeneratedCodeInfo_Annotation::_internal_begin() const {
   return _impl_.begin_;
 }
-inline int32_t GeneratedCodeInfo_Annotation::begin() const {
+inline ::int32_t GeneratedCodeInfo_Annotation::begin() const {
   // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.begin)
   return _internal_begin();
 }
-inline void GeneratedCodeInfo_Annotation::_internal_set_begin(int32_t value) {
+inline void GeneratedCodeInfo_Annotation::_internal_set_begin(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000002u;
   _impl_.begin_ = value;
 }
-inline void GeneratedCodeInfo_Annotation::set_begin(int32_t value) {
+inline void GeneratedCodeInfo_Annotation::set_begin(::int32_t value) {
   _internal_set_begin(value);
   // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.begin)
 }
 
 // optional int32 end = 4;
-inline bool GeneratedCodeInfo_Annotation::_internal_has_end() const {
+inline bool GeneratedCodeInfo_Annotation::has_end() const {
   bool value = (_impl_._has_bits_[0] & 0x00000004u) != 0;
   return value;
 }
-inline bool GeneratedCodeInfo_Annotation::has_end() const {
-  return _internal_has_end();
-}
 inline void GeneratedCodeInfo_Annotation::clear_end() {
   _impl_.end_ = 0;
   _impl_._has_bits_[0] &= ~0x00000004u;
 }
-inline int32_t GeneratedCodeInfo_Annotation::_internal_end() const {
+inline ::int32_t GeneratedCodeInfo_Annotation::_internal_end() const {
   return _impl_.end_;
 }
-inline int32_t GeneratedCodeInfo_Annotation::end() const {
+inline ::int32_t GeneratedCodeInfo_Annotation::end() const {
   // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.end)
   return _internal_end();
 }
-inline void GeneratedCodeInfo_Annotation::_internal_set_end(int32_t value) {
+inline void GeneratedCodeInfo_Annotation::_internal_set_end(::int32_t value) {
   _impl_._has_bits_[0] |= 0x00000004u;
   _impl_.end_ = value;
 }
-inline void GeneratedCodeInfo_Annotation::set_end(int32_t value) {
+inline void GeneratedCodeInfo_Annotation::set_end(::int32_t value) {
   _internal_set_end(value);
   // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.end)
 }
 
+// optional .google.protobuf.GeneratedCodeInfo.Annotation.Semantic semantic = 5;
+inline bool GeneratedCodeInfo_Annotation::has_semantic() const {
+  bool value = (_impl_._has_bits_[0] & 0x00000008u) != 0;
+  return value;
+}
+inline void GeneratedCodeInfo_Annotation::clear_semantic() {
+  _impl_.semantic_ = 0;
+  _impl_._has_bits_[0] &= ~0x00000008u;
+}
+inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::_internal_semantic() const {
+  return static_cast< ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic >(_impl_.semantic_);
+}
+inline ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic GeneratedCodeInfo_Annotation::semantic() const {
+  // @@protoc_insertion_point(field_get:google.protobuf.GeneratedCodeInfo.Annotation.semantic)
+  return _internal_semantic();
+}
+inline void GeneratedCodeInfo_Annotation::_internal_set_semantic(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic value) {
+  assert(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic_IsValid(value));
+  _impl_._has_bits_[0] |= 0x00000008u;
+  _impl_.semantic_ = value;
+}
+inline void GeneratedCodeInfo_Annotation::set_semantic(::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic value) {
+  _internal_set_semantic(value);
+  // @@protoc_insertion_point(field_set:google.protobuf.GeneratedCodeInfo.Annotation.semantic)
+}
+
 // -------------------------------------------------------------------
 
 // GeneratedCodeInfo
@@ -14721,101 +14238,62 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 PROTOBUF_NAMESPACE_OPEN
 
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type>() {
   return ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Type_descriptor();
 }
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label>() {
   return ::PROTOBUF_NAMESPACE_ID::FieldDescriptorProto_Label_descriptor();
 }
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode>() {
   return ::PROTOBUF_NAMESPACE_ID::FileOptions_OptimizeMode_descriptor();
 }
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::FieldOptions_CType> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::FieldOptions_CType>() {
   return ::PROTOBUF_NAMESPACE_ID::FieldOptions_CType_descriptor();
 }
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType>() {
   return ::PROTOBUF_NAMESPACE_ID::FieldOptions_JSType_descriptor();
 }
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel>() {
   return ::PROTOBUF_NAMESPACE_ID::MethodOptions_IdempotencyLevel_descriptor();
 }
+template <>
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic>() {
+  return ::PROTOBUF_NAMESPACE_ID::GeneratedCodeInfo_Annotation_Semantic_descriptor();
+}
 
 PROTOBUF_NAMESPACE_CLOSE
 
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fdescriptor_2eproto_2epb_2eh
diff --git a/src/google/protobuf/descriptor.proto b/src/google/protobuf/descriptor.proto
index f8eb216..0636a87 100644
--- a/src/google/protobuf/descriptor.proto
+++ b/src/google/protobuf/descriptor.proto
@@ -36,7 +36,6 @@
 // A valid .proto file can be translated directly to a FileDescriptorProto
 // without any other information (e.g. without reading its imports).
 
-
 syntax = "proto2";
 
 package google.protobuf;
@@ -86,8 +85,13 @@
   optional SourceCodeInfo source_code_info = 9;
 
   // The syntax of the proto file.
-  // The supported values are "proto2" and "proto3".
+  // The supported values are "proto2", "proto3", and "editions".
+  //
+  // If `edition` is present, this value must be "editions".
   optional string syntax = 12;
+
+  // The edition of the proto file, which is an opaque string.
+  optional string edition = 13;
 }
 
 // Describes a message type.
@@ -129,7 +133,6 @@
   // 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;
 }
@@ -305,7 +308,6 @@
   optional bool server_streaming = 6 [default = false];
 }
 
-
 // ===================================================================
 // Options
 
@@ -346,7 +348,6 @@
   // domain names.
   optional string java_package = 1;
 
-
   // 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.
@@ -373,7 +374,6 @@
   // This option has no effect on when used with the lite runtime.
   optional bool java_string_check_utf8 = 27 [default = false];
 
-
   // Generated classes can be optimized for speed or code size.
   enum OptimizeMode {
     SPEED = 1;         // Generate complete code for parsing, serialization,
@@ -390,9 +390,6 @@
   //   - Otherwise, the basename of the .proto file, without extension.
   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).
@@ -418,7 +415,6 @@
   // only to generated classes for C++.
   optional bool cc_enable_arenas = 31 [default = true];
 
-
   // Sets the objective c class prefix which is prepended to all objective c
   // generated classes from this .proto. There is no default.
   optional string objc_class_prefix = 36;
@@ -451,7 +447,6 @@
   // determining the ruby package.
   optional string ruby_package = 45;
 
-
   // The parser stores options it doesn't recognize here.
   // See the documentation for the "Options" section above.
   repeated UninterpretedOption uninterpreted_option = 999;
@@ -497,6 +492,10 @@
 
   reserved 4, 5, 6;
 
+  // NOTE: Do not set the option in .proto files. Always use the maps syntax
+  // instead. The option should only be implicitly set by the proto compiler
+  // parser.
+  //
   // Whether the message is an automatically generated map entry type for the
   // maps field.
   //
@@ -514,16 +513,11 @@
   // use a native map in the target language to hold the keys and values.
   // The reflection APIs in such implementations still need to work as
   // if the field is a repeated message field.
-  //
-  // NOTE: Do not set the option in .proto files. Always use the maps syntax
-  // instead. The option should only be implicitly set by the proto compiler
-  // parser.
   optional bool map_entry = 7;
 
   reserved 8;  // javalite_serializable
   reserved 9;  // javanano_as_lite
 
-
   // The parser stores options it doesn't recognize here. See above.
   repeated UninterpretedOption uninterpreted_option = 999;
 
@@ -592,7 +586,6 @@
   // 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 outer message
   // may return true even if the inner message has missing required fields.
@@ -604,11 +597,8 @@
   // check its required fields, regardless of whether or not the message has
   // been parsed.
   //
-  // As of 2021, lazy does no correctness checks on the byte stream during
-  // parsing.  This may lead to crashes if and when an invalid byte stream is
-  // finally parsed upon access.
-  //
-  // TODO(b/211906113):  Enable validation on lazy fields.
+  // As of May 2022, lazy verifies the contents of the byte stream during
+  // parsing.  An invalid byte stream will cause the overall parsing to fail.
   optional bool lazy = 5 [default = false];
 
   // unverified_lazy does no correctness checks on the byte stream. This should
@@ -625,7 +615,6 @@
   // 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;
 
@@ -729,7 +718,6 @@
   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,
@@ -914,8 +902,20 @@
     optional int32 begin = 3;
 
     // Identifies the ending offset in bytes in the generated code that
-    // relates to the identified offset. The end offset should be one past
+    // relates to the identified object. The end offset should be one past
     // the last relevant byte (so the length of the text = end - begin).
     optional int32 end = 4;
+
+    // Represents the identified object's effect on the element in the original
+    // .proto file.
+    enum Semantic {
+      // There is no effect or the effect is indescribable.
+      NONE = 0;
+      // The element is set or otherwise mutated.
+      SET = 1;
+      // An alias to the element is returned.
+      ALIAS = 2;
+    }
+    optional Semantic semantic = 5;
   }
 }
diff --git a/src/google/protobuf/descriptor_database.cc b/src/google/protobuf/descriptor_database.cc
index 203000d..5e0d6c3 100644
--- a/src/google/protobuf/descriptor_database.cc
+++ b/src/google/protobuf/descriptor_database.cc
@@ -32,14 +32,16 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/descriptor_database.h>
+#include "google/protobuf/descriptor_database.h"
 
 #include <algorithm>
 #include <set>
+#include <utility>
 
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/strings/ascii.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/descriptor.pb.h"
 
 
 namespace google {
@@ -52,7 +54,7 @@
   GOOGLE_CHECK(desc_proto.has_name());
   std::string full_name = prefix.empty()
                               ? desc_proto.name()
-                              : StrCat(prefix, ".", desc_proto.name());
+                              : absl::StrCat(prefix, ".", desc_proto.name());
   output->insert(full_name);
 
   for (const auto& d : desc_proto.nested_type()) {
@@ -117,7 +119,7 @@
 template <typename Value>
 bool SimpleDescriptorDatabase::DescriptorIndex<Value>::AddFile(
     const FileDescriptorProto& file, Value value) {
-  if (!InsertIfNotPresent(&by_name_, file.name(), value)) {
+  if (!by_name_.insert({file.name(), value}).second) {
     GOOGLE_LOG(ERROR) << "File already exists in database: " << file.name();
     return false;
   }
@@ -151,7 +153,7 @@
 
 // Returns true if and only if all characters in the name are alphanumerics,
 // underscores, or periods.
-bool ValidateSymbolName(StringPiece name) {
+bool ValidateSymbolName(absl::string_view 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') &&
@@ -185,9 +187,9 @@
 // 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) {
+bool IsSubSymbol(absl::string_view sub_symbol, absl::string_view super_symbol) {
   return sub_symbol == super_symbol ||
-         (HasPrefixString(super_symbol, sub_symbol) &&
+         (absl::StartsWith(super_symbol, sub_symbol) &&
           super_symbol[sub_symbol.size()] == '.');
 }
 
@@ -271,10 +273,11 @@
   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_,
-            std::make_pair(field.extendee().substr(1), field.number()),
-            value)) {
+    if (!by_extension_
+             .insert(
+                 {std::make_pair(field.extendee().substr(1), field.number()),
+                  value})
+             .second) {
       GOOGLE_LOG(ERROR) << "Extension conflicts with extension already in database: "
                     "extend "
                  << field.extendee() << " { " << field.name() << " = "
@@ -292,7 +295,9 @@
 template <typename Value>
 Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindFile(
     const std::string& filename) {
-  return FindWithDefault(by_name_, filename, Value());
+  auto it = by_name_.find(filename);
+  if (it == by_name_.end()) return {};
+  return it->second;
 }
 
 template <typename Value>
@@ -308,8 +313,9 @@
 template <typename Value>
 Value SimpleDescriptorDatabase::DescriptorIndex<Value>::FindExtension(
     const std::string& containing_type, int field_number) {
-  return FindWithDefault(
-      by_extension_, std::make_pair(containing_type, field_number), Value());
+  auto it = by_extension_.find({containing_type, field_number});
+  if (it == by_extension_.end()) return {};
+  return it->second;
 }
 
 template <typename Value>
@@ -352,6 +358,10 @@
   return index_.AddFile(*file, file);
 }
 
+bool SimpleDescriptorDatabase::AddUnowned(const FileDescriptorProto* file) {
+  return index_.AddFile(*file, file);
+}
+
 bool SimpleDescriptorDatabase::FindFileByName(const std::string& filename,
                                               FileDescriptorProto* output) {
   return MaybeCopy(index_.FindFile(filename), output);
@@ -397,24 +407,24 @@
   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,
+  Value FindFile(absl::string_view filename);
+  Value FindSymbol(absl::string_view name);
+  Value FindSymbolOnlyFlat(absl::string_view name) const;
+  Value FindExtension(absl::string_view containing_type, int field_number);
+  bool FindAllExtensionNumbers(absl::string_view containing_type,
                                std::vector<int>* output);
   void FindAllFileNames(std::vector<std::string>* output) const;
 
  private:
   friend class EncodedDescriptorDatabase;
 
-  bool AddSymbol(StringPiece symbol);
+  bool AddSymbol(absl::string_view symbol);
 
   template <typename DescProto>
-  bool AddNestedExtensions(StringPiece filename,
+  bool AddNestedExtensions(absl::string_view filename,
                            const DescProto& message_type);
   template <typename FieldProto>
-  bool AddExtension(StringPiece filename, const FieldProto& field);
+  bool AddExtension(absl::string_view filename, const FieldProto& field);
 
   // All the maps below have two representations:
   //  - a std::set<> where we insert initially.
@@ -427,8 +437,8 @@
 
   using String = std::string;
 
-  String EncodeString(StringPiece str) const { return String(str); }
-  StringPiece DecodeString(const String& str, int) const { return str; }
+  String EncodeString(absl::string_view str) const { return String(str); }
+  absl::string_view DecodeString(const String& str, int) const { return str; }
 
   struct EncodedEntry {
     // Do not use `Value` here to avoid the padding of that object.
@@ -445,7 +455,7 @@
     int data_offset;
     String encoded_name;
 
-    StringPiece name(const DescriptorIndex& index) const {
+    absl::string_view name(const DescriptorIndex& index) const {
       return index.DecodeString(encoded_name, data_offset);
     }
   };
@@ -455,10 +465,10 @@
     bool operator()(const FileEntry& a, const FileEntry& b) const {
       return a.name(index) < b.name(index);
     }
-    bool operator()(const FileEntry& a, StringPiece b) const {
+    bool operator()(const FileEntry& a, absl::string_view b) const {
       return a.name(index) < b;
     }
-    bool operator()(StringPiece a, const FileEntry& b) const {
+    bool operator()(absl::string_view a, const FileEntry& b) const {
       return a < b.name(index);
     }
   };
@@ -469,17 +479,17 @@
     int data_offset;
     String encoded_symbol;
 
-    StringPiece package(const DescriptorIndex& index) const {
+    absl::string_view package(const DescriptorIndex& index) const {
       return index.DecodeString(index.all_values_[data_offset].encoded_package,
                                 data_offset);
     }
-    StringPiece symbol(const DescriptorIndex& index) const {
+    absl::string_view 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));
+      return absl::StrCat(p, p.empty() ? "" : ".", symbol(index));
     }
   };
 
@@ -489,16 +499,16 @@
     std::string AsString(const SymbolEntry& entry) const {
       return entry.AsString(index);
     }
-    static StringPiece AsString(StringPiece str) { return str; }
+    static absl::string_view AsString(absl::string_view str) { return str; }
 
-    std::pair<StringPiece, StringPiece> GetParts(
+    std::pair<absl::string_view, absl::string_view> GetParts(
         const SymbolEntry& entry) const {
       auto package = entry.package(index);
-      if (package.empty()) return {entry.symbol(index), StringPiece{}};
+      if (package.empty()) return {entry.symbol(index), absl::string_view{}};
       return {package, entry.symbol(index)};
     }
-    std::pair<StringPiece, StringPiece> GetParts(
-        StringPiece str) const {
+    std::pair<absl::string_view, absl::string_view> GetParts(
+        absl::string_view str) const {
       return {str, {}};
     }
 
@@ -525,7 +535,7 @@
   struct ExtensionEntry {
     int data_offset;
     String encoded_extendee;
-    StringPiece extendee(const DescriptorIndex& index) const {
+    absl::string_view extendee(const DescriptorIndex& index) const {
       return index.DecodeString(encoded_extendee, data_offset).substr(1);
     }
     int extension_number;
@@ -538,10 +548,10 @@
              std::make_tuple(b.extendee(index), b.extension_number);
     }
     bool operator()(const ExtensionEntry& a,
-                    std::tuple<StringPiece, int> b) const {
+                    std::tuple<absl::string_view, int> b) const {
       return std::make_tuple(a.extendee(index), a.extension_number) < b;
     }
-    bool operator()(std::tuple<StringPiece, int> a,
+    bool operator()(std::tuple<absl::string_view, int> a,
                     const ExtensionEntry& b) const {
       return a < std::make_tuple(b.extendee(index), b.extension_number);
     }
@@ -634,9 +644,10 @@
   }
   all_values_.back().encoded_package = EncodeString(file.package());
 
-  if (!InsertIfNotPresent(
-          &by_name_, FileEntry{static_cast<int>(all_values_.size() - 1),
-                               EncodeString(file.name())}) ||
+  if (!by_name_
+           .insert({static_cast<int>(all_values_.size() - 1),
+                    EncodeString(file.name())})
+           .second ||
       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();
@@ -662,7 +673,7 @@
 }
 
 template <typename Iter, typename Iter2, typename Index>
-static bool CheckForMutualSubsymbols(StringPiece symbol_name, Iter* iter,
+static bool CheckForMutualSubsymbols(absl::string_view symbol_name, Iter* iter,
                                      Iter2 end, const Index& index) {
   if (*iter != end) {
     if (IsSubSymbol((*iter)->AsString(index), symbol_name)) {
@@ -690,7 +701,7 @@
 }
 
 bool EncodedDescriptorDatabase::DescriptorIndex::AddSymbol(
-    StringPiece symbol) {
+    absl::string_view symbol) {
   SymbolEntry entry = {static_cast<int>(all_values_.size() - 1),
                        EncodeString(symbol)};
   std::string entry_as_string = entry.AsString(*this);
@@ -730,7 +741,7 @@
 
 template <typename DescProto>
 bool EncodedDescriptorDatabase::DescriptorIndex::AddNestedExtensions(
-    StringPiece filename, const DescProto& message_type) {
+    absl::string_view filename, const DescProto& message_type) {
   for (const auto& nested_type : message_type.nested_type()) {
     if (!AddNestedExtensions(filename, nested_type)) return false;
   }
@@ -742,14 +753,14 @@
 
 template <typename FieldProto>
 bool EncodedDescriptorDatabase::DescriptorIndex::AddExtension(
-    StringPiece filename, const FieldProto& field) {
+    absl::string_view 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()}) ||
+    if (!by_extension_
+             .insert({static_cast<int>(all_values_.size() - 1),
+                      EncodeString(field.extendee()), field.number()})
+             .second ||
         std::binary_search(
             by_extension_flat_.begin(), by_extension_flat_.end(),
             std::make_pair(field.extendee().substr(1), field.number()),
@@ -769,14 +780,14 @@
 }
 
 std::pair<const void*, int>
-EncodedDescriptorDatabase::DescriptorIndex::FindSymbol(StringPiece name) {
+EncodedDescriptorDatabase::DescriptorIndex::FindSymbol(absl::string_view name) {
   EnsureFlat();
   return FindSymbolOnlyFlat(name);
 }
 
 std::pair<const void*, int>
 EncodedDescriptorDatabase::DescriptorIndex::FindSymbolOnlyFlat(
-    StringPiece name) const {
+    absl::string_view name) const {
   auto iter =
       FindLastLessOrEqual(&by_symbol_flat_, name, by_symbol_.key_comp());
 
@@ -788,7 +799,7 @@
 
 std::pair<const void*, int>
 EncodedDescriptorDatabase::DescriptorIndex::FindExtension(
-    StringPiece containing_type, int field_number) {
+    absl::string_view containing_type, int field_number) {
   EnsureFlat();
 
   auto it = std::lower_bound(
@@ -820,7 +831,7 @@
 }
 
 bool EncodedDescriptorDatabase::DescriptorIndex::FindAllExtensionNumbers(
-    StringPiece containing_type, std::vector<int>* output) {
+    absl::string_view containing_type, std::vector<int>* output) {
   EnsureFlat();
 
   bool success = false;
@@ -853,7 +864,7 @@
 
 std::pair<const void*, int>
 EncodedDescriptorDatabase::DescriptorIndex::FindFile(
-    StringPiece filename) {
+    absl::string_view filename) {
   EnsureFlat();
 
   auto it = std::lower_bound(by_name_flat_.begin(), by_name_flat_.end(),
diff --git a/src/google/protobuf/descriptor_database.h b/src/google/protobuf/descriptor_database.h
index f4f06bb..942f975 100644
--- a/src/google/protobuf/descriptor_database.h
+++ b/src/google/protobuf/descriptor_database.h
@@ -43,11 +43,11 @@
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -74,6 +74,8 @@
 class PROTOBUF_EXPORT DescriptorDatabase {
  public:
   inline DescriptorDatabase() {}
+  DescriptorDatabase(const DescriptorDatabase&) = delete;
+  DescriptorDatabase& operator=(const DescriptorDatabase&) = delete;
   virtual ~DescriptorDatabase();
 
   // Find a file by file name.  Fills in in *output and returns true if found.
@@ -136,9 +138,6 @@
   // searching all message names, otherwise returns false and leaves output
   // unchanged.
   bool FindAllMessageNames(std::vector<std::string>* output);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorDatabase);
 };
 
 // A DescriptorDatabase into which you can insert files manually.
@@ -165,6 +164,8 @@
 class PROTOBUF_EXPORT SimpleDescriptorDatabase : public DescriptorDatabase {
  public:
   SimpleDescriptorDatabase();
+  SimpleDescriptorDatabase(const SimpleDescriptorDatabase&) = delete;
+  SimpleDescriptorDatabase& operator=(const SimpleDescriptorDatabase&) = delete;
   ~SimpleDescriptorDatabase() override;
 
   // Adds the FileDescriptorProto to the database, making a copy.  The object
@@ -176,6 +177,10 @@
   // Adds the FileDescriptorProto to the database and takes ownership of it.
   bool AddAndOwn(const FileDescriptorProto* file);
 
+  // Adds the FileDescriptorProto to the database and not take ownership of it.
+  // The owner must ensure file outlives the SimpleDescriptorDatabase.
+  bool AddUnowned(const FileDescriptorProto* file);
+
   // implements DescriptorDatabase -----------------------------------
   bool FindFileByName(const std::string& filename,
                       FileDescriptorProto* output) override;
@@ -274,8 +279,6 @@
   // If file is non-nullptr, copy it into *output and return true, otherwise
   // return false.
   bool MaybeCopy(const FileDescriptorProto* file, FileDescriptorProto* output);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SimpleDescriptorDatabase);
 };
 
 // Very similar to SimpleDescriptorDatabase, but stores all the descriptors
@@ -286,6 +289,9 @@
 class PROTOBUF_EXPORT EncodedDescriptorDatabase : public DescriptorDatabase {
  public:
   EncodedDescriptorDatabase();
+  EncodedDescriptorDatabase(const EncodedDescriptorDatabase&) = delete;
+  EncodedDescriptorDatabase& operator=(const EncodedDescriptorDatabase&) =
+      delete;
   ~EncodedDescriptorDatabase() override;
 
   // Adds the FileDescriptorProto to the database.  The descriptor is provided
@@ -327,14 +333,14 @@
   // return true, otherwise return false.
   bool MaybeParse(std::pair<const void*, int> encoded_file,
                   FileDescriptorProto* output);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(EncodedDescriptorDatabase);
 };
 
 // A DescriptorDatabase that fetches files from a given pool.
 class PROTOBUF_EXPORT DescriptorPoolDatabase : public DescriptorDatabase {
  public:
   explicit DescriptorPoolDatabase(const DescriptorPool& pool);
+  DescriptorPoolDatabase(const DescriptorPoolDatabase&) = delete;
+  DescriptorPoolDatabase& operator=(const DescriptorPoolDatabase&) = delete;
   ~DescriptorPoolDatabase() override;
 
   // implements DescriptorDatabase -----------------------------------
@@ -350,7 +356,6 @@
 
  private:
   const DescriptorPool& pool_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DescriptorPoolDatabase);
 };
 
 // A DescriptorDatabase that wraps two or more others.  It first searches the
@@ -365,6 +370,8 @@
   // DescriptorDatabases need to stick around.
   explicit MergedDescriptorDatabase(
       const std::vector<DescriptorDatabase*>& sources);
+  MergedDescriptorDatabase(const MergedDescriptorDatabase&) = delete;
+  MergedDescriptorDatabase& operator=(const MergedDescriptorDatabase&) = delete;
   ~MergedDescriptorDatabase() override;
 
   // implements DescriptorDatabase -----------------------------------
@@ -387,12 +394,11 @@
 
  private:
   std::vector<DescriptorDatabase*> sources_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MergedDescriptorDatabase);
 };
 
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_DESCRIPTOR_DATABASE_H__
diff --git a/src/google/protobuf/descriptor_database_unittest.cc b/src/google/protobuf/descriptor_database_unittest.cc
index f582448..d06d0c0 100644
--- a/src/google/protobuf/descriptor_database_unittest.cc
+++ b/src/google/protobuf/descriptor_database_unittest.cc
@@ -34,18 +34,18 @@
 //
 // This file makes extensive use of RFC 3092.  :)
 
-#include <google/protobuf/descriptor_database.h>
+#include "google/protobuf/descriptor_database.h"
 
 #include <algorithm>
 #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/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 "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
 
 
@@ -572,6 +572,29 @@
   EXPECT_THAT(messages, ::testing::UnorderedElementsAre("foo.Foo", "Bar"));
 }
 
+TEST(SimpleDescriptorDatabaseExtraTest, AddUnowned) {
+  FileDescriptorProto f;
+  f.set_name("foo.proto");
+  f.set_package("foo");
+  f.add_message_type()->set_name("Foo");
+
+  FileDescriptorProto b;
+  b.set_name("bar.proto");
+  b.set_package("");
+  b.add_message_type()->set_name("Bar");
+
+  SimpleDescriptorDatabase db;
+  db.AddUnowned(&f);
+  db.AddUnowned(&b);
+
+  std::vector<std::string> packages;
+  EXPECT_TRUE(db.FindAllPackageNames(&packages));
+  EXPECT_THAT(packages, ::testing::UnorderedElementsAre("foo", ""));
+  std::vector<std::string> messages;
+  EXPECT_TRUE(db.FindAllMessageNames(&messages));
+  EXPECT_THAT(messages, ::testing::UnorderedElementsAre("foo.Foo", "Bar"));
+}
+
 // ===================================================================
 
 class MergedDescriptorDatabaseTest : public testing::Test {
diff --git a/src/google/protobuf/descriptor_unittest.cc b/src/google/protobuf/descriptor_unittest.cc
index dc47531..dff1581 100644
--- a/src/google/protobuf/descriptor_unittest.cc
+++ b/src/google/protobuf/descriptor_unittest.cc
@@ -38,33 +38,33 @@
 #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/stringprintf.h>
-#include <google/protobuf/unittest_lazy_dependencies.pb.h>
-#include <google/protobuf/unittest_proto3_arena.pb.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor_database.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/any.pb.h"
+#include "google/protobuf/compiler/importer.h"
+#include "google/protobuf/compiler/parser.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "absl/strings/str_format.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/descriptor.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor_database.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/text_format.h"
 #include <gmock/gmock.h>
-#include <google/protobuf/testing/googletest.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/stubs/logging.h"
+#include "google/protobuf/unittest_lazy_dependencies.pb.h"
+#include "google/protobuf/unittest_lazy_dependencies_custom_option.pb.h"
+#include "google/protobuf/unittest_lazy_dependencies_enum.pb.h"
+#include "google/protobuf/unittest_proto3_arena.pb.h"
+#include "absl/strings/substitute.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 using ::testing::AnyOf;
 
@@ -247,7 +247,7 @@
         break;
     }
 
-    strings::SubstituteAndAppend(&text_, "$0: $1: $2: $3\n", filename,
+    absl::SubstituteAndAppend(&text_, "$0: $1: $2: $3\n", filename,
                               element_name, location_name, message);
   }
 
@@ -292,7 +292,7 @@
         break;
     }
 
-    strings::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", filename,
+    absl::SubstituteAndAppend(&warning_text_, "$0: $1: $2: $3\n", filename,
                               element_name, location_name, message);
   }
 };
@@ -553,6 +553,29 @@
   }
 }
 
+TEST_F(FileDescriptorTest, CopyHeadingTo) {
+  FileDescriptorProto proto;
+  proto.set_name("foo.proto");
+  proto.set_package("foo.bar.baz");
+  proto.set_syntax("proto3");
+  proto.mutable_options()->set_java_package("foo.bar.baz");
+
+  // Won't be copied.
+  proto.add_message_type()->set_name("Foo");
+
+  DescriptorPool pool;
+  const FileDescriptor* file = pool.BuildFile(proto);
+  ASSERT_NE(file, nullptr);
+
+  FileDescriptorProto other;
+  file->CopyHeadingTo(&other);
+  EXPECT_EQ(other.name(), "foo.proto");
+  EXPECT_EQ(other.package(), "foo.bar.baz");
+  EXPECT_EQ(other.syntax(), "proto3");
+  EXPECT_EQ(other.options().java_package(), "foo.bar.baz");
+  EXPECT_TRUE(other.message_type().empty());
+}
+
 void ExtractDebugString(
     const FileDescriptor* file, std::set<std::string>* visited,
     std::vector<std::pair<std::string, std::string>>* debug_strings) {
@@ -569,7 +592,7 @@
  public:
   // implements ErrorCollector ---------------------------------------
   void AddError(int line, int column, const std::string& message) override {
-    last_error_ = StringPrintf("%d:%d:", line, column) + message;
+    last_error_ = absl::StrFormat("%d:%d:%s", line, column, message);
   }
 
   const std::string& last_error() { return last_error_; }
@@ -1063,6 +1086,34 @@
   EXPECT_TRUE(baz_->is_repeated());
 }
 
+TEST_F(DescriptorTest, NeedsUtf8Check) {
+  EXPECT_FALSE(foo_->requires_utf8_validation());
+  EXPECT_FALSE(bar_->requires_utf8_validation());
+
+  // Build a copy of the file in proto3.
+  FileDescriptorProto foo_file3;
+  foo_file_->CopyTo(&foo_file3);
+  foo_file3.set_syntax("proto3");
+
+  // Make this valid proto3 by removing `required` and the one group field.
+  for (auto& f : *foo_file3.mutable_message_type(1)->mutable_field()) {
+    f.clear_label();
+    if (f.type() == FieldDescriptorProto::TYPE_GROUP) {
+      f.set_type(FieldDescriptorProto::TYPE_MESSAGE);
+    }
+  }
+  // Make this valid proto3 by making the first enum value be zero.
+  foo_file3.mutable_enum_type(0)->mutable_value(0)->set_number(0);
+
+  DescriptorPool pool3;
+  const Descriptor* message3 = pool3.BuildFile(foo_file3)->message_type(1);
+  const FieldDescriptor* foo3 = message3->field(0);
+  const FieldDescriptor* bar3 = message3->field(1);
+
+  EXPECT_TRUE(foo3->requires_utf8_validation());
+  EXPECT_FALSE(bar3->requires_utf8_validation());
+}
+
 TEST_F(DescriptorTest, IsMap) {
   EXPECT_TRUE(map_->is_map());
   EXPECT_FALSE(baz_->is_map());
@@ -1535,6 +1586,23 @@
   EXPECT_EQ(enum2_, baz2_->type());
 }
 
+TEST_F(EnumDescriptorTest, IsClosed) {
+  // enum_ is proto2.
+  EXPECT_TRUE(enum_->is_closed());
+
+  // Make a proto3 version of enum_.
+  FileDescriptorProto foo_file3;
+  foo_file_->CopyTo(&foo_file3);
+  foo_file3.set_syntax("proto3");
+
+  // Make this valid proto3 by making the first enum value be zero.
+  foo_file3.mutable_enum_type(0)->mutable_value(0)->set_number(0);
+
+  DescriptorPool pool3;
+  const EnumDescriptor* enum3 = pool3.BuildFile(foo_file3)->enum_type(0);
+  EXPECT_FALSE(enum3->is_closed());
+}
+
 // ===================================================================
 
 // Test service descriptors.
@@ -2706,15 +2774,19 @@
       ->set_default_value("hello");
   AddField(message_proto, "data", 9, label, FD::TYPE_BYTES)
       ->set_default_value("\\001\\002\\003");
+  AddField(message_proto, "data2", 10, label, FD::TYPE_BYTES)
+      ->set_default_value("\\X01\\X2\\X3");
+  AddField(message_proto, "data3", 11, label, FD::TYPE_BYTES)
+      ->set_default_value("\\x01\\x2\\x3");
 
   FieldDescriptorProto* enum_field =
-      AddField(message_proto, "enum", 10, label, FD::TYPE_ENUM);
+      AddField(message_proto, "enum", 12, label, FD::TYPE_ENUM);
   enum_field->set_type_name("DummyEnum");
   enum_field->set_default_value("B");
 
   // Strings are allowed to have empty defaults.  (At one point, due to
   // a bug, empty defaults for strings were rejected.  Oops.)
-  AddField(message_proto, "empty_string", 11, label, FD::TYPE_STRING)
+  AddField(message_proto, "empty_string", 13, label, FD::TYPE_STRING)
       ->set_default_value("");
 
   // Add a second set of fields with implicit default values.
@@ -2744,7 +2816,7 @@
   ASSERT_EQ(1, file->message_type_count());
   const Descriptor* message = file->message_type(0);
 
-  ASSERT_EQ(21, message->field_count());
+  ASSERT_EQ(23, message->field_count());
 
   // Check the default values.
   ASSERT_TRUE(message->field(0)->has_default_value());
@@ -2758,6 +2830,8 @@
   ASSERT_TRUE(message->field(8)->has_default_value());
   ASSERT_TRUE(message->field(9)->has_default_value());
   ASSERT_TRUE(message->field(10)->has_default_value());
+  ASSERT_TRUE(message->field(11)->has_default_value());
+  ASSERT_TRUE(message->field(12)->has_default_value());
 
   EXPECT_EQ(-1, message->field(0)->default_value_int32());
   EXPECT_EQ(int64_t{-1000000000000}, message->field(1)->default_value_int64());
@@ -2768,11 +2842,11 @@
   EXPECT_TRUE(message->field(6)->default_value_bool());
   EXPECT_EQ("hello", message->field(7)->default_value_string());
   EXPECT_EQ("\001\002\003", message->field(8)->default_value_string());
-  EXPECT_EQ(enum_value_b, message->field(9)->default_value_enum());
-  EXPECT_EQ("", message->field(10)->default_value_string());
+  EXPECT_EQ("\001\002\003", message->field(9)->default_value_string());
+  EXPECT_EQ("\001\002\003", message->field(10)->default_value_string());
+  EXPECT_EQ(enum_value_b, message->field(11)->default_value_enum());
+  EXPECT_EQ("", message->field(12)->default_value_string());
 
-  ASSERT_FALSE(message->field(11)->has_default_value());
-  ASSERT_FALSE(message->field(12)->has_default_value());
   ASSERT_FALSE(message->field(13)->has_default_value());
   ASSERT_FALSE(message->field(14)->has_default_value());
   ASSERT_FALSE(message->field(15)->has_default_value());
@@ -2781,17 +2855,19 @@
   ASSERT_FALSE(message->field(18)->has_default_value());
   ASSERT_FALSE(message->field(19)->has_default_value());
   ASSERT_FALSE(message->field(20)->has_default_value());
+  ASSERT_FALSE(message->field(21)->has_default_value());
+  ASSERT_FALSE(message->field(22)->has_default_value());
 
-  EXPECT_EQ(0, message->field(11)->default_value_int32());
-  EXPECT_EQ(0, message->field(12)->default_value_int64());
-  EXPECT_EQ(0, message->field(13)->default_value_uint32());
-  EXPECT_EQ(0, message->field(14)->default_value_uint64());
-  EXPECT_EQ(0.0f, message->field(15)->default_value_float());
-  EXPECT_EQ(0.0, message->field(16)->default_value_double());
-  EXPECT_FALSE(message->field(17)->default_value_bool());
-  EXPECT_EQ("", message->field(18)->default_value_string());
-  EXPECT_EQ("", message->field(19)->default_value_string());
-  EXPECT_EQ(enum_value_a, message->field(20)->default_value_enum());
+  EXPECT_EQ(0, message->field(13)->default_value_int32());
+  EXPECT_EQ(0, message->field(14)->default_value_int64());
+  EXPECT_EQ(0, message->field(15)->default_value_uint32());
+  EXPECT_EQ(0, message->field(16)->default_value_uint64());
+  EXPECT_EQ(0.0f, message->field(17)->default_value_float());
+  EXPECT_EQ(0.0, message->field(18)->default_value_double());
+  EXPECT_FALSE(message->field(19)->default_value_bool());
+  EXPECT_EQ("", message->field(20)->default_value_string());
+  EXPECT_EQ("", message->field(21)->default_value_string());
+  EXPECT_EQ(enum_value_a, message->field(22)->default_value_enum());
 }
 
 TEST_F(MiscTest, FieldOptions) {
@@ -4244,7 +4320,7 @@
 }
 
 TEST_F(ValidationErrorTest, DebugStringReservedRangeMax) {
-  const FileDescriptor* file = BuildFile(strings::Substitute(
+  const FileDescriptor* file = BuildFile(absl::Substitute(
       "name: \"foo.proto\" "
       "enum_type { "
       "  name: \"Bar\""
@@ -5294,8 +5370,7 @@
       "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
       "}",
 
-      "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n"
-  );
+      "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not defined.\n");
 }
 
 TEST_F(ValidationErrorTest, InputTypeNotAMessage) {
@@ -5308,8 +5383,7 @@
       "  method { name: \"A\" input_type: \"Bar\" output_type: \"Foo\" }"
       "}",
 
-      "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n"
-  );
+      "foo.proto: TestService.A: INPUT_TYPE: \"Bar\" is not a message type.\n");
 }
 
 TEST_F(ValidationErrorTest, OutputTypeNotDefined) {
@@ -5321,8 +5395,7 @@
       "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
       "}",
 
-      "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n"
-  );
+      "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not defined.\n");
 }
 
 TEST_F(ValidationErrorTest, OutputTypeNotAMessage) {
@@ -5335,8 +5408,8 @@
       "  method { name: \"A\" input_type: \"Foo\" output_type: \"Bar\" }"
       "}",
 
-      "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message type.\n"
-  );
+      "foo.proto: TestService.A: OUTPUT_TYPE: \"Bar\" is not a message "
+      "type.\n");
 }
 
 
@@ -5557,7 +5630,7 @@
       "                                 positive_int_value: 0x80000000 } "
       "}",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+      "foo.proto: foo.proto: OPTION_VALUE: Value out of range, -2147483648 to 2147483647, "
       "for int32 option \"foo\".\n");
 }
 
@@ -5574,7 +5647,7 @@
       "                                 negative_int_value: -0x80000001 } "
       "}",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+      "foo.proto: foo.proto: OPTION_VALUE: Value out of range, -2147483648 to 2147483647, "
       "for int32 option \"foo\".\n");
 }
 
@@ -5590,7 +5663,7 @@
       "                                        is_extension: true } "
       "                                 string_value: \"5\" } }",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
+      "foo.proto: foo.proto: OPTION_VALUE: Value must be integer, from -2147483648 to 2147483647, "
       "for int32 option \"foo\".\n");
 }
 
@@ -5608,7 +5681,7 @@
       "} "
       "}",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+      "foo.proto: foo.proto: OPTION_VALUE: Value out of range, -9223372036854775808 to 9223372036854775807, "
       "for int64 option \"foo\".\n");
 }
 
@@ -5624,7 +5697,7 @@
       "                                        is_extension: true } "
       "                                 identifier_value: \"5\" } }",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value must be integer "
+      "foo.proto: foo.proto: OPTION_VALUE: Value must be integer, from -9223372036854775808 to 9223372036854775807, "
       "for int64 option \"foo\".\n");
 }
 
@@ -5640,7 +5713,7 @@
       "                                        is_extension: true } "
       "                                 positive_int_value: 0x100000000 } }",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value out of range "
+      "foo.proto: foo.proto: OPTION_VALUE: Value out of range, 0 to 4294967295, "
       "for uint32 option \"foo\".\n");
 }
 
@@ -5656,7 +5729,7 @@
       "                                        is_extension: true } "
       "                                 double_value: -5.6 } }",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
+      "foo.proto: foo.proto: OPTION_VALUE: Value must be integer, from 0 to 4294967295, "
       "for uint32 option \"foo\".\n");
 }
 
@@ -5672,7 +5745,7 @@
       "                                        is_extension: true } "
       "                                 negative_int_value: -5 } }",
 
-      "foo.proto: foo.proto: OPTION_VALUE: Value must be non-negative integer "
+      "foo.proto: foo.proto: OPTION_VALUE: Value must be integer, from 0 to 18446744073709551615, "
       "for uint64 option \"foo\".\n");
 }
 
@@ -5844,7 +5917,7 @@
 // errors.  The "value" argument is embedded inside the
 // "uninterpreted_option" portion of the result.
 static std::string EmbedAggregateValue(const char* value) {
-  return strings::Substitute(
+  return absl::Substitute(
       "name: \"foo.proto\" "
       "dependency: \"google/protobuf/descriptor.proto\" "
       "message_type { name: \"Foo\" } "
@@ -5968,8 +6041,8 @@
       "  }"
       "}",
 
-      "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not defined.\n"
-  );
+      "foo.proto: TestService.Baz: INPUT_TYPE: \"NoSuchType\" is not "
+      "defined.\n");
 
   // Make sure that if we build the same file again with the error fixed,
   // it works.  If the above rollback was incomplete, then some symbols will
@@ -6129,7 +6202,9 @@
 TEST_F(ValidationErrorTest, MapEntryBase) {
   FileDescriptorProto file_proto;
   FillValidMapEntry(&file_proto);
-  BuildFile(file_proto.DebugString());
+  std::string text_proto;
+  TextFormat::PrintToString(file_proto, &text_proto);
+  BuildFile(text_proto);
 }
 
 TEST_F(ValidationErrorTest, MapEntryExtensionRange) {
@@ -7323,34 +7398,29 @@
   }
 
  private:
-  void FullMatch(const std::string& name, const std::string& begin_with,
-                 const std::string& end_with, int* file_num) {
-    int begin_size = begin_with.size();
-    int end_size = end_with.size();
-    if (name.substr(0, begin_size) != begin_with ||
-        name.substr(name.size() - end_size, end_size) != end_with) {
-      return;
-    }
-    safe_strto32(
-        name.substr(begin_size, name.size() - end_size - begin_size), file_num);
+  void FullMatch(absl::string_view name, absl::string_view begin_with,
+                 absl::string_view end_with, int32_t* file_num) {
+    if (!absl::ConsumePrefix(&name, begin_with)) return;
+    if (!absl::ConsumeSuffix(&name, end_with)) return;
+    GOOGLE_CHECK(absl::SimpleAtoi(name, file_num));
   }
 
   bool PopulateFile(int file_num, FileDescriptorProto* output) {
     GOOGLE_CHECK_GE(file_num, 0);
     output->Clear();
-    output->set_name(strings::Substitute("file$0.proto", file_num));
+    output->set_name(absl::Substitute("file$0.proto", file_num));
     // file0.proto doesn't define Message0
     if (file_num > 0) {
       DescriptorProto* message = output->add_message_type();
-      message->set_name(strings::Substitute("Message$0", file_num));
+      message->set_name(absl::Substitute("Message$0", file_num));
       for (int i = 0; i < file_num; ++i) {
-        output->add_dependency(strings::Substitute("file$0.proto", i));
+        output->add_dependency(absl::Substitute("file$0.proto", i));
         FieldDescriptorProto* field = message->add_field();
-        field->set_name(strings::Substitute("field$0", i));
+        field->set_name(absl::Substitute("field$0", i));
         field->set_number(i);
         field->set_label(FieldDescriptorProto::LABEL_OPTIONAL);
         field->set_type(FieldDescriptorProto::TYPE_MESSAGE);
-        field->set_type_name(strings::Substitute("Message$0", i));
+        field->set_type_name(absl::Substitute("Message$0", i));
       }
     }
     return true;
@@ -7400,6 +7470,8 @@
 class AbortingErrorCollector : public DescriptorPool::ErrorCollector {
  public:
   AbortingErrorCollector() {}
+  AbortingErrorCollector(const AbortingErrorCollector&) = delete;
+  AbortingErrorCollector& operator=(const AbortingErrorCollector&) = delete;
 
   void AddError(const std::string& filename, const std::string& element_name,
                 const Message* message, ErrorLocation location,
@@ -7407,9 +7479,6 @@
     GOOGLE_LOG(FATAL) << "AddError() called unexpectedly: " << filename << " ["
                << element_name << "]: " << error_message;
   }
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(AbortingErrorCollector);
 };
 
 // A source tree containing only one file.
@@ -7417,8 +7486,10 @@
  public:
   SingletonSourceTree(const std::string& filename, const std::string& contents)
       : filename_(filename), contents_(contents) {}
+  SingletonSourceTree(const SingletonSourceTree&) = delete;
+  SingletonSourceTree& operator=(const SingletonSourceTree&) = delete;
 
-  io::ZeroCopyInputStream* Open(const std::string& filename) override {
+  io::ZeroCopyInputStream* Open(absl::string_view filename) override {
     return filename == filename_
                ? new io::ArrayInputStream(contents_.data(), contents_.size())
                : nullptr;
@@ -7427,8 +7498,6 @@
  private:
   const std::string filename_;
   const std::string contents_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(SingletonSourceTree);
 };
 
 const char* const kSourceLocationTestInput =
@@ -7523,7 +7592,7 @@
   }
 
   static std::string PrintSourceLocation(const SourceLocation& loc) {
-    return strings::Substitute("$0:$1-$2:$3", 1 + loc.start_line,
+    return absl::Substitute("$0:$1-$2:$3", 1 + loc.start_line,
                             1 + loc.start_column, 1 + loc.end_line,
                             1 + loc.end_column);
   }
@@ -8427,4 +8496,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/drop_unknown_fields_test.cc b/src/google/protobuf/drop_unknown_fields_test.cc
index 55c6b67..bcb7b2b 100644
--- a/src/google/protobuf/drop_unknown_fields_test.cc
+++ b/src/google/protobuf/drop_unknown_fields_test.cc
@@ -30,10 +30,10 @@
 
 #include <memory>
 
-#include <google/protobuf/unittest_drop_unknown_fields.pb.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message_lite.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/unittest_drop_unknown_fields.pb.h"
 
 using unittest_drop_unknown_fields::Foo;
 using unittest_drop_unknown_fields::FooWithExtraFields;
diff --git a/src/google/protobuf/duration.pb.cc b/src/google/protobuf/duration.pb.cc
index 72766bd..79bf16c 100644
--- a/src/google/protobuf/duration.pb.cc
+++ b/src/google/protobuf/duration.pb.cc
@@ -1,88 +1,112 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/duration.proto
 
-#include <google/protobuf/duration.pb.h>
+#include "google/protobuf/duration.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR Duration::Duration(
     ::_pbi::ConstantInitialized): _impl_{
-    /*decltype(_impl_.seconds_)*/int64_t{0}
+    /*decltype(_impl_.seconds_)*/::int64_t{0}
   , /*decltype(_impl_.nanos_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct DurationDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR DurationDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR DurationDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~DurationDefaultTypeInternal() {}
   union {
     Duration _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DurationDefaultTypeInternal _Duration_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DurationDefaultTypeInternal _Duration_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fduration_2eproto[1];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fduration_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _impl_.seconds_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _impl_.nanos_),
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fduration_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _impl_.seconds_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Duration, _impl_.nanos_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Duration)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Duration)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_Duration_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Duration_default_instance_._instance,
 };
-
-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\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fduration_2eproto_once;
+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\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2fduration_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fduration_2eproto = {
-    false, false, 235, descriptor_table_protodef_google_2fprotobuf_2fduration_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fduration_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fduration_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fduration_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fduration_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fduration_2eproto(&descriptor_table_google_2fprotobuf_2fduration_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 class Duration::_Internal {
@@ -96,17 +120,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Duration)
 }
 Duration::Duration(const Duration& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  Duration* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.seconds_){}
-    , decltype(_impl_.nanos_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  ::memcpy(&_impl_.seconds_, &from._impl_.seconds_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.nanos_) -
-    reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_));
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Duration)
 }
 
@@ -115,7 +131,7 @@
   (void)arena;
   (void)is_message_owned;
   new (&_impl_) Impl_{
-      decltype(_impl_.seconds_){int64_t{0}}
+      decltype(_impl_.seconds_){::int64_t{0}}
     , decltype(_impl_.nanos_){0}
     , /*decltype(_impl_._cached_size_)*/{}
   };
@@ -140,37 +156,40 @@
 
 void Duration::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Duration)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  ::memset(&_impl_.seconds_, 0, static_cast<size_t>(
+  ::memset(&_impl_.seconds_, 0, static_cast<::size_t>(
       reinterpret_cast<char*>(&_impl_.nanos_) -
       reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_));
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Duration::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _impl_.seconds_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // int32 nanos = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _impl_.nanos_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -195,10 +214,11 @@
 #undef CHK_
 }
 
-uint8_t* Duration::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Duration::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Duration)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // int64 seconds = 1;
@@ -221,11 +241,12 @@
   return target;
 }
 
-size_t Duration::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration)
-  size_t total_size = 0;
+::size_t Duration::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Duration)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -252,9 +273,10 @@
 void Duration::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Duration*>(&to_msg);
   auto& from = static_cast<const Duration&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Duration)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (from._internal_seconds() != 0) {
@@ -289,11 +311,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Duration::GetMetadata() const {
+
   return ::_pbi::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
@@ -302,6 +324,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Duration >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/duration.pb.h b/src/google/protobuf/duration.pb.h
index e3d89b9..f3cb48b 100644
--- a/src/google/protobuf/duration.pb.h
+++ b/src/google/protobuf/duration.pb.h
@@ -1,38 +1,43 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/duration.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fduration_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -41,21 +46,25 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fduration_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct DurationDefaultTypeInternal;
 PROTOBUF_EXPORT extern DurationDefaultTypeInternal _Duration_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Duration* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Duration>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Duration* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Duration>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT Duration final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Duration) */ {
  public:
@@ -145,10 +154,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -159,7 +168,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Duration";
   }
   protected:
@@ -182,20 +191,20 @@
   };
   // int64 seconds = 1;
   void clear_seconds();
-  int64_t seconds() const;
-  void set_seconds(int64_t value);
+  ::int64_t seconds() const;
+  void set_seconds(::int64_t value);
   private:
-  int64_t _internal_seconds() const;
-  void _internal_set_seconds(int64_t value);
+  ::int64_t _internal_seconds() const;
+  void _internal_set_seconds(::int64_t value);
   public:
 
   // int32 nanos = 2;
   void clear_nanos();
-  int32_t nanos() const;
-  void set_nanos(int32_t value);
+  ::int32_t nanos() const;
+  void set_nanos(::int32_t value);
   private:
-  int32_t _internal_nanos() const;
-  void _internal_set_nanos(int32_t value);
+  ::int32_t _internal_nanos() const;
+  void _internal_set_nanos(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.Duration)
@@ -206,8 +215,8 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   struct Impl_ {
-    int64_t seconds_;
-    int32_t nanos_;
+    ::int64_t seconds_;
+    ::int32_t nanos_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
@@ -216,30 +225,35 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // Duration
 
 // int64 seconds = 1;
 inline void Duration::clear_seconds() {
-  _impl_.seconds_ = int64_t{0};
+  _impl_.seconds_ = ::int64_t{0};
 }
-inline int64_t Duration::_internal_seconds() const {
+inline ::int64_t Duration::_internal_seconds() const {
   return _impl_.seconds_;
 }
-inline int64_t Duration::seconds() const {
+inline ::int64_t Duration::seconds() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Duration.seconds)
   return _internal_seconds();
 }
-inline void Duration::_internal_set_seconds(int64_t value) {
-  
+inline void Duration::_internal_set_seconds(::int64_t value) {
+
   _impl_.seconds_ = value;
 }
-inline void Duration::set_seconds(int64_t value) {
+inline void Duration::set_seconds(::int64_t value) {
   _internal_set_seconds(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Duration.seconds)
 }
@@ -248,31 +262,32 @@
 inline void Duration::clear_nanos() {
   _impl_.nanos_ = 0;
 }
-inline int32_t Duration::_internal_nanos() const {
+inline ::int32_t Duration::_internal_nanos() const {
   return _impl_.nanos_;
 }
-inline int32_t Duration::nanos() const {
+inline ::int32_t Duration::nanos() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Duration.nanos)
   return _internal_nanos();
 }
-inline void Duration::_internal_set_nanos(int32_t value) {
-  
+inline void Duration::_internal_set_nanos(::int32_t value) {
+
   _impl_.nanos_ = value;
 }
-inline void Duration::set_nanos(int32_t value) {
+inline void Duration::set_nanos(::int32_t value) {
   _internal_set_nanos(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Duration.nanos)
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fduration_2eproto_2epb_2eh
diff --git a/src/google/protobuf/duration.proto b/src/google/protobuf/duration.proto
index 81c3e36..41f40c2 100644
--- a/src/google/protobuf/duration.proto
+++ b/src/google/protobuf/duration.proto
@@ -32,13 +32,13 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
 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;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 
 // A Duration represents a signed, fixed-length span of time represented
 // as a count of seconds and fractions of seconds at nanosecond
@@ -99,7 +99,6 @@
 // be expressed in JSON format as "3.000000001s", and 3 seconds and 1
 // microsecond should be expressed in JSON format as "3.000001s".
 //
-//
 message Duration {
   // Signed seconds of the span of time. Must be from -315,576,000,000
   // to +315,576,000,000 inclusive. Note: these bounds are computed from:
diff --git a/src/google/protobuf/dynamic_message.cc b/src/google/protobuf/dynamic_message.cc
index 1c96ca2..777ec17 100644
--- a/src/google/protobuf/dynamic_message.cc
+++ b/src/google/protobuf/dynamic_message.cc
@@ -62,31 +62,30 @@
 // Item 8 of "More Effective C++" discusses this in more detail, though
 // I don't have the book on me right now so I'm not sure.
 
-#include <google/protobuf/dynamic_message.h>
+#include "google/protobuf/dynamic_message.h"
 
 #include <algorithm>
 #include <cstddef>
 #include <memory>
 #include <new>
-#include <unordered_map>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/map_field_inl.h>
-#include <google/protobuf/map_type_handler.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/map_type_handler.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/wire_format.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -105,22 +104,6 @@
 
 bool IsMapFieldInApi(const FieldDescriptor* field) { return field->is_map(); }
 
-// Sync with helpers.h.
-inline bool HasHasbit(const FieldDescriptor* field) {
-  // This predicate includes proto3 message fields only if they have "optional".
-  //   Foo submsg1 = 1;           // HasHasbit() == false
-  //   optional Foo submsg2 = 2;  // HasHasbit() == true
-  // This is slightly odd, as adding "optional" to a singular proto3 field does
-  // not change the semantics or API. However whenever any field in a message
-  // has a hasbit, it forces reflection to include hasbit offsets for *all*
-  // fields, even if almost all of them are set to -1 (no hasbit). So to avoid
-  // causing a sudden size regression for ~all proto3 messages, we give proto3
-  // message fields a hasbit only if "optional" is present. If the user is
-  // explicitly writing "optional", it is likely they are writing it on
-  // primitive fields also.
-  return (field->has_optional_keyword() || field->is_required()) &&
-         !field->options().weak();
-}
 
 inline bool InRealOneof(const FieldDescriptor* field) {
   return field->containing_oneof() &&
@@ -224,6 +207,8 @@
 
   // This should only be used by GetPrototypeNoLock() to avoid dead lock.
   DynamicMessage(DynamicMessageFactory::TypeInfo* type_info, bool lock_factory);
+  DynamicMessage(const DynamicMessage&) = delete;
+  DynamicMessage& operator=(const DynamicMessage&) = delete;
 
   ~DynamicMessage() override;
 
@@ -285,7 +270,6 @@
 
   const DynamicMessageFactory::TypeInfo* type_info_;
   mutable std::atomic<int> cached_byte_size_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessage);
 };
 
 struct DynamicMessageFactory::TypeInfo {
@@ -313,7 +297,21 @@
 
   TypeInfo() : prototype(nullptr) {}
 
-  ~TypeInfo() { delete prototype; }
+  ~TypeInfo() {
+    delete prototype;
+
+    // Scribble the payload to prevent unsanitized opt builds from silently
+    // allowing use-after-free bugs where the factory is destroyed but the
+    // DynamicMessage instances are still used.
+    // This is a common bug with DynamicMessageFactory.
+    // NOTE: This must happen after deleting the prototype.
+    if (offsets != nullptr) {
+      std::fill_n(offsets.get(), type->field_count(), 0xCDCDCDCDu);
+    }
+    if (has_bits_indices != nullptr) {
+      std::fill_n(has_bits_indices.get(), type->field_count(), 0xCDCDCDCDu);
+    }
+  }
 };
 
 DynamicMessage::DynamicMessage(const DynamicMessageFactory::TypeInfo* type_info)
@@ -653,7 +651,7 @@
 }
 
 const Message* DynamicMessageFactory::GetPrototype(const Descriptor* type) {
-  MutexLock lock(&prototypes_mutex_);
+  absl::MutexLock lock(&prototypes_mutex_);
   return GetPrototypeNoLock(type);
 }
 
@@ -705,7 +703,7 @@
   type_info->has_bits_offset = -1;
   int max_hasbit = 0;
   for (int i = 0; i < type->field_count(); i++) {
-    if (HasHasbit(type->field(i))) {
+    if (internal::cpp::HasHasbit(type->field(i))) {
       if (type_info->has_bits_offset == -1) {
         // At least one field in the message requires a hasbit, so allocate
         // hasbits.
@@ -808,8 +806,11 @@
       type_info->oneof_case_offset,
       type_info->size,
       type_info->weak_field_map_offset,
-      nullptr /* inlined_string_indices_ */,
-      0 /* inlined_string_donated_offset_ */};
+      nullptr,  // inlined_string_indices_
+      0,        // inlined_string_donated_offset_
+      -1,       // split_offset_
+      -1,       // sizeof_split_
+  };
 
   type_info->reflection.reset(
       new Reflection(type_info->type, schema, type_info->pool, this));
@@ -823,4 +824,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>  // NOLINT
+#include "google/protobuf/port_undef.inc"  // NOLINT
diff --git a/src/google/protobuf/dynamic_message.h b/src/google/protobuf/dynamic_message.h
index 6fa6425..eb4a4b5 100644
--- a/src/google/protobuf/dynamic_message.h
+++ b/src/google/protobuf/dynamic_message.h
@@ -41,21 +41,21 @@
 
 #include <algorithm>
 #include <memory>
-#include <unordered_map>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/reflection.h>
-#include <google/protobuf/repeated_field.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/reflection.h"
+#include "google/protobuf/repeated_field.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -81,6 +81,9 @@
 // encapsulates this "cache".  All DynamicMessages of the same type created
 // from the same factory will share the same support data.  Any Descriptors
 // used with a particular factory must outlive the factory.
+//
+// The thread safety for this class is subtle, see comments around GetPrototype
+// for details
 class PROTOBUF_EXPORT DynamicMessageFactory : public MessageFactory {
  public:
   // Construct a DynamicMessageFactory that will search for extensions in
@@ -95,6 +98,8 @@
   //   this is almost never what you want to do.  Almost all users should use
   //   the zero-arg constructor.
   DynamicMessageFactory(const DescriptorPool* pool);
+  DynamicMessageFactory(const DynamicMessageFactory&) = delete;
+  DynamicMessageFactory& operator=(const DynamicMessageFactory&) = delete;
 
   ~DynamicMessageFactory() override;
 
@@ -132,13 +137,11 @@
   bool delegate_to_generated_factory_;
 
   struct TypeInfo;
-  std::unordered_map<const Descriptor*, const TypeInfo*> prototypes_;
-  mutable internal::WrappedMutex prototypes_mutex_;
+  absl::flat_hash_map<const Descriptor*, const TypeInfo*> prototypes_;
+  mutable absl::Mutex prototypes_mutex_;
 
   friend class DynamicMessage;
   const Message* GetPrototypeNoLock(const Descriptor* type);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMessageFactory);
 };
 
 // Helper for computing a sorted list of map entries via reflection.
@@ -222,6 +225,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_DYNAMIC_MESSAGE_H__
diff --git a/src/google/protobuf/dynamic_message_unittest.cc b/src/google/protobuf/dynamic_message_unittest.cc
index 7ac2029..4d7b025 100644
--- a/src/google/protobuf/dynamic_message_unittest.cc
+++ b/src/google/protobuf/dynamic_message_unittest.cc
@@ -40,19 +40,19 @@
 // reflection_ops_unittest, cover the rest of the functionality used by
 // DynamicMessage.
 
-#include <google/protobuf/dynamic_message.h>
+#include "google/protobuf/dynamic_message.h"
 
 #include <memory>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_no_field_presence.pb.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/testing/googletest.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/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/test_util.h>
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_no_field_presence.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/empty.pb.cc b/src/google/protobuf/empty.pb.cc
index 3a30776..9abd09f 100644
--- a/src/google/protobuf/empty.pb.cc
+++ b/src/google/protobuf/empty.pb.cc
@@ -1,82 +1,106 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/empty.proto
 
-#include <google/protobuf/empty.pb.h>
+#include "google/protobuf/empty.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR Empty::Empty(
     ::_pbi::ConstantInitialized) {}
 struct EmptyDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EmptyDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EmptyDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EmptyDefaultTypeInternal() {}
   union {
     Empty _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EmptyDefaultTypeInternal _Empty_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EmptyDefaultTypeInternal _Empty_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fempty_2eproto[1];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fempty_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Empty, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fempty_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Empty, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Empty)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Empty)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_Empty_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Empty_default_instance_._instance,
 };
-
-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\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fempty_2eproto_once;
+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\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2fempty_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fempty_2eproto = {
-    false, false, 190, descriptor_table_protodef_google_2fprotobuf_2fempty_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fempty_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fempty_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fempty_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fempty_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fempty_2eproto(&descriptor_table_google_2fprotobuf_2fempty_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 class Empty::_Internal {
@@ -112,11 +136,11 @@
 
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Empty::GetMetadata() const {
+
   return ::_pbi::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
@@ -125,6 +149,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Empty >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/empty.pb.h b/src/google/protobuf/empty.pb.h
index ec897ea..f7f068d 100644
--- a/src/google/protobuf/empty.pb.h
+++ b/src/google/protobuf/empty.pb.h
@@ -1,39 +1,44 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/empty.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_bases.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_bases.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fempty_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -42,21 +47,25 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fempty_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct EmptyDefaultTypeInternal;
 PROTOBUF_EXPORT extern EmptyDefaultTypeInternal _Empty_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Empty* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Empty>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Empty* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Empty>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT Empty final :
     public ::PROTOBUF_NAMESPACE_ID::internal::ZeroFieldsBase /* @@protoc_insertion_point(class_definition:google.protobuf.Empty) */ {
  public:
@@ -145,7 +154,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Empty";
   }
   protected:
@@ -176,23 +185,29 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // Empty
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fempty_2eproto_2epb_2eh
diff --git a/src/google/protobuf/empty.proto b/src/google/protobuf/empty.proto
index 2227462..b87c89d 100644
--- a/src/google/protobuf/empty.proto
+++ b/src/google/protobuf/empty.proto
@@ -32,12 +32,12 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 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;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
 
 // A generic empty message that you can re-use to avoid defining duplicated
diff --git a/src/google/protobuf/endian.h b/src/google/protobuf/endian.h
index e0ee6cd..2527b3e 100644
--- a/src/google/protobuf/endian.h
+++ b/src/google/protobuf/endian.h
@@ -38,7 +38,7 @@
 #include <cstdint>
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -193,6 +193,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_ENDIAN_H__
diff --git a/src/google/protobuf/explicitly_constructed.h b/src/google/protobuf/explicitly_constructed.h
index 174c59a..c273644 100644
--- a/src/google/protobuf/explicitly_constructed.h
+++ b/src/google/protobuf/explicitly_constructed.h
@@ -35,11 +35,11 @@
 
 #include <utility>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -92,6 +92,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_EXPLICITLY_CONSTRUCTED_H__
diff --git a/src/google/protobuf/extension_set.cc b/src/google/protobuf/extension_set.cc
index fada4f5..6cd1248 100644
--- a/src/google/protobuf/extension_set.cc
+++ b/src/google/protobuf/extension_set.cc
@@ -32,32 +32,30 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/extension_set.h>
+#include "google/protobuf/extension_set.h"
 
 #include <tuple>
-#include <unordered_set>
 #include <utility>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/extension_set_inl.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/hash/hash.h"
+#include "google/protobuf/extension_set_inl.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/repeated_field.h"
 
-// clang-format off
-#include <google/protobuf/port_def.inc>  // must be last.
-// clang-format on
+// must be last.
+#include "google/protobuf/port_def.inc"
+
 namespace google {
 namespace protobuf {
 namespace internal {
-
 namespace {
 
 inline WireFormatLite::FieldType real_type(FieldType type) {
@@ -71,8 +69,6 @@
 
 // Registry stuff.
 
-// Note that we cannot use hetererogeneous lookup for std containers since we
-// need to support C++11.
 struct ExtensionEq {
   bool operator()(const ExtensionInfo& lhs, const ExtensionInfo& rhs) const {
     return lhs.message == rhs.message && lhs.number == rhs.number;
@@ -81,13 +77,12 @@
 
 struct ExtensionHasher {
   std::size_t operator()(const ExtensionInfo& info) const {
-    return std::hash<const MessageLite*>{}(info.message) ^
-           std::hash<int>{}(info.number);
+    return absl::HashOf(info.message, info.number);
   }
 };
 
 using ExtensionRegistry =
-    std::unordered_set<ExtensionInfo, ExtensionHasher, ExtensionEq>;
+    absl::flat_hash_set<ExtensionInfo, ExtensionHasher, ExtensionEq>;
 
 static const ExtensionRegistry* global_registry = nullptr;
 
@@ -96,7 +91,7 @@
 void Register(const ExtensionInfo& info) {
   static auto local_static_registry = OnShutdownDelete(new ExtensionRegistry);
   global_registry = local_static_registry;
-  if (!InsertIfNotPresent(local_static_registry, info)) {
+  if (!local_static_registry->insert(info).second) {
     GOOGLE_LOG(FATAL) << "Multiple extension registrations for type \""
                << info.message->GetTypeName() << "\", field number "
                << info.number << ".";
@@ -1964,4 +1959,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/extension_set.h b/src/google/protobuf/extension_set.h
index 0e6d052..c0dcb8c 100644
--- a/src/google/protobuf/extension_set.h
+++ b/src/google/protobuf/extension_set.h
@@ -46,16 +46,17 @@
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>  // Must be last
+#include "google/protobuf/port_def.inc"  // Must be last
 // clang-format on
 
 #ifdef SWIG
@@ -185,6 +186,8 @@
   constexpr ExtensionSet();
   explicit ExtensionSet(Arena* arena);
   ExtensionSet(ArenaInitialized, Arena* arena) : ExtensionSet(arena) {}
+  ExtensionSet(const ExtensionSet&) = delete;
+  ExtensionSet& operator=(const ExtensionSet&) = delete;
   ~ExtensionSet();
 
   // These are called at startup by protocol-compiler-generated code to
@@ -538,6 +541,8 @@
   class PROTOBUF_EXPORT LazyMessageExtension {
    public:
     LazyMessageExtension() {}
+    LazyMessageExtension(const LazyMessageExtension&) = delete;
+    LazyMessageExtension& operator=(const LazyMessageExtension&) = delete;
     virtual ~LazyMessageExtension() {}
 
     virtual LazyMessageExtension* New(Arena* arena) const = 0;
@@ -565,17 +570,15 @@
     virtual void MergeFromMessage(const MessageLite& msg, Arena* arena) = 0;
     virtual void Clear() = 0;
 
-    virtual const char* _InternalParse(const Message& prototype, Arena* arena,
-                                       LazyVerifyOption option, const char* ptr,
-                                       ParseContext* ctx) = 0;
+    virtual const char* _InternalParse(const MessageLite& prototype,
+                                       Arena* arena, LazyVerifyOption option,
+                                       const char* ptr, ParseContext* ctx) = 0;
     virtual uint8_t* WriteMessageToArray(
         const MessageLite* prototype, int number, uint8_t* target,
         io::EpsCopyOutputStream* stream) const = 0;
 
    private:
     virtual void UnusedKeyMethod();  // Dummy key method to avoid weak vtable.
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LazyMessageExtension);
   };
   // Give access to function defined below to see LazyMessageExtension.
   friend LazyMessageExtension* MaybeCreateLazyExtension(Arena* arena);
@@ -908,8 +911,6 @@
   } map_;
 
   static void DeleteFlatMap(const KeyValue* flat, uint16_t flat_capacity);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ExtensionSet);
 };
 
 constexpr ExtensionSet::ExtensionSet()
@@ -1262,6 +1263,8 @@
   template <typename ExtendeeT>
   static void Register(int number, FieldType type, bool is_packed,
                        LazyEagerVerifyFnType fn) {
+    // Avoid -Wunused-parameter
+    (void)fn;
     ExtensionSet::RegisterEnumExtension(&ExtendeeT::default_instance(), number,
                                         type, false, is_packed, IsValid);
   }
@@ -1328,6 +1331,8 @@
   template <typename ExtendeeT>
   static void Register(int number, FieldType type, bool is_packed,
                        LazyEagerVerifyFnType fn) {
+    // Avoid -Wunused-parameter
+    (void)fn;
     ExtensionSet::RegisterEnumExtension(&ExtendeeT::default_instance(), number,
                                         type, true, is_packed, IsValid);
   }
@@ -1556,6 +1561,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_EXTENSION_SET_H__
diff --git a/src/google/protobuf/extension_set_heavy.cc b/src/google/protobuf/extension_set_heavy.cc
index a4bb948..abf9e5f 100644
--- a/src/google/protobuf/extension_set_heavy.cc
+++ b/src/google/protobuf/extension_set_heavy.cc
@@ -35,24 +35,25 @@
 // Contains methods defined in extension_set.h which cannot be part of the
 // lite library because they use descriptors or reflection.
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/extension_set_inl.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/arena.h"
+#include "absl/base/casts.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/extension_set_inl.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -413,7 +414,7 @@
         if (is_lazy) {
           total_size += lazymessage_value->SpaceUsedLong();
         } else {
-          total_size += down_cast<Message*>(message_value)->SpaceUsedLong();
+          total_size += DownCast<Message*>(message_value)->SpaceUsedLong();
         }
         break;
       default:
@@ -437,4 +438,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 e4e7117..8256455 100644
--- a/src/google/protobuf/extension_set_inl.h
+++ b/src/google/protobuf/extension_set_inl.h
@@ -31,9 +31,9 @@
 #ifndef GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
 #define GOOGLE_PROTOBUF_EXTENSION_SET_INL_H__
 
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/parse_context.h>
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/parse_context.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/extension_set_unittest.cc b/src/google/protobuf/extension_set_unittest.cc
index 207e10c..3a54dd8 100644
--- a/src/google/protobuf/extension_set_unittest.cc
+++ b/src/google/protobuf/extension_set_unittest.cc
@@ -32,29 +32,32 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_mset.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/extension_set.h"
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/test_util2.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/base/casts.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/match.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.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/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 
 namespace google {
@@ -62,6 +65,7 @@
 namespace internal {
 namespace {
 
+using ::google::protobuf::internal::DownCast;
 using TestUtil::EqualsToSerialized;
 
 // This test closely mirrors third_party/protobuf/compiler/cpp/unittest.cc
@@ -547,7 +551,7 @@
   size_t size = source.ByteSizeLong();
   std::string data;
   data.resize(size);
-  uint8_t* target = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+  uint8_t* target = reinterpret_cast<uint8_t*>(&data[0]);
   uint8_t* end = source.SerializeWithCachedSizesToArray(target);
   EXPECT_EQ(size, end - target);
   EXPECT_TRUE(destination.ParseFromString(data));
@@ -569,7 +573,7 @@
   std::string data;
   data.resize(size);
   {
-    io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
     io::CodedOutputStream output_stream(&array_stream);
     source.SerializeWithCachedSizes(&output_stream);
     ASSERT_FALSE(output_stream.HadError());
@@ -591,7 +595,7 @@
   size_t size = source.ByteSizeLong();
   std::string data;
   data.resize(size);
-  uint8_t* target = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+  uint8_t* target = reinterpret_cast<uint8_t*>(&data[0]);
   uint8_t* end = source.SerializeWithCachedSizesToArray(target);
   EXPECT_EQ(size, end - target);
   EXPECT_TRUE(destination.ParseFromString(data));
@@ -613,7 +617,7 @@
   std::string data;
   data.resize(size);
   {
-    io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
     io::CodedOutputStream output_stream(&array_stream);
     source.SerializeWithCachedSizes(&output_stream);
     ASSERT_FALSE(output_stream.HadError());
@@ -852,8 +856,10 @@
     const size_t old_capacity =                                                \
         message->GetRepeatedExtension(unittest::repeated_##type##_extension)   \
             .Capacity();                                                       \
-    EXPECT_GE(old_capacity,                                                    \
-              (RepeatedFieldLowerClampLimit<cpptype, sizeof(void*)>()));       \
+    EXPECT_GE(                                                                 \
+        old_capacity,                                                          \
+        (RepeatedFieldLowerClampLimit<cpptype, std::max(sizeof(cpptype),       \
+                                                        sizeof(void*))>()));   \
     for (int i = 0; i < 16; ++i) {                                             \
       message->AddExtension(unittest::repeated_##type##_extension, value);     \
     }                                                                          \
@@ -1229,7 +1235,7 @@
     std::string prefix = "." + template_descriptor->full_name() + ".";
     if (extension->has_type_name()) {
       std::string* type_name = extension->mutable_type_name();
-      if (HasPrefixString(*type_name, prefix)) {
+      if (absl::StartsWith(*type_name, prefix)) {
         type_name->replace(0, prefix.size(), ".dynamic_extensions.");
       }
     }
diff --git a/src/google/protobuf/field_access_listener.h b/src/google/protobuf/field_access_listener.h
index 47422e6..fd54f0e 100644
--- a/src/google/protobuf/field_access_listener.h
+++ b/src/google/protobuf/field_access_listener.h
@@ -33,8 +33,8 @@
 
 #include <cstddef>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/port.h"
 
 
 namespace google {
@@ -57,7 +57,7 @@
   // to differentiate the protos during the runtime before the start of the
   // program, use this functor to get its name. We either way need it for
   // LITE_RUNTIME protos as they don't have descriptors at all.
-  explicit NoOpAccessListener(StringPiece (*name_extractor)()) {}
+  explicit NoOpAccessListener(absl::string_view (*name_extractor)()) {}
   // called repeatedly during serialization/deserialization/ByteSize of
   // Reflection as:
   //   AccessListener<MessageT>::OnSerialize(this);
diff --git a/src/google/protobuf/field_mask.pb.cc b/src/google/protobuf/field_mask.pb.cc
index 7860bfb..be8476c 100644
--- a/src/google/protobuf/field_mask.pb.cc
+++ b/src/google/protobuf/field_mask.pb.cc
@@ -1,86 +1,110 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/field_mask.proto
 
-#include <google/protobuf/field_mask.pb.h>
+#include "google/protobuf/field_mask.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR FieldMask::FieldMask(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.paths_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct FieldMaskDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FieldMaskDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FieldMaskDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FieldMaskDefaultTypeInternal() {}
   union {
     FieldMask _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2ffield_5fmask_2eproto[1];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldMask, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldMask, _impl_.paths_),
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldMask, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FieldMask, _impl_.paths_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldMask)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FieldMask)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_FieldMask_default_instance_._instance,
 };
-
-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"
-  "\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once;
+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"
+    "\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto = {
-    false, false, 223, descriptor_table_protodef_google_2fprotobuf_2ffield_5fmask_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2ffield_5fmask_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ffield_5fmask_2eproto(&descriptor_table_google_2fprotobuf_2ffield_5fmask_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 class FieldMask::_Internal {
@@ -134,7 +158,7 @@
 
 void FieldMask::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FieldMask)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -143,14 +167,15 @@
 }
 
 const char* FieldMask::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated string paths = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -160,8 +185,9 @@
             CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.FieldMask.paths"));
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -186,10 +212,11 @@
 #undef CHK_
 }
 
-uint8_t* FieldMask::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* FieldMask::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FieldMask)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated string paths = 1;
@@ -210,11 +237,12 @@
   return target;
 }
 
-size_t FieldMask::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask)
-  size_t total_size = 0;
+::size_t FieldMask::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FieldMask)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -239,9 +267,10 @@
 void FieldMask::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<FieldMask*>(&to_msg);
   auto& from = static_cast<const FieldMask&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FieldMask)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.paths_.MergeFrom(from._impl_.paths_);
@@ -266,11 +295,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FieldMask::GetMetadata() const {
+
   return ::_pbi::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
@@ -279,6 +308,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::FieldMask >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/field_mask.pb.h b/src/google/protobuf/field_mask.pb.h
index ca78877..d3617da 100644
--- a/src/google/protobuf/field_mask.pb.h
+++ b/src/google/protobuf/field_mask.pb.h
@@ -1,38 +1,43 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/field_mask.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ffield_5fmask_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -41,21 +46,25 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ffield_5fmask_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct FieldMaskDefaultTypeInternal;
 PROTOBUF_EXPORT extern FieldMaskDefaultTypeInternal _FieldMask_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldMask>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FieldMask* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FieldMask>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT FieldMask final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FieldMask) */ {
  public:
@@ -145,10 +154,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -159,7 +168,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.FieldMask";
   }
   protected:
@@ -190,12 +199,12 @@
   void set_paths(int index, const std::string& value);
   void set_paths(int index, std::string&& value);
   void set_paths(int index, const char* value);
-  void set_paths(int index, const char* value, size_t size);
+  void set_paths(int index, const char* value, ::size_t size);
   std::string* add_paths();
   void add_paths(const std::string& value);
   void add_paths(std::string&& value);
   void add_paths(const char* value);
-  void add_paths(const char* value, size_t size);
+  void add_paths(const char* value, ::size_t size);
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& paths() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_paths();
   private:
@@ -220,12 +229,17 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // FieldMask
 
 // repeated string paths = 1;
@@ -263,11 +277,10 @@
   // @@protoc_insertion_point(field_set:google.protobuf.FieldMask.paths)
 }
 inline void FieldMask::set_paths(int index, const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.paths_.Mutable(index)->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.paths_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.FieldMask.paths)
 }
-inline void FieldMask::set_paths(int index, const char* value, size_t size) {
+inline void FieldMask::set_paths(int index, const char* value, ::size_t size) {
   _impl_.paths_.Mutable(index)->assign(
     reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.FieldMask.paths)
@@ -284,11 +297,10 @@
   // @@protoc_insertion_point(field_add:google.protobuf.FieldMask.paths)
 }
 inline void FieldMask::add_paths(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.paths_.Add()->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.paths_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.FieldMask.paths)
 }
-inline void FieldMask::add_paths(const char* value, size_t size) {
+inline void FieldMask::add_paths(const char* value, ::size_t size) {
   _impl_.paths_.Add()->assign(reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_add_pointer:google.protobuf.FieldMask.paths)
 }
@@ -304,14 +316,15 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ffield_5fmask_2eproto_2epb_2eh
diff --git a/src/google/protobuf/field_mask.proto b/src/google/protobuf/field_mask.proto
index 6b5104f..b28334b 100644
--- a/src/google/protobuf/field_mask.proto
+++ b/src/google/protobuf/field_mask.proto
@@ -32,11 +32,11 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "FieldMaskProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option go_package = "google.golang.org/protobuf/types/known/fieldmaskpb";
 option cc_enable_arenas = true;
 
diff --git a/src/google/protobuf/generated_enum_reflection.h b/src/google/protobuf/generated_enum_reflection.h
index b96a9c6..31ddc12 100644
--- a/src/google/protobuf/generated_enum_reflection.h
+++ b/src/google/protobuf/generated_enum_reflection.h
@@ -42,16 +42,16 @@
 
 #include <string>
 
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/generated_enum_util.h>
+#include "google/protobuf/port.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/generated_enum_util.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -74,10 +74,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,
-                                    ConstStringParam name, int* value);
+                                    absl::string_view name, int* value);
 
 template <typename EnumType>
-bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
+bool ParseNamedEnum(const EnumDescriptor* descriptor, absl::string_view name,
                     EnumType* value) {
   int tmp;
   if (!ParseNamedEnum(descriptor, name, &tmp)) return false;
@@ -95,6 +95,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_GENERATED_ENUM_REFLECTION_H__
diff --git a/src/google/protobuf/generated_enum_util.cc b/src/google/protobuf/generated_enum_util.cc
index df7583e..ab21577 100644
--- a/src/google/protobuf/generated_enum_util.cc
+++ b/src/google/protobuf/generated_enum_util.cc
@@ -28,11 +28,11 @@
 // (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/generated_enum_util.h>
+#include "google/protobuf/generated_enum_util.h"
 
 #include <algorithm>
 
-#include <google/protobuf/generated_message_util.h>
+#include "google/protobuf/generated_message_util.h"
 
 namespace google {
 namespace protobuf {
@@ -40,7 +40,7 @@
 namespace {
 
 bool EnumCompareByName(const EnumEntry& a, const EnumEntry& b) {
-  return StringPiece(a.name) < StringPiece(b.name);
+  return absl::string_view(a.name) < absl::string_view(b.name);
 }
 
 // Gets the numeric value of the EnumEntry at the given index, but returns a
@@ -57,7 +57,7 @@
 }  // namespace
 
 bool LookUpEnumValue(const EnumEntry* enums, size_t size,
-                     StringPiece name, int* value) {
+                     absl::string_view name, int* value) {
   EnumEntry target{name, 0};
   auto it = std::lower_bound(enums, enums + size, target, EnumCompareByName);
   if (it != enums + size && it->name == name) {
diff --git a/src/google/protobuf/generated_enum_util.h b/src/google/protobuf/generated_enum_util.h
index 5d10ac0..86e1bb9 100644
--- a/src/google/protobuf/generated_enum_util.h
+++ b/src/google/protobuf/generated_enum_util.h
@@ -34,11 +34,11 @@
 
 #include <type_traits>
 
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/message_lite.h>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/message_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -58,13 +58,13 @@
 // protos. This struct and the following related functions should only be used
 // by protobuf generated code.
 struct EnumEntry {
-  StringPiece name;
+  absl::string_view name;
   int value;
 };
 
 // Looks up a numeric enum value given the string name.
 PROTOBUF_EXPORT bool LookUpEnumValue(const EnumEntry* enums, size_t size,
-                                     StringPiece name, int* value);
+                                     absl::string_view name, int* value);
 
 // Looks up an enum name given the numeric value.
 PROTOBUF_EXPORT int LookUpEnumName(const EnumEntry* enums,
@@ -80,6 +80,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_GENERATED_ENUM_UTIL_H__
diff --git a/src/google/protobuf/generated_message_bases.cc b/src/google/protobuf/generated_message_bases.cc
index 306a38e..2ccca16 100644
--- a/src/google/protobuf/generated_message_bases.cc
+++ b/src/google/protobuf/generated_message_bases.cc
@@ -28,17 +28,17 @@
 // (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/generated_message_bases.h>
+#include "google/protobuf/generated_message_bases.h"
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must be last:
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -121,4 +121,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/generated_message_bases.h b/src/google/protobuf/generated_message_bases.h
index b295218..d542ca4 100644
--- a/src/google/protobuf/generated_message_bases.h
+++ b/src/google/protobuf/generated_message_bases.h
@@ -35,14 +35,14 @@
 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
 
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/parse_context.h>
+#include "google/protobuf/arena.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/parse_context.h"
 
 // Must come last:
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -82,6 +82,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_BASES_H__
diff --git a/src/google/protobuf/generated_message_reflection.cc b/src/google/protobuf/generated_message_reflection.cc
index 2a807e0..067f45a 100644
--- a/src/google/protobuf/generated_message_reflection.cc
+++ b/src/google/protobuf/generated_message_reflection.cc
@@ -32,29 +32,37 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/generated_message_reflection.h>
+#include "google/protobuf/generated_message_reflection.h"
 
 #include <algorithm>
+#include <atomic>
+#include <cstdint>
+#include <cstring>
 #include <set>
+#include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.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/repeated_field.h>
-#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/base/casts.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/generated_message_tctable_gen.h"
+#include "google/protobuf/generated_message_tctable_impl.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/repeated_field.h"
+#include "google/protobuf/unknown_field_set.h"
 
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 #define GOOGLE_PROTOBUF_HAS_ONEOF
@@ -73,7 +81,6 @@
 using google::protobuf::internal::ReflectionSchema;
 using google::protobuf::internal::RepeatedPtrFieldBase;
 using google::protobuf::internal::StringSpaceUsedExcludingSelfLong;
-using google::protobuf::internal::WrappedMutex;
 
 namespace google {
 namespace protobuf {
@@ -95,7 +102,7 @@
 
 namespace internal {
 
-bool ParseNamedEnum(const EnumDescriptor* descriptor, ConstStringParam name,
+bool ParseNamedEnum(const EnumDescriptor* descriptor, absl::string_view name,
                     int* value) {
   const EnumValueDescriptor* d = descriptor->FindValueByName(name);
   if (d == nullptr) return false;
@@ -108,6 +115,54 @@
   return (d == nullptr ? GetEmptyString() : d->name());
 }
 
+// Internal helper routine for NameOfDenseEnum in the header file.
+// Allocates and fills a simple array of string pointers, based on
+// reflection information about the names of the enums.  This routine
+// allocates max_val + 1 entries, under the assumption that all the enums
+// fall in the range [min_val .. max_val].
+const std::string** MakeDenseEnumCache(const EnumDescriptor* desc, int min_val,
+                                       int max_val) {
+  auto* str_ptrs =
+      new const std::string*[static_cast<size_t>(max_val - min_val + 1)]();
+  const int count = desc->value_count();
+  for (int i = 0; i < count; ++i) {
+    const int num = desc->value(i)->number();
+    if (str_ptrs[num - min_val] == nullptr) {
+      // Don't over-write an existing entry, because in case of duplication, the
+      // first one wins.
+      str_ptrs[num - min_val] = &desc->value(i)->name();
+    }
+  }
+  // Change any unfilled entries to point to the empty string.
+  for (int i = 0; i < max_val - min_val + 1; ++i) {
+    if (str_ptrs[i] == nullptr) str_ptrs[i] = &GetEmptyStringAlreadyInited();
+  }
+  return str_ptrs;
+}
+
+PROTOBUF_NOINLINE const std::string& NameOfDenseEnumSlow(
+    int v, DenseEnumCacheInfo* deci) {
+  if (v < deci->min_val || v > deci->max_val)
+    return GetEmptyStringAlreadyInited();
+
+  const std::string** new_cache =
+      MakeDenseEnumCache(deci->descriptor_fn(), deci->min_val, deci->max_val);
+  const std::string** old_cache = nullptr;
+
+  if (deci->cache.compare_exchange_strong(old_cache, new_cache,
+                                          std::memory_order_release,
+                                          std::memory_order_acquire)) {
+    // We successfully stored our new cache, and the old value was nullptr.
+    return *new_cache[v - deci->min_val];
+  } else {
+    // In the time it took to create our enum cache, another thread also
+    //  created one, and put it into deci->cache.  So delete ours, and
+    // use theirs instead.
+    delete[] new_cache;
+    return *old_cache[v - deci->min_val];
+  }
+}
+
 }  // namespace internal
 
 // ===================================================================
@@ -239,6 +294,12 @@
   last_non_weak_field_index_ = descriptor_->field_count() - 1;
 }
 
+Reflection::~Reflection() {
+  // No need to use sized delete. This code path is uncommon and it would not be
+  // worth saving or recalculating the size.
+  ::operator delete(const_cast<internal::TcParseTableBase*>(tcparse_table_));
+}
+
 const UnknownFieldSet& Reflection::GetUnknownFields(
     const Message& message) const {
   return GetInternalMetadata(message).unknown_fields<UnknownFieldSet>(
@@ -394,7 +455,19 @@
       }
     }
   }
+#ifndef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG
   return total_size;
+#else
+  // Use both `this` and `dummy` to generate the seed so that the scale factor
+  // is both per-object and non-predictable, but consistent across multiple
+  // calls in the same binary.
+  static bool dummy;
+  uintptr_t seed =
+      reinterpret_cast<uintptr_t>(&dummy) ^ reinterpret_cast<uintptr_t>(this);
+  // Fuzz the size by +/- 50%.
+  double scale = (static_cast<double>(seed % 10000) / 10000) + 0.5;
+  return total_size * scale;
+#endif
 }
 
 namespace {
@@ -983,8 +1056,6 @@
     return;
   }
 
-  GOOGLE_DCHECK_EQ(message1->GetOwningArena(), message2->GetOwningArena());
-
   UnsafeArenaSwap(message1, message2);
 }
 
@@ -1014,9 +1085,6 @@
 
   std::set<int> swapped_oneof;
 
-  GOOGLE_DCHECK(!unsafe_shallow_swap || message1->GetArenaForAllocation() ==
-                                     message2->GetArenaForAllocation());
-
   const Message* prototype =
       message_factory_->GetPrototype(message1->GetDescriptor());
   for (const auto* field : fields) {
@@ -1073,6 +1141,9 @@
 void Reflection::UnsafeShallowSwapFields(
     Message* message1, Message* message2,
     const std::vector<const FieldDescriptor*>& fields) const {
+  GOOGLE_DCHECK_EQ(message1->GetArenaForAllocation(),
+            message2->GetArenaForAllocation());
+
   SwapFieldsImpl<true>(message1, message2, fields);
 }
 
@@ -1103,6 +1174,11 @@
 }
 
 void Reflection::UnsafeArenaSwap(Message* lhs, Message* rhs) const {
+  GOOGLE_DCHECK_EQ(lhs->GetOwningArena(), rhs->GetOwningArena());
+  InternalSwap(lhs, rhs);
+}
+
+void Reflection::InternalSwap(Message* lhs, Message* rhs) const {
   if (lhs == rhs) return;
 
   MutableInternalMetadata(lhs)->InternalSwap(MutableInternalMetadata(rhs));
@@ -1111,8 +1187,14 @@
     const FieldDescriptor* field = descriptor_->field(i);
     if (schema_.InRealOneof(field)) continue;
     if (schema_.IsFieldStripped(field)) continue;
+    if (schema_.IsSplit(field)) {
+      continue;
+    }
     UnsafeShallowSwapField(lhs, rhs, field);
   }
+  if (schema_.IsSplit()) {
+    std::swap(*MutableSplitField(lhs), *MutableSplitField(rhs));
+  }
   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);
@@ -2410,7 +2492,7 @@
 // -----------------------------------------------------------------------------
 
 const FieldDescriptor* Reflection::FindKnownExtensionByName(
-    const std::string& name) const {
+    absl::string_view name) const {
   if (!schema_.HasExtensionSet()) return nullptr;
   return descriptor_pool_->FindExtensionByPrintableName(descriptor_, name);
 }
@@ -2434,13 +2516,35 @@
 template <class Type>
 const Type& Reflection::GetRawNonOneof(const Message& message,
                                        const FieldDescriptor* field) const {
+  if (schema_.IsSplit(field)) {
+    return *GetConstPointerAtOffset<Type>(
+        GetSplitField(&message), schema_.GetFieldOffsetNonOneof(field));
+  }
   return GetConstRefAtOffset<Type>(message,
                                    schema_.GetFieldOffsetNonOneof(field));
 }
 
+void Reflection::PrepareSplitMessageForWrite(Message* message) const {
+  GOOGLE_DCHECK_NE(message, schema_.default_instance_);
+  void** split = MutableSplitField(message);
+  const void* default_split = GetSplitField(schema_.default_instance_);
+  if (*split == default_split) {
+    uint32_t size = schema_.SizeofSplit();
+    Arena* arena = message->GetArenaForAllocation();
+    *split = (arena == nullptr) ? ::operator new(size)
+                                : arena->AllocateAligned(size);
+    memcpy(*split, default_split, size);
+  }
+}
+
 template <class Type>
 Type* Reflection::MutableRawNonOneof(Message* message,
                                      const FieldDescriptor* field) const {
+  if (schema_.IsSplit(field)) {
+    PrepareSplitMessageForWrite(message);
+    return GetPointerAtOffset<Type>(*MutableSplitField(message),
+                                    schema_.GetFieldOffsetNonOneof(field));
+  }
   return GetPointerAtOffset<Type>(message,
                                   schema_.GetFieldOffsetNonOneof(field));
 }
@@ -2448,6 +2552,11 @@
 template <typename Type>
 Type* Reflection::MutableRaw(Message* message,
                              const FieldDescriptor* field) const {
+  if (schema_.IsSplit(field)) {
+    PrepareSplitMessageForWrite(message);
+    return GetPointerAtOffset<Type>(*MutableSplitField(message),
+                                    schema_.GetFieldOffset(field));
+  }
   return GetPointerAtOffset<Type>(message, schema_.GetFieldOffset(field));
 }
 
@@ -2864,6 +2973,397 @@
   return &(GetRaw<MapFieldBase>(message, field));
 }
 
+template <typename T>
+static uint32_t AlignTo(uint32_t v) {
+  return (v + alignof(T) - 1) & ~(alignof(T) - 1);
+}
+
+static internal::TailCallParseFunc GetFastParseFunction(
+    absl::string_view name) {
+  // This list must be synchronized with TcParser.
+  // Missing entries are replaced with MiniParse in opt mode to avoid runtime
+  // failures. It check-fails in debug mode.
+  static const auto* const map =
+      new absl::flat_hash_map<absl::string_view, internal::TailCallParseFunc>{
+          {"::_pbi::TcParser::FastF32S1", internal::TcParser::FastF32S1},
+          {"::_pbi::TcParser::FastF32S2", internal::TcParser::FastF32S2},
+          {"::_pbi::TcParser::FastF32R1", internal::TcParser::FastF32R1},
+          {"::_pbi::TcParser::FastF32R2", internal::TcParser::FastF32R2},
+          {"::_pbi::TcParser::FastF32P1", internal::TcParser::FastF32P1},
+          {"::_pbi::TcParser::FastF32P2", internal::TcParser::FastF32P2},
+          {"::_pbi::TcParser::FastF64S1", internal::TcParser::FastF64S1},
+          {"::_pbi::TcParser::FastF64S2", internal::TcParser::FastF64S2},
+          {"::_pbi::TcParser::FastF64R1", internal::TcParser::FastF64R1},
+          {"::_pbi::TcParser::FastF64R2", internal::TcParser::FastF64R2},
+          {"::_pbi::TcParser::FastF64P1", internal::TcParser::FastF64P1},
+          {"::_pbi::TcParser::FastF64P2", internal::TcParser::FastF64P2},
+          {"::_pbi::TcParser::FastV8S1", internal::TcParser::FastV8S1},
+          {"::_pbi::TcParser::FastV8S2", internal::TcParser::FastV8S2},
+          {"::_pbi::TcParser::FastV8R1", internal::TcParser::FastV8R1},
+          {"::_pbi::TcParser::FastV8R2", internal::TcParser::FastV8R2},
+          {"::_pbi::TcParser::FastV8P1", internal::TcParser::FastV8P1},
+          {"::_pbi::TcParser::FastV8P2", internal::TcParser::FastV8P2},
+          {"::_pbi::TcParser::FastV32S1", internal::TcParser::FastV32S1},
+          {"::_pbi::TcParser::FastV32S2", internal::TcParser::FastV32S2},
+          {"::_pbi::TcParser::FastV32R1", internal::TcParser::FastV32R1},
+          {"::_pbi::TcParser::FastV32R2", internal::TcParser::FastV32R2},
+          {"::_pbi::TcParser::FastV32P1", internal::TcParser::FastV32P1},
+          {"::_pbi::TcParser::FastV32P2", internal::TcParser::FastV32P2},
+          {"::_pbi::TcParser::FastV64S1", internal::TcParser::FastV64S1},
+          {"::_pbi::TcParser::FastV64S2", internal::TcParser::FastV64S2},
+          {"::_pbi::TcParser::FastV64R1", internal::TcParser::FastV64R1},
+          {"::_pbi::TcParser::FastV64R2", internal::TcParser::FastV64R2},
+          {"::_pbi::TcParser::FastV64P1", internal::TcParser::FastV64P1},
+          {"::_pbi::TcParser::FastV64P2", internal::TcParser::FastV64P2},
+          {"::_pbi::TcParser::FastZ32S1", internal::TcParser::FastZ32S1},
+          {"::_pbi::TcParser::FastZ32S2", internal::TcParser::FastZ32S2},
+          {"::_pbi::TcParser::FastZ32R1", internal::TcParser::FastZ32R1},
+          {"::_pbi::TcParser::FastZ32R2", internal::TcParser::FastZ32R2},
+          {"::_pbi::TcParser::FastZ32P1", internal::TcParser::FastZ32P1},
+          {"::_pbi::TcParser::FastZ32P2", internal::TcParser::FastZ32P2},
+          {"::_pbi::TcParser::FastZ64S1", internal::TcParser::FastZ64S1},
+          {"::_pbi::TcParser::FastZ64S2", internal::TcParser::FastZ64S2},
+          {"::_pbi::TcParser::FastZ64R1", internal::TcParser::FastZ64R1},
+          {"::_pbi::TcParser::FastZ64R2", internal::TcParser::FastZ64R2},
+          {"::_pbi::TcParser::FastZ64P1", internal::TcParser::FastZ64P1},
+          {"::_pbi::TcParser::FastZ64P2", internal::TcParser::FastZ64P2},
+          {"::_pbi::TcParser::FastErS1", internal::TcParser::FastErS1},
+          {"::_pbi::TcParser::FastErS2", internal::TcParser::FastErS2},
+          {"::_pbi::TcParser::FastErR1", internal::TcParser::FastErR1},
+          {"::_pbi::TcParser::FastErR2", internal::TcParser::FastErR2},
+          {"::_pbi::TcParser::FastErP1", internal::TcParser::FastErP1},
+          {"::_pbi::TcParser::FastErP2", internal::TcParser::FastErP2},
+          {"::_pbi::TcParser::FastEr0S1", internal::TcParser::FastEr0S1},
+          {"::_pbi::TcParser::FastEr0S2", internal::TcParser::FastEr0S2},
+          {"::_pbi::TcParser::FastEr0R1", internal::TcParser::FastEr0R1},
+          {"::_pbi::TcParser::FastEr0R2", internal::TcParser::FastEr0R2},
+          {"::_pbi::TcParser::FastEr0P1", internal::TcParser::FastEr0P1},
+          {"::_pbi::TcParser::FastEr0P2", internal::TcParser::FastEr0P2},
+          {"::_pbi::TcParser::FastEr1S1", internal::TcParser::FastEr1S1},
+          {"::_pbi::TcParser::FastEr1S2", internal::TcParser::FastEr1S2},
+          {"::_pbi::TcParser::FastEr1R1", internal::TcParser::FastEr1R1},
+          {"::_pbi::TcParser::FastEr1R2", internal::TcParser::FastEr1R2},
+          {"::_pbi::TcParser::FastEr1P1", internal::TcParser::FastEr1P1},
+          {"::_pbi::TcParser::FastEr1P2", internal::TcParser::FastEr1P2},
+          {"::_pbi::TcParser::FastEvS1", internal::TcParser::FastEvS1},
+          {"::_pbi::TcParser::FastEvS2", internal::TcParser::FastEvS2},
+          {"::_pbi::TcParser::FastEvR1", internal::TcParser::FastEvR1},
+          {"::_pbi::TcParser::FastEvR2", internal::TcParser::FastEvR2},
+          {"::_pbi::TcParser::FastEvP1", internal::TcParser::FastEvP1},
+          {"::_pbi::TcParser::FastEvP2", internal::TcParser::FastEvP2},
+          {"::_pbi::TcParser::FastBS1", internal::TcParser::FastBS1},
+          {"::_pbi::TcParser::FastBS2", internal::TcParser::FastBS2},
+          {"::_pbi::TcParser::FastBR1", internal::TcParser::FastBR1},
+          {"::_pbi::TcParser::FastBR2", internal::TcParser::FastBR2},
+          {"::_pbi::TcParser::FastSS1", internal::TcParser::FastSS1},
+          {"::_pbi::TcParser::FastSS2", internal::TcParser::FastSS2},
+          {"::_pbi::TcParser::FastSR1", internal::TcParser::FastSR1},
+          {"::_pbi::TcParser::FastSR2", internal::TcParser::FastSR2},
+          {"::_pbi::TcParser::FastUS1", internal::TcParser::FastUS1},
+          {"::_pbi::TcParser::FastUS2", internal::TcParser::FastUS2},
+          {"::_pbi::TcParser::FastUR1", internal::TcParser::FastUR1},
+          {"::_pbi::TcParser::FastUR2", internal::TcParser::FastUR2},
+          {"::_pbi::TcParser::FastBiS1", internal::TcParser::FastBiS1},
+          {"::_pbi::TcParser::FastBiS2", internal::TcParser::FastBiS2},
+          {"::_pbi::TcParser::FastSiS1", internal::TcParser::FastSiS1},
+          {"::_pbi::TcParser::FastSiS2", internal::TcParser::FastSiS2},
+          {"::_pbi::TcParser::FastUiS1", internal::TcParser::FastUiS1},
+          {"::_pbi::TcParser::FastUiS2", internal::TcParser::FastUiS2},
+          {"::_pbi::TcParser::FastBcS1", internal::TcParser::FastBcS1},
+          {"::_pbi::TcParser::FastBcS2", internal::TcParser::FastBcS2},
+          {"::_pbi::TcParser::FastScS1", internal::TcParser::FastScS1},
+          {"::_pbi::TcParser::FastScS2", internal::TcParser::FastScS2},
+          {"::_pbi::TcParser::FastUcS1", internal::TcParser::FastUcS1},
+          {"::_pbi::TcParser::FastUcS2", internal::TcParser::FastUcS2},
+          {"::_pbi::TcParser::FastMdS1", internal::TcParser::FastMdS1},
+          {"::_pbi::TcParser::FastMdS2", internal::TcParser::FastMdS2},
+          {"::_pbi::TcParser::FastGdS1", internal::TcParser::FastGdS1},
+          {"::_pbi::TcParser::FastGdS2", internal::TcParser::FastGdS2},
+          {"::_pbi::TcParser::FastMtS1", internal::TcParser::FastMtS1},
+          {"::_pbi::TcParser::FastMtS2", internal::TcParser::FastMtS2},
+          {"::_pbi::TcParser::FastGtS1", internal::TcParser::FastGtS1},
+          {"::_pbi::TcParser::FastGtS2", internal::TcParser::FastGtS2},
+          {"::_pbi::TcParser::FastMdR1", internal::TcParser::FastMdR1},
+          {"::_pbi::TcParser::FastMdR2", internal::TcParser::FastMdR2},
+          {"::_pbi::TcParser::FastGdR1", internal::TcParser::FastGdR1},
+          {"::_pbi::TcParser::FastGdR2", internal::TcParser::FastGdR2},
+          {"::_pbi::TcParser::FastMtR1", internal::TcParser::FastMtR1},
+          {"::_pbi::TcParser::FastMtR2", internal::TcParser::FastMtR2},
+          {"::_pbi::TcParser::FastGtR1", internal::TcParser::FastGtR1},
+          {"::_pbi::TcParser::FastGtR2", internal::TcParser::FastGtR2},
+          {"::_pbi::TcParser::FastEndG1", internal::TcParser::FastEndG1},
+          {"::_pbi::TcParser::FastEndG2", internal::TcParser::FastEndG2},
+      };
+  auto it = map->find(name);
+  if (it == map->end()) {
+    GOOGLE_LOG(DFATAL) << "Failed to find function: " << name;
+    // Let's not crash in opt, just in case.
+    // MiniParse is always a valid parser.
+    return &internal::TcParser::MiniParse;
+  }
+  return it->second;
+}
+
+const internal::TcParseTableBase* Reflection::CreateTcParseTableForMessageSet()
+    const {
+  // ParseLoop can't parse message set wire format.
+  // Create a dummy table that only exists to make TcParser::ParseLoop jump
+  // into the reflective parse loop.
+
+  using Table = internal::TcParseTable<0, 0, 0, 0, 1>;
+  // We use `operator new` here because the destruction will be done with
+  // `operator delete` unconditionally.
+  void* p = ::operator new(sizeof(Table));
+  auto* full_table = ::new (p) Table{
+      {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, schema_.default_instance_, nullptr},
+      {{{&internal::TcParser::ReflectionParseLoop, {}}}}};
+  GOOGLE_DCHECK_EQ(static_cast<void*>(&full_table->header),
+            static_cast<void*>(full_table));
+  return &full_table->header;
+}
+
+void Reflection::PopulateTcParseFastEntries(
+    const internal::TailCallTableInfo& table_info,
+    TcParseTableBase::FastFieldEntry* fast_entries) const {
+  for (const auto& fast_field : table_info.fast_path_fields) {
+    if (fast_field.field == nullptr) {
+      if (fast_field.func_name.empty()) {
+        // No fast entry here. Use mini parser.
+        *fast_entries++ = {internal::TcParser::MiniParse, {}};
+      } else {
+        // No field, but still a special entry.
+        *fast_entries++ = {GetFastParseFunction(fast_field.func_name),
+                           {fast_field.coded_tag, fast_field.nonfield_info}};
+      }
+    } else if (absl::StrContains(fast_field.func_name, "TcParser::FastMl")) {
+      // We can't use fast parsing for these entries because we can't specify
+      // the validator.
+      *fast_entries++ = {internal::TcParser::MiniParse, {}};
+    } else if (absl::StrContains(fast_field.func_name, "TcParser::FastEv")) {
+      // We can't use fast parsing for these entries because we can't specify
+      // the validator. Use the reflection based parser called from MiniParse.
+      // TODO(b/239592582): Implement a fast parser for these enums.
+      *fast_entries++ = {internal::TcParser::MiniParse, {}};
+    } else {
+      *fast_entries++ = {
+          GetFastParseFunction(fast_field.func_name),
+          {fast_field.coded_tag, fast_field.hasbit_idx, fast_field.aux_idx,
+           static_cast<uint16_t>(schema_.GetFieldOffset(fast_field.field))}};
+    }
+  }
+}
+
+static void PopulateTcParseLookupTable(
+    const internal::TailCallTableInfo& table_info, uint16_t* lookup_table) {
+  for (const auto& entry_block : table_info.num_to_entry_table.blocks) {
+    *lookup_table++ = entry_block.first_fnum & 0xFFFF;
+    *lookup_table++ = entry_block.first_fnum >> 16;
+    *lookup_table++ = entry_block.entries.size();
+    for (auto se16 : entry_block.entries) {
+      *lookup_table++ = se16.skipmap;
+      *lookup_table++ = se16.field_entry_offset;
+    }
+  }
+  *lookup_table++ = 0xFFFF;
+  *lookup_table++ = 0xFFFF;
+}
+
+void Reflection::PopulateTcParseEntries(
+    internal::TailCallTableInfo& table_info,
+    TcParseTableBase::FieldEntry* entries) const {
+  for (const auto& entry : table_info.field_entries) {
+    const FieldDescriptor* field = entry.field;
+    if (field->options().weak()) {
+      // Weak fields are handled by the generated fallback function.
+      // (These are handled by legacy Google-internal logic.)
+      *entries = {};
+    } else if (IsLazyField(field)) {
+      // Lazy fields require validators, which we can't access from reflection.
+      // We can just handle them in the reflection fallback for now.
+      *entries = {};
+      table_info.aux_entries[entry.aux_idx] =
+          table_info.aux_entries[entry.aux_idx + 1] = {};
+    } else if (field->type() == field->TYPE_ENUM &&
+               table_info.aux_entries[entry.aux_idx].type ==
+                   internal::TailCallTableInfo::kEnumValidator) {
+      // Mini parse can't handle it. Fallback to reflection.
+      *entries = {};
+      table_info.aux_entries[entry.aux_idx] = {};
+    } else {
+      const OneofDescriptor* oneof = field->real_containing_oneof();
+      entries->offset = schema_.GetFieldOffset(field);
+      if (oneof != nullptr) {
+        entries->has_idx = schema_.oneof_case_offset_ + 4 * oneof->index();
+      } else if (schema_.HasHasbits()) {
+        entries->has_idx =
+            static_cast<int>(8 * schema_.HasBitsOffset() + entry.hasbit_idx);
+      } else {
+        entries->has_idx = 0;
+      }
+      entries->aux_idx = entry.aux_idx;
+      entries->type_card = entry.type_card;
+    }
+
+    ++entries;
+  }
+}
+
+void Reflection::PopulateTcParseFieldAux(
+    const internal::TailCallTableInfo& table_info,
+    TcParseTableBase::FieldAux* field_aux) const {
+  for (const auto& aux_entry : table_info.aux_entries) {
+    switch (aux_entry.type) {
+      case internal::TailCallTableInfo::kNothing:
+        *field_aux++ = {};
+        break;
+      case internal::TailCallTableInfo::kInlinedStringDonatedOffset:
+        field_aux++->offset =
+            static_cast<uint32_t>(schema_.inlined_string_donated_offset_);
+        break;
+      case internal::TailCallTableInfo::kSplitOffset:
+        field_aux++->offset = schema_.SplitOffset();
+        break;
+      case internal::TailCallTableInfo::kSplitSizeof:
+        field_aux++->offset = schema_.SizeofSplit();
+        break;
+      case internal::TailCallTableInfo::kSubTable:
+      case internal::TailCallTableInfo::kSubMessageWeak:
+      case internal::TailCallTableInfo::kMessageVerifyFunc:
+        GOOGLE_LOG(FATAL) << "Not supported";
+        break;
+      case internal::TailCallTableInfo::kSubMessage:
+        field_aux++->message_default_p =
+            GetDefaultMessageInstance(aux_entry.field);
+        break;
+      case internal::TailCallTableInfo::kEnumRange:
+        field_aux++->enum_range = {aux_entry.enum_range.start,
+                                   aux_entry.enum_range.size};
+        break;
+      case internal::TailCallTableInfo::kEnumValidator:
+        GOOGLE_LOG(FATAL) << "Not supported.";
+        break;
+      case internal::TailCallTableInfo::kNumericOffset:
+        field_aux++->offset = aux_entry.offset;
+        break;
+    }
+  }
+}
+
+const internal::TcParseTableBase* Reflection::CreateTcParseTable() const {
+  using TcParseTableBase = internal::TcParseTableBase;
+
+  if (descriptor_->options().message_set_wire_format()) {
+    return CreateTcParseTableForMessageSet();
+  }
+
+  std::vector<const FieldDescriptor*> fields;
+  constexpr int kNoHasbit = -1;
+  std::vector<int> has_bit_indices(
+      static_cast<size_t>(descriptor_->field_count()), kNoHasbit);
+  std::vector<int> inlined_string_indices = has_bit_indices;
+  for (int i = 0; i < descriptor_->field_count(); ++i) {
+    auto* field = descriptor_->field(i);
+    if (schema_.IsFieldStripped(field)) continue;
+
+    fields.push_back(field);
+    has_bit_indices[static_cast<size_t>(field->index())] =
+        static_cast<int>(schema_.HasBitIndex(field));
+
+    if (IsInlined(field)) {
+      inlined_string_indices[static_cast<size_t>(field->index())] =
+          schema_.InlinedStringIndex(field);
+    }
+  }
+  std::sort(fields.begin(), fields.end(),
+            [](const FieldDescriptor* a, const FieldDescriptor* b) {
+              return a->number() < b->number();
+            });
+
+  class ReflectionOptionProvider final
+      : public internal::TailCallTableInfo::OptionProvider {
+   public:
+    explicit ReflectionOptionProvider(const Reflection& ref) : ref_(ref) {}
+    internal::TailCallTableInfo::PerFieldOptions GetForField(
+        const FieldDescriptor* field) const final {
+      const auto verify_flag = [&] {
+        if (ref_.IsEagerlyVerifiedLazyField(field))
+          return internal::field_layout::kTvEager;
+        if (ref_.IsLazilyVerifiedLazyField(field))
+          return internal::field_layout::kTvLazy;
+        return internal::field_layout::TransformValidation{};
+      };
+      return {verify_flag(),
+              ref_.IsInlined(field),  //
+
+              // Only LITE can be implicitly weak.
+              /* is_implicitly_weak */ false,
+
+              // We could change this to use direct table.
+              // Might be easier to do when all messages support TDP.
+              /* use_direct_tcparser_table */ false,
+
+              /* is_lite */ false,  //
+              ref_.schema_.IsSplit(field)};
+    }
+
+   private:
+    const Reflection& ref_;
+  };
+  internal::TailCallTableInfo table_info(
+      descriptor_, fields, ReflectionOptionProvider(*this), has_bit_indices,
+      inlined_string_indices);
+
+  const size_t fast_entries_count = table_info.fast_path_fields.size();
+  GOOGLE_CHECK_EQ(fast_entries_count, 1 << table_info.table_size_log2);
+  const uint16_t lookup_table_offset = AlignTo<uint16_t>(
+      sizeof(TcParseTableBase) +
+      fast_entries_count * sizeof(TcParseTableBase::FastFieldEntry));
+  const uint32_t field_entry_offset = AlignTo<TcParseTableBase::FieldEntry>(
+      lookup_table_offset +
+      sizeof(uint16_t) * table_info.num_to_entry_table.size16());
+  const uint32_t aux_offset = AlignTo<TcParseTableBase::FieldAux>(
+      field_entry_offset +
+      sizeof(TcParseTableBase::FieldEntry) * fields.size());
+
+  int byte_size =
+      aux_offset +
+      sizeof(TcParseTableBase::FieldAux) * table_info.aux_entries.size() +
+      sizeof(char) * table_info.field_name_data.size();
+
+  void* p = ::operator new(byte_size);
+  auto* res = ::new (p) TcParseTableBase{
+      static_cast<uint16_t>(schema_.HasHasbits() ? schema_.HasBitsOffset() : 0),
+      // extensions handled through reflection.
+      0, 0, 0,
+      static_cast<uint32_t>(fields.empty() ? 0 : fields.back()->number()),
+      static_cast<uint8_t>((fast_entries_count - 1) << 3), lookup_table_offset,
+      table_info.num_to_entry_table.skipmap32, field_entry_offset,
+      static_cast<uint16_t>(fields.size()),
+      static_cast<uint16_t>(table_info.aux_entries.size()), aux_offset,
+      schema_.default_instance_, &internal::TcParser::ReflectionFallback};
+
+  // Now copy the rest of the payloads
+  PopulateTcParseFastEntries(table_info, res->fast_entry(0));
+
+  PopulateTcParseLookupTable(table_info, res->field_lookup_begin());
+
+  PopulateTcParseEntries(table_info, res->field_entries_begin());
+
+  PopulateTcParseFieldAux(table_info, res->field_aux(0u));
+
+  // Copy the name data.
+  if (!table_info.field_name_data.empty()) {
+    memcpy(res->name_data(), table_info.field_name_data.data(),
+           table_info.field_name_data.size());
+  }
+  // Validation to make sure we used all the bytes correctly.
+  GOOGLE_CHECK_EQ(res->name_data() + table_info.field_name_data.size() -
+               reinterpret_cast<char*>(res),
+           byte_size);
+
+  return res;
+}
+
 namespace {
 
 // Helper function to transform migration schema into reflection schema.
@@ -2872,9 +3372,11 @@
     MigrationSchema migration_schema) {
   ReflectionSchema result;
   result.default_instance_ = *default_instance;
-  // First 7 offsets are offsets to the special fields. The following offsets
+  // First 9 offsets are offsets to the special fields. The following offsets
   // are the proto fields.
-  result.offsets_ = offsets + migration_schema.offsets_index + 6;
+  //
+  // TODO(congliu): Find a way to not encode sizeof_split_ in offsets.
+  result.offsets_ = offsets + migration_schema.offsets_index + 8;
   result.has_bit_indices_ = offsets + migration_schema.has_bit_indices_index;
   result.has_bits_offset_ = offsets[migration_schema.offsets_index + 0];
   result.metadata_offset_ = offsets[migration_schema.offsets_index + 1];
@@ -2884,6 +3386,8 @@
   result.weak_field_map_offset_ = offsets[migration_schema.offsets_index + 4];
   result.inlined_string_donated_offset_ =
       offsets[migration_schema.offsets_index + 5];
+  result.split_offset_ = offsets[migration_schema.offsets_index + 6];
+  result.sizeof_split_ = offsets[migration_schema.offsets_index + 7];
   result.inlined_string_indices_ =
       offsets + migration_schema.inlined_string_indices_index;
   return result;
@@ -2970,7 +3474,7 @@
  private:
   MetadataOwner() = default;  // private because singleton
 
-  WrappedMutex mu_;
+  absl::Mutex mu_;
   std::vector<std::pair<const Metadata*, const Metadata*> > metadata_arrays_;
 };
 
@@ -2981,7 +3485,7 @@
   {
     // This only happens once per proto file. So a global mutex to serialize
     // calls to AddDescriptors.
-    static WrappedMutex mu{GOOGLE_PROTOBUF_LINKER_INITIALIZED};
+    static absl::Mutex mu{absl::kConstInit};
     mu.Lock();
     AddDescriptors(table);
     mu.Unlock();
@@ -3076,9 +3580,8 @@
 namespace internal {
 
 Metadata AssignDescriptors(const DescriptorTable* (*table)(),
-                           internal::once_flag* once,
-                           const Metadata& metadata) {
-  call_once(*once, [=] {
+                           absl::once_flag* once, const Metadata& metadata) {
+  absl::call_once(*once, [=] {
     auto* t = table();
     AssignDescriptorsImpl(t, t->is_eager);
   });
@@ -3088,7 +3591,7 @@
 
 void AssignDescriptors(const DescriptorTable* table, bool eager) {
   if (!eager) eager = table->is_eager;
-  call_once(*table->once, AssignDescriptorsImpl, table, eager);
+  absl::call_once(*table->once, AssignDescriptorsImpl, table, eager);
 }
 
 AddDescriptorsRunner::AddDescriptorsRunner(const DescriptorTable* table) {
@@ -3165,4 +3668,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 334b2cc..70a75aa 100644
--- a/src/google/protobuf/generated_message_reflection.h
+++ b/src/google/protobuf/generated_message_reflection.h
@@ -38,17 +38,19 @@
 #ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_enum_reflection.h>
-#include <google/protobuf/unknown_field_set.h>
+#include <string>
 
+#include "google/protobuf/stubs/common.h"
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_enum_reflection.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/unknown_field_set.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -72,6 +74,16 @@
 class ExtensionSet;  // extension_set.h
 class WeakFieldMap;  // weak_field_map.h
 
+// 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.
+constexpr uint32_t kInvalidFieldOffsetTag = 0x40000000u;
+
+// Mask used on offsets for split fields.
+constexpr uint32_t kSplitFieldOffsetMask = 0x80000000u;
+constexpr uint32_t kLazyMask = 0x1u;
+constexpr uint32_t kInlinedMask = 0x1u;
+
 // This struct describes the internal layout of the message, hence this is
 // used to act on the message reflectively.
 //   default_instance:  The default instance of the message.  This is only
@@ -234,6 +246,24 @@
     return false;
   }
 
+  bool IsSplit() const { return split_offset_ != -1; }
+
+  bool IsSplit(const FieldDescriptor* field) const {
+    return split_offset_ != -1 &&
+           (offsets_[field->index()] & kSplitFieldOffsetMask) != 0;
+  }
+
+  // Byte offset of _split_.
+  uint32_t SplitOffset() const {
+    GOOGLE_DCHECK(IsSplit());
+    return static_cast<uint32_t>(split_offset_);
+  }
+
+  uint32_t SizeofSplit() const {
+    GOOGLE_DCHECK(IsSplit());
+    return static_cast<uint32_t>(sizeof_split_);
+  }
+
 
   bool HasWeakFields() const { return weak_field_map_offset_ > 0; }
 
@@ -254,6 +284,8 @@
   int weak_field_map_offset_;
   const uint32_t* inlined_string_indices_;
   int inlined_string_donated_offset_;
+  int split_offset_;
+  int sizeof_split_;
 
   // We tag offset values to provide additional data about fields (such as
   // "unused" or "lazy" or "inlined").
@@ -261,15 +293,15 @@
     if (type == FieldDescriptor::TYPE_MESSAGE ||
         type == FieldDescriptor::TYPE_STRING ||
         type == FieldDescriptor::TYPE_BYTES) {
-      return v & 0xFFFFFFFEu;
+      return v & (~kSplitFieldOffsetMask) & (~kInlinedMask) & (~kLazyMask);
     }
-    return v;
+    return v & (~kSplitFieldOffsetMask);
   }
 
   static bool Inlined(uint32_t v, FieldDescriptor::Type type) {
     if (type == FieldDescriptor::TYPE_STRING ||
         type == FieldDescriptor::TYPE_BYTES) {
-      return (v & 1u) != 0u;
+      return (v & kInlinedMask) != 0u;
     } else {
       // Non string/byte fields are not inlined.
       return false;
@@ -299,7 +331,7 @@
   int size;  // of serialized descriptor
   const char* descriptor;
   const char* filename;
-  once_flag* once;
+  absl::once_flag* once;
   const DescriptorTable* const* deps;
   int num_deps;
   int num_messages;
@@ -312,13 +344,6 @@
   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
@@ -332,7 +357,7 @@
 // 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,
+                                           absl::once_flag* once,
                                            const Metadata& metadata);
 
 // These cannot be in lite so we put them in the reflection.
@@ -345,10 +370,38 @@
   explicit AddDescriptorsRunner(const DescriptorTable* table);
 };
 
+struct DenseEnumCacheInfo {
+  std::atomic<const std::string**> cache;
+  int min_val;
+  int max_val;
+  const EnumDescriptor* (*descriptor_fn)();
+};
+PROTOBUF_EXPORT const std::string& NameOfDenseEnumSlow(int v,
+                                                       DenseEnumCacheInfo*);
+
+// Similar to the routine NameOfEnum, this routine returns the name of an enum.
+// Unlike that routine, it allocates, on-demand, a block of pointers to the
+// std::string objects allocated by reflection to store the enum names. This
+// way, as long as the enum values are fairly dense, looking them up can be
+// very fast. This assumes all the enums fall in the range [min_val .. max_val].
+template <const EnumDescriptor* (*descriptor_fn)(), int min_val, int max_val>
+const std::string& NameOfDenseEnum(int v) {
+  static_assert(max_val - min_val >= 0, "Too many enums between min and max.");
+  static DenseEnumCacheInfo deci = {/* atomic ptr */ {}, min_val, max_val,
+                                    descriptor_fn};
+  const std::string** cache = deci.cache.load(std::memory_order_acquire );
+  if (PROTOBUF_PREDICT_TRUE(cache != nullptr)) {
+    if (PROTOBUF_PREDICT_TRUE(v >= min_val && v <= max_val)) {
+      return *cache[v - min_val];
+    }
+  }
+  return NameOfDenseEnumSlow(v, &deci);
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_REFLECTION_H__
diff --git a/src/google/protobuf/generated_message_reflection_unittest.cc b/src/google/protobuf/generated_message_reflection_unittest.cc
index 50ce399..a4fb04c 100644
--- a/src/google/protobuf/generated_message_reflection_unittest.cc
+++ b/src/google/protobuf/generated_message_reflection_unittest.cc
@@ -42,25 +42,27 @@
 // compiler/cpp/unittest, except using the reflection interface
 // rather than generated accessors.
 
-#include <google/protobuf/generated_message_reflection.h>
+#include "google/protobuf/generated_message_reflection.h"
 
 #include <memory>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/map_unittest.pb.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_mset.pb.h>
-#include <google/protobuf/unittest_mset_wire_format.pb.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/map_test_util.h>
-#include <google/protobuf/test_util.h>
+#include "absl/strings/cord.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/unittest.pb.h"
+#include "google/protobuf/unittest_mset.pb.h"
+#include "google/protobuf/unittest_mset_wire_format.pb.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -1261,8 +1263,6 @@
   const Reflection* reflection = message.GetReflection();
   const Descriptor* descriptor = message.GetDescriptor();
 
-#define f(NAME) descriptor->FindFieldByName(NAME)
-
   // Testing every single failure mode would be too much work.  Let's just
   // check a few.
   EXPECT_DEATH(
@@ -1301,8 +1301,6 @@
       "  Message type: protobuf_unittest.TestAllTypes\n"
       "  Field       : protobuf_unittest.ForeignMessage.c\n"
       "  Problem     : Field does not match message type.");
-
-#undef f
 }
 
 #endif  // PROTOBUF_HAS_DEATH_TEST
diff --git a/src/google/protobuf/generated_message_tctable_decl.h b/src/google/protobuf/generated_message_tctable_decl.h
index b1bb1de..4d12af3 100644
--- a/src/google/protobuf/generated_message_tctable_decl.h
+++ b/src/google/protobuf/generated_message_tctable_decl.h
@@ -36,15 +36,16 @@
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
 
 #include <array>
+#include <atomic>
 #include <cstddef>
 #include <cstdint>
 #include <type_traits>
 
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/parse_context.h>
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
 
 // Must come last:
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -85,6 +86,27 @@
   uint8_t aux_idx() const { return static_cast<uint8_t>(data >> 24); }
   uint16_t offset() const { return static_cast<uint16_t>(data >> 48); }
 
+  // Constructor for special entries that do not represent a field.
+  //  - End group: `nonfield_info` is the decoded tag.
+  constexpr TcFieldData(uint16_t coded_tag, uint16_t nonfield_info)
+      : data(uint64_t{nonfield_info} << 16 |  //
+             uint64_t{coded_tag}) {}
+
+  // Fields used in non-field entries
+  //
+  //     Bit:
+  //     +-----------+-------------------+
+  //     |63    ..     32|31     ..     0|
+  //     +---------------+---------------+
+  //     :   .   :   .   :   . 16|=======| [16] coded_tag()
+  //     :   .   :   . 32|=======|   .   : [16] decoded_tag()
+  //     :---.---:---.---:   .   :   .   : [32] (unused)
+  //     +-----------+-------------------+
+  //     |63    ..     32|31     ..     0|
+  //     +---------------+---------------+
+
+  uint16_t decoded_tag() const { return static_cast<uint16_t>(data >> 16); }
+
   // Fields used in mini table parsing:
   //
   //     Bit:
@@ -100,6 +122,20 @@
   uint32_t tag() const { return static_cast<uint32_t>(data); }
   uint32_t entry_offset() const { return static_cast<uint32_t>(data >> 32); }
 
+  // Fields used for passing unknown enum values to the generic fallback:
+  //     Bit:
+  //     +-----------+-------------------+
+  //     |63    ..     32|31     ..     0|
+  //     +---------------+---------------+
+  //     :   .   :   .   |===============| [32] tag() (decoded)
+  //     |===============|   .   :   .   : [32] unknown_enum_value()
+  //     +-----------+-------------------+
+  //     |63    ..     32|31     ..     0|
+  //     +---------------+---------------+
+  int32_t unknown_enum_value() const {
+    return static_cast<int32_t>(data >> 32);
+  }
+
   uint64_t data;
 };
 
@@ -120,6 +156,8 @@
 #pragma warning(disable : 4324)
 #endif
 
+struct FieldAuxDefaultMessage {};
+
 // Base class for message-level table with info for the tail-call parser.
 struct alignas(uint64_t) TcParseTableBase {
   // Common attributes for message layout:
@@ -173,25 +211,58 @@
   // Table entry for fast-path tailcall dispatch handling.
   struct FastFieldEntry {
     // Target function for dispatch:
-    TailCallParseFunc target;
+    mutable std::atomic<TailCallParseFunc> target_atomic;
+
     // Field data used during parse:
     TcFieldData bits;
+
+    // Default initializes this instance with undefined values.
+    FastFieldEntry() = default;
+
+    // Constant initializes this instance
+    constexpr FastFieldEntry(TailCallParseFunc func, TcFieldData bits)
+        : target_atomic(func), bits(bits) {}
+
+    // FastFieldEntry is copy-able and assignable, which is intended
+    // mainly for testing and debugging purposes.
+    FastFieldEntry(const FastFieldEntry& rhs) noexcept
+        : FastFieldEntry(rhs.target(), rhs.bits) {}
+    FastFieldEntry& operator=(const FastFieldEntry& rhs) noexcept {
+      SetTarget(rhs.target());
+      bits = rhs.bits;
+      return *this;
+    }
+
+    // Protocol buffer code should use these relaxed accessors.
+    TailCallParseFunc target() const {
+      return target_atomic.load(std::memory_order_relaxed);
+    }
+    void SetTarget(TailCallParseFunc func) const {
+      return target_atomic.store(func, std::memory_order_relaxed);
+    }
   };
   // There is always at least one table entry.
   const FastFieldEntry* fast_entry(size_t idx) const {
     return reinterpret_cast<const FastFieldEntry*>(this + 1) + idx;
   }
+  FastFieldEntry* fast_entry(size_t idx) {
+    return reinterpret_cast<FastFieldEntry*>(this + 1) + idx;
+  }
 
   // Returns a begin iterator (pointer) to the start of the field lookup table.
   const uint16_t* field_lookup_begin() const {
     return reinterpret_cast<const uint16_t*>(reinterpret_cast<uintptr_t>(this) +
                                              lookup_table_offset);
   }
+  uint16_t* field_lookup_begin() {
+    return reinterpret_cast<uint16_t*>(reinterpret_cast<uintptr_t>(this) +
+                                       lookup_table_offset);
+  }
 
   // Field entry for all fields.
   struct FieldEntry {
     uint32_t offset;     // offset in the message object
-    int32_t has_idx;     // has-bit index
+    int32_t has_idx;     // has-bit index, relative to the message object
     uint16_t aux_idx;    // index for `field_aux`.
     uint16_t type_card;  // `FieldType` and `Cardinality` (see _impl.h)
   };
@@ -201,29 +272,52 @@
     return reinterpret_cast<const FieldEntry*>(
         reinterpret_cast<uintptr_t>(this) + field_entries_offset);
   }
+  FieldEntry* field_entries_begin() {
+    return reinterpret_cast<FieldEntry*>(reinterpret_cast<uintptr_t>(this) +
+                                         field_entries_offset);
+  }
 
   // Auxiliary entries for field types that need extra information.
   union FieldAux {
-    constexpr FieldAux() : message_default(nullptr) {}
+    constexpr FieldAux() : message_default_p(nullptr) {}
     constexpr FieldAux(bool (*enum_validator)(int))
         : enum_validator(enum_validator) {}
     constexpr FieldAux(field_layout::Offset off) : offset(off.off) {}
     constexpr FieldAux(int16_t range_start, uint16_t range_length)
         : enum_range{range_start, range_length} {}
-    constexpr FieldAux(const MessageLite* msg) : message_default(msg) {}
+    constexpr FieldAux(const MessageLite* msg) : message_default_p(msg) {}
+    constexpr FieldAux(FieldAuxDefaultMessage, const void* msg)
+        : message_default_p(msg) {}
+    constexpr FieldAux(const TcParseTableBase* table) : table(table) {}
+    constexpr FieldAux(LazyEagerVerifyFnType verify_func)
+        : verify_func(verify_func) {}
     bool (*enum_validator)(int);
     struct {
       int16_t start;    // minimum enum number (if it fits)
       uint16_t length;  // length of range (i.e., max = start + length - 1)
     } enum_range;
     uint32_t offset;
-    const MessageLite* message_default;
+    const void* message_default_p;
+    const TcParseTableBase* table;
+    LazyEagerVerifyFnType verify_func;
+
+    const MessageLite* message_default() const {
+      return static_cast<const MessageLite*>(message_default_p);
+    }
+    const MessageLite* message_default_weak() const {
+      return *static_cast<const MessageLite* const*>(message_default_p);
+    }
   };
   const FieldAux* field_aux(uint32_t idx) const {
     return reinterpret_cast<const FieldAux*>(reinterpret_cast<uintptr_t>(this) +
                                              aux_offset) +
            idx;
   }
+  FieldAux* field_aux(uint32_t idx) {
+    return reinterpret_cast<FieldAux*>(reinterpret_cast<uintptr_t>(this) +
+                                       aux_offset) +
+           idx;
+  }
   const FieldAux* field_aux(const FieldEntry* entry) const {
     return field_aux(entry->aux_idx);
   }
@@ -234,6 +328,11 @@
                                          aux_offset +
                                          num_aux_entries * sizeof(FieldAux));
   }
+  char* name_data() {
+    return reinterpret_cast<char*>(reinterpret_cast<uintptr_t>(this) +
+                                   aux_offset +
+                                   num_aux_entries * sizeof(FieldAux));
+  }
 };
 
 #if defined(_MSC_VER) && !defined(_WIN64)
@@ -265,7 +364,7 @@
   // Entries for all fields:
   std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
   std::array<TcParseTableBase::FieldAux, kNumFieldAux> aux_entries;
-  std::array<char, kNameTableSize> field_names;
+  std::array<char, kNameTableSize == 0 ? 1 : kNameTableSize> field_names;
 };
 
 // Partial specialization: if there are no aux entries, there will be no array.
@@ -281,7 +380,7 @@
       fast_entries;
   std::array<uint16_t, kFieldLookupSize> field_lookup_table;
   std::array<TcParseTableBase::FieldEntry, kNumFieldEntries> field_entries;
-  std::array<char, kNameTableSize> field_names;
+  std::array<char, kNameTableSize == 0 ? 1 : kNameTableSize> field_names;
 };
 
 // Partial specialization: if there are no fields at all, then we can save space
@@ -293,7 +392,7 @@
   // The fast parsing loop will always use this entry, so it must be present.
   std::array<TcParseTableBase::FastFieldEntry, 1> fast_entries;
   std::array<uint16_t, kFieldLookupSize> field_lookup_table;
-  std::array<char, kNameTableSize> field_names;
+  std::array<char, kNameTableSize == 0 ? 1 : kNameTableSize> field_names;
 };
 
 static_assert(std::is_standard_layout<TcParseTable<1>>::value,
@@ -307,6 +406,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_DECL_H__
diff --git a/src/google/protobuf/generated_message_tctable_full.cc b/src/google/protobuf/generated_message_tctable_full.cc
index b77bb8d..49777a1 100644
--- a/src/google/protobuf/generated_message_tctable_full.cc
+++ b/src/google/protobuf/generated_message_tctable_full.cc
@@ -30,24 +30,65 @@
 
 #include <cstdint>
 
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/generated_message_tctable_impl.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/generated_message_tctable_impl.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/wire_format.h"
 
-// clang-format off
-#include <google/protobuf/port_def.inc>
-// clang-format on
+// must be last
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace internal {
+using ::google::protobuf::internal::DownCast;
 
 const char* TcParser::GenericFallback(PROTOBUF_TC_PARAM_DECL) {
   return GenericFallbackImpl<Message, UnknownFieldSet>(PROTOBUF_TC_PARAM_PASS);
 }
 
+const char* TcParser::ReflectionFallback(PROTOBUF_TC_PARAM_DECL) {
+  SyncHasbits(msg, hasbits, table);
+  uint32_t tag = data.tag();
+  if (tag == 0 || (tag & 7) == WireFormatLite::WIRETYPE_END_GROUP) {
+    ctx->SetLastTag(tag);
+    return ptr;
+  }
+
+  if (MustFallbackToGeneric(PROTOBUF_TC_PARAM_PASS)) {
+    PROTOBUF_MUSTTAIL return GenericFallback(PROTOBUF_TC_PARAM_PASS);
+  }
+
+  auto* full_msg = DownCast<Message*>(msg);
+  auto* descriptor = full_msg->GetDescriptor();
+  auto* reflection = full_msg->GetReflection();
+  int field_number = WireFormatLite::GetTagFieldNumber(tag);
+  const FieldDescriptor* field = descriptor->FindFieldByNumber(field_number);
+
+  // If that failed, check if the field is an extension.
+  if (field == nullptr && descriptor->IsExtensionNumber(field_number)) {
+    if (ctx->data().pool == nullptr) {
+      field = reflection->FindKnownExtensionByNumber(field_number);
+    } else {
+      field = ctx->data().pool->FindExtensionByNumber(descriptor, field_number);
+    }
+  }
+
+  return WireFormat::_InternalParseAndMergeField(full_msg, ptr, ctx, tag,
+                                                 reflection, field);
+}
+
+const char* TcParser::ReflectionParseLoop(PROTOBUF_TC_PARAM_DECL) {
+  (void)data;
+  (void)table;
+  (void)hasbits;
+  // Call into the wire format reflective parse loop.
+  return WireFormat::_InternalParse(DownCast<Message*>(msg), ptr, ctx);
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/generated_message_tctable_gen.cc b/src/google/protobuf/generated_message_tctable_gen.cc
new file mode 100644
index 0000000..1c5e228
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_gen.cc
@@ -0,0 +1,848 @@
+// 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/generated_message_tctable_gen.h"
+
+#include <algorithm>
+#include <limits>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/generated_message_tctable_decl.h"
+#include "google/protobuf/generated_message_tctable_impl.h"
+#include "google/protobuf/wire_format.h"
+
+// Must come last:
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+
+bool GetEnumValidationRange(const EnumDescriptor* enum_type, int16_t& start,
+                            uint16_t& size) {
+  GOOGLE_CHECK_GT(enum_type->value_count(), 0) << enum_type->DebugString();
+
+  // Check if the enum values are a single, contiguous range.
+  std::vector<int> enum_values;
+  for (int i = 0, N = static_cast<int>(enum_type->value_count()); i < N; ++i) {
+    enum_values.push_back(enum_type->value(i)->number());
+  }
+  auto values_begin = enum_values.begin();
+  auto values_end = enum_values.end();
+  std::sort(values_begin, values_end);
+  enum_values.erase(std::unique(values_begin, values_end), values_end);
+
+  if (std::numeric_limits<int16_t>::min() <= enum_values[0] &&
+      enum_values[0] <= std::numeric_limits<int16_t>::max() &&
+      enum_values.size() <= std::numeric_limits<uint16_t>::max() &&
+      static_cast<int>(enum_values[0] + enum_values.size() - 1) ==
+          enum_values.back()) {
+    start = static_cast<int16_t>(enum_values[0]);
+    size = static_cast<uint16_t>(enum_values.size());
+    return true;
+  } else {
+    return false;
+  }
+}
+
+void PopulateFastFieldEntry(const TailCallTableInfo::FieldEntryInfo& entry,
+                            const TailCallTableInfo::PerFieldOptions& options,
+                            TailCallTableInfo::FastFieldInfo& info) {
+  const FieldDescriptor* field = entry.field;
+  std::string name = "::_pbi::TcParser::Fast";
+  uint8_t aux_idx = static_cast<uint8_t>(entry.aux_idx);
+
+  static const char* kPrefix[] = {
+      nullptr,  // 0
+      "F64",    // TYPE_DOUBLE = 1,
+      "F32",    // TYPE_FLOAT = 2,
+      "V64",    // TYPE_INT64 = 3,
+      "V64",    // TYPE_UINT64 = 4,
+      "V32",    // TYPE_INT32 = 5,
+      "F64",    // TYPE_FIXED64 = 6,
+      "F32",    // TYPE_FIXED32 = 7,
+      "V8",     // TYPE_BOOL = 8,
+      "",       // TYPE_STRING = 9,
+      "G",      // TYPE_GROUP = 10,
+      "M",      // TYPE_MESSAGE = 11,
+      "B",      // TYPE_BYTES = 12,
+      "V32",    // TYPE_UINT32 = 13,
+      "",       // TYPE_ENUM = 14,
+      "F32",    // TYPE_SFIXED32 = 15,
+      "F64",    // TYPE_SFIXED64 = 16,
+      "Z32",    // TYPE_SINT32 = 17,
+      "Z64",    // TYPE_SINT64 = 18,
+  };
+  name.append(kPrefix[field->type()]);
+
+  if (field->type() == field->TYPE_ENUM) {
+    // Enums are handled as:
+    //  - V32 for open enums
+    //  - Er (and Er0/Er1) for sequential enums
+    //  - Ev for the rest
+    if (cpp::HasPreservingUnknownEnumSemantics(field)) {
+      name.append("V32");
+    } else {
+      int16_t start;
+      uint16_t size;
+      if (GetEnumValidationRange(field->enum_type(), start, size)) {
+        name.append("Er");
+        int max_value = start + size - 1;
+        if (max_value <= 127 && (start == 0 || start == 1)) {
+          name.append(1, '0' + start);
+          aux_idx = max_value;
+        }
+      } else {
+        name.append("Ev");
+      }
+    }
+  }
+  if (field->type() == field->TYPE_STRING) {
+    switch (internal::cpp::GetUtf8CheckMode(field, options.is_lite)) {
+      case internal::cpp::Utf8CheckMode::kStrict:
+        name.append("U");
+        break;
+      case internal::cpp::Utf8CheckMode::kVerify:
+        name.append("S");
+        break;
+      case internal::cpp::Utf8CheckMode::kNone:
+        name.append("B");
+        break;
+    }
+  }
+  if (field->type() == field->TYPE_STRING ||
+      field->type() == field->TYPE_BYTES) {
+    if (field->options().ctype() == FieldOptions::CORD) {
+      name.append("c");
+    } else if (options.is_string_inlined) {
+      name.append("i");
+      GOOGLE_CHECK(!field->is_repeated());
+      aux_idx = static_cast<uint8_t>(entry.inlined_string_idx);
+    }
+  }
+  if (field->type() == field->TYPE_MESSAGE ||
+      field->type() == field->TYPE_GROUP) {
+    name.append(options.lazy_opt != 0               ? "l"
+                : options.use_direct_tcparser_table ? "t"
+                                                    : "d");
+  }
+
+  // The field implementation functions are prefixed by cardinality:
+  //   `S` for optional or implicit fields.
+  //   `R` for non-packed repeated.
+  //   `P` for packed repeated.
+  name.append(field->is_packed()               ? "P"
+              : field->is_repeated()           ? "R"
+              : field->real_containing_oneof() ? "O"
+                                               : "S");
+
+  // Append the tag length. Fast parsing only handles 1- or 2-byte tags.
+  name.append(field->number() < 16 ? "1" : "2");
+
+  info.func_name = std::move(name);
+  info.aux_idx = aux_idx;
+}
+
+bool IsFieldEligibleForFastParsing(
+    const TailCallTableInfo::FieldEntryInfo& entry,
+    const TailCallTableInfo::OptionProvider& option_provider) {
+  const auto* field = entry.field;
+  const auto options = option_provider.GetForField(field);
+  // Map, oneof, weak, and lazy fields are not handled on the fast path.
+  if (field->is_map() || field->real_containing_oneof() ||
+      field->options().weak() || options.is_implicitly_weak ||
+      options.should_split) {
+    return false;
+  }
+
+  // We will check for a valid auxiliary index range later. However, we might
+  // want to change the value we check for inlined string fields.
+  int aux_idx = entry.aux_idx;
+
+  switch (field->type()) {
+      // Some bytes fields can be handled on fast path.
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      if (field->options().ctype() == FieldOptions::STRING) {
+        // strings are fine...
+      } else if (field->options().ctype() == FieldOptions::CORD) {
+        // Cords are worth putting into the fast table, if they're not repeated
+        if (field->is_repeated()) return false;
+      } else {
+        return false;
+      }
+      if (options.is_string_inlined) {
+        GOOGLE_CHECK(!field->is_repeated());
+        // For inlined strings, the donation state index is stored in the
+        // `aux_idx` field of the fast parsing info. We need to check the range
+        // of that value instead of the auxiliary index.
+        aux_idx = entry.inlined_string_idx;
+      }
+      break;
+
+    default:
+      break;
+  }
+
+  if (cpp::HasHasbit(field)) {
+    // The tailcall parser can only update the first 32 hasbits. Fields with
+    // has-bits beyond the first 32 are handled by mini parsing/fallback.
+    GOOGLE_CHECK_GE(entry.hasbit_idx, 0) << field->DebugString();
+    if (entry.hasbit_idx >= 32) return false;
+  }
+
+  // If the field needs auxiliary data, then the aux index is needed. This
+  // must fit in a uint8_t.
+  if (aux_idx > std::numeric_limits<uint8_t>::max()) {
+    return false;
+  }
+
+  // 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
+  //    ^^^^^^^  ^^^^^^^
+  if (field->number() >= 1 << 11) return false;
+
+  return true;
+}
+
+absl::optional<uint32_t> GetEndGroupTag(const Descriptor* descriptor) {
+  auto* parent = descriptor->containing_type();
+  if (parent == nullptr) return absl::nullopt;
+  for (int i = 0; i < parent->field_count(); ++i) {
+    auto* field = parent->field(i);
+    if (field->type() == field->TYPE_GROUP &&
+        field->message_type() == descriptor) {
+      return WireFormatLite::MakeTag(field->number(),
+                                     WireFormatLite::WIRETYPE_END_GROUP);
+    }
+  }
+  return absl::nullopt;
+}
+
+uint32_t RecodeTagForFastParsing(uint32_t tag) {
+  GOOGLE_DCHECK_LE(tag, 0x3FFF);
+  // Construct the varint-coded tag. If it is more than 7 bits, we need to
+  // shift the high bits and add a continue bit.
+  if (uint32_t hibits = tag & 0xFFFFFF80) {
+    // hi = tag & ~0x7F
+    // lo = tag & 0x7F
+    // This shifts hi to the left by 1 to the next byte and sets the
+    // continuation bit.
+    tag = tag + hibits + 128;
+  }
+  return tag;
+}
+
+std::vector<TailCallTableInfo::FastFieldInfo> SplitFastFieldsForSize(
+    absl::optional<uint32_t> end_group_tag,
+    const std::vector<TailCallTableInfo::FieldEntryInfo>& field_entries,
+    int table_size_log2,
+    const TailCallTableInfo::OptionProvider& option_provider) {
+  std::vector<TailCallTableInfo::FastFieldInfo> result(1 << table_size_log2);
+  const uint32_t idx_mask = static_cast<uint32_t>(result.size() - 1);
+  const auto tag_to_idx = [&](uint32_t tag) {
+    // 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
+    //   tag: 1nnnnttt 0nnnnnnn
+    //        ^^^^^
+    //         idx (table_size_log2=5)
+    // 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.
+    return (tag >> 3) & idx_mask;
+  };
+
+  if (end_group_tag.has_value() && (*end_group_tag >> 14) == 0) {
+    // Fits in 1 or 2 varint bytes.
+    const uint32_t tag = RecodeTagForFastParsing(*end_group_tag);
+    const uint32_t fast_idx = tag_to_idx(tag);
+
+    TailCallTableInfo::FastFieldInfo& info = result[fast_idx];
+    info.func_name = "::_pbi::TcParser::FastEndG";
+    info.func_name.append(*end_group_tag < 128 ? "1" : "2");
+    info.coded_tag = tag;
+    info.nonfield_info = *end_group_tag;
+  }
+
+  for (const auto& entry : field_entries) {
+    if (!IsFieldEligibleForFastParsing(entry, option_provider)) {
+      continue;
+    }
+
+    const auto* field = entry.field;
+    const auto options = option_provider.GetForField(field);
+    const uint32_t tag = RecodeTagForFastParsing(WireFormat::MakeTag(field));
+    const uint32_t fast_idx = tag_to_idx(tag);
+
+    TailCallTableInfo::FastFieldInfo& info = result[fast_idx];
+    if (!info.func_name.empty()) {
+      // This field entry is already filled.
+      continue;
+    }
+
+    // Fill in this field's entry:
+    GOOGLE_CHECK(info.func_name.empty()) << info.func_name;
+    PopulateFastFieldEntry(entry, options, info);
+    info.field = field;
+    info.coded_tag = tag;
+    // If this field does not have presence, then it can set an out-of-bounds
+    // bit (tailcall parsing uses a uint64_t for hasbits, but only stores 32).
+    info.hasbit_idx = cpp::HasHasbit(field) ? entry.hasbit_idx : 63;
+  }
+  return result;
+}
+
+// Filter out fields that will be handled by mini parsing.
+std::vector<const FieldDescriptor*> FilterMiniParsedFields(
+    const std::vector<const FieldDescriptor*>& fields,
+    const TailCallTableInfo::OptionProvider& option_provider) {
+  std::vector<const FieldDescriptor*> generated_fallback_fields;
+
+  for (const auto* field : fields) {
+    auto options = option_provider.GetForField(field);
+
+    bool handled = false;
+    switch (field->type()) {
+      case FieldDescriptor::TYPE_DOUBLE:
+      case FieldDescriptor::TYPE_FLOAT:
+      case FieldDescriptor::TYPE_FIXED32:
+      case FieldDescriptor::TYPE_SFIXED32:
+      case FieldDescriptor::TYPE_FIXED64:
+      case FieldDescriptor::TYPE_SFIXED64:
+      case FieldDescriptor::TYPE_BOOL:
+      case FieldDescriptor::TYPE_UINT32:
+      case FieldDescriptor::TYPE_SINT32:
+      case FieldDescriptor::TYPE_INT32:
+      case FieldDescriptor::TYPE_UINT64:
+      case FieldDescriptor::TYPE_SINT64:
+      case FieldDescriptor::TYPE_INT64:
+      case FieldDescriptor::TYPE_ENUM:
+        // These are handled by MiniParse, so we don't need any generated
+        // fallback code.
+        handled = true;
+        break;
+
+      case FieldDescriptor::TYPE_BYTES:
+      case FieldDescriptor::TYPE_STRING:
+        if (options.is_string_inlined) {
+          // TODO(b/198211897): support InilnedStringField.
+          handled = false;
+        } else {
+          handled = true;
+        }
+        break;
+
+      case FieldDescriptor::TYPE_MESSAGE:
+      case FieldDescriptor::TYPE_GROUP:
+        // TODO(b/210762816): support remaining field types.
+        if (field->is_map() || field->options().weak()) {
+          handled = false;
+        } else {
+          handled = true;
+        }
+        break;
+
+      default:
+        handled = false;
+        break;
+    }
+    if (!handled) generated_fallback_fields.push_back(field);
+  }
+
+  return generated_fallback_fields;
+}
+
+// We only need field names for reporting UTF-8 parsing errors, so we only
+// emit them for string fields with Utf8 transform specified.
+absl::string_view FieldNameForTable(
+    const TailCallTableInfo::FieldEntryInfo& entry) {
+  const auto* field = entry.field;
+  if (field->type() == FieldDescriptor::TYPE_STRING) {
+    const uint16_t xform_val = entry.type_card & field_layout::kTvMask;
+
+    switch (xform_val) {
+      case field_layout::kTvUtf8:
+      case field_layout::kTvUtf8Debug:
+        return field->name();
+    }
+  }
+  return "";
+}
+
+std::vector<uint8_t> GenerateFieldNames(
+    const Descriptor* descriptor,
+    const std::vector<TailCallTableInfo::FieldEntryInfo>& entries) {
+  static constexpr int kMaxNameLength = 255;
+  std::vector<uint8_t> out;
+
+  bool found_needed_name = false;
+  for (const auto& entry : entries) {
+    if (!FieldNameForTable(entry).empty()) {
+      found_needed_name = true;
+      break;
+    }
+  }
+
+  // No names needed. Omit the whole table.
+  if (!found_needed_name) {
+    return out;
+  }
+
+  // First, we output the size of each string, as an unsigned byte. The first
+  // string is the message name.
+  int count = 1;
+  out.push_back(std::min(static_cast<int>(descriptor->full_name().size()),
+                         kMaxNameLength));
+  for (const auto& entry : entries) {
+    out.push_back(FieldNameForTable(entry).size());
+    ++count;
+  }
+  while (count & 7) {  // align to an 8-byte boundary
+    out.push_back(0);
+    ++count;
+  }
+  // The message name is stored at the beginning of the string
+  std::string message_name = descriptor->full_name();
+  if (message_name.size() > kMaxNameLength) {
+    static constexpr int kNameHalfLength = (kMaxNameLength - 3) / 2;
+    message_name = absl::StrCat(
+        message_name.substr(0, kNameHalfLength), "...",
+        message_name.substr(message_name.size() - kNameHalfLength));
+  }
+  out.insert(out.end(), message_name.begin(), message_name.end());
+  // Then we output the actual field names
+  for (const auto& entry : entries) {
+    const auto& field_name = FieldNameForTable(entry);
+    out.insert(out.end(), field_name.begin(), field_name.end());
+  }
+
+  return out;
+}
+
+TailCallTableInfo::NumToEntryTable MakeNumToEntryTable(
+    const std::vector<const FieldDescriptor*>& field_descriptors) {
+  TailCallTableInfo::NumToEntryTable num_to_entry_table;
+  num_to_entry_table.skipmap32 = static_cast<uint32_t>(-1);
+
+  // skip_entry_block is the current block of SkipEntries that we're
+  // appending to.  cur_block_first_fnum is the number of the first
+  // field represented by the block.
+  uint16_t field_entry_index = 0;
+  uint16_t N = field_descriptors.size();
+  // First, handle field numbers 1-32, which affect only the initial
+  // skipmap32 and don't generate additional skip-entry blocks.
+  for (; field_entry_index != N; ++field_entry_index) {
+    auto* field_descriptor = field_descriptors[field_entry_index];
+    if (field_descriptor->number() > 32) break;
+    auto skipmap32_index = field_descriptor->number() - 1;
+    num_to_entry_table.skipmap32 -= 1 << skipmap32_index;
+  }
+  // If all the field numbers were less than or equal to 32, we will have
+  // no further entries to process, and we are already done.
+  if (field_entry_index == N) return num_to_entry_table;
+
+  TailCallTableInfo::SkipEntryBlock* block = nullptr;
+  bool start_new_block = true;
+  // To determine sparseness, track the field number corresponding to
+  // the start of the most recent skip entry.
+  uint32_t last_skip_entry_start = 0;
+  for (; field_entry_index != N; ++field_entry_index) {
+    auto* field_descriptor = field_descriptors[field_entry_index];
+    uint32_t fnum = static_cast<uint32_t>(field_descriptor->number());
+    GOOGLE_CHECK_GT(fnum, last_skip_entry_start);
+    if (start_new_block == false) {
+      // If the next field number is within 15 of the last_skip_entry_start, we
+      // continue writing just to that entry.  If it's between 16 and 31 more,
+      // then we just extend the current block by one. If it's more than 31
+      // more, we have to add empty skip entries in order to continue using the
+      // existing block.  Obviously it's just 32 more, it doesn't make sense to
+      // start a whole new block, since new blocks mean having to write out
+      // their starting field number, which is 32 bits, as well as the size of
+      // the additional block, which is 16... while an empty SkipEntry16 only
+      // costs 32 bits.  So if it was 48 more, it's a slight space win; we save
+      // 16 bits, but probably at the cost of slower run time.  We're choosing
+      // 96 for now.
+      if (fnum - last_skip_entry_start > 96) start_new_block = true;
+    }
+    if (start_new_block) {
+      num_to_entry_table.blocks.push_back({fnum});
+      block = &num_to_entry_table.blocks.back();
+      start_new_block = false;
+    }
+
+    auto skip_entry_num = (fnum - block->first_fnum) / 16;
+    auto skip_entry_index = (fnum - block->first_fnum) % 16;
+    while (skip_entry_num >= block->entries.size())
+      block->entries.push_back({0xFFFF, field_entry_index});
+    block->entries[skip_entry_num].skipmap -= 1 << (skip_entry_index);
+
+    last_skip_entry_start = fnum - skip_entry_index;
+  }
+  return num_to_entry_table;
+}
+
+uint16_t MakeTypeCardForField(
+    const FieldDescriptor* field,
+    const TailCallTableInfo::PerFieldOptions& options) {
+  uint16_t type_card;
+  namespace fl = internal::field_layout;
+  if (internal::cpp::HasHasbit(field)) {
+    type_card = fl::kFcOptional;
+  } else if (field->is_repeated()) {
+    type_card = fl::kFcRepeated;
+  } else if (field->real_containing_oneof()) {
+    type_card = fl::kFcOneof;
+  } else {
+    type_card = fl::kFcSingular;
+  }
+
+  // The rest of the type uses convenience aliases:
+  switch (field->type()) {
+    case FieldDescriptor::TYPE_DOUBLE:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedDouble
+                       : fl::kDouble;
+      break;
+    case FieldDescriptor::TYPE_FLOAT:
+      type_card |= field->is_repeated() && field->is_packed() ? fl::kPackedFloat
+                                                              : fl::kFloat;
+      break;
+    case FieldDescriptor::TYPE_FIXED32:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedFixed32
+                       : fl::kFixed32;
+      break;
+    case FieldDescriptor::TYPE_SFIXED32:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedSFixed32
+                       : fl::kSFixed32;
+      break;
+    case FieldDescriptor::TYPE_FIXED64:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedFixed64
+                       : fl::kFixed64;
+      break;
+    case FieldDescriptor::TYPE_SFIXED64:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedSFixed64
+                       : fl::kSFixed64;
+      break;
+    case FieldDescriptor::TYPE_BOOL:
+      type_card |= field->is_repeated() && field->is_packed() ? fl::kPackedBool
+                                                              : fl::kBool;
+      break;
+    case FieldDescriptor::TYPE_ENUM:
+      if (internal::cpp::HasPreservingUnknownEnumSemantics(field)) {
+        // No validation is required.
+        type_card |= field->is_repeated() && field->is_packed()
+                         ? fl::kPackedOpenEnum
+                         : fl::kOpenEnum;
+      } else {
+        int16_t start;
+        uint16_t size;
+        if (GetEnumValidationRange(field->enum_type(), start, size)) {
+          // Validation is done by range check (start/length in FieldAux).
+          type_card |= field->is_repeated() && field->is_packed()
+                           ? fl::kPackedEnumRange
+                           : fl::kEnumRange;
+        } else {
+          // Validation uses the generated _IsValid function.
+          type_card |= field->is_repeated() && field->is_packed()
+                           ? fl::kPackedEnum
+                           : fl::kEnum;
+        }
+      }
+      break;
+    case FieldDescriptor::TYPE_UINT32:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedUInt32
+                       : fl::kUInt32;
+      break;
+    case FieldDescriptor::TYPE_SINT32:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedSInt32
+                       : fl::kSInt32;
+      break;
+    case FieldDescriptor::TYPE_INT32:
+      type_card |= field->is_repeated() && field->is_packed() ? fl::kPackedInt32
+                                                              : fl::kInt32;
+      break;
+    case FieldDescriptor::TYPE_UINT64:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedUInt64
+                       : fl::kUInt64;
+      break;
+    case FieldDescriptor::TYPE_SINT64:
+      type_card |= field->is_repeated() && field->is_packed()
+                       ? fl::kPackedSInt64
+                       : fl::kSInt64;
+      break;
+    case FieldDescriptor::TYPE_INT64:
+      type_card |= field->is_repeated() && field->is_packed() ? fl::kPackedInt64
+                                                              : fl::kInt64;
+      break;
+
+    case FieldDescriptor::TYPE_BYTES:
+      type_card |= fl::kBytes;
+      break;
+    case FieldDescriptor::TYPE_STRING: {
+      switch (internal::cpp::GetUtf8CheckMode(field, options.is_lite)) {
+        case internal::cpp::Utf8CheckMode::kStrict:
+          type_card |= fl::kUtf8String;
+          break;
+        case internal::cpp::Utf8CheckMode::kVerify:
+          type_card |= fl::kRawString;
+          break;
+        case internal::cpp::Utf8CheckMode::kNone:
+          type_card |= fl::kBytes;
+          break;
+      }
+      break;
+    }
+
+    case FieldDescriptor::TYPE_GROUP:
+      type_card |= 0 | fl::kMessage | fl::kRepGroup;
+      if (options.is_implicitly_weak) {
+        type_card |= fl::kTvWeakPtr;
+      } else if (options.use_direct_tcparser_table) {
+        type_card |= fl::kTvTable;
+      } else {
+        type_card |= fl::kTvDefault;
+      }
+      break;
+    case FieldDescriptor::TYPE_MESSAGE:
+      if (field->is_map()) {
+        type_card |= fl::kMap;
+      } else {
+        type_card |= fl::kMessage;
+        if (options.lazy_opt != 0) {
+          GOOGLE_CHECK(options.lazy_opt == field_layout::kTvEager ||
+                options.lazy_opt == field_layout::kTvLazy);
+          type_card |= +fl::kRepLazy | options.lazy_opt;
+        } else {
+          if (options.is_implicitly_weak) {
+            type_card |= fl::kTvWeakPtr;
+          } else if (options.use_direct_tcparser_table) {
+            type_card |= fl::kTvTable;
+          } else {
+            type_card |= fl::kTvDefault;
+          }
+        }
+      }
+      break;
+  }
+
+  // Fill in extra information about string and bytes field representations.
+  if (field->type() == FieldDescriptor::TYPE_BYTES ||
+      field->type() == FieldDescriptor::TYPE_STRING) {
+    if (field->is_repeated()) {
+      type_card |= fl::kRepSString;
+    } else {
+      type_card |= fl::kRepAString;
+    }
+  }
+
+  if (options.should_split) {
+    type_card |= fl::kSplitTrue;
+  }
+
+  return type_card;
+}
+
+}  // namespace
+
+TailCallTableInfo::TailCallTableInfo(
+    const Descriptor* descriptor,
+    const std::vector<const FieldDescriptor*>& ordered_fields,
+    const OptionProvider& option_provider,
+    const std::vector<int>& has_bit_indices,
+    const std::vector<int>& inlined_string_indices) {
+  // If this message has any inlined string fields, store the donation state
+  // offset in the first auxiliary entry, which is kInlinedStringAuxIdx.
+  if (!inlined_string_indices.empty()) {
+    aux_entries.resize(kInlinedStringAuxIdx + 1);  // Allocate our slot
+    aux_entries[kInlinedStringAuxIdx] = {kInlinedStringDonatedOffset};
+  }
+
+  // If this message is split, store the split pointer offset in the second
+  // and third auxiliary entries, which are kSplitOffsetAuxIdx and
+  // kSplitSizeAuxIdx.
+  for (auto* field : ordered_fields) {
+    if (option_provider.GetForField(field).should_split) {
+      static_assert(kSplitOffsetAuxIdx + 1 == kSplitSizeAuxIdx, "");
+      aux_entries.resize(kSplitSizeAuxIdx + 1);  // Allocate our 2 slots
+      aux_entries[kSplitOffsetAuxIdx] = {kSplitOffset};
+      aux_entries[kSplitSizeAuxIdx] = {kSplitSizeof};
+      break;
+    }
+  }
+
+  // Fill in mini table entries.
+  for (const FieldDescriptor* field : ordered_fields) {
+    auto options = option_provider.GetForField(field);
+    field_entries.push_back(
+        {field, internal::cpp ::HasHasbit(field)
+                    ? has_bit_indices[static_cast<size_t>(field->index())]
+                    : -1});
+    auto& entry = field_entries.back();
+    entry.type_card = MakeTypeCardForField(field, options);
+
+    if (field->type() == FieldDescriptor::TYPE_MESSAGE ||
+        field->type() == FieldDescriptor::TYPE_GROUP) {
+      // Message-typed fields have a FieldAux with the default instance pointer.
+      if (field->is_map()) {
+        // TODO(b/205904770): generate aux entries for maps
+      } else if (field->options().weak()) {
+        // Don't generate anything for weak fields. They are handled by the
+        // generated fallback.
+      } else if (options.lazy_opt != 0) {
+        field_entries.back().aux_idx = aux_entries.size();
+        aux_entries.push_back({kSubMessage, {field}});
+        aux_entries.push_back(
+            {kMessageVerifyFunc,
+             {options.lazy_opt == field_layout::kTvEager ? field : nullptr}});
+      } else {
+        field_entries.back().aux_idx = aux_entries.size();
+        aux_entries.push_back({options.is_implicitly_weak ? kSubMessageWeak
+                               : options.use_direct_tcparser_table
+                                   ? kSubTable
+                                   : kSubMessage,
+                               {field}});
+      }
+    } else if (field->type() == FieldDescriptor::TYPE_ENUM &&
+               !cpp::HasPreservingUnknownEnumSemantics(field)) {
+      // Enum fields which preserve unknown values (proto3 behavior) are
+      // effectively int32 fields with respect to parsing -- i.e., the value
+      // does not need to be validated at parse time.
+      //
+      // Enum fields which do not preserve unknown values (proto2 behavior) use
+      // a FieldAux to store validation information. If the enum values are
+      // sequential (and within a range we can represent), then the FieldAux
+      // entry represents the range using the minimum value (which must fit in
+      // an int16_t) and count (a uint16_t). Otherwise, the entry holds a
+      // pointer to the generated Name_IsValid function.
+
+      entry.aux_idx = aux_entries.size();
+      aux_entries.push_back({});
+      auto& aux_entry = aux_entries.back();
+
+      if (GetEnumValidationRange(field->enum_type(), aux_entry.enum_range.start,
+                                 aux_entry.enum_range.size)) {
+        aux_entry.type = kEnumRange;
+      } else {
+        aux_entry.type = kEnumValidator;
+        aux_entry.field = field;
+      }
+
+    } else if ((field->type() == FieldDescriptor::TYPE_STRING ||
+                field->type() == FieldDescriptor::TYPE_BYTES) &&
+               options.is_string_inlined) {
+      GOOGLE_CHECK(!field->is_repeated());
+      // Inlined strings have an extra marker to represent their donation state.
+      int idx = inlined_string_indices[static_cast<size_t>(field->index())];
+      // For mini parsing, the donation state index is stored as an `offset`
+      // auxiliary entry.
+      entry.aux_idx = aux_entries.size();
+      aux_entries.push_back({kNumericOffset});
+      aux_entries.back().offset = idx;
+      // For fast table parsing, the donation state index is stored instead of
+      // the aux_idx (this will limit the range to 8 bits).
+      entry.inlined_string_idx = idx;
+    }
+  }
+
+  table_size_log2 = 0;  // fallback value
+  int num_fast_fields = -1;
+  auto end_group_tag = GetEndGroupTag(descriptor);
+  for (int try_size_log2 : {0, 1, 2, 3, 4, 5}) {
+    size_t try_size = 1 << try_size_log2;
+    auto split_fields = SplitFastFieldsForSize(end_group_tag, field_entries,
+                                               try_size_log2, option_provider);
+    GOOGLE_CHECK_EQ(split_fields.size(), try_size);
+    int try_num_fast_fields = 0;
+    for (const auto& info : split_fields) {
+      if (info.field != nullptr) ++try_num_fast_fields;
+    }
+    // Use this size if (and only if) it covers more fields.
+    if (try_num_fast_fields > num_fast_fields) {
+      fast_path_fields = std::move(split_fields);
+      table_size_log2 = try_size_log2;
+      num_fast_fields = try_num_fast_fields;
+    }
+    // The largest table we allow has the same number of entries as the
+    // message has fields, rounded up to the next power of 2 (e.g., a message
+    // with 5 fields can have a fast table of size 8). A larger table *might*
+    // cover more fields in certain cases, but a larger table in that case
+    // would have mostly empty entries; so, we cap the size to avoid
+    // pathologically sparse tables.
+    if (end_group_tag.has_value()) {
+      // If this message uses group encoding, the tables are sometimes very
+      // sparse because the fields in the group avoid using the same field
+      // numbering as the parent message (even though currently, the proto
+      // compiler allows the overlap, and there is no possible conflict.)
+      // As such, this test produces a false negative as far as whether the
+      // large table will be worth it.  So we disable the test in this case.
+    } else {
+      if (try_size > ordered_fields.size()) {
+        break;
+      }
+    }
+  }
+
+  // Filter out fields that are handled by MiniParse. We don't need to generate
+  // a fallback for these, which saves code size.
+  fallback_fields = FilterMiniParsedFields(ordered_fields, option_provider);
+
+  num_to_entry_table = MakeNumToEntryTable(ordered_fields);
+  GOOGLE_CHECK_EQ(field_entries.size(), ordered_fields.size());
+  field_name_data = GenerateFieldNames(descriptor, field_entries);
+
+  // 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;
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/generated_message_tctable_gen.h b/src/google/protobuf/generated_message_tctable_gen.h
new file mode 100644
index 0000000..753f22e
--- /dev/null
+++ b/src/google/protobuf/generated_message_tctable_gen.h
@@ -0,0 +1,170 @@
+// 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 routines to generate tail-call table parsing tables.
+// Everything in this file is for internal use only.
+
+#ifndef GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_GEN_H__
+#define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_GEN_H__
+
+#include <cstdint>
+#include <functional>
+#include <string>
+#include <vector>
+
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/generated_message_tctable_decl.h"
+
+// Must come last:
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace field_layout {
+enum TransformValidation : uint16_t;
+}  // namespace field_layout
+
+// Helper class for generating tailcall parsing functions.
+struct PROTOBUF_EXPORT TailCallTableInfo {
+  struct PerFieldOptions {
+    // kTvEager, kTvLazy, or 0
+    field_layout::TransformValidation lazy_opt;
+    bool is_string_inlined;
+    bool is_implicitly_weak;
+    bool use_direct_tcparser_table;
+    bool is_lite;
+    bool should_split;
+  };
+  class OptionProvider {
+   public:
+    virtual PerFieldOptions GetForField(const FieldDescriptor*) const = 0;
+
+   protected:
+    ~OptionProvider() = default;
+  };
+
+  TailCallTableInfo(const Descriptor* descriptor,
+                    const std::vector<const FieldDescriptor*>& ordered_fields,
+                    const OptionProvider& option_provider,
+                    const std::vector<int>& has_bit_indices,
+                    const std::vector<int>& inlined_string_indices);
+
+  // Fields parsed by the table fast-path.
+  struct FastFieldInfo {
+    std::string func_name;
+    const FieldDescriptor* field;
+    uint16_t coded_tag;
+    uint8_t hasbit_idx;
+    uint8_t aux_idx;
+    uint16_t nonfield_info;
+  };
+  std::vector<FastFieldInfo> fast_path_fields;
+
+  // Fields parsed by mini parsing routines.
+  struct FieldEntryInfo {
+    const FieldDescriptor* field;
+    int hasbit_idx;
+    int inlined_string_idx;
+    uint16_t aux_idx;
+    uint16_t type_card;
+  };
+  std::vector<FieldEntryInfo> field_entries;
+
+  enum AuxType {
+    kNothing = 0,
+    kInlinedStringDonatedOffset,
+    kSplitOffset,
+    kSplitSizeof,
+    kSubMessage,
+    kSubTable,
+    kSubMessageWeak,
+    kMessageVerifyFunc,
+    kEnumRange,
+    kEnumValidator,
+    kNumericOffset,
+  };
+  struct AuxEntry {
+    AuxType type;
+    struct EnumRange {
+      int16_t start;
+      uint16_t size;
+    };
+    union {
+      const FieldDescriptor* field;
+      uint32_t offset;
+      EnumRange enum_range;
+    };
+  };
+  std::vector<AuxEntry> aux_entries;
+
+  // Fields parsed by generated fallback function.
+  std::vector<const FieldDescriptor*> fallback_fields;
+
+  struct SkipEntry16 {
+    uint16_t skipmap;
+    uint16_t field_entry_offset;
+  };
+  struct SkipEntryBlock {
+    uint32_t first_fnum;
+    std::vector<SkipEntry16> entries;
+  };
+  struct NumToEntryTable {
+    uint32_t skipmap32;  // for fields #1 - #32
+    std::vector<SkipEntryBlock> blocks;
+    // Compute the number of uint16_t required to represent this table.
+    int size16() const {
+      int size = 2;  // for the termination field#
+      for (const auto& block : blocks) {
+        // 2 for the field#, 1 for a count of skip entries, 2 for each entry.
+        size += static_cast<int>(3 + block.entries.size() * 2);
+      }
+      return size;
+    }
+  };
+  NumToEntryTable num_to_entry_table;
+
+  std::vector<uint8_t> field_name_data;
+
+  // Table size.
+  int table_size_log2;
+  // True if a generated fallback function is required instead of generic.
+  bool use_generated_fallback;
+};
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_GEN_H__
diff --git a/src/google/protobuf/generated_message_tctable_impl.h b/src/google/protobuf/generated_message_tctable_impl.h
index 21fa533..dc2e976 100644
--- a/src/google/protobuf/generated_message_tctable_impl.h
+++ b/src/google/protobuf/generated_message_tctable_impl.h
@@ -32,18 +32,20 @@
 #define GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
 
 #include <cstdint>
+#include <cstdlib>
+#include <string>
 #include <type_traits>
+#include <utility>
 
-#include <google/protobuf/port.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/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/port.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/generated_message_tctable_decl.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must come last:
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -53,6 +55,12 @@
 
 namespace internal {
 
+enum {
+  kInlinedStringAuxIdx = 0,
+  kSplitOffsetAuxIdx = 1,
+  kSplitSizeAuxIdx = 2,
+};
+
 // Field layout enums.
 //
 // Structural information about fields is packed into a 16-bit value. The enum
@@ -64,10 +72,11 @@
 //     |15        ..          8|7         ..          0|
 //     +-----------------------+-----------------------+
 //     :  .  :  .  :  .  :  .  :  .  :  .  : 3|========| [3] FieldType
-//     :     :     :     :     :     : 5|=====|  :     : [2] FieldCardinality
-//     :  .  :  .  :  .  :  . 8|========|  :  .  :  .  : [3] FieldRep
-//     :     :     :   10|=====|     :     :     :     : [2] TransformValidation
-//     :  .  :  .12|=====|  .  :  .  :  .  :  .  :  .  : [2] FormatDiscriminator
+//     :     :     :     :     :     :  . 4|==|  :     : [1] FieldSplit
+//     :     :     :     :     :    6|=====|  .  :     : [2] FieldCardinality
+//     :  .  :  .  :  .  : 9|========|  .  :  .  :  .  : [3] FieldRep
+//     :     :     :11|=====|  :     :     :     :     : [2] TransformValidation
+//     :  .  :13|=====|  :  .  :  .  :  .  :  .  :  .  : [2] FormatDiscriminator
 //     +-----------------------+-----------------------+
 //     |15        ..          8|7         ..          0|
 //     +-----------------------+-----------------------+
@@ -95,11 +104,21 @@
 
 static_assert(kFkMap < (1 << kFkBits), "too many types");
 
+// Split (1 bit):
+enum FieldSplit : uint16_t {
+  kSplitShift = kFkShift+ kFkBits,
+  kSplitBits  = 1,
+  kSplitMask  = ((1 << kSplitBits) - 1) << kSplitShift,
+
+  kSplitFalse = 0,
+  kSplitTrue  = 1 << kSplitShift,
+};
+
 // Cardinality (2 bits):
 // These values determine how many values a field can have and its presence.
 // Packed fields are represented in FieldType.
 enum Cardinality : uint16_t {
-  kFcShift    = kFkShift + kFkBits,
+  kFcShift    = kSplitShift+ kSplitBits,
   kFcBits     = 2,
   kFcMask     = ((1 << kFcBits) - 1) << kFcShift,
 
@@ -130,7 +149,6 @@
   kRepMessage  = 0,               // MessageLite*
   kRepGroup    = 1 << kRepShift,  // MessageLite* (WT=3,4)
   kRepLazy     = 2 << kRepShift,  // LazyField*
-  kRepIWeak    = 3 << kRepShift,  // ImplicitWeak
 };
 
 // Transform/validation (2 bits):
@@ -147,6 +165,15 @@
   // String fields:
   kTvUtf8Debug = 1 << kTvShift,  // proto2
   kTvUtf8      = 2 << kTvShift,  // proto3
+
+  // Message fields:
+  kTvDefault   = 1 << kTvShift,  // Aux has default_instance*
+  kTvTable     = 2 << kTvShift,  // Aux has TcParseTableBase*
+  kTvWeakPtr   = 3 << kTvShift,  // Aux has default_instance** (for weak)
+
+  // Lazy message fields:
+  kTvEager     = 1 << kTvShift,
+  kTvLazy      = 2 << kTvShift,
 };
 
 static_assert((kTvEnum & kTvRange) != 0,
@@ -175,7 +202,7 @@
 };
 
 // Update this assertion (and comments above) when adding or removing bits:
-static_assert(kFmtShift + kFmtBits == 12, "number of bits changed");
+static_assert(kFmtShift + kFmtBits == 13, "number of bits changed");
 
 // This assertion should not change unless the storage width changes:
 static_assert(kFmtShift + kFmtBits <= 16, "too many bits");
@@ -183,48 +210,48 @@
 // Convenience aliases (16 bits, with format):
 enum FieldType : uint16_t {
   // Numeric types:
-  kBool            = kFkVarint | kRep8Bits,
+  kBool            = 0 | kFkVarint | kRep8Bits,
 
-  kFixed32         = kFkFixed  | kRep32Bits | kFmtUnsigned,
-  kUInt32          = kFkVarint | kRep32Bits | kFmtUnsigned,
-  kSFixed32        = kFkFixed  | kRep32Bits | kFmtSigned,
-  kInt32           = kFkVarint | kRep32Bits | kFmtSigned,
-  kSInt32          = kFkVarint | kRep32Bits | kFmtSigned | kTvZigZag,
-  kFloat           = kFkFixed  | kRep32Bits | kFmtFloating,
-  kEnum            = kFkVarint | kRep32Bits | kFmtEnum   | kTvEnum,
-  kEnumRange       = kFkVarint | kRep32Bits | kFmtEnum   | kTvRange,
-  kOpenEnum        = kFkVarint | kRep32Bits | kFmtEnum,
+  kFixed32         = 0 | kFkFixed  | kRep32Bits | kFmtUnsigned,
+  kUInt32          = 0 | kFkVarint | kRep32Bits | kFmtUnsigned,
+  kSFixed32        = 0 | kFkFixed  | kRep32Bits | kFmtSigned,
+  kInt32           = 0 | kFkVarint | kRep32Bits | kFmtSigned,
+  kSInt32          = 0 | kFkVarint | kRep32Bits | kFmtSigned | kTvZigZag,
+  kFloat           = 0 | kFkFixed  | kRep32Bits | kFmtFloating,
+  kEnum            = 0 | kFkVarint | kRep32Bits | kFmtEnum   | kTvEnum,
+  kEnumRange       = 0 | kFkVarint | kRep32Bits | kFmtEnum   | kTvRange,
+  kOpenEnum        = 0 | kFkVarint | kRep32Bits | kFmtEnum,
 
-  kFixed64         = kFkFixed  | kRep64Bits | kFmtUnsigned,
-  kUInt64          = kFkVarint | kRep64Bits | kFmtUnsigned,
-  kSFixed64        = kFkFixed  | kRep64Bits | kFmtSigned,
-  kInt64           = kFkVarint | kRep64Bits | kFmtSigned,
-  kSInt64          = kFkVarint | kRep64Bits | kFmtSigned | kTvZigZag,
-  kDouble          = kFkFixed  | kRep64Bits | kFmtFloating,
+  kFixed64         = 0 | kFkFixed  | kRep64Bits | kFmtUnsigned,
+  kUInt64          = 0 | kFkVarint | kRep64Bits | kFmtUnsigned,
+  kSFixed64        = 0 | kFkFixed  | kRep64Bits | kFmtSigned,
+  kInt64           = 0 | kFkVarint | kRep64Bits | kFmtSigned,
+  kSInt64          = 0 | kFkVarint | kRep64Bits | kFmtSigned | kTvZigZag,
+  kDouble          = 0 | kFkFixed  | kRep64Bits | kFmtFloating,
 
-  kPackedBool      = kFkPackedVarint | kRep8Bits,
+  kPackedBool      = 0 | kFkPackedVarint | kRep8Bits,
 
-  kPackedFixed32   = kFkPackedFixed  | kRep32Bits | kFmtUnsigned,
-  kPackedUInt32    = kFkPackedVarint | kRep32Bits | kFmtUnsigned,
-  kPackedSFixed32  = kFkPackedFixed  | kRep32Bits | kFmtSigned,
-  kPackedInt32     = kFkPackedVarint | kRep32Bits | kFmtSigned,
-  kPackedSInt32    = kFkPackedVarint | kRep32Bits | kFmtSigned | kTvZigZag,
-  kPackedFloat     = kFkPackedFixed  | kRep32Bits | kFmtFloating,
-  kPackedEnum      = kFkPackedVarint | kRep32Bits | kFmtEnum   | kTvEnum,
-  kPackedEnumRange = kFkPackedVarint | kRep32Bits | kFmtEnum   | kTvRange,
-  kPackedOpenEnum  = kFkPackedVarint | kRep32Bits | kFmtEnum,
+  kPackedFixed32   = 0 | kFkPackedFixed  | kRep32Bits | kFmtUnsigned,
+  kPackedUInt32    = 0 | kFkPackedVarint | kRep32Bits | kFmtUnsigned,
+  kPackedSFixed32  = 0 | kFkPackedFixed  | kRep32Bits | kFmtSigned,
+  kPackedInt32     = 0 | kFkPackedVarint | kRep32Bits | kFmtSigned,
+  kPackedSInt32    = 0 | kFkPackedVarint | kRep32Bits | kFmtSigned | kTvZigZag,
+  kPackedFloat     = 0 | kFkPackedFixed  | kRep32Bits | kFmtFloating,
+  kPackedEnum      = 0 | kFkPackedVarint | kRep32Bits | kFmtEnum   | kTvEnum,
+  kPackedEnumRange = 0 | kFkPackedVarint | kRep32Bits | kFmtEnum   | kTvRange,
+  kPackedOpenEnum  = 0 | kFkPackedVarint | kRep32Bits | kFmtEnum,
 
-  kPackedFixed64   = kFkPackedFixed  | kRep64Bits | kFmtUnsigned,
-  kPackedUInt64    = kFkPackedVarint | kRep64Bits | kFmtUnsigned,
-  kPackedSFixed64  = kFkPackedFixed  | kRep64Bits | kFmtSigned,
-  kPackedInt64     = kFkPackedVarint | kRep64Bits | kFmtSigned,
-  kPackedSInt64    = kFkPackedVarint | kRep64Bits | kFmtSigned | kTvZigZag,
-  kPackedDouble    = kFkPackedFixed  | kRep64Bits | kFmtFloating,
+  kPackedFixed64   = 0 | kFkPackedFixed  | kRep64Bits | kFmtUnsigned,
+  kPackedUInt64    = 0 | kFkPackedVarint | kRep64Bits | kFmtUnsigned,
+  kPackedSFixed64  = 0 | kFkPackedFixed  | kRep64Bits | kFmtSigned,
+  kPackedInt64     = 0 | kFkPackedVarint | kRep64Bits | kFmtSigned,
+  kPackedSInt64    = 0 | kFkPackedVarint | kRep64Bits | kFmtSigned | kTvZigZag,
+  kPackedDouble    = 0 | kFkPackedFixed  | kRep64Bits | kFmtFloating,
 
   // String types:
-  kBytes           = kFkString | kFmtArray,
-  kRawString       = kFkString | kFmtUtf8  | kTvUtf8Debug,
-  kUtf8String      = kFkString | kFmtUtf8  | kTvUtf8,
+  kBytes           = 0 | kFkString | kFmtArray,
+  kRawString       = 0 | kFkString | kFmtUtf8  | kTvUtf8Debug,
+  kUtf8String      = 0 | kFkString | kFmtUtf8  | kTvUtf8,
 
   // Message types:
   kMessage         = kFkMessage,
@@ -232,27 +259,16 @@
   // Map types:
   kMap             = kFkMap,
 };
-
 // clang-format on
 }  // namespace field_layout
 
-// PROTOBUF_TC_PARAM_DECL are the parameters for tailcall functions, it is
-// defined in port_def.inc.
-//
-// 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.
-
-// PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL.
-#define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, table, hasbits, data
-
 #ifndef NDEBUG
 template <size_t align>
-#ifndef _MSC_VER
-[[noreturn]]
-#endif
 void AlignFail(uintptr_t address) {
   GOOGLE_LOG(FATAL) << "Unaligned (" << align << ") access at " << address;
+
+  // Explicit abort to let compilers know this function does not return
+  abort();
 }
 
 extern template void AlignFail<4>(uintptr_t);
@@ -262,8 +278,37 @@
 // TcParser implements most of the parsing logic for tailcall tables.
 class PROTOBUF_EXPORT TcParser final {
  public:
+  template <typename T>
+  static constexpr const TcParseTableBase* GetTable() {
+    return &T::_table_.header;
+  }
+
+  // == ABI of the tail call functions ==
+  // All the tail call functions have the same signature as required by clang's
+  // `musttail` attribute. However, their ABIs are different.
+  // See TcFieldData's comments for details on the layouts.
+  // The ABIs are as follow:
+  //
+  //  - The following functions ignore `data`:
+  //      ToTagDispatch, TagDispatch, MiniParse, ToParseLoop, Error,
+  //      FastUnknownEnumFallback.
+  //  - FastXXX functions expect `data` with a fast table entry ABI.
+  //  - FastEndGX functions expect `data` with a non-field entry ABI.
+  //  - MpXXX functions expect `data` with a mini table ABI.
+  //  - The fallback functions (both GenericFallbackXXX and the codegen ones)
+  //    expect only the tag in `data`. In addition, if a null `ptr` is passed,
+  //    the function is used to push an unknown enum value into the
+  //    UnknownFieldSet. The function then expects `data` to use the unknown
+  //    enum ABI, as described in `struct TcFieldData`.
+
+  static bool MustFallbackToGeneric(PROTOBUF_TC_PARAM_DECL) {
+    return ptr == nullptr;
+  }
+
   static const char* GenericFallback(PROTOBUF_TC_PARAM_DECL);
   static const char* GenericFallbackLite(PROTOBUF_TC_PARAM_DECL);
+  static const char* ReflectionFallback(PROTOBUF_TC_PARAM_DECL);
+  static const char* ReflectionParseLoop(PROTOBUF_TC_PARAM_DECL);
 
   static const char* ParseLoop(MessageLite* msg, const char* ptr,
                                ParseContext* ctx,
@@ -323,19 +368,63 @@
   static const char* FastZ64P1(PROTOBUF_TC_PARAM_DECL);
   static const char* FastZ64P2(PROTOBUF_TC_PARAM_DECL);
 
+  // Manually unrolled and specialized Varint parsing.
+  template <typename FieldType, int data_offset, int hasbit_idx>
+  static const char* SpecializedUnrolledVImpl1(PROTOBUF_TC_PARAM_DECL);
+  template <int data_offset, int hasbit_idx>
+  static const char* SpecializedFastV8S1(PROTOBUF_TC_PARAM_DECL);
+
+  template <typename FieldType, int data_offset, int hasbit_idx>
+  static constexpr TailCallParseFunc SingularVarintNoZag1() {
+    if (data_offset < 100) {
+      if (sizeof(FieldType) == 1) {
+        return &SpecializedFastV8S1<data_offset, hasbit_idx>;
+      }
+      return &SpecializedUnrolledVImpl1<FieldType, data_offset, hasbit_idx>;
+    } else if (sizeof(FieldType) == 1) {
+      return &FastV8S1;
+    } else if (sizeof(FieldType) == 4) {
+      return &FastV32S1;
+    } else if (sizeof(FieldType) == 8) {
+      return &FastV64S1;
+    } else {
+      static_assert(sizeof(FieldType) == 1 || sizeof(FieldType) == 4 ||
+                        sizeof(FieldType) == 8,
+                    "");
+      return nullptr;
+    }
+  }
+
   // Functions referenced by generated fast tables (closed enum):
   //   E: closed enum (N.B.: open enums use V32, above)
   //   r: enum range  v: enum validator (_IsValid function)
-  //   S: singular   R: repeated
+  //   S: singular   R: repeated   P: packed
   //   1/2: tag length (bytes)
   static const char* FastErS1(PROTOBUF_TC_PARAM_DECL);
   static const char* FastErS2(PROTOBUF_TC_PARAM_DECL);
   static const char* FastErR1(PROTOBUF_TC_PARAM_DECL);
   static const char* FastErR2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastErP1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastErP2(PROTOBUF_TC_PARAM_DECL);
   static const char* FastEvS1(PROTOBUF_TC_PARAM_DECL);
   static const char* FastEvS2(PROTOBUF_TC_PARAM_DECL);
   static const char* FastEvR1(PROTOBUF_TC_PARAM_DECL);
   static const char* FastEvR2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEvP1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEvP2(PROTOBUF_TC_PARAM_DECL);
+
+  static const char* FastEr0S1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr0S2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr0R1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr0R2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr0P1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr0P2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr1S1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr1S2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr1R1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr1R2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr1P1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEr1P2(PROTOBUF_TC_PARAM_DECL);
 
   // Functions referenced by generated fast tables (string types):
   //   B: bytes      S: string     U: UTF-8 string
@@ -362,18 +451,38 @@
   static const char* FastUiS1(PROTOBUF_TC_PARAM_DECL);
   static const char* FastUiS2(PROTOBUF_TC_PARAM_DECL);
 
+  static const char* FastBcS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastBcS2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastScS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastScS2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastUcS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastUcS2(PROTOBUF_TC_PARAM_DECL);
+
   // Functions referenced by generated fast tables (message types):
   //   M: message    G: group
+  //   d: default*   t: TcParseTable* (the contents of aux)  l: lazy
   //   S: singular   R: repeated
   //   1/2: tag length (bytes)
-  static const char* FastMS1(PROTOBUF_TC_PARAM_DECL);
-  static const char* FastMS2(PROTOBUF_TC_PARAM_DECL);
-  static const char* FastMR1(PROTOBUF_TC_PARAM_DECL);
-  static const char* FastMR2(PROTOBUF_TC_PARAM_DECL);
-  static const char* FastGS1(PROTOBUF_TC_PARAM_DECL);
-  static const char* FastGS2(PROTOBUF_TC_PARAM_DECL);
-  static const char* FastGR1(PROTOBUF_TC_PARAM_DECL);
-  static const char* FastGR2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMdS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMdS2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGdS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGdS2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMtS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMtS2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGtS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGtS2(PROTOBUF_TC_PARAM_DECL);
+
+  static const char* FastMlS1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMlS2(PROTOBUF_TC_PARAM_DECL);
+
+  static const char* FastMdR1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMdR2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGdR1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGdR2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMtR1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastMtR2(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGtR1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastGtR2(PROTOBUF_TC_PARAM_DECL);
 
   template <typename T>
   static inline T& RefAt(void* x, size_t offset) {
@@ -418,13 +527,36 @@
   // parsing.
   static const char* MiniParse(PROTOBUF_TC_PARAM_DECL);
 
+  static const char* FastEndG1(PROTOBUF_TC_PARAM_DECL);
+  static const char* FastEndG2(PROTOBUF_TC_PARAM_DECL);
+
  private:
   friend class GeneratedTcTableLiteTest;
+  static void* MaybeGetSplitBase(MessageLite* msg, const bool is_split,
+                                 const TcParseTableBase* table,
+                                 google::protobuf::internal::ParseContext* ctx);
 
-  template <typename TagType, bool group_coding>
+  // Test only access to verify that the right function is being called via
+  // MiniParse.
+  struct TestMiniParseResult {
+    TailCallParseFunc called_func;
+    uint32_t tag;
+    const TcParseTableBase::FieldEntry* found_entry;
+    const char* ptr;
+  };
+  static TestMiniParseResult TestMiniParse(PROTOBUF_TC_PARAM_DECL);
+  template <bool export_called_function>
+  static const char* MiniParseImpl(PROTOBUF_TC_PARAM_DECL);
+
+  template <typename TagType, bool group_coding, bool aux_is_table>
   static inline const char* SingularParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL);
-  template <typename TagType, bool group_coding>
+  template <typename TagType, bool group_coding, bool aux_is_table>
   static inline const char* RepeatedParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL);
+  template <typename TagType>
+  static inline const char* LazyMessage(PROTOBUF_TC_PARAM_DECL);
+
+  template <typename TagType>
+  static const char* FastEndGroupImpl(PROTOBUF_TC_PARAM_DECL);
 
   static inline PROTOBUF_ALWAYS_INLINE void SyncHasbits(
       MessageLite* msg, uint64_t hasbits, const TcParseTableBase* table) {
@@ -432,7 +564,7 @@
     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);
+      RefAt<uint32_t>(msg, has_bits_offset) |= static_cast<uint32_t>(hasbits);
     }
   }
 
@@ -447,16 +579,13 @@
 
   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);
-    CHK_(ptr);
     uint32_t tag = data.tag();
     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) {
@@ -465,10 +594,19 @@
                       static_cast<const MessageBaseT*>(table->default_instance),
                       &msg->_internal_metadata_, ctx);
     }
+
+    // Side channel for handling unknown data. Currently, only used for unknown
+    // enums. The value is in the 32 high bits of data.
+    if (ptr == nullptr) {
+      internal::WriteVarint(
+          num, data.unknown_enum_value(),
+          msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>());
+      return nullptr;
+    }
+
     return UnknownFieldParse(
         tag, msg->_internal_metadata_.mutable_unknown_fields<UnknownFieldsT>(),
         ptr, ctx);
-#undef CHK_
   }
 
   // Note: `inline` is needed on template function declarations below to avoid
@@ -497,21 +635,37 @@
   // Implementations for fast enum field parsing functions:
   template <typename TagType, uint16_t xform_val>
   static inline const char* SingularEnum(PROTOBUF_TC_PARAM_DECL);
+  template <typename TagType, uint8_t min>
+  static inline const char* SingularEnumSmallRange(PROTOBUF_TC_PARAM_DECL);
   template <typename TagType, uint16_t xform_val>
   static inline const char* RepeatedEnum(PROTOBUF_TC_PARAM_DECL);
+  template <typename TagType, uint16_t xform_val>
+  static inline const char* PackedEnum(PROTOBUF_TC_PARAM_DECL);
+  template <typename TagType, uint8_t min>
+  static inline const char* RepeatedEnumSmallRange(PROTOBUF_TC_PARAM_DECL);
+  template <typename TagType, uint8_t min>
+  static inline const char* PackedEnumSmallRange(PROTOBUF_TC_PARAM_DECL);
 
   // Implementations for fast string field parsing functions:
   enum Utf8Type { kNoUtf8 = 0, kUtf8 = 1, kUtf8ValidateOnly = 2 };
-  template <typename TagType, Utf8Type utf8>
+  template <typename TagType, typename FieldType, Utf8Type utf8>
   static inline const char* SingularString(PROTOBUF_TC_PARAM_DECL);
-  template <typename TagType, Utf8Type utf8>
+  template <typename TagType, typename FieldType, Utf8Type utf8>
   static inline const char* RepeatedString(PROTOBUF_TC_PARAM_DECL);
 
+  static inline const char* ParseRepeatedStringOnce(
+      const char* ptr, Arena* arena, SerialArena* serial_arena,
+      ParseContext* ctx, RepeatedPtrField<std::string>& field);
+
+  static void UnknownPackedEnum(MessageLite* msg, ParseContext* ctx,
+                                const TcParseTableBase* table, uint32_t tag,
+                                int32_t enum_value);
+
   // Mini field lookup:
   static const TcParseTableBase::FieldEntry* FindFieldEntry(
       const TcParseTableBase* table, uint32_t field_num);
-  static StringPiece MessageName(const TcParseTableBase* table);
-  static StringPiece FieldName(const TcParseTableBase* table,
+  static absl::string_view MessageName(const TcParseTableBase* table);
+  static absl::string_view FieldName(const TcParseTableBase* table,
                                      const TcParseTableBase::FieldEntry*);
   static bool ChangeOneof(const TcParseTableBase* table,
                           const TcParseTableBase::FieldEntry& entry,
@@ -521,33 +675,221 @@
   // UTF-8 validation:
   static void ReportFastUtf8Error(uint32_t decoded_tag,
                                   const TcParseTableBase* table);
-  static bool MpVerifyUtf8(StringPiece wire_bytes,
+  static bool MpVerifyUtf8(absl::string_view wire_bytes,
                            const TcParseTableBase* table,
                            const TcParseTableBase::FieldEntry& entry,
                            uint16_t xform_val);
 
   // For FindFieldEntry tests:
   friend class FindFieldEntryTest;
+  friend struct ParseFunctionGeneratorTestPeer;
+  friend struct FuzzPeer;
   static constexpr const uint32_t kMtSmallScanSize = 4;
 
   // Mini parsing:
+  template <bool is_split>
   static const char* MpVarint(PROTOBUF_TC_PARAM_DECL);
   static const char* MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL);
   static const char* MpPackedVarint(PROTOBUF_TC_PARAM_DECL);
+  template <bool is_split>
   static const char* MpFixed(PROTOBUF_TC_PARAM_DECL);
   static const char* MpRepeatedFixed(PROTOBUF_TC_PARAM_DECL);
   static const char* MpPackedFixed(PROTOBUF_TC_PARAM_DECL);
+  template <bool is_split>
   static const char* MpString(PROTOBUF_TC_PARAM_DECL);
   static const char* MpRepeatedString(PROTOBUF_TC_PARAM_DECL);
+  template <bool is_split>
   static const char* MpMessage(PROTOBUF_TC_PARAM_DECL);
   static const char* MpRepeatedMessage(PROTOBUF_TC_PARAM_DECL);
-  static const char* MpMap(PROTOBUF_TC_PARAM_DECL);
+  static const char* MpLazyMessage(PROTOBUF_TC_PARAM_DECL);
+  static const char* MpFallback(PROTOBUF_TC_PARAM_DECL);
 };
 
+// Notes:
+// 1) if data_offset is negative, it's read from data.offset()
+// 2) if hasbit_idx is negative, it's read from data.hasbit_idx()
+template <int data_offset, int hasbit_idx>
+PROTOBUF_NOINLINE const char* TcParser::SpecializedFastV8S1(
+    PROTOBUF_TC_PARAM_DECL) {
+  using TagType = uint8_t;
+
+  // Special case for a varint bool field with a tag of 1 byte:
+  // The coded_tag() field will actually contain the value too and we can check
+  // both at the same time.
+  auto coded_tag = data.coded_tag<uint16_t>();
+  if (PROTOBUF_PREDICT_TRUE(coded_tag == 0x0000 || coded_tag == 0x0100)) {
+    auto& field =
+        RefAt<bool>(msg, data_offset >= 0 ? data_offset : data.offset());
+    // Note: we use `data.data` because Clang generates suboptimal code when
+    // using coded_tag.
+    // In x86_64 this uses the CH register to read the second byte out of
+    // `data`.
+    uint8_t value = data.data >> 8;
+    // The assume allows using a mov instead of test+setne.
+    PROTOBUF_ASSUME(value <= 1);
+    field = static_cast<bool>(value);
+
+    ptr += sizeof(TagType) + 1;  // Consume the tag and the value.
+    if (hasbit_idx < 0) {
+      hasbits |= (uint64_t{1} << data.hasbit_idx());
+    } else {
+      if (hasbit_idx < 32) {
+        // `& 31` avoids a compiler warning when hasbit_idx is negative.
+        hasbits |= (uint64_t{1} << (hasbit_idx & 31));
+      } else {
+        static_assert(hasbit_idx == 63 || (hasbit_idx < 32),
+                      "hard-coded hasbit_idx should be 0-31, or the special"
+                      "value 63, which indicates the field has no has-bit.");
+        // TODO(jorg): investigate whether higher hasbit indices are worth
+        // supporting. Something like:
+        // auto& hasblock = TcParser::RefAt<uint32_t>(msg, hasbit_idx / 32 * 4);
+        // hasblock |= uint32_t{1} << (hasbit_idx % 32);
+      }
+    }
+
+    PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+  }
+
+  // If it didn't match above either the tag is wrong, or the value is encoded
+  // non-canonically.
+  // Jump to MiniParse as wrong tag is the most probable reason.
+  PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename FieldType, int data_offset, int hasbit_idx>
+PROTOBUF_NOINLINE const char* TcParser::SpecializedUnrolledVImpl1(
+    PROTOBUF_TC_PARAM_DECL) {
+  using TagType = uint8_t;
+  // super-early success test...
+  if (PROTOBUF_PREDICT_TRUE(((data.data) & 0x80FF) == 0)) {
+    ptr += sizeof(TagType);  // Consume tag
+    if (hasbit_idx < 32) {
+      hasbits |= (uint64_t{1} << hasbit_idx);
+    }
+    uint8_t value = data.data >> 8;
+    RefAt<FieldType>(msg, data_offset) = value;
+    ptr += 1;
+    PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+  }
+  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
+    PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+  }
+  ptr += sizeof(TagType);  // Consume tag
+  if (hasbit_idx < 32) {
+    hasbits |= (uint64_t{1} << hasbit_idx);
+  }
+
+  // Few registers
+  auto* out = &RefAt<FieldType>(msg, data_offset);
+  uint64_t res = 0xFF & (data.data >> 8);
+  /* if (PROTOBUF_PREDICT_FALSE(res & 0x80)) */ {
+    res = RotRight7AndReplaceLowByte(res, ptr[1]);
+    if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+      res = RotRight7AndReplaceLowByte(res, ptr[2]);
+      if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+        res = RotRight7AndReplaceLowByte(res, ptr[3]);
+        if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+          res = RotRight7AndReplaceLowByte(res, ptr[4]);
+          if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+            res = RotRight7AndReplaceLowByte(res, ptr[5]);
+            if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+              res = RotRight7AndReplaceLowByte(res, ptr[6]);
+              if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+                res = RotRight7AndReplaceLowByte(res, ptr[7]);
+                if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+                  res = RotRight7AndReplaceLowByte(res, ptr[8]);
+                  if (PROTOBUF_PREDICT_FALSE(res & 0x80)) {
+                    if (ptr[9] & 0xFE) return Error(PROTOBUF_TC_PARAM_PASS);
+                    res = RotateLeft(res, -7) & ~1;
+                    res += ptr[9] & 1;
+                    *out = RotateLeft(res, 63);
+                    ptr += 10;
+                    PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+                  }
+                  *out = RotateLeft(res, 56);
+                  ptr += 9;
+                  PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+                }
+                *out = RotateLeft(res, 49);
+                ptr += 8;
+                PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+              }
+              *out = RotateLeft(res, 42);
+              ptr += 7;
+              PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+            }
+            *out = RotateLeft(res, 35);
+            ptr += 6;
+            PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+          }
+          *out = RotateLeft(res, 28);
+          ptr += 5;
+          PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+        }
+        *out = RotateLeft(res, 21);
+        ptr += 4;
+        PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+      }
+      *out = RotateLeft(res, 14);
+      ptr += 3;
+      PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+    }
+    *out = RotateLeft(res, 7);
+    ptr += 2;
+    PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+  }
+  *out = res;
+  ptr += 1;
+  PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+}
+
+// Dispatch to the designated parse function
+inline PROTOBUF_ALWAYS_INLINE const char* TcParser::TagDispatch(
+    PROTOBUF_TC_PARAM_DECL) {
+  const auto coded_tag = UnalignedLoad<uint16_t>(ptr);
+  const size_t idx = coded_tag & table->fast_idx_mask;
+  PROTOBUF_ASSUME((idx & 7) == 0);
+  auto* fast_entry = table->fast_entry(idx >> 3);
+  data = fast_entry->bits;
+  data.data ^= coded_tag;
+  PROTOBUF_MUSTTAIL return fast_entry->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.
+inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToTagDispatch(
+    PROTOBUF_TC_PARAM_DECL) {
+  constexpr bool always_return = !PROTOBUF_TAILCALL;
+  if (always_return || !ctx->DataAvailable(ptr)) {
+    PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
+  }
+  PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_PASS);
+}
+
+inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop(
+    PROTOBUF_TC_PARAM_DECL) {
+  (void)data;
+  (void)ctx;
+  SyncHasbits(msg, hasbits, table);
+  return ptr;
+}
+
+inline PROTOBUF_ALWAYS_INLINE const char* TcParser::Error(
+    PROTOBUF_TC_PARAM_DECL) {
+  (void)data;
+  (void)ctx;
+  (void)ptr;
+  SyncHasbits(msg, hasbits, table);
+  return nullptr;
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_TCTABLE_IMPL_H__
diff --git a/src/google/protobuf/generated_message_tctable_lite.cc b/src/google/protobuf/generated_message_tctable_lite.cc
index 9993811..bbb6144 100644
--- a/src/google/protobuf/generated_message_tctable_lite.cc
+++ b/src/google/protobuf/generated_message_tctable_lite.cc
@@ -30,17 +30,20 @@
 
 #include <cstdint>
 #include <numeric>
+#include <type_traits>
 
-#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/inlined_string_field.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "absl/cleanup/cleanup.h"
+#include "google/protobuf/generated_message_tctable_decl.h"
+#include "google/protobuf/generated_message_tctable_impl.h"
+#include "google/protobuf/inlined_string_field.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "utf8_validity.h"
+
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -66,78 +69,31 @@
 // Core fast parsing implementation:
 //////////////////////////////////////////////////////////////////////////////
 
-class TcParser::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_;
-};
-
 PROTOBUF_NOINLINE const char* TcParser::ParseLoop(
     MessageLite* msg, const char* ptr, ParseContext* ctx,
     const TcParseTableBase* table) {
-  ScopedArenaSwap saved(msg, ctx);
+  // Note: TagDispatch uses a dispatch table at "&table->fast_entries".
+  // For fast dispatch, we'd like to have a pointer to that, but if we use
+  // that expression, there's no easy way to get back to "table", which we also
+  // need during dispatch.  It turns out that "table + 1" points exactly to
+  // fast_entries, so we just increment table by 1 here, to get the register
+  // holding the value we want.
+  table += 1;
   while (!ctx->Done(&ptr)) {
-    // Unconditionally read has bits, even if we don't have has bits.
-    // has_bits_offset will be 0 and we will just read something valid.
-    uint64_t hasbits = ReadAt<uint32_t>(msg, table->has_bits_offset);
-    ptr = TagDispatch(msg, ptr, ctx, table, hasbits, {});
+#if defined(__GNUC__)
+    // Note: this asm prevents the compiler (clang, specifically) from
+    // believing (thanks to CSE) that it needs to dedicate a registeer both
+    // to "table" and "&table->fast_entries".
+    // TODO(b/64614992): remove this asm
+    asm("" : "+r"(table));
+#endif
+    ptr = TagDispatch(msg, ptr, ctx, {}, table - 1, 0);
     if (ptr == nullptr) break;
     if (ctx->LastTag() != 1) break;  // Ended on terminating tag
   }
   return ptr;
 }
 
-  // Dispatch to the designated parse function
-inline PROTOBUF_ALWAYS_INLINE const char* TcParser::TagDispatch(
-    PROTOBUF_TC_PARAM_DECL) {
-  const auto coded_tag = UnalignedLoad<uint16_t>(ptr);
-  const size_t idx = coded_tag & table->fast_idx_mask;
-  PROTOBUF_ASSUME((idx & 7) == 0);
-  auto* fast_entry = table->fast_entry(idx >> 3);
-  data = fast_entry->bits;
-  data.data ^= coded_tag;
-  PROTOBUF_MUSTTAIL return fast_entry->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.
-inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToTagDispatch(
-    PROTOBUF_TC_PARAM_DECL) {
-  constexpr bool always_return = !PROTOBUF_TAILCALL;
-  if (always_return || !ctx->DataAvailable(ptr)) {
-    PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
-  }
-  PROTOBUF_MUSTTAIL return TagDispatch(PROTOBUF_TC_PARAM_PASS);
-}
-
-inline PROTOBUF_ALWAYS_INLINE const char* TcParser::ToParseLoop(
-    PROTOBUF_TC_PARAM_DECL) {
-  (void)data;
-  (void)ctx;
-  SyncHasbits(msg, hasbits, table);
-  return ptr;
-}
-
-inline PROTOBUF_ALWAYS_INLINE const char* TcParser::Error(
-    PROTOBUF_TC_PARAM_DECL) {
-  (void)data;
-  (void)ctx;
-  (void)ptr;
-  SyncHasbits(msg, hasbits, table);
-  return nullptr;
-}
-
 // On the fast path, a (matching) 1-byte tag already has the decoded value.
 static uint32_t FastDecodeTag(uint8_t coded_tag) {
   return coded_tag;
@@ -271,7 +227,7 @@
 // This is designed to be compact but not particularly fast to retrieve.
 // In particular, it takes O(n) to retrieve the name of the n'th field,
 // which is usually fine because most protos have fewer than 10 fields.
-static StringPiece FindName(const char* name_data, size_t entries,
+static absl::string_view FindName(const char* name_data, size_t entries,
                                   size_t index) {
   // The compiler unrolls these... if this isn't fast enough,
   // there's an AVX version at https://godbolt.org/z/eojrjqzfr
@@ -287,11 +243,11 @@
   return {start, size};
 }
 
-StringPiece TcParser::MessageName(const TcParseTableBase* table) {
+absl::string_view TcParser::MessageName(const TcParseTableBase* table) {
   return FindName(table->name_data(), table->num_field_entries + 1, 0);
 }
 
-StringPiece TcParser::FieldName(const TcParseTableBase* table,
+absl::string_view TcParser::FieldName(const TcParseTableBase* table,
                                       const FieldEntry* field_entry) {
   const FieldEntry* const field_entries = table->field_entries_begin();
   auto field_index = static_cast<size_t>(field_entry - field_entries);
@@ -299,13 +255,25 @@
                   field_index + 1);
 }
 
-const char* TcParser::MiniParse(PROTOBUF_TC_PARAM_DECL) {
+template <bool export_called_function>
+inline PROTOBUF_ALWAYS_INLINE const char* TcParser::MiniParseImpl(
+    PROTOBUF_TC_PARAM_DECL) {
+  TestMiniParseResult* test_out;
+  if (export_called_function) {
+    test_out = reinterpret_cast<TestMiniParseResult*>(
+        static_cast<uintptr_t>(data.data));
+  }
+
   uint32_t tag;
   ptr = ReadTagInlined(ptr, &tag);
-  if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) return nullptr;
+  if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) {
+    if (export_called_function) *test_out = {Error};
+    return Error(PROTOBUF_TC_PARAM_PASS);
+  }
 
   auto* entry = FindFieldEntry(table, tag >> 3);
   if (entry == nullptr) {
+    if (export_called_function) *test_out = {table->fallback, tag};
     data.data = tag;
     PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS);
   }
@@ -318,36 +286,94 @@
   data.data = entry_offset << 32 | tag;
 
   using field_layout::FieldKind;
-  auto field_type = entry->type_card & FieldKind::kFkMask;
-  switch (field_type) {
-    case FieldKind::kFkNone:
-      PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS);
-    case FieldKind::kFkVarint:
-      PROTOBUF_MUSTTAIL return MpVarint(PROTOBUF_TC_PARAM_PASS);
-    case FieldKind::kFkPackedVarint:
-      PROTOBUF_MUSTTAIL return MpPackedVarint(PROTOBUF_TC_PARAM_PASS);
-    case FieldKind::kFkFixed:
-      PROTOBUF_MUSTTAIL return MpFixed(PROTOBUF_TC_PARAM_PASS);
-    case FieldKind::kFkPackedFixed:
-      PROTOBUF_MUSTTAIL return MpPackedFixed(PROTOBUF_TC_PARAM_PASS);
-    case FieldKind::kFkString:
-      PROTOBUF_MUSTTAIL return MpString(PROTOBUF_TC_PARAM_PASS);
-    case FieldKind::kFkMessage:
-      PROTOBUF_MUSTTAIL return MpMessage(PROTOBUF_TC_PARAM_PASS);
-    case FieldKind::kFkMap:
-      PROTOBUF_MUSTTAIL return MpMap(PROTOBUF_TC_PARAM_PASS);
-    default:
-      return Error(PROTOBUF_TC_PARAM_PASS);
+  auto field_type =
+      entry->type_card & (+field_layout::kSplitMask | FieldKind::kFkMask);
+
+  static constexpr TailCallParseFunc kMiniParseTable[] = {
+      &MpFallback,        // FieldKind::kFkNone
+      &MpVarint<false>,   // FieldKind::kFkVarint
+      &MpPackedVarint,    // FieldKind::kFkPackedVarint
+      &MpFixed<false>,    // FieldKind::kFkFixed
+      &MpPackedFixed,     // FieldKind::kFkPackedFixed
+      &MpString<false>,   // FieldKind::kFkString
+      &MpMessage<false>,  // FieldKind::kFkMessage
+      &MpFallback,        // FieldKind::kFkMap
+      &Error,             // kSplitMask | FieldKind::kFkNone
+      &MpVarint<true>,    // kSplitMask | FieldKind::kFkVarint
+      &Error,             // kSplitMask | FieldKind::kFkPackedVarint
+      &MpFixed<true>,     // kSplitMask | FieldKind::kFkFixed
+      &Error,             // kSplitMask | FieldKind::kFkPackedFixed
+      &MpString<true>,    // kSplitMask | FieldKind::kFkString
+      &MpMessage<true>,   // kSplitMask | FieldKind::kFkMessage
+      &Error,             // kSplitMask | FieldKind::kFkMap
+  };
+  // Just to be sure we got the order right, above.
+  static_assert(0 == FieldKind::kFkNone, "Invalid table order");
+  static_assert(1 == FieldKind::kFkVarint, "Invalid table order");
+  static_assert(2 == FieldKind::kFkPackedVarint, "Invalid table order");
+  static_assert(3 == FieldKind::kFkFixed, "Invalid table order");
+  static_assert(4 == FieldKind::kFkPackedFixed, "Invalid table order");
+  static_assert(5 == FieldKind::kFkString, "Invalid table order");
+  static_assert(6 == FieldKind::kFkMessage, "Invalid table order");
+  static_assert(7 == FieldKind::kFkMap, "Invalid table order");
+
+  static_assert(8 == (+field_layout::kSplitMask | FieldKind::kFkNone),
+    "Invalid table order");
+  static_assert(9 == (+field_layout::kSplitMask | FieldKind::kFkVarint),
+    "Invalid table order");
+  static_assert(10 == (+field_layout::kSplitMask | FieldKind::kFkPackedVarint),
+    "Invalid table order");
+  static_assert(11 == (+field_layout::kSplitMask | FieldKind::kFkFixed),
+    "Invalid table order");
+  static_assert(12 == (+field_layout::kSplitMask | FieldKind::kFkPackedFixed),
+    "Invalid table order");
+  static_assert(13 == (+field_layout::kSplitMask | FieldKind::kFkString),
+    "Invalid table order");
+  static_assert(14 == (+field_layout::kSplitMask | FieldKind::kFkMessage),
+    "Invalid table order");
+  static_assert(15 == (+field_layout::kSplitMask | FieldKind::kFkMap),
+    "Invalid table order");
+
+  TailCallParseFunc parse_fn = kMiniParseTable[field_type];
+  if (export_called_function) *test_out = {parse_fn, tag, entry};
+
+  PROTOBUF_MUSTTAIL return parse_fn(PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::MiniParse(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return MiniParseImpl<false>(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE TcParser::TestMiniParseResult TcParser::TestMiniParse(
+    PROTOBUF_TC_PARAM_DECL) {
+  TestMiniParseResult result = {};
+  data.data = reinterpret_cast<uintptr_t>(&result);
+  result.ptr = MiniParseImpl<true>(PROTOBUF_TC_PARAM_PASS);
+  return result;
+}
+
+const char* TcParser::MpFallback(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename TagType>
+const char* TcParser::FastEndGroupImpl(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
+    PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
   }
+  ctx->SetLastTag(data.decoded_tag());
+  ptr += sizeof(TagType);
+  PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEndG1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEndGroupImpl<uint8_t>(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEndG2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return FastEndGroupImpl<uint16_t>(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_t*>(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.
@@ -362,9 +388,9 @@
 // Message fields
 //////////////////////////////////////////////////////////////////////////////
 
-template <typename TagType, bool group_coding>
-inline PROTOBUF_ALWAYS_INLINE
-const char* TcParser::SingularParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL) {
+template <typename TagType, bool group_coding, bool aux_is_table>
+inline PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularParseMessageAuxImpl(
+    PROTOBUF_TC_PARAM_DECL) {
   if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
     PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
   }
@@ -373,74 +399,159 @@
   hasbits |= (uint64_t{1} << data.hasbit_idx());
   SyncHasbits(msg, hasbits, table);
   auto& field = RefAt<MessageLite*>(msg, data.offset());
-  if (field == nullptr) {
-    const MessageLite* default_instance =
-        table->field_aux(data.aux_idx())->message_default;
-    field = default_instance->New(ctx->data().arena);
+
+  if (aux_is_table) {
+    const auto* inner_table = table->field_aux(data.aux_idx())->table;
+    if (field == nullptr) {
+      field = inner_table->default_instance->New(msg->GetArenaForAllocation());
+    }
+    if (group_coding) {
+      return ctx->ParseGroup<TcParser>(field, ptr, FastDecodeTag(saved_tag),
+                                       inner_table);
+    }
+    return ctx->ParseMessage<TcParser>(field, ptr, inner_table);
+  } else {
+    if (field == nullptr) {
+      const MessageLite* default_instance =
+          table->field_aux(data.aux_idx())->message_default();
+      field = default_instance->New(msg->GetArenaForAllocation());
+    }
+    if (group_coding) {
+      return ctx->ParseGroup(field, ptr, FastDecodeTag(saved_tag));
+    }
+    return ctx->ParseMessage(field, ptr);
   }
-  if (group_coding) {
-    return ctx->ParseGroup(field, ptr, FastDecodeTag(saved_tag));
-  }
-  return ctx->ParseMessage(field, ptr);
 }
 
-const char* TcParser::FastMS1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, false>(
+PROTOBUF_NOINLINE const char* TcParser::FastMdS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, false, false>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastMS2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, false>(
+PROTOBUF_NOINLINE const char* TcParser::FastMdS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, false, false>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastGS1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, true>(
+PROTOBUF_NOINLINE const char* TcParser::FastGdS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, true, false>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastGS2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, true>(
+PROTOBUF_NOINLINE const char* TcParser::FastGdS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, true, false>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-template <typename TagType, bool group_coding>
-inline PROTOBUF_ALWAYS_INLINE
-const char* TcParser::RepeatedParseMessageAuxImpl(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastMtS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastMtS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastGtS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint8_t, true, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastGtS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularParseMessageAuxImpl<uint16_t, true, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename TagType>
+const char* TcParser::LazyMessage(PROTOBUF_TC_PARAM_DECL) {
+  GOOGLE_LOG(FATAL) << "Unimplemented";
+  return nullptr;
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastMlS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return LazyMessage<uint8_t>(PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastMlS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return LazyMessage<uint16_t>(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename TagType, bool group_coding, bool aux_is_table>
+inline PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedParseMessageAuxImpl(
+    PROTOBUF_TC_PARAM_DECL) {
   if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
     PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
   }
-  auto saved_tag = UnalignedLoad<TagType>(ptr);
-  ptr += sizeof(TagType);
-  SyncHasbits(msg, hasbits, table);
-  const MessageLite* default_instance =
-      table->field_aux(data.aux_idx())->message_default;
+  const auto expected_tag = UnalignedLoad<TagType>(ptr);
+  const auto aux = *table->field_aux(data.aux_idx());
   auto& field = RefAt<RepeatedPtrFieldBase>(msg, data.offset());
-  MessageLite* submsg =
-      field.Add<GenericTypeHandler<MessageLite>>(default_instance);
-  if (group_coding) {
-    return ctx->ParseGroup(submsg, ptr, FastDecodeTag(saved_tag));
-  }
-  return ctx->ParseMessage(submsg, ptr);
+  do {
+    ptr += sizeof(TagType);
+    MessageLite* submsg = field.Add<GenericTypeHandler<MessageLite>>(
+        aux_is_table ? aux.table->default_instance : aux.message_default());
+    if (aux_is_table) {
+      if (group_coding) {
+        ptr = ctx->ParseGroup<TcParser>(submsg, ptr,
+                                        FastDecodeTag(expected_tag), aux.table);
+      } else {
+        ptr = ctx->ParseMessage<TcParser>(submsg, ptr, aux.table);
+      }
+    } else {
+      if (group_coding) {
+        ptr = ctx->ParseGroup(submsg, ptr, FastDecodeTag(expected_tag));
+      } else {
+        ptr = ctx->ParseMessage(submsg, ptr);
+      }
+    }
+    if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) {
+      PROTOBUF_MUSTTAIL return Error(PROTOBUF_TC_PARAM_PASS);
+    }
+    if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) {
+      PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
+    }
+  } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+
+  PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastMR1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, false>(
+PROTOBUF_NOINLINE const char* TcParser::FastMdR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, false, false>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastMR2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, false>(
+PROTOBUF_NOINLINE const char* TcParser::FastMdR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, false, false>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastGR1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, true>(
+PROTOBUF_NOINLINE const char* TcParser::FastGdR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, true, false>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastGR2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, true>(
+PROTOBUF_NOINLINE const char* TcParser::FastGdR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, true, false>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastMtR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastMtR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, false, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastGtR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint8_t, true, true>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastGtR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedParseMessageAuxImpl<uint16_t, true, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
@@ -461,19 +572,19 @@
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastF32S1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF32S1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularFixed<uint32_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF32S2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF32S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularFixed<uint32_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF64S1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF64S1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularFixed<uint64_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF64S2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF64S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularFixed<uint64_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
@@ -498,7 +609,7 @@
   auto elem = field.Add();
   int space = field.Capacity() - idx;
   idx = 0;
-  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  const auto expected_tag = UnalignedLoad<TagType>(ptr);
   do {
     ptr += sizeof(TagType);
     elem[idx++] = UnalignedLoad<LayoutType>(ptr);
@@ -510,19 +621,19 @@
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastF32R1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF32R1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedFixed<uint32_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF32R2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF32R2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedFixed<uint32_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF64R1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF64R1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedFixed<uint64_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF64R2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF64R2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedFixed<uint64_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
@@ -557,19 +668,19 @@
                               static_cast<RepeatedField<LayoutType>*>(&field));
 }
 
-const char* TcParser::FastF32P1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF32P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedFixed<uint32_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF32P2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF32P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedFixed<uint32_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF64P1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF64P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedFixed<uint64_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastF64P2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastF64P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedFixed<uint64_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
@@ -693,31 +804,108 @@
   return {p + 10, res1 & res2 & res3};
 }
 
+template <typename Type>
 inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p,
-                                                      uint64_t* value) {
+                                                      Type* value) {
+  static_assert(sizeof(Type) == 4 || sizeof(Type) == 8,
+                "Only [u]int32_t and [u]int64_t please");
+#ifdef __aarch64__
+  // The VarintParse parser has a faster implementation on ARM.
+  absl::conditional_t<sizeof(Type) == 4, uint32_t, uint64_t> tmp;
+  p = VarintParse(p, &tmp);
+  if (p != nullptr) {
+    *value = tmp;
+  }
+  return p;
+#endif
   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;
+    if (PROTOBUF_PREDICT_TRUE(tmp.first)) {
+      *value = static_cast<Type>(tmp.second);
+    }
     return tmp.first;
   }
 }
 
+// This overload is specifically for handling bool, because bools have very
+// different requirements and performance opportunities than ints.
+inline PROTOBUF_ALWAYS_INLINE const char* ParseVarint(const char* p,
+                                                      bool* value) {
+  unsigned char byte = static_cast<unsigned char>(*p++);
+  if (PROTOBUF_PREDICT_TRUE(byte == 0 || byte == 1)) {
+    // This is the code path almost always taken,
+    // so we take care to make it very efficient.
+    if (sizeof(byte) == sizeof(*value)) {
+      memcpy(value, &byte, 1);
+    } else {
+      // The C++ standard does not specify that a `bool` takes only one byte
+      *value = byte;
+    }
+    return p;
+  }
+  // This part, we just care about code size.
+  // Although it's almost never used, we have to support it because we guarantee
+  // compatibility for users who change a field from an int32 or int64 to a bool
+  if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+    byte = (byte - 0x80) | *p++;
+    if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+      byte = (byte - 0x80) | *p++;
+      if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+        byte = (byte - 0x80) | *p++;
+        if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+          byte = (byte - 0x80) | *p++;
+          if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+            byte = (byte - 0x80) | *p++;
+            if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+              byte = (byte - 0x80) | *p++;
+              if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+                byte = (byte - 0x80) | *p++;
+                if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+                  byte = (byte - 0x80) | *p++;
+                  if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+                    byte = (byte - 0x80) | *p++;
+                    if (PROTOBUF_PREDICT_FALSE(byte & 0x80)) {
+                      return nullptr;
+                    }
+                  }
+                }
+              }
+            }
+          }
+        }
+      }
+    }
+  }
+  *value = byte;
+  return p;
+}
+
 template <typename FieldType, bool zigzag = false>
-inline FieldType ZigZagDecodeHelper(uint64_t value) {
+inline FieldType ZigZagDecodeHelper(FieldType value) {
   return static_cast<FieldType>(value);
 }
 
 template <>
-inline int32_t ZigZagDecodeHelper<int32_t, true>(uint64_t value) {
+inline uint32_t ZigZagDecodeHelper<uint32_t, true>(uint32_t value) {
   return WireFormatLite::ZigZagDecode32(value);
 }
 
 template <>
-inline int64_t ZigZagDecodeHelper<int64_t, true>(uint64_t value) {
+inline int32_t ZigZagDecodeHelper<int32_t, true>(int32_t value) {
+  return WireFormatLite::ZigZagDecode32(value);
+}
+
+template <>
+inline uint64_t ZigZagDecodeHelper<uint64_t, true>(uint64_t value) {
+  return WireFormatLite::ZigZagDecode64(value);
+}
+
+template <>
+inline int64_t ZigZagDecodeHelper<int64_t, true>(int64_t value) {
   return WireFormatLite::ZigZagDecode64(value);
 }
 
@@ -768,9 +956,15 @@
     const ::google::protobuf::internal::TcParseTableBase* table;
     uint64_t hasbits;
   };
-  volatile Spill spill = {data.data, msg, table, hasbits};
+  Spill spill = {data.data, msg, table, hasbits};
+#if defined(__GNUC__)
+  // This empty asm block convinces the compiler that the contents of spill may
+  // have changed, and thus can't be cached in registers.  It's similar to, but
+  // more optimal than, the effect of declaring it "volatile".
+  asm("" : "+m"(spill));
+#endif
 
-  uint64_t tmp;
+  FieldType tmp;
   PROTOBUF_ASSUME(static_cast<int8_t>(*ptr) < 0);
   ptr = ParseVarint(ptr, &tmp);
 
@@ -787,44 +981,43 @@
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastV8S1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularVarint<bool, uint8_t>(
-      PROTOBUF_TC_PARAM_PASS);
+PROTOBUF_NOINLINE const char* TcParser::FastV8S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SpecializedFastV8S1<-1, -1>(PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV8S2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV8S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<bool, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV32S1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV32S1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<uint32_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV32S2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV32S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<uint32_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV64S1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV64S1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<uint64_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV64S2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV64S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<uint64_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastZ32S1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ32S1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<int32_t, uint8_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ32S2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ32S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<int32_t, uint16_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ64S1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ64S1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<int64_t, uint8_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ64S2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ64S2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularVarint<int64_t, uint16_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
@@ -842,10 +1035,10 @@
     }
   }
   auto& field = RefAt<RepeatedField<FieldType>>(msg, data.offset());
-  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  const auto expected_tag = UnalignedLoad<TagType>(ptr);
   do {
     ptr += sizeof(TagType);
-    uint64_t tmp;
+    FieldType tmp;
     ptr = ParseVarint(ptr, &tmp);
     if (ptr == nullptr) {
       return Error(PROTOBUF_TC_PARAM_PASS);
@@ -858,44 +1051,44 @@
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastV8R1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV8R1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<bool, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV8R2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV8R2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<bool, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV32R1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV32R1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<uint32_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV32R2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV32R2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<uint32_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV64R1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV64R1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<uint64_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV64R2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV64R2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<uint64_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastZ32R1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ32R1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<int32_t, uint8_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ32R2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ32R2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<int32_t, uint16_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ64R1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ64R1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<int64_t, uint8_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ64R2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ64R2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedVarint<int64_t, uint16_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
@@ -931,42 +1124,42 @@
   });
 }
 
-const char* TcParser::FastV8P1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV8P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<bool, uint8_t>(PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV8P2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV8P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<bool, uint16_t>(PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV32P1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV32P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<uint32_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV32P2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV32P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<uint32_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV64P1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV64P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<uint64_t, uint8_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastV64P2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastV64P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<uint64_t, uint16_t>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastZ32P1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ32P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<int32_t, uint8_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ32P2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ32P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<int32_t, uint16_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ64P1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ64P1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<int64_t, uint8_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastZ64P2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastZ64P2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return PackedVarint<int64_t, uint16_t, true>(
       PROTOBUF_TC_PARAM_PASS);
 }
@@ -977,10 +1170,6 @@
 
 PROTOBUF_NOINLINE const char* TcParser::FastUnknownEnumFallback(
     PROTOBUF_TC_PARAM_DECL) {
-  (void)msg;
-  (void)ctx;
-  (void)hasbits;
-
   // If we know we want to put this field directly into the unknown field set,
   // then we can skip the call to MiniParse and directly call table->fallback.
   // However, we first have to update `data` to contain the decoded tag.
@@ -1017,37 +1206,36 @@
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastErS1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastErS1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, field_layout::kTvRange>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastErS2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastErS2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, field_layout::kTvRange>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastEvS1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastEvS1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularEnum<uint8_t, field_layout::kTvEnum>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastEvS2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastEvS2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return SingularEnum<uint16_t, field_layout::kTvEnum>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
 template <typename TagType, uint16_t xform_val>
-PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedEnum(
-    PROTOBUF_TC_PARAM_DECL) {
+const char* TcParser::RepeatedEnum(PROTOBUF_TC_PARAM_DECL) {
   if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
     InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data);
     if (data.coded_tag<TagType>() == 0) {
-      // Packed parsing is handled by generated fallback.
-      PROTOBUF_MUSTTAIL return FastUnknownEnumFallback(PROTOBUF_TC_PARAM_PASS);
+      PROTOBUF_MUSTTAIL return PackedEnum<TagType, xform_val>(
+          PROTOBUF_TC_PARAM_PASS);
     } else {
       PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
     }
   }
   auto& field = RefAt<RepeatedField<int32_t>>(msg, data.offset());
-  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  const auto expected_tag = UnalignedLoad<TagType>(ptr);
   const TcParseTableBase::FieldAux aux = *table->field_aux(data.aux_idx());
   do {
     const char* ptr2 = ptr;  // save for unknown enum case
@@ -1072,30 +1260,246 @@
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastErR1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE void TcParser::UnknownPackedEnum(
+    MessageLite* msg, ParseContext* ctx, const TcParseTableBase* table,
+    uint32_t tag, int32_t enum_value) {
+  // Call the fallback function in a special mode to only act as a
+  // way to push the unknown enum into the UnknownFieldSet. This is
+  // _not_ a tail call, and we should continue processing the packed
+  // input.
+  TcFieldData data;
+  data.data = (uint64_t{static_cast<uint32_t>(enum_value)} << 32) | tag;
+  table->fallback(msg, nullptr, ctx, data, table, 0);
+}
+
+template <typename TagType, uint16_t xform_val>
+const char* TcParser::PackedEnum(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
+    InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data);
+    if (data.coded_tag<TagType>() == 0) {
+      PROTOBUF_MUSTTAIL return RepeatedEnum<TagType, xform_val>(
+          PROTOBUF_TC_PARAM_PASS);
+    } else {
+      PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+    }
+  }
+  const auto saved_tag = UnalignedLoad<TagType>(ptr);
+  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<int32_t>>(msg, data.offset());
+  const TcParseTableBase::FieldAux aux = *table->field_aux(data.aux_idx());
+  return ctx->ReadPackedVarint(ptr, [=](int32_t value) {
+    if (!EnumIsValidAux(value, xform_val, aux)) {
+      UnknownPackedEnum(msg, ctx, table, FastDecodeTag(saved_tag), value);
+    } else {
+      field->Add(value);
+    }
+  });
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastErR1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedEnum<uint8_t, field_layout::kTvRange>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastErR2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastErR2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedEnum<uint16_t, field_layout::kTvRange>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastEvR1(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastEvR1(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedEnum<uint8_t, field_layout::kTvEnum>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastEvR2(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::FastEvR2(PROTOBUF_TC_PARAM_DECL) {
   PROTOBUF_MUSTTAIL return RepeatedEnum<uint16_t, field_layout::kTvEnum>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
+PROTOBUF_NOINLINE const char* TcParser::FastErP1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnum<uint8_t, field_layout::kTvRange>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastErP2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnum<uint16_t, field_layout::kTvRange>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEvP1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnum<uint8_t, field_layout::kTvEnum>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEvP2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnum<uint16_t, field_layout::kTvEnum>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename TagType, uint8_t min>
+PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularEnumSmallRange(
+    PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
+    PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+  }
+
+  uint8_t v = ptr[sizeof(TagType)];
+  if (PROTOBUF_PREDICT_FALSE(min > v || v > data.aux_idx())) {
+    PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+  }
+
+  RefAt<int32_t>(msg, data.offset()) = v;
+  ptr += sizeof(TagType) + 1;
+  hasbits |= (uint64_t{1} << data.hasbit_idx());
+  PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr0S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnumSmallRange<uint8_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr0S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnumSmallRange<uint16_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr1S1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnumSmallRange<uint8_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr1S2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularEnumSmallRange<uint16_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename TagType, uint8_t min>
+const char* TcParser::RepeatedEnumSmallRange(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
+    InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data);
+    if (data.coded_tag<TagType>() == 0) {
+      PROTOBUF_MUSTTAIL return PackedEnumSmallRange<TagType, min>(
+          PROTOBUF_TC_PARAM_PASS);
+    } else {
+      PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+    }
+  }
+  auto& field = RefAt<RepeatedField<int32_t>>(msg, data.offset());
+  auto expected_tag = UnalignedLoad<TagType>(ptr);
+  const uint8_t max = data.aux_idx();
+  do {
+    uint8_t v = ptr[sizeof(TagType)];
+    if (PROTOBUF_PREDICT_FALSE(min > v || v > max)) {
+      PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+    }
+    field.Add(static_cast<int32_t>(v));
+    ptr += sizeof(TagType) + 1;
+    if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) break;
+  } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+
+  PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr0R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<uint8_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr0R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<uint16_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr1R1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<uint8_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr1R2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<uint16_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename TagType, uint8_t min>
+const char* TcParser::PackedEnumSmallRange(PROTOBUF_TC_PARAM_DECL) {
+  if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
+    InvertPacked<WireFormatLite::WIRETYPE_VARINT>(data);
+    if (data.coded_tag<TagType>() == 0) {
+      PROTOBUF_MUSTTAIL return RepeatedEnumSmallRange<TagType, min>(
+          PROTOBUF_TC_PARAM_PASS);
+    } else {
+      PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+    }
+  }
+  const auto saved_tag = UnalignedLoad<TagType>(ptr);
+  ptr += sizeof(TagType);
+  auto* field = &RefAt<RepeatedField<int32_t>>(msg, data.offset());
+  const uint8_t max = data.aux_idx();
+
+  int size = static_cast<int>(ReadSize(&ptr));
+  if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) {
+    return Error(PROTOBUF_TC_PARAM_PASS);
+  }
+
+  while (size > 0) {
+    uint8_t v = *ptr;
+    if (PROTOBUF_PREDICT_FALSE(min > v || v > max)) {
+      // If it is out of range it might be because it is a non-canonical varint
+      // with a small value (ie the continuation bit is on).
+      // Do the full varint parse just in case.
+      uint64_t tmp;
+      const char* const old_ptr = ptr;
+      ptr = ParseVarint(ptr, &tmp);
+      if (PROTOBUF_PREDICT_FALSE(ptr == nullptr)) {
+        return Error(PROTOBUF_TC_PARAM_PASS);
+      }
+      size -= static_cast<int>(ptr - old_ptr);
+      if (PROTOBUF_PREDICT_FALSE(size < 0)) {
+        return Error(PROTOBUF_TC_PARAM_PASS);
+      }
+      int32_t v32 = static_cast<int32_t>(tmp);
+      if (PROTOBUF_PREDICT_FALSE(min > v32 || v32 > max)) {
+        UnknownPackedEnum(msg, ctx, table, FastDecodeTag(saved_tag), v32);
+      } else {
+        field->Add(v32);
+      }
+    } else {
+      ptr += 1;
+      size -= 1;
+      field->Add(v);
+    }
+
+    if (PROTOBUF_PREDICT_FALSE(!ctx->DataAvailable(ptr))) {
+      if (ctx->Done(&ptr) && size != 0) {
+        return Error(PROTOBUF_TC_PARAM_PASS);
+      }
+    }
+  }
+
+  PROTOBUF_MUSTTAIL return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr0P1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnumSmallRange<uint8_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr0P2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnumSmallRange<uint16_t, 0>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
+PROTOBUF_NOINLINE const char* TcParser::FastEr1P1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnumSmallRange<uint8_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastEr1P2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return PackedEnumSmallRange<uint16_t, 1>(
+      PROTOBUF_TC_PARAM_PASS);
+}
+
 //////////////////////////////////////////////////////////////////////////////
 // String/bytes fields
 //////////////////////////////////////////////////////////////////////////////
 
 // Defined in wire_format_lite.cc
-void PrintUTF8ErrorLog(StringPiece message_name,
-                       StringPiece field_name, const char* operation_str,
+void PrintUTF8ErrorLog(absl::string_view message_name,
+                       absl::string_view field_name, const char* operation_str,
                        bool emit_stacktrace);
 
 void TcParser::ReportFastUtf8Error(uint32_t decoded_tag,
@@ -1108,17 +1512,34 @@
 
 namespace {
 
+// Here are overloads of ReadStringIntoArena, ReadStringNoArena and IsValidUTF8
+// for every string class for which we provide fast-table parser support.
+
+PROTOBUF_ALWAYS_INLINE inline const char* ReadStringIntoArena(
+    MessageLite* /*msg*/, const char* ptr, ParseContext* ctx,
+    uint32_t /*aux_idx*/, const TcParseTableBase* /*table*/,
+    ArenaStringPtr& field, Arena* arena) {
+  return ctx->ReadArenaString(ptr, &field, arena);
+}
+
 PROTOBUF_NOINLINE
-const char* SingularStringParserFallback(ArenaStringPtr* s, const char* ptr,
-                                         EpsCopyInputStream* stream) {
+const char* ReadStringNoArena(MessageLite* /*msg*/, const char* ptr,
+                              ParseContext* ctx, uint32_t /*aux_idx*/,
+                              const TcParseTableBase* /*table*/,
+                              ArenaStringPtr& field) {
   int size = ReadSize(&ptr);
   if (!ptr) return nullptr;
-  return stream->ReadString(ptr, size, s->MutableNoCopy(nullptr));
+  return ctx->ReadString(ptr, size, field.MutableNoCopy(nullptr));
 }
 
+PROTOBUF_ALWAYS_INLINE inline bool IsValidUTF8(ArenaStringPtr& field) {
+  return utf8_range::IsStructurallyValid(field.Get());
+}
+
+
 }  // namespace
 
-template <typename TagType, TcParser::Utf8Type utf8>
+template <typename TagType, typename FieldType, TcParser::Utf8Type utf8>
 PROTOBUF_ALWAYS_INLINE const char* TcParser::SingularString(
     PROTOBUF_TC_PARAM_DECL) {
   if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
@@ -1127,12 +1548,13 @@
   auto saved_tag = UnalignedLoad<TagType>(ptr);
   ptr += sizeof(TagType);
   hasbits |= (uint64_t{1} << data.hasbit_idx());
-  auto& field = RefAt<ArenaStringPtr>(msg, data.offset());
-  auto arena = ctx->data().arena;
+  auto& field = RefAt<FieldType>(msg, data.offset());
+  auto arena = msg->GetArenaForAllocation();
   if (arena) {
-    ptr = ctx->ReadArenaString(ptr, &field, arena);
+    ptr =
+        ReadStringIntoArena(msg, ptr, ctx, data.aux_idx(), table, field, arena);
   } else {
-    ptr = SingularStringParserFallback(&field, ptr, ctx);
+    ptr = ReadStringNoArena(msg, ptr, ctx, data.aux_idx(), table, field);
   }
   if (ptr == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
   switch (utf8) {
@@ -1142,7 +1564,7 @@
 #endif
       return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
     default:
-      if (PROTOBUF_PREDICT_TRUE(IsStructurallyValidUTF8(field.Get()))) {
+      if (PROTOBUF_PREDICT_TRUE(IsValidUTF8(field))) {
         return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
       }
       ReportFastUtf8Error(FastDecodeTag(saved_tag), table);
@@ -1151,28 +1573,30 @@
   }
 }
 
-const char* TcParser::FastBS1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularString<uint8_t, kNoUtf8>(
+PROTOBUF_NOINLINE const char* TcParser::FastBS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularString<uint8_t, ArenaStringPtr, kNoUtf8>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastBS2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularString<uint16_t, kNoUtf8>(
+PROTOBUF_NOINLINE const char* TcParser::FastBS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularString<uint16_t, ArenaStringPtr, kNoUtf8>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastSS1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularString<uint8_t, kUtf8ValidateOnly>(
+PROTOBUF_NOINLINE const char* TcParser::FastSS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularString<uint8_t, ArenaStringPtr,
+                                          kUtf8ValidateOnly>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastSS2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularString<uint16_t, kUtf8ValidateOnly>(
+PROTOBUF_NOINLINE const char* TcParser::FastSS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularString<uint16_t, ArenaStringPtr,
+                                          kUtf8ValidateOnly>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastUS1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularString<uint8_t, kUtf8>(
+PROTOBUF_NOINLINE const char* TcParser::FastUS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularString<uint8_t, ArenaStringPtr, kUtf8>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastUS2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return SingularString<uint16_t, kUtf8>(
+PROTOBUF_NOINLINE const char* TcParser::FastUS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return SingularString<uint16_t, ArenaStringPtr, kUtf8>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
@@ -1197,62 +1621,107 @@
   PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
 }
 
-template <typename TagType, TcParser::Utf8Type utf8>
+// Corded string variants:
+const char* TcParser::FastBcS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastBcS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastScS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastScS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastUcS1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+}
+const char* TcParser::FastUcS2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return MiniParse(PROTOBUF_TC_PARAM_PASS);
+}
+
+template <typename TagType, typename FieldType, TcParser::Utf8Type utf8>
 PROTOBUF_ALWAYS_INLINE const char* TcParser::RepeatedString(
     PROTOBUF_TC_PARAM_DECL) {
   if (PROTOBUF_PREDICT_FALSE(data.coded_tag<TagType>() != 0)) {
     PROTOBUF_MUSTTAIL return MiniParse(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);
-    }
+  const auto expected_tag = UnalignedLoad<TagType>(ptr);
+  auto& field = RefAt<FieldType>(msg, data.offset());
+
+  const auto validate_last_string = [expected_tag, table, &field] {
     switch (utf8) {
       case kNoUtf8:
 #ifdef NDEBUG
       case kUtf8ValidateOnly:
 #endif
-        break;
+        return true;
       default:
-        if (PROTOBUF_PREDICT_TRUE(IsStructurallyValidUTF8(*str))) {
-          break;
+        if (PROTOBUF_PREDICT_TRUE(
+                utf8_range::IsStructurallyValid(field[field.size() - 1]))) {
+          return true;
         }
         ReportFastUtf8Error(FastDecodeTag(expected_tag), table);
-        if (utf8 == kUtf8) return Error(PROTOBUF_TC_PARAM_PASS);
-        break;
+        if (utf8 == kUtf8) return false;
+        return true;
     }
-    if (!ctx->DataAvailable(ptr)) break;
-  } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+  };
+
+  auto* arena = field.GetOwningArena();
+  SerialArena* serial_arena;
+  if (PROTOBUF_PREDICT_TRUE(arena != nullptr &&
+                            arena->impl_.GetSerialArenaFast(&serial_arena) &&
+                            field.PrepareForParse())) {
+    do {
+      ptr += sizeof(TagType);
+      ptr = ParseRepeatedStringOnce(ptr, arena, serial_arena, ctx, field);
+
+      if (PROTOBUF_PREDICT_FALSE(ptr == nullptr || !validate_last_string())) {
+        return Error(PROTOBUF_TC_PARAM_PASS);
+      }
+      if (!ctx->DataAvailable(ptr)) break;
+    } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+  } else {
+    do {
+      ptr += sizeof(TagType);
+      std::string* str = field.Add();
+      ptr = InlineGreedyStringParser(str, ptr, ctx);
+      if (PROTOBUF_PREDICT_FALSE(ptr == nullptr || !validate_last_string())) {
+        return Error(PROTOBUF_TC_PARAM_PASS);
+      }
+      if (!ctx->DataAvailable(ptr)) break;
+    } while (UnalignedLoad<TagType>(ptr) == expected_tag);
+  }
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::FastBR1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedString<uint8_t, kNoUtf8>(
+PROTOBUF_NOINLINE const char* TcParser::FastBR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedString<
+      uint8_t, RepeatedPtrField<std::string>, kNoUtf8>(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastBR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedString<
+      uint16_t, RepeatedPtrField<std::string>, kNoUtf8>(PROTOBUF_TC_PARAM_PASS);
+}
+PROTOBUF_NOINLINE const char* TcParser::FastSR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedString<
+      uint8_t, RepeatedPtrField<std::string>, kUtf8ValidateOnly>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastBR2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedString<uint16_t, kNoUtf8>(
+PROTOBUF_NOINLINE const char* TcParser::FastSR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedString<
+      uint16_t, RepeatedPtrField<std::string>, kUtf8ValidateOnly>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastSR1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedString<uint8_t, kUtf8ValidateOnly>(
+PROTOBUF_NOINLINE const char* TcParser::FastUR1(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedString<uint8_t,
+                                          RepeatedPtrField<std::string>, kUtf8>(
       PROTOBUF_TC_PARAM_PASS);
 }
-const char* TcParser::FastSR2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedString<uint16_t, kUtf8ValidateOnly>(
-      PROTOBUF_TC_PARAM_PASS);
-}
-const char* TcParser::FastUR1(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedString<uint8_t, kUtf8>(
-      PROTOBUF_TC_PARAM_PASS);
-}
-const char* TcParser::FastUR2(PROTOBUF_TC_PARAM_DECL) {
-  PROTOBUF_MUSTTAIL return RepeatedString<uint16_t, kUtf8>(
+PROTOBUF_NOINLINE const char* TcParser::FastUR2(PROTOBUF_TC_PARAM_DECL) {
+  PROTOBUF_MUSTTAIL return RepeatedString<uint16_t,
+                                          RepeatedPtrField<std::string>, kUtf8>(
       PROTOBUF_TC_PARAM_PASS);
 }
 
@@ -1261,20 +1730,14 @@
 //////////////////////////////////////////////////////////////////////////////
 
 namespace {
-inline void SetHas(const TcParseTableBase* table, const FieldEntry& entry,
-                   MessageLite* msg, uint64_t& hasbits) {
-  int32_t has_idx = entry.has_idx;
-  if (has_idx < 32) {
-    hasbits |= uint64_t{1} << has_idx;
-  } else {
-    auto* hasblocks = &TcParser::RefAt<uint32_t>(msg, table->has_bits_offset);
+inline void SetHas(const FieldEntry& entry, MessageLite* msg) {
+  auto has_idx = static_cast<uint32_t>(entry.has_idx);
 #if defined(__x86_64__) && defined(__GNUC__)
-    asm("bts %1, %0\n" : "+m"(*hasblocks) : "r"(has_idx));
+  asm("bts %1, %0\n" : "+m"(*msg) : "r"(has_idx));
 #else
-    auto& hasblock = hasblocks[has_idx / 32];
-    hasblock |= uint32_t{1} << (has_idx % 32);
+  auto& hasblock = TcParser::RefAt<uint32_t>(msg, has_idx / 32 * 4);
+  hasblock |= uint32_t{1} << (has_idx % 32);
 #endif
-  }
 }
 }  // namespace
 
@@ -1285,11 +1748,8 @@
                            const TcParseTableBase::FieldEntry& entry,
                            uint32_t field_num, ParseContext* ctx,
                            MessageLite* msg) {
-  // The _oneof_case_ array offset is stored in the first aux entry.
-  uint32_t oneof_case_offset = table->field_aux(0u)->offset;
-  // The _oneof_case_ array index is stored in the has-bit index.
-  uint32_t* oneof_case =
-      &TcParser::RefAt<uint32_t>(msg, oneof_case_offset) + entry.has_idx;
+  // The _oneof_case_ value offset is stored in the has-bit index.
+  uint32_t* oneof_case = &TcParser::RefAt<uint32_t>(msg, entry.has_idx);
   uint32_t current_case = *oneof_case;
   *oneof_case = field_num;
 
@@ -1323,10 +1783,16 @@
   } else if (current_kind == field_layout::kFkMessage) {
     switch (current_rep) {
       case field_layout::kRepMessage:
-      case field_layout::kRepGroup:
-      case field_layout::kRepIWeak: {
+      case field_layout::kRepGroup: {
         auto& field = RefAt<MessageLite*>(msg, current_entry->offset);
-        if (!ctx->data().arena) {
+        if (!msg->GetArenaForAllocation()) {
+          delete field;
+        }
+        break;
+      }
+      case field_layout::kRepLazy: {
+        auto& field = RefAt<LazyField*>(msg, current_entry->offset);
+        if (!msg->GetArenaForAllocation()) {
           delete field;
         }
         break;
@@ -1340,7 +1806,40 @@
   return true;
 }
 
-const char* TcParser::MpFixed(PROTOBUF_TC_PARAM_DECL) {
+namespace {
+uint32_t GetSplitOffset(const TcParseTableBase* table) {
+  return table->field_aux(kSplitOffsetAuxIdx)->offset;
+}
+
+uint32_t GetSizeofSplit(const TcParseTableBase* table) {
+  return table->field_aux(kSplitSizeAuxIdx)->offset;
+}
+}  // namespace
+
+void* TcParser::MaybeGetSplitBase(MessageLite* msg, const bool is_split,
+                                  const TcParseTableBase* table,
+                                  ::google::protobuf::internal::ParseContext* ctx) {
+  void* out = msg;
+  if (is_split) {
+    const uint32_t split_offset = GetSplitOffset(table);
+    void* default_split =
+        TcParser::RefAt<void*>(table->default_instance, split_offset);
+    void*& split = TcParser::RefAt<void*>(msg, split_offset);
+    if (split == default_split) {
+      // Allocate split instance when needed.
+      uint32_t size = GetSizeofSplit(table);
+      Arena* arena = msg->GetArenaForAllocation();
+      split = (arena == nullptr) ? ::operator new(size)
+                                 : arena->AllocateAligned(size);
+      memcpy(split, default_split, size);
+    }
+    out = split;
+  }
+  return out;
+}
+
+template <bool is_split>
+PROTOBUF_NOINLINE const char* TcParser::MpFixed(PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   const uint16_t type_card = entry.type_card;
   const uint16_t card = type_card & field_layout::kFcMask;
@@ -1364,22 +1863,24 @@
   }
   // Set the field present:
   if (card == field_layout::kFcOptional) {
-    SetHas(table, entry, msg, hasbits);
+    SetHas(entry, msg);
   } else if (card == field_layout::kFcOneof) {
     ChangeOneof(table, entry, data.tag() >> 3, ctx, msg);
   }
+  void* const base = MaybeGetSplitBase(msg, is_split, table, ctx);
   // Copy the value:
   if (rep == field_layout::kRep64Bits) {
-    RefAt<uint64_t>(msg, entry.offset) = UnalignedLoad<uint64_t>(ptr);
+    RefAt<uint64_t>(base, entry.offset) = UnalignedLoad<uint64_t>(ptr);
     ptr += sizeof(uint64_t);
   } else {
-    RefAt<uint32_t>(msg, entry.offset) = UnalignedLoad<uint32_t>(ptr);
+    RefAt<uint32_t>(base, entry.offset) = UnalignedLoad<uint32_t>(ptr);
     ptr += sizeof(uint32_t);
   }
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::MpRepeatedFixed(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::MpRepeatedFixed(
+    PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   const uint32_t decoded_tag = data.tag();
   const uint32_t decoded_wiretype = decoded_tag & 7;
@@ -1427,7 +1928,7 @@
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::MpPackedFixed(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::MpPackedFixed(PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   const uint16_t type_card = entry.type_card;
   const uint32_t decoded_wiretype = data.tag() & 7;
@@ -1458,7 +1959,8 @@
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::MpVarint(PROTOBUF_TC_PARAM_DECL) {
+template <bool is_split>
+PROTOBUF_NOINLINE const char* TcParser::MpVarint(PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   const uint16_t type_card = entry.type_card;
   const uint16_t card = type_card & field_layout::kFcMask;
@@ -1501,24 +2003,26 @@
   // Mark the field as present:
   const bool is_oneof = card == field_layout::kFcOneof;
   if (card == field_layout::kFcOptional) {
-    SetHas(table, entry, msg, hasbits);
+    SetHas(entry, msg);
   } else if (is_oneof) {
     ChangeOneof(table, entry, data.tag() >> 3, ctx, msg);
   }
 
+  void* const base = MaybeGetSplitBase(msg, is_split, table, ctx);
   if (rep == field_layout::kRep64Bits) {
-    RefAt<uint64_t>(msg, entry.offset) = tmp;
+    RefAt<uint64_t>(base, entry.offset) = tmp;
   } else if (rep == field_layout::kRep32Bits) {
-    RefAt<uint32_t>(msg, entry.offset) = static_cast<uint32_t>(tmp);
+    RefAt<uint32_t>(base, entry.offset) = static_cast<uint32_t>(tmp);
   } else {
     GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits));
-    RefAt<bool>(msg, entry.offset) = static_cast<bool>(tmp);
+    RefAt<bool>(base, entry.offset) = static_cast<bool>(tmp);
   }
 
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::MpRepeatedVarint(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::MpRepeatedVarint(
+    PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   auto type_card = entry.type_card;
   const uint32_t decoded_tag = data.tag();
@@ -1548,6 +2052,7 @@
       field.Add(is_zigzag ? WireFormatLite::ZigZagDecode64(tmp) : tmp);
       if (!ctx->DataAvailable(ptr)) break;
       ptr2 = ReadTag(ptr, &next_tag);
+      if (ptr2 == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
     } while (next_tag == decoded_tag);
   } else if (rep == field_layout::kRep32Bits) {
     auto& field = RefAt<RepeatedField<uint32_t>>(msg, entry.offset);
@@ -1568,6 +2073,7 @@
       field.Add(tmp);
       if (!ctx->DataAvailable(ptr)) break;
       ptr2 = ReadTag(ptr, &next_tag);
+      if (ptr2 == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
     } while (next_tag == decoded_tag);
   } else {
     GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits));
@@ -1581,13 +2087,14 @@
       field.Add(static_cast<bool>(tmp));
       if (!ctx->DataAvailable(ptr)) break;
       ptr2 = ReadTag(ptr, &next_tag);
+      if (ptr2 == nullptr) return Error(PROTOBUF_TC_PARAM_PASS);
     } while (next_tag == decoded_tag);
   }
 
   PROTOBUF_MUSTTAIL return ToTagDispatch(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::MpPackedVarint(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_NOINLINE const char* TcParser::MpPackedVarint(PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   auto type_card = entry.type_card;
   auto decoded_wiretype = data.tag() & 7;
@@ -1596,13 +2103,9 @@
   if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
     PROTOBUF_MUSTTAIL return MpRepeatedVarint(PROTOBUF_TC_PARAM_PASS);
   }
-  uint16_t xform_val = (type_card & field_layout::kTvMask);
+  const uint16_t xform_val = (type_card & field_layout::kTvMask);
   const bool is_zigzag = xform_val == field_layout::kTvZigZag;
   const bool is_validated_enum = xform_val & field_layout::kTvEnum;
-  if (is_validated_enum) {
-    // TODO(b/206890171): handle enums
-    PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS);
-  }
 
   // Since ctx->ReadPackedFixed does not use TailCall<> or Return<>, sync any
   // pending hasbits now:
@@ -1616,11 +2119,22 @@
     });
   } else if (rep == field_layout::kRep32Bits) {
     auto* field = &RefAt<RepeatedField<uint32_t>>(msg, entry.offset);
-    return ctx->ReadPackedVarint(ptr, [field, is_zigzag](uint64_t value) {
-      field->Add(is_zigzag ? WireFormatLite::ZigZagDecode32(
-                                 static_cast<uint32_t>(value))
-                           : value);
-    });
+    if (is_validated_enum) {
+      const TcParseTableBase::FieldAux aux = *table->field_aux(entry.aux_idx);
+      return ctx->ReadPackedVarint(ptr, [=](int32_t value) {
+        if (!EnumIsValidAux(value, xform_val, aux)) {
+          UnknownPackedEnum(msg, ctx, table, data.tag(), value);
+        } else {
+          field->Add(value);
+        }
+      });
+    } else {
+      return ctx->ReadPackedVarint(ptr, [field, is_zigzag](uint64_t value) {
+        field->Add(is_zigzag ? WireFormatLite::ZigZagDecode32(
+                                   static_cast<uint32_t>(value))
+                             : value);
+      });
+    }
   } else {
     GOOGLE_DCHECK_EQ(rep, static_cast<uint16_t>(field_layout::kRep8Bits));
     auto* field = &RefAt<RepeatedField<bool>>(msg, entry.offset);
@@ -1631,11 +2145,11 @@
   return Error(PROTOBUF_TC_PARAM_PASS);
 }
 
-bool TcParser::MpVerifyUtf8(StringPiece wire_bytes,
+bool TcParser::MpVerifyUtf8(absl::string_view wire_bytes,
                             const TcParseTableBase* table,
                             const FieldEntry& entry, uint16_t xform_val) {
   if (xform_val == field_layout::kTvUtf8) {
-    if (!IsStructurallyValidUTF8(wire_bytes)) {
+    if (!utf8_range::IsStructurallyValid(wire_bytes)) {
       PrintUTF8ErrorLog(MessageName(table), FieldName(table, &entry), "parsing",
                         false);
       return false;
@@ -1644,7 +2158,7 @@
   }
 #ifndef NDEBUG
   if (xform_val == field_layout::kTvUtf8Debug) {
-    if (!IsStructurallyValidUTF8(wire_bytes)) {
+    if (!utf8_range::IsStructurallyValid(wire_bytes)) {
       PrintUTF8ErrorLog(MessageName(table), FieldName(table, &entry), "parsing",
                         false);
     }
@@ -1653,7 +2167,8 @@
   return true;
 }
 
-const char* TcParser::MpString(PROTOBUF_TC_PARAM_DECL) {
+template <bool is_split>
+PROTOBUF_NOINLINE const char* TcParser::MpString(PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   const uint16_t type_card = entry.type_card;
   const uint16_t card = type_card & field_layout::kFcMask;
@@ -1676,17 +2191,18 @@
   const bool is_oneof = card == field_layout::kFcOneof;
   bool need_init = false;
   if (card == field_layout::kFcOptional) {
-    SetHas(table, entry, msg, hasbits);
+    SetHas(entry, msg);
   } else if (is_oneof) {
     need_init = ChangeOneof(table, entry, data.tag() >> 3, ctx, msg);
   }
 
   bool is_valid = false;
-  Arena* arena = ctx->data().arena;
+  void* const base = MaybeGetSplitBase(msg, is_split, table, ctx);
   switch (rep) {
     case field_layout::kRepAString: {
-      auto& field = RefAt<ArenaStringPtr>(msg, entry.offset);
+      auto& field = RefAt<ArenaStringPtr>(base, entry.offset);
       if (need_init) field.InitDefault();
+      Arena* arena = msg->GetArenaForAllocation();
       if (arena) {
         ptr = ctx->ReadArenaString(ptr, &field, arena);
       } else {
@@ -1709,7 +2225,21 @@
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::MpRepeatedString(PROTOBUF_TC_PARAM_DECL) {
+PROTOBUF_ALWAYS_INLINE const char* TcParser::ParseRepeatedStringOnce(
+    const char* ptr, Arena* arena, SerialArena* serial_arena, ParseContext* ctx,
+    RepeatedPtrField<std::string>& field) {
+  int size = ReadSize(&ptr);
+  if (PROTOBUF_PREDICT_FALSE(!ptr)) return {};
+  auto* str = Arena::Create<std::string>(arena);
+  field.AddAllocatedForParse(str);
+  ptr = ctx->ReadString(ptr, size, str);
+  if (PROTOBUF_PREDICT_FALSE(!ptr)) return {};
+  PROTOBUF_ASSUME(ptr != nullptr);
+  return ptr;
+}
+
+PROTOBUF_NOINLINE const char* TcParser::MpRepeatedString(
+    PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   const uint16_t type_card = entry.type_card;
   const uint32_t decoded_tag = data.tag();
@@ -1726,18 +2256,39 @@
       auto& field = RefAt<RepeatedPtrField<std::string>>(msg, entry.offset);
       const char* ptr2 = ptr;
       uint32_t next_tag;
-      do {
-        ptr = ptr2;
-        std::string* str = field.Add();
-        ptr = InlineGreedyStringParser(str, ptr, ctx);
-        if (PROTOBUF_PREDICT_FALSE(
-                ptr == nullptr ||
-                !MpVerifyUtf8(*str, table, entry, xform_val))) {
-          return Error(PROTOBUF_TC_PARAM_PASS);
-        }
-        if (!ctx->DataAvailable(ptr)) break;
-        ptr2 = ReadTag(ptr, &next_tag);
-      } while (next_tag == decoded_tag);
+
+      auto* arena = field.GetOwningArena();
+      SerialArena* serial_arena;
+      if (PROTOBUF_PREDICT_TRUE(
+              arena != nullptr &&
+              arena->impl_.GetSerialArenaFast(&serial_arena) &&
+              field.PrepareForParse())) {
+        do {
+          ptr = ptr2;
+          ptr = ParseRepeatedStringOnce(ptr, arena, serial_arena, ctx, field);
+          if (PROTOBUF_PREDICT_FALSE(ptr == nullptr ||
+                                     !MpVerifyUtf8(field[field.size() - 1],
+                                                   table, entry, xform_val))) {
+            return Error(PROTOBUF_TC_PARAM_PASS);
+          }
+          if (!ctx->DataAvailable(ptr)) break;
+          ptr2 = ReadTag(ptr, &next_tag);
+        } while (next_tag == decoded_tag);
+      } else {
+        do {
+          ptr = ptr2;
+          std::string* str = field.Add();
+          ptr = InlineGreedyStringParser(str, ptr, ctx);
+          if (PROTOBUF_PREDICT_FALSE(
+                  ptr == nullptr ||
+                  !MpVerifyUtf8(*str, table, entry, xform_val))) {
+            return Error(PROTOBUF_TC_PARAM_PASS);
+          }
+          if (!ctx->DataAvailable(ptr)) break;
+          ptr2 = ReadTag(ptr, &next_tag);
+        } while (next_tag == decoded_tag);
+      }
+
       break;
     }
 
@@ -1751,7 +2302,13 @@
   return ToParseLoop(PROTOBUF_TC_PARAM_PASS);
 }
 
-const char* TcParser::MpMessage(PROTOBUF_TC_PARAM_DECL) {
+const char* TcParser::MpLazyMessage(PROTOBUF_TC_PARAM_DECL) {
+  GOOGLE_LOG(FATAL) << "Unimplemented";
+  return nullptr;
+}
+
+template <bool is_split>
+PROTOBUF_NOINLINE const char* TcParser::MpMessage(PROTOBUF_TC_PARAM_DECL) {
   const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
   const uint16_t type_card = entry.type_card;
   const uint16_t card = type_card & field_layout::kFcMask;
@@ -1778,32 +2335,51 @@
         goto fallback;
       }
       break;
-    default: {
+    case field_layout::kRepLazy:
+      if (decoded_wiretype != WireFormatLite::WIRETYPE_LENGTH_DELIMITED) {
+        goto fallback;
+      }
+      PROTOBUF_MUSTTAIL return MpLazyMessage(PROTOBUF_TC_PARAM_PASS);
     fallback:
-      // Lazy and implicit weak fields are handled by generated code:
-      // TODO(b/210762816): support these.
-      PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS);
-    }
+      PROTOBUF_MUSTTAIL return MpFallback(PROTOBUF_TC_PARAM_PASS);
   }
 
   const bool is_oneof = card == field_layout::kFcOneof;
   bool need_init = false;
   if (card == field_layout::kFcOptional) {
-    SetHas(table, entry, msg, hasbits);
+    SetHas(entry, msg);
   } else if (is_oneof) {
     need_init = ChangeOneof(table, entry, data.tag() >> 3, ctx, msg);
   }
-  MessageLite*& field = RefAt<MessageLite*>(msg, entry.offset);
-  if (need_init || field == nullptr) {
-    const MessageLite* default_instance =
-        table->field_aux(&entry)->message_default;
-    field = default_instance->New(ctx->data().arena);
-  }
+
+  void* const base = MaybeGetSplitBase(msg, is_split, table, ctx);
   SyncHasbits(msg, hasbits, table);
-  if (is_group) {
-    return ctx->ParseGroup(field, ptr, decoded_tag);
+  MessageLite*& field = RefAt<MessageLite*>(base, entry.offset);
+  if ((type_card & field_layout::kTvMask) == field_layout::kTvTable) {
+    auto* inner_table = table->field_aux(&entry)->table;
+    if (need_init || field == nullptr) {
+      field = inner_table->default_instance->New(msg->GetArenaForAllocation());
+    }
+    if (is_group) {
+      return ctx->ParseGroup<TcParser>(field, ptr, decoded_tag, inner_table);
+    }
+    return ctx->ParseMessage<TcParser>(field, ptr, inner_table);
+  } else {
+    if (need_init || field == nullptr) {
+      const MessageLite* def;
+      if ((type_card & field_layout::kTvMask) == field_layout::kTvDefault) {
+        def = table->field_aux(&entry)->message_default();
+      } else {
+        GOOGLE_DCHECK_EQ(type_card & field_layout::kTvMask, +field_layout::kTvWeakPtr);
+        def = table->field_aux(&entry)->message_default_weak();
+      }
+      field = def->New(msg->GetArenaForAllocation());
+    }
+    if (is_group) {
+      return ctx->ParseGroup(field, ptr, decoded_tag);
+    }
+    return ctx->ParseMessage(field, ptr);
   }
-  return ctx->ParseMessage(field, ptr);
 }
 
 const char* TcParser::MpRepeatedMessage(PROTOBUF_TC_PARAM_DECL) {
@@ -1837,21 +2413,31 @@
   }
 
   SyncHasbits(msg, hasbits, table);
-  const MessageLite* default_instance =
-      table->field_aux(&entry)->message_default;
   auto& field = RefAt<RepeatedPtrFieldBase>(msg, entry.offset);
-  MessageLite* value =
-      field.Add<GenericTypeHandler<MessageLite>>(default_instance);
-  if (is_group) {
-    return ctx->ParseGroup(value, ptr, decoded_tag);
+  const auto aux = *table->field_aux(&entry);
+  if ((type_card & field_layout::kTvMask) == field_layout::kTvTable) {
+    auto* inner_table = aux.table;
+    auto& field = RefAt<RepeatedPtrFieldBase>(msg, entry.offset);
+    MessageLite* value = field.Add<GenericTypeHandler<MessageLite>>(
+        inner_table->default_instance);
+    if (is_group) {
+      return ctx->ParseGroup<TcParser>(value, ptr, decoded_tag, inner_table);
+    }
+    return ctx->ParseMessage<TcParser>(value, ptr, inner_table);
+  } else {
+    const MessageLite* def;
+    if ((type_card & field_layout::kTvMask) == field_layout::kTvDefault) {
+      def = aux.message_default();
+    } else {
+      GOOGLE_DCHECK_EQ(type_card & field_layout::kTvMask, +field_layout::kTvWeakPtr);
+      def = aux.message_default_weak();
+    }
+    MessageLite* value = field.Add<GenericTypeHandler<MessageLite>>(def);
+    if (is_group) {
+      return ctx->ParseGroup(value, ptr, decoded_tag);
+    }
+    return ctx->ParseMessage(value, ptr);
   }
-  return ctx->ParseMessage(value, ptr);
-}
-
-const char* TcParser::MpMap(PROTOBUF_TC_PARAM_DECL) {
-  const auto& entry = RefAt<FieldEntry>(table, data.entry_offset());
-  (void)entry;
-  PROTOBUF_MUSTTAIL return table->fallback(PROTOBUF_TC_PARAM_PASS);
 }
 
 }  // namespace internal
diff --git a/src/google/protobuf/generated_message_tctable_lite_test.cc b/src/google/protobuf/generated_message_tctable_lite_test.cc
index 4310803..56b0cea 100644
--- a/src/google/protobuf/generated_message_tctable_lite_test.cc
+++ b/src/google/protobuf/generated_message_tctable_lite_test.cc
@@ -30,10 +30,10 @@
 
 #include <cstddef>
 
-#include <google/protobuf/generated_message_tctable_impl.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/generated_message_tctable_impl.h"
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
+#include "google/protobuf/wire_format_lite.h"
 
 namespace google {
 namespace protobuf {
@@ -45,7 +45,7 @@
 using ::testing::Not;
 
 MATCHER_P3(IsEntryForFieldNum, table, field_num, field_numbers_table,
-           StrCat(negation ? "isn't " : "",
+           absl::StrCat(negation ? "isn't " : "",
                         "the field entry for field number ", field_num)) {
   if (arg == nullptr) {
     *result_listener << "which is nullptr";
@@ -80,7 +80,7 @@
       }};
   // clang-format on
   int table_field_numbers[] = {1, 2, 3};
-  table.field_lookup_table = {65535, 65535};
+  table.field_lookup_table = {{65535, 65535}};
 
   auto& entries = table.field_entries;
   EXPECT_THAT(&entries[0], IsEntryForFieldNum(&table, 1, table_field_numbers));
@@ -108,7 +108,7 @@
   // Calls the private `FieldName` function.
   template <size_t kFastTableSizeLog2, size_t kNumEntries, size_t kNumFieldAux,
             size_t kNameTableSize, size_t kFieldLookupTableSize>
-  static StringPiece FieldName(
+  static absl::string_view FieldName(
       const TcParseTable<kFastTableSizeLog2, kNumEntries, kNumFieldAux,
                          kNameTableSize, kFieldLookupTableSize>& table,
       const TcParseTableBase::FieldEntry* entry) {
@@ -118,7 +118,7 @@
   // Calls the private `MessageName` function.
   template <size_t kFastTableSizeLog2, size_t kNumEntries, size_t kNumFieldAux,
             size_t kNameTableSize, size_t kFieldLookupTableSize>
-  static StringPiece MessageName(
+  static absl::string_view MessageName(
       const TcParseTable<kFastTableSizeLog2, kNumEntries, kNumFieldAux,
                          kNameTableSize, kFieldLookupTableSize>& table) {
     return TcParser::MessageName(&table.header);
@@ -300,10 +300,10 @@
     EXPECT_THAT(entry,
                 IsEntryForFieldNum(&table, field_num, table_field_numbers));
 
-    StringPiece name = FieldName(table, entry);
+    absl::string_view name = FieldName(table, entry);
     EXPECT_EQ(name.length(), field_num);
     while (name[0] == '0') name.remove_prefix(1);  // strip leading zeores
-    EXPECT_EQ(name, StrCat(field_num));
+    EXPECT_EQ(name, absl::StrCat(field_num));
   }
   for (int field_num : {0, 4, 112, 500000000}) {
     EXPECT_THAT(FindFieldEntry(table, field_num), Eq(nullptr));
@@ -557,7 +557,7 @@
   for (int field_num :
        {1, 12, 31, 42, 57, 68, 79, 90, 101, 119, 249, 402, 412}) {
     auto* entry = FindFieldEntry(test_all_types_table, field_num);
-    StringPiece name = FieldName(test_all_types_table, entry);
+    absl::string_view name = FieldName(test_all_types_table, entry);
     switch (field_num) {
       case 1:
         EXPECT_THAT(name, Eq("optional_int32"));
diff --git a/src/google/protobuf/generated_message_util.cc b/src/google/protobuf/generated_message_util.cc
index cad12a3..4dd5ccb 100644
--- a/src/google/protobuf/generated_message_util.cc
+++ b/src/google/protobuf/generated_message_util.cc
@@ -32,23 +32,23 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/generated_message_util.h>
+#include "google/protobuf/generated_message_util.h"
 
 #include <atomic>
 #include <limits>
 #include <vector>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must be included last
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -406,4 +406,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 71d15cd..42c7db7 100644
--- a/src/google/protobuf/generated_message_util.h
+++ b/src/google/protobuf/generated_message_util.h
@@ -43,22 +43,24 @@
 #include <atomic>
 #include <climits>
 #include <string>
+#include <type_traits>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/once.h>  // Add direct dep on port for pb.cc
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/any.h>
-#include <google/protobuf/has_bits.h>
-#include <google/protobuf/implicit_weak_message.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/casts.h>
+#include "google/protobuf/stubs/common.h"
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/any.h"
+#include "google/protobuf/has_bits.h"
+#include "google/protobuf/implicit_weak_message.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/wire_format_lite.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -76,15 +78,6 @@
 
 namespace internal {
 
-template <typename To, typename From>
-inline To DownCast(From* f) {
-  return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
-}
-template <typename To, typename From>
-inline To DownCast(From& f) {
-  return PROTOBUF_NAMESPACE_ID::internal::down_cast<To>(f);
-}
-
 
 // This fastpath inlines a single branch instead of having to make the
 // InitProtobufDefaults function call.
@@ -185,13 +178,58 @@
 
 // Hide atomic from the public header and allow easy change to regular int
 // on platforms where the atomic might have a perf impact.
+//
+// CachedSize is like std::atomic<int> but with some important changes:
+//
+// 1) CachedSize uses Get / Set rather than load / store.
+// 2) CachedSize always uses relaxed ordering.
+// 3) CachedSize is assignable and copy-constructible.
+// 4) CachedSize has a constexpr default constructor, and a constexpr
+//    constructor that takes an int argument.
+// 5) If the compiler supports the __atomic_load_n / __atomic_store_n builtins,
+//    then CachedSize is trivially copyable.
+//
+// Developed at https://godbolt.org/z/vYcx7zYs1 ; supports gcc, clang, MSVC.
 class PROTOBUF_EXPORT CachedSize {
+ private:
+  using Scalar = int;
+
  public:
-  int Get() const { return size_.load(std::memory_order_relaxed); }
-  void Set(int size) { size_.store(size, std::memory_order_relaxed); }
+  constexpr CachedSize() noexcept : atom_(Scalar{}) {}
+  // NOLINTNEXTLINE(google-explicit-constructor)
+  constexpr CachedSize(Scalar desired) noexcept : atom_(desired) {}
+#if PROTOBUF_BUILTIN_ATOMIC
+  constexpr CachedSize(const CachedSize& other) = default;
+
+  Scalar Get() const noexcept {
+    return __atomic_load_n(&atom_, __ATOMIC_RELAXED);
+  }
+
+  void Set(Scalar desired) noexcept {
+    __atomic_store_n(&atom_, desired, __ATOMIC_RELAXED);
+  }
+#else
+  CachedSize(const CachedSize& other) noexcept : atom_(other.Get()) {}
+  CachedSize& operator=(const CachedSize& other) noexcept {
+    Set(other.Get());
+    return *this;
+  }
+
+  Scalar Get() const noexcept {  //
+    return atom_.load(std::memory_order_relaxed);
+  }
+
+  void Set(Scalar desired) noexcept {
+    atom_.store(desired, std::memory_order_relaxed);
+  }
+#endif
 
  private:
-  std::atomic<int> size_{0};
+#if PROTOBUF_BUILTIN_ATOMIC
+  Scalar atom_;
+#else
+  std::atomic<Scalar> atom_;
+#endif
 };
 
 PROTOBUF_EXPORT void DestroyMessage(const void* message);
@@ -209,6 +247,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_GENERATED_MESSAGE_UTIL_H__
diff --git a/src/google/protobuf/has_bits.h b/src/google/protobuf/has_bits.h
index f8a4587..b90c450 100644
--- a/src/google/protobuf/has_bits.h
+++ b/src/google/protobuf/has_bits.h
@@ -31,11 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_HAS_BITS_H__
 #define GOOGLE_PROTOBUF_HAS_BITS_H__
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/port.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -112,6 +112,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_HAS_BITS_H__
diff --git a/src/google/protobuf/implicit_weak_message.cc b/src/google/protobuf/implicit_weak_message.cc
index 27ed6b6..5fac836 100644
--- a/src/google/protobuf/implicit_weak_message.cc
+++ b/src/google/protobuf/implicit_weak_message.cc
@@ -28,14 +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.
 
-#include <google/protobuf/implicit_weak_message.h>
+#include "google/protobuf/implicit_weak_message.h"
 
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 PROTOBUF_PRAGMA_INIT_SEG
 
@@ -69,4 +69,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 b894ab4..979c897 100644
--- a/src/google/protobuf/implicit_weak_message.h
+++ b/src/google/protobuf/implicit_weak_message.h
@@ -33,17 +33,17 @@
 
 #include <string>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/repeated_field.h>
+#include "google/protobuf/arena.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/repeated_field.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 // This file is logically internal-only and should only be used by protobuf
 // generated code.
@@ -62,6 +62,8 @@
       : data_(nullptr) {}
   explicit ImplicitWeakMessage(Arena* arena)
       : MessageLite(arena), data_(new std::string) {}
+  ImplicitWeakMessage(const ImplicitWeakMessage&) = delete;
+  ImplicitWeakMessage& operator=(const ImplicitWeakMessage&) = delete;
 
   ~ImplicitWeakMessage() override {
     // data_ will be null in the default instance, but we can safely call delete
@@ -115,7 +117,6 @@
   // the default instance can be constant-initialized. In the const methods, we
   // have to handle the possibility of data_ being null.
   std::string* data_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ImplicitWeakMessage);
 };
 
 struct ImplicitWeakMessageDefaultType;
@@ -208,6 +209,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IMPLICIT_WEAK_MESSAGE_H__
diff --git a/src/google/protobuf/inlined_string_field.cc b/src/google/protobuf/inlined_string_field.cc
index 0c3e476..34b73d2 100644
--- a/src/google/protobuf/inlined_string_field.cc
+++ b/src/google/protobuf/inlined_string_field.cc
@@ -28,16 +28,18 @@
 // (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/inlined_string_field.h>
+#include "google/protobuf/inlined_string_field.h"
 
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/parse_context.h>
+#include "google/protobuf/arena.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
+
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
diff --git a/src/google/protobuf/inlined_string_field.h b/src/google/protobuf/inlined_string_field.h
index 79e37d4..fe52a4d 100644
--- a/src/google/protobuf/inlined_string_field.h
+++ b/src/google/protobuf/inlined_string_field.h
@@ -34,15 +34,15 @@
 #include <string>
 #include <utility>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/port.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/message_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -130,7 +130,7 @@
   //   `donated == ((donating_states & ~mask) != 0)`
   //
   // This method never changes the `donating_states`.
-  void Set(ConstStringParam value, Arena* arena, bool donated,
+  void Set(absl::string_view value, Arena* arena, bool donated,
            uint32_t* donating_states, uint32_t mask, MessageLite* msg);
 
   // Rvalue Set. If this field is donated, this method will undonate this field
@@ -149,7 +149,7 @@
            ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
            uint32_t mask, MessageLite* msg);
 
-  void SetBytes(ConstStringParam value, Arena* arena, bool donated,
+  void SetBytes(absl::string_view value, Arena* arena, bool donated,
                 uint32_t* donating_states, uint32_t mask, MessageLite* msg);
 
   void SetBytes(std::string&& value, Arena* arena, bool donated,
@@ -167,7 +167,7 @@
                 ::google::protobuf::Arena* arena, bool donated, uint32_t* donating_states,
                 uint32_t mask, MessageLite* msg);
 
-  PROTOBUF_NDEBUG_INLINE void SetNoArena(StringPiece value);
+  PROTOBUF_NDEBUG_INLINE void SetNoArena(absl::string_view value);
   PROTOBUF_NDEBUG_INLINE void SetNoArena(std::string&& value);
 
   // Basic accessors.
@@ -228,7 +228,7 @@
     return Release();
   }
 
-  void Set(const std::string*, ConstStringParam value, Arena* arena,
+  void Set(const std::string*, absl::string_view value, Arena* arena,
            bool donated, uint32_t* donating_states, uint32_t mask,
            MessageLite* msg) {
     Set(value, arena, donated, donating_states, mask, msg);
@@ -261,7 +261,7 @@
     Set(const_string_ref, arena, donated, donating_states, mask, msg);
   }
 
-  void SetBytes(const std::string*, ConstStringParam value, Arena* arena,
+  void SetBytes(const std::string*, absl::string_view value, Arena* arena,
                 bool donated, uint32_t* donating_states, uint32_t mask,
                 MessageLite* msg) {
     Set(value, arena, donated, donating_states, mask, msg);
@@ -297,7 +297,7 @@
              msg);
   }
 
-  void SetNoArena(const std::string*, StringPiece value) {
+  void SetNoArena(const std::string*, absl::string_view value) {
     SetNoArena(value);
   }
   void SetNoArena(const std::string*, std::string&& value) {
@@ -413,7 +413,7 @@
   this->~InlinedStringField();
 }
 
-inline void InlinedStringField::SetNoArena(StringPiece value) {
+inline void InlinedStringField::SetNoArena(absl::string_view value) {
   get_mutable()->assign(value.data(), value.length());
 }
 
@@ -427,7 +427,7 @@
     MessageLite* lhs_msg,  //
     InlinedStringField* rhs, Arena* rhs_arena, bool rhs_arena_dtor_registered,
     MessageLite* rhs_msg) {
-#if GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
+#ifdef GOOGLE_PROTOBUF_INTERNAL_DONATE_STEAL_INLINE
   lhs->get_mutable()->swap(*rhs->get_mutable());
   if (!lhs_arena_dtor_registered && rhs_arena_dtor_registered) {
     lhs_msg->OnDemandRegisterArenaDtor(lhs_arena);
@@ -445,7 +445,7 @@
 #endif
 }
 
-inline void InlinedStringField::Set(ConstStringParam value, Arena* arena,
+inline void InlinedStringField::Set(absl::string_view value, Arena* arena,
                                     bool donated, uint32_t* /*donating_states*/,
                                     uint32_t /*mask*/, MessageLite* /*msg*/) {
   (void)arena;
@@ -456,17 +456,17 @@
 inline void InlinedStringField::Set(const char* str, ::google::protobuf::Arena* arena,
                                     bool donated, uint32_t* donating_states,
                                     uint32_t mask, MessageLite* msg) {
-  Set(ConstStringParam(str), arena, donated, donating_states, mask, msg);
+  Set(absl::string_view(str), arena, donated, donating_states, mask, msg);
 }
 
 inline void InlinedStringField::Set(const char* str, size_t size,
                                     ::google::protobuf::Arena* arena, bool donated,
                                     uint32_t* donating_states, uint32_t mask,
                                     MessageLite* msg) {
-  Set(ConstStringParam{str, size}, arena, donated, donating_states, mask, msg);
+  Set(absl::string_view{str, size}, arena, donated, donating_states, mask, msg);
 }
 
-inline void InlinedStringField::SetBytes(ConstStringParam value, Arena* arena,
+inline void InlinedStringField::SetBytes(absl::string_view value, Arena* arena,
                                          bool donated,
                                          uint32_t* donating_states,
                                          uint32_t mask, MessageLite* msg) {
@@ -527,6 +527,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_INLINED_STRING_FIELD_H__
diff --git a/src/google/protobuf/inlined_string_field_unittest.cc b/src/google/protobuf/inlined_string_field_unittest.cc
index 9efe6e9..bba2289 100644
--- a/src/google/protobuf/inlined_string_field_unittest.cc
+++ b/src/google/protobuf/inlined_string_field_unittest.cc
@@ -28,7 +28,7 @@
 // (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/inlined_string_field.h>
+#include "google/protobuf/inlined_string_field.h"
 
 #include <algorithm>
 #include <cstdlib>
@@ -38,13 +38,14 @@
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#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/arenastring.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arenastring.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/message.h"
 
 
 namespace google {
diff --git a/src/google/protobuf/io/BUILD.bazel b/src/google/protobuf/io/BUILD.bazel
new file mode 100644
index 0000000..88f1ee1
--- /dev/null
+++ b/src/google/protobuf/io/BUILD.bazel
@@ -0,0 +1,187 @@
+# Protobuf IO library.
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+package(
+    default_visibility = ["//visibility:public"],
+)
+
+cc_library(
+    name = "io",
+    srcs = [
+        "coded_stream.cc",
+        "zero_copy_stream.cc",
+        "zero_copy_stream_impl.cc",
+        "zero_copy_stream_impl_lite.cc",
+    ],
+    hdrs = [
+        "coded_stream.h",
+        "zero_copy_stream.h",
+        "zero_copy_stream_impl.h",
+        "zero_copy_stream_impl_lite.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/io",
+    deps = [
+        ":io_win32",
+        "//src/google/protobuf:arena",
+        "//src/google/protobuf/stubs:lite",
+        "@com_google_absl//absl/strings:internal",
+    ],
+)
+
+cc_library(
+    name = "zero_copy_sink",
+    srcs = ["zero_copy_sink.cc"],
+    hdrs = ["zero_copy_sink.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":io",
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_test(
+    name = "zero_copy_sink_test",
+    srcs = ["zero_copy_sink_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":zero_copy_sink",
+        "//src/google/protobuf/stubs",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "printer",
+    srcs = ["printer.cc"],
+    hdrs = ["printer.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/io",
+    deps = [
+        ":zero_copy_sink",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/cleanup",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/functional:function_ref",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_absl//absl/types:optional",
+        "@com_google_absl//absl/types:span",
+        "@com_google_absl//absl/types:variant",
+    ],
+)
+
+cc_library(
+    name = "tokenizer",
+    srcs = [
+        "strtod.cc",
+        "tokenizer.cc",
+    ],
+    hdrs = [
+        "strtod.h",
+        "tokenizer.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/io",
+    deps = [
+        ":io",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+    ],
+)
+
+cc_library(
+    name = "gzip_stream",
+    srcs = ["gzip_stream.cc"],
+    hdrs = ["gzip_stream.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/io",
+    deps = [
+        ":io",
+        "//src/google/protobuf/stubs",
+    ] + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": ["@zlib//:zlib"],
+    }),
+)
+
+cc_library(
+    name = "io_win32",
+    srcs = ["io_win32.cc"],
+    hdrs = ["io_win32.h"],
+    copts = COPTS,
+    include_prefix = "google/protobuf/io",
+    visibility = ["//pkg:__pkg__"],
+    deps = [
+        "//src/google/protobuf:arena",
+        "//src/google/protobuf/stubs:lite",
+    ],
+)
+
+cc_test(
+    name = "io_test",
+    srcs = [
+        "coded_stream_unittest.cc",
+        "printer_death_test.cc",
+        "printer_unittest.cc",
+        "tokenizer_unittest.cc",
+        "zero_copy_stream_unittest.cc",
+    ],
+    copts = COPTS,
+    data = [
+        "//src/google/protobuf:testdata",
+    ],
+    deps = [
+        ":gzip_stream",
+        ":io",
+        "//:protobuf",
+        "//src/google/protobuf:test_util2",
+        "//src/google/protobuf/testing",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "win32_test",
+    srcs = ["io_win32_unittest.cc"],
+    tags = [
+        "manual",
+        "windows",
+    ],
+    deps = [
+        "//:protobuf_lite",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//pkg:__pkg__"],
+)
diff --git a/src/google/protobuf/io/coded_stream.cc b/src/google/protobuf/io/coded_stream.cc
index 487e1b8..b88823f 100644
--- a/src/google/protobuf/io/coded_stream.cc
+++ b/src/google/protobuf/io/coded_stream.cc
@@ -38,7 +38,7 @@
 // will not cross the end of the buffer, since we can avoid a lot
 // of branching in this case.
 
-#include <google/protobuf/io/coded_stream.h>
+#include "google/protobuf/io/coded_stream.h"
 
 #include <limits.h>
 
@@ -46,16 +46,18 @@
 #include <cstring>
 #include <utility>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/port.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -260,7 +262,7 @@
   if (size < 0) return false;  // security: size is often user-supplied
 
   if (BufferSize() >= size) {
-    STLStringResizeUninitialized(buffer, size);
+    absl::strings_internal::STLStringResizeUninitialized(buffer, size);
     std::pair<char*, bool> z = as_string_data(buffer);
     if (z.second) {
       // Oddly enough, memcpy() requires its first two args to be non-NULL even
@@ -940,28 +942,8 @@
   return WriteStringToArray(str, target);
 }
 
-uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLineHelper(uint32_t value,
-                                                              uint8_t* target) {
-  GOOGLE_DCHECK_GE(value, 0x80);
-  target[0] |= static_cast<uint8_t>(0x80);
-  value >>= 7;
-  target[1] = static_cast<uint8_t>(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_t>(0x80);
-    value >>= 7;
-    *target = static_cast<uint8_t>(value);
-    ++target;
-  } while (value >= 0x80);
-  return target;
-}
-
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 c8fc994..6644425 100644
--- a/src/google/protobuf/io/coded_stream.h
+++ b/src/google/protobuf/io/coded_stream.h
@@ -109,7 +109,6 @@
 #ifndef GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
 #define GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
 
-
 #include <assert.h>
 
 #include <atomic>
@@ -128,15 +127,15 @@
 #endif
 
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/port.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/numeric/bits.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/port.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -178,6 +177,8 @@
   // faster than using an ArrayInputStream.  PushLimit(size) is implied by
   // this constructor.
   explicit CodedInputStream(const uint8_t* buffer, int size);
+  CodedInputStream(const CodedInputStream&) = delete;
+  CodedInputStream& operator=(const CodedInputStream&) = delete;
 
   // Destroy the CodedInputStream and position the underlying
   // ZeroCopyInputStream at the first unread byte.  If an error occurred while
@@ -518,8 +519,6 @@
   MessageFactory* GetExtensionFactory();
 
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedInputStream);
-
   const uint8_t* buffer_;
   const uint8_t* buffer_end_;  // pointer to the end of the buffer.
   ZeroCopyInputStream* input_;
@@ -681,7 +680,7 @@
     if (PROTOBUF_PREDICT_FALSE(end_ - ptr < size)) {
       return WriteRawFallback(data, size, ptr);
     }
-    std::memcpy(ptr, data, size);
+    std::memcpy(ptr, data, static_cast<unsigned int>(size));
     return ptr + size;
   }
   // Writes the buffer specified by data, size to the stream. Possibly by
@@ -899,25 +898,12 @@
   PROTOBUF_ALWAYS_INLINE static uint8_t* UnsafeVarint(T value, uint8_t* ptr) {
     static_assert(std::is_unsigned<T>::value,
                   "Varint serialization must be unsigned");
-    ptr[0] = static_cast<uint8_t>(value);
-    if (value < 0x80) {
-      return ptr + 1;
-    }
-    // Turn on continuation bit in the byte we just wrote.
-    ptr[0] |= static_cast<uint8_t>(0x80);
-    value >>= 7;
-    ptr[1] = static_cast<uint8_t>(value);
-    if (value < 0x80) {
-      return ptr + 2;
-    }
-    ptr += 2;
-    do {
-      // Turn on continuation bit in the byte we just wrote.
-      ptr[-1] |= static_cast<uint8_t>(0x80);
+    while (PROTOBUF_PREDICT_FALSE(value >= 0x80)) {
+      *ptr = static_cast<uint8_t>(value | 0x80);
       value >>= 7;
-      *ptr = static_cast<uint8_t>(value);
       ++ptr;
-    } while (value >= 0x80);
+    }
+    *ptr++ = static_cast<uint8_t>(value);
     return ptr;
   }
 
@@ -1061,6 +1047,8 @@
   template <class Stream, class = typename std::enable_if<std::is_base_of<
                               ZeroCopyOutputStream, Stream>::value>::type>
   CodedOutputStream(Stream* stream, bool eager_init);
+  CodedOutputStream(const CodedOutputStream&) = delete;
+  CodedOutputStream& operator=(const CodedOutputStream&) = delete;
 
   // Destroy the CodedOutputStream and position the underlying
   // ZeroCopyOutputStream immediately after the last byte written.
@@ -1158,10 +1146,12 @@
   void WriteVarint32(uint32_t value);
   // Like WriteVarint32()  but writing directly to the target array.
   static uint8_t* WriteVarint32ToArray(uint32_t value, uint8_t* target);
-  // Like WriteVarint32()  but writing directly to the target array, and with
-  // the less common-case paths being out of line rather than inlined.
+  // Like WriteVarint32ToArray()
+  PROTOBUF_DEPRECATED_MSG("Please use WriteVarint32ToArray() instead")
   static uint8_t* WriteVarint32ToArrayOutOfLine(uint32_t value,
-                                                uint8_t* target);
+                                                uint8_t* target) {
+    return WriteVarint32ToArray(value, target);
+  }
   // Write an unsigned integer with Varint encoding.
   void WriteVarint64(uint64_t value);
   // Like WriteVarint64()  but writing directly to the target array.
@@ -1285,10 +1275,6 @@
   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_t* WriteVarint32ToArrayOutOfLineHelper(uint32_t value,
-                                                      uint8_t* target);
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CodedOutputStream);
 };
 
 // inline methods ====================================================
@@ -1647,16 +1633,6 @@
   return EpsCopyOutputStream::UnsafeVarint(value, target);
 }
 
-inline uint8_t* CodedOutputStream::WriteVarint32ToArrayOutOfLine(
-    uint32_t value, uint8_t* target) {
-  target[0] = static_cast<uint8_t>(value);
-  if (value < 0x80) {
-    return target + 1;
-  } else {
-    return WriteVarint32ToArrayOutOfLineHelper(value, target);
-  }
-}
-
 inline uint8_t* CodedOutputStream::WriteVarint64ToArray(uint64_t value,
                                                         uint8_t* target) {
   return EpsCopyOutputStream::UnsafeVarint(value, target);
@@ -1729,15 +1705,16 @@
   // This computes value == 0 ? 1 : floor(log2(value)) / 7 + 1
   // Use an explicit multiplication to implement the divide of
   // a number in the 1..31 range.
-  // Explicit OR 0x1 to avoid calling Bits::Log2FloorNonZero(0), which is
-  // undefined.
-  uint32_t log2value = Bits::Log2FloorNonZero(value | 0x1);
+  //
+  // Explicit OR 0x1 to avoid calling absl::bit_width(0), which is
+  // requires a branch to check for on many platforms.
+  uint32_t log2value = absl::bit_width(value | 0x1) - 1;
   return static_cast<size_t>((log2value * 9 + 73) / 64);
 }
 
 inline size_t CodedOutputStream::VarintSize32PlusOne(uint32_t value) {
   // Same as above, but one more.
-  uint32_t log2value = Bits::Log2FloorNonZero(value | 0x1);
+  uint32_t log2value = absl::bit_width(value | 0x1) - 1;
   return static_cast<size_t>((log2value * 9 + 73 + 64) / 64);
 }
 
@@ -1745,15 +1722,16 @@
   // This computes value == 0 ? 1 : floor(log2(value)) / 7 + 1
   // Use an explicit multiplication to implement the divide of
   // a number in the 1..63 range.
-  // Explicit OR 0x1 to avoid calling Bits::Log2FloorNonZero(0), which is
-  // undefined.
-  uint32_t log2value = Bits::Log2FloorNonZero64(value | 0x1);
+  //
+  // Explicit OR 0x1 to avoid calling absl::bit_width(0), which is
+  // requires a branch to check for on many platforms.
+  uint32_t log2value = absl::bit_width(value | 0x1) - 1;
   return static_cast<size_t>((log2value * 9 + 73) / 64);
 }
 
 inline size_t CodedOutputStream::VarintSize64PlusOne(uint64_t value) {
   // Same as above, but one more.
-  uint32_t log2value = Bits::Log2FloorNonZero64(value | 0x1);
+  uint32_t log2value = absl::bit_width(value | 0x1) - 1;
   return static_cast<size_t>((log2value * 9 + 73 + 64) / 64);
 }
 
@@ -1777,7 +1755,7 @@
 
 inline uint8_t* CodedOutputStream::WriteRawToArray(const void* data, int size,
                                                    uint8_t* target) {
-  memcpy(target, data, size);
+  memcpy(target, data, static_cast<unsigned int>(size));
   return target + size;
 }
 
@@ -1794,6 +1772,6 @@
 #pragma runtime_checks("c", restore)
 #endif  // _MSC_VER && !defined(__INTEL_COMPILER)
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IO_CODED_STREAM_H__
diff --git a/src/google/protobuf/io/coded_stream_unittest.cc b/src/google/protobuf/io/coded_stream_unittest.cc
index b32bf45..ae55382 100644
--- a/src/google/protobuf/io/coded_stream_unittest.cc
+++ b/src/google/protobuf/io/coded_stream_unittest.cc
@@ -34,7 +34,7 @@
 //
 // This file contains tests and benchmarks.
 
-#include <google/protobuf/io/coded_stream.h>
+#include "google/protobuf/io/coded_stream.h"
 
 #include <limits.h>
 
@@ -43,17 +43,20 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/casts.h>
+#include "absl/base/casts.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+
+#include "google/protobuf/testing/googletest.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
-
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -69,7 +72,7 @@
 // run multiple times, once for each item in some input array.  TEST_1D
 // tests all cases in a single input array.  TEST_2D tests all
 // combinations of cases from two arrays.  The arrays must be statically
-// defined such that the GOOGLE_ARRAYSIZE() macro works on them.  Example:
+// defined such that the ABSL_ARRAYSIZE() macro works on them.  Example:
 //
 // int kCases[] = {1, 2, 3, 4}
 // TEST_1D(MyFixture, MyTest, kCases) {
@@ -92,7 +95,7 @@
   };                                                              \
                                                                   \
   TEST_F(FIXTURE##_##NAME##_DD, NAME) {                           \
-    for (size_t i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) {               \
+    for (size_t i = 0; i < ABSL_ARRAYSIZE(CASES); i++) {          \
       SCOPED_TRACE(testing::Message()                             \
                    << #CASES " case #" << i << ": " << CASES[i]); \
       DoSingleCase(CASES[i]);                                     \
@@ -111,8 +114,8 @@
   };                                                                        \
                                                                             \
   TEST_F(FIXTURE##_##NAME##_DD, NAME) {                                     \
-    for (size_t i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) {                        \
-      for (size_t j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) {                      \
+    for (size_t i = 0; i < ABSL_ARRAYSIZE(CASES1); i++) {                   \
+      for (size_t j = 0; j < ABSL_ARRAYSIZE(CASES2); j++) {                 \
         SCOPED_TRACE(testing::Message()                                     \
                      << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \
                      << #CASES2 " case #" << j << ": " << CASES2[j]);       \
@@ -134,7 +137,7 @@
   static uint8_t buffer_[kBufferSize];
 };
 
-uint8_t CodedStreamTest::buffer_[CodedStreamTest::kBufferSize];
+uint8_t CodedStreamTest::buffer_[CodedStreamTest::kBufferSize] = {};
 
 // We test each operation over a variety of block sizes to insure that
 // we test cases where reads or writes cross buffer boundaries, cases
@@ -725,7 +728,7 @@
 TEST_F(CodedStreamTest, ReadStringImpossiblyLargeFromStringOnStack) {
   // Same test as above, except directly use a buffer. This used to cause
   // crashes while the above did not.
-  uint8_t buffer[8];
+  uint8_t buffer[8] = {};
   CodedInputStream coded_input(buffer, 8);
   std::string str;
   EXPECT_FALSE(coded_input.ReadString(&str, 1 << 30));
@@ -1316,7 +1319,7 @@
   int backup_amount_;
 
  private:
-  char buffer_[1024];
+  char buffer_[1024] = {};
   int64_t buffer_count_;
 };
 
@@ -1345,4 +1348,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 a5284b3..d9d44a0 100644
--- a/src/google/protobuf/io/gzip_stream.cc
+++ b/src/google/protobuf/io/gzip_stream.cc
@@ -35,11 +35,11 @@
 
 
 #if HAVE_ZLIB
-#include <google/protobuf/io/gzip_stream.h>
-#include <google/protobuf/port.h>
+#include "google/protobuf/io/gzip_stream.h"
+#include "google/protobuf/port.h"
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/io/gzip_stream.h b/src/google/protobuf/io/gzip_stream.h
index 4cf71b6..eec111c 100644
--- a/src/google/protobuf/io/gzip_stream.h
+++ b/src/google/protobuf/io/gzip_stream.h
@@ -43,14 +43,13 @@
 #ifndef GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
 #define GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
 
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/port.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/port.h"
 #include "zlib.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -75,7 +74,9 @@
   // buffer_size and format may be -1 for default of 64kB and GZIP format
   explicit GzipInputStream(ZeroCopyInputStream* sub_stream,
                            Format format = AUTO, int buffer_size = -1);
-  virtual ~GzipInputStream();
+  GzipInputStream(const GzipInputStream&) = delete;
+  GzipInputStream& operator=(const GzipInputStream&) = delete;
+  ~GzipInputStream() override;
 
   // Return last error message or NULL if no error.
   inline const char* ZlibErrorMessage() const { return zcontext_.msg; }
@@ -102,8 +103,6 @@
 
   int Inflate(int flush);
   void DoNextOutput(const void** data, int* size);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipInputStream);
 };
 
 class PROTOBUF_EXPORT GzipOutputStream PROTOBUF_FUTURE_FINAL
@@ -142,8 +141,10 @@
 
   // Create a GzipOutputStream with the given options.
   GzipOutputStream(ZeroCopyOutputStream* sub_stream, const Options& options);
+  GzipOutputStream(const GzipOutputStream&) = delete;
+  GzipOutputStream& operator=(const GzipOutputStream&) = delete;
 
-  virtual ~GzipOutputStream();
+  ~GzipOutputStream() override;
 
   // Return last error message or NULL if no error.
   inline const char* ZlibErrorMessage() const { return zcontext_.msg; }
@@ -192,14 +193,12 @@
   // Takes zlib flush mode.
   // Returns zlib error code.
   int Deflate(int flush);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GzipOutputStream);
 };
 
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IO_GZIP_STREAM_H__
diff --git a/src/google/protobuf/io/io_win32.cc b/src/google/protobuf/io/io_win32.cc
index 4e81908..684c567 100644
--- a/src/google/protobuf/io/io_win32.cc
+++ b/src/google/protobuf/io/io_win32.cc
@@ -49,7 +49,7 @@
 // debug failing tests if that's caused by the long path support.
 #define SUPPORT_LONGPATHS
 
-#include <google/protobuf/io/io_win32.h>
+#include "google/protobuf/io/io_win32.h"
 
 #include <ctype.h>
 #include <direct.h>
diff --git a/src/google/protobuf/io/io_win32.h b/src/google/protobuf/io/io_win32.h
index a72b4ea..370bcaa 100644
--- a/src/google/protobuf/io/io_win32.h
+++ b/src/google/protobuf/io/io_win32.h
@@ -52,10 +52,10 @@
 #include <functional>
 #include <string>
 
-#include <google/protobuf/port.h>
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 // Compilers on Windows other than MSVC (e.g. Cygwin, MinGW32) define the
 // following functions already, except for mkdir.
@@ -134,7 +134,7 @@
 #define STDOUT_FILENO 1
 #endif
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // defined(_WIN32)
 
diff --git a/src/google/protobuf/io/io_win32_unittest.cc b/src/google/protobuf/io/io_win32_unittest.cc
index e8f378f..d4e50b8 100644
--- a/src/google/protobuf/io/io_win32_unittest.cc
+++ b/src/google/protobuf/io/io_win32_unittest.cc
@@ -40,7 +40,7 @@
 #if defined(_WIN32)
 
 #define WIN32_LEAN_AND_MEAN
-#include <google/protobuf/io/io_win32.h>
+#include "google/protobuf/io/io_win32.h"
 
 #include <errno.h>
 #include <fcntl.h>
diff --git a/src/google/protobuf/io/printer.cc b/src/google/protobuf/io/printer.cc
index 47bd00b..289f5bf 100644
--- a/src/google/protobuf/io/printer.cc
+++ b/src/google/protobuf/io/printer.cc
@@ -32,195 +32,230 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/io/printer.h"
 
-#include <cctype>
+#include <stdlib.h>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/zero_copy_stream.h>
+#include <cstddef>
+#include <functional>
+#include <map>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+#include "absl/types/variant.h"
 
 namespace google {
 namespace protobuf {
 namespace io {
-
-Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter)
-    : variable_delimiter_(variable_delimiter),
-      output_(output),
-      buffer_(NULL),
-      buffer_size_(0),
-      offset_(0),
-      at_start_of_line_(true),
-      failed_(false),
-      annotation_collector_(NULL) {}
-
-Printer::Printer(ZeroCopyOutputStream* output, char variable_delimiter,
-                 AnnotationCollector* annotation_collector)
-    : variable_delimiter_(variable_delimiter),
-      output_(output),
-      buffer_(NULL),
-      buffer_size_(0),
-      offset_(0),
-      at_start_of_line_(true),
-      failed_(false),
-      annotation_collector_(annotation_collector) {}
-
-Printer::~Printer() {
-  // Only BackUp() if we invoked Next() at least once, and we have never failed.
-  // Note that we always call `Backup`, i.e. we call BackUp(0) as some output
-  // streams have buffered output, and BackUp() serves as a flush event in such
-  // implementations.
-  if (buffer_ != nullptr && !failed_) {
-    output_->BackUp(buffer_size_);
+namespace {
+// Returns the number of spaces of the first non empty line.
+size_t RawStringIndentLen(absl::string_view format) {
+  // We are processing a call that looks like
+  //
+  // p->Emit(R"cc(
+  //   class Foo {
+  //     int x, y, z;
+  //   };
+  // )cc");
+  //
+  // or
+  //
+  // p->Emit(R"cc(
+  //
+  //   class Foo {
+  //     int x, y, z;
+  //   };
+  // )cc");
+  //
+  // To compute the indent, we need to discard all leading newlines, then
+  // count all spaces until we reach a non-space; this run of spaces is
+  // stripped off at the start of each line.
+  size_t len = 0;
+  while (absl::ConsumePrefix(&format, "\n")) {
   }
+
+  while (absl::ConsumePrefix(&format, " ")) {
+    ++len;
+  }
+
+  return len;
 }
 
-bool Printer::GetSubstitutionRange(const char* varname,
-                                   std::pair<size_t, size_t>* range) {
-  std::map<std::string, std::pair<size_t, size_t> >::const_iterator iter =
-      substitutions_.find(varname);
-  if (iter == substitutions_.end()) {
-    GOOGLE_LOG(DFATAL) << " Undefined variable in annotation: " << varname;
-    return false;
+// Returns the amount of additional indenting past `raw_string_indent_len`.
+size_t ConsumeIndentForLine(size_t raw_string_indent_len,
+                            absl::string_view& format) {
+  size_t total_indent = 0;
+  while (absl::ConsumePrefix(&format, " ")) {
+    ++total_indent;
   }
-  if (iter->second.first > iter->second.second) {
-    GOOGLE_LOG(DFATAL) << " Variable used for annotation used multiple times: "
-                << varname;
-    return false;
-  }
-  *range = iter->second;
-  return true;
-}
-
-void Printer::Annotate(const char* begin_varname, const char* end_varname,
-                       const std::string& file_path,
-                       const std::vector<int>& path) {
-  if (annotation_collector_ == NULL) {
-    // Can't generate signatures with this Printer.
-    return;
-  }
-  std::pair<size_t, size_t> begin, end;
-  if (!GetSubstitutionRange(begin_varname, &begin) ||
-      !GetSubstitutionRange(end_varname, &end)) {
-    return;
-  }
-  if (begin.first > end.second) {
-    GOOGLE_LOG(DFATAL) << "  Annotation has negative length from " << begin_varname
-                << " to " << end_varname;
+  if (total_indent < raw_string_indent_len) {
+    total_indent = 0;
   } else {
-    annotation_collector_->AddAnnotation(begin.first, end.second, file_path,
-                                         path);
+    total_indent -= raw_string_indent_len;
   }
+  return total_indent;
 }
 
-void Printer::Print(const std::map<std::string, std::string>& variables,
-                    const char* text) {
-  int size = strlen(text);
-  int pos = 0;  // The number of bytes we've written so far.
-  substitutions_.clear();
-  line_start_variables_.clear();
-
-  for (int i = 0; i < size; i++) {
-    if (text[i] == '\n') {
-      // Saw newline.  If there is more text, we may need to insert an indent
-      // here.  So, write what we have so far, including the '\n'.
-      WriteRaw(text + pos, i - pos + 1);
-      pos = i + 1;
-
-      // Setting this true will cause the next WriteRaw() to insert an indent
-      // first.
-      at_start_of_line_ = true;
-      line_start_variables_.clear();
-
-    } else if (text[i] == variable_delimiter_) {
-      // Saw the start of a variable name.
-
-      // Write what we have so far.
-      WriteRaw(text + pos, i - pos);
-      pos = i + 1;
-
-      // Find closing delimiter.
-      const char* end = strchr(text + pos, variable_delimiter_);
-      if (end == NULL) {
-        GOOGLE_LOG(DFATAL) << " Unclosed variable name.";
-        end = text + pos;
-      }
-      int endpos = end - text;
-
-      std::string varname(text + pos, endpos - pos);
-      if (varname.empty()) {
-        // Two delimiters in a row reduce to a literal delimiter character.
-        WriteRaw(&variable_delimiter_, 1);
-      } else {
-        // Replace with the variable's value.
-        std::map<std::string, std::string>::const_iterator iter =
-            variables.find(varname);
-        if (iter == variables.end()) {
-          GOOGLE_LOG(DFATAL) << " Undefined variable: " << varname;
-        } else {
-          if (at_start_of_line_ && iter->second.empty()) {
-            line_start_variables_.push_back(varname);
-          }
-          WriteRaw(iter->second.data(), iter->second.size());
-          std::pair<std::map<std::string, std::pair<size_t, size_t> >::iterator,
-                    bool>
-              inserted = substitutions_.insert(std::make_pair(
-                  varname,
-                  std::make_pair(offset_ - iter->second.size(), offset_)));
-          if (!inserted.second) {
-            // This variable was used multiple times.  Make its span have
-            // negative length so we can detect it if it gets used in an
-            // annotation.
-            inserted.first->second = std::make_pair(1, 0);
-          }
-        }
-      }
-
-      // Advance past this variable.
-      i = endpos;
-      pos = endpos + 1;
+template <typename T>
+absl::optional<T> LookupInFrameStack(
+    absl::string_view var,
+    absl::Span<std::function<absl::optional<T>(absl::string_view)>> frames) {
+  for (size_t i = frames.size(); i >= 1; --i) {
+    auto val = frames[i - 1](var);
+    if (val.has_value()) {
+      return val;
     }
   }
+  return absl::nullopt;
+}
+}  // namespace
 
-  // Write the rest.
-  WriteRaw(text + pos, size - pos);
+constexpr absl::string_view Printer::kProtocCodegenTrace;
+
+Printer::Printer(ZeroCopyOutputStream* output, Options options)
+    : sink_(output), options_(options) {
+  if (!options_.enable_codegen_trace.has_value()) {
+    // Trace-by-default is threaded through via an env var, rather than a
+    // global, so that child processes can pick it up as well. The flag
+    // --enable_codegen_trace setenv()'s this in protoc's startup code.
+    static const bool kEnableCodegenTrace =
+        ::getenv(kProtocCodegenTrace.data()) != nullptr;
+    options_.enable_codegen_trace = kEnableCodegenTrace;
+  }
 }
 
-void Printer::Indent() { indent_ += "  "; }
+absl::string_view Printer::LookupVar(absl::string_view var) {
+  LookupResult result = LookupInFrameStack(var, absl::MakeSpan(var_lookups_));
+  GOOGLE_CHECK(result.has_value()) << "could not find " << var;
+  auto* view = absl::get_if<absl::string_view>(&*result);
+  GOOGLE_CHECK(view != nullptr) << "could not find " << var
+                         << "; found callback instead";
 
+  return *view;
+}
+
+bool Printer::Validate(bool cond, Printer::PrintOptions opts,
+                       absl::FunctionRef<std::string()> message) {
+  if (!cond) {
+    if (opts.checks_are_debug_only) {
+      GOOGLE_LOG(DFATAL) << message();
+    } else {
+      GOOGLE_LOG(FATAL) << message();
+    }
+  }
+  return cond;
+}
+
+bool Printer::Validate(bool cond, Printer::PrintOptions opts,
+                       absl::string_view message) {
+  return Validate(cond, opts, [=] { return std::string(message); });
+}
+
+// This function is outlined to isolate the use of
+// GOOGLE_CHECK into the .cc file.
 void Printer::Outdent() {
-  if (indent_.empty()) {
-    GOOGLE_LOG(DFATAL) << " Outdent() without matching Indent().";
+  PrintOptions opts;
+  opts.checks_are_debug_only = true;
+  if (!Validate(indent_ >= options_.spaces_per_indent, opts,
+                "Outdent() without matching Indent()")) {
+    return;
+  }
+  indent_ -= options_.spaces_per_indent;
+}
+
+void Printer::Emit(
+    std::initializer_list<
+        VarDefinition<absl::string_view, /*allow_callbacks=*/true>>
+        vars,
+    absl::string_view format, SourceLocation loc) {
+  PrintOptions opts;
+  opts.strip_raw_string_indentation = true;
+  opts.loc = loc;
+
+  auto defs = WithDefs(vars);
+
+  PrintImpl(format, {}, opts);
+}
+
+absl::optional<std::pair<size_t, size_t>> Printer::GetSubstitutionRange(
+    absl::string_view varname, PrintOptions opts) {
+  auto it = substitutions_.find(std::string(varname));
+  if (!Validate(it != substitutions_.end(), opts, [varname] {
+        return absl::StrCat("undefined variable in annotation: ", varname);
+      })) {
+    return absl::nullopt;
+  }
+
+  std::pair<size_t, size_t> range = it->second;
+  if (!Validate(range.first <= range.second, opts, [varname] {
+        return absl::StrCat(
+            "variable used for annotation used multiple times: ", varname);
+      })) {
+    return absl::nullopt;
+  }
+
+  return range;
+}
+
+void Printer::Annotate(absl::string_view begin_varname,
+                       absl::string_view end_varname,
+                       absl::string_view file_path,
+                       const std::vector<int>& path) {
+  if (options_.annotation_collector == nullptr) {
     return;
   }
 
-  indent_.resize(indent_.size() - 2);
+  PrintOptions opts;
+  opts.checks_are_debug_only = true;
+  auto begin = GetSubstitutionRange(begin_varname, opts);
+  auto end = GetSubstitutionRange(end_varname, opts);
+  if (!begin.has_value() || !end.has_value()) {
+    return;
+  }
+  if (begin->first > end->second) {
+    GOOGLE_LOG(DFATAL) << "annotation has negative length from " << begin_varname
+                << " to " << end_varname;
+    return;
+  }
+  options_.annotation_collector->AddAnnotation(begin->first, end->second,
+                                               std::string(file_path), path);
 }
 
-void Printer::PrintRaw(const std::string& data) {
-  WriteRaw(data.data(), data.size());
-}
+void Printer::WriteRaw(const char* data, size_t size) {
+  if (failed_ || size == 0) {
+    return;
+  }
 
-void Printer::PrintRaw(const char* data) {
-  if (failed_) return;
-  WriteRaw(data, strlen(data));
-}
-
-void Printer::WriteRaw(const char* data, int size) {
-  if (failed_) return;
-  if (size == 0) return;
-
-  if (at_start_of_line_ && (size > 0) && (data[0] != '\n')) {
+  if (at_start_of_line_ && data[0] != '\n') {
     // Insert an indent.
     at_start_of_line_ = false;
-    CopyToBuffer(indent_.data(), indent_.size());
-    if (failed_) return;
+    for (size_t i = 0; i < indent_; ++i) {
+      sink_.Write(" ");
+    }
+
+    if (failed_) {
+      return;
+    }
+
     // Fix up empty variables (e.g., "{") that should be annotated as
     // coming after the indent.
-    for (std::vector<std::string>::iterator i = line_start_variables_.begin();
-         i != line_start_variables_.end(); ++i) {
-      substitutions_[*i].first += indent_.size();
-      substitutions_[*i].second += indent_.size();
+    for (const std::string& var : line_start_variables_) {
+      substitutions_[var].first += indent_;
+      substitutions_[var].second += indent_;
     }
   }
 
@@ -229,175 +264,397 @@
   // the current line.
   line_start_variables_.clear();
 
-  CopyToBuffer(data, size);
-}
-
-bool Printer::Next() {
-  do {
-    void* void_buffer;
-    if (!output_->Next(&void_buffer, &buffer_size_)) {
-      failed_ = true;
-      return false;
-    }
-    buffer_ = reinterpret_cast<char*>(void_buffer);
-  } while (buffer_size_ == 0);
-  return true;
-}
-
-void Printer::CopyToBuffer(const char* data, int size) {
-  if (failed_) return;
-  if (size == 0) return;
-
-  while (size > buffer_size_) {
-    // Data exceeds space in the buffer.  Copy what we can and request a
-    // new buffer.
-    if (buffer_size_ > 0) {
-      memcpy(buffer_, data, buffer_size_);
-      offset_ += buffer_size_;
-      data += buffer_size_;
-      size -= buffer_size_;
-    }
-    void* void_buffer;
-    failed_ = !output_->Next(&void_buffer, &buffer_size_);
-    if (failed_) return;
-    buffer_ = reinterpret_cast<char*>(void_buffer);
-  }
-
-  // Buffer is big enough to receive the data; copy it.
-  memcpy(buffer_, data, size);
-  buffer_ += size;
-  buffer_size_ -= size;
-  offset_ += size;
+  sink_.Append(data, size);
+  failed_ |= sink_.failed();
 }
 
 void Printer::IndentIfAtStart() {
-  if (at_start_of_line_) {
-    CopyToBuffer(indent_.data(), indent_.size());
-    at_start_of_line_ = false;
+  if (!at_start_of_line_) {
+    return;
   }
+
+  for (size_t i = 0; i < indent_; ++i) {
+    sink_.Write(" ");
+  }
+  at_start_of_line_ = false;
 }
 
-void Printer::FormatInternal(const std::vector<std::string>& args,
-                             const std::map<std::string, std::string>& vars,
-                             const char* format) {
-  auto save = format;
-  int arg_index = 0;
-  std::vector<AnnotationCollector::Annotation> annotations;
-  while (*format) {
-    char c = *format++;
-    switch (c) {
-      case '$':
-        format = WriteVariable(args, vars, format, &arg_index, &annotations);
+void Printer::PrintCodegenTrace(absl::optional<SourceLocation> loc) {
+  if (!options_.enable_codegen_trace.value_or(false) || !loc.has_value()) {
+    return;
+  }
+
+  if (!at_start_of_line_) {
+    at_start_of_line_ = true;
+    line_start_variables_.clear();
+    sink_.Write("\n");
+  }
+
+  PrintRaw(absl::StrFormat("%s @%s:%d\n", options_.comment_start,
+                           loc->file_name(), loc->line()));
+  at_start_of_line_ = true;
+}
+
+bool Printer::ValidateIndexLookupInBounds(size_t index,
+                                          size_t current_arg_index,
+                                          size_t args_len, PrintOptions opts) {
+  if (!Validate(index < args_len, opts, [this, index] {
+        return absl::StrFormat("annotation %c{%d%c is out of bounds",
+                               options_.variable_delimiter, index + 1,
+                               options_.variable_delimiter);
+      })) {
+    return false;
+  }
+  if (!Validate(
+          index <= current_arg_index, opts, [this, index, current_arg_index] {
+            return absl::StrFormat(
+                "annotation arg must be in correct order as given; expected "
+                "%c{%d%c but got %c{%d%c",
+                options_.variable_delimiter, current_arg_index + 1,
+                options_.variable_delimiter, options_.variable_delimiter,
+                index + 1, options_.variable_delimiter);
+          })) {
+    return false;
+  }
+  return true;
+}
+
+void Printer::PrintImpl(absl::string_view format,
+                        absl::Span<const std::string> args, PrintOptions opts) {
+  // Inside of this function, we set indentation as we print new lines from the
+  // format string. No matter how we exit this function, we should fix up the
+  // indent to what it was before we entered; a cleanup makes it easy to avoid
+  // this mistake.
+  size_t original_indent = indent_;
+  auto unindent =
+      absl::MakeCleanup([this, original_indent] { indent_ = original_indent; });
+
+  absl::string_view original = format;
+
+  line_start_variables_.clear();
+
+  if (opts.use_substitution_map) {
+    substitutions_.clear();
+  }
+
+  size_t raw_string_indent_len =
+      opts.strip_raw_string_indentation ? RawStringIndentLen(format) : 0;
+
+  if (opts.strip_raw_string_indentation) {
+    // We only want to remove a single newline from the input string to allow
+    // extra newlines at the start to go into the generated code.
+    absl::ConsumePrefix(&format, "\n");
+    while (absl::ConsumePrefix(&format, " ")) {
+    }
+  }
+
+  PrintCodegenTrace(opts.loc);
+
+  size_t arg_index = 0;
+  std::vector<AnnotationCollector::Annotation> annot_stack;
+  std::vector<std::pair<absl::string_view, size_t>> annot_records;
+  while (!format.empty()) {
+    // Skip to the next special character. We do this so that we can delay
+    // printing "normal" text until we know what kind of variable substitution
+    // we're doing, since that may require trimming whitespace.
+    size_t next_special = 0;
+    for (; next_special < format.size(); ++next_special) {
+      if (format[next_special] == options_.variable_delimiter ||
+          format[next_special] == '\n') {
+        break;
+      }
+    }
+
+    absl::string_view next_chunk = format.substr(0, next_special);
+    format = format.substr(next_special);
+
+    if (format.empty()) {
+      PrintRaw(next_chunk);
+      break;
+    }
+
+    char c = format.front();
+    format = format.substr(1);
+    if (c == '\n') {
+      PrintRaw(next_chunk);
+      at_start_of_line_ = true;
+      line_start_variables_.clear();
+      sink_.Write("\n");
+      indent_ =
+          original_indent + ConsumeIndentForLine(raw_string_indent_len, format);
+      continue;
+    } else if (c != options_.variable_delimiter) {
+      PrintRaw(next_chunk);
+      continue;
+    }
+
+    size_t end = format.find(options_.variable_delimiter);
+    if (!Validate(end != absl::string_view::npos, opts, [format] {
+          return absl::StrCat("unclosed variable name: \"",
+                              absl::CHexEscape(format), "\"");
+        })) {
+      PrintRaw(next_chunk);
+      WriteRaw(&options_.variable_delimiter, 1);
+      PrintRaw(format);
+      break;
+    }
+
+    absl::string_view match = format.substr(0, end);
+    absl::string_view var = match;
+    format = format.substr(end + 1);
+
+    if (var.empty()) {
+      // `$$` is an escape for just `$`.
+      PrintRaw(next_chunk);
+      WriteRaw(&options_.variable_delimiter, 1);
+      continue;
+    }
+
+    if (opts.use_curly_brace_substitutions && absl::ConsumePrefix(&var, "{")) {
+      PrintRaw(next_chunk);
+
+      if (!Validate(var.size() == 1u, opts, "expected single-digit variable")) {
         continue;
-      case '\n':
-        at_start_of_line_ = true;
-        line_start_variables_.clear();
-        break;
-      default:
+      }
+
+      if (!Validate(absl::ascii_isdigit(var[0]), opts,
+                    "expected digit after {")) {
+        continue;
+      }
+
+      size_t idx = var[0] - '1';
+      if (!ValidateIndexLookupInBounds(idx, arg_index, args.size(), opts)) {
+        continue;
+      }
+
+      if (idx == arg_index) {
+        ++arg_index;
+      }
+
+      IndentIfAtStart();
+      annot_stack.push_back({{sink_.bytes_written(), 0}, args[idx]});
+      continue;
+    } else if (opts.use_curly_brace_substitutions &&
+               absl::ConsumePrefix(&var, "}")) {
+      PrintRaw(next_chunk);
+
+      // The rest of var is actually ignored, and this is apparently
+      // public API now. Oops?
+      if (!Validate(!annot_stack.empty(), opts,
+                    "unexpected end of annotation")) {
+        continue;
+      }
+
+      annot_stack.back().first.second = sink_.bytes_written();
+      if (options_.annotation_collector != nullptr) {
+        options_.annotation_collector->AddAnnotationNew(annot_stack.back());
+      }
+      IndentIfAtStart();
+      annot_stack.pop_back();
+      continue;
+    }
+
+    absl::string_view prefix, suffix;
+    if (opts.strip_spaces_around_vars) {
+      var = absl::StripLeadingAsciiWhitespace(var);
+      prefix = match.substr(0, match.size() - var.size());
+      var = absl::StripTrailingAsciiWhitespace(var);
+      suffix = match.substr(prefix.size() + var.size());
+    }
+
+    if (!Validate(!var.empty(), opts, "unexpected empty variable")) {
+      PrintRaw(next_chunk);
+      continue;
+    }
+
+    LookupResult sub;
+    absl::optional<AnnotationRecord> same_name_record;
+    if (opts.allow_digit_substitutions && absl::ascii_isdigit(var[0])) {
+      PrintRaw(next_chunk);
+
+      if (!Validate(var.size() == 1u, opts, "expected single-digit variable")) {
+        continue;
+      }
+
+      size_t idx = var[0] - '1';
+      if (!ValidateIndexLookupInBounds(idx, arg_index, args.size(), opts)) {
+        continue;
+      }
+      if (idx == arg_index) {
+        ++arg_index;
+      }
+      sub = args[idx];
+    } else if (opts.use_annotation_frames &&
+               (var == "_start" || var == "_end")) {
+      bool is_start = var == "_start";
+
+      size_t next_delim = format.find('$');
+      if (!Validate(next_delim != absl::string_view::npos, opts,
+                    "$_start$ must be followed by a name and another $")) {
+        PrintRaw(next_chunk);
+        continue;
+      }
+
+      auto var = format.substr(0, next_delim);
+      format = format.substr(next_delim + 1);
+
+      if (is_start) {
+        PrintRaw(next_chunk);
         IndentIfAtStart();
-        break;
+        annot_records.push_back({var, sink_.bytes_written()});
+        // Skip all whitespace immediately after a _start.
+        while (!format.empty() && absl::ascii_isspace(format.front())) {
+          format = format.substr(1);
+        }
+      } else {
+        // Skip all whitespace immediately *before* an _end.
+        while (!next_chunk.empty() && absl::ascii_isspace(next_chunk.back())) {
+          next_chunk = next_chunk.substr(0, next_chunk.size() - 1);
+        }
+        PrintRaw(next_chunk);
+
+        // If a line consisted *only* of an _end, this will likely result in
+        // a blank line if we do not zap the newline after it, and any
+        // indentation beyond that.
+        if (at_start_of_line_) {
+          absl::ConsumePrefix(&format, "\n");
+          indent_ = original_indent +
+                    ConsumeIndentForLine(raw_string_indent_len, format);
+        }
+
+        auto record_var = annot_records.back();
+        annot_records.pop_back();
+
+        if (!Validate(record_var.first == var, opts, [record_var, var] {
+              return absl::StrFormat(
+                  "_start and _end variables must match, but got %s and %s, "
+                  "respectively",
+                  record_var.first, var);
+            })) {
+          continue;
+        }
+
+        absl::optional<AnnotationRecord> record =
+            LookupInFrameStack(var, absl::MakeSpan(annotation_lookups_));
+
+        if (!Validate(record.has_value(), opts, [var] {
+              return absl::StrCat("undefined variable: \"",
+                                  absl::CHexEscape(var), "\"");
+            })) {
+          continue;
+        }
+
+        if (options_.annotation_collector != nullptr) {
+          options_.annotation_collector->AddAnnotation(
+              record_var.second, sink_.bytes_written(), record->file_path,
+              record->path);
+        }
+      }
+
+      continue;
+    } else {
+      PrintRaw(next_chunk);
+      sub = LookupInFrameStack(var, absl::MakeSpan(var_lookups_));
+
+      if (opts.use_annotation_frames) {
+        same_name_record =
+            LookupInFrameStack(var, absl::MakeSpan(annotation_lookups_));
+      }
     }
-    push_back(c);
+
+    // By returning here in case of empty we also skip possible spaces inside
+    // the $...$, i.e. "void$ dllexpor$ f();" -> "void f();" in the empty case.
+    if (!Validate(sub.has_value(), opts, [var] {
+          return absl::StrCat("undefined variable: \"", absl::CHexEscape(var),
+                              "\"");
+        })) {
+      continue;
+    }
+
+    size_t range_start = sink_.bytes_written();
+    size_t range_end = sink_.bytes_written();
+
+    if (auto* str = absl::get_if<absl::string_view>(&*sub)) {
+      if (at_start_of_line_ && str->empty()) {
+        line_start_variables_.emplace_back(var);
+      }
+
+      if (!str->empty()) {
+        // If `sub` is empty, we do not print the spaces around it.
+        PrintRaw(prefix);
+        PrintRaw(*str);
+        range_end = sink_.bytes_written();
+        range_start = range_end - str->size();
+        PrintRaw(suffix);
+      }
+    } else {
+      auto* fnc = absl::get_if<std::function<void()>>(&*sub);
+      GOOGLE_CHECK(fnc != nullptr);
+
+      Validate(
+          prefix.empty() && suffix.empty(), opts,
+          "substitution that resolves to callback cannot contain whitespace");
+
+      range_start = sink_.bytes_written();
+      (*fnc)();
+      range_end = sink_.bytes_written();
+
+      // If we just evaluated a closure, and we are at the start of a line, that
+      // means it finished with a newline. If a newline follows immediately
+      // after, we drop it. This helps callback formatting "work as expected"
+      // with respect to forms like
+      //
+      //   class Foo {
+      //     $methods$;
+      //   };
+      //
+      // Without this line, this would turn into something like
+      //
+      //   class Foo {
+      //     void Bar() {}
+      //
+      //   };
+      //
+      // in many cases. We *also* do this if a ; or , follows the substitution,
+      // because this helps clang-format keep its head on in many cases.
+      // Users that need to keep the semi can write $foo$/**/;
+      if (!absl::ConsumePrefix(&format, ";")) {
+        absl::ConsumePrefix(&format, ",");
+      }
+      absl::ConsumePrefix(&format, "\n");
+      indent_ =
+          original_indent + ConsumeIndentForLine(raw_string_indent_len, format);
+    }
+
+    if (same_name_record.has_value() &&
+        options_.annotation_collector != nullptr) {
+      options_.annotation_collector->AddAnnotation(range_start, range_end,
+                                                   same_name_record->file_path,
+                                                   same_name_record->path);
+    }
+
+    if (opts.use_substitution_map) {
+      auto insertion = substitutions_.emplace(
+          std::string(var), std::make_pair(range_start, range_end));
+
+      if (!insertion.second) {
+        // This variable was used multiple times.
+        // Make its span have negative length so
+        // we can detect it if it gets used in an
+        // annotation.
+        insertion.first->second = {1, 0};
+      }
+    }
   }
-  if (arg_index != static_cast<int>(args.size())) {
-    GOOGLE_LOG(FATAL) << " Unused arguments. " << save;
-  }
-  if (!annotations.empty()) {
-    GOOGLE_LOG(FATAL) << " Annotation range is not-closed, expect $}$. " << save;
-  }
+
+  Validate(arg_index == args.size(), opts,
+           [original] { return absl::StrCat("unused args: ", original); });
+  Validate(annot_stack.empty(), opts, [this, original] {
+    return absl::StrFormat(
+        "annotation range was not closed; expected %c}%c: %s",
+        options_.variable_delimiter, options_.variable_delimiter, original);
+  });
 }
-
-const char* Printer::WriteVariable(
-    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;
-  auto end = strchr(format, '$');
-  if (!end) {
-    GOOGLE_LOG(FATAL) << " Unclosed variable name.";
-  }
-  format = end + 1;
-  if (end == start) {
-    // "$$" is an escape for just '$'
-    IndentIfAtStart();
-    push_back('$');
-    return format;
-  }
-  if (*start == '{') {
-    GOOGLE_CHECK(std::isdigit(start[1]));
-    GOOGLE_CHECK_EQ(end - start, 2);
-    int idx = start[1] - '1';
-    if (idx < 0 || static_cast<size_t>(idx) >= args.size()) {
-      GOOGLE_LOG(FATAL) << "Annotation ${" << idx + 1 << "$ is out of bounds.";
-    }
-    if (idx > *arg_index) {
-      GOOGLE_LOG(FATAL) << "Annotation arg must be in correct order as given. Expected"
-                 << " ${" << (*arg_index) + 1 << "$ got ${" << idx + 1 << "$.";
-    } else if (idx == *arg_index) {
-      (*arg_index)++;
-    }
-    IndentIfAtStart();
-    annotations->push_back({{offset_, 0}, args[idx]});
-    return format;
-  } else if (*start == '}') {
-    GOOGLE_CHECK(annotations);
-    if (annotations->empty()) {
-      GOOGLE_LOG(FATAL) << "Unexpected end of annotation found.";
-    }
-    auto& a = annotations->back();
-    a.first.second = offset_;
-    if (annotation_collector_) annotation_collector_->AddAnnotationNew(a);
-    annotations->pop_back();
-    return format;
-  }
-  auto start_var = start;
-  while (start_var < end && *start_var == ' ') start_var++;
-  if (start_var == end) {
-    GOOGLE_LOG(FATAL) << " Empty variable.";
-  }
-  auto end_var = end;
-  while (start_var < end_var && *(end_var - 1) == ' ') end_var--;
-  std::string var_name{
-      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(), 1U);  // No need for multi-digits
-    int idx = var_name[0] - '1';   // Start counting at 1
-    GOOGLE_CHECK_GE(idx, 0);
-    if (static_cast<size_t>(idx) >= args.size()) {
-      GOOGLE_LOG(FATAL) << "Argument $" << idx + 1 << "$ is out of bounds.";
-    }
-    if (idx > *arg_index) {
-      GOOGLE_LOG(FATAL) << "Arguments must be used in same order as given. Expected $"
-                 << (*arg_index) + 1 << "$ got $" << idx + 1 << "$.";
-    } else if (idx == *arg_index) {
-      (*arg_index)++;
-    }
-    sub = args[idx];
-  } else {
-    auto it = vars.find(var_name);
-    if (it == vars.end()) {
-      GOOGLE_LOG(FATAL) << " Unknown variable: " << var_name << ".";
-    }
-    sub = it->second;
-  }
-
-  // By returning here in case of empty we also skip possible spaces inside
-  // the $...$, i.e. "void$ dllexpor$ f();" -> "void f();" in the empty case.
-  if (sub.empty()) return format;
-
-  // We're going to write something non-empty so we need a possible indent.
-  IndentIfAtStart();
-
-  // Write the possible spaces in front.
-  CopyToBuffer(start, start_var - start);
-  // Write a non-empty substituted variable.
-  CopyToBuffer(sub.c_str(), sub.size());
-  // Finish off with writing possible trailing spaces.
-  CopyToBuffer(end_var, end - end_var);
-  return format;
-}
-
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/io/printer.h b/src/google/protobuf/io/printer.h
index 92a4321..764e335 100644
--- a/src/google/protobuf/io/printer.h
+++ b/src/google/protobuf/io/printer.h
@@ -37,27 +37,41 @@
 #ifndef GOOGLE_PROTOBUF_IO_PRINTER_H__
 #define GOOGLE_PROTOBUF_IO_PRINTER_H__
 
-
+#include <cstddef>
+#include <functional>
+#include <initializer_list>
 #include <map>
 #include <string>
+#include <type_traits>
+#include <utility>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/cleanup/cleanup.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/functional/function_ref.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/types/variant.h"
+#include "google/protobuf/io/zero_copy_sink.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace io {
-
-class ZeroCopyOutputStream;  // zero_copy_stream.h
-
 // Records annotations about a Printer's output.
 class PROTOBUF_EXPORT AnnotationCollector {
  public:
-  // Annotation is a offset range and a payload pair.
-  typedef std::pair<std::pair<size_t, size_t>, std::string> Annotation;
+  // Annotation is a offset range and a payload pair. This payload's layout is
+  // specific to derived types of AnnotationCollector.
+  using Annotation = std::pair<std::pair<size_t, size_t>, std::string>;
+
+  virtual ~AnnotationCollector() = default;
 
   // Records that the bytes in file_path beginning with begin_offset and ending
   // before end_offset are associated with the SourceCodeInfo-style path.
@@ -67,28 +81,29 @@
 
   // 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 ~AnnotationCollector() {}
+  virtual void AddAnnotationNew(Annotation&) {}
 };
 
-// Records annotations about a Printer's output to the given protocol buffer,
-// assuming that the buffer has an ::Annotation message exposing path,
-// source_file, begin and end fields.
+// Records annotations about a Printer's output to a Protobuf message,
+// assuming that it has a repeated submessage field named `annotation` with
+// fields matching
+//
+// message ??? {
+//   repeated int32 path = 1;
+//   optional string source_file = 2;
+//   optional int32 begin = 3;
+//   optional int32 end = 4;
+// }
 template <typename AnnotationProto>
 class AnnotationProtoCollector : public AnnotationCollector {
  public:
-  // annotation_proto is the protocol buffer to which new Annotations should be
-  // added. It is not owned by the AnnotationProtoCollector.
   explicit AnnotationProtoCollector(AnnotationProto* annotation_proto)
       : annotation_proto_(annotation_proto) {}
 
-  // Override for AnnotationCollector::AddAnnotation.
   void AddAnnotation(size_t begin_offset, size_t end_offset,
                      const std::string& file_path,
                      const std::vector<int>& path) override {
-    typename AnnotationProto::Annotation* annotation =
-        annotation_proto_->add_annotation();
+    auto* annotation = annotation_proto_->add_annotation();
     for (int i = 0; i < path.size(); ++i) {
       annotation->add_path(path[i]);
     }
@@ -96,7 +111,7 @@
     annotation->set_begin(begin_offset);
     annotation->set_end(end_offset);
   }
-  // Override for AnnotationCollector::AddAnnotation.
+
   void AddAnnotationNew(Annotation& a) override {
     auto* annotation = annotation_proto_->add_annotation();
     annotation->ParseFromString(a.second);
@@ -105,10 +120,202 @@
   }
 
  private:
-  // The protocol buffer to which new annotations should be added.
-  AnnotationProto* const annotation_proto_;
+  AnnotationProto* annotation_proto_;
 };
 
+// A source code printer for assisting in code generation.
+//
+// This type implements a simple templating language for substiting variables
+// into static, user-provided strings, and also tracks indentation
+// automatically.
+//
+// The main entry-point for this type is the Emit function, which can be used
+// thus:
+//
+//   Printer p(output);
+//   p.Emit({{"class", my_class_name}}, R"cc(
+//     class $class$ {
+//      public:
+//       $class$(int x) : x_(x) {}
+//      private:
+//       int x_;
+//     };
+//   )cc");
+//
+// Substitutions are of the form $var$, which is looked up in the map passed in
+// as the first argument. The variable delimiter character, $, can be chosen to
+// be something convenient for the target language. For example, in PHP, which
+// makes heavy use of $, it can be made into something like # instead.
+//
+// A literal $ can be emitted by writing $$.
+//
+// Substitutions may contain spaces around the name of the variable, which will
+// be ignored for the purposes of looking up the variable to substitute in, but
+// which will be reproduced in the output:
+//
+//   p.Emit({{"foo", "bar"}}, "$ foo $");
+//
+// emits the string " bar ". If the substituted-in variable is the empty string,
+// then the surrounding spaces are *not* printed:
+//
+//   p.Emit({{"xzy", xyz}}, "$xyz $Thing");
+//
+// If xyz is "Foo", this will become "Foo Thing", but if it is "", this becomes
+// "Thing", rather than " Thing". This helps minimize awkward whitespace in the
+// output.
+//
+// The value may be any type that can be stringified with `absl::StrCat`:
+//
+//   p.Emit({{"num", 5}}, "x = $num$;");
+//
+// If a variable is referenced in the format string that is missing, the program
+// will crash. Callers must statically know that every variable reference is
+// valid, and MUST NOT pass user-provided strings directly into Emit().
+//
+// # Callback Substitution
+//
+// Instead of passing a string into Emit(), it is possible to pass in a callback
+// as a variable mapping. This will take indentation into account, which allows
+// factoring out parts of a formatting string while ensuring braces are
+// balanced:
+//
+//   p.Emit(
+//     {{"methods", [&] {
+//       p.Emit(R"cc(
+//         int Bar() {
+//            return 42;
+//         }
+//       )cc");
+//     }}},
+//     R"cc(
+//       class Foo {
+//        public:
+//         $methods$;
+//       };
+//     )cc"
+//   );
+//
+// This emits
+//
+//   class Foo {
+//    public:
+//     int Bar() {
+//       return 42;
+//     }
+//   };
+//
+// # Lookup Frames
+//
+// If many calls to Emit() use the same set of variables, they can be stored
+// in a *variable lookup frame*, like so:
+//
+//   auto vars = p.WithVars({{"class_name", my_class_name}});
+//   p.Emit(R"cc(
+//     class $class_name$ {
+//      public:
+//       $class_name$(int x);
+//       // Etc.
+//     };
+//   )cc");
+//
+// WithVars() returns an RAII object that will "pop" the lookup frame on scope
+// exit, ensuring that the variables remain local. There are a few different
+// overloads of WithVars(); it accepts a map type, like absl::flat_hash_map,
+// either by-value (which will cause the Printer to store a copy), or by
+// pointer (which will cause the Printer to store a pointer, potentially
+// avoiding a copy.)
+//
+// p.Emit(vars, "..."); is effectively syntax sugar for
+//
+//  { auto v = p.WithVars(vars); p.Emit("..."); }
+//
+// NOTE: callbacks are *not* allowed with WithVars; callbacks should be local
+// to a specific Emit() call.
+//
+// # Annotations
+//
+// If Printer is given an AnnotationCollector, it will use it to record which
+// spans of generated code correspond to user-indicated descriptors. There are
+// a few different ways of indicating when to emit annotations.
+//
+// The WithAnnotations() function is like WithVars(), but accepts maps with
+// string keys and descriptor values. It adds an annotation variable frame and
+// returns an RAII object that pops the frame.
+//
+// There are two different ways to annotate code. In the first, when
+// substituting a variable, if there is an annotation with the same name, then
+// the resulting expanded value's span will be annotated with that annotation.
+// For example:
+//
+//   auto v = p.WithVars({{"class_name", my_class_name}});
+//   auto a = p.WithAnnotations({{"class_name", message_descriptor}});
+//   p.Emit(R"cc(
+//     class $class_name$ {
+//      public:
+//       $class_name$(int x);
+//       // Etc.
+//     };
+//   )cc");
+//
+// The span corresponding to whatever $class_name$ expands to will be annotated
+// as having come from message_descriptor.
+//
+// For convenience, this can be done with a single WithVars(), using the special
+// three-argument form:
+//
+//   auto v = p.WithVars({{"class_name", my_class_name, message_descriptor}});
+//   p.Emit(R"cc(
+//     class $class_name$ {
+//      public:
+//       $class_name$(int x);
+//       // Etc.
+//     };
+//   )cc");
+//
+//
+// Alternatively, a range may be given explicitly:
+//
+//   auto a = p.WithAnnotations({{"my_desc", message_descriptor}});
+//   p.Emit(R"cc(
+//     $_start$my_desc$
+//     class Foo {
+//       // Etc.
+//     };
+//     $_end$my_desc$
+//   )cc");
+//
+// The special $_start$ and $_end$ variables indicate the start and end of an
+// annotated span, which is annotated with the variable that follows. This
+// form can produce somewhat unreadable format strings and is not recommended.
+//
+// Note that whitespace after a $_start$ and before an $_end$ is not printed.
+//
+// # Indentation
+//
+// Printer tracks an indentation amount to add to each new line, independent
+// from indentation in an Emit() call's literal. The amount of indentation to
+// add is controlled by the WithIndent() function:
+//
+//   p.Emit("class $class_name$ {");
+//   {
+//     auto indent = p.WithIndent();
+//     p.Emit(R"cc(
+//       public:
+//        $class_name$(int x);
+//     )cc");
+//   }
+//   p.Emit("};");
+//
+// This will automatically add one level of indentation to all code in scope of
+// `indent`, which is an RAII object much like the return value of `WithVars()`.
+//
+// # Old API
+// TODO(b/242326974): Delete this documentation.
+//
+// Printer supports an older-style API that is in the process of being
+// re-written. The old documentation is reproduced here until all use-cases are
+// handled.
+//
 // This simple utility class assists in code generation.  It basically
 // allows the caller to define a set of variables and then output some
 // text with variable substitutions.  Example usage:
@@ -180,26 +387,331 @@
 //
 // This code associates the span covering "call(bar,bar)" in the output with the
 // call_ descriptor.
-
 class PROTOBUF_EXPORT Printer {
+ private:
+  // This type exists to work around an absl type that has not yet been
+  // released.
+  struct SourceLocation {
+    static SourceLocation current() { return {}; }
+    absl::string_view file_name() { return "<unknown>"; }
+    int line() { return 0; }
+  };
+
+  struct AnnotationRecord {
+    std::vector<int> path;
+    std::string file_path;
+
+    // AnnotationRecord's constructors are *not* marked as explicit,
+    // specifically so that it is possible to construct a
+    // map<string, AnnotationRecord> by writing
+    //
+    // {{"foo", my_cool_descriptor}, {"bar", "file.proto"}}
+
+    template <
+        typename String,
+        std::enable_if_t<std::is_convertible<const String&, std::string>::value,
+                         int> = 0>
+    AnnotationRecord(  // NOLINT(google-explicit-constructor)
+        const String& file_path)
+        : file_path(file_path) {}
+
+    template <typename Desc,
+              // This SFINAE clause excludes char* from matching this
+              // constructor.
+              std::enable_if_t<std::is_class<Desc>::value, int> = 0>
+    AnnotationRecord(const Desc* desc)  // NOLINT(google-explicit-constructor)
+        : file_path(desc->file()->name()) {
+      desc->GetLocationPath(&path);
+    }
+  };
+
+  // Sink type for constructing values to pass to WithVars() and Emit().
+  template <typename K, bool allow_callbacks>
+  struct VarDefinition {
+    using StringOrCallback = absl::variant<std::string, std::function<void()>>;
+
+    template <typename Key, typename Value>
+    VarDefinition(Key&& key, Value&& value)
+        : key(std::forward<Key>(key)),
+          value(ToStringOrCallback(std::forward<Value>(value), Rank2{})),
+          annotation(absl::nullopt) {}
+
+    // NOTE: This is an overload rather than taking optional<AnnotationRecord>
+    // with a default argument of nullopt, because we want to pick up
+    // AnnotationRecord's user-defined conversions. Because going from
+    // e.g. Descriptor* -> optional<AnnotationRecord> requires two user-defined
+    // conversions, this does not work.
+    template <typename Key, typename Value>
+    VarDefinition(Key&& key, Value&& value, AnnotationRecord annotation)
+        : key(std::forward<Key>(key)),
+          value(ToStringOrCallback(std::forward<Value>(value), Rank2{})),
+          annotation(std::move(annotation)) {}
+
+    K key;
+    StringOrCallback value;
+    absl::optional<AnnotationRecord> annotation;
+
+   private:
+    // go/ranked-overloads
+    struct Rank0 {};
+    struct Rank1 : Rank0 {};
+    struct Rank2 : Rank1 {};
+
+    // Dummy template for delayed instantiation, which is required for the
+    // static assert below to kick in only when this function is called when it
+    // shouldn't.
+    //
+    // This is done to produce a better error message than the "candidate does
+    // not match" SFINAE errors.
+    template <bool allowed = allow_callbacks>
+    StringOrCallback ToStringOrCallback(std::function<void()> cb, Rank2) {
+      static_assert(
+          allowed, "callback-typed variables are not allowed in this location");
+      return cb;
+    }
+
+    // Separate from the AlphaNum overload to avoid copies when taking strings
+    // by value.
+    StringOrCallback ToStringOrCallback(std::string s, Rank1) { return s; }
+
+    StringOrCallback ToStringOrCallback(const absl::AlphaNum& s, Rank0) {
+      return std::string(s.Piece());
+    }
+  };
+
+  // Provide a helper to use heterogeneous lookup when it's available.
+  template <class...>
+  using void_t = void;
+  template <typename Map, typename = void>
+  struct has_heterogeneous_lookup : std::false_type {};
+  template <typename Map>
+  struct has_heterogeneous_lookup<Map, void_t<decltype(std::declval<Map>().find(
+                                           std::declval<absl::string_view>()))>>
+      : std::true_type {};
+
+  template <typename Map,
+            std::enable_if_t<has_heterogeneous_lookup<Map>::value, int> = 0>
+  static absl::string_view ToStringKey(absl::string_view x) {
+    return x;
+  }
+  template <typename Map,
+            std::enable_if_t<!has_heterogeneous_lookup<Map>::value, int> = 0>
+  static std::string ToStringKey(absl::string_view x) {
+    return std::string(x);
+  }
+
  public:
-  // Create a printer that writes text to the given output stream.  Use the
-  // given character as the delimiter for variables.
-  Printer(ZeroCopyOutputStream* output, char variable_delimiter);
+  static constexpr char kDefaultVariableDelimiter = '$';
+  static constexpr absl::string_view kProtocCodegenTrace =
+      "PROTOC_CODEGEN_TRACE";
 
-  // Create a printer that writes text to the given output stream.  Use the
-  // given character as the delimiter for variables.  If annotation_collector
-  // is not null, Printer will provide it with annotations about code written
-  // to the stream.  annotation_collector is not owned by Printer.
+  // Options for controlling how the output of a Printer is formatted.
+  struct Options {
+    Options() = default;
+    Options(const Options&) = default;
+    Options(Options&&) = default;
+    Options(char variable_delimiter, AnnotationCollector* annotation_collector)
+        : variable_delimiter(variable_delimiter),
+          annotation_collector(annotation_collector) {}
+
+    // The delimiter for variable substitutions, e.g. $foo$.
+    char variable_delimiter = kDefaultVariableDelimiter;
+    // An optional listener the Printer calls whenever it emits a source
+    // annotation; may be null.
+    AnnotationCollector* annotation_collector = nullptr;
+    // The "comment start" token for the language being generated. This is used
+    // to allow the Printer to emit debugging annotations in the source code
+    // output.
+    absl::string_view comment_start = "//";
+    // The number of spaces that a single level of indentation adds by default;
+    // this is the amount that WithIndent() increases indentation by.
+    size_t spaces_per_indent = 2;
+    // Whether to emit a "codegen trace" for calls to Emit(). If true, each call
+    // to Emit() will print a comment indicating where in the source of the
+    // compiler the Emit() call occurred.
+    //
+    // If disengaged, defaults to whether or not the environment variable
+    // `PROTOC_CODEGEN_TRACE` is set.
+    absl::optional<bool> enable_codegen_trace = absl::nullopt;
+  };
+
+  // Constructs a new Printer with the default options to output to
+  // `output`.
+  explicit Printer(ZeroCopyOutputStream* output) : Printer(output, Options{}) {}
+
+  // Constructs a new printer with the given set of options to output to
+  // `output`.
+  Printer(ZeroCopyOutputStream* output, Options options);
+
+  // Old-style constructor. Avoid in preference to the two constructors above.
+  //
+  // Will eventually be marked as deprecated.
   Printer(ZeroCopyOutputStream* output, char variable_delimiter,
-          AnnotationCollector* annotation_collector);
+          AnnotationCollector* annotation_collector = nullptr)
+      : Printer(output, Options{variable_delimiter, annotation_collector}) {}
 
-  ~Printer();
+  Printer(const Printer&) = delete;
+  Printer& operator=(const Printer&) = delete;
+
+  // Pushes a new variable lookup frame that stores `vars` by reference.
+  //
+  // Returns an RAII object that pops the lookup frame.
+  template <typename Map>
+  auto WithVars(const Map* vars) {
+    var_lookups_.emplace_back([vars](absl::string_view var) -> LookupResult {
+      auto it = vars->find(ToStringKey<Map>(var));
+      if (it == vars->end()) {
+        return absl::nullopt;
+      }
+      return absl::string_view(it->second);
+    });
+    return absl::MakeCleanup([this] { var_lookups_.pop_back(); });
+  }
+
+  // Pushes a new variable lookup frame that stores `vars` by value.
+  //
+  // When writing `WithVars({...})`, this is the overload that will be called,
+  // and it will synthesize an `absl::flat_hash_map`.
+  //
+  // Returns an RAII object that pops the lookup frame.
+  template <typename Map = absl::flat_hash_map<std::string, std::string>,
+            std::enable_if_t<!std::is_pointer<Map>::value, int> = 0>
+  auto WithVars(Map&& vars) {
+    var_lookups_.emplace_back([vars = std::forward<Map>(vars)](
+                                  absl::string_view var) -> LookupResult {
+      auto it = vars.find(ToStringKey<Map>(var));
+      if (it == vars.end()) {
+        return absl::nullopt;
+      }
+      return absl::string_view(it->second);
+    });
+    return absl::MakeCleanup([this] { var_lookups_.pop_back(); });
+  }
+
+  auto WithVars(std::initializer_list<
+                VarDefinition<std::string, /*allow_callbacks=*/false>>
+                    vars);
+
+  // Looks up a variable set with WithVars().
+  //
+  // Will crash if:
+  // - `var` is not present in the lookup frame table.
+  // - `var` is a callback, rather than a string.
+  absl::string_view LookupVar(absl::string_view var);
+
+  // Pushes a new annotation lookup frame that stores `vars` by reference.
+  //
+  // Returns an RAII object that pops the lookup frame.
+  template <typename Map>
+  auto WithAnnotations(const Map* vars) {
+    annotation_lookups_.emplace_back(
+        [vars](absl::string_view var) -> absl::optional<AnnotationRecord> {
+          auto it = vars->find(ToStringKey<Map>(var));
+          if (it == vars->end()) {
+            return absl::nullopt;
+          }
+          return AnnotationRecord(it->second);
+        });
+    return absl::MakeCleanup([this] { annotation_lookups_.pop_back(); });
+  }
+
+  // Pushes a new variable lookup frame that stores `vars` by value.
+  //
+  // When writing `WithAnnotations({...})`, this is the overload that will be
+  // called, and it will synthesize an `absl::flat_hash_map`.
+  //
+  // Returns an RAII object that pops the lookup frame.
+  template <typename Map = absl::flat_hash_map<std::string, AnnotationRecord>>
+  auto WithAnnotations(Map&& vars) {
+    annotation_lookups_.emplace_back(
+        [vars = std::forward<Map>(vars)](
+            absl::string_view var) -> absl::optional<AnnotationRecord> {
+          auto it = vars.find(ToStringKey<Map>(var));
+          if (it == vars.end()) {
+            return absl::nullopt;
+          }
+          return AnnotationRecord(it->second);
+        });
+    return absl::MakeCleanup([this] { annotation_lookups_.pop_back(); });
+  }
+
+  // Increases the indentation by `indent` spaces; when nullopt, increments
+  // indentation by the configured default spaces_per_indent.
+  //
+  // Returns an RAII object that removes this indentation.
+  auto WithIndent(absl::optional<size_t> indent = absl::nullopt) {
+    size_t delta = indent.value_or(options_.spaces_per_indent);
+    indent_ += delta;
+    return absl::MakeCleanup([this, delta] { indent_ -= delta; });
+  }
+
+  // Emits formatted source code to the underlying output. See the class
+  // documentation for more details.
+  //
+  // `format` MUST be a string constant.
+  void Emit(absl::string_view format,
+            SourceLocation loc = SourceLocation::current()) {
+    Emit({}, format, loc);
+  }
+
+  // Emits formatted source code to the underlying output, injecting
+  // additional variables as a lookup frame for just this call. See the class
+  // documentation for more details.
+  //
+  // `format` MUST be a string constant.
+  void Emit(std::initializer_list<
+                VarDefinition<absl::string_view, /*allow_callbacks=*/true>>
+                vars,
+            absl::string_view format,
+            SourceLocation loc = SourceLocation::current());
+
+  // Write a string directly to the underlying output, performing no formatting
+  // of any sort.
+  void PrintRaw(absl::string_view data) { WriteRaw(data.data(), data.size()); }
+
+  // Write a string directly to the underlying output, performing no formatting
+  // of any sort.
+  void WriteRaw(const char* data, size_t size);
+
+  // True if any write to the underlying stream failed.  (We don't just
+  // crash in this case because this is an I/O failure, not a programming
+  // error.)
+  bool failed() const { return failed_; }
+
+  // -- Old-style API below; to be deprecated and removed. --
+  // TODO(b/242326974): Deprecate these APIs.
+
+  template <typename Map = absl::flat_hash_map<std::string, std::string>>
+  void Print(const Map& vars, absl::string_view text) {
+    PrintOptions opts;
+    opts.checks_are_debug_only = true;
+    opts.use_substitution_map = true;
+    opts.allow_digit_substitutions = false;
+
+    auto pop = WithVars(&vars);
+    PrintImpl(text, {}, opts);
+  }
+
+  template <typename... Args>
+  void Print(absl::string_view text, const Args&... args) {
+    static_assert(sizeof...(args) % 2 == 0, "");
+
+    // Include an extra arg, since a zero-length array is ill-formed, and
+    // MSVC complains.
+    absl::string_view vars[] = {args..., ""};
+    absl::flat_hash_map<absl::string_view, absl::string_view> map;
+    map.reserve(sizeof...(args) / 2);
+    for (size_t i = 0; i < sizeof...(args); i += 2) {
+      map.emplace(vars[i], vars[i + 1]);
+    }
+
+    Print(map, text);
+  }
 
   // Link a substitution variable emitted by the last call to Print to the
   // object described by descriptor.
   template <typename SomeDescriptor>
-  void Annotate(const char* varname, const SomeDescriptor* descriptor) {
+  void Annotate(absl::string_view varname, const SomeDescriptor* descriptor) {
     Annotate(varname, varname, descriptor);
   }
 
@@ -208,13 +720,12 @@
   // begins at begin_varname's value and ends after the last character of the
   // value substituted for end_varname.
   template <typename SomeDescriptor>
-  void Annotate(const char* begin_varname, const char* end_varname,
+  void Annotate(absl::string_view begin_varname, absl::string_view end_varname,
                 const SomeDescriptor* descriptor) {
-    if (annotation_collector_ == NULL) {
-      // Annotations aren't turned on for this Printer, so don't pay the cost
-      // of building the location path.
+    if (options_.annotation_collector == nullptr) {
       return;
     }
+
     std::vector<int> path;
     descriptor->GetLocationPath(&path);
     Annotate(begin_varname, end_varname, descriptor->file()->name(), path);
@@ -222,7 +733,7 @@
 
   // Link a substitution variable emitted by the last call to Print to the file
   // with path file_name.
-  void Annotate(const char* varname, const std::string& file_name) {
+  void Annotate(absl::string_view varname, absl::string_view file_name) {
     Annotate(varname, varname, file_name);
   }
 
@@ -230,158 +741,203 @@
   // the last call to Print to the file with path file_name. The range begins
   // at begin_varname's value and ends after the last character of the value
   // substituted for end_varname.
-  void Annotate(const char* begin_varname, const char* end_varname,
-                const std::string& file_name) {
-    if (annotation_collector_ == NULL) {
-      // Annotations aren't turned on for this Printer.
+  void Annotate(absl::string_view begin_varname, absl::string_view end_varname,
+                absl::string_view file_name) {
+    if (options_.annotation_collector == nullptr) {
       return;
     }
-    std::vector<int> empty_path;
-    Annotate(begin_varname, end_varname, file_name, empty_path);
+
+    Annotate(begin_varname, end_varname, file_name, {});
   }
 
-  // Print some text after applying variable substitutions.  If a particular
-  // variable in the text is not defined, this will crash.  Variables to be
-  // substituted are identified by their names surrounded by delimiter
-  // characters (as given to the constructor).  The variable bindings are
-  // defined by the given map.
-  void Print(const std::map<std::string, std::string>& variables,
-             const char* text);
+  // Indent text by `options.spaces_per_indent`; undone by Outdent().
+  void Indent() { indent_ += options_.spaces_per_indent; }
 
-  // Like the first Print(), except the substitutions are given as parameters.
-  template <typename... Args>
-  void Print(const char* text, const Args&... args) {
-    std::map<std::string, std::string> vars;
-    PrintInternal(&vars, text, args...);
-  }
-
-  // Indent text by two spaces.  After calling Indent(), two spaces will be
-  // inserted at the beginning of each line of text.  Indent() may be called
-  // multiple times to produce deeper indents.
-  void Indent();
-
-  // Reduces the current indent level by two spaces, or crashes if the indent
-  // level is zero.
+  // Undoes a call to Indent().
   void Outdent();
 
-  // Write a string to the output buffer.
-  // This method does not look for newlines to add indentation.
-  void PrintRaw(const std::string& data);
-
-  // Write a zero-delimited string to output buffer.
-  // This method does not look for newlines to add indentation.
-  void PrintRaw(const char* data);
-
-  // Write some bytes to the output buffer.
-  // This method does not look for newlines to add indentation.
-  void WriteRaw(const char* data, int size);
-
   // FormatInternal is a helper function not meant to use directly, use
-  // compiler::cpp::Formatter instead. This function is meant to support
-  // formatting text using named variables (eq. "$foo$) from a lookup map (vars)
-  // and variables directly supplied by arguments (eq "$1$" meaning first
-  // argument which is the zero index element of args).
-  void FormatInternal(const std::vector<std::string>& args,
-                      const std::map<std::string, std::string>& vars,
-                      const char* format);
+  // compiler::cpp::Formatter instead.
+  template <typename Map = absl::flat_hash_map<std::string, std::string>>
+  void FormatInternal(absl::Span<const std::string> args, const Map& vars,
+                      absl::string_view format) {
+    PrintOptions opts;
+    opts.use_curly_brace_substitutions = true;
+    opts.strip_spaces_around_vars = true;
 
-  // True if any write to the underlying stream failed.  (We don't just
-  // crash in this case because this is an I/O failure, not a programming
-  // error.)
-  bool failed() const { return failed_; }
+    auto pop = WithVars(&vars);
+    PrintImpl(format, args, opts);
+  }
 
  private:
-  // Link the output range defined by the substitution variables as emitted by
-  // the last call to Print to the object found at the SourceCodeInfo-style path
-  // in a file with path file_path. The range begins at the start of
-  // begin_varname's value and ends after the last character of the value
-  // substituted for end_varname. Note that begin_varname and end_varname
-  // may refer to the same variable.
-  void Annotate(const char* begin_varname, const char* end_varname,
-                const std::string& file_path, const std::vector<int>& path);
+  // Options for PrintImpl().
+  struct PrintOptions {
+    // The callsite of the public entry-point. Only Emit() sets this.
+    absl::optional<SourceLocation> loc;
+    // If set, Validate() calls will not crash the program.
+    bool checks_are_debug_only = false;
+    // If set, the `substitutions_` map will be populated as variables are
+    // substituted.
+    bool use_substitution_map = false;
+    // If set, the ${1$ and $}$ forms will be substituted. These are used for
+    // a slightly janky annotation-insertion mechanism in FormatInternal, that
+    // requires that passed-in substitution variables be serialized protos.
+    bool use_curly_brace_substitutions = false;
+    // If set, the $n$ forms will be substituted, pulling from the `args`
+    // argument to PrintImpl().
+    bool allow_digit_substitutions = true;
+    // If set, when a variable substitution with spaces in it, such as $ var$,
+    // is encountered, the spaces are stripped, so that it is as if it was
+    // $var$. If $var$ substitutes to a non-empty string, the removed spaces are
+    // printed around the substituted value.
+    //
+    // See the class documentation for more information on this behavior.
+    bool strip_spaces_around_vars = true;
+    // If set, leading whitespace will be stripped from the format string to
+    // determine the "extraneous indentation" that is produced when the format
+    // string is a C++ raw string. This is used to remove leading spaces from
+    // a raw string that would otherwise result in erratic indentation in the
+    // output.
+    bool strip_raw_string_indentation = false;
+    // If set, the annotation lookup frames are searched, per the annotation
+    // semantics of Emit() described in the class documentation.
+    bool use_annotation_frames = true;
+  };
 
-  // Base case
-  void PrintInternal(std::map<std::string, std::string>* vars,
-                     const char* text) {
-    Print(*vars, text);
-  }
+  // Emit an annotation for the range defined by the given substitution
+  // variables, as set by the most recent call to PrintImpl() that set
+  // `use_substitution_map` to true.
+  //
+  // The range begins at the start of `begin_varname`'s value and ends after the
+  // last byte of `end_varname`'s value.
+  //
+  // `begin_varname` and `end_varname may` refer to the same variable.
+  void Annotate(absl::string_view begin_varname, absl::string_view end_varname,
+                absl::string_view file_path, const std::vector<int>& path);
 
-  template <typename... Args>
-  void PrintInternal(std::map<std::string, std::string>* vars, const char* text,
-                     const char* key, const std::string& value,
-                     const Args&... args) {
-    (*vars)[key] = value;
-    PrintInternal(vars, text, args...);
-  }
+  // The core printing implementation. There are three public entry points,
+  // which enable different slices of functionality that are controlled by the
+  // `opts` argument.
+  void PrintImpl(absl::string_view format, absl::Span<const std::string> args,
+                 PrintOptions opts);
 
-  // Copy size worth of bytes from data to buffer_.
-  void CopyToBuffer(const char* data, int size);
+  // This is a private function only so that it can see PrintOptions.
+  static bool Validate(bool cond, PrintOptions opts,
+                       absl::FunctionRef<std::string()> message);
+  static bool Validate(bool cond, PrintOptions opts, absl::string_view message);
 
-  void push_back(char c) {
-    if (failed_) return;
-    if (buffer_size_ == 0) {
-      if (!Next()) return;
-    }
-    *buffer_++ = c;
-    buffer_size_--;
-    offset_++;
-  }
+  // Performs calls to `Validate()` to check that `index < current_arg_index`
+  // and `index < args_len`, producing appropriate log lines if the checks fail,
+  // and crashing if necessary.
+  bool ValidateIndexLookupInBounds(size_t index, size_t current_arg_index,
+                                   size_t args_len, PrintOptions opts);
 
-  bool Next();
+  // Prints indentation if `at_start_of_line_` is true.
+  void IndentIfAtStart();
 
-  inline void IndentIfAtStart();
-  const char* WriteVariable(
-      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);
+  // Prints a codegen trace, for the given location in the compiler's source.
+  void PrintCodegenTrace(absl::optional<SourceLocation> loc);
 
-  const char variable_delimiter_;
+  // The core implementation for "fully-elaborated" variable definitions. This
+  // is a private function to avoid users being able to set `allow_callbacks`.
+  template <typename K, bool allow_callbacks>
+  auto WithDefs(std::initializer_list<VarDefinition<K, allow_callbacks>> vars);
 
-  ZeroCopyOutputStream* const output_;
-  char* buffer_;
-  int buffer_size_;
-  // The current position, in bytes, in the output stream.  This is equivalent
-  // to the total number of bytes that have been written so far.  This value is
-  // used to calculate annotation ranges in the substitutions_ map below.
-  size_t offset_;
+  // Returns the start and end of the value that was substituted in place of
+  // the variable `varname` in the last call to PrintImpl() (with
+  // `use_substitution_map` set), if such a variable was substituted exactly
+  // once.
+  absl::optional<std::pair<size_t, size_t>> GetSubstitutionRange(
+      absl::string_view varname, PrintOptions opts);
 
-  std::string indent_;
-  bool at_start_of_line_;
-  bool failed_;
+  google::protobuf::io::zc_sink_internal::ZeroCopyStreamByteSink sink_;
+  Options options_;
+  size_t indent_ = 0;
+  bool at_start_of_line_ = true;
+  bool failed_ = false;
+
+  using LookupResult =
+      absl::optional<absl::variant<absl::string_view, std::function<void()>>>;
+
+  std::vector<std::function<LookupResult(absl::string_view)>> var_lookups_;
+
+  std::vector<
+      std::function<absl::optional<AnnotationRecord>(absl::string_view)>>
+      annotation_lookups_;
 
   // A map from variable name to [start, end) offsets in the output buffer.
-  // These refer to the offsets used for a variable after the last call to
-  // Print.  If a variable was used more than once, the entry used in
-  // this map is set to a negative-length span.  For singly-used variables, the
-  // start offset is the beginning of the substitution; the end offset is the
-  // last byte of the substitution plus one (such that (end - start) is the
-  // length of the substituted string).
-  std::map<std::string, std::pair<size_t, size_t> > substitutions_;
-
-  // Keeps track of the keys in substitutions_ that need to be updated when
+  //
+  // This stores the data looked up by GetSubstitutionRange().
+  std::map<std::string, std::pair<size_t, size_t>> substitutions_;
+  // Keeps track of the keys in `substitutions_` that need to be updated when
   // indents are inserted. These are keys that refer to the beginning of the
   // current line.
   std::vector<std::string> line_start_variables_;
-
-  // Returns true and sets range to the substitution range in the output for
-  // varname if varname was used once in the last call to Print. If varname
-  // was not used, or if it was used multiple times, returns false (and
-  // fails a debug assertion).
-  bool GetSubstitutionRange(const char* varname,
-                            std::pair<size_t, size_t>* range);
-
-  // If non-null, annotation_collector_ is used to store annotations about
-  // generated code.
-  AnnotationCollector* const annotation_collector_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Printer);
 };
 
+template <typename K, bool allow_callbacks>
+auto Printer::WithDefs(
+    std::initializer_list<VarDefinition<K, allow_callbacks>> vars) {
+  absl::flat_hash_map<K, absl::variant<std::string, std::function<void()>>>
+      var_map;
+  var_map.reserve(vars.size());
+
+  absl::flat_hash_map<K, AnnotationRecord> annotation_map;
+
+  for (auto& var : vars) {
+    auto result = var_map.insert({var.key, var.value});
+    GOOGLE_CHECK(result.second) << "repeated variable in Emit() or WithVars() call: \""
+                         << var.key << "\"";
+    if (var.annotation.has_value()) {
+      annotation_map.insert({var.key, *var.annotation});
+    }
+  }
+
+  var_lookups_.emplace_back(
+      [map = std::move(var_map)](absl::string_view var) -> LookupResult {
+        auto it = map.find(var);
+        if (it == map.end()) {
+          return absl::nullopt;
+        }
+        if (auto* str = absl::get_if<std::string>(&it->second)) {
+          return absl::string_view(*str);
+        }
+
+        auto* f = absl::get_if<std::function<void()>>(&it->second);
+        GOOGLE_CHECK(f != nullptr);
+        return *f;
+      });
+
+  bool has_annotations = !annotation_map.empty();
+  if (has_annotations) {
+    annotation_lookups_.emplace_back(
+        [map = std::move(annotation_map)](
+            absl::string_view var) -> absl::optional<AnnotationRecord> {
+          auto it = map.find(var);
+          if (it == map.end()) {
+            return absl::nullopt;
+          }
+          return it->second;
+        });
+  }
+
+  return absl::MakeCleanup([this, has_annotations] {
+    var_lookups_.pop_back();
+    if (has_annotations) {
+      annotation_lookups_.pop_back();
+    }
+  });
+}
+
+inline auto Printer::WithVars(
+    std::initializer_list<VarDefinition<std::string, /*allow_callbacks=*/false>>
+        vars) {
+  return WithDefs(vars);
+}
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IO_PRINTER_H__
diff --git a/src/google/protobuf/io/printer_death_test.cc b/src/google/protobuf/io/printer_death_test.cc
new file mode 100644
index 0000000..5497168
--- /dev/null
+++ b/src/google/protobuf/io/printer_death_test.cc
@@ -0,0 +1,174 @@
+// 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.
+
+#include "google/protobuf/io/printer.h"
+
+#include <ostream>
+#include <string>
+#include <tuple>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.pb.h"
+#include <gmock/gmock.h>
+#include "google/protobuf/testing/googletest.h"
+#include <gtest/gtest.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.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"
+
+namespace google {
+namespace protobuf {
+namespace io {
+class PrinterTest : public testing::Test {
+ protected:
+  ZeroCopyOutputStream* output() {
+    GOOGLE_CHECK(stream_.has_value());
+    return &*stream_;
+  }
+  absl::string_view written() {
+    stream_.reset();
+    return out_;
+  }
+
+  std::string out_;
+  absl::optional<StringOutputStream> stream_{&out_};
+};
+
+// FakeDescriptorFile defines only those members that Printer uses to write out
+// annotations.
+struct FakeDescriptorFile {
+  const std::string& name() const { return filename; }
+  std::string filename;
+};
+
+// FakeDescriptor defines only those members that Printer uses to write out
+// annotations.
+struct FakeDescriptor {
+  const FakeDescriptorFile* file() const { return &fake_file; }
+  void GetLocationPath(std::vector<int>* output) const { *output = path; }
+
+  FakeDescriptorFile fake_file;
+  std::vector<int> path;
+};
+
+class FakeAnnotationCollector : public AnnotationCollector {
+ public:
+  ~FakeAnnotationCollector() override = default;
+
+  void AddAnnotation(size_t begin_offset, size_t end_offset,
+                     const std::string& file_path,
+                     const std::vector<int>& path) override {
+  }
+};
+
+#ifdef PROTOBUF_HAS_DEATH_TEST
+TEST_F(PrinterTest, Death) {
+  Printer printer(output(), '$');
+
+  EXPECT_DEBUG_DEATH(printer.Print("$nosuchvar$"), "");
+  EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "");
+  EXPECT_DEBUG_DEATH(printer.Outdent(), "");
+}
+
+TEST_F(PrinterTest, AnnotateMultipleUsesDeath) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+  printer.Print("012$foo$4$foo$\n", "foo", "3");
+
+  FakeDescriptor descriptor{{"path"}, {33}};
+  EXPECT_DEBUG_DEATH(printer.Annotate("foo", "foo", &descriptor), "");
+}
+
+TEST_F(PrinterTest, AnnotateNegativeLengthDeath) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+  printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+
+  FakeDescriptor descriptor{{"path"}, {33}};
+  EXPECT_DEBUG_DEATH(printer.Annotate("bar", "foo", &descriptor), "");
+}
+
+TEST_F(PrinterTest, AnnotateUndefinedDeath) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+  printer.Print("012$foo$4$foo$\n", "foo", "3");
+
+  FakeDescriptor descriptor{{"path"}, {33}};
+  EXPECT_DEBUG_DEATH(printer.Annotate("bar", "bar", &descriptor), "");
+}
+
+TEST_F(PrinterTest, FormatInternalUnusedArgs) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+
+  EXPECT_DEATH(printer.FormatInternal({"arg1", "arg2"}, {}, "$1$"), "");
+}
+
+TEST_F(PrinterTest, FormatInternalOutOfOrderArgs) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+
+  EXPECT_DEATH(printer.FormatInternal({"arg1", "arg2"}, {}, "$2$ $1$"), "");
+}
+
+TEST_F(PrinterTest, FormatInternalZeroArg) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+
+  EXPECT_DEATH(printer.FormatInternal({"arg1", "arg2"}, {}, "$0$"), "");
+}
+
+TEST_F(PrinterTest, FormatInternalOutOfBounds) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+
+  EXPECT_DEATH(printer.FormatInternal({"arg1", "arg2"}, {}, "$1$ $2$ $3$"), "");
+}
+
+TEST_F(PrinterTest, FormatInternalUnknownVar) {
+  FakeAnnotationCollector collector;
+  Printer printer(output(), '$', &collector);
+
+  EXPECT_DEATH(printer.FormatInternal({}, {}, "$huh$"), "");
+  EXPECT_DEATH(printer.FormatInternal({}, {}, "$ $"), "");
+}
+#endif  // PROTOBUF_HAS_DEATH_TEST
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/io/printer_unittest.cc b/src/google/protobuf/io/printer_unittest.cc
index ed54d1d..4e2dd7a 100644
--- a/src/google/protobuf/io/printer_unittest.cc
+++ b/src/google/protobuf/io/printer_unittest.cc
@@ -32,530 +32,388 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/io/printer.h>
+#include "google/protobuf/io/printer.h"
 
+#include <ostream>
+#include <string>
+#include <tuple>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.pb.h"
+#include <gmock/gmock.h>
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.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"
 
 namespace google {
 namespace protobuf {
 namespace io {
+using ::testing::AllOf;
+using ::testing::ElementsAre;
+using ::testing::ExplainMatchResult;
+using ::testing::Field;
+using ::testing::IsEmpty;
+using ::testing::MatchesRegex;
 
-// Each test repeats over several block sizes in order to test both cases
-// where particular writes cross a buffer boundary and cases where they do
-// not.
-
-TEST(Printer, EmptyPrinter) {
-  char buffer[8192];
-  const int block_size = 100;
-  ArrayOutputStream output(buffer, GOOGLE_ARRAYSIZE(buffer), block_size);
-  Printer printer(&output, '\0');
-  EXPECT_TRUE(!printer.failed());
-}
-
-TEST(Printer, BasicPrinting) {
-  char buffer[8192];
-
-  for (int block_size = 1; block_size < 512; block_size *= 2) {
-    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
-
-    {
-      Printer printer(&output, '\0');
-
-      printer.Print("Hello World!");
-      printer.Print("  This is the same line.\n");
-      printer.Print("But this is a new one.\nAnd this is another one.");
-
-      EXPECT_FALSE(printer.failed());
-    }
-
-    buffer[output.ByteCount()] = '\0';
-
-    EXPECT_STREQ(
-        "Hello World!  This is the same line.\n"
-        "But this is a new one.\n"
-        "And this is another one.",
-        buffer);
+class PrinterTest : public testing::Test {
+ protected:
+  ZeroCopyOutputStream* output() {
+    GOOGLE_CHECK(stream_.has_value());
+    return &*stream_;
   }
-}
-
-TEST(Printer, WriteRaw) {
-  char buffer[8192];
-
-  for (int block_size = 1; block_size < 512; block_size *= 2) {
-    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
-
-    {
-      std::string string_obj = "From an object\n";
-      Printer printer(&output, '$');
-      printer.WriteRaw("Hello World!", 12);
-      printer.PrintRaw("  This is the same line.\n");
-      printer.PrintRaw("But this is a new one.\nAnd this is another one.");
-      printer.WriteRaw("\n", 1);
-      printer.PrintRaw(string_obj);
-      EXPECT_FALSE(printer.failed());
-    }
-
-    buffer[output.ByteCount()] = '\0';
-
-    EXPECT_STREQ(
-        "Hello World!  This is the same line.\n"
-        "But this is a new one.\n"
-        "And this is another one."
-        "\n"
-        "From an object\n",
-        buffer);
+  absl::string_view written() {
+    stream_.reset();
+    return out_;
   }
+
+  std::string out_;
+  absl::optional<StringOutputStream> stream_{&out_};
+};
+
+TEST_F(PrinterTest, EmptyPrinter) {
+  Printer printer(output(), '\0');
+  EXPECT_FALSE(printer.failed());
 }
 
-TEST(Printer, VariableSubstitution) {
-  char buffer[8192];
-
-  for (int block_size = 1; block_size < 512; block_size *= 2) {
-    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
-
-    {
-      Printer printer(&output, '$');
-      std::map<std::string, std::string> vars;
-
-      vars["foo"] = "World";
-      vars["bar"] = "$foo$";
-      vars["abcdefg"] = "1234";
-
-      printer.Print(vars, "Hello $foo$!\nbar = $bar$\n");
-      printer.PrintRaw("RawBit\n");
-      printer.Print(vars, "$abcdefg$\nA literal dollar sign:  $$");
-
-      vars["foo"] = "blah";
-      printer.Print(vars, "\nNow foo = $foo$.");
-
-      EXPECT_FALSE(printer.failed());
-    }
-
-    buffer[output.ByteCount()] = '\0';
-
-    EXPECT_STREQ(
-        "Hello World!\n"
-        "bar = $foo$\n"
-        "RawBit\n"
-        "1234\n"
-        "A literal dollar sign:  $\n"
-        "Now foo = blah.",
-        buffer);
-  }
-}
-
-TEST(Printer, InlineVariableSubstitution) {
-  char buffer[8192];
-
-  ArrayOutputStream output(buffer, sizeof(buffer));
-
+TEST_F(PrinterTest, BasicPrinting) {
   {
-    Printer printer(&output, '$');
+    Printer printer(output(), '\0');
+
+    printer.Print("Hello World!");
+    printer.Print("  This is the same line.\n");
+    printer.Print("But this is a new one.\nAnd this is another one.");
+    EXPECT_FALSE(printer.failed());
+  }
+
+  EXPECT_EQ(written(),
+            "Hello World!  This is the same line.\n"
+            "But this is a new one.\n"
+            "And this is another one.");
+}
+
+TEST_F(PrinterTest, WriteRaw) {
+  {
+    absl::string_view string_obj = "From an object\n";
+    Printer printer(output(), '$');
+    printer.WriteRaw("Hello World!", 12);
+    printer.PrintRaw("  This is the same line.\n");
+    printer.PrintRaw("But this is a new one.\nAnd this is another one.");
+    printer.WriteRaw("\n", 1);
+    printer.PrintRaw(string_obj);
+    EXPECT_FALSE(printer.failed());
+  }
+
+  EXPECT_EQ(written(),
+            "Hello World!  This is the same line.\n"
+            "But this is a new one.\n"
+            "And this is another one."
+            "\n"
+            "From an object\n");
+}
+
+TEST_F(PrinterTest, VariableSubstitution) {
+  {
+    Printer printer(output(), '$');
+
+    absl::flat_hash_map<std::string, std::string> vars{
+        {"foo", "World"},
+        {"bar", "$foo$"},
+        {"abcdefg", "1234"},
+    };
+
+    printer.Print(vars, "Hello $foo$!\nbar = $bar$\n");
+    printer.PrintRaw("RawBit\n");
+    printer.Print(vars, "$abcdefg$\nA literal dollar sign:  $$");
+
+    vars["foo"] = "blah";
+    printer.Print(vars, "\nNow foo = $foo$.");
+
+    EXPECT_FALSE(printer.failed());
+  }
+
+  EXPECT_EQ(written(),
+            "Hello World!\n"
+            "bar = $foo$\n"
+            "RawBit\n"
+            "1234\n"
+            "A literal dollar sign:  $\n"
+            "Now foo = blah.");
+}
+
+TEST_F(PrinterTest, InlineVariableSubstitution) {
+  {
+    Printer printer(output(), '$');
     printer.Print("Hello $foo$!\n", "foo", "World");
     printer.PrintRaw("RawBit\n");
     printer.Print("$foo$ $bar$\n", "foo", "one", "bar", "two");
     EXPECT_FALSE(printer.failed());
   }
 
-  buffer[output.ByteCount()] = '\0';
-
-  EXPECT_STREQ(
-      "Hello World!\n"
-      "RawBit\n"
-      "one two\n",
-      buffer);
+  EXPECT_EQ(written(),
+            "Hello World!\n"
+            "RawBit\n"
+            "one two\n");
 }
 
-// MockDescriptorFile defines only those members that Printer uses to write out
+// FakeDescriptorFile defines only those members that Printer uses to write out
 // annotations.
-class MockDescriptorFile {
- public:
-  explicit MockDescriptorFile(const std::string& file) : file_(file) {}
-
-  // The mock filename for this file.
-  const std::string& name() const { return file_; }
-
- private:
-  std::string file_;
+struct FakeDescriptorFile {
+  const std::string& name() const { return filename; }
+  std::string filename;
 };
 
-// MockDescriptor defines only those members that Printer uses to write out
+// FakeDescriptor defines only those members that Printer uses to write out
 // annotations.
-class MockDescriptor {
- public:
-  MockDescriptor(const std::string& file, const std::vector<int>& path)
-      : file_(file), path_(path) {}
+struct FakeDescriptor {
+  const FakeDescriptorFile* file() const { return &fake_file; }
+  void GetLocationPath(std::vector<int>* output) const { *output = path; }
 
-  // The mock file in which this descriptor was defined.
-  const MockDescriptorFile* file() const { return &file_; }
-
- private:
-  // Allows access to GetLocationPath.
-  friend class Printer;
-
-  // Copies the pre-stored path to output.
-  void GetLocationPath(std::vector<int>* output) const { *output = path_; }
-
-  MockDescriptorFile file_;
-  std::vector<int> path_;
+  FakeDescriptorFile fake_file;
+  std::vector<int> path;
 };
 
-TEST(Printer, AnnotateMap) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    std::map<std::string, std::string> vars;
-    vars["foo"] = "3";
-    vars["bar"] = "5";
-    printer.Print(vars, "012$foo$4$bar$\n");
-    std::vector<int> path_1;
-    path_1.push_back(33);
-    std::vector<int> path_2;
-    path_2.push_back(11);
-    path_2.push_back(22);
-    MockDescriptor descriptor_1("path_1", path_1);
-    MockDescriptor descriptor_2("path_2", path_2);
-    printer.Annotate("foo", "foo", &descriptor_1);
-    printer.Annotate("bar", "bar", &descriptor_2);
+class FakeAnnotationCollector : public AnnotationCollector {
+ public:
+  ~FakeAnnotationCollector() override = default;
+
+  // Records that the bytes in file_path beginning with begin_offset and ending
+  // before end_offset are associated with the SourceCodeInfo-style path.
+  void AddAnnotation(size_t begin_offset, size_t end_offset,
+                     const std::string& file_path,
+                     const std::vector<int>& path) override {
+    annotations_.emplace_back(
+        Record{begin_offset, end_offset, file_path, path});
   }
-  buffer[output.ByteCount()] = '\0';
-  EXPECT_STREQ("012345\n", buffer);
-  ASSERT_EQ(2, info.annotation_size());
-  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
-                                                 ? &info.annotation(0)
-                                                 : &info.annotation(1);
-  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
-                                                 ? &info.annotation(1)
-                                                 : &info.annotation(0);
-  ASSERT_EQ(1, foo->path_size());
-  ASSERT_EQ(2, bar->path_size());
-  EXPECT_EQ(33, foo->path(0));
-  EXPECT_EQ(11, bar->path(0));
-  EXPECT_EQ(22, bar->path(1));
-  EXPECT_EQ("path_1", foo->source_file());
-  EXPECT_EQ("path_2", bar->source_file());
-  EXPECT_EQ(3, foo->begin());
-  EXPECT_EQ(4, foo->end());
-  EXPECT_EQ(5, bar->begin());
-  EXPECT_EQ(6, bar->end());
-}
 
-TEST(Printer, AnnotateInline) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
-    std::vector<int> path_1;
-    path_1.push_back(33);
-    std::vector<int> path_2;
-    path_2.push_back(11);
-    path_2.push_back(22);
-    MockDescriptor descriptor_1("path_1", path_1);
-    MockDescriptor descriptor_2("path_2", path_2);
-    printer.Annotate("foo", "foo", &descriptor_1);
-    printer.Annotate("bar", "bar", &descriptor_2);
-  }
-  buffer[output.ByteCount()] = '\0';
-  EXPECT_STREQ("012345\n", buffer);
-  ASSERT_EQ(2, info.annotation_size());
-  const GeneratedCodeInfo::Annotation* foo = info.annotation(0).path_size() == 1
-                                                 ? &info.annotation(0)
-                                                 : &info.annotation(1);
-  const GeneratedCodeInfo::Annotation* bar = info.annotation(0).path_size() == 1
-                                                 ? &info.annotation(1)
-                                                 : &info.annotation(0);
-  ASSERT_EQ(1, foo->path_size());
-  ASSERT_EQ(2, bar->path_size());
-  EXPECT_EQ(33, foo->path(0));
-  EXPECT_EQ(11, bar->path(0));
-  EXPECT_EQ(22, bar->path(1));
-  EXPECT_EQ("path_1", foo->source_file());
-  EXPECT_EQ("path_2", bar->source_file());
-  EXPECT_EQ(3, foo->begin());
-  EXPECT_EQ(4, foo->end());
-  EXPECT_EQ(5, bar->begin());
-  EXPECT_EQ(6, bar->end());
-}
+  void AddAnnotationNew(Annotation& a) override {
+    GeneratedCodeInfo::Annotation annotation;
+    annotation.ParseFromString(a.second);
 
-TEST(Printer, AnnotateRange) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
-    std::vector<int> path;
-    path.push_back(33);
-    MockDescriptor descriptor("path", path);
-    printer.Annotate("foo", "bar", &descriptor);
-  }
-  buffer[output.ByteCount()] = '\0';
-  EXPECT_STREQ("012345\n", buffer);
-  ASSERT_EQ(1, info.annotation_size());
-  const GeneratedCodeInfo::Annotation* foobar = &info.annotation(0);
-  ASSERT_EQ(1, foobar->path_size());
-  EXPECT_EQ(33, foobar->path(0));
-  EXPECT_EQ("path", foobar->source_file());
-  EXPECT_EQ(3, foobar->begin());
-  EXPECT_EQ(6, foobar->end());
-}
-
-TEST(Printer, AnnotateEmptyRange) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    printer.Print("012$foo$4$baz$$bam$$bar$\n", "foo", "3", "bar", "5", "baz",
-                  "", "bam", "");
-    std::vector<int> path;
-    path.push_back(33);
-    MockDescriptor descriptor("path", path);
-    printer.Annotate("baz", "bam", &descriptor);
-  }
-  buffer[output.ByteCount()] = '\0';
-  EXPECT_STREQ("012345\n", buffer);
-  ASSERT_EQ(1, info.annotation_size());
-  const GeneratedCodeInfo::Annotation* bazbam = &info.annotation(0);
-  ASSERT_EQ(1, bazbam->path_size());
-  EXPECT_EQ(33, bazbam->path(0));
-  EXPECT_EQ("path", bazbam->source_file());
-  EXPECT_EQ(5, bazbam->begin());
-  EXPECT_EQ(5, bazbam->end());
-}
-
-TEST(Printer, AnnotateDespiteUnrelatedMultipleUses) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    printer.Print("012$foo$4$foo$$bar$\n", "foo", "3", "bar", "5");
-    std::vector<int> path;
-    path.push_back(33);
-    MockDescriptor descriptor("path", path);
-    printer.Annotate("bar", "bar", &descriptor);
-  }
-  buffer[output.ByteCount()] = '\0';
-  EXPECT_STREQ("0123435\n", buffer);
-  ASSERT_EQ(1, info.annotation_size());
-  const GeneratedCodeInfo::Annotation* bar = &info.annotation(0);
-  ASSERT_EQ(1, bar->path_size());
-  EXPECT_EQ(33, bar->path(0));
-  EXPECT_EQ("path", bar->source_file());
-  EXPECT_EQ(6, bar->begin());
-  EXPECT_EQ(7, bar->end());
-}
-
-TEST(Printer, AnnotateIndent) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    printer.Print("0\n");
-    printer.Indent();
-    printer.Print("$foo$", "foo", "4");
-    std::vector<int> path;
-    path.push_back(44);
-    MockDescriptor descriptor("path", path);
-    printer.Annotate("foo", &descriptor);
-    printer.Print(",\n");
-    printer.Print("$bar$", "bar", "9");
-    path[0] = 99;
-    MockDescriptor descriptor_two("path", path);
-    printer.Annotate("bar", &descriptor_two);
-    printer.Print("\n${$$D$$}$\n", "{", "", "}", "", "D", "d");
-    path[0] = 1313;
-    MockDescriptor descriptor_three("path", path);
-    printer.Annotate("{", "}", &descriptor_three);
-    printer.Outdent();
-    printer.Print("\n");
-  }
-  buffer[output.ByteCount()] = '\0';
-  EXPECT_STREQ("0\n  4,\n  9\n  d\n\n", buffer);
-  ASSERT_EQ(3, info.annotation_size());
-  const GeneratedCodeInfo::Annotation* foo = &info.annotation(0);
-  ASSERT_EQ(1, foo->path_size());
-  EXPECT_EQ(44, foo->path(0));
-  EXPECT_EQ("path", foo->source_file());
-  EXPECT_EQ(4, foo->begin());
-  EXPECT_EQ(5, foo->end());
-  const GeneratedCodeInfo::Annotation* bar = &info.annotation(1);
-  ASSERT_EQ(1, bar->path_size());
-  EXPECT_EQ(99, bar->path(0));
-  EXPECT_EQ("path", bar->source_file());
-  EXPECT_EQ(9, bar->begin());
-  EXPECT_EQ(10, bar->end());
-  const GeneratedCodeInfo::Annotation* braces = &info.annotation(2);
-  ASSERT_EQ(1, braces->path_size());
-  EXPECT_EQ(1313, braces->path(0));
-  EXPECT_EQ("path", braces->source_file());
-  EXPECT_EQ(13, braces->begin());
-  EXPECT_EQ(14, braces->end());
-}
-
-TEST(Printer, AnnotateIndentNewline) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    printer.Indent();
-    printer.Print("$A$$N$$B$C\n", "A", "", "N", "\nz", "B", "");
-    std::vector<int> path;
-    path.push_back(0);
-    MockDescriptor descriptor("path", path);
-    printer.Annotate("A", "B", &descriptor);
-    printer.Outdent();
-    printer.Print("\n");
-  }
-  buffer[output.ByteCount()] = '\0';
-  EXPECT_STREQ("\nz  C\n\n", buffer);
-  ASSERT_EQ(1, info.annotation_size());
-  const GeneratedCodeInfo::Annotation* ab = &info.annotation(0);
-  ASSERT_EQ(1, ab->path_size());
-  EXPECT_EQ(0, ab->path(0));
-  EXPECT_EQ("path", ab->source_file());
-  EXPECT_EQ(0, ab->begin());
-  EXPECT_EQ(4, ab->end());
-}
-
-TEST(Printer, Indenting) {
-  char buffer[8192];
-
-  for (int block_size = 1; block_size < 512; block_size *= 2) {
-    ArrayOutputStream output(buffer, sizeof(buffer), block_size);
-
-    {
-      Printer printer(&output, '$');
-      std::map<std::string, std::string> vars;
-
-      vars["newline"] = "\n";
-
-      printer.Print("This is not indented.\n");
-      printer.Indent();
-      printer.Print("This is indented\nAnd so is this\n");
-      printer.Outdent();
-      printer.Print("But this is not.");
-      printer.Indent();
-      printer.Print(
-          "  And this is still the same line.\n"
-          "But this is indented.\n");
-      printer.PrintRaw("RawBit has indent at start\n");
-      printer.PrintRaw("but not after a raw newline\n");
-      printer.Print(vars,
-                    "Note that a newline in a variable will break "
-                    "indenting, as we see$newline$here.\n");
-      printer.Indent();
-      printer.Print("And this");
-      printer.Outdent();
-      printer.Outdent();
-      printer.Print(" is double-indented\nBack to normal.");
-
-      EXPECT_FALSE(printer.failed());
+    Record r{a.first.first, a.first.second, annotation.source_file(), {}};
+    for (int i : annotation.path()) {
+      r.path.push_back(i);
     }
 
-    buffer[output.ByteCount()] = '\0';
-
-    EXPECT_STREQ(
-        "This is not indented.\n"
-        "  This is indented\n"
-        "  And so is this\n"
-        "But this is not.  And this is still the same line.\n"
-        "  But this is indented.\n"
-        "  RawBit has indent at start\n"
-        "but not after a raw newline\n"
-        "Note that a newline in a variable will break indenting, as we see\n"
-        "here.\n"
-        "    And this is double-indented\n"
-        "Back to normal.",
-        buffer);
+    annotations_.emplace_back(r);
   }
-}
 
-// Death tests do not work on Windows as of yet.
-#ifdef PROTOBUF_HAS_DEATH_TEST
-TEST(Printer, Death) {
-  char buffer[8192];
-
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  Printer printer(&output, '$');
-
-  EXPECT_DEBUG_DEATH(printer.Print("$nosuchvar$"), "Undefined variable");
-  EXPECT_DEBUG_DEATH(printer.Print("$unclosed"), "Unclosed variable name");
-  EXPECT_DEBUG_DEATH(printer.Outdent(), "without matching Indent");
-}
-
-TEST(Printer, AnnotateMultipleUsesDeath) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-  {
-    Printer printer(&output, '$', &info_collector);
-    printer.Print("012$foo$4$foo$\n", "foo", "3");
+  struct Record {
+    size_t start, end;
+    std::string file_path;
     std::vector<int> path;
-    path.push_back(33);
-    MockDescriptor descriptor("path", path);
-    EXPECT_DEBUG_DEATH(printer.Annotate("foo", "foo", &descriptor), "multiple");
-  }
+
+    friend std::ostream& operator<<(std::ostream& out, const Record& record) {
+      return out << "Record{" << record.start << ", " << record.end << ", \""
+                 << record.file_path << "\", ["
+                 << absl::StrJoin(record.path, ", ") << "]}";
+    }
+  };
+
+  absl::Span<const Record> Get() const { return annotations_; }
+
+ private:
+  std::vector<Record> annotations_;
+};
+
+template <typename Start, typename End, typename FilePath, typename Path>
+testing::Matcher<FakeAnnotationCollector::Record> Annotation(Start start,
+                                                             End end,
+                                                             FilePath file_path,
+                                                             Path path) {
+  return AllOf(Field("start", &FakeAnnotationCollector::Record::start, start),
+               Field("end", &FakeAnnotationCollector::Record::end, end),
+               Field("file_path", &FakeAnnotationCollector::Record::file_path,
+                     file_path),
+               Field("path", &FakeAnnotationCollector::Record::path, path));
 }
 
-TEST(Printer, AnnotateNegativeLengthDeath) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+TEST_F(PrinterTest, AnnotateMap) {
+  FakeAnnotationCollector collector;
   {
-    Printer printer(&output, '$', &info_collector);
+    Printer printer(output(), '$', &collector);
+    absl::flat_hash_map<std::string, std::string> vars = {{"foo", "3"},
+                                                          {"bar", "5"}};
+    printer.Print(vars, "012$foo$4$bar$\n");
+
+    FakeDescriptor descriptor_1{{"path_1"}, {33}};
+    FakeDescriptor descriptor_2{{"path_2"}, {11, 22}};
+    printer.Annotate("foo", "foo", &descriptor_1);
+    printer.Annotate("bar", "bar", &descriptor_2);
+  }
+
+  EXPECT_EQ(written(), "012345\n");
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(3, 4, "path_1", ElementsAre(33)),
+                          Annotation(5, 6, "path_2", ElementsAre(11, 22))));
+}
+
+TEST_F(PrinterTest, AnnotateInline) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
     printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
-    std::vector<int> path;
-    path.push_back(33);
-    MockDescriptor descriptor("path", path);
-    EXPECT_DEBUG_DEATH(printer.Annotate("bar", "foo", &descriptor), "negative");
+
+    FakeDescriptor descriptor_1{{"path_1"}, {33}};
+    FakeDescriptor descriptor_2{{"path_2"}, {11, 22}};
+    printer.Annotate("foo", "foo", &descriptor_1);
+    printer.Annotate("bar", "bar", &descriptor_2);
   }
+
+  EXPECT_EQ(written(), "012345\n");
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(3, 4, "path_1", ElementsAre(33)),
+                          Annotation(5, 6, "path_2", ElementsAre(11, 22))));
 }
 
-TEST(Printer, AnnotateUndefinedDeath) {
-  char buffer[8192];
-  ArrayOutputStream output(buffer, sizeof(buffer));
-  GeneratedCodeInfo info;
-  AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
+TEST_F(PrinterTest, AnnotateRange) {
+  FakeAnnotationCollector collector;
   {
-    Printer printer(&output, '$', &info_collector);
-    printer.Print("012$foo$4$foo$\n", "foo", "3");
-    std::vector<int> path;
-    path.push_back(33);
-    MockDescriptor descriptor("path", path);
-    EXPECT_DEBUG_DEATH(printer.Annotate("bar", "bar", &descriptor),
-                       "Undefined");
+    Printer printer(output(), '$', &collector);
+    printer.Print("012$foo$4$bar$\n", "foo", "3", "bar", "5");
+
+    FakeDescriptor descriptor{{"path"}, {33}};
+    printer.Annotate("foo", "bar", &descriptor);
   }
+
+  EXPECT_EQ(written(), "012345\n");
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(3, 6, "path", ElementsAre(33))));
 }
-#endif  // PROTOBUF_HAS_DEATH_TEST
 
-TEST(Printer, WriteFailurePartial) {
-  char buffer[17];
+TEST_F(PrinterTest, AnnotateEmptyRange) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
+    printer.Print("012$foo$4$baz$$bam$$bar$\n", "foo", "3", "bar", "5", "baz",
+                  "", "bam", "");
 
-  ArrayOutputStream output(buffer, sizeof(buffer));
+    FakeDescriptor descriptor{{"path"}, {33}};
+    printer.Annotate("baz", "bam", &descriptor);
+  }
+
+  EXPECT_EQ(written(), "012345\n");
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(5, 5, "path", ElementsAre(33))));
+}
+
+TEST_F(PrinterTest, AnnotateDespiteUnrelatedMultipleUses) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
+    printer.Print("012$foo$4$foo$$bar$\n", "foo", "3", "bar", "5");
+
+    FakeDescriptor descriptor{{"path"}, {33}};
+    printer.Annotate("bar", "bar", &descriptor);
+  }
+
+  EXPECT_EQ(written(), "0123435\n");
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(6, 7, "path", ElementsAre(33))));
+}
+
+TEST_F(PrinterTest, AnnotateIndent) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
+    printer.Print("0\n");
+    printer.Indent();
+
+    printer.Print("$foo$", "foo", "4");
+    FakeDescriptor descriptor1{{"path"}, {44}};
+    printer.Annotate("foo", &descriptor1);
+
+    printer.Print(",\n");
+    printer.Print("$bar$", "bar", "9");
+    FakeDescriptor descriptor2{{"path"}, {99}};
+    printer.Annotate("bar", &descriptor2);
+
+    printer.Print("\n${$$D$$}$\n", "{", "", "}", "", "D", "d");
+    FakeDescriptor descriptor3{{"path"}, {1313}};
+    printer.Annotate("{", "}", &descriptor3);
+
+    printer.Outdent();
+    printer.Print("\n");
+  }
+
+  EXPECT_EQ(written(), "0\n  4,\n  9\n  d\n\n");
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(4, 5, "path", ElementsAre(44)),
+                          Annotation(9, 10, "path", ElementsAre(99)),
+                          Annotation(13, 14, "path", ElementsAre(1313))));
+}
+
+TEST_F(PrinterTest, AnnotateIndentNewline) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
+    printer.Indent();
+
+    printer.Print("$A$$N$$B$C\n", "A", "", "N", "\nz", "B", "");
+    FakeDescriptor descriptor{{"path"}, {0}};
+    printer.Annotate("A", "B", &descriptor);
+
+    printer.Outdent();
+    printer.Print("\n");
+  }
+  EXPECT_EQ(written(), "\nz  C\n\n");
+
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(0, 4, "path", ElementsAre(0))));
+}
+
+TEST_F(PrinterTest, Indenting) {
+  {
+    Printer printer(output(), '$');
+    absl::flat_hash_map<std::string, std::string> vars = {{"newline", "\n"}};
+
+    printer.Print("This is not indented.\n");
+    printer.Indent();
+    printer.Print("This is indented\nAnd so is this\n");
+    printer.Outdent();
+    printer.Print("But this is not.");
+    printer.Indent();
+    printer.Print(
+        "  And this is still the same line.\n"
+        "But this is indented.\n");
+    printer.PrintRaw("RawBit has indent at start\n");
+    printer.PrintRaw("but not after a raw newline\n");
+    printer.Print(vars,
+                  "Note that a newline in a variable will break "
+                  "indenting, as we see$newline$here.\n");
+    printer.Indent();
+    printer.Print("And this");
+    printer.Outdent();
+    printer.Outdent();
+    printer.Print(" is double-indented\nBack to normal.");
+
+    EXPECT_FALSE(printer.failed());
+  }
+
+  EXPECT_EQ(
+      written(),
+      "This is not indented.\n"
+      "  This is indented\n"
+      "  And so is this\n"
+      "But this is not.  And this is still the same line.\n"
+      "  But this is indented.\n"
+      "  RawBit has indent at start\n"
+      "but not after a raw newline\n"
+      "Note that a newline in a variable will break indenting, as we see\n"
+      "here.\n"
+      "    And this is double-indented\n"
+      "Back to normal.");
+}
+
+TEST_F(PrinterTest, WriteFailurePartial) {
+  std::string buffer(17, '\xaa');
+  ArrayOutputStream output(&buffer[0], buffer.size());
   Printer printer(&output, '$');
 
   // Print 16 bytes to almost fill the buffer (should not fail).
@@ -573,13 +431,12 @@
   EXPECT_TRUE(printer.failed());
 
   // Buffer should contain the first 17 bytes written.
-  EXPECT_EQ("0123456789abcdef<", std::string(buffer, sizeof(buffer)));
+  EXPECT_EQ(buffer, "0123456789abcdef<");
 }
 
-TEST(Printer, WriteFailureExact) {
-  char buffer[16];
-
-  ArrayOutputStream output(buffer, sizeof(buffer));
+TEST_F(PrinterTest, WriteFailureExact) {
+  std::string buffer(16, '\xaa');
+  ArrayOutputStream output(&buffer[0], buffer.size());
   Printer printer(&output, '$');
 
   // Print 16 bytes to fill the buffer exactly (should not fail).
@@ -595,139 +452,358 @@
   EXPECT_TRUE(printer.failed());
 
   // Buffer should contain the first 16 bytes written.
-  EXPECT_EQ("0123456789abcdef", std::string(buffer, sizeof(buffer)));
+  EXPECT_EQ(buffer, "0123456789abcdef");
 }
 
-TEST(Printer, FormatInternal) {
-  std::vector<std::string> args{"arg1", "arg2"};
-  std::map<std::string, std::string> vars{
-      {"foo", "bar"}, {"baz", "bla"}, {"empty", ""}};
-  // Substitution tests
+TEST_F(PrinterTest, FormatInternalDirectSub) {
   {
-    // Direct arg substitution
-    std::string s;
-    {
-      StringOutputStream output(&s);
-      Printer printer(&output, '$');
-      printer.FormatInternal(args, vars, "$1$ $2$");
-    }
-    EXPECT_EQ("arg1 arg2", s);
+    Printer printer(output(), '$');
+    printer.FormatInternal({"arg1", "arg2"}, {}, "$1$ $2$");
   }
+  EXPECT_EQ(written(), "arg1 arg2");
+}
+
+TEST_F(PrinterTest, FormatInternalSubWithSpacesLeft) {
   {
-    // Variable substitution including spaces left
-    std::string s;
-    {
-      StringOutputStream output(&s);
-      Printer printer(&output, '$');
-      printer.FormatInternal({}, vars, "$foo$$ baz$$ empty$");
-    }
-    EXPECT_EQ("bar bla", s);
+    Printer printer(output(), '$');
+    printer.FormatInternal({}, {{"foo", "bar"}, {"baz", "bla"}, {"empty", ""}},
+                           "$foo$$ baz$$ empty$");
   }
+  EXPECT_EQ(written(), "bar bla");
+}
+
+TEST_F(PrinterTest, FormatInternalSubWithSpacesRight) {
   {
-    // Variable substitution including spaces right
-    std::string s;
-    {
-      StringOutputStream output(&s);
-      Printer printer(&output, '$');
-      printer.FormatInternal({}, vars, "$empty $$foo $$baz$");
-    }
-    EXPECT_EQ("bar bla", s);
+    Printer printer(output(), '$');
+    printer.FormatInternal({}, {{"foo", "bar"}, {"baz", "bla"}, {"empty", ""}},
+                           "$empty $$foo $$baz$");
   }
+  EXPECT_EQ(written(), "bar bla");
+}
+
+TEST_F(PrinterTest, FormatInternalSubMixed) {
   {
-    // Mixed variable substitution
-    std::string s;
-    {
-      StringOutputStream output(&s);
-      Printer printer(&output, '$');
-      printer.FormatInternal(args, vars, "$empty $$1$ $foo $$2$ $baz$");
-    }
-    EXPECT_EQ("arg1 bar arg2 bla", s);
+    Printer printer(output(), '$');
+    printer.FormatInternal({"arg1", "arg2"},
+                           {{"foo", "bar"}, {"baz", "bla"}, {"empty", ""}},
+                           "$empty $$1$ $foo $$2$ $baz$");
+  }
+  EXPECT_EQ(written(), "arg1 bar arg2 bla");
+}
+
+TEST_F(PrinterTest, FormatInternalIndent) {
+  {
+    Printer printer(output(), '$');
+    printer.Indent();
+    printer.FormatInternal({"arg1", "arg2"},
+                           {{"foo", "bar"}, {"baz", "bla"}, {"empty", ""}},
+                           "$empty $\n\n$1$ $foo $$2$\n$baz$");
+    printer.Outdent();
+  }
+  EXPECT_EQ(written(), "\n\n  arg1 bar arg2\n  bla");
+}
+
+TEST_F(PrinterTest, FormatInternalAnnotations) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
+
+    printer.Indent();
+    GeneratedCodeInfo::Annotation annotation;
+    annotation.set_source_file("file.proto");
+    annotation.add_path(33);
+
+    printer.FormatInternal({annotation.SerializeAsString(), "arg1", "arg2"},
+                           {{"foo", "bar"}, {"baz", "bla"}, {"empty", ""}},
+                           "$empty $\n\n${1$$2$$}$ $3$\n$baz$");
+    printer.Outdent();
   }
 
-  // Indentation tests
+  EXPECT_EQ(written(), "\n\n  arg1 arg2\n  bla");
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(4, 8, "file.proto", ElementsAre(33))));
+}
+
+TEST_F(PrinterTest, Emit) {
   {
-    // Empty lines shouldn't indent.
-    std::string s;
-    {
-      StringOutputStream output(&s);
-      Printer printer(&output, '$');
-      printer.Indent();
-      printer.FormatInternal(args, vars, "$empty $\n\n$1$ $foo $$2$\n$baz$");
-      printer.Outdent();
-    }
-    EXPECT_EQ("\n\n  arg1 bar arg2\n  bla", s);
+    Printer printer(output());
+    printer.Emit(R"cc(
+      class Foo {
+        int x, y, z;
+      };
+    )cc");
+    printer.Emit(R"java(
+      public final class Bar {
+        Bar() {}
+      }
+    )java");
   }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n"
+            "public final class Bar {\n"
+            "  Bar() {}\n"
+            "}\n");
+}
+
+TEST_F(PrinterTest, EmitKeepsExtraLine) {
   {
-    // Annotations should respect indentation.
-    std::string s;
-    GeneratedCodeInfo info;
-    {
-      StringOutputStream output(&s);
-      AnnotationProtoCollector<GeneratedCodeInfo> info_collector(&info);
-      Printer printer(&output, '$', &info_collector);
-      printer.Indent();
-      GeneratedCodeInfo::Annotation annotation;
-      annotation.set_source_file("file.proto");
-      annotation.add_path(33);
-      std::vector<std::string> args{annotation.SerializeAsString(), "arg1",
-                                    "arg2"};
-      printer.FormatInternal(args, vars, "$empty $\n\n${1$$2$$}$ $3$\n$baz$");
-      printer.Outdent();
-    }
-    EXPECT_EQ("\n\n  arg1 arg2\n  bla", s);
-    ASSERT_EQ(1, info.annotation_size());
-    const GeneratedCodeInfo::Annotation* arg1 = &info.annotation(0);
-    ASSERT_EQ(1, arg1->path_size());
-    EXPECT_EQ(33, arg1->path(0));
-    EXPECT_EQ("file.proto", arg1->source_file());
-    EXPECT_EQ(4, arg1->begin());
-    EXPECT_EQ(8, arg1->end());
+    Printer printer(output());
+    printer.Emit(R"cc(
+
+      class Foo {
+        int x, y, z;
+      };
+    )cc");
+    printer.Emit(R"java(
+
+      public final class Bar {
+        Bar() {}
+      }
+    )java");
   }
-#ifdef PROTOBUF_HAS_DEATH_TEST
-  // Death tests in case of illegal format strings.
+
+  EXPECT_EQ(written(),
+            "\n"
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n"
+            "\n"
+            "public final class Bar {\n"
+            "  Bar() {}\n"
+            "}\n");
+}
+
+TEST_F(PrinterTest, EmitWithSubs) {
   {
-    // Unused arguments
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal(args, vars, "$empty $$1$"), "Unused");
+    Printer printer(output());
+    printer.Emit(
+        {{"class", "Foo"}, {"f1", "x"}, {"f2", "y"}, {"f3", "z"}, {"init", 42}},
+        R"cc(
+          class $class$ {
+            int $f1$, $f2$, $f3$ = $init$;
+          };
+        )cc");
   }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z = 42;\n"
+            "};\n");
+}
+
+TEST_F(PrinterTest, EmitWithVars) {
   {
-    // Wrong order arguments
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal(args, vars, "$2$ $1$"), "order");
+    Printer printer(output());
+    auto v = printer.WithVars({
+        {"class", "Foo"},
+        {"f1", "x"},
+        {"f2", "y"},
+        {"f3", "z"},
+        {"init", 42},
+    });
+    printer.Emit(R"cc(
+      class $class$ {
+        int $f1$, $f2$, $f3$ = $init$;
+      };
+    )cc");
   }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z = 42;\n"
+            "};\n");
+}
+
+TEST_F(PrinterTest, EmitWithSpacedVars) {
   {
-    // Zero is illegal argument
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal(args, vars, "$0$"), "failed");
+    Printer printer(output());
+    auto v = printer.WithVars({
+        {"is_final", "final"},
+        {"isnt_final", ""},
+        {"class", "Foo"},
+    });
+    printer.Emit(R"java(
+      public $is_final $class $class$ {
+        // Stuff.
+      }
+    )java");
+    printer.Emit(R"java(
+      public $isnt_final $class $class$ {
+        // Stuff.
+      }
+    )java");
   }
+
+  EXPECT_EQ(written(),
+            "public final class Foo {\n"
+            "  // Stuff.\n"
+            "}\n"
+            "public class Foo {\n"
+            "  // Stuff.\n"
+            "}\n");
+}
+
+TEST_F(PrinterTest, EmitWithIndent) {
   {
-    // Argument out of bounds
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal(args, vars, "$1$ $2$ $3$"), "bounds");
+    Printer printer(output());
+    auto v = printer.WithIndent();
+    printer.Emit({{"f1", "x"}, {"f2", "y"}, {"f3", "z"}}, R"cc(
+      class Foo {
+        int $f1$, $f2$, $f3$;
+      };
+    )cc");
   }
+
+  EXPECT_EQ(written(),
+            "  class Foo {\n"
+            "    int x, y, z;\n"
+            "  };\n");
+}
+
+
+TEST_F(PrinterTest, EmitSameNameAnnotation) {
+  FakeAnnotationCollector collector;
   {
-    // Unknown variable
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal(args, vars, "$huh$ $1$$2$"), "Unknown");
+    Printer printer(output(), '$', &collector);
+    FakeDescriptor descriptor{{"file.proto"}, {33}};
+    auto v = printer.WithVars({{"class", "Foo"}});
+    auto a = printer.WithAnnotations({{"class", &descriptor}});
+
+    printer.Emit({{"f1", "x"}, {"f2", "y"}, {"f3", "z"}}, R"cc(
+      class $class$ {
+        int $f1$, $f2$, $f3$;
+      };
+    )cc");
   }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n");
+
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(6, 9, "file.proto", ElementsAre(33))));
+}
+
+TEST_F(PrinterTest, EmitSameNameAnnotationFileNameOnly) {
+  FakeAnnotationCollector collector;
   {
-    // Illegal variable
-    std::string s;
-    StringOutputStream output(&s);
-    Printer printer(&output, '$');
-    EXPECT_DEATH(printer.FormatInternal({}, vars, "$ $"), "Empty");
+    Printer printer(output(), '$', &collector);
+    auto v = printer.WithVars({{"class", "Foo"}});
+    auto a = printer.WithAnnotations({{"class", "file.proto"}});
+
+    printer.Emit({{"f1", "x"}, {"f2", "y"}, {"f3", "z"}}, R"cc(
+      class $class$ {
+        int $f1$, $f2$, $f3$;
+      };
+    )cc");
   }
-#endif  // PROTOBUF_HAS_DEATH_TEST
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n");
+
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(6, 9, "file.proto", IsEmpty())));
+}
+
+TEST_F(PrinterTest, EmitThreeArgWithVars) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
+    auto v = printer.WithVars({{"class", "Foo", "file.proto"}});
+
+    printer.Emit({{"f1", "x"}, {"f2", "y"}, {"f3", "z"}}, R"cc(
+      class $class$ {
+        int $f1$, $f2$, $f3$;
+      };
+    )cc");
+  }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n");
+
+  EXPECT_THAT(collector.Get(),
+              ElementsAre(Annotation(6, 9, "file.proto", IsEmpty())));
+}
+
+TEST_F(PrinterTest, EmitRangeAnnotation) {
+  FakeAnnotationCollector collector;
+  {
+    Printer printer(output(), '$', &collector);
+    FakeDescriptor descriptor1{{"file1.proto"}, {33}};
+    FakeDescriptor descriptor2{{"file2.proto"}, {11, 22}};
+    auto v = printer.WithVars({{"class", "Foo"}});
+    auto a = printer.WithAnnotations({
+        {"message", &descriptor1},
+        {"field", &descriptor2},
+    });
+
+    printer.Emit({{"f1", "x"}, {"f2", "y"}, {"f3", "z"}}, R"cc(
+      $_start$message$ class $class$ {
+        $_start$field$ int $f1$, $f2$, $f3$;
+        $_end$field$
+      };
+      $_end$message$
+    )cc");
+  }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            "  int x, y, z;\n"
+            "};\n");
+
+  EXPECT_THAT(
+      collector.Get(),
+      ElementsAre(Annotation(14, 27, "file2.proto", ElementsAre(11, 22)),
+                  Annotation(0, 30, "file1.proto", ElementsAre(33))));
+}
+
+TEST_F(PrinterTest, EmitCallbacks) {
+  {
+    Printer printer(output());
+    printer.Emit(
+        {
+            {"class", "Foo"},
+            {"method", "bar"},
+            {"methods",
+             [&] {
+               printer.Emit(R"cc(
+                 int $method$() { return 42; }
+               )cc");
+             }},
+            {"fields",
+             [&] {
+               printer.Emit(R"cc(
+                 int $method$_;
+               )cc");
+             }},
+        },
+        R"cc(
+          class $class$ {
+           public:
+            $methods$;
+
+           private:
+            $fields$;
+          };
+        )cc");
+  }
+
+  EXPECT_EQ(written(),
+            "class Foo {\n"
+            " public:\n"
+            "  int bar() { return 42; }\n"
+            "\n"
+            " private:\n"
+            "  int bar_;\n"
+            "};\n");
 }
 
 }  // namespace io
diff --git a/src/google/protobuf/io/strtod.cc b/src/google/protobuf/io/strtod.cc
index 03acb5b..202ce6a 100644
--- a/src/google/protobuf/io/strtod.cc
+++ b/src/google/protobuf/io/strtod.cc
@@ -28,17 +28,23 @@
 // (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/io/strtod.h>
+#include "google/protobuf/io/strtod.h"
 
+#include <float.h>  // FLT_DIG and DBL_DIG
+
+#include <cmath>
 #include <cstdio>
+#include <cstdlib>
 #include <cstring>
 #include <limits>
 #include <string>
+#include <system_error>  // NOLINT(build/c++11)
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/charconv.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_format.h"
 
 namespace google {
 namespace protobuf {
@@ -46,7 +52,7 @@
 
 // This approximately 0x1.ffffffp127, but we don't use 0x1.ffffffp127 because
 // it won't compile in MSVC.
-const double MAX_FLOAT_AS_DOUBLE_ROUNDED = 3.4028235677973366e+38;
+constexpr double MAX_FLOAT_AS_DOUBLE_ROUNDED = 3.4028235677973366e+38;
 
 float SafeDoubleToFloat(double value) {
   // static_cast<float> on a number larger than float can result in illegal
@@ -73,8 +79,204 @@
   }
 }
 
-double NoLocaleStrtod(const char* str, char** endptr) {
-  return google::protobuf::internal::NoLocaleStrtod(str, endptr);
+double NoLocaleStrtod(const char *str, char **endptr) {
+  double ret = 0.0;
+  // This isn't ideal, but the existing function interface does not provide any
+  // bounds.
+  const char *end = strchr(str, 0);
+  auto result = absl::from_chars(str, end, ret);
+  // from_chars() with DR 3081's current wording will return max() on
+  // overflow.  SimpleAtod returns infinity instead.
+  if (result.ec == std::errc::result_out_of_range) {
+    if (ret > 1.0) {
+      ret = std::numeric_limits<double>::infinity();
+    } else if (ret < -1.0) {
+      ret = -std::numeric_limits<double>::infinity();
+    }
+  }
+  if (endptr) {
+    *endptr = const_cast<char *>(result.ptr);
+  }
+  return ret;
+}
+
+// ----------------------------------------------------------------------
+// SimpleDtoa()
+// SimpleFtoa()
+//    We want to print the value without losing precision, but we also do
+//    not want to print more digits than necessary.  This turns out to be
+//    trickier than it sounds.  Numbers like 0.2 cannot be represented
+//    exactly in binary.  If we print 0.2 with a very large precision,
+//    e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167".
+//    On the other hand, if we set the precision too low, we lose
+//    significant digits when printing numbers that actually need them.
+//    It turns out there is no precision value that does the right thing
+//    for all numbers.
+//
+//    Our strategy is to first try printing with a precision that is never
+//    over-precise, then parse the result with strtod() to see if it
+//    matches.  If not, we print again with a precision that will always
+//    give a precise result, but may use more digits than necessary.
+//
+//    An arguably better strategy would be to use the algorithm described
+//    in "How to Print Floating-Point Numbers Accurately" by Steele &
+//    White, e.g. as implemented by David M. Gay's dtoa().  It turns out,
+//    however, that the following implementation is about as fast as
+//    DMG's code.  Furthermore, DMG's code locks mutexes, which means it
+//    will not scale well on multi-core machines.  DMG's code is slightly
+//    more accurate (in that it will never use more digits than
+//    necessary), but this is probably irrelevant for most users.
+//
+//    Rob Pike and Ken Thompson also have an implementation of dtoa() in
+//    third_party/fmt/fltfmt.cc.  Their implementation is similar to this
+//    one in that it makes guesses and then uses strtod() to check them.
+//    Their implementation is faster because they use their own code to
+//    generate the digits in the first place rather than use snprintf(),
+//    thus avoiding format string parsing overhead.  However, this makes
+//    it considerably more complicated than the following implementation,
+//    and it is embedded in a larger library.  If speed turns out to be
+//    an issue, we could re-implement this in terms of their
+//    implementation.
+// ----------------------------------------------------------------------
+
+namespace {
+// In practice, doubles should never need more than 24 bytes and floats
+// should never need more than 14 (including null terminators), but we
+// overestimate to be safe.
+constexpr int kDoubleToBufferSize = 32;
+constexpr int kFloatToBufferSize = 24;
+
+inline bool IsValidFloatChar(char c) {
+  return ('0' <= c && c <= '9') || c == 'e' || c == 'E' || c == '+' || c == '-';
+}
+
+void DelocalizeRadix(char *buffer) {
+  // Fast check:  if the buffer has a normal decimal point, assume no
+  // translation is needed.
+  if (strchr(buffer, '.') != nullptr) return;
+
+  // Find the first unknown character.
+  while (IsValidFloatChar(*buffer)) ++buffer;
+
+  if (*buffer == '\0') {
+    // No radix character found.
+    return;
+  }
+
+  // We are now pointing at the locale-specific radix character.  Replace it
+  // with '.'.
+  *buffer = '.';
+  ++buffer;
+
+  if (!IsValidFloatChar(*buffer) && *buffer != '\0') {
+    // It appears the radix was a multi-byte character.  We need to remove the
+    // extra bytes.
+    char *target = buffer;
+    do {
+      ++buffer;
+    } while (!IsValidFloatChar(*buffer) && *buffer != '\0');
+    memmove(target, buffer, strlen(buffer) + 1);
+  }
+}
+
+bool safe_strtof(const char *str, float *value) {
+  char *endptr;
+  errno = 0;  // errno only gets set on errors
+  *value = strtof(str, &endptr);
+  return *str != 0 && *endptr == 0 && errno == 0;
+}
+
+char *FloatToBuffer(float value, char *buffer) {
+  // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all
+  // platforms these days.  Just in case some system exists where FLT_DIG
+  // is significantly larger -- and risks overflowing our buffer -- we have
+  // this assert.
+  static_assert(FLT_DIG < 10, "FLT_DIG_is_too_big");
+
+  if (value == std::numeric_limits<double>::infinity()) {
+    absl::SNPrintF(buffer, kFloatToBufferSize, "inf");
+    return buffer;
+  } else if (value == -std::numeric_limits<double>::infinity()) {
+    absl::SNPrintF(buffer, kFloatToBufferSize, "-inf");
+    return buffer;
+  } else if (std::isnan(value)) {
+    absl::SNPrintF(buffer, kFloatToBufferSize, "nan");
+    return buffer;
+  }
+
+  int snprintf_result =
+      absl::SNPrintF(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value);
+
+  // The snprintf should never overflow because the buffer is significantly
+  // larger than the precision we asked for.
+  GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
+
+  float parsed_value;
+  if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) {
+    snprintf_result =
+        absl::SNPrintF(buffer, kFloatToBufferSize, "%.*g", FLT_DIG + 3, value);
+
+    // Should never overflow; see above.
+    GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
+  }
+
+  DelocalizeRadix(buffer);
+  return buffer;
+}
+
+char *DoubleToBuffer(double value, char *buffer) {
+  // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all
+  // platforms these days.  Just in case some system exists where DBL_DIG
+  // is significantly larger -- and risks overflowing our buffer -- we have
+  // this assert.
+  static_assert(DBL_DIG < 20, "DBL_DIG_is_too_big");
+
+  if (value == std::numeric_limits<double>::infinity()) {
+    absl::SNPrintF(buffer, kDoubleToBufferSize, "inf");
+    return buffer;
+  } else if (value == -std::numeric_limits<double>::infinity()) {
+    absl::SNPrintF(buffer, kDoubleToBufferSize, "-inf");
+    return buffer;
+  } else if (std::isnan(value)) {
+    absl::SNPrintF(buffer, kDoubleToBufferSize, "nan");
+    return buffer;
+  }
+
+  int snprintf_result =
+      absl::SNPrintF(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value);
+
+  // The snprintf should never overflow because the buffer is significantly
+  // larger than the precision we asked for.
+  GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
+
+  // We need to make parsed_value volatile in order to force the compiler to
+  // write it out to the stack.  Otherwise, it may keep the value in a
+  // register, and if it does that, it may keep it as a long double instead
+  // of a double.  This long double may have extra bits that make it compare
+  // unequal to "value" even though it would be exactly equal if it were
+  // truncated to a double.
+  volatile double parsed_value = NoLocaleStrtod(buffer, nullptr);
+  if (parsed_value != value) {
+    snprintf_result =
+        absl::SNPrintF(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG + 2, value);
+
+    // Should never overflow; see above.
+    GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
+  }
+
+  DelocalizeRadix(buffer);
+  return buffer;
+}
+}  // namespace
+
+std::string SimpleDtoa(double value) {
+  char buffer[kDoubleToBufferSize];
+  return DoubleToBuffer(value, buffer);
+}
+
+std::string SimpleFtoa(float value) {
+  char buffer[kFloatToBufferSize];
+  return FloatToBuffer(value, buffer);
 }
 
 }  // namespace io
diff --git a/src/google/protobuf/io/strtod.h b/src/google/protobuf/io/strtod.h
index 38f544a..851c8e6 100644
--- a/src/google/protobuf/io/strtod.h
+++ b/src/google/protobuf/io/strtod.h
@@ -35,10 +35,29 @@
 #ifndef GOOGLE_PROTOBUF_IO_STRTOD_H__
 #define GOOGLE_PROTOBUF_IO_STRTOD_H__
 
+#include <string>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 namespace google {
 namespace protobuf {
 namespace io {
 
+// ----------------------------------------------------------------------
+// SimpleDtoa()
+// SimpleFtoa()
+//    Description: converts a double or float to a string which, if
+//    passed to NoLocaleStrtod(), will produce the exact same original double
+//    (except in case of NaN; all NaNs are considered the same value).
+//    We try to keep the string short but it's not guaranteed to be as
+//    short as possible.
+//
+//    Return value: string
+// ----------------------------------------------------------------------
+PROTOBUF_EXPORT std::string SimpleDtoa(double value);
+PROTOBUF_EXPORT std::string SimpleFtoa(float value);
+
 // A locale-independent version of the standard strtod(), which always
 // uses a dot as the decimal separator.
 double NoLocaleStrtod(const char* str, char** endptr);
@@ -52,4 +71,6 @@
 }  // namespace protobuf
 }  // namespace google
 
+#include "google/protobuf/port_undef.inc"
+
 #endif  // GOOGLE_PROTOBUF_IO_STRTOD_H__
diff --git a/src/google/protobuf/io/tokenizer.cc b/src/google/protobuf/io/tokenizer.cc
index f9e0776..88bbc89 100644
--- a/src/google/protobuf/io/tokenizer.cc
+++ b/src/google/protobuf/io/tokenizer.cc
@@ -88,18 +88,17 @@
 // I'd love to hear about other alternatives, though, as this code isn't
 // exactly pretty.
 
-#include <google/protobuf/io/tokenizer.h>
+#include "google/protobuf/io/tokenizer.h"
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/io/strtod.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_format.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/io/zero_copy_stream.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -406,7 +405,7 @@
 
       case '\n': {
         if (!allow_multiline_strings_) {
-          AddError("String literals cannot cross line boundaries.");
+          AddError("Multiline strings are not allowed. Did you miss a \"?.");
           return;
         }
         NextChar();
@@ -422,7 +421,7 @@
           // Possibly followed by two more octal digits, but these will
           // just be consumed by the main loop anyway so we don't need
           // to do so explicitly here.
-        } else if (TryConsume('x')) {
+        } else if (TryConsume('x') || TryConsume('X')) {
           if (!TryConsumeOne<HexDigit>()) {
             AddError("Expected hex digits for escape sequence.");
           }
@@ -708,7 +707,7 @@
         if (current_char_ & 0x80) {
           error_collector_->AddError(
               line_, column_,
-              StringPrintf("Interpreting non ascii codepoint %d.",
+              absl::StrFormat("Interpreting non ascii codepoint %d.",
                               static_cast<unsigned char>(current_char_)));
         }
         NextChar();
@@ -746,6 +745,8 @@
       : prev_trailing_comments_(prev_trailing_comments),
         detached_comments_(detached_comments),
         next_leading_comments_(next_leading_comments),
+        num_comments_(0),
+        has_trailing_comment_(false),
         has_comment_(false),
         is_line_comment_(false),
         can_attach_to_prev_(true) {
@@ -797,6 +798,7 @@
         if (prev_trailing_comments_ != NULL) {
           prev_trailing_comments_->append(comment_buffer_);
         }
+        has_trailing_comment_ = true;
         can_attach_to_prev_ = false;
       } else {
         if (detached_comments_ != NULL) {
@@ -804,17 +806,39 @@
         }
       }
       ClearBuffer();
+      num_comments_++;
     }
   }
 
   void DetachFromPrev() { can_attach_to_prev_ = false; }
 
+  void MaybeDetachComment() {
+    int count = num_comments_;
+    if (has_comment_) count++;
+
+    // If there's one comment, make sure it is detached.
+    if (count == 1) {
+      if (has_trailing_comment_ && prev_trailing_comments_ != NULL) {
+        std::string trail = *prev_trailing_comments_;
+        if (detached_comments_ != NULL) {
+          // push trailing comment to front of detached
+          detached_comments_->insert(detached_comments_->begin(), 1, trail);
+        }
+        prev_trailing_comments_->clear();
+      }
+      // flush pending comment so it's detached instead of leading
+      Flush();
+    }
+  }
+
  private:
   std::string* prev_trailing_comments_;
   std::vector<std::string>* detached_comments_;
   std::string* next_leading_comments_;
 
   std::string comment_buffer_;
+  int num_comments_;
+  bool has_trailing_comment_;
 
   // True if any comments were read into comment_buffer_.  This can be true even
   // if comment_buffer_ is empty, namely if the comment was "/**/".
@@ -836,6 +860,9 @@
   CommentCollector collector(prev_trailing_comments, detached_comments,
                              next_leading_comments);
 
+  int prev_line = line_;
+  int trailing_comment_end_line = -1;
+
   if (current_.type == TYPE_START) {
     // Ignore unicode byte order mark(BOM) if it appears at the file
     // beginning. Only UTF-8 BOM (0xEF 0xBB 0xBF) is accepted.
@@ -849,12 +876,14 @@
       }
     }
     collector.DetachFromPrev();
+    prev_line = -1;
   } else {
     // A comment appearing on the same line must be attached to the previous
     // declaration.
     ConsumeZeroOrMore<WhitespaceNoNewline>();
     switch (TryConsumeCommentStart()) {
       case LINE_COMMENT:
+        trailing_comment_end_line = line_;
         ConsumeLineComment(collector.GetBufferForLineComment());
 
         // Don't allow comments on subsequent lines to be attached to a trailing
@@ -863,14 +892,8 @@
         break;
       case BLOCK_COMMENT:
         ConsumeBlockComment(collector.GetBufferForBlockComment());
-
+        trailing_comment_end_line = line_;
         ConsumeZeroOrMore<WhitespaceNoNewline>();
-        if (!TryConsume('\n')) {
-          // Oops, the next token is on the same line.  If we recorded a comment
-          // we really have no idea which token it should be attached to.
-          collector.ClearBuffer();
-          return Next();
-        }
 
         // Don't allow comments on subsequent lines to be attached to a trailing
         // comment.
@@ -918,6 +941,13 @@
             // makes no sense to attach a comment to the following token.
             collector.Flush();
           }
+          if (prev_line == line_ || trailing_comment_end_line == line_) {
+            // When previous token and this one are on the same line, or
+            // even if a multi-line trailing comment ends on the same line
+            // as this token, it's unclear to what token the comment
+            // should be attached. So we detach it.
+            collector.MaybeDetachComment();
+          }
           return result;
         }
         break;
@@ -1002,9 +1032,20 @@
 }
 
 double Tokenizer::ParseFloat(const std::string& text) {
+  double result = 0;
+  if (!TryParseFloat(text, &result)) {
+    GOOGLE_LOG(DFATAL)
+        << " Tokenizer::ParseFloat() passed text that could not have been"
+           " tokenized as a float: "
+        << absl::CEscape(text);
+  }
+  return result;
+}
+
+bool Tokenizer::TryParseFloat(const std::string& text, double* result) {
   const char* start = text.c_str();
   char* end;
-  double result = NoLocaleStrtod(start, &end);
+  *result = NoLocaleStrtod(start, &end);
 
   // "1e" is not a valid float, but if the tokenizer reads it, it will
   // report an error but still return it as a valid token.  We need to
@@ -1020,12 +1061,7 @@
     ++end;
   }
 
-  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);
-  return result;
+  return static_cast<size_t>(end - start) == text.size() && *start != '-';
 }
 
 // Helper to append a Unicode code point to a string as UTF8, without bringing
@@ -1052,7 +1088,7 @@
     // 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);
+    absl::StrAppendFormat(output, "\\U%08x", code_point);
     return;
   }
   tmp = ghtonl(tmp);
@@ -1145,7 +1181,7 @@
   if (text_size == 0) {
     GOOGLE_LOG(DFATAL) << " Tokenizer::ParseStringAppend() passed text that could not"
                    " have been tokenized as a string: "
-                << CEscape(text);
+                << absl::CEscape(text);
     return;
   }
 
@@ -1179,7 +1215,7 @@
         }
         output->push_back(static_cast<char>(code));
 
-      } else if (*ptr == 'x') {
+      } else if (*ptr == 'x' || *ptr == 'X') {
         // A hex escape.  May zero, one, or two digits.  (The zero case
         // will have been caught as an error earlier.)
         int code = 0;
@@ -1236,4 +1272,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/io/tokenizer.h b/src/google/protobuf/io/tokenizer.h
index 4abab7e..73877cc 100644
--- a/src/google/protobuf/io/tokenizer.h
+++ b/src/google/protobuf/io/tokenizer.h
@@ -37,15 +37,15 @@
 #ifndef GOOGLE_PROTOBUF_IO_TOKENIZER_H__
 #define GOOGLE_PROTOBUF_IO_TOKENIZER_H__
 
-
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -69,6 +69,8 @@
 class PROTOBUF_EXPORT ErrorCollector {
  public:
   inline ErrorCollector() {}
+  ErrorCollector(const ErrorCollector&) = delete;
+  ErrorCollector& operator=(const ErrorCollector&) = delete;
   virtual ~ErrorCollector();
 
   // Indicates that there was an error in the input at the given line and
@@ -82,9 +84,6 @@
   // 1 to each before printing them.
   virtual void AddWarning(int /* line */, ColumnNumber /* column */,
                           const std::string& /* message */) {}
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorCollector);
 };
 
 // This class converts a stream of raw text into a stream of tokens for
@@ -99,6 +98,8 @@
   // input stream and writes errors to the given error_collector.
   // The caller keeps ownership of input and error_collector.
   Tokenizer(ZeroCopyInputStream* input, ErrorCollector* error_collector);
+  Tokenizer(const Tokenizer&) = delete;
+  Tokenizer& operator=(const Tokenizer&) = delete;
   ~Tokenizer();
 
   enum TokenType {
@@ -149,11 +150,11 @@
 
   // Get the current token.  This is updated when Next() is called.  Before
   // the first call to Next(), current() has type TYPE_START and no contents.
-  const Token& current();
+  const Token& current() const;
 
   // Return the previous token -- i.e. what current() returned before the
   // previous call to Next().
-  const Token& previous();
+  const Token& previous() const;
 
   // Advance to the next token.  Returns false if the end of the input is
   // reached.
@@ -213,6 +214,10 @@
   // result is undefined (possibly an assert failure).
   static double ParseFloat(const std::string& text);
 
+  // Parses given text as if it were a TYPE_FLOAT token.  Returns false if the
+  // given text is not actually a valid float literal.
+  static bool TryParseFloat(const std::string& text, double* result);
+
   // Parses a TYPE_STRING token.  This never fails, so long as the text actually
   // comes from a TYPE_STRING token parsed by Tokenizer.  If it doesn't, the
   // result is undefined (possibly an assert failure).
@@ -276,8 +281,6 @@
 
   // -----------------------------------------------------------------
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Tokenizer);
-
   Token current_;   // Returned by current().
   Token previous_;  // Returned by previous().
 
@@ -423,9 +426,9 @@
 };
 
 // inline methods ====================================================
-inline const Tokenizer::Token& Tokenizer::current() { return current_; }
+inline const Tokenizer::Token& Tokenizer::current() const { return current_; }
 
-inline const Tokenizer::Token& Tokenizer::previous() { return previous_; }
+inline const Tokenizer::Token& Tokenizer::previous() const { return previous_; }
 
 inline void Tokenizer::ParseString(const std::string& text,
                                    std::string* output) {
@@ -437,6 +440,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IO_TOKENIZER_H__
diff --git a/src/google/protobuf/io/tokenizer_unittest.cc b/src/google/protobuf/io/tokenizer_unittest.cc
index 16ba940..3d59f63 100644
--- a/src/google/protobuf/io/tokenizer_unittest.cc
+++ b/src/google/protobuf/io/tokenizer_unittest.cc
@@ -32,19 +32,19 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/io/tokenizer.h>
+#include "google/protobuf/io/tokenizer.h"
 
 #include <limits.h>
 #include <math.h>
 
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
 
 namespace google {
@@ -63,7 +63,7 @@
 // run multiple times, once for each item in some input array.  TEST_1D
 // tests all cases in a single input array.  TEST_2D tests all
 // combinations of cases from two arrays.  The arrays must be statically
-// defined such that the GOOGLE_ARRAYSIZE() macro works on them.  Example:
+// defined such that the ABSL_ARRAYSIZE() macro works on them.  Example:
 //
 // int kCases[] = {1, 2, 3, 4}
 // TEST_1D(MyFixture, MyTest, kCases) {
@@ -83,7 +83,7 @@
   };                                                              \
                                                                   \
   TEST_F(FIXTURE##_##NAME##_DD, NAME) {                           \
-    for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES); i++) {                  \
+    for (int i = 0; i < ABSL_ARRAYSIZE(CASES); i++) {             \
       SCOPED_TRACE(testing::Message()                             \
                    << #CASES " case #" << i << ": " << CASES[i]); \
       DoSingleCase(CASES[i]);                                     \
@@ -102,8 +102,8 @@
   };                                                                        \
                                                                             \
   TEST_F(FIXTURE##_##NAME##_DD, NAME) {                                     \
-    for (int i = 0; i < GOOGLE_ARRAYSIZE(CASES1); i++) {                           \
-      for (int j = 0; j < GOOGLE_ARRAYSIZE(CASES2); j++) {                         \
+    for (int i = 0; i < ABSL_ARRAYSIZE(CASES1); i++) {                      \
+      for (int j = 0; j < ABSL_ARRAYSIZE(CASES2); j++) {                    \
         SCOPED_TRACE(testing::Message()                                     \
                      << #CASES1 " case #" << i << ": " << CASES1[i] << ", " \
                      << #CASES2 " case #" << j << ": " << CASES2[j]);       \
@@ -163,7 +163,7 @@
 
   // implements ErrorCollector ---------------------------------------
   void AddError(int line, int column, const std::string& message) {
-    strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message);
+    absl::SubstituteAndAppend(&text_, "$0:$1: $2\n", line, column, message);
   }
 };
 
@@ -201,7 +201,7 @@
 
 inline std::ostream& operator<<(std::ostream& out,
                                 const SimpleTokenCase& test_case) {
-  return out << CEscape(test_case.input);
+  return out << absl::CEscape(test_case.input);
 }
 
 SimpleTokenCase kSimpleTokenCases[] = {
@@ -370,7 +370,7 @@
 
 inline std::ostream& operator<<(std::ostream& out,
                                 const MultiTokenCase& test_case) {
-  return out << CEscape(test_case.input);
+  return out << absl::CEscape(test_case.input);
 }
 
 MultiTokenCase kMultiTokenCases[] = {
@@ -614,7 +614,7 @@
   tokenizer.set_comment_style(Tokenizer::SH_COMMENT_STYLE);
 
   // Advance through tokens and check that they are parsed as expected.
-  for (int i = 0; i < GOOGLE_ARRAYSIZE(kTokens); i++) {
+  for (int i = 0; i < ABSL_ARRAYSIZE(kTokens); i++) {
     EXPECT_TRUE(tokenizer.Next());
     EXPECT_EQ(tokenizer.current().text, kTokens[i]);
   }
@@ -641,7 +641,7 @@
 
 inline std::ostream& operator<<(std::ostream& out,
                                 const DocCommentCase& test_case) {
-  return out << CEscape(test_case.input);
+  return out << absl::CEscape(test_case.input);
 }
 
 DocCommentCase kDocCommentCases[] = {
@@ -651,10 +651,10 @@
      {},
      ""},
 
-    {"prev /* ignored */ next",
+    {"prev /* detached */ next",
 
      "",
-     {},
+     {" detached "},
      ""},
 
     {"prev // trailing comment\n"
@@ -665,6 +665,13 @@
      ""},
 
     {"prev\n"
+     "/* leading comment */ next",
+
+     "",
+     {},
+     " leading comment "},
+
+    {"prev\n"
      "// leading comment\n"
      "// line 2\n"
      "next",
@@ -763,6 +770,45 @@
      "",
      {},
      " leading comment\n"},
+
+    {"prev /* many comments*/ /* all inline */ /* will be handled */ next",
+
+     " many comments",
+     {" all inline "},
+     " will be handled "},
+
+    {R"pb(
+     prev /* a single block comment
+         that spans multiple lines
+         is detached if it ends
+         on the same line as next */ next"
+     )pb",
+
+     "",
+     {" a single block comment\n"
+      "that spans multiple lines\n"
+      "is detached if it ends\n"
+      "on the same line as next "},
+     ""},
+
+    {R"pb(
+     prev /* trailing */ /* leading */ next"
+     )pb",
+
+     " trailing ",
+     {},
+     " leading "},
+
+    {R"pb(
+     prev /* multi-line
+          trailing */ /* an oddly
+                      placed detached */ /* an oddly
+                                         placed leading */ next"
+     )pb",
+
+     " multi-line\ntrailing ",
+     {" an oddly\nplaced detached "},
+     " an oddly\nplaced leading "},
 };
 
 TEST_2D(TokenizerTest, DocComments, kDocCommentCases, kBlockSizes) {
@@ -796,7 +842,7 @@
             prev_trailing_comments);
 
   for (int i = 0; i < detached_comments.size(); i++) {
-    ASSERT_LT(i, GOOGLE_ARRAYSIZE(kDocCommentCases));
+    ASSERT_LT(i, ABSL_ARRAYSIZE(kDocCommentCases));
     ASSERT_TRUE(kDocCommentCases_case.detached_comments[i] != NULL);
     EXPECT_EQ(kDocCommentCases_case.detached_comments[i], detached_comments[i]);
   }
@@ -999,6 +1045,8 @@
   EXPECT_EQ("\1x\1\123\739\52\334n\3", output);
   Tokenizer::ParseString("'\\x20\\x4'", &output);
   EXPECT_EQ("\x20\x4", output);
+  Tokenizer::ParseString("'\\X20\\X4'", &output);
+  EXPECT_EQ("\x20\x4", output);
 
   // Test invalid strings that may still be tokenized as strings.
   Tokenizer::ParseString("\"\\a\\l\\v\\t", &output);  // \l is invalid
@@ -1058,16 +1106,17 @@
 };
 
 inline std::ostream& operator<<(std::ostream& out, const ErrorCase& test_case) {
-  return out << CEscape(test_case.input);
+  return out << absl::CEscape(test_case.input);
 }
 
 ErrorCase kErrorCases[] = {
     // String errors.
     {"'\\l' foo", true, "0:2: Invalid escape sequence in string literal.\n"},
-    {"'\\X' foo", true, "0:2: Invalid escape sequence in string literal.\n"},
+    {"'\\X' foo", true, "0:3: Expected hex digits for escape sequence.\n"},
     {"'\\x' foo", true, "0:3: Expected hex digits for escape sequence.\n"},
     {"'foo", false, "0:4: Unexpected end of string.\n"},
-    {"'bar\nfoo", true, "0:4: String literals cannot cross line boundaries.\n"},
+    {"'bar\nfoo", true,
+     "0:4: Multiline strings are not allowed. Did you miss a \"?.\n"},
     {"'\\u01' foo", true,
      "0:5: Expected four hex digits for \\u escape sequence.\n"},
     {"'\\u01' foo", true,
diff --git a/src/google/protobuf/util/internal/error_listener.cc b/src/google/protobuf/io/zero_copy_sink.cc
similarity index 67%
copy from src/google/protobuf/util/internal/error_listener.cc
copy to src/google/protobuf/io/zero_copy_sink.cc
index 538307b..7045648 100644
--- a/src/google/protobuf/util/internal/error_listener.cc
+++ b/src/google/protobuf/io/zero_copy_sink.cc
@@ -28,15 +28,41 @@
 // (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/util/internal/error_listener.h>
+#include "google/protobuf/io/zero_copy_sink.h"
+
+#include <algorithm>
+#include <cstddef>
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace converter {
+namespace io {
+namespace zc_sink_internal {
+void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) {
+  while (!failed_ && len > 0) {
+    if (buffer_size_ == 0) {
+      int size;
+      if (!stream_->Next(&buffer_, &size)) {
+        // There isn't a way for ByteSink to report errors.
+        buffer_size_ = 0;
+        failed_ = true;
+        return;
+      }
+      buffer_size_ = static_cast<unsigned int>(size);
+    }
 
+    auto to_write = std::min(len, buffer_size_);
+    memcpy(buffer_, bytes, to_write);
 
-}  // namespace converter
-}  // namespace util
+    buffer_ = static_cast<char*>(buffer_) + to_write;
+    buffer_size_ -= to_write;
+
+    bytes += to_write;
+    len -= to_write;
+
+    bytes_written_ += to_write;
+  }
+}
+}  // namespace zc_sink_internal
+}  // namespace io
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/io/zero_copy_sink.h b/src/google/protobuf/io/zero_copy_sink.h
new file mode 100644
index 0000000..bf1fe0e
--- /dev/null
+++ b/src/google/protobuf/io/zero_copy_sink.h
@@ -0,0 +1,80 @@
+// 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_UTIL_ZERO_COPY_SINK_H__
+#define GOOGLE_PROTOBUF_UTIL_ZERO_COPY_SINK_H__
+
+#include <cstddef>
+
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/port.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace io {
+namespace zc_sink_internal {
+
+// Internal helper class, for turning a ZeroCopyOutputStream into a sink.
+class PROTOBUF_EXPORT ZeroCopyStreamByteSink {
+ public:
+  explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream)
+      : stream_(stream) {}
+  ZeroCopyStreamByteSink(const ZeroCopyStreamByteSink&) = delete;
+  ZeroCopyStreamByteSink& operator=(const ZeroCopyStreamByteSink&) = delete;
+
+  ~ZeroCopyStreamByteSink() {
+    if (buffer_size_ > 0) {
+      stream_->BackUp(buffer_size_);
+    }
+  }
+
+  void Append(const char* bytes, size_t len);
+  void Write(absl::string_view str) { Append(str.data(), str.size()); }
+
+  size_t bytes_written() { return bytes_written_; }
+  bool failed() { return failed_; }
+
+ private:
+  io::ZeroCopyOutputStream* stream_;
+  void* buffer_ = nullptr;
+  size_t buffer_size_ = 0;
+  size_t bytes_written_ = 0;
+  bool failed_ = false;
+};
+}  // namespace zc_sink_internal
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_UTIL_ZERO_COPY_SINK_H__
diff --git a/src/google/protobuf/io/zero_copy_sink_test.cc b/src/google/protobuf/io/zero_copy_sink_test.cc
new file mode 100644
index 0000000..7c69eda
--- /dev/null
+++ b/src/google/protobuf/io/zero_copy_sink_test.cc
@@ -0,0 +1,228 @@
+// 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/io/zero_copy_sink.h"
+
+#include <algorithm>
+#include <array>
+#include <cstdint>
+#include <string>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include <gtest/gtest.h>
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+
+namespace google {
+namespace protobuf {
+namespace io {
+namespace zc_sink_internal {
+namespace {
+
+class ChunkedString {
+ public:
+  explicit ChunkedString(absl::string_view data, size_t skipped_patterns)
+      : data_(data), skipped_patterns_(skipped_patterns) {}
+
+  // Returns the next chunk; empty if out of chunks.
+  absl::string_view NextChunk() {
+    if (pattern_bit_idx_ == data_.size()) {
+      return "";
+    }
+    size_t start = pattern_bit_idx_;
+    do {
+      ++pattern_bit_idx_;
+    } while (pattern_bit_idx_ < data_.size() &&
+             (pattern_ >> pattern_bit_idx_ & 1) == 0);
+    size_t end = pattern_bit_idx_;
+    return data_.substr(start, end - start);
+  }
+
+  // Resets the stream and runs the next pattern of splits.
+  bool NextPattern() {
+    pattern_ += skipped_patterns_;
+    if (pattern_ >= (1 << data_.size())) {
+      return false;
+    }
+    pattern_bit_idx_ = 0;
+    return true;
+  }
+
+  // prints out the pattern as a sequence of quoted strings.
+  std::string PatternAsQuotedString() {
+    std::string out;
+    size_t start = 0;
+    for (size_t i = 0; i <= data_.size(); ++i) {
+      if (i == data_.size() || (pattern_ >> start & 1) != 0) {
+        if (!out.empty()) {
+          absl::StrAppend(&out, " ");
+        }
+        absl::StrAppend(
+            &out, "\"",
+            absl::CHexEscape(std::string{data_.substr(start, i - start)}),
+            "\"");
+        start = i;
+      }
+    }
+    return out;
+  }
+
+ private:
+  absl::string_view data_;
+  size_t skipped_patterns_;
+  // pattern_ is a bitset indicating at which indices we insert a seam.
+  uint64_t pattern_ = 0;
+  size_t pattern_bit_idx_ = 0;
+};
+
+class PatternedOutputStream : public io::ZeroCopyOutputStream {
+ public:
+  explicit PatternedOutputStream(ChunkedString data) : data_(data) {}
+
+  bool Next(void** buffer, int* length) override {
+    absl::string_view segment;
+    if (!back_up_.empty()) {
+      segment = back_up_.back();
+      back_up_.pop_back();
+    } else {
+      segment_ = data_.NextChunk();
+      segment = segment_;
+    }
+
+    if (segment_.empty()) {
+      return false;
+    }
+
+    // TODO(b/234159981): This is only ever constructed in test code, and only
+    // from non-const bytes, so this is a valid cast. We need to do this since
+    // OSS proto does not yet have absl::Span; once we take a full Abseil
+    // dependency we should use that here instead.
+    *buffer = const_cast<char*>(segment.data());
+    *length = static_cast<int>(segment.size());
+    byte_count_ += static_cast<int64_t>(segment.size());
+    return true;
+  }
+
+  void BackUp(int length) override {
+    GOOGLE_CHECK(length <= static_cast<int>(segment_.size()));
+
+    size_t backup = segment_.size() - static_cast<size_t>(length);
+    back_up_.push_back(segment_.substr(backup));
+    segment_ = segment_.substr(0, backup);
+    byte_count_ -= static_cast<int64_t>(length);
+  }
+
+  int64_t ByteCount() const override { return byte_count_; }
+
+ private:
+  ChunkedString data_;
+  absl::string_view segment_;
+
+  std::vector<absl::string_view> back_up_;
+  int64_t byte_count_ = 0;
+};
+
+class ZeroCopyStreamByteSinkTest : public testing::Test {
+ protected:
+  std::array<char, 10> output_{};
+  absl::string_view output_view_{output_.data(), output_.size()};
+  ChunkedString output_chunks_{output_view_, 7};
+};
+
+TEST_F(ZeroCopyStreamByteSinkTest, WriteExact) {
+  do {
+    SCOPED_TRACE(output_chunks_.PatternAsQuotedString());
+    ChunkedString input("0123456789", 1);
+
+    do {
+      SCOPED_TRACE(input.PatternAsQuotedString());
+      output_ = {};
+      PatternedOutputStream output_stream(output_chunks_);
+      ZeroCopyStreamByteSink byte_sink(&output_stream);
+      SCOPED_TRACE(input.PatternAsQuotedString());
+      absl::string_view chunk;
+      while (!(chunk = input.NextChunk()).empty()) {
+        byte_sink.Append(chunk.data(), chunk.size());
+      }
+    } while (input.NextPattern());
+
+    ASSERT_EQ(output_view_, "0123456789");
+  } while (output_chunks_.NextPattern());
+}
+
+TEST_F(ZeroCopyStreamByteSinkTest, WriteShort) {
+  do {
+    SCOPED_TRACE(output_chunks_.PatternAsQuotedString());
+    ChunkedString input("012345678", 1);
+
+    do {
+      SCOPED_TRACE(input.PatternAsQuotedString());
+      output_ = {};
+      PatternedOutputStream output_stream(output_chunks_);
+      ZeroCopyStreamByteSink byte_sink(&output_stream);
+      SCOPED_TRACE(input.PatternAsQuotedString());
+      absl::string_view chunk;
+      while (!(chunk = input.NextChunk()).empty()) {
+        byte_sink.Append(chunk.data(), chunk.size());
+      }
+    } while (input.NextPattern());
+
+    ASSERT_EQ(output_view_, absl::string_view("012345678\0", 10));
+  } while (output_chunks_.NextPattern());
+}
+
+TEST_F(ZeroCopyStreamByteSinkTest, WriteLong) {
+  do {
+    SCOPED_TRACE(output_chunks_.PatternAsQuotedString());
+    ChunkedString input("0123456789A", 1);
+
+    do {
+      SCOPED_TRACE(input.PatternAsQuotedString());
+      output_ = {};
+      PatternedOutputStream output_stream(output_chunks_);
+      ZeroCopyStreamByteSink byte_sink(&output_stream);
+      SCOPED_TRACE(input.PatternAsQuotedString());
+      absl::string_view chunk;
+      while (!(chunk = input.NextChunk()).empty()) {
+        byte_sink.Append(chunk.data(), chunk.size());
+      }
+    } while (input.NextPattern());
+
+    ASSERT_EQ(output_view_, "0123456789");
+  } while (output_chunks_.NextPattern());
+}
+}  // namespace
+}  // namespace zc_sink_internal
+}  // namespace io
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/io/zero_copy_stream.cc b/src/google/protobuf/io/zero_copy_stream.cc
index f81555e..0e3ae16 100644
--- a/src/google/protobuf/io/zero_copy_stream.cc
+++ b/src/google/protobuf/io/zero_copy_stream.cc
@@ -32,15 +32,78 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/io/zero_copy_stream.h>
+#include "google/protobuf/io/zero_copy_stream.h"
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include <utility>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/cord_buffer.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/span.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace io {
 
+bool ZeroCopyInputStream::ReadCord(absl::Cord* cord, int count) {
+  if (count <= 0) return true;
+
+  absl::CordBuffer cord_buffer = cord->GetAppendBuffer(count);
+  absl::Span<char> out = cord_buffer.available_up_to(count);
+
+  auto FetchNextChunk = [&]() -> absl::Span<const char> {
+    const void* buffer;
+    int size;
+    if (!Next(&buffer, &size)) return {};
+
+    if (size > count) {
+      BackUp(size - count);
+      size = count;
+    }
+    return absl::MakeConstSpan(static_cast<const char*>(buffer), size);
+  };
+
+  auto AppendFullBuffer = [&]() -> absl::Span<char> {
+    cord->Append(std::move(cord_buffer));
+    cord_buffer = absl::CordBuffer::CreateWithDefaultLimit(count);
+    return cord_buffer.available_up_to(count);
+  };
+
+  auto CopyBytes = [&](absl::Span<char>& dst, absl::Span<const char>& src,
+                       size_t bytes) {
+    memcpy(dst.data(), src.data(), bytes);
+    dst.remove_prefix(bytes);
+    src.remove_prefix(bytes);
+    count -= bytes;
+    cord_buffer.IncreaseLengthBy(bytes);
+  };
+
+  do {
+    absl::Span<const char> in = FetchNextChunk();
+    if (in.empty()) {
+      // Append whatever we have pending so far.
+      cord->Append(std::move(cord_buffer));
+      return false;
+    }
+
+    if (out.empty()) out = AppendFullBuffer();
+
+    while (in.size() > out.size()) {
+      CopyBytes(out, in, out.size());
+      out = AppendFullBuffer();
+    }
+
+    CopyBytes(out, in, in.size());
+  } while (count > 0);
+
+  cord->Append(std::move(cord_buffer));
+  return true;
+}
 
 bool ZeroCopyOutputStream::WriteAliasedRaw(const void* /* data */,
                                            int /* size */) {
diff --git a/src/google/protobuf/io/zero_copy_stream.h b/src/google/protobuf/io/zero_copy_stream.h
index 2041cbf..626f29d 100644
--- a/src/google/protobuf/io/zero_copy_stream.h
+++ b/src/google/protobuf/io/zero_copy_stream.h
@@ -107,12 +107,13 @@
 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
 
-
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/cord.h"
+#include "google/protobuf/port.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -127,6 +128,8 @@
 class PROTOBUF_EXPORT ZeroCopyInputStream {
  public:
   ZeroCopyInputStream() {}
+  ZeroCopyInputStream(const ZeroCopyInputStream&) = delete;
+  ZeroCopyInputStream& operator=(const ZeroCopyInputStream&) = delete;
   virtual ~ZeroCopyInputStream() {}
 
   // Obtains a chunk of data from the stream.
@@ -181,9 +184,18 @@
   // Returns the total number of bytes read since this object was created.
   virtual int64_t ByteCount() const = 0;
 
+  // Read the next `count` bytes and append it to the given Cord.
+  //
+  // In the case of a read error, the method reads as much data as possible into
+  // the cord before returning false. The default implementation iterates over
+  // the buffers and appends up to `count` bytes of data into `cord` using the
+  // `absl::CordBuffer` API.
+  //
+  // Some streams may implement this in a way that avoids copying by sharing or
+  // reference counting existing data managed by the stream implementation.
+  //
+  virtual bool ReadCord(absl::Cord* cord, int count);
 
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyInputStream);
 };
 
 // Abstract interface similar to an output stream but designed to minimize
@@ -191,6 +203,8 @@
 class PROTOBUF_EXPORT ZeroCopyOutputStream {
  public:
   ZeroCopyOutputStream() {}
+  ZeroCopyOutputStream(const ZeroCopyOutputStream&) = delete;
+  ZeroCopyOutputStream& operator=(const ZeroCopyOutputStream&) = delete;
   virtual ~ZeroCopyOutputStream() {}
 
   // Obtains a buffer into which data can be written.  Any data written
@@ -246,15 +260,12 @@
   virtual bool WriteAliasedRaw(const void* data, int size);
   virtual bool AllowsAliasing() const { return false; }
 
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyOutputStream);
 };
 
 }  // namespace io
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_H__
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.cc b/src/google/protobuf/io/zero_copy_stream_impl.cc
index c66bc86..3212783 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl.cc
@@ -43,11 +43,10 @@
 #include <algorithm>
 #include <iostream>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
 
 
 namespace google {
@@ -170,8 +169,8 @@
 
 // ===================================================================
 
-FileOutputStream::FileOutputStream(int file_descriptor, int /*block_size*/)
-    : CopyingOutputStreamAdaptor(&copying_output_),
+FileOutputStream::FileOutputStream(int file_descriptor, int block_size)
+    : CopyingOutputStreamAdaptor(&copying_output_, block_size),
       copying_output_(file_descriptor) {}
 
 bool FileOutputStream::Close() {
diff --git a/src/google/protobuf/io/zero_copy_stream_impl.h b/src/google/protobuf/io/zero_copy_stream_impl.h
index a385992..d5a119c 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl.h
@@ -40,16 +40,15 @@
 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
 
-
 #include <iosfwd>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -71,6 +70,8 @@
   // should be read and returned with each call to Next().  Otherwise,
   // a reasonable default is used.
   explicit FileInputStream(int file_descriptor, int block_size = -1);
+  FileInputStream(const FileInputStream&) = delete;
+  FileInputStream& operator=(const FileInputStream&) = delete;
 
   // Flushes any buffers and closes the underlying file.  Returns false if
   // an error occurs during the process; use GetErrno() to examine the error.
@@ -101,6 +102,8 @@
       : public CopyingInputStream {
    public:
     CopyingFileInputStream(int file_descriptor);
+    CopyingFileInputStream(const CopyingFileInputStream&) = delete;
+    CopyingFileInputStream& operator=(const CopyingFileInputStream&) = delete;
     ~CopyingFileInputStream() override;
 
     bool Close();
@@ -123,14 +126,10 @@
     // Did we try to seek once and fail?  If so, we assume this file descriptor
     // doesn't support seeking and won't try again.
     bool previous_seek_failed_;
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileInputStream);
   };
 
   CopyingFileInputStream copying_input_;
   CopyingInputStreamAdaptor impl_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileInputStream);
 };
 
 // ===================================================================
@@ -150,6 +149,8 @@
   // that should be returned by Next().  Otherwise, a reasonable default
   // is used.
   explicit FileOutputStream(int file_descriptor, int block_size = -1);
+  FileOutputStream(const FileOutputStream&) = delete;
+  FileOutputStream& operator=(const FileOutputStream&) = delete;
 
   ~FileOutputStream() override;
 
@@ -176,6 +177,8 @@
       : public CopyingOutputStream {
    public:
     CopyingFileOutputStream(int file_descriptor);
+    CopyingFileOutputStream(const CopyingFileOutputStream&) = delete;
+    CopyingFileOutputStream& operator=(const CopyingFileOutputStream&) = delete;
     ~CopyingFileOutputStream() override;
 
     bool Close();
@@ -193,13 +196,9 @@
 
     // The errno of the I/O error, if one has occurred.  Otherwise, zero.
     int errno_;
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingFileOutputStream);
   };
 
   CopyingFileOutputStream copying_output_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FileOutputStream);
 };
 
 // ===================================================================
@@ -216,6 +215,8 @@
   // should be read and returned with each call to Next().  Otherwise,
   // a reasonable default is used.
   explicit IstreamInputStream(std::istream* stream, int block_size = -1);
+  IstreamInputStream(const IstreamInputStream&) = delete;
+  IstreamInputStream& operator=(const IstreamInputStream&) = delete;
 
   // implements ZeroCopyInputStream ----------------------------------
   bool Next(const void** data, int* size) override;
@@ -228,6 +229,9 @@
       : public CopyingInputStream {
    public:
     CopyingIstreamInputStream(std::istream* input);
+    CopyingIstreamInputStream(const CopyingIstreamInputStream&) = delete;
+    CopyingIstreamInputStream& operator=(const CopyingIstreamInputStream&) =
+        delete;
     ~CopyingIstreamInputStream() override;
 
     // implements CopyingInputStream ---------------------------------
@@ -237,14 +241,10 @@
    private:
     // The stream.
     std::istream* input_;
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingIstreamInputStream);
   };
 
   CopyingIstreamInputStream copying_input_;
   CopyingInputStreamAdaptor impl_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(IstreamInputStream);
 };
 
 // ===================================================================
@@ -261,6 +261,8 @@
   // that should be returned by Next().  Otherwise, a reasonable default
   // is used.
   explicit OstreamOutputStream(std::ostream* stream, int block_size = -1);
+  OstreamOutputStream(const OstreamOutputStream&) = delete;
+  OstreamOutputStream& operator=(const OstreamOutputStream&) = delete;
   ~OstreamOutputStream() override;
 
   // implements ZeroCopyOutputStream ---------------------------------
@@ -273,6 +275,9 @@
       : public CopyingOutputStream {
    public:
     CopyingOstreamOutputStream(std::ostream* output);
+    CopyingOstreamOutputStream(const CopyingOstreamOutputStream&) = delete;
+    CopyingOstreamOutputStream& operator=(const CopyingOstreamOutputStream&) =
+        delete;
     ~CopyingOstreamOutputStream() override;
 
     // implements CopyingOutputStream --------------------------------
@@ -281,14 +286,10 @@
    private:
     // The stream.
     std::ostream* output_;
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOstreamOutputStream);
   };
 
   CopyingOstreamOutputStream copying_output_;
   CopyingOutputStreamAdaptor impl_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(OstreamOutputStream);
 };
 
 // ===================================================================
@@ -306,6 +307,8 @@
   // All streams passed in as well as the array itself must remain valid
   // until the ConcatenatingInputStream is destroyed.
   ConcatenatingInputStream(ZeroCopyInputStream* const streams[], int count);
+  ConcatenatingInputStream(const ConcatenatingInputStream&) = delete;
+  ConcatenatingInputStream& operator=(const ConcatenatingInputStream&) = delete;
   ~ConcatenatingInputStream() override = default;
 
   // implements ZeroCopyInputStream ----------------------------------
@@ -321,8 +324,6 @@
   ZeroCopyInputStream* const* streams_;
   int stream_count_;
   int64_t bytes_retired_;  // Bytes read from previous streams.
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ConcatenatingInputStream);
 };
 
 // ===================================================================
@@ -331,6 +332,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_H__
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 b3dfd84..f29a8c2 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.cc
@@ -32,15 +32,20 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
 
 #include <algorithm>
 #include <limits>
+#include <utility>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/base/casts.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+
+// Must be included last
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -154,7 +159,7 @@
   // 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(
+  absl::strings_internal::STLStringResizeUninitialized(
       target_,
       std::max(new_size,
                kMinimumSize + 0));  // "+ 0" works around GCC4 weirdness.
@@ -183,7 +188,7 @@
   int skipped = 0;
   while (skipped < count) {
     int bytes = Read(junk, std::min(count - skipped,
-                                    implicit_cast<int>(sizeof(junk))));
+                                    absl::implicit_cast<int>(sizeof(junk))));
     if (bytes <= 0) {
       // EOF or read error.
       return skipped;
@@ -462,6 +467,18 @@
   }
 }
 
+bool LimitingInputStream::ReadCord(absl::Cord* cord, int count) {
+  if (count <= 0) return true;
+  if (count <= limit_) {
+    if (!input_->ReadCord(cord, count)) return false;
+    limit_ -= count;
+    return true;
+  }
+  input_->ReadCord(cord, limit_);
+  limit_ = 0;
+  return false;
+}
+
 
 // ===================================================================
 
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 cbda328..21fe8c4 100644
--- a/src/google/protobuf/io/zero_copy_stream_impl_lite.h
+++ b/src/google/protobuf/io/zero_copy_stream_impl_lite.h
@@ -44,19 +44,19 @@
 #ifndef GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
 #define GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
 
-
 #include <iosfwd>
 #include <memory>
 #include <string>
+#include <utility>
 
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/port.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -78,6 +78,10 @@
   ArrayInputStream(const void* data, int size, int block_size = -1);
   ~ArrayInputStream() override = default;
 
+  // `ArrayInputStream` is neither copiable nor assignable
+  ArrayInputStream(const ArrayInputStream&) = delete;
+  ArrayInputStream& operator=(const ArrayInputStream&) = delete;
+
   // implements ZeroCopyInputStream ----------------------------------
   bool Next(const void** data, int* size) override;
   void BackUp(int count) override;
@@ -93,8 +97,6 @@
   int position_;
   int last_returned_size_;  // How many bytes we returned last time Next()
                             // was called (used for error checking only).
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayInputStream);
 };
 
 // ===================================================================
@@ -113,6 +115,10 @@
   ArrayOutputStream(void* data, int size, int block_size = -1);
   ~ArrayOutputStream() override = default;
 
+  // `ArrayOutputStream` is neither copiable nor assignable
+  ArrayOutputStream(const ArrayOutputStream&) = delete;
+  ArrayOutputStream& operator=(const ArrayOutputStream&) = delete;
+
   // implements ZeroCopyOutputStream ---------------------------------
   bool Next(void** data, int* size) override;
   void BackUp(int count) override;
@@ -126,8 +132,6 @@
   int position_;
   int last_returned_size_;  // How many bytes we returned last time Next()
                             // was called (used for error checking only).
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayOutputStream);
 };
 
 // ===================================================================
@@ -148,6 +152,10 @@
   explicit StringOutputStream(std::string* target);
   ~StringOutputStream() override = default;
 
+  // `StringOutputStream` is neither copiable nor assignable
+  StringOutputStream(const StringOutputStream&) = delete;
+  StringOutputStream& operator=(const StringOutputStream&) = delete;
+
   // implements ZeroCopyOutputStream ---------------------------------
   bool Next(void** data, int* size) override;
   void BackUp(int count) override;
@@ -157,8 +165,6 @@
   static constexpr size_t kMinimumSize = 16;
 
   std::string* target_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringOutputStream);
 };
 
 // Note:  There is no StringInputStream.  Instead, just create an
@@ -215,6 +221,10 @@
                                      int block_size = -1);
   ~CopyingInputStreamAdaptor() override;
 
+  // `CopyingInputStreamAdaptor` is neither copiable nor assignable
+  CopyingInputStreamAdaptor(const CopyingInputStreamAdaptor&) = delete;
+  CopyingInputStreamAdaptor& operator=(const CopyingInputStreamAdaptor&) = delete;
+
   // Call SetOwnsCopyingStream(true) to tell the CopyingInputStreamAdaptor to
   // delete the underlying CopyingInputStream when it is destroyed.
   void SetOwnsCopyingStream(bool value) { owns_copying_stream_ = value; }
@@ -255,8 +265,6 @@
   // BackUp().  These need to be returned again.
   // 0 <= backup_bytes_ <= buffer_used_
   int backup_bytes_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingInputStreamAdaptor);
 };
 
 // ===================================================================
@@ -298,6 +306,10 @@
                                       int block_size = -1);
   ~CopyingOutputStreamAdaptor() override;
 
+  // `CopyingOutputStreamAdaptor` is neither copiable nor assignable
+  CopyingOutputStreamAdaptor(const CopyingOutputStreamAdaptor&) = delete;
+  CopyingOutputStreamAdaptor& operator=(const CopyingOutputStreamAdaptor&) = delete;
+
   // Writes all pending data to the underlying stream.  Returns false if a
   // write error occurred on the underlying stream.  (The underlying
   // stream itself is not necessarily flushed.)
@@ -342,8 +354,6 @@
   // returned by Next()).  When BackUp() is called, we just reduce this.
   // 0 <= buffer_used_ <= buffer_size_.
   int buffer_used_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CopyingOutputStreamAdaptor);
 };
 
 // ===================================================================
@@ -356,42 +366,31 @@
   LimitingInputStream(ZeroCopyInputStream* input, int64_t limit);
   ~LimitingInputStream() override;
 
+  // `LimitingInputStream` is neither copiable nor assignable
+  LimitingInputStream(const LimitingInputStream&) = delete;
+  LimitingInputStream& operator=(const LimitingInputStream&) = delete;
+
   // implements ZeroCopyInputStream ----------------------------------
   bool Next(const void** data, int* size) override;
   void BackUp(int count) override;
   bool Skip(int count) override;
   int64_t ByteCount() const override;
+  bool ReadCord(absl::Cord* cord, int count) override;
 
 
  private:
   ZeroCopyInputStream* input_;
   int64_t limit_;  // Decreases as we go, becomes negative if we overshoot.
   int64_t prior_bytes_read_;  // Bytes read on underlying stream at construction
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LimitingInputStream);
 };
 
 
 // ===================================================================
 
-// mutable_string_data() and as_string_data() are workarounds to improve
-// the performance of writing new data to an existing string.  Unfortunately
-// the methods provided by the string class are suboptimal, and using memcpy()
-// is mildly annoying because it requires its pointer args to be non-NULL even
-// if we ask it to copy 0 bytes.  Furthermore, string_as_array() has the
-// property that it always returns NULL if its arg is the empty string, exactly
-// what we want to avoid if we're using it in conjunction with memcpy()!
-// With C++11, the desired memcpy() boils down to memcpy(..., &(*s)[0], size),
-// where s is a string*.  Without C++11, &(*s)[0] is not guaranteed to be safe,
-// so we use string_as_array(), and live with the extra logic that tests whether
-// *s is empty.
-
 // Return a pointer to mutable characters underlying the given string.  The
 // return value is valid until the next time the string is resized.  We
 // trust the caller to treat the return value as an array of length s->size().
 inline char* mutable_string_data(std::string* s) {
-  // This should be simpler & faster than string_as_array() because the latter
-  // is guaranteed to return NULL when *s is empty, so it has to check for that.
   return &(*s)[0];
 }
 
@@ -408,6 +407,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_IO_ZERO_COPY_STREAM_IMPL_LITE_H__
diff --git a/src/google/protobuf/io/zero_copy_stream_unittest.cc b/src/google/protobuf/io/zero_copy_stream_unittest.cc
index d4e5b54..51fb2e1 100644
--- a/src/google/protobuf/io/zero_copy_stream_unittest.cc
+++ b/src/google/protobuf/io/zero_copy_stream_unittest.cc
@@ -46,6 +46,7 @@
 //   "parametized tests" so that one set of tests can be used on all the
 //   implementations.
 
+#include <algorithm>
 #include <chrono>
 #include <thread>
 
@@ -61,23 +62,28 @@
 
 #include <memory>
 #include <sstream>
+#include <utility>
+#include <vector>
 
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/test_util2.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/test_util2.h"
 
 #if HAVE_ZLIB
-#include <google/protobuf/io/gzip_stream.h>
+#include "google/protobuf/io/gzip_stream.h"
 #endif
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 namespace google {
 namespace protobuf {
 namespace io {
@@ -139,7 +145,7 @@
 };
 
 const int IoTest::kBlockSizes[] = {-1, 1, 2, 5, 7, 10, 23, 64};
-const int IoTest::kBlockSizeCount = GOOGLE_ARRAYSIZE(IoTest::kBlockSizes);
+const int IoTest::kBlockSizeCount = ABSL_ARRAYSIZE(IoTest::kBlockSizes);
 
 bool IoTest::WriteToOutput(ZeroCopyOutputStream* output, const void* data,
                            int size) {
@@ -570,7 +576,7 @@
   // Some ad-hoc testing of compression options.
 
   std::string golden_filename =
-      TestUtil::GetTestDataPath("net/proto2/internal/testdata/golden_message");
+      TestUtil::GetTestDataPath("third_party/protobuf/testdata/golden_message");
   std::string golden;
   GOOGLE_CHECK_OK(File::GetContents(golden_filename, &golden, true));
 
@@ -719,6 +725,9 @@
 
 // Verifies that outputs up to kint32max can be created.
 TEST_F(IoTest, LargeOutput) {
+  // Filter out this test on 32-bit architectures and tsan builds.
+  if(sizeof(void*) < 8) return;
+#ifndef THREAD_SANITIZER
   std::string str;
   StringOutputStream output(&str);
   void* unused_data;
@@ -730,6 +739,90 @@
   // Further increases should be possible.
   output.Next(&unused_data, &size);
   EXPECT_GT(size, 0);
+#endif  // THREAD_SANITIZER
+}
+
+TEST(DefaultReadCordTest, ReadSmallCord) {
+  std::string source = "abcdefghijk";
+  ArrayInputStream input(source.data(), source.size());
+
+  absl::Cord dest;
+  EXPECT_TRUE(input.Skip(1));
+  EXPECT_TRUE(input.ReadCord(&dest, source.size() - 2));
+
+  EXPECT_EQ(dest, "bcdefghij");
+}
+
+TEST(DefaultReadCordTest, ReadSmallCordAfterBackUp) {
+  std::string source = "abcdefghijk";
+  ArrayInputStream input(source.data(), source.size());
+
+  absl::Cord dest;
+  const void* buffer;
+  int size;
+  EXPECT_TRUE(input.Next(&buffer, &size));
+  input.BackUp(size - 1);
+
+  EXPECT_TRUE(input.ReadCord(&dest, source.size() - 2));
+
+  EXPECT_EQ(dest, "bcdefghij");
+}
+
+TEST(DefaultReadCordTest, ReadLargeCord) {
+  std::string source = "abcdefghijk";
+  for (int i = 0; i < 1024; i++) {
+    source.append("abcdefghijk");
+  }
+
+  absl::Cord dest;
+  ArrayInputStream input(source.data(), source.size());
+  EXPECT_TRUE(input.Skip(1));
+  EXPECT_TRUE(input.ReadCord(&dest, source.size() - 2));
+
+  absl::Cord expected(source);
+  expected.RemovePrefix(1);
+  expected.RemoveSuffix(1);
+
+  EXPECT_EQ(expected, dest);
+}
+
+TEST(DefaultReadCordTest, ReadLargeCordAfterBackup) {
+  std::string source = "abcdefghijk";
+  for (int i = 0; i < 1024; i++) {
+    source.append("abcdefghijk");
+  }
+
+  absl::Cord dest;
+  ArrayInputStream input(source.data(), source.size());
+
+  const void* buffer;
+  int size;
+  EXPECT_TRUE(input.Next(&buffer, &size));
+  input.BackUp(size - 1);
+
+  EXPECT_TRUE(input.ReadCord(&dest, source.size() - 2));
+
+  absl::Cord expected(source);
+  expected.RemovePrefix(1);
+  expected.RemoveSuffix(1);
+
+  EXPECT_EQ(expected, dest);
+
+  EXPECT_TRUE(input.Next(&buffer, &size));
+  EXPECT_EQ("k", std::string(reinterpret_cast<const char*>(buffer), size));
+}
+
+TEST(DefaultReadCordTest, ReadCordEof) {
+  std::string source = "abcdefghijk";
+
+  absl::Cord dest;
+  ArrayInputStream input(source.data(), source.size());
+  input.Skip(1);
+  EXPECT_FALSE(input.ReadCord(&dest, source.size()));
+
+  absl::Cord expected(source);
+  expected.RemovePrefix(1);
+  EXPECT_EQ(expected, dest);
 }
 
 
@@ -1024,7 +1117,7 @@
                                     &input5, &input6, &input7};
 
   // Create the concatenating stream and read.
-  ConcatenatingInputStream input(streams, GOOGLE_ARRAYSIZE(streams));
+  ConcatenatingInputStream input(streams, ABSL_ARRAYSIZE(streams));
   ReadStuff(&input);
 }
 
@@ -1052,7 +1145,7 @@
 TEST_F(IoTest, LimitingInputStreamByteCount) {
   const int kHalfBufferSize = 128;
   const int kBufferSize = kHalfBufferSize * 2;
-  uint8 buffer[kBufferSize];
+  uint8 buffer[kBufferSize] = {};
 
   // Set up input. Only allow half to be read at once.
   ArrayInputStream array_input(buffer, kBufferSize, kHalfBufferSize);
diff --git a/src/google/protobuf/json/BUILD.bazel b/src/google/protobuf/json/BUILD.bazel
new file mode 100644
index 0000000..e2b8baf
--- /dev/null
+++ b/src/google/protobuf/json/BUILD.bazel
@@ -0,0 +1,270 @@
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+package(default_visibility = [
+    "//src/google/protobuf/json:__pkg__",
+    "//pkg:__pkg__",
+])
+
+licenses(["notice"])
+
+cc_library(
+    name = "json",
+    srcs = ["json.cc"],
+    hdrs = ["json.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//visibility:public"],
+    deps = [
+        ":parser",
+        ":unparser",
+        "//src/google/protobuf",
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/io:zero_copy_sink",
+        "//src/google/protobuf/util:type_resolver_util",
+        "@com_google_absl//absl/base",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "json_test",
+    srcs = ["json_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":json",
+        "//src/google/protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/util:json_format_cc_proto",
+        "//src/google/protobuf/util:json_format_proto3_cc_proto",
+        "//src/google/protobuf/util:type_resolver_util",
+        "@com_google_absl//absl/flags:flag",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "test_input_stream",
+    testonly = True,
+    hdrs = ["internal/test_input_stream.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//visibility:private"],
+    deps = [
+        "//src/google/protobuf/io",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "zero_copy_buffered_stream",
+    srcs = ["internal/zero_copy_buffered_stream.cc"],
+    hdrs = ["internal/zero_copy_buffered_stream.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/io",
+        "@com_google_absl//absl/algorithm:container",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+    ],
+)
+
+cc_test(
+    name = "zero_copy_buffered_stream_test",
+    srcs = ["internal/zero_copy_buffered_stream_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":test_input_stream",
+        ":zero_copy_buffered_stream",
+        "@com_google_absl//absl/strings",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "untyped_message",
+    srcs = ["internal/untyped_message.cc"],
+    hdrs = ["internal/untyped_message.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        "//src/google/protobuf",
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf:protobuf_lite",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/util:type_resolver_util",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_absl//absl/types:optional",
+        "@com_google_absl//absl/types:span",
+        "@com_google_absl//absl/types:variant",
+        "@utf8_range//:utf8_validity",
+    ],
+)
+
+cc_library(
+    name = "lexer",
+    srcs = ["internal/lexer.cc"],
+    hdrs = ["internal/lexer.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":message_path",
+        ":zero_copy_buffered_stream",
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/io",
+        "@com_google_absl//absl/algorithm:container",
+        "@com_google_absl//absl/numeric:bits",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+    ],
+)
+
+cc_test(
+    name = "lexer_test",
+    srcs = ["internal/lexer_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":lexer",
+        ":test_input_stream",
+        "//src/google/protobuf/io",
+        "@com_google_absl//absl/algorithm:container",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_absl//absl/types:variant",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "writer",
+    srcs = ["internal/writer.cc"],
+    hdrs = ["internal/writer.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/io:tokenizer",
+        "//src/google/protobuf/io:zero_copy_sink",
+        "@com_google_absl//absl/algorithm:container",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+    ],
+)
+
+cc_library(
+    name = "descriptor_traits",
+    hdrs = ["internal/descriptor_traits.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":lexer",
+        ":untyped_message",
+        "//src/google/protobuf",
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/util:type_resolver_util",
+        "@com_google_absl//absl/algorithm:container",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_absl//absl/types:optional",
+    ],
+)
+
+cc_library(
+    name = "parser",
+    srcs = [
+        "internal/parser.cc",
+    ],
+    hdrs = [
+        "internal/parser.h",
+        "internal/parser_traits.h",
+    ],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":descriptor_traits",
+        ":lexer",
+        "//src/google/protobuf",
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/io:zero_copy_sink",
+        "//src/google/protobuf/util:type_resolver_util",
+        "@com_google_absl//absl/base",
+        "@com_google_absl//absl/base:core_headers",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/container:flat_hash_set",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_absl//absl/types:optional",
+        "@com_google_absl//absl/types:span",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "unparser",
+    srcs = [
+        "internal/unparser.cc",
+    ],
+    hdrs = [
+        "internal/unparser.h",
+        "internal/unparser_traits.h",
+    ],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        ":descriptor_traits",
+        ":untyped_message",
+        ":writer",
+        "//src/google/protobuf",
+        "//src/google/protobuf:port_def",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/util:type_resolver_util",
+        "@com_google_absl//absl/container:flat_hash_map",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/strings",
+        "@com_google_absl//absl/strings:str_format",
+        "@com_google_absl//absl/types:optional",
+        "@com_google_absl//absl/types:variant",
+    ],
+)
+
+cc_library(
+    name = "message_path",
+    srcs = ["internal/message_path.cc"],
+    hdrs = ["internal/message_path.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    deps = [
+        "//src/google/protobuf",
+        "@com_google_absl//absl/cleanup",
+        "@com_google_absl//absl/strings",
+    ],
+)
diff --git a/src/google/protobuf/json/internal/descriptor_traits.h b/src/google/protobuf/json/internal/descriptor_traits.h
new file mode 100644
index 0000000..fb309e9
--- /dev/null
+++ b/src/google/protobuf/json/internal/descriptor_traits.h
@@ -0,0 +1,529 @@
+// 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_JSON_INTERNAL_DESCRIPTOR_TRAITS_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_DESCRIPTOR_TRAITS_H__
+
+#include <array>
+#include <cfloat>
+#include <cmath>
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <string>
+#include <utility>
+
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "absl/algorithm/container.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "google/protobuf/json/internal/lexer.h"
+#include "google/protobuf/json/internal/untyped_message.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+// Traits for working with descriptor.proto and type.proto generically.
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+enum class MessageType {
+  kNotWellKnown,
+  kAny,
+  kWrapper,
+  kStruct,
+  kList,
+  kValue,
+  kNull,
+  kTimestamp,
+  kDuration,
+  kFieldMask,
+};
+
+inline MessageType ClassifyMessage(absl::string_view name) {
+  constexpr absl::string_view kWellKnownPkg = "google.protobuf.";
+  if (!absl::StartsWith(name, kWellKnownPkg)) {
+    return MessageType::kNotWellKnown;
+  }
+  name = name.substr(kWellKnownPkg.size());
+
+  switch (name.size()) {
+    case 3:
+      if (name == "Any") {
+        return MessageType::kAny;
+      }
+      break;
+    case 5:
+      if (name == "Value") {
+        return MessageType::kValue;
+      }
+      break;
+    case 6:
+      if (name == "Struct") {
+        return MessageType::kStruct;
+      }
+      break;
+    case 8:
+      if (name == "Duration") {
+        return MessageType::kDuration;
+      }
+      break;
+    case 9:
+      if (name == "BoolValue") {
+        return MessageType::kWrapper;
+      }
+      if (name == "NullValue") {
+        return MessageType::kNull;
+      }
+      if (name == "ListValue") {
+        return MessageType::kList;
+      }
+      if (name == "Timestamp") {
+        return MessageType::kTimestamp;
+      }
+      if (name == "FieldMask") {
+        return MessageType::kFieldMask;
+      }
+      break;
+    case 10:
+      if (name == "BytesValue" || name == "FloatValue" ||
+          name == "Int32Value" || name == "Int64Value") {
+        return MessageType::kWrapper;
+      }
+      break;
+    case 11:
+      if (name == "DoubleValue" || name == "StringValue" ||
+          name == "UInt32Value" || name == "UInt64Value") {
+        return MessageType::kWrapper;
+      }
+      break;
+    default:
+      break;
+  }
+
+  return MessageType::kNotWellKnown;
+}
+
+// Helper alias templates to avoid needing to write `typename` in function
+// signatures.
+template <typename Traits>
+using Field = typename Traits::Field;
+template <typename Traits>
+using Desc = typename Traits::Desc;
+
+// Traits for proto2-ish descriptors.
+struct Proto2Descriptor {
+  // A descriptor for introspecting the fields of a message type.
+  //
+  // Desc<Traits> needs to be handled through a const Desc& in most (but not
+  // all, in the case of ResolverTraits) cases, so we do not include the const*
+  // annotation on this type.
+  using Desc = Descriptor;
+
+  // A field descriptor for introspecting a single field.
+  //
+  // Field<Traits> is always copyable, so this can be a pointer directly.
+  using Field = const FieldDescriptor*;
+
+  /// Functions for working with descriptors. ///
+
+  static absl::string_view TypeName(const Desc& d) { return d.full_name(); }
+
+  static absl::optional<Field> FieldByNumber(const Desc& d, int32_t number) {
+    if (const auto* field = d.FindFieldByNumber(number)) {
+      return field;
+    }
+    return absl::nullopt;
+  }
+
+  static Field MustHaveField(const Desc& d, int32_t number,
+                             JsonLocation::SourceLocation loc =
+                                 JsonLocation::SourceLocation::current()) {
+    auto f = FieldByNumber(d, number);
+    if (!f.has_value()) {
+      GOOGLE_LOG(FATAL)
+          << absl::StrFormat(
+                 "%s has, by definition, a field numbered %d, but it could not "
+                 "be "
+                 "looked up; this is a bug",
+                 TypeName(d), number);
+    }
+    return *f;
+  }
+
+  static absl::optional<Field> FieldByName(const Desc& d,
+                                           absl::string_view name) {
+    if (const auto* field = d.FindFieldByCamelcaseName(name)) {
+      return field;
+    }
+
+    if (const auto* field = d.FindFieldByName(name)) {
+      return field;
+    }
+
+    for (int i = 0; i < d.field_count(); ++i) {
+      const auto* field = d.field(i);
+      if (field->has_json_name() && field->json_name() == name) {
+        return field;
+      }
+    }
+
+    return absl::nullopt;
+  }
+
+  static Field KeyField(const Desc& d) { return d.map_key(); }
+
+  static Field ValueField(const Desc& d) { return d.map_value(); }
+
+  static size_t FieldCount(const Desc& d) { return d.field_count(); }
+
+  static Field FieldByIndex(const Desc& d, size_t idx) { return d.field(idx); }
+
+  static absl::optional<Field> ExtensionByName(const Desc& d,
+                                               absl::string_view name) {
+    auto* field = d.file()->pool()->FindExtensionByName(name);
+    if (field == nullptr) {
+      return absl::nullopt;
+    }
+    return field;
+  }
+
+  /// Functions for introspecting fields. ///
+
+  static absl::string_view FieldName(Field f) { return f->name(); }
+  static absl::string_view FieldJsonName(Field f) {
+    return f->has_json_name() ? f->json_name() : f->camelcase_name();
+  }
+  static absl::string_view FieldFullName(Field f) { return f->full_name(); }
+
+  static absl::string_view FieldTypeName(Field f) {
+    if (f->type() == FieldDescriptor::TYPE_MESSAGE) {
+      return f->message_type()->full_name();
+    }
+    if (f->type() == FieldDescriptor::TYPE_ENUM) {
+      return f->enum_type()->full_name();
+    }
+    return "";
+  }
+
+  static FieldDescriptor::Type FieldType(Field f) { return f->type(); }
+
+  static int32_t FieldNumber(Field f) { return f->number(); }
+
+  static bool Is32Bit(Field f) {
+    switch (f->cpp_type()) {
+      case FieldDescriptor::CPPTYPE_UINT32:
+      case FieldDescriptor::CPPTYPE_INT32:
+      case FieldDescriptor::CPPTYPE_ENUM:
+      case FieldDescriptor::CPPTYPE_FLOAT:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  static const Desc& ContainingType(Field f) { return *f->containing_type(); }
+
+  static bool IsMap(Field f) { return f->is_map(); }
+
+  static bool IsRepeated(Field f) { return f->is_repeated(); }
+
+  static bool IsOptional(Field f) { return f->has_presence(); }
+
+  static bool IsImplicitPresence(Field f) {
+    return !f->is_repeated() && !f->has_presence();
+  }
+
+  static bool IsExtension(Field f) { return f->is_extension(); }
+
+  static bool IsOneof(Field f) { return f->containing_oneof() != nullptr; }
+
+  static absl::StatusOr<int32_t> EnumNumberByName(Field f,
+                                                  absl::string_view name,
+                                                  bool case_insensitive) {
+    if (case_insensitive) {
+      for (int i = 0; i < f->enum_type()->value_count(); ++i) {
+        const auto* ev = f->enum_type()->value(i);
+        if (absl::EqualsIgnoreCase(name, ev->name())) {
+          return ev->number();
+        }
+      }
+      return absl::InvalidArgumentError(
+          absl::StrFormat("unknown enum value: '%s'", name));
+    }
+
+    if (const auto* ev = f->enum_type()->FindValueByName(name)) {
+      return ev->number();
+    }
+
+    return absl::InvalidArgumentError(
+        absl::StrFormat("unknown enum value: '%s'", name));
+  }
+
+  static absl::StatusOr<std::string> EnumNameByNumber(Field f, int32_t number) {
+    if (const auto* ev = f->enum_type()->FindValueByNumber(number)) {
+      return ev->name();
+    }
+    return absl::InvalidArgumentError(
+        absl::StrFormat("unknown enum number: '%d'", number));
+  }
+
+  // Looks up the corresponding Desc for `f`'s type, if there is one, and
+  // calls `body` with it.
+  //
+  // This needs to have this funny callback API since whether or not the
+  // Descriptor equivalent is an owning type depends on the trait.
+  template <typename F>
+  static absl::Status WithFieldType(Field f, F body) {
+    return body(*f->message_type());
+  }
+
+  // Like WithFieldType, but using dynamic lookup by type URL.
+  template <typename F>
+  static absl::Status WithDynamicType(const Desc& desc,
+                                      const std::string& type_url, F body) {
+    size_t slash = type_url.rfind('/');
+    if (slash == absl::string_view::npos || slash == 0) {
+      return absl::InvalidArgumentError(absl::StrCat(
+          "@type must contain at least one / and a nonempty host; got: ",
+          type_url));
+    }
+    absl::string_view type_name(type_url);
+    type_name = type_name.substr(slash + 1);
+
+    const Descriptor* dyn_desc =
+        desc.file()->pool()->FindMessageTypeByName(type_name);
+    if (dyn_desc == nullptr) {
+      return absl::InvalidArgumentError(
+          absl::StrFormat("could not find @type '%s'", type_url));
+    }
+
+    return body(*dyn_desc);
+  }
+};
+
+// Traits for proto3-ish deserialization.
+//
+// See Proto2Descriptor for API docs.
+struct Proto3Type {
+  using Desc = ResolverPool::Message;
+  using Field = const ResolverPool::Field*;
+
+  /// Functions for working with descriptors. ///
+  static absl::string_view TypeName(const Desc& d) { return d.proto().name(); }
+
+  static absl::optional<Field> FieldByNumber(const Desc& d, int32_t number) {
+    const auto* f = d.FindField(number);
+    return f == nullptr ? absl::nullopt : absl::make_optional(f);
+  }
+
+  static Field MustHaveField(const Desc& d, int32_t number,
+                             JsonLocation::SourceLocation loc =
+                                 JsonLocation::SourceLocation::current()) {
+    auto f = FieldByNumber(d, number);
+    if (!f.has_value()) {
+      GOOGLE_LOG(FATAL)
+          << absl::StrFormat(
+                 "%s has, by definition, a field numbered %d, but it could not "
+                 "be "
+                 "looked up; this is a bug",
+                 TypeName(d), number);
+    }
+    return *f;
+  }
+
+  static absl::optional<Field> FieldByName(const Desc& d,
+                                           absl::string_view name) {
+    const auto* f = d.FindField(name);
+    return f == nullptr ? absl::nullopt : absl::make_optional(f);
+  }
+
+  static Field KeyField(const Desc& d) { return &d.FieldsByIndex()[0]; }
+
+  static Field ValueField(const Desc& d) { return &d.FieldsByIndex()[1]; }
+
+  static size_t FieldCount(const Desc& d) { return d.proto().fields_size(); }
+
+  static Field FieldByIndex(const Desc& d, size_t idx) {
+    return &d.FieldsByIndex()[idx];
+  }
+
+  static absl::optional<Field> ExtensionByName(const Desc& d,
+                                               absl::string_view name) {
+    // type.proto cannot represent extensions, so this function always
+    // fails.
+    return absl::nullopt;
+  }
+
+  /// Functions for introspecting fields. ///
+
+  static absl::string_view FieldName(Field f) { return f->proto().name(); }
+  static absl::string_view FieldJsonName(Field f) {
+    return f->proto().json_name();
+  }
+  static absl::string_view FieldFullName(Field f) { return f->proto().name(); }
+
+  static absl::string_view FieldTypeName(Field f) {
+    absl::string_view url = f->proto().type_url();
+
+    // If there is no slash, `slash` is string_view::npos, which is guaranteed
+    // to be -1.
+    size_t slash = url.rfind('/');
+    return url.substr(slash + 1);
+  }
+
+  static FieldDescriptor::Type FieldType(Field f) {
+    // The descriptor.proto and type.proto field type enums are required to be
+    // the same, so we leverage this.
+    return static_cast<FieldDescriptor::Type>(f->proto().kind());
+  }
+
+  static int32_t FieldNumber(Field f) { return f->proto().number(); }
+
+  static bool Is32Bit(Field f) {
+    switch (f->proto().kind()) {
+      case google::protobuf::Field::TYPE_INT32:
+      case google::protobuf::Field::TYPE_SINT32:
+      case google::protobuf::Field::TYPE_UINT32:
+      case google::protobuf::Field::TYPE_FIXED32:
+      case google::protobuf::Field::TYPE_SFIXED32:
+      case google::protobuf::Field::TYPE_FLOAT:
+        return true;
+      default:
+        return false;
+    }
+  }
+
+  static const Desc& ContainingType(Field f) { return f->parent(); }
+  static bool IsMap(Field f) {
+    if (f->proto().kind() != google::protobuf::Field::TYPE_MESSAGE) {
+      return false;
+    }
+
+    bool value = false;
+    (void)WithFieldType(f, [&value](const Desc& desc) {
+      value = absl::c_any_of(desc.proto().options(), [&](auto& option) {
+        return option.name() == "map_entry";
+      });
+      return absl::OkStatus();
+    });
+    return value;
+  }
+
+  static bool IsRepeated(Field f) {
+    return f->proto().cardinality() ==
+           google::protobuf::Field::CARDINALITY_REPEATED;
+  }
+
+  static bool IsOptional(Field f) {
+    // Implicit presence requires this weird check: in proto3, everything is
+    // implicit presence, except for things that are members of oneofs,
+    // which is how proto3 optional is represented.
+    if (f->parent().proto().syntax() == google::protobuf::SYNTAX_PROTO3) {
+      return f->proto().oneof_index() != 0;
+    }
+
+    return f->proto().cardinality() ==
+               google::protobuf::Field::CARDINALITY_OPTIONAL ||
+           google::protobuf::Field::CARDINALITY_REQUIRED;
+  }
+
+  static bool IsImplicitPresence(Field f) {
+    return !IsRepeated(f) && !IsOptional(f);
+  }
+
+  static bool IsExtension(Field f) { return false; }
+
+  static bool IsOneof(Field f) { return f->proto().oneof_index() != 0; }
+
+  static absl::StatusOr<int32_t> EnumNumberByName(Field f,
+                                                  absl::string_view name,
+                                                  bool case_insensitive) {
+    auto e = f->EnumType();
+    RETURN_IF_ERROR(e.status());
+
+    for (const auto& ev : (**e).proto().enumvalue()) {
+      if (case_insensitive) {
+        // Two ifs to avoid doing operator== twice if the names are not equal.
+        if (absl::EqualsIgnoreCase(ev.name(), name)) {
+          return ev.number();
+        }
+      } else if (ev.name() == name) {
+        return ev.number();
+      }
+    }
+    return absl::InvalidArgumentError(
+        absl::StrFormat("unknown enum value: '%s'", name));
+  }
+
+  static absl::StatusOr<std::string> EnumNameByNumber(Field f, int32_t number) {
+    auto e = f->EnumType();
+    RETURN_IF_ERROR(e.status());
+
+    for (const auto& ev : (**e).proto().enumvalue()) {
+      if (ev.number() == number) {
+        return ev.name();
+      }
+    }
+    return absl::InvalidArgumentError(
+        absl::StrFormat("unknown enum number: '%d'", number));
+  }
+
+  template <typename F>
+  static absl::Status WithFieldType(Field f, F body) {
+    auto m = f->MessageType();
+    RETURN_IF_ERROR(m.status());
+    return body(**m);
+  }
+
+  template <typename F>
+  static absl::Status WithDynamicType(const Desc& desc,
+                                      const std::string& type_url, F body) {
+    auto dyn_desc = desc.pool()->FindMessage(type_url);
+    RETURN_IF_ERROR(dyn_desc.status());
+    return body(**dyn_desc);
+  }
+};
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_DESCRIPTOR_TRAITS_INTERNAL_H__
diff --git a/src/google/protobuf/json/internal/lexer.cc b/src/google/protobuf/json/internal/lexer.cc
new file mode 100644
index 0000000..5698eab
--- /dev/null
+++ b/src/google/protobuf/json/internal/lexer.cc
@@ -0,0 +1,541 @@
+// 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/json/internal/lexer.h"
+
+#include <sys/types.h>
+
+#include <atomic>
+#include <cfloat>
+#include <cmath>
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <ostream>
+#include <string>
+#include <utility>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/algorithm/container.h"
+#include "absl/numeric/bits.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+namespace {
+// Randomly inserts bonus whitespace of a few different kinds into a string.
+//
+// This utility is intended to make error messages hostile to machine
+// interpretation as a Hyrum's Law countermeasure, without potentially confusing
+// human readers.
+void HardenAgainstHyrumsLaw(absl::string_view to_obfuscate, std::string& out) {
+  // Get some simple randomness from ASLR, which is enabled in most
+  // environments. Our goal is to be annoying, not secure.
+  static const void* const kAslrSeed = &kAslrSeed;
+  // Per-call randomness from a relaxed atomic.
+  static std::atomic<uintptr_t> kCounterSeed{0};
+
+  constexpr uint64_t kA = 0x5851f42d4c957f2dull;
+  constexpr uint64_t kB = 0x14057b7ef767814full;
+
+  uint64_t state = absl::bit_cast<uintptr_t>(kAslrSeed) + kB +
+                   kCounterSeed.fetch_add(1, std::memory_order_relaxed);
+  auto rng = [&state, &kA, &kB] {
+    state = state * kA + kB;
+    return absl::rotr(static_cast<uint32_t>(((state >> 18) ^ state) >> 27),
+                      state >> 59);
+  };
+  (void)rng();  // Advance state once.
+
+  out.reserve(to_obfuscate.size() + absl::c_count(to_obfuscate, ' '));
+  for (char c : to_obfuscate) {
+    out.push_back(c);
+    if (c != ' ' || rng() % 3 != 0) {
+      continue;
+    }
+
+    size_t count = rng() % 2 + 1;
+    for (size_t i = 0; i < count; ++i) {
+      out.push_back(' ');
+    }
+  }
+}
+}  // namespace
+
+constexpr size_t ParseOptions::kDefaultDepth;
+
+absl::Status JsonLocation::Invalid(absl::string_view message,
+                                   SourceLocation sl) const {
+  // NOTE: we intentionally do not harden the "invalid JSON" part, so that
+  // people have a hope of grepping for it in logs. That part is easy to
+  // commit to, as stability goes.
+  //
+  // This copies the error twice. Because this is the "unhappy" path, this
+  // function is cold and can afford the waste.
+  std::string status_message = "invalid JSON";
+  std::string to_obfuscate;
+  if (path != nullptr) {
+    absl::StrAppend(&to_obfuscate, " in ");
+    path->Describe(to_obfuscate);
+    to_obfuscate.push_back(',');
+  }
+  absl::StrAppendFormat(&to_obfuscate, " near %zu:%zu (offset %zu): %s",
+                        line + 1, col + 1, offset, message);
+  HardenAgainstHyrumsLaw(to_obfuscate, status_message);
+
+  return absl::InvalidArgumentError(std::move(status_message));
+}
+
+absl::StatusOr<JsonLexer::Kind> JsonLexer::PeekKind() {
+  RETURN_IF_ERROR(SkipToToken());
+  char c = stream_.PeekChar();
+  switch (c) {
+    case '{':
+      return JsonLexer::kObj;
+    case '[':
+      return JsonLexer::kArr;
+    case '"':
+    case '\'':
+      return JsonLexer::kStr;
+    case '-':
+    case '0':
+    case '1':
+    case '2':
+    case '3':
+    case '4':
+    case '5':
+    case '6':
+    case '7':
+    case '8':
+    case '9':
+      return JsonLexer::kNum;
+    case 't':
+      return JsonLexer::kTrue;
+    case 'f':
+      return JsonLexer::kFalse;
+    case 'n':
+      return JsonLexer::kNull;
+    default:
+      return Invalid(absl::StrFormat("unexpected character: '%c'", c));
+  }
+}
+
+absl::Status JsonLexer::SkipValue() {
+  absl::StatusOr<Kind> kind = PeekKind();
+  RETURN_IF_ERROR(kind.status());
+
+  switch (*kind) {
+    case JsonLexer::kObj:
+      return VisitObject(
+          [this](LocationWith<MaybeOwnedString>&) { return SkipValue(); });
+    case JsonLexer::kArr:
+      return VisitArray([this] { return SkipValue(); });
+    case JsonLexer::kStr:
+      return ParseUtf8().status();
+    case JsonLexer::kNum:
+      return ParseNumber().status();
+    case JsonLexer::kTrue:
+      return Expect("true");
+    case JsonLexer::kFalse:
+      return Expect("false");
+    case JsonLexer::kNull:
+      return Expect("null");
+    default:
+      break;
+  }
+  // Some compilers seem to fail to realize this is a basic block
+  // terminator and incorrectly believe this function is missing
+  // a return.
+  GOOGLE_CHECK(false) << "unreachable";
+  return absl::OkStatus();
+}
+
+absl::StatusOr<uint16_t> JsonLexer::ParseU16HexCodepoint() {
+  absl::StatusOr<LocationWith<MaybeOwnedString>> escape = Take(4);
+  RETURN_IF_ERROR(escape.status());
+
+  uint16_t u16 = 0;
+  for (char c : escape->value.AsView()) {
+    if (c >= '0' && c <= '9') {
+      c -= '0';
+    } else if (c >= 'a' && c <= 'f') {
+      c = c - 'a' + 10;
+    } else if (c >= 'A' && c <= 'F') {
+      c = c - 'A' + 10;
+    } else {
+      return Invalid("invalid Unicode escape");
+    }
+    u16 <<= 4;
+    u16 |= c;
+  }
+
+  return u16;
+}
+
+absl::Status JsonLexer::SkipToToken() {
+  while (true) {
+    RETURN_IF_ERROR(stream_.BufferAtLeast(1).status());
+    switch (stream_.PeekChar()) {
+      case '\n':
+        RETURN_IF_ERROR(Advance(1));
+        ++json_loc_.line;
+        json_loc_.col = 0;
+        break;
+      case '\r':
+      case '\t':
+      case ' ':
+        RETURN_IF_ERROR(Advance(1));
+        break;
+      default:
+        return absl::OkStatus();
+    }
+  }
+}
+
+absl::StatusOr<LocationWith<MaybeOwnedString>> JsonLexer::ParseRawNumber() {
+  RETURN_IF_ERROR(SkipToToken());
+
+  enum { kInt, kFraction, kExponent } state = kInt;
+  char prev_var = 0;
+  auto number = TakeWhile([state, prev_var](size_t index, char c) mutable {
+    char prev = prev_var;
+    prev_var = c;
+    if (absl::ascii_isdigit(c)) {
+      return true;
+    }
+
+    bool last_was_int = absl::ascii_isdigit(prev);
+    // These checks handle transitions between the integer, fractional, and
+    // exponent part of a number. This will cut off at the first syntax error.
+    // Because all numbers must be followed by `,`, `]`, or `}`, we can let
+    // that catch what's left behind.
+    if (state == kInt && c == '-') {
+      return !last_was_int;
+    }
+    if (state == kInt && last_was_int && c == '.') {
+      state = kFraction;
+      return true;
+    }
+    if (state != kExponent && last_was_int && (c == 'e' || c == 'E')) {
+      state = kExponent;
+      return true;
+    }
+    if ((prev == 'e' || prev == 'E') && (c == '-' || c == '+')) {
+      return true;
+    }
+
+    return false;
+  });
+
+  RETURN_IF_ERROR(number.status());
+  absl::string_view number_text = number->value.AsView();
+
+  if (number_text.empty() || number_text == "-") {
+    return number->loc.Invalid("expected a number");
+  }
+
+  auto without_minus =
+      number_text[0] == '-' ? number_text.substr(1) : number_text;
+  if (without_minus.size() > 1 && without_minus[0] == '0' &&
+      absl::ascii_isdigit(without_minus[1])) {
+    return number->loc.Invalid("number cannot have extraneous leading zero");
+  }
+
+  if (number_text.back() == '.') {
+    return number->loc.Invalid("number cannot have trailing period");
+  }
+
+  double d;
+  if (!absl::SimpleAtod(number_text, &d) || !std::isfinite(d)) {
+    return number->loc.Invalid(
+        absl::StrFormat("invalid number: '%s'", number_text));
+  }
+
+  // Find the next token, to make sure we didn't leave something behind we
+  // shouldn't have.
+  if (!stream_.AtEof()) {
+    RETURN_IF_ERROR(SkipToToken());
+    switch (stream_.PeekChar()) {
+      case ',':
+      case ']':
+      case '}':
+        break;
+      default:
+        return Invalid(
+            absl::StrFormat("unexpected character: '%c'", stream_.PeekChar()));
+    }
+  }
+
+  return number;
+}
+
+absl::StatusOr<LocationWith<double>> JsonLexer::ParseNumber() {
+  auto number = ParseRawNumber();
+  RETURN_IF_ERROR(number.status());
+
+  double d;
+  if (!absl::SimpleAtod(number->value.AsView(), &d) || !std::isfinite(d)) {
+    return number->loc.Invalid(
+        absl::StrFormat("invalid number: '%s'", number->value.AsView()));
+  }
+
+  return LocationWith<double>{d, number->loc};
+}
+
+absl::StatusOr<size_t> JsonLexer::ParseUnicodeEscape(char out_utf8[4]) {
+  auto hex = ParseU16HexCodepoint();
+  RETURN_IF_ERROR(hex.status());
+
+  uint32_t rune = *hex;
+  if (rune >= 0xd800 && rune <= 0xdbff) {
+    // Surrogate pair: two 16-bit codepoints become a 32-bit codepoint.
+    uint32_t high = rune;
+
+    RETURN_IF_ERROR(Expect("\\u"));
+    auto hex = ParseU16HexCodepoint();
+    RETURN_IF_ERROR(hex.status());
+
+    uint32_t low = *hex;
+    if (low < 0xdc00 || low > 0xdfff) {
+      return Invalid("invalid low surrogate");
+    }
+
+    rune = (high & 0x3ff) << 10;
+    rune |= (low & 0x3ff);
+    rune += 0x10000;
+  } else if (rune >= 0xdc00 && rune <= 0xdfff) {
+    return Invalid("unpaired low surrogate");
+  }
+
+  // Write as UTF-8.
+  if (rune <= 0x7f) {
+    out_utf8[0] = rune;
+    return 1;
+  } else if (rune <= 0x07ff) {
+    out_utf8[0] = ((rune >> 6) & 0x1f) | 0xc0;
+    out_utf8[1] = ((rune >> 0) & 0x3f) | 0x80;
+    return 2;
+  } else if (rune <= 0xffff) {
+    out_utf8[0] = ((rune >> 12) & 0x0f) | 0xe0;
+    out_utf8[1] = ((rune >> 6) & 0x3f) | 0x80;
+    out_utf8[2] = ((rune >> 0) & 0x3f) | 0x80;
+    return 3;
+  } else if (rune < 0x10ffff) {
+    out_utf8[0] = ((rune >> 18) & 0x07) | 0xF0;
+    out_utf8[1] = ((rune >> 12) & 0x3f) | 0x80;
+    out_utf8[2] = ((rune >> 6) & 0x3f) | 0x80;
+    out_utf8[3] = ((rune >> 0) & 0x3f) | 0x80;
+    return 4;
+  } else {
+    return Invalid("invalid codepoint");
+  }
+}
+
+static char ParseSimpleEscape(char c, bool allow_legacy_syntax) {
+  switch (c) {
+    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';
+    case '\'':
+      if (allow_legacy_syntax) {
+        return '\'';
+      }
+      ABSL_FALLTHROUGH_INTENDED;
+    default:
+      return 0;
+  }
+}
+
+absl::StatusOr<LocationWith<MaybeOwnedString>> JsonLexer::ParseUtf8() {
+  RETURN_IF_ERROR(SkipToToken());
+  // This is a non-standard extension accepted by the ESF parser that we will
+  // need to accept for backwards-compat.
+  bool is_single_quote = stream_.PeekChar() == '\'';
+  if (!options_.allow_legacy_syntax && is_single_quote) {
+    return Invalid("expected '\"'");
+  }
+
+  JsonLocation loc = json_loc_;
+  RETURN_IF_ERROR(Expect(is_single_quote ? "'" : "\""));
+
+  // on_heap is empty if we do not need to heap-allocate the string.
+  std::string on_heap;
+  LocationWith<Mark> mark = BeginMark();
+  while (true) {
+    RETURN_IF_ERROR(stream_.BufferAtLeast(1).status());
+
+    char c = stream_.PeekChar();
+    RETURN_IF_ERROR(Advance(1));
+    switch (c) {
+      case '"':
+      case '\'': {
+        if (c != (is_single_quote ? '\'' : '"')) {
+          goto normal_character;
+        }
+
+        if (!on_heap.empty()) {
+          return LocationWith<MaybeOwnedString>{
+              MaybeOwnedString(std::move(on_heap)), loc};
+        }
+        // NOTE: the 1 below clips off the " from the end of the string.
+        return LocationWith<MaybeOwnedString>{mark.value.UpToUnread(1), loc};
+      }
+      case '\\': {
+        if (on_heap.empty()) {
+          // The 1 skips over the `\`.
+          on_heap = std::string(mark.value.UpToUnread(1).AsView());
+          // Clang-tidy incorrectly notes this as being moved-from multiple
+          // times, but it can only occur in one loop iteration. The mark is
+          // destroyed only if we need to handle an escape when on_heap is
+          // empty. Because this branch unconditionally pushes to on_heap, this
+          // condition can never be reached in any iteration that follows it.
+          // This, at most one move every actually occurs.
+          std::move(mark).value.Discard();
+        }
+        RETURN_IF_ERROR(stream_.BufferAtLeast(1).status());
+
+        char c = stream_.PeekChar();
+        RETURN_IF_ERROR(Advance(1));
+        if (c == 'u' || (c == 'U' && options_.allow_legacy_syntax)) {
+          // Ensure there is actual space to scribble the UTF-8 onto.
+          on_heap.resize(on_heap.size() + 4);
+          auto written = ParseUnicodeEscape(&on_heap[on_heap.size() - 4]);
+          RETURN_IF_ERROR(written.status());
+          on_heap.resize(on_heap.size() - 4 + *written);
+        } else {
+          char escape = ParseSimpleEscape(c, options_.allow_legacy_syntax);
+          if (escape == 0) {
+            return Invalid(absl::StrFormat("invalid escape char: '%c'", c));
+          }
+          on_heap.push_back(escape);
+        }
+        break;
+      }
+      normal_character:
+      default: {
+        uint8_t uc = static_cast<uint8_t>(c);
+        // If people have newlines in their strings, that's their problem; it
+        // is too difficult to support correctly in our location tracking, and
+        // is out of spec, so users will get slightly wrong locations in errors.
+        if ((uc < 0x20 || uc == 0xff) && !options_.allow_legacy_syntax) {
+          return Invalid(absl::StrFormat(
+              "invalid control character 0x%02x in string", uc));
+        }
+
+        // Verify this is valid UTF-8. UTF-8 is a varint encoding satisfying
+        // one of the following (big-endian) patterns:
+        //
+        // 0b0xxxxxxx
+        // 0b110xxxxx'10xxxxxx
+        // 0b1110xxxx'10xxxxxx'10xxxxxx
+        // 0b11110xxx'10xxxxxx'10xxxxxx'10xxxxxx
+        //
+        // We don't need to decode it; just validate it.
+        size_t lookahead = 0;
+        switch (absl::countl_one(uc)) {
+          case 0:
+            break;
+          case 2:
+            lookahead = 1;
+            break;
+          case 3:
+            lookahead = 2;
+            break;
+          case 4:
+            lookahead = 3;
+            break;
+          default:
+            return Invalid("invalid UTF-8 in string");
+        }
+
+        if (!on_heap.empty()) {
+          on_heap.push_back(c);
+        }
+        for (int i = 0; i < lookahead; ++i) {
+          RETURN_IF_ERROR(stream_.BufferAtLeast(1).status());
+          uint8_t uc = static_cast<uint8_t>(stream_.PeekChar());
+          if ((uc >> 6) != 2) {
+            return Invalid("invalid UTF-8 in string");
+          }
+          if (!on_heap.empty()) {
+            on_heap.push_back(stream_.PeekChar());
+          }
+          RETURN_IF_ERROR(Advance(1));
+        }
+        break;
+      }
+    }
+  }
+
+  return Invalid("EOF inside string");
+}
+
+absl::StatusOr<LocationWith<MaybeOwnedString>> JsonLexer::ParseBareWord() {
+  RETURN_IF_ERROR(SkipToToken());
+  auto ident = TakeWhile(
+      [](size_t, char c) { return c == '_' || absl::ascii_isalnum(c); });
+  RETURN_IF_ERROR(ident.status());
+  absl::string_view text = ident->value.AsView();
+
+  if (text.empty() || absl::ascii_isdigit(text[0]) || text == "null" ||
+      text == "true" || text == "false") {
+    return ident->loc.Invalid("expected bare word");
+  }
+  return ident;
+}
+
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/json/internal/lexer.h b/src/google/protobuf/json/internal/lexer.h
new file mode 100644
index 0000000..a4631cc
--- /dev/null
+++ b/src/google/protobuf/json/internal/lexer.h
@@ -0,0 +1,361 @@
+// 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.
+
+// Internal JSON tokenization utilities; not public API.
+#ifndef GOOGLE_PROTOBUF_JSON_INTERNAL_LEXER_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_LEXER_H__
+
+#include <array>
+#include <cfloat>
+#include <cmath>
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <ostream>
+#include <string>
+#include <utility>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/json/internal/message_path.h"
+#include "google/protobuf/json/internal/zero_copy_buffered_stream.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+// This is a duplicate of JsonParseOptions from json_util.h; it must be
+// re-defined here so that :json_lexer does not need to depend on :json_util.
+struct ParseOptions {
+  bool ignore_unknown_fields = false;
+  bool case_insensitive_enum_parsing = false;
+
+  static constexpr size_t kDefaultDepth = 100;
+
+  // The number of times we may recurse before bailing out on the grounds of
+  // avoiding pathological input.
+  int recursion_depth = kDefaultDepth;
+
+  // The original parser used by json_util2 accepted a number of non-standard
+  // options. Setting this flag enables them.
+  //
+  // What those extensions were is explicitly not documented, beyond what exists
+  // in the unit tests; we intend to remove this setting eventually. See
+  // b/234868512.
+  bool allow_legacy_syntax = false;
+};
+
+// A position in JSON input, for error context.
+struct JsonLocation {
+  // This type exists to work around an absl type that has not yet been
+  // released.
+  struct SourceLocation {
+    static SourceLocation current() { return {}; }
+  };
+
+  // Line and column are both zero-indexed in-memory.
+  size_t offset = 0;
+  size_t line = 0;
+  size_t col = 0;
+  const MessagePath* path = nullptr;
+
+  // Creates an absl::InvalidArgumentError with line/column information.
+  absl::Status Invalid(absl::string_view message,
+                       SourceLocation sl = SourceLocation::current()) const;
+};
+
+template <typename T>
+struct LocationWith {
+  T value;
+  JsonLocation loc;
+};
+
+class JsonLexer {
+ public:
+  // A kind of token that PeekKind() can detect.
+  enum Kind {
+    kObj,
+    kArr,
+    kStr,
+    kNum,
+    kTrue,
+    kFalse,
+    kNull,
+  };
+
+  using SourceLocation = JsonLocation::SourceLocation;
+
+  JsonLexer(io::ZeroCopyInputStream* stream, const ParseOptions& options,
+            MessagePath* path = nullptr, JsonLocation start = {})
+      : stream_(stream), options_(options), json_loc_(start), path_(path) {
+    json_loc_.path = path_;
+  }
+
+  const ParseOptions& options() const { return options_; }
+
+  const MessagePath& path() const { return *path_; }
+  MessagePath& path() { return *path_; }
+
+  // Creates an absl::InvalidArgumentError with line/column information.
+  absl::Status Invalid(absl::string_view message,
+                       SourceLocation sl = SourceLocation::current()) {
+    return json_loc_.Invalid(message, sl);
+  }
+
+  // Expects the next bytes to be parsed (after consuming whitespace) to be
+  // exactly `literal`. If they are, consumes them; otherwise returns an error.
+  absl::Status Expect(absl::string_view literal,
+                      SourceLocation sl = SourceLocation::current()) {
+    RETURN_IF_ERROR(SkipToToken());
+    auto buffering = stream_.BufferAtLeast(literal.size());
+    RETURN_IF_ERROR(buffering.status());
+
+    if (!absl::StartsWith(stream_.Unread(), literal)) {
+      return Invalid(
+          absl::StrFormat("unexpected character: '%c'; expected '%s'",
+                          stream_.PeekChar(), literal),
+          sl);
+    }
+
+    return Advance(literal.size());
+  }
+
+  // Like Expect(), but returns a boolean. This makes it clear that the
+  // lookahead is failible.
+  bool Peek(absl::string_view literal) {
+    // Suppress the error; this can only fail on EOF in which case we would
+    // return false regardless.
+    (void)SkipToToken();
+    auto ignored = stream_.BufferAtLeast(literal.size());
+    if (!absl::StartsWith(stream_.Unread(), literal)) {
+      return false;
+    }
+
+    // We just ensured we had enough buffered so we can suppress this error.
+    (void)Advance(literal.size());
+    return true;
+  }
+
+  // Like Peek(string), but returns true if and only if a token of the given
+  // kind can be lexed next. Returns false on EOF, just like Peek(string).
+  bool Peek(Kind needle) {
+    auto kind = PeekKind();
+    return kind.ok() && *kind == needle;
+  }
+
+  // Consumes all whitespace and other ignored characters until the next
+  // token.
+  //
+  // This function returns an error on EOF, so PeekChar() can be safely
+  // called if it returns ok.
+  absl::Status SkipToToken();
+
+  // Returns which kind of value token (i.e., something that can occur after
+  // a `:`) is next up to be parsed.
+  absl::StatusOr<Kind> PeekKind();
+
+  // Parses a JSON number.
+  absl::StatusOr<LocationWith<double>> ParseNumber();
+
+  // Parses a number as a string, without turning it into an integer.
+  absl::StatusOr<LocationWith<MaybeOwnedString>> ParseRawNumber();
+
+  // Parses a UTF-8 string. If the contents of the string happen to actually be
+  // UTF-8, it will return a zero-copy view; otherwise it will allocate.
+  absl::StatusOr<LocationWith<MaybeOwnedString>> ParseUtf8();
+
+  // Walks over an array, calling `f` each time an element is reached.
+  //
+  // `f` should have type `() -> absl::Status`.
+  template <typename F>
+  absl::Status VisitArray(F f);
+
+  // Walks over an object, calling `f` just after parsing each `:`.
+  //
+  // `f` should have type `(absl::string_view) -> absl::Status`.
+  template <typename F>
+  absl::Status VisitObject(F f);
+
+  // Parses a single value and discards it.
+  absl::Status SkipValue();
+
+  // Forwards of functions from ZeroCopyBufferedStream.
+
+  bool AtEof() {
+    // Ignore whitespace for the purposes of finding the EOF. This will return
+    // an error if we hit EOF, so we discard it.
+    (void)SkipToToken();
+    return stream_.AtEof();
+  }
+
+  absl::StatusOr<LocationWith<MaybeOwnedString>> Take(size_t len) {
+    JsonLocation loc = json_loc_;
+    auto taken = stream_.Take(len);
+    RETURN_IF_ERROR(taken.status());
+    return LocationWith<MaybeOwnedString>{*std::move(taken), loc};
+  }
+
+  template <typename Pred>
+  absl::StatusOr<LocationWith<MaybeOwnedString>> TakeWhile(Pred p) {
+    JsonLocation loc = json_loc_;
+    auto taken = stream_.TakeWhile(std::move(p));
+    RETURN_IF_ERROR(taken.status());
+    return LocationWith<MaybeOwnedString>{*std::move(taken), loc};
+  }
+
+  LocationWith<Mark> BeginMark() { return {stream_.BeginMark(), json_loc_}; }
+
+ private:
+  friend BufferingGuard;
+  friend Mark;
+  friend MaybeOwnedString;
+
+  absl::Status Push() {
+    if (options_.recursion_depth == 0) {
+      return Invalid("JSON content was too deeply nested");
+    }
+    --options_.recursion_depth;
+    return absl::OkStatus();
+  }
+
+  void Pop() { ++options_.recursion_depth; }
+
+  // Parses the next four bytes as a 16-bit hex numeral.
+  absl::StatusOr<uint16_t> ParseU16HexCodepoint();
+
+  // Parses a Unicode escape (\uXXXX); this may be a surrogate pair, so it may
+  // consume the character that follows. Both are encoded as utf8 into
+  // `out_utf8`; returns the number of bytes written.
+  absl::StatusOr<size_t> ParseUnicodeEscape(char out_utf8[4]);
+
+  // Parses an alphanumeric "identifier", for use with the non-standard
+  // "unquoted keys" extension.
+  absl::StatusOr<LocationWith<MaybeOwnedString>> ParseBareWord();
+
+  absl::Status Advance(size_t bytes) {
+    RETURN_IF_ERROR(stream_.Advance(bytes));
+    json_loc_.offset += static_cast<int>(bytes);
+    json_loc_.col += static_cast<int>(bytes);
+    return absl::OkStatus();
+  }
+
+  ZeroCopyBufferedStream stream_;
+
+  ParseOptions options_;
+  JsonLocation json_loc_;
+  MessagePath* path_;
+};
+
+template <typename F>
+absl::Status JsonLexer::VisitArray(F f) {
+  RETURN_IF_ERROR(Expect("["));
+  RETURN_IF_ERROR(Push());
+
+  if (Peek("]")) {
+    Pop();
+    return absl::OkStatus();
+  }
+
+  bool has_comma = true;
+  do {
+    if (!has_comma) {
+      return Invalid("expected ','");
+    }
+    RETURN_IF_ERROR(f());
+    has_comma = Peek(",");
+  } while (!Peek("]"));
+
+  if (!options_.allow_legacy_syntax && has_comma) {
+    return Invalid("expected ']'");
+  }
+
+  Pop();
+  return absl::OkStatus();
+}
+
+// Walks over an object, calling `f` just after parsing each `:`.
+//
+// `f` should have type `(MaybeOwnedString&) -> absl::Status`.
+template <typename F>
+absl::Status JsonLexer::VisitObject(F f) {
+  RETURN_IF_ERROR(Expect("{"));
+  RETURN_IF_ERROR(Push());
+
+  if (Peek("}")) {
+    Pop();
+    return absl::OkStatus();
+  }
+
+  bool has_comma = true;
+  do {
+    if (!has_comma) {
+      return Invalid("expected ','");
+    }
+    RETURN_IF_ERROR(SkipToToken());
+
+    absl::StatusOr<LocationWith<MaybeOwnedString>> key;
+    if (stream_.PeekChar() == '"' || stream_.PeekChar() == '\'') {
+      key = ParseUtf8();
+    } else if (options_.allow_legacy_syntax) {
+      key = ParseBareWord();
+    } else {
+      return Invalid("expected '\"'");
+    }
+
+    RETURN_IF_ERROR(key.status());
+    RETURN_IF_ERROR(Expect(":"));
+    RETURN_IF_ERROR(f(*key));
+    has_comma = Peek(",");
+  } while (!Peek("}"));
+  Pop();
+
+  if (!options_.allow_legacy_syntax && has_comma) {
+    return Invalid("expected '}'");
+  }
+
+  return absl::OkStatus();
+}
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_LEXER_H__
diff --git a/src/google/protobuf/json/internal/lexer_test.cc b/src/google/protobuf/json/internal/lexer_test.cc
new file mode 100644
index 0000000..6213172
--- /dev/null
+++ b/src/google/protobuf/json/internal/lexer_test.cc
@@ -0,0 +1,741 @@
+// 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/json/internal/lexer.h"
+
+#include <cstddef>
+#include <cstdint>
+#include <functional>
+#include <ostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include "absl/algorithm/container.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/variant.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/json/internal/test_input_stream.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+namespace {
+using ::testing::_;
+using ::testing::ElementsAre;
+using ::testing::Field;
+using ::testing::HasSubstr;
+using ::testing::IsEmpty;
+using ::testing::Pair;
+using ::testing::SizeIs;
+using ::testing::VariantWith;
+
+// TODO(b/234474291): Use the gtest versions once that's available in OSS.
+MATCHER_P(IsOkAndHolds, inner,
+          absl::StrCat("is OK and holds ", testing::PrintToString(inner))) {
+  if (!arg.ok()) {
+    *result_listener << arg.status();
+    return false;
+  }
+  return testing::ExplainMatchResult(inner, *arg, result_listener);
+}
+
+// absl::Status GetStatus(const absl::Status& s) { return s; }
+template <typename T>
+absl::Status GetStatus(const absl::StatusOr<T>& s) {
+  return s.status();
+}
+
+MATCHER_P(StatusIs, status,
+          absl::StrCat(".status() is ", testing::PrintToString(status))) {
+  return GetStatus(arg).code() == status;
+}
+
+#define EXPECT_OK(x) EXPECT_THAT(x, StatusIs(absl::StatusCode::kOk))
+#define ASSERT_OK(x) ASSERT_THAT(x, StatusIs(absl::StatusCode::kOk))
+
+// TODO(b/234868512): There are several tests that validate non-standard
+// behavior that is assumed to be present in the wild due to Hyrum's Law. These
+// tests are grouped under the `NonStandard` suite. These tests ensure the
+// non-standard syntax is accepted, and that disabling legacy mode rejects them.
+//
+// All other tests are strictly-conforming.
+
+// A generic JSON value, which is gtest-matcher friendly and stream-printable.
+struct Value {
+  static absl::StatusOr<Value> Parse(io::ZeroCopyInputStream* stream,
+                                     ParseOptions options = {}) {
+    JsonLexer lex(stream, options);
+    return Parse(lex);
+  }
+  static absl::StatusOr<Value> Parse(JsonLexer& lex) {
+    absl::StatusOr<JsonLexer::Kind> kind = lex.PeekKind();
+    RETURN_IF_ERROR(kind.status());
+
+    switch (*kind) {
+      case JsonLexer::kNull:
+        RETURN_IF_ERROR(lex.Expect("null"));
+        return Value{Null{}};
+      case JsonLexer::kFalse:
+        RETURN_IF_ERROR(lex.Expect("false"));
+        return Value{false};
+      case JsonLexer::kTrue:
+        RETURN_IF_ERROR(lex.Expect("true"));
+        return Value{true};
+      case JsonLexer::kNum: {
+        absl::StatusOr<LocationWith<double>> num = lex.ParseNumber();
+        RETURN_IF_ERROR(num.status());
+        return Value{num->value};
+      }
+      case JsonLexer::kStr: {
+        absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+        RETURN_IF_ERROR(str.status());
+        return Value{str->value.ToString()};
+      }
+      case JsonLexer::kArr: {
+        std::vector<Value> arr;
+        absl::Status s = lex.VisitArray([&arr, &lex]() -> absl::Status {
+          absl::StatusOr<Value> val = Value::Parse(lex);
+          RETURN_IF_ERROR(val.status());
+          arr.emplace_back(*std::move(val));
+          return absl::OkStatus();
+        });
+        RETURN_IF_ERROR(s);
+        return Value{std::move(arr)};
+      }
+      case JsonLexer::kObj: {
+        std::vector<std::pair<std::string, Value>> obj;
+        absl::Status s = lex.VisitObject(
+            [&obj, &lex](LocationWith<MaybeOwnedString>& key) -> absl::Status {
+              absl::StatusOr<Value> val = Value::Parse(lex);
+              RETURN_IF_ERROR(val.status());
+              obj.emplace_back(std::move(key.value.ToString()),
+                               *std::move(val));
+              return absl::OkStatus();
+            });
+        RETURN_IF_ERROR(s);
+        return Value{std::move(obj)};
+      }
+    }
+    return absl::InternalError("Unrecognized kind in lexer");
+  }
+
+  friend std::ostream& operator<<(std::ostream& os, const Value& v) {
+    if (absl::holds_alternative<Null>(v.value)) {
+      os << "null";
+    } else if (const auto* x = absl::get_if<bool>(&v.value)) {
+      os << "bool:" << (*x ? "true" : "false");
+    } else if (const auto* x = absl::get_if<double>(&v.value)) {
+      os << "num:" << *x;
+    } else if (const auto* x = absl::get_if<std::string>(&v.value)) {
+      os << "str:" << absl::CHexEscape(*x);
+    } else if (const auto* x = absl::get_if<Array>(&v.value)) {
+      os << "arr:[";
+      bool first = true;
+      for (const auto& val : *x) {
+        if (!first) {
+          os << ", ";
+        }
+        os << val;
+      }
+      os << "]";
+    } else if (const auto* x = absl::get_if<Object>(&v.value)) {
+      os << "obj:[";
+      bool first = true;
+      for (const auto& kv : *x) {
+        if (!first) {
+          os << ", ";
+          first = false;
+        }
+        os << kv.first << ":" << kv.second;
+      }
+      os << "]";
+    }
+    return os;
+  }
+
+  struct Null {};
+  using Array = std::vector<Value>;
+  using Object = std::vector<std::pair<std::string, Value>>;
+  absl::variant<Null, bool, double, std::string, Array, Object> value;
+};
+
+template <typename T, typename M>
+testing::Matcher<const Value&> ValueIs(M inner) {
+  return Field(&Value::value, VariantWith<T>(inner));
+}
+
+// Executes `test` once for each three-segment split of `json`.
+void Do(absl::string_view json,
+        std::function<void(io::ZeroCopyInputStream*)> test,
+        bool verify_all_consumed = true) {
+  SCOPED_TRACE(absl::StrCat("json: ", absl::CHexEscape(json)));
+
+  for (size_t i = 0; i < json.size(); ++i) {
+    for (size_t j = 0; j < json.size() - i + 1; ++j) {
+      SCOPED_TRACE(absl::StrFormat("json[0:%d], json[%d:%d], json[%d:%d]", i, i,
+                                   i + j, i + j, json.size()));
+      std::string first(json.substr(0, i));
+      std::string second(json.substr(i, j));
+      std::string third(json.substr(i + j));
+
+      TestInputStream in = {first, second, third};
+      test(&in);
+      if (testing::Test::HasFailure()) {
+        return;
+      }
+
+      if (verify_all_consumed) {
+        if (!absl::c_all_of(third,
+                            [](char c) { return absl::ascii_isspace(c); })) {
+          ASSERT_GE(in.Consumed(), 3);
+        } else if (!absl::c_all_of(
+                       second, [](char c) { return absl::ascii_isspace(c); })) {
+          ASSERT_GE(in.Consumed(), 2);
+        } else {
+          ASSERT_GE(in.Consumed(), 1);
+        }
+      }
+    }
+  }
+}
+
+void BadInner(absl::string_view json, ParseOptions opts = {}) {
+  Do(
+      json,
+      [=](io::ZeroCopyInputStream* stream) {
+        EXPECT_THAT(Value::Parse(stream, opts),
+                    StatusIs(absl::StatusCode::kInvalidArgument));
+      },
+      false);
+}
+
+// Like Do, but runs a legacy syntax test twice: once with legacy settings, once
+// without. For the latter, the test is expected to fail; for the former,
+// `test` is called so it can run expectations.
+void DoLegacy(absl::string_view json, std::function<void(const Value&)> test) {
+  Do(json, [&](io::ZeroCopyInputStream* stream) {
+    ParseOptions options;
+    options.allow_legacy_syntax = true;
+    auto value = Value::Parse(stream, options);
+    ASSERT_OK(value);
+    test(*value);
+  });
+  BadInner(json);
+}
+
+// Like Bad, but ensures json fails to parse in both modes.
+void Bad(absl::string_view json) {
+  ParseOptions options;
+  options.allow_legacy_syntax = true;
+  BadInner(json, options);
+  BadInner(json);
+}
+
+TEST(LexerTest, Null) {
+  Do("null", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream), IsOkAndHolds(ValueIs<Value::Null>(_)));
+  });
+}
+
+TEST(LexerTest, False) {
+  Do("false", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream), IsOkAndHolds(ValueIs<bool>(false)));
+  });
+}
+
+TEST(LexerTest, True) {
+  Do("true", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream), IsOkAndHolds(ValueIs<bool>(true)));
+  });
+}
+
+TEST(LexerTest, Typos) {
+  Bad("-");
+  Bad("-foo");
+  Bad("nule");
+}
+
+TEST(LexerTest, UnknownCharacters) {
+  Bad("*&#25");
+  Bad("[*&#25]");
+  Bad("{key: *&#25}");
+}
+
+TEST(LexerTest, EmptyString) {
+  Do(R"json("")json", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<std::string>(IsEmpty())));
+  });
+}
+
+TEST(LexerTest, SimpleString) {
+  Do(R"json("My String")json", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<std::string>("My String")));
+  });
+}
+
+TEST(NonStandard, SingleQuoteString) {
+  DoLegacy(R"json('My String')json", [=](const Value& value) {
+    EXPECT_THAT(value, ValueIs<std::string>("My String"));
+  });
+}
+
+TEST(NonStandard, ControlCharsInString) {
+  DoLegacy("\"\1\2\3\4\5\6\7\b\n\f\r\"", [=](const Value& value) {
+    EXPECT_THAT(value, ValueIs<std::string>("\1\2\3\4\5\6\7\b\n\f\r"));
+  });
+}
+
+TEST(LexerTest, Latin) {
+  Do(R"json("Pokémon")json", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<std::string>("Pokémon")));
+  });
+}
+
+TEST(LexerTest, Cjk) {
+  Do(R"json("施氏食獅史")json", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<std::string>("施氏食獅史")));
+  });
+}
+
+TEST(LexerTest, BrokenString) {
+  Bad(R"json("broken)json");
+  Bad(R"json("broken')json");
+  Bad(R"json("broken\")json");
+}
+
+TEST(NonStandard, BrokenString) {
+  Bad(R"json('broken)json");
+  Bad(R"json('broken")json");
+}
+
+TEST(LexerTest, BrokenEscape) {
+  Bad(R"json("\)json");
+  Bad(R"json("\a")json");
+  Bad(R"json("\u")json");
+  Bad(R"json("\u123")json");
+  Bad(R"json("\u{1f36f}")json");
+  Bad(R"json("\u123$$$")json");
+  Bad(R"json("\ud800\udcfg")json");
+}
+
+void GoodNumber(absl::string_view json, double value) {
+  Do(json, [value](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream), IsOkAndHolds(ValueIs<double>(value)));
+  });
+}
+
+TEST(LexerTest, Zero) {
+  GoodNumber("0", 0);
+  GoodNumber("0.0", 0);
+  GoodNumber("0.000", 0);
+  GoodNumber("-0", -0.0);
+  GoodNumber("-0.0", -0.0);
+
+  Bad("00");
+  Bad("-00");
+}
+
+TEST(LexerTest, Integer) {
+  GoodNumber("123456", 123456);
+  GoodNumber("-79497823553162768", -79497823553162768);
+  GoodNumber("11779497823553163264", 11779497823553163264u);
+
+  Bad("0777");
+}
+
+TEST(LexerTest, Overflow) {
+  GoodNumber("18446744073709551616", 18446744073709552000.0);
+  GoodNumber("-18446744073709551616", -18446744073709551616.0);
+
+  Bad("1.89769e308");
+  Bad("-1.89769e308");
+}
+
+TEST(LexerTest, Double) {
+  GoodNumber("42.5", 42.5);
+  GoodNumber("42.50", 42.50);
+  GoodNumber("-1045.235", -1045.235);
+  GoodNumber("-0.235", -0.235);
+
+  Bad("42.");
+  Bad("01.3");
+  Bad(".5");
+  Bad("-.5");
+}
+
+TEST(LexerTest, Scientific) {
+  GoodNumber("1.2345e+10", 1.2345e+10);
+  GoodNumber("1.2345e-10", 1.2345e-10);
+  GoodNumber("1.2345e10", 1.2345e10);
+  GoodNumber("1.2345E+10", 1.2345e+10);
+  GoodNumber("1.2345E-10", 1.2345e-10);
+  GoodNumber("1.2345E10", 1.2345e10);
+  GoodNumber("0e0", 0);
+  GoodNumber("9E9", 9e9);
+
+  Bad("1.e5");
+  Bad("-e5");
+  Bad("1e");
+  Bad("1e-");
+  Bad("1e+");
+}
+
+TEST(LexerTest, EmptyArray) {
+  Do("[]", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<Value::Array>(IsEmpty())));
+  });
+}
+
+TEST(LexerTest, PrimitiveArray) {
+  absl::string_view json = R"json(
+    [true, false, null, "string"]
+  )json";
+  Do(json, [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<Value::Array>(ElementsAre(
+                    ValueIs<bool>(true),            //
+                    ValueIs<bool>(false),           //
+                    ValueIs<Value::Null>(_),        //
+                    ValueIs<std::string>("string")  //
+                    ))));
+  });
+}
+
+TEST(LexerTest, BrokenArray) {
+  Bad("[");
+  Bad("[[");
+  Bad("[true, null}");
+}
+
+TEST(LexerTest, BrokenStringInArray) { Bad(R"json(["Unterminated])json"); }
+
+TEST(LexerTest, NestedArray) {
+  absl::string_view json = R"json(
+    [
+      [22, -127, 45.3, -1056.4, 11779497823553162765],
+      {"key": true}
+    ]
+  )json";
+  Do(json, [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<Value::Array>(ElementsAre(
+                    ValueIs<Value::Array>(ElementsAre(
+                        ValueIs<double>(22),                    //
+                        ValueIs<double>(-127),                  //
+                        ValueIs<double>(45.3),                  //
+                        ValueIs<double>(-1056.4),               //
+                        ValueIs<double>(11779497823553162765u)  //
+                        )),
+                    ValueIs<Value::Object>(
+                        ElementsAre(Pair("key", ValueIs<bool>(true))))))));
+  });
+}
+
+TEST(LexerTest, EmptyObject) {
+  Do("{}", [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<Value::Object>(IsEmpty())));
+  });
+}
+
+TEST(LexerTest, BrokenObject) {
+  Bad("{");
+  Bad("{{");
+  Bad(R"json({"key": true])json");
+  Bad(R"json({"key")json");
+  Bad(R"json({"key":})json");
+}
+
+TEST(LexerTest, BrokenStringInObject) {
+  Bad(R"json({"oops": "Unterminated})json");
+}
+
+TEST(LexerTest, NonPairInObject) {
+  Bad("{null}");
+  Bad("{true}");
+  Bad("{false}");
+  Bad("{42}");
+  Bad("{[null]}");
+  Bad(R"json({{"nest_pas": true}})json");
+  Bad(R"json({"missing colon"})json");
+}
+
+TEST(NonStandard, NonPairInObject) {
+  Bad("{'missing colon'}");
+  Bad("{missing_colon}");
+}
+
+TEST(LexerTest, WrongCommas) {
+  Bad("[null null]");
+  Bad("[null,, null]");
+  Bad(R"json({"a": 0 "b": true})json");
+  Bad(R"json({"a": 0,, "b": true})json");
+}
+
+TEST(NonStandard, Keys) {
+  DoLegacy(R"json({'s': true})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(
+                           ElementsAre(Pair("s", ValueIs<bool>(true)))));
+  });
+  DoLegacy(R"json({key: null})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(
+                           ElementsAre(Pair("key", ValueIs<Value::Null>(_)))));
+  });
+  DoLegacy(R"json({snake_key: []})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(ElementsAre(Pair(
+                           "snake_key", ValueIs<Value::Array>(IsEmpty())))));
+  });
+  DoLegacy(R"json({camelKey: {}})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(ElementsAre(Pair(
+                           "camelKey", ValueIs<Value::Object>(IsEmpty())))));
+  });
+}
+
+TEST(NonStandard, KeywordPrefixedKeys) {
+  DoLegacy(R"json({nullkey: "a"})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(ElementsAre(
+                           Pair("nullkey", ValueIs<std::string>("a")))));
+  });
+  DoLegacy(R"json({truekey: "b"})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(ElementsAre(
+                           Pair("truekey", ValueIs<std::string>("b")))));
+  });
+  DoLegacy(R"json({falsekey: "c"})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(ElementsAre(
+                           Pair("falsekey", ValueIs<std::string>("c")))));
+  });
+}
+
+TEST(LexerTest, BadKeys) {
+  Bad("{null: 0}");
+  Bad("{true: 0}");
+  Bad("{false: 0}");
+  Bad("{lisp-kebab: 0}");
+  Bad("{42: true}");
+}
+
+TEST(LexerTest, NestedObject) {
+  absl::string_view json = R"json(
+    {
+      "t": true,
+      "f": false,
+      "n": null,
+      "s": "a string",
+      "pi": 22,
+      "ni": -127,
+      "pd": 45.3,
+      "nd": -1056.4,
+      "pl": 11779497823553162765,
+      "l": [ [ ] ],
+      "o": { "key": true }
+    }
+  )json";
+  Do(json, [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<Value::Object>(ElementsAre(
+                    Pair("t", ValueIs<bool>(true)),                      //
+                    Pair("f", ValueIs<bool>(false)),                     //
+                    Pair("n", ValueIs<Value::Null>(_)),                  //
+                    Pair("s", ValueIs<std::string>("a string")),         //
+                    Pair("pi", ValueIs<double>(22)),                     //
+                    Pair("ni", ValueIs<double>(-127)),                   //
+                    Pair("pd", ValueIs<double>(45.3)),                   //
+                    Pair("nd", ValueIs<double>(-1056.4)),                //
+                    Pair("pl", ValueIs<double>(11779497823553162765u)),  //
+                    Pair("l", ValueIs<Value::Array>(ElementsAre(
+                                  ValueIs<Value::Array>(IsEmpty())))),  //
+                    Pair("o", ValueIs<Value::Object>(ElementsAre(
+                                  Pair("key", ValueIs<bool>(true)))))  //
+                    ))));
+  });
+}
+
+TEST(LexerTest, RejectNonUtf8) {
+  absl::string_view json = R"json(
+    { "address": x"施氏食獅史" }
+  )json";
+  Bad(absl::StrReplaceAll(json, {{"x", "\xff"}}));
+}
+
+TEST(LexerTest, RejectNonUtf8String) {
+  absl::string_view json = R"json(
+    { "address": "施氏x食獅史" }
+  )json";
+  Bad(absl::StrReplaceAll(json, {{"x", "\xff"}}));
+}
+
+TEST(LexerTest, RejectNonUtf8Prefix) { Bad("\xff{}"); }
+
+TEST(LexerTest, SurrogateEscape) {
+  absl::string_view json = R"json(
+    [ "\ud83d\udc08\u200D\u2b1B\ud83d\uDdA4" ]
+  )json";
+  Do(json, [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<Value::Array>(
+                    ElementsAre(ValueIs<std::string>("🐈‍⬛🖤")))));
+  });
+}
+
+TEST(LexerTest, InvalidCodePoint) { Bad(R"json(["\ude36"])json"); }
+
+TEST(LexerTest, LonelyHighSurrogate) {
+  Bad(R"json(["\ud83d"])json");
+  Bad(R"json(["\ud83d|trailing"])json");
+  Bad(R"json(["\ud83d\ude--"])json");
+  Bad(R"json(["\ud83d\ud83d"])json");
+}
+
+TEST(LexerTest, AsciiEscape) {
+  absl::string_view json = R"json(
+    ["\b", "\ning", "test\f", "\r\t", "test\\\"\/ing"]
+  )json";
+  Do(json, [](io::ZeroCopyInputStream* stream) {
+    EXPECT_THAT(Value::Parse(stream),
+                IsOkAndHolds(ValueIs<Value::Array>(ElementsAre(
+                    ValueIs<std::string>("\b"),           //
+                    ValueIs<std::string>("\ning"),        //
+                    ValueIs<std::string>("test\f"),       //
+                    ValueIs<std::string>("\r\t"),         //
+                    ValueIs<std::string>("test\\\"/ing")  //
+                    ))));
+  });
+}
+
+TEST(NonStandard, AsciiEscape) {
+  DoLegacy(R"json(["\'", '\''])json", [](const Value& value) {
+    EXPECT_THAT(value,
+                ValueIs<Value::Array>(ElementsAre(ValueIs<std::string>("'"),  //
+                                                  ValueIs<std::string>("'")   //
+                                                  )));
+  });
+}
+
+TEST(NonStandard, TrailingCommas) {
+  DoLegacy(R"json({"foo": 42,})json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Object>(
+                           ElementsAre(Pair("foo", ValueIs<double>(42)))));
+  });
+  DoLegacy(R"json({"foo": [42,],})json", [](const Value& value) {
+    EXPECT_THAT(
+        value,
+        ValueIs<Value::Object>(ElementsAre(Pair(
+            "foo", ValueIs<Value::Array>(ElementsAre(ValueIs<double>(42)))))));
+  });
+  DoLegacy(R"json([42,])json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Array>(ElementsAre(ValueIs<double>(42))));
+  });
+  DoLegacy(R"json([{},])json", [](const Value& value) {
+    EXPECT_THAT(value, ValueIs<Value::Array>(
+                           ElementsAre(ValueIs<Value::Object>(IsEmpty()))));
+  });
+}
+
+// These strings are enormous; so that the test actually finishes in a
+// reasonable time, we skip using Do().
+
+TEST(LexerTest, ArrayRecursion) {
+  std::string ok = std::string(ParseOptions::kDefaultDepth, '[') +
+                   std::string(ParseOptions::kDefaultDepth, ']');
+
+  {
+    io::ArrayInputStream stream(ok.data(), static_cast<int>(ok.size()));
+    auto value = Value::Parse(&stream);
+    ASSERT_OK(value);
+
+    Value* v = &*value;
+    for (int i = 0; i < ParseOptions::kDefaultDepth - 1; ++i) {
+      ASSERT_THAT(*v, ValueIs<Value::Array>(SizeIs(1)));
+      v = &absl::get<Value::Array>(v->value)[0];
+    }
+    ASSERT_THAT(*v, ValueIs<Value::Array>(IsEmpty()));
+  }
+
+  {
+    std::string evil = absl::StrFormat("[%s]", ok);
+    io::ArrayInputStream stream(evil.data(), static_cast<int>(evil.size()));
+    ASSERT_THAT(Value::Parse(&stream),
+                StatusIs(absl::StatusCode::kInvalidArgument));
+  }
+}
+
+TEST(LexerTest, ObjectRecursion) {
+  std::string ok;
+  for (int i = 0; i < ParseOptions::kDefaultDepth - 1; ++i) {
+    absl::StrAppend(&ok, "{\"k\":");
+  }
+  absl::StrAppend(&ok, "{");
+  ok += std::string(ParseOptions::kDefaultDepth, '}');
+
+  {
+    io::ArrayInputStream stream(ok.data(), static_cast<int>(ok.size()));
+    auto value = Value::Parse(&stream);
+    ASSERT_OK(value);
+
+    Value* v = &*value;
+    for (int i = 0; i < ParseOptions::kDefaultDepth - 1; ++i) {
+      ASSERT_THAT(*v, ValueIs<Value::Object>(ElementsAre(Pair("k", _))));
+      v = &absl::get<Value::Object>(v->value)[0].second;
+    }
+    ASSERT_THAT(*v, ValueIs<Value::Object>(IsEmpty()));
+  }
+  {
+    std::string evil = absl::StrFormat("{\"k\":%s}", ok);
+    io::ArrayInputStream stream(evil.data(), static_cast<int>(evil.size()));
+    ASSERT_THAT(Value::Parse(&stream),
+                StatusIs(absl::StatusCode::kInvalidArgument));
+  }
+}
+}  // namespace
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/json/internal/message_path.cc
similarity index 66%
rename from src/google/protobuf/util/internal/location_tracker.h
rename to src/google/protobuf/json/internal/message_path.cc
index 68fefcc..f3a41c1 100644
--- a/src/google/protobuf/util/internal/location_tracker.h
+++ b/src/google/protobuf/json/internal/message_path.cc
@@ -28,43 +28,40 @@
 // (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_UTIL_INTERNAL_LOCATION_TRACKER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__
+#include "google/protobuf/json/internal/message_path.h"
 
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
+#include "absl/strings/str_cat.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace converter {
+namespace json_internal {
+void MessagePath::Describe(std::string& out) const {
+  absl::StrAppend(&out, components_.front().type_name);
+  if (components_.size() == 1) {
+    return;
+  }
 
-// LocationTrackerInterface is an interface for classes that track
-// the location information for the purpose of error reporting.
-class PROTOBUF_EXPORT LocationTrackerInterface {
- public:
-  virtual ~LocationTrackerInterface() {}
+  absl::StrAppend(&out, " @ ");
+  for (size_t i = 1; i < components_.size(); ++i) {
+    absl::StrAppend(&out, i == 1 ? "" : ".", components_[i].field_name);
+    if (components_[i].repeated_index >= 0) {
+      absl::StrAppend(&out, "[", components_[i].repeated_index, "]");
+    }
+  }
+  absl::string_view kind_name =
+      FieldDescriptor::TypeName(components_.back().type);
+  absl::StrAppend(&out, ": ", kind_name);
 
-  // Returns the object location as human readable string.
-  virtual std::string ToString() const = 0;
-
- protected:
-  LocationTrackerInterface() {}
-
- private:
-  // Please do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface);
-};
-
-}  // namespace converter
-}  // namespace util
+  absl::string_view type_name = components_.back().type_name;
+  if (!type_name.empty()) {
+    absl::StrAppend(&out, " ", type_name);
+  }
+}
+}  // namespace json_internal
 }  // namespace protobuf
 }  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__
diff --git a/src/google/protobuf/json/internal/message_path.h b/src/google/protobuf/json/internal/message_path.h
new file mode 100644
index 0000000..b1a3f9f
--- /dev/null
+++ b/src/google/protobuf/json/internal/message_path.h
@@ -0,0 +1,84 @@
+// 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_JSON_INTERNAL_MESSAGE_PATH_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_MESSAGE_PATH_H__
+
+#include <string>
+#include <vector>
+
+#include "absl/cleanup/cleanup.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor.h"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+// A path in a Protobuf message, annotated specifically for producing nice
+// errors.
+class MessagePath {
+ public:
+  explicit MessagePath(absl::string_view message_root)
+      : components_(
+            {Component{FieldDescriptor::TYPE_MESSAGE, message_root, "", -1}}) {}
+
+  // Pushes a new field name, along with an optional type name if it is
+  // a message or enum.
+  //
+  // Returns an RAII object that will pop the field component on scope exit.
+  auto Push(absl::string_view field_name, FieldDescriptor::Type type,
+            absl::string_view type_name = "") {
+    // -1 makes it so the first call to NextRepeated makes the index 0.
+    components_.push_back(Component{type, type_name, field_name, -1});
+    return absl::MakeCleanup([this] { components_.pop_back(); });
+  }
+
+  // Increments the index of this field, indicating it is a repeated field.
+  //
+  // The first time this is called, the field will be marked as repeated and
+  // the index will become 0.
+  void NextRepeated() { ++components_.back().repeated_index; }
+
+  // Appends a description of the current state of the path to `out`.
+  void Describe(std::string& out) const;
+
+ private:
+  struct Component {
+    FieldDescriptor::Type type;
+    absl::string_view type_name, field_name;
+    int32_t repeated_index;
+  };
+  std::vector<Component> components_;
+};
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_MESSAGE_PATH_H__
diff --git a/src/google/protobuf/json/internal/parser.cc b/src/google/protobuf/json/internal/parser.cc
new file mode 100644
index 0000000..617b029
--- /dev/null
+++ b/src/google/protobuf/json/internal/parser.cc
@@ -0,0 +1,1375 @@
+// 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/json/internal/parser.h"
+
+#include <cfloat>
+#include <cmath>
+#include <cstdint>
+#include <cstring>
+#include <limits>
+#include <memory>
+#include <string>
+#include <utility>
+
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "absl/base/attributes.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/match.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_split.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+#include "google/protobuf/io/zero_copy_sink.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/json/internal/descriptor_traits.h"
+#include "google/protobuf/json/internal/lexer.h"
+#include "google/protobuf/json/internal/parser_traits.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+namespace {
+// This file contains code that drives a JsonLexer to visit a JSON document and
+// convert it into some form of proto.
+//
+// This semantic layer is duplicated: proto2-ish code can deserialize directly
+// into a message, whereas proto3-ish code deserializes into a byte stream,
+// using TypeResolvers instead of Descriptors.
+//
+// The parsing code is templated over which of these two reflection + output
+// combinations is used. The traits types that collect the per-instantiation
+// functionality can be found in json_util2_parser_traits-inl.h.
+
+// This table maps an unsigned `char` value, interpreted as an ASCII character,
+// to a corresponding value in the base64 alphabet (both traditional and
+// "web-safe" characters are included).
+//
+// If a character is not valid base64, it maps to -1; this is used by the bit
+// operations that assemble a base64-encoded word to determine if an error
+// occurred, by checking the sign bit.
+constexpr signed char kBase64Table[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};
+
+uint32_t Base64Lookup(char c) {
+  // Sign-extend return value so high bit will be set on any unexpected char.
+  return static_cast<uint32_t>(kBase64Table[static_cast<uint8_t>(c)]);
+}
+
+// Decodes `base64` in-place, shrinking the length as appropriate.
+absl::StatusOr<absl::Span<char>> DecodeBase64InPlace(absl::Span<char> base64) {
+  // 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 = base64.data();
+  const char* ptr = base64.data();
+  const char* end = ptr + base64.size();
+  const char* end4 = ptr + (base64.size() & ~3u);
+
+  for (; ptr < end4; ptr += 4, out += 3) {
+    auto val = Base64Lookup(ptr[0]) << 18 | Base64Lookup(ptr[1]) << 12 |
+               Base64Lookup(ptr[2]) << 6 | Base64Lookup(ptr[3]) << 0;
+
+    if (static_cast<int32_t>(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) {
+    uint32_t val = ~0u;
+    switch (end - ptr) {
+      case 2:
+        val = Base64Lookup(ptr[0]) << 18 | Base64Lookup(ptr[1]) << 12;
+        out[0] = val >> 16;
+        out += 1;
+        break;
+      case 3:
+        val = Base64Lookup(ptr[0]) << 18 | Base64Lookup(ptr[1]) << 12 |
+              Base64Lookup(ptr[2]) << 6;
+        out[0] = val >> 16;
+        out[1] = (val >> 8) & 0xff;
+        out += 2;
+        break;
+    }
+
+    if (static_cast<int32_t>(val) < 0) {
+      return absl::InvalidArgumentError("corrupt base64");
+    }
+  }
+
+  return absl::Span<char>(base64.data(),
+                          static_cast<size_t>(out - base64.data()));
+}
+
+template <typename T>
+absl::StatusOr<LocationWith<T>> ParseIntInner(JsonLexer& lex, double lo,
+                                              double hi) {
+  absl::StatusOr<JsonLexer::Kind> kind = lex.PeekKind();
+  RETURN_IF_ERROR(kind.status());
+
+  LocationWith<T> n;
+  switch (*kind) {
+    case JsonLexer::kNum: {
+      absl::StatusOr<LocationWith<MaybeOwnedString>> x = lex.ParseRawNumber();
+      RETURN_IF_ERROR(x.status());
+      n.loc = x->loc;
+      if (absl::SimpleAtoi(x->value.AsView(), &n.value)) {
+        break;
+      }
+
+      double d;
+      if (!absl::SimpleAtod(x->value.AsView(), &d) || !std::isfinite(d)) {
+        return x->loc.Invalid(
+            absl::StrFormat("invalid number: '%s'", x->value.AsView()));
+      }
+
+      // Conversion overflow here would be UB.
+      if (lo > d || d > hi) {
+        return lex.Invalid("JSON number out of range for int");
+      }
+      n.value = static_cast<T>(d);
+      if (d - static_cast<double>(n.value) != 0) {
+        return lex.Invalid(
+            "expected integer, but JSON number had fractional part");
+      }
+      break;
+    }
+    case JsonLexer::kStr: {
+      absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+      RETURN_IF_ERROR(str.status());
+      // SimpleAtoi will ignore leading and trailing whitespace, so we need
+      // to check for it ourselves.
+      for (char c : str->value.AsView()) {
+        if (absl::ascii_isspace(c)) {
+          return lex.Invalid("non-number characters in quoted number");
+        }
+      }
+      if (!absl::SimpleAtoi(str->value.AsView(), &n.value)) {
+        return str->loc.Invalid("non-number characters in quoted number");
+      }
+      n.loc = str->loc;
+      break;
+    }
+    default:
+      return lex.Invalid("expected number or string");
+  }
+
+  return n;
+}
+
+template <typename Traits>
+absl::StatusOr<int64_t> ParseInt(JsonLexer& lex, Field<Traits> field) {
+  absl::StatusOr<LocationWith<int64_t>> n =
+      ParseIntInner<int64_t>(lex, -9007199254740992.0, 9007199254740992.0);
+  RETURN_IF_ERROR(n.status());
+
+  if (Traits::Is32Bit(field)) {
+    if (std::numeric_limits<int32_t>::min() > n->value ||
+        n->value > std::numeric_limits<int32_t>::max()) {
+      return n->loc.Invalid("integer out of range");
+    }
+  }
+
+  return n->value;
+}
+
+template <typename Traits>
+absl::StatusOr<uint64_t> ParseUInt(JsonLexer& lex, Field<Traits> field) {
+  absl::StatusOr<LocationWith<uint64_t>> n =
+      ParseIntInner<uint64_t>(lex, 0, 18014398509481984.0);
+  RETURN_IF_ERROR(n.status());
+
+  if (Traits::Is32Bit(field)) {
+    if (n->value > std::numeric_limits<uint32_t>::max()) {
+      return n->loc.Invalid("integer out of range");
+    }
+  }
+
+  return n->value;
+}
+
+template <typename Traits>
+absl::StatusOr<double> ParseFp(JsonLexer& lex, Field<Traits> field) {
+  absl::StatusOr<JsonLexer::Kind> kind = lex.PeekKind();
+  RETURN_IF_ERROR(kind.status());
+
+  double n;
+  switch (*kind) {
+    case JsonLexer::kNum: {
+      absl::StatusOr<LocationWith<double>> d = lex.ParseNumber();
+      RETURN_IF_ERROR(d.status());
+      n = d->value;
+      break;
+    }
+    case JsonLexer::kStr: {
+      absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+      RETURN_IF_ERROR(str.status());
+
+      if (str->value == "NaN") {
+        n = NAN;
+      } else if (str->value == "Infinity") {
+        n = INFINITY;
+      } else if (str->value == "-Infinity") {
+        n = -INFINITY;
+      } else if (!absl::SimpleAtod(str->value.AsView(), &n)) {
+        return str->loc.Invalid("non-number characters in quoted number");
+      }
+      break;
+    }
+    default:
+      return lex.Invalid("expected number or string");
+  }
+
+  if (Traits::Is32Bit(field)) {
+    // Detect out-of-range 32-bit floats by seeing whether the conversion result
+    // is still finite. Finite extreme values may have textual representations
+    // that parse to 64-bit values outside the 32-bit range, but which are
+    // closer to the 32-bit extreme than to the "next value with the same
+    // precision".
+    if (std::isfinite(n) && !std::isfinite(static_cast<float>(n))) {
+      return lex.Invalid("float out of range");
+    }
+  }
+
+  return n;
+}
+
+template <typename Traits>
+absl::StatusOr<std::string> ParseStrOrBytes(JsonLexer& lex,
+                                            Field<Traits> field) {
+  absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+  RETURN_IF_ERROR(str.status());
+
+  if (Traits::FieldType(field) == FieldDescriptor::TYPE_BYTES) {
+    std::string& b64 = str->value.ToString();
+    absl::StatusOr<absl::Span<char>> decoded =
+        DecodeBase64InPlace(absl::MakeSpan(&b64[0], b64.size()));
+    if (!decoded.ok()) {
+      return str->loc.Invalid(decoded.status().message());
+    }
+    b64.resize(decoded->size());
+  }
+
+  return std::move(str->value.ToString());
+}
+
+template <typename Traits>
+absl::StatusOr<absl::optional<int32_t>> ParseEnumFromStr(JsonLexer& lex,
+                                                         MaybeOwnedString& str,
+                                                         Field<Traits> field) {
+  absl::StatusOr<int32_t> value = Traits::EnumNumberByName(
+      field, str.AsView(), lex.options().case_insensitive_enum_parsing);
+  if (value.ok()) {
+    return absl::optional<int32_t>(*value);
+  }
+
+  int32_t i;
+  if (absl::SimpleAtoi(str.AsView(), &i)) {
+    return absl::optional<int32_t>(i);
+  } else if (lex.options().ignore_unknown_fields) {
+    return {absl::nullopt};
+  }
+
+  return value.status();
+}
+
+// Parses an enum; can return nullopt if a quoted enumerator that we don't
+// know about is received and `ignore_unknown_fields` is set.
+template <typename Traits>
+absl::StatusOr<absl::optional<int32_t>> ParseEnum(JsonLexer& lex,
+                                                  Field<Traits> field) {
+  absl::StatusOr<JsonLexer::Kind> kind = lex.PeekKind();
+  RETURN_IF_ERROR(kind.status());
+
+  int32_t n = 0;
+  switch (*kind) {
+    case JsonLexer::kStr: {
+      absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+      RETURN_IF_ERROR(str.status());
+
+      auto e = ParseEnumFromStr<Traits>(lex, str->value, field);
+      RETURN_IF_ERROR(e.status());
+      if (!e->has_value()) {
+        return {absl::nullopt};
+      }
+      n = **e;
+      break;
+    }
+    case JsonLexer::kNum:
+      return ParseInt<Traits>(lex, field);
+    default:
+      return lex.Invalid("expected number or string");
+  }
+
+  return n;
+}
+
+// Mutually recursive with functions that follow.
+template <typename Traits>
+absl::Status ParseMessage(JsonLexer& lex, const Desc<Traits>& desc,
+                          Msg<Traits>& msg, bool any_reparse);
+template <typename Traits>
+absl::Status ParseField(JsonLexer& lex, const Desc<Traits>& desc,
+                        absl::string_view name, Msg<Traits>& msg);
+
+template <typename Traits>
+absl::Status ParseSingular(JsonLexer& lex, Field<Traits> field,
+                           Msg<Traits>& msg) {
+  auto field_type = Traits::FieldType(field);
+  if (lex.Peek(JsonLexer::kNull)) {
+    auto message_type = ClassifyMessage(Traits::FieldTypeName(field));
+    switch (field_type) {
+      case FieldDescriptor::TYPE_ENUM:
+        if (message_type == MessageType::kNull) {
+          Traits::SetEnum(field, msg, 0);
+        }
+        break;
+      case FieldDescriptor::TYPE_MESSAGE: {
+        if (message_type == MessageType::kValue) {
+          return Traits::NewMsg(
+              field, msg,
+              [&](const Desc<Traits>& type, Msg<Traits>& msg) -> absl::Status {
+                auto field = Traits::FieldByNumber(type, 1);
+                GOOGLE_DCHECK(field.has_value());
+                RETURN_IF_ERROR(lex.Expect("null"));
+                Traits::SetEnum(Traits::MustHaveField(type, 1), msg, 0);
+                return absl::OkStatus();
+              });
+        }
+        break;
+      }
+      default:
+        break;
+    }
+    return lex.Expect("null");
+  }
+
+  switch (field_type) {
+    case FieldDescriptor::TYPE_FLOAT: {
+      auto x = ParseFp<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+      Traits::SetFloat(field, msg, *x);
+      break;
+    }
+    case FieldDescriptor::TYPE_DOUBLE: {
+      auto x = ParseFp<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+      Traits::SetDouble(field, msg, *x);
+      break;
+    }
+
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_INT64: {
+      auto x = ParseInt<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+      Traits::SetInt64(field, msg, *x);
+      break;
+    }
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_UINT64: {
+      auto x = ParseUInt<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+      Traits::SetUInt64(field, msg, *x);
+      break;
+    }
+
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_INT32: {
+      auto x = ParseInt<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+      Traits::SetInt32(field, msg, static_cast<int32_t>(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_UINT32: {
+      auto x = ParseUInt<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+      Traits::SetUInt32(field, msg, static_cast<uint32_t>(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_BOOL: {
+      absl::StatusOr<JsonLexer::Kind> kind = lex.PeekKind();
+      RETURN_IF_ERROR(kind.status());
+
+      switch (*kind) {
+        case JsonLexer::kTrue:
+          RETURN_IF_ERROR(lex.Expect("true"));
+          Traits::SetBool(field, msg, true);
+          break;
+        case JsonLexer::kFalse:
+          RETURN_IF_ERROR(lex.Expect("false"));
+          Traits::SetBool(field, msg, false);
+          break;
+        case JsonLexer::kStr: {
+          if (!lex.options().allow_legacy_syntax) {
+            goto bad;
+          }
+
+          auto x = lex.ParseUtf8();
+          RETURN_IF_ERROR(x.status());
+
+          bool flag;
+          if (!absl::SimpleAtob(x->value, &flag)) {
+            // Is this error a lie? Do we accept things otyher than "true" and
+            // "false" because SimpleAtob does? Absolutely!
+            return x->loc.Invalid("expected 'true' or 'false'");
+          }
+          Traits::SetBool(field, msg, flag);
+
+          break;
+        }
+        bad:
+        default:
+          return lex.Invalid("expected 'true' or 'false'");
+      }
+      break;
+    }
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES: {
+      auto x = ParseStrOrBytes<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+      Traits::SetString(field, msg, *x);
+      break;
+    }
+    case FieldDescriptor::TYPE_ENUM: {
+      absl::StatusOr<absl::optional<int32_t>> x = ParseEnum<Traits>(lex, field);
+      RETURN_IF_ERROR(x.status());
+
+      if (x->has_value() || Traits::IsImplicitPresence(field)) {
+        Traits::SetEnum(field, msg, x->value_or(0));
+      }
+      break;
+    }
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP: {
+      return Traits::NewMsg(
+          field, msg,
+          [&](const Desc<Traits>& type, Msg<Traits>& msg) -> absl::Status {
+            return ParseMessage<Traits>(lex, type, msg,
+                                        /*any_reparse=*/false);
+          });
+    }
+    default:
+      return lex.Invalid(
+          absl::StrCat("unsupported field type: ", Traits::FieldType(field)));
+  }
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status EmitNull(JsonLexer& lex, Field<Traits> field, Msg<Traits>& msg) {
+  switch (Traits::FieldType(field)) {
+    case FieldDescriptor::TYPE_FLOAT:
+      Traits::SetFloat(field, msg, 0);
+      break;
+    case FieldDescriptor::TYPE_DOUBLE:
+      Traits::SetDouble(field, msg, 0);
+      break;
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_INT64:
+      Traits::SetInt64(field, msg, 0);
+      break;
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_UINT64:
+      Traits::SetUInt64(field, msg, 0);
+      break;
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_INT32:
+      Traits::SetInt32(field, msg, 0);
+      break;
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_UINT32:
+      Traits::SetUInt32(field, msg, 0);
+      break;
+    case FieldDescriptor::TYPE_BOOL:
+      Traits::SetBool(field, msg, false);
+      break;
+    case FieldDescriptor::TYPE_STRING:
+    case FieldDescriptor::TYPE_BYTES:
+      Traits::SetString(field, msg, "");
+      break;
+    case FieldDescriptor::TYPE_ENUM:
+      Traits::SetEnum(field, msg, 0);
+      break;
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP:
+      return Traits::NewMsg(field, msg,
+                            [](const auto&, const auto&) -> absl::Status {
+                              return absl::OkStatus();
+                            });
+    default:
+      return lex.Invalid(
+          absl::StrCat("unsupported field type: ", Traits::FieldType(field)));
+  }
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status ParseArray(JsonLexer& lex, Field<Traits> field, Msg<Traits>& msg) {
+  if (lex.Peek(JsonLexer::kNull)) {
+    return lex.Expect("null");
+  }
+
+  return lex.VisitArray([&]() -> absl::Status {
+    lex.path().NextRepeated();
+    MessageType type = ClassifyMessage(Traits::FieldTypeName(field));
+
+    if (lex.Peek(JsonLexer::kNull)) {
+      if (type == MessageType::kValue) {
+        return ParseSingular<Traits>(lex, field, msg);
+      }
+      if (type == MessageType::kNull) {
+        return ParseSingular<Traits>(lex, field, msg);
+      }
+
+      if (lex.options().allow_legacy_syntax) {
+        RETURN_IF_ERROR(lex.Expect("null"));
+        return EmitNull<Traits>(lex, field, msg);
+      }
+      return lex.Invalid("null cannot occur inside of repeated fields");
+    }
+
+    // Note that this is sufficient to catch when we are inside of a ListValue,
+    // because a ListValue's sole field is of type Value. Thus, we only need to
+    // classify cases in which we are inside of an array and parsing messages
+    // that like looking like arrays.
+    //
+    // This will also correctly handle e.g. writing out a ListValue with the
+    // legacy syntax of `{"values": [[0], [1], [2]]}`, which does not go through
+    // the custom parser handler.
+    bool can_flatten =
+        type != MessageType::kValue && type != MessageType::kList;
+    if (can_flatten && lex.options().allow_legacy_syntax &&
+        lex.Peek(JsonLexer::kArr)) {
+      // You read that right. In legacy mode, if we encounter an array within
+      // an array, we just flatten it as part of the current array!
+      //
+      // This DOES NOT apply when parsing a google.protobuf.Value or a
+      // google.protobuf.ListValue!
+      return ParseArray<Traits>(lex, field, msg);
+    }
+    return ParseSingular<Traits>(lex, field, msg);
+  });
+}
+
+template <typename Traits>
+absl::Status ParseMap(JsonLexer& lex, Field<Traits> field, Msg<Traits>& msg) {
+  if (lex.Peek(JsonLexer::kNull)) {
+    return lex.Expect("null");
+  }
+
+  absl::flat_hash_set<std::string> keys_seen;
+  return lex.VisitObject(
+      [&](LocationWith<MaybeOwnedString>& key) -> absl::Status {
+        lex.path().NextRepeated();
+        auto insert_result = keys_seen.emplace(key.value.AsView());
+        if (!insert_result.second) {
+          return key.loc.Invalid(absl::StrFormat(
+              "got unexpectedly-repeated repeated map key: '%s'",
+              key.value.AsView()));
+        }
+        return Traits::NewMsg(
+            field, msg,
+            [&](const Desc<Traits>& type, Msg<Traits>& entry) -> absl::Status {
+              auto key_field = Traits::KeyField(type);
+              switch (Traits::FieldType(key_field)) {
+                case FieldDescriptor::TYPE_INT64:
+                case FieldDescriptor::TYPE_SINT64:
+                case FieldDescriptor::TYPE_SFIXED64: {
+                  int64_t n;
+                  if (!absl::SimpleAtoi(key.value.AsView(), &n)) {
+                    return key.loc.Invalid(
+                        "non-number characters in quoted number");
+                  }
+                  Traits::SetInt64(key_field, entry, n);
+                  break;
+                }
+                case FieldDescriptor::TYPE_UINT64:
+                case FieldDescriptor::TYPE_FIXED64: {
+                  uint64_t n;
+                  if (!absl::SimpleAtoi(key.value.AsView(), &n)) {
+                    return key.loc.Invalid(
+                        "non-number characters in quoted number");
+                  }
+                  Traits::SetUInt64(key_field, entry, n);
+                  break;
+                }
+                case FieldDescriptor::TYPE_INT32:
+                case FieldDescriptor::TYPE_SINT32:
+                case FieldDescriptor::TYPE_SFIXED32: {
+                  int32_t n;
+                  if (!absl::SimpleAtoi(key.value.AsView(), &n)) {
+                    return key.loc.Invalid(
+                        "non-number characters in quoted number");
+                  }
+                  Traits::SetInt32(key_field, entry, n);
+                  break;
+                }
+                case FieldDescriptor::TYPE_UINT32:
+                case FieldDescriptor::TYPE_FIXED32: {
+                  uint32_t n;
+                  if (!absl::SimpleAtoi(key.value.AsView(), &n)) {
+                    return key.loc.Invalid(
+                        "non-number characters in quoted number");
+                  }
+                  Traits::SetUInt32(key_field, entry, n);
+                  break;
+                }
+                case FieldDescriptor::TYPE_BOOL: {
+                  if (key.value == "true") {
+                    Traits::SetBool(key_field, entry, true);
+                  } else if (key.value == "false") {
+                    Traits::SetBool(key_field, entry, false);
+                  } else {
+                    return key.loc.Invalid(absl::StrFormat(
+                        "expected bool string, got '%s'", key.value.AsView()));
+                  }
+                  break;
+                }
+                case FieldDescriptor::TYPE_ENUM: {
+                  MaybeOwnedString key_str = key.value;
+                  auto e = ParseEnumFromStr<Traits>(lex, key_str, field);
+                  RETURN_IF_ERROR(e.status());
+                  Traits::SetEnum(key_field, entry, e->value_or(0));
+                  break;
+                }
+                case FieldDescriptor::TYPE_STRING: {
+                  Traits::SetString(key_field, entry,
+                                    std::move(key.value.ToString()));
+                  break;
+                }
+                default:
+                  return lex.Invalid("unsupported map key type");
+              }
+
+              return ParseSingular<Traits>(lex, Traits::ValueField(type),
+                                           entry);
+            });
+      });
+}
+
+absl::optional<uint32_t> TakeTimeDigitsWithSuffixAndAdvance(
+    absl::string_view& data, int max_digits, absl::string_view end) {
+  GOOGLE_DCHECK_LE(max_digits, 9);
+
+  uint32_t val = 0;
+  int limit = max_digits;
+  while (!data.empty()) {
+    if (limit-- < 0) {
+      return absl::nullopt;
+    }
+    uint32_t digit = data[0] - '0';
+    if (digit >= 10) {
+      break;
+    }
+
+    val *= 10;
+    val += digit;
+    data = data.substr(1);
+  }
+  if (!absl::StartsWith(data, end)) {
+    return absl::nullopt;
+  }
+
+  data = data.substr(end.size());
+  return val;
+}
+
+absl::optional<int32_t> TakeNanosAndAdvance(absl::string_view& data) {
+  int32_t frac_secs = 0;
+  size_t frac_digits = 0;
+  if (absl::StartsWith(data, ".")) {
+    for (char c : data.substr(1)) {
+      if (!absl::ascii_isdigit(c)) {
+        break;
+      }
+      ++frac_digits;
+    }
+    auto digits = data.substr(1, frac_digits);
+    if (frac_digits == 0 || frac_digits > 9 ||
+        !absl::SimpleAtoi(digits, &frac_secs)) {
+      return absl::nullopt;
+    }
+    data = data.substr(frac_digits + 1);
+  }
+  for (int i = 0; i < 9 - frac_digits; ++i) {
+    frac_secs *= 10;
+  }
+  return frac_secs;
+}
+
+template <typename Traits>
+absl::Status ParseTimestamp(JsonLexer& lex, const Desc<Traits>& desc,
+                            Msg<Traits>& msg) {
+  if (lex.Peek(JsonLexer::kNull)) {
+    return lex.Expect("null");
+  }
+
+  absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+  RETURN_IF_ERROR(str.status());
+
+  absl::string_view data = str->value.AsView();
+  if (data.size() < 20) {
+    return str->loc.Invalid("timestamp string too short");
+  }
+
+  int64_t secs;
+  {
+    /* 1972-01-01T01:00:00 */
+    auto year = TakeTimeDigitsWithSuffixAndAdvance(data, 4, "-");
+    if (!year.has_value() || *year == 0) {
+      return str->loc.Invalid("bad year in timestamp");
+    }
+    auto mon = TakeTimeDigitsWithSuffixAndAdvance(data, 2, "-");
+    if (!mon.has_value() || *mon == 0) {
+      return str->loc.Invalid("bad month in timestamp");
+    }
+    auto day = TakeTimeDigitsWithSuffixAndAdvance(data, 2, "T");
+    if (!day.has_value() || *day == 0) {
+      return str->loc.Invalid("bad day in timestamp");
+    }
+    auto hour = TakeTimeDigitsWithSuffixAndAdvance(data, 2, ":");
+    if (!hour.has_value()) {
+      return str->loc.Invalid("bad hours in timestamp");
+    }
+    auto min = TakeTimeDigitsWithSuffixAndAdvance(data, 2, ":");
+    if (!min.has_value()) {
+      return str->loc.Invalid("bad minutes in timestamp");
+    }
+    auto sec = TakeTimeDigitsWithSuffixAndAdvance(data, 2, "");
+    if (!sec.has_value()) {
+      return str->loc.Invalid("bad seconds in timestamp");
+    }
+
+    uint32_t m_adj = *mon - 3;  // March-based month.
+    uint32_t carry = m_adj > *mon ? 1 : 0;
+
+    uint32_t year_base = 4800;  // Before min year, multiple of 400.
+    uint32_t y_adj = *year + year_base - carry;
+
+    uint32_t month_days = ((m_adj + carry * 12) * 62719 + 769) / 2048;
+    uint32_t leap_days = y_adj / 4 - y_adj / 100 + y_adj / 400;
+    int32_t epoch_days =
+        y_adj * 365 + leap_days + month_days + (*day - 1) - 2472632;
+
+    secs = int64_t{epoch_days} * 86400 + *hour * 3600 + *min * 60 + *sec;
+  }
+
+  auto nanos = TakeNanosAndAdvance(data);
+  if (!nanos.has_value()) {
+    return str->loc.Invalid("timestamp had bad nanoseconds");
+  }
+
+  if (data.empty()) {
+    return str->loc.Invalid("timestamp missing timezone offset");
+  }
+
+  {
+    // [+-]hh:mm or Z
+    bool neg = false;
+    switch (data[0]) {
+      case '-':
+        neg = true;
+        ABSL_FALLTHROUGH_INTENDED;
+      case '+': {
+        if (data.size() != 6) {
+          return str->loc.Invalid("timestamp offset of wrong size.");
+        }
+
+        data = data.substr(1);
+        auto hour = TakeTimeDigitsWithSuffixAndAdvance(data, 2, ":");
+        auto mins = TakeTimeDigitsWithSuffixAndAdvance(data, 2, "");
+        if (!hour.has_value() || !mins.has_value()) {
+          return str->loc.Invalid("timestamp offset has bad hours and minutes");
+        }
+
+        int64_t offset = (*hour * 60 + *mins) * 60;
+        secs += (neg ? offset : -offset);
+        break;
+      }
+      // Lowercase z is not accepted, per the spec.
+      case 'Z':
+        if (data.size() == 1) {
+          break;
+        }
+        ABSL_FALLTHROUGH_INTENDED;
+      default:
+        return str->loc.Invalid("bad timezone offset");
+    }
+  }
+
+  Traits::SetInt64(Traits::MustHaveField(desc, 1), msg, secs);
+  Traits::SetInt32(Traits::MustHaveField(desc, 2), msg, *nanos);
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status ParseDuration(JsonLexer& lex, const Desc<Traits>& desc,
+                           Msg<Traits>& msg) {
+  if (lex.Peek(JsonLexer::kNull)) {
+    return lex.Expect("null");
+  }
+
+  constexpr int64_t kMaxSeconds = int64_t{3652500} * 86400;
+
+  absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+  RETURN_IF_ERROR(str.status());
+
+  size_t int_part_end = 0;
+  for (char c : str->value.AsView()) {
+    if (!absl::ascii_isdigit(c) && c != '-') {
+      break;
+    }
+    ++int_part_end;
+  }
+  if (int_part_end == 0) {
+    return str->loc.Invalid("duration must start with an integer");
+  }
+
+  absl::string_view sec_digits = str->value.AsView().substr(0, int_part_end);
+  int64_t secs;
+  if (!absl::SimpleAtoi(sec_digits, &secs)) {
+    return str->loc.Invalid("duration had bad seconds");
+  }
+
+  if (secs > kMaxSeconds || secs < -kMaxSeconds) {
+    return str->loc.Invalid("duration out of range");
+  }
+
+  absl::string_view rest = str->value.AsView().substr(int_part_end);
+  auto nanos = TakeNanosAndAdvance(rest);
+  if (!nanos.has_value()) {
+    return str->loc.Invalid("duration had bad nanoseconds");
+  }
+
+  bool isNegative = (secs < 0) || absl::StartsWith(sec_digits, "-");
+  if (isNegative) {
+    *nanos *= -1;
+  }
+
+  if (rest != "s") {
+    return str->loc.Invalid("duration must end with a single 's'");
+  }
+
+  Traits::SetInt64(Traits::MustHaveField(desc, 1), msg, secs);
+  Traits::SetInt32(Traits::MustHaveField(desc, 2), msg, *nanos);
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status ParseFieldMask(JsonLexer& lex, const Desc<Traits>& desc,
+                            Msg<Traits>& msg) {
+  absl::StatusOr<LocationWith<MaybeOwnedString>> str = lex.ParseUtf8();
+  RETURN_IF_ERROR(str.status());
+  auto paths = str->value.AsView();
+
+  // The special case of the empty string is not handled correctly below,
+  // because StrSplit("", ',') is [""], not [].
+  if (paths.empty()) {
+    return absl::OkStatus();
+  }
+
+  // google.protobuf.FieldMask has a single field with number 1.
+  auto paths_field = Traits::MustHaveField(desc, 1);
+  for (absl::string_view path : absl::StrSplit(paths, ',')) {
+    std::string snake_path;
+    // Assume approximately six-letter words, so add one extra space for an
+    // underscore for every six bytes.
+    snake_path.reserve(path.size() * 7 / 6);
+    for (char c : path) {
+      if (absl::ascii_isdigit(c) || absl::ascii_islower(c) || c == '.') {
+        snake_path.push_back(c);
+      } else if (absl::ascii_isupper(c)) {
+        snake_path.push_back('_');
+        snake_path.push_back(absl::ascii_tolower(c));
+      } else if (lex.options().allow_legacy_syntax) {
+        snake_path.push_back(c);
+      } else {
+        return str->loc.Invalid("unexpected character in FieldMask");
+      }
+    }
+    Traits::SetString(paths_field, msg, snake_path);
+  }
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status ParseAny(JsonLexer& lex, const Desc<Traits>& desc,
+                      Msg<Traits>& msg) {
+  // Buffer an entire object. Because @type can occur anywhere, we're forced
+  // to do this.
+  RETURN_IF_ERROR(lex.SkipToToken());
+  auto mark = lex.BeginMark();
+
+  // Search for @type, buffering the entire object along the way so we can
+  // reparse it.
+  absl::optional<MaybeOwnedString> type_url;
+  RETURN_IF_ERROR(lex.VisitObject(
+      [&](const LocationWith<MaybeOwnedString>& key) -> absl::Status {
+        if (key.value == "@type") {
+          if (type_url.has_value()) {
+            return key.loc.Invalid("repeated @type in Any");
+          }
+
+          absl::StatusOr<LocationWith<MaybeOwnedString>> maybe_url =
+              lex.ParseUtf8();
+          RETURN_IF_ERROR(maybe_url.status());
+          type_url = std::move(maybe_url)->value;
+          return absl::OkStatus();
+        }
+        return lex.SkipValue();
+      }));
+
+  // Build a new lexer over the skipped object.
+  absl::string_view any_text = mark.value.UpToUnread();
+  io::ArrayInputStream in(any_text.data(), any_text.size());
+  // Copying lex.options() is important; it inherits the recursion
+  // limit.
+  JsonLexer any_lex(&in, lex.options(), &lex.path(), mark.loc);
+
+  if (!type_url.has_value() && !lex.options().allow_legacy_syntax) {
+    return mark.loc.Invalid("missing @type in Any");
+  }
+
+  if (type_url.has_value()) {
+    Traits::SetString(Traits::MustHaveField(desc, 1), msg, type_url->AsView());
+    return Traits::NewDynamic(
+        Traits::MustHaveField(desc, 2), type_url->ToString(), msg,
+        [&](const Desc<Traits>& desc, Msg<Traits>& msg) {
+          auto pop = any_lex.path().Push("<any>", FieldDescriptor::TYPE_MESSAGE,
+                                         Traits::TypeName(desc));
+          return ParseMessage<Traits>(any_lex, desc, msg,
+                                      /*any_reparse=*/true);
+        });
+  } else {
+    // Empty {} is accepted in legacy mode.
+    GOOGLE_DCHECK(lex.options().allow_legacy_syntax);
+    RETURN_IF_ERROR(any_lex.VisitObject([&](auto&) {
+      return mark.loc.Invalid(
+          "in legacy mode, missing @type in Any is only allowed for an empty "
+          "object");
+    }));
+    return absl::OkStatus();
+  }
+}
+
+// These are mutually recursive with ParseValue.
+template <typename Traits>
+absl::Status ParseStructValue(JsonLexer& lex, const Desc<Traits>& desc,
+                              Msg<Traits>& msg);
+template <typename Traits>
+absl::Status ParseListValue(JsonLexer& lex, const Desc<Traits>& desc,
+                            Msg<Traits>& msg);
+
+template <typename Traits>
+absl::Status ParseValue(JsonLexer& lex, const Desc<Traits>& desc,
+                        Msg<Traits>& msg) {
+  auto kind = lex.PeekKind();
+  RETURN_IF_ERROR(kind.status());
+  // NOTE: The field numbers 1 through 6 are the numbers of the oneof fields
+  // in google.protobuf.Value. Conformance tests verify the correctness of
+  // these numbers.
+  switch (*kind) {
+    case JsonLexer::kNull: {
+      auto field = Traits::MustHaveField(desc, 1);
+      auto pop =
+          lex.path().Push(Traits::FieldName(field), Traits::FieldType(field),
+                          Traits::FieldTypeName(field));
+
+      RETURN_IF_ERROR(lex.Expect("null"));
+      Traits::SetEnum(field, msg, 0);
+      break;
+    }
+    case JsonLexer::kNum: {
+      auto field = Traits::MustHaveField(desc, 2);
+      auto pop =
+          lex.path().Push(Traits::FieldName(field), Traits::FieldType(field),
+                          Traits::FieldTypeName(field));
+
+      auto number = lex.ParseNumber();
+      RETURN_IF_ERROR(number.status());
+      Traits::SetDouble(field, msg, number->value);
+      break;
+    }
+    case JsonLexer::kStr: {
+      auto field = Traits::MustHaveField(desc, 3);
+      auto pop =
+          lex.path().Push(Traits::FieldName(field), Traits::FieldType(field),
+                          Traits::FieldTypeName(field));
+
+      auto str = lex.ParseUtf8();
+      RETURN_IF_ERROR(str.status());
+      Traits::SetString(field, msg, std::move(str->value.ToString()));
+      break;
+    }
+    case JsonLexer::kFalse:
+    case JsonLexer::kTrue: {
+      auto field = Traits::MustHaveField(desc, 4);
+      auto pop =
+          lex.path().Push(Traits::FieldName(field), Traits::FieldType(field),
+                          Traits::FieldTypeName(field));
+
+      // "Quoted" bools, including non-standard Abseil Atob bools, are not
+      // supported, because all strings are treated as genuine JSON strings.
+      if (*kind == JsonLexer::kTrue) {
+        RETURN_IF_ERROR(lex.Expect("true"));
+        Traits::SetBool(field, msg, true);
+      } else {
+        RETURN_IF_ERROR(lex.Expect("false"));
+        Traits::SetBool(field, msg, false);
+      }
+      break;
+    }
+    case JsonLexer::kObj: {
+      auto field = Traits::MustHaveField(desc, 5);
+      auto pop =
+          lex.path().Push(Traits::FieldName(field), Traits::FieldType(field),
+                          Traits::FieldTypeName(field));
+
+      return Traits::NewMsg(field, msg, [&](auto& desc, auto& msg) {
+        return ParseStructValue<Traits>(lex, desc, msg);
+      });
+    }
+    case JsonLexer::kArr: {
+      auto field = Traits::MustHaveField(desc, 6);
+      auto pop =
+          lex.path().Push(Traits::FieldName(field), Traits::FieldType(field),
+                          Traits::FieldTypeName(field));
+
+      return Traits::NewMsg(field, msg, [&](auto& desc, auto& msg) {
+        return ParseListValue<Traits>(lex, desc, msg);
+      });
+    }
+  }
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status ParseStructValue(JsonLexer& lex, const Desc<Traits>& desc,
+                              Msg<Traits>& msg) {
+  auto entry_field = Traits::MustHaveField(desc, 1);
+  auto pop = lex.path().Push("<struct>", FieldDescriptor::TYPE_MESSAGE,
+                             Traits::FieldTypeName(entry_field));
+
+  // Structs are always cleared even if set to {}.
+  Traits::RecordAsSeen(entry_field, msg);
+
+  // Parsing a map does the right thing: Struct has a single map<string,
+  // Value> field; keys are correctly parsed as strings, and the values
+  // recurse into ParseMessage, which will be routed into ParseValue. This
+  // results in some extra overhead, but performance is not what we're going
+  // for here.
+  return ParseMap<Traits>(lex, entry_field, msg);
+}
+
+template <typename Traits>
+absl::Status ParseListValue(JsonLexer& lex, const Desc<Traits>& desc,
+                            Msg<Traits>& msg) {
+  auto entry_field = Traits::MustHaveField(desc, 1);
+  auto pop = lex.path().Push("<list>", FieldDescriptor::TYPE_MESSAGE,
+                             Traits::FieldTypeName(entry_field));
+
+  // ListValues are always cleared even if set to [].
+  Traits::RecordAsSeen(entry_field, msg);
+  // Parsing an array does the right thing: see the analogous comment in
+  // ParseStructValue.
+  return ParseArray<Traits>(lex, entry_field, msg);
+}
+
+template <typename Traits>
+absl::Status ParseField(JsonLexer& lex, const Desc<Traits>& desc,
+                        absl::string_view name, Msg<Traits>& msg) {
+  absl::optional<Field<Traits>> field;
+  if (absl::StartsWith(name, "[") && absl::EndsWith(name, "]")) {
+    absl::string_view extn_name = name.substr(1, name.size() - 2);
+    field = Traits::ExtensionByName(desc, extn_name);
+  } else {
+    field = Traits::FieldByName(desc, name);
+  }
+
+  if (!field.has_value()) {
+    if (!lex.options().ignore_unknown_fields) {
+      return lex.Invalid(absl::StrFormat("no such field: '%s'", name));
+    }
+    return lex.SkipValue();
+  }
+
+  auto pop = lex.path().Push(name, Traits::FieldType(*field),
+                             Traits::FieldTypeName(*field));
+
+  if (Traits::HasParsed(
+          *field, msg,
+          /*allow_repeated_non_oneof=*/lex.options().allow_legacy_syntax) &&
+      !lex.Peek(JsonLexer::kNull)) {
+    return lex.Invalid(absl::StrFormat(
+        "'%s' has already been set (either directly or as part of a oneof)",
+        name));
+  }
+
+  if (Traits::IsMap(*field)) {
+    return ParseMap<Traits>(lex, *field, msg);
+  }
+
+  if (Traits::IsRepeated(*field)) {
+    if (lex.options().allow_legacy_syntax && !lex.Peek(JsonLexer::kArr)) {
+      // The original ESF parser permits a single element in place of an array
+      // thereof.
+      return ParseSingular<Traits>(lex, *field, msg);
+    }
+    return ParseArray<Traits>(lex, *field, msg);
+  }
+
+  return ParseSingular<Traits>(lex, *field, msg);
+}
+
+template <typename Traits>
+absl::Status ParseMessage(JsonLexer& lex, const Desc<Traits>& desc,
+                          Msg<Traits>& msg, bool any_reparse) {
+  MessageType type = ClassifyMessage(Traits::TypeName(desc));
+  if (!any_reparse) {
+    switch (type) {
+      case MessageType::kAny:
+        return ParseAny<Traits>(lex, desc, msg);
+      case MessageType::kValue:
+        return ParseValue<Traits>(lex, desc, msg);
+      case MessageType::kStruct:
+        return ParseStructValue<Traits>(lex, desc, msg);
+      default:
+        break;
+    }
+    // For some types, the ESF parser permits parsing the "non-special" version.
+    // It is not clear if this counts as out-of-spec, but we're treating it as
+    // such.
+    bool is_upcoming_object = lex.Peek(JsonLexer::kObj);
+    if (!(is_upcoming_object && lex.options().allow_legacy_syntax)) {
+      switch (type) {
+        case MessageType::kList:
+          return ParseListValue<Traits>(lex, desc, msg);
+        case MessageType::kWrapper: {
+          return ParseSingular<Traits>(lex, Traits::MustHaveField(desc, 1),
+                                       msg);
+        }
+        case MessageType::kTimestamp:
+          return ParseTimestamp<Traits>(lex, desc, msg);
+        case MessageType::kDuration:
+          return ParseDuration<Traits>(lex, desc, msg);
+        case MessageType::kFieldMask:
+          return ParseFieldMask<Traits>(lex, desc, msg);
+        default:
+          break;
+      }
+    }
+  }
+
+  return lex.VisitObject(
+      [&](LocationWith<MaybeOwnedString>& name) -> absl::Status {
+        // If this is a well-known type, we expect its contents to be inside
+        // of a JSON field named "value".
+        if (any_reparse) {
+          if (name.value == "@type") {
+            RETURN_IF_ERROR(lex.SkipValue());
+            return absl::OkStatus();
+          }
+          if (type != MessageType::kNotWellKnown) {
+            if (name.value != "value") {
+              return lex.Invalid(
+                  "fields in a well-known-typed Any must be @type or value");
+            }
+            // Parse the upcoming value as the message itself. This is *not*
+            // an Any reparse because we do not expect to see @type in the
+            // upcoming value.
+            return ParseMessage<Traits>(lex, desc, msg,
+                                        /*any_reparse=*/false);
+          }
+        }
+
+        return ParseField<Traits>(lex, desc, name.value.AsView(), msg);
+      });
+}
+}  // namespace
+
+absl::Status JsonStringToMessage(absl::string_view input, Message* message,
+                                 json_internal::ParseOptions options) {
+  MessagePath path(message->GetDescriptor()->full_name());
+  PROTOBUF_DLOG(INFO) << "json2/input: " << absl::CHexEscape(input);
+  io::ArrayInputStream in(input.data(), input.size());
+  JsonLexer lex(&in, options, &path);
+
+  ParseProto2Descriptor::Msg msg(message);
+  absl::Status s =
+      ParseMessage<ParseProto2Descriptor>(lex, *message->GetDescriptor(), msg,
+                                          /*any_reparse=*/false);
+  if (s.ok() && !lex.AtEof()) {
+    s = absl::InvalidArgumentError(
+        "extraneous characters after end of JSON object");
+  }
+
+  PROTOBUF_DLOG(INFO) << "json2/status: " << s;
+  PROTOBUF_DLOG(INFO) << "json2/output: " << message->DebugString();
+
+  return s;
+}
+
+absl::Status JsonToBinaryStream(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* json_input,
+                                io::ZeroCopyOutputStream* binary_output,
+                                json_internal::ParseOptions options) {
+  // NOTE: Most of the contortions in this function are to allow for capture of
+  // input and output of the parser in GOOGLE_DLOG mode. Destruction order is very
+  // critical in this function, because io::ZeroCopy*Stream types usually only
+  // flush on destruction.
+
+  // For GOOGLE_DLOG, we would like to print out the input and output, which requires
+  // buffering both instead of doing "zero copy". This block, and the one at
+  // the end of the function, set up and tear down interception of the input
+  // and output streams.
+  std::string copy;
+  std::string out;
+  absl::optional<io::ArrayInputStream> tee_input;
+  absl::optional<io::StringOutputStream> tee_output;
+  if (PROTOBUF_DEBUG) {
+    const void* data;
+    int len;
+    while (json_input->Next(&data, &len)) {
+      copy.resize(copy.size() + len);
+      std::memcpy(&copy[copy.size() - len], data, len);
+    }
+    tee_input.emplace(copy.data(), copy.size());
+    tee_output.emplace(&out);
+  }
+
+  PROTOBUF_DLOG(INFO) << "json2/input: " << absl::CHexEscape(copy);
+
+  // This scope forces the CodedOutputStream inside of `msg` to flush before we
+  // possibly handle logging the binary protobuf output.
+  absl::Status s;
+  {
+    MessagePath path(type_url);
+    JsonLexer lex(tee_input.has_value() ? &*tee_input : json_input, options,
+                  &path);
+    Msg<ParseProto3Type> msg(tee_output.has_value() ? &*tee_output
+                                                    : binary_output);
+
+    ResolverPool pool(resolver);
+    auto desc = pool.FindMessage(type_url);
+    RETURN_IF_ERROR(desc.status());
+
+    s = ParseMessage<ParseProto3Type>(lex, **desc, msg, /*any_reparse=*/false);
+    if (s.ok() && !lex.AtEof()) {
+      s = absl::InvalidArgumentError(
+          "extraneous characters after end of JSON object");
+    }
+  }
+
+  if (PROTOBUF_DEBUG) {
+    tee_output.reset();  // Flush the output stream.
+    io::zc_sink_internal::ZeroCopyStreamByteSink(binary_output)
+        .Append(out.data(), out.size());
+  }
+
+  PROTOBUF_DLOG(INFO) << "json2/status: " << s;
+  PROTOBUF_DLOG(INFO) << "json2/output: " << absl::BytesToHexString(out);
+  return s;
+}
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/json/internal/parser.h
similarity index 61%
copy from src/google/protobuf/util/internal/location_tracker.h
copy to src/google/protobuf/json/internal/parser.h
index 68fefcc..79ba29a 100644
--- a/src/google/protobuf/util/internal/location_tracker.h
+++ b/src/google/protobuf/json/internal/parser.h
@@ -28,43 +28,32 @@
 // (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_UTIL_INTERNAL_LOCATION_TRACKER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__
+#ifndef GOOGLE_PROTOBUF_JSON_INTERNAL_PARSER_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_PARSER_H__
 
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/message.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/json/internal/lexer.h"
+#include "google/protobuf/util/type_resolver.h"
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace converter {
-
-// LocationTrackerInterface is an interface for classes that track
-// the location information for the purpose of error reporting.
-class PROTOBUF_EXPORT LocationTrackerInterface {
- public:
-  virtual ~LocationTrackerInterface() {}
-
-  // Returns the object location as human readable string.
-  virtual std::string ToString() const = 0;
-
- protected:
-  LocationTrackerInterface() {}
-
- private:
-  // Please do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface);
-};
-
-}  // namespace converter
-}  // namespace util
+namespace json_internal {
+// Internal version of google::protobuf::util::JsonStringToMessage; see json_util.h for
+// details.
+absl::Status JsonStringToMessage(absl::string_view input, Message* message,
+                                 json_internal::ParseOptions options);
+// Internal version of google::protobuf::util::JsonToBinaryStream; see json_util.h for
+// details.
+absl::Status JsonToBinaryStream(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* json_input,
+                                io::ZeroCopyOutputStream* binary_output,
+                                json_internal::ParseOptions options);
+}  // namespace json_internal
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_PARSER_H__
diff --git a/src/google/protobuf/json/internal/parser_traits.h b/src/google/protobuf/json/internal/parser_traits.h
new file mode 100644
index 0000000..cfe74a2
--- /dev/null
+++ b/src/google/protobuf/json/internal/parser_traits.h
@@ -0,0 +1,425 @@
+// 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_JSON_INTERNAL_PARSER_TRAITS_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_PARSER_TRAITS_H__
+
+#include <cfloat>
+#include <cmath>
+#include <cstdint>
+#include <limits>
+#include <string>
+#include <utility>
+
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "absl/base/attributes.h"
+#include "absl/base/casts.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/json/internal/descriptor_traits.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+using ::google::protobuf::internal::WireFormatLite;
+
+// See the comment in json_util2_parser.cc for more information.
+//
+// The type traits in this file  describe how to parse to a protobuf
+// representation used by the JSON API, either via proto reflection or by
+// emitting wire format to an output stream.
+
+// Helper alias templates to avoid needing to write `typename` in function
+// signatures.
+template <typename Traits>
+using Msg = typename Traits::Msg;
+
+struct ParseProto2Descriptor : Proto2Descriptor {
+  // A message value that fields can be written to, but not read from.
+  class Msg {
+   public:
+    explicit Msg(Message* msg) : msg_(msg) {}
+
+   private:
+    friend ParseProto2Descriptor;
+    Message* msg_;
+    // Because `msg` might already have oneofs set, we need to track which were
+    // set *during* the parse separately.
+    absl::flat_hash_set<int> parsed_oneofs_indices_;
+    absl::flat_hash_set<int> parsed_fields_;
+  };
+
+  static bool HasParsed(Field f, const Msg& msg,
+                        bool allow_repeated_non_oneof) {
+    if (f->real_containing_oneof()) {
+      return msg.parsed_oneofs_indices_.contains(
+          f->real_containing_oneof()->index());
+    }
+    if (allow_repeated_non_oneof) {
+      return false;
+    }
+    return msg.parsed_fields_.contains(f->number());
+  }
+
+  /// Functions for writing fields. ///
+
+  // Marks a field as having been "seen". This will clear the field if it is
+  // the first occurrence thereof.
+  //
+  // All setters call this function automatically, but it may also be called
+  // eagerly to clear a pre-existing value that might not be overwritten, such
+  // as when parsing a repeated field.
+  static void RecordAsSeen(Field f, Msg& msg) {
+    bool inserted = msg.parsed_fields_.insert(f->number()).second;
+    if (inserted) {
+      msg.msg_->GetReflection()->ClearField(msg.msg_, f);
+    }
+
+    if (f->real_containing_oneof() != nullptr) {
+      msg.parsed_oneofs_indices_.insert(f->real_containing_oneof()->index());
+    }
+  }
+
+  // Adds a new message and calls body on it.
+  //
+  // Body should have a signature `absl::Status(const Desc&, Msg&)`.
+  template <typename F>
+  static absl::Status NewMsg(Field f, Msg& msg, F body) {
+    RecordAsSeen(f, msg);
+
+    Message* new_msg;
+    if (f->is_repeated()) {
+      new_msg = msg.msg_->GetReflection()->AddMessage(msg.msg_, f);
+    } else {
+      new_msg = msg.msg_->GetReflection()->MutableMessage(msg.msg_, f);
+    }
+    Msg wrapper(new_msg);
+    return body(*f->message_type(), wrapper);
+  }
+
+  // Adds a new dynamic message with the given type name and calls body on it.
+  //
+  // Body should have a signature `absl::Status(const Desc&, Msg&)`.
+  template <typename F>
+  static absl::Status NewDynamic(Field f, const std::string& type_url, Msg& msg,
+                                 F body) {
+    RecordAsSeen(f, msg);
+    return WithDynamicType(
+        *f->containing_type(), type_url, [&](const Desc& desc) -> absl::Status {
+          DynamicMessageFactory factory;
+          std::unique_ptr<Message> dynamic(factory.GetPrototype(&desc)->New());
+          Msg wrapper(dynamic.get());
+          RETURN_IF_ERROR(body(desc, wrapper));
+
+          if (f->is_repeated()) {
+            msg.msg_->GetReflection()->AddString(msg.msg_, f,
+                                                 dynamic->SerializeAsString());
+          } else {
+            msg.msg_->GetReflection()->SetString(msg.msg_, f,
+                                                 dynamic->SerializeAsString());
+          }
+          return absl::OkStatus();
+        });
+  }
+
+  static void SetFloat(Field f, Msg& msg, float x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddFloat(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetFloat(msg.msg_, f, x);
+    }
+  }
+
+  static void SetDouble(Field f, Msg& msg, double x) {
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddDouble(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetDouble(msg.msg_, f, x);
+    }
+  }
+
+  static void SetInt64(Field f, Msg& msg, int64_t x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddInt64(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetInt64(msg.msg_, f, x);
+    }
+  }
+
+  static void SetUInt64(Field f, Msg& msg, uint64_t x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddUInt64(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetUInt64(msg.msg_, f, x);
+    }
+  }
+
+  static void SetInt32(Field f, Msg& msg, int32 x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddInt32(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetInt32(msg.msg_, f, x);
+    }
+  }
+
+  static void SetUInt32(Field f, Msg& msg, uint32 x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddUInt32(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetUInt32(msg.msg_, f, x);
+    }
+  }
+
+  static void SetBool(Field f, Msg& msg, bool x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddBool(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetBool(msg.msg_, f, x);
+    }
+  }
+
+  static void SetString(Field f, Msg& msg, absl::string_view x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddString(msg.msg_, f, std::string(x));
+    } else {
+      msg.msg_->GetReflection()->SetString(msg.msg_, f, std::string(x));
+    }
+  }
+
+  static void SetEnum(Field f, Msg& msg, int32_t x) {
+    RecordAsSeen(f, msg);
+    if (f->is_repeated()) {
+      msg.msg_->GetReflection()->AddEnumValue(msg.msg_, f, x);
+    } else {
+      msg.msg_->GetReflection()->SetEnumValue(msg.msg_, f, x);
+    }
+  }
+};
+
+// Traits for proto3-ish deserialization.
+//
+// This includes a rudimentary proto serializer, since message fields are
+// written directly instead of being reflectively written to a proto field.
+//
+// See MessageTraits for API docs.
+struct ParseProto3Type : Proto3Type {
+  class Msg {
+   public:
+    explicit Msg(io::ZeroCopyOutputStream* stream) : stream_(stream) {}
+
+   private:
+    friend ParseProto3Type;
+    io::CodedOutputStream stream_;
+    absl::flat_hash_set<int32_t> parsed_oneofs_indices_;
+    absl::flat_hash_set<int32_t> parsed_fields_;
+  };
+
+  static bool HasParsed(Field f, const Msg& msg,
+                        bool allow_repeated_non_oneof) {
+    if (f->proto().oneof_index() != 0) {
+      return msg.parsed_oneofs_indices_.contains(f->proto().oneof_index());
+    }
+    if (allow_repeated_non_oneof) {
+      return false;
+    }
+    return msg.parsed_fields_.contains(f->proto().number());
+  }
+
+  /// Functions for writing fields. ///
+
+  static void RecordAsSeen(Field f, Msg& msg) {
+    msg.parsed_fields_.insert(f->proto().number());
+    if (f->proto().oneof_index() != 0) {
+      msg.parsed_oneofs_indices_.insert(f->proto().oneof_index());
+    }
+  }
+
+  template <typename F>
+  static absl::Status NewMsg(Field f, Msg& msg, F body) {
+    return NewDynamic(f, f->proto().type_url(), msg, body);
+  }
+
+  template <typename F>
+  static absl::Status NewDynamic(Field f, const std::string& type_url, Msg& msg,
+                                 F body) {
+    RecordAsSeen(f, msg);
+    return WithDynamicType(
+        f->parent(), type_url, [&](const Desc& desc) -> absl::Status {
+          if (f->proto().kind() == google::protobuf::Field::TYPE_GROUP) {
+            msg.stream_.WriteTag(f->proto().number() << 3 |
+                                 WireFormatLite::WIRETYPE_START_GROUP);
+            RETURN_IF_ERROR(body(desc, msg));
+            msg.stream_.WriteTag(f->proto().number() << 3 |
+                                 WireFormatLite::WIRETYPE_END_GROUP);
+            return absl::OkStatus();
+          }
+
+          std::string out;
+          io::StringOutputStream stream(&out);
+          Msg new_msg(&stream);
+          RETURN_IF_ERROR(body(desc, new_msg));
+
+          new_msg.stream_.Trim();  // Should probably be called "Flush()".
+          absl::string_view written(
+              out.data(), static_cast<size_t>(new_msg.stream_.ByteCount()));
+          SetString(f, msg, written);
+          return absl::OkStatus();
+        });
+  }
+
+  static void SetFloat(Field f, Msg& msg, float x) {
+    RecordAsSeen(f, msg);
+    msg.stream_.WriteTag(f->proto().number() << 3 |
+                         WireFormatLite::WIRETYPE_FIXED32);
+    msg.stream_.WriteLittleEndian32(absl::bit_cast<uint32_t>(x));
+  }
+
+  static void SetDouble(Field f, Msg& msg, double x) {
+    RecordAsSeen(f, msg);
+    msg.stream_.WriteTag(f->proto().number() << 3 |
+                         WireFormatLite::WIRETYPE_FIXED64);
+    msg.stream_.WriteLittleEndian64(absl::bit_cast<uint64_t>(x));
+  }
+
+  static void SetInt64(Field f, Msg& msg, int64_t x) {
+    SetInt<int64_t, google::protobuf::Field::TYPE_INT64,
+           google::protobuf::Field::TYPE_SFIXED64,
+           google::protobuf::Field::TYPE_SINT64>(f, msg, x);
+  }
+
+  static void SetUInt64(Field f, Msg& msg, uint64_t x) {
+    SetInt<uint64_t, google::protobuf::Field::TYPE_UINT64,
+           google::protobuf::Field::TYPE_FIXED64,
+           google::protobuf::Field::TYPE_UNKNOWN>(f, msg, x);
+  }
+
+  static void SetInt32(Field f, Msg& msg, int32_t x) {
+    SetInt<int32_t, google::protobuf::Field::TYPE_INT32,
+           google::protobuf::Field::TYPE_SFIXED32,
+           google::protobuf::Field::TYPE_SINT32>(f, msg, x);
+  }
+
+  static void SetUInt32(Field f, Msg& msg, uint32_t x) {
+    SetInt<uint32_t, google::protobuf::Field::TYPE_UINT32,
+           google::protobuf::Field::TYPE_FIXED32,
+           google::protobuf::Field::TYPE_UNKNOWN>(f, msg, x);
+  }
+
+  static void SetBool(Field f, Msg& msg, bool x) {
+    RecordAsSeen(f, msg);
+    msg.stream_.WriteTag(f->proto().number() << 3);
+    char b = x ? 0x01 : 0x00;
+    msg.stream_.WriteRaw(&b, 1);
+  }
+
+  static void SetString(Field f, Msg& msg, absl::string_view x) {
+    RecordAsSeen(f, msg);
+    msg.stream_.WriteTag(f->proto().number() << 3 |
+                         WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
+    msg.stream_.WriteVarint64(static_cast<uint64_t>(x.size()));
+    msg.stream_.WriteRaw(x.data(), x.size());
+  }
+
+  static void SetEnum(Field f, Msg& msg, int32_t x) {
+    RecordAsSeen(f, msg);
+    msg.stream_.WriteTag(f->proto().number() << 3);
+    // Sign extension is deliberate here.
+    msg.stream_.WriteVarint32(x);
+  }
+
+ private:
+  using Kind = google::protobuf::Field::Kind;
+  // Sets a field of *some* integer type, with the given kinds for the possible
+  // encodings. This avoids quadruplicating this code in the helpers for the
+  // four major integer types.
+  template <typename Int, Kind varint, Kind fixed, Kind zigzag>
+  static void SetInt(Field f, Msg& msg, Int x) {
+    RecordAsSeen(f, msg);
+    switch (f->proto().kind()) {
+      case zigzag:
+        // Regardless of the integer type, ZigZag64 will do the right thing,
+        // because ZigZag is not dependent on the width of the integer: it is
+        // always `2 * abs(n) + (n < 0)`.
+        x = static_cast<Int>(
+            internal::WireFormatLite::ZigZagEncode64(static_cast<int64_t>(x)));
+        ABSL_FALLTHROUGH_INTENDED;
+      case varint:
+        msg.stream_.WriteTag(f->proto().number() << 3 |
+                             WireFormatLite::WIRETYPE_VARINT);
+        if (sizeof(Int) == 4) {
+          msg.stream_.WriteVarint32(static_cast<uint32_t>(x));
+        } else {
+          msg.stream_.WriteVarint64(static_cast<uint64_t>(x));
+        }
+        break;
+      case fixed: {
+        if (sizeof(Int) == 4) {
+          msg.stream_.WriteTag(f->proto().number() << 3 |
+                               WireFormatLite::WIRETYPE_FIXED32);
+          msg.stream_.WriteLittleEndian32(static_cast<uint32_t>(x));
+        } else {
+          msg.stream_.WriteTag(f->proto().number() << 3 |
+                               WireFormatLite::WIRETYPE_FIXED64);
+          msg.stream_.WriteLittleEndian64(static_cast<uint64_t>(x));
+        }
+        break;
+      }
+      default: {  // Unreachable.
+      }
+    }
+  }
+};
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_PARSER_TRAITS_H__
diff --git a/src/google/protobuf/json/internal/test_input_stream.h b/src/google/protobuf/json/internal/test_input_stream.h
new file mode 100644
index 0000000..1a05c9b
--- /dev/null
+++ b/src/google/protobuf/json/internal/test_input_stream.h
@@ -0,0 +1,106 @@
+// 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_UTIL_TEST_INPUT_STREAM_H__
+#define GOOGLE_PROTOBUF_UTIL_TEST_INPUT_STREAM_H__
+
+#include <initializer_list>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+// A ZeroCopyInputStream for writing unit tests.
+class TestInputStream final : public io::ZeroCopyInputStream {
+ public:
+  TestInputStream(std::initializer_list<std::string> strings)
+      : strings_(strings) {}
+  explicit TestInputStream(std::vector<std::string> strings)
+      : strings_(std::move(strings)) {}
+  ~TestInputStream() override = default;
+
+  size_t Consumed() const { return next_; }
+
+  bool Next(const void** data, int* size) override {
+    if (next_ == strings_.size()) {
+      return false;
+    }
+
+    if (next_ > 0) {
+      // Destroy the previous string so that ASAN can catch misbehavior
+      // correctly.
+      ReconstructAt(&strings_[next_ - 1]);
+    }
+
+    absl::string_view next = strings_[next_++];
+    *data = next.data();
+    *size = static_cast<int>(next.size());
+    return true;
+  }
+
+  // TestInputStream currently does not support these members.
+  void BackUp(int) override { GOOGLE_CHECK(false); }
+  bool Skip(int) override {
+    GOOGLE_CHECK(false);
+    return false;
+  }
+  int64_t ByteCount() const override {
+    GOOGLE_CHECK(false);
+    return 0;
+  }
+
+ private:
+  // Some versions of Clang can't figure out that
+  //   x.std::string::~string()
+  // is valid syntax, so we indirect through a type param, instead.
+  //
+  // Of course, our luck has it that std::destroy_at is a C++17 feature. :)
+  template <typename T>
+  static void ReconstructAt(T* p) {
+    p->~T();
+    new (p) T;
+  }
+
+  std::vector<std::string> strings_;
+  size_t next_ = 0;
+};
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#endif  // GOOGLE_PROTOBUF_UTIL_TEST_INPUT_STREAM_H__
diff --git a/src/google/protobuf/json/internal/unparser.cc b/src/google/protobuf/json/internal/unparser.cc
new file mode 100644
index 0000000..6b83019
--- /dev/null
+++ b/src/google/protobuf/json/internal/unparser.cc
@@ -0,0 +1,880 @@
+// 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/json/internal/unparser.h"
+
+#include <cfloat>
+#include <complex>
+#include <cstdint>
+#include <cstring>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <utility>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "absl/status/status.h"
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/json/internal/descriptor_traits.h"
+#include "google/protobuf/json/internal/unparser_traits.h"
+#include "google/protobuf/json/internal/writer.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+namespace {
+template <typename Traits>
+bool IsEmpty(const Msg<Traits>& msg, const Desc<Traits>& desc) {
+  size_t count = Traits::FieldCount(desc);
+  for (size_t i = 0; i < count; ++i) {
+    if (Traits::GetSize(Traits::FieldByIndex(desc, i), msg) > 0) {
+      return false;
+    }
+  }
+  return true;
+}
+
+enum class IntegerEnumStyle {
+  kQuoted,
+  kUnquoted,
+};
+
+template <typename Traits>
+void WriteEnum(JsonWriter& writer, Field<Traits> field, int32_t value,
+               IntegerEnumStyle int_style = IntegerEnumStyle::kUnquoted) {
+  if (ClassifyMessage(Traits::FieldTypeName(field)) == MessageType::kNull) {
+    writer.Write("null");
+    return;
+  }
+
+  if (!writer.options().always_print_enums_as_ints) {
+    auto name = Traits::EnumNameByNumber(field, value);
+    if (name.ok()) {
+      writer.Write("\"", *name, "\"");
+      return;
+    }
+  }
+
+  if (int_style == IntegerEnumStyle::kQuoted) {
+    writer.Write("\"", value, "\"");
+  } else {
+    writer.Write(value);
+  }
+}
+
+// Mutually recursive with functions that follow.
+template <typename Traits>
+absl::Status WriteMessage(JsonWriter& writer, const Msg<Traits>& msg,
+                          const Desc<Traits>& desc, bool is_top_level = false);
+
+// This is templatized so that defaults, singular, and repeated fields can both
+// use the same enormous switch-case.
+template <typename Traits, typename... Args>
+absl::Status WriteSingular(JsonWriter& writer, Field<Traits> field,
+                           Args&&... args) {
+  // When the pack `args` is empty, the caller has requested printing the
+  // default value.
+  bool is_default = sizeof...(Args) == 0;
+  switch (Traits::FieldType(field)) {
+    case FieldDescriptor::TYPE_FLOAT: {
+      auto x = Traits::GetFloat(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      if (writer.options().allow_legacy_syntax && is_default &&
+          !std::isfinite(*x)) {
+        *x = 0;
+      }
+      writer.Write(*x);
+      break;
+    }
+    case FieldDescriptor::TYPE_DOUBLE: {
+      auto x = Traits::GetDouble(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      if (writer.options().allow_legacy_syntax && is_default &&
+          !std::isfinite(*x)) {
+        *x = 0;
+      }
+      writer.Write(*x);
+      break;
+    }
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_INT64: {
+      auto x = Traits::GetInt64(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_UINT64: {
+      auto x = Traits::GetUInt64(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_INT32: {
+      auto x = Traits::GetInt32(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(*x);
+      break;
+    }
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_UINT32: {
+      auto x = Traits::GetUInt32(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(*x);
+      break;
+    }
+    case FieldDescriptor::TYPE_BOOL: {
+      auto x = Traits::GetBool(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(*x ? "true" : "false");
+      break;
+    }
+    case FieldDescriptor::TYPE_STRING: {
+      auto x = Traits::GetString(field, writer.ScratchBuf(),
+                                 std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_BYTES: {
+      auto x = Traits::GetString(field, writer.ScratchBuf(),
+                                 std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      if (writer.options().allow_legacy_syntax && is_default) {
+        // Although difficult to verify, it appears that the original ESF parser
+        // fails to unescape the contents of a
+        // google.protobuf.Field.default_value, which may potentially be
+        // escaped if it is for a `bytes` field (note that default_value is a
+        // `string` regardless of what type the field is).
+        //
+        // However, our parser's type.proto guts actually know to do this
+        // correctly, so this bug must be manually re-introduced.
+        writer.WriteBase64(absl::CEscape(*x));
+      } else {
+        writer.WriteBase64(*x);
+      }
+      break;
+    }
+    case FieldDescriptor::TYPE_ENUM: {
+      auto x = Traits::GetEnumValue(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      WriteEnum<Traits>(writer, field, *x);
+      break;
+    }
+    case FieldDescriptor::TYPE_MESSAGE:
+    case FieldDescriptor::TYPE_GROUP: {
+      auto x = Traits::GetMessage(field, std::forward<Args>(args)...);
+      RETURN_IF_ERROR(x.status());
+      return WriteMessage<Traits>(writer, **x, Traits::GetDesc(**x));
+    }
+    default:
+      return absl::InvalidArgumentError(
+          absl::StrCat("unsupported field type: ", Traits::FieldType(field)));
+  }
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteRepeated(JsonWriter& writer, const Msg<Traits>& msg,
+                           Field<Traits> field) {
+  writer.Write("[");
+  writer.Push();
+
+  size_t count = Traits::GetSize(field, msg);
+  bool first = true;
+  for (size_t i = 0; i < count; ++i) {
+    if (ClassifyMessage(Traits::FieldTypeName(field)) == MessageType::kValue) {
+      bool empty = false;
+      RETURN_IF_ERROR(Traits::WithFieldType(
+          field, [&](const Desc<Traits>& desc) -> absl::Status {
+            auto inner = Traits::GetMessage(field, msg, i);
+            RETURN_IF_ERROR(inner.status());
+            empty = IsEmpty<Traits>(**inner, desc);
+            return absl::OkStatus();
+          }));
+
+      // Empty google.protobuf.Values are silently discarded.
+      if (empty) {
+        continue;
+      }
+    }
+    writer.WriteComma(first);
+    writer.NewLine();
+    RETURN_IF_ERROR(WriteSingular<Traits>(writer, field, msg, i));
+  }
+
+  writer.Pop();
+  if (!first) {
+    writer.NewLine();
+  }
+  writer.Write("]");
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteMapKey(JsonWriter& writer, const Msg<Traits>& entry,
+                         Field<Traits> field) {
+  switch (Traits::FieldType(field)) {
+    case FieldDescriptor::TYPE_SFIXED64:
+    case FieldDescriptor::TYPE_SINT64:
+    case FieldDescriptor::TYPE_INT64: {
+      auto x = Traits::GetInt64(field, entry);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_FIXED64:
+    case FieldDescriptor::TYPE_UINT64: {
+      auto x = Traits::GetUInt64(field, entry);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_SFIXED32:
+    case FieldDescriptor::TYPE_SINT32:
+    case FieldDescriptor::TYPE_INT32: {
+      auto x = Traits::GetInt32(field, entry);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_FIXED32:
+    case FieldDescriptor::TYPE_UINT32: {
+      auto x = Traits::GetUInt32(field, entry);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_BOOL: {
+      auto x = Traits::GetBool(field, entry);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x ? "true" : "false"));
+      break;
+    }
+    case FieldDescriptor::TYPE_STRING: {
+      auto x = Traits::GetString(field, writer.ScratchBuf(), entry);
+      RETURN_IF_ERROR(x.status());
+      writer.Write(MakeQuoted(*x));
+      break;
+    }
+    case FieldDescriptor::TYPE_ENUM: {
+      auto x = Traits::GetEnumValue(field, entry);
+      RETURN_IF_ERROR(x.status());
+      WriteEnum<Traits>(writer, field, *x, IntegerEnumStyle::kQuoted);
+      break;
+    }
+    default:
+      return absl::InvalidArgumentError(
+          absl::StrCat("unsupported map key type: ", Traits::FieldType(field)));
+  }
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::StatusOr<bool> IsEmptyValue(const Msg<Traits>& msg, Field<Traits> field) {
+  if (ClassifyMessage(Traits::FieldTypeName(field)) != MessageType::kValue) {
+    return false;
+  }
+  bool empty = false;
+  RETURN_IF_ERROR(Traits::WithFieldType(
+      field, [&](const Desc<Traits>& desc) -> absl::Status {
+        auto inner = Traits::GetMessage(field, msg);
+        RETURN_IF_ERROR(inner.status());
+        empty = IsEmpty<Traits>(**inner, desc);
+        return absl::OkStatus();
+      }));
+  return empty;
+}
+
+template <typename Traits>
+absl::Status WriteMap(JsonWriter& writer, const Msg<Traits>& msg,
+                      Field<Traits> field) {
+  writer.Write("{");
+  writer.Push();
+
+  size_t count = Traits::GetSize(field, msg);
+  bool first = true;
+  for (size_t i = 0; i < count; ++i) {
+    absl::StatusOr<const Msg<Traits>*> entry =
+        Traits::GetMessage(field, msg, i);
+    RETURN_IF_ERROR(entry.status());
+    const Desc<Traits>& type = Traits::GetDesc(**entry);
+
+    auto is_empty = IsEmptyValue<Traits>(**entry, Traits::ValueField(type));
+    RETURN_IF_ERROR(is_empty.status());
+    if (*is_empty) {
+      // Empty google.protobuf.Values are silently discarded.
+      continue;
+    }
+
+    writer.WriteComma(first);
+    writer.NewLine();
+    RETURN_IF_ERROR(
+        WriteMapKey<Traits>(writer, **entry, Traits::KeyField(type)));
+    writer.Write(":");
+    writer.Whitespace(" ");
+    RETURN_IF_ERROR(
+        WriteSingular<Traits>(writer, Traits::ValueField(type), **entry));
+  }
+
+  writer.Pop();
+  if (!first) {
+    writer.NewLine();
+  }
+  writer.Write("}");
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteField(JsonWriter& writer, const Msg<Traits>& msg,
+                        Field<Traits> field, bool& first) {
+  if (!Traits::IsRepeated(field)) {  // Repeated case is handled in
+                                     // WriteRepeated.
+    auto is_empty = IsEmptyValue<Traits>(msg, field);
+    RETURN_IF_ERROR(is_empty.status());
+    if (*is_empty) {
+      // Empty google.protobuf.Values are silently discarded.
+      return absl::OkStatus();
+    }
+  }
+
+  writer.WriteComma(first);
+  writer.NewLine();
+
+  if (Traits::IsExtension(field)) {
+    writer.Write(MakeQuoted("[", Traits::FieldFullName(field), "]"), ":");
+  } else if (writer.options().preserve_proto_field_names) {
+    writer.Write(MakeQuoted(Traits::FieldName(field)), ":");
+  } else {
+    // The generator for type.proto and the internals of descriptor.cc disagree
+    // on what the json name of a PascalCase field is supposed to be; type.proto
+    // seems to (incorrectly?) capitalize the first letter, which is the
+    // behavior ESF defaults to. To fix this, if the original field name starts
+    // with an uppercase letter, and the Json name does not, we uppercase it.
+    absl::string_view original_name = Traits::FieldName(field);
+    absl::string_view json_name = Traits::FieldJsonName(field);
+    if (writer.options().allow_legacy_syntax &&
+        absl::ascii_isupper(original_name[0]) &&
+        !absl::ascii_isupper(json_name[0])) {
+      writer.Write(MakeQuoted(absl::ascii_toupper(original_name[0]),
+                              original_name.substr(1)),
+                   ":");
+    } else {
+      writer.Write(MakeQuoted(json_name), ":");
+    }
+  }
+  writer.Whitespace(" ");
+
+  if (Traits::IsMap(field)) {
+    return WriteMap<Traits>(writer, msg, field);
+  } else if (Traits::IsRepeated(field)) {
+    return WriteRepeated<Traits>(writer, msg, field);
+  } else if (Traits::GetSize(field, msg) == 0) {
+    // We can only get here if always_print_primitive_fields is true.
+    GOOGLE_DCHECK(writer.options().always_print_primitive_fields);
+
+    if (Traits::FieldType(field) == FieldDescriptor::TYPE_GROUP) {
+      // We do not yet have full group support, but this is required so that we
+      // pass the same tests as the ESF parser.
+      writer.Write("null");
+      return absl::OkStatus();
+    }
+    return WriteSingular<Traits>(writer, field);
+  }
+
+  return WriteSingular<Traits>(writer, field, msg);
+}
+
+template <typename Traits>
+absl::Status WriteFields(JsonWriter& writer, const Msg<Traits>& msg,
+                         const Desc<Traits>& desc, bool& first) {
+  std::vector<Field<Traits>> fields;
+  size_t total = Traits::FieldCount(desc);
+  fields.reserve(total);
+  for (size_t i = 0; i < total; ++i) {
+    Field<Traits> field = Traits::FieldByIndex(desc, i);
+
+    bool has = Traits::GetSize(field, msg) > 0;
+    if (writer.options().always_print_primitive_fields) {
+      bool is_singular_message =
+          !Traits::IsRepeated(field) &&
+          Traits::FieldType(field) == FieldDescriptor::TYPE_MESSAGE;
+      has |= !is_singular_message && !Traits::IsOneof(field);
+    }
+
+    if (has) {
+      fields.push_back(field);
+    }
+  }
+
+  // Add extensions *before* sorting.
+  Traits::FindAndAppendExtensions(msg, fields);
+
+  // Fields are guaranteed to be serialized in field number order.
+  absl::c_sort(fields, [](const auto& a, const auto& b) {
+    return Traits::FieldNumber(a) < Traits::FieldNumber(b);
+  });
+
+  for (auto field : fields) {
+    RETURN_IF_ERROR(WriteField<Traits>(writer, msg, field, first));
+  }
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteStructValue(JsonWriter& writer, const Msg<Traits>& msg,
+                              const Desc<Traits>& desc);
+template <typename Traits>
+absl::Status WriteListValue(JsonWriter& writer, const Msg<Traits>& msg,
+                            const Desc<Traits>& desc);
+
+template <typename Traits>
+absl::Status WriteValue(JsonWriter& writer, const Msg<Traits>& msg,
+                        const Desc<Traits>& desc, bool is_top_level) {
+  // NOTE: The field numbers 1 through 6 are the numbers of the oneof fields in
+  // google.protobuf.Value. Conformance tests verify the correctness of these
+  // numbers.
+  if (Traits::GetSize(Traits::MustHaveField(desc, 1), msg) > 0) {
+    writer.Write("null");
+    return absl::OkStatus();
+  }
+
+  auto number_field = Traits::MustHaveField(desc, 2);
+  if (Traits::GetSize(number_field, msg) > 0) {
+    auto x = Traits::GetDouble(number_field, msg);
+    RETURN_IF_ERROR(x.status());
+    writer.Write(*x);
+    return absl::OkStatus();
+  }
+
+  auto string_field = Traits::MustHaveField(desc, 3);
+  if (Traits::GetSize(string_field, msg) > 0) {
+    auto x = Traits::GetString(string_field, writer.ScratchBuf(), msg);
+    RETURN_IF_ERROR(x.status());
+    writer.Write(MakeQuoted(*x));
+    return absl::OkStatus();
+  }
+
+  auto bool_field = Traits::MustHaveField(desc, 4);
+  if (Traits::GetSize(bool_field, msg) > 0) {
+    auto x = Traits::GetBool(bool_field, msg);
+    RETURN_IF_ERROR(x.status());
+    writer.Write(*x ? "true" : "false");
+    return absl::OkStatus();
+  }
+
+  auto struct_field = Traits::MustHaveField(desc, 5);
+  if (Traits::GetSize(struct_field, msg) > 0) {
+    auto x = Traits::GetMessage(struct_field, msg);
+    RETURN_IF_ERROR(x.status());
+    return Traits::WithFieldType(struct_field, [&](const Desc<Traits>& type) {
+      return WriteStructValue<Traits>(writer, **x, type);
+    });
+  }
+
+  auto list_field = Traits::MustHaveField(desc, 6);
+  if (Traits::GetSize(list_field, msg) > 0) {
+    auto x = Traits::GetMessage(list_field, msg);
+    RETURN_IF_ERROR(x.status());
+    return Traits::WithFieldType(list_field, [&](const Desc<Traits>& type) {
+      return WriteListValue<Traits>(writer, **x, type);
+    });
+  }
+
+  GOOGLE_CHECK(is_top_level) << "empty, non-top-level Value must be handled one layer "
+                         "up, since it prints an empty string; reaching this "
+                         "statement is always a bug";
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteStructValue(JsonWriter& writer, const Msg<Traits>& msg,
+                              const Desc<Traits>& desc) {
+  return WriteMap<Traits>(writer, msg, Traits::MustHaveField(desc, 1));
+}
+
+template <typename Traits>
+absl::Status WriteListValue(JsonWriter& writer, const Msg<Traits>& msg,
+                            const Desc<Traits>& desc) {
+  return WriteRepeated<Traits>(writer, msg, Traits::MustHaveField(desc, 1));
+}
+
+template <typename Traits>
+absl::Status WriteTimestamp(JsonWriter& writer, const Msg<Traits>& msg,
+                            const Desc<Traits>& desc) {
+  auto secs_field = Traits::MustHaveField(desc, 1);
+  auto secs = Traits::GetSize(secs_field, msg) > 0
+                  ? Traits::GetInt64(secs_field, msg)
+                  : 0;
+  RETURN_IF_ERROR(secs.status());
+
+  if (*secs < -62135596800) {
+    return absl::InvalidArgumentError(
+        "minimum acceptable time value is 0001-01-01T00:00:00Z");
+  } else if (*secs > 253402300799) {
+    return absl::InvalidArgumentError(
+        "maximum acceptable time value is 9999-12-31T23:59:59Z");
+  }
+
+  // Ensure seconds is positive.
+  *secs += 62135596800;
+
+  auto nanos_field = Traits::MustHaveField(desc, 2);
+  auto nanos = Traits::GetSize(nanos_field, msg) > 0
+                   ? Traits::GetInt32(nanos_field, msg)
+                   : 0;
+  RETURN_IF_ERROR(nanos.status());
+
+  // 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.
+  int32_t L, N, I, J, K;
+  L = static_cast<int32_t>(*secs / 86400) - 719162 + 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;
+
+  int32_t sec = *secs % 60;
+  int32_t min = (*secs / 60) % 60;
+  int32_t hour = (*secs / 3600) % 24;
+
+  if (*nanos == 0) {
+    writer.Write(absl::StrFormat(R"("%04d-%02d-%02dT%02d:%02d:%02dZ")", I, J, K,
+                                 hour, min, sec));
+    return absl::OkStatus();
+  }
+
+  size_t digits = 9;
+  uint32_t frac_seconds = std::abs(*nanos);
+  while (frac_seconds % 1000 == 0) {
+    frac_seconds /= 1000;
+    digits -= 3;
+  }
+
+  writer.Write(absl::StrFormat(R"("%04d-%02d-%02dT%02d:%02d:%02d.%.*dZ")", I, J,
+                               K, hour, min, sec, digits, frac_seconds));
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteDuration(JsonWriter& writer, const Msg<Traits>& msg,
+                           const Desc<Traits>& desc) {
+  constexpr int64_t kMaxSeconds = int64_t{3652500} * 86400;
+  constexpr int64_t kMaxNanos = 999999999;
+
+  auto secs_field = Traits::MustHaveField(desc, 1);
+  auto secs = Traits::GetSize(secs_field, msg) > 0
+                  ? Traits::GetInt64(secs_field, msg)
+                  : 0;
+  RETURN_IF_ERROR(secs.status());
+
+  if (*secs > kMaxSeconds || *secs < -kMaxSeconds) {
+    return absl::InvalidArgumentError("duration out of range");
+  }
+
+  auto nanos_field = Traits::MustHaveField(desc, 2);
+  auto nanos = Traits::GetSize(nanos_field, msg) > 0
+                   ? Traits::GetInt32(nanos_field, msg)
+                   : 0;
+  RETURN_IF_ERROR(nanos.status());
+
+  if (*nanos > kMaxNanos || *nanos < -kMaxNanos) {
+    return absl::InvalidArgumentError("duration out of range");
+  }
+  if ((*secs != 0) && (*nanos != 0) && ((*secs < 0) != (*nanos < 0))) {
+    return absl::InvalidArgumentError("nanos and seconds signs do not match");
+  }
+
+  if (*nanos == 0) {
+    writer.Write(absl::StrFormat(R"("%ds")", *secs));
+    return absl::OkStatus();
+  }
+
+  size_t digits = 9;
+  uint32_t frac_seconds = std::abs(*nanos);
+  while (frac_seconds % 1000 == 0) {
+    frac_seconds /= 1000;
+    digits -= 3;
+  }
+
+  absl::string_view sign = ((*secs < 0) || (*nanos < 0)) ? "-" : "";
+  writer.Write(absl::StrFormat(R"("%s%d.%.*ds")", sign, std::abs(*secs), digits,
+                               frac_seconds));
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteFieldMask(JsonWriter& writer, const Msg<Traits>& msg,
+                            const Desc<Traits>& desc) {
+  // google.protobuf.FieldMask has a single field with number 1.
+  auto paths_field = Traits::MustHaveField(desc, 1);
+  size_t paths = Traits::GetSize(paths_field, msg);
+  writer.Write('"');
+
+  bool first = true;
+  for (size_t i = 0; i < paths; ++i) {
+    writer.WriteComma(first);
+    auto path = Traits::GetString(paths_field, writer.ScratchBuf(), msg, i);
+    RETURN_IF_ERROR(path.status());
+    bool saw_under = false;
+    for (char c : *path) {
+      if (absl::ascii_islower(c) && saw_under) {
+        writer.Write(absl::ascii_toupper(c));
+      } else if (absl::ascii_isdigit(c) || absl::ascii_islower(c) || c == '.') {
+        writer.Write(c);
+      } else if (c == '_' &&
+                 (!saw_under || writer.options().allow_legacy_syntax)) {
+        saw_under = true;
+        continue;
+      } else if (!writer.options().allow_legacy_syntax) {
+        return absl::InvalidArgumentError("unexpected character in FieldMask");
+      } else {
+        if (saw_under) {
+          writer.Write('_');
+        }
+        writer.Write(c);
+      }
+      saw_under = false;
+    }
+  }
+  writer.Write('"');
+
+  return absl::OkStatus();
+}
+
+template <typename Traits>
+absl::Status WriteAny(JsonWriter& writer, const Msg<Traits>& msg,
+                      const Desc<Traits>& desc) {
+  auto type_url_field = Traits::MustHaveField(desc, 1);
+  auto value_field = Traits::MustHaveField(desc, 2);
+
+  bool has_type_url = Traits::GetSize(type_url_field, msg) > 0;
+  bool has_value = Traits::GetSize(value_field, msg) > 0;
+  if (!has_type_url && !has_value) {
+    writer.Write("{}");
+    return absl::OkStatus();
+  } else if (!has_type_url) {
+    return absl::InvalidArgumentError("broken Any: missing type URL");
+  } else if (!has_value && !writer.options().allow_legacy_syntax) {
+    return absl::InvalidArgumentError("broken Any: missing value");
+  }
+
+  writer.Write("{");
+  writer.Push();
+
+  auto type_url = Traits::GetString(type_url_field, writer.ScratchBuf(), msg);
+  RETURN_IF_ERROR(type_url.status());
+  writer.NewLine();
+  writer.Write("\"@type\":");
+  writer.Whitespace(" ");
+  writer.Write(MakeQuoted(*type_url));
+
+  return Traits::WithDynamicType(
+      desc, std::string(*type_url),
+      [&](const Desc<Traits>& any_desc) -> absl::Status {
+        absl::string_view any_bytes;
+        if (has_value) {
+          absl::StatusOr<absl::string_view> bytes =
+              Traits::GetString(value_field, writer.ScratchBuf(), msg);
+          RETURN_IF_ERROR(bytes.status());
+          any_bytes = *bytes;
+        }
+
+        return Traits::WithDecodedMessage(
+            any_desc, any_bytes,
+            [&](const Msg<Traits>& unerased) -> absl::Status {
+              bool first = false;
+              if (ClassifyMessage(Traits::TypeName(any_desc)) !=
+                  MessageType::kNotWellKnown) {
+                writer.WriteComma(first);
+                writer.NewLine();
+                writer.Write("\"value\":");
+                writer.Whitespace(" ");
+                RETURN_IF_ERROR(
+                    WriteMessage<Traits>(writer, unerased, any_desc));
+              } else {
+                RETURN_IF_ERROR(
+                    WriteFields<Traits>(writer, unerased, any_desc, first));
+              }
+              writer.Pop();
+              if (!first) {
+                writer.NewLine();
+              }
+              writer.Write("}");
+              return absl::OkStatus();
+            });
+      });
+}
+
+template <typename Traits>
+absl::Status WriteMessage(JsonWriter& writer, const Msg<Traits>& msg,
+                          const Desc<Traits>& desc, bool is_top_level) {
+  switch (ClassifyMessage(Traits::TypeName(desc))) {
+    case MessageType::kAny:
+      return WriteAny<Traits>(writer, msg, desc);
+    case MessageType::kWrapper: {
+      auto field = Traits::MustHaveField(desc, 1);
+      if (Traits::GetSize(field, msg) == 0) {
+        return WriteSingular<Traits>(writer, field);
+      }
+      return WriteSingular<Traits>(writer, field, msg);
+    }
+    case MessageType::kValue:
+      return WriteValue<Traits>(writer, msg, desc, is_top_level);
+    case MessageType::kStruct:
+      return WriteStructValue<Traits>(writer, msg, desc);
+    case MessageType::kList:
+      return WriteListValue<Traits>(writer, msg, desc);
+    case MessageType::kTimestamp:
+      return WriteTimestamp<Traits>(writer, msg, desc);
+    case MessageType::kDuration:
+      return WriteDuration<Traits>(writer, msg, desc);
+    case MessageType::kFieldMask:
+      return WriteFieldMask<Traits>(writer, msg, desc);
+    default: {
+      writer.Write("{");
+      writer.Push();
+      bool first = true;
+      RETURN_IF_ERROR(WriteFields<Traits>(writer, msg, desc, first));
+      writer.Pop();
+      if (!first) {
+        writer.NewLine();
+      }
+      writer.Write("}");
+      return absl::OkStatus();
+    }
+  }
+}
+}  // namespace
+
+absl::Status MessageToJsonString(const Message& message, std::string* output,
+                                 json_internal::WriterOptions options) {
+  PROTOBUF_DLOG(INFO) << "json2/input: " << message.DebugString();
+  io::StringOutputStream out(output);
+  JsonWriter writer(&out, options);
+  absl::Status s = WriteMessage<UnparseProto2Descriptor>(
+      writer, message, *message.GetDescriptor(), /*is_top_level=*/true);
+  PROTOBUF_DLOG(INFO) << "json2/status: " << s;
+  RETURN_IF_ERROR(s);
+
+  writer.NewLine();
+  PROTOBUF_DLOG(INFO) << "json2/output: " << absl::CHexEscape(*output);
+  return absl::OkStatus();
+}
+
+absl::Status BinaryToJsonStream(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* binary_input,
+                                io::ZeroCopyOutputStream* json_output,
+                                json_internal::WriterOptions options) {
+  // NOTE: Most of the contortions in this function are to allow for capture of
+  // input and output of the parser in GOOGLE_DLOG mode. Destruction order is very
+  // critical in this function, because io::ZeroCopy*Stream types usually only
+  // flush on destruction.
+
+  // For GOOGLE_DLOG, we would like to print out the input and output, which requires
+  // buffering both instead of doing "zero copy". This block, and the one at
+  // the end of the function, set up and tear down interception of the input
+  // and output streams.
+  std::string copy;
+  std::string out;
+  absl::optional<io::ArrayInputStream> tee_input;
+  absl::optional<io::StringOutputStream> tee_output;
+  if (PROTOBUF_DEBUG) {
+    const void* data;
+    int len;
+    while (binary_input->Next(&data, &len)) {
+      copy.resize(copy.size() + len);
+      std::memcpy(&copy[copy.size() - len], data, len);
+    }
+    tee_input.emplace(copy.data(), copy.size());
+    tee_output.emplace(&out);
+  }
+
+  PROTOBUF_DLOG(INFO) << "json2/input: " << absl::BytesToHexString(copy);
+
+  ResolverPool pool(resolver);
+  auto desc = pool.FindMessage(type_url);
+  RETURN_IF_ERROR(desc.status());
+
+  io::CodedInputStream stream(tee_input.has_value() ? &*tee_input
+                                                    : binary_input);
+  auto msg = UntypedMessage::ParseFromStream(*desc, stream);
+  RETURN_IF_ERROR(msg.status());
+
+  JsonWriter writer(tee_output.has_value() ? &*tee_output : json_output,
+                    options);
+  absl::Status s = WriteMessage<UnparseProto3Type>(
+      writer, *msg, UnparseProto3Type::GetDesc(*msg),
+      /*is_top_level=*/true);
+  PROTOBUF_DLOG(INFO) << "json2/status: " << s;
+  RETURN_IF_ERROR(s);
+
+  if (PROTOBUF_DEBUG) {
+    tee_output.reset();  // Flush the output stream.
+    io::zc_sink_internal::ZeroCopyStreamByteSink(json_output)
+        .Append(out.data(), out.size());
+  }
+
+  PROTOBUF_DLOG(INFO) << "json2/output: " << absl::CHexEscape(out);
+
+  writer.NewLine();
+  return absl::OkStatus();
+}
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/util/internal/location_tracker.h b/src/google/protobuf/json/internal/unparser.h
similarity index 61%
copy from src/google/protobuf/util/internal/location_tracker.h
copy to src/google/protobuf/json/internal/unparser.h
index 68fefcc..a9a935d 100644
--- a/src/google/protobuf/util/internal/location_tracker.h
+++ b/src/google/protobuf/json/internal/unparser.h
@@ -28,43 +28,32 @@
 // (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_UTIL_INTERNAL_LOCATION_TRACKER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__
+#ifndef GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_H__
 
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/message.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/json/internal/writer.h"
+#include "google/protobuf/util/type_resolver.h"
 
 namespace google {
 namespace protobuf {
-namespace util {
-namespace converter {
-
-// LocationTrackerInterface is an interface for classes that track
-// the location information for the purpose of error reporting.
-class PROTOBUF_EXPORT LocationTrackerInterface {
- public:
-  virtual ~LocationTrackerInterface() {}
-
-  // Returns the object location as human readable string.
-  virtual std::string ToString() const = 0;
-
- protected:
-  LocationTrackerInterface() {}
-
- private:
-  // Please do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(LocationTrackerInterface);
-};
-
-}  // namespace converter
-}  // namespace util
+namespace json_internal {
+// Internal version of google::protobuf::util::MessageToJsonString; see json_util.h for
+// details.
+absl::Status MessageToJsonString(const Message& message, std::string* output,
+                                 json_internal::WriterOptions options);
+// Internal version of google::protobuf::util::BinaryToJsonStream; see json_util.h for
+// details.
+absl::Status BinaryToJsonStream(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* binary_input,
+                                io::ZeroCopyOutputStream* json_output,
+                                json_internal::WriterOptions options);
+}  // namespace json_internal
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_LOCATION_TRACKER_H__
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_H__
diff --git a/src/google/protobuf/json/internal/unparser_traits.h b/src/google/protobuf/json/internal/unparser_traits.h
new file mode 100644
index 0000000..cab762b
--- /dev/null
+++ b/src/google/protobuf/json/internal/unparser_traits.h
@@ -0,0 +1,443 @@
+// 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_JSON_INTERNAL_UNPARSER_TRAITS_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_TRAITS_H__
+
+#include <algorithm>
+#include <cfloat>
+#include <cstdint>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/status/status.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/types/variant.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/json/internal/descriptor_traits.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+// The type traits in this file provide describe how to read from protobuf
+// representation used by the JSON API, either via proto reflection or via
+// something ad-hoc for type.proto.
+
+// Helper alias templates to avoid needing to write `typename` in function
+// signatures.
+template <typename Traits>
+using Msg = typename Traits::Msg;
+
+// Traits for proto2-ish deserialization.
+struct UnparseProto2Descriptor : Proto2Descriptor {
+  // A message value that fields can be read from.
+  using Msg = Message;
+
+  static const Desc& GetDesc(const Msg& msg) { return *msg.GetDescriptor(); }
+
+  // Appends extension fields to `fields`.
+  static void FindAndAppendExtensions(const Msg& msg,
+                                      std::vector<Field>& fields) {
+    // Note that it is *not* correct to use ListFields for getting a list of
+    // fields to write, because the way that JSON decides to print non-extension
+    // fields is slightly subtle. That logic is handled elsewhere; we're only
+    // here to get extensions.
+    std::vector<Field> all_fields;
+    msg.GetReflection()->ListFields(msg, &all_fields);
+
+    for (Field field : all_fields) {
+      if (field->is_extension()) {
+        fields.push_back(field);
+      }
+    }
+  }
+
+  static size_t GetSize(Field f, const Msg& msg) {
+    if (f->is_repeated()) {
+      return msg.GetReflection()->FieldSize(msg, f);
+    } else {
+      return msg.GetReflection()->HasField(msg, f) ? 1 : 0;
+    }
+  }
+
+  static absl::StatusOr<float> GetFloat(Field f) {
+    return f->default_value_float();
+  }
+
+  static absl::StatusOr<double> GetDouble(Field f) {
+    return f->default_value_double();
+  }
+
+  static absl::StatusOr<int32_t> GetInt32(Field f) {
+    return f->default_value_int32();
+  }
+
+  static absl::StatusOr<uint32_t> GetUInt32(Field f) {
+    return f->default_value_uint32();
+  }
+
+  static absl::StatusOr<int64_t> GetInt64(Field f) {
+    return f->default_value_int64();
+  }
+
+  static absl::StatusOr<uint64_t> GetUInt64(Field f) {
+    return f->default_value_uint64();
+  }
+
+  static absl::StatusOr<bool> GetBool(Field f) {
+    return f->default_value_bool();
+  }
+
+  static absl::StatusOr<int32_t> GetEnumValue(Field f) {
+    return f->default_value_enum()->number();
+  }
+
+  static absl::StatusOr<absl::string_view> GetString(Field f,
+                                                     std::string& scratch) {
+    return f->default_value_string();
+  }
+
+  static absl::StatusOr<const Msg*> GetMessage(Field f) {
+    return absl::InternalError("message fields cannot have defaults");
+  }
+
+  static absl::StatusOr<float> GetFloat(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetFloat(msg, f);
+  }
+
+  static absl::StatusOr<double> GetDouble(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetDouble(msg, f);
+  }
+
+  static absl::StatusOr<int32_t> GetInt32(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetInt32(msg, f);
+  }
+
+  static absl::StatusOr<uint32_t> GetUInt32(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetUInt32(msg, f);
+  }
+
+  static absl::StatusOr<int64_t> GetInt64(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetInt64(msg, f);
+  }
+
+  static absl::StatusOr<uint64_t> GetUInt64(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetUInt64(msg, f);
+  }
+
+  static absl::StatusOr<bool> GetBool(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetBool(msg, f);
+  }
+
+  static absl::StatusOr<int32_t> GetEnumValue(Field f, const Msg& msg) {
+    return msg.GetReflection()->GetEnumValue(msg, f);
+  }
+
+  static absl::StatusOr<absl::string_view> GetString(Field f,
+                                                     std::string& scratch,
+                                                     const Msg& msg) {
+    return msg.GetReflection()->GetStringReference(msg, f, &scratch);
+  }
+
+  static absl::StatusOr<const Msg*> GetMessage(Field f, const Msg& msg) {
+    return &msg.GetReflection()->GetMessage(msg, f);
+  }
+
+  static absl::StatusOr<float> GetFloat(Field f, const Msg& msg, size_t idx) {
+    return msg.GetReflection()->GetRepeatedFloat(msg, f, idx);
+  }
+
+  static absl::StatusOr<double> GetDouble(Field f, const Msg& msg, size_t idx) {
+    return msg.GetReflection()->GetRepeatedDouble(msg, f, idx);
+  }
+
+  static absl::StatusOr<int32_t> GetInt32(Field f, const Msg& msg, size_t idx) {
+    return msg.GetReflection()->GetRepeatedInt32(msg, f, idx);
+  }
+
+  static absl::StatusOr<uint32_t> GetUInt32(Field f, const Msg& msg,
+                                            size_t idx) {
+    return msg.GetReflection()->GetRepeatedUInt32(msg, f, idx);
+  }
+
+  static absl::StatusOr<int64_t> GetInt64(Field f, const Msg& msg, size_t idx) {
+    return msg.GetReflection()->GetRepeatedInt64(msg, f, idx);
+  }
+
+  static absl::StatusOr<uint64_t> GetUInt64(Field f, const Msg& msg,
+                                            size_t idx) {
+    return msg.GetReflection()->GetRepeatedUInt64(msg, f, idx);
+  }
+
+  static absl::StatusOr<bool> GetBool(Field f, const Msg& msg, size_t idx) {
+    return msg.GetReflection()->GetRepeatedBool(msg, f, idx);
+  }
+
+  static absl::StatusOr<int32_t> GetEnumValue(Field f, const Msg& msg,
+                                              size_t idx) {
+    return msg.GetReflection()->GetRepeatedEnumValue(msg, f, idx);
+  }
+
+  static absl::StatusOr<absl::string_view> GetString(Field f,
+                                                     std::string& scratch,
+                                                     const Msg& msg,
+                                                     size_t idx) {
+    return msg.GetReflection()->GetRepeatedStringReference(msg, f, idx,
+                                                           &scratch);
+  }
+
+  static absl::StatusOr<const Msg*> GetMessage(Field f, const Msg& msg,
+                                               size_t idx) {
+    return &msg.GetReflection()->GetRepeatedMessage(msg, f, idx);
+  }
+
+  template <typename F>
+  static absl::Status WithDecodedMessage(const Desc& desc,
+                                         absl::string_view data, F body) {
+    DynamicMessageFactory factory;
+    std::unique_ptr<Message> unerased(factory.GetPrototype(&desc)->New());
+    unerased->ParseFromString(data);
+
+    // Explicitly create a const reference, so that we do not accidentally pass
+    // a mutable reference to `body`.
+    const Msg& ref = *unerased;
+    return body(ref);
+  }
+};
+
+struct UnparseProto3Type : Proto3Type {
+  using Msg = UntypedMessage;
+
+  static const Desc& GetDesc(const Msg& msg) { return msg.desc(); }
+
+  static void FindAndAppendExtensions(const Msg&, std::vector<Field>&) {
+    // type.proto does not support extensions.
+  }
+
+  static size_t GetSize(Field f, const Msg& msg) {
+    return msg.Count(f->proto().number());
+  }
+
+  static absl::StatusOr<float> GetFloat(Field f) {
+    if (f->proto().default_value().empty()) {
+      return 0.0;
+    }
+    float x;
+    if (!absl::SimpleAtof(f->proto().default_value(), &x)) {
+      return absl::InternalError(absl::StrCat(
+          "bad default value in type.proto: ", f->parent().proto().name()));
+    }
+    return x;
+  }
+
+  static absl::StatusOr<double> GetDouble(Field f) {
+    if (f->proto().default_value().empty()) {
+      return 0.0;
+    }
+    double x;
+    if (!absl::SimpleAtod(f->proto().default_value(), &x)) {
+      return absl::InternalError(absl::StrCat(
+          "bad default value in type.proto: ", f->parent().proto().name()));
+    }
+    return x;
+  }
+
+  static absl::StatusOr<int32_t> GetInt32(Field f) {
+    if (f->proto().default_value().empty()) {
+      return 0;
+    }
+    int32_t x;
+    if (!absl::SimpleAtoi(f->proto().default_value(), &x)) {
+      return absl::InternalError(absl::StrCat(
+          "bad default value in type.proto: ", f->parent().proto().name()));
+    }
+    return x;
+  }
+
+  static absl::StatusOr<uint32_t> GetUInt32(Field f) {
+    if (f->proto().default_value().empty()) {
+      return 0;
+    }
+    uint32_t x;
+    if (!absl::SimpleAtoi(f->proto().default_value(), &x)) {
+      return absl::InternalError(absl::StrCat(
+          "bad default value in type.proto: ", f->parent().proto().name()));
+    }
+    return x;
+  }
+
+  static absl::StatusOr<int64_t> GetInt64(Field f) {
+    if (f->proto().default_value().empty()) {
+      return 0;
+    }
+    int64_t x;
+    if (!absl::SimpleAtoi(f->proto().default_value(), &x)) {
+      return absl::InternalError(absl::StrCat(
+          "bad default value in type.proto: ", f->parent().proto().name()));
+    }
+    return x;
+  }
+
+  static absl::StatusOr<uint64_t> GetUInt64(Field f) {
+    if (f->proto().default_value().empty()) {
+      return 0;
+    }
+    uint64_t x;
+    if (!absl::SimpleAtoi(f->proto().default_value(), &x)) {
+      return absl::InternalError(absl::StrCat(
+          "bad default value in type.proto: ", f->parent().proto().name()));
+    }
+    return x;
+  }
+
+  static absl::StatusOr<bool> GetBool(Field f) {
+    if (f->proto().default_value().empty()) {
+      return false;
+    } else if (f->proto().default_value() == "false") {
+      return false;
+    } else if (f->proto().default_value() == "true") {
+      return true;
+    } else {
+      return absl::InternalError(absl::StrCat(
+          "bad default value in type.proto: ", f->parent().proto().name()));
+    }
+  }
+
+  static absl::StatusOr<int32_t> GetEnumValue(Field f) {
+    if (f->proto().default_value().empty()) {
+      auto e = f->EnumType();
+      RETURN_IF_ERROR(e.status());
+
+      return (**e).proto().enumvalue(0).number();
+    }
+    return EnumNumberByName(f, f->proto().default_value(),
+                            /*case_insensitive=*/false);
+  }
+
+  static absl::StatusOr<absl::string_view> GetString(Field f,
+                                                     std::string& scratch) {
+    absl::CUnescape(f->proto().default_value(), &scratch);
+    return scratch;
+  }
+
+  static absl::StatusOr<const Msg*> GetMessage(Field f) {
+    return absl::InternalError("message fields cannot have defaults");
+  }
+
+  static absl::StatusOr<float> GetFloat(Field f, const Msg& msg,
+                                        size_t idx = 0) {
+    return msg.Get<float>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<double> GetDouble(Field f, const Msg& msg,
+                                          size_t idx = 0) {
+    return msg.Get<double>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<int32_t> GetInt32(Field f, const Msg& msg,
+                                          size_t idx = 0) {
+    return msg.Get<int32_t>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<uint32_t> GetUInt32(Field f, const Msg& msg,
+                                            size_t idx = 0) {
+    return msg.Get<uint32_t>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<int64_t> GetInt64(Field f, const Msg& msg,
+                                          size_t idx = 0) {
+    return msg.Get<int64_t>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<uint64_t> GetUInt64(Field f, const Msg& msg,
+                                            size_t idx = 0) {
+    return msg.Get<uint64_t>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<bool> GetBool(Field f, const Msg& msg, size_t idx = 0) {
+    return msg.Get<Msg::Bool>(f->proto().number())[idx] == Msg::kTrue;
+  }
+
+  static absl::StatusOr<int32_t> GetEnumValue(Field f, const Msg& msg,
+                                              size_t idx = 0) {
+    return msg.Get<int32_t>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<absl::string_view> GetString(Field f,
+                                                     std::string& scratch,
+                                                     const Msg& msg,
+                                                     size_t idx = 0) {
+    return msg.Get<std::string>(f->proto().number())[idx];
+  }
+
+  static absl::StatusOr<const Msg*> GetMessage(Field f, const Msg& msg,
+                                               size_t idx = 0) {
+    return &msg.Get<Msg>(f->proto().number())[idx];
+  }
+
+  template <typename F>
+  static absl::Status WithDecodedMessage(const Desc& desc,
+                                         absl::string_view data, F body) {
+    io::CodedInputStream stream(reinterpret_cast<const uint8_t*>(data.data()),
+                                data.size());
+    auto unerased = Msg::ParseFromStream(&desc, stream);
+    RETURN_IF_ERROR(unerased.status());
+
+    // Explicitly create a const reference, so that we do not accidentally pass
+    // a mutable reference to `body`.
+    const Msg& ref = *unerased;
+    return body(ref);
+  }
+};
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_UNPARSER_TRAITS_H__
diff --git a/src/google/protobuf/json/internal/untyped_message.cc b/src/google/protobuf/json/internal/untyped_message.cc
new file mode 100644
index 0000000..a7d949d
--- /dev/null
+++ b/src/google/protobuf/json/internal/untyped_message.cc
@@ -0,0 +1,548 @@
+// 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/json/internal/untyped_message.h"
+
+#include <algorithm>
+#include <cfloat>
+#include <cstdint>
+#include <memory>
+#include <sstream>
+#include <string>
+#include <type_traits>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+#include "absl/types/variant.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "utf8_validity.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+using ::google::protobuf::Field;
+using ::google::protobuf::internal::WireFormatLite;
+
+absl::StatusOr<const ResolverPool::Message*> ResolverPool::Field::MessageType()
+    const {
+  GOOGLE_CHECK(proto().kind() == google::protobuf::Field::TYPE_MESSAGE ||
+        proto().kind() == google::protobuf::Field::TYPE_GROUP)
+      << proto().kind();
+  if (type_ == nullptr) {
+    auto type = pool_->FindMessage(proto().type_url());
+    RETURN_IF_ERROR(type.status());
+    type_ = *type;
+  }
+  return reinterpret_cast<const Message*>(type_);
+}
+
+absl::StatusOr<const ResolverPool::Enum*> ResolverPool::Field::EnumType()
+    const {
+  GOOGLE_CHECK(proto().kind() == google::protobuf::Field::TYPE_ENUM) << proto().kind();
+  if (type_ == nullptr) {
+    auto type = pool_->FindEnum(proto().type_url());
+    RETURN_IF_ERROR(type.status());
+    type_ = *type;
+  }
+  return reinterpret_cast<const Enum*>(type_);
+}
+
+absl::Span<const ResolverPool::Field> ResolverPool::Message::FieldsByIndex()
+    const {
+  if (raw_.fields_size() > 0 && fields_ == nullptr) {
+    fields_ = std::unique_ptr<Field[]>(new Field[raw_.fields_size()]);
+    for (size_t i = 0; i < raw_.fields_size(); ++i) {
+      fields_[i].pool_ = pool_;
+      fields_[i].raw_ = &raw_.fields(i);
+      fields_[i].parent_ = this;
+    }
+  }
+
+  return absl::MakeSpan(fields_.get(), proto().fields_size());
+}
+
+const ResolverPool::Field* ResolverPool::Message::FindField(
+    absl::string_view name) const {
+  if (raw_.fields_size() == 0) {
+    return nullptr;
+  }
+
+  if (fields_by_name_.empty()) {
+    const Field* found = nullptr;
+    for (auto& field : FieldsByIndex()) {
+      if (field.proto().name() == name || field.proto().json_name() == name) {
+        found = &field;
+      }
+      fields_by_name_.try_emplace(field.proto().name(), &field);
+      fields_by_name_.try_emplace(field.proto().json_name(), &field);
+    }
+    return found;
+  }
+
+  auto it = fields_by_name_.find(name);
+  return it == fields_by_name_.end() ? nullptr : it->second;
+}
+
+const ResolverPool::Field* ResolverPool::Message::FindField(
+    int32_t number) const {
+  if (raw_.fields_size() == 0) {
+    return nullptr;
+  }
+
+  bool is_small = raw_.fields_size() < 8;
+  if (is_small || fields_by_number_.empty()) {
+    const Field* found = nullptr;
+    for (auto& field : FieldsByIndex()) {
+      if (field.proto().number() == number) {
+        found = &field;
+      }
+      if (!is_small) {
+        fields_by_number_.try_emplace(field.proto().number(), &field);
+      }
+    }
+    return found;
+  }
+
+  auto it = fields_by_number_.find(number);
+  return it == fields_by_number_.end() ? nullptr : it->second;
+}
+
+absl::StatusOr<const ResolverPool::Message*> ResolverPool::FindMessage(
+    absl::string_view url) {
+  auto it = messages_.find(url);
+  if (it != messages_.end()) {
+    return it->second.get();
+  }
+
+  auto msg = absl::WrapUnique(new Message(this));
+  std::string url_buf(url);
+  RETURN_IF_ERROR(resolver_->ResolveMessageType(url_buf, &msg->raw_));
+
+  return messages_.try_emplace(std::move(url_buf), std::move(msg))
+      .first->second.get();
+}
+
+absl::StatusOr<const ResolverPool::Enum*> ResolverPool::FindEnum(
+    absl::string_view url) {
+  auto it = enums_.find(url);
+  if (it != enums_.end()) {
+    return it->second.get();
+  }
+
+  auto enoom = absl::WrapUnique(new Enum(this));
+  std::string url_buf(url);
+  RETURN_IF_ERROR(resolver_->ResolveEnumType(url_buf, &enoom->raw_));
+
+  return enums_.try_emplace(std::move(url_buf), std::move(enoom))
+      .first->second.get();
+}
+
+absl::Status UntypedMessage::Decode(io::CodedInputStream& stream,
+                                    absl::optional<int32_t> current_group) {
+  while (true) {
+    std::vector<int32_t> group_stack;
+    uint32_t tag = stream.ReadTag();
+    if (tag == 0) {
+      return absl::OkStatus();
+    }
+
+    int32_t field_number = tag >> 3;
+    int32_t wire_type = tag & 7;
+
+    // EGROUP markers can show up as "unknown fields", so we need to handle them
+    // before we even do field lookup. Being inside of a group behaves as if a
+    // special field has been added to the message.
+    if (wire_type == WireFormatLite::WIRETYPE_END_GROUP) {
+      if (!current_group.has_value()) {
+        return absl::InvalidArgumentError(absl::StrFormat(
+            "attempted to close group %d before SGROUP tag", field_number));
+      }
+      if (field_number != *current_group) {
+        return absl::InvalidArgumentError(
+            absl::StrFormat("attempted to close group %d while inside group %d",
+                            field_number, *current_group));
+      }
+      return absl::OkStatus();
+    }
+
+    const auto* field = desc_->FindField(field_number);
+    if (!group_stack.empty() || field == nullptr) {
+      // Skip unknown field. If the group-stack is non-empty, we are in the
+      // process of working through an unknown group.
+      switch (wire_type) {
+        case WireFormatLite::WIRETYPE_VARINT: {
+          uint64_t x;
+          if (!stream.ReadVarint64(&x)) {
+            return absl::InvalidArgumentError("unexpected EOF");
+          }
+          continue;
+        }
+        case WireFormatLite::WIRETYPE_FIXED64: {
+          uint64_t x;
+          if (!stream.ReadLittleEndian64(&x)) {
+            return absl::InvalidArgumentError("unexpected EOF");
+          }
+          continue;
+        }
+        case WireFormatLite::WIRETYPE_FIXED32: {
+          uint32_t x;
+          if (!stream.ReadLittleEndian32(&x)) {
+            return absl::InvalidArgumentError("unexpected EOF");
+          }
+          continue;
+        }
+        case WireFormatLite::WIRETYPE_LENGTH_DELIMITED: {
+          uint32_t x;
+          if (!stream.ReadVarint32(&x)) {
+            return absl::InvalidArgumentError("unexpected EOF");
+          }
+          stream.Skip(x);
+          continue;
+        }
+        case WireFormatLite::WIRETYPE_START_GROUP: {
+          group_stack.push_back(field_number);
+          continue;
+        }
+        case WireFormatLite::WIRETYPE_END_GROUP: {
+          if (group_stack.empty()) {
+            return absl::InvalidArgumentError(absl::StrFormat(
+                "attempted to close group %d before SGROUP tag", field_number));
+          }
+          if (field_number != group_stack.back()) {
+            return absl::InvalidArgumentError(absl::StrFormat(
+                "attempted to close group %d while inside group %d",
+                field_number, *current_group));
+          }
+          group_stack.pop_back();
+          continue;
+        }
+        default:
+          return absl::InvalidArgumentError(
+              absl::StrCat("unknown wire type: ", wire_type));
+      }
+    }
+    switch (wire_type) {
+      case WireFormatLite::WIRETYPE_VARINT:
+        RETURN_IF_ERROR(DecodeVarint(stream, *field));
+        break;
+      case WireFormatLite::WIRETYPE_FIXED64:
+        RETURN_IF_ERROR(Decode64Bit(stream, *field));
+        break;
+      case WireFormatLite::WIRETYPE_FIXED32:
+        RETURN_IF_ERROR(Decode32Bit(stream, *field));
+        break;
+      case WireFormatLite::WIRETYPE_LENGTH_DELIMITED:
+        RETURN_IF_ERROR(DecodeDelimited(stream, *field));
+        break;
+      case WireFormatLite::WIRETYPE_START_GROUP: {
+        if (field->proto().kind() != Field::TYPE_GROUP) {
+          return absl::InvalidArgumentError(absl::StrFormat(
+              "field number %d is not a group", field->proto().number()));
+        }
+        auto group_desc = field->MessageType();
+        RETURN_IF_ERROR(group_desc.status());
+
+        UntypedMessage group(*group_desc);
+        RETURN_IF_ERROR(group.Decode(stream, field_number));
+        RETURN_IF_ERROR(InsertField<UntypedMessage>(*field, std::move(group)));
+        break;
+      }
+      case WireFormatLite::WIRETYPE_END_GROUP:
+        GOOGLE_CHECK(false) << "unreachable";
+        break;
+      default:
+        return absl::InvalidArgumentError(
+            absl::StrCat("unknown wire type: ", wire_type));
+    }
+  }
+
+  return absl::OkStatus();
+}
+
+absl::Status UntypedMessage::DecodeVarint(io::CodedInputStream& stream,
+                                          const ResolverPool::Field& field) {
+  switch (field.proto().kind()) {
+    case Field::TYPE_BOOL: {
+      char byte;
+      if (!stream.ReadRaw(&byte, 1)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      switch (byte) {
+        case 0:
+          RETURN_IF_ERROR(InsertField(field, kFalse));
+          break;
+        case 1:
+          RETURN_IF_ERROR(InsertField(field, kTrue));
+          break;
+        default:
+          return absl::InvalidArgumentError(
+              absl::StrFormat("bad value for bool: \\x%02x", byte));
+      }
+      break;
+    }
+    case Field::TYPE_INT32:
+    case Field::TYPE_SINT32:
+    case Field::TYPE_UINT32:
+    case Field::TYPE_ENUM: {
+      uint32_t x;
+      if (!stream.ReadVarint32(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      if (field.proto().kind() == Field::TYPE_UINT32) {
+        RETURN_IF_ERROR(InsertField(field, x));
+        break;
+      }
+      if (field.proto().kind() == Field::TYPE_SINT32) {
+        x = WireFormatLite::ZigZagDecode32(x);
+      }
+      RETURN_IF_ERROR(InsertField(field, static_cast<int32_t>(x)));
+      break;
+    }
+    case Field::TYPE_INT64:
+    case Field::TYPE_SINT64:
+    case Field::TYPE_UINT64: {
+      uint64_t x;
+      if (!stream.ReadVarint64(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      if (field.proto().kind() == Field::TYPE_UINT64) {
+        RETURN_IF_ERROR(InsertField(field, x));
+        break;
+      }
+      if (field.proto().kind() == Field::TYPE_SINT64) {
+        x = WireFormatLite::ZigZagDecode64(x);
+      }
+      RETURN_IF_ERROR(InsertField(field, static_cast<int64_t>(x)));
+      break;
+    }
+    default:
+      return absl::InvalidArgumentError(absl::StrFormat(
+          "field type %d (number %d) does not support varint fields",
+          field.proto().kind(), field.proto().number()));
+  }
+  return absl::OkStatus();
+}
+
+absl::Status UntypedMessage::Decode64Bit(io::CodedInputStream& stream,
+                                         const ResolverPool::Field& field) {
+  switch (field.proto().kind()) {
+    case Field::TYPE_FIXED64: {
+      uint64_t x;
+      if (!stream.ReadLittleEndian64(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      RETURN_IF_ERROR(InsertField(field, x));
+      break;
+    }
+    case Field::TYPE_SFIXED64: {
+      uint64_t x;
+      if (!stream.ReadLittleEndian64(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      RETURN_IF_ERROR(InsertField(field, static_cast<int64_t>(x)));
+      break;
+    }
+    case Field::TYPE_DOUBLE: {
+      uint64_t x;
+      if (!stream.ReadLittleEndian64(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      RETURN_IF_ERROR(InsertField(field, absl::bit_cast<double>(x)));
+      break;
+    }
+    default:
+      return absl::InvalidArgumentError(
+          absl::StrFormat("field type %d (number %d) does not support "
+                          "type 64-bit fields",
+                          field.proto().kind(), field.proto().number()));
+  }
+  return absl::OkStatus();
+}
+
+absl::Status UntypedMessage::Decode32Bit(io::CodedInputStream& stream,
+                                         const ResolverPool::Field& field) {
+  switch (field.proto().kind()) {
+    case Field::TYPE_FIXED32: {
+      uint32_t x;
+      if (!stream.ReadLittleEndian32(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      RETURN_IF_ERROR(InsertField(field, x));
+      break;
+    }
+    case Field::TYPE_SFIXED32: {
+      uint32_t x;
+      if (!stream.ReadLittleEndian32(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      RETURN_IF_ERROR(InsertField(field, static_cast<int32_t>(x)));
+      break;
+    }
+    case Field::TYPE_FLOAT: {
+      uint32_t x;
+      if (!stream.ReadLittleEndian32(&x)) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      RETURN_IF_ERROR(InsertField(field, absl::bit_cast<float>(x)));
+      break;
+    }
+    default:
+      return absl::InvalidArgumentError(absl::StrFormat(
+          "field type %d (number %d) does not support 32-bit fields",
+          field.proto().kind(), field.proto().number()));
+  }
+  return absl::OkStatus();
+}
+
+absl::Status UntypedMessage::DecodeDelimited(io::CodedInputStream& stream,
+                                             const ResolverPool::Field& field) {
+  auto limit = stream.ReadLengthAndPushLimit();
+  if (limit == 0) {
+    return absl::InvalidArgumentError("unexpected EOF");
+  }
+
+  switch (field.proto().kind()) {
+    case Field::TYPE_STRING:
+    case Field::TYPE_BYTES: {
+      std::string buf;
+      if (!stream.ReadString(&buf, stream.BytesUntilLimit())) {
+        return absl::InvalidArgumentError("unexpected EOF");
+      }
+      if (field.proto().kind() == Field::TYPE_STRING) {
+        if (desc_->proto().syntax() == google::protobuf::SYNTAX_PROTO3 &&
+            utf8_range::IsStructurallyValid(buf)) {
+          return absl::InvalidArgumentError("proto3 strings must be UTF-8");
+        }
+      }
+
+      RETURN_IF_ERROR(InsertField<std::string>(field, std::move(buf)));
+      break;
+    }
+    case Field::TYPE_MESSAGE: {
+      auto inner_desc = field.MessageType();
+      RETURN_IF_ERROR(inner_desc.status());
+
+      auto inner = ParseFromStream(*inner_desc, stream);
+      RETURN_IF_ERROR(inner.status());
+      RETURN_IF_ERROR(InsertField<UntypedMessage>(field, std::move(*inner)));
+      break;
+    }
+    default: {
+      // This is definitely a packed field.
+      while (stream.BytesUntilLimit() > 0) {
+        switch (field.proto().kind()) {
+          case Field::TYPE_BOOL:
+          case Field::TYPE_INT32:
+          case Field::TYPE_SINT32:
+          case Field::TYPE_UINT32:
+          case Field::TYPE_ENUM:
+          case Field::TYPE_INT64:
+          case Field::TYPE_SINT64:
+          case Field::TYPE_UINT64:
+            RETURN_IF_ERROR(DecodeVarint(stream, field));
+            break;
+          case Field::TYPE_FIXED64:
+          case Field::TYPE_SFIXED64:
+          case Field::TYPE_DOUBLE:
+            RETURN_IF_ERROR(Decode64Bit(stream, field));
+            break;
+          case Field::TYPE_FIXED32:
+          case Field::TYPE_SFIXED32:
+          case Field::TYPE_FLOAT:
+            RETURN_IF_ERROR(Decode32Bit(stream, field));
+            break;
+          default:
+            return absl::InvalidArgumentError(absl::StrFormat(
+                "field type %d (number %d) does not support type 2 records",
+                field.proto().kind(), field.proto().number()));
+        }
+      }
+      break;
+    }
+  }
+  stream.PopLimit(limit);
+  return absl::OkStatus();
+}
+
+template <typename T>
+absl::Status UntypedMessage::InsertField(const ResolverPool::Field& field,
+                                         T value) {
+  int32_t number = field.proto().number();
+  auto emplace_result = fields_.try_emplace(number, std::move(value));
+  if (emplace_result.second) {
+    return absl::OkStatus();
+  }
+
+  if (field.proto().cardinality() !=
+      google::protobuf::Field::CARDINALITY_REPEATED) {
+    return absl::InvalidArgumentError(
+        absl::StrCat("repeated entries for singular field number ", number));
+  }
+
+  Value& slot = emplace_result.first->second;
+  if (auto* extant = absl::get_if<T>(&slot)) {
+    std::vector<T> repeated;
+    repeated.push_back(std::move(*extant));
+    repeated.push_back(std::move(value));
+
+    slot = std::move(repeated);
+  } else if (auto* extant = absl::get_if<std::vector<T>>(&slot)) {
+    extant->push_back(std::move(value));
+  } else {
+    return absl::InvalidArgumentError(
+        absl::StrFormat("inconsistent types for field number %d: tried to "
+                        "insert %s, but index was %d",
+                        number, typeid(T).name(), slot.index()));
+  }
+
+  return absl::OkStatus();
+}
+
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/json/internal/untyped_message.h b/src/google/protobuf/json/internal/untyped_message.h
new file mode 100644
index 0000000..6b2822e
--- /dev/null
+++ b/src/google/protobuf/json/internal/untyped_message.h
@@ -0,0 +1,259 @@
+// 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_UITL_UNTYPED_MESSAGE_H__
+#define GOOGLE_PROTOBUF_UITL_UNTYPED_MESSAGE_H__
+
+#include <cstddef>
+#include <cstdint>
+#include <memory>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/message.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/status/status.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "absl/types/optional.h"
+#include "absl/types/span.h"
+#include "absl/types/variant.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+struct SizeVisitor {
+  template <typename T>
+  size_t operator()(const std::vector<T>& x) {
+    return x.size();
+  }
+
+  template <typename T>
+  size_t operator()(const T& x) {
+    return 1;
+  }
+};
+
+// A DescriptorPool-like type for caching lookups from a TypeResolver.
+//
+// This type and all of its nested types are thread-hostile.
+class ResolverPool {
+ public:
+  class Message;
+  class Enum;
+  class Field {
+   public:
+    Field(const Field&) = delete;
+    Field& operator=(const Field&) = delete;
+
+    absl::StatusOr<const Message*> MessageType() const;
+    absl::StatusOr<const Enum*> EnumType() const;
+
+    const Message& parent() const { return *parent_; }
+    const google::protobuf::Field& proto() const { return *raw_; }
+
+   private:
+    friend class ResolverPool;
+
+    Field() = default;
+
+    ResolverPool* pool_ = nullptr;
+    const google::protobuf::Field* raw_ = nullptr;
+    const Message* parent_ = nullptr;
+    mutable const void* type_ = nullptr;
+  };
+
+  class Message {
+   public:
+    Message(const Message&) = delete;
+    Message& operator=(const Message&) = delete;
+
+    absl::Span<const Field> FieldsByIndex() const;
+    const Field* FindField(absl::string_view name) const;
+    const Field* FindField(int32_t number) const;
+
+    const google::protobuf::Type& proto() const { return raw_; }
+    ResolverPool* pool() const { return pool_; }
+
+   private:
+    friend class ResolverPool;
+
+    explicit Message(ResolverPool* pool) : pool_(pool) {}
+
+    ResolverPool* pool_;
+    google::protobuf::Type raw_;
+    mutable std::unique_ptr<Field[]> fields_;
+    mutable absl::flat_hash_map<absl::string_view, const Field*>
+        fields_by_name_;
+    mutable absl::flat_hash_map<int32_t, const Field*> fields_by_number_;
+  };
+
+  class Enum {
+   public:
+    Enum(const Enum&) = delete;
+    Enum& operator=(const Enum&) = delete;
+
+    const google::protobuf::Enum& proto() const { return raw_; }
+    ResolverPool* pool() const { return pool_; }
+
+   private:
+    friend class ResolverPool;
+
+    explicit Enum(ResolverPool* pool) : pool_(pool) {}
+
+    ResolverPool* pool_;
+    google::protobuf::Enum raw_;
+    mutable absl::flat_hash_map<absl::string_view, google::protobuf::EnumValue*>
+        values_;
+  };
+
+  explicit ResolverPool(google::protobuf::util::TypeResolver* resolver)
+      : resolver_(resolver) {}
+
+  ResolverPool(const ResolverPool&) = delete;
+  ResolverPool& operator=(const ResolverPool&) = delete;
+
+  absl::StatusOr<const Message*> FindMessage(absl::string_view url);
+  absl::StatusOr<const Enum*> FindEnum(absl::string_view url);
+
+ private:
+  absl::flat_hash_map<std::string, std::unique_ptr<Message>> messages_;
+  absl::flat_hash_map<std::string, std::unique_ptr<Enum>> enums_;
+  google::protobuf::util::TypeResolver* resolver_;
+};
+
+// A parsed wire-format proto that uses TypeReslover for parsing.
+//
+// This type is an implementation detail of the JSON parser.
+class UntypedMessage final {
+ public:
+  // New nominal type instead of `bool` to avoid vector<bool> shenanigans.
+  enum Bool : unsigned char { kTrue, kFalse };
+  using Value = absl::variant<Bool, int32_t, uint32_t, int64_t, uint64_t, float,
+                              double, std::string, UntypedMessage,
+                              //
+                              std::vector<Bool>, std::vector<int32_t>,
+                              std::vector<uint32_t>, std::vector<int64_t>,
+                              std::vector<uint64_t>, std::vector<float>,
+                              std::vector<double>, std::vector<std::string>,
+                              std::vector<UntypedMessage>>;
+
+  UntypedMessage(const UntypedMessage&) = delete;
+  UntypedMessage& operator=(const UntypedMessage&) = delete;
+  UntypedMessage(UntypedMessage&&) = default;
+  UntypedMessage& operator=(UntypedMessage&&) = default;
+
+  // Tries to parse a proto with the given descriptor from an input stream.
+  static absl::StatusOr<UntypedMessage> ParseFromStream(
+      const ResolverPool::Message* desc, io::CodedInputStream& stream) {
+    UntypedMessage msg(std::move(desc));
+    RETURN_IF_ERROR(msg.Decode(stream));
+    return std::move(msg);
+  }
+
+  // Returns the number of elements in a field by number.
+  //
+  // Optional fields are treated like repeated fields with one or zero elements.
+  size_t Count(int32_t field_number) const {
+    auto it = fields_.find(field_number);
+    if (it == fields_.end()) {
+      return 0;
+    }
+
+    return absl::visit(SizeVisitor{}, it->second);
+  }
+
+  // Returns the contents of a field by number.
+  //
+  // Optional fields are treated like repeated fields with one or zero elements.
+  // If the field is not set, returns an empty span.
+  //
+  // If `T` is the wrong type, this function crashes.
+  template <typename T>
+  absl::Span<const T> Get(int32_t field_number) const {
+    auto it = fields_.find(field_number);
+    if (it == fields_.end()) {
+      return {};
+    }
+
+    if (auto* val = absl::get_if<T>(&it->second)) {
+      return absl::Span<const T>(val, 1);
+    } else if (auto* vec = absl::get_if<std::vector<T>>(&it->second)) {
+      return *vec;
+    } else {
+      GOOGLE_CHECK(false) << "wrong type for UntypedMessage::Get(" << field_number
+                   << ")";
+      return {};  // avoid compiler warning.
+    }
+  }
+
+  const ResolverPool::Message& desc() const { return *desc_; }
+
+ private:
+  enum Cardinality { kSingular, kRepeated };
+
+  explicit UntypedMessage(const ResolverPool::Message* desc) : desc_(desc) {}
+
+  absl::Status Decode(io::CodedInputStream& stream,
+                      absl::optional<int32_t> current_group = absl::nullopt);
+
+  absl::Status DecodeVarint(io::CodedInputStream& stream,
+                            const ResolverPool::Field& field);
+  absl::Status Decode64Bit(io::CodedInputStream& stream,
+                           const ResolverPool::Field& field);
+  absl::Status Decode32Bit(io::CodedInputStream& stream,
+                           const ResolverPool::Field& field);
+  absl::Status DecodeDelimited(io::CodedInputStream& stream,
+                               const ResolverPool::Field& field);
+
+  template <typename T>
+  absl::Status InsertField(const ResolverPool::Field& field, T value);
+
+  const ResolverPool::Message* desc_;
+  absl::flat_hash_map<int32_t, Value> fields_;
+};
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_UITL_UNTYPED_MESSAGE_H__
diff --git a/src/google/protobuf/json/internal/writer.cc b/src/google/protobuf/json/internal/writer.cc
new file mode 100644
index 0000000..20fa3e9
--- /dev/null
+++ b/src/google/protobuf/json/internal/writer.cc
@@ -0,0 +1,329 @@
+// 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/json/internal/writer.h"
+
+#include <cstdint>
+#include <initializer_list>
+#include <limits>
+#include <utility>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/algorithm/container.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+
+// Tries to write a non-finite double if necessary; returns false if
+// nothing was written.
+bool JsonWriter::MaybeWriteSpecialFp(double val) {
+  if (val == std::numeric_limits<double>::infinity()) {
+    Write("\"Infinity\"");
+  } else if (val == -std::numeric_limits<double>::infinity()) {
+    Write("\"-Infinity\"");
+  } else if (std::isnan(val)) {
+    Write("\"NaN\"");
+  } else {
+    return false;
+  }
+  return true;
+}
+
+void JsonWriter::WriteBase64(absl::string_view str) {
+  // This is the regular base64, not the "web-safe" version.
+  constexpr absl::string_view kBase64 =
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
+  const char* ptr = str.data();
+  const char* end = ptr + str.size();
+
+  // Reads the `n`th character off of `ptr` while gracefully avoiding
+  // sign extension due to implicit conversions
+  auto read = [&](size_t n) {
+    return static_cast<size_t>(static_cast<uint8_t>(ptr[n]));
+  };
+
+  char buf[4];
+  absl::string_view view(buf, sizeof(buf));
+  Write("\"");
+
+  while (end - ptr >= 3) {
+    buf[0] = kBase64[read(0) >> 2];
+    buf[1] = kBase64[((read(0) & 0x3) << 4) | (read(1) >> 4)];
+    buf[2] = kBase64[((read(1) & 0xf) << 2) | (read(2) >> 6)];
+    buf[3] = kBase64[read(2) & 0x3f];
+    Write(view);
+    ptr += 3;
+  }
+
+  switch (end - ptr) {
+    case 2:
+      buf[0] = kBase64[read(0) >> 2];
+      buf[1] = kBase64[((read(0) & 0x3) << 4) | (read(1) >> 4)];
+      buf[2] = kBase64[(read(1) & 0xf) << 2];
+      buf[3] = '=';
+      Write(view);
+      break;
+    case 1:
+      buf[0] = kBase64[read(0) >> 2];
+      buf[1] = kBase64[((read(0) & 0x3) << 4)];
+      buf[2] = '=';
+      buf[3] = '=';
+      Write(view);
+      break;
+  }
+
+  Write("\"");
+}
+
+// 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 constexpr uint16_t kMinHighSurrogate = 0xd800;
+
+// 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 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 constexpr uint16_t kMaxLowSurrogate = 0xdfff;
+
+// The minimum value of a unicode supplementary code point.
+// See http://www.unicode.org/glossary/#supplementary_code_point
+static constexpr uint32_t kMinSupplementaryCodePoint = 0x010000;
+
+// The maximum value of a unicode code point.
+// See http://www.unicode.org/glossary/#code_point
+static constexpr uint32_t kMaxCodePoint = 0x10ffff;
+
+// Indicates decoding failure; not a valid Unicode scalar.
+static constexpr uint32_t kErrorSentinel = 0xaaaaaaaa;
+
+// A Unicode Scalar encoded two ways.
+struct Utf8Scalar {
+  // The Unicode scalar value as a 32-bit integer. If decoding failed, this
+  // is equal to kErrorSentinel.
+  uint32_t u32;
+  // The Unicode scalar value encoded as UTF-8 bytes. May not reflect the
+  // contents of `u32` if it is kErrorSentinel.
+  absl::string_view utf8;
+};
+
+// Parses a single UTF-8-encoded Unicode scalar from `str`. Returns a pair of
+// the scalar and the UTF-8-encoded content corresponding to it from `str`.
+//
+// Returns U+FFFD on failure, and consumes an unspecified number of bytes in
+// doing so.
+static Utf8Scalar ConsumeUtf8Scalar(absl::string_view& str) {
+  GOOGLE_DCHECK(!str.empty());
+  uint32_t scalar = static_cast<uint8_t>(str[0]);
+  const char* start = str.data();
+  size_t len = 1;
+
+  str = str.substr(1);
+
+  // Verify this is valid UTF-8. UTF-8 is a varint encoding satisfying
+  // one of the following (big-endian) patterns:
+  //
+  // 0b0xxxxxxx
+  // 0b110xxxxx'10xxxxxx
+  // 0b1110xxxx'10xxxxxx'10xxxxxx
+  // 0b11110xxx'10xxxxxx'10xxxxxx'10xxxxxx
+  //
+  // We don't need to decode it; just validate it.
+  int lookahead = 0;
+  switch (absl::countl_one(static_cast<uint8_t>(scalar))) {
+    case 0:
+      break;
+    case 2:
+      lookahead = 1;
+      scalar &= (1 << 5) - 1;
+      break;
+    case 3:
+      lookahead = 2;
+      scalar &= (1 << 4) - 1;
+      break;
+    case 4:
+      lookahead = 3;
+      scalar &= (1 << 3) - 1;
+      break;
+    default:
+      scalar = kErrorSentinel;
+      break;
+  }
+
+  for (int i = 0; i < lookahead; ++i) {
+    if (str.empty()) {
+      scalar = kErrorSentinel;
+      break;
+    }
+
+    uint8_t next = str[0];
+    str = str.substr(1);
+    ++len;
+
+    // Looking for top 2 bits are 0b10.
+    if (next >> 6 != 2) {
+      scalar = kErrorSentinel;
+      break;
+    }
+    next &= (1 << 6) - 1;
+    scalar <<= 6;
+    scalar |= next;
+  }
+
+  if (scalar > kMaxCodePoint) {
+    scalar = kErrorSentinel;
+  }
+
+  return {scalar, absl::string_view(start, len)};
+}
+
+// Decides whether we must escape `scalar`.
+//
+// If the given Unicode scalar would not use a \u escape, `custom_escape` will
+// be set to a non-empty string.
+static bool MustEscape(uint32_t scalar, absl::string_view& custom_escape) {
+  switch (scalar) {
+    // These escapes are defined by the JSON spec. We do not escape /.
+    case '\n':
+      custom_escape = R"(\n)";
+      return true;
+    case '\r':
+      custom_escape = R"(\r)";
+      return true;
+    case '\t':
+      custom_escape = R"(\t)";
+      return true;
+    case '\"':
+      custom_escape = R"(\")";
+      return true;
+    case '\f':
+      custom_escape = R"(\f)";
+      return true;
+    case '\b':
+      custom_escape = R"(\b)";
+      return true;
+    case '\\':
+      custom_escape = R"(\\)";
+      return true;
+
+    case kErrorSentinel:
+      // Decoding failure turns into spaces, *not* replacement characters. We
+      // handle this separately from "normal" spaces so that it follows the
+      // escaping code-path.
+      //
+      // Note that literal replacement characters in the input string DO NOT
+      // get turned into spaces; this is only for decoding failures!
+      custom_escape = " ";
+      return true;
+
+    // These are not required by the JSON spec, but help
+    // to prevent security bugs in JavaScript.
+    //
+    // These were originally present in the ESF parser, so they are kept for
+    // legacy compatibility (and because escaping most of these is in good
+    // taste, regardless).
+    case '<':
+    case '>':
+    case 0xfeff:      // Zero width no-break space.
+    case 0xfff9:      // Interlinear annotation anchor.
+    case 0xfffa:      // Interlinear annotation separator.
+    case 0xfffb:      // Interlinear annotation terminator.
+    case 0x00ad:      // Soft-hyphen.
+    case 0x06dd:      // Arabic end of ayah.
+    case 0x070f:      // Syriac abbreviation mark.
+    case 0x17b4:      // Khmer vowel inherent Aq.
+    case 0x17b5:      // Khmer vowel inherent Aa.
+    case 0x000e0001:  // Language tag.
+      return true;
+    default:
+      static constexpr std::pair<uint32_t, uint32_t> kEscapedRanges[] = {
+          {0x0000, 0x001f},          // ASCII control.
+          {0x007f, 0x009f},          // High ASCII bytes.
+          {0x0600, 0x0603},          // Arabic signs.
+          {0x200b, 0x200f},          // Zero width etc.
+          {0x2028, 0x202e},          // Separators etc.
+          {0x2060, 0x2064},          // Invisible etc.
+          {0x206a, 0x206f},          // Shaping etc.
+          {0x0001d173, 0x0001d17a},  // Music formatting.
+          {0x000e0020, 0x000e007f},  // TAG symbols.
+      };
+
+      return absl::c_any_of(kEscapedRanges, [scalar](auto range) {
+        return range.first <= scalar && scalar <= range.second;
+      });
+  }
+}
+
+void JsonWriter::WriteEscapedUtf8(absl::string_view str) {
+  while (!str.empty()) {
+    auto scalar = ConsumeUtf8Scalar(str);
+    absl::string_view custom_escape;
+
+    if (!MustEscape(scalar.u32, custom_escape)) {
+      Write(scalar.utf8);
+      continue;
+    }
+
+    if (!custom_escape.empty()) {
+      Write(custom_escape);
+      continue;
+    }
+
+    if (scalar.u32 < 0x10000) {
+      WriteUEscape(scalar.u32);
+      continue;
+    }
+
+    uint16_t lo =
+        (scalar.u32 & (kMaxLowSurrogate - kMinLowSurrogate)) + kMinLowSurrogate;
+    uint16_t hi = (scalar.u32 >> 10) +
+                  (kMinHighSurrogate - (kMinSupplementaryCodePoint >> 10));
+    WriteUEscape(hi);
+    WriteUEscape(lo);
+  }
+}
+
+void JsonWriter::WriteUEscape(uint16_t val) {
+  char hex[7];
+  int len = absl::SNPrintF(hex, sizeof(hex), R"(\u%04x)", val);
+  Write(absl::string_view(hex, static_cast<size_t>(len)));
+}
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/json/internal/writer.h b/src/google/protobuf/json/internal/writer.h
new file mode 100644
index 0000000..31a7de7
--- /dev/null
+++ b/src/google/protobuf/json/internal/writer.h
@@ -0,0 +1,241 @@
+// 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_JSON_INTERNAL_WRITER_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_WRITER_H__
+
+#include <cfloat>
+#include <cmath>
+#include <cstdint>
+#include <iostream>
+#include <limits>
+#include <ostream>
+#include <string>
+#include <tuple>
+#include <type_traits>
+#include <utility>
+
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/io/zero_copy_sink.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+struct WriterOptions {
+  // Whether to add spaces, line breaks and indentation to make the JSON output
+  // easy to read.
+  bool add_whitespace = false;
+  // Whether to always print primitive fields. By default proto3 primitive
+  // fields with default values will be omitted in JSON output. For example, an
+  // int32 field set to 0 will be omitted. Set this flag to true will override
+  // the default behavior and print primitive fields regardless of their values.
+  bool always_print_primitive_fields = false;
+  // Whether to always print enums as ints. By default they are rendered as
+  // strings.
+  bool always_print_enums_as_ints = false;
+  // Whether to preserve proto field names
+  bool preserve_proto_field_names = false;
+  // The original parser used by json_util2 accepted a number of non-standard
+  // options. Setting this flag enables them.
+  //
+  // What those extensions were is explicitly not documented, beyond what exists
+  // in the unit tests; we intend to remove this setting eventually. See
+  // b/234868512.
+  bool allow_legacy_syntax = false;
+};
+
+template <typename Tuple, typename F, size_t... i>
+void EachInner(const Tuple& value, F f, std::index_sequence<i...>) {
+  int ignored[] = {
+      (f(std::get<i>(value)), 0)...};  // NOLINT(readability/braces)
+  (void)ignored;
+}
+
+// Executes f on each element of value.
+template <typename Tuple, typename F>
+void Each(const Tuple& value, F f) {
+  EachInner(value, f,
+            std::make_index_sequence<std::tuple_size<Tuple>::value>());
+}
+
+// See JsonWriter::Write().
+template <typename... T>
+struct Quoted {
+  std::tuple<T...> value;
+};
+
+// Because this is not C++17 yet, we cannot add a deduction guide.
+template <typename... T>
+static Quoted<T...> MakeQuoted(T... t) {
+  return Quoted<T...>{std::make_tuple(t...)};
+}
+
+class JsonWriter {
+ public:
+  JsonWriter(io::ZeroCopyOutputStream* out, WriterOptions options)
+      : sink_(out), options_(options) {}
+
+  const WriterOptions& options() const { return options_; }
+
+  void Push() { ++indent_; }
+  void Pop() { --indent_; }
+
+  // The many overloads of Write() will write a value to the underlying stream.
+  // Some values may want to be quoted; the Quoted<> type will automatically add
+  // quotes and escape sequences.
+  //
+  // Note that Write() is not implemented for 64-bit integers, since they
+  // cannot be crisply represented without quotes; use MakeQuoted for that.
+
+  void Write(absl::string_view str) { sink_.Append(str.data(), str.size()); }
+
+  void Write(char c) { sink_.Append(&c, 1); }
+
+  // The precision on this and the following function are completely made-up,
+  // in an attempt to match the behavior of the ESF parser.
+  void Write(double val) {
+    if (!MaybeWriteSpecialFp(val)) {
+      Write(io::SimpleDtoa(val));
+    }
+  }
+
+  void Write(float val) {
+    if (!MaybeWriteSpecialFp(val)) {
+      Write(io::SimpleFtoa(val));
+    }
+  }
+
+  void Write(int32_t val) {
+    char buf[22];
+    int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
+    absl::string_view view(buf, static_cast<size_t>(len));
+    Write(view);
+  }
+
+  void Write(uint32_t val) {
+    char buf[22];
+    int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
+    absl::string_view view(buf, static_cast<size_t>(len));
+    Write(view);
+  }
+
+  void Write(int64_t) = delete;
+  void Write(uint64_t) = delete;
+
+  template <typename... Ts>
+  void Write(Quoted<Ts...> val) {
+    Write('"');
+    Each(val.value, [this](auto x) { this->WriteQuoted(x); });
+    Write('"');
+  }
+
+  template <typename... Ts>
+  auto Write(Ts... args) ->
+      // This bit of SFINAE avoids this function being called with one argument,
+      // so the other overloads of Write() can be picked up instead.
+      typename std::enable_if<sizeof...(Ts) != 1, void>::type {
+    Each(std::make_tuple(args...), [this](auto x) { this->Write(x); });
+  }
+
+  void Whitespace(absl::string_view ws) {
+    if (options_.add_whitespace) {
+      Write(ws);
+    }
+  }
+
+  void NewLine() {
+    Whitespace("\n");
+    for (int i = 0; i < indent_; ++i) {
+      Whitespace(" ");
+    }
+  }
+
+  void WriteComma(bool& is_first) {
+    if (is_first) {
+      is_first = false;
+      return;
+    }
+    Write(",");
+  }
+
+  void WriteBase64(absl::string_view str);
+
+  // Returns a buffer that can be re-used throughout a writing session as
+  // variable-length scratch space.
+  std::string& ScratchBuf() { return scratch_buf_; }
+
+ private:
+  template <typename T>
+  void WriteQuoted(T val) {
+    Write(val);
+  }
+
+  void WriteQuoted(absl::string_view val) { WriteEscapedUtf8(val); }
+
+  void WriteQuoted(int64_t val) {
+    char buf[22];
+    int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
+    absl::string_view view(buf, static_cast<size_t>(len));
+    Write(view);
+  }
+
+  void WriteQuoted(uint64_t val) {
+    char buf[22];
+    int len = absl::SNPrintF(buf, sizeof(buf), "%d", val);
+    absl::string_view view(buf, static_cast<size_t>(len));
+    Write(view);
+  }
+
+  // Tries to write a non-finite double if necessary; returns false if
+  // nothing was written.
+  bool MaybeWriteSpecialFp(double val);
+
+  void WriteEscapedUtf8(absl::string_view str);
+  void WriteUEscape(uint16_t val);
+
+  io::zc_sink_internal::ZeroCopyStreamByteSink sink_;
+  WriterOptions options_;
+  int indent_ = 0;
+
+  std::string scratch_buf_;
+};
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_WRITER_H__
diff --git a/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc b/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc
new file mode 100644
index 0000000..9801ed2
--- /dev/null
+++ b/src/google/protobuf/json/internal/zero_copy_buffered_stream.cc
@@ -0,0 +1,148 @@
+// 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/json/internal/zero_copy_buffered_stream.h"
+
+#include <algorithm>
+#include <iterator>
+#include <string>
+#include <utility>
+
+#include "absl/algorithm/container.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+absl::Status ZeroCopyBufferedStream::Advance(size_t bytes) {
+  while (bytes != 0) {
+    if (Unread().empty() && !ReadChunk()) {
+      return absl::InvalidArgumentError("unexpected EOF");
+    }
+    size_t to_skip = std::min(bytes, Unread().size());
+    cursor_ += to_skip;
+    bytes -= to_skip;
+  }
+
+  if (using_buf_) {
+    GOOGLE_DCHECK_LE(cursor_, buffer_start_ + buf_.size());
+  } else {
+    GOOGLE_DCHECK_LE(cursor_, last_chunk_.size());
+  }
+
+  return absl::OkStatus();
+}
+
+absl::StatusOr<BufferingGuard> ZeroCopyBufferedStream::BufferAtLeast(
+    size_t bytes) {
+  // This MUST be an empty guard before the first call to ReadChunk();
+  // otherwise we risk unconditional buffering.
+  BufferingGuard guard;
+  while (Unread().size() < bytes) {
+    if (!Unread().empty()) {
+      // We must buffer before reading if Unread() is nonempty; otherwise we
+      // risk discarding part of the unread buffer. However, we must NOT
+      // buffer before calling ReadChunk if it *is* empty, because then we
+      // would buffer unconditionally.
+      //
+      // There are tests to verify both of these cases.
+      guard = BufferingGuard(this);
+    }
+    if (!ReadChunk()) {
+      return absl::InvalidArgumentError("unexpected EOF");
+    }
+    guard = BufferingGuard(this);
+  }
+  GOOGLE_DCHECK_GE(Unread().size(), bytes);
+  return BufferingGuard(this);
+}
+
+void ZeroCopyBufferedStream::DownRefBuffer() {
+  GOOGLE_DCHECK_GT(outstanding_buffer_borrows_, 0);
+
+  --outstanding_buffer_borrows_;
+  if (outstanding_buffer_borrows_ > 0 || !using_buf_) {
+    return;
+  }
+
+  // The "virtual length" is the size of the buffer cursor_ indexes into, which
+  // is bigger than buf_.
+  size_t virtual_buf_len = buf_.size() + buffer_start_;
+  size_t last_chunk_in_buf = virtual_buf_len - last_chunk_.size();
+  // If we are inside of `last_chunk_`, set the cursor there; otherwise, we have
+  // a dangling reference somewhere.
+  GOOGLE_DCHECK_LE(last_chunk_in_buf, virtual_buf_len) << absl::StrFormat(
+      "%d, %d, %d", buf_.size(), last_chunk_.size(), buffer_start_);
+  if (cursor_ <= last_chunk_in_buf) {
+    cursor_ = 0;
+  } else {
+    cursor_ -= last_chunk_in_buf;
+  }
+  buf_.clear();
+  using_buf_ = false;
+}
+
+bool ZeroCopyBufferedStream::ReadChunk() {
+  if (eof_) {
+    return false;
+  }
+  // We are buffering a second chunk, so we need to put the current chunk
+  // into the buffer.
+  if (outstanding_buffer_borrows_ > 0 && !using_buf_) {
+    absl::c_copy(RawBuffer(buffer_start_), std::back_inserter(buf_));
+    using_buf_ = true;
+  }
+
+  const void* data;
+  int len;
+  if (!stream_->Next(&data, &len)) {
+    eof_ = true;
+    return false;
+  }
+
+  last_chunk_ = absl::string_view(static_cast<const char*>(data),
+                                  static_cast<size_t>(len));
+  if (using_buf_) {
+    absl::c_copy(last_chunk_, std::back_inserter(buf_));
+    // Cursor does not need to move, because it is still inside of `buf_`.
+  } else {
+    cursor_ = 0;
+    buffer_start_ = 0;
+  }
+  return true;
+}
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/json/internal/zero_copy_buffered_stream.h b/src/google/protobuf/json/internal/zero_copy_buffered_stream.h
new file mode 100644
index 0000000..dc081e0
--- /dev/null
+++ b/src/google/protobuf/json/internal/zero_copy_buffered_stream.h
@@ -0,0 +1,355 @@
+// 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_JSON_INTERNAL_ZERO_COPY_BUFFERED_STREAM_H__
+#define GOOGLE_PROTOBUF_JSON_INTERNAL_ZERO_COPY_BUFFERED_STREAM_H__
+
+#include <algorithm>
+#include <cstdint>
+#include <iostream>
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+// Utilities for parsing contiguous buffers out of ZeroCopyInputStreams.
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+// Forward decl. for use by helper types below.
+class ZeroCopyBufferedStream;
+
+// An RAII type that represents holding a reference into the backing buffer
+// of a ZeroCopyBufferedStream. This allows for automatic management of the
+// backing buffer.
+class BufferingGuard {
+ public:
+  explicit BufferingGuard(ZeroCopyBufferedStream* owner = nullptr);
+  ~BufferingGuard();
+
+  BufferingGuard(const BufferingGuard& other) : BufferingGuard(other.owner_) {}
+  BufferingGuard& operator=(const BufferingGuard& other) {
+    this->~BufferingGuard();
+    new (this) BufferingGuard(other);
+    return *this;
+  }
+
+ private:
+  friend class Mark;
+  ZeroCopyBufferedStream* owner_ = nullptr;
+};
+
+// A string that may own its contents, or live inside of a buffer owned by
+// a ZeroCopyBufferedStream.
+//
+// Note that this type holds onto a reference to the owning
+// ZeroCopyBufferedStream; this allows it to be durable against strings being
+// moved around for buffering puroses.
+class MaybeOwnedString {
+ public:
+  explicit MaybeOwnedString(std::string value) : data_(std::move(value)) {}
+  MaybeOwnedString(ZeroCopyBufferedStream* stream, size_t start, size_t len,
+                   BufferingGuard token)
+      : data_(StreamOwned{stream, start, len}), token_(token) {}
+
+  // Returns the string as a view, regardless of whether it is owned or not.
+  absl::string_view AsView() const {
+    if (auto* unowned = absl::get_if<StreamOwned>(&data_)) {
+      return unowned->AsView();
+    }
+
+    return absl::get<std::string>(data_);
+  }
+
+  operator absl::string_view() const { return AsView(); }  // NOLINT
+
+  // Returns a reference to an owned string; if the wrapped string is not
+  // owned, this function will perform a copy and make it owned.
+  std::string& ToString() {
+    if (auto* unowned = absl::get_if<StreamOwned>(&data_)) {
+      data_ = std::string(unowned->AsView());
+      token_ = BufferingGuard{};
+    }
+
+    return absl::get<std::string>(data_);
+  }
+
+  template <typename String>
+  friend bool operator==(const MaybeOwnedString& lhs, const String& rhs) {
+    return lhs.AsView() == rhs;
+  }
+  template <typename String>
+  friend bool operator!=(const MaybeOwnedString& lhs, const String& rhs) {
+    return !(lhs == rhs);
+  }
+
+ private:
+  struct StreamOwned {
+    ZeroCopyBufferedStream* stream;
+    size_t start, len;
+    absl::string_view AsView() const;
+  };
+  absl::variant<std::string, StreamOwned> data_;
+  BufferingGuard token_;
+};
+
+// A mark in a stream. See ZeroCopyBufferedStream::Mark().
+class Mark {
+ public:
+  // Returns a maybe-owned string up to the unread bytes boundary, except for
+  // the last `clip` bytes.
+  MaybeOwnedString UpToUnread(size_t clip = 0) const;
+
+  // Discards this mark and its hold on the buffer.
+  void Discard() && { guard_ = BufferingGuard(); }
+
+ private:
+  friend ZeroCopyBufferedStream;
+  Mark(size_t offset, BufferingGuard guard) : offset_(offset), guard_(guard) {}
+
+  size_t offset_;
+  BufferingGuard guard_;
+};
+
+// A wrapper over a ZeroCopyInputStream that allows doing as-needed buffer for
+// obtaining contiguous chunks larger than those the underlying stream might
+// provide, while minimizing the amount of actual copying.
+class ZeroCopyBufferedStream {
+ public:
+  explicit ZeroCopyBufferedStream(io::ZeroCopyInputStream* stream)
+      : stream_(stream) {}
+
+  // Returns whether the stream is currently at eof.
+  //
+  // This function will buffer at least one character to verify whether it
+  // actually *is* at EOF.
+  bool AtEof() {
+    (void)BufferAtLeast(1);
+    return eof_;
+  }
+
+  // Takes exactly n characters from a string.
+  absl::StatusOr<MaybeOwnedString> Take(size_t len) {
+    auto buffering = BufferAtLeast(len);
+    RETURN_IF_ERROR(buffering.status());
+
+    size_t start = cursor_;
+    RETURN_IF_ERROR(Advance(len));
+    return MaybeOwnedString(this, start, len, *buffering);
+  }
+
+  // Takes characters to form a string, according to the given predicate. Stops
+  // early if an EOF is hit.
+  //
+  // The predicate must have type `(int, char) -> bool`; the first argument
+  // is the index of the character.
+  template <typename Pred>
+  absl::StatusOr<MaybeOwnedString> TakeWhile(Pred p);
+
+  // Places a mark in the stream, ensuring that all characters consumed after
+  // the mark are buffered. This can be used to parse some characters and then
+  // recover everything that follows as a contiguous string_view so that it may
+  // be processed a second time.
+  //
+  // The returned value is an RAII type that ensure the buffer sticks around
+  // long enough.
+  Mark BeginMark() { return Mark(cursor_, BufferingGuard(this)); }
+
+  // Peeks the next character in the stream.
+  //
+  // This function will not enable buffering on its own, and will read past the
+  // end of the buffer if at EOF; BufferAtLeast() should be called before
+  // calling this function.
+  char PeekChar() {
+    GOOGLE_DCHECK(!Unread().empty());
+    return Unread()[0];
+  }
+
+  // Advances the cursor by the given number of bytes.
+  absl::Status Advance(size_t bytes);
+
+  // Returns a view of the current buffer, which may be either the owned
+  // `buf_` or the stream-owned `last_chunk_`.
+  //
+  // The returned view is unstable: calling any function may invalidate it,
+  // because there will not be a `BufferingGuard` to guard it.
+  absl::string_view RawBuffer(size_t start,
+                              size_t len = absl::string_view::npos) const;
+
+  // Returns a view of RawBuffer, unread bytes; this will not be the entirety
+  // of the underlying stream.
+  absl::string_view Unread() const { return RawBuffer(cursor_); }
+
+  bool IsBuffering() const { return using_buf_; }
+
+  // Buffers at least `bytes` bytes ahead of the current cursor position,
+  // possibly enabling buffering.
+  //
+  // Returns an error if that many bytes could not be RawBuffer.
+  absl::StatusOr<BufferingGuard> BufferAtLeast(size_t bytes);
+
+ private:
+  friend BufferingGuard;
+  friend Mark;
+  friend MaybeOwnedString;
+
+  // Increments the buffering refcount; this will also update `buffer_start_` if
+  // necessary.
+  void UpRefBuffer() {
+    if (outstanding_buffer_borrows_++ == 0) {
+      buffer_start_ = cursor_;
+    }
+  }
+
+  // Decrements the buffering refcount; calling this function if the refcount is
+  // zero is undefined behavior.
+  //
+  // This function should not be called directly; it is called automatically
+  // by the destructor of `BufferingGuard`.
+  void DownRefBuffer();
+
+  // Obtains a new chunk from the underlying stream; returns whether there is
+  // still more data to read.
+  bool ReadChunk();
+
+  // The streamer implements a buffering stream on top of the given stream, by
+  // the following mechanism:
+  // - `cursor_` is an offset into either `last_chunk_` or `buf_`, which can
+  //   be obtained via RawBuffer() and Unread():
+  //   - If `using_buf_` is true, it is an offset into `buf_`.
+  //   - Otherwise it is an offset into `last_chunk_`.
+  // - If `outstanding_buffer_borrows_ > 0`, someone needs the buffer to stick
+  //   around. MaybeUnownedString::StreamOwned is implemented such that it does
+  //   not hold onto `last_chunk_` directly, so we can freely copy it into
+  //   `buf_` as needed arises.
+  //   - Note that we can copy only part if we update `buffer_start_`; see
+  //     RawBuffer().
+  // - If we would read more data and `outstanding_buffer_borrows_ > 0`, instead
+  //   of trashing `last_chunk_`, we copy it into `buf_` and append to `buf_`
+  //   each time we read.
+  // - If `outstanding_buffer_borrows_ == 0`, we can trash `buf_` and go back to
+  //   using `last_chunk_` directly. See `DownRefBuffer()`.
+  io::ZeroCopyInputStream* stream_;
+  absl::string_view last_chunk_;
+  std::vector<char> buf_;
+  bool using_buf_ = false;
+  size_t cursor_ = 0;
+  // Invariant: this always refers to the earliest point at which we requested
+  // buffering, since the last time outstanding_buffer_borrows_ was zero.
+  size_t buffer_start_ = 0;
+  bool eof_ = false;
+  int outstanding_buffer_borrows_ = 0;
+};
+
+// These functions all rely on the definition of ZeroCopyBufferedStream, so must
+// come after it.
+inline BufferingGuard::BufferingGuard(ZeroCopyBufferedStream* owner)
+    : owner_(owner) {
+  if (owner_ != nullptr) {
+    owner_->UpRefBuffer();
+  }
+}
+
+inline BufferingGuard::~BufferingGuard() {
+  if (owner_ != nullptr) {
+    owner_->DownRefBuffer();
+    owner_ = nullptr;
+  }
+}
+
+inline absl::string_view MaybeOwnedString::StreamOwned::AsView() const {
+  return stream->RawBuffer(start, len);
+}
+
+inline MaybeOwnedString Mark::UpToUnread(size_t clip) const {
+  return MaybeOwnedString(guard_.owner_, offset_,
+                          guard_.owner_->cursor_ - offset_ - clip, guard_);
+}
+
+template <typename Pred>
+absl::StatusOr<MaybeOwnedString> ZeroCopyBufferedStream::TakeWhile(Pred p) {
+  size_t start = cursor_;
+  BufferingGuard guard(this);
+  while (true) {
+    if (!BufferAtLeast(1).ok()) {
+      // We treat EOF as ending the take, rather than being an error.
+      break;
+    }
+    if (!p(cursor_ - start, PeekChar())) {
+      break;
+    }
+    RETURN_IF_ERROR(Advance(1));
+  }
+
+  return MaybeOwnedString(this, start, cursor_ - start, guard);
+}
+
+inline absl::string_view ZeroCopyBufferedStream::RawBuffer(size_t start,
+                                                           size_t len) const {
+  absl::string_view view = last_chunk_;
+  if (using_buf_) {
+    GOOGLE_DCHECK_LE(buffer_start_, start);
+    start -= buffer_start_;
+    view = absl::string_view(buf_.data(), buf_.size());
+  }
+#if 0
+    // This print statement is especially useful for trouble-shooting low-level
+    // bugs in the buffering logic.
+    GOOGLE_LOG(INFO) << absl::StreamFormat("%s(\"%s\")[%d:%d]/%d:%d @ %p",
+                                    using_buf_ ? "buf_" : "last_chunk_",
+                                    view, start, static_cast<int>(len),
+                                    buffer_start_, cursor_, this);
+#endif
+  GOOGLE_DCHECK_LE(start, view.size());
+  if (len == absl::string_view::npos) {
+    return view.substr(start);
+  }
+
+  GOOGLE_DCHECK_LE(start + len, view.size());
+  return view.substr(start, len);
+}
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+#endif  // GOOGLE_PROTOBUF_JSON_INTERNAL_ZERO_COPY_BUFFERED_STREAM_H__
diff --git a/src/google/protobuf/json/internal/zero_copy_buffered_stream_test.cc b/src/google/protobuf/json/internal/zero_copy_buffered_stream_test.cc
new file mode 100644
index 0000000..714062e
--- /dev/null
+++ b/src/google/protobuf/json/internal/zero_copy_buffered_stream_test.cc
@@ -0,0 +1,165 @@
+// 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/json/internal/zero_copy_buffered_stream.h"
+
+#include <string>
+#include <utility>
+#include <vector>
+
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/json/internal/test_input_stream.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+namespace google {
+namespace protobuf {
+namespace json_internal {
+namespace {
+// TODO(b/234474291): Use the gtest versions once that's available in OSS.
+MATCHER_P(IsOkAndHolds, inner,
+          absl::StrCat("is OK and holds ", testing::PrintToString(inner))) {
+  if (!arg.ok()) {
+    *result_listener << arg.status();
+    return false;
+  }
+  return testing::ExplainMatchResult(inner, *arg, result_listener);
+}
+
+absl::Status GetStatus(const absl::Status& s) { return s; }
+template <typename T>
+absl::Status GetStatus(const absl::StatusOr<T>& s) {
+  return s.status();
+}
+
+MATCHER_P(StatusIs, status,
+          absl::StrCat(".status() is ", testing::PrintToString(status))) {
+  return GetStatus(arg).code() == status;
+}
+
+#define EXPECT_OK(x) EXPECT_THAT(x, StatusIs(absl::StatusCode::kOk))
+#define ASSERT_OK(x) ASSERT_THAT(x, StatusIs(absl::StatusCode::kOk))
+
+TEST(ZcBufferTest, ReadUnbuffered) {
+  TestInputStream in{"foo", "bar", "baz"};
+  ZeroCopyBufferedStream stream(&in);
+
+  {
+    auto chunk = stream.Take(3);
+    EXPECT_FALSE(stream.IsBuffering());
+    EXPECT_THAT(chunk, IsOkAndHolds("foo"));
+  }
+
+  {
+    auto chunk = stream.Take(3);
+    EXPECT_FALSE(stream.IsBuffering());
+    EXPECT_THAT(chunk, IsOkAndHolds("bar"));
+  }
+
+  {
+    auto chunk = stream.Take(3);
+    EXPECT_FALSE(stream.IsBuffering());
+    EXPECT_THAT(chunk, IsOkAndHolds("baz"));
+  }
+}
+
+TEST(ZcBufferTest, ReadBuffered) {
+  TestInputStream in{"foo", "bar", "baz"};
+  ZeroCopyBufferedStream stream(&in);
+
+  {
+    auto chunk = stream.Take(4);
+    EXPECT_TRUE(stream.IsBuffering());
+    EXPECT_THAT(chunk, IsOkAndHolds("foob"));
+  }
+
+  {
+    auto chunk = stream.Take(2);
+    EXPECT_FALSE(stream.IsBuffering());
+    EXPECT_THAT(chunk, IsOkAndHolds("ar"));
+  }
+}
+
+TEST(ZcBufferTest, HoldAcrossSeam) {
+  TestInputStream in{"foo", "bar", "baz"};
+  ZeroCopyBufferedStream stream(&in);
+
+  auto chunk = stream.Take(3);
+  EXPECT_FALSE(stream.IsBuffering());
+  EXPECT_THAT(chunk, IsOkAndHolds("foo"));
+
+  auto chunk2 = stream.Take(3);
+  EXPECT_TRUE(stream.IsBuffering());
+  EXPECT_THAT(chunk2, IsOkAndHolds("bar"));
+  EXPECT_THAT(chunk, IsOkAndHolds("foo"));
+}
+
+TEST(ZcBufferTest, BufferAcrossSeam) {
+  TestInputStream in{"foo", "bar", "baz"};
+  ZeroCopyBufferedStream stream(&in);
+
+  auto chunk = stream.Take(2);
+  EXPECT_FALSE(stream.IsBuffering());
+  EXPECT_THAT(chunk, IsOkAndHolds("fo"));
+
+  auto chunk2 = stream.Take(3);
+  EXPECT_TRUE(stream.IsBuffering());
+  EXPECT_THAT(chunk2, IsOkAndHolds("oba"));
+  EXPECT_THAT(chunk, IsOkAndHolds("fo"));
+}
+
+TEST(ZcBufferTest, MarkUnbuffered) {
+  TestInputStream in{"foo", "bar", "baz"};
+  ZeroCopyBufferedStream stream(&in);
+
+  ASSERT_OK(stream.Advance(1));
+  auto mark = stream.BeginMark();
+  ASSERT_OK(stream.Advance(2));
+  EXPECT_FALSE(stream.IsBuffering());
+  EXPECT_THAT(mark.UpToUnread(), "oo");
+}
+
+TEST(ZcBufferTest, MarkBuffered) {
+  TestInputStream in{"foo", "bar", "baz"};
+  ZeroCopyBufferedStream stream(&in);
+
+  ASSERT_OK(stream.Advance(1));
+  auto mark = stream.BeginMark();
+  ASSERT_OK(stream.Advance(5));
+  EXPECT_TRUE(stream.IsBuffering());
+  EXPECT_THAT(mark.UpToUnread(), "oobar");
+}
+}  // namespace
+}  // namespace json_internal
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/json/json.cc b/src/google/protobuf/json/json.cc
new file mode 100644
index 0000000..6cbc0bb
--- /dev/null
+++ b/src/google/protobuf/json/json.cc
@@ -0,0 +1,133 @@
+// 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/json/json.h"
+
+#include <string>
+
+#include "absl/status/status.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/json/internal/parser.h"
+#include "google/protobuf/json/internal/unparser.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json {
+
+absl::Status BinaryToJsonStream(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* binary_input,
+                                io::ZeroCopyOutputStream* json_output,
+                                const PrintOptions& options) {
+  google::protobuf::json_internal::WriterOptions opts;
+  opts.add_whitespace = options.add_whitespace;
+  opts.preserve_proto_field_names = options.preserve_proto_field_names;
+  opts.always_print_enums_as_ints = options.always_print_enums_as_ints;
+  opts.always_print_primitive_fields = options.always_print_primitive_fields;
+
+  // TODO(b/234868512): Drop this setting.
+  opts.allow_legacy_syntax = true;
+
+  return google::protobuf::json_internal::BinaryToJsonStream(
+      resolver, type_url, binary_input, json_output, opts);
+}
+
+absl::Status BinaryToJsonString(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                const std::string& binary_input,
+                                std::string* json_output,
+                                const PrintOptions& 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,
+                            options);
+}
+
+absl::Status JsonToBinaryStream(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                io::ZeroCopyInputStream* json_input,
+                                io::ZeroCopyOutputStream* binary_output,
+                                const ParseOptions& options) {
+  google::protobuf::json_internal::ParseOptions opts;
+  opts.ignore_unknown_fields = options.ignore_unknown_fields;
+  opts.case_insensitive_enum_parsing = options.case_insensitive_enum_parsing;
+
+  // TODO(b/234868512): Drop this setting.
+  opts.allow_legacy_syntax = true;
+
+  return google::protobuf::json_internal::JsonToBinaryStream(
+      resolver, type_url, json_input, binary_output, opts);
+}
+
+absl::Status JsonToBinaryString(google::protobuf::util::TypeResolver* resolver,
+                                const std::string& type_url,
+                                absl::string_view json_input,
+                                std::string* binary_output,
+                                const ParseOptions& 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,
+                            options);
+}
+
+absl::Status MessageToJsonString(const Message& message, std::string* output,
+                                 const PrintOptions& options) {
+  google::protobuf::json_internal::WriterOptions opts;
+  opts.add_whitespace = options.add_whitespace;
+  opts.preserve_proto_field_names = options.preserve_proto_field_names;
+  opts.always_print_enums_as_ints = options.always_print_enums_as_ints;
+  opts.always_print_primitive_fields = options.always_print_primitive_fields;
+
+  // TODO(b/234868512): Drop this setting.
+  opts.allow_legacy_syntax = true;
+
+  return google::protobuf::json_internal::MessageToJsonString(message, output, opts);
+}
+
+absl::Status JsonStringToMessage(absl::string_view input, Message* message,
+                                 const ParseOptions& options) {
+  google::protobuf::json_internal::ParseOptions opts;
+  opts.ignore_unknown_fields = options.ignore_unknown_fields;
+  opts.case_insensitive_enum_parsing = options.case_insensitive_enum_parsing;
+
+  // TODO(b/234868512): Drop this setting.
+  opts.allow_legacy_syntax = true;
+
+  return google::protobuf::json_internal::JsonStringToMessage(input, message, opts);
+}
+}  // namespace json
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/json/json.h b/src/google/protobuf/json/json.h
new file mode 100644
index 0000000..531de6b
--- /dev/null
+++ b/src/google/protobuf/json/json.h
@@ -0,0 +1,190 @@
+// 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.
+
+// Utility functions to convert between protobuf binary format and proto3 JSON
+// format.
+#ifndef GOOGLE_PROTOBUF_JSON_JSON_H__
+#define GOOGLE_PROTOBUF_JSON_JSON_H__
+
+#include <string>
+
+#include "absl/status/status.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/util/type_resolver.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json {
+struct ParseOptions {
+  // Whether to ignore unknown JSON fields during parsing
+  bool ignore_unknown_fields = false;
+
+  // If true, when a lowercase enum value fails to parse, try convert it to
+  // UPPER_CASE and see if it matches a valid enum.
+  // WARNING: This option exists only to preserve legacy behavior. Avoid using
+  // this option. If your enum needs to support different casing, consider using
+  // allow_alias instead.
+  bool case_insensitive_enum_parsing = false;
+
+  ParseOptions()
+      : ignore_unknown_fields(false), case_insensitive_enum_parsing(false) {}
+};
+
+struct PrintOptions {
+  // Whether to add spaces, line breaks and indentation to make the JSON output
+  // easy to read.
+  bool add_whitespace = false;
+  // Whether to always print primitive fields. By default proto3 primitive
+  // fields with default values will be omitted in JSON output. For example, an
+  // int32 field set to 0 will be omitted. Set this flag to true will override
+  // the default behavior and print primitive fields regardless of their values.
+  bool always_print_primitive_fields = false;
+  // Whether to always print enums as ints. By default they are rendered as
+  // strings.
+  bool always_print_enums_as_ints = false;
+  // Whether to preserve proto field names
+  bool preserve_proto_field_names = false;
+
+  PrintOptions()
+      : add_whitespace(false),
+        always_print_primitive_fields(false),
+        always_print_enums_as_ints(false),
+        preserve_proto_field_names(false) {}
+};
+
+// Converts from protobuf message to JSON and appends it to |output|. This is a
+// simple wrapper of BinaryToJsonString(). It will use the DescriptorPool of the
+// passed-in message to resolve Any types.
+//
+// Please note that non-OK statuses are not a stable output of this API and
+// subject to change without notice.
+PROTOBUF_EXPORT absl::Status MessageToJsonString(const Message& message,
+                                                 std::string* output,
+                                                 const PrintOptions& options);
+
+inline absl::Status MessageToJsonString(const Message& message,
+                                        std::string* output) {
+  return MessageToJsonString(message, output, PrintOptions());
+}
+
+// Converts from JSON to protobuf message. This is a simple wrapper of
+// JsonStringToBinary(). It will use the DescriptorPool of the passed-in
+// message to resolve Any types.
+//
+// Please note that non-OK statuses are not a stable output of this API and
+// subject to change without notice.
+PROTOBUF_EXPORT absl::Status JsonStringToMessage(absl::string_view input,
+                                                 Message* message,
+                                                 const ParseOptions& options);
+
+inline absl::Status JsonStringToMessage(absl::string_view input,
+                                        Message* message) {
+  return JsonStringToMessage(input, message, ParseOptions());
+}
+
+// Converts protobuf binary data to JSON.
+// The conversion will fail if:
+//   1. TypeResolver fails to resolve a type.
+//   2. input is not valid protobuf wire format, or conflicts with the type
+//      information returned by TypeResolver.
+// Note that unknown fields will be discarded silently.
+//
+// Please note that non-OK statuses are not a stable output of this API and
+// subject to change without notice.
+PROTOBUF_EXPORT absl::Status BinaryToJsonStream(
+    google::protobuf::util::TypeResolver* resolver, const std::string& type_url,
+    io::ZeroCopyInputStream* binary_input,
+    io::ZeroCopyOutputStream* json_output, const PrintOptions& options);
+
+inline absl::Status BinaryToJsonStream(google::protobuf::util::TypeResolver* resolver,
+                                       const std::string& type_url,
+                                       io::ZeroCopyInputStream* binary_input,
+                                       io::ZeroCopyOutputStream* json_output) {
+  return BinaryToJsonStream(resolver, type_url, binary_input, json_output,
+                            PrintOptions());
+}
+
+PROTOBUF_EXPORT absl::Status BinaryToJsonString(
+    google::protobuf::util::TypeResolver* resolver, const std::string& type_url,
+    const std::string& binary_input, std::string* json_output,
+    const PrintOptions& options);
+
+inline absl::Status BinaryToJsonString(google::protobuf::util::TypeResolver* resolver,
+                                       const std::string& type_url,
+                                       const std::string& binary_input,
+                                       std::string* json_output) {
+  return BinaryToJsonString(resolver, type_url, binary_input, json_output,
+                            PrintOptions());
+}
+
+// Converts JSON data to protobuf binary format.
+// The conversion will fail if:
+//   1. TypeResolver fails to resolve a type.
+//   2. input is not valid JSON format, or conflicts with the type
+//      information returned by TypeResolver.
+//
+// Please note that non-OK statuses are not a stable output of this API and
+// subject to change without notice.
+PROTOBUF_EXPORT absl::Status JsonToBinaryStream(
+    google::protobuf::util::TypeResolver* resolver, const std::string& type_url,
+    io::ZeroCopyInputStream* json_input,
+    io::ZeroCopyOutputStream* binary_output, const ParseOptions& options);
+
+inline absl::Status JsonToBinaryStream(
+    google::protobuf::util::TypeResolver* resolver, const std::string& type_url,
+    io::ZeroCopyInputStream* json_input,
+    io::ZeroCopyOutputStream* binary_output) {
+  return JsonToBinaryStream(resolver, type_url, json_input, binary_output,
+                            ParseOptions());
+}
+
+PROTOBUF_EXPORT absl::Status JsonToBinaryString(
+    google::protobuf::util::TypeResolver* resolver, const std::string& type_url,
+    absl::string_view json_input, std::string* binary_output,
+    const ParseOptions& options);
+
+inline absl::Status JsonToBinaryString(google::protobuf::util::TypeResolver* resolver,
+                                       const std::string& type_url,
+                                       absl::string_view json_input,
+                                       std::string* binary_output) {
+  return JsonToBinaryString(resolver, type_url, json_input, binary_output,
+                            ParseOptions());
+}
+}  // namespace json
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_JSON_JSON_H__
diff --git a/src/google/protobuf/json/json_test.cc b/src/google/protobuf/json/json_test.cc
new file mode 100644
index 0000000..3e0ad83
--- /dev/null
+++ b/src/google/protobuf/json/json_test.cc
@@ -0,0 +1,1317 @@
+// 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/json/json.h"
+
+#include <algorithm>
+#include <cstdint>
+#include <list>
+#include <memory>
+#include <string>
+#include <vector>
+
+#include "google/protobuf/duration.pb.h"
+#include "google/protobuf/field_mask.pb.h"
+#include "google/protobuf/struct.pb.h"
+#include "google/protobuf/timestamp.pb.h"
+#include "google/protobuf/wrappers.pb.h"
+#include <gmock/gmock.h>
+#include <gtest/gtest.h>
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor_database.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/util/json_format.pb.h"
+#include "google/protobuf/util/json_format_proto3.pb.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "google/protobuf/util/type_resolver_util.h"
+#include "google/protobuf/stubs/status_macros.h"
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
+namespace google {
+namespace protobuf {
+namespace json {
+namespace {
+using ::google::protobuf::util::TypeResolver;
+using ::proto3::MapIn;
+using ::proto3::TestAny;
+using ::proto3::TestEnumValue;
+using ::proto3::TestMap;
+using ::proto3::TestMessage;
+using ::proto3::TestOneof;
+using ::proto3::TestWrapper;
+using ::testing::ElementsAre;
+using ::testing::IsEmpty;
+using ::testing::Not;
+using ::testing::SizeIs;
+
+// TODO(b/234474291): Use the gtest versions once that's available in OSS.
+MATCHER_P(IsOkAndHolds, inner,
+          absl::StrCat("is OK and holds ", testing::PrintToString(inner))) {
+  if (!arg.ok()) {
+    *result_listener << arg.status();
+    return false;
+  }
+  return testing::ExplainMatchResult(inner, *arg, result_listener);
+}
+
+absl::Status GetStatus(const absl::Status& s) { return s; }
+template <typename T>
+absl::Status GetStatus(const absl::StatusOr<T>& s) {
+  return s.status();
+}
+
+MATCHER_P(StatusIs, status,
+          absl::StrCat(".status() is ", testing::PrintToString(status))) {
+  return GetStatus(arg).code() == status;
+}
+
+#define EXPECT_OK(x) EXPECT_THAT(x, StatusIs(absl::StatusCode::kOk))
+#define ASSERT_OK(x) ASSERT_THAT(x, StatusIs(absl::StatusCode::kOk))
+
+enum class Codec {
+  kReflective,
+  kResolver,
+};
+
+class JsonTest : public testing::TestWithParam<Codec> {
+ protected:
+  absl::StatusOr<std::string> ToJson(const Message& proto,
+                                     PrintOptions options = {}) {
+    if (GetParam() == Codec::kReflective) {
+      std::string result;
+      RETURN_IF_ERROR(MessageToJsonString(proto, &result, options));
+      return result;
+    }
+    std::string proto_data = proto.SerializeAsString();
+    io::ArrayInputStream in(proto_data.data(), proto_data.size());
+
+    std::string result;
+    io::StringOutputStream out(&result);
+
+    RETURN_IF_ERROR(BinaryToJsonStream(
+        resolver_.get(),
+        absl::StrCat("type.googleapis.com/", proto.GetTypeName()), &in, &out,
+        options));
+    return result;
+  }
+
+  // The out parameter comes first since `json` tends to be a very long string,
+  // and clang-format does a poor job if it is not the last parameter.
+  absl::Status ToProto(Message& proto, absl::string_view json,
+                       ParseOptions options = {}) {
+    if (GetParam() == Codec::kReflective) {
+      return JsonStringToMessage(json, &proto, options);
+    }
+    io::ArrayInputStream in(json.data(), json.size());
+
+    std::string result;
+    io::StringOutputStream out(&result);
+
+    RETURN_IF_ERROR(JsonToBinaryStream(
+        resolver_.get(),
+        absl::StrCat("type.googleapis.com/", proto.GetTypeName()), &in, &out,
+        options));
+
+    if (!proto.ParseFromString(result)) {
+      return absl::InternalError("wire format parse failed");
+    }
+    return absl::OkStatus();
+  }
+
+  template <typename Proto>
+  absl::StatusOr<Proto> ToProto(absl::string_view json,
+                                ParseOptions options = {}) {
+    Proto proto;
+    RETURN_IF_ERROR(ToProto(proto, json, options));
+    return proto;
+  }
+
+  std::unique_ptr<TypeResolver> resolver_{
+      google::protobuf::util::NewTypeResolverForDescriptorPool(
+          "type.googleapis.com", DescriptorPool::generated_pool())};
+};
+
+INSTANTIATE_TEST_SUITE_P(JsonTestSuite, JsonTest,
+                         testing::Values(Codec::kReflective, Codec::kResolver));
+
+TEST_P(JsonTest, TestWhitespaces) {
+  TestMessage m;
+  m.mutable_message_value();
+  m.set_string_value("foo");
+  m.add_repeated_bool_value(true);
+  m.add_repeated_bool_value(false);
+
+  EXPECT_THAT(
+      ToJson(m),
+      IsOkAndHolds(
+          R"({"stringValue":"foo","messageValue":{},"repeatedBoolValue":[true,false]})"));
+
+  PrintOptions options;
+  options.add_whitespace = true;
+  // Note: whitespace here is significant.
+  EXPECT_THAT(ToJson(m, options), IsOkAndHolds(R"({
+ "stringValue": "foo",
+ "messageValue": {},
+ "repeatedBoolValue": [
+  true,
+  false
+ ]
+}
+)"));
+}
+
+TEST_P(JsonTest, TestDefaultValues) {
+  TestMessage m;
+  EXPECT_THAT(ToJson(m), IsOkAndHolds("{}"));
+
+  PrintOptions options;
+  options.always_print_primitive_fields = true;
+  EXPECT_THAT(ToJson(m, options), IsOkAndHolds("{\"boolValue\":false,"
+                                               "\"int32Value\":0,"
+                                               "\"int64Value\":\"0\","
+                                               "\"uint32Value\":0,"
+                                               "\"uint64Value\":\"0\","
+                                               "\"floatValue\":0,"
+                                               "\"doubleValue\":0,"
+                                               "\"stringValue\":\"\","
+                                               "\"bytesValue\":\"\","
+                                               "\"enumValue\":\"FOO\","
+                                               "\"repeatedBoolValue\":[],"
+                                               "\"repeatedInt32Value\":[],"
+                                               "\"repeatedInt64Value\":[],"
+                                               "\"repeatedUint32Value\":[],"
+                                               "\"repeatedUint64Value\":[],"
+                                               "\"repeatedFloatValue\":[],"
+                                               "\"repeatedDoubleValue\":[],"
+                                               "\"repeatedStringValue\":[],"
+                                               "\"repeatedBytesValue\":[],"
+                                               "\"repeatedEnumValue\":[],"
+                                               "\"repeatedMessageValue\":[]"
+                                               "}"));
+
+  m.set_string_value("i am a test string value");
+  m.set_bytes_value("i am a test bytes value");
+  EXPECT_THAT(
+      ToJson(m, options),
+      IsOkAndHolds("{\"boolValue\":false,"
+                   "\"int32Value\":0,"
+                   "\"int64Value\":\"0\","
+                   "\"uint32Value\":0,"
+                   "\"uint64Value\":\"0\","
+                   "\"floatValue\":0,"
+                   "\"doubleValue\":0,"
+                   "\"stringValue\":\"i am a test string value\","
+                   "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
+                   "\"enumValue\":\"FOO\","
+                   "\"repeatedBoolValue\":[],"
+                   "\"repeatedInt32Value\":[],"
+                   "\"repeatedInt64Value\":[],"
+                   "\"repeatedUint32Value\":[],"
+                   "\"repeatedUint64Value\":[],"
+                   "\"repeatedFloatValue\":[],"
+                   "\"repeatedDoubleValue\":[],"
+                   "\"repeatedStringValue\":[],"
+                   "\"repeatedBytesValue\":[],"
+                   "\"repeatedEnumValue\":[],"
+                   "\"repeatedMessageValue\":[]"
+                   "}"));
+
+  EXPECT_THAT(
+      ToJson(protobuf_unittest::TestAllTypes(), options),
+      IsOkAndHolds(
+          R"({"optionalInt32":0,"optionalInt64":"0","optionalUint32":0,)"
+          R"("optionalUint64":"0","optionalSint32":0,"optionalSint64":"0","optionalFixed32":0,)"
+          R"("optionalFixed64":"0","optionalSfixed32":0,"optionalSfixed64":"0",)"
+          R"("optionalFloat":0,"optionalDouble":0,"optionalBool":false,"optionalString":"",)"
+          R"("optionalBytes":"","optionalgroup":null,"optionalNestedEnum":"FOO","optionalForeignEnum":"FOREIGN_FOO",)"
+          R"("optionalImportEnum":"IMPORT_FOO","optionalStringPiece":"","optionalCord":"",)"
+          R"("repeatedInt32":[],"repeatedInt64":[],"repeatedUint32":[],"repeatedUint64":[],)"
+          R"("repeatedSint32":[],"repeatedSint64":[],"repeatedFixed32":[],"repeatedFixed64":[],)"
+          R"("repeatedSfixed32":[],"repeatedSfixed64":[],"repeatedFloat":[],"repeatedDouble":[],)"
+          R"("repeatedBool":[],"repeatedString":[],"repeatedBytes":[],"repeatedgroup":[],)"
+          R"("repeatedNestedMessage":[],"repeatedForeignMessage":[],"repeatedImportMessage":[],)"
+          R"("repeatedNestedEnum":[],"repeatedForeignEnum":[],"repeatedImportEnum":[],)"
+          R"("repeatedStringPiece":[],"repeatedCord":[],"repeatedLazyMessage":[],"defaultInt32":41,)"
+          R"("defaultInt64":"42","defaultUint32":43,"defaultUint64":"44","defaultSint32":-45,)"
+          R"("defaultSint64":"46","defaultFixed32":47,"defaultFixed64":"48","defaultSfixed32":49,)"
+          R"("defaultSfixed64":"-50","defaultFloat":51.5,"defaultDouble":52000,"defaultBool":true,)"
+          R"("defaultString":"hello","defaultBytes":"d29ybGQ=","defaultNestedEnum":"BAR",)"
+          R"("defaultForeignEnum":"FOREIGN_BAR","defaultImportEnum":"IMPORT_BAR",)"
+          R"("defaultStringPiece":"abc","defaultCord":"123"})"));
+
+  EXPECT_THAT(
+      ToJson(protobuf_unittest::TestExtremeDefaultValues(), options),
+      IsOkAndHolds(
+          R"({"escapedBytes":"XDAwMFwwMDFcMDA3XDAxMFwwMTRcblxyXHRcMDEzXFxcJ1wiXDM3Ng==")"
+          R"(,"largeUint32":4294967295,"largeUint64":"18446744073709551615",)"
+          R"("smallInt32":-2147483647,"smallInt64":"-9223372036854775807",)"
+          R"("utf8String":"ሴ","zeroFloat":0,"oneFloat":1,"smallFloat":1.5,)"
+          R"("negativeOneFloat":-1,"negativeFloat":-1.5,"largeFloat":2e+08,)"
+          R"("smallNegativeFloat":-8e-28,"infDouble":0,"negInfDouble":0,)"
+          R"("nanDouble":0,"infFloat":0,"negInfFloat":0,"nanFloat":0,)"
+          R"("cppTrigraph":"? ? ?? ?? ??? ??/ ??-","reallySmallInt32":-2147483648)"
+          R"(,"reallySmallInt64":"-9223372036854775808","stringWithZero":"hel\u0000lo")"
+          R"(,"bytesWithZero":"d29yXDAwMGxk","stringPieceWithZero":"ab\u0000c")"
+          R"(,"cordWithZero":"12\u00003","replacementString":"${unknown}"})"));
+}
+
+TEST_P(JsonTest, TestPreserveProtoFieldNames) {
+  TestMessage m;
+  m.mutable_message_value();
+
+  PrintOptions options;
+  options.preserve_proto_field_names = true;
+  EXPECT_THAT(ToJson(m, options), IsOkAndHolds("{\"message_value\":{}}"));
+
+}
+
+TEST_P(JsonTest, Camels) {
+  protobuf_unittest::TestCamelCaseFieldNames m;
+  m.set_stringfield("sTRINGfIELD");
+
+  EXPECT_THAT(ToJson(m), IsOkAndHolds(R"({"StringField":"sTRINGfIELD"})"));
+}
+
+TEST_P(JsonTest, EvilString) {
+  auto m = ToProto<TestMessage>(R"json(
+    {"string_value": ")json"
+                                "\n\r\b\f\1\2\3"
+                                "\"}");
+  ASSERT_OK(m);
+  EXPECT_EQ(m->string_value(), "\n\r\b\f\1\2\3");
+}
+
+TEST_P(JsonTest, TestAlwaysPrintEnumsAsInts) {
+  TestMessage orig;
+  orig.set_enum_value(proto3::BAR);
+  orig.add_repeated_enum_value(proto3::FOO);
+  orig.add_repeated_enum_value(proto3::BAR);
+
+  PrintOptions print_options;
+  print_options.always_print_enums_as_ints = true;
+
+  auto printed = ToJson(orig, print_options);
+  ASSERT_THAT(printed,
+              IsOkAndHolds("{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}"));
+
+  auto parsed = ToProto<TestMessage>(*printed);
+  ASSERT_OK(parsed);
+
+  EXPECT_EQ(parsed->enum_value(), proto3::BAR);
+  EXPECT_THAT(parsed->repeated_enum_value(),
+              ElementsAre(proto3::FOO, proto3::BAR));
+}
+
+TEST_P(JsonTest, TestPrintEnumsAsIntsWithDefaultValue) {
+  TestEnumValue orig;
+  // orig.set_enum_value1(proto3::FOO)
+  orig.set_enum_value2(proto3::FOO);
+  orig.set_enum_value3(proto3::BAR);
+
+  PrintOptions print_options;
+  print_options.always_print_enums_as_ints = true;
+  print_options.always_print_primitive_fields = true;
+
+  auto printed = ToJson(orig, print_options);
+  ASSERT_THAT(
+      printed,
+      IsOkAndHolds("{\"enumValue1\":0,\"enumValue2\":0,\"enumValue3\":1}"));
+
+  auto parsed = ToProto<TestEnumValue>(*printed);
+
+  EXPECT_EQ(parsed->enum_value1(), proto3::FOO);
+  EXPECT_EQ(parsed->enum_value2(), proto3::FOO);
+  EXPECT_EQ(parsed->enum_value3(), proto3::BAR);
+}
+
+TEST_P(JsonTest, TestPrintProto2EnumAsIntWithDefaultValue) {
+  protobuf_unittest::TestDefaultEnumValue orig;
+
+  PrintOptions print_options;
+  print_options.always_print_enums_as_ints = true;
+  print_options.always_print_primitive_fields = true;
+
+  auto printed = ToJson(orig, print_options);
+  ASSERT_THAT(printed, IsOkAndHolds("{\"enumValue\":2}"));
+
+  auto parsed = ToProto<protobuf_unittest::TestDefaultEnumValue>(*printed);
+  ASSERT_OK(parsed);
+
+  EXPECT_EQ(parsed->enum_value(), protobuf_unittest::DEFAULT);
+}
+
+TEST_P(JsonTest, QuotedEnumValue) {
+  auto m = ToProto<TestEnumValue>(R"json(
+    {"enumValue1": "1"}
+  )json");
+  ASSERT_OK(m);
+  EXPECT_THAT(m->enum_value1(), proto3::BAR);
+}
+
+TEST_P(JsonTest, WebSafeBytes) {
+  auto m = ToProto<TestMessage>(R"json({
+      "bytesValue": "-_"
+  })json");
+  ASSERT_OK(m);
+
+  EXPECT_EQ(m->bytes_value(), "\xfb");
+}
+
+TEST_P(JsonTest, ParseMessage) {
+  auto m = ToProto<TestMessage>(R"json(
+    {
+      "boolValue": true,
+      "int32Value": 1234567891,
+      "int64Value": -5302428716536692736,
+      "uint32Value": 42,
+      "uint64Value": 530242871653669,
+      "floatValue": 3.4e+38,
+      "doubleValue": -55.3,
+      "stringValue": "foo bar baz",
+      "enumValue": "BAR",
+      "messageValue": {
+        "value": 2048
+      },
+
+      "repeatedBoolValue": [true],
+      "repeatedInt32Value": [0, -42],
+      "repeatedUint64Value": [1, 2],
+      "repeatedDoubleValue": [1.5, -2],
+      "repeatedStringValue": ["foo", "bar ", ""],
+      "repeatedEnumValue": [1, "FOO"],
+      "repeatedMessageValue": [
+        {"value": 40},
+        {},
+        {"value": 96}
+      ]
+    }
+  )json");
+  ASSERT_OK(m);
+
+  EXPECT_TRUE(m->bool_value());
+  EXPECT_EQ(m->int32_value(), 1234567891);
+  EXPECT_EQ(m->int64_value(), -5302428716536692736);
+  EXPECT_EQ(m->uint32_value(), 42);
+  EXPECT_EQ(m->uint64_value(), 530242871653669);
+  EXPECT_EQ(m->float_value(), 3.4e+38f);
+  EXPECT_EQ(m->double_value(),
+            -55.3);  // This value is intentionally not a nice
+                     // round number in base 2, so its floating point
+                     // representation has many digits at the end, which
+                     // printing back to JSON must handle well.
+  EXPECT_EQ(m->string_value(), "foo bar baz");
+  EXPECT_EQ(m->enum_value(), proto3::EnumType::BAR);
+  EXPECT_EQ(m->message_value().value(), 2048);
+
+  EXPECT_THAT(m->repeated_bool_value(), ElementsAre(true));
+  EXPECT_THAT(m->repeated_int32_value(), ElementsAre(0, -42));
+  EXPECT_THAT(m->repeated_uint64_value(), ElementsAre(1, 2));
+  EXPECT_THAT(m->repeated_double_value(), ElementsAre(1.5, -2));
+  EXPECT_THAT(m->repeated_string_value(), ElementsAre("foo", "bar ", ""));
+  EXPECT_THAT(m->repeated_enum_value(), ElementsAre(proto3::BAR, proto3::FOO));
+
+  ASSERT_THAT(m->repeated_message_value(), SizeIs(3));
+  EXPECT_EQ(m->repeated_message_value(0).value(), 40);
+  EXPECT_EQ(m->repeated_message_value(1).value(), 0);
+  EXPECT_EQ(m->repeated_message_value(2).value(), 96);
+
+  EXPECT_THAT(
+      ToJson(*m),
+      IsOkAndHolds(
+          R"({"boolValue":true,"int32Value":1234567891,"int64Value":"-5302428716536692736",)"
+          R"("uint32Value":42,"uint64Value":"530242871653669","floatValue":3.4e+38,)"
+          R"("doubleValue":-55.3,"stringValue":"foo bar baz","enumValue":"BAR",)"
+          R"("messageValue":{"value":2048},"repeatedBoolValue":[true],"repeatedInt32Value":[0,-42])"
+          R"(,"repeatedUint64Value":["1","2"],"repeatedDoubleValue":[1.5,-2],)"
+          R"("repeatedStringValue":["foo","bar ",""],"repeatedEnumValue":["BAR","FOO"],)"
+          R"("repeatedMessageValue":[{"value":40},{},{"value":96}]})"));
+}
+
+TEST_P(JsonTest, CurseOfAtob) {
+  auto m = ToProto<TestMessage>(R"json(
+    {
+      repeatedBoolValue: ["0", "1", "false", "true", "f", "t", "no", "yes", "n", "y"]
+    }
+  )json");
+  ASSERT_OK(m);
+  EXPECT_THAT(m->repeated_bool_value(),
+              ElementsAre(false, true, false, true, false, true, false, true,
+                          false, true));
+}
+
+TEST_P(JsonTest, FloatPrecision) {
+  google::protobuf::Value v;
+  v.mutable_list_value()->add_values()->set_number_value(0.9900000095367432);
+  v.mutable_list_value()->add_values()->set_number_value(0.8799999952316284);
+
+  EXPECT_THAT(ToJson(v),
+              IsOkAndHolds("[0.99000000953674316,0.87999999523162842]"));
+}
+
+TEST_P(JsonTest, FloatMinMaxValue) {
+  // 3.4028235e38 is FLT_MAX to 8-significant-digits. The final digit (5)
+  // is rounded up; that means that when parsing this as a 64-bit FP number,
+  // the value ends up higher than FLT_MAX. We still want to accept it though,
+  // as a reasonable representation of FLT_MAX.
+  auto m = ToProto<TestMessage>(R"json(
+    {
+      "repeatedFloatValue": [3.4028235e38, -3.4028235e38],
+    }
+  )json");
+  ASSERT_OK(m);
+  EXPECT_THAT(m->repeated_float_value(), ElementsAre(FLT_MAX, -FLT_MAX));
+}
+
+TEST_P(JsonTest, FloatOutOfRange) {
+  // Check that the slightly-lenient parsing demonstrated in FloatMinMaxValue
+  // doesn't mean we allow all values. The value being parsed differs only
+  // in the least significant (represented) digit.
+  auto m = ToProto<TestMessage>(R"json(
+    {
+      "floatValue": 3.4028236e38
+    }
+  )json");
+  EXPECT_THAT(m, StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_P(JsonTest, ParseLegacySingleRepeatedField) {
+  auto m = ToProto<TestMessage>(R"json({
+    "repeatedInt32Value": 1997,
+    "repeatedStringValue": "oh no",
+    "repeatedEnumValue": "BAR",
+    "repeatedMessageValue": {"value": -1}
+  })json");
+  ASSERT_OK(m);
+
+  EXPECT_THAT(m->repeated_int32_value(), ElementsAre(1997));
+  EXPECT_THAT(m->repeated_string_value(), ElementsAre("oh no"));
+  EXPECT_THAT(m->repeated_enum_value(), ElementsAre(proto3::EnumType::BAR));
+
+  ASSERT_THAT(m->repeated_message_value(), SizeIs(1));
+  EXPECT_EQ(m->repeated_message_value(0).value(), -1);
+
+  EXPECT_THAT(ToJson(*m),
+              IsOkAndHolds(R"({"repeatedInt32Value":[1997],)"
+                           R"("repeatedStringValue":["oh no"],)"
+                           R"("repeatedEnumValue":["BAR"],)"
+                           R"("repeatedMessageValue":[{"value":-1}]})"));
+}
+
+TEST_P(JsonTest, ParseMap) {
+  TestMap message;
+  (*message.mutable_string_map())["hello"] = 1234;
+  auto printed = ToJson(message);
+  ASSERT_THAT(printed, IsOkAndHolds(R"({"stringMap":{"hello":1234}})"));
+
+  auto other = ToProto<TestMap>(*printed);
+  ASSERT_OK(other);
+  EXPECT_EQ(other->DebugString(), message.DebugString());
+}
+
+TEST_P(JsonTest, RepeatedMapKey) {
+  EXPECT_THAT(ToProto<TestMap>(R"json({
+    "string_map": {
+      "twiceKey": 0,
+      "twiceKey": 1
+    }
+  })json"),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_P(JsonTest, ParsePrimitiveMapIn) {
+  MapIn message;
+  PrintOptions print_options;
+  print_options.always_print_primitive_fields = true;
+  auto printed = ToJson(message, print_options);
+  ASSERT_THAT(
+      ToJson(message, print_options),
+      IsOkAndHolds(R"({"other":"","things":[],"mapInput":{},"mapAny":{}})"));
+
+  auto other = ToProto<MapIn>(*printed);
+  ASSERT_OK(other);
+  EXPECT_EQ(other->DebugString(), message.DebugString());
+}
+
+TEST_P(JsonTest, PrintPrimitiveOneof) {
+  TestOneof message;
+  PrintOptions options;
+  options.always_print_primitive_fields = true;
+  message.mutable_oneof_message_value();
+  EXPECT_THAT(ToJson(message, options),
+              IsOkAndHolds(R"({"oneofMessageValue":{"value":0}})"));
+
+  message.set_oneof_int32_value(1);
+  EXPECT_THAT(ToJson(message, options),
+              IsOkAndHolds(R"({"oneofInt32Value":1})"));
+}
+
+TEST_P(JsonTest, ParseOverOneof) {
+  TestOneof m;
+  m.set_oneof_string_value("foo");
+  ASSERT_OK(ToProto(m, R"json({
+    "oneofInt32Value": 5,
+  })json"));
+  EXPECT_EQ(m.oneof_int32_value(), 5);
+}
+
+TEST_P(JsonTest, RepeatedSingularKeys) {
+  auto m = ToProto<TestMessage>(R"json({
+    "int32Value": 1,
+    "int32Value": 2
+  })json");
+  EXPECT_OK(m);
+  EXPECT_EQ(m->int32_value(), 2);
+}
+
+TEST_P(JsonTest, RepeatedRepeatedKeys) {
+  auto m = ToProto<TestMessage>(R"json({
+    "repeatedInt32Value": [1],
+    "repeatedInt32Value": [2, 3]
+  })json");
+  EXPECT_OK(m);
+  EXPECT_THAT(m->repeated_int32_value(), ElementsAre(1, 2, 3));
+}
+
+TEST_P(JsonTest, RepeatedOneofKeys) {
+  EXPECT_THAT(ToProto<TestOneof>(R"json({
+    "oneofInt32Value": 1,
+    "oneofStringValue": "foo"
+  })json"),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_P(JsonTest, TestParseIgnoreUnknownFields) {
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  EXPECT_OK(ToProto<TestMessage>(R"({"unknownName":0})", options));
+
+  TestMessage m;
+  m.GetReflection()->MutableUnknownFields(&m)->AddFixed32(9001, 9001);
+  m.GetReflection()->MutableUnknownFields(&m)->AddFixed64(9001, 9001);
+  m.GetReflection()->MutableUnknownFields(&m)->AddVarint(9001, 9001);
+  m.GetReflection()->MutableUnknownFields(&m)->AddLengthDelimited(9001, "9001");
+  EXPECT_THAT(ToJson(m), IsOkAndHolds("{}"));
+}
+
+TEST_P(JsonTest, TestParseErrors) {
+  // Parsing should fail if the field name can not be recognized.
+  EXPECT_THAT(ToProto<TestMessage>(R"({"unknownName": 0})"),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+  // Parsing should fail if the value is invalid.
+  EXPECT_THAT(ToProto<TestMessage>(R"("{"int32Value": 2147483648})"),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_P(JsonTest, TestDynamicMessage) {
+  // Create a new DescriptorPool with the same protos as the generated one.
+  DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
+  DescriptorPool pool(&database);
+  // A dynamic version of the test proto.
+  DynamicMessageFactory factory;
+  std::unique_ptr<Message> message(
+      factory.GetPrototype(pool.FindMessageTypeByName("proto3.TestMessage"))
+          ->New());
+  ASSERT_OK(ToProto(*message, R"json(
+    {
+      "int32Value": 1024,
+      "repeatedInt32Value": [1, 2],
+      "messageValue": {
+        "value": 2048
+      },
+      "repeatedMessageValue": [
+        {"value": 40},
+        {"value": 96}
+      ]
+    }
+  )json"));
+
+  // Convert to generated message for easy inspection.
+  TestMessage generated;
+  EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
+
+  EXPECT_EQ(generated.int32_value(), 1024);
+  EXPECT_THAT(generated.repeated_int32_value(), ElementsAre(1, 2));
+
+  EXPECT_EQ(generated.message_value().value(), 2048);
+  ASSERT_EQ(generated.repeated_message_value_size(), 2);
+  EXPECT_EQ(generated.repeated_message_value(0).value(), 40);
+  EXPECT_EQ(generated.repeated_message_value(1).value(), 96);
+
+  auto message_json = ToJson(*message);
+  ASSERT_OK(message_json);
+  auto generated_json = ToJson(generated);
+  ASSERT_OK(generated_json);
+  EXPECT_EQ(*message_json, *generated_json);
+}
+
+TEST_P(JsonTest, TestParsingAny) {
+  auto m = ToProto<TestAny>(R"json(
+    {
+      "value": {
+        "@type": "type.googleapis.com/proto3.TestMessage",
+        "int32_value": 5,
+        "string_value": "expected_value",
+        "message_value": {"value": 1}
+      }
+    }
+  )json");
+  ASSERT_OK(m);
+
+  TestMessage t;
+  ASSERT_TRUE(m->value().UnpackTo(&t));
+  EXPECT_EQ(t.int32_value(), 5);
+  EXPECT_EQ(t.string_value(), "expected_value");
+  EXPECT_EQ(t.message_value().value(), 1);
+
+  EXPECT_THAT(
+      ToJson(*m),
+      IsOkAndHolds(
+          R"({"value":{"@type":"type.googleapis.com/proto3.TestMessage",)"
+          R"("int32Value":5,"stringValue":"expected_value","messageValue":{"value":1}}})"));
+}
+
+TEST_P(JsonTest, TestParsingAnyMiddleAtType) {
+  auto m = ToProto<TestAny>(R"json(
+    {
+      "value": {
+        "int32_value": 5,
+        "string_value": "expected_value",
+        "@type": "type.googleapis.com/proto3.TestMessage",
+        "message_value": {"value": 1}
+      }
+    }
+  )json");
+  ASSERT_OK(m);
+
+  TestMessage t;
+  ASSERT_TRUE(m->value().UnpackTo(&t));
+  EXPECT_EQ(t.int32_value(), 5);
+  EXPECT_EQ(t.string_value(), "expected_value");
+  EXPECT_EQ(t.message_value().value(), 1);
+}
+
+TEST_P(JsonTest, TestParsingAnyEndAtType) {
+  auto m = ToProto<TestAny>(R"json(
+    {
+      "value": {
+        "int32_value": 5,
+        "string_value": "expected_value",
+        "message_value": {"value": 1},
+        "@type": "type.googleapis.com/proto3.TestMessage"
+      }
+    }
+  )json");
+  ASSERT_OK(m);
+
+  TestMessage t;
+  ASSERT_TRUE(m->value().UnpackTo(&t));
+  EXPECT_EQ(t.int32_value(), 5);
+  EXPECT_EQ(t.string_value(), "expected_value");
+  EXPECT_EQ(t.message_value().value(), 1);
+}
+
+TEST_P(JsonTest, TestParsingNestedAnys) {
+  auto m = ToProto<TestAny>(R"json(
+    {
+      "value": {
+        "value": {
+          "int32_value": 5,
+          "string_value": "expected_value",
+          "message_value": {"value": 1},
+          "@type": "type.googleapis.com/proto3.TestMessage"
+        },
+        "@type": "type.googleapis.com/google.protobuf.Any"
+      }
+    }
+  )json");
+  ASSERT_OK(m);
+
+  google::protobuf::Any inner;
+  ASSERT_TRUE(m->value().UnpackTo(&inner));
+
+  TestMessage t;
+  ASSERT_TRUE(inner.UnpackTo(&t));
+  EXPECT_EQ(t.int32_value(), 5);
+  EXPECT_EQ(t.string_value(), "expected_value");
+  EXPECT_EQ(t.message_value().value(), 1);
+
+  EXPECT_THAT(
+      ToJson(*m),
+      IsOkAndHolds(
+          R"({"value":{"@type":"type.googleapis.com/google.protobuf.Any",)"
+          R"("value":{"@type":"type.googleapis.com/proto3.TestMessage",)"
+          R"("int32Value":5,"stringValue":"expected_value","messageValue":{"value":1}}}})"));
+}
+
+TEST_P(JsonTest, TestParsingBrokenAny) {
+  auto m = ToProto<TestAny>(R"json(
+    {
+      "value": {}
+    }
+  )json");
+  ASSERT_OK(m);
+  EXPECT_EQ(m->value().type_url(), "");
+  EXPECT_EQ(m->value().value(), "");
+
+  EXPECT_THAT(ToProto<TestAny>(R"json(
+    {
+      "value": {
+        "type_url": "garbage",
+        "value": "bW9yZSBnYXJiYWdl"
+      }
+    }
+  )json"),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+
+  TestAny m2;
+  m2.mutable_value();
+  EXPECT_THAT(ToJson(m2), IsOkAndHolds(R"({"value":{}})"));
+  m2.mutable_value()->set_value("garbage");
+  // The ESF parser does not return InvalidArgument for this error.
+  EXPECT_THAT(ToJson(m2), Not(StatusIs(absl::StatusCode::kOk)));
+
+  m2.Clear();
+  m2.mutable_value()->set_type_url("type.googleapis.com/proto3.TestMessage");
+  EXPECT_THAT(
+      ToJson(m2),
+      IsOkAndHolds(
+          R"({"value":{"@type":"type.googleapis.com/proto3.TestMessage"}})"));
+}
+
+TEST_P(JsonTest, TestFlatList) {
+  auto m = ToProto<TestMessage>(R"json(
+    {
+      "repeatedInt32Value": [[[5]], [6]]
+    }
+  )json");
+  ASSERT_OK(m);
+  EXPECT_THAT(m->repeated_int32_value(), ElementsAre(5, 6));
+
+  // The above flatteing behavior is suppressed for google::protobuf::ListValue.
+  auto m2 = ToProto<google::protobuf::Value>(R"json(
+    {
+      "repeatedInt32Value": [[[5]], [6]]
+    }
+  )json");
+  ASSERT_OK(m2);
+  auto fields = m2->struct_value().fields();
+  auto list = fields["repeatedInt32Value"].list_value();
+  EXPECT_EQ(list.values(0)
+                .list_value()
+                .values(0)
+                .list_value()
+                .values(0)
+                .number_value(),
+            5);
+  EXPECT_EQ(list.values(1).list_value().values(0).number_value(), 6);
+}
+
+TEST_P(JsonTest, ParseWrappers) {
+  auto m = ToProto<TestWrapper>(R"json(
+    {
+      "boolValue": true,
+      "int32Value": 42,
+      "stringValue": "ieieo",
+    }
+  )json");
+  ASSERT_OK(m);
+
+  EXPECT_TRUE(m->bool_value().value());
+  EXPECT_EQ(m->int32_value().value(), 42);
+  EXPECT_EQ(m->string_value().value(), "ieieo");
+
+  EXPECT_THAT(
+      ToJson(*m),
+      IsOkAndHolds(
+          R"({"boolValue":true,"int32Value":42,"stringValue":"ieieo"})"));
+
+  auto m2 = ToProto<TestWrapper>(R"json(
+    {
+      "boolValue": { "value": true },
+      "int32Value": { "value": 42 },
+      "stringValue": { "value": "ieieo" },
+    }
+  )json");
+  ASSERT_OK(m2);
+
+  EXPECT_TRUE(m2->bool_value().value());
+  EXPECT_EQ(m2->int32_value().value(), 42);
+  EXPECT_EQ(m2->string_value().value(), "ieieo");
+}
+
+TEST_P(JsonTest, TestParsingUnknownAnyFields) {
+  absl::string_view input = R"json(
+    {
+      "value": {
+        "@type": "type.googleapis.com/proto3.TestMessage",
+        "unknown_field": "UNKNOWN_VALUE",
+        "string_value": "expected_value"
+      }
+    }
+  )json";
+
+  EXPECT_THAT(ToProto<TestAny>(input),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  auto m = ToProto<TestAny>(input, options);
+  ASSERT_OK(m);
+
+  TestMessage t;
+  ASSERT_TRUE(m->value().UnpackTo(&t));
+  EXPECT_EQ(t.string_value(), "expected_value");
+}
+
+TEST_P(JsonTest, TestHugeBareString) {
+  auto m = ToProto<TestMessage>(R"json({
+    "int64Value": 6009652459062546621
+  })json");
+  ASSERT_OK(m);
+  EXPECT_EQ(m->int64_value(), 6009652459062546621);
+}
+
+TEST_P(JsonTest, TestParsingUnknownEnumsProto2) {
+  absl::string_view input = R"json({"ayuLmao": "UNKNOWN_VALUE"})json";
+
+  EXPECT_THAT(ToProto<protobuf_unittest::TestNumbers>(input),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  auto m = ToProto<protobuf_unittest::TestNumbers>(input, options);
+  ASSERT_OK(m);
+  EXPECT_FALSE(m->has_a());
+}
+
+TEST_P(JsonTest, TestParsingUnknownEnumsProto3) {
+  TestMessage m;
+  absl::string_view input = R"json({"enum_value":"UNKNOWN_VALUE"})json";
+
+  m.set_enum_value(proto3::BAR);
+  ASSERT_THAT(ToProto(m, input), StatusIs(absl::StatusCode::kInvalidArgument));
+  EXPECT_EQ(m.enum_value(), proto3::BAR);  // Keep previous value
+
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  ASSERT_OK(ToProto(m, input, options));
+  EXPECT_EQ(m.enum_value(), 0);  // Unknown enum value must be decoded as 0
+}
+
+TEST_P(JsonTest, TestParsingUnknownEnumsProto3FromInt) {
+  TestMessage m;
+  absl::string_view input = R"json({"enum_value":12345})json";
+
+  m.set_enum_value(proto3::BAR);
+  ASSERT_OK(ToProto(m, input));
+  EXPECT_EQ(m.enum_value(), 12345);
+
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  ASSERT_OK(ToProto(m, input, options));
+  EXPECT_EQ(m.enum_value(), 12345);
+}
+
+// Trying to pass an object as an enum field value is always treated as an
+// error
+TEST_P(JsonTest, TestParsingUnknownEnumsProto3FromObject) {
+  absl::string_view input = R"json({"enum_value": {}})json";
+
+  EXPECT_THAT(ToProto<TestMessage>(input),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  EXPECT_THAT(ToProto<TestMessage>(input, options),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_P(JsonTest, TestParsingUnknownEnumsProto3FromArray) {
+  absl::string_view input = R"json({"enum_value": []})json";
+
+  EXPECT_THAT(ToProto<TestMessage>(input),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  EXPECT_THAT(ToProto<TestMessage>(input, options),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_P(JsonTest, TestParsingRepeatedUnknownEnums) {
+  absl::string_view input = R"json({
+    "repeated_enum_value": ["FOO", "BAZ", "BAR"]
+  })json";
+
+  EXPECT_THAT(ToProto<TestMessage>(input),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+
+  ParseOptions options;
+  options.ignore_unknown_fields = true;
+  auto m = ToProto<TestMessage>(input, options);
+  ASSERT_OK(m);
+  EXPECT_THAT(m->repeated_enum_value(), ElementsAre(proto3::FOO, proto3::BAR));
+}
+
+TEST_P(JsonTest, TestParsingEnumCaseSensitive) {
+  TestMessage m;
+  m.set_enum_value(proto3::FOO);
+  EXPECT_THAT(ToProto(m, R"json({"enum_value": "bar"})json"),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+  // Default behavior is case-sensitive, so keep previous value.
+  EXPECT_EQ(m.enum_value(), proto3::FOO);
+}
+
+TEST_P(JsonTest, TestParsingEnumLowercase) {
+  ParseOptions options;
+  options.case_insensitive_enum_parsing = true;
+  auto m =
+      ToProto<TestMessage>(R"json({"enum_value": "TLSv1_2"})json", options);
+  ASSERT_OK(m);
+  EXPECT_THAT(m->enum_value(), proto3::TLSv1_2);
+}
+
+TEST_P(JsonTest, TestParsingEnumIgnoreCase) {
+  TestMessage m;
+  m.set_enum_value(proto3::FOO);
+
+  ParseOptions options;
+  options.case_insensitive_enum_parsing = true;
+  ASSERT_OK(ToProto(m, R"json({"enum_value":"bar"})json", options));
+  EXPECT_EQ(m.enum_value(), proto3::BAR);
+}
+
+TEST_P(JsonTest, Extensions) {
+  if (GetParam() == Codec::kResolver) {
+    GTEST_SKIP();
+  }
+
+  auto m = ToProto<protobuf_unittest::TestMixedFieldsAndExtensions>(R"json({
+    "[protobuf_unittest.TestMixedFieldsAndExtensions.c]": 42,
+    "a": 5,
+    "b": [1, 2, 3],
+    "[protobuf_unittest.TestMixedFieldsAndExtensions.d]": [1, 1, 2, 3, 5, 8, 13]
+  })json");
+  ASSERT_OK(m);
+  EXPECT_EQ(m->a(), 5);
+  EXPECT_THAT(m->b(), ElementsAre(1, 2, 3));
+  EXPECT_EQ(m->GetExtension(protobuf_unittest::TestMixedFieldsAndExtensions::c),
+            42);
+  EXPECT_THAT(
+      m->GetRepeatedExtension(protobuf_unittest::TestMixedFieldsAndExtensions::d),
+      ElementsAre(1, 1, 2, 3, 5, 8, 13));
+
+  EXPECT_THAT(
+      ToJson(*m),
+      IsOkAndHolds(
+          R"({"a":5,)"
+          R"("[protobuf_unittest.TestMixedFieldsAndExtensions.c]":42,)"
+          R"("b":[1,2,3],)"
+          R"("[protobuf_unittest.TestMixedFieldsAndExtensions.d]":[1,1,2,3,5,8,13]})"));
+}
+
+// Parsing does NOT work like MergeFrom: existing repeated field values are
+// clobbered, not appended to.
+TEST_P(JsonTest, TestOverwriteRepeated) {
+  TestMessage m;
+  m.add_repeated_int32_value(5);
+
+  ASSERT_OK(ToProto(m, R"json({"repeated_int32_value": [1, 2, 3]})json"));
+  EXPECT_THAT(m.repeated_int32_value(), ElementsAre(1, 2, 3));
+}
+
+
+TEST_P(JsonTest, TestDuration) {
+  auto m = ToProto<proto3::TestDuration>(R"json(
+    {
+      "value": "123456.789s",
+      "repeated_value": ["0.1s", "999s"]
+    }
+  )json");
+  ASSERT_OK(m);
+
+  EXPECT_EQ(m->value().seconds(), 123456);
+  EXPECT_EQ(m->value().nanos(), 789000000);
+
+  EXPECT_THAT(m->repeated_value(), SizeIs(2));
+  EXPECT_EQ(m->repeated_value(0).seconds(), 0);
+  EXPECT_EQ(m->repeated_value(0).nanos(), 100000000);
+  EXPECT_EQ(m->repeated_value(1).seconds(), 999);
+  EXPECT_EQ(m->repeated_value(1).nanos(), 0);
+
+  EXPECT_THAT(
+      ToJson(*m),
+      IsOkAndHolds(
+          R"({"value":"123456.789s","repeatedValue":["0.100s","999s"]})"));
+
+  auto m2 = ToProto<proto3::TestDuration>(R"json(
+    {
+      "value": {"seconds": 4, "nanos": 5},
+    }
+  )json");
+  ASSERT_OK(m2);
+
+  EXPECT_EQ(m2->value().seconds(), 4);
+  EXPECT_EQ(m2->value().nanos(), 5);
+
+  // Negative duration with zero seconds.
+  auto m3 = ToProto<proto3::TestDuration>(R"json(
+    {
+      "value": {"nanos": -5},
+    }
+  )json");
+  ASSERT_OK(m3);
+  EXPECT_EQ(m3->value().seconds(), 0);
+  EXPECT_EQ(m3->value().nanos(), -5);
+  EXPECT_THAT(ToJson(m3->value()), IsOkAndHolds("\"-0.000000005s\""));
+
+  // Negative duration with zero nanos.
+  auto m4 = ToProto<proto3::TestDuration>(R"json(
+    {
+      "value": {"seconds": -5},
+    }
+  )json");
+  ASSERT_OK(m4);
+  EXPECT_EQ(m4->value().seconds(), -5);
+  EXPECT_EQ(m4->value().nanos(), 0);
+  EXPECT_THAT(ToJson(m4->value()), IsOkAndHolds("\"-5s\""));
+
+  // Parse "0.5s" as a JSON string.
+  auto m5 = ToProto<proto3::TestDuration>(R"json(
+    {
+      "value": "0.5s",
+    }
+  )json");
+  ASSERT_OK(m5);
+  EXPECT_EQ(m5->value().seconds(), 0);
+  EXPECT_EQ(m5->value().nanos(), 500000000);
+  EXPECT_THAT(ToJson(m5->value()), IsOkAndHolds("\"0.500s\""));
+}
+
+// These tests are not exhaustive; tests in //third_party/protobuf/conformance
+// are more comprehensive.
+TEST_P(JsonTest, TestTimestamp) {
+  auto m = ToProto<proto3::TestTimestamp>(R"json(
+    {
+      "value": "1996-02-27T12:00:00Z",
+      "repeated_value": ["9999-12-31T23:59:59Z"]
+    }
+  )json");
+  ASSERT_OK(m);
+
+  EXPECT_EQ(m->value().seconds(), 825422400);
+  EXPECT_EQ(m->value().nanos(), 0);
+  EXPECT_THAT(m->repeated_value(), SizeIs(1));
+  EXPECT_EQ(m->repeated_value(0).seconds(), 253402300799);
+  EXPECT_EQ(m->repeated_value(0).nanos(), 0);
+
+  EXPECT_THAT(
+      ToJson(*m),
+      IsOkAndHolds(
+          R"({"value":"1996-02-27T12:00:00Z","repeatedValue":["9999-12-31T23:59:59Z"]})"));
+
+  auto m2 = ToProto<proto3::TestTimestamp>(R"json(
+    {
+      "value": {"seconds": 4, "nanos": 5},
+    }
+  )json");
+  ASSERT_OK(m2);
+
+  EXPECT_EQ(m2->value().seconds(), 4);
+  EXPECT_EQ(m2->value().nanos(), 5);
+}
+
+// This test case comes from Envoy's tests. They like to parse a Value out of
+// YAML, turn it into JSON, and then parse it as a different proto. This means
+// we must be extremely careful with integer fields, because they need to
+// round-trip through doubles. This happens all over Envoy. :(
+TEST_P(JsonTest, TestEnvoyRoundTrip) {
+  auto m = ToProto<google::protobuf::Value>(R"json(
+    {
+      "value": {"seconds": 1234567891, "nanos": 234000000},
+    }
+  )json");
+  ASSERT_OK(m);
+
+  auto j = ToJson(*m);
+  ASSERT_OK(j);
+
+  auto m2 = ToProto<proto3::TestTimestamp>(*j);
+  ASSERT_OK(m2);
+
+  EXPECT_EQ(m2->value().seconds(), 1234567891);
+  EXPECT_EQ(m2->value().nanos(), 234000000);
+}
+
+TEST_P(JsonTest, TestFieldMask) {
+  auto m = ToProto<proto3::TestFieldMask>(R"json(
+    {
+      "value": "foo,bar.bazBaz"
+    }
+  )json");
+  ASSERT_OK(m);
+
+  EXPECT_THAT(m->value().paths(), ElementsAre("foo", "bar.baz_baz"));
+  EXPECT_THAT(ToJson(*m), IsOkAndHolds(R"({"value":"foo,bar.bazBaz"})"));
+
+  auto m2 = ToProto<proto3::TestFieldMask>(R"json(
+    {
+      "value": {
+        "paths": ["yep.really"]
+      },
+    }
+  )json");
+  ASSERT_OK(m2);
+
+  EXPECT_THAT(m2->value().paths(), ElementsAre("yep.really"));
+}
+
+TEST_P(JsonTest, TestFieldMaskSnakeCase) {
+  auto m = ToProto<proto3::TestFieldMask>(R"json(
+    {
+      "value": "foo_bar"
+    }
+  )json");
+  ASSERT_OK(m);
+
+  EXPECT_THAT(m->value().paths(), ElementsAre("foo_bar"));
+}
+
+TEST_P(JsonTest, TestLegalNullsInArray) {
+  auto m = ToProto<proto3::TestNullValue>(R"json({
+    "repeatedNullValue": [null]
+  })json");
+  ASSERT_OK(m);
+
+  EXPECT_THAT(m->repeated_null_value(),
+              ElementsAre(google::protobuf::NULL_VALUE));
+
+  auto m2 = ToProto<proto3::TestValue>(R"json({
+    "repeatedValue": [null]
+  })json");
+  ASSERT_OK(m2);
+
+  ASSERT_THAT(m2->repeated_value(), SizeIs(1));
+  EXPECT_TRUE(m2->repeated_value(0).has_null_value());
+
+  m2->Clear();
+  m2->mutable_value();  // Materialize an empty singular Value.
+  m2->add_repeated_value();
+  m2->add_repeated_value()->set_string_value("solitude");
+  m2->add_repeated_value();
+  EXPECT_THAT(ToJson(*m2), IsOkAndHolds(R"({"repeatedValue":["solitude"]})"));
+}
+
+TEST_P(JsonTest, EmptyValue) {
+  EXPECT_THAT(ToJson(google::protobuf::Value()), IsOkAndHolds(""));
+
+  google::protobuf::Struct s;
+  s.mutable_fields()->emplace("empty", google::protobuf::Value());
+  EXPECT_THAT(ToJson(s), IsOkAndHolds("{}"));
+}
+
+TEST_P(JsonTest, TrailingGarbage) {
+  EXPECT_THAT(ToProto<TestMessage>("{}garbage"),
+              StatusIs(absl::StatusCode::kInvalidArgument));
+}
+
+TEST_P(JsonTest, ListList) {
+  auto m = ToProto<proto3::TestListValue>(R"json({
+    "repeated_value": [["ayy", "lmao"]]
+  })json");
+  ASSERT_OK(m);
+
+  EXPECT_EQ(m->repeated_value(0).values(0).string_value(), "ayy");
+  EXPECT_EQ(m->repeated_value(0).values(1).string_value(), "lmao");
+
+  m = ToProto<proto3::TestListValue>(R"json({
+    "repeated_value": [{
+      "values": ["ayy", "lmao"]
+    }]
+  })json");
+  ASSERT_OK(m);
+
+  EXPECT_EQ(m->repeated_value(0).values(0).string_value(), "ayy");
+  EXPECT_EQ(m->repeated_value(0).values(1).string_value(), "lmao");
+}
+
+TEST_P(JsonTest, HtmlEscape) {
+  TestMessage m;
+  m.set_string_value("</script>");
+  EXPECT_THAT(ToJson(m),
+              IsOkAndHolds(R"({"stringValue":"\u003c/script\u003e"})"));
+
+  proto3::TestEvilJson m2;
+  PrintOptions opts;
+  opts.always_print_primitive_fields = true;
+  EXPECT_THAT(
+      ToJson(m2, opts),
+      IsOkAndHolds(
+          R"({"regular_name":0,"\u003c/script\u003e":0,)"
+          R"("unbalanced\"quotes":0,)"
+          R"("\"\u003cscript\u003ealert('hello!);\u003c/script\u003e":0})"));
+}
+
+TEST_P(JsonTest, FieldOrder) {
+  // $ protoscope -s <<< "3: 3 22: 2 1: 1 22: 2"
+  std::string out;
+  absl::Status s = BinaryToJsonString(
+      resolver_.get(), "type.googleapis.com/proto3.TestMessage",
+      "\x18\x03\xb0\x01\x02\x08\x01\xb0\x01\x02", &out);
+  ASSERT_OK(s);
+  EXPECT_EQ(
+      out, R"({"boolValue":true,"int64Value":"3","repeatedInt32Value":[2,2]})");
+}
+
+// JSON values get special treatment when it comes to pre-existing values in
+// their repeated fields, when parsing through their dedicated syntax.
+TEST_P(JsonTest, ClearPreExistingRepeatedInJsonValues) {
+  google::protobuf::ListValue l;
+  l.add_values()->set_string_value("hello");
+  ASSERT_OK(JsonStringToMessage("[]", &l));
+  EXPECT_THAT(l.values(), IsEmpty());
+
+  google::protobuf::Struct s;
+  (*s.mutable_fields())["hello"].set_string_value("world");
+  ASSERT_OK(JsonStringToMessage("{}", &s));
+  EXPECT_THAT(s.fields(), IsEmpty());
+}
+
+}  // namespace
+}  // namespace json
+}  // namespace protobuf
+}  // namespace google
diff --git a/src/google/protobuf/lazy_field_lite.cc b/src/google/protobuf/lazy_field_lite.cc
new file mode 100644
index 0000000..1830523
--- /dev/null
+++ b/src/google/protobuf/lazy_field_lite.cc
@@ -0,0 +1,149 @@
+// Protocol Buffers - Google's data interchange format
+// Copyright 2022 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 <limits>
+#include <memory>
+#include <utility>
+
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/lazy_field.h"
+
+// Must be included last.
+// clang-format off
+#include "google/protobuf/port_def.inc"
+// clang-format on
+
+namespace google {
+namespace protobuf {
+namespace internal {
+
+namespace {
+
+// Returns the initial depth for a local context.
+// --The default depth for lazily verified LazyField.
+// --Eagerly verified LazyField has no limit (max int).
+inline int GetInitDepth(LazyVerifyOption option) {
+  return option == LazyVerifyOption::kLazy
+             ? io::CodedInputStream::GetDefaultRecursionLimit()
+             : std::numeric_limits<int>::max();
+}  // namespace
+
+template <typename T>
+inline bool ParseWithOuterContextImpl(const T& input, LazyVerifyOption option,
+                                      ParseContext* ctx, MessageLite* message) {
+  GOOGLE_DCHECK(ctx == nullptr || !ctx->AliasingEnabled());
+
+  // Create local context with depth.
+  const char* ptr;
+  ParseContext local_ctx =
+      ctx != nullptr ? ctx->Spawn(&ptr, input)
+                     : ParseContext(GetInitDepth(option), false, &ptr, input);
+
+  if (ctx == nullptr ||
+      ctx->lazy_parse_mode() == ParseContext::LazyParseMode::kEagerVerify) {
+    // Unparsed data is already verified at parsing. Disable eager-verification.
+    (void)local_ctx.set_lazy_parse_mode(ParseContext::LazyParseMode::kLazy);
+  }
+
+  ptr = message->_InternalParse(ptr, &local_ctx);
+
+  if (ctx != nullptr && local_ctx.missing_required_fields()) {
+    ctx->SetMissingRequiredFields();
+  }
+
+  return ptr != nullptr &&
+         (local_ctx.EndedAtEndOfStream() || local_ctx.EndedAtLimit());
+}
+
+}  // namespace
+
+namespace {
+class ByPrototype {
+ public:
+  explicit ByPrototype(const MessageLite* prototype) : prototype_(prototype) {}
+
+  MessageLite* New(Arena* arena) const { return prototype_->New(arena); }
+
+  const MessageLite& Default() const { return *prototype_; }
+
+ private:
+  const MessageLite* prototype_;
+};
+}  // namespace
+
+const MessageLite& LazyField::GetByPrototype(const MessageLite& prototype,
+                                             Arena* arena,
+                                             LazyVerifyOption option,
+                                             ParseContext* ctx) const {
+  return GetGeneric(ByPrototype(&prototype), arena, option, ctx);
+}
+
+MessageLite* LazyField::MutableByPrototype(const MessageLite& prototype,
+                                           Arena* arena,
+                                           LazyVerifyOption option,
+                                           ParseContext* ctx) {
+  return MutableGeneric(ByPrototype(&prototype), arena, option, ctx);
+}
+
+MessageLite* LazyField::ReleaseByPrototype(const MessageLite& prototype,
+                                           Arena* arena,
+                                           LazyVerifyOption option) {
+  return ReleaseGeneric(ByPrototype(&prototype), arena, option);
+}
+
+MessageLite* LazyField::UnsafeArenaReleaseByPrototype(
+    const MessageLite& prototype, Arena* arena, LazyVerifyOption option) {
+  return UnsafeArenaReleaseGeneric(ByPrototype(&prototype), arena, option);
+}
+
+bool LazyField::ParseWithOuterContext(MessageLite* message,
+                                      LazyVerifyOption option,
+                                      ParseContext* ctx) const {
+  absl::optional<absl::string_view> flat = unparsed_.TryFlat();
+  if (flat.has_value()) {
+    return ParseWithOuterContextImpl(*flat, option, ctx, message);
+  }
+
+  io::CordInputStream input(unparsed_);
+  return ParseWithOuterContextImpl(&input, option, ctx, message);
+}
+
+void LazyField::LogParseError(const MessageLite* message) {
+  GOOGLE_LOG_EVERY_N(INFO, 100) << "Lazy parsing failed for " << message->GetTypeName()
+                         << " error=" << message->InitializationErrorString()
+                         << " (N = " << COUNTER << ")";
+}
+
+}  // namespace internal
+}  // namespace protobuf
+}  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/lite_arena_unittest.cc b/src/google/protobuf/lite_arena_unittest.cc
index d68c6c9..927663d 100644
--- a/src/google/protobuf/lite_arena_unittest.cc
+++ b/src/google/protobuf/lite_arena_unittest.cc
@@ -28,8 +28,8 @@
 // (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/arena_test_util.h>
-#include <google/protobuf/map_lite_test_util.h>
+#include "google/protobuf/arena_test_util.h"
+#include "google/protobuf/map_lite_test_util.h"
 #include <gtest/gtest.h>
 
 namespace google {
diff --git a/src/google/protobuf/lite_unittest.cc b/src/google/protobuf/lite_unittest.cc
index 583d325..d89a17d 100644
--- a/src/google/protobuf/lite_unittest.cc
+++ b/src/google/protobuf/lite_unittest.cc
@@ -34,21 +34,22 @@
 #include <iostream>
 #include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/map_lite_unittest.pb.h>
-#include <google/protobuf/unittest_lite.pb.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/arena_test_util.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/map_lite_test_util.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/test_util_lite.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "absl/strings/match.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/arena_test_util.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/map_lite_test_util.h"
+#include "google/protobuf/map_lite_unittest.pb.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/test_util_lite.h"
+#include "google/protobuf/unittest_lite.pb.h"
+#include "google/protobuf/wire_format_lite.h"
 
 namespace google {
 namespace protobuf {
@@ -674,8 +675,7 @@
     MapLiteTestUtil::SetMapFields(&message1);
     size_t size = message1.ByteSizeLong();
     data.resize(size);
-    ::uint8_t* start =
-        reinterpret_cast<::uint8_t*>(::google::protobuf::string_as_array(&data));
+    ::uint8_t* start = reinterpret_cast<::uint8_t*>(&data[0]);
     ::uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
     EXPECT_EQ(size, end - start);
     EXPECT_TRUE(message2.ParseFromString(data));
@@ -695,7 +695,7 @@
     data.resize(size);
     {
       // Allow the output stream to buffer only one byte at a time.
-      io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+      io::ArrayOutputStream array_stream(&data[0], size, 1);
       io::CodedOutputStream output_stream(&array_stream);
       message1.SerializeWithCachedSizes(&output_stream);
       EXPECT_FALSE(output_stream.HadError());
@@ -1143,8 +1143,8 @@
 
 TEST(Lite, DebugString) {
   protobuf_unittest::TestAllTypesLite message1, message2;
-  EXPECT_TRUE(HasPrefixString(message1.DebugString(), "MessageLite at 0x"));
-  EXPECT_TRUE(HasPrefixString(message2.DebugString(), "MessageLite at 0x"));
+  EXPECT_TRUE(absl::StartsWith(message1.DebugString(), "MessageLite at 0x"));
+  EXPECT_TRUE(absl::StartsWith(message2.DebugString(), "MessageLite at 0x"));
 
   // DebugString() and ShortDebugString() are the same for now.
   EXPECT_EQ(message1.DebugString(), message1.ShortDebugString());
diff --git a/src/google/protobuf/map.cc b/src/google/protobuf/map.cc
index d60a9a2..3490fca 100644
--- a/src/google/protobuf/map.cc
+++ b/src/google/protobuf/map.cc
@@ -28,13 +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.
 
-#include <google/protobuf/map.h>
+#include "google/protobuf/map.h"
 
 namespace google {
 namespace protobuf {
 namespace internal {
 
-void* const kGlobalEmptyTable[kGlobalEmptyTableSize] = {nullptr};
+const TableEntryPtr kGlobalEmptyTable[kGlobalEmptyTableSize] = {};
 
 }  // namespace internal
 }  // namespace protobuf
diff --git a/src/google/protobuf/map.h b/src/google/protobuf/map.h
index 008c192..f03f9e6 100644
--- a/src/google/protobuf/map.h
+++ b/src/google/protobuf/map.h
@@ -38,6 +38,7 @@
 #define GOOGLE_PROTOBUF_MAP_H__
 
 
+#include <algorithm>
 #include <functional>
 #include <initializer_list>
 #include <iterator>
@@ -55,19 +56,19 @@
 #include <mach/mach_time.h>
 #endif
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/generated_enum_util.h>
-#include <google/protobuf/map_type_handler.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/generated_enum_util.h"
+#include "google/protobuf/map_type_handler.h"
+#include "google/protobuf/port.h"
+
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -192,10 +193,19 @@
   Arena* arena_;
 };
 
+// To save on binary size and simplify generic uses of the map types we collapse
+// signed/unsigned versions of the same sized integer to the unsigned version.
+template <typename T, typename = void>
+struct KeyForBaseImpl {
+  using type = T;
+};
 template <typename T>
-using KeyForTree =
-    typename std::conditional<std::is_scalar<T>::value, T,
-                              std::reference_wrapper<const T>>::type;
+struct KeyForBaseImpl<T, std::enable_if_t<std::is_integral<T>::value &&
+                                          std::is_signed<T>::value>> {
+  using type = std::make_unsigned_t<T>;
+};
+template <typename T>
+using KeyForBase = typename KeyForBaseImpl<T>::type;
 
 // Default case: Not transparent.
 // We use std::hash<key_type>/std::less<key_type> and all the lookup functions
@@ -258,22 +268,85 @@
 };
 #endif  // defined(__cpp_lib_string_view)
 
+struct NodeBase {
+  // Align the node to allow KeyNode to predict the location of the key.
+  // This way sizeof(NodeBase) contains any possible padding it was going to
+  // have between NodeBase and the key.
+  alignas(int64_t) alignas(double) alignas(void*) NodeBase* next;
+};
+
+inline NodeBase* EraseFromLinkedList(NodeBase* item, NodeBase* head) {
+  if (head == item) {
+    return head->next;
+  } else {
+    head->next = EraseFromLinkedList(item, head->next);
+    return head;
+  }
+}
+
+inline bool TableEntryIsTooLong(NodeBase* node) {
+  const size_t kMaxLength = 8;
+  size_t count = 0;
+  do {
+    ++count;
+    node = node->next;
+  } while (node != nullptr);
+  // Invariant: no linked list ever is more than kMaxLength in length.
+  GOOGLE_DCHECK_LE(count, kMaxLength);
+  return count >= kMaxLength;
+}
+
+template <typename T>
+using KeyForTree = std::conditional_t<std::is_integral<T>::value, uint64_t,
+                                      std::reference_wrapper<const T>>;
+
+template <typename T>
+using LessForTree = typename TransparentSupport<
+    std::conditional_t<std::is_integral<T>::value, uint64_t, T>>::less;
+
 template <typename Key>
 using TreeForMap =
-    std::map<KeyForTree<Key>, void*, typename TransparentSupport<Key>::less,
-             MapAllocator<std::pair<const KeyForTree<Key>, void*>>>;
+    std::map<KeyForTree<Key>, NodeBase*, LessForTree<Key>,
+             MapAllocator<std::pair<const KeyForTree<Key>, NodeBase*>>>;
 
-inline bool TableEntryIsEmpty(void* const* table, size_t b) {
-  return table[b] == nullptr;
+// Type safe tagged pointer.
+// We convert to/from nodes and trees using the operations below.
+// They ensure that the tags are used correctly.
+// There are three states:
+//  - x == 0: the entry is empty
+//  - x != 0 && (x&1) == 0: the entry is a node list
+//  - x != 0 && (x&1) == 1: the entry is a tree
+enum class TableEntryPtr : uintptr_t;
+
+inline bool TableEntryIsEmpty(TableEntryPtr entry) {
+  return entry == TableEntryPtr{};
 }
-inline bool TableEntryIsNonEmptyList(void* const* table, size_t b) {
-  return table[b] != nullptr && table[b] != table[b ^ 1];
+inline bool TableEntryIsTree(TableEntryPtr entry) {
+  return (static_cast<uintptr_t>(entry) & 1) == 1;
 }
-inline bool TableEntryIsTree(void* const* table, size_t b) {
-  return !TableEntryIsEmpty(table, b) && !TableEntryIsNonEmptyList(table, b);
+inline bool TableEntryIsList(TableEntryPtr entry) {
+  return !TableEntryIsTree(entry);
 }
-inline bool TableEntryIsList(void* const* table, size_t b) {
-  return !TableEntryIsTree(table, b);
+inline bool TableEntryIsNonEmptyList(TableEntryPtr entry) {
+  return !TableEntryIsEmpty(entry) && TableEntryIsList(entry);
+}
+inline NodeBase* TableEntryToNode(TableEntryPtr entry) {
+  GOOGLE_DCHECK(TableEntryIsList(entry));
+  return reinterpret_cast<NodeBase*>(static_cast<uintptr_t>(entry));
+}
+inline TableEntryPtr NodeToTableEntry(NodeBase* node) {
+  GOOGLE_DCHECK((reinterpret_cast<uintptr_t>(node) & 1) == 0);
+  return static_cast<TableEntryPtr>(reinterpret_cast<uintptr_t>(node));
+}
+template <typename Tree>
+Tree* TableEntryToTree(TableEntryPtr entry) {
+  GOOGLE_DCHECK(TableEntryIsTree(entry));
+  return reinterpret_cast<Tree*>(static_cast<uintptr_t>(entry) - 1);
+}
+template <typename Tree>
+TableEntryPtr TreeToTableEntry(Tree* node) {
+  GOOGLE_DCHECK((reinterpret_cast<uintptr_t>(node) & 1) == 0);
+  return static_cast<TableEntryPtr>(reinterpret_cast<uintptr_t>(node) | 1);
 }
 
 // This captures all numeric types.
@@ -288,12 +361,14 @@
 }
 
 constexpr size_t kGlobalEmptyTableSize = 1;
-PROTOBUF_EXPORT extern void* const kGlobalEmptyTable[kGlobalEmptyTableSize];
+PROTOBUF_EXPORT extern const TableEntryPtr
+    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>
-PROTOBUF_NOINLINE size_t SpaceUsedInTable(void** table, size_t num_buckets,
+PROTOBUF_NOINLINE size_t SpaceUsedInTable(TableEntryPtr* table,
+                                          size_t num_buckets,
                                           size_t num_elements,
                                           size_t sizeof_node) {
   size_t size = 0;
@@ -303,10 +378,10 @@
   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)) {
+  for (size_t b = 0; b < num_buckets; ++b) {
+    if (internal::TableEntryIsTree(table[b])) {
       using Tree = TreeForMap<Key>;
-      Tree* tree = static_cast<Tree*>(table[b]);
+      Tree* tree = TableEntryToTree<Tree>(table[b]);
       // Estimated cost of the red-black tree nodes, 3 pointers plus a
       // bool (plus alignment, so 4 pointers).
       size += tree->size() *
@@ -331,8 +406,530 @@
 
 inline size_t SpaceUsedInValues(const void*) { return 0; }
 
+// The value might be of different signedness, so use memcpy to extract it.
+template <typename T, std::enable_if_t<std::is_integral<T>::value, int> = 0>
+T ReadKey(const void* ptr) {
+  T out;
+  memcpy(&out, ptr, sizeof(T));
+  return out;
+}
+
+template <typename T, std::enable_if_t<!std::is_integral<T>::value, int> = 0>
+const T& ReadKey(const void* ptr) {
+  return *reinterpret_cast<const T*>(ptr);
+}
+
+template <typename Key>
+class KeyMapBase {
+  using Allocator = internal::MapAllocator<void*>;
+  static_assert(!std::is_signed<Key>::value || !std::is_integral<Key>::value,
+                "");
+
+ public:
+  using size_type = size_t;
+  using hasher = typename TransparentSupport<Key>::hash;
+
+  explicit constexpr KeyMapBase(Arena* arena)
+      : num_elements_(0),
+        num_buckets_(internal::kGlobalEmptyTableSize),
+        seed_(0),
+        index_of_first_non_null_(internal::kGlobalEmptyTableSize),
+        table_(const_cast<TableEntryPtr*>(internal::kGlobalEmptyTable)),
+        alloc_(arena) {}
+
+  KeyMapBase(const KeyMapBase&) = delete;
+  KeyMapBase& operator=(const KeyMapBase&) = delete;
+
+ protected:
+  enum { kMinTableSize = 8 };
+
+  struct KeyNode : NodeBase {
+    static constexpr size_t kOffset = sizeof(NodeBase);
+    decltype(auto) key() const {
+      return ReadKey<Key>(reinterpret_cast<const char*>(this) + kOffset);
+    }
+  };
+
+  // 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;
+
+  class KeyIteratorBase {
+   public:
+    // Invariants:
+    // node_ is always correct. This is handy because the most common
+    // operations are operator* and operator-> and they only use node_.
+    // When node_ is set to a non-null value, all the other non-const fields
+    // are updated to be correct also, but those fields can become stale
+    // if the underlying map is modified.  When those fields are needed they
+    // are rechecked, and updated if necessary.
+    KeyIteratorBase() : node_(nullptr), m_(nullptr), bucket_index_(0) {}
+
+    explicit KeyIteratorBase(const KeyMapBase* m) : m_(m) {
+      SearchFrom(m->index_of_first_non_null_);
+    }
+
+    KeyIteratorBase(KeyNode* n, const KeyMapBase* m, size_type index)
+        : node_(n), m_(m), bucket_index_(index) {}
+
+    KeyIteratorBase(TreeIterator tree_it, const KeyMapBase* m, size_type index)
+        : node_(NodeFromTreeIterator(tree_it)), m_(m), bucket_index_(index) {}
+
+    // Advance through buckets, looking for the first that isn't empty.
+    // If nothing non-empty is found then leave node_ == nullptr.
+    void SearchFrom(size_type start_bucket) {
+      GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ ||
+             !m_->TableEntryIsEmpty(m_->index_of_first_non_null_));
+      for (size_type i = start_bucket; i < m_->num_buckets_; ++i) {
+        TableEntryPtr entry = m_->table_[i];
+        if (entry == TableEntryPtr{}) continue;
+        bucket_index_ = i;
+        if (PROTOBUF_PREDICT_TRUE(internal::TableEntryIsList(entry))) {
+          node_ = static_cast<KeyNode*>(TableEntryToNode(entry));
+        } else {
+          Tree* tree = TableEntryToTree<Tree>(entry);
+          GOOGLE_DCHECK(!tree->empty());
+          node_ = static_cast<KeyNode*>(tree->begin()->second);
+        }
+        return;
+      }
+      node_ = nullptr;
+      bucket_index_ = 0;
+    }
+
+    friend bool operator==(const KeyIteratorBase& a, const KeyIteratorBase& b) {
+      return a.node_ == b.node_;
+    }
+    friend bool operator!=(const KeyIteratorBase& a, const KeyIteratorBase& b) {
+      return a.node_ != b.node_;
+    }
+
+    KeyIteratorBase& operator++() {
+      if (node_->next == nullptr) {
+        SearchFrom(bucket_index_ + 1);
+      } else {
+        node_ = static_cast<KeyNode*>(node_->next);
+      }
+      return *this;
+    }
+
+    KeyNode* node_;
+    const KeyMapBase* m_;
+    size_type bucket_index_;
+  };
+
+ public:
+  Arena* arena() const { return this->alloc_.arena(); }
+
+  void Swap(KeyMapBase* 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_);
+  }
+
+  hasher hash_function() const { return {}; }
+
+  static size_type max_size() {
+    return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28);
+  }
+  size_type size() const { return num_elements_; }
+  bool empty() const { return size() == 0; }
+
+ protected:
+  PROTOBUF_NOINLINE void erase_no_destroy(size_type b, KeyNode* node) {
+    TreeIterator tree_it;
+    const bool is_list = revalidate_if_necessary(b, node, &tree_it);
+    if (is_list) {
+      GOOGLE_DCHECK(TableEntryIsNonEmptyList(b));
+      auto* head = TableEntryToNode(table_[b]);
+      head = EraseFromLinkedList(node, head);
+      table_[b] = NodeToTableEntry(head);
+    } else {
+      GOOGLE_DCHECK(this->TableEntryIsTree(b));
+      Tree* tree = internal::TableEntryToTree<Tree>(this->table_[b]);
+      if (tree_it != tree->begin()) {
+        auto* prev = std::prev(tree_it)->second;
+        prev->next = prev->next->next;
+      }
+      tree->erase(tree_it);
+      if (tree->empty()) {
+        this->DestroyTree(tree);
+        this->table_[b] = TableEntryPtr{};
+      }
+    }
+    --num_elements_;
+    if (PROTOBUF_PREDICT_FALSE(b == index_of_first_non_null_)) {
+      while (index_of_first_non_null_ < num_buckets_ &&
+             TableEntryIsEmpty(index_of_first_non_null_)) {
+        ++index_of_first_non_null_;
+      }
+    }
+  }
+
+  struct NodeAndBucket {
+    NodeBase* node;
+    size_type bucket;
+  };
+  // TODO(sbenza): We can reduce duplication by coercing `K` to a common type.
+  // Eg, for string keys we can coerce to string_view. Otherwise, we instantiate
+  // this with all the different `char[N]` of the caller.
+  template <typename K>
+  NodeAndBucket FindHelper(const K& k, TreeIterator* it = nullptr) const {
+    size_type b = BucketNumber(k);
+    if (TableEntryIsNonEmptyList(b)) {
+      auto* node = internal::TableEntryToNode(table_[b]);
+      do {
+        if (internal::TransparentSupport<Key>::Equals(
+                static_cast<KeyNode*>(node)->key(), k)) {
+          return {node, b};
+        } else {
+          node = node->next;
+        }
+      } while (node != nullptr);
+    } else if (TableEntryIsTree(b)) {
+      Tree* tree = internal::TableEntryToTree<Tree>(table_[b]);
+      auto tree_it = tree->find(k);
+      if (it != nullptr) *it = tree_it;
+      if (tree_it != tree->end()) {
+        return {tree_it->second, b};
+      }
+    }
+    return {nullptr, b};
+  }
+
+  // Insert the given Node in bucket b.  If that would make bucket b too big,
+  // and bucket b is not a tree, create a tree for buckets b.
+  // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct
+  // bucket.  num_elements_ is not modified.
+  void InsertUnique(size_type b, KeyNode* node) {
+    GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ ||
+           !TableEntryIsEmpty(index_of_first_non_null_));
+    // In practice, the code that led to this point may have already
+    // determined whether we are inserting into an empty list, a short list,
+    // 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.
+    GOOGLE_DCHECK(FindHelper(node->key()).node == nullptr);
+    if (TableEntryIsEmpty(b)) {
+      InsertUniqueInList(b, node);
+      index_of_first_non_null_ = (std::min)(index_of_first_non_null_, b);
+    } else if (TableEntryIsNonEmptyList(b) && !TableEntryIsTooLong(b)) {
+      InsertUniqueInList(b, node);
+    } else {
+      if (TableEntryIsNonEmptyList(b)) {
+        TreeConvert(b);
+      }
+      GOOGLE_DCHECK(TableEntryIsTree(b))
+          << (void*)table_[b] << " " << (uintptr_t)table_[b];
+      InsertUniqueInTree(b, node);
+      index_of_first_non_null_ = (std::min)(index_of_first_non_null_, b);
+    }
+  }
+
+  // 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.
+  void InsertUniqueInList(size_type b, KeyNode* node) {
+    if (!TableEntryIsEmpty(b) && ShouldInsertAfterHead(node)) {
+      auto* first = TableEntryToNode(table_[b]);
+      node->next = first->next;
+      first->next = node;
+    } else {
+      node->next = TableEntryToNode(table_[b]);
+      table_[b] = NodeToTableEntry(node);
+    }
+  }
+
+  // Helper for InsertUnique.  Handles the case where bucket b points to a
+  // Tree.
+  void InsertUniqueInTree(size_type b, KeyNode* node) {
+    auto* tree = TableEntryToTree<Tree>(table_[b]);
+    auto it = tree->insert({node->key(), node}).first;
+    // Maintain the linked list of the nodes in the tree.
+    // For simplicity, they are in the same order as the tree iteration.
+    if (it != tree->begin()) {
+      auto* prev = std::prev(it)->second;
+      prev->next = node;
+    }
+    auto next = std::next(it);
+    node->next = next != tree->end() ? next->second : nullptr;
+  }
+
+  // Returns whether it did resize.  Currently this is only used when
+  // num_elements_ increases, though it could be used in other situations.
+  // It checks for load too low as well as load too high: because any number
+  // of erases can occur between inserts, the load could be as low as 0 here.
+  // Resizing to a lower size is not always helpful, but failing to do so can
+  // destroy the expected big-O bounds for some operations. By having the
+  // policy that sometimes we resize down as well as up, clients can easily
+  // keep O(size()) = O(number of buckets) if they want that.
+  bool ResizeIfLoadIsOutOfRange(size_type new_size) {
+    const size_type kMaxMapLoadTimes16 = 12;  // controls RAM vs CPU tradeoff
+    const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16;
+    const size_type lo_cutoff = hi_cutoff / 4;
+    // We don't care how many elements are in trees.  If a lot are,
+    // we may resize even though there are many empty buckets.  In
+    // practice, this seems fine.
+    if (PROTOBUF_PREDICT_FALSE(new_size >= hi_cutoff)) {
+      if (num_buckets_ <= max_size() / 2) {
+        Resize(num_buckets_ * 2);
+        return true;
+      }
+    } else if (PROTOBUF_PREDICT_FALSE(new_size <= lo_cutoff &&
+                                      num_buckets_ > kMinTableSize)) {
+      size_type lg2_of_size_reduction_factor = 1;
+      // It's possible we want to shrink a lot here... size() could even be 0.
+      // So, estimate how much to shrink by making sure we don't shrink so
+      // much that we would need to grow the table after a few inserts.
+      const size_type hypothetical_size = new_size * 5 / 4 + 1;
+      while ((hypothetical_size << lg2_of_size_reduction_factor) < hi_cutoff) {
+        ++lg2_of_size_reduction_factor;
+      }
+      size_type new_num_buckets = std::max<size_type>(
+          kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor);
+      if (new_num_buckets != num_buckets_) {
+        Resize(new_num_buckets);
+        return true;
+      }
+    }
+    return false;
+  }
+
+  // Resize to the given number of buckets.
+  void Resize(size_t new_num_buckets) {
+    if (num_buckets_ == 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);
+    const auto old_table = table_;
+    const size_type old_table_size = num_buckets_;
+    num_buckets_ = new_num_buckets;
+    table_ = CreateEmptyTable(num_buckets_);
+    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 (internal::TableEntryIsNonEmptyList(old_table[i])) {
+        TransferList(static_cast<KeyNode*>(TableEntryToNode(old_table[i])));
+      } else if (internal::TableEntryIsTree(old_table[i])) {
+        TransferTree(TableEntryToTree<Tree>(old_table[i]));
+      }
+    }
+    Dealloc<TableEntryPtr>(old_table, old_table_size);
+  }
+
+  // Transfer all nodes in the list `node` into `this`.
+  void TransferList(KeyNode* node) {
+    do {
+      auto* next = static_cast<KeyNode*>(node->next);
+      InsertUnique(BucketNumber(node->key()), node);
+      node = next;
+    } while (node != nullptr);
+  }
+
+  // Transfer all nodes in the tree `tree` into `this` and destroy the tree.
+  void TransferTree(Tree* tree) {
+    auto* node = tree->begin()->second;
+    DestroyTree(tree);
+    TransferList(static_cast<KeyNode*>(node));
+  }
+
+  bool TableEntryIsEmpty(size_type b) const {
+    return internal::TableEntryIsEmpty(table_[b]);
+  }
+  bool TableEntryIsNonEmptyList(size_type b) const {
+    return internal::TableEntryIsNonEmptyList(table_[b]);
+  }
+  bool TableEntryIsTree(size_type b) const {
+    return internal::TableEntryIsTree(table_[b]);
+  }
+  bool TableEntryIsList(size_type b) const {
+    return internal::TableEntryIsList(table_[b]);
+  }
+
+  void TreeConvert(size_type b) {
+    GOOGLE_DCHECK(!TableEntryIsTree(b));
+    Tree* tree =
+        Arena::Create<Tree>(alloc_.arena(), typename Tree::key_compare(),
+                            typename Tree::allocator_type(alloc_));
+    size_type count = CopyListToTree(b, tree);
+    GOOGLE_DCHECK_EQ(count, tree->size());
+    table_[b] = TreeToTableEntry(tree);
+    // Relink the nodes.
+    NodeBase* next = nullptr;
+    auto it = tree->end();
+    do {
+      auto* node = (--it)->second;
+      node->next = next;
+      next = node;
+    } while (it != tree->begin());
+  }
+
+  // Copy a linked list in the given bucket to a tree.
+  // Returns the number of things it copied.
+  size_type CopyListToTree(size_type b, Tree* tree) {
+    size_type count = 0;
+    auto* node = TableEntryToNode(table_[b]);
+    while (node != nullptr) {
+      tree->insert({static_cast<KeyNode*>(node)->key(), node});
+      ++count;
+      auto* next = node->next;
+      node->next = nullptr;
+      node = next;
+    }
+    return count;
+  }
+
+  // Return whether table_[b] is a linked list that seems awfully long.
+  // Requires table_[b] to point to a non-empty linked list.
+  bool TableEntryIsTooLong(size_type b) {
+    return internal::TableEntryIsTooLong(TableEntryToNode(table_[b]));
+  }
+
+  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_t h = hash_function()(k) ^ seed_;
+
+    // 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_t kPhi = uint64_t{0x9e3779b97f4a7c15};
+    return ((kPhi * h) >> 32) & (num_buckets_ - 1);
+  }
+
+  // Return a power of two no less than max(kMinTableSize, n).
+  // Assumes either n < kMinTableSize or n is a power of two.
+  size_type TableSize(size_type n) {
+    return n < static_cast<size_type>(kMinTableSize)
+               ? static_cast<size_type>(kMinTableSize)
+               : n;
+  }
+
+  // Use alloc_ to allocate an array of n objects of type U.
+  template <typename U>
+  U* Alloc(size_type n) {
+    using alloc_type = typename Allocator::template rebind<U>::other;
+    return alloc_type(alloc_).allocate(n);
+  }
+
+  // Use alloc_ to deallocate an array of n objects of type U.
+  template <typename U>
+  void Dealloc(U* t, size_type n) {
+    using alloc_type = typename Allocator::template rebind<U>::other;
+    alloc_type(alloc_).deallocate(t, n);
+  }
+
+  void DestroyTree(Tree* tree) {
+    if (alloc_.arena() == nullptr) {
+      delete tree;
+    }
+  }
+
+  TableEntryPtr* CreateEmptyTable(size_type n) {
+    GOOGLE_DCHECK(n >= kMinTableSize);
+    GOOGLE_DCHECK_EQ(n & (n - 1), 0u);
+    TableEntryPtr* result = Alloc<TableEntryPtr>(n);
+    memset(result, 0, n * sizeof(result[0]));
+    return result;
+  }
+
+  // Return a randomish value.
+  size_type Seed() const {
+    // 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) >> 4;
+#if !defined(GOOGLE_PROTOBUF_NO_RDTSC)
+#if defined(__APPLE__)
+    // Use a commpage-based fast time function on Apple environments (MacOS,
+    // iOS, tvOS, watchOS, etc).
+    s += mach_absolute_time();
+#elif defined(__x86_64__) && defined(__GNUC__)
+    uint32_t hi, lo;
+    asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
+    s += ((static_cast<uint64_t>(hi) << 32) | lo);
+#elif defined(__aarch64__) && defined(__GNUC__)
+    // There is no rdtsc on ARMv8. CNTVCT_EL0 is the virtual counter of the
+    // system timer. It runs at a different frequency than the CPU's, but is
+    // the best source of time-based entropy we get.
+    uint64_t virtual_timer_value;
+    asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
+    s += virtual_timer_value;
+#endif
+#endif  // !defined(GOOGLE_PROTOBUF_NO_RDTSC)
+    return s;
+  }
+
+  // Assumes node_ and m_ are correct and non-null, but other fields may be
+  // stale.  Fix them as needed.  Then return true iff node_ points to a
+  // Node in a list.  If false is returned then *it is modified to be
+  // a valid iterator for node_.
+  bool revalidate_if_necessary(size_t& bucket_index, KeyNode* node,
+                               TreeIterator* it) const {
+    // Force bucket_index to be in range.
+    bucket_index &= (num_buckets_ - 1);
+    // Common case: the bucket we think is relevant points to `node`.
+    if (table_[bucket_index] == NodeToTableEntry(node)) return true;
+    // Less common: the bucket is a linked list with node_ somewhere in it,
+    // but not at the head.
+    if (TableEntryIsNonEmptyList(bucket_index)) {
+      auto* l = TableEntryToNode(table_[bucket_index]);
+      while ((l = l->next) != nullptr) {
+        if (l == node) {
+          return true;
+        }
+      }
+    }
+    // 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 the key.
+    auto res = FindHelper(node->key(), it);
+    bucket_index = res.bucket;
+    return TableEntryIsList(bucket_index);
+  }
+
+  size_type num_elements_;
+  size_type num_buckets_;
+  size_type seed_;
+  size_type index_of_first_non_null_;
+  TableEntryPtr* table_;  // an array with num_buckets_ entries
+  Allocator alloc_;
+};
+
 }  // namespace internal
 
+#ifdef PROTOBUF_FUTURE_MAP_PAIR_UPGRADE
+// This is the class for Map's internal value_type.
+template <typename Key, typename T>
+using MapPair = std::pair<const Key, T>;
+#else
 // This is the class for Map's internal value_type. Instead of using
 // std::pair as value_type, we use this class which provides us more control of
 // its process of construction and destruction.
@@ -363,6 +960,7 @@
   friend class Arena;
   friend class Map<Key, T>;
 };
+#endif
 
 // Map is an associative container type used to store protobuf map
 // fields.  Each Map instance may or may not use a different hash function, a
@@ -379,6 +977,7 @@
  public:
   using key_type = Key;
   using mapped_type = T;
+  using init_type = std::pair<Key, T>;
   using value_type = MapPair<Key, T>;
 
   using pointer = value_type*;
@@ -421,6 +1020,22 @@
   ~Map() {}
 
  private:
+  template <typename P>
+  struct SameAsElementReference
+      : std::is_same<typename std::remove_cv<
+                         typename std::remove_reference<reference>::type>::type,
+                     typename std::remove_cv<
+                         typename std::remove_reference<P>::type>::type> {};
+
+  template <class P>
+  using RequiresInsertable =
+      typename std::enable_if<std::is_convertible<P, init_type>::value ||
+                                  SameAsElementReference<P>::value,
+                              int>::type;
+  template <class P>
+  using RequiresNotInit =
+      typename std::enable_if<!std::is_same<P, init_type>::value, int>::type;
+
   using Allocator = internal::MapAllocator<void*>;
 
   // InnerMap is a generic hash-based map.  It doesn't contain any
@@ -455,241 +1070,104 @@
   // 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 {
+  class InnerMap : public internal::KeyMapBase<internal::KeyForBase<Key>> {
    public:
-    explicit constexpr InnerMap(Arena* arena)
-        : hasher(),
-          num_elements_(0),
-          num_buckets_(internal::kGlobalEmptyTableSize),
-          seed_(0),
-          index_of_first_non_null_(internal::kGlobalEmptyTableSize),
-          table_(const_cast<void**>(internal::kGlobalEmptyTable)),
-          alloc_(arena) {}
+    explicit constexpr InnerMap(Arena* arena) : InnerMap::KeyMapBase(arena) {}
+
+    InnerMap(const InnerMap&) = delete;
+    InnerMap& operator=(const InnerMap&) = delete;
 
     ~InnerMap() {
-      if (alloc_.arena() == nullptr &&
-          num_buckets_ != internal::kGlobalEmptyTableSize) {
+      if (this->alloc_.arena() == nullptr &&
+          this->num_buckets_ != internal::kGlobalEmptyTableSize) {
         clear();
-        Dealloc<void*>(table_, num_buckets_);
+        this->template Dealloc<TableEntryPtr>(this->table_, this->num_buckets_);
       }
     }
 
    private:
-    enum { kMinTableSize = 8 };
-
     // Linked-list nodes, as one would expect for a chaining hash table.
-    struct Node {
+    struct Node : InnerMap::KeyMapBase::KeyNode {
       value_type kv;
-      Node* next;
     };
 
-    // 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) {
+      static_assert(PROTOBUF_FIELD_OFFSET(Node, kv.first) ==
+                        InnerMap::KeyMapBase::KeyNode::kOffset,
+                    "");
       return static_cast<Node*>(it->second);
     }
 
+    using TableEntryPtr = internal::TableEntryPtr;
+
     // iterator and const_iterator are instantiations of iterator_base.
     template <typename KeyValueType>
-    class iterator_base {
+    class iterator_base : public InnerMap::KeyMapBase::KeyIteratorBase {
+      using Base = typename InnerMap::KeyMapBase::KeyIteratorBase;
+
      public:
       using reference = KeyValueType&;
       using pointer = KeyValueType*;
 
-      // Invariants:
-      // node_ is always correct. This is handy because the most common
-      // operations are operator* and operator-> and they only use node_.
-      // When node_ is set to a non-null value, all the other non-const fields
-      // are updated to be correct also, but those fields can become stale
-      // if the underlying map is modified.  When those fields are needed they
-      // are rechecked, and updated if necessary.
-      iterator_base() : node_(nullptr), m_(nullptr), bucket_index_(0) {}
-
-      explicit iterator_base(const InnerMap* m) : m_(m) {
-        SearchFrom(m->index_of_first_non_null_);
-      }
-
+      using Base::Base;
+      iterator_base() = default;
       // Any iterator_base can convert to any other.  This is overkill, and we
       // rely on the enclosing class to use it wisely.  The standard "iterator
       // can convert to const_iterator" is OK but the reverse direction is not.
-      template <typename U>
-      explicit iterator_base(const iterator_base<U>& it)
-          : node_(it.node_), m_(it.m_), bucket_index_(it.bucket_index_) {}
+      iterator_base(const Base& base) : Base(base) {}  // NOLINT
 
-      iterator_base(Node* n, const InnerMap* m, size_type index)
-          : node_(n), m_(m), bucket_index_(index) {}
-
-      iterator_base(TreeIterator tree_it, const InnerMap* m, size_type 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);
+      reference operator*() const {
+        return static_cast<Node*>(this->node_)->kv;
       }
-
-      // Advance through buckets, looking for the first that isn't empty.
-      // If nothing non-empty is found then leave node_ == nullptr.
-      void SearchFrom(size_type start_bucket) {
-        GOOGLE_DCHECK(m_->index_of_first_non_null_ == m_->num_buckets_ ||
-               m_->table_[m_->index_of_first_non_null_] != nullptr);
-        node_ = nullptr;
-        for (bucket_index_ = start_bucket; bucket_index_ < m_->num_buckets_;
-             bucket_index_++) {
-          if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
-            node_ = static_cast<Node*>(m_->table_[bucket_index_]);
-            break;
-          } else if (m_->TableEntryIsTree(bucket_index_)) {
-            Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
-            GOOGLE_DCHECK(!tree->empty());
-            node_ = NodeFromTreeIterator(tree->begin());
-            break;
-          }
-        }
-      }
-
-      reference operator*() const { return node_->kv; }
       pointer operator->() const { return &(operator*()); }
-
-      friend bool operator==(const iterator_base& a, const iterator_base& b) {
-        return a.node_ == b.node_;
-      }
-      friend bool operator!=(const iterator_base& a, const iterator_base& b) {
-        return a.node_ != b.node_;
-      }
-
-      iterator_base& operator++() {
-        if (node_->next == nullptr) {
-          TreeIterator tree_it;
-          const bool is_list = revalidate_if_necessary(&tree_it);
-          if (is_list) {
-            SearchFrom(bucket_index_ + 1);
-          } else {
-            GOOGLE_DCHECK_EQ(bucket_index_ & 1, 0u);
-            Tree* tree = static_cast<Tree*>(m_->table_[bucket_index_]);
-            if (++tree_it == tree->end()) {
-              SearchFrom(bucket_index_ + 2);
-            } else {
-              node_ = NodeFromTreeIterator(tree_it);
-            }
-          }
-        } else {
-          node_ = node_->next;
-        }
-        return *this;
-      }
-
-      iterator_base operator++(int /* unused */) {
-        iterator_base tmp = *this;
-        ++*this;
-        return tmp;
-      }
-
-      // Assumes node_ and m_ are correct and non-null, but other fields may be
-      // stale.  Fix them as needed.  Then return true iff node_ points to a
-      // Node in a list.  If false is returned then *it is modified to be
-      // a valid iterator for node_.
-      bool revalidate_if_necessary(TreeIterator* it) {
-        GOOGLE_DCHECK(node_ != nullptr && m_ != nullptr);
-        // Force bucket_index_ to be in range.
-        bucket_index_ &= (m_->num_buckets_ - 1);
-        // Common case: the bucket we think is relevant points to node_.
-        if (m_->table_[bucket_index_] == static_cast<void*>(node_)) return true;
-        // Less common: the bucket is a linked list with node_ somewhere in it,
-        // but not at the head.
-        if (m_->TableEntryIsNonEmptyList(bucket_index_)) {
-          Node* l = static_cast<Node*>(m_->table_[bucket_index_]);
-          while ((l = l->next) != nullptr) {
-            if (l == node_) {
-              return true;
-            }
-          }
-        }
-        // 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 the key.
-        iterator_base i(m_->find(node_->kv.first, it));
-        bucket_index_ = i.bucket_index_;
-        return m_->TableEntryIsList(bucket_index_);
-      }
-
-      Node* node_;
-      const InnerMap* m_;
-      size_type bucket_index_;
     };
 
    public:
     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(); }
     const_iterator begin() const { return const_iterator(this); }
     const_iterator end() const { return const_iterator(); }
 
     void clear() {
-      for (size_type b = 0; b < num_buckets_; b++) {
-        if (TableEntryIsNonEmptyList(b)) {
-          Node* node = static_cast<Node*>(table_[b]);
-          table_[b] = nullptr;
-          do {
-            Node* next = node->next;
-            DestroyNode(node);
-            node = next;
-          } while (node != nullptr);
-        } else if (TableEntryIsTree(b)) {
-          Tree* tree = static_cast<Tree*>(table_[b]);
-          GOOGLE_DCHECK(table_[b] == table_[b + 1] && (b & 1) == 0);
-          table_[b] = table_[b + 1] = nullptr;
-          typename Tree::iterator tree_it = tree->begin();
-          do {
-            Node* node = NodeFromTreeIterator(tree_it);
-            typename Tree::iterator next = tree_it;
-            ++next;
-            tree->erase(tree_it);
-            DestroyNode(node);
-            tree_it = next;
-          } while (tree_it != tree->end());
-          DestroyTree(tree);
-          b++;
+      for (size_type b = 0; b < this->num_buckets_; b++) {
+        internal::NodeBase* node;
+        if (this->TableEntryIsNonEmptyList(b)) {
+          node = internal::TableEntryToNode(this->table_[b]);
+          this->table_[b] = TableEntryPtr{};
+        } else if (this->TableEntryIsTree(b)) {
+          Tree* tree = internal::TableEntryToTree<Tree>(this->table_[b]);
+          this->table_[b] = TableEntryPtr{};
+          node = NodeFromTreeIterator(tree->begin());
+          this->DestroyTree(tree);
+        } else {
+          continue;
         }
+        do {
+          auto* next = node->next;
+          DestroyNode(static_cast<Node*>(node));
+          node = next;
+        } while (node != nullptr);
       }
-      num_elements_ = 0;
-      index_of_first_non_null_ = num_buckets_;
+      this->num_elements_ = 0;
+      this->index_of_first_non_null_ = this->num_buckets_;
     }
 
-    const hasher& hash_function() const { return *this; }
-
-    static size_type max_size() {
-      return static_cast<size_type>(1) << (sizeof(void**) >= 8 ? 60 : 28);
-    }
-    size_type size() const { return num_elements_; }
-    bool empty() const { return size() == 0; }
-
     template <typename K>
     iterator find(const K& k) {
-      return iterator(FindHelper(k).first);
+      auto res = this->FindHelper(k);
+      return iterator(static_cast<Node*>(res.node), this, res.bucket);
     }
 
     template <typename K>
     const_iterator find(const K& k) const {
-      return FindHelper(k).first;
+      auto res = this->FindHelper(k);
+      return const_iterator(static_cast<Node*>(res.node), this, res.bucket);
     }
 
     // Inserts a new element into the container if there is no element with the
@@ -720,73 +1198,48 @@
 
     void erase(iterator it) {
       GOOGLE_DCHECK_EQ(it.m_, this);
-      typename Tree::iterator tree_it;
-      const bool is_list = it.revalidate_if_necessary(&tree_it);
-      size_type b = it.bucket_index_;
-      Node* const item = it.node_;
-      if (is_list) {
-        GOOGLE_DCHECK(TableEntryIsNonEmptyList(b));
-        Node* head = static_cast<Node*>(table_[b]);
-        head = EraseFromLinkedList(item, head);
-        table_[b] = static_cast<void*>(head);
-      } else {
-        GOOGLE_DCHECK(TableEntryIsTree(b));
-        Tree* tree = static_cast<Tree*>(table_[b]);
-        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.
-          b &= ~static_cast<size_type>(1);
-          DestroyTree(tree);
-          table_[b] = table_[b + 1] = nullptr;
-        }
-      }
-      DestroyNode(item);
-      --num_elements_;
-      if (PROTOBUF_PREDICT_FALSE(b == index_of_first_non_null_)) {
-        while (index_of_first_non_null_ < num_buckets_ &&
-               table_[index_of_first_non_null_] == nullptr) {
-          ++index_of_first_non_null_;
-        }
-      }
+      auto* node = static_cast<Node*>(it.node_);
+      this->erase_no_destroy(it.bucket_index_, node);
+      DestroyNode(node);
     }
 
     size_t SpaceUsedInternal() const {
-      return internal::SpaceUsedInTable<Key>(table_, num_buckets_,
-                                             num_elements_, sizeof(Node));
+      return internal::SpaceUsedInTable<Key>(this->table_, this->num_buckets_,
+                                             this->num_elements_, sizeof(Node));
     }
 
    private:
     template <typename K, typename... Args>
     std::pair<iterator, bool> TryEmplaceInternal(K&& k, Args&&... args) {
-      std::pair<const_iterator, size_type> p = FindHelper(k);
+      auto p = this->FindHelper(k);
       // Case 1: key was already present.
-      if (p.first.node_ != nullptr)
-        return std::make_pair(iterator(p.first), false);
+      if (p.node != nullptr)
+        return std::make_pair(
+            iterator(static_cast<Node*>(p.node), this, p.bucket), false);
       // Case 2: insert.
-      if (ResizeIfLoadIsOutOfRange(num_elements_ + 1)) {
-        p = FindHelper(k);
+      if (this->ResizeIfLoadIsOutOfRange(this->num_elements_ + 1)) {
+        p = this->FindHelper(k);
       }
-      const size_type b = p.second;  // bucket number
+      const size_type b = p.bucket;  // bucket number
       // 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;
-      Node* node = Alloc<Node>(1);
+      Node* node = this->template Alloc<Node>(1);
       // Even when arena is nullptr, CreateInArenaStorage is still used to
       // ensure the arena of submessage will be consistent. Otherwise,
       // submessage may have its own arena when message-owned arena is enabled.
       // Note: This only works if `Key` is not arena constructible.
       Arena::CreateInArenaStorage(const_cast<Key*>(&node->kv.first),
-                                  alloc_.arena(),
+                                  this->alloc_.arena(),
                                   static_cast<TypeToInit>(std::forward<K>(k)));
       // Note: if `T` is arena constructible, `Args` needs to be empty.
-      Arena::CreateInArenaStorage(&node->kv.second, alloc_.arena(),
+      Arena::CreateInArenaStorage(&node->kv.second, this->alloc_.arena(),
                                   std::forward<Args>(args)...);
 
-      iterator result = InsertUnique(b, node);
-      ++num_elements_;
-      return std::make_pair(result, true);
+      this->InsertUnique(b, node);
+      ++this->num_elements_;
+      return std::make_pair(iterator(node, this, b), true);
     }
 
     // A helper function to perform an assignment of `mapped_type`.
@@ -830,358 +1283,17 @@
       return TryEmplaceInternal(std::forward<Args>(args)...);
     }
 
-    const_iterator find(const Key& k, TreeIterator* it) const {
-      return FindHelper(k, it).first;
-    }
-    template <typename K>
-    std::pair<const_iterator, size_type> FindHelper(const K& k) const {
-      return FindHelper(k, nullptr);
-    }
-    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 (internal::TransparentSupport<Key>::Equals(node->kv.first, k)) {
-            return std::make_pair(const_iterator(node, this, b), b);
-          } else {
-            node = node->next;
-          }
-        } while (node != nullptr);
-      } else if (TableEntryIsTree(b)) {
-        GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
-        b &= ~static_cast<size_t>(1);
-        Tree* tree = static_cast<Tree*>(table_[b]);
-        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);
-        }
-      }
-      return std::make_pair(end(), b);
-    }
-
-    // Insert the given Node in bucket b.  If that would make bucket b too big,
-    // and bucket b is not a tree, create a tree for buckets b and b^1 to share.
-    // Requires count(*KeyPtrFromNodePtr(node)) == 0 and that b is the correct
-    // bucket.  num_elements_ is not modified.
-    iterator InsertUnique(size_type b, Node* node) {
-      GOOGLE_DCHECK(index_of_first_non_null_ == num_buckets_ ||
-             table_[index_of_first_non_null_] != nullptr);
-      // In practice, the code that led to this point may have already
-      // determined whether we are inserting into an empty list, a short list,
-      // 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(node->kv.first) == end());
-      if (TableEntryIsEmpty(b)) {
-        result = InsertUniqueInList(b, node);
-      } else if (TableEntryIsNonEmptyList(b)) {
-        if (PROTOBUF_PREDICT_FALSE(TableEntryIsTooLong(b))) {
-          TreeConvert(b);
-          result = InsertUniqueInTree(b, node);
-          GOOGLE_DCHECK_EQ(result.bucket_index_, b & ~static_cast<size_type>(1));
-        } else {
-          // Insert into a pre-existing list.  This case cannot modify
-          // index_of_first_non_null_, so we skip the code to update it.
-          return InsertUniqueInList(b, node);
-        }
-      } else {
-        // Insert into a pre-existing tree.  This case cannot modify
-        // index_of_first_non_null_, so we skip the code to update it.
-        return InsertUniqueInTree(b, node);
-      }
-      // parentheses around (std::min) prevents macro expansion of min(...)
-      index_of_first_non_null_ =
-          (std::min)(index_of_first_non_null_, result.bucket_index_);
-      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);
-    }
-
-    // Helper for InsertUnique.  Handles the case where bucket b points to a
-    // Tree.
-    iterator InsertUniqueInTree(size_type b, Node* node) {
-      GOOGLE_DCHECK_EQ(table_[b], table_[b ^ 1]);
-      // Maintain the invariant that node->next is null for all Nodes in Trees.
-      node->next = nullptr;
-      return iterator(
-          static_cast<Tree*>(table_[b])->insert({node->kv.first, node}).first,
-          this, b & ~static_cast<size_t>(1));
-    }
-
-    // Returns whether it did resize.  Currently this is only used when
-    // num_elements_ increases, though it could be used in other situations.
-    // It checks for load too low as well as load too high: because any number
-    // of erases can occur between inserts, the load could be as low as 0 here.
-    // Resizing to a lower size is not always helpful, but failing to do so can
-    // destroy the expected big-O bounds for some operations. By having the
-    // policy that sometimes we resize down as well as up, clients can easily
-    // keep O(size()) = O(number of buckets) if they want that.
-    bool ResizeIfLoadIsOutOfRange(size_type new_size) {
-      const size_type kMaxMapLoadTimes16 = 12;  // controls RAM vs CPU tradeoff
-      const size_type hi_cutoff = num_buckets_ * kMaxMapLoadTimes16 / 16;
-      const size_type lo_cutoff = hi_cutoff / 4;
-      // We don't care how many elements are in trees.  If a lot are,
-      // we may resize even though there are many empty buckets.  In
-      // practice, this seems fine.
-      if (PROTOBUF_PREDICT_FALSE(new_size >= hi_cutoff)) {
-        if (num_buckets_ <= max_size() / 2) {
-          Resize(num_buckets_ * 2);
-          return true;
-        }
-      } else if (PROTOBUF_PREDICT_FALSE(new_size <= lo_cutoff &&
-                                        num_buckets_ > kMinTableSize)) {
-        size_type lg2_of_size_reduction_factor = 1;
-        // It's possible we want to shrink a lot here... size() could even be 0.
-        // So, estimate how much to shrink by making sure we don't shrink so
-        // much that we would need to grow the table after a few inserts.
-        const size_type hypothetical_size = new_size * 5 / 4 + 1;
-        while ((hypothetical_size << lg2_of_size_reduction_factor) <
-               hi_cutoff) {
-          ++lg2_of_size_reduction_factor;
-        }
-        size_type new_num_buckets = std::max<size_type>(
-            kMinTableSize, num_buckets_ >> lg2_of_size_reduction_factor);
-        if (new_num_buckets != num_buckets_) {
-          Resize(new_num_buckets);
-          return true;
-        }
-      }
-      return false;
-    }
-
-    // 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_;
-      num_buckets_ = new_num_buckets;
-      table_ = CreateEmptyTable(num_buckets_);
-      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 (internal::TableEntryIsNonEmptyList(old_table, i)) {
-          TransferList(old_table, i);
-        } else if (internal::TableEntryIsTree(old_table, i)) {
-          TransferTree(old_table, i++);
-        }
-      }
-      Dealloc<void*>(old_table, old_table_size);
-    }
-
-    void TransferList(void* const* table, size_type index) {
-      Node* node = static_cast<Node*>(table[index]);
-      do {
-        Node* next = node->next;
-        InsertUnique(BucketNumber(node->kv.first), node);
-        node = next;
-      } while (node != nullptr);
-    }
-
-    void TransferTree(void* const* table, size_type index) {
-      Tree* tree = static_cast<Tree*>(table[index]);
-      typename Tree::iterator tree_it = tree->begin();
-      do {
-        InsertUnique(BucketNumber(std::cref(tree_it->first).get()),
-                     NodeFromTreeIterator(tree_it));
-      } while (++tree_it != tree->end());
-      DestroyTree(tree);
-    }
-
-    Node* EraseFromLinkedList(Node* item, Node* head) {
-      if (head == item) {
-        return head->next;
-      } else {
-        head->next = EraseFromLinkedList(item, head->next);
-        return head;
-      }
-    }
-
-    bool TableEntryIsEmpty(size_type b) const {
-      return internal::TableEntryIsEmpty(table_, b);
-    }
-    bool TableEntryIsNonEmptyList(size_type b) const {
-      return internal::TableEntryIsNonEmptyList(table_, b);
-    }
-    bool TableEntryIsTree(size_type b) const {
-      return internal::TableEntryIsTree(table_, b);
-    }
-    bool TableEntryIsList(size_type b) const {
-      return internal::TableEntryIsList(table_, b);
-    }
-
-    void TreeConvert(size_type b) {
-      GOOGLE_DCHECK(!TableEntryIsTree(b) && !TableEntryIsTree(b ^ 1));
-      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);
-    }
-
-    // Copy a linked list in the given bucket to a tree.
-    // Returns the number of things it copied.
-    size_type CopyListToTree(size_type b, Tree* tree) {
-      size_type count = 0;
-      Node* node = static_cast<Node*>(table_[b]);
-      while (node != nullptr) {
-        tree->insert({node->kv.first, node});
-        ++count;
-        Node* next = node->next;
-        node->next = nullptr;
-        node = next;
-      }
-      return count;
-    }
-
-    // Return whether table_[b] is a linked list that seems awfully long.
-    // Requires table_[b] to point to a non-empty linked list.
-    bool TableEntryIsTooLong(size_type b) {
-      const size_type kMaxLength = 8;
-      size_type count = 0;
-      Node* node = static_cast<Node*>(table_[b]);
-      do {
-        ++count;
-        node = node->next;
-      } while (node != nullptr);
-      // Invariant: no linked list ever is more than kMaxLength in length.
-      GOOGLE_DCHECK_LE(count, kMaxLength);
-      return count >= kMaxLength;
-    }
-
-    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_t h = hash_function()(k) ^ seed_;
-
-      // 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_t kPhi = uint64_t{0x9e3779b97f4a7c15};
-      return ((kPhi * h) >> 32) & (num_buckets_ - 1);
-    }
-
-    // Return a power of two no less than max(kMinTableSize, n).
-    // Assumes either n < kMinTableSize or n is a power of two.
-    size_type TableSize(size_type n) {
-      return n < static_cast<size_type>(kMinTableSize)
-                 ? static_cast<size_type>(kMinTableSize)
-                 : n;
-    }
-
-    // Use alloc_ to allocate an array of n objects of type U.
-    template <typename U>
-    U* Alloc(size_type n) {
-      using alloc_type = typename Allocator::template rebind<U>::other;
-      return alloc_type(alloc_).allocate(n);
-    }
-
-    // Use alloc_ to deallocate an array of n objects of type U.
-    template <typename U>
-    void Dealloc(U* t, size_type n) {
-      using alloc_type = typename Allocator::template rebind<U>::other;
-      alloc_type(alloc_).deallocate(t, n);
-    }
-
     void DestroyNode(Node* node) {
-      if (alloc_.arena() == nullptr) {
-        delete node;
+      if (this->alloc_.arena() == nullptr) {
+        node->kv.first.~key_type();
+        node->kv.second.~mapped_type();
+        this->Dealloc(node, 1);
       }
     }
 
-    void DestroyTree(Tree* tree) {
-      if (alloc_.arena() == nullptr) {
-        delete tree;
-      }
-    }
-
-    void** CreateEmptyTable(size_type n) {
-      GOOGLE_DCHECK(n >= kMinTableSize);
-      GOOGLE_DCHECK_EQ(n & (n - 1), 0u);
-      void** result = Alloc<void*>(n);
-      memset(result, 0, n * sizeof(result[0]));
-      return result;
-    }
-
-    // Return a randomish value.
-    size_type Seed() const {
-      // 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) >> 4;
-#if !defined(GOOGLE_PROTOBUF_NO_RDTSC)
-#if defined(__APPLE__)
-      // Use a commpage-based fast time function on Apple environments (MacOS,
-      // iOS, tvOS, watchOS, etc).
-      s += mach_absolute_time();
-#elif defined(__x86_64__) && defined(__GNUC__)
-      uint32_t hi, lo;
-      asm volatile("rdtsc" : "=a"(lo), "=d"(hi));
-      s += ((static_cast<uint64_t>(hi) << 32) | lo);
-#elif defined(__aarch64__) && defined(__GNUC__)
-      // There is no rdtsc on ARMv8. CNTVCT_EL0 is the virtual counter of the
-      // system timer. It runs at a different frequency than the CPU's, but is
-      // the best source of time-based entropy we get.
-      uint64_t virtual_timer_value;
-      asm volatile("mrs %0, cntvct_el0" : "=r"(virtual_timer_value));
-      s += virtual_timer_value;
-#endif
-#endif  // !defined(GOOGLE_PROTOBUF_NO_RDTSC)
-      return s;
-    }
-
     friend class Arena;
     using InternalArenaConstructable_ = void;
     using DestructorSkippable_ = void;
-
-    size_type num_elements_;
-    size_type num_buckets_;
-    size_type seed_;
-    size_type index_of_first_non_null_;
-    void** table_;  // an array with num_buckets_ entries
-    Allocator alloc_;
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(InnerMap);
   };  // end of class InnerMap
 
   template <typename LookupKey>
@@ -1210,7 +1322,11 @@
       ++it_;
       return *this;
     }
-    const_iterator operator++(int) { return const_iterator(it_++); }
+    const_iterator operator++(int) {
+      auto copy = *this;
+      ++*this;
+      return copy;
+    }
 
     friend bool operator==(const const_iterator& a, const const_iterator& b) {
       return a.it_ == b.it_;
@@ -1243,7 +1359,11 @@
       ++it_;
       return *this;
     }
-    iterator operator++(int) { return iterator(it_++); }
+    iterator operator++(int) {
+      auto copy = *this;
+      ++*this;
+      return copy;
+    }
 
     // Allow implicit conversion to const_iterator.
     operator const_iterator() const {  // NOLINT(runtime/explicit)
@@ -1270,7 +1390,6 @@
   const_iterator cbegin() const { return begin(); }
   const_iterator cend() const { return end(); }
 
-  // Capacity
   size_type size() const { return elements_.size(); }
   bool empty() const { return size() == 0; }
 
@@ -1351,23 +1470,31 @@
         elements_.try_emplace(std::forward<K>(k), std::forward<Args>(args)...);
     return std::pair<iterator, bool>(iterator(p.first), p.second);
   }
-  std::pair<iterator, bool> insert(const value_type& value) {
-    return try_emplace(value.first, value.second);
+  std::pair<iterator, bool> insert(init_type&& value) {
+    return try_emplace(std::move(value.first), std::move(value.second));
   }
-  std::pair<iterator, bool> insert(value_type&& value) {
-    return try_emplace(value.first, std::move(value.second));
+  template <typename P, RequiresInsertable<P> = 0>
+  std::pair<iterator, bool> insert(P&& value) {
+    return try_emplace(std::forward<P>(value).first,
+                       std::forward<P>(value).second);
   }
   template <typename... Args>
   std::pair<iterator, bool> emplace(Args&&... args) {
-    return insert(value_type(std::forward<Args>(args)...));
+    return EmplaceInternal(Rank0{}, std::forward<Args>(args)...);
   }
   template <class InputIt>
   void insert(InputIt first, InputIt last) {
     for (; first != last; ++first) {
-      try_emplace(first->first, first->second);
+      auto&& pair = *first;
+      try_emplace(pair.first, pair.second);
     }
   }
-  void insert(std::initializer_list<value_type> values) {
+  void insert(std::initializer_list<init_type> values) {
+    insert(values.begin(), values.end());
+  }
+  template <typename P, RequiresNotInit<P> = 0,
+            RequiresInsertable<const P&> = 0>
+  void insert(std::initializer_list<P> values) {
     insert(values.begin(), values.end());
   }
 
@@ -1405,7 +1532,7 @@
 
   void swap(Map& other) {
     if (arena() == other.arena()) {
-      InternalSwap(other);
+      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
@@ -1416,11 +1543,9 @@
     }
   }
 
-  void InternalSwap(Map& other) { elements_.Swap(&other.elements_); }
+  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 {}; }
 
   size_t SpaceUsedExcludingSelfLong() const {
     if (empty()) return 0;
@@ -1428,6 +1553,23 @@
   }
 
  private:
+  struct Rank1 {};
+  struct Rank0 : Rank1 {};
+
+  // We try to construct `init_type` from `Args` with a fall back to
+  // `value_type`. The latter is less desired as it unconditionally makes a copy
+  // of `value_type::first`.
+  template <typename... Args>
+  auto EmplaceInternal(Rank0, Args&&... args) ->
+      typename std::enable_if<std::is_constructible<init_type, Args...>::value,
+                              std::pair<iterator, bool>>::type {
+    return insert(init_type(std::forward<Args>(args)...));
+  }
+  template <typename... Args>
+  std::pair<iterator, bool> EmplaceInternal(Rank1, Args&&... args) {
+    return insert(value_type(std::forward<Args>(args)...));
+  }
+
   Arena* arena() const { return elements_.arena(); }
   InnerMap elements_;
 
@@ -1440,9 +1582,18 @@
   friend class internal::MapFieldLite;
 };
 
+namespace internal {
+template <typename... T>
+PROTOBUF_NOINLINE void MapMergeFrom(Map<T...>& dest, const Map<T...>& src) {
+  for (const auto& elem : src) {
+    dest[elem.first] = elem.second;
+  }
+}
+}  // namespace internal
+
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_MAP_H__
diff --git a/src/google/protobuf/map_entry.h b/src/google/protobuf/map_entry.h
index 536dec9..d220d90 100644
--- a/src/google/protobuf/map_entry.h
+++ b/src/google/protobuf/map_entry.h
@@ -31,16 +31,16 @@
 #ifndef GOOGLE_PROTOBUF_MAP_ENTRY_H__
 #define GOOGLE_PROTOBUF_MAP_ENTRY_H__
 
-#include <google/protobuf/port.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/map_entry_lite.h>
-#include <google/protobuf/map_type_handler.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/port.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/map_entry_lite.h"
+#include "google/protobuf/map_type_handler.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -98,6 +98,8 @@
   explicit MapEntry(Arena* arena)
       : MapEntryImpl<Derived, Message, Key, Value, kKeyFieldType,
                      kValueFieldType>(arena) {}
+  MapEntry(const MapEntry&) = delete;
+  MapEntry& operator=(const MapEntry&) = delete;
   ~MapEntry() override {
     Message::_internal_metadata_.template Delete<UnknownFieldSet>();
   }
@@ -121,14 +123,12 @@
   template <typename C, typename K, typename V,
             WireFormatLite::FieldType k_wire_type, WireFormatLite::FieldType>
   friend class internal::MapField;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntry);
 };
 
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_MAP_ENTRY_H__
diff --git a/src/google/protobuf/map_entry_lite.h b/src/google/protobuf/map_entry_lite.h
index 6b08cd9..411be6e 100644
--- a/src/google/protobuf/map_entry_lite.h
+++ b/src/google/protobuf/map_entry_lite.h
@@ -37,19 +37,20 @@
 #include <string>
 #include <utility>
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/map.h>
-#include <google/protobuf/map_type_handler.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/arena.h"
+#include "absl/base/casts.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/map.h"
+#include "google/protobuf/map_type_handler.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
+
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
@@ -102,7 +103,7 @@
 };
 
 // MapEntryImpl is used to implement parsing and serialization of map entries.
-// It uses Curious Recursive Template Pattern (CRTP) to provide the type of
+// It uses Curiously Recurring Template Pattern (CRTP) to provide the type of
 // the eventual code to the template code.
 template <typename Derived, typename Base, typename Key, typename Value,
           WireFormatLite::FieldType kKeyFieldType,
@@ -159,6 +160,9 @@
         value_(ValueTypeHandler::Constinit()),
         _has_bits_{} {}
 
+  MapEntryImpl(const MapEntryImpl&) = delete;
+  MapEntryImpl& operator=(const MapEntryImpl&) = delete;
+
   ~MapEntryImpl() override {
     if (Base::GetArenaForAllocation() != nullptr) return;
     KeyTypeHandler::DeleteNoArena(key_);
@@ -167,10 +171,10 @@
 
   // accessors ======================================================
 
-  virtual inline const KeyMapEntryAccessorType& key() const {
+  inline const KeyMapEntryAccessorType& key() const {
     return KeyTypeHandler::GetExternalReference(key_);
   }
-  virtual inline const ValueMapEntryAccessorType& value() const {
+  inline const ValueMapEntryAccessorType& value() const {
     return ValueTypeHandler::DefaultIfNotInitialized(value_);
   }
   inline KeyMapEntryAccessorType* mutable_key() {
@@ -425,12 +429,14 @@
   typedef void DestructorSkippable_;
   template <typename C, typename K, typename V, WireFormatLite::FieldType,
             WireFormatLite::FieldType>
-  friend class internal::MapEntry;
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::MapEntry;
   template <typename C, typename K, typename V, WireFormatLite::FieldType,
             WireFormatLite::FieldType>
-  friend class internal::MapFieldLite;
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::MapFieldLite;
 
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryImpl);
+  template <typename DerivedT, typename KeyT, typename TT,
+            WireFormatLite::FieldType, WireFormatLite::FieldType>
+  friend class ::PROTOBUF_NAMESPACE_ID::internal::MapField;
 };
 
 template <typename T, typename Key, typename Value,
@@ -443,14 +449,13 @@
                        kValueFieldType>
       SuperType;
   constexpr MapEntryLite() {}
+  MapEntryLite(const MapEntryLite&) = delete;
+  MapEntryLite& operator=(const MapEntryLite&) = delete;
   explicit MapEntryLite(Arena* arena) : SuperType(arena) {}
   ~MapEntryLite() override {
     MessageLite::_internal_metadata_.template Delete<std::string>();
   }
   void MergeFrom(const MapEntryLite& other) { MergeFromInternal(other); }
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapEntryLite);
 };
 
 // Helpers for deterministic serialization =============================
@@ -558,6 +563,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_MAP_ENTRY_LITE_H__
diff --git a/src/google/protobuf/map_field.cc b/src/google/protobuf/map_field.cc
index ed662df..b340104 100644
--- a/src/google/protobuf/map_field.cc
+++ b/src/google/protobuf/map_field.cc
@@ -28,18 +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.
 
-#include <google/protobuf/map_field.h>
+#include "google/protobuf/map_field.h"
 
 #include <vector>
 
-#include <google/protobuf/map_field_inl.h>
+#include "google/protobuf/port.h"
+#include "google/protobuf/map_field_inl.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace internal {
+using ::google::protobuf::internal::DownCast;
 
 void MapFieldBase::Destruct() {
   if (arena_ == nullptr) {
@@ -427,7 +429,7 @@
 }
 
 void DynamicMapField::Swap(MapFieldBase* other) {
-  DynamicMapField* other_field = down_cast<DynamicMapField*>(other);
+  DynamicMapField* other_field = DownCast<DynamicMapField*>(other);
   std::swap(this->MapFieldBase::repeated_field_, other_field->repeated_field_);
   map_.swap(other_field->map_);
   // a relaxed swap of the atomic
@@ -651,4 +653,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/map_field.h b/src/google/protobuf/map_field.h
index 287d58f..0f1a607 100644
--- a/src/google/protobuf/map_field.h
+++ b/src/google/protobuf/map_field.h
@@ -34,22 +34,22 @@
 #include <atomic>
 #include <functional>
 
-#include <google/protobuf/arena.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/map_entry.h>
-#include <google/protobuf/map_field_lite.h>
-#include <google/protobuf/map_type_handler.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/arena.h"
+#include "google/protobuf/port.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/map_entry.h"
+#include "google/protobuf/map_field_lite.h"
+#include "google/protobuf/map_type_handler.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/unknown_field_set.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -342,10 +342,12 @@
   constexpr MapFieldBase(ConstantInitialized)
       : arena_(nullptr),
         repeated_field_(nullptr),
-        mutex_(GOOGLE_PROTOBUF_LINKER_INITIALIZED),
+        mutex_(absl::kConstInit),
         state_(STATE_MODIFIED_MAP) {}
   explicit MapFieldBase(Arena* arena)
       : arena_(arena), repeated_field_(nullptr), state_(STATE_MODIFIED_MAP) {}
+  MapFieldBase(const MapFieldBase&) = delete;
+  MapFieldBase& operator=(const MapFieldBase&) = delete;
 
  protected:
   ~MapFieldBase() {  // "protected" stops users from deleting a `MapFieldBase *`
@@ -449,9 +451,8 @@
   Arena* arena_;
   mutable RepeatedPtrField<Message>* repeated_field_;
 
-  mutable internal::WrappedMutex
-      mutex_;  // The thread to synchronize map and repeated field
-               // needs to get lock first;
+  mutable absl::Mutex mutex_;  // The thread to synchronize map and repeated
+                               // field needs to get lock first;
   mutable std::atomic<State> state_;
 
  private:
@@ -484,8 +485,6 @@
 
   // Swaps state_ with another MapFieldBase
   void SwapState(MapFieldBase* other);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapFieldBase);
 };
 
 // This class provides common Map Reflection implementations for generated
@@ -494,6 +493,8 @@
 class TypeDefinedMapFieldBase : public MapFieldBase {
  public:
   TypeDefinedMapFieldBase() {}
+  TypeDefinedMapFieldBase(const TypeDefinedMapFieldBase&) = delete;
+  TypeDefinedMapFieldBase& operator=(const TypeDefinedMapFieldBase&) = delete;
 
   // This constructor is for constant initialized global instances.
   // It uses a linker initialized mutex, so it is not compatible with regular
@@ -529,7 +530,6 @@
   void IncreaseIterator(MapIterator* map_iter) const override;
 
   virtual void SetMapIteratorValue(MapIterator* map_iter) const = 0;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeDefinedMapFieldBase);
 };
 
 // This class provides access to map field using generated api. It is used for
@@ -562,6 +562,8 @@
   typedef Map<Key, T> MapType;
 
   MapField() : impl_() {}
+  MapField(const MapField&) = delete;
+  MapField& operator=(const MapField&) = delete;
   virtual ~MapField() {}  // Destruct() must already have been called!
   void Destruct() {
     impl_.Destruct();
@@ -635,7 +637,6 @@
 
   friend class ::PROTOBUF_NAMESPACE_ID::Arena;
   friend class MapFieldStateTest;  // For testing, it needs raw access to impl_
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapField);
 };
 
 template <typename Derived, typename Key, typename T,
@@ -664,6 +665,8 @@
  public:
   explicit DynamicMapField(const Message* default_entry);
   DynamicMapField(const Message* default_entry, Arena* arena);
+  DynamicMapField(const DynamicMapField&) = delete;
+  DynamicMapField& operator=(const DynamicMapField&) = delete;
   virtual ~DynamicMapField();
 
   // Implement MapFieldBase
@@ -694,7 +697,6 @@
   void SyncMapWithRepeatedFieldNoLock() const override;
   size_t SpaceUsedExcludingSelfNoLock() const override;
   void SetMapIteratorValue(MapIterator* map_iter) const override;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DynamicMapField);
 };
 
 }  // namespace internal
@@ -941,6 +943,6 @@
 #pragma warning(pop)  // restore warning C4265
 #endif                // _MSC_VER
 
-#include <google/protobuf/port_undef.inc>
+#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 7c4c232..9311abd 100644
--- a/src/google/protobuf/map_field_inl.h
+++ b/src/google/protobuf/map_field_inl.h
@@ -33,10 +33,14 @@
 
 #include <memory>
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/map.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/map_type_handler.h>
+#include "absl/base/casts.h"
+#include "google/protobuf/map.h"
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/map_type_handler.h"
+#include "google/protobuf/port.h"
+
+// must be last
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -278,7 +282,7 @@
 void MapField<Derived, Key, T, kKeyFieldType, kValueFieldType>::Swap(
     MapFieldBase* other) {
   MapFieldBase::Swap(other);
-  MapField* other_field = down_cast<MapField*>(other);
+  MapField* other_field = DownCast<MapField*>(other);
   impl_.Swap(&other_field->impl_);
 }
 
@@ -287,7 +291,7 @@
           WireFormatLite::FieldType kValueFieldType>
 void MapField<Derived, Key, T, kKeyFieldType,
               kValueFieldType>::UnsafeShallowSwap(MapFieldBase* other) {
-  InternalSwap(down_cast<MapField*>(other));
+  InternalSwap(DownCast<MapField*>(other));
 }
 
 template <typename Derived, typename Key, typename T,
@@ -325,7 +329,7 @@
   for (typename Map<Key, T>::const_iterator it = map.begin(); it != map.end();
        ++it) {
     EntryType* new_entry =
-        down_cast<EntryType*>(default_entry->New(this->MapFieldBase::arena_));
+        DownCast<EntryType*>(default_entry->New(this->MapFieldBase::arena_));
     repeated_field->AddAllocated(new_entry);
     (*new_entry->mutable_key()) = it->first;
     (*new_entry->mutable_value()) = it->second;
@@ -372,4 +376,6 @@
 }  // namespace protobuf
 }  // namespace google
 
+#include "google/protobuf/port_undef.inc"
+
 #endif  // GOOGLE_PROTOBUF_MAP_FIELD_INL_H__
diff --git a/src/google/protobuf/map_field_lite.h b/src/google/protobuf/map_field_lite.h
index 53bf7a0..fe2f2b2 100644
--- a/src/google/protobuf/map_field_lite.h
+++ b/src/google/protobuf/map_field_lite.h
@@ -33,15 +33,15 @@
 
 #include <type_traits>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/map.h>
-#include <google/protobuf/map_entry_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/port.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/map.h"
+#include "google/protobuf/map_entry_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -83,7 +83,7 @@
     // data in it, as would happen if a vector was resize'd to zero.
     // Map::Swap with an empty map accomplishes that.
     decltype(map_) swapped_map(map_.arena());
-    map_.InternalSwap(swapped_map);
+    map_.InternalSwap(&swapped_map);
   }
   ~MapFieldLite() {
     if (map_.arena() == nullptr && !map_.empty()) {
@@ -99,13 +99,10 @@
   int size() const { return static_cast<int>(map_.size()); }
   void Clear() { return map_.clear(); }
   void MergeFrom(const MapFieldLite& other) {
-    for (typename Map<Key, T>::const_iterator it = other.map_.begin();
-         it != other.map_.end(); ++it) {
-      map_[it->first] = it->second;
-    }
+    internal::MapMergeFrom(map_, other.map_);
   }
   void Swap(MapFieldLite* other) { map_.swap(other->map_); }
-  void InternalSwap(MapFieldLite* other) { map_.InternalSwap(other->map_); }
+  void InternalSwap(MapFieldLite* other) { map_.InternalSwap(&other->map_); }
 
   // Used in the implementation of parsing. Caller should take the ownership iff
   // arena_ is nullptr.
@@ -204,6 +201,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_MAP_FIELD_LITE_H__
diff --git a/src/google/protobuf/map_field_test.cc b/src/google/protobuf/map_field_test.cc
index 1659c95..c041883 100644
--- a/src/google/protobuf/map_field_test.cc
+++ b/src/google/protobuf/map_field_test.cc
@@ -30,23 +30,24 @@
 
 #include <map>
 #include <memory>
-#include <unordered_map>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/map_unittest.pb.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/map.h>
-#include <google/protobuf/map_field_inl.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/map.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/arena_test_util.h>
-#include <google/protobuf/map_test_util.h>
+#include "absl/container/flat_hash_map.h"
+#include "absl/strings/str_format.h"
+#include "google/protobuf/arena_test_util.h"
+#include "google/protobuf/map_test_util.h"
+#include "google/protobuf/map_unittest.pb.h"
+#include "google/protobuf/unittest.pb.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -71,14 +72,6 @@
   MapFieldBaseStub() {}
   virtual ~MapFieldBaseStub() { MapFieldBase::Destruct(); }
   explicit MapFieldBaseStub(Arena* arena) : MapFieldBase(arena) {}
-  // Get underlined repeated field without synchronizing map.
-  RepeatedPtrField<Message>* InternalRepeatedField() { return repeated_field_; }
-  bool IsMapClean() {
-    return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_MAP;
-  }
-  bool IsRepeatedClean() {
-    return state_.load(std::memory_order_relaxed) != STATE_MODIFIED_REPEATED;
-  }
   void SetMapDirty() {
     state_.store(STATE_MODIFIED_MAP, std::memory_order_relaxed);
   }
@@ -292,26 +285,28 @@
 
   void Expect(MapFieldType* map_field, State state, int map_size,
               int repeated_size, bool is_repeated_null) {
-    MapFieldBase* map_field_base = map_field;
-    MapFieldBaseStub* stub =
-        reinterpret_cast<MapFieldBaseStub*>(map_field_base);
-
     // We use MutableMap on impl_ because we don't want to disturb the syncing
     Map<int32_t, int32_t>* map = map_field->impl_.MutableMap();
-    RepeatedPtrField<Message>* repeated_field = stub->InternalRepeatedField();
+    RepeatedPtrField<Message>* repeated_field = map_field->repeated_field_;
 
     switch (state) {
       case MAP_DIRTY:
-        EXPECT_FALSE(stub->IsMapClean());
-        EXPECT_TRUE(stub->IsRepeatedClean());
+        EXPECT_FALSE(map_field->state_.load(std::memory_order_relaxed) !=
+                     MapFieldType::STATE_MODIFIED_MAP);
+        EXPECT_TRUE(map_field->state_.load(std::memory_order_relaxed) !=
+                    MapFieldType::STATE_MODIFIED_REPEATED);
         break;
       case REPEATED_DIRTY:
-        EXPECT_TRUE(stub->IsMapClean());
-        EXPECT_FALSE(stub->IsRepeatedClean());
+        EXPECT_TRUE(map_field->state_.load(std::memory_order_relaxed) !=
+                    MapFieldType::STATE_MODIFIED_MAP);
+        EXPECT_FALSE(map_field->state_.load(std::memory_order_relaxed) !=
+                     MapFieldType::STATE_MODIFIED_REPEATED);
         break;
       case CLEAN:
-        EXPECT_TRUE(stub->IsMapClean());
-        EXPECT_TRUE(stub->IsRepeatedClean());
+        EXPECT_TRUE(map_field->state_.load(std::memory_order_relaxed) !=
+                    MapFieldType::STATE_MODIFIED_MAP);
+        EXPECT_TRUE(map_field->state_.load(std::memory_order_relaxed) !=
+                    MapFieldType::STATE_MODIFIED_REPEATED);
         break;
       default:
         FAIL();
diff --git a/src/google/protobuf/map_lite_test_util.cc b/src/google/protobuf/map_lite_test_util.cc
index 121f267..d519ba4 100644
--- a/src/google/protobuf/map_lite_test_util.cc
+++ b/src/google/protobuf/map_lite_test_util.cc
@@ -28,10 +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 <google/protobuf/map_lite_test_util.h>
+#include "google/protobuf/map_lite_test_util.h"
 
-#include <google/protobuf/map_lite_unittest.pb.h>
-#include <google/protobuf/map_test_util_impl.h>
+#include "google/protobuf/map_lite_unittest.pb.h"
+#include "google/protobuf/map_test_util_impl.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/map_lite_test_util.h b/src/google/protobuf/map_lite_test_util.h
index 573de7b..a4a1e61 100644
--- a/src/google/protobuf/map_lite_test_util.h
+++ b/src/google/protobuf/map_lite_test_util.h
@@ -31,7 +31,7 @@
 #ifndef GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
 #define GOOGLE_PROTOBUF_MAP_LITE_TEST_UTIL_H__
 
-#include <google/protobuf/map_lite_unittest.pb.h>
+#include "google/protobuf/map_lite_unittest.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/map_proto2_unittest.proto b/src/google/protobuf/map_proto2_unittest.proto
index 20d58f9..9cda195 100644
--- a/src/google/protobuf/map_proto2_unittest.proto
+++ b/src/google/protobuf/map_proto2_unittest.proto
@@ -29,25 +29,26 @@
 // OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
 
 syntax = "proto2";
-option cc_enable_arenas = true;
 
 import "google/protobuf/unittest_import.proto";
 
+option cc_enable_arenas = true;
+
 // 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 map_test_util.h we do "using namespace unittest = protobuf_unittest".
 package protobuf_unittest;
 
 enum Proto2MapEnum {
-  PROTO2_MAP_ENUM_FOO   = 0;
-  PROTO2_MAP_ENUM_BAR   = 1;
-  PROTO2_MAP_ENUM_BAZ   = 2;
+  PROTO2_MAP_ENUM_FOO = 0;
+  PROTO2_MAP_ENUM_BAR = 1;
+  PROTO2_MAP_ENUM_BAZ = 2;
 }
 
 enum Proto2MapEnumPlusExtra {
-  E_PROTO2_MAP_ENUM_FOO   = 0;
-  E_PROTO2_MAP_ENUM_BAR   = 1;
-  E_PROTO2_MAP_ENUM_BAZ   = 2;
+  E_PROTO2_MAP_ENUM_FOO = 0;
+  E_PROTO2_MAP_ENUM_BAR = 1;
+  E_PROTO2_MAP_ENUM_BAZ = 2;
   E_PROTO2_MAP_ENUM_EXTRA = 3;
 }
 
diff --git a/src/google/protobuf/map_test.cc b/src/google/protobuf/map_test.cc
index f7c024c..5f78a3e 100644
--- a/src/google/protobuf/map_test.cc
+++ b/src/google/protobuf/map_test.cc
@@ -28,10 +28,12 @@
 // (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/map_proto2_unittest.pb.h>
-#include <google/protobuf/map_unittest.pb.h>
-#include <google/protobuf/reflection_tester.h>
-#include <google/protobuf/test_util2.h>
+#include "absl/container/flat_hash_set.h"
+#include "google/protobuf/map_proto2_unittest.pb.h"
+#include "google/protobuf/map_unittest.pb.h"
+#include "google/protobuf/reflection_tester.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_import.pb.h"
 
 
 #define BRIDGE_UNITTEST ::google::protobuf::bridge_unittest
@@ -41,13 +43,13 @@
 
 // Must include after defining UNITTEST, etc.
 // clang-format off
-#include <google/protobuf/test_util.inc>
-#include <google/protobuf/map_test_util.inc>
-#include <google/protobuf/map_test.inc>
+#include "google/protobuf/test_util.inc"
+#include "google/protobuf/map_test_util.inc"
+#include "google/protobuf/map_test.inc"
 // clang-format on
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -84,3 +86,5 @@
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
+
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/map_test.inc b/src/google/protobuf/map_test.inc
index 18a7bfb..9be584c 100644
--- a/src/google/protobuf/map_test.inc
+++ b/src/google/protobuf/map_test.inc
@@ -42,40 +42,40 @@
 #include <random>
 #include <set>
 #include <sstream>
-#include <unordered_map>
-#include <unordered_set>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/descriptor.pb.h"
 #include <gmock/gmock.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/substitute.h>
-#include <google/protobuf/arena_test_util.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor_database.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/map.h>
-#include <google/protobuf/map_field_inl.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/test_util2.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/util/message_differencer.h>
-#include <google/protobuf/util/time_util.h>
-#include <google/protobuf/wire_format.h>
+#include "absl/base/casts.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/arena_test_util.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor_database.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/map.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/test_util2.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/util/message_differencer.h"
+#include "google/protobuf/util/time_util.h"
+#include "google/protobuf/wire_format.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -92,6 +92,7 @@
 }
 
 namespace {
+using internal::DownCast;
 
 // Map API Test =====================================================
 
@@ -500,18 +501,12 @@
   }
 }
 
-// EXPECT i0 and i1 to be the same.  Advancing them should have the same effect,
-// too.
+// EXPECT i0 and i1 to be the same.
 template <typename Iter>
 static void TestEqualIterators(Iter i0, Iter i1, Iter end) {
-  const int kMaxAdvance = 10;
-  for (int i = 0; i < kMaxAdvance; i++) {
-    EXPECT_EQ(i0 == end, i1 == end);
-    if (i0 == end) return;
-    EXPECT_EQ(&*i0, &*i1) << "iter " << i;
-    ++i0;
-    ++i1;
-  }
+  EXPECT_EQ(i0 == end, i1 == end);
+  if (i0 == end) return;
+  EXPECT_EQ(&*i0, &*i1);
 }
 
 template <typename IteratorType>
@@ -570,8 +565,8 @@
   ASSERT_EQ(n, m.size());
   // Create maps of pointers and iterators.
   // These should remain valid even if we modify m.
-  std::unordered_map<int, Map<int, int>::value_type*> mp(n);
-  std::unordered_map<int, Map<int, int>::iterator> mi(n);
+  absl::flat_hash_map<int, Map<int, int>::value_type*> mp(n);
+  absl::flat_hash_map<int, Map<int, int>::iterator> mi(n);
   for (Map<int, int>::iterator it = m.begin(); it != m.end(); ++it) {
     mp[it->first] = &*it;
     mi[it->first] = it;
@@ -737,6 +732,47 @@
   EXPECT_FALSE(result2.second);
 }
 
+TEST_F(MapImplTest, InsertSingleBraceInitList) {
+  int32_t key = 0;
+  int32_t value1 = 100;
+  int32_t value2 = 101;
+
+  // Insert a non-existing key.
+  auto result1 = map_.insert({key, value1});
+  ExpectSingleElement(key, value1);
+
+  auto it1 = result1.first;
+  EXPECT_EQ(key, it1->first);
+  EXPECT_EQ(value1, it1->second);
+  EXPECT_TRUE(result1.second);
+
+  // Insert an existing key.
+  auto result2 = map_.insert({key, value2});
+  ExpectSingleElement(key, value1);
+
+  auto it2 = result2.first;
+  EXPECT_TRUE(it1 == it2);
+  EXPECT_FALSE(result2.second);
+}
+
+TEST_F(MapImplTest, InsertSingleBraceInitListTypeMismatch) {
+  int32_t key = 0;
+  int32_t value1 = 100;
+  int32_t value2 = 101;
+  Map<int64_t, int64_t> m;
+
+  // Insert a non-existing key.
+  auto result1 = m.insert({key, value1});
+  EXPECT_TRUE(result1.second);
+
+  // Insert an existing key.
+  auto result2 = m.insert({key, value2});
+  EXPECT_FALSE(result2.second);
+
+  EXPECT_TRUE(result1.first == result2.first);
+}
+
+
 TEST_F(MapImplTest, TryEmplace) {
   using ::testing::Pair;
   using ::testing::UnorderedElementsAre;
@@ -769,6 +805,59 @@
       m, UnorderedElementsAre(Pair(1, "one"), Pair(2, "two"), Pair(42, "aaa")));
 }
 
+#ifndef PROTOBUF_FUTURE_MAP_PAIR_UPGRADE
+
+TEST_F(MapImplTest, EmplaceKeyOnly) {
+  using ::testing::Pair;
+  using ::testing::UnorderedElementsAre;
+
+  Map<int32_t, std::string> m;
+
+  m.emplace(1);
+  EXPECT_EQ(m.size(), 1);
+
+  const int32_t key = 42;
+  m.emplace(key);
+  EXPECT_THAT(m, UnorderedElementsAre(Pair(1, ""), Pair(42, "")));
+}
+
+#else
+
+TEST_F(MapImplTest, ValueTypeNoImplicitConversion) {
+  using vt = typename Map<const char*, int>::value_type;
+
+  EXPECT_FALSE((std::is_convertible<
+                vt, std::pair<std::string, std::vector<std::string>>>::value));
+}
+
+enum class ConstructorType {
+  kDefault,
+  kCopy,
+  kMove,
+};
+
+struct ConstructorTag {
+  ConstructorTag() : invoked_constructor(ConstructorType::kDefault) {}
+  ConstructorTag(const ConstructorTag&)
+      : invoked_constructor(ConstructorType::kCopy) {}
+  ConstructorTag(ConstructorTag&&)
+      : invoked_constructor(ConstructorType::kMove) {}
+
+  ConstructorType invoked_constructor;
+};
+
+TEST_F(MapImplTest, ValueTypeHasMoveConstructor) {
+  using vt = typename Map<ConstructorTag, ConstructorTag>::value_type;
+  ConstructorTag l, r;
+
+  vt pair(l, std::move(r));
+
+  EXPECT_EQ(pair.first.invoked_constructor, ConstructorType::kCopy);
+  EXPECT_EQ(pair.second.invoked_constructor, ConstructorType::kMove);
+}
+
+#endif  // !PROTOBUF_FUTURE_MAP_PAIR_UPGRADE
+
 struct CountedInstance {
   CountedInstance() { ++num_created; }
   CountedInstance(const CountedInstance&) : CountedInstance() {}
@@ -1253,6 +1342,10 @@
   // An newly constructed map should have no space used.
   EXPECT_EQ(m.SpaceUsedExcludingSelfLong(), 0);
 
+  struct IntIntNode : internal::NodeBase {
+    std::pair<int32_t, int32_t> kv;
+  };
+
   size_t capacity = kMinCap;
   for (int i = 0; i < 100; ++i) {
     m[i];
@@ -1260,27 +1353,32 @@
     if (m.size() >= capacity * kMaxLoadFactor) {
       capacity *= 2;
     }
-    EXPECT_EQ(
-        m.SpaceUsedExcludingSelfLong(),
-        sizeof(void*) * capacity +
-            m.size() * sizeof(std::pair<std::pair<int32_t, int32_t>, void*>));
+    EXPECT_EQ(m.SpaceUsedExcludingSelfLong(),
+              sizeof(void*) * capacity + m.size() * sizeof(IntIntNode));
   }
 
   // Test string, and non-scalar keys.
   Map<std::string, int32_t> m2;
   std::string str = "Some arbitrarily large string";
   m2[str] = 1;
+
+  struct StringIntNode : internal::NodeBase {
+    std::pair<std::string, int32_t> kv;
+  };
+
   EXPECT_EQ(m2.SpaceUsedExcludingSelfLong(),
-            sizeof(void*) * kMinCap +
-                sizeof(std::pair<std::pair<std::string, int32_t>, void*>) +
+            sizeof(void*) * kMinCap + sizeof(StringIntNode) +
                 internal::StringSpaceUsedExcludingSelfLong(str));
 
+  struct IntAllTypesNode : internal::NodeBase {
+    std::pair<int32_t, TestAllTypes> kv;
+  };
+
   // Test messages, and non-scalar values.
   Map<int32_t, TestAllTypes> m3;
   m3[0].set_optional_string(str);
   EXPECT_EQ(m3.SpaceUsedExcludingSelfLong(),
-            sizeof(void*) * kMinCap +
-                sizeof(std::pair<std::pair<int32_t, TestAllTypes>, void*>) +
+            sizeof(void*) * kMinCap + sizeof(IntAllTypesNode) +
                 m3[0].SpaceUsedLong() - sizeof(m3[0]));
 }
 
@@ -1393,7 +1491,7 @@
 
 static int Func(int i, int j) { return i * j; }
 
-static std::string StrFunc(int i, int j) { return StrCat(Func(i, j)); }
+static std::string StrFunc(int i, int j) { return absl::StrCat(Func(i, j)); }
 
 static int Int(const std::string& value) {
   int result = 0;
@@ -1516,7 +1614,7 @@
           message_int32_message.GetReflection()->GetInt32(
               message_int32_message, fd_map_int32_foreign_message_key);
       const ForeignMessage& value_int32_message =
-          down_cast<const ForeignMessage&>(
+          DownCast<const ForeignMessage&>(
               message_int32_message.GetReflection()->GetMessage(
                   message_int32_message, fd_map_int32_foreign_message_value));
       EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
@@ -1553,7 +1651,7 @@
           message_int32_message.GetReflection()->GetInt32(
               message_int32_message, fd_map_int32_foreign_message_key);
       const ForeignMessage& value_int32_message =
-          down_cast<const ForeignMessage&>(
+          DownCast<const ForeignMessage&>(
               message_int32_message.GetReflection()->GetMessage(
                   message_int32_message, fd_map_int32_foreign_message_value));
       EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
@@ -1590,7 +1688,7 @@
       int32_t key_int32_message =
           message_int32_message->GetReflection()->GetInt32(
               *message_int32_message, fd_map_int32_foreign_message_key);
-      ForeignMessage* value_int32_message = down_cast<ForeignMessage*>(
+      ForeignMessage* value_int32_message = DownCast<ForeignMessage*>(
           message_int32_message->GetReflection()->MutableMessage(
               message_int32_message, fd_map_int32_foreign_message_value));
       value_int32_message->set_c(Func(key_int32_message, -6));
@@ -1746,7 +1844,7 @@
           message_int32_message.GetReflection()->GetInt32(
               message_int32_message, fd_map_int32_foreign_message_key);
       const ForeignMessage& value_int32_message =
-          down_cast<const ForeignMessage&>(
+          DownCast<const ForeignMessage&>(
               message_int32_message.GetReflection()->GetMessage(
                   message_int32_message, fd_map_int32_foreign_message_value));
       EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
@@ -1787,7 +1885,7 @@
           message_int32_message.GetReflection()->GetInt32(
               message_int32_message, fd_map_int32_foreign_message_key);
       const ForeignMessage& value_int32_message =
-          down_cast<const ForeignMessage&>(
+          DownCast<const ForeignMessage&>(
               message_int32_message.GetReflection()->GetMessage(
                   message_int32_message, fd_map_int32_foreign_message_value));
       EXPECT_EQ(value_int32_message.c(), Func(key_int32_message, 6));
@@ -1846,10 +1944,8 @@
   // Test iterators.
   {
     int index = 0;
-    std::unordered_map<int32_t, int32_t> result;
-    for (RepeatedFieldRef<Message>::iterator it = mf_int32_int32.begin();
-         it != mf_int32_int32.end(); ++it) {
-      const Message& message = *it;
+    absl::flat_hash_map<int32_t, int32_t> result;
+    for (const auto& message : mf_int32_int32) {
       int32_t key =
           message.GetReflection()->GetInt32(message, fd_map_int32_in32_key);
       int32_t value =
@@ -1858,19 +1954,15 @@
       ++index;
     }
     EXPECT_EQ(10, index);
-    for (std::unordered_map<int32_t, int32_t>::const_iterator it =
-             result.begin();
-         it != result.end(); ++it) {
-      EXPECT_EQ(message.map_int32_int32().at(it->first), it->second);
+    for (const auto& kv : result) {
+      EXPECT_EQ(message.map_int32_int32().at(kv.first), kv.second);
     }
   }
 
   {
     int index = 0;
-    std::unordered_map<int32_t, double> result;
-    for (RepeatedFieldRef<Message>::iterator it = mf_int32_double.begin();
-         it != mf_int32_double.end(); ++it) {
-      const Message& message = *it;
+    absl::flat_hash_map<int32_t, double> result;
+    for (const auto& message : mf_int32_double) {
       int32_t key =
           message.GetReflection()->GetInt32(message, fd_map_int32_double_key);
       double value = message.GetReflection()->GetDouble(
@@ -1879,19 +1971,15 @@
       ++index;
     }
     EXPECT_EQ(10, index);
-    for (std::unordered_map<int32_t, double>::const_iterator it =
-             result.begin();
-         it != result.end(); ++it) {
-      EXPECT_EQ(message.map_int32_double().at(it->first), it->second);
+    for (const auto& kv : result) {
+      EXPECT_EQ(message.map_int32_double().at(kv.first), kv.second);
     }
   }
 
   {
     int index = 0;
-    std::unordered_map<std::string, std::string> result;
-    for (RepeatedFieldRef<Message>::iterator it = mf_string_string.begin();
-         it != mf_string_string.end(); ++it) {
-      const Message& message = *it;
+    absl::flat_hash_map<std::string, std::string> result;
+    for (const auto& message : mf_string_string) {
       std::string key =
           message.GetReflection()->GetString(message, fd_map_string_string_key);
       std::string value = message.GetReflection()->GetString(
@@ -1900,10 +1988,8 @@
       ++index;
     }
     EXPECT_EQ(10, index);
-    for (std::unordered_map<std::string, std::string>::const_iterator it =
-             result.begin();
-         it != result.end(); ++it) {
-      EXPECT_EQ(message.map_string_string().at(it->first), it->second);
+    for (const auto& kv : result) {
+      EXPECT_EQ(message.map_string_string().at(kv.first), kv.second);
     }
   }
 
@@ -1917,7 +2003,7 @@
       int32_t key = message.GetReflection()->GetInt32(
           message, fd_map_int32_foreign_message_key);
       const ForeignMessage& sub_message =
-          down_cast<const ForeignMessage&>(message.GetReflection()->GetMessage(
+          DownCast<const ForeignMessage&>(message.GetReflection()->GetMessage(
               message, fd_map_int32_foreign_message_value));
       result[key].MergeFrom(sub_message);
       ++index;
@@ -2072,13 +2158,13 @@
     const Message& message0a =
         mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get());
     const ForeignMessage& sub_message0a =
-        down_cast<const ForeignMessage&>(message0a.GetReflection()->GetMessage(
+        DownCast<const ForeignMessage&>(message0a.GetReflection()->GetMessage(
             message0a, fd_map_int32_foreign_message_value));
     int32_t int32_value0a = sub_message0a.c();
     const Message& message9a =
         mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get());
     const ForeignMessage& sub_message9a =
-        down_cast<const ForeignMessage&>(message9a.GetReflection()->GetMessage(
+        DownCast<const ForeignMessage&>(message9a.GetReflection()->GetMessage(
             message9a, fd_map_int32_foreign_message_value));
     int32_t int32_value9a = sub_message9a.c();
 
@@ -2087,13 +2173,13 @@
     const Message& message0b =
         mmf_int32_foreign_message.Get(0, entry_int32_foreign_message.get());
     const ForeignMessage& sub_message0b =
-        down_cast<const ForeignMessage&>(message0b.GetReflection()->GetMessage(
+        DownCast<const ForeignMessage&>(message0b.GetReflection()->GetMessage(
             message0b, fd_map_int32_foreign_message_value));
     int32_t int32_value0b = sub_message0b.c();
     const Message& message9b =
         mmf_int32_foreign_message.Get(9, entry_int32_foreign_message.get());
     const ForeignMessage& sub_message9b =
-        down_cast<const ForeignMessage&>(message9b.GetReflection()->GetMessage(
+        DownCast<const ForeignMessage&>(message9b.GetReflection()->GetMessage(
             message9b, fd_map_int32_foreign_message_value));
     int32_t int32_value9b = sub_message9b.c();
 
@@ -2431,7 +2517,7 @@
 
   MapTestUtil::SetMapFields(&message1);
 
-  const Message* source = implicit_cast<const Message*>(&message1);
+  const Message* source = absl::implicit_cast<const Message*>(&message1);
   message2.CopyFrom(*source);
 
   MapTestUtil::ExpectMapFieldsSet(message2);
@@ -2597,7 +2683,7 @@
   MapTestUtil::SetMapFields(&message1);
   size_t size = message1.ByteSizeLong();
   data.resize(size);
-  uint8_t* start = reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&data));
+  uint8_t* start = reinterpret_cast<uint8_t*>(&data[0]);
   uint8_t* end = message1.SerializeWithCachedSizesToArray(start);
   EXPECT_EQ(size, end - start);
   EXPECT_TRUE(message2.ParseFromString(data));
@@ -2613,7 +2699,7 @@
   data.resize(size);
   {
     // Allow the output stream to buffer only one byte at a time.
-    io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&data), size, 1);
+    io::ArrayOutputStream array_stream(&data[0], size, 1);
     io::CodedOutputStream output_stream(&array_stream);
     message1.SerializeWithCachedSizes(&output_stream);
     EXPECT_FALSE(output_stream.HadError());
@@ -2938,7 +3024,7 @@
   *p++ = 0;
   *p++ = WireFormatLite::MakeTag(2, WireFormatLite::WIRETYPE_LENGTH_DELIMITED);
   *p++ = payload_size;
-  StrAppend(&s, dummy4_s, dummy5_s);
+  absl::StrAppend(&s, dummy4_s, dummy5_s);
 
   // Test key then value then value.
   int key = 0;
@@ -3644,7 +3730,7 @@
     const T& t) {
   const size_t size = t.ByteSizeLong();
   std::string result(size, '\0');
-  io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
+  io::ArrayOutputStream array_stream(&result[0], size);
   io::CodedOutputStream output_stream(&array_stream);
   output_stream.SetSerializationDeterministic(true);
   t.SerializePartialToCodedStream(&output_stream);
@@ -3658,7 +3744,7 @@
     const T& t) {
   const size_t size = t.ByteSizeLong();
   std::string result(size, '\0');
-  io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
+  io::ArrayOutputStream array_stream(&result[0], size);
   io::CodedOutputStream output_stream(&array_stream);
   output_stream.SetSerializationDeterministic(true);
   t.SerializeToCodedStream(&output_stream);
@@ -3671,7 +3757,7 @@
 static std::string DeterministicSerialization(const T& t) {
   const size_t size = t.ByteSizeLong();
   std::string result(size, '\0');
-  io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&result), size);
+  io::ArrayOutputStream array_stream(&result[0], size);
   {
     io::CodedOutputStream output_stream(&array_stream);
     output_stream.SetSerializationDeterministic(true);
@@ -3689,7 +3775,7 @@
 static std::string ConstructKey(uint64_t n) {
   std::string s(n % static_cast<uint64_t>(9), '\0');
   if (s.empty()) {
-    return StrCat(n);
+    return absl::StrCat(n);
   } else {
     while (n != 0) {
       s[n % s.size()] = (n >> 10) & 0x7f;
@@ -3749,7 +3835,7 @@
   const std::string filename = "golden_message_maps";
   std::string golden;
   GOOGLE_CHECK_OK(File::GetContents(
-      TestUtil::GetTestDataPath("net/proto2/internal/testdata/" + filename),
+      TestUtil::GetTestDataPath("third_party/protobuf/testdata/" + filename),
       &golden, true));
   t.ParseFromString(golden);
   *(p.mutable_m()) = t;
@@ -3791,11 +3877,10 @@
 
   std::string expected_text;
   GOOGLE_CHECK_OK(
-      File::GetContents(TestUtil::GetTestDataPath("net/proto2/internal/"
+      File::GetContents(TestUtil::GetTestDataPath("third_party/protobuf/"
                                                   "testdata/map_test_data.txt"),
                         &expected_text, true));
 
-  CleanStringLineEndings(&expected_text, false);
   std::string actual_text;
   TextFormat::PrintToString(*message, &actual_text);
   EXPECT_EQ(actual_text, expected_text);
@@ -3808,11 +3893,10 @@
 
   std::string expected_text;
   GOOGLE_CHECK_OK(
-      File::GetContents(TestUtil::GetTestDataPath("net/proto2/internal/"
+      File::GetContents(TestUtil::GetTestDataPath("third_party/protobuf/"
                                                   "testdata/map_test_data.txt"),
                         &expected_text, true));
 
-  CleanStringLineEndings(&expected_text, false);
   TextFormat::Printer printer;
   std::string actual_text;
   printer.PrintToString(message, &actual_text);
@@ -3828,10 +3912,10 @@
 
 TEST(TextFormatMapTest, ParseCorruptedString) {
   std::string serialized_message;
-  GOOGLE_CHECK_OK(
-      File::GetContents(TestUtil::GetTestDataPath(
-                            "net/proto2/internal/testdata/golden_message_maps"),
-                        &serialized_message, true));
+  GOOGLE_CHECK_OK(File::GetContents(
+      TestUtil::GetTestDataPath(
+          "third_party/protobuf/testdata/golden_message_maps"),
+      &serialized_message, true));
   UNITTEST::TestMaps message;
   GOOGLE_CHECK(message.ParseFromString(serialized_message));
   TestParseCorruptedString<UNITTEST::TestMaps, true>(message);
@@ -4068,4 +4152,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/map_test_util.h b/src/google/protobuf/map_test_util.h
index f3215db..fd35eb7 100644
--- a/src/google/protobuf/map_test_util.h
+++ b/src/google/protobuf/map_test_util.h
@@ -31,14 +31,15 @@
 #ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
 #define GOOGLE_PROTOBUF_MAP_TEST_UTIL_H__
 
-#include <google/protobuf/map_unittest.pb.h>
-#include <google/protobuf/reflection_tester.h>
+#include "google/protobuf/map_unittest.pb.h"
+#include "google/protobuf/reflection_tester.h"
+#include "google/protobuf/unittest.pb.h"
 
 #define UNITTEST ::protobuf_unittest
 #define BRIDGE_UNITTEST ::google::protobuf::bridge_unittest
 
 // Must be included after defining UNITTEST, etc.
-#include <google/protobuf/map_test_util.inc>
+#include "google/protobuf/map_test_util.inc"
 
 #undef UNITTEST
 #undef BRIDGE_UNITTEST
diff --git a/src/google/protobuf/map_test_util.inc b/src/google/protobuf/map_test_util.inc
index 5b12c76..14b781a 100644
--- a/src/google/protobuf/map_test_util.inc
+++ b/src/google/protobuf/map_test_util.inc
@@ -28,9 +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.
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/map_test_util_impl.h>
-#include <google/protobuf/message.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/map_test_util_impl.h"
+#include "google/protobuf/message.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/map_test_util_impl.h b/src/google/protobuf/map_test_util_impl.h
index 655aec8..adbc3fc 100644
--- a/src/google/protobuf/map_test_util_impl.h
+++ b/src/google/protobuf/map_test_util_impl.h
@@ -31,8 +31,8 @@
 #ifndef GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
 #define GOOGLE_PROTOBUF_MAP_TEST_UTIL_IMPL_H__
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 #include <gtest/gtest.h>
 
 
diff --git a/src/google/protobuf/map_type_handler.h b/src/google/protobuf/map_type_handler.h
index c210c63..8979734 100644
--- a/src/google/protobuf/map_type_handler.h
+++ b/src/google/protobuf/map_type_handler.h
@@ -31,11 +31,11 @@
 #ifndef GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
 #define GOOGLE_PROTOBUF_MAP_TYPE_HANDLER_H__
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/wire_format_lite.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
diff --git a/src/google/protobuf/map_unittest.proto b/src/google/protobuf/map_unittest.proto
index 263ef61..ed623f8 100644
--- a/src/google/protobuf/map_unittest.proto
+++ b/src/google/protobuf/map_unittest.proto
@@ -76,7 +76,6 @@
   map<int32, int32> map2 = 2;
 }
 
-
 enum MapEnum {
   MAP_ENUM_FOO = 0;
   MAP_ENUM_BAR = 1;
@@ -111,7 +110,9 @@
 // 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 6cdc6c8..492e0f0 100644
--- a/src/google/protobuf/message.cc
+++ b/src/google/protobuf/message.cc
@@ -32,40 +32,41 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/message.h>
+#include "google/protobuf/message.h"
 
 #include <iostream>
 #include <stack>
-#include <unordered_map>
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/logging.h>
-#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/stubs/strutil.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/map_field_inl.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/reflection_internal.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/hash.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/base/casts.h"
+#include "absl/container/flat_hash_map.h"
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/generated_message_tctable_impl.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/reflection_internal.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
-
 namespace internal {
 
 // TODO(gerbens) make this factorized better. This should not have to hop
@@ -75,6 +76,7 @@
 
 }  // namespace internal
 
+using internal::DownCast;
 using internal::ReflectionOps;
 using internal::WireFormat;
 using internal::WireFormatLite;
@@ -92,7 +94,7 @@
 }
 
 void Message::CheckTypeAndMergeFrom(const MessageLite& other) {
-  MergeFrom(*down_cast<const Message*>(&other));
+  MergeFrom(*DownCast<const Message*>(&other));
 }
 
 void Message::CopyFrom(const Message& from) {
@@ -152,7 +154,7 @@
 std::string Message::InitializationErrorString() const {
   std::vector<std::string> errors;
   FindInitializationErrors(&errors);
-  return Join(errors, ", ");
+  return absl::StrJoin(errors, ", ");
 }
 
 void Message::CheckInitialized() const {
@@ -167,7 +169,15 @@
 
 const char* Message::_InternalParse(const char* ptr,
                                     internal::ParseContext* ctx) {
+#if defined(PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION)
+  auto meta = GetMetadata();
+  ptr = internal::TcParser::ParseLoop(this, ptr, ctx,
+                                      meta.reflection->GetTcParseTable());
+
+  return ptr;
+#else
   return WireFormat::_InternalParse(this, ptr, ctx);
+#endif
 }
 
 uint8_t* Message::_InternalSerialize(uint8_t* target,
@@ -213,6 +223,18 @@
   return salt;
 }
 
+namespace internal {
+void* CreateSplitMessageGeneric(Arena* arena, const void* default_split,
+                                size_t size, const void* message,
+                                const void* default_message) {
+  GOOGLE_DCHECK_NE(message, default_message);
+  void* split =
+      (arena == nullptr) ? ::operator new(size) : arena->AllocateAligned(size);
+  memcpy(split, default_split, size);
+  return split;
+}
+}  // namespace internal
+
 // =============================================================================
 // MessageFactory
 
@@ -220,11 +242,6 @@
 
 namespace {
 
-
-#define HASH_MAP std::unordered_map
-#define STR_HASH_FXN hash<::google::protobuf::StringPiece>
-
-
 class GeneratedMessageFactory final : public MessageFactory {
  public:
   static GeneratedMessageFactory* singleton();
@@ -236,14 +253,58 @@
   const Message* GetPrototype(const Descriptor* type) override;
 
  private:
-  // Only written at static init time, so does not require locking.
-  HASH_MAP<StringPiece, const google::protobuf::internal::DescriptorTable*,
-           STR_HASH_FXN>
-      file_map_;
+  const Message* FindInTypeMap(const Descriptor* type)
+      ABSL_SHARED_LOCKS_REQUIRED(mutex_)
+  {
+    auto it = type_map_.find(type);
+    if (it == type_map_.end()) return nullptr;
+    return it->second;
+  }
 
-  internal::WrappedMutex mutex_;
-  // Initialized lazily, so requires locking.
-  std::unordered_map<const Descriptor*, const Message*> type_map_;
+  const google::protobuf::internal::DescriptorTable* FindInFileMap(
+      absl::string_view name) {
+    auto it = files_.find(name);
+    if (it == files_.end()) return nullptr;
+    return *it;
+  }
+
+  struct DescriptorByNameHash {
+    using is_transparent = void;
+    size_t operator()(const google::protobuf::internal::DescriptorTable* t) const {
+      return absl::HashOf(absl::string_view{t->filename});
+    }
+
+    size_t operator()(absl::string_view name) const {
+      return absl::HashOf(name);
+    }
+  };
+  struct DescriptorByNameEq {
+    using is_transparent = void;
+    bool operator()(const google::protobuf::internal::DescriptorTable* lhs,
+                    const google::protobuf::internal::DescriptorTable* rhs) const {
+      return lhs == rhs || (*this)(lhs->filename, rhs->filename);
+    }
+    bool operator()(absl::string_view lhs,
+                    const google::protobuf::internal::DescriptorTable* rhs) const {
+      return (*this)(lhs, rhs->filename);
+    }
+    bool operator()(const google::protobuf::internal::DescriptorTable* lhs,
+                    absl::string_view rhs) const {
+      return (*this)(lhs->filename, rhs);
+    }
+    bool operator()(absl::string_view lhs, absl::string_view rhs) const {
+      return lhs == rhs;
+    }
+  };
+
+  // Only written at static init time, so does not require locking.
+  absl::flat_hash_set<const google::protobuf::internal::DescriptorTable*,
+                      DescriptorByNameHash, DescriptorByNameEq>
+      files_;
+
+  absl::Mutex mutex_;
+  absl::flat_hash_map<const Descriptor*, const Message*> type_map_
+      ABSL_GUARDED_BY(mutex_);
 };
 
 GeneratedMessageFactory* GeneratedMessageFactory::singleton() {
@@ -254,7 +315,7 @@
 
 void GeneratedMessageFactory::RegisterFile(
     const google::protobuf::internal::DescriptorTable* table) {
-  if (!InsertIfNotPresent(&file_map_, table->filename, table)) {
+  if (!files_.insert(table).second) {
     GOOGLE_LOG(FATAL) << "File is already registered: " << table->filename;
   }
 }
@@ -269,7 +330,7 @@
   // function during GetPrototype(), in which case we already have locked
   // the mutex.
   mutex_.AssertHeld();
-  if (!InsertIfNotPresent(&type_map_, descriptor, prototype)) {
+  if (!type_map_.try_emplace(descriptor, prototype).second) {
     GOOGLE_LOG(DFATAL) << "Type is already registered: " << descriptor->full_name();
   }
 }
@@ -277,8 +338,8 @@
 
 const Message* GeneratedMessageFactory::GetPrototype(const Descriptor* type) {
   {
-    ReaderMutexLock lock(&mutex_);
-    const Message* result = FindPtrOrNull(type_map_, type);
+    absl::ReaderMutexLock lock(&mutex_);
+    const Message* result = FindInTypeMap(type);
     if (result != nullptr) return result;
   }
 
@@ -288,7 +349,7 @@
 
   // Apparently the file hasn't been registered yet.  Let's do that now.
   const internal::DescriptorTable* registration_data =
-      FindPtrOrNull(file_map_, type->file()->name().c_str());
+      FindInFileMap(type->file()->name());
   if (registration_data == nullptr) {
     GOOGLE_LOG(DFATAL) << "File appears to be in generated pool but wasn't "
                    "registered: "
@@ -296,15 +357,15 @@
     return nullptr;
   }
 
-  WriterMutexLock lock(&mutex_);
+  absl::WriterMutexLock lock(&mutex_);
 
   // Check if another thread preempted us.
-  const Message* result = FindPtrOrNull(type_map_, type);
+  const Message* result = FindInTypeMap(type);
   if (result == nullptr) {
     // Nope.  OK, register everything.
     internal::RegisterFileLevelMetadata(registration_data);
     // Should be here now.
-    result = FindPtrOrNull(type_map_, type);
+    result = FindInTypeMap(type);
   }
 
   if (result == nullptr) {
@@ -396,9 +457,18 @@
     GenericTypeHandler<Message>::GetOwningArena(Message* value) {
   return value->GetOwningArena();
 }
+
+template void InternalMetadata::DoClear<UnknownFieldSet>();
+template void InternalMetadata::DoMergeFrom<UnknownFieldSet>(
+    const UnknownFieldSet& other);
+template void InternalMetadata::DoSwap<UnknownFieldSet>(UnknownFieldSet* other);
+template Arena* InternalMetadata::DeleteOutOfLineHelper<UnknownFieldSet>();
+template UnknownFieldSet*
+InternalMetadata::mutable_unknown_fields_slow<UnknownFieldSet>();
+
 }  // namespace internal
 
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/message.h b/src/google/protobuf/message.h
index 39ec154..f08b346 100644
--- a/src/google/protobuf/message.h
+++ b/src/google/protobuf/message.h
@@ -116,19 +116,24 @@
 #include <type_traits>
 #include <vector>
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/map.h>  // TODO(b/211442718): cleanup
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/port.h"
+#include "absl/base/call_once.h"
+#include "absl/base/casts.h"
+#include "absl/functional/function_ref.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/generated_message_tctable_decl.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/map.h"  // TODO(b/211442718): cleanup
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/port.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -153,10 +158,12 @@
 class MapReflectionTester;
 
 namespace internal {
+struct FuzzPeer;
 struct DescriptorTable;
 class MapFieldBase;
 class SwapFieldHelper;
 class CachedSize;
+struct TailCallTableInfo;
 }  // namespace internal
 class UnknownFieldSet;  // unknown_field_set.h
 namespace io {
@@ -175,7 +182,10 @@
 
 namespace internal {
 class MapFieldPrinterHelper;  // text_format.cc
-}
+void PerformAbslStringify(
+    const Message& message,
+    absl::FunctionRef<void(absl::string_view)> append);  // text_format.cc
+}  // namespace internal
 namespace util {
 class MessageDifferencer;
 }
@@ -203,12 +213,12 @@
 
 namespace internal {
 template <class To>
-inline To* GetPointerAtOffset(Message* message, uint32_t offset) {
+inline To* GetPointerAtOffset(void* message, uint32_t offset) {
   return reinterpret_cast<To*>(reinterpret_cast<char*>(message) + offset);
 }
 
 template <class To>
-const To* GetConstPointerAtOffset(const Message* message, uint32_t offset) {
+const To* GetConstPointerAtOffset(const void* message, uint32_t offset) {
   return reinterpret_cast<const To*>(reinterpret_cast<const char*>(message) +
                                      offset);
 }
@@ -240,6 +250,8 @@
 class PROTOBUF_EXPORT Message : public MessageLite {
  public:
   constexpr Message() {}
+  Message(const Message&) = delete;
+  Message& operator=(const Message&) = delete;
 
   // Basic Operations ------------------------------------------------
 
@@ -298,6 +310,10 @@
   // using reflection (rather than the generated code implementation for
   // ByteSize()). Like ByteSize(), its CPU time is linear in the number of
   // fields defined for the proto.
+  //
+  // Note: The precise value of this method should never be depended on, and can
+  // change substantially due to internal details.  In debug builds, this will
+  // include a random fuzz factor to prevent these dependencies.
   virtual size_t SpaceUsedLong() const;
 
   PROTOBUF_DEPRECATED_MSG("Please use SpaceUsedLong() instead")
@@ -318,6 +334,15 @@
   // Convenience function useful in GDB.  Prints DebugString() to stdout.
   void PrintDebugString() const;
 
+  // Implementation of the `AbslStringify` interface. This adds something
+  // similar to either `ShortDebugString()` or `DebugString()` to the sink.
+  // Do not rely on exact format.
+  template <typename Sink>
+  friend void AbslStringify(Sink& sink, const google::protobuf::Message& message) {
+    internal::PerformAbslStringify(
+        message, [&](absl::string_view content) { sink.Append(content); });
+  }
+
   // Reflection-based methods ----------------------------------------
   // These methods are pure-virtual in MessageLite, but Message provides
   // reflection-based default implementations.
@@ -400,12 +425,14 @@
 
  protected:
   static uint64_t GetInvariantPerBuild(uint64_t salt);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Message);
 };
 
 namespace internal {
+// Creates and returns an allocation for a split message.
+void* CreateSplitMessageGeneric(Arena* arena, const void* default_split,
+                                size_t size, const void* message,
+                                const void* default_message);
+
 // Forward-declare interfaces used to implement RepeatedFieldRef.
 // These are protobuf internals that users shouldn't care about.
 class RepeatedFieldAccessor;
@@ -459,6 +486,10 @@
 // memory leaks.  So, instead we ended up with this flat interface.
 class PROTOBUF_EXPORT Reflection final {
  public:
+  Reflection(const Reflection&) = delete;
+  Reflection& operator=(const Reflection&) = delete;
+  ~Reflection();
+
   // Get the UnknownFieldSet for the message.  This contains fields which
   // were seen when the Message was parsed but were not recognized according
   // to the Message's definition.
@@ -476,6 +507,11 @@
     return internal::ToIntSize(SpaceUsedLong(message));
   }
 
+  // Returns true if the given message is a default message instance.
+  bool IsDefaultInstance(const Message& message) const {
+    return schema_.IsDefaultInstance(message);
+  }
+
   // Check if the given non-repeated field is set.
   bool HasField(const Message& message, const FieldDescriptor* field) const;
 
@@ -773,6 +809,7 @@
                  std::string value) const;
   void AddEnum(Message* message, const FieldDescriptor* field,
                const EnumValueDescriptor* value) const;
+
   // Add an integer value to a repeated enum field rather than
   // EnumValueDescriptor. For proto3 this is just setting the enum field to the
   // value specified, for proto2 it's more complicated. If value is a known enum
@@ -892,8 +929,7 @@
 
   // Try to find an extension of this message type by fully-qualified field
   // name.  Returns nullptr if no extension is known for this name or number.
-  const FieldDescriptor* FindKnownExtensionByName(
-      const std::string& name) const;
+  const FieldDescriptor* FindKnownExtensionByName(absl::string_view name) const;
 
   // Try to find an extension of this message type by field number.
   // Returns nullptr if no extension is known for this name or number.
@@ -955,6 +991,7 @@
   template <typename T>
   RepeatedPtrField<T>* MutableRepeatedPtrFieldInternal(
       Message* message, const FieldDescriptor* field) const;
+
   // Obtain a pointer to a Repeated Field Structure and do some type checking:
   //   on field->cpp_type(),
   //   on field->field_option().ctype() (if ctype >= 0)
@@ -1029,6 +1066,11 @@
   bool IsLazilyVerifiedLazyField(const FieldDescriptor* field) const;
   bool IsEagerlyVerifiedLazyField(const FieldDescriptor* field) const;
 
+  bool IsSplit(const FieldDescriptor* field) const {
+    return schema_.IsSplit(field);
+  }
+
+  friend class FastReflectionBase;
   friend class FastReflectionMessageMutator;
   friend bool internal::IsDescendant(Message& root, const Message& message);
 
@@ -1042,10 +1084,34 @@
   // contain weak fields, then this field equals descriptor_->field_count().
   int last_non_weak_field_index_;
 
+  // The table-driven parser table.
+  // This table is generated on demand for Message types that did not override
+  // _InternalParse. It uses the reflection information to do so.
+  mutable absl::once_flag tcparse_table_once_;
+  using TcParseTableBase = internal::TcParseTableBase;
+  mutable const TcParseTableBase* tcparse_table_ = nullptr;
+
+  const TcParseTableBase* GetTcParseTable() const {
+    absl::call_once(tcparse_table_once_,
+                    [&] { tcparse_table_ = CreateTcParseTable(); });
+    return tcparse_table_;
+  }
+
+  const TcParseTableBase* CreateTcParseTable() const;
+  const TcParseTableBase* CreateTcParseTableForMessageSet() const;
+  void PopulateTcParseFastEntries(
+      const internal::TailCallTableInfo& table_info,
+      TcParseTableBase::FastFieldEntry* fast_entries) const;
+  void PopulateTcParseEntries(internal::TailCallTableInfo& table_info,
+                              TcParseTableBase::FieldEntry* entries) const;
+  void PopulateTcParseFieldAux(const internal::TailCallTableInfo& table_info,
+                               TcParseTableBase::FieldAux* field_aux) const;
+
   template <typename T, typename Enable>
   friend class RepeatedFieldRef;
   template <typename T, typename Enable>
   friend class MutableRepeatedFieldRef;
+  friend class Message;
   friend class ::PROTOBUF_NAMESPACE_ID::MessageLayoutInspector;
   friend class ::PROTOBUF_NAMESPACE_ID::AssignDescriptorsHelper;
   friend class DynamicMessageFactory;
@@ -1060,6 +1126,7 @@
   friend class internal::WireFormat;
   friend class internal::ReflectionOps;
   friend class internal::SwapFieldHelper;
+  friend struct internal::FuzzPeer;
   // Needed for implementing text format for map.
   friend class internal::MapFieldPrinterHelper;
 
@@ -1174,6 +1241,14 @@
   inline void SwapInlinedStringDonated(Message* lhs, Message* rhs,
                                        const FieldDescriptor* field) const;
 
+  // Returns the `_split_` pointer. Requires: IsSplit() == true.
+  inline const void* GetSplitField(const Message* message) const;
+  // Returns the address of the `_split_` pointer. Requires: IsSplit() == true.
+  inline void** MutableSplitField(Message* message) const;
+
+  // Allocate the split instance if needed.
+  void PrepareSplitMessageForWrite(Message* message) 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(
@@ -1197,6 +1272,8 @@
   void SwapOneofField(Message* lhs, Message* rhs,
                       const OneofDescriptor* oneof_descriptor) const;
 
+  void InternalSwap(Message* lhs, Message* rhs) const;
+
   inline bool HasOneofField(const Message& message,
                             const FieldDescriptor* field) const;
   inline void SetOneofCase(Message* message,
@@ -1260,14 +1337,17 @@
                                              const Reflection* reflection,
                                              const char* ptr,
                                              internal::ParseContext* ctx);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reflection);
 };
 
 // Abstract interface for a factory for message objects.
+//
+// The thread safety for this class is implementation dependent, see comments
+// around GetPrototype for details
 class PROTOBUF_EXPORT MessageFactory {
  public:
   inline MessageFactory() {}
+  MessageFactory(const MessageFactory&) = delete;
+  MessageFactory& operator=(const MessageFactory&) = delete;
   virtual ~MessageFactory();
 
   // Given a Descriptor, gets or constructs the default (prototype) Message
@@ -1323,9 +1403,6 @@
   static void InternalRegisterGeneratedMessage(const Descriptor* descriptor,
                                                const Message* prototype);
 
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageFactory);
 };
 
 #define DECLARE_GET_REPEATED_FIELD(TYPE)                           \
@@ -1372,7 +1449,7 @@
 #else
   bool ok = from != nullptr &&
             T::default_instance().GetReflection() == from->GetReflection();
-  return ok ? down_cast<const T*>(from) : nullptr;
+  return ok ? internal::DownCast<const T*>(from) : nullptr;
 #endif
 }
 
@@ -1481,17 +1558,32 @@
           static_cast<uint32_t>(field->number()));
 }
 
+const void* Reflection::GetSplitField(const Message* message) const {
+  GOOGLE_DCHECK(schema_.IsSplit());
+  return *internal::GetConstPointerAtOffset<void*>(message,
+                                                   schema_.SplitOffset());
+}
+
+void** Reflection::MutableSplitField(Message* message) const {
+  GOOGLE_DCHECK(schema_.IsSplit());
+  return internal::GetPointerAtOffset<void*>(message, schema_.SplitOffset());
+}
+
 template <typename Type>
 const Type& Reflection::GetRaw(const Message& message,
                                const FieldDescriptor* field) const {
   GOOGLE_DCHECK(!schema_.InRealOneof(field) || HasOneofField(message, field))
       << "Field = " << field->full_name();
+  if (schema_.IsSplit(field)) {
+    return *internal::GetConstPointerAtOffset<Type>(
+        GetSplitField(&message), schema_.GetFieldOffset(field));
+  }
   return internal::GetConstRefAtOffset<Type>(message,
                                              schema_.GetFieldOffset(field));
 }
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_MESSAGE_H__
diff --git a/src/google/protobuf/message_lite.cc b/src/google/protobuf/message_lite.cc
index da66c19..161758d 100644
--- a/src/google/protobuf/message_lite.cc
+++ b/src/google/protobuf/message_lite.cc
@@ -33,39 +33,48 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/message_lite.h"
 
 #include <climits>
 #include <cstdint>
 #include <string>
+#include <utility>
 
-#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/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/arena.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/stubs/mutex.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "absl/base/dynamic_annotations.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/synchronization/mutex.h"
+#include "google/protobuf/generated_message_util.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/parse_context.h"
+#include "google/protobuf/repeated_field.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 
+MessageLite::~MessageLite(){
+// Defined out of line to save code space
+}
+
 std::string MessageLite::InitializationErrorString() const {
   return "(cannot determine missing fields for lite message)";
 }
 
 std::string MessageLite::DebugString() const {
   std::uintptr_t address = reinterpret_cast<std::uintptr_t>(this);
-  return StrCat("MessageLite at 0x", strings::Hex(address));
+  return absl::StrCat("MessageLite at 0x", absl::Hex(address));
 }
 
 namespace {
@@ -112,8 +121,8 @@
   return result;
 }
 
-inline StringPiece as_string_view(const void* data, int size) {
-  return StringPiece(static_cast<const char*>(data), size);
+inline absl::string_view as_string_view(const void* data, int size) {
+  return absl::string_view(static_cast<const char*>(data), size);
 }
 
 // Returns true of all required fields are present / have values.
@@ -136,7 +145,7 @@
 namespace internal {
 
 template <bool aliasing>
-bool MergeFromImpl(StringPiece input, MessageLite* msg,
+bool MergeFromImpl(absl::string_view input, MessageLite* msg,
                    MessageLite::ParseFlags parse_flags) {
   const char* ptr;
   internal::ParseContext ctx(io::CodedInputStream::GetDefaultRecursionLimit(),
@@ -178,9 +187,9 @@
   return false;
 }
 
-template bool MergeFromImpl<false>(StringPiece input, MessageLite* msg,
+template bool MergeFromImpl<false>(absl::string_view input, MessageLite* msg,
                                    MessageLite::ParseFlags parse_flags);
-template bool MergeFromImpl<true>(StringPiece input, MessageLite* msg,
+template bool MergeFromImpl<true>(absl::string_view input, MessageLite* msg,
                                   MessageLite::ParseFlags parse_flags);
 template bool MergeFromImpl<false>(io::ZeroCopyInputStream* input,
                                    MessageLite* msg,
@@ -305,11 +314,11 @@
   return ParseFrom<kParsePartial>(internal::BoundedZCIS{input, size});
 }
 
-bool MessageLite::ParseFromString(ConstStringParam data) {
+bool MessageLite::ParseFromString(absl::string_view data) {
   return ParseFrom<kParse>(data);
 }
 
-bool MessageLite::ParsePartialFromString(ConstStringParam data) {
+bool MessageLite::ParsePartialFromString(absl::string_view data) {
   return ParseFrom<kParsePartial>(data);
 }
 
@@ -321,7 +330,7 @@
   return ParseFrom<kParsePartial>(as_string_view(data, size));
 }
 
-bool MessageLite::MergeFromString(ConstStringParam data) {
+bool MessageLite::MergeFromString(absl::string_view data) {
   return ParseFrom<kMerge>(data);
 }
 
@@ -451,7 +460,8 @@
     return false;
   }
 
-  STLStringResizeUninitializedAmortized(output, old_size + byte_size);
+  absl::strings_internal::STLStringResizeUninitializedAmortized(
+      output, old_size + byte_size);
   uint8_t* start =
       reinterpret_cast<uint8_t*>(io::mutable_string_data(output) + old_size);
   SerializeToArrayImpl(*this, start, byte_size);
@@ -566,7 +576,7 @@
   }
 
   std::vector<std::pair<void (*)(const void*), const void*>> functions;
-  Mutex mutex;
+  absl::Mutex mutex;
 };
 
 static void RunZeroArgFunc(const void* arg) {
@@ -580,7 +590,7 @@
 
 void OnShutdownRun(void (*f)(const void*), const void* arg) {
   auto shutdown_data = ShutdownData::get();
-  MutexLock lock(&shutdown_data->mutex);
+  absl::MutexLock lock(&shutdown_data->mutex);
   shutdown_data->functions.push_back(std::make_pair(f, arg));
 }
 
@@ -599,4 +609,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/message_lite.h b/src/google/protobuf/message_lite.h
index 950ae1a..38e903e 100644
--- a/src/google/protobuf/message_lite.h
+++ b/src/google/protobuf/message_lite.h
@@ -43,19 +43,20 @@
 #include <climits>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/explicitly_constructed.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/stubs/hash.h>  // TODO(b/211442718): cleanup
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/port.h"
+#include "absl/base/call_once.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/explicitly_constructed.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/port.h"
+
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 #ifdef SWIG
@@ -168,7 +169,9 @@
 class PROTOBUF_EXPORT MessageLite {
  public:
   constexpr MessageLite() {}
-  virtual ~MessageLite() = default;
+  MessageLite(const MessageLite&) = delete;
+  MessageLite& operator=(const MessageLite&) = delete;
+  virtual ~MessageLite();
 
   // Basic Operations ------------------------------------------------
 
@@ -277,11 +280,11 @@
   // 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().
-  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(ConstStringParam data);
+  PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromString(absl::string_view data);
   // Like ParseFromString(), but accepts messages that are missing
   // required fields.
   PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParsePartialFromString(
-      ConstStringParam data);
+      absl::string_view data);
   // Parse a protocol buffer contained in an array of bytes.
   PROTOBUF_ATTRIBUTE_REINITIALIZES bool ParseFromArray(const void* data,
                                                        int size);
@@ -312,7 +315,7 @@
   bool MergePartialFromCodedStream(io::CodedInputStream* input);
 
   // Merge a protocol buffer contained in a string.
-  bool MergeFromString(ConstStringParam data);
+  bool MergeFromString(absl::string_view data);
 
 
   // Serialization ---------------------------------------------------
@@ -492,19 +495,17 @@
   void LogInitializationErrorMessage() const;
 
   bool MergeFromImpl(io::CodedInputStream* input, ParseFlags parse_flags);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageLite);
 };
 
 namespace internal {
 
 template <bool alias>
-bool MergeFromImpl(StringPiece input, MessageLite* msg,
+bool MergeFromImpl(absl::string_view input, MessageLite* msg,
                    MessageLite::ParseFlags parse_flags);
-extern template bool MergeFromImpl<false>(StringPiece input,
+extern template bool MergeFromImpl<false>(absl::string_view input,
                                           MessageLite* msg,
                                           MessageLite::ParseFlags parse_flags);
-extern template bool MergeFromImpl<true>(StringPiece input,
+extern template bool MergeFromImpl<true>(absl::string_view input,
                                          MessageLite* msg,
                                          MessageLite::ParseFlags parse_flags);
 
@@ -586,6 +587,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_MESSAGE_LITE_H__
diff --git a/src/google/protobuf/message_unittest.cc b/src/google/protobuf/message_unittest.cc
index f71f60c..dbf84b6 100644
--- a/src/google/protobuf/message_unittest.cc
+++ b/src/google/protobuf/message_unittest.cc
@@ -32,7 +32,7 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/unittest.pb.h>
+#include "google/protobuf/unittest.pb.h"
 
 #define MESSAGE_TEST_NAME MessageTest
 #define MESSAGE_FACTORY_TEST_NAME MessageFactoryTest
@@ -42,7 +42,7 @@
 
 // Must include after the above macros.
 // clang-format off
-#include <google/protobuf/test_util.inc>
-#include <google/protobuf/message_unittest.inc>
-#include <google/protobuf/arena.h>
+#include "google/protobuf/test_util.inc"
+#include "google/protobuf/message_unittest.inc"
+#include "google/protobuf/arena.h"
 // clang-format on
diff --git a/src/google/protobuf/message_unittest.inc b/src/google/protobuf/message_unittest.inc
index fa2bbbf..af53144 100644
--- a/src/google/protobuf/message_unittest.inc
+++ b/src/google/protobuf/message_unittest.inc
@@ -40,31 +40,34 @@
 #include <sys/types.h>
 
 #include <cmath>
+#include <functional>
 #include <limits>
+#include <vector>
 
-#include <google/protobuf/message.h>
+#include "google/protobuf/message.h"
+#include "absl/strings/cord.h"
 #ifndef _MSC_VER
 #include <unistd.h>
 #endif
 #include <fstream>
 #include <sstream>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.pb.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.pb.h"
 #include <gmock/gmock.h>
-#include <google/protobuf/testing/googletest.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/arena.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/generated_message_reflection.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/test_util2.h>
+#include "google/protobuf/stubs/logging.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/test_util2.h"
 
 
 namespace google {
@@ -124,7 +127,7 @@
 
 TEST(MESSAGE_TEST_NAME, ParseFromFileDescriptor) {
   std::string filename =
-      TestUtil::GetTestDataPath("net/proto2/internal/testdata/golden_message");
+      TestUtil::GetTestDataPath("third_party/protobuf/testdata/golden_message");
   int file = open(filename.c_str(), O_RDONLY | O_BINARY);
   ASSERT_GE(file, 0);
 
@@ -137,7 +140,7 @@
 
 TEST(MESSAGE_TEST_NAME, ParsePackedFromFileDescriptor) {
   std::string filename = TestUtil::GetTestDataPath(
-      "net/proto2/internal/testdata/golden_packed_fields_message");
+      "third_party/protobuf/testdata/golden_packed_fields_message");
   int file = open(filename.c_str(), O_RDONLY | O_BINARY);
   ASSERT_GE(file, 0);
 
@@ -255,7 +258,7 @@
   }
 
   EXPECT_THAT(errors,
-              testing::ElementsAre(strings::Substitute(
+              testing::ElementsAre(absl::Substitute(
                   "Can't parse message of type \"$0.TestChildExtension\" "
                   "because it is missing required fields: "
                   "optional_extension.($0.TestRequired.single).a, "
@@ -285,6 +288,32 @@
   EXPECT_TRUE(TestUtil::EqualsToSerialized(q, p.SerializePartialAsString()));
 }
 
+TEST(MESSAGE_TEST_NAME, UninitializedAndTooDeep) {
+  UNITTEST::TestRequiredForeign original;
+  original.mutable_optional_message()->set_a(1);
+  original.mutable_optional_lazy_message()
+      ->mutable_child()
+      ->mutable_payload()
+      ->set_optional_int64(0);
+
+  std::string data;
+  ASSERT_TRUE(original.SerializePartialToString(&data));
+
+  UNITTEST::TestRequiredForeign pass;
+  ASSERT_TRUE(pass.ParsePartialFromString(data));
+  ASSERT_FALSE(pass.IsInitialized());
+
+  io::ArrayInputStream array_stream(data.data(), data.size());
+  io::CodedInputStream input_stream(&array_stream);
+  input_stream.SetRecursionLimit(2);
+
+  UNITTEST::TestRequiredForeign fail;
+  EXPECT_FALSE(fail.ParsePartialFromCodedStream(&input_stream));
+
+  UNITTEST::TestRequiredForeign fail_uninitialized;
+  EXPECT_FALSE(fail_uninitialized.ParseFromString(data));
+}
+
 TEST(MESSAGE_TEST_NAME, ExplicitLazyExceedRecursionLimit) {
   UNITTEST::NestedTestAllTypes original, parsed;
   // Build proto with recursion depth of 3.
@@ -422,6 +451,25 @@
   EXPECT_FALSE(p.ParseFromString(serialized));
 }
 
+TEST(MESSAGE_TEST_NAME, ParseFailsIfGroupFieldMalformed) {
+  UNITTEST::TestMutualRecursionA original, parsed;
+  original.mutable_bb()
+      ->mutable_a()
+      ->mutable_subgroup()
+      ->mutable_sub_message()
+      ->mutable_b()
+      ->set_optional_int32(-1);
+
+  std::string data;
+  ASSERT_TRUE(original.SerializeToString(&data));
+  // Should parse correctly.
+  ASSERT_TRUE(parsed.ParseFromString(data));
+  // Overwriting the last byte of varint (-1) to 0xFF results in malformed wire.
+  data[data.size() - 2] = 0xFF;
+
+  EXPECT_FALSE(parsed.ParseFromString(data));
+}
+
 TEST(MESSAGE_TEST_NAME, UninitializedAndMalformed) {
   UNITTEST::TestRequiredForeign o, p1, p2;
   o.mutable_optional_message()->set_a(-1);
@@ -1127,5 +1175,348 @@
             std::signbit(out_message.optional_double()));
 }
 
+// Adds `non_canonical_bytes` bytes to the varint representation at the tail of
+// the buffer.
+// `buf` points to the start of the buffer, `p` points to one-past-the-end.
+// Returns the new one-past-the-end pointer.
+uint8_t* AddNonCanonicalBytes(const uint8_t* buf, uint8_t* p,
+                              int non_canonical_bytes) {
+  // varint can have a max of 10 bytes.
+  while (non_canonical_bytes-- > 0 && p - buf < 10) {
+    // Add a dummy byte at the end.
+    p[-1] |= 0x80;
+    p[0] = 0;
+    ++p;
+  }
+  return p;
+}
+
+std::string EncodeEnumValue(int number, int value, int non_canonical_bytes,
+                            bool use_packed) {
+  uint8_t buf[100];
+  uint8_t* p = buf;
+
+  if (use_packed) {
+    p = internal::WireFormatLite::WriteEnumNoTagToArray(value, p);
+    p = AddNonCanonicalBytes(buf, p, non_canonical_bytes);
+
+    std::string payload(buf, p);
+    p = buf;
+    p = internal::WireFormatLite::WriteStringToArray(number, payload, p);
+    return std::string(buf, p);
+
+  } else {
+    p = internal::WireFormatLite::WriteEnumToArray(number, value, p);
+    p = AddNonCanonicalBytes(buf, p, non_canonical_bytes);
+    return std::string(buf, p);
+  }
+}
+
+std::string EncodeOverlongEnum(int number, bool use_packed) {
+  uint8_t buf[100];
+  uint8_t* p = buf;
+
+  std::string overlong(16, static_cast<char>(0x80));
+  if (use_packed) {
+    p = internal::WireFormatLite::WriteStringToArray(number, overlong, p);
+    return std::string(buf, p);
+  } else {
+    p = internal::WireFormatLite::WriteTagToArray(
+        number, internal::WireFormatLite::WIRETYPE_VARINT, p);
+    p = std::copy(overlong.begin(), overlong.end(), p);
+    return std::string(buf, p);
+  }
+}
+
+std::string EncodeOtherField() {
+  UNITTEST::EnumParseTester obj;
+  obj.set_other_field(1);
+  return obj.SerializeAsString();
+}
+
+TEST(MESSAGE_TEST_NAME, TestEnumParsers) {
+  UNITTEST::EnumParseTester obj;
+
+  const auto other_field = EncodeOtherField();
+
+  // Encode a boolean field for many different cases and verify that it can be
+  // parsed as expected.
+  // There are:
+  //  - optional/repeated/packed fields
+  //  - field tags that encode in 1/2/3 bytes
+  //  - canonical and non-canonical encodings of the varint
+  //  - last vs not last field
+  //  - label combinations to trigger different parsers: sequential, small
+  //  sequential, non-validated.
+
+  constexpr int kInvalidValue = 0x900913;
+  auto* ref = obj.GetReflection();
+  auto* descriptor = obj.descriptor();
+  for (bool use_packed : {false, true}) {
+    SCOPED_TRACE(use_packed);
+    for (bool use_tail_field : {false, true}) {
+      SCOPED_TRACE(use_tail_field);
+      for (int non_canonical_bytes = 0; non_canonical_bytes < 5;
+           ++non_canonical_bytes) {
+        SCOPED_TRACE(non_canonical_bytes);
+        for (int i = 0; i < descriptor->field_count(); ++i) {
+          const auto* field = descriptor->field(i);
+          if (field->name() == "other_field") continue;
+          if (!field->is_repeated() && use_packed) continue;
+          SCOPED_TRACE(field->full_name());
+          const auto* enum_desc = field->enum_type();
+          for (int e = 0; e < enum_desc->value_count(); ++e) {
+            const auto* value_desc = enum_desc->value(e);
+            if (value_desc->number() < 0 && non_canonical_bytes > 0) {
+              // Negative numbers only have a canonical representation.
+              continue;
+            }
+            SCOPED_TRACE(value_desc->number());
+            GOOGLE_CHECK_NE(value_desc->number(), kInvalidValue)
+                << "Invalid value is a real label.";
+            auto encoded =
+                EncodeEnumValue(field->number(), value_desc->number(),
+                                non_canonical_bytes, use_packed);
+            if (use_tail_field) {
+              // Make sure that fields after this one can be parsed too. ie test
+              // that the "next" jump is correct too.
+              encoded += other_field;
+            }
+
+            EXPECT_TRUE(obj.ParseFromString(encoded));
+            if (field->is_repeated()) {
+              ASSERT_EQ(ref->FieldSize(obj, field), 1);
+              EXPECT_EQ(ref->GetRepeatedEnumValue(obj, field, 0),
+                        value_desc->number());
+            } else {
+              EXPECT_TRUE(ref->HasField(obj, field));
+              EXPECT_EQ(ref->GetEnumValue(obj, field), value_desc->number());
+            }
+            auto& unknown = ref->GetUnknownFields(obj);
+            ASSERT_EQ(unknown.field_count(), 0);
+          }
+
+          {
+            SCOPED_TRACE("Invalid value");
+            // Try an invalid value, which should go to the unknown fields.
+            EXPECT_TRUE(obj.ParseFromString(
+                EncodeEnumValue(field->number(), kInvalidValue,
+                                non_canonical_bytes, use_packed)));
+            if (field->is_repeated()) {
+              ASSERT_EQ(ref->FieldSize(obj, field), 0);
+            } else {
+              EXPECT_FALSE(ref->HasField(obj, field));
+              EXPECT_EQ(ref->GetEnumValue(obj, field),
+                        enum_desc->value(0)->number());
+            }
+            auto& unknown = ref->GetUnknownFields(obj);
+            ASSERT_EQ(unknown.field_count(), 1);
+            EXPECT_EQ(unknown.field(0).number(), field->number());
+            EXPECT_EQ(unknown.field(0).type(), unknown.field(0).TYPE_VARINT);
+            EXPECT_EQ(unknown.field(0).varint(), kInvalidValue);
+          }
+          {
+            SCOPED_TRACE("Overlong varint");
+            // Try an overlong varint. It should fail parsing, but not trigger
+            // any sanitizer warning.
+            EXPECT_FALSE(obj.ParseFromString(
+                EncodeOverlongEnum(field->number(), use_packed)));
+          }
+        }
+      }
+    }
+  }
+}
+
+std::string EncodeBoolValue(int number, bool value, int non_canonical_bytes) {
+  uint8_t buf[100];
+  uint8_t* p = buf;
+
+  p = internal::WireFormatLite::WriteBoolToArray(number, value, p);
+  p = AddNonCanonicalBytes(buf, p, non_canonical_bytes);
+  return std::string(buf, p);
+}
+
+TEST(MESSAGE_TEST_NAME, TestBoolParsers) {
+  UNITTEST::BoolParseTester obj;
+
+  const auto other_field = EncodeOtherField();
+
+  // Encode a boolean field for many different cases and verify that it can be
+  // parsed as expected.
+  // There are:
+  //  - optional/repeated/packed fields
+  //  - field tags that encode in 1/2/3 bytes
+  //  - canonical and non-canonical encodings of the varint
+  //  - last vs not last field
+
+  auto* ref = obj.GetReflection();
+  auto* descriptor = obj.descriptor();
+  for (bool use_tail_field : {false, true}) {
+    SCOPED_TRACE(use_tail_field);
+    for (int non_canonical_bytes = 0; non_canonical_bytes < 10;
+         ++non_canonical_bytes) {
+      SCOPED_TRACE(non_canonical_bytes);
+      for (int i = 0; i < descriptor->field_count(); ++i) {
+        const auto* field = descriptor->field(i);
+        if (field->name() == "other_field") continue;
+        SCOPED_TRACE(field->full_name());
+        for (bool value : {false, true}) {
+          SCOPED_TRACE(value);
+          auto encoded =
+              EncodeBoolValue(field->number(), value, non_canonical_bytes);
+          if (use_tail_field) {
+            // Make sure that fields after this one can be parsed too. ie test
+            // that the "next" jump is correct too.
+            encoded += other_field;
+          }
+
+          EXPECT_TRUE(obj.ParseFromString(encoded));
+          if (field->is_repeated()) {
+            ASSERT_EQ(ref->FieldSize(obj, field), 1);
+            EXPECT_EQ(ref->GetRepeatedBool(obj, field, 0), value);
+          } else {
+            EXPECT_TRUE(ref->HasField(obj, field));
+            EXPECT_EQ(ref->GetBool(obj, field), value);
+          }
+          auto& unknown = ref->GetUnknownFields(obj);
+          ASSERT_EQ(unknown.field_count(), 0);
+        }
+      }
+    }
+  }
+}
+
+TEST(MESSAGE_TEST_NAME, IsDefaultInstance) {
+  UNITTEST::TestAllTypes msg;
+  const auto& default_msg = UNITTEST::TestAllTypes::default_instance();
+  const auto* r = msg.GetReflection();
+  EXPECT_TRUE(r->IsDefaultInstance(default_msg));
+  EXPECT_FALSE(r->IsDefaultInstance(msg));
+}
+
+std::string EncodeStringValue(int number, const std::string& value) {
+  uint8_t buf[100];
+  return std::string(
+      buf, internal::WireFormatLite::WriteStringToArray(number, value, buf));
+}
+
+class TestInputStream final : public io::ZeroCopyInputStream {
+ public:
+  explicit TestInputStream(absl::string_view payload, size_t break_pos)
+      : payload_(payload), break_pos_(break_pos) {}
+
+  bool Next(const void** data, int* size) override {
+    if (payload_.empty()) return false;
+    const auto to_consume = payload_.substr(0, break_pos_);
+    *data = to_consume.data();
+    *size = to_consume.size();
+    payload_.remove_prefix(to_consume.size());
+    // The next time will consume the rest.
+    break_pos_ = payload_.npos;
+
+    return true;
+  }
+
+  void BackUp(int) override { GOOGLE_CHECK(false); }
+  bool Skip(int) override {
+    GOOGLE_CHECK(false);
+    return false;
+  }
+  int64_t ByteCount() const override {
+    GOOGLE_CHECK(false);
+    return 0;
+  }
+
+ private:
+  absl::string_view payload_;
+  size_t break_pos_;
+};
+
+TEST(MESSAGE_TEST_NAME, TestRepeatedStringParsers) {
+  google::protobuf::Arena arena;
+
+  const std::string sample =
+      "abcdefghijklmnopqrstuvwxyz"
+      "ABCDEFGHIJKLMNOPQRSTUVWXYZ";
+
+  const auto* const descriptor = UNITTEST::StringParseTester::descriptor();
+
+  static const size_t sso_capacity = std::string().capacity();
+  if (sso_capacity == 0) GTEST_SKIP();
+  // SSO, !SSO, and off-by-one just in case
+  for (size_t size :
+       {sso_capacity - 1, sso_capacity, sso_capacity + 1, sso_capacity + 2}) {
+    SCOPED_TRACE(size);
+    const std::string value = sample.substr(0, size);
+    for (int i = 0; i < descriptor->field_count(); ++i) {
+        const auto* field = descriptor->field(i);
+        SCOPED_TRACE(field->full_name());
+        const auto encoded = EncodeStringValue(field->number(), sample) +
+                             EncodeStringValue(field->number(), value);
+        // Check for different breaks in the input stream to test cases where
+        // the payload can be read and can't be read in one go.
+        for (size_t i = 1; i <= encoded.size(); ++i) {
+          TestInputStream input_stream(encoded, i);
+
+          auto& obj = *arena.CreateMessage<UNITTEST::StringParseTester>(&arena);
+          auto* ref = obj.GetReflection();
+          EXPECT_TRUE(obj.ParseFromZeroCopyStream(&input_stream));
+          if (field->is_repeated()) {
+            ASSERT_EQ(ref->FieldSize(obj, field), 2);
+            EXPECT_EQ(ref->GetRepeatedString(obj, field, 0), sample);
+            EXPECT_EQ(ref->GetRepeatedString(obj, field, 1), value);
+          } else {
+            EXPECT_EQ(ref->GetString(obj, field), value);
+          }
+        }
+    }
+  }
+}
+
+TEST(MESSAGE_TEST_NAME, TestRegressionOnParseFailureNotSettingHasBits) {
+  std::string single_field;
+  // We use blocks because we want fully new instances of the proto. We are
+  // testing .Clear(), so we can't use it to set up the test.
+  {
+    UNITTEST::TestAllTypes message;
+    message.set_optional_int32(17);
+    single_field = message.SerializeAsString();
+  }
+  const auto validate_message = [] (auto& message) {
+    if (!message.has_optional_int32()) {
+      EXPECT_EQ(message.optional_int32(), 0);
+    }
+    message.Clear();
+    EXPECT_FALSE(message.has_optional_int32());
+    EXPECT_EQ(message.optional_int32(), 0);
+  };
+  {
+    // Verify the setup is correct.
+    UNITTEST::TestAllTypes message;
+    EXPECT_FALSE(message.has_optional_int32());
+    EXPECT_EQ(message.optional_int32(), 0);
+    EXPECT_TRUE(message.ParseFromString(single_field));
+    validate_message(message);
+  }
+  {
+    // Run the regression.
+    // These are the steps:
+    // - The stream contains a fast field, and then a failure in MiniParse
+    // - The parsing fails.
+    // - We call clear.
+    // - The fast field should be reset.
+    UNITTEST::TestAllTypes message;
+    EXPECT_FALSE(message.has_optional_int32());
+    EXPECT_EQ(message.optional_int32(), 0);
+    // The second tag will fail to parse because it has too many continuation
+    // bits.
+    auto with_error =
+        absl::StrCat(single_field, std::string(100, static_cast<char>(0x80)));
+    EXPECT_FALSE(message.ParseFromString(with_error));
+    validate_message(message);
+  }
+}
+
 }  // namespace protobuf
 }  // namespace google
diff --git a/src/google/protobuf/metadata_lite.h b/src/google/protobuf/metadata_lite.h
index 0c31517..0700327 100644
--- a/src/google/protobuf/metadata_lite.h
+++ b/src/google/protobuf/metadata_lite.h
@@ -32,12 +32,13 @@
 #define GOOGLE_PROTOBUF_METADATA_LITE_H__
 
 #include <string>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/port.h>
+
+#include "google/protobuf/arena.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -45,6 +46,9 @@
 
 namespace google {
 namespace protobuf {
+
+class UnknownFieldSet;
+
 namespace internal {
 
 // This is the representation for messages that support arena allocation. It
@@ -280,6 +284,19 @@
 template <>
 PROTOBUF_EXPORT void InternalMetadata::DoSwap<std::string>(std::string* other);
 
+// Instantiated once in message.cc (where the definition of UnknownFieldSet is
+// known) to prevent much duplication across translation units of a large build.
+extern template PROTOBUF_EXPORT void
+InternalMetadata::DoClear<UnknownFieldSet>();
+extern template PROTOBUF_EXPORT void
+InternalMetadata::DoMergeFrom<UnknownFieldSet>(const UnknownFieldSet& other);
+extern template PROTOBUF_EXPORT void
+InternalMetadata::DoSwap<UnknownFieldSet>(UnknownFieldSet* other);
+extern template PROTOBUF_EXPORT Arena*
+InternalMetadata::DeleteOutOfLineHelper<UnknownFieldSet>();
+extern template PROTOBUF_EXPORT UnknownFieldSet*
+InternalMetadata::mutable_unknown_fields_slow<UnknownFieldSet>();
+
 // This helper RAII class is needed to efficiently parse unknown fields. We
 // should only call mutable_unknown_fields if there are actual unknown fields.
 // The obvious thing to just use a stack string and swap it at the end of
@@ -311,6 +328,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_METADATA_LITE_H__
diff --git a/src/google/protobuf/no_field_presence_test.cc b/src/google/protobuf/no_field_presence_test.cc
index 2582cfe..a02cd92 100644
--- a/src/google/protobuf/no_field_presence_test.cc
+++ b/src/google/protobuf/no_field_presence_test.cc
@@ -30,11 +30,11 @@
 
 #include <string>
 
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_no_field_presence.pb.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/descriptor.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_no_field_presence.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/parse_context.cc b/src/google/protobuf/parse_context.cc
index 59852fd..9e591ad 100644
--- a/src/google/protobuf/parse_context.cc
+++ b/src/google/protobuf/parse_context.cc
@@ -28,19 +28,17 @@
 // (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/parse_context.h>
+#include "google/protobuf/parse_context.h"
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/endian.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "utf8_validity.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -267,19 +265,22 @@
 const char* ParseContext::ReadSizeAndPushLimitAndDepth(const char* ptr,
                                                        int* old_limit) {
   int size = ReadSize(&ptr);
-  if (PROTOBUF_PREDICT_FALSE(!ptr)) {
+  if (PROTOBUF_PREDICT_FALSE(!ptr) || depth_ <= 0) {
     *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;
+  --depth_;
   return ptr;
 }
 
 const char* ParseContext::ParseMessage(MessageLite* msg, const char* ptr) {
   int old;
   ptr = ReadSizeAndPushLimitAndDepth(ptr, &old);
-  ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr;
+  if (ptr == nullptr) return ptr;
+  auto old_depth = depth_;
+  ptr = msg->_InternalParse(ptr, this);
+  if (ptr != nullptr) GOOGLE_DCHECK_EQ(old_depth, depth_);
   depth_++;
   if (!PopLimit(old)) return nullptr;
   return ptr;
@@ -299,7 +300,7 @@
   WriteVarint(val, s);
 }
 
-void WriteLengthDelimited(uint32_t num, StringPiece val, std::string* s) {
+void WriteLengthDelimited(uint32_t num, absl::string_view val, std::string* s) {
   WriteVarint((num << 3) + 2, s);
   WriteVarint(val.size(), s);
   s->append(val.data(), val.size());
@@ -307,7 +308,7 @@
 
 std::pair<const char*, uint32_t> VarintParseSlow32(const char* p,
                                                    uint32_t res) {
-  for (std::uint32_t i = 2; i < 5; i++) {
+  for (std::uint32_t i = 1; i < 5; i++) {
     uint32_t byte = static_cast<uint8_t>(p[i]);
     res += (byte - 1) << (7 * i);
     if (PROTOBUF_PREDICT_TRUE(byte < 128)) {
@@ -327,7 +328,7 @@
 std::pair<const char*, uint64_t> VarintParseSlow64(const char* p,
                                                    uint32_t res32) {
   uint64_t res = res32;
-  for (std::uint32_t i = 2; i < 10; i++) {
+  for (std::uint32_t i = 1; i < 10; i++) {
     uint64_t byte = static_cast<uint8_t>(p[i]);
     res += (byte - 1) << (7 * i);
     if (PROTOBUF_PREDICT_TRUE(byte < 128)) {
@@ -376,12 +377,12 @@
 }
 
 // Defined in wire_format_lite.cc
-void PrintUTF8ErrorLog(StringPiece message_name,
-                       StringPiece field_name, const char* operation_str,
+void PrintUTF8ErrorLog(absl::string_view message_name,
+                       absl::string_view field_name, const char* operation_str,
                        bool emit_stacktrace);
 
-bool VerifyUTF8(StringPiece str, const char* field_name) {
-  if (!IsStructurallyValidUTF8(str)) {
+bool VerifyUTF8(absl::string_view str, const char* field_name) {
+  if (!utf8_range::IsStructurallyValid(str)) {
     PrintUTF8ErrorLog("", field_name, "parsing", false);
     return false;
   }
@@ -541,8 +542,226 @@
   return FieldParser(tag, field_parser, ptr, ctx);
 }
 
+#ifdef __aarch64__
+// Generally, speaking, the ARM-optimized Varint decode algorithm is to extract
+// and concatenate all potentially valid data bits, compute the actual length
+// of the Varint, and mask off the data bits which are not actually part of the
+// result.  More detail on the two main parts is shown below.
+//
+// 1) Extract and concatenate all potentially valid data bits.
+//    Two ARM-specific features help significantly:
+//    a) Efficient and non-destructive bit extraction (UBFX)
+//    b) A single instruction can perform both an OR with a shifted
+//       second operand in one cycle.  E.g., the following two lines do the same
+//       thing
+//       ```result = operand_1 | (operand2 << 7);```
+//       ```ORR %[result], %[operand_1], %[operand_2], LSL #7```
+//    The figure below shows the implementation for handling four chunks.
+//
+// Bits   32    31-24    23   22-16    15    14-8      7     6-0
+//      +----+---------+----+---------+----+---------+----+---------+
+//      |CB 3| Chunk 3 |CB 2| Chunk 2 |CB 1| Chunk 1 |CB 0| Chunk 0 |
+//      +----+---------+----+---------+----+---------+----+---------+
+//                |              |              |              |
+//               UBFX           UBFX           UBFX           UBFX    -- cycle 1
+//                |              |              |              |
+//                V              V              V              V
+//               Combined LSL #7 and ORR     Combined LSL #7 and ORR  -- cycle 2
+//                                 |             |
+//                                 V             V
+//                            Combined LSL #14 and ORR                -- cycle 3
+//                                       |
+//                                       V
+//                                Parsed bits 0-27
+//
+//
+// 2) Calculate the index of the cleared continuation bit in order to determine
+//    where the encoded Varint ends and the size of the decoded value.  The
+//    easiest way to do this is mask off all data bits, leaving just the
+//    continuation bits.  We actually need to do the masking on an inverted
+//    copy of the data, which leaves a 1 in all continuation bits which were
+//    originally clear.  The number of trailing zeroes in this value indicates
+//    the size of the Varint.
+//
+//  AND  0x80    0x80    0x80    0x80    0x80    0x80    0x80    0x80
+//
+// Bits   63      55      47      39      31      23      15       7
+//      +----+--+----+--+----+--+----+--+----+--+----+--+----+--+----+--+
+// ~    |CB 7|  |CB 6|  |CB 5|  |CB 4|  |CB 3|  |CB 2|  |CB 1|  |CB 0|  |
+//      +----+--+----+--+----+--+----+--+----+--+----+--+----+--+----+--+
+//         |       |       |       |       |       |       |       |
+//         V       V       V       V       V       V       V       V
+// Bits   63      55      47      39      31      23      15       7
+//      +----+--+----+--+----+--+----+--+----+--+----+--+----+--+----+--+
+//      |~CB 7|0|~CB 6|0|~CB 5|0|~CB 4|0|~CB 3|0|~CB 2|0|~CB 1|0|~CB 0|0|
+//      +----+--+----+--+----+--+----+--+----+--+----+--+----+--+----+--+
+//                                      |
+//                                     CTZ
+//                                      V
+//                     Index of first cleared continuation bit
+//
+//
+// While this is implemented in C++ significant care has been taken to ensure
+// the compiler emits the best instruction sequence.  In some cases we use the
+// following two functions to manipulate the compiler's scheduling decisions.
+//
+// Controls compiler scheduling by telling it that the first value is modified
+// by the second value the callsite.  This is useful if non-critical path
+// instructions are too aggressively scheduled, resulting in a slowdown of the
+// actual critical path due to opportunity costs.  An example usage is shown
+// where a false dependence of num_bits on result is added to prevent checking
+// for a very unlikely error until all critical path instructions have been
+// fetched.
+//
+// ```
+// num_bits = <multiple operations to calculate new num_bits value>
+// result = <multiple operations to calculate result>
+// num_bits = ValueBarrier(num_bits, result);
+// if (num_bits == 63) {
+//   GOOGLE_LOG(FATAL) << "Invalid num_bits value";
+// }
+// ```
+template <typename V1Type, typename V2Type>
+PROTOBUF_ALWAYS_INLINE inline V1Type ValueBarrier(V1Type value1,
+                                                  V2Type value2) {
+  asm("" : "+r"(value1) : "r"(value2));
+  return value1;
+}
+
+// Falsely indicate that the specific value is modified at this location.  This
+// prevents code which depends on this value from being scheduled earlier.
+template <typename V1Type>
+PROTOBUF_ALWAYS_INLINE inline V1Type ValueBarrier(V1Type value1) {
+  asm("" : "+r"(value1));
+  return value1;
+}
+
+PROTOBUF_ALWAYS_INLINE inline uint64_t ExtractAndMergeTwoChunks(
+    uint64_t data, uint64_t first_byte) {
+  GOOGLE_DCHECK_LE(first_byte, 6);
+  uint64_t first = Ubfx7(data, first_byte * 8);
+  uint64_t second = Ubfx7(data, (first_byte + 1) * 8);
+  return ForceToRegister(first | (second << 7));
+}
+
+struct SlowPathEncodedInfo {
+  const char* p;
+  uint64_t last8;
+  uint64_t valid_bits;
+  uint64_t valid_chunk_bits;
+  uint64_t masked_cont_bits;
+};
+
+// Performs multiple actions which are identical between 32 and 64 bit Varints
+// in order to compute the length of the encoded Varint and compute the new
+// of p.
+PROTOBUF_ALWAYS_INLINE inline SlowPathEncodedInfo ComputeLengthAndUpdateP(
+    const char* p) {
+  SlowPathEncodedInfo result;
+  // Load the last two bytes of the encoded Varint.
+  std::memcpy(&result.last8, p + 2, sizeof(result.last8));
+  uint64_t mask = ForceToRegister(0x8080808080808080);
+  // Only set continuation bits remain
+  result.masked_cont_bits = ForceToRegister(mask & (~result.last8));
+  // The first cleared continuation bit is the most significant 1 in the
+  // reversed value.  Result is undefined for an input of 0 and we handle that
+  // case below.
+  result.valid_bits = absl::countr_zero(result.masked_cont_bits);
+  // Calculates the number of chunks in the encoded Varint.  This value is low
+  // by three as neither the cleared continuation chunk nor the first two chunks
+  // are counted.
+  uint64_t set_continuation_bits = result.valid_bits >> 3;
+  // Update p to point past the encoded Varint.
+  result.p = p + set_continuation_bits + 3;
+  // Calculate number of valid data bits in the decoded value so invalid bits
+  // can be masked off.  Value is too low by 14 but we account for that when
+  // calculating the mask.
+  result.valid_chunk_bits = result.valid_bits - set_continuation_bits;
+  return result;
+}
+
+constexpr uint64_t kResultMaskUnshifted = 0xffffffffffffc000ULL;
+constexpr uint64_t kFirstResultBitChunk1 = 1 * 7;
+constexpr uint64_t kFirstResultBitChunk2 = 2 * 7;
+constexpr uint64_t kFirstResultBitChunk3 = 3 * 7;
+constexpr uint64_t kFirstResultBitChunk4 = 4 * 7;
+constexpr uint64_t kFirstResultBitChunk6 = 6 * 7;
+constexpr uint64_t kFirstResultBitChunk8 = 8 * 7;
+constexpr uint64_t kValidBitsForInvalidVarint = 0x60;
+
+PROTOBUF_NOINLINE const char* VarintParseSlowArm64(const char* p, uint64_t* out,
+                                                   uint64_t first8) {
+  SlowPathEncodedInfo info = ComputeLengthAndUpdateP(p);
+  // Extract data bits from the low six chunks.  This includes chunks zero and
+  // one which we already know are valid.
+  uint64_t merged_01 = ExtractAndMergeTwoChunks(first8, /*first_chunk=*/0);
+  uint64_t merged_23 = ExtractAndMergeTwoChunks(first8, /*first_chunk=*/2);
+  uint64_t merged_45 = ExtractAndMergeTwoChunks(first8, /*first_chunk=*/4);
+  // Low 42 bits of decoded value.
+  uint64_t result = merged_01 | merged_23 << kFirstResultBitChunk2 |
+                    merged_45 << kFirstResultBitChunk4;
+  // This immediate ends in 14 zeroes since valid_chunk_bits is too low by 14.
+  uint64_t result_mask = kResultMaskUnshifted << info.valid_chunk_bits;
+  // masked_cont_bits is 0 iff the Varint is invalid.  In that case
+  info.valid_bits =
+      info.masked_cont_bits ? info.valid_bits : kValidBitsForInvalidVarint;
+  // Test for early exit if Varint does not exceed 6 chunks.  Branching on one
+  // bit is faster on ARM than via a compare and branch.
+  if (PROTOBUF_PREDICT_FALSE((info.valid_bits & 0x20) != 0)) {
+    // Extract data bits from high four chunks.
+    uint64_t merged_67 = ExtractAndMergeTwoChunks(first8, /*first_chunk=*/6);
+    // Last two chunks come from last two bytes of info.last8.
+    uint64_t merged_89 =
+        ExtractAndMergeTwoChunks(info.last8, /*first_chunk=*/6);
+    result |= merged_67 << kFirstResultBitChunk6;
+    result |= merged_89 << kFirstResultBitChunk8;
+    // Handle an invalid Varint with all 10 continuation bits set.
+    info.masked_cont_bits = ValueBarrier(info.masked_cont_bits);
+    if (PROTOBUF_PREDICT_FALSE(info.masked_cont_bits == 0)) {
+      *out = 0;
+      return nullptr;
+    }
+  }
+  // Mask off invalid data bytes.
+  result &= ~result_mask;
+  *out = result;
+  return info.p;
+}
+
+// See comments in VarintParseSlowArm64 for a description of the algorithm.
+// Differences in the 32 bit version are noted below.
+PROTOBUF_NOINLINE const char* VarintParseSlowArm32(const char* p, uint32_t* out,
+                                                   uint64_t first8) {
+  // This also skips the slop bytes.
+  SlowPathEncodedInfo info = ComputeLengthAndUpdateP(p);
+  // Extract data bits from chunks 1-4.  Chunk zero is merged in below.
+  uint64_t merged_12 = ExtractAndMergeTwoChunks(first8, /*first_chunk=*/1);
+  uint64_t merged_34 = ExtractAndMergeTwoChunks(first8, /*first_chunk=*/3);
+  first8 = ValueBarrier(first8, p);
+  uint64_t result = Ubfx7(first8, /*start=*/0);
+  result = ForceToRegister(result | merged_12 << kFirstResultBitChunk1);
+  result = ForceToRegister(result | merged_34 << kFirstResultBitChunk3);
+  uint64_t result_mask = kResultMaskUnshifted << info.valid_chunk_bits;
+  result &= ~result_mask;
+  // It is extremely unlikely that a Varint is invalid so checking that
+  // condition isn't on the critical path. Here we make sure that we don't do so
+  // until result has been computed.
+  info.masked_cont_bits = ValueBarrier(info.masked_cont_bits, result);
+  if (PROTOBUF_PREDICT_FALSE(info.masked_cont_bits == 0)) {
+    // Makes the compiler think out was modified here.  This ensures it won't
+    // predicate this extremely predictable branch.
+    out = ValueBarrier(out);
+    *out = 0;
+    return nullptr;
+  }
+  *out = result;
+  return info.p;
+}
+
+#endif  // __aarch64__
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/parse_context.h b/src/google/protobuf/parse_context.h
index 7aea50c..e1ff16c 100644
--- a/src/google/protobuf/parse_context.h
+++ b/src/google/protobuf/parse_context.h
@@ -36,21 +36,23 @@
 #include <string>
 #include <type_traits>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/endian.h>
-#include <google/protobuf/implicit_weak_message.h>
-#include <google/protobuf/inlined_string_field.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/arena.h"
+#include "absl/strings/internal/resize_uninitialized.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/endian.h"
+#include "google/protobuf/implicit_weak_message.h"
+#include "google/protobuf/inlined_string_field.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/wire_format_lite.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 
 namespace google {
@@ -64,11 +66,11 @@
 
 // Template code below needs to know about the existence of these functions.
 PROTOBUF_EXPORT void WriteVarint(uint32_t num, uint64_t val, std::string* s);
-PROTOBUF_EXPORT void WriteLengthDelimited(uint32_t num, StringPiece val,
+PROTOBUF_EXPORT void WriteLengthDelimited(uint32_t num, absl::string_view val,
                                           std::string* s);
 // Inline because it is just forwarding to s->WriteVarint
 inline void WriteVarint(uint32_t num, uint64_t val, UnknownFieldSet* s);
-inline void WriteLengthDelimited(uint32_t num, StringPiece val,
+inline void WriteLengthDelimited(uint32_t num, absl::string_view val,
                                  UnknownFieldSet* s);
 
 
@@ -157,7 +159,13 @@
   PROTOBUF_NODISCARD const char* ReadString(const char* ptr, int size,
                                             std::string* s) {
     if (size <= buffer_end_ + kSlopBytes - ptr) {
-      s->assign(ptr, size);
+      // Fundamentally we just want to do assign to the string.
+      // However micro-benchmarks regress on string reading cases. So we copy
+      // the same logic from the old CodedInputStream ReadString. Note: as of
+      // Apr 2021, this is still a significant win over `assign()`.
+      absl::strings_internal::STLStringResizeUninitialized(s, size);
+      char* z = &(*s)[0];
+      memcpy(z, ptr, size);
       return ptr + size;
     }
     return ReadStringFallback(ptr, size, s);
@@ -204,6 +212,10 @@
   int BytesUntilLimit(const char* ptr) const {
     return limit_ + static_cast<int>(buffer_end_ - ptr);
   }
+  // Maximum number of sequential bytes that can be read starting from `ptr`.
+  int MaximumReadSize(const char* ptr) const {
+    return static_cast<int>(limit_end_ - ptr) + kSlopBytes;
+  }
   // Returns true if more data is available, if false is returned one has to
   // call Done for further checks.
   bool DataAvailable(const char* ptr) { return ptr < limit_end_; }
@@ -229,7 +241,7 @@
     return res.second;
   }
 
-  const char* InitFrom(StringPiece flat) {
+  const char* InitFrom(absl::string_view flat) {
     overall_limit_ = 0;
     if (flat.size() > kSlopBytes) {
       limit_ = kSlopBytes;
@@ -238,7 +250,9 @@
       if (aliasing_ == kOnPatch) aliasing_ = kNoDelta;
       return flat.data();
     } else {
-      std::memcpy(buffer_, flat.data(), flat.size());
+      if (!flat.empty()) {
+        std::memcpy(buffer_, flat.data(), flat.size());
+      }
       limit_ = 0;
       limit_end_ = buffer_end_ = buffer_ + flat.size();
       next_chunk_ = nullptr;
@@ -325,7 +339,7 @@
 
   template <typename A>
   const char* AppendSize(const char* ptr, int size, const A& append) {
-    int chunk_size = buffer_end_ + kSlopBytes - ptr;
+    int chunk_size = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
     do {
       GOOGLE_DCHECK(size > chunk_size);
       if (next_chunk_ == nullptr) return nullptr;
@@ -339,7 +353,7 @@
       ptr = Next();
       if (ptr == nullptr) return nullptr;  // passed the limit
       ptr += kSlopBytes;
-      chunk_size = buffer_end_ + kSlopBytes - ptr;
+      chunk_size = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
     } while (size > chunk_size);
     append(ptr, size);
     return ptr + size;
@@ -387,7 +401,6 @@
   struct Data {
     const DescriptorPool* pool = nullptr;
     MessageFactory* factory = nullptr;
-    Arena* arena = nullptr;
   };
 
   template <typename... T>
@@ -427,12 +440,49 @@
                                     bool>::type = true>
   PROTOBUF_NODISCARD const char* ParseMessage(T* msg, const char* ptr);
 
+  template <typename TcParser, typename Table>
+  PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE const char* ParseMessage(
+      MessageLite* msg, const char* ptr, const Table* table) {
+    int old;
+    ptr = ReadSizeAndPushLimitAndDepthInlined(ptr, &old);
+    auto old_depth = depth_;
+    ptr = ptr ? TcParser::ParseLoop(msg, ptr, this, table) : nullptr;
+    if (ptr != nullptr) GOOGLE_DCHECK_EQ(old_depth, depth_);
+    depth_++;
+    if (!PopLimit(old)) return nullptr;
+    return ptr;
+  }
+
   template <typename T>
   PROTOBUF_NODISCARD PROTOBUF_NDEBUG_INLINE const char* ParseGroup(
       T* msg, const char* ptr, uint32_t tag) {
     if (--depth_ < 0) return nullptr;
     group_depth_++;
+    auto old_depth = depth_;
+    auto old_group_depth = group_depth_;
     ptr = msg->_InternalParse(ptr, this);
+    if (ptr != nullptr) {
+      GOOGLE_DCHECK_EQ(old_depth, depth_);
+      GOOGLE_DCHECK_EQ(old_group_depth, group_depth_);
+    }
+    group_depth_--;
+    depth_++;
+    if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr;
+    return ptr;
+  }
+
+  template <typename TcParser, typename Table>
+  PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE const char* ParseGroup(
+      MessageLite* msg, const char* ptr, uint32_t tag, const Table* table) {
+    if (--depth_ < 0) return nullptr;
+    group_depth_++;
+    auto old_depth = depth_;
+    auto old_group_depth = group_depth_;
+    ptr = TcParser::ParseLoop(msg, ptr, this, table);
+    if (ptr != nullptr) {
+      GOOGLE_DCHECK_EQ(old_depth, depth_);
+      GOOGLE_DCHECK_EQ(old_group_depth, group_depth_);
+    }
     group_depth_--;
     depth_++;
     if (PROTOBUF_PREDICT_FALSE(!ConsumeEndGroup(tag))) return nullptr;
@@ -451,6 +501,11 @@
   PROTOBUF_NODISCARD const char* ReadSizeAndPushLimitAndDepth(const char* ptr,
                                                               int* old_limit);
 
+  // As above, but fully inlined for the cases where we care about performance
+  // more than size. eg TcParser.
+  PROTOBUF_NODISCARD PROTOBUF_ALWAYS_INLINE const char*
+  ReadSizeAndPushLimitAndDepthInlined(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.
@@ -534,21 +589,64 @@
   return tmp.first;
 }
 
+#ifdef __aarch64__
+const char* VarintParseSlowArm64(const char* p, uint64_t* out, uint64_t first8);
+const char* VarintParseSlowArm32(const char* p, uint32_t* out, uint64_t first8);
+
+inline const char* VarintParseSlowArm(const char* p, uint32_t* out,
+                                      uint64_t first8) {
+  return VarintParseSlowArm32(p, out, first8);
+}
+
+inline const char* VarintParseSlowArm(const char* p, uint64_t* out,
+                                      uint64_t first8) {
+  return VarintParseSlowArm64(p, out, first8);
+}
+
+// Moves data into a register and returns data.  This impacts the compiler's
+// scheduling and instruction selection decisions.
+static PROTOBUF_ALWAYS_INLINE inline uint64_t ForceToRegister(uint64_t data) {
+  asm("" : "+r"(data));
+  return data;
+}
+
+// Performs a 7 bit UBFX (Unsigned Bit Extract) starting at the indicated bit.
+static PROTOBUF_ALWAYS_INLINE inline uint64_t Ubfx7(uint64_t data,
+                                                    uint64_t start) {
+  return ForceToRegister((data >> start) & 0x7f);
+}
+
+#endif  // __aarch64__
+
 template <typename T>
 PROTOBUF_NODISCARD const char* VarintParse(const char* p, T* out) {
+#if defined(__aarch64__) && defined(PROTOBUF_LITTLE_ENDIAN)
+  // This optimization is not supported in big endian mode
+  uint64_t first8;
+  std::memcpy(&first8, p, sizeof(first8));
+  if (PROTOBUF_PREDICT_TRUE((first8 & 0x80) == 0)) {
+    *out = static_cast<uint8_t>(first8);
+    return p + 1;
+  }
+  if (PROTOBUF_PREDICT_TRUE((first8 & 0x8000) == 0)) {
+    uint64_t chunk1;
+    uint64_t chunk2;
+    // Extracting the two chunks this way gives a speedup for this path.
+    chunk1 = Ubfx7(first8, 0);
+    chunk2 = Ubfx7(first8, 8);
+    *out = chunk1 | (chunk2 << 7);
+    return p + 2;
+  }
+  return VarintParseSlowArm(p, out, first8);
+#else   // __aarch64__
   auto ptr = reinterpret_cast<const uint8_t*>(p);
   uint32_t res = ptr[0];
-  if (!(res & 0x80)) {
+  if ((res & 0x80) == 0) {
     *out = res;
     return p + 1;
   }
-  uint32_t byte = ptr[1];
-  res += (byte - 1) << 7;
-  if (!(byte & 0x80)) {
-    *out = res;
-    return p + 2;
-  }
   return VarintParseSlow(p, res, out);
+#endif  // __aarch64__
 }
 
 // Used for tags, could read up to 5 bytes which must be available.
@@ -590,6 +688,7 @@
 
 PROTOBUF_NODISCARD inline PROTOBUF_ALWAYS_INLINE uint64_t
 RotRight7AndReplaceLowByte(uint64_t res, const char& byte) {
+  // TODO(b/239808098): remove the inline assembly
 #if defined(__x86_64__) && defined(__GNUC__)
   // This will only use one register for `res`.
   // `byte` comes as a reference to allow the compiler to generate code like:
@@ -749,12 +848,28 @@
                                                           const char* ptr) {
   int old;
   ptr = ReadSizeAndPushLimitAndDepth(ptr, &old);
-  ptr = ptr ? msg->_InternalParse(ptr, this) : nullptr;
+  if (ptr == nullptr) return ptr;
+  auto old_depth = depth_;
+  ptr = msg->_InternalParse(ptr, this);
+  if (ptr != nullptr) GOOGLE_DCHECK_EQ(old_depth, depth_);
   depth_++;
   if (!PopLimit(old)) return nullptr;
   return ptr;
 }
 
+inline const char* ParseContext::ReadSizeAndPushLimitAndDepthInlined(
+    const char* ptr, int* old_limit) {
+  int size = ReadSize(&ptr);
+  if (PROTOBUF_PREDICT_FALSE(!ptr)) {
+    // Make sure this isn't uninitialized even on error return
+    *old_limit = 0;
+    return nullptr;
+  }
+  *old_limit = PushLimit(ptr, size);
+  if (--depth_ < 0) return nullptr;
+  return ptr;
+}
+
 template <typename Tag, typename T>
 const char* EpsCopyInputStream::ReadRepeatedFixed(const char* ptr,
                                                   Tag expected_tag,
@@ -783,7 +898,7 @@
 const char* EpsCopyInputStream::ReadPackedFixed(const char* ptr, int size,
                                                 RepeatedField<T>* out) {
   GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
-  int nbytes = buffer_end_ + kSlopBytes - ptr;
+  int nbytes = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
   while (size > nbytes) {
     int num = nbytes / sizeof(T);
     int old_entries = out->size();
@@ -801,14 +916,16 @@
     ptr = Next();
     if (ptr == nullptr) return nullptr;
     ptr += kSlopBytes - (nbytes - block_size);
-    nbytes = buffer_end_ + kSlopBytes - ptr;
+    nbytes = static_cast<int>(buffer_end_ + kSlopBytes - ptr);
   }
   int num = size / sizeof(T);
+  int block_size = num * sizeof(T);
+  if (num == 0) return size == block_size ? ptr : nullptr;
   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
+  GOOGLE_CHECK(dst != nullptr) << out << "," << num;
   std::memcpy(dst, ptr, block_size);
 #else
   for (int i = 0; i < num; i++) dst[i] = UnalignedLoad<T>(ptr + i * sizeof(T));
@@ -833,11 +950,11 @@
 const char* EpsCopyInputStream::ReadPackedVarint(const char* ptr, Add add) {
   int size = ReadSize(&ptr);
   GOOGLE_PROTOBUF_PARSER_ASSERT(ptr);
-  int chunk_size = buffer_end_ - ptr;
+  int chunk_size = static_cast<int>(buffer_end_ - ptr);
   while (size > chunk_size) {
     ptr = ReadPackedVarintArray(ptr, buffer_end_, add);
     if (ptr == nullptr) return nullptr;
-    int overrun = ptr - buffer_end_;
+    int overrun = static_cast<int>(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
@@ -858,7 +975,7 @@
     ptr = Next();
     if (ptr == nullptr) return nullptr;
     ptr += overrun;
-    chunk_size = buffer_end_ - ptr;
+    chunk_size = static_cast<int>(buffer_end_ - ptr);
   }
   auto end = ptr + size;
   ptr = ReadPackedVarintArray(ptr, end, add);
@@ -867,7 +984,7 @@
 
 // Helper for verification of utf8
 PROTOBUF_EXPORT
-bool VerifyUTF8(StringPiece s, const char* field_name);
+bool VerifyUTF8(absl::string_view s, const char* field_name);
 
 inline bool VerifyUTF8(const std::string* s, const char* field_name) {
   return VerifyUTF8(*s, field_name);
@@ -1020,6 +1137,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_PARSE_CONTEXT_H__
diff --git a/src/google/protobuf/port.h b/src/google/protobuf/port.h
index a5c060b..f3c6e66 100644
--- a/src/google/protobuf/port.h
+++ b/src/google/protobuf/port.h
@@ -36,17 +36,27 @@
 #ifndef GOOGLE_PROTOBUF_PORT_H__
 #define GOOGLE_PROTOBUF_PORT_H__
 
+#include <cassert>
 #include <cstddef>
 #include <new>
+#include <type_traits>
+
+
+// must be last
+#include "google/protobuf/port_def.inc"
 
 
 namespace google {
 namespace protobuf {
 namespace internal {
+
+
 inline void SizedDelete(void* p, size_t size) {
 #if defined(__cpp_sized_deallocation)
   ::operator delete(p, size);
 #else
+  // Avoid -Wunused-parameter
+  (void)size;
   ::operator delete(p);
 #endif
 }
@@ -54,6 +64,8 @@
 #if defined(__cpp_sized_deallocation)
   ::operator delete[](p, size);
 #else
+  // Avoid -Wunused-parameter
+  (void)size;
   ::operator delete[](p);
 #endif
 }
@@ -73,8 +85,35 @@
   explicit ArenaInitialized() = default;
 };
 
+template <typename To, typename From>
+inline To DownCast(From* f) {
+  static_assert(
+      std::is_base_of<From, typename std::remove_pointer<To>::type>::value,
+      "illegal DownCast");
+
+#if PROTOBUF_RTTI
+  // RTTI: debug mode only!
+  assert(f == nullptr || dynamic_cast<To>(f) != nullptr);
+#endif
+  return static_cast<To>(f);
+}
+
+template <typename ToRef, typename From>
+inline ToRef DownCast(From& f) {
+  using To = typename std::remove_reference<ToRef>::type;
+  static_assert(std::is_base_of<From, To>::value, "illegal DownCast");
+
+#if PROTOBUF_RTTI
+  // RTTI: debug mode only!
+  assert(dynamic_cast<To*>(&f) != nullptr);
+#endif
+  return *static_cast<To*>(&f);
+}
+
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
+#include "google/protobuf/port_undef.inc"
+
 #endif  // GOOGLE_PROTOBUF_PORT_H__
diff --git a/src/google/protobuf/port_def.inc b/src/google/protobuf/port_def.inc
index f454411..056161c 100644
--- a/src/google/protobuf/port_def.inc
+++ b/src/google/protobuf/port_def.inc
@@ -118,6 +118,15 @@
 #define PROTOBUF_has_builtin_DEFINED_
 #endif
 
+#ifdef ADDRESS_SANITIZER
+#include <sanitizer/asan_interface.h>
+#define PROTOBUF_POISON_MEMORY_REGION(p, n) ASAN_POISON_MEMORY_REGION(p, n)
+#define PROTOBUF_UNPOISON_MEMORY_REGION(p, n) ASAN_UNPOISON_MEMORY_REGION(p, n)
+#else  // ADDRESS_SANITIZER
+#define PROTOBUF_POISON_MEMORY_REGION(p, n)
+#define PROTOBUF_UNPOISON_MEMORY_REGION(p, n)
+#endif  // ADDRESS_SANITIZER
+
 // Portable PROTOBUF_BUILTIN_BSWAPxx definitions
 // Code must check for availability, e.g.: `defined(PROTOBUF_BUILTIN_BSWAP32)`
 #ifdef PROTOBUF_BUILTIN_BSWAP16
@@ -139,6 +148,11 @@
 #define PROTOBUF_BUILTIN_BSWAP64(x) __builtin_bswap64(x)
 #endif
 
+// Portable check for gcc-style atomic built-ins
+#if __has_builtin(__atomic_load_n)
+#define PROTOBUF_BUILTIN_ATOMIC 1
+#endif
+
 // Portable check for GCC minimum version:
 // https://gcc.gnu.org/onlinedocs/cpp/Common-Predefined-Macros.html
 #if defined(__GNUC__) && defined(__GNUC_MINOR__) \
@@ -149,6 +163,13 @@
 #  define PROTOBUF_GNUC_MIN(x, y) 0
 #endif
 
+#if defined(__clang__) && defined(__clang_major__) && defined(__clang_minor__)
+#define PROTOBUF_CLANG_MIN(x, y) \
+  (__clang_major__ > (x) || __clang_major__ == (x) && __clang_minor__ >= (y))
+#else
+#define PROTOBUF_CLANG_MIN(x, y) 0
+#endif
+
 // Portable check for MSVC minimum version:
 // https://docs.microsoft.com/en-us/cpp/preprocessor/predefined-macros
 #if defined(_MSC_VER)
@@ -169,11 +190,29 @@
 // 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.
-// PROTOBUF_FUTURE_FINAL is used on classes that are historically not marked as
-// final, but that may be marked final in future (breaking) releases.
-// #define PROTOBUF_FUTURE_BREAKING_CHANGES 1
-// #define PROTOBUF_FUTURE_FINAL final
+
+#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+
+// Used to upgrade google::protobuf::MapPair<K, V> to std::pair<const K, V>.
+// Owner: mordberg@
+#define PROTOBUF_FUTURE_MAP_PAIR_UPGRADE 1
+
+// Used on classes that are historically not marked as final, but that may be
+// marked final in future (breaking) releases.
+// Owner: kfm@
+#define PROTOBUF_FUTURE_FINAL final
+
+// Used to remove the RTTI checks for `DefaultFieldComparator`.
+// Owner: kfm@
+#define PROTOBUF_FUTURE_REMOVE_DEFAULT_FIELD_COMPARATOR 1
+
+// Used to remove the manipulation of cleared elements in RepeatedPtrField.
+// Owner: mkruskal@
+#define PROTOBUF_FUTURE_REMOVE_CLEARED_API 1
+
+#else
 #define PROTOBUF_FUTURE_FINAL
+#endif
 
 #ifdef PROTOBUF_VERSION
 #error PROTOBUF_VERSION was previously defined
@@ -356,15 +395,6 @@
 # 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
-
 #ifdef PROTOBUF_RETURNS_NONNULL
 #error PROTOBUF_RETURNS_NONNULL was previously defined
 #endif
@@ -527,12 +557,20 @@
 #error PROTOBUF_FORCE_RESET_IN_CLEAR was previously defined
 #endif
 
+#ifdef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG
+#error PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG was previously defined
+#endif
+
 // Force copy the default string to a string field so that non-optimized builds
 // have harder-to-rely-on address stability.
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
 #error PROTOBUF_FORCE_COPY_DEFAULT_STRING was previously defined
 #endif
 
+#ifdef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION
+#error PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION was previously defined
+#endif
+
 #ifdef PROTOBUF_FALLTHROUGH_INTENDED
 #error PROTOBUF_FALLTHROUGH_INTENDED was previously defined
 #endif
@@ -635,30 +673,39 @@
 // 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) && !defined(_MSC_VER)
-#define PROTOBUF_CONSTINIT constinit
-#define PROTOBUF_CONSTEXPR constexpr
+
+// Lexan sets both MSV_VER and clang, so handle it with the clang path.
+#if defined(_MSC_VER) && !defined(__clang__)
+// MSVC 17 currently seems to raise an error about constant-initialized pointers.
+# if PROTOBUF_MSC_VER_MIN(1930)
+#  define PROTOBUF_CONSTINIT
+#  define PROTOBUF_CONSTEXPR constexpr
+# endif
+#else
+# if defined(__cpp_constinit) && !defined(__CYGWIN__)
+#  define PROTOBUF_CONSTINIT constinit
+#  define PROTOBUF_CONSTEXPR constexpr
 // Some older Clang versions incorrectly raise an error about
 // constant-initializing weak default instance pointers. Versions 12.0 and
 // higher seem to work, except that XCode 12.5.1 shows the error even though it
 // uses Clang 12.0.5.
-// Clang-cl on Windows raises error also.
-#elif !defined(_MSC_VER) && __has_cpp_attribute(clang::require_constant_initialization) && \
-    ((defined(__APPLE__) && __clang_major__ >= 13) ||                \
-     (!defined(__APPLE__) && __clang_major__ >= 12))
-#define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]]
-#define PROTOBUF_CONSTEXPR constexpr
-#elif PROTOBUF_GNUC_MIN(12, 2)
-#define PROTOBUF_CONSTINIT __constinit
-#define PROTOBUF_CONSTEXPR constexpr
-// MSVC 17 currently seems to raise an error about constant-initialized pointers.
-#elif defined(_MSC_VER) && _MSC_VER >= 1930
-#define PROTOBUF_CONSTINIT
-#define PROTOBUF_CONSTEXPR constexpr
-#else
+# elif !defined(__CYGWIN__) && \
+    __has_cpp_attribute(clang::require_constant_initialization) && \
+        ((defined(__APPLE__) && PROTOBUF_CLANG_MIN(13, 0)) ||             \
+     (!defined(__APPLE__) && PROTOBUF_CLANG_MIN(12, 0)))
+#  define PROTOBUF_CONSTINIT [[clang::require_constant_initialization]]
+#  define PROTOBUF_CONSTEXPR constexpr
+# elif PROTOBUF_GNUC_MIN(12, 2)
+#  define PROTOBUF_CONSTINIT __constinit
+#  define PROTOBUF_CONSTEXPR constexpr
+# endif
+#endif
+
+#ifndef PROTOBUF_CONSTINIT
 #define PROTOBUF_CONSTINIT
 #define PROTOBUF_CONSTEXPR
 #endif
@@ -771,21 +818,35 @@
 #  endif
 #endif
 
-// Tail call table-driven parsing can be enabled by defining
-// PROTOBUF_EXPERIMENTAL_USE_TAIL_CALL_TABLE_PARSER at compilation time. Note
-// that this macro is for small-scale testing only, and is not supported.
+// Tail call table-driven parsing is enabled by default.
 #ifdef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED
 #error PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED was previously declared
 #endif
-#if defined(PROTOBUF_EXPERIMENTAL_USE_TAIL_CALL_TABLE_PARSER)
 #define PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED 1
-#endif
 
-#define PROTOBUF_TC_PARAM_DECL                                 \
-  ::google::protobuf::MessageLite *msg, const char *ptr,                 \
-      ::google::protobuf::internal::ParseContext *ctx,                   \
-      const ::google::protobuf::internal::TcParseTableBase *table,       \
-      uint64_t hasbits, ::google::protobuf::internal::TcFieldData data
+#ifdef PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION
+#error PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION was previously defined
+#endif
+#if !defined(PROTOBUF_TEMPORARY_DISABLE_TABLE_PARSER_ON_REFLECTION)
+#define PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION 1
+#endif  // PROTOBUF_ENABLE_FORCE_ALLOCATION_ON_CONSTRUCTION
+
+// 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.
+// Arguments `msg`, `ptr` and `ctx` are the 1st/2nd/3rd argument to match the
+// signature of ParseLoop.
+//
+// Note for x86_64: `data` must be the third or fourth argument for performance
+// reasons. In order to efficiently read the second byte of `data` we need it to
+// be passed in RDX or RCX.
+#define PROTOBUF_TC_PARAM_DECL                 \
+  ::google::protobuf::MessageLite *msg, const char *ptr, \
+      ::google::protobuf::internal::ParseContext *ctx,   \
+      ::google::protobuf::internal::TcFieldData data,    \
+      const ::google::protobuf::internal::TcParseTableBase *table, uint64_t hasbits
+// PROTOBUF_TC_PARAM_PASS passes values to match PROTOBUF_TC_PARAM_DECL.
+#define PROTOBUF_TC_PARAM_PASS msg, ptr, ctx, data, table, hasbits
 
 #ifdef PROTOBUF_UNUSED
 #error PROTOBUF_UNUSED was previously defined
@@ -801,13 +862,36 @@
 
 // ThreadSafeArenaz is turned off completely in opensource builds.
 
+// autoheader defines this in some circumstances
+#ifdef PACKAGE
+#define PROTOBUF_DID_UNDEF_PACKAGE
+#pragma push_macro("PACKAGE")
+#undef PACKAGE
+#endif
+
+// autoheader defines this in some circumstances
+#ifdef PACKAGE
+#define PROTOBUF_DID_UNDEF_PACKAGE
+#pragma push_macro("PACKAGE")
+#undef PACKAGE
+#endif
+
+// linux is a legacy MACRO defined in most popular C++ standards.
+#ifdef linux
+#pragma push_macro("linux")
+#undef linux
+#define PROTOBUF_DID_UNDEF_LINUX
+#endif
+
 // Windows declares several inconvenient macro names.  We #undef them and then
 // restore them in port_undef.inc.
-#ifdef _MSC_VER
+#ifdef _WIN32
 #pragma push_macro("CREATE_NEW")
 #undef CREATE_NEW
 #pragma push_macro("DELETE")
 #undef DELETE
+#pragma push_macro("DOMAIN")
+#undef DOMAIN
 #pragma push_macro("DOUBLE_CLICK")
 #undef DOUBLE_CLICK
 #pragma push_macro("ERROR")
@@ -820,6 +904,8 @@
 #undef ERROR_NOT_FOUND
 #pragma push_macro("GetClassName")
 #undef GetClassName
+#pragma push_macro("GetCurrentTime")
+#undef GetCurrentTime
 #pragma push_macro("GetMessage")
 #undef GetMessage
 #pragma push_macro("GetObject")
@@ -856,7 +942,7 @@
 #undef STRICT
 #pragma push_macro("timezone")
 #undef timezone
-#endif  // _MSC_VER
+#endif  // _WIN32
 
 #ifdef __APPLE__
 // Inconvenient macro names from usr/include/math.h in some macOS SDKs.
@@ -870,6 +956,11 @@
 // Inconvenient macro names from usr/include/sys/syslimits.h in some macOS SDKs.
 #pragma push_macro("UID_MAX")
 #undef UID_MAX
+#pragma push_macro("GID_MAX")
+#undef GID_MAX
+// TYPE_BOOL is defined in the MacOS's ConditionalMacros.h.
+#pragma push_macro("TYPE_BOOL")
+#undef TYPE_BOOL
 #endif  // __APPLE__
 
 #if defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER)
@@ -879,13 +970,40 @@
 #undef DEBUG
 #endif // defined(__clang__) || PROTOBUF_GNUC_MIN(3, 0) || defined(_MSC_VER)
 
-#if PROTOBUF_GNUC_MIN(3, 0)
+// Protobuf does not support building with a number of warnings that are noisy
+// (and of variable quality across compiler versions) or impossible to implement
+// effectively but which people turn on anyways.
+#ifdef __clang__
+#pragma clang diagnostic push
+// -Wshorten-64-to-32 is a typical pain where we diff pointers.
+//   char* p = strchr(s, '\n');
+//   return p ? p - s : -1;
+#pragma clang diagnostic ignored "-Wshorten-64-to-32"
+#endif
+#ifdef __GNUC__
+#pragma GCC diagnostic push
+// Some of the warnings below only exist in some GCC versions; those version
+// ranges are poorly documented.
+#pragma GCC diagnostic ignored "-Wpragmas"
 // 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 __clang__
+// TODO(b/255348263): Upgrade our kokoro Ubuntu to use clang 6, then change th 5 to a 6
+static_assert(PROTOBUF_CLANG_MIN(5, 0), "Protobuf only supports Clang 6.0 and newer.");
 #endif
+// Some versions of GCC seem to think that
+//  [this] { Foo(); }
+// leaves `this` unused, even though `Foo();` is a member function of the
+// captured `this`.
+// https://bugzilla.mozilla.org/show_bug.cgi?id=1373625
+#pragma GCC diagnostic ignored "-Wunused-lambda-capture"
+// -Wsign-conversion causes a lot of warnings on mostly code like:
+//   int index = ...
+//   int value = vec[index];
+#pragma GCC diagnostic ignored "-Wsign-conversion"
+#endif  // __GNUC__
 
 // Silence some MSVC warnings in all our code.
 #ifdef _MSC_VER
@@ -903,6 +1021,23 @@
 #pragma warning(disable: 4125)
 #endif
 
+#if PROTOBUF_ENABLE_DEBUG_LOGGING_MAY_LEAK_PII
+#define PROTOBUF_DEBUG true
+#else
+#define PROTOBUF_DEBUG false
+#endif
+
+// This `for` allows us to condition the `GOOGLE_LOG` on the define above, so that
+// code can write `PROTOBUF_DLOG(INFO) << ...;` and have it turned off when
+// debug logging is off.
+//
+// This is a `for`, not and `if`, to avoid it accidentally chaining with an
+// `else` below it.
+#define PROTOBUF_DLOG(x) \
+  for (bool b = PROTOBUF_DEBUG; b; b = false) GOOGLE_LOG(x)
+
+#define PROTO2_IS_OSS true
+
 // 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.
diff --git a/src/google/protobuf/port_undef.inc b/src/google/protobuf/port_undef.inc
index e880fa5..97cda49 100644
--- a/src/google/protobuf/port_undef.inc
+++ b/src/google/protobuf/port_undef.inc
@@ -35,10 +35,14 @@
 #error "port_undef.inc must be included after port_def.inc"
 #endif
 
+#undef PROTOBUF_POISON_MEMORY_REGION
+#undef PROTOBUF_UNPOISON_MEMORY_REGION
 #undef PROTOBUF_BUILTIN_BSWAP16
 #undef PROTOBUF_BUILTIN_BSWAP32
 #undef PROTOBUF_BUILTIN_BSWAP64
+#undef PROTOBUF_BUILTIN_ATOMIC
 #undef PROTOBUF_GNUC_MIN
+#undef PROTOBUF_CLANG_MIN
 #undef PROTOBUF_MSC_VER_MIN
 #undef PROTOBUF_CPLUSPLUS_MIN
 #undef PROTOBUF_NAMESPACE
@@ -53,7 +57,6 @@
 #undef PROTOBUF_DEPRECATED
 #undef PROTOBUF_DEPRECATED_ENUM
 #undef PROTOBUF_DEPRECATED_MSG
-#undef PROTOBUF_FUNC_ALIGN
 #undef PROTOBUF_RETURNS_NONNULL
 #undef PROTOBUF_ATTRIBUTE_REINITIALIZES
 #undef PROTOBUF_RTTI
@@ -72,7 +75,9 @@
 #undef PROTOBUF_FORCE_COPY_IN_SWAP
 #undef PROTOBUF_FORCE_COPY_IN_MOVE
 #undef PROTOBUF_FORCE_RESET_IN_CLEAR
+#undef PROTOBUF_FUZZ_MESSAGE_SPACE_USED_LONG
 #undef PROTOBUF_FORCE_COPY_DEFAULT_STRING
+#undef PROTOBUF_FORCE_ALLOCATION_ON_CONSTRUCTION
 #undef PROTOBUF_NAMESPACE_OPEN
 #undef PROTOBUF_NAMESPACE_CLOSE
 #undef PROTOBUF_UNUSED
@@ -99,26 +104,47 @@
 #undef PROTOBUF_MSAN
 #undef PROTOBUF_TSAN
 #undef PROTOBUF_TAIL_CALL_TABLE_PARSER_ENABLED
+#undef PROTOBUF_USE_TABLE_PARSER_ON_REFLECTION
 #undef PROTOBUF_TC_PARAM_DECL
 #undef PROTOBUF_EXCLUSIVE_LOCKS_REQUIRED
 #undef PROTOBUF_LOCKS_EXCLUDED
 #undef PROTOBUF_NO_THREAD_SAFETY_ANALYSIS
 #undef PROTOBUF_GUARDED_BY
+#undef PROTOBUF_DEBUG
+#undef PROTOBUF_DLOG
+#undef PROTO2_IS_OSS
 
 #ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
 #undef PROTOBUF_FUTURE_BREAKING_CHANGES
+#undef PROTOBUF_FUTURE_MAP_PAIR_UPGRADE
+#undef PROTOBUF_FUTURE_REMOVE_DEFAULT_FIELD_COMPARATOR
+#undef PROTOBUF_FUTURE_REMOVE_CLEARED_API
 #endif
 
-// Restore macro that may have been #undef'd in port_def.inc.
-#ifdef _MSC_VER
+#undef PROTOBUF_FUTURE_FINAL
+
+// Restore macros that may have been #undef'd in port_def.inc.
+
+#ifdef PROTOBUF_DID_UNDEF_PACKAGE
+#pragma pop_macro("PACKAGE")
+#undef PROTOBUF_DID_UNDEF_PACKAGE
+#endif
+
+#ifdef PROTOBUF_DID_UNDEF_LINUX
+#pragma pop_macro("linux")
+#endif
+
+#ifdef _WIN32
 #pragma pop_macro("CREATE_NEW")
 #pragma pop_macro("DELETE")
+#pragma pop_macro("DOMAIN")
 #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("GetClassName")
+#pragma pop_macro("GetCurrentTime")
 #pragma pop_macro("GetMessage")
 #pragma pop_macro("GetObject")
 #pragma pop_macro("IGNORE")
@@ -144,6 +170,8 @@
 #pragma pop_macro("TRUE")
 #pragma pop_macro("FALSE")
 #pragma pop_macro("UID_MAX")
+#pragma pop_macro("GID_MAX")
+#pragma pop_macro("TYPE_BOOL")
 #endif  // __APPLE__
 
 #if defined(__clang__) || defined(__GNUC__) || defined(_MSC_VER)
@@ -154,6 +182,10 @@
 #pragma GCC diagnostic pop
 #endif
 
+#ifdef __clang__
+#pragma clang diagnostic pop
+#endif
+
 // Pop the warning(push) from port_def.inc
 #ifdef _MSC_VER
 #pragma warning(pop)
diff --git a/src/google/protobuf/preserve_unknown_enum_test.cc b/src/google/protobuf/preserve_unknown_enum_test.cc
index 7e6bbf1..8d6d8c8 100644
--- a/src/google/protobuf/preserve_unknown_enum_test.cc
+++ b/src/google/protobuf/preserve_unknown_enum_test.cc
@@ -28,12 +28,12 @@
 // (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/unittest.pb.h>
-#include <google/protobuf/unittest_preserve_unknown_enum.pb.h>
-#include <google/protobuf/unittest_preserve_unknown_enum2.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_preserve_unknown_enum.pb.h"
+#include "google/protobuf/unittest_preserve_unknown_enum2.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/proto3_arena_lite_unittest.cc b/src/google/protobuf/proto3_arena_lite_unittest.cc
index 06b8d08..acff0ac 100644
--- a/src/google/protobuf/proto3_arena_lite_unittest.cc
+++ b/src/google/protobuf/proto3_arena_lite_unittest.cc
@@ -32,10 +32,9 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/unittest_proto3_arena.pb.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/arena.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/unittest_proto3_arena.pb.h"
 
 using proto3_arena_unittest::TestAllTypes;
 
diff --git a/src/google/protobuf/proto3_arena_unittest.cc b/src/google/protobuf/proto3_arena_unittest.cc
index cfbe198..1d72734 100644
--- a/src/google/protobuf/proto3_arena_unittest.cc
+++ b/src/google/protobuf/proto3_arena_unittest.cc
@@ -32,18 +32,17 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_proto3_arena.pb.h>
-#include <google/protobuf/unittest_proto3_optional.pb.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/arena.h"
+#include "google/protobuf/text_format.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/test_util.h>
+#include "absl/strings/match.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_proto3_arena.pb.h"
+#include "google/protobuf/unittest_proto3_optional.pb.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 using proto3_arena_unittest::ForeignMessage;
 using proto3_arena_unittest::TestAllTypes;
@@ -297,7 +296,7 @@
 
   for (int i = 0; i < d->field_count(); i++) {
     const FieldDescriptor* f = d->field(i);
-    if (HasPrefixString(f->name(), "singular")) {
+    if (absl::StartsWith(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();
diff --git a/src/google/protobuf/proto3_lite_unittest.cc b/src/google/protobuf/proto3_lite_unittest.cc
index abeeedb..e3012db 100644
--- a/src/google/protobuf/proto3_lite_unittest.cc
+++ b/src/google/protobuf/proto3_lite_unittest.cc
@@ -28,13 +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.
 
-#include <google/protobuf/unittest_proto3.pb.h>
+#include "google/protobuf/unittest_proto3.pb.h"
 
 #define LITE_TEST_NAME Proto3LiteTest
 #define UNITTEST ::proto3_unittest
 
 // Must include after the above macros.
-#include <google/protobuf/proto3_lite_unittest.inc>
+#include "google/protobuf/proto3_lite_unittest.inc"
 
 // Make extract script happy.
 namespace google {
diff --git a/src/google/protobuf/proto3_lite_unittest.inc b/src/google/protobuf/proto3_lite_unittest.inc
index 5878163..a60bb68 100644
--- a/src/google/protobuf/proto3_lite_unittest.inc
+++ b/src/google/protobuf/proto3_lite_unittest.inc
@@ -32,8 +32,7 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/arena.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/arena.h"
 #include <gtest/gtest.h>
 
 using UNITTEST::TestAllTypes;
diff --git a/src/google/protobuf/reflection.h b/src/google/protobuf/reflection.h
index 7b75a43..df9e5a7 100644
--- a/src/google/protobuf/reflection.h
+++ b/src/google/protobuf/reflection.h
@@ -36,15 +36,15 @@
 
 #include <memory>
 
-#include <google/protobuf/message.h>
-#include <google/protobuf/generated_enum_util.h>
+#include "google/protobuf/message.h"
+#include "google/protobuf/generated_enum_util.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -565,6 +565,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_REFLECTION_H__
diff --git a/src/google/protobuf/reflection_internal.h b/src/google/protobuf/reflection_internal.h
index f749c3e..5e2cfa0 100644
--- a/src/google/protobuf/reflection_internal.h
+++ b/src/google/protobuf/reflection_internal.h
@@ -31,9 +31,10 @@
 #ifndef GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
 #define GOOGLE_PROTOBUF_REFLECTION_INTERNAL_H__
 
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/reflection.h>
-#include <google/protobuf/repeated_field.h>
+#include "absl/strings/cord.h"
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/reflection.h"
+#include "google/protobuf/repeated_field.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/reflection_ops.cc b/src/google/protobuf/reflection_ops.cc
index 3a1972e..0ef6c9a 100644
--- a/src/google/protobuf/reflection_ops.cc
+++ b/src/google/protobuf/reflection_ops.cc
@@ -31,21 +31,22 @@
 // Author: kenton@google.com (Kenton Varda)
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
-#include <google/protobuf/reflection_ops.h>
+#include "google/protobuf/reflection_ops.h"
 
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/map_field_inl.h>
-#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/unknown_field_set.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -374,7 +375,7 @@
   }
   if (index != -1) {
     result.append("[");
-    result.append(StrCat(index));
+    result.append(absl::StrCat(index));
     result.append("]");
   }
   result.append(".");
@@ -456,4 +457,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/reflection_ops.h b/src/google/protobuf/reflection_ops.h
index 0a45702..b6f1bd2 100644
--- a/src/google/protobuf/reflection_ops.h
+++ b/src/google/protobuf/reflection_ops.h
@@ -38,15 +38,15 @@
 #ifndef GOOGLE_PROTOBUF_REFLECTION_OPS_H__
 #define GOOGLE_PROTOBUF_REFLECTION_OPS_H__
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/message.h>
+#include "google/protobuf/message.h"
+#include "google/protobuf/port.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +63,8 @@
 // This class is really a namespace that contains only static methods.
 class PROTOBUF_EXPORT ReflectionOps {
  public:
+  ReflectionOps() = delete;
+
   static void Copy(const Message& from, Message* to);
   static void Merge(const Message& from, Message* to);
   static void Clear(Message* message);
@@ -77,16 +79,12 @@
   static void FindInitializationErrors(const Message& message,
                                        const std::string& prefix,
                                        std::vector<std::string>* errors);
-
- private:
-  // All methods are static.  No need to construct.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionOps);
 };
 
 }  // namespace internal
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_REFLECTION_OPS_H__
diff --git a/src/google/protobuf/reflection_ops_unittest.cc b/src/google/protobuf/reflection_ops_unittest.cc
index 513ce47..6f46109 100644
--- a/src/google/protobuf/reflection_ops_unittest.cc
+++ b/src/google/protobuf/reflection_ops_unittest.cc
@@ -32,17 +32,16 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/reflection_ops.h>
+#include "google/protobuf/reflection_ops.h"
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/descriptor.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/test_util.h>
+#include "absl/strings/str_join.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
 
-#include <google/protobuf/stubs/strutil.h>
 
 namespace google {
 namespace protobuf {
@@ -460,7 +459,7 @@
 static std::string FindInitializationErrors(const Message& message) {
   std::vector<std::string> errors;
   ReflectionOps::FindInitializationErrors(message, "", &errors);
-  return Join(errors, ",");
+  return absl::StrJoin(errors, ",");
 }
 
 TEST(ReflectionOpsTest, FindInitializationErrors) {
diff --git a/src/google/protobuf/reflection_tester.cc b/src/google/protobuf/reflection_tester.cc
index 4c6db03..23084dc 100644
--- a/src/google/protobuf/reflection_tester.cc
+++ b/src/google/protobuf/reflection_tester.cc
@@ -28,14 +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.
 
-#include <google/protobuf/reflection_tester.h>
+#include "google/protobuf/reflection_tester.h"
 
 #include <gtest/gtest.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/message.h>
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/message.h"
 
 // Must include last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -1670,4 +1670,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/reflection_tester.h b/src/google/protobuf/reflection_tester.h
index 3a2dc81..7a124af 100644
--- a/src/google/protobuf/reflection_tester.h
+++ b/src/google/protobuf/reflection_tester.h
@@ -31,10 +31,10 @@
 #ifndef GOOGLE_PROTOBUF_REFLECTION_TESTER_H__
 #define GOOGLE_PROTOBUF_REFLECTION_TESTER_H__
 
-#include <google/protobuf/message.h>
+#include "google/protobuf/message.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -117,6 +117,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_REFLECTION_TESTER_H__
diff --git a/src/google/protobuf/repeated_field.cc b/src/google/protobuf/repeated_field.cc
index 7264d0a..ebafc9b 100644
--- a/src/google/protobuf/repeated_field.cc
+++ b/src/google/protobuf/repeated_field.cc
@@ -32,15 +32,17 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/repeated_field.h>
+#include "google/protobuf/repeated_field.h"
 
 #include <algorithm>
+#include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/cord.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -53,7 +55,6 @@
 template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedField<uint64_t>;
 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 internal {
 template class PROTOBUF_EXPORT_TEMPLATE_DEFINE RepeatedIterator<bool>;
@@ -68,4 +69,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/repeated_field.h b/src/google/protobuf/repeated_field.h
index 3fb734e..bc70129 100644
--- a/src/google/protobuf/repeated_field.h
+++ b/src/google/protobuf/repeated_field.h
@@ -52,16 +52,17 @@
 #include <type_traits>
 #include <utility>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/repeated_ptr_field.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/repeated_ptr_field.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -94,60 +95,41 @@
 constexpr int kRepeatedFieldUpperClampLimit =
     (std::numeric_limits<int>::max() / 2) + 1;
 
-template <typename Iter>
-inline int CalculateReserve(Iter begin, Iter end, std::forward_iterator_tag) {
-  return static_cast<int>(std::distance(begin, end));
-}
-
-template <typename Iter>
-inline int CalculateReserve(Iter /*begin*/, Iter /*end*/,
-                            std::input_iterator_tag /*unused*/) {
-  return -1;
-}
-
-template <typename Iter>
-inline int CalculateReserve(Iter begin, Iter end) {
-  typedef typename std::iterator_traits<Iter>::iterator_category Category;
-  return CalculateReserve(begin, end, Category());
-}
-
-// Swaps two blocks of memory of size sizeof(T).
-template <typename T>
-inline void SwapBlock(char* p, char* q) {
-  T tmp;
-  memcpy(&tmp, p, sizeof(T));
-  memcpy(p, q, sizeof(T));
-  memcpy(q, &tmp, sizeof(T));
-}
-
 // Swaps two blocks of memory of size kSize:
-//  template <int kSize> void memswap(char* p, char* q);
-template <int kSize>
-inline typename std::enable_if<(kSize == 0), void>::type memswap(char*, char*) {
-}
-
-#define PROTO_MEMSWAP_DEF_SIZE(reg_type, max_size)                           \
-  template <int kSize>                                                       \
-  typename std::enable_if<(kSize >= sizeof(reg_type) && kSize < (max_size)), \
-                          void>::type                                        \
-  memswap(char* p, char* q) {                                                \
-    SwapBlock<reg_type>(p, q);                                               \
-    memswap<kSize - sizeof(reg_type)>(p + sizeof(reg_type),                  \
-                                      q + sizeof(reg_type));                 \
-  }
-
-PROTO_MEMSWAP_DEF_SIZE(uint8_t, 2)
-PROTO_MEMSWAP_DEF_SIZE(uint16_t, 4)
-PROTO_MEMSWAP_DEF_SIZE(uint32_t, 8)
-
-#ifdef __SIZEOF_INT128__
-PROTO_MEMSWAP_DEF_SIZE(uint64_t, 16)
-PROTO_MEMSWAP_DEF_SIZE(__uint128_t, (1u << 31))
+template <size_t kSize>
+void memswap(char* a, char* b) {
+#if __SIZEOF_INT128__
+  using Buffer = __uint128_t;
 #else
-PROTO_MEMSWAP_DEF_SIZE(uint64_t, (1u << 31))
+  using Buffer = uint64_t;
 #endif
 
-#undef PROTO_MEMSWAP_DEF_SIZE
+  constexpr size_t kBlockSize = sizeof(Buffer);
+  Buffer buf;
+  for (size_t i = 0; i < kSize / kBlockSize; ++i) {
+    memcpy(&buf, a, kBlockSize);
+    memcpy(a, b, kBlockSize);
+    memcpy(b, &buf, kBlockSize);
+    a += kBlockSize;
+    b += kBlockSize;
+  }
+
+#if defined(__GNUC__) && !defined(__clang__)
+  // Workaround GCC bug: https://gcc.gnu.org/bugzilla/show_bug.cgi?id=99578
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wpragmas"
+#pragma GCC diagnostic ignored "-Wstringop-overflow"
+#endif  // __GNUC__
+
+  // Swap the leftover bytes, could be zero.
+  memcpy(&buf, a, kSize % kBlockSize);
+  memcpy(a, b, kSize % kBlockSize);
+  memcpy(b, &buf, kSize % kBlockSize);
+
+#if defined(__GNUC__) && !defined(__clang__)
+#pragma GCC diagnostic pop
+#endif  // GCC
+}
 
 template <typename Element>
 class RepeatedIterator;
@@ -246,16 +228,10 @@
   Element* mutable_data();
   const Element* data() const;
 
-  // Swaps entire contents with "other". If they are separate arenas then,
+  // Swaps entire contents with "other". If they are separate arenas, then
   // copies data between each other.
   void Swap(RepeatedField* other);
 
-  // Swaps entire contents with "other". Should be called only if the caller can
-  // guarantee that both repeated fields are on the same arena or are on the
-  // heap. Swapping between different arenas is disallowed and caught by a
-  // GOOGLE_DCHECK (see API docs for details).
-  void UnsafeArenaSwap(RepeatedField* other);
-
   // Swaps two elements.
   void SwapElements(int index1, int index2);
 
@@ -313,8 +289,14 @@
   iterator erase(const_iterator first, const_iterator last);
 
   // Gets the Arena on which this RepeatedField stores its elements.
+  // Message-owned arenas are not exposed by this method, which will return
+  // nullptr for messages owned by MOAs.
   inline Arena* GetArena() const {
-    return GetOwningArena();
+    Arena* arena = GetOwningArena();
+    if (arena == nullptr || arena->InternalIsMessageOwnedArena()) {
+      return nullptr;
+    }
+    return arena;
   }
 
   // For internal use only.
@@ -322,6 +304,7 @@
   // This is public due to it being called by generated code.
   inline void InternalSwap(RepeatedField* other);
 
+
  private:
   template <typename T> friend class Arena::InternalHelper;
 
@@ -331,6 +314,12 @@
                               : rep()->arena;
   }
 
+  // Swaps entire contents with "other". Should be called only if the caller can
+  // guarantee that both repeated fields are on the same arena or are on the
+  // heap. Swapping between different arenas is disallowed and caught by a
+  // GOOGLE_DCHECK (see API docs for details).
+  void UnsafeArenaSwap(RepeatedField* other);
+
   static constexpr int kInitialSize = 0;
   // A note on the representation here (see also comment below for
   // RepeatedPtrFieldBase's struct Rep):
@@ -344,6 +333,16 @@
   // RepeatedField class to avoid costly cache misses due to the indirection.
   int current_size_;
   int total_size_;
+
+  // Replaces current_size_ with new_size and returns the previous value of
+  // current_size_. This function is intended to be the only place where
+  // current_size_ is modified.
+  inline int ExchangeCurrentSize(int new_size) {
+    const int prev_size = current_size_;
+    current_size_ = new_size;
+    return prev_size;
+  }
+
   // Pad the Rep after arena allow for power-of-two byte sizes when
   // sizeof(Element) > sizeof(Arena*). eg for 16-byte objects.
   static PROTOBUF_CONSTEXPR const size_t kRepHeaderSize =
@@ -356,6 +355,7 @@
     }
   };
 
+
   // 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
   // the arena pointer without an extra allocation in the constructor.
@@ -448,8 +448,13 @@
   //
   // Typically, due to the fact that 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
+  // 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 executes at only 1 or 2 cycles.
@@ -461,7 +466,11 @@
       capacity_ = repeated_field_->total_size_;
       buffer_ = repeated_field_->unsafe_elements();
     }
-    ~FastAdderImpl() { repeated_field_->current_size_ = index_; }
+    FastAdderImpl(const FastAdderImpl&) = delete;
+    FastAdderImpl& operator=(const FastAdderImpl&) = delete;
+    ~FastAdderImpl() {
+      repeated_field_->current_size_ = index_;
+    }
 
     void Add(Element val) {
       if (index_ == capacity_) {
@@ -478,8 +487,6 @@
     int index_;
     int capacity_;
     Element* buffer_;
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl);
   };
 
   // FastAdder is a wrapper for adding fields. The specialization above handles
@@ -488,11 +495,12 @@
   class FastAdderImpl<I, false> {
    public:
     explicit FastAdderImpl(RepeatedField* rf) : repeated_field_(rf) {}
+    FastAdderImpl(const FastAdderImpl&) = delete;
+    FastAdderImpl& operator=(const FastAdderImpl&) = delete;
     void Add(const Element& val) { repeated_field_->Add(val); }
 
    private:
     RepeatedField* repeated_field_;
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastAdderImpl);
   };
 
   using FastAdder = FastAdderImpl<>;
@@ -616,13 +624,13 @@
 template <typename Element>
 inline void RepeatedField<Element>::AddAlreadyReserved(const Element& value) {
   GOOGLE_DCHECK_LT(current_size_, total_size_);
-  elements()[current_size_++] = value;
+  elements()[ExchangeCurrentSize(current_size_ + 1)] = value;
 }
 
 template <typename Element>
 inline Element* RepeatedField<Element>::AddAlreadyReserved() {
   GOOGLE_DCHECK_LT(current_size_, total_size_);
-  return &elements()[current_size_++];
+  return &elements()[ExchangeCurrentSize(current_size_ + 1)];
 }
 
 template <typename Element>
@@ -633,9 +641,7 @@
   // total_size_ == 0. In this case the return pointer points to a zero size
   // array (n == 0). Hence we can just use unsafe_elements(), because the user
   // cannot dereference the pointer anyway.
-  Element* ret = unsafe_elements() + current_size_;
-  current_size_ += elements;
-  return ret;
+  return unsafe_elements() + ExchangeCurrentSize(current_size_ + elements);
 }
 
 template <typename Element>
@@ -643,9 +649,11 @@
   GOOGLE_DCHECK_GE(new_size, 0);
   if (new_size > current_size_) {
     Reserve(new_size);
-    std::fill(&elements()[current_size_], &elements()[new_size], value);
+    std::fill(&elements()[ExchangeCurrentSize(new_size)], &elements()[new_size],
+              value);
+  } else {
+    ExchangeCurrentSize(new_size);
   }
-  current_size_ = new_size;
 }
 
 template <typename Element>
@@ -685,46 +693,41 @@
 
 template <typename Element>
 inline void RepeatedField<Element>::Add(const Element& value) {
-  uint32_t size = current_size_;
-  if (static_cast<int>(size) == total_size_) {
+  if (current_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);
+    elements()[ExchangeCurrentSize(current_size_ + 1)] = std::move(tmp);
   } else {
-    elements()[size] = value;
+    elements()[ExchangeCurrentSize(current_size_ + 1)] = value;
   }
-  current_size_ = size + 1;
 }
 
 template <typename Element>
 inline Element* RepeatedField<Element>::Add() {
-  uint32_t size = current_size_;
-  if (static_cast<int>(size) == total_size_) Reserve(total_size_ + 1);
-  auto ptr = &elements()[size];
-  current_size_ = size + 1;
-  return ptr;
+  if (current_size_ == total_size_) Reserve(total_size_ + 1);
+  return &elements()[ExchangeCurrentSize(current_size_ + 1)];
 }
 
 template <typename Element>
 template <typename Iter>
 inline void RepeatedField<Element>::Add(Iter begin, Iter end) {
-  int reserve = internal::CalculateReserve(begin, end);
-  if (reserve != -1) {
-    if (reserve == 0) {
-      return;
-    }
+  if (std::is_base_of<
+          std::forward_iterator_tag,
+          typename std::iterator_traits<Iter>::iterator_category>::value) {
+    int additional = static_cast<int>(std::distance(begin, end));
+    if (additional == 0) return;
 
-    Reserve(reserve + size());
+    int new_size = current_size_ + additional;
+    Reserve(new_size);
     // TODO(ckennelly):  The compiler loses track of the buffer freshly
     // allocated by Reserve() by the time we call elements, so it cannot
     // guarantee that elements does not alias [begin(), end()).
     //
     // If restrict is available, annotating the pointer obtained from elements()
     // causes this to lower to memcpy instead of memmove.
-    std::copy(begin, end, elements() + size());
-    current_size_ = reserve + size();
+    std::copy(begin, end, elements() + ExchangeCurrentSize(new_size));
   } else {
     FastAdder fast_adder(this);
     for (; begin != end; ++begin) fast_adder.Add(*begin);
@@ -734,7 +737,7 @@
 template <typename Element>
 inline void RepeatedField<Element>::RemoveLast() {
   GOOGLE_DCHECK_GT(current_size_, 0);
-  current_size_--;
+  ExchangeCurrentSize(current_size_ - 1);
 }
 
 template <typename Element>
@@ -759,7 +762,7 @@
 
 template <typename Element>
 inline void RepeatedField<Element>::Clear() {
-  current_size_ = 0;
+  ExchangeCurrentSize(0);
 }
 
 template <typename Element>
@@ -980,7 +983,7 @@
 inline void RepeatedField<Element>::Truncate(int new_size) {
   GOOGLE_DCHECK_LE(new_size, current_size_);
   if (current_size_ > 0) {
-    current_size_ = new_size;
+    ExchangeCurrentSize(new_size);
   }
 }
 
@@ -1214,6 +1217,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_REPEATED_FIELD_H__
diff --git a/src/google/protobuf/repeated_field_reflection_unittest.cc b/src/google/protobuf/repeated_field_reflection_unittest.cc
index 25e8200..f86ac0b 100644
--- a/src/google/protobuf/repeated_field_reflection_unittest.cc
+++ b/src/google/protobuf/repeated_field_reflection_unittest.cc
@@ -33,25 +33,27 @@
 // Test reflection methods for aggregate access to Repeated[Ptr]Fields.
 // This test proto2 methods on a proto2 layout.
 
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/reflection.h>
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/reflection.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/test_util.h>
+#include "absl/base/casts.h"
+#include "absl/strings/cord.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
 
 namespace google {
 namespace protobuf {
+namespace {
 
+using internal::DownCast;
 using unittest::ForeignMessage;
 using unittest::TestAllExtensions;
 using unittest::TestAllTypes;
 
-namespace {
-
 static int Func(int i, int j) { return i * j; }
 
-static std::string StrFunc(int i, int j) { return StrCat(Func(i, 4)); }
+static std::string StrFunc(int i, int j) { return absl::StrCat(Func(i, 4)); }
 
 TEST(RepeatedFieldReflectionTest, RegularFields) {
   TestAllTypes message;
@@ -113,7 +115,7 @@
     EXPECT_EQ(rf_double.Get(i), Func(i, 2));
     EXPECT_EQ(rpf_string.Get(i), StrFunc(i, 5));
     EXPECT_EQ(rpf_foreign_message.Get(i).c(), Func(i, 6));
-    EXPECT_EQ(down_cast<const ForeignMessage*>(&rpf_message.Get(i))->c(),
+    EXPECT_EQ(DownCast<const ForeignMessage*>(&rpf_message.Get(i))->c(),
               Func(i, 6));
 
     // Check gets through mutable objects.
@@ -121,7 +123,7 @@
     EXPECT_EQ(mrf_double->Get(i), Func(i, 2));
     EXPECT_EQ(mrpf_string->Get(i), StrFunc(i, 5));
     EXPECT_EQ(mrpf_foreign_message->Get(i).c(), Func(i, 6));
-    EXPECT_EQ(down_cast<const ForeignMessage*>(&mrpf_message->Get(i))->c(),
+    EXPECT_EQ(DownCast<const ForeignMessage*>(&mrpf_message->Get(i))->c(),
               Func(i, 6));
 
     // Check sets through mutable objects.
@@ -133,7 +135,7 @@
     EXPECT_EQ(message.repeated_double(i), Func(i, -2));
     EXPECT_EQ(message.repeated_string(i), StrFunc(i, -5));
     EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, -6));
-    down_cast<ForeignMessage*>(mrpf_message->Mutable(i))->set_c(Func(i, 7));
+    DownCast<ForeignMessage*>(mrpf_message->Mutable(i))->set_c(Func(i, 7));
     EXPECT_EQ(message.repeated_foreign_message(i).c(), Func(i, 7));
   }
 
@@ -293,7 +295,7 @@
     ForeignMessage scratch_space;
     EXPECT_EQ(rf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6));
     EXPECT_EQ(
-        down_cast<const ForeignMessage&>(rf_message.Get(i, &scratch_space)).c(),
+        DownCast<const ForeignMessage&>(rf_message.Get(i, &scratch_space)).c(),
         Func(i, 6));
 
     // Check gets through mutable objects.
@@ -302,8 +304,7 @@
     EXPECT_EQ(mrf_string.Get(i), StrFunc(i, 5));
     EXPECT_EQ(mrf_foreign_message.Get(i, &scratch_space).c(), Func(i, 6));
     EXPECT_EQ(
-        down_cast<const ForeignMessage&>(mrf_message.Get(i, &scratch_space))
-            .c(),
+        DownCast<const ForeignMessage&>(mrf_message.Get(i, &scratch_space)).c(),
         Func(i, 6));
 
     // Check sets through mutable objects.
diff --git a/src/google/protobuf/repeated_field_unittest.cc b/src/google/protobuf/repeated_field_unittest.cc
index d8a82bf..4906cdd 100644
--- a/src/google/protobuf/repeated_field_unittest.cc
+++ b/src/google/protobuf/repeated_field_unittest.cc
@@ -35,7 +35,7 @@
 // TODO(kenton):  Improve this unittest to bring it up to the standards of
 //   other proto2 unittests.
 
-#include <google/protobuf/repeated_field.h>
+#include "google/protobuf/repeated_field.h"
 
 #include <algorithm>
 #include <cstdlib>
@@ -47,17 +47,18 @@
 #include <type_traits>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 #include <gmock/gmock.h>
-#include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/numeric/bits.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/unittest.pb.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -179,7 +180,7 @@
         // Must be `>= 16`, as expected by the Arena.
         ASSERT_GE(last_alloc, 16);
         // Must be of a power of two.
-        size_t log2 = Bits::Log2FloorNonZero64(last_alloc);
+        size_t log2 = absl::bit_width(last_alloc) - 1;
         ASSERT_EQ((1 << log2), last_alloc);
       }
 
@@ -305,6 +306,60 @@
   }
 }
 
+template <int kSize>
+void TestMemswap() {
+  SCOPED_TRACE(kSize);
+
+  const auto a_char = [](int i) -> char { return (i % ('z' - 'a')) + 'a'; };
+  const auto b_char = [](int i) -> char { return (i % ('Z' - 'A')) + 'A'; };
+  std::string a, b;
+  for (int i = 0; i < kSize; ++i) {
+    a += a_char(i);
+    b += b_char(i);
+  }
+  // We will not swap these.
+  a += "+";
+  b += "-";
+
+  std::string expected_a = b, expected_b = a;
+  expected_a.back() = '+';
+  expected_b.back() = '-';
+
+  internal::memswap<kSize>(&a[0], &b[0]);
+
+  // ODR use the functions in a way that forces the linker to keep them. That
+  // way we can see their generated code.
+  volatile auto odr_use_for_asm_dump = &internal::memswap<kSize>;
+  (void)odr_use_for_asm_dump;
+
+  EXPECT_EQ(expected_a, a);
+  EXPECT_EQ(expected_b, b);
+}
+
+TEST(Memswap, VerifyWithSmallAndLargeSizes) {
+  // Arbitrary sizes
+  TestMemswap<0>();
+  TestMemswap<1>();
+  TestMemswap<10>();
+  TestMemswap<100>();
+  TestMemswap<1000>();
+  TestMemswap<10000>();
+  TestMemswap<100000>();
+  TestMemswap<1000000>();
+
+  // Pointer aligned sizes
+  TestMemswap<sizeof(void*) * 1>();
+  TestMemswap<sizeof(void*) * 7>();
+  TestMemswap<sizeof(void*) * 17>();
+  TestMemswap<sizeof(void*) * 27>();
+
+  // Test also just the block size and no leftover.
+  TestMemswap<64 * 1>();
+  TestMemswap<64 * 2>();
+  TestMemswap<64 * 3>();
+  TestMemswap<64 * 4>();
+}
+
 // Determines how much space was reserved by the given field by adding elements
 // to it until it re-allocates its space.
 static int ReservedSpace(RepeatedField<int>* field) {
@@ -374,14 +429,14 @@
 
 TEST(RepeatedField, ReserveLowerClamp) {
   int clamped_value = internal::CalculateReserveSize<bool, sizeof(void*)>(0, 1);
-  EXPECT_GE(clamped_value, 8 / sizeof(bool));
+  EXPECT_GE(clamped_value, sizeof(void*) / sizeof(bool));
   EXPECT_EQ((internal::RepeatedFieldLowerClampLimit<bool, sizeof(void*)>()),
             clamped_value);
   // EXPECT_EQ(clamped_value, (internal::CalculateReserveSize<bool,
   // sizeof(void*)>( clamped_value, 2)));
 
   clamped_value = internal::CalculateReserveSize<int, sizeof(void*)>(0, 1);
-  EXPECT_GE(clamped_value, 8 / sizeof(int));
+  EXPECT_GE(clamped_value, sizeof(void*) / sizeof(int));
   EXPECT_EQ((internal::RepeatedFieldLowerClampLimit<int, sizeof(void*)>()),
             clamped_value);
   // EXPECT_EQ(clamped_value, (internal::CalculateReserveSize<int,
@@ -588,14 +643,16 @@
 // an input iterator.
 TEST(RepeatedField, AddRange5) {
   RepeatedField<int> me;
+  me.Add(0);
 
   std::stringstream ss;
   ss << 1 << ' ' << 2;
 
   me.Add(std::istream_iterator<int>(ss), std::istream_iterator<int>());
-  ASSERT_EQ(me.size(), 2);
-  ASSERT_EQ(me.Get(0), 1);
-  ASSERT_EQ(me.Get(1), 2);
+  ASSERT_EQ(me.size(), 3);
+  ASSERT_EQ(me.Get(0), 0);
+  ASSERT_EQ(me.Get(1), 1);
+  ASSERT_EQ(me.Get(2), 2);
 }
 
 TEST(RepeatedField, AddAndAssignRanges) {
@@ -1258,7 +1315,7 @@
 
   field.Clear();
   EXPECT_EQ(field.ClearedCount(), 2);
-#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES
+#ifndef PROTOBUF_FUTURE_REMOVE_CLEARED_API
   EXPECT_EQ(field.ReleaseCleared(), original);  // Take ownership again.
   EXPECT_EQ(field.ClearedCount(), 1);
   EXPECT_NE(field.Add(), original);
@@ -1270,7 +1327,7 @@
   EXPECT_EQ(field.ClearedCount(), 1);
   EXPECT_EQ(field.Add(), original);
   EXPECT_EQ(field.ClearedCount(), 0);
-#endif  // !PROTOBUF_FUTURE_BREAKING_CHANGES
+#endif  // !PROTOBUF_FUTURE_REMOVE_CLEARED_API
 }
 
 // Test all code paths in AddAllocated().
@@ -1642,7 +1699,8 @@
           // Create an array with "sz" elements and "extra" cleared elements.
           // Use an arena to avoid copies from debug-build stability checks.
           Arena arena;
-          RepeatedPtrField<std::string> field(&arena);
+          auto& field =
+              *Arena::CreateMessage<RepeatedPtrField<std::string>>(&arena);
           for (int i = 0; i < sz + extra; ++i) {
             subject.push_back(new std::string());
             field.AddAllocated(subject[i]);
@@ -2277,11 +2335,11 @@
   TestAllTypes goldenproto;
   for (int i = 0; i < 10; ++i) {
     std::string* new_data = new std::string;
-    *new_data = "name-" + StrCat(i);
+    *new_data = "name-" + absl::StrCat(i);
     data.push_back(new_data);
 
     new_data = goldenproto.add_repeated_string();
-    *new_data = "name-" + StrCat(i);
+    *new_data = "name-" + absl::StrCat(i);
   }
   TestAllTypes testproto;
   std::copy(data.begin(), data.end(),
@@ -2314,7 +2372,7 @@
   auto* goldenproto = Arena::CreateMessage<TestAllTypes>(&arena);
   for (int i = 0; i < 10; ++i) {
     auto* new_data = goldenproto->add_repeated_string();
-    *new_data = "name-" + StrCat(i);
+    *new_data = "name-" + absl::StrCat(i);
     data.push_back(new_data);
   }
   auto* testproto = Arena::CreateMessage<TestAllTypes>(&arena);
@@ -2360,4 +2418,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/repeated_ptr_field.cc b/src/google/protobuf/repeated_ptr_field.cc
index 8e86727..1661474 100644
--- a/src/google/protobuf/repeated_ptr_field.cc
+++ b/src/google/protobuf/repeated_ptr_field.cc
@@ -34,14 +34,14 @@
 
 #include <algorithm>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/implicit_weak_message.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/port.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/implicit_weak_message.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -116,7 +116,7 @@
     InternalExtend(1);  // Equivalent to "Reserve(total_size_ + 1)"
   }
   ++rep_->allocated_size;
-  rep_->elements[current_size_++] = obj;
+  rep_->elements[ExchangeCurrentSize(current_size_ + 1)] = obj;
   return obj;
 }
 
@@ -125,13 +125,14 @@
   // Close up a gap of "num" elements starting at offset "start".
   for (int i = start + num; i < rep_->allocated_size; ++i)
     rep_->elements[i - num] = rep_->elements[i];
-  current_size_ -= num;
+  ExchangeCurrentSize(current_size_ - num);
   rep_->allocated_size -= num;
 }
 
 MessageLite* RepeatedPtrFieldBase::AddWeak(const MessageLite* prototype) {
   if (rep_ != nullptr && current_size_ < rep_->allocated_size) {
-    return reinterpret_cast<MessageLite*>(rep_->elements[current_size_++]);
+    return reinterpret_cast<MessageLite*>(
+        rep_->elements[ExchangeCurrentSize(current_size_ + 1)]);
   }
   if (!rep_ || rep_->allocated_size == total_size_) {
     Reserve(total_size_ + 1);
@@ -140,7 +141,7 @@
   MessageLite* result = prototype
                             ? prototype->New(arena_)
                             : Arena::CreateMessage<ImplicitWeakMessage>(arena_);
-  rep_->elements[current_size_++] = result;
+  rep_->elements[ExchangeCurrentSize(current_size_ + 1)] = result;
   return result;
 }
 
@@ -149,4 +150,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/repeated_ptr_field.h b/src/google/protobuf/repeated_ptr_field.h
index 401230b..8d3a310 100644
--- a/src/google/protobuf/repeated_ptr_field.h
+++ b/src/google/protobuf/repeated_ptr_field.h
@@ -58,15 +58,16 @@
 #include <string>
 #include <type_traits>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/port.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -210,7 +211,8 @@
   typename TypeHandler::Type* Add(
       const typename TypeHandler::Type* prototype = nullptr) {
     if (rep_ != nullptr && current_size_ < rep_->allocated_size) {
-      return cast<TypeHandler>(rep_->elements[current_size_++]);
+      return cast<TypeHandler>(
+          rep_->elements[ExchangeCurrentSize(current_size_ + 1)]);
     }
     typename TypeHandler::Type* result =
         TypeHandler::NewFromPrototype(prototype, arena_);
@@ -223,7 +225,9 @@
       typename std::enable_if<TypeHandler::Movable::value>::type* = nullptr>
   inline void Add(typename TypeHandler::Type&& value) {
     if (rep_ != nullptr && current_size_ < rep_->allocated_size) {
-      *cast<TypeHandler>(rep_->elements[current_size_++]) = std::move(value);
+      *cast<TypeHandler>(
+          rep_->elements[ExchangeCurrentSize(current_size_ + 1)]) =
+          std::move(value);
       return;
     }
     if (!rep_ || rep_->allocated_size == total_size_) {
@@ -232,7 +236,7 @@
     ++rep_->allocated_size;
     typename TypeHandler::Type* result =
         TypeHandler::New(arena_, std::move(value));
-    rep_->elements[current_size_++] = result;
+    rep_->elements[ExchangeCurrentSize(current_size_ + 1)] = result;
   }
 
   template <typename TypeHandler>
@@ -283,12 +287,7 @@
     const int n = current_size_;
     GOOGLE_DCHECK_GE(n, 0);
     if (n > 0) {
-      void* const* elements = rep_->elements;
-      int i = 0;
-      do {
-        TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
-      } while (i < n);
-      current_size_ = 0;
+      ClearNonEmpty<TypeHandler>();
     }
   }
 
@@ -317,11 +316,40 @@
     std::tie(arena_, current_size_, total_size_, rep_) = temp;
   }
 
+  // Prepares the container for adding elements via `AddAllocatedForParse`.
+  // It ensures some invariants to avoid checking then in the Add loop:
+  //  - rep_ is not null.
+  //  - there are no preallocated elements.
+  //  Returns true if the invariants hold and `AddAllocatedForParse` can be
+  //  used.
+  bool PrepareForParse() {
+    if (current_size_ == total_size_) {
+      InternalExtend(1);
+    }
+    return rep_->allocated_size == current_size_;
+  }
+
+  // Similar to `AddAllocated` but faster.
+  // Can only be invoked after a call to `PrepareForParse` that returned `true`,
+  // or other calls to `AddAllocatedForParse`.
+  template <typename TypeHandler>
+  void AddAllocatedForParse(typename TypeHandler::Type* value) {
+    PROTOBUF_ASSUME(rep_ != nullptr);
+    PROTOBUF_ASSUME(current_size_ == rep_->allocated_size);
+    if (current_size_ == total_size_) {
+      // The array is completely full with no cleared objects, so grow it.
+      InternalExtend(1);
+    }
+    rep_->elements[current_size_++] = value;
+    ++rep_->allocated_size;
+  }
+
  protected:
   template <typename TypeHandler>
   void RemoveLast() {
     GOOGLE_DCHECK_GT(current_size_, 0);
-    TypeHandler::Clear(cast<TypeHandler>(rep_->elements[--current_size_]));
+    ExchangeCurrentSize(current_size_ - 1);
+    TypeHandler::Clear(cast<TypeHandler>(rep_->elements[current_size_]));
   }
 
   template <typename TypeHandler>
@@ -403,7 +431,8 @@
   template <typename TypeHandler>
   typename TypeHandler::Type* AddFromCleared() {
     if (rep_ != nullptr && current_size_ < rep_->allocated_size) {
-      return cast<TypeHandler>(rep_->elements[current_size_++]);
+      return cast<TypeHandler>(
+          rep_->elements[ExchangeCurrentSize(current_size_ + 1)]);
     } else {
       return nullptr;
     }
@@ -439,7 +468,7 @@
       ++rep_->allocated_size;
     }
 
-    rep_->elements[current_size_++] = value;
+    rep_->elements[ExchangeCurrentSize(current_size_ + 1)] = value;
   }
 
   template <typename TypeHandler>
@@ -454,8 +483,9 @@
   template <typename TypeHandler>
   typename TypeHandler::Type* UnsafeArenaReleaseLast() {
     GOOGLE_DCHECK_GT(current_size_, 0);
+    ExchangeCurrentSize(current_size_ - 1);
     typename TypeHandler::Type* result =
-        cast<TypeHandler>(rep_->elements[--current_size_]);
+        cast<TypeHandler>(rep_->elements[current_size_]);
     --rep_->allocated_size;
     if (current_size_ < rep_->allocated_size) {
       // There are cleared elements on the end; replace the removed element
@@ -508,8 +538,7 @@
         // allocated list.
         elems[rep_->allocated_size] = elems[current_size_];
       }
-      elems[current_size_] = value;
-      current_size_ = current_size_ + 1;
+      elems[ExchangeCurrentSize(current_size_ + 1)] = value;
       rep_->allocated_size = rep_->allocated_size + 1;
     } else {
       AddAllocatedSlowWithCopy<TypeHandler>(value, element_arena, arena);
@@ -531,8 +560,7 @@
         // allocated list.
         elems[rep_->allocated_size] = elems[current_size_];
       }
-      elems[current_size_] = value;
-      current_size_ = current_size_ + 1;
+      elems[ExchangeCurrentSize(current_size_ + 1)] = value;
       ++rep_->allocated_size;
     } else {
       UnsafeArenaAddAllocated<TypeHandler>(value);
@@ -612,7 +640,16 @@
     temp.Destroy<TypeHandler>();  // Frees rep_ if `other` had no arena.
   }
 
-  inline Arena* GetArena() const { return arena_; }
+  // Gets the Arena on which this RepeatedPtrField stores its elements.
+  // Message-owned arenas are not exposed by this method, which will return
+  // nullptr for messages owned by MOAs.
+  inline Arena* GetArena() const {
+    Arena* arena = GetOwningArena();
+    if (arena == nullptr || arena->InternalIsMessageOwnedArena()) {
+      return nullptr;
+    }
+    return arena;
+  }
 
  protected:
   inline Arena* GetOwningArena() const { return arena_; }
@@ -635,6 +672,16 @@
   Arena* arena_;
   int current_size_;
   int total_size_;
+
+  // Replaces current_size_ with new_size and returns the previous value of
+  // current_size_. This function is intended to be the only place where
+  // current_size_ is modified.
+  inline int ExchangeCurrentSize(int new_size) {
+    int prev_size = current_size_;
+    current_size_ = new_size;
+    return prev_size;
+  }
+
   struct Rep {
     int allocated_size;
     // Here we declare a huge array as a way of approximating C's "flexible
@@ -654,12 +701,26 @@
     return reinterpret_cast<const typename TypeHandler::Type*>(element);
   }
 
+  // Out-of-line helper routine for Clear() once the inlined check has
+  // determined the container is non-empty
+  template <typename TypeHandler>
+  PROTOBUF_NOINLINE void ClearNonEmpty() {
+    const int n = current_size_;
+    void* const* elements = rep_->elements;
+    int i = 0;
+    GOOGLE_DCHECK_GT(n,
+              0);  // do/while loop to avoid initial test because we know n > 0
+    do {
+      TypeHandler::Clear(cast<TypeHandler>(elements[i++]));
+    } while (i < n);
+    ExchangeCurrentSize(0);
+  }
+
   // Non-templated inner function to avoid code duplication. Takes a function
   // pointer to the type-specific (templated) inner allocate/merge loop.
-  void MergeFromInternal(const RepeatedPtrFieldBase& other,
-                         void (RepeatedPtrFieldBase::*inner_loop)(void**,
-                                                                  void**, int,
-                                                                  int)) {
+  PROTOBUF_NOINLINE void MergeFromInternal(
+      const RepeatedPtrFieldBase& other,
+      void (RepeatedPtrFieldBase::*inner_loop)(void**, void**, int, int)) {
     // Note: wrapper has already guaranteed that other.rep_ != nullptr here.
     int other_size = other.current_size_;
     void** other_elements = other.rep_->elements;
@@ -667,7 +728,7 @@
     int allocated_elems = rep_->allocated_size - current_size_;
     (this->*inner_loop)(new_elements, other_elements, other_size,
                         allocated_elems);
-    current_size_ += other_size;
+    ExchangeCurrentSize(current_size_ + other_size);
     if (rep_->allocated_size < current_size_) {
       rep_->allocated_size = current_size_;
     }
@@ -762,7 +823,7 @@
     }
   }
   static inline Arena* GetOwningArena(GenericType* value) {
-    return Arena::GetOwningArena<Type>(value);
+    return Arena::InternalGetOwningArena(value);
   }
 
   static inline void Clear(GenericType* value) { value->Clear(); }
@@ -820,10 +881,10 @@
   typedef std::string Type;
   using Movable = IsMovable<Type>;
 
-  static inline std::string* New(Arena* arena) {
+  static PROTOBUF_NOINLINE std::string* New(Arena* arena) {
     return Arena::Create<std::string>(arena);
   }
-  static inline std::string* New(Arena* arena, std::string&& value) {
+  static PROTOBUF_NOINLINE std::string* New(Arena* arena, std::string&& value) {
     return Arena::Create<std::string>(arena, std::move(value));
   }
   static inline std::string* NewFromPrototype(const std::string*,
@@ -934,10 +995,6 @@
 
   // Gets the underlying array.  This pointer is possibly invalidated by
   // any add or remove operation.
-  //
-  // This API is deprecated. Instead of directly working with element array,
-  // use APIs in repeated_field_util.h; e.g. sorting, etc.
-  PROTOBUF_DEPRECATED_MSG("Use APIs in repeated_field_util.h")
   Element** mutable_data();
   const Element* const* data() const;
 
@@ -1083,7 +1140,7 @@
   // Gets the number of cleared objects that are currently being kept
   // around for reuse.
   int ClearedCount() const;
-#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES
+#ifndef PROTOBUF_FUTURE_REMOVE_CLEARED_API
   // Adds an element to the pool of cleared objects, passing ownership to
   // the RepeatedPtrField.  The element must be cleared prior to calling
   // this method.
@@ -1098,7 +1155,7 @@
   // This method cannot be called when the repeated field is on an arena; doing
   // so will trigger a GOOGLE_DCHECK-failure.
   PROTOBUF_NODISCARD Element* ReleaseCleared();
-#endif  // !PROTOBUF_FUTURE_BREAKING_CHANGES
+#endif  // !PROTOBUF_FUTURE_REMOVE_CLEARED_API
 
   // Removes the element referenced by position.
   //
@@ -1141,7 +1198,12 @@
   void ExtractSubrangeInternal(int start, int num, Element** elements,
                                std::false_type);
 
+  void AddAllocatedForParse(Element* p) {
+    return RepeatedPtrFieldBase::AddAllocatedForParse<TypeHandler>(p);
+  }
+
   friend class Arena;
+  friend class internal::TcParser;
 
   template <typename T>
   friend struct WeakRepeatedPtrField;
@@ -1270,7 +1332,7 @@
 }
 
 template <typename Element>
-inline Element* RepeatedPtrField<Element>::Add() {
+PROTOBUF_NOINLINE Element* RepeatedPtrField<Element>::Add() {
   return RepeatedPtrFieldBase::Add<TypeHandler>();
 }
 
@@ -1285,7 +1347,7 @@
   if (std::is_base_of<
           std::forward_iterator_tag,
           typename std::iterator_traits<Iter>::iterator_category>::value) {
-    int reserve = std::distance(begin, end);
+    int reserve = static_cast<int>(std::distance(begin, end));
     Reserve(size() + reserve);
   }
   for (; begin != end; ++begin) {
@@ -1430,8 +1492,8 @@
 template <typename Element>
 inline typename RepeatedPtrField<Element>::iterator
 RepeatedPtrField<Element>::erase(const_iterator first, const_iterator last) {
-  size_type pos_offset = std::distance(cbegin(), first);
-  size_type last_offset = std::distance(cbegin(), last);
+  size_type pos_offset = static_cast<size_type>(std::distance(cbegin(), first));
+  size_type last_offset = static_cast<size_type>(std::distance(cbegin(), last));
   DeleteSubrange(pos_offset, last_offset - pos_offset);
   return begin() + pos_offset;
 }
@@ -1505,7 +1567,7 @@
   return RepeatedPtrFieldBase::ClearedCount();
 }
 
-#ifndef PROTOBUF_FUTURE_BREAKING_CHANGES
+#ifndef PROTOBUF_FUTURE_REMOVE_CLEARED_API
 template <typename Element>
 inline void RepeatedPtrField<Element>::AddCleared(Element* value) {
   return RepeatedPtrFieldBase::AddCleared<TypeHandler>(value);
@@ -1515,7 +1577,7 @@
 inline Element* RepeatedPtrField<Element>::ReleaseCleared() {
   return RepeatedPtrFieldBase::ReleaseCleared<TypeHandler>();
 }
-#endif  // !PROTOBUF_FUTURE_BREAKING_CHANGES
+#endif  // !PROTOBUF_FUTURE_REMOVE_CLEARED_API
 
 template <typename Element>
 inline void RepeatedPtrField<Element>::Reserve(int new_size) {
@@ -1959,12 +2021,9 @@
       mutable_field);
 }
 
-extern template class PROTOBUF_EXPORT_TEMPLATE_DECLARE
-    RepeatedPtrField<std::string>;
-
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_REPEATED_PTR_FIELD_H__
diff --git a/src/google/protobuf/service.cc b/src/google/protobuf/service.cc
index 5394568..da1ae78 100644
--- a/src/google/protobuf/service.cc
+++ b/src/google/protobuf/service.cc
@@ -32,7 +32,7 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/service.h>
+#include "google/protobuf/service.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/service.h b/src/google/protobuf/service.h
index d288eb5..a512e71 100644
--- a/src/google/protobuf/service.h
+++ b/src/google/protobuf/service.h
@@ -102,15 +102,17 @@
 
 
 #include <string>
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/common.h>
+
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/port.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -134,6 +136,8 @@
 class PROTOBUF_EXPORT Service {
  public:
   inline Service() {}
+  Service(const Service&) = delete;
+  Service& operator=(const Service&) = delete;
   virtual ~Service();
 
   // When constructing a stub, you may pass STUB_OWNS_CHANNEL as the second
@@ -190,9 +194,6 @@
       const MethodDescriptor* method) const = 0;
   virtual const Message& GetResponsePrototype(
       const MethodDescriptor* method) const = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Service);
 };
 
 // An RpcController mediates a single method call.  The primary purpose of
@@ -206,6 +207,8 @@
 class PROTOBUF_EXPORT RpcController {
  public:
   inline RpcController() {}
+  RpcController(const RpcController&) = delete;
+  RpcController& operator=(const RpcController&) = delete;
   virtual ~RpcController();
 
   // Client-side methods ---------------------------------------------
@@ -256,9 +259,6 @@
   //
   // NotifyOnCancel() must be called no more than once per request.
   virtual void NotifyOnCancel(Closure* callback) = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcController);
 };
 
 // Abstract interface for an RPC channel.  An RpcChannel represents a
@@ -272,6 +272,8 @@
 class PROTOBUF_EXPORT RpcChannel {
  public:
   inline RpcChannel() {}
+  RpcChannel(const RpcChannel&) = delete;
+  RpcChannel& operator=(const RpcChannel&) = delete;
   virtual ~RpcChannel();
 
   // Call the given method of the remote service.  The signature of this
@@ -282,14 +284,11 @@
   virtual void CallMethod(const MethodDescriptor* method,
                           RpcController* controller, const Message* request,
                           Message* response, Closure* done) = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(RpcChannel);
 };
 
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_SERVICE_H__
diff --git a/src/google/protobuf/source_context.pb.cc b/src/google/protobuf/source_context.pb.cc
index e7525e9..a4cec86 100644
--- a/src/google/protobuf/source_context.pb.cc
+++ b/src/google/protobuf/source_context.pb.cc
@@ -1,86 +1,110 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/source_context.proto
 
-#include <google/protobuf/source_context.pb.h>
+#include "google/protobuf/source_context.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR SourceContext::SourceContext(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.file_name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct SourceContextDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR SourceContextDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR SourceContextDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~SourceContextDefaultTypeInternal() {}
   union {
     SourceContext _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceContextDefaultTypeInternal _SourceContext_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 SourceContextDefaultTypeInternal _SourceContext_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fsource_5fcontext_2eproto[1];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceContext, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceContext, _impl_.file_name_),
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceContext, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::SourceContext, _impl_.file_name_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceContext)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::SourceContext)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_SourceContext_default_instance_._instance,
 };
-
-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\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once;
+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\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto = {
-    false, false, 240, descriptor_table_protodef_google_2fprotobuf_2fsource_5fcontext_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fsource_5fcontext_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fsource_5fcontext_2eproto(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fsource_5fcontext_2eproto(&descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 class SourceContext::_Internal {
@@ -146,7 +170,7 @@
 
 void SourceContext::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.SourceContext)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -155,20 +179,22 @@
 }
 
 const char* SourceContext::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string file_name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_file_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.SourceContext.file_name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -193,10 +219,11 @@
 #undef CHK_
 }
 
-uint8_t* SourceContext::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* SourceContext::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.SourceContext)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string file_name = 1;
@@ -217,11 +244,12 @@
   return target;
 }
 
-size_t SourceContext::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext)
-  size_t total_size = 0;
+::size_t SourceContext::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.SourceContext)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -245,9 +273,10 @@
 void SourceContext::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<SourceContext*>(&to_msg);
   auto& from = static_cast<const SourceContext&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.SourceContext)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (!from._internal_file_name().empty()) {
@@ -279,11 +308,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata SourceContext::GetMetadata() const {
+
   return ::_pbi::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
@@ -292,6 +321,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::SourceContext >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/source_context.pb.h b/src/google/protobuf/source_context.pb.h
index 4ab7ec7..c1468c8 100644
--- a/src/google/protobuf/source_context.pb.h
+++ b/src/google/protobuf/source_context.pb.h
@@ -1,38 +1,43 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/source_context.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fsource_5fcontext_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -41,21 +46,25 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fsource_5fcontext_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct SourceContextDefaultTypeInternal;
 PROTOBUF_EXPORT extern SourceContextDefaultTypeInternal _SourceContext_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceContext* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::SourceContext* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::SourceContext>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT SourceContext final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.SourceContext) */ {
  public:
@@ -145,10 +154,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -159,7 +168,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.SourceContext";
   }
   protected:
@@ -210,12 +219,17 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // SourceContext
 
 // string file_name = 1;
@@ -242,11 +256,11 @@
   return _impl_.file_name_.Get();
 }
 inline void SourceContext::_internal_set_file_name(const std::string& value) {
-  
+
   _impl_.file_name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* SourceContext::_internal_mutable_file_name() {
-  
+
   return _impl_.file_name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* SourceContext::release_file_name() {
@@ -254,11 +268,6 @@
   return _impl_.file_name_.Release();
 }
 inline void SourceContext::set_allocated_file_name(std::string* file_name) {
-  if (file_name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.file_name_.SetAllocated(file_name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.file_name_.IsDefault()) {
@@ -269,14 +278,15 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fsource_5fcontext_2eproto_2epb_2eh
diff --git a/src/google/protobuf/source_context.proto b/src/google/protobuf/source_context.proto
index 06bfc43..135f50f 100644
--- a/src/google/protobuf/source_context.proto
+++ b/src/google/protobuf/source_context.proto
@@ -32,11 +32,11 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option java_package = "com.google.protobuf";
 option java_outer_classname = "SourceContextProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option go_package = "google.golang.org/protobuf/types/known/sourcecontextpb";
 
 // `SourceContext` represents information about the source of a
diff --git a/src/google/protobuf/string_member_robber.h b/src/google/protobuf/string_member_robber.h
index a4c1051..e16069a 100644
--- a/src/google/protobuf/string_member_robber.h
+++ b/src/google/protobuf/string_member_robber.h
@@ -34,5 +34,8 @@
 #include <string>
 #include <type_traits>
 
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+
 
 #endif  // GOOGLE_PROTOBUF_STRING_MEMBER_ROBBER_H__
diff --git a/src/google/protobuf/struct.pb.cc b/src/google/protobuf/struct.pb.cc
index 87c72d4..096cf25 100644
--- a/src/google/protobuf/struct.pb.cc
+++ b/src/google/protobuf/struct.pb.cc
@@ -1,168 +1,201 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/struct.proto
 
-#include <google/protobuf/struct.pb.h>
+#include "google/protobuf/struct.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse(
     ::_pbi::ConstantInitialized) {}
 struct Struct_FieldsEntry_DoNotUseDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUseDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR Struct_FieldsEntry_DoNotUseDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~Struct_FieldsEntry_DoNotUseDefaultTypeInternal() {}
   union {
     Struct_FieldsEntry_DoNotUse _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Struct_FieldsEntry_DoNotUseDefaultTypeInternal _Struct_FieldsEntry_DoNotUse_default_instance_;
 PROTOBUF_CONSTEXPR Struct::Struct(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.fields_)*/{::_pbi::ConstantInitialized()}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct StructDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR StructDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR StructDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~StructDefaultTypeInternal() {}
   union {
     Struct _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 StructDefaultTypeInternal _Struct_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 StructDefaultTypeInternal _Struct_default_instance_;
 PROTOBUF_CONSTEXPR Value::Value(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.kind_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}
   , /*decltype(_impl_._oneof_case_)*/{}} {}
 struct ValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR ValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR ValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~ValueDefaultTypeInternal() {}
   union {
     Value _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ValueDefaultTypeInternal _Value_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ValueDefaultTypeInternal _Value_default_instance_;
 PROTOBUF_CONSTEXPR ListValue::ListValue(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.values_)*/{}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct ListValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR ListValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR ListValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~ListValueDefaultTypeInternal() {}
   union {
     ListValue _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ListValueDefaultTypeInternal _ListValue_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 ListValueDefaultTypeInternal _ListValue_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fstruct_2eproto[4];
 static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto[1];
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _has_bits_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, key_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, value_),
-  0,
-  1,
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct, _impl_.fields_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _internal_metadata_),
-  ~0u,  // no _extensions_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _impl_._oneof_case_[0]),
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  ::_pbi::kInvalidFieldOffsetTag,
-  ::_pbi::kInvalidFieldOffsetTag,
-  ::_pbi::kInvalidFieldOffsetTag,
-  ::_pbi::kInvalidFieldOffsetTag,
-  ::_pbi::kInvalidFieldOffsetTag,
-  ::_pbi::kInvalidFieldOffsetTag,
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _impl_.kind_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ListValue, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ListValue, _impl_.values_),
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fstruct_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _has_bits_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, key_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse, value_),
+    0,
+    1,
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Struct, _impl_.fields_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _internal_metadata_),
+    ~0u,  // no _extensions_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _impl_._oneof_case_[0]),
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    ::_pbi::kInvalidFieldOffsetTag,
+    ::_pbi::kInvalidFieldOffsetTag,
+    ::_pbi::kInvalidFieldOffsetTag,
+    ::_pbi::kInvalidFieldOffsetTag,
+    ::_pbi::kInvalidFieldOffsetTag,
+    ::_pbi::kInvalidFieldOffsetTag,
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _impl_.kind_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ListValue, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::ListValue, _impl_.values_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, 8, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse)},
-  { 10, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Struct)},
-  { 17, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Value)},
-  { 30, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ListValue)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, 10, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse)},
+        { 12, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Struct)},
+        { 21, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Value)},
+        { 36, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::ListValue)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_Struct_FieldsEntry_DoNotUse_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Struct_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Value_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Struct_FieldsEntry_DoNotUse_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Struct_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Value_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_._instance,
 };
-
-const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
-  "\n\034google/protobuf/struct.proto\022\017google.p"
-  "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo"
-  "gle.protobuf.Struct.FieldsEntry\032E\n\013Field"
-  "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo"
-  "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull"
-  "_value\030\001 \001(\0162\032.google.protobuf.NullValue"
-  "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val"
-  "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru"
-  "ct_value\030\005 \001(\0132\027.google.protobuf.StructH"
-  "\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\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fstruct_2eproto_once;
+const char descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+    "\n\034google/protobuf/struct.proto\022\017google.p"
+    "rotobuf\"\204\001\n\006Struct\0223\n\006fields\030\001 \003(\0132#.goo"
+    "gle.protobuf.Struct.FieldsEntry\032E\n\013Field"
+    "sEntry\022\013\n\003key\030\001 \001(\t\022%\n\005value\030\002 \001(\0132\026.goo"
+    "gle.protobuf.Value:\0028\001\"\352\001\n\005Value\0220\n\nnull"
+    "_value\030\001 \001(\0162\032.google.protobuf.NullValue"
+    "H\000\022\026\n\014number_value\030\002 \001(\001H\000\022\026\n\014string_val"
+    "ue\030\003 \001(\tH\000\022\024\n\nbool_value\030\004 \001(\010H\000\022/\n\014stru"
+    "ct_value\030\005 \001(\0132\027.google.protobuf.StructH"
+    "\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\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2fstruct_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fstruct_2eproto = {
-    false, false, 638, descriptor_table_protodef_google_2fprotobuf_2fstruct_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fstruct_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fstruct_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fstruct_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fstruct_2eproto(&descriptor_table_google_2fprotobuf_2fstruct_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::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);
@@ -176,8 +209,6 @@
       return false;
   }
 }
-
-
 // ===================================================================
 
 Struct_FieldsEntry_DoNotUse::Struct_FieldsEntry_DoNotUse() {}
@@ -191,7 +222,6 @@
       &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fstruct_2eproto[0]);
 }
-
 // ===================================================================
 
 class Struct::_Internal {
@@ -255,7 +285,7 @@
 
 void Struct::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Struct)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -264,14 +294,15 @@
 }
 
 const char* Struct::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // map<string, .google.protobuf.Value> fields = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -279,8 +310,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -305,10 +337,11 @@
 #undef CHK_
 }
 
-uint8_t* Struct::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Struct::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Struct)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // map<string, .google.protobuf.Value> fields = 1;
@@ -345,11 +378,12 @@
   return target;
 }
 
-size_t Struct::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct)
-  size_t total_size = 0;
+::size_t Struct::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Struct)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -375,9 +409,10 @@
 void Struct::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Struct*>(&to_msg);
   auto& from = static_cast<const Struct&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Struct)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.fields_.MergeFrom(from._impl_.fields_);
@@ -402,15 +437,17 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Struct::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fstruct_2eproto[1]);
 }
-
 // ===================================================================
 
 class Value::_Internal {
  public:
+  static constexpr ::int32_t kOneofCaseOffset =
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Value, _impl_._oneof_case_);
   static const ::PROTOBUF_NAMESPACE_ID::Struct& struct_value(const Value* msg);
   static const ::PROTOBUF_NAMESPACE_ID::ListValue& list_value(const Value* msg);
 };
@@ -576,7 +613,7 @@
 
 void Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -585,61 +622,68 @@
 }
 
 const char* Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // .google.protobuf.NullValue null_value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_null_value(static_cast<::PROTOBUF_NAMESPACE_ID::NullValue>(val));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // double number_value = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 17)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 17)) {
           _internal_set_number_value(::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr));
           ptr += sizeof(double);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string string_value = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           auto str = _internal_mutable_string_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Value.string_value"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // bool bool_value = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 32)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 32)) {
           _internal_set_bool_value(::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr));
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.Struct struct_value = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 42)) {
           ptr = ctx->ParseMessage(_internal_mutable_struct_value(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.ListValue list_value = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           ptr = ctx->ParseMessage(_internal_mutable_list_value(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -664,27 +708,28 @@
 #undef CHK_
 }
 
-uint8_t* Value::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Value::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // .google.protobuf.NullValue null_value = 1;
-  if (_internal_has_null_value()) {
+  if (kind_case() == kNullValue) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteEnumToArray(
       1, this->_internal_null_value(), target);
   }
 
   // double number_value = 2;
-  if (_internal_has_number_value()) {
+  if (kind_case() == kNumberValue) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteDoubleToArray(2, this->_internal_number_value(), target);
   }
 
   // string string_value = 3;
-  if (_internal_has_string_value()) {
+  if (kind_case() == kStringValue) {
     ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::VerifyUtf8String(
       this->_internal_string_value().data(), static_cast<int>(this->_internal_string_value().length()),
       ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::SERIALIZE,
@@ -694,20 +739,20 @@
   }
 
   // bool bool_value = 4;
-  if (_internal_has_bool_value()) {
+  if (kind_case() == kBoolValue) {
     target = stream->EnsureSpace(target);
     target = ::_pbi::WireFormatLite::WriteBoolToArray(4, this->_internal_bool_value(), target);
   }
 
   // .google.protobuf.Struct struct_value = 5;
-  if (_internal_has_struct_value()) {
+  if (kind_case() == kStructValue) {
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(5, _Internal::struct_value(this),
         _Internal::struct_value(this).GetCachedSize(), target, stream);
   }
 
   // .google.protobuf.ListValue list_value = 6;
-  if (_internal_has_list_value()) {
+  if (kind_case() == kListValue) {
     target = ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite::
       InternalWriteMessage(6, _Internal::list_value(this),
         _Internal::list_value(this).GetCachedSize(), target, stream);
@@ -721,11 +766,12 @@
   return target;
 }
 
-size_t Value::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value)
-  size_t total_size = 0;
+::size_t Value::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Value)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -784,9 +830,10 @@
 void Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Value*>(&to_msg);
   auto& from = static_cast<const Value&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Value)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   switch (from.kind_case()) {
@@ -842,11 +889,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Value::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fstruct_2eproto_getter, &descriptor_table_google_2fprotobuf_2fstruct_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fstruct_2eproto[2]);
 }
-
 // ===================================================================
 
 class ListValue::_Internal {
@@ -900,7 +947,7 @@
 
 void ListValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.ListValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -909,14 +956,15 @@
 }
 
 const char* ListValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // repeated .google.protobuf.Value values = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -924,8 +972,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<10>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -950,10 +999,11 @@
 #undef CHK_
 }
 
-uint8_t* ListValue::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* ListValue::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.ListValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // repeated .google.protobuf.Value values = 1;
@@ -972,11 +1022,12 @@
   return target;
 }
 
-size_t ListValue::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue)
-  size_t total_size = 0;
+::size_t ListValue::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.ListValue)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1000,9 +1051,10 @@
 void ListValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<ListValue*>(&to_msg);
   auto& from = static_cast<const ListValue&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.ListValue)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.values_.MergeFrom(from._impl_.values_);
@@ -1027,11 +1079,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata ListValue::GetMetadata() const {
+
   return ::_pbi::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
@@ -1052,6 +1104,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::ListValue >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/struct.pb.h b/src/google/protobuf/struct.pb.h
index fb47fce..23e0e87 100644
--- a/src/google/protobuf/struct.pb.h
+++ b/src/google/protobuf/struct.pb.h
@@ -1,42 +1,47 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/struct.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/map.h>  // IWYU pragma: export
-#include <google/protobuf/map_entry.h>
-#include <google/protobuf/map_field_inl.h>
-#include <google/protobuf/generated_enum_reflection.h>
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/map.h"  // IWYU pragma: export
+#include "google/protobuf/map_entry.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/generated_enum_reflection.h"
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fstruct_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -45,9 +50,10 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fstruct_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct ListValueDefaultTypeInternal;
@@ -61,42 +67,55 @@
 class Value;
 struct ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern ValueDefaultTypeInternal _Value_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ListValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ListValue>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Struct* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Struct>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Value>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::ListValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::ListValue>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Struct* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Struct>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Struct_FieldsEntry_DoNotUse>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Value>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
 
+PROTOBUF_NAMESPACE_OPEN
 enum NullValue : int {
   NULL_VALUE = 0,
-  NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
-  NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
+  NullValue_INT_MIN_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::min(),
+  NullValue_INT_MAX_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::max(),
 };
-PROTOBUF_EXPORT bool NullValue_IsValid(int value);
-constexpr NullValue NullValue_MIN = NULL_VALUE;
-constexpr NullValue NullValue_MAX = NULL_VALUE;
-constexpr int NullValue_ARRAYSIZE = NullValue_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* NullValue_descriptor();
-template<typename T>
-inline const std::string& NullValue_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, NullValue>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function NullValue_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    NullValue_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool NullValue_IsValid(int value);
+constexpr NullValue NullValue_MIN = static_cast<NullValue>(0);
+constexpr NullValue NullValue_MAX = static_cast<NullValue>(0);
+constexpr int NullValue_ARRAYSIZE = 0 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+NullValue_descriptor();
+template <typename T>
+const std::string& NullValue_Name(T value) {
+  static_assert(std::is_same<T, NullValue>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to NullValue_Name().");
+  return NullValue_Name(static_cast<NullValue>(value));
 }
-inline bool NullValue_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, NullValue* value) {
+template <>
+inline const std::string& NullValue_Name(NullValue value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<NullValue_descriptor,
+                                                 0, 0>(
+      static_cast<int>(value));
+}
+inline bool NullValue_Parse(absl::string_view name, NullValue* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<NullValue>(
-    NullValue_descriptor(), name, value);
+      NullValue_descriptor(), name, value);
 }
+
 // ===================================================================
 
-class Struct_FieldsEntry_DoNotUse : public ::PROTOBUF_NAMESPACE_ID::internal::MapEntry<Struct_FieldsEntry_DoNotUse, 
+
+// -------------------------------------------------------------------
+
+class Struct_FieldsEntry_DoNotUse final : 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> {
@@ -119,7 +138,6 @@
   ::PROTOBUF_NAMESPACE_ID::Metadata GetMetadata() const final;
   friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto;
 };
-
 // -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Struct final :
@@ -211,10 +229,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -225,7 +243,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Struct";
   }
   protected:
@@ -282,8 +300,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Value) */ {
@@ -384,10 +401,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -398,7 +415,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Value";
   }
   protected:
@@ -425,9 +442,6 @@
   };
   // .google.protobuf.NullValue null_value = 1;
   bool has_null_value() const;
-  private:
-  bool _internal_has_null_value() const;
-  public:
   void clear_null_value();
   ::PROTOBUF_NAMESPACE_ID::NullValue null_value() const;
   void set_null_value(::PROTOBUF_NAMESPACE_ID::NullValue value);
@@ -438,9 +452,6 @@
 
   // double number_value = 2;
   bool has_number_value() const;
-  private:
-  bool _internal_has_number_value() const;
-  public:
   void clear_number_value();
   double number_value() const;
   void set_number_value(double value);
@@ -451,9 +462,6 @@
 
   // 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;
   template <typename ArgT0 = const std::string&, typename... ArgT>
@@ -469,9 +477,6 @@
 
   // bool bool_value = 4;
   bool has_bool_value() const;
-  private:
-  bool _internal_has_bool_value() const;
-  public:
   void clear_bool_value();
   bool bool_value() const;
   void set_bool_value(bool value);
@@ -546,13 +551,12 @@
       ::PROTOBUF_NAMESPACE_ID::ListValue* list_value_;
     } kind_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
-    uint32_t _oneof_case_[1];
+    ::uint32_t _oneof_case_[1];
 
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fstruct_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT ListValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.ListValue) */ {
@@ -643,10 +647,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -657,7 +661,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.ListValue";
   }
   protected:
@@ -712,14 +716,19 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
 // -------------------------------------------------------------------
 
+// -------------------------------------------------------------------
+
 // Struct
 
 // map<string, .google.protobuf.Value> fields = 1;
@@ -756,23 +765,20 @@
 // Value
 
 // .google.protobuf.NullValue null_value = 1;
-inline bool Value::_internal_has_null_value() const {
-  return kind_case() == kNullValue;
-}
 inline bool Value::has_null_value() const {
-  return _internal_has_null_value();
+  return kind_case() == kNullValue;
 }
 inline void Value::set_has_null_value() {
   _impl_._oneof_case_[0] = kNullValue;
 }
 inline void Value::clear_null_value() {
-  if (_internal_has_null_value()) {
+  if (kind_case() == kNullValue) {
     _impl_.kind_.null_value_ = 0;
     clear_has_kind();
   }
 }
 inline ::PROTOBUF_NAMESPACE_ID::NullValue Value::_internal_null_value() const {
-  if (_internal_has_null_value()) {
+  if (kind_case() == kNullValue) {
     return static_cast< ::PROTOBUF_NAMESPACE_ID::NullValue >(_impl_.kind_.null_value_);
   }
   return static_cast< ::PROTOBUF_NAMESPACE_ID::NullValue >(0);
@@ -782,7 +788,7 @@
   return _internal_null_value();
 }
 inline void Value::_internal_set_null_value(::PROTOBUF_NAMESPACE_ID::NullValue value) {
-  if (!_internal_has_null_value()) {
+  if (kind_case() != kNullValue) {
     clear_kind();
     set_has_null_value();
   }
@@ -794,29 +800,26 @@
 }
 
 // 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();
+  return kind_case() == kNumberValue;
 }
 inline void Value::set_has_number_value() {
   _impl_._oneof_case_[0] = kNumberValue;
 }
 inline void Value::clear_number_value() {
-  if (_internal_has_number_value()) {
+  if (kind_case() == kNumberValue) {
     _impl_.kind_.number_value_ = 0;
     clear_has_kind();
   }
 }
 inline double Value::_internal_number_value() const {
-  if (_internal_has_number_value()) {
+  if (kind_case() == kNumberValue) {
     return _impl_.kind_.number_value_;
   }
   return 0;
 }
 inline void Value::_internal_set_number_value(double value) {
-  if (!_internal_has_number_value()) {
+  if (kind_case() != kNumberValue) {
     clear_kind();
     set_has_number_value();
   }
@@ -832,17 +835,14 @@
 }
 
 // string string_value = 3;
-inline bool Value::_internal_has_string_value() const {
-  return kind_case() == kStringValue;
-}
 inline bool Value::has_string_value() const {
-  return _internal_has_string_value();
+  return kind_case() == kStringValue;
 }
 inline void Value::set_has_string_value() {
   _impl_._oneof_case_[0] = kStringValue;
 }
 inline void Value::clear_string_value() {
-  if (_internal_has_string_value()) {
+  if (kind_case() == kStringValue) {
     _impl_.kind_.string_value_.Destroy();
     clear_has_kind();
   }
@@ -853,7 +853,7 @@
 }
 template <typename ArgT0, typename... ArgT>
 inline void Value::set_string_value(ArgT0&& arg0, ArgT... args) {
-  if (!_internal_has_string_value()) {
+  if (kind_case() != kStringValue) {
     clear_kind();
     set_has_string_value();
     _impl_.kind_.string_value_.InitDefault();
@@ -867,13 +867,13 @@
   return _s;
 }
 inline const std::string& Value::_internal_string_value() const {
-  if (_internal_has_string_value()) {
+  if (kind_case() == kStringValue) {
     return _impl_.kind_.string_value_.Get();
   }
   return ::PROTOBUF_NAMESPACE_ID::internal::GetEmptyStringAlreadyInited();
 }
 inline void Value::_internal_set_string_value(const std::string& value) {
-  if (!_internal_has_string_value()) {
+  if (kind_case() != kStringValue) {
     clear_kind();
     set_has_string_value();
     _impl_.kind_.string_value_.InitDefault();
@@ -881,7 +881,7 @@
   _impl_.kind_.string_value_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Value::_internal_mutable_string_value() {
-  if (!_internal_has_string_value()) {
+  if (kind_case() != kStringValue) {
     clear_kind();
     set_has_string_value();
     _impl_.kind_.string_value_.InitDefault();
@@ -890,7 +890,7 @@
 }
 inline std::string* Value::release_string_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.Value.string_value)
-  if (_internal_has_string_value()) {
+  if (kind_case() == kStringValue) {
     clear_has_kind();
     return _impl_.kind_.string_value_.Release();
   } else {
@@ -909,29 +909,26 @@
 }
 
 // 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();
+  return kind_case() == kBoolValue;
 }
 inline void Value::set_has_bool_value() {
   _impl_._oneof_case_[0] = kBoolValue;
 }
 inline void Value::clear_bool_value() {
-  if (_internal_has_bool_value()) {
+  if (kind_case() == kBoolValue) {
     _impl_.kind_.bool_value_ = false;
     clear_has_kind();
   }
 }
 inline bool Value::_internal_bool_value() const {
-  if (_internal_has_bool_value()) {
+  if (kind_case() == kBoolValue) {
     return _impl_.kind_.bool_value_;
   }
   return false;
 }
 inline void Value::_internal_set_bool_value(bool value) {
-  if (!_internal_has_bool_value()) {
+  if (kind_case() != kBoolValue) {
     clear_kind();
     set_has_bool_value();
   }
@@ -947,17 +944,17 @@
 }
 
 // .google.protobuf.Struct struct_value = 5;
-inline bool Value::_internal_has_struct_value() const {
+inline bool Value::has_struct_value() const {
   return kind_case() == kStructValue;
 }
-inline bool Value::has_struct_value() const {
-  return _internal_has_struct_value();
+inline bool Value::_internal_has_struct_value() const {
+  return kind_case() == kStructValue;
 }
 inline void Value::set_has_struct_value() {
   _impl_._oneof_case_[0] = kStructValue;
 }
 inline void Value::clear_struct_value() {
-  if (_internal_has_struct_value()) {
+  if (kind_case() == kStructValue) {
     if (GetArenaForAllocation() == nullptr) {
       delete _impl_.kind_.struct_value_;
     }
@@ -966,7 +963,7 @@
 }
 inline ::PROTOBUF_NAMESPACE_ID::Struct* Value::release_struct_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.Value.struct_value)
-  if (_internal_has_struct_value()) {
+  if (kind_case() == kStructValue) {
     clear_has_kind();
     ::PROTOBUF_NAMESPACE_ID::Struct* temp = _impl_.kind_.struct_value_;
     if (GetArenaForAllocation() != nullptr) {
@@ -979,7 +976,7 @@
   }
 }
 inline const ::PROTOBUF_NAMESPACE_ID::Struct& Value::_internal_struct_value() const {
-  return _internal_has_struct_value()
+  return kind_case() == kStructValue
       ? *_impl_.kind_.struct_value_
       : reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::Struct&>(::PROTOBUF_NAMESPACE_ID::_Struct_default_instance_);
 }
@@ -989,7 +986,7 @@
 }
 inline ::PROTOBUF_NAMESPACE_ID::Struct* Value::unsafe_arena_release_struct_value() {
   // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.struct_value)
-  if (_internal_has_struct_value()) {
+  if (kind_case() == kStructValue) {
     clear_has_kind();
     ::PROTOBUF_NAMESPACE_ID::Struct* temp = _impl_.kind_.struct_value_;
     _impl_.kind_.struct_value_ = nullptr;
@@ -1007,7 +1004,7 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.struct_value)
 }
 inline ::PROTOBUF_NAMESPACE_ID::Struct* Value::_internal_mutable_struct_value() {
-  if (!_internal_has_struct_value()) {
+  if (kind_case() != kStructValue) {
     clear_kind();
     set_has_struct_value();
     _impl_.kind_.struct_value_ = CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::Struct >(GetArenaForAllocation());
@@ -1021,17 +1018,17 @@
 }
 
 // .google.protobuf.ListValue list_value = 6;
-inline bool Value::_internal_has_list_value() const {
+inline bool Value::has_list_value() const {
   return kind_case() == kListValue;
 }
-inline bool Value::has_list_value() const {
-  return _internal_has_list_value();
+inline bool Value::_internal_has_list_value() const {
+  return kind_case() == kListValue;
 }
 inline void Value::set_has_list_value() {
   _impl_._oneof_case_[0] = kListValue;
 }
 inline void Value::clear_list_value() {
-  if (_internal_has_list_value()) {
+  if (kind_case() == kListValue) {
     if (GetArenaForAllocation() == nullptr) {
       delete _impl_.kind_.list_value_;
     }
@@ -1040,7 +1037,7 @@
 }
 inline ::PROTOBUF_NAMESPACE_ID::ListValue* Value::release_list_value() {
   // @@protoc_insertion_point(field_release:google.protobuf.Value.list_value)
-  if (_internal_has_list_value()) {
+  if (kind_case() == kListValue) {
     clear_has_kind();
     ::PROTOBUF_NAMESPACE_ID::ListValue* temp = _impl_.kind_.list_value_;
     if (GetArenaForAllocation() != nullptr) {
@@ -1053,7 +1050,7 @@
   }
 }
 inline const ::PROTOBUF_NAMESPACE_ID::ListValue& Value::_internal_list_value() const {
-  return _internal_has_list_value()
+  return kind_case() == kListValue
       ? *_impl_.kind_.list_value_
       : reinterpret_cast< ::PROTOBUF_NAMESPACE_ID::ListValue&>(::PROTOBUF_NAMESPACE_ID::_ListValue_default_instance_);
 }
@@ -1063,7 +1060,7 @@
 }
 inline ::PROTOBUF_NAMESPACE_ID::ListValue* Value::unsafe_arena_release_list_value() {
   // @@protoc_insertion_point(field_unsafe_arena_release:google.protobuf.Value.list_value)
-  if (_internal_has_list_value()) {
+  if (kind_case() == kListValue) {
     clear_has_kind();
     ::PROTOBUF_NAMESPACE_ID::ListValue* temp = _impl_.kind_.list_value_;
     _impl_.kind_.list_value_ = nullptr;
@@ -1081,7 +1078,7 @@
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Value.list_value)
 }
 inline ::PROTOBUF_NAMESPACE_ID::ListValue* Value::_internal_mutable_list_value() {
-  if (!_internal_has_list_value()) {
+  if (kind_case() != kListValue) {
     clear_kind();
     set_has_list_value();
     _impl_.kind_.list_value_ = CreateMaybeMessage< ::PROTOBUF_NAMESPACE_ID::ListValue >(GetArenaForAllocation());
@@ -1148,24 +1145,19 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 PROTOBUF_NAMESPACE_OPEN
 
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::NullValue> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::NullValue>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::NullValue> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::NullValue>() {
   return ::PROTOBUF_NAMESPACE_ID::NullValue_descriptor();
 }
 
@@ -1173,5 +1165,6 @@
 
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fstruct_2eproto_2epb_2eh
diff --git a/src/google/protobuf/struct.proto b/src/google/protobuf/struct.proto
index 0ac843c..c4ea645 100644
--- a/src/google/protobuf/struct.proto
+++ b/src/google/protobuf/struct.proto
@@ -32,13 +32,13 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
 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;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 
 // `Struct` represents a structured data value, consisting of fields
 // which map to dynamically typed values. In some languages, `Struct`
diff --git a/src/google/protobuf/stubs/BUILD.bazel b/src/google/protobuf/stubs/BUILD.bazel
new file mode 100644
index 0000000..6bea8ac
--- /dev/null
+++ b/src/google/protobuf/stubs/BUILD.bazel
@@ -0,0 +1,101 @@
+# Protobuf stubs library.
+#   These are utilities that mirror the behavior of internal Google code.
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS")
+
+package(
+    default_visibility = ["//:__subpackages__"],
+)
+
+cc_library(
+    name = "lite",
+    srcs = [
+        "common.cc",
+    ],
+    hdrs = [
+        "callback.h",
+        "common.h",
+        "logging.h",
+        "mathutil.h",
+        "platform_macros.h",
+        "port.h",
+        "status_macros.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/stubs",
+    linkopts = LINK_OPTS,
+    deps = [
+        "//src/google/protobuf:port_def",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_library(
+    name = "stubs",
+    srcs = [
+    ],
+    hdrs = [
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/stubs",
+    textual_hdrs = [
+        "callback.h",
+        "common.h",
+        "logging.h",
+        "mathutil.h",
+        "platform_macros.h",
+        "port.h",
+        "status_macros.h",
+    ],
+    deps = [
+        ":lite",
+        "//src/google/protobuf:port_def",
+        "@com_google_absl//absl/status",
+        "@com_google_absl//absl/status:statusor",
+        "@com_google_absl//absl/strings",
+    ],
+)
+
+cc_test(
+    name = "stubs_test",
+    srcs = [
+        "common_unittest.cc",
+    ],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    linkopts = LINK_OPTS,
+    deps = [
+        ":lite",
+        ":stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//pkg:__pkg__"],
+)
diff --git a/src/google/protobuf/stubs/bytestream.cc b/src/google/protobuf/stubs/bytestream.cc
deleted file mode 100644
index 980d6f6..0000000
--- a/src/google/protobuf/stubs/bytestream.cc
+++ /dev/null
@@ -1,194 +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 <google/protobuf/stubs/bytestream.h>
-
-#include <string.h>
-#include <algorithm>
-
-#include <google/protobuf/stubs/logging.h>
-
-namespace google {
-namespace protobuf {
-namespace strings {
-
-void ByteSource::CopyTo(ByteSink* sink, size_t n) {
-  while (n > 0) {
-    StringPiece fragment = Peek();
-    if (fragment.empty()) {
-      GOOGLE_LOG(DFATAL) << "ByteSource::CopyTo() overran input.";
-      break;
-    }
-    std::size_t fragment_size = std::min<std::size_t>(n, fragment.size());
-    sink->Append(fragment.data(), fragment_size);
-    Skip(fragment_size);
-    n -= fragment_size;
-  }
-}
-
-void ByteSink::Flush() {}
-
-void UncheckedArrayByteSink::Append(const char* data, size_t n) {
-  if (data != dest_) {
-    // Catch cases where the pointer returned by GetAppendBuffer() was modified.
-    GOOGLE_DCHECK(!(dest_ <= data && data < (dest_ + n)))
-        << "Append() data[] overlaps with dest_[]";
-    memcpy(dest_, data, n);
-  }
-  dest_ += n;
-}
-
-CheckedArrayByteSink::CheckedArrayByteSink(char* outbuf, size_t capacity)
-    : outbuf_(outbuf), capacity_(capacity), size_(0), overflowed_(false) {
-}
-
-void CheckedArrayByteSink::Append(const char* bytes, size_t n) {
-  size_t available = capacity_ - size_;
-  if (n > available) {
-    n = available;
-    overflowed_ = true;
-  }
-  if (n > 0 && bytes != (outbuf_ + size_)) {
-    // Catch cases where the pointer returned by GetAppendBuffer() was modified.
-    GOOGLE_DCHECK(!(outbuf_ <= bytes && bytes < (outbuf_ + capacity_)))
-        << "Append() bytes[] overlaps with outbuf_[]";
-    memcpy(outbuf_ + size_, bytes, n);
-  }
-  size_ += n;
-}
-
-GrowingArrayByteSink::GrowingArrayByteSink(size_t estimated_size)
-    : capacity_(estimated_size),
-      buf_(new char[estimated_size]),
-      size_(0) {
-}
-
-GrowingArrayByteSink::~GrowingArrayByteSink() {
-  delete[] buf_;  // Just in case the user didn't call GetBuffer.
-}
-
-void GrowingArrayByteSink::Append(const char* bytes, size_t n) {
-  size_t available = capacity_ - size_;
-  if (bytes != (buf_ + size_)) {
-    // Catch cases where the pointer returned by GetAppendBuffer() was modified.
-    // We need to test for this before calling Expand() which may reallocate.
-    GOOGLE_DCHECK(!(buf_ <= bytes && bytes < (buf_ + capacity_)))
-        << "Append() bytes[] overlaps with buf_[]";
-  }
-  if (n > available) {
-    Expand(n - available);
-  }
-  if (n > 0 && bytes != (buf_ + size_)) {
-    memcpy(buf_ + size_, bytes, n);
-  }
-  size_ += n;
-}
-
-char* GrowingArrayByteSink::GetBuffer(size_t* nbytes) {
-  ShrinkToFit();
-  char* b = buf_;
-  *nbytes = size_;
-  buf_ = nullptr;
-  size_ = capacity_ = 0;
-  return b;
-}
-
-void GrowingArrayByteSink::Expand(size_t amount) {  // Expand by at least 50%.
-  size_t new_capacity = std::max(capacity_ + amount, (3 * capacity_) / 2);
-  char* bigger = new char[new_capacity];
-  memcpy(bigger, buf_, size_);
-  delete[] buf_;
-  buf_ = bigger;
-  capacity_ = new_capacity;
-}
-
-void GrowingArrayByteSink::ShrinkToFit() {
-  // Shrink only if the buffer is large and size_ is less than 3/4
-  // of capacity_.
-  if (capacity_ > 256 && size_ < (3 * capacity_) / 4) {
-    char* just_enough = new char[size_];
-    memcpy(just_enough, buf_, size_);
-    delete[] buf_;
-    buf_ = just_enough;
-    capacity_ = size_;
-  }
-}
-
-void StringByteSink::Append(const char* data, size_t n) {
-  dest_->append(data, n);
-}
-
-size_t ArrayByteSource::Available() const {
-  return input_.size();
-}
-
-StringPiece ArrayByteSource::Peek() {
-  return input_;
-}
-
-void ArrayByteSource::Skip(size_t n) {
-  GOOGLE_DCHECK_LE(n, input_.size());
-  input_.remove_prefix(n);
-}
-
-LimitByteSource::LimitByteSource(ByteSource *source, size_t limit)
-  : source_(source),
-    limit_(limit) {
-}
-
-size_t LimitByteSource::Available() const {
-  size_t available = source_->Available();
-  if (available > limit_) {
-    available = limit_;
-  }
-
-  return available;
-}
-
-StringPiece LimitByteSource::Peek() {
-  StringPiece piece = source_->Peek();
-  return StringPiece(piece.data(), std::min(piece.size(), limit_));
-}
-
-void LimitByteSource::Skip(size_t n) {
-  GOOGLE_DCHECK_LE(n, limit_);
-  source_->Skip(n);
-  limit_ -= n;
-}
-
-void LimitByteSource::CopyTo(ByteSink *sink, size_t n) {
-  GOOGLE_DCHECK_LE(n, limit_);
-  source_->CopyTo(sink, n);
-  limit_ -= n;
-}
-
-}  // namespace strings
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/bytestream.h b/src/google/protobuf/stubs/bytestream.h
deleted file mode 100644
index c7a48de..0000000
--- a/src/google/protobuf/stubs/bytestream.h
+++ /dev/null
@@ -1,351 +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.
-
-// This file declares the ByteSink and ByteSource abstract interfaces. These
-// interfaces represent objects that consume (ByteSink) or produce (ByteSource)
-// a sequence of bytes. Using these abstract interfaces in your APIs can help
-// make your code work with a variety of input and output types.
-//
-// This file also declares the following commonly used implementations of these
-// interfaces.
-//
-//   ByteSink:
-//      UncheckedArrayByteSink  Writes to an array, without bounds checking
-//      CheckedArrayByteSink    Writes to an array, with bounds checking
-//      GrowingArrayByteSink    Allocates and writes to a growable buffer
-//      StringByteSink          Writes to an STL string
-//      NullByteSink            Consumes a never-ending stream of bytes
-//
-//   ByteSource:
-//      ArrayByteSource         Reads from an array or string/StringPiece
-//      LimitedByteSource       Limits the number of bytes read from an
-
-#ifndef GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
-#define GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
-
-#include <stddef.h>
-#include <string>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stringpiece.h>
-
-#include <google/protobuf/port_def.inc>
-
-class CordByteSink;
-
-namespace google {
-namespace protobuf {
-namespace strings {
-
-// An abstract interface for an object that consumes a sequence of bytes. This
-// interface offers a way to append data as well as a Flush() function.
-//
-// Example:
-//
-//   string my_data;
-//   ...
-//   ByteSink* sink = ...
-//   sink->Append(my_data.data(), my_data.size());
-//   sink->Flush();
-//
-class PROTOBUF_EXPORT ByteSink {
- public:
-  ByteSink() {}
-  virtual ~ByteSink() {}
-
-  // Appends the "n" bytes starting at "bytes".
-  virtual void Append(const char* bytes, size_t n) = 0;
-
-  // Flushes internal buffers. The default implementation does nothing. ByteSink
-  // subclasses may use internal buffers that require calling Flush() at the end
-  // of the stream.
-  virtual void Flush();
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSink);
-};
-
-// An abstract interface for an object that produces a fixed-size sequence of
-// bytes.
-//
-// Example:
-//
-//   ByteSource* source = ...
-//   while (source->Available() > 0) {
-//     StringPiece data = source->Peek();
-//     ... do something with "data" ...
-//     source->Skip(data.length());
-//   }
-//
-class PROTOBUF_EXPORT ByteSource {
- public:
-  ByteSource() {}
-  virtual ~ByteSource() {}
-
-  // Returns the number of bytes left to read from the source. Available()
-  // should decrease by N each time Skip(N) is called. Available() may not
-  // increase. Available() returning 0 indicates that the ByteSource is
-  // exhausted.
-  //
-  // Note: Size() may have been a more appropriate name as it's more
-  //       indicative of the fixed-size nature of a ByteSource.
-  virtual size_t Available() const = 0;
-
-  // Returns a StringPiece of the next contiguous region of the source. Does not
-  // reposition the source. The returned region is empty iff Available() == 0.
-  //
-  // The returned region is valid until the next call to Skip() or until this
-  // object is destroyed, whichever occurs first.
-  //
-  // The length of the returned StringPiece will be <= Available().
-  virtual StringPiece Peek() = 0;
-
-  // Skips the next n bytes. Invalidates any StringPiece returned by a previous
-  // call to Peek().
-  //
-  // REQUIRES: Available() >= n
-  virtual void Skip(size_t n) = 0;
-
-  // Writes the next n bytes in this ByteSource to the given ByteSink, and
-  // advances this ByteSource past the copied bytes. The default implementation
-  // of this method just copies the bytes normally, but subclasses might
-  // override CopyTo to optimize certain cases.
-  //
-  // REQUIRES: Available() >= n
-  virtual void CopyTo(ByteSink* sink, size_t n);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSource);
-};
-
-//
-// Some commonly used implementations of ByteSink
-//
-
-// Implementation of ByteSink that writes to an unsized byte array. No
-// bounds-checking is performed--it is the caller's responsibility to ensure
-// that the destination array is large enough.
-//
-// Example:
-//
-//   char buf[10];
-//   UncheckedArrayByteSink sink(buf);
-//   sink.Append("hi", 2);    // OK
-//   sink.Append(data, 100);  // WOOPS! Overflows buf[10].
-//
-class PROTOBUF_EXPORT UncheckedArrayByteSink : public ByteSink {
- public:
-  explicit UncheckedArrayByteSink(char* dest) : dest_(dest) {}
-  virtual void Append(const char* data, size_t n) override;
-
-  // Returns the current output pointer so that a caller can see how many bytes
-  // were produced.
-  //
-  // Note: this method is not part of the ByteSink interface.
-  char* CurrentDestination() const { return dest_; }
-
- private:
-  char* dest_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UncheckedArrayByteSink);
-};
-
-// Implementation of ByteSink that writes to a sized byte array. This sink will
-// not write more than "capacity" bytes to outbuf. Once "capacity" bytes are
-// appended, subsequent bytes will be ignored and Overflowed() will return true.
-// Overflowed() does not cause a runtime error (i.e., it does not CHECK fail).
-//
-// Example:
-//
-//   char buf[10];
-//   CheckedArrayByteSink sink(buf, 10);
-//   sink.Append("hi", 2);    // OK
-//   sink.Append(data, 100);  // Will only write 8 more bytes
-//
-class PROTOBUF_EXPORT CheckedArrayByteSink : public ByteSink {
- public:
-  CheckedArrayByteSink(char* outbuf, size_t capacity);
-  virtual void Append(const char* bytes, size_t n) override;
-
-  // Returns the number of bytes actually written to the sink.
-  size_t NumberOfBytesWritten() const { return size_; }
-
-  // Returns true if any bytes were discarded, i.e., if there was an
-  // attempt to write more than 'capacity' bytes.
-  bool Overflowed() const { return overflowed_; }
-
- private:
-  char* outbuf_;
-  const size_t capacity_;
-  size_t size_;
-  bool overflowed_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CheckedArrayByteSink);
-};
-
-// Implementation of ByteSink that allocates an internal buffer (a char array)
-// and expands it as needed to accommodate appended data (similar to a string),
-// and allows the caller to take ownership of the internal buffer via the
-// GetBuffer() method. The buffer returned from GetBuffer() must be deleted by
-// the caller with delete[]. GetBuffer() also sets the internal buffer to be
-// empty, and subsequent appends to the sink will create a new buffer. The
-// destructor will free the internal buffer if GetBuffer() was not called.
-//
-// Example:
-//
-//   GrowingArrayByteSink sink(10);
-//   sink.Append("hi", 2);
-//   sink.Append(data, n);
-//   const char* buf = sink.GetBuffer();  // Ownership transferred
-//   delete[] buf;
-//
-class PROTOBUF_EXPORT GrowingArrayByteSink : public strings::ByteSink {
- public:
-  explicit GrowingArrayByteSink(size_t estimated_size);
-  virtual ~GrowingArrayByteSink();
-  virtual void Append(const char* bytes, size_t n) override;
-
-  // Returns the allocated buffer, and sets nbytes to its size. The caller takes
-  // ownership of the buffer and must delete it with delete[].
-  char* GetBuffer(size_t* nbytes);
-
- private:
-  void Expand(size_t amount);
-  void ShrinkToFit();
-
-  size_t capacity_;
-  char* buf_;
-  size_t size_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(GrowingArrayByteSink);
-};
-
-// Implementation of ByteSink that appends to the given string.
-// Existing contents of "dest" are not modified; new data is appended.
-//
-// Example:
-//
-//   string dest = "Hello ";
-//   StringByteSink sink(&dest);
-//   sink.Append("World", 5);
-//   assert(dest == "Hello World");
-//
-class PROTOBUF_EXPORT StringByteSink : public ByteSink {
- public:
-  explicit StringByteSink(std::string* dest) : dest_(dest) {}
-  virtual void Append(const char* data, size_t n) override;
-
- private:
-  std::string* dest_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StringByteSink);
-};
-
-// Implementation of ByteSink that discards all data.
-//
-// Example:
-//
-//   NullByteSink sink;
-//   sink.Append(data, data.size());  // All data ignored.
-//
-class PROTOBUF_EXPORT NullByteSink : public ByteSink {
- public:
-  NullByteSink() {}
-  void Append(const char* /*data*/, size_t /*n*/) override {}
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NullByteSink);
-};
-
-//
-// Some commonly used implementations of ByteSource
-//
-
-// Implementation of ByteSource that reads from a StringPiece.
-//
-// Example:
-//
-//   string data = "Hello";
-//   ArrayByteSource source(data);
-//   assert(source.Available() == 5);
-//   assert(source.Peek() == "Hello");
-//
-class PROTOBUF_EXPORT ArrayByteSource : public ByteSource {
- public:
-  explicit ArrayByteSource(StringPiece s) : input_(s) {}
-
-  virtual size_t Available() const override;
-  virtual StringPiece Peek() override;
-  virtual void Skip(size_t n) override;
-
- private:
-  StringPiece   input_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ArrayByteSource);
-};
-
-// Implementation of ByteSource that wraps another ByteSource, limiting the
-// number of bytes returned.
-//
-// The caller maintains ownership of the underlying source, and may not use the
-// underlying source while using the LimitByteSource object.  The underlying
-// source's pointer is advanced by n bytes every time this LimitByteSource
-// object is advanced by n.
-//
-// Example:
-//
-//   string data = "Hello World";
-//   ArrayByteSource abs(data);
-//   assert(abs.Available() == data.size());
-//
-//   LimitByteSource limit(abs, 5);
-//   assert(limit.Available() == 5);
-//   assert(limit.Peek() == "Hello");
-//
-class PROTOBUF_EXPORT LimitByteSource : public ByteSource {
- public:
-  // Returns at most "limit" bytes from "source".
-  LimitByteSource(ByteSource* source, size_t limit);
-
-  virtual size_t Available() const override;
-  virtual StringPiece Peek() override;
-  virtual void Skip(size_t n) override;
-
-  // We override CopyTo so that we can forward to the underlying source, in
-  // case it has an efficient implementation of CopyTo.
-  virtual void CopyTo(ByteSink* sink, size_t n) override;
-
- private:
-  ByteSource* source_;
-  size_t limit_;
-};
-
-}  // namespace strings
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_BYTESTREAM_H_
diff --git a/src/google/protobuf/stubs/bytestream_unittest.cc b/src/google/protobuf/stubs/bytestream_unittest.cc
deleted file mode 100644
index cb11825..0000000
--- a/src/google/protobuf/stubs/bytestream_unittest.cc
+++ /dev/null
@@ -1,146 +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 <google/protobuf/stubs/bytestream.h>
-
-#include <stdio.h>
-#include <string.h>
-#include <algorithm>
-
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-namespace google {
-namespace protobuf {
-namespace strings {
-namespace {
-
-// We use this class instead of ArrayByteSource to simulate a ByteSource that
-// contains multiple fragments.  ArrayByteSource returns the entire array in
-// one fragment.
-class MockByteSource : public ByteSource {
- public:
-  MockByteSource(StringPiece data, int block_size)
-    : data_(data), block_size_(block_size) {}
-
-  size_t Available() const { return data_.size(); }
-  StringPiece Peek() {
-    return data_.substr(0, block_size_);
-  }
-  void Skip(size_t n) { data_.remove_prefix(n); }
-
- private:
-  StringPiece data_;
-  int block_size_;
-};
-
-TEST(ByteSourceTest, CopyTo) {
-  StringPiece data("Hello world!");
-  MockByteSource source(data, 3);
-  std::string str;
-  StringByteSink sink(&str);
-
-  source.CopyTo(&sink, data.size());
-  EXPECT_EQ(data, str);
-}
-
-TEST(ByteSourceTest, CopySubstringTo) {
-  StringPiece data("Hello world!");
-  MockByteSource source(data, 3);
-  source.Skip(1);
-  std::string str;
-  StringByteSink sink(&str);
-
-  source.CopyTo(&sink, data.size() - 2);
-  EXPECT_EQ(data.substr(1, data.size() - 2), str);
-  EXPECT_EQ("!", source.Peek());
-}
-
-TEST(ByteSourceTest, LimitByteSource) {
-  StringPiece data("Hello world!");
-  MockByteSource source(data, 3);
-  LimitByteSource limit_source(&source, 6);
-  EXPECT_EQ(6, limit_source.Available());
-  limit_source.Skip(1);
-  EXPECT_EQ(5, limit_source.Available());
-
-  {
-    std::string str;
-    StringByteSink sink(&str);
-    limit_source.CopyTo(&sink, limit_source.Available());
-    EXPECT_EQ("ello ", str);
-    EXPECT_EQ(0, limit_source.Available());
-    EXPECT_EQ(6, source.Available());
-  }
-
-  {
-    std::string str;
-    StringByteSink sink(&str);
-    source.CopyTo(&sink, source.Available());
-    EXPECT_EQ("world!", str);
-    EXPECT_EQ(0, source.Available());
-  }
-}
-
-TEST(ByteSourceTest, CopyToStringByteSink) {
-  StringPiece data("Hello world!");
-  MockByteSource source(data, 3);
-  std::string str;
-  StringByteSink sink(&str);
-  source.CopyTo(&sink, data.size());
-  EXPECT_EQ(data, str);
-}
-
-// Verify that ByteSink is subclassable and Flush() overridable.
-class FlushingByteSink : public StringByteSink {
- public:
-  explicit FlushingByteSink(std::string* dest) : StringByteSink(dest) {}
-  virtual void Flush() { Append("z", 1); }
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FlushingByteSink);
-};
-
-// Write and Flush via the ByteSink superclass interface.
-void WriteAndFlush(ByteSink* s) {
-  s->Append("abc", 3);
-  s->Flush();
-}
-
-TEST(ByteSinkTest, Flush) {
-  std::string str;
-  FlushingByteSink f_sink(&str);
-  WriteAndFlush(&f_sink);
-  EXPECT_STREQ("abcz", str.c_str());
-}
-
-}  // namespace
-}  // namespace strings
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/callback.h b/src/google/protobuf/stubs/callback.h
index 43d546d..ed4b9f7 100644
--- a/src/google/protobuf/stubs/callback.h
+++ b/src/google/protobuf/stubs/callback.h
@@ -1,11 +1,39 @@
+// 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_STUBS_CALLBACK_H_
 #define GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
 
 #include <type_traits>
 
-#include <google/protobuf/stubs/macros.h>
-
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 // ===================================================================
 // emulates google3/base/callback.h
@@ -73,48 +101,44 @@
 class PROTOBUF_EXPORT Closure {
  public:
   Closure() {}
+  Closure(const Closure&) = delete;
+  Closure& operator=(const Closure&) = delete;
   virtual ~Closure();
 
   virtual void Run() = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Closure);
 };
 
 template<typename R>
 class ResultCallback {
  public:
   ResultCallback() {}
+  ResultCallback(const ResultCallback&) = delete;
+  ResultCallback& operator=(const ResultCallback&) = delete;
   virtual ~ResultCallback() {}
 
   virtual R Run() = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback);
 };
 
 template <typename R, typename A1>
 class PROTOBUF_EXPORT ResultCallback1 {
  public:
   ResultCallback1() {}
+  ResultCallback1(const ResultCallback1&) = delete;
+  ResultCallback1& operator=(const ResultCallback1&) = delete;
   virtual ~ResultCallback1() {}
 
   virtual R Run(A1) = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback1);
 };
 
 template <typename R, typename A1, typename A2>
 class PROTOBUF_EXPORT ResultCallback2 {
  public:
   ResultCallback2() {}
+  ResultCallback2(const ResultCallback2&) = delete;
+  ResultCallback2& operator=(const ResultCallback2&) = delete;
   virtual ~ResultCallback2() {}
 
   virtual R Run(A1,A2) = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ResultCallback2);
 };
 
 namespace internal {
@@ -578,6 +602,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_STUBS_CALLBACK_H_
diff --git a/src/google/protobuf/stubs/casts.h b/src/google/protobuf/stubs/casts.h
deleted file mode 100644
index ad29dac..0000000
--- a/src/google/protobuf/stubs/casts.h
+++ /dev/null
@@ -1,138 +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.
-
-#ifndef GOOGLE_PROTOBUF_CASTS_H__
-#define GOOGLE_PROTOBUF_CASTS_H__
-
-#include <google/protobuf/stubs/common.h>
-
-#include <google/protobuf/port_def.inc>
-#include <type_traits>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-// Use implicit_cast as a safe version of static_cast or const_cast
-// for upcasting in the type hierarchy (i.e. casting a pointer to Foo
-// to a pointer to SuperclassOfFoo or casting a pointer to Foo to
-// a const pointer to Foo).
-// 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 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.:
-//
-//   implicit_cast<ToType>(expr)
-//
-// implicit_cast would have been part of the C++ standard library,
-// but the proposal was submitted too late.  It will probably make
-// its way into the language in the future.
-template<typename To, typename From>
-inline To implicit_cast(From const &f) {
-  return f;
-}
-
-// When you upcast (that is, cast a pointer from type Foo to type
-// SuperclassOfFoo), it's fine to use implicit_cast<>, since upcasts
-// always succeed.  When you downcast (that is, cast a pointer from
-// type Foo to type SubclassOfFoo), static_cast<> isn't safe, because
-// how do you know the pointer is really of type SubclassOfFoo?  It
-// could be a bare Foo, or of type DifferentSubclassOfFoo.  Thus,
-// when you downcast, you should use this macro.  In debug mode, we
-// use dynamic_cast<> to double-check the downcast is legal (we die
-// if it's not).  In normal mode, we do the efficient static_cast<>
-// instead.  Thus, it's important to test in debug mode to make sure
-// the cast is legal!
-//    This is the only place in the code we should use dynamic_cast<>.
-// In particular, you SHOULDN'T be using dynamic_cast<> in order to
-// do RTTI (eg code like this:
-//    if (dynamic_cast<Subclass1>(foo)) HandleASubclass1Object(foo);
-//    if (dynamic_cast<Subclass2>(foo)) HandleASubclass2Object(foo);
-// You should design the code some other way not to need this.
-
-template<typename To, typename From>     // use like this: down_cast<T*>(foo);
-inline To down_cast(From* f) {                   // so we only accept pointers
-  // Ensures that To is a sub-type of From *.  This test is here only
-  // for compile-time type checking, and has no overhead in an
-  // optimized build at run-time, as it will be optimized away
-  // completely.
-  if (false) {
-    implicit_cast<From*, To>(0);
-  }
-
-#if !defined(NDEBUG) && PROTOBUF_RTTI
-  assert(f == nullptr || dynamic_cast<To>(f) != nullptr);  // RTTI: debug mode only!
-#endif
-  return static_cast<To>(f);
-}
-
-template<typename To, typename From>    // use like this: down_cast<T&>(foo);
-inline To down_cast(From& f) {
-  typedef typename std::remove_reference<To>::type* ToAsPointer;
-  // Ensures that To is a sub-type of From *.  This test is here only
-  // for compile-time type checking, and has no overhead in an
-  // optimized build at run-time, as it will be optimized away
-  // completely.
-  if (false) {
-    implicit_cast<From*, ToAsPointer>(0);
-  }
-
-#if !defined(NDEBUG) && PROTOBUF_RTTI
-  // RTTI: debug mode only!
-  assert(dynamic_cast<ToAsPointer>(&f) != nullptr);
-#endif
-  return *static_cast<ToAsPointer>(&f);
-}
-
-template<typename To, typename From>
-inline To bit_cast(const From& from) {
-  static_assert(sizeof(From) == sizeof(To), "bit_cast_with_different_sizes");
-  To dest;
-  memcpy(&dest, &from, sizeof(dest));
-  return dest;
-}
-
-}  // namespace internal
-
-// We made these internal so that they would show up as such in the docs,
-// but we don't want to stick "internal::" in front of them everywhere.
-using internal::implicit_cast;
-using internal::down_cast;
-using internal::bit_cast;
-
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_CASTS_H__
diff --git a/src/google/protobuf/stubs/common.cc b/src/google/protobuf/stubs/common.cc
index e0a807f..b029e09 100644
--- a/src/google/protobuf/stubs/common.cc
+++ b/src/google/protobuf/stubs/common.cc
@@ -30,12 +30,13 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
+
+#include <errno.h>
+#include <stdio.h>
 
 #include <atomic>
-#include <errno.h>
 #include <sstream>
-#include <stdio.h>
 #include <vector>
 
 #ifdef _WIN32
@@ -49,15 +50,14 @@
 #include <android/log.h>
 #endif
 
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/stringpiece.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/int128.h>
+#include "absl/status/status.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/logging.h"
 
-#include <google/protobuf/port_def.inc>
+// Must be last.
+#include "google/protobuf/port_def.inc"  // NOLINT
 
 namespace google {
 namespace protobuf {
@@ -108,6 +108,21 @@
   return buffer;
 }
 
+std::string ProtocVersionString(int version) {
+  int minor = (version / 1000) % 1000;
+  int micro = version % 1000;
+
+  // 128 bytes should always be enough, but we use snprintf() anyway to be
+  // safe.
+  char buffer[128];
+  snprintf(buffer, sizeof(buffer), "%d.%d", minor, micro);
+
+  // Guard against broken MSVC snprintf().
+  buffer[sizeof(buffer) - 1] = '\0';
+
+  return buffer;
+}
+
 }  // namespace internal
 
 // ===================================================================
@@ -178,7 +193,7 @@
 }
 
 static LogHandler* log_handler_ = &DefaultLogHandler;
-static std::atomic<int> log_silencer_count_ = ATOMIC_VAR_INIT(0);
+static std::atomic<int> log_silencer_count_{0};
 
 LogMessage& LogMessage::operator<<(const std::string& value) {
   message_ += value;
@@ -190,36 +205,29 @@
   return *this;
 }
 
-LogMessage& LogMessage::operator<<(const StringPiece& value) {
-  message_ += value.ToString();
+LogMessage& LogMessage::operator<<(absl::string_view value) {
+  absl::StrAppend(&message_, value);
   return *this;
 }
 
-LogMessage& LogMessage::operator<<(const util::Status& status) {
+LogMessage& LogMessage::operator<<(const absl::Status& status) {
   message_ += status.ToString();
   return *this;
 }
 
-LogMessage& LogMessage::operator<<(const uint128& value) {
-  std::ostringstream str;
-  str << value;
-  message_ += str.str();
-  return *this;
-}
-
 LogMessage& LogMessage::operator<<(char value) {
-  return *this << StringPiece(&value, 1);
+  return *this << absl::string_view(&value, 1);
 }
 
 LogMessage& LogMessage::operator<<(void* value) {
-  StrAppend(&message_, strings::Hex(reinterpret_cast<uintptr_t>(value)));
+  absl::StrAppend(&message_, absl::Hex(reinterpret_cast<uintptr_t>(value)));
   return *this;
 }
 
 #undef DECLARE_STREAM_OPERATOR
 #define DECLARE_STREAM_OPERATOR(TYPE)              \
   LogMessage& LogMessage::operator<<(TYPE value) { \
-    StrAppend(&message_, value);                   \
+    absl::StrAppend(&message_, value);             \
     return *this;                                  \
   }
 
@@ -321,4 +329,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"  // NOLINT
diff --git a/src/google/protobuf/stubs/common.h b/src/google/protobuf/stubs/common.h
index a57165f..e81c24f 100644
--- a/src/google/protobuf/stubs/common.h
+++ b/src/google/protobuf/stubs/common.h
@@ -43,10 +43,27 @@
 #include <string>
 #include <vector>
 
-#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>
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/platform_macros.h"
+#include "google/protobuf/stubs/port.h"
+
+// Enforce C++14 as the minimum.
+#if defined(_MSVC_LANG)
+#if _MSVC_LANG < 201402L
+#error "C++ versions less than C++14 are not supported."
+#endif  // _MSVC_LANG < 201402L
+#elif defined(__cplusplus)
+// Special-case GCC < 5.0, as it has a strange __cplusplus value for C++14
+#if defined(__GNUC__) && __GNUC__ < 5
+#if __cplusplus < 201300L
+#error "C++ versions less than C++14 are not supported."
+#endif  // __cplusplus < 201300L
+#else // defined(__GNUC__) && __GNUC__ < 5
+#if __cplusplus < 201402L
+#error "C++ versions less than C++14 are not supported."
+#endif  // __cplusplus < 201402L
+#endif // defined(__GNUC__) && __GNUC__ < 5
+#endif
 
 #ifndef PROTOBUF_USE_EXCEPTIONS
 #if defined(_MSC_VER) && defined(_CPPUNWIND)
@@ -69,7 +86,7 @@
 #include <pthread.h>
 #endif
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace std {}
 
@@ -106,7 +123,12 @@
                                    const char* filename);
 
 // Converts a numeric version number to a string.
-std::string PROTOBUF_EXPORT VersionString(int version);
+std::string PROTOBUF_EXPORT
+VersionString(int version);  // NOLINT(runtime/string)
+
+// Prints the protoc compiler version (no major version)
+std::string PROTOBUF_EXPORT
+ProtocVersionString(int version);  // NOLINT(runtime/string)
 
 }  // namespace internal
 
@@ -120,39 +142,6 @@
     __FILE__)
 
 
-// ===================================================================
-// from google3/util/utf8/public/unilib.h
-
-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(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(StringPiece str);
-
-// Coerce UTF-8 byte string in src_str to be
-// a structurally-valid equal-length string by selectively
-// overwriting illegal bytes with replace_char (typically ' ' or '?').
-// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
-// src_str is read-only.
-//
-// Returns pointer to output buffer, src_str.data() if no changes were made,
-//  or idst if some bytes were changed. idst is allocated by the caller
-//  and must be at least as big as src_str
-//
-// Optimized for: all structurally valid and no byte copying is done.
-//
-PROTOBUF_EXPORT char* UTF8CoerceToStructurallyValid(StringPiece str, char* dst,
-                                                    char replace_char);
-
-}  // namespace internal
-
 // This lives in message_lite.h now, but we leave this here for any users that
 // #include common.h and not message_lite.h.
 PROTOBUF_EXPORT void ShutdownProtobufLibrary();
@@ -192,6 +181,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_COMMON_H__
diff --git a/src/google/protobuf/stubs/common_unittest.cc b/src/google/protobuf/stubs/common_unittest.cc
index c55e452..71058c0 100644
--- a/src/google/protobuf/stubs/common_unittest.cc
+++ b/src/google/protobuf/stubs/common_unittest.cc
@@ -30,17 +30,18 @@
 
 // Author: kenton@google.com (Kenton Varda)
 
-#include <vector>
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/substitute.h>
+#include "google/protobuf/stubs/common.h"
 
-#include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
 
+#include <vector>
+
+#include "absl/strings/ascii.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/testing/googletest.h"
+
 namespace google {
 namespace protobuf {
 namespace {
@@ -56,7 +57,7 @@
   std::string version = PACKAGE_VERSION;
   int pos = 0;
   while (pos < version.size() &&
-         (ascii_isdigit(version[pos]) || version[pos] == '.')) {
+         (absl::ascii_isdigit(version[pos]) || version[pos] == '.')) {
     ++pos;
   }
   version.erase(pos);
@@ -81,9 +82,8 @@
 
 void CaptureLog(LogLevel level, const char* filename, int line,
                 const std::string& message) {
-  captured_messages_.push_back(
-    strings::Substitute("$0 $1:$2: $3",
-      implicit_cast<int>(level), filename, line, message));
+  captured_messages_.push_back(absl::Substitute(
+      "$0 $1:$2: $3", static_cast<int>(level), filename, line, message));
 }
 
 TEST(LoggingTest, DefaultLogging) {
@@ -94,11 +94,14 @@
   GOOGLE_LOG(ERROR  ) << "An error.";
 
   std::string text = GetCapturedTestStderr();
-  EXPECT_EQ(
-    "[libprotobuf INFO " __FILE__ ":" + SimpleItoa(line + 1) + "] A message.\n"
-    "[libprotobuf WARNING " __FILE__ ":" + SimpleItoa(line + 2) + "] A warning.\n"
-    "[libprotobuf ERROR " __FILE__ ":" + SimpleItoa(line + 3) + "] An error.\n",
-    text);
+  EXPECT_EQ(absl::StrCat("[libprotobuf INFO " __FILE__ ":", line + 1,
+                         "] A message.\n"
+                         "[libprotobuf WARNING " __FILE__ ":",
+                         line + 2,
+                         "] A warning.\n"
+                         "[libprotobuf ERROR " __FILE__ ":",
+                         line + 3, "] An error.\n"),
+            text);
 }
 
 TEST(LoggingTest, NullLogging) {
@@ -127,12 +130,10 @@
   EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog);
 
   ASSERT_EQ(2, captured_messages_.size());
-  EXPECT_EQ(
-    "2 " __FILE__ ":" + SimpleItoa(start_line + 1) + ": An error.",
-    captured_messages_[0]);
-  EXPECT_EQ(
-    "1 " __FILE__ ":" + SimpleItoa(start_line + 2) + ": A warning.",
-    captured_messages_[1]);
+  EXPECT_EQ(absl::StrCat("2 " __FILE__ ":", start_line + 1, ": An error."),
+            captured_messages_[0]);
+  EXPECT_EQ(absl::StrCat("1 " __FILE__ ":", start_line + 2, ": A warning."),
+            captured_messages_[1]);
 }
 
 TEST(LoggingTest, SilenceLogging) {
@@ -153,12 +154,10 @@
   EXPECT_TRUE(SetLogHandler(old_handler) == &CaptureLog);
 
   ASSERT_EQ(2, captured_messages_.size());
-  EXPECT_EQ(
-    "0 " __FILE__ ":" + SimpleItoa(line1) + ": Visible1",
-    captured_messages_[0]);
-  EXPECT_EQ(
-    "0 " __FILE__ ":" + SimpleItoa(line2) + ": Visible2",
-    captured_messages_[1]);
+  EXPECT_EQ(absl::StrCat("0 " __FILE__ ":", line1, ": Visible1"),
+            captured_messages_[0]);
+  EXPECT_EQ(absl::StrCat("0 " __FILE__ ":", line2, ": Visible2"),
+            captured_messages_[1]);
 }
 
 class ClosureTest : public testing::Test {
diff --git a/src/google/protobuf/stubs/hash.h b/src/google/protobuf/stubs/hash.h
deleted file mode 100644
index a7ec068..0000000
--- a/src/google/protobuf/stubs/hash.h
+++ /dev/null
@@ -1,114 +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)
-
-#ifndef GOOGLE_PROTOBUF_STUBS_HASH_H__
-#define GOOGLE_PROTOBUF_STUBS_HASH_H__
-
-#include <cstring>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START \
-  namespace google {                                      \
-  namespace protobuf {
-# define GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END }}
-
-namespace google {
-namespace protobuf {
-
-template <typename Key>
-struct hash : public std::hash<Key> {};
-
-template <typename Key>
-struct hash<const Key*> {
-  inline size_t operator()(const Key* key) const {
-    return reinterpret_cast<size_t>(key);
-  }
-};
-
-// Unlike the old SGI version, the TR1 "hash" does not special-case char*.  So,
-// we go ahead and provide our own implementation.
-template <>
-struct hash<const char*> {
-  inline size_t operator()(const char* str) const {
-    size_t result = 0;
-    for (; *str != '\0'; str++) {
-      result = 5 * result + static_cast<size_t>(*str);
-    }
-    return result;
-  }
-};
-
-template<>
-struct hash<bool> {
-  size_t operator()(bool x) const {
-    return static_cast<size_t>(x);
-  }
-};
-
-template <>
-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 std::string& a, const std::string& b) const {
-    return a < b;
-  }
-};
-
-template <typename First, typename Second>
-struct hash<std::pair<First, Second> > {
-  inline size_t operator()(const std::pair<First, Second>& key) const {
-    size_t first_hash = hash<First>()(key.first);
-    size_t second_hash = hash<Second>()(key.second);
-
-    // FIXME(kenton):  What is the best way to compute this hash?  I have
-    // no idea!  This seems a bit better than an XOR.
-    return first_hash * ((1 << 16) - 1) + second_hash;
-  }
-
-  static const size_t bucket_size = 4;
-  static const size_t min_buckets = 8;
-  inline bool operator()(const std::pair<First, Second>& a,
-                           const std::pair<First, Second>& b) const {
-    return a < b;
-  }
-};
-
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_STUBS_HASH_H__
diff --git a/src/google/protobuf/stubs/int128.cc b/src/google/protobuf/stubs/int128.cc
deleted file mode 100644
index a151cfb..0000000
--- a/src/google/protobuf/stubs/int128.cc
+++ /dev/null
@@ -1,193 +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 <google/protobuf/stubs/int128.h>
-
-#include <iomanip>
-#include <ostream>  // NOLINT(readability/streams)
-#include <sstream>
-
-#include <google/protobuf/stubs/logging.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-
-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.
-//
-// For example:
-//   Given: 5 (decimal) == 101 (binary)
-//   Returns: 2
-#define STEP(T, n, pos, sh)                   \
-  do {                                        \
-    if ((n) >= (static_cast<T>(1) << (sh))) { \
-      (n) = (n) >> (sh);                      \
-      (pos) |= (sh);                          \
-    }                                         \
-  } while (0)
-static inline int Fls64(uint64_t n) {
-  GOOGLE_DCHECK_NE(0, n);
-  int pos = 0;
-  STEP(uint64_t, n, pos, 0x20);
-  uint32_t n32 = n;
-  STEP(uint32_t, n32, pos, 0x10);
-  STEP(uint32_t, n32, pos, 0x08);
-  STEP(uint32_t, n32, pos, 0x04);
-  return pos + ((uint64_t{0x3333333322221100u} >> (n32 << 2)) & 0x3);
-}
-#undef STEP
-
-// Like Fls64() above, but returns the 0-based position of the last set bit
-// (i.e., most significant bit) in the given uint128. The argument may not be 0.
-static inline int Fls128(uint128 n) {
-  if (uint64_t hi = Uint128High64(n)) {
-    return Fls64(hi) + 64;
-  }
-  return Fls64(Uint128Low64(n));
-}
-
-void uint128::DivModImpl(uint128 dividend, uint128 divisor,
-                         uint128* quotient_ret, uint128* remainder_ret) {
-  if (divisor == 0) {
-    GOOGLE_LOG(FATAL) << "Division or mod by zero: dividend.hi=" << dividend.hi_
-                      << ", lo=" << dividend.lo_;
-  } else if (dividend < divisor) {
-    *quotient_ret = 0;
-    *remainder_ret = dividend;
-    return;
-  } else {
-    int dividend_bit_length = Fls128(dividend);
-    int divisor_bit_length = Fls128(divisor);
-    int difference = dividend_bit_length - divisor_bit_length;
-    uint128 quotient = 0;
-    while (difference >= 0) {
-      quotient <<= 1;
-      uint128 shifted_divisor = divisor << difference;
-      if (shifted_divisor <= dividend) {
-        dividend -= shifted_divisor;
-        quotient += 1;
-      }
-      difference -= 1;
-    }
-    //record the final quotient and remainder
-    *quotient_ret = quotient;
-    *remainder_ret = dividend;
-  }
-}
-
-
-uint128& uint128::operator/=(const uint128& divisor) {
-  uint128 quotient = 0;
-  uint128 remainder = 0;
-  DivModImpl(*this, divisor, &quotient, &remainder);
-  *this = quotient;
-  return *this;
-}
-uint128& uint128::operator%=(const uint128& divisor) {
-  uint128 quotient = 0;
-  uint128 remainder = 0;
-  DivModImpl(*this, divisor, &quotient, &remainder);
-  *this = remainder;
-  return *this;
-}
-
-std::ostream& operator<<(std::ostream& o, const uint128& b) {
-  std::ios_base::fmtflags flags = o.flags();
-
-  // Select a divisor which is the largest power of the base < 2^64.
-  uint128 div;
-  std::streamsize div_base_log;
-  switch (flags & std::ios::basefield) {
-    case std::ios::hex:
-      div =
-          static_cast<uint64_t>(uint64_t{0x1000000000000000u});  // 16^15
-      div_base_log = 15;
-      break;
-    case std::ios::oct:
-      div = static_cast<uint64_t>(
-          uint64_t{01000000000000000000000u});  // 8^21
-      div_base_log = 21;
-      break;
-    default:  // std::ios::dec
-      div = static_cast<uint64_t>(
-          uint64_t{10000000000000000000u});  // 10^19
-      div_base_log = 19;
-      break;
-  }
-
-  // Now piece together the uint128 representation from three chunks of
-  // the original value, each less than "div" and therefore representable
-  // as a uint64.
-  std::ostringstream os;
-  std::ios_base::fmtflags copy_mask =
-      std::ios::basefield | std::ios::showbase | std::ios::uppercase;
-  os.setf(flags & copy_mask, copy_mask);
-  uint128 high = b;
-  uint128 low;
-  uint128::DivModImpl(high, div, &high, &low);
-  uint128 mid;
-  uint128::DivModImpl(high, div, &high, &mid);
-  if (high.lo_ != 0) {
-    os << high.lo_;
-    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
-    os << mid.lo_;
-    os << std::setw(div_base_log);
-  } else if (mid.lo_ != 0) {
-    os << mid.lo_;
-    os << std::noshowbase << std::setfill('0') << std::setw(div_base_log);
-  }
-  os << low.lo_;
-  std::string rep = os.str();
-
-  // Add the requisite padding.
-  std::streamsize width = o.width(0);
-  auto repSize = static_cast<std::streamsize>(rep.size());
-  if (width > repSize) {
-    if ((flags & std::ios::adjustfield) == std::ios::left) {
-      rep.append(width - repSize, o.fill());
-    } else {
-      rep.insert(static_cast<std::string::size_type>(0), width - repSize,
-                 o.fill());
-    }
-  }
-
-  // Stream the final representation in a single "<<" call.
-  return o << rep;
-}
-
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>  // NOLINT
diff --git a/src/google/protobuf/stubs/int128.h b/src/google/protobuf/stubs/int128.h
deleted file mode 100644
index 92d7bdf..0000000
--- a/src/google/protobuf/stubs/int128.h
+++ /dev/null
@@ -1,387 +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_STUBS_INT128_H_
-#define GOOGLE_PROTOBUF_STUBS_INT128_H_
-
-#include <google/protobuf/stubs/common.h>
-
-#include <iosfwd>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-
-struct uint128_pod;
-
-// TODO(xiaofeng): Define GOOGLE_PROTOBUF_HAS_CONSTEXPR when constexpr is
-// available.
-#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
-# define UINT128_CONSTEXPR constexpr
-#else
-# define UINT128_CONSTEXPR
-#endif
-
-// An unsigned 128-bit integer type. Thread-compatible.
-class PROTOBUF_EXPORT uint128 {
- public:
-  UINT128_CONSTEXPR uint128();  // Sets to 0, but don't trust on this behavior.
-  UINT128_CONSTEXPR uint128(uint64_t top, uint64_t bottom);
-#ifndef SWIG
-  UINT128_CONSTEXPR uint128(int bottom);
-  UINT128_CONSTEXPR uint128(uint32_t bottom);   // Top 96 bits = 0
-#endif
-  UINT128_CONSTEXPR uint128(uint64_t bottom);   // hi_ = 0
-  UINT128_CONSTEXPR uint128(const uint128_pod &val);
-
-  // Trivial copy constructor, assignment operator and destructor.
-
-  void Initialize(uint64_t top, uint64_t bottom);
-
-  // Arithmetic operators.
-  uint128& operator+=(const uint128& b);
-  uint128& operator-=(const uint128& b);
-  uint128& operator*=(const uint128& b);
-  // Long division/modulo for uint128.
-  uint128& operator/=(const uint128& b);
-  uint128& operator%=(const uint128& b);
-  uint128 operator++(int);
-  uint128 operator--(int);
-  uint128& operator<<=(int);
-  uint128& operator>>=(int);
-  uint128& operator&=(const uint128& b);
-  uint128& operator|=(const uint128& b);
-  uint128& operator^=(const uint128& b);
-  uint128& operator++();
-  uint128& operator--();
-
-  friend uint64_t Uint128Low64(const uint128& v);
-  friend uint64_t Uint128High64(const uint128& v);
-
-  // We add "std::" to avoid including all of port.h.
-  PROTOBUF_EXPORT friend std::ostream& operator<<(std::ostream& o,
-                                                  const uint128& b);
-
- private:
-  static void DivModImpl(uint128 dividend, uint128 divisor,
-                         uint128* quotient_ret, uint128* remainder_ret);
-
-  // Little-endian memory order optimizations can benefit from
-  // having lo_ first, hi_ last.
-  // See util/endian/endian.h and Load128/Store128 for storing a uint128.
-  uint64_t lo_;
-  uint64_t hi_;
-
-  // Not implemented, just declared for catching automatic type conversions.
-  uint128(uint8_t);
-  uint128(uint16_t);
-  uint128(float v);
-  uint128(double v);
-};
-
-// This is a POD form of uint128 which can be used for static variables which
-// need to be operated on as uint128.
-struct uint128_pod {
-  // Note: The ordering of fields is different than 'class uint128' but the
-  // same as its 2-arg constructor.  This enables more obvious initialization
-  // of static instances, which is the primary reason for this struct in the
-  // first place.  This does not seem to defeat any optimizations wrt
-  // operations involving this struct.
-  uint64_t hi;
-  uint64_t lo;
-};
-
-PROTOBUF_EXPORT extern const uint128_pod kuint128max;
-
-// allow uint128 to be logged
-PROTOBUF_EXPORT extern std::ostream& operator<<(std::ostream& o,
-                                                const uint128& b);
-
-// Methods to access low and high pieces of 128-bit value.
-// Defined externally from uint128 to facilitate conversion
-// to native 128-bit types when compilers support them.
-inline uint64_t Uint128Low64(const uint128& v) { return v.lo_; }
-inline uint64_t Uint128High64(const uint128& v) { return v.hi_; }
-
-// TODO: perhaps it would be nice to have int128, a signed 128-bit type?
-
-// --------------------------------------------------------------------------
-//                      Implementation details follow
-// --------------------------------------------------------------------------
-inline bool operator==(const uint128& lhs, const uint128& rhs) {
-  return (Uint128Low64(lhs) == Uint128Low64(rhs) &&
-          Uint128High64(lhs) == Uint128High64(rhs));
-}
-inline bool operator!=(const uint128& lhs, const uint128& rhs) {
-  return !(lhs == rhs);
-}
-
-inline UINT128_CONSTEXPR uint128::uint128() : lo_(0), hi_(0) {}
-inline UINT128_CONSTEXPR uint128::uint128(uint64_t top, uint64_t bottom)
-    : lo_(bottom), hi_(top) {}
-inline UINT128_CONSTEXPR uint128::uint128(const uint128_pod& v)
-    : lo_(v.lo), hi_(v.hi) {}
-inline UINT128_CONSTEXPR uint128::uint128(uint64_t bottom)
-    : lo_(bottom), hi_(0) {}
-#ifndef SWIG
-inline UINT128_CONSTEXPR uint128::uint128(uint32_t bottom)
-    : lo_(bottom), hi_(0) {}
-inline UINT128_CONSTEXPR uint128::uint128(int bottom)
-    : lo_(bottom), hi_(static_cast<int64_t>((bottom < 0) ? -1 : 0)) {}
-#endif
-
-#undef UINT128_CONSTEXPR
-
-inline void uint128::Initialize(uint64_t top, uint64_t bottom) {
-  hi_ = top;
-  lo_ = bottom;
-}
-
-// Comparison operators.
-
-#define CMP128(op)                                                \
-inline bool operator op(const uint128& lhs, const uint128& rhs) { \
-  return (Uint128High64(lhs) == Uint128High64(rhs)) ?             \
-      (Uint128Low64(lhs) op Uint128Low64(rhs)) :                  \
-      (Uint128High64(lhs) op Uint128High64(rhs));                 \
-}
-
-CMP128(<)
-CMP128(>)
-CMP128(>=)
-CMP128(<=)
-
-#undef CMP128
-
-// Unary operators
-
-inline uint128 operator-(const uint128& val) {
-  const uint64_t hi_flip = ~Uint128High64(val);
-  const uint64_t lo_flip = ~Uint128Low64(val);
-  const uint64_t lo_add = lo_flip + 1;
-  if (lo_add < lo_flip) {
-    return uint128(hi_flip + 1, lo_add);
-  }
-  return uint128(hi_flip, lo_add);
-}
-
-inline bool operator!(const uint128& val) {
-  return !Uint128High64(val) && !Uint128Low64(val);
-}
-
-// Logical operators.
-
-inline uint128 operator~(const uint128& val) {
-  return uint128(~Uint128High64(val), ~Uint128Low64(val));
-}
-
-#define LOGIC128(op)                                                 \
-inline uint128 operator op(const uint128& lhs, const uint128& rhs) { \
-  return uint128(Uint128High64(lhs) op Uint128High64(rhs),           \
-                 Uint128Low64(lhs) op Uint128Low64(rhs));            \
-}
-
-LOGIC128(|)
-LOGIC128(&)
-LOGIC128(^)
-
-#undef LOGIC128
-
-#define LOGICASSIGN128(op)                                   \
-inline uint128& uint128::operator op(const uint128& other) { \
-  hi_ op other.hi_;                                          \
-  lo_ op other.lo_;                                          \
-  return *this;                                              \
-}
-
-LOGICASSIGN128(|=)
-LOGICASSIGN128(&=)
-LOGICASSIGN128(^=)
-
-#undef LOGICASSIGN128
-
-// Shift operators.
-
-inline uint128 operator<<(const uint128& val, int amount) {
-  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
-  if (amount < 64) {
-    if (amount == 0) {
-      return val;
-    }
-    uint64_t new_hi = (Uint128High64(val) << amount) |
-                      (Uint128Low64(val) >> (64 - amount));
-    uint64_t new_lo = Uint128Low64(val) << amount;
-    return uint128(new_hi, new_lo);
-  } else if (amount < 128) {
-    return uint128(Uint128Low64(val) << (amount - 64), 0);
-  } else {
-    return uint128(0, 0);
-  }
-}
-
-inline uint128 operator>>(const uint128& val, int amount) {
-  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
-  if (amount < 64) {
-    if (amount == 0) {
-      return val;
-    }
-    uint64_t new_hi = Uint128High64(val) >> amount;
-    uint64_t new_lo = (Uint128Low64(val) >> amount) |
-                      (Uint128High64(val) << (64 - amount));
-    return uint128(new_hi, new_lo);
-  } else if (amount < 128) {
-    return uint128(0, Uint128High64(val) >> (amount - 64));
-  } else {
-    return uint128(0, 0);
-  }
-}
-
-inline uint128& uint128::operator<<=(int amount) {
-  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
-  if (amount < 64) {
-    if (amount != 0) {
-      hi_ = (hi_ << amount) | (lo_ >> (64 - amount));
-      lo_ = lo_ << amount;
-    }
-  } else if (amount < 128) {
-    hi_ = lo_ << (amount - 64);
-    lo_ = 0;
-  } else {
-    hi_ = 0;
-    lo_ = 0;
-  }
-  return *this;
-}
-
-inline uint128& uint128::operator>>=(int amount) {
-  // uint64 shifts of >= 64 are undefined, so we will need some special-casing.
-  if (amount < 64) {
-    if (amount != 0) {
-      lo_ = (lo_ >> amount) | (hi_ << (64 - amount));
-      hi_ = hi_ >> amount;
-    }
-  } else if (amount < 128) {
-    lo_ = hi_ >> (amount - 64);
-    hi_ = 0;
-  } else {
-    lo_ = 0;
-    hi_ = 0;
-  }
-  return *this;
-}
-
-inline uint128 operator+(const uint128& lhs, const uint128& rhs) {
-  return uint128(lhs) += rhs;
-}
-
-inline uint128 operator-(const uint128& lhs, const uint128& rhs) {
-  return uint128(lhs) -= rhs;
-}
-
-inline uint128 operator*(const uint128& lhs, const uint128& rhs) {
-  return uint128(lhs) *= rhs;
-}
-
-inline uint128 operator/(const uint128& lhs, const uint128& rhs) {
-  return uint128(lhs) /= rhs;
-}
-
-inline uint128 operator%(const uint128& lhs, const uint128& rhs) {
-  return uint128(lhs) %= rhs;
-}
-
-inline uint128& uint128::operator+=(const uint128& b) {
-  hi_ += b.hi_;
-  uint64_t lolo = lo_ + b.lo_;
-  if (lolo < lo_)
-    ++hi_;
-  lo_ = lolo;
-  return *this;
-}
-
-inline uint128& uint128::operator-=(const uint128& b) {
-  hi_ -= b.hi_;
-  if (b.lo_ > lo_)
-    --hi_;
-  lo_ -= b.lo_;
-  return *this;
-}
-
-inline uint128& uint128::operator*=(const uint128& b) {
-  uint64_t a96 = hi_ >> 32;
-  uint64_t a64 = hi_ & 0xffffffffu;
-  uint64_t a32 = lo_ >> 32;
-  uint64_t a00 = lo_ & 0xffffffffu;
-  uint64_t b96 = b.hi_ >> 32;
-  uint64_t b64 = b.hi_ & 0xffffffffu;
-  uint64_t b32 = b.lo_ >> 32;
-  uint64_t b00 = b.lo_ & 0xffffffffu;
-  // multiply [a96 .. a00] x [b96 .. b00]
-  // terms higher than c96 disappear off the high side
-  // terms c96 and c64 are safe to ignore carry bit
-  uint64_t c96 = a96 * b00 + a64 * b32 + a32 * b64 + a00 * b96;
-  uint64_t c64 = a64 * b00 + a32 * b32 + a00 * b64;
-  this->hi_ = (c96 << 32) + c64;
-  this->lo_ = 0;
-  // add terms after this one at a time to capture carry
-  *this += uint128(a32 * b00) << 32;
-  *this += uint128(a00 * b32) << 32;
-  *this += a00 * b00;
-  return *this;
-}
-
-inline uint128 uint128::operator++(int) {
-  uint128 tmp(*this);
-  *this += 1;
-  return tmp;
-}
-
-inline uint128 uint128::operator--(int) {
-  uint128 tmp(*this);
-  *this -= 1;
-  return tmp;
-}
-
-inline uint128& uint128::operator++() {
-  *this += 1;
-  return *this;
-}
-
-inline uint128& uint128::operator--() {
-  *this -= 1;
-  return *this;
-}
-
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_INT128_H_
diff --git a/src/google/protobuf/stubs/int128_unittest.cc b/src/google/protobuf/stubs/int128_unittest.cc
deleted file mode 100644
index b1634f0..0000000
--- a/src/google/protobuf/stubs/int128_unittest.cc
+++ /dev/null
@@ -1,511 +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 <google/protobuf/stubs/int128.h>
-
-#include <algorithm>
-#include <sstream>
-#include <utility>
-
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-
-TEST(Int128, AllTests) {
-  uint128 zero(0);
-  uint128 one(1);
-  uint128 one_2arg(0, 1);
-  uint128 two(0, 2);
-  uint128 three(0, 3);
-  uint128 big(2000, 2);
-  uint128 big_minus_one(2000, 1);
-  uint128 bigger(2001, 1);
-  uint128 biggest(kuint128max);
-  uint128 high_low(1, 0);
-  uint128 low_high(0, std::numeric_limits<uint64_t>::max());
-  EXPECT_LT(one, two);
-  EXPECT_GT(two, one);
-  EXPECT_LT(one, big);
-  EXPECT_LT(one, big);
-  EXPECT_EQ(one, one_2arg);
-  EXPECT_NE(one, two);
-  EXPECT_GT(big, one);
-  EXPECT_GE(big, two);
-  EXPECT_GE(big, big_minus_one);
-  EXPECT_GT(big, big_minus_one);
-  EXPECT_LT(big_minus_one, big);
-  EXPECT_LE(big_minus_one, big);
-  EXPECT_NE(big_minus_one, big);
-  EXPECT_LT(big, biggest);
-  EXPECT_LE(big, biggest);
-  EXPECT_GT(biggest, big);
-  EXPECT_GE(biggest, big);
-  EXPECT_EQ(big, ~~big);
-  EXPECT_EQ(one, one | one);
-  EXPECT_EQ(big, big | big);
-  EXPECT_EQ(one, one | zero);
-  EXPECT_EQ(one, one & one);
-  EXPECT_EQ(big, big & big);
-  EXPECT_EQ(zero, one & zero);
-  EXPECT_EQ(zero, big & ~big);
-  EXPECT_EQ(zero, one ^ one);
-  EXPECT_EQ(zero, big ^ big);
-  EXPECT_EQ(one, one ^ zero);
-
-  // Shift operators.
-  EXPECT_EQ(big, big << 0);
-  EXPECT_EQ(big, big >> 0);
-  EXPECT_GT(big << 1, big);
-  EXPECT_LT(big >> 1, big);
-  EXPECT_EQ(big, (big << 10) >> 10);
-  EXPECT_EQ(big, (big >> 1) << 1);
-  EXPECT_EQ(one, (one << 80) >> 80);
-  EXPECT_EQ(zero, (one >> 80) << 80);
-  EXPECT_EQ(zero, big >> 128);
-  EXPECT_EQ(zero, big << 128);
-
-  // Shift assignments.
-  uint128 big_copy = big;
-  EXPECT_EQ(big << 0, big_copy <<= 0);
-  big_copy = big;
-  EXPECT_EQ(big >> 0, big_copy >>= 0);
-  big_copy = big;
-  EXPECT_EQ(big << 1, big_copy <<= 1);
-  big_copy = big;
-  EXPECT_EQ(big >> 1, big_copy >>= 1);
-  big_copy = big;
-  EXPECT_EQ(big << 10, big_copy <<= 10);
-  big_copy = big;
-  EXPECT_EQ(big >> 10, big_copy >>= 10);
-  big_copy = big;
-  EXPECT_EQ(big << 64, big_copy <<= 64);
-  big_copy = big;
-  EXPECT_EQ(big >> 64, big_copy >>= 64);
-  big_copy = big;
-  EXPECT_EQ(big << 73, big_copy <<= 73);
-  big_copy = big;
-  EXPECT_EQ(big >> 73, big_copy >>= 73);
-  big_copy = big;
-  EXPECT_EQ(big << 128, big_copy <<= 128);
-  big_copy = big;
-  EXPECT_EQ(big >> 128, big_copy >>= 128);
-
-  EXPECT_EQ(Uint128High64(biggest), std::numeric_limits<uint64_t>::max());
-  EXPECT_EQ(Uint128Low64(biggest), std::numeric_limits<uint64_t>::max());
-  EXPECT_EQ(zero + one, one);
-  EXPECT_EQ(one + one, two);
-  EXPECT_EQ(big_minus_one + one, big);
-  EXPECT_EQ(one - one, zero);
-  EXPECT_EQ(one - zero, one);
-  EXPECT_EQ(zero - one, biggest);
-  EXPECT_EQ(big - big, zero);
-  EXPECT_EQ(big - one, big_minus_one);
-  EXPECT_EQ(big + std::numeric_limits<uint64_t>::max(), bigger);
-  EXPECT_EQ(biggest + 1, zero);
-  EXPECT_EQ(zero - 1, biggest);
-  EXPECT_EQ(high_low - one, low_high);
-  EXPECT_EQ(low_high + one, high_low);
-  EXPECT_EQ(Uint128High64((uint128(1) << 64) - 1), 0);
-  EXPECT_EQ(Uint128Low64((uint128(1) << 64) - 1), std::numeric_limits<uint64_t>::max());
-  EXPECT_TRUE(!!one);
-  EXPECT_TRUE(!!high_low);
-  EXPECT_FALSE(!!zero);
-  EXPECT_FALSE(!one);
-  EXPECT_FALSE(!high_low);
-  EXPECT_TRUE(!zero);
-  EXPECT_TRUE(zero == 0);
-  EXPECT_FALSE(zero != 0);
-  EXPECT_FALSE(one == 0);
-  EXPECT_TRUE(one != 0);
-
-  uint128 test = zero;
-  EXPECT_EQ(++test, one);
-  EXPECT_EQ(test, one);
-  EXPECT_EQ(test++, one);
-  EXPECT_EQ(test, two);
-  EXPECT_EQ(test -= 2, zero);
-  EXPECT_EQ(test, zero);
-  EXPECT_EQ(test += 2, two);
-  EXPECT_EQ(test, two);
-  EXPECT_EQ(--test, one);
-  EXPECT_EQ(test, one);
-  EXPECT_EQ(test--, one);
-  EXPECT_EQ(test, zero);
-  EXPECT_EQ(test |= three, three);
-  EXPECT_EQ(test &= one, one);
-  EXPECT_EQ(test ^= three, two);
-  EXPECT_EQ(test >>= 1, one);
-  EXPECT_EQ(test <<= 1, two);
-
-  EXPECT_EQ(big, -(-big));
-  EXPECT_EQ(two, -((-one) - 1));
-  EXPECT_EQ(kuint128max, -one);
-  EXPECT_EQ(zero, -zero);
-
-  GOOGLE_LOG(INFO) << one;
-  GOOGLE_LOG(INFO) << big_minus_one;
-}
-
-TEST(Int128, PodTests) {
-  uint128_pod pod = { 12345, 67890 };
-  uint128 from_pod(pod);
-  EXPECT_EQ(12345, Uint128High64(from_pod));
-  EXPECT_EQ(67890, Uint128Low64(from_pod));
-
-  uint128 zero(0);
-  uint128_pod zero_pod = {0, 0};
-  uint128 one(1);
-  uint128_pod one_pod = {0, 1};
-  uint128 two(2);
-  uint128_pod two_pod = {0, 2};
-  uint128 three(3);
-  uint128_pod three_pod = {0, 3};
-  uint128 big(1, 0);
-  uint128_pod big_pod = {1, 0};
-
-  EXPECT_EQ(zero, zero_pod);
-  EXPECT_EQ(zero_pod, zero);
-  EXPECT_EQ(zero_pod, zero_pod);
-  EXPECT_EQ(one, one_pod);
-  EXPECT_EQ(one_pod, one);
-  EXPECT_EQ(one_pod, one_pod);
-  EXPECT_EQ(two, two_pod);
-  EXPECT_EQ(two_pod, two);
-  EXPECT_EQ(two_pod, two_pod);
-
-  EXPECT_NE(one, two_pod);
-  EXPECT_NE(one_pod, two);
-  EXPECT_NE(one_pod, two_pod);
-
-  EXPECT_LT(one, two_pod);
-  EXPECT_LT(one_pod, two);
-  EXPECT_LT(one_pod, two_pod);
-  EXPECT_LE(one, one_pod);
-  EXPECT_LE(one_pod, one);
-  EXPECT_LE(one_pod, one_pod);
-  EXPECT_LE(one, two_pod);
-  EXPECT_LE(one_pod, two);
-  EXPECT_LE(one_pod, two_pod);
-
-  EXPECT_GT(two, one_pod);
-  EXPECT_GT(two_pod, one);
-  EXPECT_GT(two_pod, one_pod);
-  EXPECT_GE(two, two_pod);
-  EXPECT_GE(two_pod, two);
-  EXPECT_GE(two_pod, two_pod);
-  EXPECT_GE(two, one_pod);
-  EXPECT_GE(two_pod, one);
-  EXPECT_GE(two_pod, one_pod);
-
-  EXPECT_EQ(three, one | two_pod);
-  EXPECT_EQ(three, one_pod | two);
-  EXPECT_EQ(three, one_pod | two_pod);
-  EXPECT_EQ(one, three & one_pod);
-  EXPECT_EQ(one, three_pod & one);
-  EXPECT_EQ(one, three_pod & one_pod);
-  EXPECT_EQ(two, three ^ one_pod);
-  EXPECT_EQ(two, three_pod ^ one);
-  EXPECT_EQ(two, three_pod ^ one_pod);
-  EXPECT_EQ(two, three & (~one));
-  EXPECT_EQ(three, ~~three);
-
-  EXPECT_EQ(two, two_pod << 0);
-  EXPECT_EQ(two, one_pod << 1);
-  EXPECT_EQ(big, one_pod << 64);
-  EXPECT_EQ(zero, one_pod << 128);
-  EXPECT_EQ(two, two_pod >> 0);
-  EXPECT_EQ(one, two_pod >> 1);
-  EXPECT_EQ(one, big_pod >> 64);
-
-  EXPECT_EQ(one, zero + one_pod);
-  EXPECT_EQ(one, zero_pod + one);
-  EXPECT_EQ(one, zero_pod + one_pod);
-  EXPECT_EQ(one, two - one_pod);
-  EXPECT_EQ(one, two_pod - one);
-  EXPECT_EQ(one, two_pod - one_pod);
-}
-
-TEST(Int128, OperatorAssignReturnRef) {
-  uint128 v(1);
-  (v += 4) -= 3;
-  EXPECT_EQ(2, v);
-}
-
-TEST(Int128, Multiply) {
-  uint128 a, b, c;
-
-  // Zero test.
-  a = 0;
-  b = 0;
-  c = a * b;
-  EXPECT_EQ(0, c);
-
-  // Max carries.
-  a = uint128(0) - 1;
-  b = uint128(0) - 1;
-  c = a * b;
-  EXPECT_EQ(1, c);
-
-  // Self-operation with max carries.
-  c = uint128(0) - 1;
-  c *= c;
-  EXPECT_EQ(1, c);
-
-  // 1-bit x 1-bit.
-  for (int i = 0; i < 64; ++i) {
-    for (int j = 0; j < 64; ++j) {
-      a = uint128(1) << i;
-      b = uint128(1) << j;
-      c = a * b;
-      EXPECT_EQ(uint128(1) << (i+j), c);
-    }
-  }
-
-  // Verified with dc.
-  a = uint128(uint64_t{0xffffeeeeddddccccu}, uint64_t{0xbbbbaaaa99998888u});
-  b = uint128(uint64_t{0x7777666655554444u}, uint64_t{0x3333222211110000u});
-  c = a * b;
-  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(uint64_t{0x0123456789abcdefu}, uint64_t{0xfedcba9876543210u});
-  b = uint128(uint64_t{0x02468ace13579bdfu}, uint64_t{0xfdb97531eca86420u});
-  c = a * b;
-  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));
-}
-
-TEST(Int128, AliasTests) {
-  uint128 x1(1, 2);
-  uint128 x2(2, 4);
-  x1 += x1;
-  EXPECT_EQ(x2, x1);
-
-  uint128 x3(1, static_cast<uint64_t>(1) << 63);
-  uint128 x4(3, 0);
-  x3 += x3;
-  EXPECT_EQ(x4, x3);
-}
-
-#ifdef PROTOBUF_HAS_DEATH_TEST
-TEST(Int128, DivideByZeroCheckFails) {
-  uint128 a = 0;
-  uint128 b = 0;
-  EXPECT_DEATH(a / b, "Division or mod by zero:");
-  a = 123;
-  EXPECT_DEATH(a / b, "Division or mod by zero:");
-}
-
-TEST(Int128, ModByZeroCheckFails) {
-  uint128 a = 0;
-  uint128 b = 0;
-  EXPECT_DEATH(a % b, "Division or mod by zero:");
-  a = 123;
-  EXPECT_DEATH(a % b, "Division or mod by zero:");
-}
-#endif  // PROTOBUF_HAS_DEATH_TEST
-
-TEST(Int128, DivideAndMod) {
-  // a := q * b + r
-  uint128 a, b, q, r;
-
-  // Zero test.
-  a = 0;
-  b = 123;
-  q = a / b;
-  r = a % b;
-  EXPECT_EQ(0, q);
-  EXPECT_EQ(0, r);
-
-  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.
-
-  uint128 result_q, result_r;
-  result_q = a / b;
-  result_r = a % b;
-  EXPECT_EQ(q, result_q);
-  EXPECT_EQ(r, result_r);
-
-  // Try the other way around.
-  std::swap(q, b);
-  result_q = a / b;
-  result_r = a % b;
-  EXPECT_EQ(q, result_q);
-  EXPECT_EQ(r, result_r);
-  // Restore.
-  std::swap(b, q);
-
-  // Dividend < divisor; result should be q:0 r:<dividend>.
-  std::swap(a, b);
-  result_q = a / b;
-  result_r = a % b;
-  EXPECT_EQ(0, result_q);
-  EXPECT_EQ(a, result_r);
-  // Try the other way around.
-  std::swap(a, q);
-  result_q = a / b;
-  result_r = a % b;
-  EXPECT_EQ(0, result_q);
-  EXPECT_EQ(a, result_r);
-  // Restore.
-  std::swap(q, a);
-  std::swap(b, a);
-
-  // Try a large remainder.
-  b = a / 2 + 1;
-  uint128 expected_r(uint64_t{0x29876d3a0e38ea61u},
-                     uint64_t{0xdf92cba98c83ffffu});
-  // Sanity checks.
-  ASSERT_EQ(a / 2 - 1, expected_r);
-  ASSERT_EQ(a, b + expected_r);
-  result_q = a / b;
-  result_r = a % b;
-  EXPECT_EQ(1, result_q);
-  EXPECT_EQ(expected_r, result_r);
-}
-
-static uint64_t RandomUint64() {
-  uint64_t v1 = rand();
-  uint64_t v2 = rand();
-  uint64_t v3 = rand();
-  return v1 * v2 + v3;
-}
-
-TEST(Int128, DivideAndModRandomInputs) {
-  const int kNumIters = 1 << 18;
-  for (int i = 0; i < kNumIters; ++i) {
-    const uint128 a(RandomUint64(), RandomUint64());
-    const uint128 b(RandomUint64(), RandomUint64());
-    if (b == 0) {
-      continue;  // Avoid a div-by-zero.
-    }
-    const uint128 q = a / b;
-    const uint128 r = a % b;
-    ASSERT_EQ(a, b * q + r);
-  }
-}
-
-#ifdef GOOGLE_PROTOBUF_HAS_CONSTEXPR
-TEST(Int128, ConstexprTest) {
-  constexpr uint128 zero;
-  constexpr uint128 one = 1;
-  constexpr uint128_pod pod = {2, 3};
-  constexpr uint128 from_pod = pod;
-  constexpr uint128 minus_two = -2;
-  EXPECT_EQ(one, uint128(1));
-  EXPECT_EQ(from_pod, uint128(2, 3));
-  EXPECT_EQ(minus_two, uint128(-1ULL, -2ULL));
-}
-
-TEST(Int128, Traits) {
-  EXPECT_TRUE(std::is_trivially_copy_constructible<uint128>::value);
-  EXPECT_TRUE(std::is_trivially_copy_assignable<uint128>::value);
-  EXPECT_TRUE(std::is_trivially_destructible<uint128>::value);
-}
-#endif  // GOOGLE_PROTOBUF_HAS_CONSTEXPR
-
-TEST(Int128, OStream) {
-  struct {
-    uint128 val;
-    std::ios_base::fmtflags flags;
-    std::streamsize width;
-    char fill;
-    const char* rep;
-  } cases[] = {
-      // zero with different bases
-      {uint128(0), std::ios::dec, 0, '_', "0"},
-      {uint128(0), std::ios::oct, 0, '_', "0"},
-      {uint128(0), std::ios::hex, 0, '_', "0"},
-      // crossover between lo_ and hi_
-      {uint128(0, -1), std::ios::dec, 0, '_', "18446744073709551615"},
-      {uint128(0, -1), std::ios::oct, 0, '_', "1777777777777777777777"},
-      {uint128(0, -1), std::ios::hex, 0, '_', "ffffffffffffffff"},
-      {uint128(1, 0), std::ios::dec, 0, '_', "18446744073709551616"},
-      {uint128(1, 0), std::ios::oct, 0, '_', "2000000000000000000000"},
-      {uint128(1, 0), std::ios::hex, 0, '_', "10000000000000000"},
-      // just the top bit
-      {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"},
-      {uint128(-1, -1), std::ios::oct, 0, '_',
-       "3777777777777777777777777777777777777777777"},
-      {uint128(-1, -1), std::ios::hex, 0, '_',
-       "ffffffffffffffffffffffffffffffff"},
-      // uppercase
-      {uint128(-1, -1), std::ios::hex | std::ios::uppercase, 0, '_',
-       "FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF"},
-      // showbase
-      {uint128(1), std::ios::dec | std::ios::showbase, 0, '_', "1"},
-      {uint128(1), std::ios::oct | std::ios::showbase, 0, '_', "01"},
-      {uint128(1), std::ios::hex | std::ios::showbase, 0, '_', "0x1"},
-      // showbase does nothing on zero
-      {uint128(0), std::ios::dec | std::ios::showbase, 0, '_', "0"},
-      {uint128(0), std::ios::oct | std::ios::showbase, 0, '_', "0"},
-      {uint128(0), std::ios::hex | std::ios::showbase, 0, '_', "0"},
-      // showpos does nothing on unsigned types
-      {uint128(1), std::ios::dec | std::ios::showpos, 0, '_', "1"},
-      // padding
-      {uint128(9), std::ios::dec, 6, '_', "_____9"},
-      {uint128(12345), std::ios::dec, 6, '_', "_12345"},
-      // left adjustment
-      {uint128(9), std::ios::dec | std::ios::left, 6, '_', "9_____"},
-      {uint128(12345), std::ios::dec | std::ios::left, 6, '_', "12345_"},
-  };
-  for (size_t i = 0; i < GOOGLE_ARRAYSIZE(cases); ++i) {
-    std::ostringstream os;
-    os.flags(cases[i].flags);
-    os.width(cases[i].width);
-    os.fill(cases[i].fill);
-    os << cases[i].val;
-    EXPECT_EQ(cases[i].rep, os.str());
-  }
-}
-}  // 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 8ecc2fa..004c557 100644
--- a/src/google/protobuf/stubs/logging.h
+++ b/src/google/protobuf/stubs/logging.h
@@ -31,12 +31,12 @@
 #ifndef GOOGLE_PROTOBUF_STUBS_LOGGING_H_
 #define GOOGLE_PROTOBUF_STUBS_LOGGING_H_
 
-#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 "absl/status/status.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/stubs/port.h"
 
-#include <google/protobuf/port_def.inc>
+// Must be last.
+#include "google/protobuf/port_def.inc"  // NOLINT
 
 // ===================================================================
 // emulates google3/base/logging.h
@@ -86,8 +86,8 @@
   LogMessage& operator<<(unsigned long long value);
   LogMessage& operator<<(double value);
   LogMessage& operator<<(void* value);
-  LogMessage& operator<<(const StringPiece& value);
-  LogMessage& operator<<(const util::Status& status);
+  LogMessage& operator<<(absl::string_view value);
+  LogMessage& operator<<(const absl::Status& status);
   LogMessage& operator<<(const uint128& value);
 
  private:
@@ -234,6 +234,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"  // NOLINT
 
 #endif  // GOOGLE_PROTOBUF_STUBS_LOGGING_H_
diff --git a/src/google/protobuf/stubs/macros.h b/src/google/protobuf/stubs/macros.h
deleted file mode 100644
index ae9a8b9..0000000
--- a/src/google/protobuf/stubs/macros.h
+++ /dev/null
@@ -1,93 +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_MACROS_H__
-#define GOOGLE_PROTOBUF_MACROS_H__
-
-namespace google {
-namespace protobuf {
-
-#undef GOOGLE_DISALLOW_EVIL_CONSTRUCTORS
-#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() = delete;                                  \
-  TypeName(const TypeName&) = delete;                   \
-  void operator=(const TypeName&) = delete
-
-// ===================================================================
-// from google3/base/basictypes.h
-
-// The GOOGLE_ARRAYSIZE(arr) macro returns the # of elements in an array arr.
-// The expression is a compile-time constant, and therefore can be
-// used in defining new arrays, for example.
-//
-// GOOGLE_ARRAYSIZE catches a few type errors.  If you see a compiler error
-//
-//   "warning: division by zero in ..."
-//
-// when using GOOGLE_ARRAYSIZE, you are (wrongfully) giving it a pointer.
-// You should only use GOOGLE_ARRAYSIZE on statically allocated arrays.
-//
-// The following comments are on the implementation details, and can
-// be ignored by the users.
-//
-// ARRAYSIZE(arr) works by inspecting sizeof(arr) (the # of bytes in
-// the array) and sizeof(*(arr)) (the # of bytes in one array
-// element).  If the former is divisible by the latter, perhaps arr is
-// indeed an array, in which case the division result is the # of
-// elements in the array.  Otherwise, arr cannot possibly be an array,
-// and we generate a compiler error to prevent the code from
-// compiling.
-//
-// Since the size of bool is implementation-defined, we need to cast
-// !(sizeof(a) & sizeof(*(a))) to size_t in order to ensure the final
-// result has type size_t.
-//
-// This macro is not perfect as it wrongfully accepts certain
-// pointers, namely where the pointer size is divisible by the pointee
-// size.  Since all our code has to go through a 32-bit compiler,
-// where a pointer is 4 bytes, this means all pointers to a type whose
-// size is 3 or greater than 4 will be (righteously) rejected.
-//
-// Kudos to Jorg Brown for this simple and elegant implementation.
-
-#undef GOOGLE_ARRAYSIZE
-#define GOOGLE_ARRAYSIZE(a) \
-  ((sizeof(a) / sizeof(*(a))) / \
-   static_cast<size_t>(!(sizeof(a) % sizeof(*(a)))))
-
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_MACROS_H__
diff --git a/src/google/protobuf/stubs/map_util.h b/src/google/protobuf/stubs/map_util.h
deleted file mode 100644
index 24e098a..0000000
--- a/src/google/protobuf/stubs/map_util.h
+++ /dev/null
@@ -1,769 +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.
-
-// from google3/util/gtl/map_util.h
-// Author: Anton Carver
-
-#ifndef GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
-#define GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
-
-#include <stddef.h>
-#include <iterator>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <google/protobuf/stubs/common.h>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-// Local implementation of RemoveConst to avoid including base/type_traits.h.
-template <class T> struct RemoveConst { typedef T type; };
-template <class T> struct RemoveConst<const T> : RemoveConst<T> {};
-}  // namespace internal
-
-//
-// Find*()
-//
-
-// Returns a const reference to the value associated with the given key if it
-// exists. Crashes otherwise.
-//
-// This is intended as a replacement for operator[] as an rvalue (for reading)
-// when the key is guaranteed to exist.
-//
-// operator[] for lookup is discouraged for several reasons:
-//  * It has a side-effect of inserting missing keys
-//  * It is not thread-safe (even when it is not inserting, it can still
-//      choose to resize the underlying storage)
-//  * It invalidates iterators (when it chooses to resize)
-//  * It default constructs a value object even if it doesn't need to
-//
-// This version assumes the key is printable, and includes it in the fatal log
-// message.
-template <class Collection>
-const typename Collection::value_type::second_type&
-FindOrDie(const Collection& collection,
-          const typename Collection::value_type::first_type& key) {
-  typename Collection::const_iterator it = collection.find(key);
-  GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
-  return it->second;
-}
-
-// Same as above, but returns a non-const reference.
-template <class Collection>
-typename Collection::value_type::second_type&
-FindOrDie(Collection& collection,  // NOLINT
-          const typename Collection::value_type::first_type& key) {
-  typename Collection::iterator it = collection.find(key);
-  GOOGLE_CHECK(it != collection.end()) << "Map key not found: " << key;
-  return it->second;
-}
-
-// Same as FindOrDie above, but doesn't log the key on failure.
-template <class Collection>
-const typename Collection::value_type::second_type&
-FindOrDieNoPrint(const Collection& collection,
-                 const typename Collection::value_type::first_type& key) {
-  typename Collection::const_iterator it = collection.find(key);
-  GOOGLE_CHECK(it != collection.end()) << "Map key not found";
-  return it->second;
-}
-
-// Same as above, but returns a non-const reference.
-template <class Collection>
-typename Collection::value_type::second_type&
-FindOrDieNoPrint(Collection& collection,  // NOLINT
-                 const typename Collection::value_type::first_type& key) {
-  typename Collection::iterator it = collection.find(key);
-  GOOGLE_CHECK(it != collection.end()) << "Map key not found";
-  return it->second;
-}
-
-// Returns a const reference to the value associated with the given key if it
-// exists, otherwise returns a const reference to the provided default value.
-//
-// WARNING: If a temporary object is passed as the default "value,"
-// this function will return a reference to that temporary object,
-// which will be destroyed at the end of the statement. A common
-// example: if you have a map with string values, and you pass a char*
-// as the default "value," either use the returned value immediately
-// or store it in a string (not string&).
-// Details: http://go/findwithdefault
-template <class Collection>
-const typename Collection::value_type::second_type&
-FindWithDefault(const Collection& collection,
-                const typename Collection::value_type::first_type& key,
-                const typename Collection::value_type::second_type& value) {
-  typename Collection::const_iterator it = collection.find(key);
-  if (it == collection.end()) {
-    return value;
-  }
-  return it->second;
-}
-
-// Returns a pointer to the const value associated with the given key if it
-// exists, or nullptr otherwise.
-template <class Collection>
-const typename Collection::value_type::second_type*
-FindOrNull(const Collection& collection,
-           const typename Collection::value_type::first_type& key) {
-  typename Collection::const_iterator it = collection.find(key);
-  if (it == collection.end()) {
-    return 0;
-  }
-  return &it->second;
-}
-
-// Same as above but returns a pointer to the non-const value.
-template <class Collection>
-typename Collection::value_type::second_type*
-FindOrNull(Collection& collection,  // NOLINT
-           const typename Collection::value_type::first_type& key) {
-  typename Collection::iterator it = collection.find(key);
-  if (it == collection.end()) {
-    return 0;
-  }
-  return &it->second;
-}
-
-// Returns the pointer value associated with the given key. If none is found,
-// nullptr is returned. The function is designed to be used with a map of keys to
-// pointers.
-//
-// This function does not distinguish between a missing key and a key mapped
-// to nullptr.
-template <class Collection>
-typename Collection::value_type::second_type
-FindPtrOrNull(const Collection& collection,
-              const typename Collection::value_type::first_type& key) {
-  typename Collection::const_iterator it = collection.find(key);
-  if (it == collection.end()) {
-    return typename Collection::value_type::second_type();
-  }
-  return it->second;
-}
-
-// Same as above, except takes non-const reference to collection.
-//
-// This function is needed for containers that propagate constness to the
-// pointee, such as boost::ptr_map.
-template <class Collection>
-typename Collection::value_type::second_type
-FindPtrOrNull(Collection& collection,  // NOLINT
-              const typename Collection::value_type::first_type& key) {
-  typename Collection::iterator it = collection.find(key);
-  if (it == collection.end()) {
-    return typename Collection::value_type::second_type();
-  }
-  return it->second;
-}
-
-// Finds the pointer value associated with the given key in a map whose values
-// are linked_ptrs. Returns nullptr if key is not found.
-template <class Collection>
-typename Collection::value_type::second_type::element_type*
-FindLinkedPtrOrNull(const Collection& collection,
-                    const typename Collection::value_type::first_type& key) {
-  typename Collection::const_iterator it = collection.find(key);
-  if (it == collection.end()) {
-    return 0;
-  }
-  // Since linked_ptr::get() is a const member returning a non const,
-  // we do not need a version of this function taking a non const collection.
-  return it->second.get();
-}
-
-// Same as above, but dies if the key is not found.
-template <class Collection>
-typename Collection::value_type::second_type::element_type&
-FindLinkedPtrOrDie(const Collection& collection,
-                   const typename Collection::value_type::first_type& key) {
-  typename Collection::const_iterator it = collection.find(key);
-  GOOGLE_CHECK(it != collection.end()) <<  "key not found: " << key;
-  // Since linked_ptr::operator*() is a const member returning a non const,
-  // we do not need a version of this function taking a non const collection.
-  return *it->second;
-}
-
-// Finds the value associated with the given key and copies it to *value (if not
-// nullptr). Returns false if the key was not found, true otherwise.
-template <class Collection, class Key, class Value>
-bool FindCopy(const Collection& collection,
-              const Key& key,
-              Value* const value) {
-  typename Collection::const_iterator it = collection.find(key);
-  if (it == collection.end()) {
-    return false;
-  }
-  if (value) {
-    *value = it->second;
-  }
-  return true;
-}
-
-//
-// Contains*()
-//
-
-// Returns true if and only if the given collection contains the given key.
-template <class Collection, class Key>
-bool ContainsKey(const Collection& collection, const Key& key) {
-  return collection.find(key) != collection.end();
-}
-
-// Returns true if and only if the given collection contains the given key-value
-// pair.
-template <class Collection, class Key, class Value>
-bool ContainsKeyValuePair(const Collection& collection,
-                          const Key& key,
-                          const Value& value) {
-  typedef typename Collection::const_iterator const_iterator;
-  std::pair<const_iterator, const_iterator> range = collection.equal_range(key);
-  for (const_iterator it = range.first; it != range.second; ++it) {
-    if (it->second == value) {
-      return true;
-    }
-  }
-  return false;
-}
-
-//
-// Insert*()
-//
-
-// Inserts the given key-value pair into the collection. Returns true if and
-// only if the key from the given pair didn't previously exist. Otherwise, the
-// value in the map is replaced with the value from the given pair.
-template <class Collection>
-bool InsertOrUpdate(Collection* const collection,
-                    const typename Collection::value_type& vt) {
-  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
-  if (!ret.second) {
-    // update
-    ret.first->second = vt.second;
-    return false;
-  }
-  return true;
-}
-
-// Same as above, except that the key and value are passed separately.
-template <class Collection>
-bool InsertOrUpdate(Collection* const collection,
-                    const typename Collection::value_type::first_type& key,
-                    const typename Collection::value_type::second_type& value) {
-  return InsertOrUpdate(
-      collection, typename Collection::value_type(key, value));
-}
-
-// Inserts/updates all the key-value pairs from the range defined by the
-// iterators "first" and "last" into the given collection.
-template <class Collection, class InputIterator>
-void InsertOrUpdateMany(Collection* const collection,
-                        InputIterator first, InputIterator last) {
-  for (; first != last; ++first) {
-    InsertOrUpdate(collection, *first);
-  }
-}
-
-// Change the value associated with a particular key in a map or hash_map
-// of the form map<Key, Value*> which owns the objects pointed to by the
-// value pointers.  If there was an existing value for the key, it is deleted.
-// True indicates an insert took place, false indicates an update + delete.
-template <class Collection>
-bool InsertAndDeleteExisting(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key,
-    const typename Collection::value_type::second_type& value) {
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(key, value));
-  if (!ret.second) {
-    delete ret.first->second;
-    ret.first->second = value;
-    return false;
-  }
-  return true;
-}
-
-// Inserts the given key and value into the given collection if and only if the
-// given key did NOT already exist in the collection. If the key previously
-// existed in the collection, the value is not changed. Returns true if the
-// key-value pair was inserted; returns false if the key was already present.
-template <class Collection>
-bool InsertIfNotPresent(Collection* const collection,
-                        const typename Collection::value_type& vt) {
-  return collection->insert(vt).second;
-}
-
-// Same as above except the key and value are passed separately.
-template <class Collection>
-bool InsertIfNotPresent(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key,
-    const typename Collection::value_type::second_type& value) {
-  return InsertIfNotPresent(
-      collection, typename Collection::value_type(key, value));
-}
-
-// Same as above except dies if the key already exists in the collection.
-template <class Collection>
-void InsertOrDie(Collection* const collection,
-                 const typename Collection::value_type& value) {
-  GOOGLE_CHECK(InsertIfNotPresent(collection, value))
-      << "duplicate value: " << value;
-}
-
-// Same as above except doesn't log the value on error.
-template <class Collection>
-void InsertOrDieNoPrint(Collection* const collection,
-                        const typename Collection::value_type& value) {
-  GOOGLE_CHECK(InsertIfNotPresent(collection, value)) << "duplicate value.";
-}
-
-// Inserts the key-value pair into the collection. Dies if key was already
-// present.
-template <class Collection>
-void InsertOrDie(Collection* const collection,
-                 const typename Collection::value_type::first_type& key,
-                 const typename Collection::value_type::second_type& data) {
-  GOOGLE_CHECK(InsertIfNotPresent(collection, key, data))
-      << "duplicate key: " << key;
-}
-
-// Same as above except doesn't log the key on error.
-template <class Collection>
-void InsertOrDieNoPrint(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key,
-    const typename Collection::value_type::second_type& data) {
-  GOOGLE_CHECK(InsertIfNotPresent(collection, key, data)) << "duplicate key.";
-}
-
-// Inserts a new key and default-initialized value. Dies if the key was already
-// present. Returns a reference to the value. Example usage:
-//
-// map<int, SomeProto> m;
-// SomeProto& proto = InsertKeyOrDie(&m, 3);
-// proto.set_field("foo");
-template <class Collection>
-typename Collection::value_type::second_type& InsertKeyOrDie(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key) {
-  typedef typename Collection::value_type value_type;
-  std::pair<typename Collection::iterator, bool> res =
-      collection->insert(value_type(key, typename value_type::second_type()));
-  GOOGLE_CHECK(res.second) << "duplicate key: " << key;
-  return res.first->second;
-}
-
-//
-// Lookup*()
-//
-
-// Looks up a given key and value pair in a collection and inserts the key-value
-// pair if it's not already present. Returns a reference to the value associated
-// with the key.
-template <class Collection>
-typename Collection::value_type::second_type&
-LookupOrInsert(Collection* const collection,
-               const typename Collection::value_type& vt) {
-  return collection->insert(vt).first->second;
-}
-
-// Same as above except the key-value are passed separately.
-template <class Collection>
-typename Collection::value_type::second_type&
-LookupOrInsert(Collection* const collection,
-               const typename Collection::value_type::first_type& key,
-               const typename Collection::value_type::second_type& value) {
-  return LookupOrInsert(
-      collection, typename Collection::value_type(key, value));
-}
-
-// Counts the number of equivalent elements in the given "sequence", and stores
-// the results in "count_map" with element as the key and count as the value.
-//
-// Example:
-//   vector<string> v = {"a", "b", "c", "a", "b"};
-//   map<string, int> m;
-//   AddTokenCounts(v, 1, &m);
-//   assert(m["a"] == 2);
-//   assert(m["b"] == 2);
-//   assert(m["c"] == 1);
-template <typename Sequence, typename Collection>
-void AddTokenCounts(
-    const Sequence& sequence,
-    const typename Collection::value_type::second_type& increment,
-    Collection* const count_map) {
-  for (typename Sequence::const_iterator it = sequence.begin();
-       it != sequence.end(); ++it) {
-    typename Collection::value_type::second_type& value =
-        LookupOrInsert(count_map, *it,
-                       typename Collection::value_type::second_type());
-    value += increment;
-  }
-}
-
-// Returns a reference to the value associated with key. If not found, a value
-// is default constructed on the heap and added to the map.
-//
-// This function is useful for containers of the form map<Key, Value*>, where
-// inserting a new key, value pair involves constructing a new heap-allocated
-// Value, and storing a pointer to that in the collection.
-template <class Collection>
-typename Collection::value_type::second_type&
-LookupOrInsertNew(Collection* const collection,
-                  const typename Collection::value_type::first_type& key) {
-  typedef typename std::iterator_traits<
-    typename Collection::value_type::second_type>::value_type Element;
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(
-          key,
-          static_cast<typename Collection::value_type::second_type>(nullptr)));
-  if (ret.second) {
-    ret.first->second = new Element();
-  }
-  return ret.first->second;
-}
-
-// Same as above but constructs the value using the single-argument constructor
-// and the given "arg".
-template <class Collection, class Arg>
-typename Collection::value_type::second_type&
-LookupOrInsertNew(Collection* const collection,
-                  const typename Collection::value_type::first_type& key,
-                  const Arg& arg) {
-  typedef typename std::iterator_traits<
-    typename Collection::value_type::second_type>::value_type Element;
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(
-          key,
-          static_cast<typename Collection::value_type::second_type>(nullptr)));
-  if (ret.second) {
-    ret.first->second = new Element(arg);
-  }
-  return ret.first->second;
-}
-
-// Lookup of linked/shared pointers is used in two scenarios:
-//
-// Use LookupOrInsertNewLinkedPtr if the container owns the elements.
-// In this case it is fine working with the raw pointer as long as it is
-// guaranteed that no other thread can delete/update an accessed element.
-// A mutex will need to lock the container operation as well as the use
-// of the returned elements. Finding an element may be performed using
-// FindLinkedPtr*().
-//
-// Use LookupOrInsertNewSharedPtr if the container does not own the elements
-// for their whole lifetime. This is typically the case when a reader allows
-// parallel updates to the container. In this case a Mutex only needs to lock
-// container operations, but all element operations must be performed on the
-// shared pointer. Finding an element must be performed using FindPtr*() and
-// cannot be done with FindLinkedPtr*() even though it compiles.
-
-// Lookup a key in a map or hash_map whose values are linked_ptrs.  If it is
-// missing, set collection[key].reset(new Value::element_type) and return that.
-// Value::element_type must be default constructable.
-template <class Collection>
-typename Collection::value_type::second_type::element_type*
-LookupOrInsertNewLinkedPtr(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key) {
-  typedef typename Collection::value_type::second_type Value;
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(key, Value()));
-  if (ret.second) {
-    ret.first->second.reset(new typename Value::element_type);
-  }
-  return ret.first->second.get();
-}
-
-// A variant of LookupOrInsertNewLinkedPtr where the value is constructed using
-// a single-parameter constructor.  Note: the constructor argument is computed
-// even if it will not be used, so only values cheap to compute should be passed
-// here.  On the other hand it does not matter how expensive the construction of
-// the actual stored value is, as that only occurs if necessary.
-template <class Collection, class Arg>
-typename Collection::value_type::second_type::element_type*
-LookupOrInsertNewLinkedPtr(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key,
-    const Arg& arg) {
-  typedef typename Collection::value_type::second_type Value;
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(key, Value()));
-  if (ret.second) {
-    ret.first->second.reset(new typename Value::element_type(arg));
-  }
-  return ret.first->second.get();
-}
-
-// Lookup a key in a map or hash_map whose values are shared_ptrs.  If it is
-// missing, set collection[key].reset(new Value::element_type). Unlike
-// LookupOrInsertNewLinkedPtr, this function returns the shared_ptr instead of
-// the raw pointer. Value::element_type must be default constructable.
-template <class Collection>
-typename Collection::value_type::second_type&
-LookupOrInsertNewSharedPtr(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key) {
-  typedef typename Collection::value_type::second_type SharedPtr;
-  typedef typename Collection::value_type::second_type::element_type Element;
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(key, SharedPtr()));
-  if (ret.second) {
-    ret.first->second.reset(new Element());
-  }
-  return ret.first->second;
-}
-
-// A variant of LookupOrInsertNewSharedPtr where the value is constructed using
-// a single-parameter constructor.  Note: the constructor argument is computed
-// even if it will not be used, so only values cheap to compute should be passed
-// here.  On the other hand it does not matter how expensive the construction of
-// the actual stored value is, as that only occurs if necessary.
-template <class Collection, class Arg>
-typename Collection::value_type::second_type&
-LookupOrInsertNewSharedPtr(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key,
-    const Arg& arg) {
-  typedef typename Collection::value_type::second_type SharedPtr;
-  typedef typename Collection::value_type::second_type::element_type Element;
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(key, SharedPtr()));
-  if (ret.second) {
-    ret.first->second.reset(new Element(arg));
-  }
-  return ret.first->second;
-}
-
-//
-// Misc Utility Functions
-//
-
-// Updates the value associated with the given key. If the key was not already
-// present, then the key-value pair are inserted and "previous" is unchanged. If
-// the key was already present, the value is updated and "*previous" will
-// contain a copy of the old value.
-//
-// InsertOrReturnExisting has complementary behavior that returns the
-// address of an already existing value, rather than updating it.
-template <class Collection>
-bool UpdateReturnCopy(Collection* const collection,
-                      const typename Collection::value_type::first_type& key,
-                      const typename Collection::value_type::second_type& value,
-                      typename Collection::value_type::second_type* previous) {
-  std::pair<typename Collection::iterator, bool> ret =
-      collection->insert(typename Collection::value_type(key, value));
-  if (!ret.second) {
-    // update
-    if (previous) {
-      *previous = ret.first->second;
-    }
-    ret.first->second = value;
-    return true;
-  }
-  return false;
-}
-
-// Same as above except that the key and value are passed as a pair.
-template <class Collection>
-bool UpdateReturnCopy(Collection* const collection,
-                      const typename Collection::value_type& vt,
-                      typename Collection::value_type::second_type* previous) {
-  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
-  if (!ret.second) {
-    // update
-    if (previous) {
-      *previous = ret.first->second;
-    }
-    ret.first->second = vt.second;
-    return true;
-  }
-  return false;
-}
-
-// Tries to insert the given key-value pair into the collection. Returns nullptr if
-// the insert succeeds. Otherwise, returns a pointer to the existing value.
-//
-// This complements UpdateReturnCopy in that it allows to update only after
-// verifying the old value and still insert quickly without having to look up
-// twice. Unlike UpdateReturnCopy this also does not come with the issue of an
-// undefined previous* in case new data was inserted.
-template <class Collection>
-typename Collection::value_type::second_type* InsertOrReturnExisting(
-    Collection* const collection, const typename Collection::value_type& vt) {
-  std::pair<typename Collection::iterator, bool> ret = collection->insert(vt);
-  if (ret.second) {
-    return nullptr;  // Inserted, no existing previous value.
-  } else {
-    return &ret.first->second;  // Return address of already existing value.
-  }
-}
-
-// Same as above, except for explicit key and data.
-template <class Collection>
-typename Collection::value_type::second_type* InsertOrReturnExisting(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key,
-    const typename Collection::value_type::second_type& data) {
-  return InsertOrReturnExisting(collection,
-                                typename Collection::value_type(key, data));
-}
-
-// Erases the collection item identified by the given key, and returns the value
-// associated with that key. It is assumed that the value (i.e., the
-// mapped_type) is a pointer. Returns nullptr if the key was not found in the
-// collection.
-//
-// Examples:
-//   map<string, MyType*> my_map;
-//
-// One line cleanup:
-//     delete EraseKeyReturnValuePtr(&my_map, "abc");
-//
-// Use returned value:
-//     std::unique_ptr<MyType> value_ptr(
-//         EraseKeyReturnValuePtr(&my_map, "abc"));
-//     if (value_ptr.get())
-//       value_ptr->DoSomething();
-//
-template <class Collection>
-typename Collection::value_type::second_type EraseKeyReturnValuePtr(
-    Collection* const collection,
-    const typename Collection::value_type::first_type& key) {
-  typename Collection::iterator it = collection->find(key);
-  if (it == collection->end()) {
-    return nullptr;
-  }
-  typename Collection::value_type::second_type v = it->second;
-  collection->erase(it);
-  return v;
-}
-
-// Inserts all the keys from map_container into key_container, which must
-// support insert(MapContainer::key_type).
-//
-// Note: any initial contents of the key_container are not cleared.
-template <class MapContainer, class KeyContainer>
-void InsertKeysFromMap(const MapContainer& map_container,
-                       KeyContainer* key_container) {
-  GOOGLE_CHECK(key_container != nullptr);
-  for (typename MapContainer::const_iterator it = map_container.begin();
-       it != map_container.end(); ++it) {
-    key_container->insert(it->first);
-  }
-}
-
-// Appends all the keys from map_container into key_container, which must
-// support push_back(MapContainer::key_type).
-//
-// Note: any initial contents of the key_container are not cleared.
-template <class MapContainer, class KeyContainer>
-void AppendKeysFromMap(const MapContainer& map_container,
-                       KeyContainer* key_container) {
-  GOOGLE_CHECK(key_container != nullptr);
-  for (typename MapContainer::const_iterator it = map_container.begin();
-       it != map_container.end(); ++it) {
-    key_container->push_back(it->first);
-  }
-}
-
-// A more specialized overload of AppendKeysFromMap to optimize reallocations
-// for the common case in which we're appending keys to a vector and hence can
-// (and sometimes should) call reserve() first.
-//
-// (It would be possible to play SFINAE games to call reserve() for any
-// container that supports it, but this seems to get us 99% of what we need
-// without the complexity of a SFINAE-based solution.)
-template <class MapContainer, class KeyType>
-void AppendKeysFromMap(const MapContainer& map_container,
-                       std::vector<KeyType>* key_container) {
-  GOOGLE_CHECK(key_container != nullptr);
-  // We now have the opportunity to call reserve(). Calling reserve() every
-  // time is a bad idea for some use cases: libstdc++'s implementation of
-  // vector<>::reserve() resizes the vector's backing store to exactly the
-  // given size (unless it's already at least that big). Because of this,
-  // the use case that involves appending a lot of small maps (total size
-  // N) one by one to a vector would be O(N^2). But never calling reserve()
-  // loses the opportunity to improve the use case of adding from a large
-  // map to an empty vector (this improves performance by up to 33%). A
-  // number of heuristics are possible; see the discussion in
-  // cl/34081696. Here we use the simplest one.
-  if (key_container->empty()) {
-    key_container->reserve(map_container.size());
-  }
-  for (typename MapContainer::const_iterator it = map_container.begin();
-       it != map_container.end(); ++it) {
-    key_container->push_back(it->first);
-  }
-}
-
-// Inserts all the values from map_container into value_container, which must
-// support push_back(MapContainer::mapped_type).
-//
-// Note: any initial contents of the value_container are not cleared.
-template <class MapContainer, class ValueContainer>
-void AppendValuesFromMap(const MapContainer& map_container,
-                         ValueContainer* value_container) {
-  GOOGLE_CHECK(value_container != nullptr);
-  for (typename MapContainer::const_iterator it = map_container.begin();
-       it != map_container.end(); ++it) {
-    value_container->push_back(it->second);
-  }
-}
-
-// A more specialized overload of AppendValuesFromMap to optimize reallocations
-// for the common case in which we're appending values to a vector and hence
-// can (and sometimes should) call reserve() first.
-//
-// (It would be possible to play SFINAE games to call reserve() for any
-// container that supports it, but this seems to get us 99% of what we need
-// without the complexity of a SFINAE-based solution.)
-template <class MapContainer, class ValueType>
-void AppendValuesFromMap(const MapContainer& map_container,
-                         std::vector<ValueType>* value_container) {
-  GOOGLE_CHECK(value_container != nullptr);
-  // See AppendKeysFromMap for why this is done.
-  if (value_container->empty()) {
-    value_container->reserve(map_container.size());
-  }
-  for (typename MapContainer::const_iterator it = map_container.begin();
-       it != map_container.end(); ++it) {
-    value_container->push_back(it->second);
-  }
-}
-
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_STUBS_MAP_UTIL_H__
diff --git a/src/google/protobuf/stubs/mathutil.h b/src/google/protobuf/stubs/mathutil.h
index 1d16bce..908b245 100644
--- a/src/google/protobuf/stubs/mathutil.h
+++ b/src/google/protobuf/stubs/mathutil.h
@@ -30,12 +30,13 @@
 #ifndef GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
 #define GOOGLE_PROTOBUF_STUBS_MATHUTIL_H_
 
-#include <cmath>
 #include <float.h>
+
+#include <cmath>
 #include <limits>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/stubs/mutex.h b/src/google/protobuf/stubs/mutex.h
deleted file mode 100644
index c459991..0000000
--- a/src/google/protobuf/stubs/mutex.h
+++ /dev/null
@@ -1,218 +0,0 @@
-// Copyright (c) 2006, Google Inc.
-// 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 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_STUBS_MUTEX_H_
-#define GOOGLE_PROTOBUF_STUBS_MUTEX_H_
-
-#include <mutex>
-
-#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-#include <windows.h>
-
-// GetMessage conflicts with GeneratedMessageReflection::GetMessage().
-#ifdef GetMessage
-#undef GetMessage
-#endif
-
-#endif
-
-#include <google/protobuf/stubs/macros.h>
-
-// Define thread-safety annotations for use below, if we are building with
-// Clang.
-#if defined(__clang__) && !defined(SWIG)
-#define GOOGLE_PROTOBUF_ACQUIRE(...) \
-  __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
-
-#include <google/protobuf/port_def.inc>
-
-// ===================================================================
-// emulates google3/base/mutex.h
-namespace google {
-namespace protobuf {
-namespace internal {
-
-#define GOOGLE_PROTOBUF_LINKER_INITIALIZED
-
-#ifdef GOOGLE_PROTOBUF_SUPPORT_WINDOWS_XP
-
-// This class is a lightweight replacement for std::mutex on Windows platforms.
-// std::mutex 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.
-class PROTOBUF_EXPORT CriticalSectionLock {
- public:
-  CriticalSectionLock() { InitializeCriticalSection(&critical_section_); }
-  ~CriticalSectionLock() { DeleteCriticalSection(&critical_section_); }
-  void lock() { EnterCriticalSection(&critical_section_); }
-  void unlock() { LeaveCriticalSection(&critical_section_); }
-
- private:
-  CRITICAL_SECTION critical_section_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(CriticalSectionLock);
-};
-
-#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:
-#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.
-  // May fail to crash when it should; will never crash when it should not.
-  void AssertHeld() const {}
-
- private:
-#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 GOOGLE_PROTOBUF_SCOPED_CAPABILITY PROTOBUF_EXPORT MutexLock {
- public:
-  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);
-};
-
-// TODO(kenton):  Implement these?  Hard to implement portably.
-typedef MutexLock ReaderMutexLock;
-typedef MutexLock WriterMutexLock;
-
-// MutexLockMaybe is like MutexLock, but is a no-op when mu is nullptr.
-class PROTOBUF_EXPORT MutexLockMaybe {
- public:
-  explicit MutexLockMaybe(Mutex *mu) :
-    mu_(mu) { if (this->mu_ != nullptr) { this->mu_->Lock(); } }
-  ~MutexLockMaybe() { if (this->mu_ != nullptr) { this->mu_->Unlock(); } }
- private:
-  Mutex *const mu_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MutexLockMaybe);
-};
-
-#if defined(GOOGLE_PROTOBUF_NO_THREADLOCAL)
-template<typename T>
-class ThreadLocalStorage {
- public:
-  ThreadLocalStorage() {
-    pthread_key_create(&key_, &ThreadLocalStorage::Delete);
-  }
-  ~ThreadLocalStorage() {
-    pthread_key_delete(key_);
-  }
-  T* Get() {
-    T* result = static_cast<T*>(pthread_getspecific(key_));
-    if (result == nullptr) {
-      result = new T();
-      pthread_setspecific(key_, result);
-    }
-    return result;
-  }
- private:
-  static void Delete(void* value) {
-    delete static_cast<T*>(value);
-  }
-  pthread_key_t key_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ThreadLocalStorage);
-};
-#endif
-
-}  // namespace internal
-
-// We made these internal so that they would show up as such in the docs,
-// but we don't want to stick "internal::" in front of them everywhere.
-using internal::Mutex;
-using internal::MutexLock;
-using internal::ReaderMutexLock;
-using internal::WriterMutexLock;
-using internal::MutexLockMaybe;
-
-}  // namespace protobuf
-}  // namespace google
-
-#undef GOOGLE_PROTOBUF_ACQUIRE
-#undef GOOGLE_PROTOBUF_RELEASE
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_MUTEX_H_
diff --git a/src/google/protobuf/stubs/port.h b/src/google/protobuf/stubs/port.h
index b074cb1..d459a94 100644
--- a/src/google/protobuf/stubs/port.h
+++ b/src/google/protobuf/stubs/port.h
@@ -32,15 +32,17 @@
 #define GOOGLE_PROTOBUF_STUBS_PORT_H_
 
 #include <assert.h>
-#include <cstdint>
 #include <stdlib.h>
-#include <cstddef>
-#include <string>
 #include <string.h>
 
-#include <google/protobuf/stubs/platform_macros.h>
+#include <cstddef>
+#include <cstdint>
+#include <string>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/stubs/platform_macros.h"
+
+// Must be last.
+#include "google/protobuf/port_def.inc"  // NOLINT
 
 #undef PROTOBUF_LITTLE_ENDIAN
 #ifdef _WIN32
@@ -126,8 +128,6 @@
 namespace google {
 namespace protobuf {
 
-using ConstStringParam = const std::string &;
-
 typedef unsigned int uint;
 
 typedef int8_t int8;
@@ -147,57 +147,6 @@
 static const uint32 kuint32max = 0xFFFFFFFFu;
 static const uint64 kuint64max = uint64_t{0xFFFFFFFFFFFFFFFFu};
 
-#if defined(ADDRESS_SANITIZER) || defined(THREAD_SANITIZER) ||\
-    defined(MEMORY_SANITIZER)
-
-#ifdef __cplusplus
-extern "C" {
-#endif  // __cplusplus
-uint16_t __sanitizer_unaligned_load16(const void *p);
-uint32_t __sanitizer_unaligned_load32(const void *p);
-uint64_t __sanitizer_unaligned_load64(const void *p);
-void __sanitizer_unaligned_store16(void *p, uint16_t v);
-void __sanitizer_unaligned_store32(void *p, uint32_t v);
-void __sanitizer_unaligned_store64(void *p, uint64_t v);
-#ifdef __cplusplus
-}  // extern "C"
-#endif  // __cplusplus
-
-inline uint16_t GOOGLE_UNALIGNED_LOAD16(const void *p) {
-  return __sanitizer_unaligned_load16(p);
-}
-
-inline uint32_t GOOGLE_UNALIGNED_LOAD32(const void *p) {
-  return __sanitizer_unaligned_load32(p);
-}
-
-inline uint64_t GOOGLE_UNALIGNED_LOAD64(const void *p) {
-  return __sanitizer_unaligned_load64(p);
-}
-
-inline void GOOGLE_UNALIGNED_STORE16(void *p, uint16_t v) {
-  __sanitizer_unaligned_store16(p, v);
-}
-
-inline void GOOGLE_UNALIGNED_STORE32(void *p, uint32_t v) {
-  __sanitizer_unaligned_store32(p, v);
-}
-
-inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64_t v) {
-  __sanitizer_unaligned_store64(p, v);
-}
-
-#elif defined(GOOGLE_PROTOBUF_USE_UNALIGNED) && GOOGLE_PROTOBUF_USE_UNALIGNED
-
-#define GOOGLE_UNALIGNED_LOAD16(_p) (*reinterpret_cast<const uint16_t *>(_p))
-#define GOOGLE_UNALIGNED_LOAD32(_p) (*reinterpret_cast<const uint32_t *>(_p))
-#define GOOGLE_UNALIGNED_LOAD64(_p) (*reinterpret_cast<const uint64_t *>(_p))
-
-#define GOOGLE_UNALIGNED_STORE16(_p, _val) (*reinterpret_cast<uint16_t *>(_p) = (_val))
-#define GOOGLE_UNALIGNED_STORE32(_p, _val) (*reinterpret_cast<uint32_t *>(_p) = (_val))
-#define GOOGLE_UNALIGNED_STORE64(_p, _val) (*reinterpret_cast<uint64_t *>(_p) = (_val))
-
-#else
 inline uint16_t GOOGLE_UNALIGNED_LOAD16(const void *p) {
   uint16_t t;
   memcpy(&t, p, sizeof t);
@@ -227,7 +176,6 @@
 inline void GOOGLE_UNALIGNED_STORE64(void *p, uint64_t v) {
   memcpy(p, &v, sizeof v);
 }
-#endif
 
 #if defined(GOOGLE_PROTOBUF_OS_NACL) \
     || (defined(__ANDROID__) && defined(__clang__) \
@@ -283,69 +231,6 @@
 #endif
 
 // ===================================================================
-// from google3/util/bits/bits.h
-
-class Bits {
- public:
-  static uint32_t Log2FloorNonZero(uint32_t n) {
-#if defined(__GNUC__)
-  return 31 ^ static_cast<uint32_t>(__builtin_clz(n));
-#elif defined(_MSC_VER)
-  unsigned long where;
-  _BitScanReverse(&where, n);
-  return where;
-#else
-  return Log2FloorNonZero_Portable(n);
-#endif
-  }
-
-  static uint32_t Log2FloorNonZero64(uint64_t n) {
-    // Older versions of clang run into an instruction-selection failure when
-    // it encounters __builtin_clzll:
-    // https://bugs.chromium.org/p/nativeclient/issues/detail?id=4395
-    // This includes arm-nacl-clang and clang in older Android NDK versions.
-    // To work around this, when we build with those we use the portable
-    // implementation instead.
-#if defined(__GNUC__) && !defined(GOOGLE_PROTOBUF_USE_PORTABLE_LOG2)
-  return 63 ^ static_cast<uint32_t>(__builtin_clzll(n));
-#elif defined(_MSC_VER) && defined(_M_X64)
-  unsigned long where;
-  _BitScanReverse64(&where, n);
-  return where;
-#else
-  return Log2FloorNonZero64_Portable(n);
-#endif
-  }
- private:
-  static int Log2FloorNonZero_Portable(uint32_t n) {
-    if (n == 0)
-      return -1;
-    int log = 0;
-    uint32_t value = n;
-    for (int i = 4; i >= 0; --i) {
-      int shift = (1 << i);
-      uint32_t x = value >> shift;
-      if (x != 0) {
-        value = x;
-        log += shift;
-      }
-    }
-    assert(value == 1);
-    return log;
-  }
-
-  static int Log2FloorNonZero64_Portable(uint64_t n) {
-    const uint32_t topbits = static_cast<uint32_t>(n >> 32);
-    if (topbits == 0) {
-      // Top bits are zero, so scan in bottom bits
-      return static_cast<int>(Log2FloorNonZero(static_cast<uint32_t>(n)));
-    } else {
-      return 32 + static_cast<int>(Log2FloorNonZero(topbits));
-    }
-  }
-};
-
-// ===================================================================
 // from google3/util/endian/endian.h
 PROTOBUF_EXPORT uint32_t ghtonl(uint32_t x);
 
@@ -408,6 +293,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_STUBS_PORT_H_
diff --git a/src/google/protobuf/stubs/status.cc b/src/google/protobuf/stubs/status.cc
deleted file mode 100644
index f5c0fa4..0000000
--- a/src/google/protobuf/stubs/status.cc
+++ /dev/null
@@ -1,262 +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 <google/protobuf/stubs/status.h>
-
-#include <ostream>
-#include <stdio.h>
-#include <string>
-#include <utility>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace status_internal {
-namespace {
-
-inline std::string StatusCodeToString(StatusCode code) {
-  switch (code) {
-    case StatusCode::kOk:
-      return "OK";
-    case StatusCode::kCancelled:
-      return "CANCELLED";
-    case StatusCode::kUnknown:
-      return "UNKNOWN";
-    case StatusCode::kInvalidArgument:
-      return "INVALID_ARGUMENT";
-    case StatusCode::kDeadlineExceeded:
-      return "DEADLINE_EXCEEDED";
-    case StatusCode::kNotFound:
-      return "NOT_FOUND";
-    case StatusCode::kAlreadyExists:
-      return "ALREADY_EXISTS";
-    case StatusCode::kPermissionDenied:
-      return "PERMISSION_DENIED";
-    case StatusCode::kUnauthenticated:
-      return "UNAUTHENTICATED";
-    case StatusCode::kResourceExhausted:
-      return "RESOURCE_EXHAUSTED";
-    case StatusCode::kFailedPrecondition:
-      return "FAILED_PRECONDITION";
-    case StatusCode::kAborted:
-      return "ABORTED";
-    case StatusCode::kOutOfRange:
-      return "OUT_OF_RANGE";
-    case StatusCode::kUnimplemented:
-      return "UNIMPLEMENTED";
-    case StatusCode::kInternal:
-      return "INTERNAL";
-    case StatusCode::kUnavailable:
-      return "UNAVAILABLE";
-    case StatusCode::kDataLoss:
-      return "DATA_LOSS";
-  }
-
-  // No default clause, clang will abort if a code is missing from
-  // above switch.
-  return "UNKNOWN";
-}
-
-}  // namespace
-
-Status::Status() : error_code_(StatusCode::kOk) {}
-
-Status::Status(StatusCode error_code, StringPiece error_message)
-    : error_code_(error_code) {
-  if (error_code != StatusCode::kOk) {
-    error_message_ = error_message.ToString();
-  }
-}
-
-Status::Status(const Status& other)
-    : error_code_(other.error_code_), error_message_(other.error_message_) {
-}
-
-Status& Status::operator=(const Status& other) {
-  error_code_ = other.error_code_;
-  error_message_ = other.error_message_;
-  return *this;
-}
-
-bool Status::operator==(const Status& x) const {
-  return error_code_ == x.error_code_ &&
-      error_message_ == x.error_message_;
-}
-
-std::string Status::ToString() const {
-  if (error_code_ == StatusCode::kOk) {
-    return "OK";
-  } else {
-    if (error_message_.empty()) {
-      return StatusCodeToString(error_code_);
-    } else {
-      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
deleted file mode 100644
index c858cf6..0000000
--- a/src/google/protobuf/stubs/status.h
+++ /dev/null
@@ -1,196 +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_STUBS_STATUS_H_
-#define GOOGLE_PROTOBUF_STUBS_STATUS_H_
-
-#include <string>
-
-#include <google/protobuf/stubs/stringpiece.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace status_internal {
-
-// These values must match error codes defined in google/rpc/code.proto.
-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,
-};
-
-class PROTOBUF_EXPORT Status {
- public:
-  // Creates a "successful" status.
-  Status();
-
-  // 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::kOk is
-  // constructed.
-  Status(StatusCode error_code, StringPiece error_message);
-  Status(const Status&);
-  Status& operator=(const Status& x);
-  ~Status() {}
-
-  // Accessor
-  bool ok() const { return error_code_ == StatusCode::kOk; }
-  StatusCode code() const { return error_code_; }
-  StringPiece message() const {
-    return error_message_;
-  }
-
-  bool operator==(const Status& x) const;
-  bool operator!=(const Status& x) const {
-    return !operator==(x);
-  }
-
-  // Return a combination of the error code name and message.
-  std::string ToString() const;
-
- private:
-  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
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_STATUS_H_
diff --git a/src/google/protobuf/stubs/status_macros.h b/src/google/protobuf/stubs/status_macros.h
index 407ff4c..fc2267e 100644
--- a/src/google/protobuf/stubs/status_macros.h
+++ b/src/google/protobuf/stubs/status_macros.h
@@ -33,9 +33,12 @@
 #ifndef GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
 #define GOOGLE_PROTOBUF_STUBS_STATUS_MACROS_H_
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
+#include "absl/status/status.h"
+#include "absl/status/statusor.h"
+#include "google/protobuf/stubs/common.h"
+
+// Needs to be last.
+#include "google/protobuf/port_def.inc"  // NOLINT
 
 namespace google {
 namespace protobuf {
@@ -49,7 +52,7 @@
 #define RETURN_IF_ERROR(expr)                                                \
   do {                                                                       \
     /* Using _status below to avoid capture problems if expr is "status". */ \
-    const PROTOBUF_NAMESPACE_ID::util::Status _status = (expr);              \
+    const absl::Status _status = (expr);                                     \
     if (PROTOBUF_PREDICT_FALSE(!_status.ok())) return _status;               \
   } while (0)
 
@@ -57,16 +60,16 @@
 #define STATUS_MACROS_CONCAT_NAME_INNER(x, y) x##y
 #define STATUS_MACROS_CONCAT_NAME(x, y) STATUS_MACROS_CONCAT_NAME_INNER(x, y)
 
-template<typename T>
-Status DoAssignOrReturn(T& lhs, StatusOr<T> result) {
+template <typename T>
+absl::Status DoAssignOrReturn(T& lhs, absl::StatusOr<T> result) {
   if (result.ok()) {
     lhs = result.value();
   }
   return result.status();
 }
 
-#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr) \
-  Status status = DoAssignOrReturn(lhs, (rexpr)); \
+#define ASSIGN_OR_RETURN_IMPL(status, lhs, rexpr)       \
+  absl::Status status = DoAssignOrReturn(lhs, (rexpr)); \
   if (PROTOBUF_PREDICT_FALSE(!status.ok())) return status;
 
 // Executes an expression that returns a util::StatusOr, extracting its value
@@ -79,11 +82,13 @@
 // WARNING: ASSIGN_OR_RETURN expands into multiple statements; it cannot be used
 //  in a single statement (e.g. as the body of an if statement without {})!
 #define ASSIGN_OR_RETURN(lhs, rexpr) \
-  ASSIGN_OR_RETURN_IMPL( \
+  ASSIGN_OR_RETURN_IMPL(             \
       STATUS_MACROS_CONCAT_NAME(_status_or_value, __COUNTER__), lhs, rexpr);
 
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
 
+#include "google/protobuf/port_undef.inc"  // NOLINT
+
 #endif  // GOOGLE_PROTOBUF_STUBS_STATUS_H_
diff --git a/src/google/protobuf/stubs/status_test.cc b/src/google/protobuf/stubs/status_test.cc
deleted file mode 100644
index 9e9edf7..0000000
--- a/src/google/protobuf/stubs/status_test.cc
+++ /dev/null
@@ -1,278 +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 <google/protobuf/stubs/status.h>
-
-#include <stdio.h>
-
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-namespace google {
-namespace protobuf {
-namespace {
-
-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::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) {
-  util::Status status;
-  GOOGLE_CHECK_OK(status);
-  GOOGLE_CHECK_OK(status) << "Failed";
-  GOOGLE_DCHECK_OK(status) << "Failed";
-}
-
-TEST(Status, ErrorMessage) {
-  util::Status status = util::InvalidArgumentError("");
-  EXPECT_FALSE(status.ok());
-  EXPECT_EQ("", status.message().ToString());
-  EXPECT_EQ("INVALID_ARGUMENT", status.ToString());
-  status = util::InvalidArgumentError("msg");
-  EXPECT_FALSE(status.ok());
-  EXPECT_EQ("msg", status.message().ToString());
-  EXPECT_EQ("INVALID_ARGUMENT:msg", status.ToString());
-  status = util::Status(util::StatusCode::kOk, "msg");
-  EXPECT_TRUE(status.ok());
-  EXPECT_EQ("", status.message().ToString());
-  EXPECT_EQ("OK", status.ToString());
-}
-
-TEST(Status, Copy) {
-  util::Status a = util::UnknownError("message");
-  util::Status b(a);
-  ASSERT_EQ(a.ToString(), b.ToString());
-}
-
-TEST(Status, Assign) {
-  util::Status a = util::UnknownError("message");
-  util::Status b;
-  b = a;
-  ASSERT_EQ(a.ToString(), b.ToString());
-}
-
-TEST(Status, AssignEmpty) {
-  util::Status a = util::UnknownError("message");
-  util::Status b;
-  a = b;
-  ASSERT_EQ(std::string("OK"), a.ToString());
-  ASSERT_TRUE(b.ok());
-  ASSERT_TRUE(a.ok());
-}
-
-TEST(Status, EqualsOK) { ASSERT_EQ(util::OkStatus(), util::Status()); }
-
-TEST(Status, EqualsSame) {
-  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::CancelledError("message");
-  const util::Status b = a;
-  ASSERT_EQ(a, b);
-}
-
-TEST(Status, EqualsDifferentCode) {
-  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::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
deleted file mode 100644
index 9c0a178..0000000
--- a/src/google/protobuf/stubs/statusor.cc
+++ /dev/null
@@ -1,48 +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 <google/protobuf/stubs/statusor.h>
-
-#include <google/protobuf/stubs/logging.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace statusor_internal {
-
-void StatusOrHelper::Crash(const Status& status) {
-  GOOGLE_LOG(FATAL) << "Attempting to fetch value instead of handling error "
-                    << status.ToString();
-}
-
-}  // 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
deleted file mode 100644
index 20e603e..0000000
--- a/src/google/protobuf/stubs/statusor.h
+++ /dev/null
@@ -1,253 +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.
-
-// StatusOr<T> is the union of a Status object and a T
-// 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 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
-// function which may fail.
-//
-// Example client usage for a StatusOr<T>, where T is not a pointer:
-//
-//  StatusOr<float> result = DoBigCalculationThatCouldFail();
-//  if (result.ok()) {
-//    float answer = result.value();
-//    printf("Big calculation yielded: %f", answer);
-//  } else {
-//    LOG(ERROR) << result.status();
-//  }
-//
-// Example client usage for a StatusOr<T*>:
-//
-//  StatusOr<Foo*> result = FooFactory::MakeNewFoo(arg);
-//  if (result.ok()) {
-//    std::unique_ptr<Foo> foo(result.value());
-//    foo->DoSomethingCool();
-//  } else {
-//    LOG(ERROR) << result.status();
-//  }
-//
-// Example factory implementation returning StatusOr<T*>:
-//
-//  StatusOr<Foo*> FooFactory::MakeNewFoo(int arg) {
-//    if (arg <= 0) {
-//      return InvalidArgumentError("Arg must be positive");
-//    } else {
-//      return new Foo(arg);
-//    }
-//  }
-//
-
-#ifndef GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
-#define GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
-
-#include <new>
-#include <string>
-#include <utility>
-
-#include <google/protobuf/stubs/status.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace statusor_internal {
-
-template<typename T>
-class StatusOr {
-  template<typename U> friend class StatusOr;
-
- public:
-  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 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 != 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
-  // 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()'
-  // when when the return type is StatusOr<T>.
-  //
-  // REQUIRES: if T is a plain pointer, value != nullptr. This requirement is
-  // DCHECKed. In optimized builds, passing a null pointer here will have
-  // the effect of passing PosixErrorSpace::EINVAL as a fallback.
-  StatusOr(const T& value);  // NOLINT
-
-  // Copy constructor.
-  StatusOr(const StatusOr& other);
-
-  // Conversion copy constructor, T must be copy constructible from U
-  template<typename U>
-  StatusOr(const StatusOr<U>& other);
-
-  // Assignment operator.
-  StatusOr& operator=(const StatusOr& other);
-
-  // Conversion assignment operator, T must be assignable from U
-  template<typename U>
-  StatusOr& operator=(const StatusOr<U>& other);
-
-  // Returns a reference to our status. If this contains a T, then
-  // 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().
-  const T& value () const;
-
- private:
-  Status status_;
-  T value_;
-};
-
-////////////////////////////////////////////////////////////////////////////////
-// Implementation details for StatusOr<T>
-
-class PROTOBUF_EXPORT StatusOrHelper {
- public:
-  // Move type-agnostic error handling to the .cc.
-  static void Crash(const util::Status& status);
-
-  // Customized behavior for StatusOr<T> vs. StatusOr<T*>
-  template<typename T>
-  struct Specialize;
-};
-
-template<typename T>
-struct StatusOrHelper::Specialize {
-  // For non-pointer T, a reference can never be nullptr.
-  static inline bool IsValueNull(const T& /*t*/) { return false; }
-};
-
-template<typename T>
-struct StatusOrHelper::Specialize<T*> {
-  static inline bool IsValueNull(const T* t) { return t == nullptr; }
-};
-
-template <typename T>
-inline StatusOr<T>::StatusOr() : status_(util::UnknownError("")) {}
-
-template<typename T>
-inline StatusOr<T>::StatusOr(const Status& status) {
-  if (status.ok()) {
-    status_ = util::InternalError("OkStatus() is not a valid argument.");
-  } else {
-    status_ = status;
-  }
-}
-
-template<typename T>
-inline StatusOr<T>::StatusOr(const T& value) {
-  if (StatusOrHelper::Specialize<T>::IsValueNull(value)) {
-    status_ = util::InternalError("nullptr is not a valid argument.");
-  } else {
-    status_ = util::OkStatus();
-    value_ = value;
-  }
-}
-
-template<typename T>
-inline StatusOr<T>::StatusOr(const StatusOr<T>& other)
-    : status_(other.status_), value_(other.value_) {
-}
-
-template<typename T>
-inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<T>& other) {
-  status_ = other.status_;
-  value_ = other.value_;
-  return *this;
-}
-
-template<typename T>
-template<typename U>
-inline StatusOr<T>::StatusOr(const StatusOr<U>& other)
-    : status_(other.status_), value_(other.status_.ok() ? other.value_ : T()) {
-}
-
-template<typename T>
-template<typename U>
-inline StatusOr<T>& StatusOr<T>::operator=(const StatusOr<U>& other) {
-  status_ = other.status_;
-  if (status_.ok()) value_ = other.value_;
-  return *this;
-}
-
-template<typename T>
-inline const Status& StatusOr<T>::status() const {
-  return status_;
-}
-
-template<typename T>
-inline bool StatusOr<T>::ok() const {
-  return status().ok();
-}
-
-template<typename T>
-inline const T& StatusOr<T>::value() const {
-  if (!status_.ok()) {
-    StatusOrHelper::Crash(status_);
-  }
-  return value_;
-}
-
-}  // namespace statusor_internal
-
-using ::google::protobuf::util::statusor_internal::StatusOr;
-
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_STATUSOR_H_
diff --git a/src/google/protobuf/stubs/statusor_test.cc b/src/google/protobuf/stubs/statusor_test.cc
deleted file mode 100644
index 403adcc..0000000
--- a/src/google/protobuf/stubs/statusor_test.cc
+++ /dev/null
@@ -1,272 +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 <google/protobuf/stubs/statusor.h>
-
-#include <errno.h>
-#include <memory>
-
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace {
-
-class Base1 {
- public:
-  virtual ~Base1() {}
-  int pad;
-};
-
-class Base2 {
- public:
-  virtual ~Base2() {}
-  int yetotherpad;
-};
-
-class Derived : public Base1, public Base2 {
- public:
-  virtual ~Derived() {}
-  int evenmorepad;
-};
-
-class CopyNoAssign {
- public:
-  explicit CopyNoAssign(int value) : foo(value) {}
-  CopyNoAssign(const CopyNoAssign& other) : foo(other.foo) {}
-  int foo;
- private:
-  const CopyNoAssign& operator=(const CopyNoAssign&);
-};
-
-TEST(StatusOr, TestDefaultCtor) {
-  StatusOr<int> thing;
-  EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(util::UnknownError(""), thing.status());
-}
-
-TEST(StatusOr, TestStatusCtor) {
-  StatusOr<int> thing(util::CancelledError(""));
-  EXPECT_FALSE(thing.ok());
-  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.value());
-}
-
-TEST(StatusOr, TestCopyCtorStatusOk) {
-  const int kI = 4;
-  StatusOr<int> original(kI);
-  StatusOr<int> copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.value(), copy.value());
-}
-
-TEST(StatusOr, TestCopyCtorStatusNotOk) {
-  StatusOr<int> original(util::CancelledError(""));
-  StatusOr<int> copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-}
-
-TEST(StatusOr, TestCopyCtorStatusOKConverting) {
-  const int kI = 4;
-  StatusOr<int>    original(kI);
-  StatusOr<double> copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.value(), copy.value());
-}
-
-TEST(StatusOr, TestCopyCtorStatusNotOkConverting) {
-  StatusOr<int> original(util::CancelledError(""));
-  StatusOr<double> copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-}
-
-TEST(StatusOr, TestAssignmentStatusOk) {
-  const int kI = 4;
-  StatusOr<int> source(kI);
-  StatusOr<int> target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.value(), target.value());
-}
-
-TEST(StatusOr, TestAssignmentStatusNotOk) {
-  StatusOr<int> source(util::CancelledError(""));
-  StatusOr<int> target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-}
-
-TEST(StatusOr, TestAssignmentStatusOKConverting) {
-  const int kI = 4;
-  StatusOr<int>    source(kI);
-  StatusOr<double> target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-  EXPECT_DOUBLE_EQ(source.value(), target.value());
-}
-
-TEST(StatusOr, TestAssignmentStatusNotOkConverting) {
-  StatusOr<int> source(util::CancelledError(""));
-  StatusOr<double> target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-}
-
-TEST(StatusOr, TestStatus) {
-  StatusOr<int> good(4);
-  EXPECT_TRUE(good.ok());
-  StatusOr<int> bad(util::CancelledError(""));
-  EXPECT_FALSE(bad.ok());
-  EXPECT_EQ(util::CancelledError(""), bad.status());
-}
-
-TEST(StatusOr, TestValue) {
-  const int kI = 4;
-  StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.value());
-}
-
-TEST(StatusOr, TestValueConst) {
-  const int kI = 4;
-  const StatusOr<int> thing(kI);
-  EXPECT_EQ(kI, thing.value());
-}
-
-TEST(StatusOr, TestPointerDefaultCtor) {
-  StatusOr<int*> thing;
-  EXPECT_FALSE(thing.ok());
-  EXPECT_EQ(util::UnknownError(""), thing.status());
-}
-
-TEST(StatusOr, TestPointerStatusCtor) {
-  StatusOr<int*> thing(util::CancelledError(""));
-  EXPECT_FALSE(thing.ok());
-  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.value());
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusOk) {
-  const int kI = 0;
-  StatusOr<const int*> original(&kI);
-  StatusOr<const int*> copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(original.value(), copy.value());
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusNotOk) {
-  StatusOr<int*> original(util::CancelledError(""));
-  StatusOr<int*> copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusOKConverting) {
-  Derived derived;
-  StatusOr<Derived*> original(&derived);
-  StatusOr<Base2*>   copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-  EXPECT_EQ(static_cast<const Base2*>(original.value()), copy.value());
-}
-
-TEST(StatusOr, TestPointerCopyCtorStatusNotOkConverting) {
-  StatusOr<Derived*> original(util::CancelledError(""));
-  StatusOr<Base2*>   copy(original);
-  EXPECT_EQ(original.status(), copy.status());
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusOk) {
-  const int kI = 0;
-  StatusOr<const int*> source(&kI);
-  StatusOr<const int*> target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(source.value(), target.value());
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusNotOk) {
-  StatusOr<int*> source(util::CancelledError(""));
-  StatusOr<int*> target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusOKConverting) {
-  Derived derived;
-  StatusOr<Derived*> source(&derived);
-  StatusOr<Base2*>   target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-  EXPECT_EQ(static_cast<const Base2*>(source.value()), target.value());
-}
-
-TEST(StatusOr, TestPointerAssignmentStatusNotOkConverting) {
-  StatusOr<Derived*> source(util::CancelledError(""));
-  StatusOr<Base2*>   target;
-  target = source;
-  EXPECT_EQ(source.status(), target.status());
-}
-
-TEST(StatusOr, TestPointerStatus) {
-  const int kI = 0;
-  StatusOr<const int*> good(&kI);
-  EXPECT_TRUE(good.ok());
-  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.value());
-}
-
-TEST(StatusOr, TestPointerValueConst) {
-  const int kI = 0;
-  const StatusOr<const int*> thing(&kI);
-  EXPECT_EQ(&kI, thing.value());
-}
-
-}  // namespace
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/stl_util.h b/src/google/protobuf/stubs/stl_util.h
deleted file mode 100644
index e6260d0..0000000
--- a/src/google/protobuf/stubs/stl_util.h
+++ /dev/null
@@ -1,90 +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.
-
-// from google3/util/gtl/stl_util.h
-
-#ifndef GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
-#define GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
-
-#include <google/protobuf/stubs/common.h>
-
-#include <algorithm>
-
-// Must be last.
-#include <google/protobuf/port_def.inc>  // NOLINT
-
-namespace google {
-namespace protobuf {
-
-// Inside Google, this function implements a horrible, disgusting hack in which
-// we reach into the string's private implementation and resize it without
-// initializing the new bytes.  In some cases doing this can significantly
-// 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(std::string* s, size_t new_size) {
-  s->resize(new_size);
-}
-
-// As above, but we make sure to follow amortized growth in which we always
-// increase the capacity by at least a constant factor >1.
-inline void STLStringResizeUninitializedAmortized(std::string* s,
-                                                  size_t new_size) {
-  const size_t cap = s->capacity();
-  if (new_size > cap) {
-    // Make sure to always grow by at least a factor of 2x.
-    s->reserve(std::max<size_t>(new_size, 2 * cap));
-  }
-  STLStringResizeUninitialized(s, new_size);
-}
-
-// Return a mutable char* pointing to a string's internal buffer,
-// which may not be null-terminated. Writing through this pointer will
-// modify the string.
-//
-// string_as_array(&str)[i] is valid for 0 <= i < str.size() until the
-// next call to a string method that invalidates iterators.
-//
-// As of 2006-04, there is no standard-blessed way of getting a
-// mutable reference to a string's internal buffer. However, issue 530
-// (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(std::string* str) {
-  // DO NOT USE const_cast<char*>(str->data())! See the unittest for why.
-  return str->empty() ? nullptr : &*str->begin();
-}
-
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>  // NOLINT
-
-#endif  // GOOGLE_PROTOBUF_STUBS_STL_UTIL_H__
diff --git a/src/google/protobuf/stubs/stringpiece.cc b/src/google/protobuf/stubs/stringpiece.cc
deleted file mode 100644
index 7188046..0000000
--- a/src/google/protobuf/stubs/stringpiece.cc
+++ /dev/null
@@ -1,256 +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 <google/protobuf/stubs/stringpiece.h>
-
-#include <string.h>
-#include <algorithm>
-#include <climits>
-#include <string>
-#include <ostream>
-
-#include <google/protobuf/stubs/logging.h>
-
-namespace google {
-namespace protobuf {
-namespace stringpiece_internal {
-
-std::ostream& operator<<(std::ostream& o, StringPiece piece) {
-  o.write(piece.data(), piece.size());
-  return o;
-}
-
-void StringPiece::LogFatalSizeTooBig(size_t size, const char* details) {
-  GOOGLE_LOG(FATAL) << "size too big: " << size << " details: " << details;
-}
-
-void StringPiece::CopyToString(std::string* target) const {
-  target->assign(ptr_, length_);
-}
-
-void StringPiece::AppendToString(std::string* target) const {
-  target->append(ptr_, length_);
-}
-
-bool StringPiece::Consume(StringPiece x) {
-  if (starts_with(x)) {
-    ptr_ += x.length_;
-    length_ -= x.length_;
-    return true;
-  }
-  return false;
-}
-
-bool StringPiece::ConsumeFromEnd(StringPiece x) {
-  if (ends_with(x)) {
-    length_ -= x.length_;
-    return true;
-  }
-  return false;
-}
-
-StringPiece::size_type StringPiece::copy(char* buf, size_type n,
-                                         size_type pos) const {
-  size_type ret = std::min(length_ - pos, n);
-  memcpy(buf, ptr_ + pos, ret);
-  return ret;
-}
-
-bool StringPiece::contains(StringPiece s) const {
-  return find(s, 0) != npos;
-}
-
-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;
-  }
-  const char *result = std::search(ptr_ + pos, ptr_ + length_,
-                                   s.ptr_, s.ptr_ + s.length_);
-  return result == ptr_ + length_ ? npos : result - ptr_;
-}
-
-StringPiece::size_type StringPiece::find(char c, size_type pos) const {
-  if (length_ <= 0 || pos >= static_cast<size_type>(length_)) {
-    return npos;
-  }
-  const char* result = static_cast<const char*>(
-      memchr(ptr_ + pos, c, length_ - pos));
-  return result != nullptr ? result - ptr_ : npos;
-}
-
-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);
-
-  const char* last = ptr_ + std::min(ulen - s.length_, pos) + s.length_;
-  const char* result = std::find_end(ptr_, last, s.ptr_, s.ptr_ + s.length_);
-  return result != last ? result - ptr_ : npos;
-}
-
-// Search range is [0..pos] inclusive.  If pos == npos, search everything.
-StringPiece::size_type StringPiece::rfind(char c, size_type pos) const {
-  // Note: memrchr() is not available on Windows.
-  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;
-}
-
-// For each character in characters_wanted, sets the index corresponding
-// to the ASCII code of that character to 1 in table.  This is used by
-// the find_.*_of methods below to tell whether or not a character is in
-// the lookup table in constant time.
-// The argument `table' must be an array that is large enough to hold all
-// the possible values of an unsigned char.  Thus it should be be declared
-// as follows:
-//   bool table[UCHAR_MAX + 1]
-static inline void BuildLookupTable(StringPiece characters_wanted,
-                                    bool* table) {
-  const StringPiece::size_type length = characters_wanted.length();
-  const char* const data = characters_wanted.data();
-  for (StringPiece::size_type i = 0; i < length; ++i) {
-    table[static_cast<unsigned char>(data[i])] = true;
-  }
-}
-
-StringPiece::size_type StringPiece::find_first_of(StringPiece s,
-                                                  size_type pos) const {
-  if (empty() || s.empty()) {
-    return npos;
-  }
-  // Avoid the cost of BuildLookupTable() for a single-character search.
-  if (s.length_ == 1) return find_first_of(s.ptr_[0], pos);
-
-  bool lookup[UCHAR_MAX + 1] = { false };
-  BuildLookupTable(s, lookup);
-  for (size_type i = pos; i < length_; ++i) {
-    if (lookup[static_cast<unsigned char>(ptr_[i])]) {
-      return i;
-    }
-  }
-  return npos;
-}
-
-StringPiece::size_type StringPiece::find_first_not_of(StringPiece s,
-                                                      size_type pos) const {
-  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 (size_type i = pos; i < length_; ++i) {
-    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
-      return i;
-    }
-  }
-  return npos;
-}
-
-StringPiece::size_type StringPiece::find_first_not_of(char c,
-                                                      size_type pos) const {
-  if (empty()) return npos;
-
-  for (; pos < static_cast<size_type>(length_); ++pos) {
-    if (ptr_[pos] != c) {
-      return pos;
-    }
-  }
-  return npos;
-}
-
-StringPiece::size_type StringPiece::find_last_of(StringPiece s,
-                                                 size_type pos) const {
-  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 (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::size_type StringPiece::find_last_not_of(StringPiece s,
-                                                     size_type pos) const {
-  if (empty()) return npos;
-
-  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) {
-    if (!lookup[static_cast<unsigned char>(ptr_[i])]) {
-      return i;
-    }
-    if (i == 0) break;
-  }
-  return npos;
-}
-
-StringPiece::size_type StringPiece::find_last_not_of(char c,
-                                                     size_type pos) const {
-  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;
-  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
deleted file mode 100644
index c63e25b..0000000
--- a/src/google/protobuf/stubs/stringpiece.h
+++ /dev/null
@@ -1,402 +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.
-
-// A StringPiece points to part or all of a string, Cord, double-quoted string
-// literal, or other string-like object.  A StringPiece does *not* own the
-// string to which it points.  A StringPiece is not null-terminated.
-//
-// You can use StringPiece as a function or method parameter.  A StringPiece
-// parameter can receive a double-quoted string literal argument, a "const
-// char*" argument, a string argument, or a StringPiece argument with no data
-// copying.  Systematic use of StringPiece for arguments reduces data
-// copies and strlen() calls.
-//
-// Prefer passing StringPieces by value:
-//   void MyFunction(StringPiece arg);
-// If circumstances require, you may also pass by const reference:
-//   void MyFunction(const StringPiece& arg);  // not preferred
-// Both of these have the same lifetime semantics.  Passing by value
-// generates slightly smaller code.  For more discussion, see the thread
-// go/stringpiecebyvalue on c-users.
-//
-// StringPiece is also suitable for local variables if you know that
-// the lifetime of the underlying object is longer than the lifetime
-// of your StringPiece variable.
-//
-// Beware of binding a StringPiece to a temporary:
-//   StringPiece sp = obj.MethodReturningString();  // BAD: lifetime problem
-//
-// This code is okay:
-//   string str = obj.MethodReturningString();  // str owns its contents
-//   StringPiece sp(str);  // GOOD, because str outlives sp
-//
-// StringPiece is sometimes a poor choice for a return value and usually a poor
-// choice for a data member.  If you do use a StringPiece this way, it is your
-// responsibility to ensure that the object pointed to by the StringPiece
-// outlives the StringPiece.
-//
-// A StringPiece may represent just part of a string; thus the name "Piece".
-// For example, when splitting a string, vector<StringPiece> is a natural data
-// type for the output.  For another example, a Cord is a non-contiguous,
-// potentially very long string-like object.  The Cord class has an interface
-// that iteratively provides StringPiece objects that point to the
-// successive pieces of a Cord object.
-//
-// A StringPiece is not null-terminated.  If you write code that scans a
-// StringPiece, you must check its length before reading any characters.
-// Common idioms that work on null-terminated strings do not work on
-// StringPiece objects.
-//
-// There are several ways to create a null StringPiece:
-//   StringPiece()
-//   StringPiece(nullptr)
-//   StringPiece(nullptr, 0)
-// For all of the above, sp.data() == nullptr, sp.length() == 0,
-// and sp.empty() == true.  Also, if you create a StringPiece with
-// a non-null pointer then sp.data() != nullptr.  Once created,
-// sp.data() will stay either nullptr or not-nullptr, except if you call
-// sp.clear() or sp.set().
-//
-// Thus, you can use StringPiece(nullptr) to signal an out-of-band value
-// that is different from other StringPiece values.  This is similar
-// to the way that const char* p1 = nullptr; is different from
-// const char* p2 = "";.
-//
-// There are many ways to create an empty StringPiece:
-//   StringPiece()
-//   StringPiece(nullptr)
-//   StringPiece(nullptr, 0)
-//   StringPiece("")
-//   StringPiece("", 0)
-//   StringPiece("abcdef", 0)
-//   StringPiece("abcdef"+6, 0)
-// For all of the above, sp.length() will be 0 and sp.empty() will be true.
-// For some empty StringPiece values, sp.data() will be nullptr.
-// For some empty StringPiece values, sp.data() will not be nullptr.
-//
-// Be careful not to confuse: null StringPiece and empty StringPiece.
-// The set of empty StringPieces properly includes the set of null StringPieces.
-// That is, every null StringPiece is an empty StringPiece,
-// but some non-null StringPieces are empty Stringpieces too.
-//
-// All empty StringPiece values compare equal to each other.
-// Even a null StringPieces compares equal to a non-null empty StringPiece:
-//  StringPiece() == StringPiece("", 0)
-//  StringPiece(nullptr) == StringPiece("abc", 0)
-//  StringPiece(nullptr, 0) == StringPiece("abcdef"+6, 0)
-//
-// Look carefully at this example:
-//   StringPiece("") == nullptr
-// True or false?  TRUE, because StringPiece::operator== converts
-// the right-hand side from nullptr to StringPiece(nullptr),
-// and then compares two zero-length spans of characters.
-// However, we are working to make this example produce a compile error.
-//
-// Suppose you want to write:
-//   bool TestWhat?(StringPiece sp) { return sp == nullptr; }  // BAD
-// Do not do that.  Write one of these instead:
-//   bool TestNull(StringPiece sp) { return sp.data() == nullptr; }
-//   bool TestEmpty(StringPiece sp) { return sp.empty(); }
-// The intent of TestWhat? is unclear.  Did you mean TestNull or TestEmpty?
-// Right now, TestWhat? behaves likes TestEmpty.
-// We are working to make TestWhat? produce a compile error.
-// TestNull is good to test for an out-of-band signal.
-// TestEmpty is good to test for an empty StringPiece.
-//
-// Caveats (again):
-// (1) The lifetime of the pointed-to string (or piece of a string)
-//     must be longer than the lifetime of the StringPiece.
-// (2) There may or may not be a '\0' character after the end of
-//     StringPiece data.
-// (3) A null StringPiece is empty.
-//     An empty StringPiece may or may not be a null StringPiece.
-
-#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
-#define GOOGLE_PROTOBUF_STUBS_STRINGPIECE_H_
-
-#include <assert.h>
-#include <stddef.h>
-#include <string.h>
-#include <iosfwd>
-#include <limits>
-#include <string>
-
-#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 {
-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_;
-  size_type length_;
-
-  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, "string length exceeds max size");
-    }
-#endif
-    return size;
-  }
-
-  // Out-of-line error path.
-  static void LogFatalSizeTooBig(size_type size, const char* details);
-
- public:
-  // We provide non-explicit singleton constructors so users can pass
-  // in a "const char*" or a "string" wherever a "StringPiece" is
-  // expected.
-  //
-  // Style guide exception granted:
-  // http://goto/style-guide-exception-20978288
-  StringPiece() : ptr_(nullptr), length_(0) {}
-
-  StringPiece(const char* str)  // NOLINT(runtime/explicit)
-      : ptr_(str), length_(0) {
-    if (str != nullptr) {
-      length_ = CheckSize(strlen(str));
-    }
-  }
-
-  template <class Allocator>
-  StringPiece(  // NOLINT(runtime/explicit)
-      const std::basic_string<char, std::char_traits<char>, Allocator>& str)
-      : ptr_(str.data()), length_(0) {
-    length_ = CheckSize(str.size());
-  }
-
-#if defined(__cpp_lib_string_view)
-  StringPiece(  // NOLINT(runtime/explicit)
-      std::string_view str)
-      : ptr_(str.data()), length_(0) {
-    length_ = CheckSize(str.size());
-  }
-#endif
-
-  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_pointer data() const { return ptr_; }
-  size_type size() const { return length_; }
-  size_type length() const { return length_; }
-  bool empty() const { return length_ == 0; }
-
-  char operator[](size_type i) const {
-    assert(i < length_);
-    return ptr_[i];
-  }
-
-  void remove_prefix(size_type n) {
-    assert(length_ >= n);
-    ptr_ += n;
-    length_ -= n;
-  }
-
-  void remove_suffix(size_type n) {
-    assert(length_ >= n);
-    length_ -= n;
-  }
-
-  // returns {-1, 0, 1}
-  int compare(StringPiece x) const {
-    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;
-    if (length_ < x.length_) return -1;
-    if (length_ > x.length_) return 1;
-    return 0;
-  }
-
-  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.
-  std::string ToString() const {
-    if (ptr_ == nullptr) return "";
-    return std::string(data(), static_cast<size_type>(size()));
-  }
-
-  explicit operator std::string() const { return ToString(); }
-
-  void CopyToString(std::string* target) const;
-  void AppendToString(std::string* target) const;
-
-  bool starts_with(StringPiece x) const {
-    return (length_ >= x.length_) &&
-           (memcmp(ptr_, x.ptr_, static_cast<size_t>(x.length_)) == 0);
-  }
-
-  bool ends_with(StringPiece x) const {
-    return ((length_ >= x.length_) &&
-            (memcmp(ptr_ + (length_-x.length_), x.ptr_,
-                 static_cast<size_t>(x.length_)) == 0));
-  }
-
-  // Checks whether StringPiece starts with x and if so advances the beginning
-  // of it to past the match.  It's basically a shortcut for starts_with
-  // followed by remove_prefix.
-  bool Consume(StringPiece x);
-  // Like above but for the end of the string.
-  bool ConsumeFromEnd(StringPiece x);
-
-  // standard STL container boilerplate
-  static const size_type npos;
-  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_);
-  }
-  size_type max_size() const { return length_; }
-  size_type capacity() const { return length_; }
-
-  // cpplint.py emits a false positive [build/include_what_you_use]
-  size_type copy(char* buf, size_type n, size_type pos = 0) const;  // NOLINT
-
-  bool contains(StringPiece s) 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;
-
-  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);
-  }
-  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);
-  }
-  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;
-};
-
-// This large function is defined inline so that in a fairly common case where
-// 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::size_type len = x.size();
-  if (len != y.size()) {
-    return false;
-  }
-
-  return x.data() == y.data() || len <= 0 ||
-      memcmp(x.data(), y.data(), static_cast<size_t>(len)) == 0;
-}
-
-inline bool operator!=(StringPiece x, StringPiece y) {
-  return !(x == y);
-}
-
-inline bool operator<(StringPiece x, StringPiece y) {
-  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());
-}
-
-inline bool operator>(StringPiece x, StringPiece y) {
-  return y < x;
-}
-
-inline bool operator<=(StringPiece x, StringPiece y) {
-  return !(x > y);
-}
-
-inline bool operator>=(StringPiece x, StringPiece y) {
-  return !(x < y);
-}
-
-// allow StringPiece to be logged
-extern std::ostream& operator<<(std::ostream& o, StringPiece piece);
-
-}  // namespace stringpiece_internal
-
-using ::google::protobuf::stringpiece_internal::StringPiece;
-
-}  // namespace protobuf
-}  // namespace google
-
-GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_START
-template<> struct hash<StringPiece> {
-  size_t operator()(const StringPiece& s) const {
-    size_t result = 0;
-    for (const char *str = s.data(), *end = str + s.size(); str < end; str++) {
-      result = 5 * result + static_cast<size_t>(*str);
-    }
-    return result;
-  }
-};
-GOOGLE_PROTOBUF_HASH_NAMESPACE_DECLARATION_END
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // STRINGS_STRINGPIECE_H_
diff --git a/src/google/protobuf/stubs/stringpiece_unittest.cc b/src/google/protobuf/stubs/stringpiece_unittest.cc
deleted file mode 100644
index ba904cb..0000000
--- a/src/google/protobuf/stubs/stringpiece_unittest.cc
+++ /dev/null
@@ -1,695 +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 <google/protobuf/stubs/stringpiece.h>
-
-#include <iterator>
-#include <map>
-#include <string>
-#include <utility>
-#include <vector>
-
-#include <google/protobuf/testing/googletest.h>
-#include <google/protobuf/stubs/hash.h>
-#include <gtest/gtest.h>
-
-namespace google {
-namespace protobuf {
-namespace {
-TEST(StringPiece, Ctor) {
-  {
-    // Null.
-    StringPiece s10;
-    EXPECT_TRUE(s10.data() == nullptr);
-    EXPECT_EQ(0, s10.length());
-  }
-
-  {
-    // const char* without length.
-    const char* hello = "hello";
-    StringPiece s20(hello);
-    EXPECT_TRUE(s20.data() == hello);
-    EXPECT_EQ(5, s20.length());
-
-    // const char* with length.
-    StringPiece s21(hello, 4);
-    EXPECT_TRUE(s21.data() == hello);
-    EXPECT_EQ(4, s21.length());
-
-    // Not recommended, but valid C++
-    StringPiece s22(hello, 6);
-    EXPECT_TRUE(s22.data() == hello);
-    EXPECT_EQ(6, s22.length());
-  }
-
-  {
-    // std::string.
-    std::string hola = "hola";
-    StringPiece s30(hola);
-    EXPECT_TRUE(s30.data() == hola.data());
-    EXPECT_EQ(4, s30.length());
-
-    // std::string with embedded '\0'.
-    hola.push_back('\0');
-    hola.append("h2");
-    hola.push_back('\0');
-    StringPiece s31(hola);
-    EXPECT_TRUE(s31.data() == hola.data());
-    EXPECT_EQ(8, s31.length());
-  }
-
-#if defined(HAS_GLOBAL_STRING)
-  {
-    // ::string
-    std::string bonjour = "bonjour";
-    StringPiece s40(bonjour);
-    EXPECT_TRUE(s40.data() == bonjour.data());
-    EXPECT_EQ(7, s40.length());
-  }
-#endif
-
-  // TODO(mec): StringPiece(StringPiece x, int pos);
-  // TODO(mec): StringPiece(StringPiece x, int pos, int len);
-  // TODO(mec): StringPiece(const StringPiece&);
-}
-
-TEST(StringPiece, STLComparator) {
-  std::string s1("foo");
-  std::string s2("bar");
-  std::string s3("baz");
-
-  StringPiece p1(s1);
-  StringPiece p2(s2);
-  StringPiece p3(s3);
-
-  typedef std::map<StringPiece, int> TestMap;
-  TestMap map;
-
-  map.insert(std::make_pair(p1, 0));
-  map.insert(std::make_pair(p2, 1));
-  map.insert(std::make_pair(p3, 2));
-  EXPECT_EQ(map.size(), 3);
-
-  TestMap::const_iterator iter = map.begin();
-  EXPECT_EQ(iter->second, 1);
-  ++iter;
-  EXPECT_EQ(iter->second, 2);
-  ++iter;
-  EXPECT_EQ(iter->second, 0);
-  ++iter;
-  EXPECT_TRUE(iter == map.end());
-
-  TestMap::iterator new_iter = map.find("zot");
-  EXPECT_TRUE(new_iter == map.end());
-
-  new_iter = map.find("bar");
-  EXPECT_TRUE(new_iter != map.end());
-
-  map.erase(new_iter);
-  EXPECT_EQ(map.size(), 2);
-
-  iter = map.begin();
-  EXPECT_EQ(iter->second, 2);
-  ++iter;
-  EXPECT_EQ(iter->second, 0);
-  ++iter;
-  EXPECT_TRUE(iter == map.end());
-}
-
-TEST(StringPiece, ComparisonOperators) {
-#define COMPARE(result, op, x, y) \
-  EXPECT_EQ(result, StringPiece((x)) op StringPiece((y))); \
-  EXPECT_EQ(result, StringPiece((x)).compare(StringPiece((y))) op 0)
-
-  COMPARE(true, ==, "",   "");
-  COMPARE(true, ==, "", nullptr);
-  COMPARE(true, ==, nullptr, "");
-  COMPARE(true, ==, "a",  "a");
-  COMPARE(true, ==, "aa", "aa");
-  COMPARE(false, ==, "a",  "");
-  COMPARE(false, ==, "",   "a");
-  COMPARE(false, ==, "a",  "b");
-  COMPARE(false, ==, "a",  "aa");
-  COMPARE(false, ==, "aa", "a");
-
-  COMPARE(false, !=, "",   "");
-  COMPARE(false, !=, "a",  "a");
-  COMPARE(false, !=, "aa", "aa");
-  COMPARE(true, !=, "a",  "");
-  COMPARE(true, !=, "",   "a");
-  COMPARE(true, !=, "a",  "b");
-  COMPARE(true, !=, "a",  "aa");
-  COMPARE(true, !=, "aa", "a");
-
-  COMPARE(true, <, "a",  "b");
-  COMPARE(true, <, "a",  "aa");
-  COMPARE(true, <, "aa", "b");
-  COMPARE(true, <, "aa", "bb");
-  COMPARE(false, <, "a",  "a");
-  COMPARE(false, <, "b",  "a");
-  COMPARE(false, <, "aa", "a");
-  COMPARE(false, <, "b",  "aa");
-  COMPARE(false, <, "bb", "aa");
-
-  COMPARE(true, <=, "a",  "a");
-  COMPARE(true, <=, "a",  "b");
-  COMPARE(true, <=, "a",  "aa");
-  COMPARE(true, <=, "aa", "b");
-  COMPARE(true, <=, "aa", "bb");
-  COMPARE(false, <=, "b",  "a");
-  COMPARE(false, <=, "aa", "a");
-  COMPARE(false, <=, "b",  "aa");
-  COMPARE(false, <=, "bb", "aa");
-
-  COMPARE(false, >=, "a",  "b");
-  COMPARE(false, >=, "a",  "aa");
-  COMPARE(false, >=, "aa", "b");
-  COMPARE(false, >=, "aa", "bb");
-  COMPARE(true, >=, "a",  "a");
-  COMPARE(true, >=, "b",  "a");
-  COMPARE(true, >=, "aa", "a");
-  COMPARE(true, >=, "b",  "aa");
-  COMPARE(true, >=, "bb", "aa");
-
-  COMPARE(false, >, "a",  "a");
-  COMPARE(false, >, "a",  "b");
-  COMPARE(false, >, "a",  "aa");
-  COMPARE(false, >, "aa", "b");
-  COMPARE(false, >, "aa", "bb");
-  COMPARE(true, >, "b",  "a");
-  COMPARE(true, >, "aa", "a");
-  COMPARE(true, >, "b",  "aa");
-  COMPARE(true, >, "bb", "aa");
-
-  std::string x;
-  for (int i = 0; i < 256; i++) {
-    x += 'a';
-    std::string y = x;
-    COMPARE(true, ==, x, y);
-    for (int j = 0; j < i; j++) {
-      std::string z = x;
-      z[j] = 'b';       // Differs in position 'j'
-      COMPARE(false, ==, x, z);
-      COMPARE(true, <, x, z);
-      COMPARE(true, >, z, x);
-      if (j + 1 < i) {
-        z[j + 1] = 'A';  // Differs in position 'j+1' as well
-        COMPARE(false, ==, x, z);
-        COMPARE(true, <, x, z);
-        COMPARE(true, >, z, x);
-        z[j + 1] = 'z';  // Differs in position 'j+1' as well
-        COMPARE(false, ==, x, z);
-        COMPARE(true, <, x, z);
-        COMPARE(true, >, z, x);
-      }
-    }
-  }
-
-#undef COMPARE
-}
-
-TEST(StringPiece, STL1) {
-  const StringPiece a("abcdefghijklmnopqrstuvwxyz");
-  const StringPiece b("abc");
-  const StringPiece c("xyz");
-  const StringPiece d("foobar");
-  const StringPiece e;
-  std::string temp("123");
-  temp += '\0';
-  temp += "456";
-  const StringPiece f(temp);
-
-  EXPECT_EQ(a[6], 'g');
-  EXPECT_EQ(b[0], 'a');
-  EXPECT_EQ(c[2], 'z');
-  EXPECT_EQ(f[3], '\0');
-  EXPECT_EQ(f[5], '5');
-
-  EXPECT_EQ(*d.data(), 'f');
-  EXPECT_EQ(d.data()[5], 'r');
-  EXPECT_TRUE(e.data() == nullptr);
-
-  EXPECT_EQ(*a.begin(), 'a');
-  EXPECT_EQ(*(b.begin() + 2), 'c');
-  EXPECT_EQ(*(c.end() - 1), 'z');
-
-  EXPECT_EQ(*a.rbegin(), 'z');
-  EXPECT_EQ(*(b.rbegin() + 2), 'a');
-  EXPECT_EQ(*(c.rend() - 1), 'x');
-  EXPECT_TRUE(a.rbegin() + 26 == a.rend());
-
-  EXPECT_EQ(a.size(), 26);
-  EXPECT_EQ(b.size(), 3);
-  EXPECT_EQ(c.size(), 3);
-  EXPECT_EQ(d.size(), 6);
-  EXPECT_EQ(e.size(), 0);
-  EXPECT_EQ(f.size(), 7);
-
-  EXPECT_TRUE(!d.empty());
-  EXPECT_TRUE(d.begin() != d.end());
-  EXPECT_TRUE(d.begin() + 6 == d.end());
-
-  EXPECT_TRUE(e.empty());
-  EXPECT_TRUE(e.begin() == e.end());
-
-  EXPECT_GE(a.max_size(), a.capacity());
-  EXPECT_GE(a.capacity(), a.size());
-
-  char buf[4] = { '%', '%', '%', '%' };
-  EXPECT_EQ(a.copy(buf, 4), 4);
-  EXPECT_EQ(buf[0], a[0]);
-  EXPECT_EQ(buf[1], a[1]);
-  EXPECT_EQ(buf[2], a[2]);
-  EXPECT_EQ(buf[3], a[3]);
-  EXPECT_EQ(a.copy(buf, 3, 7), 3);
-  EXPECT_EQ(buf[0], a[7]);
-  EXPECT_EQ(buf[1], a[8]);
-  EXPECT_EQ(buf[2], a[9]);
-  EXPECT_EQ(buf[3], a[3]);
-  EXPECT_EQ(c.copy(buf, 99), 3);
-  EXPECT_EQ(buf[0], c[0]);
-  EXPECT_EQ(buf[1], c[1]);
-  EXPECT_EQ(buf[2], c[2]);
-  EXPECT_EQ(buf[3], a[3]);
-}
-
-// Separated from STL1() because some compilers produce an overly
-// large stack frame for the combined function.
-TEST(StringPiece, STL2) {
-  const StringPiece a("abcdefghijklmnopqrstuvwxyz");
-  const StringPiece b("abc");
-  const StringPiece c("xyz");
-  const StringPiece e;
-  const StringPiece f("123" "\0" "456", 7);
-
-  EXPECT_EQ(StringPiece::npos, std::string::npos);
-
-  EXPECT_EQ(a.find(b), 0);
-  EXPECT_EQ(a.find(b, 1), StringPiece::npos);
-  EXPECT_EQ(a.find(c), 23);
-  EXPECT_EQ(a.find(c, 9), 23);
-  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(e), 0);
-  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(e.find(b), StringPiece::npos);
-  EXPECT_EQ(e.find(b, 7), StringPiece::npos);
-
-  size_t empty_search_pos = std::string().find(std::string());
-  EXPECT_EQ(e.find(e), empty_search_pos);
-  EXPECT_EQ(e.find(e, 4), std::string().find(std::string(), 4));
-
-  EXPECT_EQ(a.find('a'), 0);
-  EXPECT_EQ(a.find('c'), 2);
-  EXPECT_EQ(a.find('z'), 25);
-  EXPECT_EQ(a.find('$'), StringPiece::npos);
-  EXPECT_EQ(a.find('\0'), StringPiece::npos);
-  EXPECT_EQ(f.find('\0'), 3);
-  EXPECT_EQ(f.find('3'), 2);
-  EXPECT_EQ(f.find('5'), 5);
-  EXPECT_EQ(g.find('o'), 4);
-  EXPECT_EQ(g.find('o', 4), 4);
-  EXPECT_EQ(g.find('o', 5), 8);
-  EXPECT_EQ(a.find('b', 5), StringPiece::npos);
-  // empty string nonsense
-  EXPECT_EQ(e.find('\0'), StringPiece::npos);
-  EXPECT_EQ(e.find('\0', 7), StringPiece::npos);
-  EXPECT_EQ(e.find('x'), StringPiece::npos);
-  EXPECT_EQ(e.find('x', 7), StringPiece::npos);
-
-  EXPECT_EQ(a.rfind(b), 0);
-  EXPECT_EQ(a.rfind(b, 1), 0);
-  EXPECT_EQ(a.rfind(c), 23);
-  EXPECT_EQ(a.rfind(c, 22), StringPiece::npos);
-  EXPECT_EQ(a.rfind(c, 1), StringPiece::npos);
-  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(e), a.as_string().rfind(std::string()));
-  EXPECT_EQ(a.rfind(e, 17), 17);
-  EXPECT_EQ(a.rfind(g), StringPiece::npos);
-  EXPECT_EQ(e.rfind(b), StringPiece::npos);
-  EXPECT_EQ(e.rfind(b, 7), StringPiece::npos);
-  // empty string nonsense
-  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);
-  EXPECT_EQ(g.rfind('o', 8), 8);
-  EXPECT_EQ(g.rfind('o', 7), 4);
-  EXPECT_EQ(g.rfind('o', 3), StringPiece::npos);
-  EXPECT_EQ(f.rfind('\0'), 3);
-  EXPECT_EQ(f.rfind('\0', 12), 3);
-  EXPECT_EQ(f.rfind('3'), 2);
-  EXPECT_EQ(f.rfind('5'), 5);
-  // empty string nonsense
-  EXPECT_EQ(e.rfind('o'), StringPiece::npos);
-  EXPECT_EQ(e.rfind('o', 7), StringPiece::npos);
-
-  EXPECT_EQ(a.find_first_of(b), 0);
-  EXPECT_EQ(a.find_first_of(b, 0), 0);
-  EXPECT_EQ(a.find_first_of(b, 1), 1);
-  EXPECT_EQ(a.find_first_of(b, 2), 2);
-  EXPECT_EQ(a.find_first_of(b, 3), StringPiece::npos);
-  EXPECT_EQ(a.find_first_of(c), 23);
-  EXPECT_EQ(a.find_first_of(c, 23), 23);
-  EXPECT_EQ(a.find_first_of(c, 24), 24);
-  EXPECT_EQ(a.find_first_of(c, 25), 25);
-  EXPECT_EQ(a.find_first_of(c, 26), StringPiece::npos);
-  EXPECT_EQ(g.find_first_of(b), 13);
-  EXPECT_EQ(g.find_first_of(c), 0);
-  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(e), StringPiece::npos);
-  EXPECT_EQ(e.find_first_of(b), StringPiece::npos);
-  EXPECT_EQ(e.find_first_of(e), StringPiece::npos);
-
-  EXPECT_EQ(a.find_first_not_of(b), 3);
-  EXPECT_EQ(a.find_first_not_of(c), 0);
-  EXPECT_EQ(b.find_first_not_of(a), StringPiece::npos);
-  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(e), 0);
-  // empty string nonsense
-  EXPECT_EQ(e.find_first_not_of(a), StringPiece::npos);
-  EXPECT_EQ(e.find_first_not_of(e), StringPiece::npos);
-
-  StringPiece h("====");
-  EXPECT_EQ(h.find_first_not_of('='), StringPiece::npos);
-  EXPECT_EQ(h.find_first_not_of('=', 3), StringPiece::npos);
-  EXPECT_EQ(h.find_first_not_of('\0'), 0);
-  EXPECT_EQ(g.find_first_not_of('x'), 2);
-  EXPECT_EQ(f.find_first_not_of('\0'), 0);
-  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(e.find_first_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(e.find_first_not_of('\0'), StringPiece::npos);
-
-  //  StringPiece g("xx not found bb");
-  StringPiece i("56");
-  EXPECT_EQ(h.find_last_of(a), StringPiece::npos);
-  EXPECT_EQ(g.find_last_of(a), g.size()-1);
-  EXPECT_EQ(a.find_last_of(b), 2);
-  EXPECT_EQ(a.find_last_of(c), a.size()-1);
-  EXPECT_EQ(f.find_last_of(i), 6);
-  EXPECT_EQ(a.find_last_of('a'), 0);
-  EXPECT_EQ(a.find_last_of('b'), 1);
-  EXPECT_EQ(a.find_last_of('z'), 25);
-  EXPECT_EQ(a.find_last_of('a', 5), 0);
-  EXPECT_EQ(a.find_last_of('b', 5), 1);
-  EXPECT_EQ(a.find_last_of('b', 0), StringPiece::npos);
-  EXPECT_EQ(a.find_last_of('z', 25), 25);
-  EXPECT_EQ(a.find_last_of('z', 24), StringPiece::npos);
-  EXPECT_EQ(f.find_last_of(i, 5), 5);
-  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(e), StringPiece::npos);
-  EXPECT_EQ(f.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(f), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(e, 4), StringPiece::npos);
-  EXPECT_EQ(e.find_last_of(f, 4), StringPiece::npos);
-
-  EXPECT_EQ(a.find_last_not_of(b), a.size()-1);
-  EXPECT_EQ(a.find_last_not_of(c), 22);
-  EXPECT_EQ(b.find_last_not_of(a), StringPiece::npos);
-  EXPECT_EQ(b.find_last_not_of(b), StringPiece::npos);
-  EXPECT_EQ(f.find_last_not_of(i), 4);
-  EXPECT_EQ(a.find_last_not_of(c, 24), 22);
-  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(e), f.size()-1);
-  EXPECT_EQ(f.find_last_not_of(e, 4), 4);
-  EXPECT_EQ(e.find_last_not_of(e), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(f), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of(e, 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);
-  EXPECT_EQ(h.find_last_not_of('='), StringPiece::npos);
-  EXPECT_EQ(b.find_last_not_of('c'), 1);
-  EXPECT_EQ(h.find_last_not_of('x', 2), 2);
-  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(e.find_last_not_of('x'), StringPiece::npos);
-  EXPECT_EQ(e.find_last_not_of('\0'), StringPiece::npos);
-
-  EXPECT_EQ(a.substr(0, 3), b);
-  EXPECT_EQ(a.substr(23), c);
-  EXPECT_EQ(a.substr(23, 3), c);
-  EXPECT_EQ(a.substr(23, 99), c);
-  EXPECT_EQ(a.substr(0), a);
-  EXPECT_EQ(a.substr(3, 2), "de");
-  // empty string nonsense
-  EXPECT_EQ(a.substr(99, 2), 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);
-}
-
-TEST(StringPiece, Custom) {
-  StringPiece a("foobar");
-  std::string s1("123");
-  s1 += '\0';
-  s1 += "456";
-  StringPiece b(s1);
-  StringPiece e;
-  std::string s2;
-
-  // CopyToString
-  a.CopyToString(&s2);
-  EXPECT_EQ(s2.size(), 6);
-  EXPECT_EQ(s2, "foobar");
-  b.CopyToString(&s2);
-  EXPECT_EQ(s2.size(), 7);
-  EXPECT_EQ(s1, s2);
-  e.CopyToString(&s2);
-  EXPECT_TRUE(s2.empty());
-
-  // AppendToString
-  s2.erase();
-  a.AppendToString(&s2);
-  EXPECT_EQ(s2.size(), 6);
-  EXPECT_EQ(s2, "foobar");
-  a.AppendToString(&s2);
-  EXPECT_EQ(s2.size(), 12);
-  EXPECT_EQ(s2, "foobarfoobar");
-
-  // starts_with
-  EXPECT_TRUE(a.starts_with(a));
-  EXPECT_TRUE(a.starts_with("foo"));
-  EXPECT_TRUE(a.starts_with(e));
-  EXPECT_TRUE(b.starts_with(s1));
-  EXPECT_TRUE(b.starts_with(b));
-  EXPECT_TRUE(b.starts_with(e));
-  EXPECT_TRUE(e.starts_with(""));
-  EXPECT_TRUE(!a.starts_with(b));
-  EXPECT_TRUE(!b.starts_with(a));
-  EXPECT_TRUE(!e.starts_with(a));
-
-  // ends with
-  EXPECT_TRUE(a.ends_with(a));
-  EXPECT_TRUE(a.ends_with("bar"));
-  EXPECT_TRUE(a.ends_with(e));
-  EXPECT_TRUE(b.ends_with(s1));
-  EXPECT_TRUE(b.ends_with(b));
-  EXPECT_TRUE(b.ends_with(e));
-  EXPECT_TRUE(e.ends_with(""));
-  EXPECT_TRUE(!a.ends_with(b));
-  EXPECT_TRUE(!b.ends_with(a));
-  EXPECT_TRUE(!e.ends_with(a));
-
-  // remove_prefix
-  StringPiece c(a);
-  c.remove_prefix(3);
-  EXPECT_EQ(c, "bar");
-  c = a;
-  c.remove_prefix(0);
-  EXPECT_EQ(c, a);
-  c.remove_prefix(c.size());
-  EXPECT_EQ(c, e);
-
-  // remove_suffix
-  c = a;
-  c.remove_suffix(3);
-  EXPECT_EQ(c, "foo");
-  c = a;
-  c.remove_suffix(0);
-  EXPECT_EQ(c, a);
-  c.remove_suffix(c.size());
-  EXPECT_EQ(c, e);
-
-  c = StringPiece("foobar", 7);
-
-  // as_string
-  std::string s3(a.as_string().c_str(), 7);
-  EXPECT_EQ(c, s3);
-  std::string s4(e.as_string());
-  EXPECT_TRUE(s4.empty());
-
-  // ToString
-  {
-    std::string s5(a.ToString().c_str(), 7);
-    EXPECT_EQ(c, s5);
-    std::string s6(e.ToString());
-    EXPECT_TRUE(s6.empty());
-  }
-
-  // Consume
-  {
-    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");
-  }
-
-  {
-    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) {
-  StringPiece a("abcdefg");
-  StringPiece b("abcd");
-  StringPiece c("efg");
-  StringPiece d("gh");
-  EXPECT_TRUE(a.contains(b));
-  EXPECT_TRUE(a.contains(c));
-  EXPECT_TRUE(!a.contains(d));
-}
-
-TEST(StringPiece, NullInput) {
-  // we used to crash here, but now we don't.
-  StringPiece s(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());
-}
-
-TEST(StringPiece, Comparisons2) {
-  StringPiece abc("abcdefghijklmnopqrstuvwxyz");
-
-  // check comparison operations on strings longer than 4 bytes.
-  EXPECT_EQ(abc, StringPiece("abcdefghijklmnopqrstuvwxyz"));
-  EXPECT_EQ(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyz")), 0);
-
-  EXPECT_LT(abc, StringPiece("abcdefghijklmnopqrstuvwxzz"));
-  EXPECT_LT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxzz")), 0);
-
-  EXPECT_GT(abc, StringPiece("abcdefghijklmnopqrstuvwxyy"));
-  EXPECT_GT(abc.compare(StringPiece("abcdefghijklmnopqrstuvwxyy")), 0);
-
-  // starts_with
-  EXPECT_TRUE(abc.starts_with(abc));
-  EXPECT_TRUE(abc.starts_with("abcdefghijklm"));
-  EXPECT_TRUE(!abc.starts_with("abcdefguvwxyz"));
-
-  // ends_with
-  EXPECT_TRUE(abc.ends_with(abc));
-  EXPECT_TRUE(!abc.ends_with("abcdefguvwxyz"));
-  EXPECT_TRUE(abc.ends_with("nopqrstuvwxyz"));
-}
-
-TEST(ComparisonOpsTest, StringCompareNotAmbiguous) {
-  EXPECT_EQ("hello", std::string("hello"));
-  EXPECT_LT("hello", std::string("world"));
-}
-
-TEST(ComparisonOpsTest, HeterogenousStringPieceEquals) {
-  EXPECT_EQ(StringPiece("hello"), std::string("hello"));
-  EXPECT_EQ("hello", StringPiece("hello"));
-}
-
-TEST(FindOneCharTest, EdgeCases) {
-  StringPiece a("xxyyyxx");
-
-  // Set a = "xyyyx".
-  a.remove_prefix(1);
-  a.remove_suffix(1);
-
-  EXPECT_EQ(0, a.find('x'));
-  EXPECT_EQ(0, a.find('x', 0));
-  EXPECT_EQ(4, a.find('x', 1));
-  EXPECT_EQ(4, a.find('x', 4));
-  EXPECT_EQ(StringPiece::npos, a.find('x', 5));
-
-  EXPECT_EQ(4, a.rfind('x'));
-  EXPECT_EQ(4, a.rfind('x', 5));
-  EXPECT_EQ(4, a.rfind('x', 4));
-  EXPECT_EQ(0, a.rfind('x', 3));
-  EXPECT_EQ(0, a.rfind('x', 0));
-
-  // Set a = "yyy".
-  a.remove_prefix(1);
-  a.remove_suffix(1);
-
-  EXPECT_EQ(StringPiece::npos, a.find('x'));
-  EXPECT_EQ(StringPiece::npos, a.rfind('x'));
-}
-
-#ifdef PROTOBUF_HAS_DEATH_TEST
-#ifndef NDEBUG
-TEST(NonNegativeLenTest, NonNegativeLen) {
-  EXPECT_DEATH(StringPiece("xyz", -1), "string length exceeds max size");
-}
-#endif  // ndef DEBUG
-#endif  // PROTOBUF_HAS_DEATH_TEST
-
-}  // namespace
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/stringprintf.cc b/src/google/protobuf/stubs/stringprintf.cc
deleted file mode 100644
index a6ad4c0..0000000
--- a/src/google/protobuf/stubs/stringprintf.cc
+++ /dev/null
@@ -1,175 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2012 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.
-
-// from google3/base/stringprintf.cc
-
-#include <google/protobuf/stubs/stringprintf.h>
-
-#include <errno.h>
-#include <stdarg.h> // For va_list and related operations
-#include <stdio.h> // MSVC requires this for _vsnprintf
-#include <vector>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-
-namespace google {
-namespace protobuf {
-
-#ifdef _MSC_VER
-#ifndef va_copy
-// Define va_copy for MSVC. This is a hack, assuming va_list is simply a
-// pointer into the stack and is safe to copy.
-#define va_copy(dest, src) ((dest) = (src))
-#endif
-#endif
-
-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];
-
-  // It's possible for methods that use a va_list to invalidate
-  // the data in it upon use.  The fix is to make a copy
-  // of the structure before using it and use that copy instead.
-  va_list backup_ap;
-  va_copy(backup_ap, ap);
-  int result = vsnprintf(space, kSpaceLength, format, backup_ap);
-  va_end(backup_ap);
-
-  if (result < kSpaceLength) {
-    if (result >= 0) {
-      // Normal case -- everything fit.
-      dst->append(space, result);
-      return;
-    }
-
-#ifdef _MSC_VER
-    {
-      // Error or MSVC running out of space.  MSVC 8.0 and higher
-      // can be asked about space needed with the special idiom below:
-      va_copy(backup_ap, ap);
-      result = vsnprintf(nullptr, 0, format, backup_ap);
-      va_end(backup_ap);
-    }
-#endif
-
-    if (result < 0) {
-      // Just an error.
-      return;
-    }
-  }
-
-  // Increase the buffer size to the size requested by vsnprintf,
-  // plus one for the closing \0.
-  int length = result+1;
-  char* buf = new char[length];
-
-  // Restore the va_list before we use it again
-  va_copy(backup_ap, ap);
-  result = vsnprintf(buf, length, format, backup_ap);
-  va_end(backup_ap);
-
-  if (result >= 0 && result < length) {
-    // It fit
-    dst->append(buf, result);
-  }
-  delete[] buf;
-}
-
-std::string StringPrintf(const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  std::string result;
-  StringAppendV(&result, format, ap);
-  va_end(ap);
-  return result;
-}
-
-const std::string& SStringPrintf(std::string* dst, const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  dst->clear();
-  StringAppendV(dst, format, ap);
-  va_end(ap);
-  return *dst;
-}
-
-void StringAppendF(std::string* dst, const char* format, ...) {
-  va_list ap;
-  va_start(ap, format);
-  StringAppendV(dst, format, ap);
-  va_end(ap);
-}
-
-// Max arguments supported by StringPrintVector
-const int kStringPrintfVectorMaxArgs = 32;
-
-// An empty block of zero for filler arguments.  This is const so that if
-// printf tries to write to it (via %n) then the program gets a SIGSEGV
-// and we can fix the problem or protect against an attack.
-static const char string_printf_empty_block[256] = { '\0' };
-
-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. "
-      << "Feel free to add support for more if you need it.";
-
-  // Add filler arguments so that bogus format+args have a harder time
-  // crashing the program, corrupting the program (%n),
-  // or displaying random chunks of memory to users.
-
-  const char* cstr[kStringPrintfVectorMaxArgs];
-  for (int i = 0; i < v.size(); ++i) {
-    cstr[i] = v[i].c_str();
-  }
-  for (int i = v.size(); i < GOOGLE_ARRAYSIZE(cstr); ++i) {
-    cstr[i] = &string_printf_empty_block[0];
-  }
-
-  // I do not know any way to pass kStringPrintfVectorMaxArgs arguments,
-  // or any way to build a va_list by hand, or any API for printf
-  // that accepts an array of arguments.  The best I can do is stick
-  // this COMPILE_ASSERT right next to the actual statement.
-
-  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],
-                      cstr[10], cstr[11], cstr[12], cstr[13], cstr[14],
-                      cstr[15], cstr[16], cstr[17], cstr[18], cstr[19],
-                      cstr[20], cstr[21], cstr[22], cstr[23], cstr[24],
-                      cstr[25], cstr[26], cstr[27], cstr[28], cstr[29],
-                      cstr[30], cstr[31]);
-}
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/stringprintf.h b/src/google/protobuf/stubs/stringprintf.h
deleted file mode 100644
index e3858be..0000000
--- a/src/google/protobuf/stubs/stringprintf.h
+++ /dev/null
@@ -1,85 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2012 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.
-
-// from google3/base/stringprintf.h
-//
-// Printf variants that place their output in a C++ string.
-//
-// Usage:
-//      string result = StringPrintf("%d %s\n", 10, "hello");
-//      SStringPrintf(&result, "%d %s\n", 10, "hello");
-//      StringAppendF(&result, "%d %s\n", 20, "there");
-
-#ifndef GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
-#define GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
-
-#include <stdarg.h>
-#include <string>
-#include <vector>
-
-#include <google/protobuf/stubs/common.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-
-// Return a C++ string
-PROTOBUF_EXPORT extern std::string StringPrintf(const char* format, ...);
-
-// Store result into a supplied string and return it
-PROTOBUF_EXPORT extern const std::string& SStringPrintf(std::string* dst,
-                                                        const char* format,
-                                                        ...);
-
-// Append result to a supplied string
-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(std::string* dst, const char* format,
-                                          va_list ap);
-
-// The max arguments supported by StringPrintfVector
-PROTOBUF_EXPORT extern const int kStringPrintfVectorMaxArgs;
-
-// 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 std::string StringPrintfVector(
-    const char* format, const std::vector<std::string>& v);
-
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_STRINGPRINTF_H
diff --git a/src/google/protobuf/stubs/stringprintf_unittest.cc b/src/google/protobuf/stubs/stringprintf_unittest.cc
deleted file mode 100644
index dbecd2b..0000000
--- a/src/google/protobuf/stubs/stringprintf_unittest.cc
+++ /dev/null
@@ -1,155 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2012 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.
-
-// from google3/base/stringprintf_unittest.cc
-
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-#include <array>
-#include <cerrno>
-#include <string>
-
-namespace google {
-namespace protobuf {
-namespace {
-
-TEST(StringPrintfTest, Empty) {
-#if 0
-  // gcc 2.95.3, gcc 4.1.0, and gcc 4.2.2 all warn about this:
-  // warning: zero-length printf format string.
-  // so we do not allow them in google3.
-  EXPECT_EQ("", StringPrintf(""));
-#endif
-  EXPECT_EQ("", StringPrintf("%s", std::string().c_str()));
-  EXPECT_EQ("", StringPrintf("%s", ""));
-}
-
-TEST(StringPrintfTest, Misc) {
-// MSVC and mingw does not support $ format specifier.
-#if !defined(_MSC_VER) && !defined(__MINGW32__)
-  EXPECT_EQ("123hello w", StringPrintf("%3$d%2$s %1$c", 'w', "hello", 123));
-#endif  // !_MSC_VER
-}
-
-TEST(StringAppendFTest, Empty) {
-  std::string value("Hello");
-  const char* empty = "";
-  StringAppendF(&value, "%s", empty);
-  EXPECT_EQ("Hello", value);
-}
-
-TEST(StringAppendFTest, EmptyString) {
-  std::string value("Hello");
-  StringAppendF(&value, "%s", "");
-  EXPECT_EQ("Hello", value);
-}
-
-TEST(StringAppendFTest, String) {
-  std::string value("Hello");
-  StringAppendF(&value, " %s", "World");
-  EXPECT_EQ("Hello World", value);
-}
-
-TEST(StringAppendFTest, Int) {
-  std::string value("Hello");
-  StringAppendF(&value, " %d", 123);
-  EXPECT_EQ("Hello 123", value);
-}
-
-TEST(StringPrintfTest, Multibyte) {
-  // If we are in multibyte mode and feed invalid multibyte sequence,
-  // StringPrintf should return an empty string instead of running
-  // out of memory while trying to determine destination buffer size.
-  // see b/4194543.
-
-  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";
-  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
-  // (e.g. eglibc-2.15, aka pre-GRTEv3) emit the codepoint verbatim.
-  // We test that the output is one of the above.
-  EXPECT_TRUE(value.empty() || value == kInvalidCodePoint);
-
-  // Repeat with longer string, to make sure that the dynamically
-  // allocated path in StringAppendV is handled correctly.
-  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[0]);
-
-  setlocale(LC_CTYPE, old_locale.c_str());
-}
-
-TEST(StringPrintfTest, NoMultibyte) {
-  // No multibyte handling, but the string contains funny chars.
-  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");
-  std::string value = StringPrintf("%.*s", 3, "\375\067s");
-  setlocale(LC_CTYPE, old_locale.c_str());
-  EXPECT_EQ("\375\067s", value);
-}
-
-TEST(StringPrintfTest, DontOverwriteErrno) {
-  // Check that errno isn't overwritten unless we're printing
-  // something significantly larger than what people are normally
-  // printing in their badly written PLOG() statements.
-  errno = ECHILD;
-  std::string value = StringPrintf("Hello, %s!", "World");
-  EXPECT_EQ(ECHILD, errno);
-}
-
-TEST(StringPrintfTest, LargeBuf) {
-  // Check that the large buffer is handled correctly.
-  int n = 2048;
-  char* buf = new char[n+1];
-  memset(buf, ' ', n);
-  buf[n] = 0;
-  std::string value = StringPrintf("%s", buf);
-  EXPECT_EQ(buf, value);
-  delete[] buf;
-}
-
-}  // anonymous namespace
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/structurally_valid.cc b/src/google/protobuf/stubs/structurally_valid.cc
deleted file mode 100644
index a535736..0000000
--- a/src/google/protobuf/stubs/structurally_valid.cc
+++ /dev/null
@@ -1,617 +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: jrm@google.com (Jim Meehan)
-
-#include <google/protobuf/stubs/common.h>
-
-#include <google/protobuf/stubs/stringpiece.h>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-// These four-byte entries compactly encode how many bytes 0..255 to delete
-// in making a string replacement, how many bytes to add 0..255, and the offset
-// 0..64k-1 of the replacement string in remap_string.
-struct RemapEntry {
-  uint8_t delete_bytes;
-  uint8_t add_bytes;
-  uint16_t bytes_offset;
-};
-
-// Exit type codes for state tables. All but the first get stuffed into
-// signed one-byte entries. The first is only generated by executable code.
-// To distinguish from next-state entries, these must be contiguous and
-// all <= kExitNone
-typedef enum {
-  kExitDstSpaceFull = 239,
-  kExitIllegalStructure,  // 240
-  kExitOK,                // 241
-  kExitReject,            // ...
-  kExitReplace1,
-  kExitReplace2,
-  kExitReplace3,
-  kExitReplace21,
-  kExitReplace31,
-  kExitReplace32,
-  kExitReplaceOffset1,
-  kExitReplaceOffset2,
-  kExitReplace1S0,
-  kExitSpecial,
-  kExitDoAgain,
-  kExitRejectAlt,
-  kExitNone               // 255
-} ExitReason;
-
-
-// This struct represents one entire state table. The three initialized byte
-// areas are state_table, remap_base, and remap_string. state0 and state0_size
-// give the byte offset and length within state_table of the initial state --
-// table lookups are expected to start and end in this state, but for
-// truncated UTF-8 strings, may end in a different state. These allow a quick
-// test for that condition. entry_shift is 8 for tables subscripted by a full
-// byte value and 6 for space-optimized tables subscripted by only six
-// significant bits in UTF-8 continuation bytes.
-typedef struct {
-  const uint32_t state0;
-  const uint32_t state0_size;
-  const uint32_t total_size;
-  const int max_expand;
-  const int entry_shift;
-  const int bytes_per_entry;
-  const uint32_t losub;
-  const uint32_t hiadd;
-  const uint8_t* state_table;
-  const RemapEntry* remap_base;
-  const uint8_t* remap_string;
-  const uint8_t* fast_state;
-} UTF8StateMachineObj;
-
-typedef UTF8StateMachineObj UTF8ScanObj;
-
-#define X__ (kExitIllegalStructure)
-#define RJ_ (kExitReject)
-#define S1_ (kExitReplace1)
-#define S2_ (kExitReplace2)
-#define S3_ (kExitReplace3)
-#define S21 (kExitReplace21)
-#define S31 (kExitReplace31)
-#define S32 (kExitReplace32)
-#define T1_ (kExitReplaceOffset1)
-#define T2_ (kExitReplaceOffset2)
-#define S11 (kExitReplace1S0)
-#define SP_ (kExitSpecial)
-#define D__ (kExitDoAgain)
-#define RJA (kExitRejectAlt)
-
-//  Entire table has 9 state blocks of 256 entries each
-static const unsigned int utf8acceptnonsurrogates_STATE0 = 0;     // state[0]
-static const unsigned int utf8acceptnonsurrogates_STATE0_SIZE = 256;  // =[1]
-static const unsigned int utf8acceptnonsurrogates_TOTAL_SIZE = 2304;
-static const unsigned int utf8acceptnonsurrogates_MAX_EXPAND_X4 = 0;
-static const unsigned int utf8acceptnonsurrogates_SHIFT = 8;
-static const unsigned int utf8acceptnonsurrogates_BYTES = 1;
-static const unsigned int utf8acceptnonsurrogates_LOSUB = 0x20202020;
-static const unsigned int utf8acceptnonsurrogates_HIADD = 0x00000000;
-
-static const uint8_t utf8acceptnonsurrogates[] = {
-// state[0] 0x000000 Byte 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,   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,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  2,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   7,   3,   3,
-  4,   5,   5,   5,   6, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[1] 0x000080 Byte 2 of 2
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-  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,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[2] 0x000000 Byte 2 of 3
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[3] 0x001000 Byte 2 of 3
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[4] 0x000000 Byte 2 of 4
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[5] 0x040000 Byte 2 of 4
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[6] 0x100000 Byte 2 of 4
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-  3,   3,   3,   3,   3,   3,   3,   3,    3,   3,   3,   3,   3,   3,   3,   3,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[7] 0x00d000 Byte 2 of 3
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  1,   1,   1,   1,   1,   1,   1,   1,    1,   1,   1,   1,   1,   1,   1,   1,
-  8,   8,   8,   8,   8,   8,   8,   8,    8,   8,   8,   8,   8,   8,   8,   8,
-  8,   8,   8,   8,   8,   8,   8,   8,    8,   8,   8,   8,   8,   8,   8,   8,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-// state[8] 0x00d800 Byte 3 of 3
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-
-RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
-RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
-RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
-RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,  RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_, RJ_,
-
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-X__, X__, X__, X__, X__, X__, X__, X__,  X__, X__, X__, X__, X__, X__, X__, X__,
-};
-
-// Remap base[0] = (del, add, string_offset)
-static const RemapEntry utf8acceptnonsurrogates_remap_base[] = {
-{0, 0, 0} };
-
-// Remap string[0]
-static const unsigned char utf8acceptnonsurrogates_remap_string[] = {
-0 };
-
-static const unsigned char utf8acceptnonsurrogates_fast[256] = {
-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, 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,
-
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-1, 1, 1, 1, 1, 1, 1, 1,  1, 1, 1, 1, 1, 1, 1, 1,
-};
-
-static const UTF8ScanObj utf8acceptnonsurrogates_obj = {
-  utf8acceptnonsurrogates_STATE0,
-  utf8acceptnonsurrogates_STATE0_SIZE,
-  utf8acceptnonsurrogates_TOTAL_SIZE,
-  utf8acceptnonsurrogates_MAX_EXPAND_X4,
-  utf8acceptnonsurrogates_SHIFT,
-  utf8acceptnonsurrogates_BYTES,
-  utf8acceptnonsurrogates_LOSUB,
-  utf8acceptnonsurrogates_HIADD,
-  utf8acceptnonsurrogates,
-  utf8acceptnonsurrogates_remap_base,
-  utf8acceptnonsurrogates_remap_string,
-  utf8acceptnonsurrogates_fast
-};
-
-
-#undef X__
-#undef RJ_
-#undef S1_
-#undef S2_
-#undef S3_
-#undef S21
-#undef S31
-#undef S32
-#undef T1_
-#undef T2_
-#undef S11
-#undef SP_
-#undef D__
-#undef RJA
-
-// Return true if current Tbl pointer is within state0 range
-// Note that unsigned compare checks both ends of range simultaneously
-static inline bool InStateZero(const UTF8ScanObj* st, const uint8_t* Tbl) {
-  const uint8_t* Tbl0 = &st->state_table[st->state0];
-  return (static_cast<uint32_t>(Tbl - Tbl0) < st->state0_size);
-}
-
-namespace {
-
-// Scan a UTF-8 string based on state table.
-// Always scan complete UTF-8 characters
-// Set number of bytes scanned. Return reason for exiting
-int UTF8GenericScan(const UTF8ScanObj* st,
-                    const char * str,
-                    int str_length,
-                    int* bytes_consumed) {
-  *bytes_consumed = 0;
-  if (str_length == 0) return kExitOK;
-
-  int eshift = st->entry_shift;
-  const uint8_t* isrc = reinterpret_cast<const uint8_t*>(str);
-  const uint8_t* src = isrc;
-  const uint8_t* srclimit = isrc + str_length;
-  const uint8_t* srclimit8 = str_length < 7 ? isrc : srclimit - 7;
-  const uint8_t* Tbl_0 = &st->state_table[st->state0];
-
- DoAgain:
-  // Do state-table scan
-  int e = 0;
-  uint8_t c;
-  const uint8_t* Tbl2 = &st->fast_state[0];
-  const uint32_t losub = st->losub;
-  const uint32_t hiadd = st->hiadd;
-  // Check initial few bytes one at a time until 8-byte aligned
-  //----------------------------
-  while ((((uintptr_t)src & 0x07) != 0) &&
-         (src < srclimit) &&
-         Tbl2[src[0]] == 0) {
-    src++;
-  }
-  if (((uintptr_t)src & 0x07) == 0) {
-    // Do fast for groups of 8 identity bytes.
-    // This covers a lot of 7-bit ASCII ~8x faster then the 1-byte loop,
-    // including slowing slightly on cr/lf/ht
-    //----------------------------
-    while (src < srclimit8) {
-      uint32_t s0123 = (reinterpret_cast<const uint32_t *>(src))[0];
-      uint32_t s4567 = (reinterpret_cast<const uint32_t *>(src))[1];
-      src += 8;
-      // This is a fast range check for all bytes in [lowsub..0x80-hiadd)
-      uint32_t temp = (s0123 - losub) | (s0123 + hiadd) |
-                      (s4567 - losub) | (s4567 + hiadd);
-      if ((temp & 0x80808080) != 0) {
-        // We typically end up here on cr/lf/ht; src was incremented
-        int e0123 = (Tbl2[src[-8]] | Tbl2[src[-7]]) |
-                    (Tbl2[src[-6]] | Tbl2[src[-5]]);
-        if (e0123 != 0) {
-          src -= 8;
-          break;
-        }    // Exit on Non-interchange
-        e0123 = (Tbl2[src[-4]] | Tbl2[src[-3]]) |
-                (Tbl2[src[-2]] | Tbl2[src[-1]]);
-        if (e0123 != 0) {
-          src -= 4;
-          break;
-        }    // Exit on Non-interchange
-        // Else OK, go around again
-      }
-    }
-  }
-  //----------------------------
-
-  // Byte-at-a-time scan
-  //----------------------------
-  const uint8_t* Tbl = Tbl_0;
-  while (src < srclimit) {
-    c = *src;
-    e = Tbl[c];
-    src++;
-    if (e >= kExitIllegalStructure) {break;}
-    Tbl = &Tbl_0[e << eshift];
-  }
-  //----------------------------
-
-  // Exit possibilities:
-  //  Some exit code, !state0, back up over last char
-  //  Some exit code, state0, back up one byte exactly
-  //  source consumed, !state0, back up over partial char
-  //  source consumed, state0, exit OK
-  // For illegal byte in state0, avoid backup up over PREVIOUS char
-  // For truncated last char, back up to beginning of it
-
-  if (e >= kExitIllegalStructure) {
-    // Back up over exactly one byte of rejected/illegal UTF-8 character
-    src--;
-    // Back up more if needed
-    if (!InStateZero(st, Tbl)) {
-      do {
-        src--;
-      } while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
-    }
-  } else if (!InStateZero(st, Tbl)) {
-    // Back up over truncated UTF-8 character
-    e = kExitIllegalStructure;
-    do {
-      src--;
-    } while ((src > isrc) && ((src[0] & 0xc0) == 0x80));
-  } else {
-    // Normal termination, source fully consumed
-    e = kExitOK;
-  }
-
-  if (e == kExitDoAgain) {
-    // Loop back up to the fast scan
-    goto DoAgain;
-  }
-
-  *bytes_consumed = src - isrc;
-  return e;
-}
-
-int UTF8GenericScanFastAscii(const UTF8ScanObj* st,
-                    const char * str,
-                    int str_length,
-                    int* bytes_consumed) {
-  *bytes_consumed = 0;
-  if (str_length == 0) return kExitOK;
-
-  const uint8_t* isrc =  reinterpret_cast<const uint8_t*>(str);
-  const uint8_t* src = isrc;
-  const uint8_t* srclimit = isrc + str_length;
-  const uint8_t* srclimit8 = str_length < 7 ? isrc : srclimit - 7;
-  int n;
-  int rest_consumed;
-  int exit_reason;
-  do {
-    // Check initial few bytes one at a time until 8-byte aligned
-    while ((((uintptr_t)src & 0x07) != 0) &&
-           (src < srclimit) && (src[0] < 0x80)) {
-      src++;
-    }
-    if (((uintptr_t)src & 0x07) == 0) {
-      while ((src < srclimit8) &&
-             (((reinterpret_cast<const uint32_t*>(src)[0] |
-                reinterpret_cast<const uint32_t*>(src)[1]) &
-               0x80808080) == 0)) {
-        src += 8;
-      }
-    }
-    while ((src < srclimit) && (src[0] < 0x80)) {
-      src++;
-    }
-    // Run state table on the rest
-    n = src - isrc;
-    exit_reason = UTF8GenericScan(st, str + n, str_length - n, &rest_consumed);
-    src += rest_consumed;
-  } while ( exit_reason == kExitDoAgain );
-
-  *bytes_consumed = src - isrc;
-  return exit_reason;
-}
-
-// Hack:  On some compilers the static tables are initialized at startup.
-//   We can't use them until they are initialized.  However, some Protocol
-//   Buffer parsing happens at static init time and may try to validate
-//   UTF-8 strings.  Since UTF-8 validation is only used for debugging
-//   anyway, we simply always return success if initialization hasn't
-//   occurred yet.
-
-bool module_initialized_ = false;
-
-struct InitDetector {
-  InitDetector() {
-    module_initialized_ = true;
-  }
-};
-InitDetector init_detector;
-
-}  // namespace
-
-bool IsStructurallyValidUTF8(const char* buf, int len) {
-  if (!module_initialized_) return true;
-
-  int bytes_consumed = 0;
-  UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj,
-                           buf, len, &bytes_consumed);
-  return (bytes_consumed == len);
-}
-
-int UTF8SpnStructurallyValid(StringPiece str) {
-  if (!module_initialized_) return str.size();
-
-  int bytes_consumed = 0;
-  UTF8GenericScanFastAscii(&utf8acceptnonsurrogates_obj,
-                           str.data(), str.size(), &bytes_consumed);
-  return bytes_consumed;
-}
-
-// Coerce UTF-8 byte string in src_str to be
-// a structurally-valid equal-length string by selectively
-// overwriting illegal bytes with replace_char (typically blank).
-// replace_char must be legal printable 7-bit Ascii 0x20..0x7e.
-// src_str is read-only. If any overwriting is needed, a modified byte string
-// is created in idst, length isrclen.
-//
-// Returns pointer to output buffer, isrc if no changes were made,
-//  or idst if some bytes were changed.
-//
-// Fast case: all is structurally valid and no byte copying is done.
-//
-char* UTF8CoerceToStructurallyValid(StringPiece src_str, char* idst,
-                                    const char replace_char) {
-  const char* isrc = src_str.data();
-  const int len = src_str.length();
-  int n = UTF8SpnStructurallyValid(src_str);
-  if (n == len) {               // Normal case -- all is cool, return
-    return const_cast<char*>(isrc);
-  } else {                      // Unusual case -- copy w/o bad bytes
-    const char* src = isrc;
-    const char* srclimit = isrc + len;
-    char* dst = idst;
-    memmove(dst, src, n);       // Copy initial good chunk
-    src += n;
-    dst += n;
-    while (src < srclimit) {    // src points to bogus byte or is off the end
-      dst[0] = replace_char;                    // replace one bad byte
-      src++;
-      dst++;
-      StringPiece str2(src, srclimit - src);
-      n = UTF8SpnStructurallyValid(str2);       // scan the remainder
-      memmove(dst, src, n);                     // copy next good chunk
-      src += n;
-      dst += n;
-    }
-  }
-  return idst;
-}
-
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/structurally_valid_unittest.cc b/src/google/protobuf/stubs/structurally_valid_unittest.cc
deleted file mode 100644
index ebd9c42..0000000
--- a/src/google/protobuf/stubs/structurally_valid_unittest.cc
+++ /dev/null
@@ -1,71 +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 2008 Google Inc. All Rights Reserved.
-// Author: xpeng@google.com (Peter Peng)
-
-#include <google/protobuf/stubs/common.h>
-#include <gtest/gtest.h>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-namespace {
-
-TEST(StructurallyValidTest, ValidUTF8String) {
-  // On GCC, this string can be written as:
-  //   "abcd 1234 - \u2014\u2013\u2212"
-  // MSVC seems to interpret \u differently.
-  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
-  for (int i = 1; i < 8; ++i) {
-    EXPECT_TRUE(IsStructurallyValidUTF8(valid_str.data() + i,
-                                        valid_str.size() - i));
-  }
-}
-
-TEST(StructurallyValidTest, InvalidUTF8String) {
-  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
-  for (int i = 1; i < 8; ++i) {
-    EXPECT_FALSE(IsStructurallyValidUTF8(invalid_str.data() + i,
-                                         invalid_str.size() - i));
-  }
-}
-
-}  // namespace
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/strutil.cc b/src/google/protobuf/stubs/strutil.cc
deleted file mode 100644
index 594c8ea..0000000
--- a/src/google/protobuf/stubs/strutil.cc
+++ /dev/null
@@ -1,2479 +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.
-
-// from google3/strings/strutil.cc
-
-#include <google/protobuf/stubs/strutil.h>
-
-#include <errno.h>
-#include <float.h>    // FLT_DIG and DBL_DIG
-#include <limits.h>
-#include <stdio.h>
-#include <cmath>
-#include <iterator>
-#include <limits>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/stl_util.h>
-
-#ifdef _WIN32
-// MSVC has only _snprintf, not snprintf.
-//
-// MinGW has both snprintf and _snprintf, but they appear to be different
-// functions.  The former is buggy.  When invoked like so:
-//   char buffer[32];
-//   snprintf(buffer, 32, "%.*g\n", FLT_DIG, 1.23e10f);
-// it prints "1.23000e+10".  This is plainly wrong:  %g should never print
-// trailing zeros after the decimal point.  For some reason this bug only
-// occurs with some input values, not all.  In any case, _snprintf does the
-// right thing, so we use it.
-#define snprintf _snprintf
-#endif
-
-namespace google {
-namespace protobuf {
-
-// These are defined as macros on some platforms.  #undef them so that we can
-// redefine them.
-#undef isxdigit
-#undef isprint
-
-// The definitions of these in ctype.h change based on locale.  Since our
-// string manipulation is all in relation to the protocol buffer and C++
-// languages, we always want to use the C locale.  So, we re-define these
-// exactly as we want them.
-inline bool isxdigit(char c) {
-  return ('0' <= c && c <= '9') ||
-         ('a' <= c && c <= 'f') ||
-         ('A' <= c && c <= 'F');
-}
-
-inline bool isprint(char c) {
-  return c >= 0x20 && c <= 0x7E;
-}
-
-// ----------------------------------------------------------------------
-// ReplaceCharacters
-//    Replaces any occurrence of the character 'remove' (or the characters
-//    in 'remove') with the character '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);
-       str != nullptr;
-       str = strpbrk(str + 1, remove)) {
-    (*s)[str - str_start] = replacewith;
-  }
-}
-
-void StripWhitespace(std::string *str) {
-  int str_length = str->length();
-
-  // Strip off leading whitespace.
-  int first = 0;
-  while (first < str_length && ascii_isspace(str->at(first))) {
-    ++first;
-  }
-  // If entire string is white space.
-  if (first == str_length) {
-    str->clear();
-    return;
-  }
-  if (first > 0) {
-    str->erase(0, first);
-    str_length -= first;
-  }
-
-  // Strip off trailing whitespace.
-  int last = str_length - 1;
-  while (last >= 0 && ascii_isspace(str->at(last))) {
-    --last;
-  }
-  if (last != (str_length - 1) && last >= 0) {
-    str->erase(last + 1, std::string::npos);
-  }
-}
-
-// ----------------------------------------------------------------------
-// StringReplace()
-//    Replace the "old" pattern with the "new" pattern in a string,
-//    and append the result to "res".  If replace_all is false,
-//    it only replaces the first instance of "old."
-// ----------------------------------------------------------------------
-
-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;
-  }
-
-  std::string::size_type start_pos = 0;
-  std::string::size_type pos;
-  do {
-    pos = s.find(oldsub, start_pos);
-    if (pos == std::string::npos) {
-      break;
-    }
-    res->append(s, start_pos, pos - start_pos);
-    res->append(newsub);
-    start_pos = pos + oldsub.size();  // start searching again after the "old"
-  } while (replace_all);
-  res->append(s, start_pos, s.length() - start_pos);
-}
-
-// ----------------------------------------------------------------------
-// StringReplace()
-//    Give me a string and two patterns "old" and "new", and I replace
-//    the first instance of "old" in the string with "new", if it
-//    exists.  If "global" is true; call this repeatedly until it
-//    fails.  RETURN a new string, regardless of whether the replacement
-//    happened or not.
-// ----------------------------------------------------------------------
-
-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;
-}
-
-// ----------------------------------------------------------------------
-// SplitStringUsing()
-//    Split a string using a character delimiter. Append the components
-//    to 'result'.
-//
-// Note: For multi-character delimiters, this routine will split on *ANY* of
-// the characters in the string, not the entire string as a single delimiter.
-// ----------------------------------------------------------------------
-template <typename ITR>
-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];
-    const char* p = full.data();
-    const char* end = p + full.size();
-    while (p != end) {
-      if (*p == c) {
-        ++p;
-      } else {
-        const char* start = p;
-        while (++p != end && *p != c);
-        *result++ = std::string(start, p - start);
-      }
-    }
-    return;
-  }
-
-  std::string::size_type begin_index, end_index;
-  begin_index = full.find_first_not_of(delim);
-  while (begin_index != std::string::npos) {
-    end_index = full.find_first_of(delim, begin_index);
-    if (end_index == std::string::npos) {
-      *result++ = std::string(full.substr(begin_index));
-      return;
-    }
-    *result++ =
-        std::string(full.substr(begin_index, (end_index - begin_index)));
-    begin_index = full.find_first_not_of(delim, end_index);
-  }
-}
-
-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);
-}
-
-// Split a string using a character delimiter. Append the components
-// to 'result'.  If there are consecutive delimiters, this function
-// will return corresponding empty strings. The string is split into
-// at most the specified number of pieces greedily. This means that the
-// last piece may possibly be split further. To split into as many pieces
-// as possible, specify 0 as the number of pieces.
-//
-// If "full" is the empty string, yields an empty string as the only value.
-//
-// If "pieces" is negative for some reason, it returns the whole string
-// ----------------------------------------------------------------------
-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 == std::string::npos) {
-      *result++ = std::string(full.substr(begin_index));
-      return;
-    }
-    *result++ =
-        std::string(full.substr(begin_index, (end_index - begin_index)));
-    begin_index = end_index + 1;
-  }
-  *result++ = std::string(full.substr(begin_index));
-}
-
-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);
-}
-
-// ----------------------------------------------------------------------
-// JoinStrings()
-//    This merges a vector of string components with delim inserted
-//    as separaters between components.
-//
-// ----------------------------------------------------------------------
-template <class ITERATOR>
-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);
-
-  // Precompute resulting length so we can reserve() memory in one shot.
-  int length = 0;
-  for (ITERATOR iter = start; iter != end; ++iter) {
-    if (iter != start) {
-      length += delim_length;
-    }
-    length += iter->size();
-  }
-  result->reserve(length);
-
-  // Now combine everything.
-  for (ITERATOR iter = start; iter != end; ++iter) {
-    if (iter != start) {
-      result->append(delim, delim_length);
-    }
-    result->append(iter->data(), iter->size());
-  }
-}
-
-void JoinStrings(const std::vector<std::string> &components, const char *delim,
-                 std::string *result) {
-  JoinStringsIterator(components.begin(), components.end(), delim, result);
-}
-
-// ----------------------------------------------------------------------
-// UnescapeCEscapeSequences()
-//    This does all the unescaping that C does: \ooo, \r, \n, etc
-//    Returns length of resulting string.
-//    The implementation of \x parses any positive number of hex digits,
-//    but it is an error if the value requires more than 8 bits, and the
-//    result is truncated to 8 bits.
-//
-//    The second call stores its errors in a supplied string vector.
-//    If the string vector pointer is nullptr, it reports the errors with LOG().
-// ----------------------------------------------------------------------
-
-#define IS_OCTAL_DIGIT(c) (((c) >= '0') && ((c) <= '7'))
-
-// Protocol buffers doesn't ever care about errors, but I don't want to remove
-// the code.
-#define LOG_STRING(LEVEL, VECTOR) GOOGLE_LOG_IF(LEVEL, false)
-
-int UnescapeCEscapeSequences(const char* source, char* dest) {
-  return UnescapeCEscapeSequences(source, dest, nullptr);
-}
-
-int UnescapeCEscapeSequences(const char *source, char *dest,
-                             std::vector<std::string> *errors) {
-  GOOGLE_DCHECK(errors == nullptr) << "Error reporting not implemented.";
-
-  char* d = dest;
-  const char* p = source;
-
-  // Small optimization for case where source = dest and there's no escaping
-  while ( p == d && *p != '\0' && *p != '\\' )
-    p++, d++;
-
-  while (*p != '\0') {
-    if (*p != '\\') {
-      *d++ = *p++;
-    } else {
-      switch ( *++p ) {                    // skip past the '\\'
-        case '\0':
-          LOG_STRING(ERROR, errors) << "String cannot end with \\";
-          *d = '\0';
-          return d - dest;   // we're done with p
-        case 'a':  *d++ = '\a';  break;
-        case 'b':  *d++ = '\b';  break;
-        case 'f':  *d++ = '\f';  break;
-        case 'n':  *d++ = '\n';  break;
-        case 'r':  *d++ = '\r';  break;
-        case 't':  *d++ = '\t';  break;
-        case 'v':  *d++ = '\v';  break;
-        case '\\': *d++ = '\\';  break;
-        case '?':  *d++ = '\?';  break;    // \?  Who knew?
-        case '\'': *d++ = '\'';  break;
-        case '"':  *d++ = '\"';  break;
-        case '0': case '1': case '2': case '3':  // octal digit: 1 to 3 digits
-        case '4': case '5': case '6': case '7': {
-          char ch = *p - '0';
-          if ( IS_OCTAL_DIGIT(p[1]) )
-            ch = ch * 8 + *++p - '0';
-          if ( IS_OCTAL_DIGIT(p[1]) )      // safe (and easy) to do this twice
-            ch = ch * 8 + *++p - '0';      // now points at last digit
-          *d++ = ch;
-          break;
-        }
-        case 'x': case 'X': {
-          if (!isxdigit(p[1])) {
-            if (p[1] == '\0') {
-              LOG_STRING(ERROR, errors) << "String cannot end with \\x";
-            } else {
-              LOG_STRING(ERROR, errors) <<
-                "\\x cannot be followed by non-hex digit: \\" << *p << p[1];
-            }
-            break;
-          }
-          unsigned int ch = 0;
-          const char *hex_start = p;
-          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 "
-                << "\\" << std::string(hex_start, p + 1 - hex_start)
-                << " exceeds 8 bits";
-          *d++ = ch;
-          break;
-        }
-#if 0  // TODO(kenton):  Support \u and \U?  Requires runetochar().
-        case 'u': {
-          // \uhhhh => convert 4 hex digits to UTF-8
-          char32 rune = 0;
-          const char *hex_start = p;
-          for (int i = 0; i < 4; ++i) {
-            if (isxdigit(p[1])) {  // Look one char ahead.
-              rune = (rune << 4) + hex_digit_to_int(*++p);  // Advance p.
-            } else {
-              LOG_STRING(ERROR, errors)
-                << "\\u must be followed by 4 hex digits: \\"
-                <<  std::string(hex_start, p+1-hex_start);
-              break;
-            }
-          }
-          d += runetochar(d, &rune);
-          break;
-        }
-        case 'U': {
-          // \Uhhhhhhhh => convert 8 hex digits to UTF-8
-          char32 rune = 0;
-          const char *hex_start = p;
-          for (int i = 0; i < 8; ++i) {
-            if (isxdigit(p[1])) {  // Look one char ahead.
-              // Don't change rune until we're sure this
-              // is within the Unicode limit, but do advance p.
-              char32 newrune = (rune << 4) + hex_digit_to_int(*++p);
-              if (newrune > 0x10FFFF) {
-                LOG_STRING(ERROR, errors)
-                  << "Value of \\"
-                  << std::string(hex_start, p + 1 - hex_start)
-                  << " exceeds Unicode limit (0x10FFFF)";
-                break;
-              } else {
-                rune = newrune;
-              }
-            } else {
-              LOG_STRING(ERROR, errors)
-                << "\\U must be followed by 8 hex digits: \\"
-                <<  std::string(hex_start, p+1-hex_start);
-              break;
-            }
-          }
-          d += runetochar(d, &rune);
-          break;
-        }
-#endif
-        default:
-          LOG_STRING(ERROR, errors) << "Unknown escape sequence: \\" << *p;
-      }
-      p++;                                 // read past letter we escaped
-    }
-  }
-  *d = '\0';
-  return d - dest;
-}
-
-// ----------------------------------------------------------------------
-// UnescapeCEscapeString()
-//    This does the same thing as UnescapeCEscapeSequences, but creates
-//    a new string. The caller does not need to worry about allocating
-//    a dest buffer. This should be used for non performance critical
-//    tasks such as printing debug messages. It is safe for src and dest
-//    to be the same.
-//
-//    The second call stores its errors in a supplied string vector.
-//    If the string vector pointer is nullptr, it reports the errors with LOG().
-//
-//    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 std::string &src, std::string *dest) {
-  return UnescapeCEscapeString(src, dest, nullptr);
-}
-
-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);
-  dest->assign(unescaped.get(), len);
-  return len;
-}
-
-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 std::string(unescaped.get(), len);
-}
-
-// ----------------------------------------------------------------------
-// CEscapeString()
-// CHexEscapeString()
-//    Copies 'src' to 'dest', escaping dangerous characters using
-//    C-style escape sequences. This is very useful for preparing query
-//    flags. 'src' and 'dest' should not overlap. The 'Hex' version uses
-//    hexadecimal rather than octal sequences.
-//    Returns the number of bytes written to 'dest' (not including the \0)
-//    or -1 if there was insufficient space.
-//
-//    Currently only \n, \r, \t, ", ', \ and !isprint() chars are escaped.
-// ----------------------------------------------------------------------
-int CEscapeInternal(const char* src, int src_len, char* dest,
-                    int dest_len, bool use_hex, bool utf8_safe) {
-  const char* src_end = src + src_len;
-  int used = 0;
-  bool last_hex_escape = false; // true if last output char was \xNN
-
-  for (; src < src_end; src++) {
-    if (dest_len - used < 2)   // Need space for two letter escape
-      return -1;
-
-    bool is_hex_escape = false;
-    switch (*src) {
-      case '\n': dest[used++] = '\\'; dest[used++] = 'n';  break;
-      case '\r': dest[used++] = '\\'; dest[used++] = 'r';  break;
-      case '\t': dest[used++] = '\\'; dest[used++] = 't';  break;
-      case '\"': dest[used++] = '\\'; dest[used++] = '\"'; break;
-      case '\'': dest[used++] = '\\'; dest[used++] = '\''; break;
-      case '\\': dest[used++] = '\\'; dest[used++] = '\\'; break;
-      default:
-        // Note that if we emit \xNN and the src 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 ((!utf8_safe || static_cast<uint8_t>(*src) < 0x80) &&
-            (!isprint(*src) ||
-             (last_hex_escape && isxdigit(*src)))) {
-          if (dest_len - used < 4) // need space for 4 letter escape
-            return -1;
-          sprintf(dest + used, (use_hex ? "\\x%02x" : "\\%03o"),
-                  static_cast<uint8_t>(*src));
-          is_hex_escape = use_hex;
-          used += 4;
-        } else {
-          dest[used++] = *src; break;
-        }
-    }
-    last_hex_escape = is_hex_escape;
-  }
-
-  if (dest_len - used < 1)   // make sure that there is room for \0
-    return -1;
-
-  dest[used] = '\0';   // doesn't count towards return value though
-  return used;
-}
-
-// Calculates the length of the C-style escaped version of 'src'.
-// Assumes that non-printable characters are escaped using octal sequences, and
-// that UTF-8 bytes are not handled specially.
-static inline size_t CEscapedLength(StringPiece src) {
-  static char c_escaped_len[256] = {
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 2, 2, 4, 4, 2, 4, 4,  // \t, \n, \r
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    1, 1, 2, 1, 1, 1, 1, 2, 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'..'9'
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'A'..'O'
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 2, 1, 1, 1,  // 'P'..'Z', '\'
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,  // 'a'..'o'
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 4,  // 'p'..'z', DEL
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-    4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4, 4,
-  };
-
-  size_t escaped_len = 0;
-  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];
-  }
-  return escaped_len;
-}
-
-// ----------------------------------------------------------------------
-// Escapes 'src' using C-style escape sequences, and appends the escaped string
-// to 'dest'. This version is faster than calling CEscapeInternal as it computes
-// 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, std::string *dest) {
-  size_t escaped_len = CEscapedLength(src);
-  if (escaped_len == src.size()) {
-    dest->append(src.data(), src.size());
-    return;
-  }
-
-  size_t cur_dest_len = dest->size();
-  dest->resize(cur_dest_len + escaped_len);
-  char* append_ptr = &(*dest)[cur_dest_len];
-
-  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;
-      case '\r': *append_ptr++ = '\\'; *append_ptr++ = 'r'; break;
-      case '\t': *append_ptr++ = '\\'; *append_ptr++ = 't'; break;
-      case '\"': *append_ptr++ = '\\'; *append_ptr++ = '\"'; break;
-      case '\'': *append_ptr++ = '\\'; *append_ptr++ = '\''; break;
-      case '\\': *append_ptr++ = '\\'; *append_ptr++ = '\\'; break;
-      default:
-        if (!isprint(c)) {
-          *append_ptr++ = '\\';
-          *append_ptr++ = '0' + c / 64;
-          *append_ptr++ = '0' + (c % 64) / 8;
-          *append_ptr++ = '0' + c % 8;
-        } else {
-          *append_ptr++ = c;
-        }
-        break;
-    }
-  }
-}
-
-std::string CEscape(const std::string &src) {
-  std::string dest;
-  CEscapeAndAppend(src, &dest);
-  return dest;
-}
-
-namespace strings {
-
-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 std::string(dest.get(), len);
-}
-
-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 std::string(dest.get(), len);
-}
-
-}  // namespace strings
-
-// ----------------------------------------------------------------------
-// strto32_adaptor()
-// strtou32_adaptor()
-//    Implementation of strto[u]l replacements that have identical
-//    overflow and underflow characteristics for both ILP-32 and LP-64
-//    platforms, including errno preservation in error-free calls.
-// ----------------------------------------------------------------------
-
-int32_t strto32_adaptor(const char *nptr, char **endptr, int base) {
-  const int saved_errno = errno;
-  errno = 0;
-  const long result = strtol(nptr, endptr, base);
-  if (errno == ERANGE && result == LONG_MIN) {
-    return std::numeric_limits<int32_t>::min();
-  } else if (errno == ERANGE && result == LONG_MAX) {
-    return std::numeric_limits<int32_t>::max();
-  } else if (errno == 0 && result < std::numeric_limits<int32_t>::min()) {
-    errno = ERANGE;
-    return std::numeric_limits<int32_t>::min();
-  } else if (errno == 0 && result > std::numeric_limits<int32_t>::max()) {
-    errno = ERANGE;
-    return std::numeric_limits<int32_t>::max();
-  }
-  if (errno == 0)
-    errno = saved_errno;
-  return static_cast<int32_t>(result);
-}
-
-uint32_t strtou32_adaptor(const char *nptr, char **endptr, int base) {
-  const int saved_errno = errno;
-  errno = 0;
-  const unsigned long result = strtoul(nptr, endptr, base);
-  if (errno == ERANGE && result == ULONG_MAX) {
-    return std::numeric_limits<uint32_t>::max();
-  } else if (errno == 0 && result > std::numeric_limits<uint32_t>::max()) {
-    errno = ERANGE;
-    return std::numeric_limits<uint32_t>::max();
-  }
-  if (errno == 0)
-    errno = saved_errno;
-  return static_cast<uint32_t>(result);
-}
-
-inline bool safe_parse_sign(std::string *text /*inout*/,
-                            bool *negative_ptr /*output*/) {
-  const char* start = text->data();
-  const char* end = start + text->size();
-
-  // Consume whitespace.
-  while (start < end && (start[0] == ' ')) {
-    ++start;
-  }
-  while (start < end && (end[-1] == ' ')) {
-    --end;
-  }
-  if (start >= end) {
-    return false;
-  }
-
-  // Consume sign.
-  *negative_ptr = (start[0] == '-');
-  if (*negative_ptr || start[0] == '+') {
-    ++start;
-    if (start >= end) {
-      return false;
-    }
-  }
-  *text = text->substr(start - text->data(), end - start);
-  return true;
-}
-
-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();
-  assert(vmax > 0);
-  assert(vmax >= base);
-  const IntType vmax_over_base = vmax / base;
-  const char* start = text.data();
-  const char* end = start + text.size();
-  // loop over digits
-  for (; start < end; ++start) {
-    unsigned char c = static_cast<unsigned char>(start[0]);
-    int digit = c - '0';
-    if (digit >= base || digit < 0) {
-      *value_p = value;
-      return false;
-    }
-    if (value > vmax_over_base) {
-      *value_p = vmax;
-      return false;
-    }
-    value *= base;
-    if (value > vmax - digit) {
-      *value_p = vmax;
-      return false;
-    }
-    value += digit;
-  }
-  *value_p = value;
-  return true;
-}
-
-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();
-  assert(vmin < 0);
-  assert(vmin <= 0 - base);
-  IntType vmin_over_base = vmin / base;
-  // 2003 c++ standard [expr.mul]
-  // "... the sign of the remainder is implementation-defined."
-  // Although (vmin/base)*base + vmin%base is always vmin.
-  // 2011 c++ standard tightens the spec but we cannot rely on it.
-  if (vmin % base > 0) {
-    vmin_over_base += 1;
-  }
-  const char* start = text.data();
-  const char* end = start + text.size();
-  // loop over digits
-  for (; start < end; ++start) {
-    unsigned char c = static_cast<unsigned char>(start[0]);
-    int digit = c - '0';
-    if (digit >= base || digit < 0) {
-      *value_p = value;
-      return false;
-    }
-    if (value < vmin_over_base) {
-      *value_p = vmin;
-      return false;
-    }
-    value *= base;
-    if (value < vmin + digit) {
-      *value_p = vmin;
-      return false;
-    }
-    value -= digit;
-  }
-  *value_p = value;
-  return true;
-}
-
-template <typename IntType>
-bool safe_int_internal(std::string text, IntType *value_p) {
-  *value_p = 0;
-  bool negative;
-  if (!safe_parse_sign(&text, &negative)) {
-    return false;
-  }
-  if (!negative) {
-    return safe_parse_positive_int(text, value_p);
-  } else {
-    return safe_parse_negative_int(text, 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) {
-    return false;
-  }
-  return safe_parse_positive_int(text, value_p);
-}
-
-// ----------------------------------------------------------------------
-// FastIntToBuffer()
-// FastInt64ToBuffer()
-// FastHexToBuffer()
-// FastHex64ToBuffer()
-// FastHex32ToBuffer()
-// ----------------------------------------------------------------------
-
-// Offset into buffer where FastInt64ToBuffer places the end of string
-// null character.  Also used by FastInt64ToBufferLeft.
-static const int kFastInt64ToBufferOffset = 21;
-
-char *FastInt64ToBuffer(int64_t i, char* buffer) {
-  // We could collapse the positive and negative sections, but that
-  // would be slightly slower for positive numbers...
-  // 22 bytes is enough to store -2**64, -18446744073709551616.
-  char* p = buffer + kFastInt64ToBufferOffset;
-  *p-- = '\0';
-  if (i >= 0) {
-    do {
-      *p-- = '0' + i % 10;
-      i /= 10;
-    } while (i > 0);
-    return p + 1;
-  } else {
-    // On different platforms, % and / have different behaviors for
-    // negative numbers, so we need to jump through hoops to make sure
-    // we don't divide negative numbers.
-    if (i > -10) {
-      i = -i;
-      *p-- = '0' + i;
-      *p = '-';
-      return p;
-    } else {
-      // Make sure we aren't at MIN_INT, in which case we can't say i = -i
-      i = i + 10;
-      i = -i;
-      *p-- = '0' + i % 10;
-      // Undo what we did a moment ago
-      i = i / 10 + 1;
-      do {
-        *p-- = '0' + i % 10;
-        i /= 10;
-      } while (i > 0);
-      *p = '-';
-      return p;
-    }
-  }
-}
-
-// Offset into buffer where FastInt32ToBuffer places the end of string
-// null character.  Also used by FastInt32ToBufferLeft
-static const int kFastInt32ToBufferOffset = 11;
-
-// Yes, this is a duplicate of FastInt64ToBuffer.  But, we need this for the
-// compiler to generate 32 bit arithmetic instructions.  It's much faster, at
-// least with 32 bit binaries.
-char *FastInt32ToBuffer(int32_t i, char* buffer) {
-  // We could collapse the positive and negative sections, but that
-  // would be slightly slower for positive numbers...
-  // 12 bytes is enough to store -2**32, -4294967296.
-  char* p = buffer + kFastInt32ToBufferOffset;
-  *p-- = '\0';
-  if (i >= 0) {
-    do {
-      *p-- = '0' + i % 10;
-      i /= 10;
-    } while (i > 0);
-    return p + 1;
-  } else {
-    // On different platforms, % and / have different behaviors for
-    // negative numbers, so we need to jump through hoops to make sure
-    // we don't divide negative numbers.
-    if (i > -10) {
-      i = -i;
-      *p-- = '0' + i;
-      *p = '-';
-      return p;
-    } else {
-      // Make sure we aren't at MIN_INT, in which case we can't say i = -i
-      i = i + 10;
-      i = -i;
-      *p-- = '0' + i % 10;
-      // Undo what we did a moment ago
-      i = i / 10 + 1;
-      do {
-        *p-- = '0' + i % 10;
-        i /= 10;
-      } while (i > 0);
-      *p = '-';
-      return p;
-    }
-  }
-}
-
-char *FastHexToBuffer(int i, char* buffer) {
-  GOOGLE_CHECK(i >= 0) << "FastHexToBuffer() wants non-negative integers, not " << i;
-
-  static const char *hexdigits = "0123456789abcdef";
-  char *p = buffer + 21;
-  *p-- = '\0';
-  do {
-    *p-- = hexdigits[i & 15];   // mod by 16
-    i >>= 4;                    // divide by 16
-  } while (i > 0);
-  return p + 1;
-}
-
-char *InternalFastHexToBuffer(uint64_t value, char* buffer, int num_byte) {
-  static const char *hexdigits = "0123456789abcdef";
-  buffer[num_byte] = '\0';
-  for (int i = num_byte - 1; i >= 0; i--) {
-#ifdef _M_X64
-    // MSVC x64 platform has a bug optimizing the uint32(value) in the #else
-    // block. Given that the uint32 cast was to improve performance on 32-bit
-    // platforms, we use 64-bit '&' directly.
-    buffer[i] = hexdigits[value & 0xf];
-#else
-    buffer[i] = hexdigits[uint32_t(value) & 0xf];
-#endif
-    value >>= 4;
-  }
-  return buffer;
-}
-
-char *FastHex64ToBuffer(uint64_t value, char* buffer) {
-  return InternalFastHexToBuffer(value, buffer, 16);
-}
-
-char *FastHex32ToBuffer(uint32_t value, char* buffer) {
-  return InternalFastHexToBuffer(value, buffer, 8);
-}
-
-// ----------------------------------------------------------------------
-// FastInt32ToBufferLeft()
-// FastUInt32ToBufferLeft()
-// FastInt64ToBufferLeft()
-// FastUInt64ToBufferLeft()
-//
-// Like the Fast*ToBuffer() functions above, these are intended for speed.
-// Unlike the Fast*ToBuffer() functions, however, these functions write
-// their output to the beginning of the buffer (hence the name, as the
-// output is left-aligned).  The caller is responsible for ensuring that
-// the buffer has enough space to hold the output.
-//
-// Returns a pointer to the end of the string (i.e. the null character
-// terminating the string).
-// ----------------------------------------------------------------------
-
-static const char two_ASCII_digits[100][2] = {
-  {'0','0'}, {'0','1'}, {'0','2'}, {'0','3'}, {'0','4'},
-  {'0','5'}, {'0','6'}, {'0','7'}, {'0','8'}, {'0','9'},
-  {'1','0'}, {'1','1'}, {'1','2'}, {'1','3'}, {'1','4'},
-  {'1','5'}, {'1','6'}, {'1','7'}, {'1','8'}, {'1','9'},
-  {'2','0'}, {'2','1'}, {'2','2'}, {'2','3'}, {'2','4'},
-  {'2','5'}, {'2','6'}, {'2','7'}, {'2','8'}, {'2','9'},
-  {'3','0'}, {'3','1'}, {'3','2'}, {'3','3'}, {'3','4'},
-  {'3','5'}, {'3','6'}, {'3','7'}, {'3','8'}, {'3','9'},
-  {'4','0'}, {'4','1'}, {'4','2'}, {'4','3'}, {'4','4'},
-  {'4','5'}, {'4','6'}, {'4','7'}, {'4','8'}, {'4','9'},
-  {'5','0'}, {'5','1'}, {'5','2'}, {'5','3'}, {'5','4'},
-  {'5','5'}, {'5','6'}, {'5','7'}, {'5','8'}, {'5','9'},
-  {'6','0'}, {'6','1'}, {'6','2'}, {'6','3'}, {'6','4'},
-  {'6','5'}, {'6','6'}, {'6','7'}, {'6','8'}, {'6','9'},
-  {'7','0'}, {'7','1'}, {'7','2'}, {'7','3'}, {'7','4'},
-  {'7','5'}, {'7','6'}, {'7','7'}, {'7','8'}, {'7','9'},
-  {'8','0'}, {'8','1'}, {'8','2'}, {'8','3'}, {'8','4'},
-  {'8','5'}, {'8','6'}, {'8','7'}, {'8','8'}, {'8','9'},
-  {'9','0'}, {'9','1'}, {'9','2'}, {'9','3'}, {'9','4'},
-  {'9','5'}, {'9','6'}, {'9','7'}, {'9','8'}, {'9','9'}
-};
-
-char* FastUInt32ToBufferLeft(uint32_t u, char* buffer) {
-  uint32_t digits;
-  const char *ASCII_digits = nullptr;
-  // The idea of this implementation is to trim the number of divides to as few
-  // as possible by using multiplication and subtraction rather than mod (%),
-  // and by outputting two digits at a time rather than one.
-  // The huge-number case is first, in the hopes that the compiler will output
-  // that case in one branch-free block of code, and only output conditional
-  // branches into it from below.
-  if (u >= 1000000000) {  // >= 1,000,000,000
-    digits = u / 100000000;  // 100,000,000
-    ASCII_digits = two_ASCII_digits[digits];
-    buffer[0] = ASCII_digits[0];
-    buffer[1] = ASCII_digits[1];
-    buffer += 2;
-sublt100_000_000:
-    u -= digits * 100000000;  // 100,000,000
-lt100_000_000:
-    digits = u / 1000000;  // 1,000,000
-    ASCII_digits = two_ASCII_digits[digits];
-    buffer[0] = ASCII_digits[0];
-    buffer[1] = ASCII_digits[1];
-    buffer += 2;
-sublt1_000_000:
-    u -= digits * 1000000;  // 1,000,000
-lt1_000_000:
-    digits = u / 10000;  // 10,000
-    ASCII_digits = two_ASCII_digits[digits];
-    buffer[0] = ASCII_digits[0];
-    buffer[1] = ASCII_digits[1];
-    buffer += 2;
-sublt10_000:
-    u -= digits * 10000;  // 10,000
-lt10_000:
-    digits = u / 100;
-    ASCII_digits = two_ASCII_digits[digits];
-    buffer[0] = ASCII_digits[0];
-    buffer[1] = ASCII_digits[1];
-    buffer += 2;
-sublt100:
-    u -= digits * 100;
-lt100:
-    digits = u;
-    ASCII_digits = two_ASCII_digits[digits];
-    buffer[0] = ASCII_digits[0];
-    buffer[1] = ASCII_digits[1];
-    buffer += 2;
-done:
-    *buffer = 0;
-    return buffer;
-  }
-
-  if (u < 100) {
-    digits = u;
-    if (u >= 10) goto lt100;
-    *buffer++ = '0' + digits;
-    goto done;
-  }
-  if (u  <  10000) {   // 10,000
-    if (u >= 1000) goto lt10_000;
-    digits = u / 100;
-    *buffer++ = '0' + digits;
-    goto sublt100;
-  }
-  if (u  <  1000000) {   // 1,000,000
-    if (u >= 100000) goto lt1_000_000;
-    digits = u / 10000;  //    10,000
-    *buffer++ = '0' + digits;
-    goto sublt10_000;
-  }
-  if (u  <  100000000) {   // 100,000,000
-    if (u >= 10000000) goto lt100_000_000;
-    digits = u / 1000000;  //   1,000,000
-    *buffer++ = '0' + digits;
-    goto sublt1_000_000;
-  }
-  // we already know that u < 1,000,000,000
-  digits = u / 100000000;   // 100,000,000
-  *buffer++ = '0' + digits;
-  goto sublt100_000_000;
-}
-
-char* FastInt32ToBufferLeft(int32_t i, char* buffer) {
-  uint32_t u = 0;
-  if (i < 0) {
-    *buffer++ = '-';
-    u -= i;
-  } else {
-    u = i;
-  }
-  return FastUInt32ToBufferLeft(u, buffer);
-}
-
-char* FastUInt64ToBufferLeft(uint64_t u64, char* buffer) {
-  int digits;
-  const char *ASCII_digits = nullptr;
-
-  uint32_t u = static_cast<uint32_t>(u64);
-  if (u == u64) return FastUInt32ToBufferLeft(u, buffer);
-
-  uint64_t top_11_digits = u64 / 1000000000;
-  buffer = FastUInt64ToBufferLeft(top_11_digits, buffer);
-  u = u64 - (top_11_digits * 1000000000);
-
-  digits = u / 10000000;  // 10,000,000
-  GOOGLE_DCHECK_LT(digits, 100);
-  ASCII_digits = two_ASCII_digits[digits];
-  buffer[0] = ASCII_digits[0];
-  buffer[1] = ASCII_digits[1];
-  buffer += 2;
-  u -= digits * 10000000;  // 10,000,000
-  digits = u / 100000;  // 100,000
-  ASCII_digits = two_ASCII_digits[digits];
-  buffer[0] = ASCII_digits[0];
-  buffer[1] = ASCII_digits[1];
-  buffer += 2;
-  u -= digits * 100000;  // 100,000
-  digits = u / 1000;  // 1,000
-  ASCII_digits = two_ASCII_digits[digits];
-  buffer[0] = ASCII_digits[0];
-  buffer[1] = ASCII_digits[1];
-  buffer += 2;
-  u -= digits * 1000;  // 1,000
-  digits = u / 10;
-  ASCII_digits = two_ASCII_digits[digits];
-  buffer[0] = ASCII_digits[0];
-  buffer[1] = ASCII_digits[1];
-  buffer += 2;
-  u -= digits * 10;
-  digits = u;
-  *buffer++ = '0' + digits;
-  *buffer = 0;
-  return buffer;
-}
-
-char* FastInt64ToBufferLeft(int64_t i, char* buffer) {
-  uint64_t u = 0;
-  if (i < 0) {
-    *buffer++ = '-';
-    u -= i;
-  } else {
-    u = i;
-  }
-  return FastUInt64ToBufferLeft(u, buffer);
-}
-
-// ----------------------------------------------------------------------
-// SimpleItoa()
-//    Description: converts an integer to a string.
-//
-//    Return value: string
-// ----------------------------------------------------------------------
-
-std::string SimpleItoa(int i) {
-  char buffer[kFastToBufferSize];
-  return (sizeof(i) == 4) ?
-    FastInt32ToBuffer(i, buffer) :
-    FastInt64ToBuffer(i, buffer);
-}
-
-std::string SimpleItoa(unsigned int i) {
-  char buffer[kFastToBufferSize];
-  return std::string(buffer, (sizeof(i) == 4)
-                                 ? FastUInt32ToBufferLeft(i, buffer)
-                                 : FastUInt64ToBufferLeft(i, buffer));
-}
-
-std::string SimpleItoa(long i) {
-  char buffer[kFastToBufferSize];
-  return (sizeof(i) == 4) ?
-    FastInt32ToBuffer(i, buffer) :
-    FastInt64ToBuffer(i, buffer);
-}
-
-std::string SimpleItoa(unsigned long i) {
-  char buffer[kFastToBufferSize];
-  return std::string(buffer, (sizeof(i) == 4)
-                                 ? FastUInt32ToBufferLeft(i, buffer)
-                                 : FastUInt64ToBufferLeft(i, buffer));
-}
-
-std::string SimpleItoa(long long i) {
-  char buffer[kFastToBufferSize];
-  return (sizeof(i) == 4) ?
-    FastInt32ToBuffer(i, buffer) :
-    FastInt64ToBuffer(i, buffer);
-}
-
-std::string SimpleItoa(unsigned long long i) {
-  char buffer[kFastToBufferSize];
-  return std::string(buffer, (sizeof(i) == 4)
-                                 ? FastUInt32ToBufferLeft(i, buffer)
-                                 : FastUInt64ToBufferLeft(i, buffer));
-}
-
-// ----------------------------------------------------------------------
-// SimpleDtoa()
-// SimpleFtoa()
-// DoubleToBuffer()
-// FloatToBuffer()
-//    We want to print the value without losing precision, but we also do
-//    not want to print more digits than necessary.  This turns out to be
-//    trickier than it sounds.  Numbers like 0.2 cannot be represented
-//    exactly in binary.  If we print 0.2 with a very large precision,
-//    e.g. "%.50g", we get "0.2000000000000000111022302462515654042363167".
-//    On the other hand, if we set the precision too low, we lose
-//    significant digits when printing numbers that actually need them.
-//    It turns out there is no precision value that does the right thing
-//    for all numbers.
-//
-//    Our strategy is to first try printing with a precision that is never
-//    over-precise, then parse the result with strtod() to see if it
-//    matches.  If not, we print again with a precision that will always
-//    give a precise result, but may use more digits than necessary.
-//
-//    An arguably better strategy would be to use the algorithm described
-//    in "How to Print Floating-Point Numbers Accurately" by Steele &
-//    White, e.g. as implemented by David M. Gay's dtoa().  It turns out,
-//    however, that the following implementation is about as fast as
-//    DMG's code.  Furthermore, DMG's code locks mutexes, which means it
-//    will not scale well on multi-core machines.  DMG's code is slightly
-//    more accurate (in that it will never use more digits than
-//    necessary), but this is probably irrelevant for most users.
-//
-//    Rob Pike and Ken Thompson also have an implementation of dtoa() in
-//    third_party/fmt/fltfmt.cc.  Their implementation is similar to this
-//    one in that it makes guesses and then uses strtod() to check them.
-//    Their implementation is faster because they use their own code to
-//    generate the digits in the first place rather than use snprintf(),
-//    thus avoiding format string parsing overhead.  However, this makes
-//    it considerably more complicated than the following implementation,
-//    and it is embedded in a larger library.  If speed turns out to be
-//    an issue, we could re-implement this in terms of their
-//    implementation.
-// ----------------------------------------------------------------------
-
-std::string SimpleDtoa(double value) {
-  char buffer[kDoubleToBufferSize];
-  return DoubleToBuffer(value, buffer);
-}
-
-std::string SimpleFtoa(float value) {
-  char buffer[kFloatToBufferSize];
-  return FloatToBuffer(value, buffer);
-}
-
-static inline bool IsValidFloatChar(char c) {
-  return ('0' <= c && c <= '9') ||
-         c == 'e' || c == 'E' ||
-         c == '+' || c == '-';
-}
-
-void DelocalizeRadix(char* buffer) {
-  // Fast check:  if the buffer has a normal decimal point, assume no
-  // translation is needed.
-  if (strchr(buffer, '.') != nullptr) return;
-
-  // Find the first unknown character.
-  while (IsValidFloatChar(*buffer)) ++buffer;
-
-  if (*buffer == '\0') {
-    // No radix character found.
-    return;
-  }
-
-  // We are now pointing at the locale-specific radix character.  Replace it
-  // with '.'.
-  *buffer = '.';
-  ++buffer;
-
-  if (!IsValidFloatChar(*buffer) && *buffer != '\0') {
-    // It appears the radix was a multi-byte character.  We need to remove the
-    // extra bytes.
-    char* target = buffer;
-    do { ++buffer; } while (!IsValidFloatChar(*buffer) && *buffer != '\0');
-    memmove(target, buffer, strlen(buffer) + 1);
-  }
-}
-
-char* DoubleToBuffer(double value, char* buffer) {
-  // DBL_DIG is 15 for IEEE-754 doubles, which are used on almost all
-  // platforms these days.  Just in case some system exists where DBL_DIG
-  // is significantly larger -- and risks overflowing our buffer -- we have
-  // this assert.
-  static_assert(DBL_DIG < 20, "DBL_DIG_is_too_big");
-
-  if (value == std::numeric_limits<double>::infinity()) {
-    strcpy(buffer, "inf");
-    return buffer;
-  } else if (value == -std::numeric_limits<double>::infinity()) {
-    strcpy(buffer, "-inf");
-    return buffer;
-  } else if (std::isnan(value)) {
-    strcpy(buffer, "nan");
-    return buffer;
-  }
-
-  int snprintf_result =
-    snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG, value);
-
-  // The snprintf should never overflow because the buffer is significantly
-  // larger than the precision we asked for.
-  GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
-
-  // We need to make parsed_value volatile in order to force the compiler to
-  // write it out to the stack.  Otherwise, it may keep the value in a
-  // register, and if it does that, it may keep it as a long double instead
-  // of a double.  This long double may have extra bits that make it compare
-  // unequal to "value" even though it would be exactly equal if it were
-  // truncated to a double.
-  volatile double parsed_value = internal::NoLocaleStrtod(buffer, nullptr);
-  if (parsed_value != value) {
-    snprintf_result =
-        snprintf(buffer, kDoubleToBufferSize, "%.*g", DBL_DIG + 2, value);
-
-    // Should never overflow; see above.
-    GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kDoubleToBufferSize);
-  }
-
-  DelocalizeRadix(buffer);
-  return buffer;
-}
-
-static int memcasecmp(const char *s1, const char *s2, size_t len) {
-  const unsigned char *us1 = reinterpret_cast<const unsigned char *>(s1);
-  const unsigned char *us2 = reinterpret_cast<const unsigned char *>(s2);
-
-  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])));
-    if (diff != 0) return diff;
-  }
-  return 0;
-}
-
-inline bool CaseEqual(StringPiece s1, StringPiece s2) {
-  if (s1.size() != s2.size()) return false;
-  return memcasecmp(s1.data(), s2.data(), s1.size()) == 0;
-}
-
-bool safe_strtob(StringPiece str, bool* value) {
-  GOOGLE_CHECK(value != nullptr) << "nullptr output boolean given.";
-  if (CaseEqual(str, "true") || CaseEqual(str, "t") ||
-      CaseEqual(str, "yes") || CaseEqual(str, "y") ||
-      CaseEqual(str, "1")) {
-    *value = true;
-    return true;
-  }
-  if (CaseEqual(str, "false") || CaseEqual(str, "f") ||
-      CaseEqual(str, "no") || CaseEqual(str, "n") ||
-      CaseEqual(str, "0")) {
-    *value = false;
-    return true;
-  }
-  return false;
-}
-
-bool safe_strtof(const char* str, float* value) {
-  char* endptr;
-  errno = 0;  // errno only gets set on errors
-#if defined(_WIN32) || defined (__hpux)  // has no strtof()
-  *value = internal::NoLocaleStrtod(str, &endptr);
-#else
-  *value = strtof(str, &endptr);
-#endif
-  return *str != 0 && *endptr == 0 && errno == 0;
-}
-
-bool safe_strtod(const char* str, double* value) {
-  char* endptr;
-  *value = internal::NoLocaleStrtod(str, &endptr);
-  if (endptr != str) {
-    while (ascii_isspace(*endptr)) ++endptr;
-  }
-  // Ignore range errors from strtod.  The values it
-  // returns on underflow and overflow are the right
-  // fallback in a robust setting.
-  return *str != '\0' && *endptr == '\0';
-}
-
-bool safe_strto32(const std::string &str, int32_t *value) {
-  return safe_int_internal(str, value);
-}
-
-bool safe_strtou32(const std::string &str, uint32_t *value) {
-  return safe_uint_internal(str, value);
-}
-
-bool safe_strto64(const std::string &str, int64_t *value) {
-  return safe_int_internal(str, value);
-}
-
-bool safe_strtou64(const std::string &str, uint64_t *value) {
-  return safe_uint_internal(str, value);
-}
-
-char* FloatToBuffer(float value, char* buffer) {
-  // FLT_DIG is 6 for IEEE-754 floats, which are used on almost all
-  // platforms these days.  Just in case some system exists where FLT_DIG
-  // is significantly larger -- and risks overflowing our buffer -- we have
-  // this assert.
-  static_assert(FLT_DIG < 10, "FLT_DIG_is_too_big");
-
-  if (value == std::numeric_limits<double>::infinity()) {
-    strcpy(buffer, "inf");
-    return buffer;
-  } else if (value == -std::numeric_limits<double>::infinity()) {
-    strcpy(buffer, "-inf");
-    return buffer;
-  } else if (std::isnan(value)) {
-    strcpy(buffer, "nan");
-    return buffer;
-  }
-
-  int snprintf_result =
-    snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG, value);
-
-  // The snprintf should never overflow because the buffer is significantly
-  // larger than the precision we asked for.
-  GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
-
-  float parsed_value;
-  if (!safe_strtof(buffer, &parsed_value) || parsed_value != value) {
-    snprintf_result =
-        snprintf(buffer, kFloatToBufferSize, "%.*g", FLT_DIG + 3, value);
-
-    // Should never overflow; see above.
-    GOOGLE_DCHECK(snprintf_result > 0 && snprintf_result < kFloatToBufferSize);
-  }
-
-  DelocalizeRadix(buffer);
-  return buffer;
-}
-
-namespace strings {
-
-AlphaNum::AlphaNum(strings::Hex hex) {
-  char *const end = &digits[kFastToBufferSize];
-  char *writer = end;
-  uint64_t value = hex.value;
-  uint64_t width = hex.spec;
-  // We accomplish minimum width by OR'ing in 0x10000 to the user's value,
-  // where 0x10000 is the smallest hex number that is as wide as the user
-  // asked for.
-  uint64_t mask = (static_cast<uint64_t>(1) << ((width - 1) * 4)) | value;
-  static const char hexdigits[] = "0123456789abcdef";
-  do {
-    *--writer = hexdigits[value & 0xF];
-    value >>= 4;
-    mask >>= 4;
-  } while (mask != 0);
-  piece_data_ = writer;
-  piece_size_ = end - writer;
-}
-
-}  // namespace strings
-
-// ----------------------------------------------------------------------
-// StrCat()
-//    This merges the given strings or integers, with no delimiter.  This
-//    is designed to be the fastest possible way to construct a string out
-//    of a mix of raw C strings, C++ strings, and integer values.
-// ----------------------------------------------------------------------
-
-// Append is merely a version of memcpy that returns the address of the byte
-// after the area just overwritten.  It comes in multiple flavors to minimize
-// call overhead.
-static char *Append1(char *out, const AlphaNum &x) {
-  if (x.size() > 0) {
-    memcpy(out, x.data(), x.size());
-    out += x.size();
-  }
-  return out;
-}
-
-static char *Append2(char *out, const AlphaNum &x1, const AlphaNum &x2) {
-  if (x1.size() > 0) {
-    memcpy(out, x1.data(), x1.size());
-    out += x1.size();
-  }
-  if (x2.size() > 0) {
-    memcpy(out, x2.data(), x2.size());
-    out += x2.size();
-  }
-  return out;
-}
-
-static char *Append4(char *out, const AlphaNum &x1, const AlphaNum &x2,
-                     const AlphaNum &x3, const AlphaNum &x4) {
-  if (x1.size() > 0) {
-    memcpy(out, x1.data(), x1.size());
-    out += x1.size();
-  }
-  if (x2.size() > 0) {
-    memcpy(out, x2.data(), x2.size());
-    out += x2.size();
-  }
-  if (x3.size() > 0) {
-    memcpy(out, x3.data(), x3.size());
-    out += x3.size();
-  }
-  if (x4.size() > 0) {
-    memcpy(out, x4.data(), x4.size());
-    out += x4.size();
-  }
-  return out;
-}
-
-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);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return 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);
-  out = Append1(out, c);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return 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);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return 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);
-  out = Append1(out, e);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return 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();
-  char *out = Append4(begin, a, b, c, d);
-  out = Append2(out, e, f);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return 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();
-  char *out = Append4(begin, a, b, c, d);
-  out = Append2(out, e, f);
-  out = Append1(out, g);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return 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();
-  char *out = Append4(begin, a, b, c, d);
-  out = Append4(out, e, f, g, h);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return 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();
-  char *out = Append4(begin, a, b, c, d);
-  out = Append4(out, e, f, g, h);
-  out = Append1(out, i);
-  GOOGLE_DCHECK_EQ(out, begin + result.size());
-  return result;
-}
-
-// It's possible to call StrAppend with a char * pointer that is partway into
-// the string we're appending to.  However the results of this are random.
-// Therefore, check for this in debug mode.  Use unsigned math so we only have
-// to do one comparison.
-#define GOOGLE_DCHECK_NO_OVERLAP(dest, src) \
-    GOOGLE_DCHECK_GT(uintptr_t((src).data() - (dest).data()), \
-                     uintptr_t((dest).size()))
-
-void StrAppend(std::string *result, const AlphaNum &a) {
-  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
-  result->append(a.data(), a.size());
-}
-
-void StrAppend(std::string *result, const AlphaNum &a, const AlphaNum &b) {
-  GOOGLE_DCHECK_NO_OVERLAP(*result, a);
-  GOOGLE_DCHECK_NO_OVERLAP(*result, b);
-  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(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);
-  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);
-  out = Append1(out, c);
-  GOOGLE_DCHECK_EQ(out, begin + result->size());
-}
-
-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);
-  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 std::string &substring,
-                           const std::string &replacement, std::string *s) {
-  GOOGLE_CHECK(s != nullptr);
-  if (s->empty() || substring.empty())
-    return 0;
-  std::string tmp;
-  int num_replacements = 0;
-  int pos = 0;
-  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);
-    // Append the replacement for the match.
-    tmp.append(replacement.begin(), replacement.end());
-  }
-  // Append the content after the last match. If no replacements were made, the
-  // original string is left untouched.
-  if (num_replacements > 0) {
-    tmp.append(*s, pos, s->length() - pos);
-    s->swap(tmp);
-  }
-  return num_replacements;
-}
-
-int CalculateBase64EscapedLen(int input_len, bool do_padding) {
-  // Base64 encodes three bytes of input at a time. If the input is not
-  // divisible by three, we pad as appropriate.
-  //
-  // (from http://tools.ietf.org/html/rfc3548)
-  // Special processing is performed if fewer than 24 bits are available
-  // at the end of the data being encoded.  A full encoding quantum is
-  // always completed at the end of a quantity.  When fewer than 24 input
-  // bits are available in an input group, zero bits are added (on the
-  // right) to form an integral number of 6-bit groups.  Padding at the
-  // end of the data is performed using the '=' character.  Since all base
-  // 64 input is an integral number of octets, only the following cases
-  // can arise:
-
-
-  // Base64 encodes each three bytes of input into four bytes of output.
-  int len = (input_len / 3) * 4;
-
-  if (input_len % 3 == 0) {
-    // (from http://tools.ietf.org/html/rfc3548)
-    // (1) the final quantum of encoding input is an integral multiple of 24
-    // bits; here, the final unit of encoded output will be an integral
-    // multiple of 4 characters with no "=" padding,
-  } else if (input_len % 3 == 1) {
-    // (from http://tools.ietf.org/html/rfc3548)
-    // (2) the final quantum of encoding input is exactly 8 bits; here, the
-    // final unit of encoded output will be two characters followed by two
-    // "=" padding characters, or
-    len += 2;
-    if (do_padding) {
-      len += 2;
-    }
-  } else {  // (input_len % 3 == 2)
-    // (from http://tools.ietf.org/html/rfc3548)
-    // (3) the final quantum of encoding input is exactly 16 bits; here, the
-    // final unit of encoded output will be three characters followed by one
-    // "=" padding character.
-    len += 3;
-    if (do_padding) {
-      len += 1;
-    }
-  }
-
-  assert(len >= input_len);  // make sure we didn't overflow
-  return len;
-}
-
-// Base64Escape does padding, so this calculation includes padding.
-int CalculateBase64EscapedLen(int input_len) {
-  return CalculateBase64EscapedLen(input_len, true);
-}
-
-// ----------------------------------------------------------------------
-// int Base64Unescape() - base64 decoder
-// int Base64Escape() - base64 encoder
-// int WebSafeBase64Unescape() - Google's variation of base64 decoder
-// int WebSafeBase64Escape() - Google's variation of base64 encoder
-//
-// Check out
-// http://tools.ietf.org/html/rfc2045 for formal description, but what we
-// care about is that...
-//   Take the encoded stuff in groups of 4 characters and turn each
-//   character into a code 0 to 63 thus:
-//           A-Z map to 0 to 25
-//           a-z map to 26 to 51
-//           0-9 map to 52 to 61
-//           +(- for WebSafe) maps to 62
-//           /(_ for WebSafe) maps to 63
-//   There will be four numbers, all less than 64 which can be represented
-//   by a 6 digit binary number (aaaaaa, bbbbbb, cccccc, dddddd respectively).
-//   Arrange the 6 digit binary numbers into three bytes as such:
-//   aaaaaabb bbbbcccc ccdddddd
-//   Equals signs (one or two) are used at the end of the encoded block to
-//   indicate that the text was not an integer multiple of three bytes long.
-// ----------------------------------------------------------------------
-
-int Base64UnescapeInternal(const char *src_param, int szsrc,
-                           char *dest, int szdest,
-                           const signed char* unbase64) {
-  static const char kPad64Equals = '=';
-  static const char kPad64Dot = '.';
-
-  int decode = 0;
-  int destidx = 0;
-  int state = 0;
-  unsigned int ch = 0;
-  unsigned int temp = 0;
-
-  // If "char" is signed by default, using *src as an array index results in
-  // accessing negative array elements. Treat the input as a pointer to
-  // unsigned char to avoid this.
-  const unsigned char *src = reinterpret_cast<const unsigned char*>(src_param);
-
-  // The GET_INPUT macro gets the next input character, skipping
-  // over any whitespace, and stopping when we reach the end of the
-  // string or when we read any non-data character.  The arguments are
-  // an arbitrary identifier (used as a label for goto) and the number
-  // of data bytes that must remain in the input to avoid aborting the
-  // loop.
-#define GET_INPUT(label, remain)                 \
-  label:                                         \
-    --szsrc;                                     \
-    ch = *src++;                                 \
-    decode = unbase64[ch];                       \
-    if (decode < 0) {                            \
-      if (ascii_isspace(ch) && szsrc >= remain)  \
-        goto label;                              \
-      state = 4 - remain;                        \
-      break;                                     \
-    }
-
-  // if dest is null, we're just checking to see if it's legal input
-  // rather than producing output.  (I suspect this could just be done
-  // with a regexp...).  We duplicate the loop so this test can be
-  // outside it instead of in every iteration.
-
-  if (dest) {
-    // This loop consumes 4 input bytes and produces 3 output bytes
-    // per iteration.  We can't know at the start that there is enough
-    // data left in the string for a full iteration, so the loop may
-    // break out in the middle; if so 'state' will be set to the
-    // number of input bytes read.
-
-    while (szsrc >= 4)  {
-      // We'll start by optimistically assuming that the next four
-      // bytes of the string (src[0..3]) are four good data bytes
-      // (that is, no nulls, whitespace, padding chars, or illegal
-      // chars).  We need to test src[0..2] for nulls individually
-      // before constructing temp to preserve the property that we
-      // never read past a null in the string (no matter how long
-      // szsrc claims the string is).
-
-      if (!src[0] || !src[1] || !src[2] ||
-          (temp = ((unsigned(unbase64[src[0]]) << 18) |
-                   (unsigned(unbase64[src[1]]) << 12) |
-                   (unsigned(unbase64[src[2]]) << 6) |
-                   (unsigned(unbase64[src[3]])))) & 0x80000000) {
-        // Iff any of those four characters was bad (null, illegal,
-        // whitespace, padding), then temp's high bit will be set
-        // (because unbase64[] is -1 for all bad characters).
-        //
-        // We'll back up and resort to the slower decoder, which knows
-        // how to handle those cases.
-
-        GET_INPUT(first, 4);
-        temp = decode;
-        GET_INPUT(second, 3);
-        temp = (temp << 6) | decode;
-        GET_INPUT(third, 2);
-        temp = (temp << 6) | decode;
-        GET_INPUT(fourth, 1);
-        temp = (temp << 6) | decode;
-      } else {
-        // We really did have four good data bytes, so advance four
-        // characters in the string.
-
-        szsrc -= 4;
-        src += 4;
-        decode = -1;
-        ch = '\0';
-      }
-
-      // temp has 24 bits of input, so write that out as three bytes.
-
-      if (destidx+3 > szdest) return -1;
-      dest[destidx+2] = temp;
-      temp >>= 8;
-      dest[destidx+1] = temp;
-      temp >>= 8;
-      dest[destidx] = temp;
-      destidx += 3;
-    }
-  } else {
-    while (szsrc >= 4)  {
-      if (!src[0] || !src[1] || !src[2] ||
-          (temp = ((unsigned(unbase64[src[0]]) << 18) |
-                   (unsigned(unbase64[src[1]]) << 12) |
-                   (unsigned(unbase64[src[2]]) << 6) |
-                   (unsigned(unbase64[src[3]])))) & 0x80000000) {
-        GET_INPUT(first_no_dest, 4);
-        GET_INPUT(second_no_dest, 3);
-        GET_INPUT(third_no_dest, 2);
-        GET_INPUT(fourth_no_dest, 1);
-      } else {
-        szsrc -= 4;
-        src += 4;
-        decode = -1;
-        ch = '\0';
-      }
-      destidx += 3;
-    }
-  }
-
-#undef GET_INPUT
-
-  // if the loop terminated because we read a bad character, return
-  // now.
-  if (decode < 0 && ch != '\0' &&
-      ch != kPad64Equals && ch != kPad64Dot && !ascii_isspace(ch))
-    return -1;
-
-  if (ch == kPad64Equals || ch == kPad64Dot) {
-    // if we stopped by hitting an '=' or '.', un-read that character -- we'll
-    // look at it again when we count to check for the proper number of
-    // equals signs at the end.
-    ++szsrc;
-    --src;
-  } else {
-    // This loop consumes 1 input byte per iteration.  It's used to
-    // clean up the 0-3 input bytes remaining when the first, faster
-    // loop finishes.  'temp' contains the data from 'state' input
-    // characters read by the first loop.
-    while (szsrc > 0)  {
-      --szsrc;
-      ch = *src++;
-      decode = unbase64[ch];
-      if (decode < 0) {
-        if (ascii_isspace(ch)) {
-          continue;
-        } else if (ch == '\0') {
-          break;
-        } else if (ch == kPad64Equals || ch == kPad64Dot) {
-          // back up one character; we'll read it again when we check
-          // for the correct number of pad characters at the end.
-          ++szsrc;
-          --src;
-          break;
-        } else {
-          return -1;
-        }
-      }
-
-      // Each input character gives us six bits of output.
-      temp = (temp << 6) | decode;
-      ++state;
-      if (state == 4) {
-        // If we've accumulated 24 bits of output, write that out as
-        // three bytes.
-        if (dest) {
-          if (destidx+3 > szdest) return -1;
-          dest[destidx+2] = temp;
-          temp >>= 8;
-          dest[destidx+1] = temp;
-          temp >>= 8;
-          dest[destidx] = temp;
-        }
-        destidx += 3;
-        state = 0;
-        temp = 0;
-      }
-    }
-  }
-
-  // Process the leftover data contained in 'temp' at the end of the input.
-  int expected_equals = 0;
-  switch (state) {
-    case 0:
-      // Nothing left over; output is a multiple of 3 bytes.
-      break;
-
-    case 1:
-      // Bad input; we have 6 bits left over.
-      return -1;
-
-    case 2:
-      // Produce one more output byte from the 12 input bits we have left.
-      if (dest) {
-        if (destidx+1 > szdest) return -1;
-        temp >>= 4;
-        dest[destidx] = temp;
-      }
-      ++destidx;
-      expected_equals = 2;
-      break;
-
-    case 3:
-      // Produce two more output bytes from the 18 input bits we have left.
-      if (dest) {
-        if (destidx+2 > szdest) return -1;
-        temp >>= 2;
-        dest[destidx+1] = temp;
-        temp >>= 8;
-        dest[destidx] = temp;
-      }
-      destidx += 2;
-      expected_equals = 1;
-      break;
-
-    default:
-      // state should have no other values at this point.
-      GOOGLE_LOG(FATAL) << "This can't happen; base64 decoder state = " << state;
-  }
-
-  // The remainder of the string should be all whitespace, mixed with
-  // exactly 0 equals signs, or exactly 'expected_equals' equals
-  // signs.  (Always accepting 0 equals signs is a google extension
-  // not covered in the RFC, as is accepting dot as the pad character.)
-
-  int equals = 0;
-  while (szsrc > 0 && *src) {
-    if (*src == kPad64Equals || *src == kPad64Dot)
-      ++equals;
-    else if (!ascii_isspace(*src))
-      return -1;
-    --szsrc;
-    ++src;
-  }
-
-  return (equals == 0 || equals == expected_equals) ? destidx : -1;
-}
-
-// The arrays below were generated by the following code
-// #include <sys/time.h>
-// #include <stdlib.h>
-// #include <string.h>
-// #include <stdio.h>
-// main()
-// {
-//   static const char Base64[] =
-//     "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-//   const char *pos;
-//   int idx, i, j;
-//   printf("    ");
-//   for (i = 0; i < 255; i += 8) {
-//     for (j = i; j < i + 8; j++) {
-//       pos = strchr(Base64, j);
-//       if ((pos == nullptr) || (j == 0))
-//         idx = -1;
-//       else
-//         idx = pos - Base64;
-//       if (idx == -1)
-//         printf(" %2d,     ", idx);
-//       else
-//         printf(" %2d/""*%c*""/,", idx, j);
-//     }
-//     printf("\n    ");
-//   }
-// }
-//
-// where the value of "Base64[]" was replaced by one of the base-64 conversion
-// tables from the functions below.
-static const signed char kUnBase64[] = {
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -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*/,
-   7/*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
-};
-static const signed char kUnWebSafeBase64[] = {
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -1,      -1,      -1,
-  -1,      -1,      -1,      -1,      -1,      -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,
-  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*/,
-   7/*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
-};
-
-int WebSafeBase64Unescape(const char *src, int szsrc, char *dest, int szdest) {
-  return Base64UnescapeInternal(src, szsrc, dest, szdest, kUnWebSafeBase64);
-}
-
-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
-  const int dest_len = 3 * (slen / 4) + (slen % 4);
-
-  dest->resize(dest_len);
-
-  // We are getting the destination buffer by getting the beginning of the
-  // string and converting it into a char *.
-  const int len = Base64UnescapeInternal(src, slen, string_as_array(dest),
-                                         dest_len, unbase64);
-  if (len < 0) {
-    dest->clear();
-    return false;
-  }
-
-  // could be shorter if there was padding
-  GOOGLE_DCHECK_LE(len, dest_len);
-  dest->erase(len);
-
-  return true;
-}
-
-bool Base64Unescape(StringPiece src, std::string *dest) {
-  return Base64UnescapeInternal(src.data(), src.size(), dest, kUnBase64);
-}
-
-bool WebSafeBase64Unescape(StringPiece src, std::string *dest) {
-  return Base64UnescapeInternal(src.data(), src.size(), dest, kUnWebSafeBase64);
-}
-
-int Base64EscapeInternal(const unsigned char *src, int szsrc,
-                         char *dest, int szdest, const char *base64,
-                         bool do_padding) {
-  static const char kPad64 = '=';
-
-  if (szsrc <= 0) return 0;
-
-  if (szsrc * 4 > szdest * 3) return 0;
-
-  char *cur_dest = dest;
-  const unsigned char *cur_src = src;
-
-  char *limit_dest = dest + szdest;
-  const unsigned char *limit_src = src + szsrc;
-
-  // 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_t in = BigEndian::Load32(cur_src) >> 8;
-
-    cur_dest[0] = base64[in >> 18];
-    in &= 0x3FFFF;
-    cur_dest[1] = base64[in >> 12];
-    in &= 0xFFF;
-    cur_dest[2] = base64[in >> 6];
-    in &= 0x3F;
-    cur_dest[3] = base64[in];
-
-    cur_dest += 4;
-    cur_src += 3;
-  }
-  // To save time, we didn't update szdest or szsrc in the loop.  So do it now.
-  szdest = limit_dest - cur_dest;
-  szsrc = limit_src - cur_src;
-
-  /* now deal with the tail (<=3 bytes) */
-  switch (szsrc) {
-    case 0:
-      // Nothing left; nothing more to do.
-      break;
-    case 1: {
-      // One byte left: this encodes to two characters, and (optionally)
-      // two pad characters to round out the four-character cipherblock.
-      if ((szdest -= 2) < 0) return 0;
-      uint32_t in = cur_src[0];
-      cur_dest[0] = base64[in >> 2];
-      in &= 0x3;
-      cur_dest[1] = base64[in << 4];
-      cur_dest += 2;
-      if (do_padding) {
-        if ((szdest -= 2) < 0) return 0;
-        cur_dest[0] = kPad64;
-        cur_dest[1] = kPad64;
-        cur_dest += 2;
-      }
-      break;
-    }
-    case 2: {
-      // Two bytes left: this encodes to three characters, and (optionally)
-      // one pad character to round out the four-character cipherblock.
-      if ((szdest -= 3) < 0) return 0;
-      uint32_t in = BigEndian::Load16(cur_src);
-      cur_dest[0] = base64[in >> 10];
-      in &= 0x3FF;
-      cur_dest[1] = base64[in >> 4];
-      in &= 0x00F;
-      cur_dest[2] = base64[in << 2];
-      cur_dest += 3;
-      if (do_padding) {
-        if ((szdest -= 1) < 0) return 0;
-        cur_dest[0] = kPad64;
-        cur_dest += 1;
-      }
-      break;
-    }
-    case 3: {
-      // Three bytes left: same as in the big loop above.  We can't do this in
-      // the loop because the loop above always reads 4 bytes, and the fourth
-      // byte is past the end of the input.
-      if ((szdest -= 4) < 0) return 0;
-      uint32_t in = (cur_src[0] << 16) + BigEndian::Load16(cur_src + 1);
-      cur_dest[0] = base64[in >> 18];
-      in &= 0x3FFFF;
-      cur_dest[1] = base64[in >> 12];
-      in &= 0xFFF;
-      cur_dest[2] = base64[in >> 6];
-      in &= 0x3F;
-      cur_dest[3] = base64[in];
-      cur_dest += 4;
-      break;
-    }
-    default:
-      // Should not be reached: blocks of 4 bytes are handled
-      // in the while loop before this switch statement.
-      GOOGLE_LOG(FATAL) << "Logic problem? szsrc = " << szsrc;
-      break;
-  }
-  return (cur_dest - dest);
-}
-
-static const char kBase64Chars[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/";
-
-static const char kWebSafeBase64Chars[] =
-"ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789-_";
-
-int Base64Escape(const unsigned char *src, int szsrc, char *dest, int szdest) {
-  return Base64EscapeInternal(src, szsrc, dest, szdest, kBase64Chars, true);
-}
-int WebSafeBase64Escape(const unsigned char *src, int szsrc, char *dest,
-                        int szdest, bool do_padding) {
-  return Base64EscapeInternal(src, szsrc, dest, szdest,
-                              kWebSafeBase64Chars, do_padding);
-}
-
-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);
-  const int escaped_len = Base64EscapeInternal(src, szsrc,
-                                               string_as_array(dest),
-                                               dest->size(),
-                                               base64_chars,
-                                               do_padding);
-  GOOGLE_DCHECK_EQ(calc_escaped_size, escaped_len);
-  dest->erase(escaped_len);
-}
-
-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, std::string *dest,
-                         bool do_padding) {
-  Base64EscapeInternal(src, szsrc, dest, do_padding, kWebSafeBase64Chars);
-}
-
-void Base64Escape(StringPiece src, std::string *dest) {
-  Base64Escape(reinterpret_cast<const unsigned char*>(src.data()),
-               src.size(), dest, true);
-}
-
-void WebSafeBase64Escape(StringPiece src, std::string *dest) {
-  WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
-                      src.size(), dest, false);
-}
-
-void WebSafeBase64EscapeWithPadding(StringPiece src, std::string *dest) {
-  WebSafeBase64Escape(reinterpret_cast<const unsigned char*>(src.data()),
-                      src.size(), dest, true);
-}
-
-// Helper to append a Unicode code point to a string as UTF8, without bringing
-// in any external dependencies.
-int EncodeAsUTF8Char(uint32_t code_point, char* output) {
-  uint32_t tmp = 0;
-  int len = 0;
-  if (code_point <= 0x7f) {
-    tmp = code_point;
-    len = 1;
-  } else if (code_point <= 0x07ff) {
-    tmp = 0x0000c080 |
-        ((code_point & 0x07c0) << 2) |
-        (code_point & 0x003f);
-    len = 2;
-  } else if (code_point <= 0xffff) {
-    tmp = 0x00e08080 |
-        ((code_point & 0xf000) << 4) |
-        ((code_point & 0x0fc0) << 2) |
-        (code_point & 0x003f);
-    len = 3;
-  } else {
-    // UTF-16 is only defined for code points up to 0x10FFFF, and UTF-8 is
-    // normally only defined up to there as well.
-    tmp = 0xf0808080 |
-        ((code_point & 0x1c0000) << 6) |
-        ((code_point & 0x03f000) << 4) |
-        ((code_point & 0x000fc0) << 2) |
-        (code_point & 0x003f);
-    len = 4;
-  }
-  tmp = ghtonl(tmp);
-  memcpy(output, reinterpret_cast<const char*>(&tmp) + sizeof(tmp) - len, len);
-  return len;
-}
-
-// Table of UTF-8 character lengths, based on first byte
-static const unsigned char kUTF8LenTbl[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, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
-    1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 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, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
-
-// Return length of a single UTF-8 source character
-int UTF8FirstLetterNumBytes(const char* src, int len) {
-  if (len == 0) {
-    return 0;
-  }
-  return kUTF8LenTbl[*reinterpret_cast<const uint8_t*>(src)];
-}
-
-// ----------------------------------------------------------------------
-// CleanStringLineEndings()
-//   Clean up a multi-line string to conform to Unix line endings.
-//   Reads from src and appends to dst, so usually dst should be empty.
-//
-//   If there is no line ending at the end of a non-empty string, it can
-//   be added automatically.
-//
-//   Four different types of input are correctly handled:
-//
-//     - Unix/Linux files: line ending is LF: pass through unchanged
-//
-//     - DOS/Windows files: line ending is CRLF: convert to LF
-//
-//     - Legacy Mac files: line ending is CR: convert to LF
-//
-//     - Garbled files: random line endings: convert gracefully
-//                      lonely CR, lonely LF, CRLF: convert to LF
-//
-//   @param src The multi-line string to convert
-//   @param dst The converted string is appended to this string
-//   @param auto_end_last_line Automatically terminate the last line
-//
-//   Limitations:
-//
-//     This does not do the right thing for CRCRLF files created by
-//     broken programs that do another Unix->DOS conversion on files
-//     that are already in CRLF format.  For this, a two-pass approach
-//     brute-force would be needed that
-//
-//       (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 std::string &src, std::string *dst,
-                            bool auto_end_last_line) {
-  if (dst->empty()) {
-    dst->append(src);
-    CleanStringLineEndings(dst, auto_end_last_line);
-  } else {
-    std::string tmp = src;
-    CleanStringLineEndings(&tmp, auto_end_last_line);
-    dst->append(tmp);
-  }
-}
-
-void CleanStringLineEndings(std::string *str, bool auto_end_last_line) {
-  ptrdiff_t output_pos = 0;
-  bool r_seen = false;
-  ptrdiff_t len = str->size();
-
-  char *p = &(*str)[0];
-
-  for (ptrdiff_t input_pos = 0; input_pos < len;) {
-    if (!r_seen && input_pos + 8 < len) {
-      uint64_t v = GOOGLE_UNALIGNED_LOAD64(p + input_pos);
-      // Loop over groups of 8 bytes at a time until we come across
-      // a word that has a byte whose value is less than or equal to
-      // '\r' (i.e. could contain a \n (0x0a) or a \r (0x0d) ).
-      //
-      // We use a has_less macro that quickly tests a whole 64-bit
-      // word to see if any of the bytes has a value < N.
-      //
-      // For more details, see:
-      //   http://graphics.stanford.edu/~seander/bithacks.html#HasLessInWord
-#define has_less(x, n) (((x) - ~0ULL / 255 * (n)) & ~(x) & ~0ULL / 255 * 128)
-      if (!has_less(v, '\r' + 1)) {
-#undef has_less
-        // No byte in this word has a value that could be a \r or a \n
-        if (output_pos != input_pos) {
-          GOOGLE_UNALIGNED_STORE64(p + output_pos, v);
-        }
-        input_pos += 8;
-        output_pos += 8;
-        continue;
-      }
-    }
-    std::string::const_reference in = p[input_pos];
-    if (in == '\r') {
-      if (r_seen) p[output_pos++] = '\n';
-      r_seen = true;
-    } else if (in == '\n') {
-      if (input_pos != output_pos)
-        p[output_pos++] = '\n';
-      else
-        output_pos++;
-      r_seen = false;
-    } else {
-      if (r_seen) p[output_pos++] = '\n';
-      r_seen = false;
-      if (input_pos != output_pos)
-        p[output_pos++] = in;
-      else
-        output_pos++;
-    }
-    input_pos++;
-  }
-  if (r_seen ||
-      (auto_end_last_line && output_pos > 0 && p[output_pos - 1] != '\n')) {
-    str->resize(output_pos + 1);
-    str->operator[](output_pos) = '\n';
-  } else if (output_pos < len) {
-    str->resize(output_pos);
-  }
-}
-
-namespace internal {
-
-// ----------------------------------------------------------------------
-// NoLocaleStrtod()
-//   This code will make you cry.
-// ----------------------------------------------------------------------
-
-namespace {
-
-// Returns a string identical to *input except that the character pointed to
-// by radix_pos (which should be '.') is replaced with the locale-specific
-// radix character.
-std::string LocalizeRadix(const char *input, const char *radix_pos) {
-  // Determine the locale-specific radix character by calling sprintf() to
-  // print the number 1.5, then stripping off the digits.  As far as I can
-  // tell, this is the only portable, thread-safe way to get the C library
-  // to divuldge the locale's radix character.  No, localeconv() is NOT
-  // thread-safe.
-  char temp[16];
-  int size = snprintf(temp, sizeof(temp), "%.1f", 1.5);
-  GOOGLE_CHECK_EQ(temp[0], '1');
-  GOOGLE_CHECK_EQ(temp[size - 1], '5');
-  GOOGLE_CHECK_LE(size, 6);
-
-  // Now replace the '.' in the input with it.
-  std::string result;
-  result.reserve(strlen(input) + size - 3);
-  result.append(input, radix_pos);
-  result.append(temp + 1, size - 2);
-  result.append(radix_pos + 1);
-  return result;
-}
-
-}  // namespace
-
-double NoLocaleStrtod(const char *str, char **endptr) {
-  // We cannot simply set the locale to "C" temporarily with setlocale()
-  // as this is not thread-safe.  Instead, we try to parse in the current
-  // locale first.  If parsing stops at a '.' character, then this is a
-  // pretty good hint that we're actually in some other locale in which
-  // '.' is not the radix character.
-
-  char *temp_endptr;
-  double result = strtod(str, &temp_endptr);
-  if (endptr != NULL) *endptr = temp_endptr;
-  if (*temp_endptr != '.') return result;
-
-  // Parsing halted on a '.'.  Perhaps we're in a different locale?  Let's
-  // try to replace the '.' with a locale-specific radix character and
-  // try again.
-  std::string localized = LocalizeRadix(str, temp_endptr);
-  const char *localized_cstr = localized.c_str();
-  char *localized_endptr;
-  result = strtod(localized_cstr, &localized_endptr);
-  if ((localized_endptr - localized_cstr) > (temp_endptr - str)) {
-    // This attempt got further, so replacing the decimal must have helped.
-    // Update endptr to point at the right location.
-    if (endptr != NULL) {
-      // size_diff is non-zero if the localized radix has multiple bytes.
-      int size_diff = localized.size() - strlen(str);
-      // const_cast is necessary to match the strtod() interface.
-      *endptr = const_cast<char *>(
-          str + (localized_endptr - localized_cstr - size_diff));
-    }
-  }
-
-  return result;
-}
-
-}  // namespace internal
-
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/strutil.h b/src/google/protobuf/stubs/strutil.h
deleted file mode 100644
index 9658abf..0000000
--- a/src/google/protobuf/stubs/strutil.h
+++ /dev/null
@@ -1,950 +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.
-
-// from google3/strings/strutil.h
-
-#ifndef GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
-#define GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/stringpiece.h>
-#include <stdlib.h>
-
-#include <cstring>
-#include <google/protobuf/port_def.inc>
-#include <vector>
-
-namespace google {
-namespace protobuf {
-
-#if defined(_MSC_VER) && _MSC_VER < 1800
-#define strtoll  _strtoi64
-#define strtoull _strtoui64
-#elif defined(__DECCXX) && defined(__osf__)
-// HP C++ on Tru64 does not have strtoll, but strtol is already 64-bit.
-#define strtoll strtol
-#define strtoull strtoul
-#endif
-
-// ----------------------------------------------------------------------
-// ascii_isalnum()
-//    Check if an ASCII character is alphanumeric.  We can't use ctype's
-//    isalnum() because it is affected by locale.  This function is applied
-//    to identifiers in the protocol buffer language, not to natural-language
-//    strings, so locale should not be taken into account.
-// ascii_isdigit()
-//    Like above, but only accepts digits.
-// ascii_isspace()
-//    Check if the character is a space character.
-// ----------------------------------------------------------------------
-
-inline bool ascii_isalnum(char c) {
-  return ('a' <= c && c <= 'z') ||
-         ('A' <= c && c <= 'Z') ||
-         ('0' <= c && c <= '9');
-}
-
-inline bool ascii_isdigit(char c) {
-  return ('0' <= c && c <= '9');
-}
-
-inline bool ascii_isspace(char c) {
-  return c == ' ' || c == '\t' || c == '\n' || c == '\v' || c == '\f' ||
-      c == '\r';
-}
-
-inline bool ascii_isupper(char c) {
-  return c >= 'A' && c <= 'Z';
-}
-
-inline bool ascii_islower(char c) {
-  return c >= 'a' && c <= 'z';
-}
-
-inline char ascii_toupper(char c) {
-  return ascii_islower(c) ? c - ('a' - 'A') : c;
-}
-
-inline char ascii_tolower(char c) {
-  return ascii_isupper(c) ? c + ('a' - 'A') : c;
-}
-
-inline int hex_digit_to_int(char c) {
-  /* Assume ASCII. */
-  int x = static_cast<unsigned char>(c);
-  if (x > '9') {
-    x += 9;
-  }
-  return x & 0xf;
-}
-
-// ----------------------------------------------------------------------
-// HasPrefixString()
-//    Check if a string begins with a given prefix.
-// StripPrefixString()
-//    Given a string and a putative prefix, returns the string minus the
-//    prefix string if the prefix matches, otherwise the original
-//    string.
-// ----------------------------------------------------------------------
-inline bool HasPrefixString(StringPiece str, StringPiece prefix) {
-  return str.size() >= prefix.size() &&
-         memcmp(str.data(), prefix.data(), prefix.size()) == 0;
-}
-
-inline std::string StripPrefixString(const std::string& str,
-                                     const std::string& prefix) {
-  if (HasPrefixString(str, prefix)) {
-    return str.substr(prefix.size());
-  } else {
-    return str;
-  }
-}
-
-// ----------------------------------------------------------------------
-// HasSuffixString()
-//    Return true if str ends in suffix.
-// StripSuffixString()
-//    Given a string and a putative suffix, returns the string minus the
-//    suffix string if the suffix matches, otherwise the original
-//    string.
-// ----------------------------------------------------------------------
-inline bool HasSuffixString(StringPiece str, StringPiece suffix) {
-  return str.size() >= suffix.size() &&
-         memcmp(str.data() + str.size() - suffix.size(), suffix.data(),
-                suffix.size()) == 0;
-}
-
-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 {
-    return str;
-  }
-}
-
-// ----------------------------------------------------------------------
-// ReplaceCharacters
-//    Replaces any occurrence of the character 'remove' (or the characters
-//    in 'remove') with the character 'replacewith'.
-//    Good for keeping html characters or protocol characters (\t) out
-//    of places where they might cause a problem.
-// StripWhitespace
-//    Removes whitespaces from both ends of the given string.
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT void ReplaceCharacters(std::string* s, const char* remove,
-                                       char replacewith);
-
-PROTOBUF_EXPORT void StripWhitespace(std::string* s);
-
-// ----------------------------------------------------------------------
-// LowerString()
-// UpperString()
-// ToUpper()
-//    Convert the characters in "s" to lowercase or uppercase.  ASCII-only:
-//    these functions intentionally ignore locale because they are applied to
-//    identifiers used in the Protocol Buffer language, not to natural-language
-//    strings.
-// ----------------------------------------------------------------------
-
-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(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 void ToUpper(std::string* s) { UpperString(s); }
-
-inline std::string ToUpper(const std::string& s) {
-  std::string out = s;
-  UpperString(&out);
-  return out;
-}
-
-// ----------------------------------------------------------------------
-// StringReplace()
-//    Give me a string and two patterns "old" and "new", and I replace
-//    the first instance of "old" in the string with "new", if it
-//    exists.  RETURN a new string, regardless of whether the replacement
-//    happened or not.
-// ----------------------------------------------------------------------
-
-PROTOBUF_EXPORT std::string StringReplace(const std::string& s,
-                                          const std::string& oldsub,
-                                          const std::string& newsub,
-                                          bool replace_all);
-
-// ----------------------------------------------------------------------
-// SplitStringUsing()
-//    Split a string using a character delimiter. Append the components
-//    to 'result'.  If there are consecutive delimiters, this function skips
-//    over all of them.
-// ----------------------------------------------------------------------
-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'.
-// If there are consecutive delimiters, this function will return
-// corresponding empty strings.  If you want to drop the empty
-// strings, try SplitStringUsing().
-//
-// If "full" is the empty string, yields an empty string as the only value.
-// ----------------------------------------------------------------------
-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<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 {
-    SplitStringAllowEmpty(full, delim, &result);
-  }
-  return result;
-}
-
-// ----------------------------------------------------------------------
-// JoinStrings()
-//    These methods concatenate a vector of strings into a C++ string, using
-//    the C-string "delim" as a separator between components. There are two
-//    flavors of the function, one flavor returns the concatenated string,
-//    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<std::string>& components,
-                                 const char* delim, std::string* result);
-
-inline std::string JoinStrings(const std::vector<std::string>& components,
-                               const char* delim) {
-  std::string result;
-  JoinStrings(components, delim, &result);
-  return result;
-}
-
-// ----------------------------------------------------------------------
-// UnescapeCEscapeSequences()
-//    Copies "source" to "dest", rewriting C-style escape sequences
-//    -- '\n', '\r', '\\', '\ooo', etc -- to their ASCII
-//    equivalents.  "dest" must be sufficiently large to hold all
-//    the characters in the rewritten string (i.e. at least as large
-//    as strlen(source) + 1 should be safe, since the replacements
-//    are always shorter than the original escaped sequences).  It's
-//    safe for source and dest to be the same.  RETURNS the length
-//    of dest.
-//
-//    It allows hex sequences \xhh, or generally \xhhhhh with an
-//    arbitrary number of hex digits, but all of them together must
-//    specify a value of a single byte (e.g. \x0045 is equivalent
-//    to \x45, and \x1234 is erroneous).
-//
-//    It also allows escape sequences of the form \uhhhh (exactly four
-//    hex digits, upper or lower case) or \Uhhhhhhhh (exactly eight
-//    hex digits, upper or lower case) to specify a Unicode code
-//    point. The dest array will contain the UTF8-encoded version of
-//    that code-point (e.g., if source contains \u2019, then dest will
-//    contain the three bytes 0xE2, 0x80, and 0x99).
-//
-//    Errors: In the first form of the call, errors are reported with
-//    LOG(ERROR). The same is true for the second form of the call if
-//    the pointer to the string std::vector is nullptr; otherwise, error
-//    messages are stored in the std::vector. In either case, the effect on
-//    the dest array is not defined, but rest of the source will be
-//    processed.
-//    ----------------------------------------------------------------------
-
-PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest);
-PROTOBUF_EXPORT int UnescapeCEscapeSequences(const char* source, char* dest,
-                                             std::vector<std::string>* errors);
-
-// ----------------------------------------------------------------------
-// UnescapeCEscapeString()
-//    This does the same thing as UnescapeCEscapeSequences, but creates
-//    a new string. The caller does not need to worry about allocating
-//    a dest buffer. This should be used for non performance critical
-//    tasks such as printing debug messages. It is safe for src and dest
-//    to be the same.
-//
-//    The second call stores its errors in a supplied string vector.
-//    If the string vector pointer is nullptr, it reports the errors with LOG().
-//
-//    In the first and second calls, the length of dest is returned. In the
-//    the third call, the new string is returned.
-// ----------------------------------------------------------------------
-
-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()
-//    Escapes 'src' using C-style escape sequences and returns the resulting
-//    string.
-//
-//    Escaped chars: \n, \r, \t, ", ', \, and !isprint().
-// ----------------------------------------------------------------------
-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, std::string* dest);
-
-namespace strings {
-// Like CEscape() but does not escape bytes with the upper bit set.
-PROTOBUF_EXPORT std::string Utf8SafeCEscape(const std::string& src);
-
-// Like CEscape() but uses hex (\x) escapes instead of octals.
-PROTOBUF_EXPORT std::string CHexEscape(const std::string& src);
-}  // namespace strings
-
-// ----------------------------------------------------------------------
-// strto32()
-// strtou32()
-// strto64()
-// strtou64()
-//    Architecture-neutral plug compatible replacements for strtol() and
-//    strtoul().  Long's have different lengths on ILP-32 and LP-64
-//    platforms, so using these is safer, from the point of view of
-//    overflow behavior, than using the standard libc functions.
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT int32_t strto32_adaptor(const char* nptr, char** endptr,
-                                        int base);
-PROTOBUF_EXPORT uint32_t strtou32_adaptor(const char* nptr, char** endptr,
-                                          int base);
-
-inline int32_t strto32(const char *nptr, char **endptr, int base) {
-  if (sizeof(int32_t) == sizeof(long))
-    return strtol(nptr, endptr, base);
-  else
-    return strto32_adaptor(nptr, endptr, base);
-}
-
-inline uint32_t strtou32(const char *nptr, char **endptr, int base) {
-  if (sizeof(uint32_t) == sizeof(unsigned long))
-    return strtoul(nptr, endptr, base);
-  else
-    return strtou32_adaptor(nptr, endptr, base);
-}
-
-// 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_t strto64(const char *nptr, char **endptr, int base) {
-  static_assert(sizeof(int64_t) == sizeof(long long),
-                "sizeof int64_t is not sizeof long long");
-  return strtoll(nptr, endptr, base);
-}
-
-inline uint64_t strtou64(const char *nptr, char **endptr, int base) {
-  static_assert(sizeof(uint64_t) == sizeof(unsigned long long),
-                "sizeof uint64_t is not sizeof unsigned long long");
-  return strtoull(nptr, endptr, base);
-}
-
-// ----------------------------------------------------------------------
-// safe_strtob()
-// safe_strto32()
-// safe_strtou32()
-// safe_strto64()
-// safe_strtou64()
-// safe_strtof()
-// safe_strtod()
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT bool safe_strtob(StringPiece str, bool* value);
-
-PROTOBUF_EXPORT bool safe_strto32(const std::string& str, int32_t* value);
-PROTOBUF_EXPORT bool safe_strtou32(const std::string& str, uint32_t* value);
-inline bool safe_strto32(const char* str, int32_t* value) {
-  return safe_strto32(std::string(str), value);
-}
-inline bool safe_strto32(StringPiece str, int32_t* value) {
-  return safe_strto32(str.ToString(), value);
-}
-inline bool safe_strtou32(const char* str, uint32_t* value) {
-  return safe_strtou32(std::string(str), value);
-}
-inline bool safe_strtou32(StringPiece str, uint32_t* value) {
-  return safe_strtou32(str.ToString(), value);
-}
-
-PROTOBUF_EXPORT bool safe_strto64(const std::string& str, int64_t* value);
-PROTOBUF_EXPORT bool safe_strtou64(const std::string& str, uint64_t* value);
-inline bool safe_strto64(const char* str, int64_t* value) {
-  return safe_strto64(std::string(str), value);
-}
-inline bool safe_strto64(StringPiece str, int64_t* value) {
-  return safe_strto64(str.ToString(), value);
-}
-inline bool safe_strtou64(const char* str, uint64_t* value) {
-  return safe_strtou64(std::string(str), value);
-}
-inline bool safe_strtou64(StringPiece str, uint64_t* value) {
-  return safe_strtou64(str.ToString(), value);
-}
-
-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 std::string& str, float* value) {
-  return safe_strtof(str.c_str(), 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) {
-  return safe_strtof(str.ToString(), value);
-}
-inline bool safe_strtod(StringPiece str, double* value) {
-  return safe_strtod(str.ToString(), value);
-}
-
-// ----------------------------------------------------------------------
-// FastIntToBuffer()
-// FastHexToBuffer()
-// FastHex64ToBuffer()
-// FastHex32ToBuffer()
-// FastTimeToBuffer()
-//    These are intended for speed.  FastIntToBuffer() assumes the
-//    integer is non-negative.  FastHexToBuffer() puts output in
-//    hex rather than decimal.  FastTimeToBuffer() puts the output
-//    into RFC822 format.
-//
-//    FastHex64ToBuffer() puts a 64-bit unsigned value in hex-format,
-//    padded to exactly 16 bytes (plus one byte for '\0')
-//
-//    FastHex32ToBuffer() puts a 32-bit unsigned value in hex-format,
-//    padded to exactly 8 bytes (plus one byte for '\0')
-//
-//       All functions take the output buffer as an arg.
-//    They all return a pointer to the beginning of the output,
-//    which may not be the beginning of the input buffer.
-// ----------------------------------------------------------------------
-
-// Suggested buffer size for FastToBuffer functions.  Also works with
-// DoubleToBuffer() and FloatToBuffer().
-static const int kFastToBufferSize = 32;
-
-PROTOBUF_EXPORT char* FastInt32ToBuffer(int32_t i, char* buffer);
-PROTOBUF_EXPORT char* FastInt64ToBuffer(int64_t i, char* buffer);
-char* FastUInt32ToBuffer(uint32_t i, char* buffer);  // inline below
-char* FastUInt64ToBuffer(uint64_t i, char* buffer);  // inline below
-PROTOBUF_EXPORT char* FastHexToBuffer(int i, char* buffer);
-PROTOBUF_EXPORT char* FastHex64ToBuffer(uint64_t i, char* buffer);
-PROTOBUF_EXPORT char* FastHex32ToBuffer(uint32_t i, char* buffer);
-
-// at least 22 bytes long
-inline char* FastIntToBuffer(int i, char* buffer) {
-  return (sizeof(i) == 4 ?
-          FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
-}
-inline char* FastUIntToBuffer(unsigned int i, char* buffer) {
-  return (sizeof(i) == 4 ?
-          FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
-}
-inline char* FastLongToBuffer(long i, char* buffer) {
-  return (sizeof(i) == 4 ?
-          FastInt32ToBuffer(i, buffer) : FastInt64ToBuffer(i, buffer));
-}
-inline char* FastULongToBuffer(unsigned long i, char* buffer) {
-  return (sizeof(i) == 4 ?
-          FastUInt32ToBuffer(i, buffer) : FastUInt64ToBuffer(i, buffer));
-}
-
-// ----------------------------------------------------------------------
-// FastInt32ToBufferLeft()
-// FastUInt32ToBufferLeft()
-// FastInt64ToBufferLeft()
-// FastUInt64ToBufferLeft()
-//
-// Like the Fast*ToBuffer() functions above, these are intended for speed.
-// Unlike the Fast*ToBuffer() functions, however, these functions write
-// their output to the beginning of the buffer (hence the name, as the
-// output is left-aligned).  The caller is responsible for ensuring that
-// the buffer has enough space to hold the output.
-//
-// Returns a pointer to the end of the string (i.e. the null character
-// terminating the string).
-// ----------------------------------------------------------------------
-
-PROTOBUF_EXPORT char* FastInt32ToBufferLeft(int32_t i, char* buffer);
-PROTOBUF_EXPORT char* FastUInt32ToBufferLeft(uint32_t i, char* buffer);
-PROTOBUF_EXPORT char* FastInt64ToBufferLeft(int64_t i, char* buffer);
-PROTOBUF_EXPORT char* FastUInt64ToBufferLeft(uint64_t i, char* buffer);
-
-// Just define these in terms of the above.
-inline char* FastUInt32ToBuffer(uint32_t i, char* buffer) {
-  FastUInt32ToBufferLeft(i, buffer);
-  return buffer;
-}
-inline char* FastUInt64ToBuffer(uint64_t i, char* buffer) {
-  FastUInt64ToBufferLeft(i, buffer);
-  return buffer;
-}
-
-inline std::string SimpleBtoa(bool value) { return value ? "true" : "false"; }
-
-// ----------------------------------------------------------------------
-// SimpleItoa()
-//    Description: converts an integer to a string.
-//
-//    Return value: string
-// ----------------------------------------------------------------------
-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()
-// SimpleFtoa()
-// DoubleToBuffer()
-// FloatToBuffer()
-//    Description: converts a double or float to a string which, if
-//    passed to NoLocaleStrtod(), will produce the exact same original double
-//    (except in case of NaN; all NaNs are considered the same value).
-//    We try to keep the string short but it's not guaranteed to be as
-//    short as possible.
-//
-//    DoubleToBuffer() and FloatToBuffer() write the text to the given
-//    buffer and return it.  The buffer must be at least
-//    kDoubleToBufferSize bytes for doubles and kFloatToBufferSize
-//    bytes for floats.  kFastToBufferSize is also guaranteed to be large
-//    enough to hold either.
-//
-//    Return value: string
-// ----------------------------------------------------------------------
-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);
-
-// In practice, doubles should never need more than 24 bytes and floats
-// should never need more than 14 (including null terminators), but we
-// overestimate to be safe.
-static const int kDoubleToBufferSize = 32;
-static const int kFloatToBufferSize = 24;
-
-namespace strings {
-
-enum PadSpec {
-  NO_PAD = 1,
-  ZERO_PAD_2,
-  ZERO_PAD_3,
-  ZERO_PAD_4,
-  ZERO_PAD_5,
-  ZERO_PAD_6,
-  ZERO_PAD_7,
-  ZERO_PAD_8,
-  ZERO_PAD_9,
-  ZERO_PAD_10,
-  ZERO_PAD_11,
-  ZERO_PAD_12,
-  ZERO_PAD_13,
-  ZERO_PAD_14,
-  ZERO_PAD_15,
-  ZERO_PAD_16,
-};
-
-struct Hex {
-  uint64_t value;
-  enum PadSpec spec;
-  template <class Int>
-  explicit Hex(Int v, PadSpec s = NO_PAD)
-      : spec(s) {
-    // Prevent sign-extension by casting integers to
-    // their unsigned counterparts.
-#ifdef LANG_CXX11
-    static_assert(
-        sizeof(v) == 1 || sizeof(v) == 2 || sizeof(v) == 4 || sizeof(v) == 8,
-        "Unknown integer type");
-#endif
-    value = sizeof(v) == 1 ? static_cast<uint8_t>(v)
-          : sizeof(v) == 2 ? static_cast<uint16_t>(v)
-          : sizeof(v) == 4 ? static_cast<uint32_t>(v)
-          : static_cast<uint64_t>(v);
-  }
-};
-
-struct PROTOBUF_EXPORT AlphaNum {
-  const char *piece_data_;  // move these to string_ref eventually
-  size_t piece_size_;       // move these to string_ref eventually
-
-  char digits[kFastToBufferSize];
-
-  // No bool ctor -- bools convert to an integral type.
-  // A bool ctor would also convert incoming pointers (bletch).
-
-  AlphaNum(int i32)
-      : piece_data_(digits),
-        piece_size_(FastInt32ToBufferLeft(i32, digits) - &digits[0]) {}
-  AlphaNum(unsigned int u32)
-      : piece_data_(digits),
-        piece_size_(FastUInt32ToBufferLeft(u32, digits) - &digits[0]) {}
-  AlphaNum(long long i64)
-      : piece_data_(digits),
-        piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
-  AlphaNum(unsigned long long u64)
-      : piece_data_(digits),
-        piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
-
-  // Note: on some architectures, "long" is only 32 bits, not 64, but the
-  // performance hit of using FastInt64ToBufferLeft to handle 32-bit values
-  // is quite minor.
-  AlphaNum(long i64)
-      : piece_data_(digits),
-        piece_size_(FastInt64ToBufferLeft(i64, digits) - &digits[0]) {}
-  AlphaNum(unsigned long u64)
-      : piece_data_(digits),
-        piece_size_(FastUInt64ToBufferLeft(u64, digits) - &digits[0]) {}
-
-  AlphaNum(float f)
-    : piece_data_(digits), piece_size_(strlen(FloatToBuffer(f, digits))) {}
-  AlphaNum(double f)
-    : piece_data_(digits), piece_size_(strlen(DoubleToBuffer(f, digits))) {}
-
-  AlphaNum(Hex hex);
-
-  AlphaNum(const char* c_str)
-      : piece_data_(c_str), piece_size_(strlen(c_str)) {}
-  // TODO: Add a string_ref constructor, eventually
-  // AlphaNum(const StringPiece &pc) : piece(pc) {}
-
-  AlphaNum(const std::string& str)
-      : piece_data_(str.data()), piece_size_(str.size()) {}
-
-  AlphaNum(StringPiece str)
-      : piece_data_(str.data()), piece_size_(str.size()) {}
-
-  size_t size() const { return piece_size_; }
-  const char *data() const { return piece_data_; }
-
- private:
-  // Use ":" not ':'
-  AlphaNum(char c);  // NOLINT(runtime/explicit)
-
-  // Disallow copy and assign.
-  AlphaNum(const AlphaNum&);
-  void operator=(const AlphaNum&);
-};
-
-}  // namespace strings
-
-using strings::AlphaNum;
-
-// ----------------------------------------------------------------------
-// StrCat()
-//    This merges the given strings or numbers, with no delimiter.  This
-//    is designed to be the fastest possible way to construct a string out
-//    of a mix of raw C strings, strings, bool values,
-//    and numeric values.
-//
-//    Don't use this for user-visible strings.  The localization process
-//    works poorly on strings built up out of fragments.
-//
-//    For clarity and performance, don't use StrCat when appending to a
-//    string.  In particular, avoid using any of these (anti-)patterns:
-//      str.append(StrCat(...)
-//      str += StrCat(...)
-//      str = StrCat(str, ...)
-//    where the last is the worse, with the potential to change a loop
-//    from a linear time operation with O(1) dynamic allocations into a
-//    quadratic time operation with O(n) dynamic allocations.  StrAppend
-//    is a better choice than any of the above, subject to the restriction
-//    of StrAppend(&str, a, b, c, ...) that none of the a, b, c, ... may
-//    be a reference into str.
-// ----------------------------------------------------------------------
-
-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 std::string StrCat(const AlphaNum& a) {
-  return std::string(a.data(), a.size());
-}
-
-// ----------------------------------------------------------------------
-// StrAppend()
-//    Same as above, but adds the output to the given string.
-//    WARNING: For speed, StrAppend does not try to check each of its input
-//    arguments to be sure that they are not a subset of the string being
-//    appended to.  That is, while this will work:
-//
-//    string s = "foo";
-//    s += s;
-//
-//    This will not (necessarily) work:
-//
-//    string s = "foo";
-//    StrAppend(&s, s);
-//
-//    Note: while StrCat supports appending up to 9 arguments, StrAppend
-//    is currently limited to 4.  That's rarely an issue except when
-//    automatically transforming StrCat to StrAppend, and can easily be
-//    worked around as consecutive calls to StrAppend are quite efficient.
-// ----------------------------------------------------------------------
-
-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(std::string* dest, const AlphaNum& a,
-                               const AlphaNum& b, const AlphaNum& c);
-PROTOBUF_EXPORT void StrAppend(std::string* dest, const AlphaNum& a,
-                               const AlphaNum& b, const AlphaNum& c,
-                               const AlphaNum& d);
-
-// ----------------------------------------------------------------------
-// Join()
-//    These methods concatenate a range of components into a C++ string, using
-//    the C-string "delim" as a separator between components.
-// ----------------------------------------------------------------------
-template <typename Iterator>
-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);
-    }
-    StrAppend(result, *it);
-  }
-}
-
-template <typename Range>
-std::string Join(const Range& components, const char* delim) {
-  std::string result;
-  Join(components.begin(), components.end(), delim, &result);
-  return result;
-}
-
-// ----------------------------------------------------------------------
-// ToHex()
-//    Return a lower-case hex string representation of the given integer.
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT std::string ToHex(uint64_t num);
-
-// ----------------------------------------------------------------------
-// GlobalReplaceSubstring()
-//    Replaces all instances of a substring in a string.  Does nothing
-//    if 'substring' is empty.  Returns the number of replacements.
-//
-//    NOTE: The string pieces must not overlap s.
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT int GlobalReplaceSubstring(const std::string& substring,
-                                           const std::string& replacement,
-                                           std::string* s);
-
-// ----------------------------------------------------------------------
-// Base64Unescape()
-//    Converts "src" which is encoded in Base64 to its binary equivalent and
-//    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, std::string* dest);
-
-// ----------------------------------------------------------------------
-// WebSafeBase64Unescape()
-//    This is a variation of Base64Unescape which uses '-' instead of '+', and
-//    '_' instead of '/'. src is not null terminated, instead specify len. I
-//    recommend that slen<szdest, but we honor szdest anyway.
-//    RETURNS the length of dest, or -1 if src contains invalid chars.
-
-//    The variation that stores into a string clears the string first, and
-//    returns false (with dest empty) if src contains invalid chars; for
-//    this version src and dest must be different strings.
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT int WebSafeBase64Unescape(const char* src, int slen, char* dest,
-                                          int szdest);
-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.
-// This function may return incorrect results if given input_len values that
-// are extremely high, which should happen rarely.
-PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len, bool do_padding);
-// Use this version when calling Base64Escape without a do_padding arg.
-PROTOBUF_EXPORT int CalculateBase64EscapedLen(int input_len);
-
-// ----------------------------------------------------------------------
-// Base64Escape()
-// WebSafeBase64Escape()
-//    Encode "src" to "dest" using base64 encoding.
-//    src is not null terminated, instead specify len.
-//    'dest' should have at least CalculateBase64EscapedLen() length.
-//    RETURNS the length of dest.
-//    The WebSafe variation use '-' instead of '+' and '_' instead of '/'
-//    so that we can place the out in the URL or cookies without having
-//    to escape them.  It also has an extra parameter "do_padding",
-//    which when set to false will prevent padding with "=".
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT int Base64Escape(const unsigned char* src, int slen, char* dest,
-                                 int szdest);
-PROTOBUF_EXPORT int WebSafeBase64Escape(const unsigned char* src, int slen,
-                                        char* dest, int szdest,
-                                        bool do_padding);
-// Encode src into dest with padding.
-PROTOBUF_EXPORT void Base64Escape(StringPiece src, std::string* dest);
-// Encode src into dest web-safely without padding.
-PROTOBUF_EXPORT void WebSafeBase64Escape(StringPiece src, std::string* dest);
-// Encode src into dest web-safely with padding.
-PROTOBUF_EXPORT void WebSafeBase64EscapeWithPadding(StringPiece src,
-                                                    std::string* dest);
-
-PROTOBUF_EXPORT void Base64Escape(const unsigned char* src, int szsrc,
-                                  std::string* dest, bool do_padding);
-PROTOBUF_EXPORT void WebSafeBase64Escape(const unsigned char* src, int szsrc,
-                                         std::string* dest, bool do_padding);
-
-inline bool IsValidCodePoint(uint32_t code_point) {
-  return code_point < 0xD800 ||
-         (code_point >= 0xE000 && code_point <= 0x10FFFF);
-}
-
-static const int UTFmax = 4;
-// ----------------------------------------------------------------------
-// EncodeAsUTF8Char()
-//  Helper to append a Unicode code point to a string as UTF8, without bringing
-//  in any external dependencies. The output buffer must be as least 4 bytes
-//  large.
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT int EncodeAsUTF8Char(uint32_t code_point, char* output);
-
-// ----------------------------------------------------------------------
-// UTF8FirstLetterNumBytes()
-//   Length of the first UTF-8 character.
-// ----------------------------------------------------------------------
-PROTOBUF_EXPORT int UTF8FirstLetterNumBytes(const char* src, int len);
-
-// From google3/third_party/absl/strings/escaping.h
-
-// ----------------------------------------------------------------------
-// CleanStringLineEndings()
-//   Clean up a multi-line string to conform to Unix line endings.
-//   Reads from src and appends to dst, so usually dst should be empty.
-//
-//   If there is no line ending at the end of a non-empty string, it can
-//   be added automatically.
-//
-//   Four different types of input are correctly handled:
-//
-//     - Unix/Linux files: line ending is LF: pass through unchanged
-//
-//     - DOS/Windows files: line ending is CRLF: convert to LF
-//
-//     - Legacy Mac files: line ending is CR: convert to LF
-//
-//     - Garbled files: random line endings: convert gracefully
-//                      lonely CR, lonely LF, CRLF: convert to LF
-//
-//   @param src The multi-line string to convert
-//   @param dst The converted string is appended to this string
-//   @param auto_end_last_line Automatically terminate the last line
-//
-//   Limitations:
-//
-//     This does not do the right thing for CRCRLF files created by
-//     broken programs that do another Unix->DOS conversion on files
-//     that are already in CRLF format.  For this, a two-pass approach
-//     brute-force would be needed that
-//
-//       (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 std::string& src,
-                                            std::string* dst,
-                                            bool auto_end_last_line);
-
-// Same as above, but transforms the argument in place.
-PROTOBUF_EXPORT void CleanStringLineEndings(std::string* str,
-                                            bool auto_end_last_line);
-
-namespace strings {
-inline bool EndsWith(StringPiece text, StringPiece suffix) {
-  return suffix.empty() ||
-      (text.size() >= suffix.size() &&
-       memcmp(text.data() + (text.size() - suffix.size()), suffix.data(),
-              suffix.size()) == 0);
-}
-}  // namespace strings
-
-namespace internal {
-
-// A locale-independent version of the standard strtod(), which always
-// uses a dot as the decimal separator.
-double NoLocaleStrtod(const char* str, char** endptr);
-
-}  // namespace internal
-
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_STRUTIL_H__
diff --git a/src/google/protobuf/stubs/strutil_unittest.cc b/src/google/protobuf/stubs/strutil_unittest.cc
deleted file mode 100644
index 0bb9558..0000000
--- a/src/google/protobuf/stubs/strutil_unittest.cc
+++ /dev/null
@@ -1,884 +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)
-
-#include <google/protobuf/stubs/strutil.h>
-
-#include <locale.h>
-
-#include <google/protobuf/stubs/stl_util.h>
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-#ifdef _WIN32
-#define snprintf _snprintf
-#endif
-
-namespace google {
-namespace protobuf {
-namespace {
-
-// TODO(kenton):  Copy strutil tests from google3?
-
-TEST(StringUtilityTest, ImmuneToLocales) {
-  // Remember the old locale.
-  char* old_locale_cstr = setlocale(LC_NUMERIC, nullptr);
-  ASSERT_TRUE(old_locale_cstr != nullptr);
-  std::string old_locale = old_locale_cstr;
-
-  // Set the locale to "C".
-  ASSERT_TRUE(setlocale(LC_NUMERIC, "C") != nullptr);
-
-  EXPECT_EQ("1.5", SimpleDtoa(1.5));
-  EXPECT_EQ("1.5", SimpleFtoa(1.5));
-
-  if (setlocale(LC_NUMERIC, "es_ES") == nullptr &&
-      setlocale(LC_NUMERIC, "es_ES.utf8") == nullptr) {
-    // Some systems may not have the desired locale available.
-    GOOGLE_LOG(WARNING)
-      << "Couldn't set locale to es_ES.  Skipping this test.";
-  } else {
-    EXPECT_EQ("1.5", SimpleDtoa(1.5));
-    EXPECT_EQ("1.5", SimpleFtoa(1.5));
-  }
-
-  // Return to original locale.
-  setlocale(LC_NUMERIC, old_locale.c_str());
-}
-
-#define EXPECT_EQ_ARRAY(len, x, y, msg)                     \
-  for (int j = 0; j < len; ++j) {                           \
-    EXPECT_EQ(x[j], y[j]) << "" # x << " != " # y           \
-                          << " byte " << j << ": " << msg;  \
-  }
-
-static struct {
-  int plain_length;
-  const char* plaintext;
-  const char* ciphertext;
-} base64_tests[] = {
-  // Empty string.
-  { 0, "", ""},
-
-  // Basic bit patterns;
-  // values obtained with "echo -n '...' | uuencode -m test"
-
-  { 1, "\000", "AA==" },
-  { 1, "\001", "AQ==" },
-  { 1, "\002", "Ag==" },
-  { 1, "\004", "BA==" },
-  { 1, "\010", "CA==" },
-  { 1, "\020", "EA==" },
-  { 1, "\040", "IA==" },
-  { 1, "\100", "QA==" },
-  { 1, "\200", "gA==" },
-
-  { 1, "\377", "/w==" },
-  { 1, "\376", "/g==" },
-  { 1, "\375", "/Q==" },
-  { 1, "\373", "+w==" },
-  { 1, "\367", "9w==" },
-  { 1, "\357", "7w==" },
-  { 1, "\337", "3w==" },
-  { 1, "\277", "vw==" },
-  { 1, "\177", "fw==" },
-  { 2, "\000\000", "AAA=" },
-  { 2, "\000\001", "AAE=" },
-  { 2, "\000\002", "AAI=" },
-  { 2, "\000\004", "AAQ=" },
-  { 2, "\000\010", "AAg=" },
-  { 2, "\000\020", "ABA=" },
-  { 2, "\000\040", "ACA=" },
-  { 2, "\000\100", "AEA=" },
-  { 2, "\000\200", "AIA=" },
-  { 2, "\001\000", "AQA=" },
-  { 2, "\002\000", "AgA=" },
-  { 2, "\004\000", "BAA=" },
-  { 2, "\010\000", "CAA=" },
-  { 2, "\020\000", "EAA=" },
-  { 2, "\040\000", "IAA=" },
-  { 2, "\100\000", "QAA=" },
-  { 2, "\200\000", "gAA=" },
-
-  { 2, "\377\377", "//8=" },
-  { 2, "\377\376", "//4=" },
-  { 2, "\377\375", "//0=" },
-  { 2, "\377\373", "//s=" },
-  { 2, "\377\367", "//c=" },
-  { 2, "\377\357", "/+8=" },
-  { 2, "\377\337", "/98=" },
-  { 2, "\377\277", "/78=" },
-  { 2, "\377\177", "/38=" },
-  { 2, "\376\377", "/v8=" },
-  { 2, "\375\377", "/f8=" },
-  { 2, "\373\377", "+/8=" },
-  { 2, "\367\377", "9/8=" },
-  { 2, "\357\377", "7/8=" },
-  { 2, "\337\377", "3/8=" },
-  { 2, "\277\377", "v/8=" },
-  { 2, "\177\377", "f/8=" },
-
-  { 3, "\000\000\000", "AAAA" },
-  { 3, "\000\000\001", "AAAB" },
-  { 3, "\000\000\002", "AAAC" },
-  { 3, "\000\000\004", "AAAE" },
-  { 3, "\000\000\010", "AAAI" },
-  { 3, "\000\000\020", "AAAQ" },
-  { 3, "\000\000\040", "AAAg" },
-  { 3, "\000\000\100", "AABA" },
-  { 3, "\000\000\200", "AACA" },
-  { 3, "\000\001\000", "AAEA" },
-  { 3, "\000\002\000", "AAIA" },
-  { 3, "\000\004\000", "AAQA" },
-  { 3, "\000\010\000", "AAgA" },
-  { 3, "\000\020\000", "ABAA" },
-  { 3, "\000\040\000", "ACAA" },
-  { 3, "\000\100\000", "AEAA" },
-  { 3, "\000\200\000", "AIAA" },
-  { 3, "\001\000\000", "AQAA" },
-  { 3, "\002\000\000", "AgAA" },
-  { 3, "\004\000\000", "BAAA" },
-  { 3, "\010\000\000", "CAAA" },
-  { 3, "\020\000\000", "EAAA" },
-  { 3, "\040\000\000", "IAAA" },
-  { 3, "\100\000\000", "QAAA" },
-  { 3, "\200\000\000", "gAAA" },
-
-  { 3, "\377\377\377", "////" },
-  { 3, "\377\377\376", "///+" },
-  { 3, "\377\377\375", "///9" },
-  { 3, "\377\377\373", "///7" },
-  { 3, "\377\377\367", "///3" },
-  { 3, "\377\377\357", "///v" },
-  { 3, "\377\377\337", "///f" },
-  { 3, "\377\377\277", "//+/" },
-  { 3, "\377\377\177", "//9/" },
-  { 3, "\377\376\377", "//7/" },
-  { 3, "\377\375\377", "//3/" },
-  { 3, "\377\373\377", "//v/" },
-  { 3, "\377\367\377", "//f/" },
-  { 3, "\377\357\377", "/+//" },
-  { 3, "\377\337\377", "/9//" },
-  { 3, "\377\277\377", "/7//" },
-  { 3, "\377\177\377", "/3//" },
-  { 3, "\376\377\377", "/v//" },
-  { 3, "\375\377\377", "/f//" },
-  { 3, "\373\377\377", "+///" },
-  { 3, "\367\377\377", "9///" },
-  { 3, "\357\377\377", "7///" },
-  { 3, "\337\377\377", "3///" },
-  { 3, "\277\377\377", "v///" },
-  { 3, "\177\377\377", "f///" },
-
-  // Random numbers: values obtained with
-  //
-  //  #! /bin/bash
-  //  dd bs=$1 count=1 if=/dev/random of=/tmp/bar.random
-  //  od -N $1 -t o1 /tmp/bar.random
-  //  uuencode -m test < /tmp/bar.random
-  //
-  // where $1 is the number of bytes (2, 3)
-
-  { 2, "\243\361", "o/E=" },
-  { 2, "\024\167", "FHc=" },
-  { 2, "\313\252", "y6o=" },
-  { 2, "\046\041", "JiE=" },
-  { 2, "\145\236", "ZZ4=" },
-  { 2, "\254\325", "rNU=" },
-  { 2, "\061\330", "Mdg=" },
-  { 2, "\245\032", "pRo=" },
-  { 2, "\006\000", "BgA=" },
-  { 2, "\375\131", "/Vk=" },
-  { 2, "\303\210", "w4g=" },
-  { 2, "\040\037", "IB8=" },
-  { 2, "\261\372", "sfo=" },
-  { 2, "\335\014", "3Qw=" },
-  { 2, "\233\217", "m48=" },
-  { 2, "\373\056", "+y4=" },
-  { 2, "\247\232", "p5o=" },
-  { 2, "\107\053", "Rys=" },
-  { 2, "\204\077", "hD8=" },
-  { 2, "\276\211", "vok=" },
-  { 2, "\313\110", "y0g=" },
-  { 2, "\363\376", "8/4=" },
-  { 2, "\251\234", "qZw=" },
-  { 2, "\103\262", "Q7I=" },
-  { 2, "\142\312", "Yso=" },
-  { 2, "\067\211", "N4k=" },
-  { 2, "\220\001", "kAE=" },
-  { 2, "\152\240", "aqA=" },
-  { 2, "\367\061", "9zE=" },
-  { 2, "\133\255", "W60=" },
-  { 2, "\176\035", "fh0=" },
-  { 2, "\032\231", "Gpk=" },
-
-  { 3, "\013\007\144", "Cwdk" },
-  { 3, "\030\112\106", "GEpG" },
-  { 3, "\047\325\046", "J9Um" },
-  { 3, "\310\160\022", "yHAS" },
-  { 3, "\131\100\237", "WUCf" },
-  { 3, "\064\342\134", "NOJc" },
-  { 3, "\010\177\004", "CH8E" },
-  { 3, "\345\147\205", "5WeF" },
-  { 3, "\300\343\360", "wOPw" },
-  { 3, "\061\240\201", "MaCB" },
-  { 3, "\225\333\044", "ldsk" },
-  { 3, "\215\137\352", "jV/q" },
-  { 3, "\371\147\160", "+Wdw" },
-  { 3, "\030\320\051", "GNAp" },
-  { 3, "\044\174\241", "JHyh" },
-  { 3, "\260\127\037", "sFcf" },
-  { 3, "\111\045\033", "SSUb" },
-  { 3, "\202\114\107", "gkxH" },
-  { 3, "\057\371\042", "L/ki" },
-  { 3, "\223\247\244", "k6ek" },
-  { 3, "\047\216\144", "J45k" },
-  { 3, "\203\070\327", "gzjX" },
-  { 3, "\247\140\072", "p2A6" },
-  { 3, "\124\115\116", "VE1O" },
-  { 3, "\157\162\050", "b3Io" },
-  { 3, "\357\223\004", "75ME" },
-  { 3, "\052\117\156", "Kk9u" },
-  { 3, "\347\154\000", "52wA" },
-  { 3, "\303\012\142", "wwpi" },
-  { 3, "\060\035\362", "MB3y" },
-  { 3, "\130\226\361", "WJbx" },
-  { 3, "\173\013\071", "ews5" },
-  { 3, "\336\004\027", "3gQX" },
-  { 3, "\357\366\234", "7/ac" },
-  { 3, "\353\304\111", "68RJ" },
-  { 3, "\024\264\131", "FLRZ" },
-  { 3, "\075\114\251", "PUyp" },
-  { 3, "\315\031\225", "zRmV" },
-  { 3, "\154\201\276", "bIG+" },
-  { 3, "\200\066\072", "gDY6" },
-  { 3, "\142\350\267", "Yui3" },
-  { 3, "\033\000\166", "GwB2" },
-  { 3, "\210\055\077", "iC0/" },
-  { 3, "\341\037\124", "4R9U" },
-  { 3, "\161\103\152", "cUNq" },
-  { 3, "\270\142\131", "uGJZ" },
-  { 3, "\337\076\074", "3z48" },
-  { 3, "\375\106\362", "/Uby" },
-  { 3, "\227\301\127", "l8FX" },
-  { 3, "\340\002\234", "4AKc" },
-  { 3, "\121\064\033", "UTQb" },
-  { 3, "\157\134\143", "b1xj" },
-  { 3, "\247\055\327", "py3X" },
-  { 3, "\340\142\005", "4GIF" },
-  { 3, "\060\260\143", "MLBj" },
-  { 3, "\075\203\170", "PYN4" },
-  { 3, "\143\160\016", "Y3AO" },
-  { 3, "\313\013\063", "ywsz" },
-  { 3, "\174\236\135", "fJ5d" },
-  { 3, "\103\047\026", "QycW" },
-  { 3, "\365\005\343", "9QXj" },
-  { 3, "\271\160\223", "uXCT" },
-  { 3, "\362\255\172", "8q16" },
-  { 3, "\113\012\015", "SwoN" },
-
-  // various lengths, generated by this python script:
-  //
-  // from string import lowercase as lc
-  // for i in range(27):
-  //   print '{ %2d, "%s",%s "%s" },' % (i, lc[:i], ' ' * (26-i),
-  //                                     lc[:i].encode('base64').strip())
-
-  {  0, "",                           "" },
-  {  1, "a",                          "YQ==" },
-  {  2, "ab",                         "YWI=" },
-  {  3, "abc",                        "YWJj" },
-  {  4, "abcd",                       "YWJjZA==" },
-  {  5, "abcde",                      "YWJjZGU=" },
-  {  6, "abcdef",                     "YWJjZGVm" },
-  {  7, "abcdefg",                    "YWJjZGVmZw==" },
-  {  8, "abcdefgh",                   "YWJjZGVmZ2g=" },
-  {  9, "abcdefghi",                  "YWJjZGVmZ2hp" },
-  { 10, "abcdefghij",                 "YWJjZGVmZ2hpag==" },
-  { 11, "abcdefghijk",                "YWJjZGVmZ2hpams=" },
-  { 12, "abcdefghijkl",               "YWJjZGVmZ2hpamts" },
-  { 13, "abcdefghijklm",              "YWJjZGVmZ2hpamtsbQ==" },
-  { 14, "abcdefghijklmn",             "YWJjZGVmZ2hpamtsbW4=" },
-  { 15, "abcdefghijklmno",            "YWJjZGVmZ2hpamtsbW5v" },
-  { 16, "abcdefghijklmnop",           "YWJjZGVmZ2hpamtsbW5vcA==" },
-  { 17, "abcdefghijklmnopq",          "YWJjZGVmZ2hpamtsbW5vcHE=" },
-  { 18, "abcdefghijklmnopqr",         "YWJjZGVmZ2hpamtsbW5vcHFy" },
-  { 19, "abcdefghijklmnopqrs",        "YWJjZGVmZ2hpamtsbW5vcHFycw==" },
-  { 20, "abcdefghijklmnopqrst",       "YWJjZGVmZ2hpamtsbW5vcHFyc3Q=" },
-  { 21, "abcdefghijklmnopqrstu",      "YWJjZGVmZ2hpamtsbW5vcHFyc3R1" },
-  { 22, "abcdefghijklmnopqrstuv",     "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dg==" },
-  { 23, "abcdefghijklmnopqrstuvw",    "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnc=" },
-  { 24, "abcdefghijklmnopqrstuvwx",   "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4" },
-  { 25, "abcdefghijklmnopqrstuvwxy",  "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eQ==" },
-  { 26, "abcdefghijklmnopqrstuvwxyz", "YWJjZGVmZ2hpamtsbW5vcHFyc3R1dnd4eXo=" },
-};
-
-static struct {
-  const char* plaintext;
-  const char* ciphertext;
-} base64_strings[] = {
-    // Some google quotes
-    // 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 "
-     "that was unusual or somehow undesirable. So one of the things "
-     "I care a lot about is helping to remove that stigma, "
-     "to show girls that you can be feminine, you can like the things "
-     "that girls like, but you can also be really good at technology. "
-     "You can be really good at building things."
-     " - Marissa Meyer, Newsweek, 2010-12-22"
-     "\n",
-
-     "SSB3YXMgYWx3YXlzIGdvb2QgYXQgbWF0aCBhbmQgc2NpZW5jZSwgYW5kIEkg"
-     "bmV2ZXIgcmVhbGl6ZWQgdGhhdCB3YXMgdW51c3VhbCBvciBzb21laG93IHVu"
-     "ZGVzaXJhYmxlLiBTbyBvbmUgb2YgdGhlIHRoaW5ncyBJIGNhcmUgYSBsb3Qg"
-     "YWJvdXQgaXMgaGVscGluZyB0byByZW1vdmUgdGhhdCBzdGlnbWEsIHRvIHNo"
-     "b3cgZ2lybHMgdGhhdCB5b3UgY2FuIGJlIGZlbWluaW5lLCB5b3UgY2FuIGxp"
-     "a2UgdGhlIHRoaW5ncyB0aGF0IGdpcmxzIGxpa2UsIGJ1dCB5b3UgY2FuIGFs"
-     "c28gYmUgcmVhbGx5IGdvb2QgYXQgdGVjaG5vbG9neS4gWW91IGNhbiBiZSBy"
-     "ZWFsbHkgZ29vZCBhdCBidWlsZGluZyB0aGluZ3MuIC0gTWFyaXNzYSBNZXll"
-     "ciwgTmV3c3dlZWssIDIwMTAtMTItMjIK"},
-
-    {"Typical first year for a new cluster: "
-     "~0.5 overheating "
-     "~1 PDU failure "
-     "~1 rack-move "
-     "~1 network rewiring "
-     "~20 rack failures "
-     "~5 racks go wonky "
-     "~8 network maintenances "
-     "~12 router reloads "
-     "~3 router failures "
-     "~dozens of minor 30-second blips for dns "
-     "~1000 individual machine failures "
-     "~thousands of hard drive failures "
-     "slow disks, bad memory, misconfigured machines, flaky machines, etc."
-     " - Jeff Dean, The Joys of Real Hardware"
-     "\n",
-
-     "VHlwaWNhbCBmaXJzdCB5ZWFyIGZvciBhIG5ldyBjbHVzdGVyOiB-MC41IG92"
-     "ZXJoZWF0aW5nIH4xIFBEVSBmYWlsdXJlIH4xIHJhY2stbW92ZSB-MSBuZXR3"
-     "b3JrIHJld2lyaW5nIH4yMCByYWNrIGZhaWx1cmVzIH41IHJhY2tzIGdvIHdv"
-     "bmt5IH44IG5ldHdvcmsgbWFpbnRlbmFuY2VzIH4xMiByb3V0ZXIgcmVsb2Fk"
-     "cyB-MyByb3V0ZXIgZmFpbHVyZXMgfmRvemVucyBvZiBtaW5vciAzMC1zZWNv"
-     "bmQgYmxpcHMgZm9yIGRucyB-MTAwMCBpbmRpdmlkdWFsIG1hY2hpbmUgZmFp"
-     "bHVyZXMgfnRob3VzYW5kcyBvZiBoYXJkIGRyaXZlIGZhaWx1cmVzIHNsb3cg"
-     "ZGlza3MsIGJhZCBtZW1vcnksIG1pc2NvbmZpZ3VyZWQgbWFjaGluZXMsIGZs"
-     "YWt5IG1hY2hpbmVzLCBldGMuIC0gSmVmZiBEZWFuLCBUaGUgSm95cyBvZiBS"
-     "ZWFsIEhhcmR3YXJlCg"},
-
-    {"I'm the head of the webspam team at Google.  "
-     "That means that if you type your name into Google and get porn back, "
-     "it's my fault. Unless you're a porn star, in which case porn is a "
-     "completely reasonable response."
-     " - Matt Cutts, Google Plus"
-     "\n",
-
-     "SSdtIHRoZSBoZWFkIG9mIHRoZSB3ZWJzcGFtIHRlYW0gYXQgR29vZ2xlLiAg"
-     "VGhhdCBtZWFucyB0aGF0IGlmIHlvdSB0eXBlIHlvdXIgbmFtZSBpbnRvIEdv"
-     "b2dsZSBhbmQgZ2V0IHBvcm4gYmFjaywgaXQncyBteSBmYXVsdC4gVW5sZXNz"
-     "IHlvdSdyZSBhIHBvcm4gc3RhciwgaW4gd2hpY2ggY2FzZSBwb3JuIGlzIGEg"
-     "Y29tcGxldGVseSByZWFzb25hYmxlIHJlc3BvbnNlLiAtIE1hdHQgQ3V0dHMs"
-     "IEdvb2dsZSBQbHVzCg"},
-
-    {"It will still be a long time before machines approach human "
-     "intelligence. "
-     "But luckily, machines don't actually have to be intelligent; "
-     "they just have to fake it. Access to a wealth of information, "
-     "combined with a rudimentary decision-making capacity, "
-     "can often be almost as useful. Of course, the results are better yet "
-     "when coupled with intelligence. A reference librarian with access to "
-     "a good search engine is a formidable tool."
-     " - Craig Silverstein, Siemens Pictures of the Future, Spring 2004"
-     "\n",
-
-     "SXQgd2lsbCBzdGlsbCBiZSBhIGxvbmcgdGltZSBiZWZvcmUgbWFjaGluZXMg"
-     "YXBwcm9hY2ggaHVtYW4gaW50ZWxsaWdlbmNlLiBCdXQgbHVja2lseSwgbWFj"
-     "aGluZXMgZG9uJ3QgYWN0dWFsbHkgaGF2ZSB0byBiZSBpbnRlbGxpZ2VudDsg"
-     "dGhleSBqdXN0IGhhdmUgdG8gZmFrZSBpdC4gQWNjZXNzIHRvIGEgd2VhbHRo"
-     "IG9mIGluZm9ybWF0aW9uLCBjb21iaW5lZCB3aXRoIGEgcnVkaW1lbnRhcnkg"
-     "ZGVjaXNpb24tbWFraW5nIGNhcGFjaXR5LCBjYW4gb2Z0ZW4gYmUgYWxtb3N0"
-     "IGFzIHVzZWZ1bC4gT2YgY291cnNlLCB0aGUgcmVzdWx0cyBhcmUgYmV0dGVy"
-     "IHlldCB3aGVuIGNvdXBsZWQgd2l0aCBpbnRlbGxpZ2VuY2UuIEEgcmVmZXJl"
-     "bmNlIGxpYnJhcmlhbiB3aXRoIGFjY2VzcyB0byBhIGdvb2Qgc2VhcmNoIGVu"
-     "Z2luZSBpcyBhIGZvcm1pZGFibGUgdG9vbC4gLSBDcmFpZyBTaWx2ZXJzdGVp"
-     "biwgU2llbWVucyBQaWN0dXJlcyBvZiB0aGUgRnV0dXJlLCBTcHJpbmcgMjAw"
-     "NAo"},
-
-    // Degenerate edge case
-    {"", ""},
-};
-
-TEST(Base64, EscapeAndUnescape) {
-  // Check the short strings; this tests the math (and boundaries)
-  for (int i = 0; i < sizeof(base64_tests) / sizeof(base64_tests[0]); ++i) {
-    char encode_buffer[100];
-    int encode_length;
-    char decode_buffer[100];
-    int decode_length;
-    int cipher_length;
-    std::string decode_str;
-
-    const unsigned char* unsigned_plaintext =
-      reinterpret_cast<const unsigned char*>(base64_tests[i].plaintext);
-
-    StringPiece plaintext(base64_tests[i].plaintext,
-                          base64_tests[i].plain_length);
-
-    cipher_length = strlen(base64_tests[i].ciphertext);
-
-    // The basic escape function:
-    memset(encode_buffer, 0, sizeof(encode_buffer));
-    encode_length = Base64Escape(unsigned_plaintext,
-                                 base64_tests[i].plain_length,
-                                 encode_buffer,
-                                 sizeof(encode_buffer));
-    //    Is it of the expected 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].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, cipher_length);
-    //    Is it still of the expected 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].ciphertext);
-
-    // If we decode it back:
-    decode_str.clear();
-    EXPECT_TRUE(
-        Base64Unescape(StringPiece(encode_buffer, cipher_length), &decode_str));
-
-    //    Is it of the expected length?
-    EXPECT_EQ(base64_tests[i].plain_length, decode_str.length());
-
-    //    Is it the expected decoded value?
-    EXPECT_EQ(plaintext, decode_str);
-
-    // Let's try with a pre-populated string.
-    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));
-
-    std::string decoded("this junk should be ignored");
-    EXPECT_TRUE(
-        Base64Unescape(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);
-
-    // Our decoder treats the padding '=' characters at the end as
-    // optional (but if there are any, there must be the correct
-    // number of them.)  If encode_buffer has any, run some additional
-    // tests that fiddle with them.
-    char* first_equals = strchr(encode_buffer, '=');
-    if (first_equals) {
-      // How many equals signs does the string start with?
-      int equals = (*(first_equals+1) == '=') ? 2 : 1;
-
-      // Try chopping off the equals sign(s) entirely.  The decoder
-      // should still be okay with this.
-      std::string decoded2("this junk should also be ignored");
-      *first_equals = '\0';
-      EXPECT_TRUE(Base64Unescape(
-          StringPiece(encode_buffer, first_equals - encode_buffer), &decoded2));
-      EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
-      EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
-
-      // Now test chopping off the equals sign(s) and adding
-      // whitespace.  Our decoder should still accept this.
-      decoded2.assign("this junk should be ignored");
-      *first_equals = ' ';
-      *(first_equals+1) = '\0';
-      EXPECT_TRUE(Base64Unescape(
-          StringPiece(encode_buffer, first_equals - encode_buffer + 1),
-          &decoded2));
-      EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
-      EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
-
-      // Now stick a bad character at the end of the string.  The decoder
-      // should refuse this string.
-      decoded2.assign("this junk should be ignored");
-      *first_equals = '?';
-      *(first_equals+1) = '\0';
-      EXPECT_TRUE(
-          !Base64Unescape(
-              StringPiece(encode_buffer, first_equals - encode_buffer + 1),
-              &decoded2));
-
-      int len;
-
-      // Test whitespace mixed with the padding.  (eg "AA = = ")  The
-      // decoder should accept this.
-      if (equals == 2) {
-        snprintf(first_equals, 6, " = = ");
-        len = first_equals - encode_buffer + 5;
-      } else {
-        snprintf(first_equals, 6, " = ");
-        len = first_equals - encode_buffer + 3;
-      }
-      decoded2.assign("this junk should be ignored");
-      EXPECT_TRUE(
-          Base64Unescape(StringPiece(encode_buffer, len), &decoded2));
-      EXPECT_EQ(decoded.size(), base64_tests[i].plain_length);
-      EXPECT_EQ_ARRAY(decoded.size(), decoded, base64_tests[i].plaintext, i);
-
-      // Test whitespace mixed with the padding, but with the wrong
-      // number of equals signs (eg "AA = ").  The decoder should
-      // refuse these strings.
-      if (equals == 1) {
-        snprintf(first_equals, 6, " = = ");
-        len = first_equals - encode_buffer + 5;
-      } else {
-        snprintf(first_equals, 6, " = ");
-        len = first_equals - encode_buffer + 3;
-      }
-      EXPECT_TRUE(
-          !Base64Unescape(StringPiece(encode_buffer, len), &decoded2));
-    }
-
-    // Cool! the basic Base64 encoder/decoder works.
-    // Let's try the alternate alphabet: tr -- '+/' '-_'
-
-    char websafe[100];
-    memset(websafe, 0, sizeof(websafe));
-    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] = '_'; }
-    }
-
-    // The websafe escape function:
-    memset(encode_buffer, 0, sizeof(encode_buffer));
-    encode_length = WebSafeBase64Escape(unsigned_plaintext,
-                                                 base64_tests[i].plain_length,
-                                                 encode_buffer,
-                                                 sizeof(encode_buffer),
-                                                 true);
-    //    Is it of the expected length?
-    EXPECT_EQ(encode_length, cipher_length);
-    EXPECT_EQ(
-        CalculateBase64EscapedLen(base64_tests[i].plain_length, true),
-        encode_length);
-
-    //    Is it the expected encoded value?
-    EXPECT_STREQ(encode_buffer, websafe);
-
-    //    If we encode it into a buffer of exactly the right length...
-    memset(encode_buffer, 0, sizeof(encode_buffer));
-    encode_length =
-        WebSafeBase64Escape(unsigned_plaintext, base64_tests[i].plain_length,
-                            encode_buffer, cipher_length, true);
-    //    Is it still of the expected 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 string version of the encoder
-    encoded = "this junk should be ignored";
-    WebSafeBase64Escape(
-        unsigned_plaintext, base64_tests[i].plain_length,
-        &encoded, true);
-    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, cipher_length,
-                                          decode_buffer, sizeof(decode_buffer));
-
-    //    Is it of the expected length?
-    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
-
-    //    Is it the expected decoded value?
-    EXPECT_EQ(0,
-              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
-
-    //    If we decode it into a buffer of exactly the right length...
-    memset(decode_buffer, 0, sizeof(decode_buffer));
-    decode_length = WebSafeBase64Unescape(encode_buffer, cipher_length,
-                                          decode_buffer, decode_length);
-
-    //    Is it still of the expected length?
-    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
-
-    //    And is it the expected decoded value?
-    EXPECT_EQ(0,
-              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
-
-    // Try using '.' for the pad character.
-    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, cipher_length,
-                                          decode_buffer, sizeof(decode_buffer));
-
-    // Is it of the expected length?
-    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
-
-    // Is it the expected decoded value?
-    EXPECT_EQ(0,
-              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
-
-    // If we decode it into a buffer of exactly the right length...
-    memset(decode_buffer, 0, sizeof(decode_buffer));
-    decode_length = WebSafeBase64Unescape(encode_buffer, cipher_length,
-                                          decode_buffer, decode_length);
-
-    // Is it still of the expected length?
-    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
-
-    // And is it the expected decoded value?
-    EXPECT_EQ(0,
-              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
-
-    // Let's try the string version of the decoder
-    decoded = "this junk should be ignored";
-    EXPECT_TRUE(WebSafeBase64Unescape(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);
-
-    // Okay! the websafe Base64 encoder/decoder works.
-    // Let's try the unpadded version
-
-    for (int c = 0; c < sizeof(websafe); ++c) {
-      if ('=' == websafe[c]) {
-        websafe[c] = '\0';
-        cipher_length = c;
-        break;
-      }
-    }
-
-    // The websafe escape function:
-    memset(encode_buffer, 0, sizeof(encode_buffer));
-    encode_length = WebSafeBase64Escape(unsigned_plaintext,
-                                                 base64_tests[i].plain_length,
-                                                 encode_buffer,
-                                                 sizeof(encode_buffer),
-                                                 false);
-    //    Is it of the expected length?
-    EXPECT_EQ(encode_length, cipher_length);
-    EXPECT_EQ(
-        CalculateBase64EscapedLen(base64_tests[i].plain_length, false),
-        encode_length);
-
-    //    Is it the expected encoded value?
-    EXPECT_STREQ(encode_buffer, websafe);
-
-    //    If we encode it into a buffer of exactly the right length...
-    memset(encode_buffer, 0, sizeof(encode_buffer));
-    encode_length =
-        WebSafeBase64Escape(unsigned_plaintext, base64_tests[i].plain_length,
-                            encode_buffer, cipher_length, false);
-    //    Is it still of the expected 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
-    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(), 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, cipher_length,
-                                          decode_buffer, sizeof(decode_buffer));
-
-    //    Is it of the expected length?
-    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
-
-    //    Is it the expected decoded value?
-    EXPECT_EQ(0,
-              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
-
-    //    If we decode it into a buffer of exactly the right length...
-    memset(decode_buffer, 0, sizeof(decode_buffer));
-    decode_length = WebSafeBase64Unescape(encode_buffer, cipher_length,
-                                          decode_buffer, decode_length);
-
-    //    Is it still of the expected length?
-    EXPECT_EQ(decode_length, base64_tests[i].plain_length);
-
-    //    And is it the expected decoded value?
-    EXPECT_EQ(0,
-              memcmp(decode_buffer, base64_tests[i].plaintext, decode_length));
-
-
-    // Let's try the string version of the decoder
-    decoded = "this junk should be ignored";
-    EXPECT_TRUE(WebSafeBase64Unescape(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);
-
-    // This value works.  Try the next.
-  }
-
-  // Now try the long strings, this tests the streaming
-  for (int i = 0; i < sizeof(base64_strings) / sizeof(base64_strings[0]);
-       ++i) {
-    const unsigned char* unsigned_plaintext =
-      reinterpret_cast<const unsigned char*>(base64_strings[i].plaintext);
-    int plain_length = strlen(base64_strings[i].plaintext);
-    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(cipher_length, encode_length);
-    EXPECT_EQ(
-        CalculateBase64EscapedLen(plain_length, false), encode_length);
-    buffer[ encode_length ] = '\0';
-    EXPECT_STREQ(base64_strings[i].ciphertext, &buffer[0]);
-  }
-
-  // Verify the behavior when decoding bad data
-  {
-    const char* bad_data = "ab-/";
-    std::string buf;
-    EXPECT_FALSE(Base64Unescape(StringPiece(bad_data), &buf));
-    EXPECT_TRUE(!WebSafeBase64Unescape(bad_data, &buf));
-    EXPECT_TRUE(buf.empty());
-  }
-}
-
-// Test StrCat of ints and longs of various sizes and signdedness.
-TEST(StrCat, Ints) {
-  const short s = -1;  // NOLINT(runtime/int)
-  const uint16_t us = 2;
-  const int i = -3;
-  const unsigned int ui = 4;
-  const long l = -5;                 // NOLINT(runtime/int)
-  const unsigned long ul = 6;        // NOLINT(runtime/int)
-  const long long ll = -7;           // NOLINT(runtime/int)
-  const unsigned long long ull = 8;  // NOLINT(runtime/int)
-  const ptrdiff_t ptrdiff = -9;
-  const size_t size = 10;
-  const intptr_t intptr = -12;
-  const uintptr_t uintptr = 13;
-  std::string answer;
-  answer = StrCat(s, us);
-  EXPECT_EQ(answer, "-12");
-  answer = StrCat(i, ui);
-  EXPECT_EQ(answer, "-34");
-  answer = StrCat(l, ul);
-  EXPECT_EQ(answer, "-56");
-  answer = StrCat(ll, ull);
-  EXPECT_EQ(answer, "-78");
-  answer = StrCat(ptrdiff, size);
-  EXPECT_EQ(answer, "-910");
-  answer = StrCat(ptrdiff, intptr);
-  EXPECT_EQ(answer, "-9-12");
-  answer = StrCat(uintptr, 0);
-  EXPECT_EQ(answer, "130");
-}
-
-class ReplaceChars
-    : public ::testing::TestWithParam<
-          std::tuple<std::string, std::string, const char*, char>> {};
-
-TEST_P(ReplaceChars, ReplacesAllOccurencesOfAnyCharInReplaceWithAReplaceChar) {
-  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);
-  ASSERT_EQ(expected, string_to_replace_in);
-}
-
-INSTANTIATE_TEST_CASE_P(
-    Replace, ReplaceChars,
-    ::testing::Values(
-        std::make_tuple("", "", "", '_'),    // empty string should remain empty
-        std::make_tuple(" ", " ", "", '_'),  // no replacement string
-        std::make_tuple(" ", " ", "_-abcedf",
-                        '*'),  // replacement character not in string
-        std::make_tuple("replace", "Replace", "R",
-                        'r'),  // replace one character
-        std::make_tuple("not_spaces__", "not\nspaces\t ", " \t\r\n",
-                        '_'),  // replace some special characters
-        std::make_tuple("c++", "cxx", "x",
-                        '+'),  // same character multiple times
-        std::make_tuple("qvvvvvng v T", "queueing a T", "aeiou",
-                        'v')));  // replace all voewls
-
-class StripWs
-    : public ::testing::TestWithParam<std::tuple<std::string, std::string>> {};
-
-TEST_P(StripWs, AlwaysStripsLeadingAndTrailingWhitespace) {
-  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);
-}
-
-INSTANTIATE_TEST_CASE_P(
-    Strip, StripWs,
-    ::testing::Values(
-        std::make_tuple("", ""),   // empty string should remain empty
-        std::make_tuple("", " "),  // only ws should become empty
-        std::make_tuple("no whitespace",
-                        " no whitespace"),  // leading ws removed
-        std::make_tuple("no whitespace",
-                        "no whitespace "),  // trailing ws removed
-        std::make_tuple("no whitespace",
-                        " no whitespace "),  // same nb. of leading and trailing
-        std::make_tuple(
-            "no whitespace",
-            "  no whitespace "),  // different nb. of leading/trailing
-        std::make_tuple("no whitespace",
-                        " no whitespace  ")));  // more trailing than leading
-
-}  // anonymous namespace
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/substitute.cc b/src/google/protobuf/stubs/substitute.cc
deleted file mode 100644
index d301682..0000000
--- a/src/google/protobuf/stubs/substitute.cc
+++ /dev/null
@@ -1,136 +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)
-
-#include <google/protobuf/stubs/substitute.h>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/stl_util.h>
-
-namespace google {
-namespace protobuf {
-namespace strings {
-
-using internal::SubstituteArg;
-
-// Returns the number of args in arg_array which were passed explicitly
-// to Substitute().
-static int CountSubstituteArgs(const SubstituteArg* const* args_array) {
-  int count = 0;
-  while (args_array[count] != nullptr && args_array[count]->size() != -1) {
-    ++count;
-  }
-  return count;
-}
-
-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(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
-  };
-
-  // Determine total size needed.
-  int size = 0;
-  for (int i = 0; format[i] != '\0'; i++) {
-    if (format[i] == '$') {
-      if (ascii_isdigit(format[i+1])) {
-        int index = format[i+1] - '0';
-        if (args_array[index]->size() == -1) {
-          GOOGLE_LOG(DFATAL)
-            << "strings::Substitute format string invalid: asked for \"$"
-            << index << "\", but only " << CountSubstituteArgs(args_array)
-            << " args were given.  Full format string was: \""
-            << CEscape(format) << "\".";
-          return;
-        }
-        size += args_array[index]->size();
-        ++i;  // Skip next char.
-      } else if (format[i+1] == '$') {
-        ++size;
-        ++i;  // Skip next char.
-      } else {
-        GOOGLE_LOG(DFATAL)
-          << "Invalid strings::Substitute() format string: \""
-          << CEscape(format) << "\".";
-        return;
-      }
-    } else {
-      ++size;
-    }
-  }
-
-  if (size == 0) return;
-
-  // Build the string.
-  int original_size = output->size();
-  STLStringResizeUninitialized(output, original_size + size);
-  char* target = string_as_array(output) + original_size;
-  for (int i = 0; format[i] != '\0'; i++) {
-    if (format[i] == '$') {
-      if (ascii_isdigit(format[i+1])) {
-        unsigned int index = format[i+1] - '0';
-        assert(index < 10);
-        const SubstituteArg* src = args_array[index];
-        memcpy(target, src->data(), src->size());
-        target += src->size();
-        ++i;  // Skip next char.
-      } else if (format[i+1] == '$') {
-        *target++ = '$';
-        ++i;  // Skip next char.
-      }
-    } else {
-      *target++ = format[i];
-    }
-  }
-
-  GOOGLE_DCHECK_EQ(target - output->data(), output->size());
-}
-
-}  // namespace strings
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/substitute.h b/src/google/protobuf/stubs/substitute.h
deleted file mode 100644
index 0f851de..0000000
--- a/src/google/protobuf/stubs/substitute.h
+++ /dev/null
@@ -1,178 +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)
-// from google3/strings/substitute.h
-
-#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_
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace strings {
-
-// ----------------------------------------------------------------------
-// strings::Substitute()
-// strings::SubstituteAndAppend()
-//   Kind of like StringPrintf, but different.
-//
-//   Example:
-//     string GetMessage(string first_name, string last_name, int age) {
-//       return strings::Substitute("My name is $0 $1 and I am $2 years old.",
-//                                  first_name, last_name, age);
-//     }
-//
-//   Differences from StringPrintf:
-//   * The format string does not identify the types of arguments.
-//     Instead, the magic of C++ deals with this for us.  See below
-//     for a list of accepted types.
-//   * Substitutions in the format string are identified by a '$'
-//     followed by a digit.  So, you can use arguments out-of-order and
-//     use the same argument multiple times.
-//   * It's much faster than StringPrintf.
-//
-//   Supported types:
-//   * Strings (const char*, const string&)
-//     * Note that this means you do not have to add .c_str() to all of
-//       your strings.  In fact, you shouldn't; it will be slower.
-//   * int32, int64, uint32, uint64:  Formatted using SimpleItoa().
-//   * float, double:  Formatted using SimpleFtoa() and SimpleDtoa().
-//   * bool:  Printed as "true" or "false".
-//
-//   SubstituteAndAppend() is like Substitute() but appends the result to
-//   *output.  Example:
-//
-//     string str;
-//     strings::SubstituteAndAppend(&str,
-//                                  "My name is $0 $1 and I am $2 years old.",
-//                                  first_name, last_name, age);
-//
-//   Substitute() is significantly faster than StringPrintf().  For very
-//   large strings, it may be orders of magnitude faster.
-// ----------------------------------------------------------------------
-
-namespace internal {  // Implementation details.
-
-class SubstituteArg {
- public:
-  inline SubstituteArg(const char* value)
-    : text_(value), size_(strlen(text_)) {}
-  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()
-    : text_(nullptr), size_(-1) {}
-
-  // Primitives
-  // We don't overload for signed and unsigned char because if people are
-  // explicitly declaring their chars as signed or unsigned then they are
-  // probably actually using them as 8-bit integers and would probably
-  // prefer an integer representation.  But, we don't really know.  So, we
-  // make the caller decide what to do.
-  inline SubstituteArg(char value)
-    : text_(scratch_), size_(1) { scratch_[0] = value; }
-  inline SubstituteArg(short value)
-    : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(unsigned short value)
-    : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(int value)
-    : text_(FastInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(unsigned int value)
-    : text_(FastUInt32ToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(long value)
-    : text_(FastLongToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(unsigned long value)
-    : text_(FastULongToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(long long value)
-    : text_(FastInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(unsigned long long value)
-    : text_(FastUInt64ToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(float value)
-    : text_(FloatToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(double value)
-    : text_(DoubleToBuffer(value, scratch_)), size_(strlen(text_)) {}
-  inline SubstituteArg(bool value)
-    : text_(value ? "true" : "false"), size_(strlen(text_)) {}
-
-  inline const char* data() const { return text_; }
-  inline int size() const { return size_; }
-
- private:
-  const char* text_;
-  int size_;
-  char scratch_[kFastToBufferSize];
-};
-
-}  // namespace internal
-
-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(
-    std::string* output, 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());
-
-}  // namespace strings
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif // GOOGLE_PROTOBUF_STUBS_SUBSTITUTE_H_
diff --git a/src/google/protobuf/stubs/template_util.h b/src/google/protobuf/stubs/template_util.h
deleted file mode 100644
index feef904..0000000
--- a/src/google/protobuf/stubs/template_util.h
+++ /dev/null
@@ -1,138 +0,0 @@
-// Copyright 2005 Google Inc.
-// 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 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: lar@google.com (Laramie Leavitt)
-//
-// Template metaprogramming utility functions.
-//
-// This code is compiled directly on many platforms, including client
-// platforms like Windows, Mac, and embedded systems.  Before making
-// any changes here, make sure that you're not breaking any platforms.
-//
-//
-// The names chosen here reflect those used in tr1 and the boost::mpl
-// library, there are similar operations used in the Loki library as
-// well.  I prefer the boost names for 2 reasons:
-// 1.  I think that portions of the Boost libraries are more likely to
-// be included in the c++ standard.
-// 2.  It is not impossible that some of the boost libraries will be
-// included in our own build in the future.
-// Both of these outcomes means that we may be able to directly replace
-// some of these with boost equivalents.
-//
-#ifndef GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
-#define GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-// Types small_ and big_ are guaranteed such that sizeof(small_) <
-// sizeof(big_)
-typedef char small_;
-
-struct big_ {
-  char dummy[2];
-};
-
-// Identity metafunction.
-template <class T>
-struct identity_ {
-  typedef T type;
-};
-
-// integral_constant, defined in tr1, is a wrapper for an integer
-// value. We don't really need this generality; we could get away
-// with hardcoding the integer type to bool. We use the fully
-// general integer_constant for compatibility with tr1.
-
-template<class T, T v>
-struct integral_constant {
-  static const T value = v;
-  typedef T value_type;
-  typedef integral_constant<T, v> type;
-};
-
-template <class T, T v> const T integral_constant<T, v>::value;
-
-
-// Abbreviations: true_type and false_type are structs that represent boolean
-// true and false values. Also define the boost::mpl versions of those names,
-// true_ and false_.
-typedef integral_constant<bool, true>  true_type;
-typedef integral_constant<bool, false> false_type;
-typedef true_type  true_;
-typedef false_type false_;
-
-// if_ is a templatized conditional statement.
-// if_<cond, A, B> is a compile time evaluation of cond.
-// if_<>::type contains A if cond is true, B otherwise.
-template<bool cond, typename A, typename B>
-struct if_{
-  typedef A type;
-};
-
-template<typename A, typename B>
-struct if_<false, A, B> {
-  typedef B type;
-};
-
-
-// type_equals_ is a template type comparator, similar to Loki IsSameType.
-// type_equals_<A, B>::value is true iff "A" is the same type as "B".
-//
-// New code should prefer base::is_same, defined in base/type_traits.h.
-// It is functionally identical, but is_same is the standard spelling.
-template<typename A, typename B>
-struct type_equals_ : public false_ {
-};
-
-template<typename A>
-struct type_equals_<A, A> : public true_ {
-};
-
-// and_ is a template && operator.
-// and_<A, B>::value evaluates "A::value && B::value".
-template<typename A, typename B>
-struct and_ : public integral_constant<bool, (A::value && B::value)> {
-};
-
-// or_ is a template || operator.
-// or_<A, B>::value evaluates "A::value || B::value".
-template<typename A, typename B>
-struct or_ : public integral_constant<bool, (A::value || B::value)> {
-};
-
-
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_TEMPLATE_UTIL_H_
diff --git a/src/google/protobuf/stubs/template_util_unittest.cc b/src/google/protobuf/stubs/template_util_unittest.cc
deleted file mode 100644
index b1745e2..0000000
--- a/src/google/protobuf/stubs/template_util_unittest.cc
+++ /dev/null
@@ -1,130 +0,0 @@
-// Copyright 2005 Google Inc.
-// 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 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: lar@google.com (Laramie Leavitt)
-//
-// These tests are really compile time tests.
-// If you try to step through this in a debugger
-// you will not see any evaluations, merely that
-// value is assigned true or false sequentially.
-
-#include <google/protobuf/stubs/template_util.h>
-
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-namespace GOOGLE_NAMESPACE = google::protobuf::internal;
-
-namespace google {
-namespace protobuf {
-namespace internal {
-namespace {
-
-TEST(TemplateUtilTest, TestSize) {
-  EXPECT_GT(sizeof(GOOGLE_NAMESPACE::big_), sizeof(GOOGLE_NAMESPACE::small_));
-}
-
-TEST(TemplateUtilTest, TestIntegralConstants) {
-  // test the built-in types.
-  EXPECT_TRUE(true_type::value);
-  EXPECT_FALSE(false_type::value);
-
-  typedef integral_constant<int, 1> one_type;
-  EXPECT_EQ(1, one_type::value);
-}
-
-TEST(TemplateUtilTest, TestTemplateIf) {
-  typedef if_<true, true_type, false_type>::type if_true;
-  EXPECT_TRUE(if_true::value);
-
-  typedef if_<false, true_type, false_type>::type if_false;
-  EXPECT_FALSE(if_false::value);
-}
-
-TEST(TemplateUtilTest, TestTemplateTypeEquals) {
-  // Check that the TemplateTypeEquals works correctly.
-  bool value = false;
-
-  // Test the same type is true.
-  value = type_equals_<int, int>::value;
-  EXPECT_TRUE(value);
-
-  // Test different types are false.
-  value = type_equals_<float, int>::value;
-  EXPECT_FALSE(value);
-
-  // Test type aliasing.
-  typedef const int foo;
-  value = type_equals_<const foo, const int>::value;
-  EXPECT_TRUE(value);
-}
-
-TEST(TemplateUtilTest, TestTemplateAndOr) {
-  // Check that the TemplateTypeEquals works correctly.
-  bool value = false;
-
-  // Yes && Yes == true.
-  value = and_<true_, true_>::value;
-  EXPECT_TRUE(value);
-  // Yes && No == false.
-  value = and_<true_, false_>::value;
-  EXPECT_FALSE(value);
-  // No && Yes == false.
-  value = and_<false_, true_>::value;
-  EXPECT_FALSE(value);
-  // No && No == false.
-  value = and_<false_, false_>::value;
-  EXPECT_FALSE(value);
-
-  // Yes || Yes == true.
-  value = or_<true_, true_>::value;
-  EXPECT_TRUE(value);
-  // Yes || No == true.
-  value = or_<true_, false_>::value;
-  EXPECT_TRUE(value);
-  // No || Yes == true.
-  value = or_<false_, true_>::value;
-  EXPECT_TRUE(value);
-  // No || No == false.
-  value = or_<false_, false_>::value;
-  EXPECT_FALSE(value);
-}
-
-TEST(TemplateUtilTest, TestIdentity) {
-  EXPECT_TRUE(
-      (type_equals_<GOOGLE_NAMESPACE::identity_<int>::type, int>::value));
-  EXPECT_TRUE(
-      (type_equals_<GOOGLE_NAMESPACE::identity_<void>::type, void>::value));
-}
-
-}  // anonymous namespace
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/time.cc b/src/google/protobuf/stubs/time.cc
deleted file mode 100644
index 692cb82..0000000
--- a/src/google/protobuf/stubs/time.cc
+++ /dev/null
@@ -1,365 +0,0 @@
-#include <google/protobuf/stubs/time.h>
-
-#include <ctime>
-
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/strutil.h>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-namespace {
-static const int64_t kSecondsPerMinute = 60;
-static const int64_t kSecondsPerHour = 3600;
-static const int64_t kSecondsPerDay = kSecondsPerHour * 24;
-static const int64_t kSecondsPer400Years =
-    kSecondsPerDay * (400 * 365 + 400 / 4 - 3);
-// Seconds from 0001-01-01T00:00:00 to 1970-01-01T:00:00:00
-static const int64_t kSecondsFromEraToEpoch = 62135596800LL;
-// The range of timestamp values we support.
-static const int64_t kMinTime = -62135596800LL;  // 0001-01-01T00:00:00
-static const int64_t kMaxTime = 253402300799LL;  // 9999-12-31T23:59:59
-
-static const int kNanosPerMillisecond = 1000000;
-static const int kNanosPerMicrosecond = 1000;
-
-// Count the seconds from the given year (start at Jan 1, 00:00) to 100 years
-// after.
-int64_t SecondsPer100Years(int year) {
-  if (year % 400 == 0 || year % 400 > 300) {
-    return kSecondsPerDay * (100 * 365 + 100 / 4);
-  } else {
-    return kSecondsPerDay * (100 * 365 + 100 / 4 - 1);
-  }
-}
-
-// Count the seconds from the given year (start at Jan 1, 00:00) to 4 years
-// after.
-int64_t SecondsPer4Years(int year) {
-  if ((year % 100 == 0 || year % 100 > 96) &&
-      !(year % 400 == 0 || year % 400 > 396)) {
-    // No leap years.
-    return kSecondsPerDay * (4 * 365);
-  } else {
-    // One leap years.
-    return kSecondsPerDay * (4 * 365 + 1);
-  }
-}
-
-bool IsLeapYear(int year) {
-  return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
-}
-
-int64_t SecondsPerYear(int year) {
-  return kSecondsPerDay * (IsLeapYear(year) ? 366 : 365);
-}
-
-static const int kDaysInMonth[13] = {
-  0, 31, 28, 31, 30, 31, 30, 31, 31, 30, 31, 30, 31
-};
-
-int64_t SecondsPerMonth(int month, bool leap) {
-  if (month == 2 && leap) {
-    return kSecondsPerDay * (kDaysInMonth[month] + 1);
-  }
-  return kSecondsPerDay * kDaysInMonth[month];
-}
-
-static const int kDaysSinceJan[13] = {
-  0, 0, 31, 59, 90, 120, 151, 181, 212, 243, 273, 304, 334,
-};
-
-bool ValidateDateTime(const DateTime& time) {
-  if (time.year < 1 || time.year > 9999 ||
-      time.month < 1 || time.month > 12 ||
-      time.day < 1 || time.day > 31 ||
-      time.hour < 0 || time.hour > 23 ||
-      time.minute < 0 || time.minute > 59 ||
-      time.second < 0 || time.second > 59) {
-    return false;
-  }
-  if (time.month == 2 && IsLeapYear(time.year)) {
-    return time.day <= kDaysInMonth[time.month] + 1;
-  } else {
-    return time.day <= kDaysInMonth[time.month];
-  }
-}
-
-// Count the number of seconds elapsed from 0001-01-01T00:00:00 to the given
-// time.
-int64_t SecondsSinceCommonEra(const DateTime& time) {
-  int64_t result = 0;
-  // Years should be between 1 and 9999.
-  assert(time.year >= 1 && time.year <= 9999);
-  int year = 1;
-  if ((time.year - year) >= 400) {
-    int count_400years = (time.year - year) / 400;
-    result += kSecondsPer400Years * count_400years;
-    year += count_400years * 400;
-  }
-  while ((time.year - year) >= 100) {
-    result += SecondsPer100Years(year);
-    year += 100;
-  }
-  while ((time.year - year) >= 4) {
-    result += SecondsPer4Years(year);
-    year += 4;
-  }
-  while (time.year > year) {
-    result += SecondsPerYear(year);
-    ++year;
-  }
-  // Months should be between 1 and 12.
-  assert(time.month >= 1 && time.month <= 12);
-  int month = time.month;
-  result += kSecondsPerDay * kDaysSinceJan[month];
-  if (month > 2 && IsLeapYear(year)) {
-    result += kSecondsPerDay;
-  }
-  assert(time.day >= 1 &&
-         time.day <= (month == 2 && IsLeapYear(year)
-                          ? kDaysInMonth[month] + 1
-                          : kDaysInMonth[month]));
-  result += kSecondsPerDay * (time.day - 1);
-  result += kSecondsPerHour * time.hour +
-      kSecondsPerMinute * time.minute +
-      time.second;
-  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_t nanos) {
-  if (nanos % kNanosPerMillisecond == 0) {
-    return StringPrintf("%03d", nanos / kNanosPerMillisecond);
-  } else if (nanos % kNanosPerMicrosecond == 0) {
-    return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
-  } else {
-    return StringPrintf("%09d", nanos);
-  }
-}
-
-// Parses an integer from a null-terminated char sequence. The method
-// consumes at most "width" chars. Returns a pointer after the consumed
-// integer, or nullptr if the data does not start with an integer or the
-// integer value does not fall in the range of [min_value, max_value].
-const char* ParseInt(const char* data, int width, int min_value,
-                     int max_value, int* result) {
-  if (!ascii_isdigit(*data)) {
-    return nullptr;
-  }
-  int value = 0;
-  for (int i = 0; i < width; ++i, ++data) {
-    if (ascii_isdigit(*data)) {
-      value = value * 10 + (*data - '0');
-    } else {
-      break;
-    }
-  }
-  if (value >= min_value && value <= max_value) {
-    *result = value;
-    return data;
-  } else {
-    return nullptr;
-  }
-}
-
-// Consumes the fractional parts of a second into nanos. For example,
-// "010" will be parsed to 10000000 nanos.
-const char* ParseNanos(const char* data, int32_t* nanos) {
-  if (!ascii_isdigit(*data)) {
-    return nullptr;
-  }
-  int value = 0;
-  int len = 0;
-  // Consume as many digits as there are but only take the first 9 into
-  // account.
-  while (ascii_isdigit(*data)) {
-    if (len < 9) {
-      value = value * 10 + *data - '0';
-    }
-    ++len;
-    ++data;
-  }
-  while (len < 9) {
-    value = value * 10;
-    ++len;
-  }
-  *nanos = value;
-  return data;
-}
-
-const char* ParseTimezoneOffset(const char* data, int64_t* offset) {
-  // Accept format "HH:MM". E.g., "08:00"
-  int hour;
-  if ((data = ParseInt(data, 2, 0, 23, &hour)) == nullptr) {
-    return nullptr;
-  }
-  if (*data++ != ':') {
-    return nullptr;
-  }
-  int minute;
-  if ((data = ParseInt(data, 2, 0, 59, &minute)) == nullptr) {
-    return nullptr;
-  }
-  *offset = (hour * 60 + minute) * 60;
-  return data;
-}
-}  // namespace
-
-bool SecondsToDateTime(int64_t seconds, DateTime* time) {
-  if (seconds < kMinTime || seconds > kMaxTime) {
-    return false;
-  }
-  // It's easier to calculate the DateTime starting from 0001-01-01T00:00:00
-  seconds = seconds + kSecondsFromEraToEpoch;
-  int year = 1;
-  if (seconds >= kSecondsPer400Years) {
-    int count_400years = seconds / kSecondsPer400Years;
-    year += 400 * count_400years;
-    seconds %= kSecondsPer400Years;
-  }
-  while (seconds >= SecondsPer100Years(year)) {
-    seconds -= SecondsPer100Years(year);
-    year += 100;
-  }
-  while (seconds >= SecondsPer4Years(year)) {
-    seconds -= SecondsPer4Years(year);
-    year += 4;
-  }
-  while (seconds >= SecondsPerYear(year)) {
-    seconds -= SecondsPerYear(year);
-    year += 1;
-  }
-  bool leap = IsLeapYear(year);
-  int month = 1;
-  while (seconds >= SecondsPerMonth(month, leap)) {
-    seconds -= SecondsPerMonth(month, leap);
-    ++month;
-  }
-  int day = 1 + seconds / kSecondsPerDay;
-  seconds %= kSecondsPerDay;
-  int hour = seconds / kSecondsPerHour;
-  seconds %= kSecondsPerHour;
-  int minute = seconds / kSecondsPerMinute;
-  seconds %= kSecondsPerMinute;
-  time->year = year;
-  time->month = month;
-  time->day = day;
-  time->hour = hour;
-  time->minute = minute;
-  time->second = static_cast<int>(seconds);
-  return true;
-}
-
-bool DateTimeToSeconds(const DateTime& time, int64_t* seconds) {
-  if (!ValidateDateTime(time)) {
-    return false;
-  }
-  *seconds = SecondsSinceCommonEra(time) - kSecondsFromEraToEpoch;
-  return true;
-}
-
-void GetCurrentTime(int64_t* seconds, int32_t* nanos) {
-  // TODO(xiaofeng): Improve the accuracy of this implementation (or just
-  // remove this method from protobuf).
-  *seconds = time(nullptr);
-  *nanos = 0;
-}
-
-std::string FormatTime(int64_t seconds, int32_t nanos) {
-  DateTime time;
-  if (nanos < 0 || nanos > 999999999 || !SecondsToDateTime(seconds, &time)) {
-    return "InvalidTime";
-  }
-  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 std::string& value, int64_t* seconds, int32_t* nanos) {
-  DateTime time;
-  const char* data = value.c_str();
-  // We only accept:
-  //   Z-normalized: 2015-05-20T13:29:35.120Z
-  //   With UTC offset: 2015-05-20T13:29:35.120-08:00
-
-  // Parse year
-  if ((data = ParseInt(data, 4, 1, 9999, &time.year)) == nullptr) {
-    return false;
-  }
-  // Expect '-'
-  if (*data++ != '-') return false;
-  // Parse month
-  if ((data = ParseInt(data, 2, 1, 12, &time.month)) == nullptr) {
-    return false;
-  }
-  // Expect '-'
-  if (*data++ != '-') return false;
-  // Parse day
-  if ((data = ParseInt(data, 2, 1, 31, &time.day)) == nullptr) {
-    return false;
-  }
-  // Expect 'T'
-  if (*data++ != 'T') return false;
-  // Parse hour
-  if ((data = ParseInt(data, 2, 0, 23, &time.hour)) == nullptr) {
-    return false;
-  }
-  // Expect ':'
-  if (*data++ != ':') return false;
-  // Parse minute
-  if ((data = ParseInt(data, 2, 0, 59, &time.minute)) == nullptr) {
-    return false;
-  }
-  // Expect ':'
-  if (*data++ != ':') return false;
-  // Parse second
-  if ((data = ParseInt(data, 2, 0, 59, &time.second)) == nullptr) {
-    return false;
-  }
-  if (!DateTimeToSeconds(time, seconds)) {
-    return false;
-  }
-  // Parse nanoseconds.
-  if (*data == '.') {
-    ++data;
-    // Parse nanoseconds.
-    if ((data = ParseNanos(data, nanos)) == nullptr) {
-      return false;
-    }
-  } else {
-    *nanos = 0;
-  }
-  // Parse UTC offsets.
-  if (*data == 'Z') {
-    ++data;
-  } else if (*data == '+') {
-    ++data;
-    int64_t offset;
-    if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) {
-      return false;
-    }
-    *seconds -= offset;
-  } else if (*data == '-') {
-    ++data;
-    int64_t offset;
-    if ((data = ParseTimezoneOffset(data, &offset)) == nullptr) {
-      return false;
-    }
-    *seconds += offset;
-  } else {
-    return false;
-  }
-  // Done with parsing.
-  return *data == 0;
-}
-
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/stubs/time.h b/src/google/protobuf/stubs/time.h
deleted file mode 100644
index 8b6e562..0000000
--- a/src/google/protobuf/stubs/time.h
+++ /dev/null
@@ -1,82 +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_STUBS_TIME_H_
-#define GOOGLE_PROTOBUF_STUBS_TIME_H_
-
-#include <cstdint>
-
-#include <google/protobuf/stubs/common.h>
-
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-
-struct DateTime {
-  int year;
-  int month;
-  int day;
-  int hour;
-  int minute;
-  int second;
-};
-
-// Converts a timestamp (seconds elapsed since 1970-01-01T00:00:00, could be
-// negative to represent time before 1970-01-01) to DateTime. Returns false
-// if the timestamp is not in the range between 0001-01-01T00:00:00 and
-// 9999-12-31T23:59:59.
-bool PROTOBUF_EXPORT SecondsToDateTime(int64_t seconds, DateTime* time);
-// Converts DateTime to a timestamp (seconds since 1970-01-01T00:00:00).
-// Returns false if the DateTime is not valid or is not in the valid range.
-bool PROTOBUF_EXPORT DateTimeToSeconds(const DateTime& time, int64_t* seconds);
-
-void PROTOBUF_EXPORT GetCurrentTime(int64_t* seconds, int32_t* nanos);
-
-// Formats a time string in RFC3339 format.
-//
-// For example, "2015-05-20T13:29:35.120Z". For nanos, 0, 3, 6 or 9 fractional
-// digits will be used depending on how many are required to represent the exact
-// value.
-//
-// Note that "nanos" must in the range of [0, 999999999].
-std::string PROTOBUF_EXPORT FormatTime(int64_t seconds, int32_t 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 std::string& value, int64_t* seconds,
-                               int32_t* nanos);
-
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_STUBS_TIME_H_
diff --git a/src/google/protobuf/stubs/time_test.cc b/src/google/protobuf/stubs/time_test.cc
deleted file mode 100644
index 1ce0a1c..0000000
--- a/src/google/protobuf/stubs/time_test.cc
+++ /dev/null
@@ -1,261 +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 <google/protobuf/stubs/time.h>
-
-#include <google/protobuf/testing/googletest.h>
-#include <gtest/gtest.h>
-
-namespace google {
-namespace protobuf {
-namespace internal {
-namespace {
-static const int64 kSecondsPerDay = 3600 * 24;
-
-// 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;
-  time.year = year;
-  time.month = month;
-  time.day = day;
-  time.hour = time.minute = time.second = 0;
-  int64 result;
-  GOOGLE_CHECK(DateTimeToSeconds(time, &result));
-  // Check that a roundtrip produces the same result.
-  GOOGLE_CHECK(SecondsToDateTime(result, &time));
-  GOOGLE_CHECK(time.year == year);
-  GOOGLE_CHECK(time.month == month);
-  GOOGLE_CHECK(time.day == day);
-  return result;
-}
-
-TEST(DateTimeTest, SimpleTime) {
-  DateTime time;
-  ASSERT_TRUE(SecondsToDateTime(1, &time));
-  EXPECT_EQ(1970, time.year);
-  EXPECT_EQ(1, time.month);
-  EXPECT_EQ(1, time.day);
-  EXPECT_EQ(0, time.hour);
-  EXPECT_EQ(0, time.minute);
-  EXPECT_EQ(1, time.second);
-  int64 seconds;
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  EXPECT_EQ(1, seconds);
-
-  ASSERT_TRUE(SecondsToDateTime(-1, &time));
-  EXPECT_EQ(1969, time.year);
-  EXPECT_EQ(12, time.month);
-  EXPECT_EQ(31, time.day);
-  EXPECT_EQ(23, time.hour);
-  EXPECT_EQ(59, time.minute);
-  EXPECT_EQ(59, time.second);
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  EXPECT_EQ(-1, seconds);
-
-  DateTime start, end;
-  start.year = 1;
-  start.month = 1;
-  start.day = 1;
-  start.hour = 0;
-  start.minute = 0;
-  start.second = 0;
-  end.year = 9999;
-  end.month = 12;
-  end.day = 31;
-  end.hour = 23;
-  end.minute = 59;
-  end.second = 59;
-  int64 start_time, end_time;
-  ASSERT_TRUE(DateTimeToSeconds(start, &start_time));
-  ASSERT_TRUE(DateTimeToSeconds(end, &end_time));
-  EXPECT_EQ(315537897599LL, end_time - start_time);
-  ASSERT_TRUE(SecondsToDateTime(start_time, &time));
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  EXPECT_EQ(start_time, seconds);
-  ASSERT_TRUE(SecondsToDateTime(end_time, &time));
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  EXPECT_EQ(end_time, seconds);
-}
-
-TEST(DateTimeTest, DayInMonths) {
-  // Check that month boundaries are handled correctly.
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 1, 1) - CreateTimestamp(2014, 12, 31));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 2, 1) - CreateTimestamp(2015, 1, 31));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 4, 1) - CreateTimestamp(2015, 3, 31));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 5, 1) - CreateTimestamp(2015, 4, 30));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 6, 1) - CreateTimestamp(2015, 5, 31));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 7, 1) - CreateTimestamp(2015, 6, 30));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 8, 1) - CreateTimestamp(2015, 7, 31));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 9, 1) - CreateTimestamp(2015, 8, 31));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 10, 1) - CreateTimestamp(2015, 9, 30));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 11, 1) - CreateTimestamp(2015, 10, 31));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 12, 1) - CreateTimestamp(2015, 11, 30));
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2016, 1, 1) - CreateTimestamp(2015, 12, 31));
-}
-
-TEST(DateTimeTest, LeapYear) {
-  // Non-leap year.
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2015, 3, 1) - CreateTimestamp(2015, 2, 28));
-  // Leap year.
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2016, 3, 1) - CreateTimestamp(2016, 2, 29));
-  // Non-leap year.
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2100, 3, 1) - CreateTimestamp(2100, 2, 28));
-  // Leap year.
-  EXPECT_EQ(kSecondsPerDay,
-            CreateTimestamp(2400, 3, 1) - CreateTimestamp(2400, 2, 29));
-}
-
-TEST(DateTimeTest, WrongDays) {
-  int64 seconds;
-  DateTime time;
-  time.hour = 0;
-  time.minute = 0;
-  time.second = 0;
-  time.month = 2;
-
-  // Non-leap year.
-  time.year = 2015;
-  time.day = 29;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-
-  // Leap year.
-  time.year = 2016;
-  time.day = 29;
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  time.day = 30;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-
-  // Non-leap year.
-  time.year = 2100;
-  time.day = 29;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-
-  // Leap year.
-  time.year = 2400;
-  time.day = 29;
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  time.day = 30;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-
-  // Non-february
-  time.year = 2015;
-  time.month = 1;
-  time.day = 0;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-  time.day = 1;
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  time.day = 31;
-  ASSERT_TRUE(DateTimeToSeconds(time, &seconds));
-  time.day = 32;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-
-  // Bad month
-  time.year = 2015;
-  time.month = 0;
-  time.day = 1;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-  time.month = 13;
-  ASSERT_FALSE(DateTimeToSeconds(time, &seconds));
-}
-
-TEST(DateTimeTest, StringFormat) {
-  DateTime start, end;
-  start.year = 1;
-  start.month = 1;
-  start.day = 1;
-  start.hour = 0;
-  start.minute = 0;
-  start.second = 0;
-  end.year = 9999;
-  end.month = 12;
-  end.day = 31;
-  end.hour = 23;
-  end.minute = 59;
-  end.second = 59;
-  int64 start_time, end_time;
-  ASSERT_TRUE(DateTimeToSeconds(start, &start_time));
-  ASSERT_TRUE(DateTimeToSeconds(end, &end_time));
-
-  EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(start_time, 0));
-  EXPECT_EQ("9999-12-31T23:59:59Z", FormatTime(end_time, 0));
-
-  // Make sure the nanoseconds part is formatted correctly.
-  EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(0, 10000000));
-  EXPECT_EQ("1970-01-01T00:00:00.000010Z", FormatTime(0, 10000));
-  EXPECT_EQ("1970-01-01T00:00:00.000000010Z", FormatTime(0, 10));
-}
-
-TEST(DateTimeTest, ParseString) {
-  int64 seconds;
-  int32 nanos;
-  ASSERT_TRUE(ParseTime("0001-01-01T00:00:00Z", &seconds, &nanos));
-  EXPECT_EQ("0001-01-01T00:00:00Z", FormatTime(seconds, nanos));
-  ASSERT_TRUE(ParseTime("9999-12-31T23:59:59.999999999Z", &seconds, &nanos));
-  EXPECT_EQ("9999-12-31T23:59:59.999999999Z", FormatTime(seconds, nanos));
-
-  // Test time zone offsets.
-  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00-08:00", &seconds, &nanos));
-  EXPECT_EQ("1970-01-01T08:00:00Z", FormatTime(seconds, nanos));
-  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00+08:00", &seconds, &nanos));
-  EXPECT_EQ("1969-12-31T16:00:00Z", FormatTime(seconds, nanos));
-
-  // Test nanoseconds.
-  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.01Z", &seconds, &nanos));
-  EXPECT_EQ("1970-01-01T00:00:00.010Z", FormatTime(seconds, nanos));
-  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00001-08:00", &seconds, &nanos));
-  EXPECT_EQ("1970-01-01T08:00:00.000010Z", FormatTime(seconds, nanos));
-  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.00000001+08:00", &seconds, &nanos));
-  EXPECT_EQ("1969-12-31T16:00:00.000000010Z", FormatTime(seconds, nanos));
-  // Fractional parts less than 1 nanosecond will be ignored.
-  ASSERT_TRUE(ParseTime("1970-01-01T00:00:00.0123456789Z", &seconds, &nanos));
-  EXPECT_EQ("1970-01-01T00:00:00.012345678Z", FormatTime(seconds, nanos));
-}
-
-}  // namespace
-}  // namespace internal
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/test_messages_proto2.proto b/src/google/protobuf/test_messages_proto2.proto
index c7b9c48..1cc7c86 100644
--- a/src/google/protobuf/test_messages_proto2.proto
+++ b/src/google/protobuf/test_messages_proto2.proto
@@ -40,6 +40,7 @@
 package protobuf_test_messages.proto2;
 
 option java_package = "com.google.protobuf_test_messages.proto2";
+option objc_class_prefix = "Proto2";
 
 // This is the default, but we specify it here explicitly.
 option optimize_for = SPEED;
@@ -195,21 +196,21 @@
   }
 
   // default values
-  optional int32 default_int32 = 241 [ default = -123456789];
-  optional int64 default_int64 = 242 [ default = -9123456789123456789];
-  optional uint32 default_uint32 = 243 [ default = 2123456789];
-  optional uint64 default_uint64 = 244 [ default = 10123456789123456789];
-  optional sint32 default_sint32 = 245 [ default = -123456789];
+  optional int32 default_int32 = 241 [default = -123456789];
+  optional int64 default_int64 = 242 [default = -9123456789123456789];
+  optional uint32 default_uint32 = 243 [default = 2123456789];
+  optional uint64 default_uint64 = 244 [default = 10123456789123456789];
+  optional sint32 default_sint32 = 245 [default = -123456789];
   optional sint64 default_sint64 = 246 [default = -9123456789123456789];
-  optional fixed32 default_fixed32 = 247 [ default = 2123456789];
-  optional fixed64 default_fixed64 = 248 [ default = 10123456789123456789];
-  optional sfixed32 default_sfixed32 = 249 [ default = -123456789];
+  optional fixed32 default_fixed32 = 247 [default = 2123456789];
+  optional fixed64 default_fixed64 = 248 [default = 10123456789123456789];
+  optional sfixed32 default_sfixed32 = 249 [default = -123456789];
   optional sfixed64 default_sfixed64 = 250 [default = -9123456789123456789];
-  optional float default_float = 251 [ default = 9e9];
-  optional double default_double = 252 [ default = 7e22];
-  optional bool default_bool = 253 [ default = true];
-  optional string default_string = 254 [ default = "Rosebud"];
-  optional bytes default_bytes = 255 [ default = "joshua"];
+  optional float default_float = 251 [default = 9e9];
+  optional double default_double = 252 [default = 7e22];
+  optional bool default_bool = 253 [default = true];
+  optional string default_string = 254 [default = "Rosebud"];
+  optional bytes default_bytes = 255 [default = "joshua"];
 
   // Test field-name-to-JSON-name convention.
   // (protobuf says names can be any valid C/C++ identifier.)
@@ -282,8 +283,7 @@
   repeated int32 repeated_int32 = 1011;
 }
 
-message NullHypothesisProto2 {
-}
+message NullHypothesisProto2 {}
 
 message EnumOnlyProto2 {
   enum Bool {
@@ -295,3 +295,9 @@
 message OneStringProto2 {
   optional string data = 1;
 }
+
+message ProtoWithKeywords {
+  optional int32 inline = 1;
+  optional string concept = 2;
+  repeated string requires = 3;
+}
diff --git a/src/google/protobuf/test_util.cc b/src/google/protobuf/test_util.cc
index 795cb6a..5fee8ff 100644
--- a/src/google/protobuf/test_util.cc
+++ b/src/google/protobuf/test_util.cc
@@ -38,7 +38,7 @@
 #include <windows.h>
 #endif
 
-#include <google/protobuf/test_util.h>
+#include "google/protobuf/test_util.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/test_util.h b/src/google/protobuf/test_util.h
index b18d7b6..5449ed6 100644
--- a/src/google/protobuf/test_util.h
+++ b/src/google/protobuf/test_util.h
@@ -35,17 +35,17 @@
 #ifndef GOOGLE_PROTOBUF_TEST_UTIL_H__
 #define GOOGLE_PROTOBUF_TEST_UTIL_H__
 
-#include <google/protobuf/unittest.pb.h>
+#include "google/protobuf/unittest.pb.h"
 
 #define UNITTEST ::protobuf_unittest
 #define UNITTEST_IMPORT ::protobuf_unittest_import
 // Must be included when the preprocessor symbols above are defined.
-#include <google/protobuf/test_util.inc>
+#include "google/protobuf/test_util.inc"
 #undef UNITTEST
 #undef UNITTEST_IMPORT
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +63,8 @@
   // the latter case, ReflectionTester searches for extension fields in
   // its file.
   explicit ReflectionTester(const Descriptor* base_descriptor);
+  ReflectionTester(const ReflectionTester&) = delete;
+  ReflectionTester& operator=(const ReflectionTester&) = delete;
 
   void SetAllFieldsViaReflection(Message* message);
   void ModifyRepeatedFieldsViaReflection(Message* message);
@@ -120,8 +122,6 @@
   void ExpectAllFieldsSetViaReflection1(const Message& message);
   void ExpectAllFieldsSetViaReflection2(const Message& message);
   void ExpectAllFieldsSetViaReflection3(const Message& message);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ReflectionTester);
 };
 
 inline TestUtil::ReflectionTester::ReflectionTester(
@@ -1223,7 +1223,7 @@
       "optional_foreign_message",
       "optional_import_message",
   };
-  for (int i = 0; i < GOOGLE_ARRAYSIZE(fields); i++) {
+  for (int i = 0; i < ABSL_ARRAYSIZE(fields); i++) {
     Message* released = reflection->ReleaseMessage(message, F(fields[i]));
     switch (expected_release_state) {
       case IS_NULL:
@@ -1272,6 +1272,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_TEST_UTIL_H__
diff --git a/src/google/protobuf/test_util.inc b/src/google/protobuf/test_util.inc
index 8d44afa..4512db2 100644
--- a/src/google/protobuf/test_util.inc
+++ b/src/google/protobuf/test_util.inc
@@ -37,11 +37,11 @@
 // within an enclosing namespace and requires header files to be included
 // out of this file.
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/message.h"
 
 namespace google {
 namespace protobuf {
@@ -1935,7 +1935,7 @@
             message.GetExtension(UNITTEST::unpacked_sfixed64_extension, 1));
   EXPECT_EQ(711, message.GetExtension(UNITTEST::unpacked_float_extension, 1));
   EXPECT_EQ(712, message.GetExtension(UNITTEST::unpacked_double_extension, 1));
-  EXPECT_EQ(false, message.GetExtension(UNITTEST::unpacked_bool_extension, 1));
+  EXPECT_FALSE(message.GetExtension(UNITTEST::unpacked_bool_extension, 1));
   EXPECT_EQ(UNITTEST::FOREIGN_BAZ,
             message.GetExtension(UNITTEST::unpacked_enum_extension, 1));
 }
diff --git a/src/google/protobuf/test_util2.h b/src/google/protobuf/test_util2.h
index 540af63..07a712c 100644
--- a/src/google/protobuf/test_util2.h
+++ b/src/google/protobuf/test_util2.h
@@ -31,27 +31,33 @@
 #ifndef GOOGLE_PROTOBUF_TEST_UTIL2_H__
 #define GOOGLE_PROTOBUF_TEST_UTIL2_H__
 
-#include <google/protobuf/stubs/strutil.h>
+#include <string>
 
-#include <google/protobuf/testing/googletest.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/util/message_differencer.h>
+#include "google/protobuf/testing/googletest.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/string_view.h"
+#include "absl/strings/strip.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/util/message_differencer.h"
 
 namespace google {
 namespace protobuf {
 namespace TestUtil {
 
-// Translate net/proto2/* -> google/protobuf/*
-inline std::string TranslatePathToOpensource(const std::string& google3_path) {
-  const std::string prefix = "net/proto2/";
-  GOOGLE_CHECK(google3_path.find(prefix) == 0) << google3_path;
-  std::string path = google3_path.substr(prefix.size());
+// Translate net/proto2/* or third_party/protobuf/* to google/protobuf/*.
+inline std::string TranslatePathToOpensource(absl::string_view google3_path) {
+  constexpr absl::string_view net_proto2 = "net/proto2/";
+  constexpr absl::string_view third_party_protobuf = "third_party/protobuf/";
+  if (!absl::ConsumePrefix(&google3_path, net_proto2)) {
+    GOOGLE_CHECK(absl::ConsumePrefix(&google3_path, third_party_protobuf))
+        << google3_path;
+  }
 
-  path = StringReplace(path, "internal/", "", false);
-  path = StringReplace(path, "proto/", "", false);
-  path = StringReplace(path, "public/", "", false);
-  return "google/protobuf/" + path;
+  absl::ConsumePrefix(&google3_path, "internal/");
+  absl::ConsumePrefix(&google3_path, "proto/");
+  absl::ConsumeSuffix(&google3_path, "public/");
+  return absl::StrCat("google/protobuf/", google3_path);
 }
 
 inline std::string MaybeTranslatePath(const std::string& google3_path) {
diff --git a/src/google/protobuf/test_util_lite.cc b/src/google/protobuf/test_util_lite.cc
index 628f1a0..f09a218 100644
--- a/src/google/protobuf/test_util_lite.cc
+++ b/src/google/protobuf/test_util_lite.cc
@@ -32,12 +32,12 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/test_util_lite.h>
+#include "google/protobuf/test_util_lite.h"
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/strutil.h>
+#include "absl/strings/string_view.h"
 
 namespace google {
 namespace protobuf {
@@ -326,7 +326,9 @@
   EXPECT_EQ(310, message.repeated_sfixed64(1));
   EXPECT_EQ(311, message.repeated_float(1));
   EXPECT_EQ(312, message.repeated_double(1));
-  EXPECT_EQ(false, message.repeated_bool(1));
+  // EXPECT_EQ(false, ...) triggers a compiler warning in some platforms.
+  //   warning: converting ‘false’ to pointer type
+  EXPECT_FALSE(message.repeated_bool(1));
   EXPECT_EQ("315", message.repeated_string(1));
   EXPECT_EQ("316", message.repeated_bytes(1));
 
@@ -376,7 +378,7 @@
   EXPECT_EQ(410, message.default_sfixed64());
   EXPECT_EQ(411, message.default_float());
   EXPECT_EQ(412, message.default_double());
-  EXPECT_EQ(false, message.default_bool());
+  EXPECT_FALSE(message.default_bool());
   EXPECT_EQ("415", message.default_string());
   EXPECT_EQ("416", message.default_bytes());
 
@@ -439,7 +441,7 @@
   EXPECT_EQ(0, message.optional_sfixed64());
   EXPECT_EQ(0, message.optional_float());
   EXPECT_EQ(0, message.optional_double());
-  EXPECT_EQ(false, message.optional_bool());
+  EXPECT_FALSE(message.optional_bool());
   EXPECT_EQ("", message.optional_string());
   EXPECT_EQ("", message.optional_bytes());
 
@@ -728,7 +730,7 @@
   EXPECT_EQ(710, message.packed_sfixed64(1));
   EXPECT_EQ(711, message.packed_float(1));
   EXPECT_EQ(712, message.packed_double(1));
-  EXPECT_EQ(false, message.packed_bool(1));
+  EXPECT_FALSE(message.packed_bool(1));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAZ, message.packed_enum(1));
 }
 
@@ -1256,8 +1258,7 @@
             message.GetExtension(unittest::repeated_float_extension_lite, 1));
   EXPECT_EQ(312,
             message.GetExtension(unittest::repeated_double_extension_lite, 1));
-  EXPECT_EQ(false,
-            message.GetExtension(unittest::repeated_bool_extension_lite, 1));
+  EXPECT_FALSE(message.GetExtension(unittest::repeated_bool_extension_lite, 1));
   EXPECT_EQ("315",
             message.GetExtension(unittest::repeated_string_extension_lite, 1));
   EXPECT_EQ("316",
@@ -1335,7 +1336,7 @@
             message.GetExtension(unittest::default_sfixed64_extension_lite));
   EXPECT_EQ(411, message.GetExtension(unittest::default_float_extension_lite));
   EXPECT_EQ(412, message.GetExtension(unittest::default_double_extension_lite));
-  EXPECT_EQ(false, message.GetExtension(unittest::default_bool_extension_lite));
+  EXPECT_FALSE(message.GetExtension(unittest::default_bool_extension_lite));
   EXPECT_EQ("415",
             message.GetExtension(unittest::default_string_extension_lite));
   EXPECT_EQ("416",
@@ -1428,8 +1429,7 @@
             message.GetExtension(unittest::optional_sfixed64_extension_lite));
   EXPECT_EQ(0, message.GetExtension(unittest::optional_float_extension_lite));
   EXPECT_EQ(0, message.GetExtension(unittest::optional_double_extension_lite));
-  EXPECT_EQ(false,
-            message.GetExtension(unittest::optional_bool_extension_lite));
+  EXPECT_FALSE(message.GetExtension(unittest::optional_bool_extension_lite));
   EXPECT_EQ("", message.GetExtension(unittest::optional_string_extension_lite));
   EXPECT_EQ("", message.GetExtension(unittest::optional_bytes_extension_lite));
 
@@ -1883,8 +1883,7 @@
             message.GetExtension(unittest::packed_float_extension_lite, 1));
   EXPECT_EQ(712,
             message.GetExtension(unittest::packed_double_extension_lite, 1));
-  EXPECT_EQ(false,
-            message.GetExtension(unittest::packed_bool_extension_lite, 1));
+  EXPECT_FALSE(message.GetExtension(unittest::packed_bool_extension_lite, 1));
   EXPECT_EQ(unittest::FOREIGN_LITE_BAZ,
             message.GetExtension(unittest::packed_enum_extension_lite, 1));
 }
diff --git a/src/google/protobuf/test_util_lite.h b/src/google/protobuf/test_util_lite.h
index 34edf94..7ed6029 100644
--- a/src/google/protobuf/test_util_lite.h
+++ b/src/google/protobuf/test_util_lite.h
@@ -35,7 +35,7 @@
 #ifndef GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
 #define GOOGLE_PROTOBUF_TEST_UTIL_LITE_H__
 
-#include <google/protobuf/unittest_lite.pb.h>
+#include "google/protobuf/unittest_lite.pb.h"
 
 namespace google {
 namespace protobuf {
@@ -45,6 +45,8 @@
 
 class TestUtilLite {
  public:
+  TestUtilLite() = delete;
+
   // Set every field in the message to a unique value.
   static void SetAllFields(unittest::TestAllTypesLite* message);
   static void SetAllExtensions(unittest::TestAllExtensionsLite* message);
@@ -90,9 +92,6 @@
   static void ExpectPackedClear(const unittest::TestPackedTypesLite& message);
   static void ExpectPackedExtensionsClear(
       const unittest::TestPackedExtensionsLite& message);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TestUtilLite);
 };
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/testing/BUILD.bazel b/src/google/protobuf/testing/BUILD.bazel
new file mode 100644
index 0000000..20e37b6
--- /dev/null
+++ b/src/google/protobuf/testing/BUILD.bazel
@@ -0,0 +1,42 @@
+# Protobuf testing support.
+#   This package contains testonly utilities used in C++ unit tests.
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("//build_defs:cpp_opts.bzl", "COPTS", "LINK_OPTS")
+
+package(default_visibility = ["//:__subpackages__"])
+
+cc_library(
+    name = "testing",
+    testonly = 1,
+    srcs = [
+        "file.cc",
+        "googletest.cc",
+    ],
+    hdrs = [
+        "file.h",
+        "googletest.h",
+    ],
+    copts = COPTS,
+    include_prefix = "google/protobuf/testing",
+    linkopts = LINK_OPTS,
+    deps = [
+        "//:protobuf_lite",  # for ShutdownProtobufLibrary
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs:lite",
+        "@com_google_absl//absl/strings",
+        "@com_google_googletest//:gtest",
+    ],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**/*"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
diff --git a/src/google/protobuf/testing/file.cc b/src/google/protobuf/testing/file.cc
index 7b62887..c4acd4b 100644
--- a/src/google/protobuf/testing/file.cc
+++ b/src/google/protobuf/testing/file.cc
@@ -31,7 +31,8 @@
 // Author: kenton@google.com (Kenton Varda)
 // emulates google3/file/base/file.cc
 
-#include <google/protobuf/testing/file.h>
+#include "google/protobuf/testing/file.h"
+
 #include <stdio.h>
 #include <sys/stat.h>
 #include <sys/types.h>
@@ -45,8 +46,8 @@
 #endif
 #include <errno.h>
 
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/stubs/logging.h>
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/stubs/logging.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/testing/file.h b/src/google/protobuf/testing/file.h
index f18f685..18348a6 100644
--- a/src/google/protobuf/testing/file.h
+++ b/src/google/protobuf/testing/file.h
@@ -34,7 +34,7 @@
 #ifndef GOOGLE_PROTOBUF_TESTING_FILE_H__
 #define GOOGLE_PROTOBUF_TESTING_FILE_H__
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
 
 namespace google {
 namespace protobuf {
@@ -45,6 +45,9 @@
 // in tests.
 class File {
  public:
+  File(const File&) = delete;
+  File& operator=(const File&) = delete;
+
   // Check if the file exists.
   static bool Exists(const std::string& name);
 
@@ -96,9 +99,6 @@
                           bool /*is_default*/) {
     return WriteStringToFile(contents, name);
   }
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(File);
 };
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/testing/googletest.cc b/src/google/protobuf/testing/googletest.cc
index 88343f9..8697e87 100644
--- a/src/google/protobuf/testing/googletest.cc
+++ b/src/google/protobuf/testing/googletest.cc
@@ -31,14 +31,17 @@
 // Author: kenton@google.com (Kenton Varda)
 // emulates google3/testing/base/public/googletest.cc
 
-#include <google/protobuf/testing/googletest.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/io/io_win32.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <sys/stat.h>
-#include <sys/types.h>
+#include "google/protobuf/testing/googletest.h"
+
 #include <errno.h>
 #include <stdlib.h>
+#include <sys/stat.h>
+#include <sys/types.h>
+
+#include "absl/strings/match.h"
+#include "absl/strings/str_replace.h"
+#include "google/protobuf/io/io_win32.h"
+#include "google/protobuf/testing/file.h"
 #ifdef _MSC_VER
 // #include <direct.h>
 #else
@@ -144,13 +147,13 @@
   }
   // On Win32, tmpnam() returns a file prefixed with '\', but which is supposed
   // to be used in the current working directory.  WTF?
-  if (HasPrefixString(result, "\\")) {
+  if (absl::StartsWith(result, "\\")) {
     result.erase(0, 1);
   }
   // The Win32 API accepts forward slashes as a path delimiter as long as the
   // path doesn't use the "\\?\" prefix.
   // Let's avoid confusion and use only forward slashes.
-  result = StringReplace(result, "\\", "/", true);
+  result = absl::StrReplaceAll(result, {{"\\", "/"}});
 #endif  // _WIN32
   return result;
 }
diff --git a/src/google/protobuf/testing/googletest.h b/src/google/protobuf/testing/googletest.h
index 6a0c694..87c8a41 100644
--- a/src/google/protobuf/testing/googletest.h
+++ b/src/google/protobuf/testing/googletest.h
@@ -34,11 +34,14 @@
 #ifndef GOOGLE_PROTOBUF_GOOGLETEST_H__
 #define GOOGLE_PROTOBUF_GOOGLETEST_H__
 
+#include <gmock/gmock.h>
+
 #include <map>
 #include <vector>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <gmock/gmock.h>
+
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+
 // Disable death tests if we use exceptions in CHECK().
 #if !PROTOBUF_USE_EXCEPTIONS && defined(GTEST_HAS_DEATH_TEST) && \
     !GTEST_OS_WINDOWS
@@ -81,6 +84,8 @@
 class ScopedMemoryLog {
  public:
   ScopedMemoryLog();
+  ScopedMemoryLog(const ScopedMemoryLog&) = delete;
+  ScopedMemoryLog& operator=(const ScopedMemoryLog&) = delete;
   virtual ~ScopedMemoryLog();
 
   // Fetches all messages with the given severity level.
@@ -94,8 +99,6 @@
                         const std::string& message);
 
   static ScopedMemoryLog* active_log_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ScopedMemoryLog);
 };
 
 }  // namespace protobuf
diff --git a/src/google/protobuf/testing/zcgunzip.cc b/src/google/protobuf/testing/zcgunzip.cc
deleted file mode 100644
index 68f8172..0000000
--- a/src/google/protobuf/testing/zcgunzip.cc
+++ /dev/null
@@ -1,84 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2009 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: brianolson@google.com (Brian Olson)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// Test program to verify that GzipInputStream is compatible with command line
-// gunzip or java.util.zip.GzipInputStream
-//
-// Reads gzip stream on standard input and writes decompressed data to standard
-// output.
-
-#include <assert.h>
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef _WIN32
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-#endif
-
-#include <google/protobuf/io/gzip_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-
-using google::protobuf::io::FileInputStream;
-using google::protobuf::io::GzipInputStream;
-
-int main(int argc, const char** argv) {
-  FileInputStream fin(STDIN_FILENO);
-  GzipInputStream in(&fin);
-
-  while (true) {
-    const void* inptr;
-    int inlen;
-    bool ok;
-    ok = in.Next(&inptr, &inlen);
-    if (!ok) {
-      break;
-    }
-    if (inlen > 0) {
-      int err = write(STDOUT_FILENO, inptr, inlen);
-      if (err != inlen) {
-        fprintf(stderr, "write unexpectedly returned %d.\n", err);
-        return 1;
-      }
-    }
-  }
-
-  return 0;
-}
diff --git a/src/google/protobuf/testing/zcgzip.cc b/src/google/protobuf/testing/zcgzip.cc
deleted file mode 100644
index 808d058..0000000
--- a/src/google/protobuf/testing/zcgzip.cc
+++ /dev/null
@@ -1,87 +0,0 @@
-// Protocol Buffers - Google's data interchange format
-// Copyright 2009 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: brianolson@google.com (Brian Olson)
-//  Based on original Protocol Buffers design by
-//  Sanjay Ghemawat, Jeff Dean, and others.
-//
-// Test program to verify that GzipOutputStream is compatible with command line
-// gzip or java.util.zip.GzipOutputStream
-//
-// Reads data on standard input and writes compressed gzip stream to standard
-// output.
-
-#include <fcntl.h>
-#include <stdio.h>
-#include <stdlib.h>
-#include <unistd.h>
-
-#ifdef _WIN32
-#ifndef STDIN_FILENO
-#define STDIN_FILENO 0
-#endif
-#ifndef STDOUT_FILENO
-#define STDOUT_FILENO 1
-#endif
-#endif
-
-#include <google/protobuf/io/gzip_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-
-using google::protobuf::io::FileOutputStream;
-using google::protobuf::io::GzipOutputStream;
-
-int main(int argc, const char** argv) {
-  FileOutputStream fout(STDOUT_FILENO);
-  GzipOutputStream out(&fout);
-  int readlen;
-
-  while (true) {
-    void* outptr;
-    int outlen;
-    bool ok;
-    do {
-      ok = out.Next(&outptr, &outlen);
-      if (!ok) {
-        break;
-      }
-    } while (outlen <= 0);
-    readlen = read(STDIN_FILENO, outptr, outlen);
-    if (readlen <= 0) {
-      out.BackUp(outlen);
-      break;
-    }
-    if (readlen < outlen) {
-      out.BackUp(outlen - readlen);
-    }
-  }
-
-  return 0;
-}
diff --git a/src/google/protobuf/text_format.cc b/src/google/protobuf/text_format.cc
index 05987d3..d6298c8 100644
--- a/src/google/protobuf/text_format.cc
+++ b/src/google/protobuf/text_format.cc
@@ -32,7 +32,7 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/text_format.h>
+#include "google/protobuf/text_format.h"
 
 #include <float.h>
 #include <stdio.h>
@@ -42,29 +42,34 @@
 #include <climits>
 #include <cmath>
 #include <limits>
+#include <set>
+#include <string>
 #include <utility>
 #include <vector>
 
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/tokenizer.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/any.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/strtod.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/strings/ascii.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/numbers.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_join.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/any.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/map_field.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -87,6 +92,12 @@
 const char kDebugStringSilentMarker[] = "";
 const char kDebugStringSilentMarkerForDetection[] = "\t ";
 
+// Controls insertion of a marker making debug strings non-parseable.
+PROTOBUF_EXPORT std::atomic<bool> enable_debug_text_redaction_marker;
+
+// Controls insertion of a randomized marker in debug strings.
+PROTOBUF_EXPORT std::atomic<bool> enable_debug_text_random_marker;
+
 // Controls insertion of kDebugStringSilentMarker.
 PROTOBUF_EXPORT std::atomic<bool> enable_debug_text_format_marker;
 }  // namespace internal
@@ -98,6 +109,12 @@
   printer.SetExpandAny(true);
   printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load(
       std::memory_order_relaxed));
+  printer.SetRedactDebugString(
+      internal::enable_debug_text_redaction_marker.load(
+          std::memory_order_relaxed));
+  printer.SetRandomizeDebugString(
+      internal::enable_debug_text_random_marker.load(
+          std::memory_order_relaxed));
 
   printer.PrintToString(*this, &debug_string);
 
@@ -112,6 +129,12 @@
   printer.SetExpandAny(true);
   printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load(
       std::memory_order_relaxed));
+  printer.SetRedactDebugString(
+      internal::enable_debug_text_redaction_marker.load(
+          std::memory_order_relaxed));
+  printer.SetRandomizeDebugString(
+      internal::enable_debug_text_random_marker.load(
+          std::memory_order_relaxed));
 
   printer.PrintToString(*this, &debug_string);
   // Single line mode currently might have an extra space at the end.
@@ -130,6 +153,12 @@
   printer.SetExpandAny(true);
   printer.SetInsertSilentMarker(internal::enable_debug_text_format_marker.load(
       std::memory_order_relaxed));
+  printer.SetRedactDebugString(
+      internal::enable_debug_text_redaction_marker.load(
+          std::memory_order_relaxed));
+  printer.SetRandomizeDebugString(
+      internal::enable_debug_text_random_marker.load(
+          std::memory_order_relaxed));
 
   printer.PrintToString(*this, &debug_string);
 
@@ -138,6 +167,23 @@
 
 void Message::PrintDebugString() const { printf("%s", DebugString().c_str()); }
 
+namespace internal {
+
+void PerformAbslStringify(const Message& message,
+                          absl::FunctionRef<void(absl::string_view)> append) {
+  // TODO(b/249835002): consider using the single line version for short
+  TextFormat::Printer printer;
+  printer.SetExpandAny(true);
+  printer.SetInsertSilentMarker(true);
+  printer.SetRedactDebugString(true);
+  printer.SetRandomizeDebugString(true);
+  std::string result;
+  printer.PrintToString(message, &result);
+  append(result);
+}
+
+}  // namespace internal
+
 
 // ===========================================================================
 // Implementation of the parse information tree class.
@@ -175,14 +221,13 @@
     index = 0;
   }
 
-  const std::vector<TextFormat::ParseLocationRange>* locations =
-      FindOrNull(locations_, field);
-  if (locations == nullptr ||
-      index >= static_cast<int64_t>(locations->size())) {
+  auto it = locations_.find(field);
+  if (it == locations_.end() ||
+      index >= static_cast<int64_t>(it->second.size())) {
     return TextFormat::ParseLocationRange();
   }
 
-  return (*locations)[index];
+  return it->second[static_cast<size_t>(index)];
 }
 
 TextFormat::ParseInfoTree* TextFormat::ParseInfoTree::GetTreeForNested(
@@ -197,7 +242,7 @@
     return nullptr;
   }
 
-  return it->second[index].get();
+  return it->second[static_cast<size_t>(index)].get();
 }
 
 namespace {
@@ -229,7 +274,7 @@
 // ===========================================================================
 // Internal class for parsing an ASCII representation of a Protocol Message.
 // This class makes use of the Protocol Message compiler's tokenizer found
-// in //net/proto2/io/public/tokenizer.h. Note that class's Parse
+// in //third_party/protobuf/io/tokenizer.h. Note that class's Parse
 // method is *not* thread-safe and should only be used in a single thread at
 // a time.
 
@@ -294,6 +339,8 @@
     // Consume the starting token.
     tokenizer_.Next();
   }
+  ParserImpl(const ParserImpl&) = delete;
+  ParserImpl& operator=(const ParserImpl&) = delete;
   ~ParserImpl() {}
 
   // Parses the ASCII representation specified in input and saves the
@@ -368,8 +415,6 @@
   static constexpr int64_t kint64max = std::numeric_limits<int64_t>::max();
   static constexpr uint64_t kuint64max = std::numeric_limits<uint64_t>::max();
 
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserImpl);
-
   // Reports an error with the given message with information indicating
   // the position (as derived from the current token).
   void ReportError(const std::string& message) {
@@ -429,7 +474,7 @@
       std::string full_type_name, prefix;
       DO(ConsumeAnyTypeUrl(&full_type_name, &prefix));
       std::string prefix_and_full_type_name =
-          StrCat(prefix, full_type_name);
+          absl::StrCat(prefix, full_type_name);
       DO(ConsumeBeforeWhitespace("]"));
       TryConsumeWhitespace();
       // ':' is optional between message labels and values.
@@ -489,7 +534,7 @@
       TryConsumeWhitespace();
 
       int32_t field_number;
-      if (allow_field_number_ && safe_strto32(field_name, &field_number)) {
+      if (allow_field_number_ && absl::SimpleAtoi(field_name, &field_number)) {
         if (descriptor->IsExtensionNumber(field_number)) {
           field = finder_
                       ? finder_->FindExtensionByNumber(descriptor, field_number)
@@ -507,7 +552,7 @@
         // field names.
         if (field == nullptr) {
           std::string lower_field_name = field_name;
-          LowerString(&lower_field_name);
+          absl::AsciiStrToLower(&lower_field_name);
           field = descriptor->FindFieldByName(lower_field_name);
           // If the case-insensitive match worked but the field is NOT a group,
           if (field != nullptr &&
@@ -523,7 +568,7 @@
 
         if (field == nullptr && allow_case_insensitive_field_) {
           std::string lower_field_name = field_name;
-          LowerString(&lower_field_name);
+          absl::AsciiStrToLower(&lower_field_name);
           field = descriptor->FindFieldByLowercaseName(lower_field_name);
         }
 
@@ -563,6 +608,11 @@
       return SkipFieldMessage();
     }
 
+    if (field->options().deprecated()) {
+      ReportWarning("text format contains deprecated field \"" + field_name +
+                    "\"");
+    }
+
     if (singular_overwrite_policy_ == FORBID_SINGULAR_OVERWRITES) {
       // Fail if the field is not repeated and it has already been specified.
       if (!field->is_repeated() && reflection->HasField(*message, field)) {
@@ -638,11 +688,6 @@
     // semicolons.
     TryConsume(";") || TryConsume(",");
 
-    if (field->options().deprecated()) {
-      ReportWarning("text format contains deprecated field \"" + field_name +
-                    "\"");
-    }
-
     // If a parse info tree exists, add the location for the parsed
     // field.
     if (parse_info_tree_ != nullptr) {
@@ -695,7 +740,7 @@
                            const FieldDescriptor* field) {
     if (--recursion_limit_ < 0) {
       ReportError(
-          StrCat("Message is too deep, the parser exceeded the "
+          absl::StrCat("Message is too deep, the parser exceeded the "
                        "configured recursion limit of ",
                        initial_recursion_limit_, "."));
       return false;
@@ -731,7 +776,7 @@
   bool SkipFieldMessage() {
     if (--recursion_limit_ < 0) {
       ReportError(
-          StrCat("Message is too deep, the parser exceeded the "
+          absl::StrCat("Message is too deep, the parser exceeded the "
                        "configured recursion limit of ",
                        initial_recursion_limit_, "."));
       return false;
@@ -845,7 +890,7 @@
         } else if (LookingAt("-") ||
                    LookingAtType(io::Tokenizer::TYPE_INTEGER)) {
           DO(ConsumeSignedInteger(&int_value, kint32max));
-          value = StrCat(int_value);  // for error reporting
+          value = absl::StrCat(int_value);  // for error reporting
           enum_value = enum_type->FindValueByNumber(int_value);
         } else {
           ReportError("Expected integer or identifier, got: " +
@@ -891,7 +936,7 @@
   bool SkipFieldValue() {
     if (--recursion_limit_ < 0) {
       ReportError(
-          StrCat("Message is too deep, the parser exceeded the "
+          absl::StrCat("Message is too deep, the parser exceeded the "
                        "configured recursion limit of ",
                        initial_recursion_limit_, "."));
       return false;
@@ -905,16 +950,18 @@
       return true;
     }
     if (TryConsume("[")) {
-      while (true) {
-        if (!LookingAt("{") && !LookingAt("<")) {
-          DO(SkipFieldValue());
-        } else {
-          DO(SkipFieldMessage());
+      if (!TryConsume("]")) {
+        while (true) {
+          if (!LookingAt("{") && !LookingAt("<")) {
+            DO(SkipFieldValue());
+          } else {
+            DO(SkipFieldMessage());
+          }
+          if (TryConsume("]")) {
+            break;
+          }
+          DO(Consume(","));
         }
-        if (TryConsume("]")) {
-          break;
-        }
-        DO(Consume(","));
       }
       ++recursion_limit_;
       return true;
@@ -957,7 +1004,7 @@
     //   inf, inff, infinity, nan
     if (has_minus && LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
       std::string text = tokenizer_.current().text;
-      LowerString(&text);
+      absl::AsciiStrToLower(&text);
       if (text != "inf" &&
           text != "infinity" && text != "nan") {
         ReportError("Invalid float number: " + text);
@@ -1162,7 +1209,7 @@
       tokenizer_.Next();
     } else if (LookingAtType(io::Tokenizer::TYPE_IDENTIFIER)) {
       std::string text = tokenizer_.current().text;
-      LowerString(&text);
+      absl::AsciiStrToLower(&text);
       if (text == "inf" ||
           text == "infinity") {
         *value = std::numeric_limits<double>::infinity();
@@ -1284,7 +1331,7 @@
     had_silent_marker_ = false;
     if (LookingAtType(io::Tokenizer::TYPE_WHITESPACE)) {
       if (tokenizer_.current().text ==
-          StrCat(" ", internal::kDebugStringSilentMarkerForDetection)) {
+          absl::StrCat(" ", internal::kDebugStringSilentMarkerForDetection)) {
         had_silent_marker_ = true;
       }
       tokenizer_.Next();
@@ -1300,6 +1347,8 @@
     explicit ParserErrorCollector(TextFormat::Parser::ParserImpl* parser)
         : parser_(parser) {}
 
+    ParserErrorCollector(const ParserErrorCollector&) = delete;
+    ParserErrorCollector& operator=(const ParserErrorCollector&) = delete;
     ~ParserErrorCollector() override {}
 
     void AddError(int line, int column, const std::string& message) override {
@@ -1311,7 +1360,6 @@
     }
 
    private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ParserErrorCollector);
     TextFormat::Parser::ParserImpl* parser_;
   };
 
@@ -1336,7 +1384,7 @@
 
 // ===========================================================================
 // Internal class for writing text to the io::ZeroCopyOutputStream. Adapted
-// from the Printer found in //net/proto2/io/public/printer.h
+// from the Printer found in //third_party/protobuf/io/printer.h
 class TextFormat::Printer::TextGenerator
     : public TextFormat::BaseTextGenerator {
  public:
@@ -1362,6 +1410,8 @@
         indent_level_(initial_indent_level),
         initial_indent_level_(initial_indent_level) {}
 
+  TextGenerator(const TextGenerator&) = delete;
+  TextGenerator& operator=(const TextGenerator&) = delete;
   ~TextGenerator() override {
     // Only BackUp() if we're sure we've successfully called Next() at least
     // once.
@@ -1421,15 +1471,15 @@
   // error.)
   bool failed() const { return failed_; }
 
-  void PrintMaybeWithMarker(StringPiece text) {
+  void PrintMaybeWithMarker(MarkerToken, absl::string_view text) override {
     Print(text.data(), text.size());
     if (ConsumeInsertSilentMarker()) {
       PrintLiteral(internal::kDebugStringSilentMarker);
     }
   }
 
-  void PrintMaybeWithMarker(StringPiece text_head,
-                            StringPiece text_tail) {
+  void PrintMaybeWithMarker(MarkerToken, absl::string_view text_head,
+                            absl::string_view text_tail) override {
     Print(text_head.data(), text_head.size());
     if (ConsumeInsertSilentMarker()) {
       PrintLiteral(internal::kDebugStringSilentMarker);
@@ -1438,8 +1488,6 @@
   }
 
  private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextGenerator);
-
   void Write(const char* data, size_t size) {
     if (failed_) return;
     if (size == 0) return;
@@ -1530,13 +1578,10 @@
   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(" ", "{ ");
+      generator->PrintMaybeWithMarker(MarkerToken(), " ", "{ ");
     } else {
-      text_generator->PrintMaybeWithMarker(" ", "{\n");
+      generator->PrintMaybeWithMarker(MarkerToken(), " ", "{\n");
     }
   }
 };
@@ -1549,7 +1594,7 @@
   void PrintString(const std::string& val,
                    TextFormat::BaseTextGenerator* generator) const override {
     generator->PrintLiteral("\"");
-    generator->PrintString(strings::Utf8SafeCEscape(val));
+    generator->PrintString(absl::Utf8SafeCEscape(val));
     generator->PrintLiteral("\"");
   }
   void PrintBytes(const std::string& val,
@@ -1603,12 +1648,12 @@
 
 namespace {
 
-bool CheckParseInputSize(StringPiece input,
+bool CheckParseInputSize(absl::string_view input,
                          io::ErrorCollector* error_collector) {
   if (input.size() > INT_MAX) {
     error_collector->AddError(
         -1, 0,
-        StrCat(
+        absl::StrCat(
             "Input size too large: ", static_cast<int64_t>(input.size()),
             " bytes", " > ", INT_MAX, " bytes."));
     return false;
@@ -1635,7 +1680,7 @@
   return MergeUsingImpl(input, output, &parser);
 }
 
-bool TextFormat::Parser::ParseFromString(ConstStringParam input,
+bool TextFormat::Parser::ParseFromString(absl::string_view input,
                                          Message* output) {
   DO(CheckParseInputSize(input, error_collector_));
   io::ArrayInputStream input_stream(input.data(), input.size());
@@ -1653,7 +1698,7 @@
   return MergeUsingImpl(input, output, &parser);
 }
 
-bool TextFormat::Parser::MergeFromString(ConstStringParam input,
+bool TextFormat::Parser::MergeFromString(absl::string_view input,
                                          Message* output) {
   DO(CheckParseInputSize(input, error_collector_));
   io::ArrayInputStream input_stream(input.data(), input.size());
@@ -1669,7 +1714,7 @@
     output->FindInitializationErrors(&missing_fields);
     parser_impl->ReportError(-1, 0,
                              "Message missing required fields: " +
-                                 Join(missing_fields, ", "));
+                                 absl::StrJoin(missing_fields, ", "));
     return false;
   }
   return true;
@@ -1698,12 +1743,12 @@
   return Parser().Merge(input, output);
 }
 
-/* static */ bool TextFormat::ParseFromString(ConstStringParam input,
+/* static */ bool TextFormat::ParseFromString(absl::string_view input,
                                               Message* output) {
   return Parser().ParseFromString(input, output);
 }
 
-/* static */ bool TextFormat::MergeFromString(ConstStringParam input,
+/* static */ bool TextFormat::MergeFromString(absl::string_view input,
                                               Message* output) {
   return Parser().MergeFromString(input, output);
 }
@@ -1723,13 +1768,7 @@
     output_.append(text, size);
   }
 
-// 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
   std::string Consume() && { return std::move(output_); }
-#else  // !LANG_CXX11
-  const std::string& Get() { return output_; }
-#endif  // LANG_CXX11
 
  private:
   std::string output_;
@@ -1743,17 +1782,10 @@
 TextFormat::FieldValuePrinter::FieldValuePrinter() {}
 TextFormat::FieldValuePrinter::~FieldValuePrinter() {}
 
-#if 0  // LANG_CXX11
 #define FORWARD_IMPL(fn, ...)            \
   StringBaseTextGenerator generator;     \
   delegate_.fn(__VA_ARGS__, &generator); \
   return std::move(generator).Consume()
-#else  // !LANG_CXX11
-#define FORWARD_IMPL(fn, ...)            \
-  StringBaseTextGenerator generator;     \
-  delegate_.fn(__VA_ARGS__, &generator); \
-  return generator.Get()
-#endif  // LANG_CXX11
 
 std::string TextFormat::FieldValuePrinter::PrintBool(bool val) const {
   FORWARD_IMPL(PrintBool, val);
@@ -1819,27 +1851,27 @@
 }
 void TextFormat::FastFieldValuePrinter::PrintInt32(
     int32_t val, BaseTextGenerator* generator) const {
-  generator->PrintString(StrCat(val));
+  generator->PrintString(absl::StrCat(val));
 }
 void TextFormat::FastFieldValuePrinter::PrintUInt32(
     uint32_t val, BaseTextGenerator* generator) const {
-  generator->PrintString(StrCat(val));
+  generator->PrintString(absl::StrCat(val));
 }
 void TextFormat::FastFieldValuePrinter::PrintInt64(
     int64_t val, BaseTextGenerator* generator) const {
-  generator->PrintString(StrCat(val));
+  generator->PrintString(absl::StrCat(val));
 }
 void TextFormat::FastFieldValuePrinter::PrintUInt64(
     uint64_t val, BaseTextGenerator* generator) const {
-  generator->PrintString(StrCat(val));
+  generator->PrintString(absl::StrCat(val));
 }
 void TextFormat::FastFieldValuePrinter::PrintFloat(
     float val, BaseTextGenerator* generator) const {
-  generator->PrintString(!std::isnan(val) ? SimpleFtoa(val) : "nan");
+  generator->PrintString(!std::isnan(val) ? io::SimpleFtoa(val) : "nan");
 }
 void TextFormat::FastFieldValuePrinter::PrintDouble(
     double val, BaseTextGenerator* generator) const {
-  generator->PrintString(!std::isnan(val) ? SimpleDtoa(val) : "nan");
+  generator->PrintString(!std::isnan(val) ? io::SimpleDtoa(val) : "nan");
 }
 void TextFormat::FastFieldValuePrinter::PrintEnum(
     int32_t /*val*/, const std::string& name,
@@ -1850,7 +1882,7 @@
 void TextFormat::FastFieldValuePrinter::PrintString(
     const std::string& val, BaseTextGenerator* generator) const {
   generator->PrintLiteral("\"");
-  generator->PrintString(CEscape(val));
+  generator->PrintString(absl::CEscape(val));
   generator->PrintLiteral("\"");
 }
 void TextFormat::FastFieldValuePrinter::PrintBytes(
@@ -1997,6 +2029,8 @@
       use_field_number_(false),
       use_short_repeated_primitives_(false),
       insert_silent_marker_(false),
+      redact_debug_string_(false),
+      randomize_debug_string_(false),
       hide_unknown_fields_(false),
       print_message_fields_in_index_order_(false),
       expand_any_(false),
@@ -2089,6 +2123,13 @@
                                 io::ZeroCopyOutputStream* output) const {
   TextGenerator generator(output, insert_silent_marker_, initial_indent_level_);
 
+#ifndef PROTO2_OPENSOURCE
+#ifdef SUPPORT_EXPLICIT_DEBUG_STRING
+  internal::PrintTextMarker(&generator, redact_debug_string_,
+                            randomize_debug_string_, single_line_mode_);
+#endif
+#endif
+
   Print(message, &generator);
 
   // Output false if the generator failed internally.
@@ -2131,7 +2172,7 @@
 }  // namespace
 
 bool TextFormat::Printer::PrintAny(const Message& message,
-                                   TextGenerator* generator) const {
+                                   BaseTextGenerator* generator) const {
   const FieldDescriptor* type_url_field;
   const FieldDescriptor* value_field;
   if (!internal::GetAnyFieldDescriptors(message, &type_url_field,
@@ -2179,7 +2220,7 @@
 }
 
 void TextFormat::Printer::Print(const Message& message,
-                                TextGenerator* generator) const {
+                                BaseTextGenerator* generator) const {
   const Reflection* reflection = message.GetReflection();
   if (!reflection) {
     // This message does not provide any way to describe its structure.
@@ -2199,10 +2240,20 @@
     itr->second->Print(message, single_line_mode_, generator);
     return;
   }
+  PrintMessage(message, generator);
+}
+
+void TextFormat::Printer::PrintMessage(const Message& message,
+                                       BaseTextGenerator* generator) const {
+  if (generator == nullptr) {
+    return;
+  }
+  const Descriptor* descriptor = message.GetDescriptor();
   if (descriptor->full_name() == internal::kAnyFullTypeName && expand_any_ &&
       PrintAny(message, generator)) {
     return;
   }
+  const Reflection* reflection = message.GetReflection();
   std::vector<const FieldDescriptor*> fields;
   if (descriptor->options().map_entry()) {
     fields.push_back(descriptor->field(0));
@@ -2417,7 +2468,7 @@
 void TextFormat::Printer::PrintField(const Message& message,
                                      const Reflection* reflection,
                                      const FieldDescriptor* field,
-                                     TextGenerator* generator) const {
+                                     BaseTextGenerator* generator) const {
   if (use_short_repeated_primitives_ && field->is_repeated() &&
       field->cpp_type() != FieldDescriptor::CPPTYPE_STRING &&
       field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
@@ -2465,7 +2516,7 @@
       printer->PrintMessageEnd(sub_message, field_index, count,
                                single_line_mode_, generator);
     } else {
-      generator->PrintMaybeWithMarker(": ");
+      generator->PrintMaybeWithMarker(MarkerToken(), ": ");
       // Write the field value.
       PrintFieldValue(message, reflection, field, field_index, generator);
       if (single_line_mode_) {
@@ -2485,12 +2536,12 @@
 
 void TextFormat::Printer::PrintShortRepeatedField(
     const Message& message, const Reflection* reflection,
-    const FieldDescriptor* field, TextGenerator* generator) const {
+    const FieldDescriptor* field, BaseTextGenerator* generator) const {
   // Print primitive repeated field in short form.
   int size = reflection->FieldSize(message, field);
   PrintFieldName(message, /*field_index=*/-1, /*field_count=*/size, reflection,
                  field, generator);
-  generator->PrintMaybeWithMarker(": ", "[");
+  generator->PrintMaybeWithMarker(MarkerToken(), ": ", "[");
   for (int i = 0; i < size; i++) {
     if (i > 0) generator->PrintLiteral(", ");
     PrintFieldValue(message, reflection, field, i, generator);
@@ -2506,11 +2557,11 @@
                                          int field_index, int field_count,
                                          const Reflection* reflection,
                                          const FieldDescriptor* field,
-                                         TextGenerator* generator) const {
+                                         BaseTextGenerator* generator) const {
   // if use_field_number_ is true, prints field number instead
   // of field name.
   if (use_field_number_) {
-    generator->PrintString(StrCat(field->number()));
+    generator->PrintString(absl::StrCat(field->number()));
     return;
   }
 
@@ -2523,11 +2574,20 @@
                                           const Reflection* reflection,
                                           const FieldDescriptor* field,
                                           int index,
-                                          TextGenerator* generator) const {
+                                          BaseTextGenerator* generator) const {
   GOOGLE_DCHECK(field->is_repeated() || (index == -1))
       << "Index must be -1 for non-repeated fields";
 
   const FastFieldValuePrinter* printer = GetFieldPrinter(field);
+#ifndef PROTO2_OPENSOURCE
+#ifdef SUPPORT_EXPLICIT_DEBUG_STRING
+  if (redact_debug_string_ && internal::ShouldRedactField(field)) {
+    std::string redacted_value = "go/redact-debug-string";
+    generator->PrintString(redacted_value);
+    return;
+  }
+#endif
+#endif
 
   switch (field->cpp_type()) {
 #define OUTPUT_FIELD(CPPTYPE, METHOD)                                \
@@ -2589,7 +2649,7 @@
         // it is possible for the user to force an unknown integer value.  So we
         // simply use the integer value itself as the enum value name in this
         // case.
-        printer->PrintEnum(enum_value, StrCat(enum_value), generator);
+        printer->PrintEnum(enum_value, absl::StrCat(enum_value), generator);
       }
       break;
     }
@@ -2635,17 +2695,17 @@
 }
 
 void TextFormat::Printer::PrintUnknownFields(
-    const UnknownFieldSet& unknown_fields, TextGenerator* generator,
+    const UnknownFieldSet& unknown_fields, BaseTextGenerator* generator,
     int recursion_budget) const {
   for (int i = 0; i < unknown_fields.field_count(); i++) {
     const UnknownField& field = unknown_fields.field(i);
-    std::string field_number = StrCat(field.number());
+    std::string field_number = absl::StrCat(field.number());
 
     switch (field.type()) {
       case UnknownField::TYPE_VARINT:
         generator->PrintString(field_number);
-        generator->PrintMaybeWithMarker(": ");
-        generator->PrintString(StrCat(field.varint()));
+        generator->PrintMaybeWithMarker(MarkerToken(), ": ");
+        generator->PrintString(absl::StrCat(field.varint()));
         if (single_line_mode_) {
           generator->PrintLiteral(" ");
         } else {
@@ -2654,9 +2714,9 @@
         break;
       case UnknownField::TYPE_FIXED32: {
         generator->PrintString(field_number);
-        generator->PrintMaybeWithMarker(": ", "0x");
+        generator->PrintMaybeWithMarker(MarkerToken(), ": ", "0x");
         generator->PrintString(
-            StrCat(strings::Hex(field.fixed32(), strings::ZERO_PAD_8)));
+            absl::StrCat(absl::Hex(field.fixed32(), absl::kZeroPad8)));
         if (single_line_mode_) {
           generator->PrintLiteral(" ");
         } else {
@@ -2666,9 +2726,9 @@
       }
       case UnknownField::TYPE_FIXED64: {
         generator->PrintString(field_number);
-        generator->PrintMaybeWithMarker(": ", "0x");
+        generator->PrintMaybeWithMarker(MarkerToken(), ": ", "0x");
         generator->PrintString(
-            StrCat(strings::Hex(field.fixed64(), strings::ZERO_PAD_16)));
+            absl::StrCat(absl::Hex(field.fixed64(), absl::kZeroPad16)));
         if (single_line_mode_) {
           generator->PrintLiteral(" ");
         } else {
@@ -2691,9 +2751,9 @@
           // This field is parseable as a Message.
           // So it is probably an embedded message.
           if (single_line_mode_) {
-            generator->PrintMaybeWithMarker(" ", "{ ");
+            generator->PrintMaybeWithMarker(MarkerToken(), " ", "{ ");
           } else {
-            generator->PrintMaybeWithMarker(" ", "{\n");
+            generator->PrintMaybeWithMarker(MarkerToken(), " ", "{\n");
             generator->Indent();
           }
           PrintUnknownFields(embedded_unknown_fields, generator,
@@ -2707,8 +2767,8 @@
         } 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->PrintMaybeWithMarker(": ", "\"");
-          generator->PrintString(CEscape(value));
+          generator->PrintMaybeWithMarker(MarkerToken(), ": ", "\"");
+          generator->PrintString(absl::CEscape(value));
           if (single_line_mode_) {
             generator->PrintLiteral("\" ");
           } else {
@@ -2720,9 +2780,9 @@
       case UnknownField::TYPE_GROUP:
         generator->PrintString(field_number);
         if (single_line_mode_) {
-          generator->PrintMaybeWithMarker(" ", "{ ");
+          generator->PrintMaybeWithMarker(MarkerToken(), " ", "{ ");
         } else {
-          generator->PrintMaybeWithMarker(" ", "{\n");
+          generator->PrintMaybeWithMarker(MarkerToken(), " ", "{\n");
           generator->Indent();
         }
         // For groups, we recurse without checking the budget. This is OK,
@@ -2743,4 +2803,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/text_format.h b/src/google/protobuf/text_format.h
index e10bef7..2cd4024 100644
--- a/src/google/protobuf/text_format.h
+++ b/src/google/protobuf/text_format.h
@@ -39,19 +39,22 @@
 #define GOOGLE_PROTOBUF_TEXT_FORMAT_H__
 
 
+#include <atomic>
 #include <map>
 #include <memory>
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/message_lite.h>
+#include "google/protobuf/port.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/port.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -63,6 +66,11 @@
 namespace internal {
 PROTOBUF_EXPORT extern const char kDebugStringSilentMarker[1];
 PROTOBUF_EXPORT extern const char kDebugStringSilentMarkerForDetection[3];
+
+PROTOBUF_EXPORT extern std::atomic<bool> enable_debug_text_redaction_marker;
+PROTOBUF_EXPORT extern std::atomic<bool> enable_debug_text_random_marker;
+PROTOBUF_EXPORT extern std::atomic<bool> enable_debug_text_format_marker;
+
 }  // namespace internal
 
 namespace io {
@@ -76,6 +84,9 @@
 // This class is really a namespace that contains only static methods.
 class PROTOBUF_EXPORT TextFormat {
  public:
+  TextFormat(const TextFormat&) = delete;
+  TextFormat& operator=(const TextFormat&) = delete;
+
   // Outputs a textual representation of the given message to the given
   // output stream. Returns false if printing fails.
   static bool Print(const Message& message, io::ZeroCopyOutputStream* output);
@@ -104,7 +115,22 @@
                                       const FieldDescriptor* field, int index,
                                       std::string* output);
 
+  // Forward declare `Printer` for `BaseTextGenerator::MarkerToken` which
+  // restricts some methods of `BaseTextGenerator` to the class `Printer`.
+  class Printer;
+
   class PROTOBUF_EXPORT BaseTextGenerator {
+   private:
+    // Passkey (go/totw/134#what-about-stdshared-ptr) that allows `Printer`
+    // (but not derived classes) to call `PrintMaybeWithMarker` and its
+    // `Printer::TextGenerator` to overload it.
+    // This prevents users from bypassing the marker generation.
+    class MarkerToken {
+     private:
+      explicit MarkerToken() = default;  // 'explicit' prevents aggregate init.
+      friend class Printer;
+    };
+
    public:
     virtual ~BaseTextGenerator();
 
@@ -122,6 +148,20 @@
     void PrintLiteral(const char (&text)[n]) {
       Print(text, n - 1);  // n includes the terminating zero character.
     }
+
+    // Internal to Printer, access regulated by `MarkerToken`.
+    virtual void PrintMaybeWithMarker(MarkerToken, absl::string_view text) {
+      Print(text.data(), text.size());
+    }
+
+    // Internal to Printer, access regulated by `MarkerToken`.
+    virtual void PrintMaybeWithMarker(MarkerToken, absl::string_view text_head,
+                                      absl::string_view text_tail) {
+      Print(text_head.data(), text_head.size());
+      Print(text_tail.data(), text_tail.size());
+    }
+
+    friend class Printer;
   };
 
   // The default printer that converts scalar values from fields into their
@@ -131,6 +171,8 @@
   class PROTOBUF_EXPORT FastFieldValuePrinter {
    public:
     FastFieldValuePrinter();
+    FastFieldValuePrinter(const FastFieldValuePrinter&) = delete;
+    FastFieldValuePrinter& operator=(const FastFieldValuePrinter&) = delete;
     virtual ~FastFieldValuePrinter();
     virtual void PrintBool(bool val, BaseTextGenerator* generator) const;
     virtual void PrintInt32(int32_t val, BaseTextGenerator* generator) const;
@@ -167,15 +209,14 @@
     virtual void PrintMessageEnd(const Message& message, int field_index,
                                  int field_count, bool single_line_mode,
                                  BaseTextGenerator* generator) const;
-
-   private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FastFieldValuePrinter);
   };
 
   // Deprecated: please use FastFieldValuePrinter instead.
   class PROTOBUF_EXPORT FieldValuePrinter {
    public:
     FieldValuePrinter();
+    FieldValuePrinter(const FieldValuePrinter&) = delete;
+    FieldValuePrinter& operator=(const FieldValuePrinter&) = delete;
     virtual ~FieldValuePrinter();
     virtual std::string PrintBool(bool val) const;
     virtual std::string PrintInt32(int32_t val) const;
@@ -199,18 +240,16 @@
 
    private:
     FastFieldValuePrinter delegate_;
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldValuePrinter);
   };
 
   class PROTOBUF_EXPORT MessagePrinter {
    public:
     MessagePrinter() {}
+    MessagePrinter(const MessagePrinter&) = delete;
+    MessagePrinter& operator=(const MessagePrinter&) = delete;
     virtual ~MessagePrinter() {}
     virtual void Print(const Message& message, bool single_line_mode,
                        BaseTextGenerator* generator) const = 0;
-
-   private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessagePrinter);
   };
 
   // Interface that Printers or Parsers can use to find extensions, or types
@@ -371,17 +410,38 @@
     bool RegisterMessagePrinter(const Descriptor* descriptor,
                                 const MessagePrinter* printer);
 
+    // Default printing for messages, which allows registered message printers
+    // to fall back to default printing without losing the ability to control
+    // sub-messages or fields.
+    // NOTE: If the passed in `text_generaor` is not actually the current
+    // `TextGenerator`, then no output will be produced.
+    void PrintMessage(const Message& message,
+                      BaseTextGenerator* generator) const;
+
    private:
     friend std::string Message::DebugString() const;
     friend std::string Message::ShortDebugString() const;
     friend std::string Message::Utf8DebugString() const;
+    friend void internal::PerformAbslStringify(
+        const Message& message,
+        absl::FunctionRef<void(absl::string_view)> append);
 
-    // Sets whether *DebugString should insert a silent marker.
+    // Sets whether silent markers will be inserted.
     void SetInsertSilentMarker(bool v) { insert_silent_marker_ = v; }
 
+    // Sets whether strings will be redacted and thus unparsable.
+    void SetRedactDebugString(bool redact) { redact_debug_string_ = redact; }
+
+    // Sets whether the output string should be made non-deterministic.
+    // This discourages equality checks based on serialized string comparisons.
+    void SetRandomizeDebugString(bool randomize) {
+      randomize_debug_string_ = randomize;
+    }
+
     // Forward declaration of an internal class used to print the text
     // output to the OutputStream (see text_format.cc for implementation).
     class TextGenerator;
+    using MarkerToken = BaseTextGenerator::MarkerToken;
 
     // Forward declaration of an internal class used to print field values for
     // DebugString APIs (see text_format.cc for implementation).
@@ -395,40 +455,40 @@
 
     // Internal Print method, used for writing to the OutputStream via
     // the TextGenerator class.
-    void Print(const Message& message, TextGenerator* generator) const;
+    void Print(const Message& message, BaseTextGenerator* generator) const;
 
     // Print a single field.
     void PrintField(const Message& message, const Reflection* reflection,
                     const FieldDescriptor* field,
-                    TextGenerator* generator) const;
+                    BaseTextGenerator* generator) const;
 
     // Print a repeated primitive field in short form.
     void PrintShortRepeatedField(const Message& message,
                                  const Reflection* reflection,
                                  const FieldDescriptor* field,
-                                 TextGenerator* generator) const;
+                                 BaseTextGenerator* generator) const;
 
     // Print the name of a field -- i.e. everything that comes before the
     // ':' for a single name/value pair.
     void PrintFieldName(const Message& message, int field_index,
                         int field_count, const Reflection* reflection,
                         const FieldDescriptor* field,
-                        TextGenerator* generator) const;
+                        BaseTextGenerator* generator) const;
 
     // Outputs a textual representation of the value of the field supplied on
     // the message supplied or the default value if not set.
     void PrintFieldValue(const Message& message, const Reflection* reflection,
                          const FieldDescriptor* field, int index,
-                         TextGenerator* generator) const;
+                         BaseTextGenerator* generator) const;
 
     // Print the fields in an UnknownFieldSet.  They are printed by tag number
     // only.  Embedded messages are heuristically identified by attempting to
     // parse them (subject to the recursion budget).
     void PrintUnknownFields(const UnknownFieldSet& unknown_fields,
-                            TextGenerator* generator,
+                            BaseTextGenerator* generator,
                             int recursion_budget) const;
 
-    bool PrintAny(const Message& message, TextGenerator* generator) const;
+    bool PrintAny(const Message& message, BaseTextGenerator* generator) const;
 
     const FastFieldValuePrinter* GetFieldPrinter(
         const FieldDescriptor* field) const {
@@ -442,6 +502,8 @@
     bool use_field_number_;
     bool use_short_repeated_primitives_;
     bool insert_silent_marker_;
+    bool redact_debug_string_;
+    bool randomize_debug_string_;
     bool hide_unknown_fields_;
     bool print_message_fields_in_index_order_;
     bool expand_any_;
@@ -476,13 +538,13 @@
   // google::protobuf::MessageLite::ParseFromString().
   static bool Parse(io::ZeroCopyInputStream* input, Message* output);
   // Like Parse(), but reads directly from a string.
-  static bool ParseFromString(ConstStringParam input, Message* output);
+  static bool ParseFromString(absl::string_view 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(ConstStringParam input, Message* output);
+  static bool MergeFromString(absl::string_view 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,
@@ -571,11 +633,11 @@
     // Like TextFormat::Parse().
     bool Parse(io::ZeroCopyInputStream* input, Message* output);
     // Like TextFormat::ParseFromString().
-    bool ParseFromString(ConstStringParam input, Message* output);
+    bool ParseFromString(absl::string_view input, Message* output);
     // Like TextFormat::Merge().
     bool Merge(io::ZeroCopyInputStream* input, Message* output);
     // Like TextFormat::MergeFromString().
-    bool MergeFromString(ConstStringParam input, Message* output);
+    bool MergeFromString(absl::string_view input, Message* output);
 
     // Set where to report parse errors.  If nullptr (the default), errors will
     // be printed to stderr.
@@ -670,10 +732,9 @@
                                     ParseLocationRange location);
   static inline ParseInfoTree* CreateNested(ParseInfoTree* info_tree,
                                             const FieldDescriptor* field);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TextFormat);
 };
 
+
 inline void TextFormat::RecordLocation(ParseInfoTree* info_tree,
                                        const FieldDescriptor* field,
                                        ParseLocationRange location) {
@@ -688,6 +749,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_TEXT_FORMAT_H__
diff --git a/src/google/protobuf/text_format_unittest.cc b/src/google/protobuf/text_format_unittest.cc
index 126f2f3..1bca2df 100644
--- a/src/google/protobuf/text_format_unittest.cc
+++ b/src/google/protobuf/text_format_unittest.cc
@@ -32,7 +32,7 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/text_format.h>
+#include "google/protobuf/text_format.h"
 
 #include <math.h>
 #include <stdlib.h>
@@ -40,44 +40,45 @@
 #include <atomic>
 #include <limits>
 #include <memory>
+#include <string>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/testing/file.h>
-#include <google/protobuf/any.pb.h>
-#include <google/protobuf/map_unittest.pb.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_mset.pb.h>
-#include <google/protobuf/unittest_mset_wire_format.pb.h>
-#include <google/protobuf/unittest_proto3.pb.h>
-#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/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/testing/file.h"
+#include "google/protobuf/any.pb.h"
 #include <gmock/gmock.h>
-#include <google/protobuf/testing/googletest.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/test_util.h>
-#include <google/protobuf/test_util2.h>
+#include "google/protobuf/stubs/logging.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/strings/str_replace.h"
+#include "absl/strings/substitute.h"
+#include "google/protobuf/io/tokenizer.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/map_unittest.pb.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"
+#include "google/protobuf/unittest_proto3.pb.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 
-namespace internal {
-// Controls insertion of DEBUG_STRING_SILENT_MARKER.
-extern PROTOBUF_EXPORT std::atomic<bool> enable_debug_text_format_marker;
-}  // namespace internal
-
 // Can't use an anonymous namespace here due to brokenness of Tru64 compiler.
 namespace text_format_unittest {
 
 using ::google::protobuf::internal::kDebugStringSilentMarker;
+using ::testing::AllOf;
+using ::testing::HasSubstr;
 
 // A basic string with different escapable characters for testing.
 const std::string kEscapeTestString =
@@ -94,10 +95,9 @@
   static void SetUpTestSuite() {
     GOOGLE_CHECK_OK(File::GetContents(
         TestUtil::GetTestDataPath(
-            "net/proto2/internal/"
+            "third_party/protobuf/"
             "testdata/text_format_unittest_data_oneof_implemented.txt"),
         &static_proto_text_format_, true));
-    CleanStringLineEndings(&static_proto_text_format_, false);
   }
 
   TextFormatTest() : proto_text_format_(static_proto_text_format_) {}
@@ -116,10 +116,9 @@
  public:
   static void SetUpTestSuite() {
     GOOGLE_CHECK_OK(File::GetContents(
-        TestUtil::GetTestDataPath("net/proto2/internal/testdata/"
+        TestUtil::GetTestDataPath("third_party/protobuf/testdata/"
                                   "text_format_unittest_extensions_data.txt"),
         &static_proto_text_format_, true));
-    CleanStringLineEndings(&static_proto_text_format_, false);
   }
 
   TextFormatExtensionsTest() : proto_text_format_(static_proto_text_format_) {}
@@ -155,13 +154,14 @@
   proto_.mutable_optional_foreign_message();
 
   EXPECT_EQ(proto_.ShortDebugString(),
-            StrCat("optional_int32: ", kDebugStringSilentMarker,
+            absl::StrCat("optional_int32: ", kDebugStringSilentMarker,
                          "1 "
                          "optional_string: \"hello\" "
                          "optional_nested_message { bb: 2 } "
                          "optional_foreign_message { }"));
 }
 
+
 TEST_F(TextFormatTest, ShortPrimitiveRepeateds) {
   proto_.set_optional_int32(123);
   proto_.add_repeated_int32(456);
@@ -229,7 +229,7 @@
 
   // Hardcode a correct value to test against.
   std::string correct_string =
-      StrCat("optional_string: ", kDebugStringSilentMarker,
+      absl::StrCat("optional_string: ", kDebugStringSilentMarker,
                    kEscapeTestStringEscaped, "\n");
 
   // Compare.
@@ -238,7 +238,7 @@
   // the protocol buffer contains no UTF-8 text.
   EXPECT_EQ(correct_string, utf8_debug_string);
 
-  std::string expected_short_debug_string = StrCat(
+  std::string expected_short_debug_string = absl::StrCat(
       "optional_string: ", kDebugStringSilentMarker, kEscapeTestStringEscaped);
   EXPECT_EQ(expected_short_debug_string, proto_.ShortDebugString());
 }
@@ -254,11 +254,11 @@
 
   // Hardcode a correct value to test against.
   std::string correct_utf8_string =
-      StrCat("optional_string: ", kDebugStringSilentMarker,
+      absl::StrCat("optional_string: ", kDebugStringSilentMarker,
                    "\"\350\260\267\346\255\214\"\n"
                    "optional_bytes: \"\\350\\260\\267\\346\\255\\214\"\n");
   std::string correct_string =
-      StrCat("optional_string: ", kDebugStringSilentMarker,
+      absl::StrCat("optional_string: ", kDebugStringSilentMarker,
                    "\"\\350\\260\\267\\346\\255\\214\"\n"
                    "optional_bytes: \"\\350\\260\\267\\346\\255\\214\"\n");
 
@@ -283,7 +283,7 @@
   unknown_fields->AddVarint(8, 2);
   unknown_fields->AddVarint(8, 3);
 
-  EXPECT_EQ(StrCat("5: ", kDebugStringSilentMarker,
+  EXPECT_EQ(absl::StrCat("5: ", kDebugStringSilentMarker,
                          "1\n"
                          "5: 0x00000002\n"
                          "5: 0x0000000000000003\n"
@@ -459,7 +459,7 @@
 class CustomUInt32FieldValuePrinter : public TextFormat::FieldValuePrinter {
  public:
   std::string PrintUInt32(uint32_t val) const override {
-    return StrCat(FieldValuePrinter::PrintUInt32(val), "u");
+    return absl::StrCat(FieldValuePrinter::PrintUInt32(val), "u");
   }
 };
 
@@ -483,7 +483,7 @@
 class CustomInt32FieldValuePrinter : public TextFormat::FieldValuePrinter {
  public:
   std::string PrintInt32(int32_t val) const override {
-    return StrCat("value-is(", FieldValuePrinter::PrintInt32(val), ")");
+    return absl::StrCat("value-is(", FieldValuePrinter::PrintInt32(val), ")");
   }
 };
 
@@ -534,8 +534,8 @@
 class CustomMessageFieldValuePrinter : public TextFormat::FieldValuePrinter {
  public:
   std::string PrintInt32(int32_t v) const override {
-    return StrCat(FieldValuePrinter::PrintInt32(v), "  # x",
-                        strings::Hex(v));
+    return absl::StrCat(FieldValuePrinter::PrintInt32(v), "  # x",
+                        absl::Hex(v));
   }
 
   std::string PrintMessageStart(const Message& message, int field_index,
@@ -544,7 +544,7 @@
     if (single_line_mode) {
       return " { ";
     }
-    return StrCat(" {  # ", message.GetDescriptor()->name(), ": ",
+    return absl::StrCat(" {  # ", message.GetDescriptor()->name(), ": ",
                         field_index, "\n");
   }
 };
@@ -590,7 +590,7 @@
       TextFormat::BaseTextGenerator* generator) const override {
     if (message.ByteSizeLong() > 0) {
       generator->PrintString(
-          strings::Substitute("# REDACTED, $0 bytes\n", message.ByteSizeLong()));
+          absl::Substitute("# REDACTED, $0 bytes\n", message.ByteSizeLong()));
     }
     return true;
   }
@@ -634,7 +634,7 @@
   std::string PrintMessageStart(const Message& message, int field_index,
                                 int field_count,
                                 bool single_line_comment) const override {
-    return StrCat(" {  # 1\n", "  # 2\n");
+    return absl::StrCat(" {  # 1\n", "  # 2\n");
   }
 };
 
@@ -780,15 +780,24 @@
   ~CustomNestedMessagePrinter() override {}
   void Print(const Message& message, bool single_line_mode,
              TextFormat::BaseTextGenerator* generator) const override {
-    generator->PrintLiteral("custom");
+    generator->PrintLiteral("// custom\n");
+    if (printer_ != nullptr) {
+      printer_->PrintMessage(message, generator);
+    }
   }
+
+  void SetPrinter(TextFormat::Printer* printer) { printer_ = printer; }
+
+ private:
+  TextFormat::Printer* printer_ = nullptr;
 };
 
 TEST_F(TextFormatTest, CustomMessagePrinter) {
   TextFormat::Printer printer;
+  auto* custom_printer = new CustomNestedMessagePrinter;
   printer.RegisterMessagePrinter(
       unittest::TestAllTypes::NestedMessage::default_instance().descriptor(),
-      new CustomNestedMessagePrinter);
+      custom_printer);
 
   unittest::TestAllTypes message;
   std::string text;
@@ -797,7 +806,11 @@
 
   message.mutable_optional_nested_message()->set_bb(1);
   EXPECT_TRUE(printer.PrintToString(message, &text));
-  EXPECT_EQ("optional_nested_message {\n  custom}\n", text);
+  EXPECT_EQ("optional_nested_message {\n  // custom\n}\n", text);
+
+  custom_printer->SetPrinter(&printer);
+  EXPECT_TRUE(printer.PrintToString(message, &text));
+  EXPECT_EQ("optional_nested_message {\n  // custom\n  bb: 1\n}\n", text);
 }
 
 TEST_F(TextFormatTest, ParseBasic) {
@@ -817,7 +830,7 @@
 TEST_F(TextFormatTest, ParseEnumFieldFromNumber) {
   // Create a parse string with a numerical value for an enum field.
   std::string parse_string =
-      strings::Substitute("optional_nested_enum: $0", unittest::TestAllTypes::BAZ);
+      absl::Substitute("optional_nested_enum: $0", unittest::TestAllTypes::BAZ);
   EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto_));
   EXPECT_TRUE(proto_.has_optional_nested_enum());
   EXPECT_EQ(unittest::TestAllTypes::BAZ, proto_.optional_nested_enum());
@@ -826,7 +839,7 @@
 TEST_F(TextFormatTest, ParseEnumFieldFromNegativeNumber) {
   ASSERT_LT(unittest::SPARSE_E, 0);
   std::string parse_string =
-      strings::Substitute("sparse_enum: $0", unittest::SPARSE_E);
+      absl::Substitute("sparse_enum: $0", unittest::SPARSE_E);
   unittest::SparseEnumMessage proto;
   EXPECT_TRUE(TextFormat::ParseFromString(parse_string, &proto));
   EXPECT_TRUE(proto.has_sparse_enum());
@@ -845,7 +858,7 @@
   proto.add_repeated_nested_enum(
       static_cast<proto3_unittest::TestAllTypes::NestedEnum>(-2147483648));
 
-  EXPECT_EQ(StrCat("repeated_nested_enum: ", kDebugStringSilentMarker,
+  EXPECT_EQ(absl::StrCat("repeated_nested_enum: ", kDebugStringSilentMarker,
                          "10\n"
                          "repeated_nested_enum: -10\n"
                          "repeated_nested_enum: 2147483647\n"
@@ -1035,6 +1048,19 @@
   EXPECT_EQ(4, proto_.repeatedgroup(1).a());
 }
 
+TEST_F(TextFormatTest, ParseShortRepeatedUnknownEmpty) {
+  std::string parse_string =
+      "repeated_string: \"before\"\n"
+      "unknown_field: []\n"
+      "repeated_string: \"after\"\n";
+  TextFormat::Parser parser;
+  parser.AllowUnknownField(true);
+
+  ASSERT_TRUE(parser.ParseFromString(parse_string, &proto_));
+
+  EXPECT_EQ(2, proto_.repeated_string_size());
+}
+
 
 TEST_F(TextFormatTest, Comments) {
   // Test that comments are ignored.
@@ -1069,10 +1095,8 @@
 
 // Some platforms (e.g. Windows) insist on padding the exponent to three
 // digits when one or two would be just fine.
-static std::string RemoveRedundantZeros(std::string text) {
-  text = StringReplace(text, "e+0", "e+", true);
-  text = StringReplace(text, "e-0", "e-", true);
-  return text;
+static std::string RemoveRedundantZeros(absl::string_view text) {
+  return absl::StrReplaceAll(text, {{"e+0", "e+"}, {"e-0", "e-"}});
 }
 
 TEST_F(TextFormatTest, PrintExotic) {
@@ -1103,7 +1127,7 @@
   //   have this problem, so we switched to that instead.
 
   EXPECT_EQ(
-      StrCat("repeated_int64: ", kDebugStringSilentMarker,
+      absl::StrCat("repeated_int64: ", kDebugStringSilentMarker,
                    "-9223372036854775808\n"
                    "repeated_uint64: 18446744073709551615\n"
                    "repeated_double: 123.456\n"
@@ -1163,7 +1187,7 @@
   message.add_repeated_double(1.2345678987654e100);
   message.add_repeated_double(1.23456789876543e100);
 
-  EXPECT_EQ(StrCat("repeated_float: ", kDebugStringSilentMarker,
+  EXPECT_EQ(absl::StrCat("repeated_float: ", kDebugStringSilentMarker,
                          "1\n"
                          "repeated_float: 1.2\n"
                          "repeated_float: 1.23\n"
@@ -1401,7 +1425,7 @@
     parser_.RecordErrorsTo(&error_collector);
     EXPECT_EQ(expected_result, parser_.ParseFromString(input, proto))
         << input << " -> " << proto->DebugString();
-    EXPECT_EQ(StrCat(line, ":", col, ": ", message, "\n"),
+    EXPECT_EQ(absl::StrCat(line, ":", col, ": ", message, "\n"),
               error_collector.text_);
     parser_.RecordErrorsTo(nullptr);
   }
@@ -1442,7 +1466,7 @@
 
     // implements ErrorCollector -------------------------------------
     void AddError(int line, int column, const std::string& message) override {
-      strings::SubstituteAndAppend(&text_, "$0:$1: $2\n", line + 1, column + 1,
+      absl::SubstituteAndAppend(&text_, "$0:$1: $2\n", line + 1, column + 1,
                                 message);
     }
 
@@ -1636,7 +1660,7 @@
   // enum
   EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAR, "BAR");
   EXPECT_FIELD(nested_enum, unittest::TestAllTypes::BAZ,
-               StrCat(unittest::TestAllTypes::BAZ));
+               absl::StrCat(unittest::TestAllTypes::BAZ));
   EXPECT_INVALID(nested_enum, "FOOBAR");
 
   // message
@@ -1898,18 +1922,22 @@
   ExpectMessage("deprecated_int32: 42",
                 "WARNING:text format contains deprecated field "
                 "\"deprecated_int32\"",
-                1, 21, &message, true);
+                1, 17, &message, true);
+  ExpectMessage("deprecated_message {\n#blah\n#blah\n#blah\n}\n",
+                "WARNING:text format contains deprecated field "
+                "\"deprecated_message\"",
+                1, 20, &message, true);
 }
 
 TEST_F(TextFormatParserTest, SetRecursionLimit) {
   const char* format = "child: { $0 }";
   std::string input;
-  for (int i = 0; i < 100; ++i) input = strings::Substitute(format, input);
+  for (int i = 0; i < 100; ++i) input = absl::Substitute(format, input);
 
   unittest::NestedTestAllTypes message;
   ExpectSuccessAndTree(input, &message, nullptr);
 
-  input = strings::Substitute(format, input);
+  input = absl::Substitute(format, input);
   parser_.SetRecursionLimit(100);
   ExpectMessage(input,
                 "Message is too deep, the parser exceeded the configured "
@@ -1923,8 +1951,8 @@
 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);
+  for (int i = 0; i < 99; ++i) input = absl::Substitute(format, input);
+  std::string not_deep_input = absl::StrCat("unknown_nested_array: ", input);
 
   parser_.AllowUnknownField(true);
   parser_.SetRecursionLimit(100);
@@ -1932,8 +1960,8 @@
   unittest::NestedTestAllTypes message;
   ExpectSuccessAndTree(not_deep_input, &message, nullptr);
 
-  input = strings::Substitute(format, input);
-  std::string deep_input = StrCat("unknown_nested_array: ", input);
+  input = absl::Substitute(format, input);
+  std::string deep_input = absl::StrCat("unknown_nested_array: ", input);
   ExpectMessage(
       deep_input,
       "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no "
@@ -1948,7 +1976,7 @@
 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);
+  for (int i = 0; i < 100; ++i) input = absl::Substitute(format, input);
 
   parser_.AllowUnknownField(true);
   parser_.SetRecursionLimit(100);
@@ -1956,7 +1984,7 @@
   unittest::NestedTestAllTypes message;
   ExpectSuccessAndTree(input, &message, nullptr);
 
-  input = strings::Substitute(format, input);
+  input = absl::Substitute(format, input);
   ExpectMessage(
       input,
       "WARNING:Message type \"protobuf_unittest.NestedTestAllTypes\" has no "
@@ -2277,4 +2305,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/timestamp.pb.cc b/src/google/protobuf/timestamp.pb.cc
index 728a004..a64dbc0 100644
--- a/src/google/protobuf/timestamp.pb.cc
+++ b/src/google/protobuf/timestamp.pb.cc
@@ -1,88 +1,112 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/timestamp.proto
 
-#include <google/protobuf/timestamp.pb.h>
+#include "google/protobuf/timestamp.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR Timestamp::Timestamp(
     ::_pbi::ConstantInitialized): _impl_{
-    /*decltype(_impl_.seconds_)*/int64_t{0}
+    /*decltype(_impl_.seconds_)*/::int64_t{0}
   , /*decltype(_impl_.nanos_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct TimestampDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR TimestampDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR TimestampDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~TimestampDefaultTypeInternal() {}
   union {
     Timestamp _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TimestampDefaultTypeInternal _Timestamp_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TimestampDefaultTypeInternal _Timestamp_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2ftimestamp_2eproto[1];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _impl_.seconds_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _impl_.nanos_),
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2ftimestamp_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _impl_.seconds_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Timestamp, _impl_.nanos_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Timestamp)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Timestamp)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Timestamp_default_instance_._instance,
 };
-
-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\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once;
+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\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2ftimestamp_2eproto = {
-    false, false, 239, descriptor_table_protodef_google_2fprotobuf_2ftimestamp_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2ftimestamp_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2ftimestamp_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2ftimestamp_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftimestamp_2eproto(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftimestamp_2eproto(&descriptor_table_google_2fprotobuf_2ftimestamp_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 class Timestamp::_Internal {
@@ -96,17 +120,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Timestamp)
 }
 Timestamp::Timestamp(const Timestamp& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  Timestamp* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.seconds_){}
-    , decltype(_impl_.nanos_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  ::memcpy(&_impl_.seconds_, &from._impl_.seconds_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.nanos_) -
-    reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_));
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Timestamp)
 }
 
@@ -115,7 +131,7 @@
   (void)arena;
   (void)is_message_owned;
   new (&_impl_) Impl_{
-      decltype(_impl_.seconds_){int64_t{0}}
+      decltype(_impl_.seconds_){::int64_t{0}}
     , decltype(_impl_.nanos_){0}
     , /*decltype(_impl_._cached_size_)*/{}
   };
@@ -140,37 +156,40 @@
 
 void Timestamp::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Timestamp)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  ::memset(&_impl_.seconds_, 0, static_cast<size_t>(
+  ::memset(&_impl_.seconds_, 0, static_cast<::size_t>(
       reinterpret_cast<char*>(&_impl_.nanos_) -
       reinterpret_cast<char*>(&_impl_.seconds_)) + sizeof(_impl_.nanos_));
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Timestamp::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // int64 seconds = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _impl_.seconds_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // int32 nanos = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _impl_.nanos_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -195,10 +214,11 @@
 #undef CHK_
 }
 
-uint8_t* Timestamp::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Timestamp::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Timestamp)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // int64 seconds = 1;
@@ -221,11 +241,12 @@
   return target;
 }
 
-size_t Timestamp::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp)
-  size_t total_size = 0;
+::size_t Timestamp::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Timestamp)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -252,9 +273,10 @@
 void Timestamp::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Timestamp*>(&to_msg);
   auto& from = static_cast<const Timestamp&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Timestamp)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (from._internal_seconds() != 0) {
@@ -289,11 +311,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Timestamp::GetMetadata() const {
+
   return ::_pbi::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
@@ -302,6 +324,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Timestamp >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/timestamp.pb.h b/src/google/protobuf/timestamp.pb.h
index b55d0a4..7ddb84c 100644
--- a/src/google/protobuf/timestamp.pb.h
+++ b/src/google/protobuf/timestamp.pb.h
@@ -1,38 +1,43 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/timestamp.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftimestamp_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -41,21 +46,25 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftimestamp_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct TimestampDefaultTypeInternal;
 PROTOBUF_EXPORT extern TimestampDefaultTypeInternal _Timestamp_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Timestamp* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Timestamp>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Timestamp* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Timestamp>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT Timestamp final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Timestamp) */ {
  public:
@@ -145,10 +154,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -159,7 +168,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Timestamp";
   }
   protected:
@@ -182,20 +191,20 @@
   };
   // int64 seconds = 1;
   void clear_seconds();
-  int64_t seconds() const;
-  void set_seconds(int64_t value);
+  ::int64_t seconds() const;
+  void set_seconds(::int64_t value);
   private:
-  int64_t _internal_seconds() const;
-  void _internal_set_seconds(int64_t value);
+  ::int64_t _internal_seconds() const;
+  void _internal_set_seconds(::int64_t value);
   public:
 
   // int32 nanos = 2;
   void clear_nanos();
-  int32_t nanos() const;
-  void set_nanos(int32_t value);
+  ::int32_t nanos() const;
+  void set_nanos(::int32_t value);
   private:
-  int32_t _internal_nanos() const;
-  void _internal_set_nanos(int32_t value);
+  ::int32_t _internal_nanos() const;
+  void _internal_set_nanos(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.Timestamp)
@@ -206,8 +215,8 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   struct Impl_ {
-    int64_t seconds_;
-    int32_t nanos_;
+    ::int64_t seconds_;
+    ::int32_t nanos_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
@@ -216,30 +225,35 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // Timestamp
 
 // int64 seconds = 1;
 inline void Timestamp::clear_seconds() {
-  _impl_.seconds_ = int64_t{0};
+  _impl_.seconds_ = ::int64_t{0};
 }
-inline int64_t Timestamp::_internal_seconds() const {
+inline ::int64_t Timestamp::_internal_seconds() const {
   return _impl_.seconds_;
 }
-inline int64_t Timestamp::seconds() const {
+inline ::int64_t Timestamp::seconds() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.seconds)
   return _internal_seconds();
 }
-inline void Timestamp::_internal_set_seconds(int64_t value) {
-  
+inline void Timestamp::_internal_set_seconds(::int64_t value) {
+
   _impl_.seconds_ = value;
 }
-inline void Timestamp::set_seconds(int64_t value) {
+inline void Timestamp::set_seconds(::int64_t value) {
   _internal_set_seconds(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.seconds)
 }
@@ -248,31 +262,32 @@
 inline void Timestamp::clear_nanos() {
   _impl_.nanos_ = 0;
 }
-inline int32_t Timestamp::_internal_nanos() const {
+inline ::int32_t Timestamp::_internal_nanos() const {
   return _impl_.nanos_;
 }
-inline int32_t Timestamp::nanos() const {
+inline ::int32_t Timestamp::nanos() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Timestamp.nanos)
   return _internal_nanos();
 }
-inline void Timestamp::_internal_set_nanos(int32_t value) {
-  
+inline void Timestamp::_internal_set_nanos(::int32_t value) {
+
   _impl_.nanos_ = value;
 }
-inline void Timestamp::set_nanos(int32_t value) {
+inline void Timestamp::set_nanos(::int32_t value) {
   _internal_set_nanos(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Timestamp.nanos)
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftimestamp_2eproto_2epb_2eh
diff --git a/src/google/protobuf/timestamp.proto b/src/google/protobuf/timestamp.proto
index 3b2df6d..2fb527c 100644
--- a/src/google/protobuf/timestamp.proto
+++ b/src/google/protobuf/timestamp.proto
@@ -32,13 +32,13 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
 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;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 
 // 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
@@ -90,7 +90,6 @@
 //     Timestamp timestamp = Timestamp.newBuilder().setSeconds(millis / 1000)
 //         .setNanos((int) ((millis % 1000) * 1000000)).build();
 //
-//
 // Example 5: Compute Timestamp from Java `Instant.now()`.
 //
 //     Instant now = Instant.now();
@@ -99,7 +98,6 @@
 //         Timestamp.newBuilder().setSeconds(now.getEpochSecond())
 //             .setNanos(now.getNano()).build();
 //
-//
 // Example 6: Compute Timestamp from current time in Python.
 //
 //     timestamp = Timestamp()
@@ -132,7 +130,6 @@
 // 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.
 //
-//
 message Timestamp {
   // Represents seconds of UTC time since Unix epoch
   // 1970-01-01T00:00:00Z. Must be from 0001-01-01T00:00:00Z to
diff --git a/src/google/protobuf/type.pb.cc b/src/google/protobuf/type.pb.cc
index e29bbb8..d1faed9 100644
--- a/src/google/protobuf/type.pb.cc
+++ b/src/google/protobuf/type.pb.cc
@@ -1,25 +1,23 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/type.proto
 
-#include <google/protobuf/type.pb.h>
+#include "google/protobuf/type.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR Type::Type(
     ::_pbi::ConstantInitialized): _impl_{
@@ -31,14 +29,15 @@
   , /*decltype(_impl_.syntax_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct TypeDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR TypeDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR TypeDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~TypeDefaultTypeInternal() {}
   union {
     Type _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeDefaultTypeInternal _Type_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 TypeDefaultTypeInternal _Type_default_instance_;
 PROTOBUF_CONSTEXPR Field::Field(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.options_)*/{}
@@ -53,14 +52,15 @@
   , /*decltype(_impl_.packed_)*/false
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct FieldDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FieldDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FieldDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FieldDefaultTypeInternal() {}
   union {
     Field _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldDefaultTypeInternal _Field_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FieldDefaultTypeInternal _Field_default_instance_;
 PROTOBUF_CONSTEXPR Enum::Enum(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.enumvalue_)*/{}
@@ -70,14 +70,15 @@
   , /*decltype(_impl_.syntax_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct EnumDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EnumDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EnumDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EnumDefaultTypeInternal() {}
   union {
     Enum _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDefaultTypeInternal _Enum_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumDefaultTypeInternal _Enum_default_instance_;
 PROTOBUF_CONSTEXPR EnumValue::EnumValue(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.options_)*/{}
@@ -85,168 +86,204 @@
   , /*decltype(_impl_.number_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct EnumValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR EnumValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR EnumValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~EnumValueDefaultTypeInternal() {}
   union {
     EnumValue _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueDefaultTypeInternal _EnumValue_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 EnumValueDefaultTypeInternal _EnumValue_default_instance_;
 PROTOBUF_CONSTEXPR Option::Option(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.name_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_.value_)*/nullptr
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct OptionDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR OptionDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR OptionDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~OptionDefaultTypeInternal() {}
   union {
     Option _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OptionDefaultTypeInternal _Option_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 OptionDefaultTypeInternal _Option_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2ftype_2eproto[5];
 static const ::_pb::EnumDescriptor* file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[3];
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2ftype_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.fields_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.oneofs_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.source_context_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.syntax_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.kind_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.cardinality_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.number_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.type_url_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.oneof_index_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.packed_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.json_name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.default_value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.enumvalue_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.options_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.source_context_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.syntax_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.number_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.options_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _impl_.name_),
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _impl_.value_),
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2ftype_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.fields_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.oneofs_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.source_context_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Type, _impl_.syntax_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.kind_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.cardinality_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.number_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.type_url_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.oneof_index_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.packed_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.json_name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Field, _impl_.default_value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.enumvalue_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.options_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.source_context_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Enum, _impl_.syntax_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.number_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::EnumValue, _impl_.options_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _impl_.name_),
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Option, _impl_.value_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Type)},
-  { 12, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Field)},
-  { 28, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Enum)},
-  { 39, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValue)},
-  { 48, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Option)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Type)},
+        { 14, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Field)},
+        { 32, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Enum)},
+        { 45, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::EnumValue)},
+        { 56, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Option)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_Type_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Field_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Enum_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_EnumValue_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Option_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Type_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Field_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Enum_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_EnumValue_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Option_default_instance_._instance,
 };
-
-const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
-  "\n\032google/protobuf/type.proto\022\017google.pro"
-  "tobuf\032\031google/protobuf/any.proto\032$google"
-  "/protobuf/source_context.proto\"\327\001\n\004Type\022"
-  "\014\n\004name\030\001 \001(\t\022&\n\006fields\030\002 \003(\0132\026.google.p"
-  "rotobuf.Field\022\016\n\006oneofs\030\003 \003(\t\022(\n\007options"
-  "\030\004 \003(\0132\027.google.protobuf.Option\0226\n\016sourc"
-  "e_context\030\005 \001(\0132\036.google.protobuf.Source"
-  "Context\022\'\n\006syntax\030\006 \001(\0162\027.google.protobu"
-  "f.Syntax\"\325\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.googl"
-  "e.protobuf.Field.Kind\0227\n\013cardinality\030\002 \001"
-  "(\0162\".google.protobuf.Field.Cardinality\022\016"
-  "\n\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url"
-  "\030\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 "
-  "\001(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.O"
-  "ption\022\021\n\tjson_name\030\n \001(\t\022\025\n\rdefault_valu"
-  "e\030\013 \001(\t\"\310\002\n\004Kind\022\020\n\014TYPE_UNKNOWN\020\000\022\017\n\013TY"
-  "PE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT6"
-  "4\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014"
-  "TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE"
-  "_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n"
-  "\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TY"
-  "PE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXE"
-  "D32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020"
-  "\021\022\017\n\013TYPE_SINT64\020\022\"t\n\013Cardinality\022\027\n\023CAR"
-  "DINALITY_UNKNOWN\020\000\022\030\n\024CARDINALITY_OPTION"
-  "AL\020\001\022\030\n\024CARDINALITY_REQUIRED\020\002\022\030\n\024CARDIN"
-  "ALITY_REPEATED\020\003\"\316\001\n\004Enum\022\014\n\004name\030\001 \001(\t\022"
-  "-\n\tenumvalue\030\002 \003(\0132\032.google.protobuf.Enu"
-  "mValue\022(\n\007options\030\003 \003(\0132\027.google.protobu"
-  "f.Option\0226\n\016source_context\030\004 \001(\0132\036.googl"
-  "e.protobuf.SourceContext\022\'\n\006syntax\030\005 \001(\016"
-  "2\027.google.protobuf.Syntax\"S\n\tEnumValue\022\014"
-  "\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\022(\n\007options\030"
-  "\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/proto"
-  "buf/types/known/typepb\370\001\001\242\002\003GPB\252\002\036Google"
-  ".Protobuf.WellKnownTypesb\006proto3"
-  ;
-static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2ftype_2eproto_deps[2] = {
-  &::descriptor_table_google_2fprotobuf_2fany_2eproto,
-  &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
+const char descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+    "\n\032google/protobuf/type.proto\022\017google.pro"
+    "tobuf\032\031google/protobuf/any.proto\032$google"
+    "/protobuf/source_context.proto\"\327\001\n\004Type\022"
+    "\014\n\004name\030\001 \001(\t\022&\n\006fields\030\002 \003(\0132\026.google.p"
+    "rotobuf.Field\022\016\n\006oneofs\030\003 \003(\t\022(\n\007options"
+    "\030\004 \003(\0132\027.google.protobuf.Option\0226\n\016sourc"
+    "e_context\030\005 \001(\0132\036.google.protobuf.Source"
+    "Context\022\'\n\006syntax\030\006 \001(\0162\027.google.protobu"
+    "f.Syntax\"\325\005\n\005Field\022)\n\004kind\030\001 \001(\0162\033.googl"
+    "e.protobuf.Field.Kind\0227\n\013cardinality\030\002 \001"
+    "(\0162\".google.protobuf.Field.Cardinality\022\016"
+    "\n\006number\030\003 \001(\005\022\014\n\004name\030\004 \001(\t\022\020\n\010type_url"
+    "\030\006 \001(\t\022\023\n\013oneof_index\030\007 \001(\005\022\016\n\006packed\030\010 "
+    "\001(\010\022(\n\007options\030\t \003(\0132\027.google.protobuf.O"
+    "ption\022\021\n\tjson_name\030\n \001(\t\022\025\n\rdefault_valu"
+    "e\030\013 \001(\t\"\310\002\n\004Kind\022\020\n\014TYPE_UNKNOWN\020\000\022\017\n\013TY"
+    "PE_DOUBLE\020\001\022\016\n\nTYPE_FLOAT\020\002\022\016\n\nTYPE_INT6"
+    "4\020\003\022\017\n\013TYPE_UINT64\020\004\022\016\n\nTYPE_INT32\020\005\022\020\n\014"
+    "TYPE_FIXED64\020\006\022\020\n\014TYPE_FIXED32\020\007\022\r\n\tTYPE"
+    "_BOOL\020\010\022\017\n\013TYPE_STRING\020\t\022\016\n\nTYPE_GROUP\020\n"
+    "\022\020\n\014TYPE_MESSAGE\020\013\022\016\n\nTYPE_BYTES\020\014\022\017\n\013TY"
+    "PE_UINT32\020\r\022\r\n\tTYPE_ENUM\020\016\022\021\n\rTYPE_SFIXE"
+    "D32\020\017\022\021\n\rTYPE_SFIXED64\020\020\022\017\n\013TYPE_SINT32\020"
+    "\021\022\017\n\013TYPE_SINT64\020\022\"t\n\013Cardinality\022\027\n\023CAR"
+    "DINALITY_UNKNOWN\020\000\022\030\n\024CARDINALITY_OPTION"
+    "AL\020\001\022\030\n\024CARDINALITY_REQUIRED\020\002\022\030\n\024CARDIN"
+    "ALITY_REPEATED\020\003\"\316\001\n\004Enum\022\014\n\004name\030\001 \001(\t\022"
+    "-\n\tenumvalue\030\002 \003(\0132\032.google.protobuf.Enu"
+    "mValue\022(\n\007options\030\003 \003(\0132\027.google.protobu"
+    "f.Option\0226\n\016source_context\030\004 \001(\0132\036.googl"
+    "e.protobuf.SourceContext\022\'\n\006syntax\030\005 \001(\016"
+    "2\027.google.protobuf.Syntax\"S\n\tEnumValue\022\014"
+    "\n\004name\030\001 \001(\t\022\016\n\006number\030\002 \001(\005\022(\n\007options\030"
+    "\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/proto"
+    "buf/types/known/typepb\370\001\001\242\002\003GPB\252\002\036Google"
+    ".Protobuf.WellKnownTypesb\006proto3"
 };
-static ::_pbi::once_flag descriptor_table_google_2fprotobuf_2ftype_2eproto_once;
+static const ::_pbi::DescriptorTable* const descriptor_table_google_2fprotobuf_2ftype_2eproto_deps[2] =
+    {
+        &::descriptor_table_google_2fprotobuf_2fany_2eproto,
+        &::descriptor_table_google_2fprotobuf_2fsource_5fcontext_2eproto,
+};
+static ::absl::once_flag descriptor_table_google_2fprotobuf_2ftype_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2ftype_2eproto = {
-    false, false, 1592, descriptor_table_protodef_google_2fprotobuf_2ftype_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2ftype_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2ftype_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2ftype_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2ftype_2eproto(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::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);
@@ -278,8 +315,9 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr Field_Kind Field::TYPE_UNKNOWN;
 constexpr Field_Kind Field::TYPE_DOUBLE;
 constexpr Field_Kind Field::TYPE_FLOAT;
@@ -302,7 +340,9 @@
 constexpr Field_Kind Field::Kind_MIN;
 constexpr Field_Kind Field::Kind_MAX;
 constexpr int Field::Kind_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Cardinality_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
   return file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[1];
@@ -318,8 +358,9 @@
       return false;
   }
 }
+#if (__cplusplus < 201703) && \
+  (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 
-#if (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 constexpr Field_Cardinality Field::CARDINALITY_UNKNOWN;
 constexpr Field_Cardinality Field::CARDINALITY_OPTIONAL;
 constexpr Field_Cardinality Field::CARDINALITY_REQUIRED;
@@ -327,7 +368,9 @@
 constexpr Field_Cardinality Field::Cardinality_MIN;
 constexpr Field_Cardinality Field::Cardinality_MAX;
 constexpr int Field::Cardinality_ARRAYSIZE;
-#endif  // (__cplusplus < 201703) && (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
+
+#endif  // (__cplusplus < 201703) &&
+        // (!defined(_MSC_VER) || (_MSC_VER >= 1900 && _MSC_VER < 1912))
 const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Syntax_descriptor() {
   ::PROTOBUF_NAMESPACE_ID::internal::AssignDescriptors(&descriptor_table_google_2fprotobuf_2ftype_2eproto);
   return file_level_enum_descriptors_google_2fprotobuf_2ftype_2eproto[2];
@@ -341,8 +384,6 @@
       return false;
   }
 }
-
-
 // ===================================================================
 
 class Type::_Internal {
@@ -437,7 +478,7 @@
 
 void Type::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Type)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -454,24 +495,26 @@
 }
 
 const char* Type::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Type.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Field fields = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -479,12 +522,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated string oneofs = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -494,12 +538,13 @@
             CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Type.oneofs"));
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Option options = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -507,25 +552,28 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<34>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.SourceContext source_context = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 42)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 42)) {
           ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.Syntax syntax = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 48)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 48)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -550,10 +598,11 @@
 #undef CHK_
 }
 
-uint8_t* Type::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Type::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Type)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string name = 1;
@@ -614,11 +663,12 @@
   return target;
 }
 
-size_t Type::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type)
-  size_t total_size = 0;
+::size_t Type::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Type)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -677,9 +727,10 @@
 void Type::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Type*>(&to_msg);
   auto& from = static_cast<const Type&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Type)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.fields_.MergeFrom(from._impl_.fields_);
@@ -730,11 +781,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Type::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
       file_level_metadata_google_2fprotobuf_2ftype_2eproto[0]);
 }
-
 // ===================================================================
 
 class Field::_Internal {
@@ -797,7 +848,7 @@
       _this->GetArenaForAllocation());
   }
   ::memcpy(&_impl_.kind_, &from._impl_.kind_,
-    static_cast<size_t>(reinterpret_cast<char*>(&_impl_.packed_) -
+    static_cast<::size_t>(reinterpret_cast<char*>(&_impl_.packed_) -
     reinterpret_cast<char*>(&_impl_.kind_)) + sizeof(_impl_.packed_));
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Field)
 }
@@ -861,7 +912,7 @@
 
 void Field::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Field)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -870,83 +921,91 @@
   _impl_.type_url_.ClearToEmpty();
   _impl_.json_name_.ClearToEmpty();
   _impl_.default_value_.ClearToEmpty();
-  ::memset(&_impl_.kind_, 0, static_cast<size_t>(
+  ::memset(&_impl_.kind_, 0, static_cast<::size_t>(
       reinterpret_cast<char*>(&_impl_.packed_) -
       reinterpret_cast<char*>(&_impl_.kind_)) + sizeof(_impl_.packed_));
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Field::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // .google.protobuf.Field.Kind kind = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_kind(static_cast<::PROTOBUF_NAMESPACE_ID::Field_Kind>(val));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.Field.Cardinality cardinality = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_cardinality(static_cast<::PROTOBUF_NAMESPACE_ID::Field_Cardinality>(val));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // int32 number = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 24)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 24)) {
           _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string name = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string type_url = 6;
       case 6:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 50)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 50)) {
           auto str = _internal_mutable_type_url();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.type_url"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // int32 oneof_index = 7;
       case 7:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 56)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 56)) {
           _impl_.oneof_index_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // bool packed = 8;
       case 8:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 64)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 64)) {
           _impl_.packed_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Option options = 9;
       case 9:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 74)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 74)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -954,28 +1013,31 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<74>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string json_name = 10;
       case 10:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 82)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 82)) {
           auto str = _internal_mutable_json_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.json_name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // string default_value = 11;
       case 11:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 90)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 90)) {
           auto str = _internal_mutable_default_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Field.default_value"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1000,10 +1062,11 @@
 #undef CHK_
 }
 
-uint8_t* Field::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Field::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Field)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // .google.protobuf.Field.Kind kind = 1;
@@ -1094,11 +1157,12 @@
   return target;
 }
 
-size_t Field::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field)
-  size_t total_size = 0;
+::size_t Field::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Field)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1177,9 +1241,10 @@
 void Field::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Field*>(&to_msg);
   auto& from = static_cast<const Field&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Field)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.options_.MergeFrom(from._impl_.options_);
@@ -1255,11 +1320,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Field::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
       file_level_metadata_google_2fprotobuf_2ftype_2eproto[1]);
 }
-
 // ===================================================================
 
 class Enum::_Internal {
@@ -1351,7 +1416,7 @@
 
 void Enum::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Enum)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1367,24 +1432,26 @@
 }
 
 const char* Enum::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Enum.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.EnumValue enumvalue = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1392,12 +1459,13 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<18>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Option options = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1405,25 +1473,28 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.SourceContext source_context = 4;
       case 4:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 34)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 34)) {
           ptr = ctx->ParseMessage(_internal_mutable_source_context(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.Syntax syntax = 5;
       case 5:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 40)) {
-          uint64_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 40)) {
+          ::uint32_t val = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
           _internal_set_syntax(static_cast<::PROTOBUF_NAMESPACE_ID::Syntax>(val));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1448,10 +1519,11 @@
 #undef CHK_
 }
 
-uint8_t* Enum::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Enum::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Enum)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string name = 1;
@@ -1502,11 +1574,12 @@
   return target;
 }
 
-size_t Enum::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum)
-  size_t total_size = 0;
+::size_t Enum::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Enum)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1557,9 +1630,10 @@
 void Enum::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Enum*>(&to_msg);
   auto& from = static_cast<const Enum&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Enum)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.enumvalue_.MergeFrom(from._impl_.enumvalue_);
@@ -1608,11 +1682,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Enum::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
       file_level_metadata_google_2fprotobuf_2ftype_2eproto[2]);
 }
-
 // ===================================================================
 
 class EnumValue::_Internal {
@@ -1684,7 +1758,7 @@
 
 void EnumValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.EnumValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1695,32 +1769,35 @@
 }
 
 const char* EnumValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.EnumValue.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // int32 number = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 16)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 16)) {
           _impl_.number_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // repeated .google.protobuf.Option options = 3;
       case 3:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 26)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 26)) {
           ptr -= 1;
           do {
             ptr += 1;
@@ -1728,8 +1805,9 @@
             CHK_(ptr);
             if (!ctx->DataAvailable(ptr)) break;
           } while (::PROTOBUF_NAMESPACE_ID::internal::ExpectTag<26>(ptr));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1754,10 +1832,11 @@
 #undef CHK_
 }
 
-uint8_t* EnumValue::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* EnumValue::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.EnumValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string name = 1;
@@ -1792,11 +1871,12 @@
   return target;
 }
 
-size_t EnumValue::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue)
-  size_t total_size = 0;
+::size_t EnumValue::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.EnumValue)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1832,9 +1912,10 @@
 void EnumValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<EnumValue*>(&to_msg);
   auto& from = static_cast<const EnumValue&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.EnumValue)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   _this->_impl_.options_.MergeFrom(from._impl_.options_);
@@ -1872,11 +1953,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata EnumValue::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2ftype_2eproto_getter, &descriptor_table_google_2fprotobuf_2ftype_2eproto_once,
       file_level_metadata_google_2fprotobuf_2ftype_2eproto[3]);
 }
-
 // ===================================================================
 
 class Option::_Internal {
@@ -1959,7 +2040,7 @@
 
 void Option::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Option)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1972,28 +2053,31 @@
 }
 
 const char* Option::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string name = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_name();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.Option.name"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       // .google.protobuf.Any value = 2;
       case 2:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 18)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 18)) {
           ptr = ctx->ParseMessage(_internal_mutable_value(), ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -2018,10 +2102,11 @@
 #undef CHK_
 }
 
-uint8_t* Option::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Option::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Option)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string name = 1;
@@ -2049,11 +2134,12 @@
   return target;
 }
 
-size_t Option::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Option)
-  size_t total_size = 0;
+::size_t Option::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Option)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -2084,9 +2170,10 @@
 void Option::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Option*>(&to_msg);
   auto& from = static_cast<const Option&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Option)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (!from._internal_name().empty()) {
@@ -2123,11 +2210,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Option::GetMetadata() const {
+
   return ::_pbi::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
@@ -2152,6 +2239,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::Option >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/type.pb.h b/src/google/protobuf/type.pb.h
index f6cba20..16884af 100644
--- a/src/google/protobuf/type.pb.h
+++ b/src/google/protobuf/type.pb.h
@@ -1,41 +1,46 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/type.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/generated_enum_reflection.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/any.pb.h>
-#include <google/protobuf/source_context.pb.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/generated_enum_reflection.h"
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/any.pb.h"
+#include "google/protobuf/source_context.pb.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2ftype_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -44,9 +49,10 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2ftype_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct EnumDefaultTypeInternal;
@@ -63,16 +69,19 @@
 class Type;
 struct TypeDefaultTypeInternal;
 PROTOBUF_EXPORT extern TypeDefaultTypeInternal _Type_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Enum* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Enum>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValue>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Field* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Field>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Option* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Option>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Type* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Type>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Enum* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Enum>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::EnumValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::EnumValue>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Field* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Field>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Option* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Option>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Type* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Type>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
 
+PROTOBUF_NAMESPACE_OPEN
 enum Field_Kind : int {
   Field_Kind_TYPE_UNKNOWN = 0,
   Field_Kind_TYPE_DOUBLE = 1,
@@ -93,82 +102,107 @@
   Field_Kind_TYPE_SFIXED64 = 16,
   Field_Kind_TYPE_SINT32 = 17,
   Field_Kind_TYPE_SINT64 = 18,
-  Field_Kind_Field_Kind_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
-  Field_Kind_Field_Kind_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
+  Field_Kind_Field_Kind_INT_MIN_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::min(),
+  Field_Kind_Field_Kind_INT_MAX_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::max(),
 };
-PROTOBUF_EXPORT bool Field_Kind_IsValid(int value);
-constexpr Field_Kind Field_Kind_Kind_MIN = Field_Kind_TYPE_UNKNOWN;
-constexpr Field_Kind Field_Kind_Kind_MAX = Field_Kind_TYPE_SINT64;
-constexpr int Field_Kind_Kind_ARRAYSIZE = Field_Kind_Kind_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Kind_descriptor();
-template<typename T>
-inline const std::string& Field_Kind_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, Field_Kind>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function Field_Kind_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    Field_Kind_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool Field_Kind_IsValid(int value);
+constexpr Field_Kind Field_Kind_Kind_MIN = static_cast<Field_Kind>(0);
+constexpr Field_Kind Field_Kind_Kind_MAX = static_cast<Field_Kind>(18);
+constexpr int Field_Kind_Kind_ARRAYSIZE = 18 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+Field_Kind_descriptor();
+template <typename T>
+const std::string& Field_Kind_Name(T value) {
+  static_assert(std::is_same<T, Field_Kind>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to Kind_Name().");
+  return Field_Kind_Name(static_cast<Field_Kind>(value));
 }
-inline bool Field_Kind_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Kind* value) {
+template <>
+inline const std::string& Field_Kind_Name(Field_Kind value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<Field_Kind_descriptor,
+                                                 0, 18>(
+      static_cast<int>(value));
+}
+inline bool Field_Kind_Parse(absl::string_view name, Field_Kind* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Kind>(
-    Field_Kind_descriptor(), name, value);
+      Field_Kind_descriptor(), name, value);
 }
 enum Field_Cardinality : int {
   Field_Cardinality_CARDINALITY_UNKNOWN = 0,
   Field_Cardinality_CARDINALITY_OPTIONAL = 1,
   Field_Cardinality_CARDINALITY_REQUIRED = 2,
   Field_Cardinality_CARDINALITY_REPEATED = 3,
-  Field_Cardinality_Field_Cardinality_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
-  Field_Cardinality_Field_Cardinality_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
+  Field_Cardinality_Field_Cardinality_INT_MIN_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::min(),
+  Field_Cardinality_Field_Cardinality_INT_MAX_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::max(),
 };
-PROTOBUF_EXPORT bool Field_Cardinality_IsValid(int value);
-constexpr Field_Cardinality Field_Cardinality_Cardinality_MIN = Field_Cardinality_CARDINALITY_UNKNOWN;
-constexpr Field_Cardinality Field_Cardinality_Cardinality_MAX = Field_Cardinality_CARDINALITY_REPEATED;
-constexpr int Field_Cardinality_Cardinality_ARRAYSIZE = Field_Cardinality_Cardinality_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Field_Cardinality_descriptor();
-template<typename T>
-inline const std::string& Field_Cardinality_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, Field_Cardinality>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function Field_Cardinality_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    Field_Cardinality_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool Field_Cardinality_IsValid(int value);
+constexpr Field_Cardinality Field_Cardinality_Cardinality_MIN = static_cast<Field_Cardinality>(0);
+constexpr Field_Cardinality Field_Cardinality_Cardinality_MAX = static_cast<Field_Cardinality>(3);
+constexpr int Field_Cardinality_Cardinality_ARRAYSIZE = 3 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+Field_Cardinality_descriptor();
+template <typename T>
+const std::string& Field_Cardinality_Name(T value) {
+  static_assert(std::is_same<T, Field_Cardinality>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to Cardinality_Name().");
+  return Field_Cardinality_Name(static_cast<Field_Cardinality>(value));
 }
-inline bool Field_Cardinality_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Field_Cardinality* value) {
+template <>
+inline const std::string& Field_Cardinality_Name(Field_Cardinality value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<Field_Cardinality_descriptor,
+                                                 0, 3>(
+      static_cast<int>(value));
+}
+inline bool Field_Cardinality_Parse(absl::string_view name, Field_Cardinality* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Field_Cardinality>(
-    Field_Cardinality_descriptor(), name, value);
+      Field_Cardinality_descriptor(), name, value);
 }
 enum Syntax : int {
   SYNTAX_PROTO2 = 0,
   SYNTAX_PROTO3 = 1,
-  Syntax_INT_MIN_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::min(),
-  Syntax_INT_MAX_SENTINEL_DO_NOT_USE_ = std::numeric_limits<int32_t>::max()
+  Syntax_INT_MIN_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::min(),
+  Syntax_INT_MAX_SENTINEL_DO_NOT_USE_ =
+      std::numeric_limits<::int32_t>::max(),
 };
-PROTOBUF_EXPORT bool Syntax_IsValid(int value);
-constexpr Syntax Syntax_MIN = SYNTAX_PROTO2;
-constexpr Syntax Syntax_MAX = SYNTAX_PROTO3;
-constexpr int Syntax_ARRAYSIZE = Syntax_MAX + 1;
 
-PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Syntax_descriptor();
-template<typename T>
-inline const std::string& Syntax_Name(T enum_t_value) {
-  static_assert(::std::is_same<T, Syntax>::value ||
-    ::std::is_integral<T>::value,
-    "Incorrect type passed to function Syntax_Name.");
-  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfEnum(
-    Syntax_descriptor(), enum_t_value);
+PROTOBUF_EXPORT bool Syntax_IsValid(int value);
+constexpr Syntax Syntax_MIN = static_cast<Syntax>(0);
+constexpr Syntax Syntax_MAX = static_cast<Syntax>(1);
+constexpr int Syntax_ARRAYSIZE = 1 + 1;
+PROTOBUF_EXPORT const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
+Syntax_descriptor();
+template <typename T>
+const std::string& Syntax_Name(T value) {
+  static_assert(std::is_same<T, Syntax>::value ||
+                    std::is_integral<T>::value,
+                "Incorrect type passed to Syntax_Name().");
+  return Syntax_Name(static_cast<Syntax>(value));
 }
-inline bool Syntax_Parse(
-    ::PROTOBUF_NAMESPACE_ID::ConstStringParam name, Syntax* value) {
+template <>
+inline const std::string& Syntax_Name(Syntax value) {
+  return ::PROTOBUF_NAMESPACE_ID::internal::NameOfDenseEnum<Syntax_descriptor,
+                                                 0, 1>(
+      static_cast<int>(value));
+}
+inline bool Syntax_Parse(absl::string_view name, Syntax* value) {
   return ::PROTOBUF_NAMESPACE_ID::internal::ParseNamedEnum<Syntax>(
-    Syntax_descriptor(), name, value);
+      Syntax_descriptor(), name, value);
 }
+
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT Type final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Type) */ {
  public:
@@ -258,10 +292,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -272,7 +306,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Type";
   }
   protected:
@@ -326,12 +360,12 @@
   void set_oneofs(int index, const std::string& value);
   void set_oneofs(int index, std::string&& value);
   void set_oneofs(int index, const char* value);
-  void set_oneofs(int index, const char* value, size_t size);
+  void set_oneofs(int index, const char* value, ::size_t size);
   std::string* add_oneofs();
   void add_oneofs(const std::string& value);
   void add_oneofs(std::string&& value);
   void add_oneofs(const char* value);
-  void add_oneofs(const char* value, size_t size);
+  void add_oneofs(const char* value, ::size_t size);
   const ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>& oneofs() const;
   ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField<std::string>* mutable_oneofs();
   private:
@@ -416,8 +450,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Field final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Field) */ {
@@ -508,10 +541,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -522,7 +555,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Field";
   }
   protected:
@@ -537,101 +570,62 @@
 
   // nested types ----------------------------------------------------
 
-  typedef Field_Kind Kind;
-  static constexpr Kind TYPE_UNKNOWN =
-    Field_Kind_TYPE_UNKNOWN;
-  static constexpr Kind TYPE_DOUBLE =
-    Field_Kind_TYPE_DOUBLE;
-  static constexpr Kind TYPE_FLOAT =
-    Field_Kind_TYPE_FLOAT;
-  static constexpr Kind TYPE_INT64 =
-    Field_Kind_TYPE_INT64;
-  static constexpr Kind TYPE_UINT64 =
-    Field_Kind_TYPE_UINT64;
-  static constexpr Kind TYPE_INT32 =
-    Field_Kind_TYPE_INT32;
-  static constexpr Kind TYPE_FIXED64 =
-    Field_Kind_TYPE_FIXED64;
-  static constexpr Kind TYPE_FIXED32 =
-    Field_Kind_TYPE_FIXED32;
-  static constexpr Kind TYPE_BOOL =
-    Field_Kind_TYPE_BOOL;
-  static constexpr Kind TYPE_STRING =
-    Field_Kind_TYPE_STRING;
-  static constexpr Kind TYPE_GROUP =
-    Field_Kind_TYPE_GROUP;
-  static constexpr Kind TYPE_MESSAGE =
-    Field_Kind_TYPE_MESSAGE;
-  static constexpr Kind TYPE_BYTES =
-    Field_Kind_TYPE_BYTES;
-  static constexpr Kind TYPE_UINT32 =
-    Field_Kind_TYPE_UINT32;
-  static constexpr Kind TYPE_ENUM =
-    Field_Kind_TYPE_ENUM;
-  static constexpr Kind TYPE_SFIXED32 =
-    Field_Kind_TYPE_SFIXED32;
-  static constexpr Kind TYPE_SFIXED64 =
-    Field_Kind_TYPE_SFIXED64;
-  static constexpr Kind TYPE_SINT32 =
-    Field_Kind_TYPE_SINT32;
-  static constexpr Kind TYPE_SINT64 =
-    Field_Kind_TYPE_SINT64;
+  using Kind = Field_Kind;
+  static constexpr Kind TYPE_UNKNOWN = Field_Kind_TYPE_UNKNOWN;
+  static constexpr Kind TYPE_DOUBLE = Field_Kind_TYPE_DOUBLE;
+  static constexpr Kind TYPE_FLOAT = Field_Kind_TYPE_FLOAT;
+  static constexpr Kind TYPE_INT64 = Field_Kind_TYPE_INT64;
+  static constexpr Kind TYPE_UINT64 = Field_Kind_TYPE_UINT64;
+  static constexpr Kind TYPE_INT32 = Field_Kind_TYPE_INT32;
+  static constexpr Kind TYPE_FIXED64 = Field_Kind_TYPE_FIXED64;
+  static constexpr Kind TYPE_FIXED32 = Field_Kind_TYPE_FIXED32;
+  static constexpr Kind TYPE_BOOL = Field_Kind_TYPE_BOOL;
+  static constexpr Kind TYPE_STRING = Field_Kind_TYPE_STRING;
+  static constexpr Kind TYPE_GROUP = Field_Kind_TYPE_GROUP;
+  static constexpr Kind TYPE_MESSAGE = Field_Kind_TYPE_MESSAGE;
+  static constexpr Kind TYPE_BYTES = Field_Kind_TYPE_BYTES;
+  static constexpr Kind TYPE_UINT32 = Field_Kind_TYPE_UINT32;
+  static constexpr Kind TYPE_ENUM = Field_Kind_TYPE_ENUM;
+  static constexpr Kind TYPE_SFIXED32 = Field_Kind_TYPE_SFIXED32;
+  static constexpr Kind TYPE_SFIXED64 = Field_Kind_TYPE_SFIXED64;
+  static constexpr Kind TYPE_SINT32 = Field_Kind_TYPE_SINT32;
+  static constexpr Kind TYPE_SINT64 = Field_Kind_TYPE_SINT64;
   static inline bool Kind_IsValid(int value) {
     return Field_Kind_IsValid(value);
   }
-  static constexpr Kind Kind_MIN =
-    Field_Kind_Kind_MIN;
-  static constexpr Kind Kind_MAX =
-    Field_Kind_Kind_MAX;
-  static constexpr int Kind_ARRAYSIZE =
-    Field_Kind_Kind_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  Kind_descriptor() {
+  static constexpr Kind Kind_MIN = Field_Kind_Kind_MIN;
+  static constexpr Kind Kind_MAX = Field_Kind_Kind_MAX;
+  static constexpr int Kind_ARRAYSIZE = Field_Kind_Kind_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Kind_descriptor() {
     return Field_Kind_descriptor();
   }
-  template<typename T>
-  static inline const std::string& Kind_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, Kind>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function Kind_Name.");
-    return Field_Kind_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& Kind_Name(T value) {
+    return Field_Kind_Name(value);
   }
-  static inline bool Kind_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      Kind* value) {
+  static inline bool Kind_Parse(absl::string_view name, Kind* value) {
     return Field_Kind_Parse(name, value);
   }
 
-  typedef Field_Cardinality Cardinality;
-  static constexpr Cardinality CARDINALITY_UNKNOWN =
-    Field_Cardinality_CARDINALITY_UNKNOWN;
-  static constexpr Cardinality CARDINALITY_OPTIONAL =
-    Field_Cardinality_CARDINALITY_OPTIONAL;
-  static constexpr Cardinality CARDINALITY_REQUIRED =
-    Field_Cardinality_CARDINALITY_REQUIRED;
-  static constexpr Cardinality CARDINALITY_REPEATED =
-    Field_Cardinality_CARDINALITY_REPEATED;
+  using Cardinality = Field_Cardinality;
+  static constexpr Cardinality CARDINALITY_UNKNOWN = Field_Cardinality_CARDINALITY_UNKNOWN;
+  static constexpr Cardinality CARDINALITY_OPTIONAL = Field_Cardinality_CARDINALITY_OPTIONAL;
+  static constexpr Cardinality CARDINALITY_REQUIRED = Field_Cardinality_CARDINALITY_REQUIRED;
+  static constexpr Cardinality CARDINALITY_REPEATED = Field_Cardinality_CARDINALITY_REPEATED;
   static inline bool Cardinality_IsValid(int value) {
     return Field_Cardinality_IsValid(value);
   }
-  static constexpr Cardinality Cardinality_MIN =
-    Field_Cardinality_Cardinality_MIN;
-  static constexpr Cardinality Cardinality_MAX =
-    Field_Cardinality_Cardinality_MAX;
-  static constexpr int Cardinality_ARRAYSIZE =
-    Field_Cardinality_Cardinality_ARRAYSIZE;
-  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor*
-  Cardinality_descriptor() {
+  static constexpr Cardinality Cardinality_MIN = Field_Cardinality_Cardinality_MIN;
+  static constexpr Cardinality Cardinality_MAX = Field_Cardinality_Cardinality_MAX;
+  static constexpr int Cardinality_ARRAYSIZE = Field_Cardinality_Cardinality_ARRAYSIZE;
+  static inline const ::PROTOBUF_NAMESPACE_ID::EnumDescriptor* Cardinality_descriptor() {
     return Field_Cardinality_descriptor();
   }
-  template<typename T>
-  static inline const std::string& Cardinality_Name(T enum_t_value) {
-    static_assert(::std::is_same<T, Cardinality>::value ||
-      ::std::is_integral<T>::value,
-      "Incorrect type passed to function Cardinality_Name.");
-    return Field_Cardinality_Name(enum_t_value);
+  template <typename T>
+  static inline const std::string& Cardinality_Name(T value) {
+    return Field_Cardinality_Name(value);
   }
-  static inline bool Cardinality_Parse(::PROTOBUF_NAMESPACE_ID::ConstStringParam name,
-      Cardinality* value) {
+  static inline bool Cardinality_Parse(absl::string_view name, Cardinality* value) {
     return Field_Cardinality_Parse(name, value);
   }
 
@@ -743,20 +737,20 @@
 
   // int32 number = 3;
   void clear_number();
-  int32_t number() const;
-  void set_number(int32_t value);
+  ::int32_t number() const;
+  void set_number(::int32_t value);
   private:
-  int32_t _internal_number() const;
-  void _internal_set_number(int32_t value);
+  ::int32_t _internal_number() const;
+  void _internal_set_number(::int32_t value);
   public:
 
   // int32 oneof_index = 7;
   void clear_oneof_index();
-  int32_t oneof_index() const;
-  void set_oneof_index(int32_t value);
+  ::int32_t oneof_index() const;
+  void set_oneof_index(::int32_t value);
   private:
-  int32_t _internal_oneof_index() const;
-  void _internal_set_oneof_index(int32_t value);
+  ::int32_t _internal_oneof_index() const;
+  void _internal_set_oneof_index(::int32_t value);
   public:
 
   // bool packed = 8;
@@ -783,15 +777,14 @@
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr default_value_;
     int kind_;
     int cardinality_;
-    int32_t number_;
-    int32_t oneof_index_;
+    ::int32_t number_;
+    ::int32_t oneof_index_;
     bool packed_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Enum final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Enum) */ {
@@ -882,10 +875,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -896,7 +889,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Enum";
   }
   protected:
@@ -1014,8 +1007,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT EnumValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.EnumValue) */ {
@@ -1106,10 +1098,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1120,7 +1112,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.EnumValue";
   }
   protected:
@@ -1176,11 +1168,11 @@
 
   // int32 number = 2;
   void clear_number();
-  int32_t number() const;
-  void set_number(int32_t value);
+  ::int32_t number() const;
+  void set_number(::int32_t value);
   private:
-  int32_t _internal_number() const;
-  void _internal_set_number(int32_t value);
+  ::int32_t _internal_number() const;
+  void _internal_set_number(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.EnumValue)
@@ -1193,13 +1185,12 @@
   struct Impl_ {
     ::PROTOBUF_NAMESPACE_ID::RepeatedPtrField< ::PROTOBUF_NAMESPACE_ID::Option > options_;
     ::PROTOBUF_NAMESPACE_ID::internal::ArenaStringPtr name_;
-    int32_t number_;
+    ::int32_t number_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2ftype_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Option final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Option) */ {
@@ -1290,10 +1281,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1304,7 +1295,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Option";
   }
   protected:
@@ -1375,12 +1366,17 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // Type
 
 // string name = 1;
@@ -1407,11 +1403,11 @@
   return _impl_.name_.Get();
 }
 inline void Type::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Type::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Type::release_name() {
@@ -1419,11 +1415,6 @@
   return _impl_.name_.Release();
 }
 inline void Type::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -1508,11 +1499,10 @@
   // @@protoc_insertion_point(field_set:google.protobuf.Type.oneofs)
 }
 inline void Type::set_oneofs(int index, const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.oneofs_.Mutable(index)->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.oneofs_.Mutable(index)->assign(value);
   // @@protoc_insertion_point(field_set_char:google.protobuf.Type.oneofs)
 }
-inline void Type::set_oneofs(int index, const char* value, size_t size) {
+inline void Type::set_oneofs(int index, const char* value, ::size_t size) {
   _impl_.oneofs_.Mutable(index)->assign(
     reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_set_pointer:google.protobuf.Type.oneofs)
@@ -1529,11 +1519,10 @@
   // @@protoc_insertion_point(field_add:google.protobuf.Type.oneofs)
 }
 inline void Type::add_oneofs(const char* value) {
-  GOOGLE_DCHECK(value != nullptr);
-  _impl_.oneofs_.Add()->assign(value);
+  GOOGLE_DCHECK(value != nullptr);  _impl_.oneofs_.Add()->assign(value);
   // @@protoc_insertion_point(field_add_char:google.protobuf.Type.oneofs)
 }
-inline void Type::add_oneofs(const char* value, size_t size) {
+inline void Type::add_oneofs(const char* value, ::size_t size) {
   _impl_.oneofs_.Add()->assign(reinterpret_cast<const char*>(value), size);
   // @@protoc_insertion_point(field_add_pointer:google.protobuf.Type.oneofs)
 }
@@ -1610,11 +1599,6 @@
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_);
   }
   _impl_.source_context_ = source_context;
-  if (source_context) {
-    
-  } else {
-    
-  }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Type.source_context)
 }
 inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Type::release_source_context() {
@@ -1665,9 +1649,9 @@
       source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_context, submessage_arena);
     }
-    
+
   } else {
-    
+
   }
   _impl_.source_context_ = source_context;
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Type.source_context)
@@ -1741,18 +1725,18 @@
 inline void Field::clear_number() {
   _impl_.number_ = 0;
 }
-inline int32_t Field::_internal_number() const {
+inline ::int32_t Field::_internal_number() const {
   return _impl_.number_;
 }
-inline int32_t Field::number() const {
+inline ::int32_t Field::number() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Field.number)
   return _internal_number();
 }
-inline void Field::_internal_set_number(int32_t value) {
-  
+inline void Field::_internal_set_number(::int32_t value) {
+
   _impl_.number_ = value;
 }
-inline void Field::set_number(int32_t value) {
+inline void Field::set_number(::int32_t value) {
   _internal_set_number(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Field.number)
 }
@@ -1781,11 +1765,11 @@
   return _impl_.name_.Get();
 }
 inline void Field::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Field::release_name() {
@@ -1793,11 +1777,6 @@
   return _impl_.name_.Release();
 }
 inline void Field::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -1831,11 +1810,11 @@
   return _impl_.type_url_.Get();
 }
 inline void Field::_internal_set_type_url(const std::string& value) {
-  
+
   _impl_.type_url_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_type_url() {
-  
+
   return _impl_.type_url_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Field::release_type_url() {
@@ -1843,11 +1822,6 @@
   return _impl_.type_url_.Release();
 }
 inline void Field::set_allocated_type_url(std::string* type_url) {
-  if (type_url != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.type_url_.SetAllocated(type_url, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.type_url_.IsDefault()) {
@@ -1861,18 +1835,18 @@
 inline void Field::clear_oneof_index() {
   _impl_.oneof_index_ = 0;
 }
-inline int32_t Field::_internal_oneof_index() const {
+inline ::int32_t Field::_internal_oneof_index() const {
   return _impl_.oneof_index_;
 }
-inline int32_t Field::oneof_index() const {
+inline ::int32_t Field::oneof_index() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Field.oneof_index)
   return _internal_oneof_index();
 }
-inline void Field::_internal_set_oneof_index(int32_t value) {
-  
+inline void Field::_internal_set_oneof_index(::int32_t value) {
+
   _impl_.oneof_index_ = value;
 }
-inline void Field::set_oneof_index(int32_t value) {
+inline void Field::set_oneof_index(::int32_t value) {
   _internal_set_oneof_index(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Field.oneof_index)
 }
@@ -1889,7 +1863,7 @@
   return _internal_packed();
 }
 inline void Field::_internal_set_packed(bool value) {
-  
+
   _impl_.packed_ = value;
 }
 inline void Field::set_packed(bool value) {
@@ -1961,11 +1935,11 @@
   return _impl_.json_name_.Get();
 }
 inline void Field::_internal_set_json_name(const std::string& value) {
-  
+
   _impl_.json_name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_json_name() {
-  
+
   return _impl_.json_name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Field::release_json_name() {
@@ -1973,11 +1947,6 @@
   return _impl_.json_name_.Release();
 }
 inline void Field::set_allocated_json_name(std::string* json_name) {
-  if (json_name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.json_name_.SetAllocated(json_name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.json_name_.IsDefault()) {
@@ -2011,11 +1980,11 @@
   return _impl_.default_value_.Get();
 }
 inline void Field::_internal_set_default_value(const std::string& value) {
-  
+
   _impl_.default_value_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Field::_internal_mutable_default_value() {
-  
+
   return _impl_.default_value_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Field::release_default_value() {
@@ -2023,11 +1992,6 @@
   return _impl_.default_value_.Release();
 }
 inline void Field::set_allocated_default_value(std::string* default_value) {
-  if (default_value != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.default_value_.SetAllocated(default_value, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.default_value_.IsDefault()) {
@@ -2065,11 +2029,11 @@
   return _impl_.name_.Get();
 }
 inline void Enum::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Enum::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Enum::release_name() {
@@ -2077,11 +2041,6 @@
   return _impl_.name_.Release();
 }
 inline void Enum::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -2193,11 +2152,6 @@
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.source_context_);
   }
   _impl_.source_context_ = source_context;
-  if (source_context) {
-    
-  } else {
-    
-  }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Enum.source_context)
 }
 inline ::PROTOBUF_NAMESPACE_ID::SourceContext* Enum::release_source_context() {
@@ -2248,9 +2202,9 @@
       source_context = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, source_context, submessage_arena);
     }
-    
+
   } else {
-    
+
   }
   _impl_.source_context_ = source_context;
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Enum.source_context)
@@ -2304,11 +2258,11 @@
   return _impl_.name_.Get();
 }
 inline void EnumValue::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* EnumValue::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* EnumValue::release_name() {
@@ -2316,11 +2270,6 @@
   return _impl_.name_.Release();
 }
 inline void EnumValue::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -2334,18 +2283,18 @@
 inline void EnumValue::clear_number() {
   _impl_.number_ = 0;
 }
-inline int32_t EnumValue::_internal_number() const {
+inline ::int32_t EnumValue::_internal_number() const {
   return _impl_.number_;
 }
-inline int32_t EnumValue::number() const {
+inline ::int32_t EnumValue::number() const {
   // @@protoc_insertion_point(field_get:google.protobuf.EnumValue.number)
   return _internal_number();
 }
-inline void EnumValue::_internal_set_number(int32_t value) {
-  
+inline void EnumValue::_internal_set_number(::int32_t value) {
+
   _impl_.number_ = value;
 }
-inline void EnumValue::set_number(int32_t value) {
+inline void EnumValue::set_number(::int32_t value) {
   _internal_set_number(value);
   // @@protoc_insertion_point(field_set:google.protobuf.EnumValue.number)
 }
@@ -2418,11 +2367,11 @@
   return _impl_.name_.Get();
 }
 inline void Option::_internal_set_name(const std::string& value) {
-  
+
   _impl_.name_.Set(value, GetArenaForAllocation());
 }
 inline std::string* Option::_internal_mutable_name() {
-  
+
   return _impl_.name_.Mutable(GetArenaForAllocation());
 }
 inline std::string* Option::release_name() {
@@ -2430,11 +2379,6 @@
   return _impl_.name_.Release();
 }
 inline void Option::set_allocated_name(std::string* name) {
-  if (name != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.name_.SetAllocated(name, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.name_.IsDefault()) {
@@ -2466,11 +2410,6 @@
     delete reinterpret_cast<::PROTOBUF_NAMESPACE_ID::MessageLite*>(_impl_.value_);
   }
   _impl_.value_ = value;
-  if (value) {
-    
-  } else {
-    
-  }
   // @@protoc_insertion_point(field_unsafe_arena_set_allocated:google.protobuf.Option.value)
 }
 inline ::PROTOBUF_NAMESPACE_ID::Any* Option::release_value() {
@@ -2521,45 +2460,40 @@
       value = ::PROTOBUF_NAMESPACE_ID::internal::GetOwnedMessage(
           message_arena, value, submessage_arena);
     }
-    
+
   } else {
-    
+
   }
   _impl_.value_ = value;
   // @@protoc_insertion_point(field_set_allocated:google.protobuf.Option.value)
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 PROTOBUF_NAMESPACE_OPEN
 
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::Field_Kind> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::Field_Kind>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::Field_Kind> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::Field_Kind>() {
   return ::PROTOBUF_NAMESPACE_ID::Field_Kind_descriptor();
 }
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::Field_Cardinality> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::Field_Cardinality>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::Field_Cardinality> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::Field_Cardinality>() {
   return ::PROTOBUF_NAMESPACE_ID::Field_Cardinality_descriptor();
 }
-template <> struct is_proto_enum< ::PROTOBUF_NAMESPACE_ID::Syntax> : ::std::true_type {};
 template <>
-inline const EnumDescriptor* GetEnumDescriptor< ::PROTOBUF_NAMESPACE_ID::Syntax>() {
+struct is_proto_enum<::PROTOBUF_NAMESPACE_ID::Syntax> : std::true_type {};
+template <>
+inline const EnumDescriptor* GetEnumDescriptor<::PROTOBUF_NAMESPACE_ID::Syntax>() {
   return ::PROTOBUF_NAMESPACE_ID::Syntax_descriptor();
 }
 
@@ -2567,5 +2501,6 @@
 
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2ftype_2eproto_2epb_2eh
diff --git a/src/google/protobuf/type.proto b/src/google/protobuf/type.proto
index d3f6a68..fd25a41 100644
--- a/src/google/protobuf/type.proto
+++ b/src/google/protobuf/type.proto
@@ -35,12 +35,12 @@
 import "google/protobuf/any.proto";
 import "google/protobuf/source_context.proto";
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
 option java_package = "com.google.protobuf";
 option java_outer_classname = "TypeProto";
 option java_multiple_files = true;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option go_package = "google.golang.org/protobuf/types/known/typepb";
 
 // A protocol buffer message type.
diff --git a/src/google/protobuf/unittest.proto b/src/google/protobuf/unittest.proto
index f1b0bd0..fa95bbd 100644
--- a/src/google/protobuf/unittest.proto
+++ b/src/google/protobuf/unittest.proto
@@ -194,9 +194,12 @@
 
 message TestDeprecatedFields {
   optional int32 deprecated_int32 = 1 [deprecated=true];
+  repeated string deprecated_repeated_string = 4 [deprecated=true];
+  optional TestAllTypes.NestedMessage deprecated_message = 3 [deprecated=true];
   oneof oneof_fields {
     int32 deprecated_int32_in_oneof = 2 [deprecated=true];
   }
+  optional TestDeprecatedFields nested = 5;
 }
 
 message TestDeprecatedMessage {
@@ -221,6 +224,12 @@
   reserved "bar", "baz";
 }
 
+enum TestReservedEnumFields {
+  UNKNOWN = 0;
+  reserved 2, 15, 9 to 11;
+  reserved "bar", "baz";
+}
+
 message TestAllExtensions {
   extensions 1 to max;
 }
@@ -340,9 +349,22 @@
   optional bytes oneof_bytes_extension = 114;
 }
 
+message TestMixedFieldsAndExtensions {
+  optional int32 a = 1;
+  repeated fixed32 b = 3;
+  extensions 2, 4;
+  extend TestMixedFieldsAndExtensions {
+    optional int32 c = 2;
+    repeated fixed32 d = 4;
+  }
+}
+
 message TestGroup {
   optional group OptionalGroup = 16 {
     optional int32 a = 17;
+    optional int32 zz = 89;  // fast table size must be at least 16, for this
+                             // field to be parsed by the fast parser, since
+                             // 89 - 17 = 72 is a multiple of 8.
   }
   optional ForeignEnum optional_foreign_enum = 22;
 }
@@ -459,6 +481,9 @@
   optional TestRequired optional_message = 1;
   repeated TestRequired repeated_message = 2;
   optional int32 dummy = 3;
+
+  // Missing required fields must not affect verification of child messages.
+  optional NestedTestAllTypes optional_lazy_message = 4 [lazy = true];
 }
 
 message TestRequiredMessage {
@@ -556,9 +581,11 @@
 // Additional messages for testing lazy fields.
 message TestEagerMessage {
   optional TestAllTypes sub_message = 1 [lazy=false];
+  optional TestAllTypes sub_message_slow = 100000 [lazy=false];
 }
 message TestLazyMessage {
   optional TestAllTypes sub_message = 1 [lazy=true];
+  optional TestAllTypes sub_message_slow = 100000 [lazy=true];
 }
 message TestEagerMaybeLazy {
   message NestedMessage {
@@ -861,13 +888,13 @@
     int32 foo_int = 1;
     string foo_string = 2;
     NestedMessage foo_message = 3;
+    NestedMessage foo_lazy_message = 4 [lazy = true];
   }
   message NestedMessage {
     required double required_double = 1;
   }
 }
 
-
 // Test messages for packed fields
 
 message TestPackedTypes {
@@ -972,6 +999,14 @@
   repeated sint32 packed_extension = 2006 [packed = true];
 }
 
+message TestRepeatedString {
+  repeated string repeated_string1 = 1;
+  repeated string repeated_string2 = 2;
+
+  repeated bytes repeated_bytes11 = 11;
+  repeated bytes repeated_bytes12 = 12;
+}
+
 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
@@ -1048,7 +1083,6 @@
   optional int64 m6 = 6;
 }
 
-
 // Test that RPC services work.
 message FooRequest  {}
 message FooResponse {}
@@ -1061,7 +1095,6 @@
   rpc Bar(BarRequest) returns (BarResponse);
 }
 
-
 message BarRequest  {}
 message BarResponse {}
 
@@ -1415,4 +1448,135 @@
   optional Nested optional_nested = 1;
 }
 
+// This message contains different kind of enums to exercise the different
+// parsers in table-driven.
+message EnumParseTester {
+  enum SeqSmall0 {
+    SEQ_SMALL_0_DEFAULT = 0;
+    SEQ_SMALL_0_1 = 1;
+    SEQ_SMALL_0_2 = 2;
+  };
+  optional SeqSmall0 optional_seq_small_0_lowfield = 1;
+  optional SeqSmall0 optional_seq_small_0_midfield = 1001;
+  optional SeqSmall0 optional_seq_small_0_hifield = 1000001;
+  repeated SeqSmall0 repeated_seq_small_0_lowfield = 2;
+  repeated SeqSmall0 repeated_seq_small_0_midfield = 1002;
+  repeated SeqSmall0 repeated_seq_small_0_hifield = 1000002;
+  repeated SeqSmall0 packed_seq_small_0_lowfield = 3 [packed = true];
+  repeated SeqSmall0 packed_seq_small_0_midfield = 1003 [packed = true];
+  repeated SeqSmall0 packed_seq_small_0_hifield = 1000003 [packed = true];
 
+  enum SeqSmall1 {
+    SEQ_SMALL_1_DEFAULT = 1;
+    SEQ_SMALL_1_2 = 2;
+    SEQ_SMALL_1_3 = 3;
+  };
+  optional SeqSmall1 optional_seq_small_1_lowfield = 4;
+  optional SeqSmall1 optional_seq_small_1_midfield = 1004;
+  optional SeqSmall1 optional_seq_small_1_hifield = 1000004;
+  repeated SeqSmall1 repeated_seq_small_1_lowfield = 5;
+  repeated SeqSmall1 repeated_seq_small_1_midfield = 1005;
+  repeated SeqSmall1 repeated_seq_small_1_hifield = 1000005;
+  repeated SeqSmall1 packed_seq_small_1_lowfield = 6 [packed = true];
+  repeated SeqSmall1 packed_seq_small_1_midfield = 1006 [packed = true];
+  repeated SeqSmall1 packed_seq_small_1_hifield = 1000006 [packed = true];
+
+  enum SeqLarge {
+    SEQ_LARGE_DEFAULT = -1;
+    SEQ_LARGE_0 = 0;
+    SEQ_LARGE_1 = 1;
+    SEQ_LARGE_2 = 2;
+    SEQ_LARGE_3 = 3;
+    SEQ_LARGE_4 = 4;
+    SEQ_LARGE_5 = 5;
+    SEQ_LARGE_6 = 6;
+    SEQ_LARGE_7 = 7;
+    SEQ_LARGE_8 = 8;
+    SEQ_LARGE_9 = 9;
+    SEQ_LARGE_10 = 10;
+    SEQ_LARGE_11 = 11;
+    SEQ_LARGE_12 = 12;
+    SEQ_LARGE_13 = 13;
+    SEQ_LARGE_14 = 14;
+    SEQ_LARGE_15 = 15;
+    SEQ_LARGE_16 = 16;
+    SEQ_LARGE_17 = 17;
+    SEQ_LARGE_18 = 18;
+    SEQ_LARGE_19 = 19;
+    SEQ_LARGE_20 = 20;
+    SEQ_LARGE_21 = 21;
+    SEQ_LARGE_22 = 22;
+    SEQ_LARGE_23 = 23;
+    SEQ_LARGE_24 = 24;
+    SEQ_LARGE_25 = 25;
+    SEQ_LARGE_26 = 26;
+    SEQ_LARGE_27 = 27;
+    SEQ_LARGE_28 = 28;
+    SEQ_LARGE_29 = 29;
+    SEQ_LARGE_30 = 30;
+    SEQ_LARGE_31 = 31;
+    SEQ_LARGE_32 = 32;
+    SEQ_LARGE_33 = 33;
+  };
+  optional SeqLarge optional_seq_large_lowfield = 7;
+  optional SeqLarge optional_seq_large_midfield = 1007;
+  optional SeqLarge optional_seq_large_hifield = 1000007;
+  repeated SeqLarge repeated_seq_large_lowfield = 8;
+  repeated SeqLarge repeated_seq_large_midfield = 1008;
+  repeated SeqLarge repeated_seq_large_hifield = 1000008;
+  repeated SeqLarge packed_seq_large_lowfield = 9 [packed = true];
+  repeated SeqLarge packed_seq_large_midfield = 1009 [packed = true];
+  repeated SeqLarge packed_seq_large_hifield = 1000009 [packed = true];
+
+  enum Arbitrary {
+    ARBITRARY_DEFAULT = -123123;
+    ARBITRARY_1 = -123;
+    ARBITRARY_2 = 213;
+    ARBITRARY_3 = 213213;
+    ARBITRARY_MIN = -2147483648;
+    ARBITRARY_MAX = 2147483647;
+  };
+  optional Arbitrary optional_arbitrary_lowfield = 10;
+  optional Arbitrary optional_arbitrary_midfield = 1010;
+  optional Arbitrary optional_arbitrary_hifield = 1000010;
+  repeated Arbitrary repeated_arbitrary_lowfield = 11;
+  repeated Arbitrary repeated_arbitrary_midfield = 1011;
+  repeated Arbitrary repeated_arbitrary_hifield = 1000011;
+  repeated Arbitrary packed_arbitrary_lowfield = 12 [packed = true];
+  repeated Arbitrary packed_arbitrary_midfield = 1012 [packed = true];
+  repeated Arbitrary packed_arbitrary_hifield = 1000012 [packed = true];
+
+  // An arbitrary field we can append to to break the runs of repeated fields.
+  optional int32 other_field = 99;
+};
+
+// This message contains different kind of bool fields to exercise the different
+// parsers in table-drived.
+message BoolParseTester {
+  optional bool optional_bool_lowfield = 1;
+  optional bool optional_bool_midfield = 1001;
+  optional bool optional_bool_hifield = 1000001;
+  repeated bool repeated_bool_lowfield = 2;
+  repeated bool repeated_bool_midfield = 1002;
+  repeated bool repeated_bool_hifield = 1000002;
+  repeated bool packed_bool_lowfield = 3 [packed = true];
+  repeated bool packed_bool_midfield = 1003 [packed = true];
+  repeated bool packed_bool_hifield = 1000003 [packed = true];
+
+  // An arbitrary field we can append to to break the runs of repeated fields.
+  optional int32 other_field = 99;
+};
+
+message StringParseTester {
+  optional string optional_string_lowfield = 1;
+  optional string optional_string_midfield = 1001;
+  optional string optional_string_hifield = 1000001;
+  repeated string repeated_string_lowfield = 2;
+  repeated string repeated_string_midfield = 1002;
+  repeated string repeated_string_hifield = 1000002;
+};
+
+message BadFieldNames{
+  optional int32 OptionalInt32 = 1;
+  optional int32 for = 2;
+}
diff --git a/src/google/protobuf/unittest_embed_optimize_for.proto b/src/google/protobuf/unittest_embed_optimize_for.proto
index d8b0f9b..2a5f137 100644
--- a/src/google/protobuf/unittest_embed_optimize_for.proto
+++ b/src/google/protobuf/unittest_embed_optimize_for.proto
@@ -35,10 +35,11 @@
 // A proto file which imports a proto file that uses optimize_for = CODE_SIZE.
 
 syntax = "proto2";
-import "google/protobuf/unittest_optimize_for.proto";
 
 package protobuf_unittest;
 
+import "google/protobuf/unittest_optimize_for.proto";
+
 // We optimize for speed here, but we are importing a proto that is optimized
 // for code size.
 option optimize_for = SPEED;
diff --git a/src/google/protobuf/unittest_empty.proto b/src/google/protobuf/unittest_empty.proto
index 36443e7..632cc04 100644
--- a/src/google/protobuf/unittest_empty.proto
+++ b/src/google/protobuf/unittest_empty.proto
@@ -1,3 +1,5 @@
+// NOLINT(no_package_specified): Test proto with no package
+
 // Protocol Buffers - Google's data interchange format
 // Copyright 2008 Google Inc.  All rights reserved.
 // https://developers.google.com/protocol-buffers/
@@ -27,7 +29,7 @@
 // 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.
@@ -36,3 +38,4 @@
 // correctly.)
 
 syntax = "proto2";
+
diff --git a/src/google/protobuf/unittest_enormous_descriptor.proto b/src/google/protobuf/unittest_enormous_descriptor.proto
index c700a27..a0dd2a2 100644
--- a/src/google/protobuf/unittest_enormous_descriptor.proto
+++ b/src/google/protobuf/unittest_enormous_descriptor.proto
@@ -28,6 +28,7 @@
 // (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 2009 Google Inc.  All rights reserved.
 // Author: kenton@google.com (Kenton Varda)
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
@@ -44,6 +45,7 @@
 // Avoid generating insanely long methods.
 option optimize_for = CODE_SIZE;
 
+// clang-format off
 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"];
@@ -1046,3 +1048,4 @@
   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"];
 }
+// clang-format on
diff --git a/src/google/protobuf/unittest_import.proto b/src/google/protobuf/unittest_import.proto
index 8d03e38..4fc0ebb 100644
--- a/src/google/protobuf/unittest_import.proto
+++ b/src/google/protobuf/unittest_import.proto
@@ -64,7 +64,6 @@
   IMPORT_BAZ = 9;
 }
 
-
 // To use an enum in a map, it must has the first value as 0.
 enum ImportEnumForMap {
   UNKNOWN = 0;
diff --git a/src/google/protobuf/unittest_import_lite.proto b/src/google/protobuf/unittest_import_lite.proto
index a7afa45..ab4a0ac 100644
--- a/src/google/protobuf/unittest_import_lite.proto
+++ b/src/google/protobuf/unittest_import_lite.proto
@@ -33,14 +33,14 @@
 // This is like unittest_import.proto but with optimize_for = LITE_RUNTIME.
 
 syntax = "proto2";
+
 package protobuf_unittest_import;
 
-option optimize_for = LITE_RUNTIME;
-
-option java_package = "com.google.protobuf";
-
 import public "google/protobuf/unittest_import_public_lite.proto";
 
+option optimize_for = LITE_RUNTIME;
+option java_package = "com.google.protobuf";
+
 message ImportMessageLite {
   optional int32 d = 1;
 }
diff --git a/src/google/protobuf/unittest_import_public_lite.proto b/src/google/protobuf/unittest_import_public_lite.proto
index 33549c2..b64e7f8 100644
--- a/src/google/protobuf/unittest_import_public_lite.proto
+++ b/src/google/protobuf/unittest_import_public_lite.proto
@@ -35,7 +35,6 @@
 package protobuf_unittest_import;
 
 option optimize_for = LITE_RUNTIME;
-
 option java_package = "com.google.protobuf";
 
 message PublicImportMessageLite {
diff --git a/src/google/protobuf/unittest_lazy_dependencies.proto b/src/google/protobuf/unittest_lazy_dependencies.proto
index 2f5efd2..244a886 100644
--- a/src/google/protobuf/unittest_lazy_dependencies.proto
+++ b/src/google/protobuf/unittest_lazy_dependencies.proto
@@ -40,9 +40,9 @@
 
 // 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_generic_services = true;    // auto-added
+option java_generic_services = true;  // auto-added
+option py_generic_services = true;    // auto-added
 option cc_enable_arenas = true;
 
 // We don't put this in a package within proto2 because we need to make sure
@@ -67,8 +67,7 @@
   optional LazyMessage lazy_message = 1;
 }
 
-message MessageCustomOption {
-}
+message MessageCustomOption {}
 
 message MessageCustomOption2 {
   option (lazy_enum_option) = LAZY_ENUM_0;
diff --git a/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto b/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto
index 2243825..466948e 100644
--- a/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto
+++ b/src/google/protobuf/unittest_lazy_dependencies_custom_option.proto
@@ -36,14 +36,14 @@
 
 syntax = "proto2";
 
-import "google/protobuf/unittest_lazy_dependencies_enum.proto";
 import "google/protobuf/descriptor.proto";
+import "google/protobuf/unittest_lazy_dependencies_enum.proto";
 
 // 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_generic_services = true;    // auto-added
+option java_generic_services = true;  // auto-added
+option py_generic_services = true;    // auto-added
 option cc_enable_arenas = true;
 
 // We don't put this in a package within proto2 because we need to make sure
diff --git a/src/google/protobuf/unittest_lazy_dependencies_enum.proto b/src/google/protobuf/unittest_lazy_dependencies_enum.proto
index 9be64d8..5edcc1f 100644
--- a/src/google/protobuf/unittest_lazy_dependencies_enum.proto
+++ b/src/google/protobuf/unittest_lazy_dependencies_enum.proto
@@ -38,9 +38,9 @@
 
 // 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_generic_services = true;    // auto-added
+option java_generic_services = true;  // auto-added
+option py_generic_services = true;    // auto-added
 option cc_enable_arenas = true;
 
 // We don't put this in a package within proto2 because we need to make sure
diff --git a/src/google/protobuf/unittest_lite_imports_nonlite.proto b/src/google/protobuf/unittest_lite_imports_nonlite.proto
index 8a47016..4fdc170 100644
--- a/src/google/protobuf/unittest_lite_imports_nonlite.proto
+++ b/src/google/protobuf/unittest_lite_imports_nonlite.proto
@@ -33,6 +33,7 @@
 // Tests that a "lite" message can import a regular message.
 
 syntax = "proto2";
+
 package protobuf_unittest;
 
 import "google/protobuf/unittest.proto";
diff --git a/src/google/protobuf/unittest_mset.proto b/src/google/protobuf/unittest_mset.proto
index 3294994..fd6aaa5 100644
--- a/src/google/protobuf/unittest_mset.proto
+++ b/src/google/protobuf/unittest_mset.proto
@@ -53,6 +53,12 @@
   optional NestedTestMessageSetContainer child = 2;
 }
 
+message NestedTestInt {
+  optional fixed32 a = 1;
+  optional int32 b = 3;
+  optional NestedTestInt child = 2;
+}
+
 message TestMessageSetExtension1 {
   extend proto2_wireformat_unittest.TestMessageSet {
     optional TestMessageSetExtension1 message_set_extension = 1545008;
@@ -69,11 +75,6 @@
   optional string str = 25;
 }
 
-message NestedTestInt {
-  optional fixed32 a = 1;
-  optional NestedTestInt child = 2;
-}
-
 message TestMessageSetExtension3 {
   extend proto2_wireformat_unittest.TestMessageSet {
     optional TestMessageSetExtension3 message_set_extension = 195273129;
diff --git a/src/google/protobuf/unittest_mset_wire_format.proto b/src/google/protobuf/unittest_mset_wire_format.proto
index 04e4352..de73d74 100644
--- a/src/google/protobuf/unittest_mset_wire_format.proto
+++ b/src/google/protobuf/unittest_mset_wire_format.proto
@@ -35,6 +35,7 @@
 // This file contains messages for testing message_set_wire_format.
 
 syntax = "proto2";
+
 package proto2_wireformat_unittest;
 
 option cc_enable_arenas = true;
@@ -44,6 +45,7 @@
 // A message with message_set_wire_format.
 message TestMessageSet {
   option message_set_wire_format = true;
+
   extensions 4 to max;
 }
 
diff --git a/src/google/protobuf/unittest_no_field_presence.proto b/src/google/protobuf/unittest_no_field_presence.proto
index 994afff..c03b7a5 100644
--- a/src/google/protobuf/unittest_no_field_presence.proto
+++ b/src/google/protobuf/unittest_no_field_presence.proto
@@ -33,10 +33,10 @@
 syntax = "proto3";
 
 // We want to test embedded proto2 messages, so include some proto2 types.
-import "google/protobuf/unittest.proto";
-
 package proto2_nofieldpresence_unittest;
 
+import "google/protobuf/unittest.proto";
+
 // This proto includes every type of field in both singular and repeated
 // forms.
 message TestAllTypes {
@@ -53,65 +53,66 @@
   // Singular
   // TODO: remove 'optional' labels as soon as CL 69188077 is LGTM'd to make
   // 'optional' optional.
-     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;
+  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;
+  float optional_float = 11;
+  double optional_double = 12;
+  bool optional_bool = 13;
+  string optional_string = 14;
+  bytes optional_bytes = 15;
 
-  NestedMessage                        optional_nested_message  = 18;
-  ForeignMessage                       optional_foreign_message = 19;
-  protobuf_unittest.TestAllTypes         optional_proto2_message = 20;
+  NestedMessage optional_nested_message = 18;
+  ForeignMessage optional_foreign_message = 19;
+  protobuf_unittest.TestAllTypes optional_proto2_message = 20;
 
-  NestedEnum                           optional_nested_enum     = 21;
-  ForeignEnum                          optional_foreign_enum    = 22;
+  NestedEnum optional_nested_enum = 21;
+  ForeignEnum optional_foreign_enum = 22;
   // N.B.: proto2-enum-type fields not allowed, because their default values
   // might not be zero.
-  //optional protobuf_unittest.ForeignEnum          optional_proto2_enum     = 23;
+  // optional protobuf_unittest.ForeignEnum          optional_proto2_enum     =
+  // 23;
 
-  string optional_string_piece = 24 [ctype=STRING_PIECE];
-  string optional_cord = 25 [ctype=CORD];
+  string optional_string_piece = 24 [ctype = STRING_PIECE];
+  string optional_cord = 25 [ctype = CORD];
 
-  NestedMessage optional_lazy_message = 30 [lazy=true];
+  NestedMessage optional_lazy_message = 30 [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 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 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 NestedMessage                        repeated_nested_message  = 48;
-  repeated ForeignMessage                       repeated_foreign_message = 49;
-  repeated protobuf_unittest.TestAllTypes         repeated_proto2_message  = 50;
+  repeated NestedMessage repeated_nested_message = 48;
+  repeated ForeignMessage repeated_foreign_message = 49;
+  repeated protobuf_unittest.TestAllTypes repeated_proto2_message = 50;
 
-  repeated NestedEnum                           repeated_nested_enum     = 51;
-  repeated ForeignEnum                          repeated_foreign_enum    = 52;
+  repeated NestedEnum repeated_nested_enum = 51;
+  repeated ForeignEnum repeated_foreign_enum = 52;
 
-  repeated string repeated_string_piece = 54 [ctype=STRING_PIECE];
-  repeated string repeated_cord = 55 [ctype=CORD];
+  repeated string repeated_string_piece = 54 [ctype = STRING_PIECE];
+  repeated string repeated_cord = 55 [ctype = CORD];
 
-  repeated NestedMessage repeated_lazy_message = 57 [lazy=true];
+  repeated NestedMessage repeated_lazy_message = 57 [lazy = true];
 
   oneof oneof_field {
     uint32 oneof_uint32 = 111;
diff --git a/src/google/protobuf/unittest_no_generic_services.proto b/src/google/protobuf/unittest_no_generic_services.proto
index 57a0d16..7b18aaf 100644
--- a/src/google/protobuf/unittest_no_generic_services.proto
+++ b/src/google/protobuf/unittest_no_generic_services.proto
@@ -42,7 +42,9 @@
   extensions 1000 to max;
 }
 
-enum TestEnum { FOO = 1; }
+enum TestEnum {
+  FOO = 1;
+}
 
 extend TestMessage {
   optional int32 test_extension = 1000;
diff --git a/src/google/protobuf/unittest_optimize_for.proto b/src/google/protobuf/unittest_optimize_for.proto
index ee9cc7b..f01ae71 100644
--- a/src/google/protobuf/unittest_optimize_for.proto
+++ b/src/google/protobuf/unittest_optimize_for.proto
@@ -35,10 +35,11 @@
 // A proto file which uses optimize_for = CODE_SIZE.
 
 syntax = "proto2";
-import "google/protobuf/unittest.proto";
 
 package protobuf_unittest;
 
+import "google/protobuf/unittest.proto";
+
 option optimize_for = CODE_SIZE;
 
 message TestOptimizedForSize {
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum.proto b/src/google/protobuf/unittest_preserve_unknown_enum.proto
index 2f91332..ab51c00 100644
--- a/src/google/protobuf/unittest_preserve_unknown_enum.proto
+++ b/src/google/protobuf/unittest_preserve_unknown_enum.proto
@@ -31,8 +31,8 @@
 syntax = "proto3";
 
 package proto3_preserve_unknown_enum_unittest;
-option objc_class_prefix = "UnknownEnums";
 
+option objc_class_prefix = "UnknownEnums";
 option csharp_namespace = "Google.Protobuf.TestProtos";
 
 enum MyEnum {
@@ -51,7 +51,7 @@
 message MyMessage {
   MyEnum e = 1;
   repeated MyEnum repeated_e = 2;
-  repeated MyEnum repeated_packed_e = 3 [packed=true];
+  repeated MyEnum repeated_packed_e = 3 [packed = true];
   repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4;  // not packed
   oneof o {
     MyEnum oneof_e_1 = 5;
@@ -62,8 +62,8 @@
 message MyMessagePlusExtra {
   MyEnumPlusExtra e = 1;
   repeated MyEnumPlusExtra repeated_e = 2;
-  repeated MyEnumPlusExtra repeated_packed_e = 3 [packed=true];
-  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed=true];
+  repeated MyEnumPlusExtra repeated_packed_e = 3 [packed = true];
+  repeated MyEnumPlusExtra repeated_packed_unexpected_e = 4 [packed = true];
   oneof o {
     MyEnumPlusExtra oneof_e_1 = 5;
     MyEnumPlusExtra oneof_e_2 = 6;
diff --git a/src/google/protobuf/unittest_preserve_unknown_enum2.proto b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
index adf4296..dfce0e0 100644
--- a/src/google/protobuf/unittest_preserve_unknown_enum2.proto
+++ b/src/google/protobuf/unittest_preserve_unknown_enum2.proto
@@ -41,7 +41,7 @@
 message MyMessage {
   optional MyEnum e = 1;
   repeated MyEnum repeated_e = 2;
-  repeated MyEnum repeated_packed_e = 3 [packed=true];
+  repeated MyEnum repeated_packed_e = 3 [packed = true];
   repeated MyEnum repeated_packed_unexpected_e = 4;  // not packed
   oneof o {
     MyEnum oneof_e_1 = 5;
diff --git a/src/google/protobuf/unittest_well_known_types.proto b/src/google/protobuf/unittest_well_known_types.proto
index c907524..f030700 100644
--- a/src/google/protobuf/unittest_well_known_types.proto
+++ b/src/google/protobuf/unittest_well_known_types.proto
@@ -1,3 +1,33 @@
+// 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 = "proto3";
 
 package protobuf_unittest;
diff --git a/src/google/protobuf/unknown_field_set.cc b/src/google/protobuf/unknown_field_set.cc
index 74c358e..8b104f7 100644
--- a/src/google/protobuf/unknown_field_set.cc
+++ b/src/google/protobuf/unknown_field_set.cc
@@ -32,24 +32,26 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/unknown_field_set.h"
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.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/extension_set.h>
-#include <google/protobuf/generated_message_tctable_decl.h>
-#include <google/protobuf/generated_message_tctable_impl.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/internal/resize_uninitialized.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/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/parse_context.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -243,7 +245,7 @@
 bool UnknownFieldSet::SerializeToString(std::string* output) const {
   const size_t size =
       google::protobuf::internal::WireFormat::ComputeUnknownFieldsSize(*this);
-  STLStringResizeUninitializedAmortized(output, size);
+  absl::strings_internal::STLStringResizeUninitializedAmortized(output, size);
   google::protobuf::internal::WireFormat::SerializeUnknownFieldsToArray(
       *this, reinterpret_cast<uint8_t*>(const_cast<char*>(output->data())));
   return true;
@@ -347,4 +349,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/unknown_field_set.h b/src/google/protobuf/unknown_field_set.h
index 9aa2cbb..85e51a5 100644
--- a/src/google/protobuf/unknown_field_set.h
+++ b/src/google/protobuf/unknown_field_set.h
@@ -44,16 +44,17 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/parse_context.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
@@ -86,6 +87,8 @@
 class PROTOBUF_EXPORT UnknownFieldSet {
  public:
   UnknownFieldSet();
+  UnknownFieldSet(const UnknownFieldSet&) = delete;
+  UnknownFieldSet& operator=(const UnknownFieldSet&) = delete;
   ~UnknownFieldSet();
 
   // Remove all fields.
@@ -209,7 +212,6 @@
   }
 
   std::vector<UnknownField> fields_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(UnknownFieldSet);
 };
 
 namespace internal {
@@ -217,7 +219,7 @@
 inline void WriteVarint(uint32_t num, uint64_t val, UnknownFieldSet* unknown) {
   unknown->AddVarint(num, val);
 }
-inline void WriteLengthDelimited(uint32_t num, StringPiece val,
+inline void WriteLengthDelimited(uint32_t num, absl::string_view val,
                                  UnknownFieldSet* unknown) {
   unknown->AddLengthDelimited(num)->assign(val.data(), val.size());
 }
@@ -403,5 +405,5 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 #endif  // GOOGLE_PROTOBUF_UNKNOWN_FIELD_SET_H__
diff --git a/src/google/protobuf/unknown_field_set_unittest.cc b/src/google/protobuf/unknown_field_set_unittest.cc
index 7f9a598..9401e56 100644
--- a/src/google/protobuf/unknown_field_set_unittest.cc
+++ b/src/google/protobuf/unknown_field_set_unittest.cc
@@ -35,29 +35,31 @@
 // This test is testing a lot more than just the UnknownFieldSet class.  It
 // tests handling of unknown fields throughout the system.
 
-#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/unknown_field_set.h"
 
 #include <string>
-#include <unordered_set>
 #include <vector>
 
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_lite.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/mutex.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/stubs/callback.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
 #include <gmock/gmock.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/time.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/container/flat_hash_set.h"
+#include "absl/strings/cord.h"
+#include "absl/synchronization/mutex.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_lite.pb.h"
+#include "google/protobuf/wire_format.h"
+
 
 namespace google {
 namespace protobuf {
@@ -134,7 +136,7 @@
     }
   }
 
-  std::unordered_set<uint32_t> unknown_tags;
+  absl::flat_hash_set<uint32_t> unknown_tags;
   for (int i = 0; i < unknown_fields_->field_count(); i++) {
     unknown_tags.insert(unknown_fields_->field(i).number());
   }
@@ -204,15 +206,13 @@
   slow_buffer.resize(size);
   fast_buffer.resize(size);
 
-  uint8_t* target =
-      reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&fast_buffer));
+  uint8_t* target = reinterpret_cast<uint8_t*>(&fast_buffer[0]);
   uint8_t* result = WireFormat::SerializeUnknownFieldsToArray(
       empty_message_.unknown_fields(), target);
   EXPECT_EQ(size, result - target);
 
   {
-    io::ArrayOutputStream raw_stream(::google::protobuf::string_as_array(&slow_buffer), size,
-                                     1);
+    io::ArrayOutputStream raw_stream(&slow_buffer[0], size, 1);
     io::CodedOutputStream output_stream(&raw_stream);
     WireFormat::SerializeUnknownFields(empty_message_.unknown_fields(),
                                        &output_stream);
@@ -648,7 +648,7 @@
   }
 }
 
-#define MAKE_VECTOR(x) std::vector<int>(x, x + GOOGLE_ARRAYSIZE(x))
+#define MAKE_VECTOR(x) std::vector<int>(x, x + ABSL_ARRAYSIZE(x))
 TEST_F(UnknownFieldSetTest, DeleteByNumber) {
   CheckDeleteByNumber(std::vector<int>(), 1, std::vector<int>());
   static const int kTestFieldNumbers1[] = {1, 2, 3};
diff --git a/src/google/protobuf/util/BUILD.bazel b/src/google/protobuf/util/BUILD.bazel
new file mode 100644
index 0000000..404b346
--- /dev/null
+++ b/src/google/protobuf/util/BUILD.bazel
@@ -0,0 +1,280 @@
+################################################################################
+# Protocol Buffers C++ Utilities
+################################################################################
+
+load("@rules_cc//cc:defs.bzl", "cc_library", "cc_proto_library", "cc_test")
+load("@rules_pkg//:mappings.bzl", "pkg_files", "strip_prefix")
+load("@rules_proto//proto:defs.bzl", "proto_library")
+load("//build_defs:cpp_opts.bzl", "COPTS")
+
+cc_library(
+    name = "delimited_message_util",
+    srcs = ["delimited_message_util.cc"],
+    hdrs = ["delimited_message_util.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        "//:protobuf_lite",
+        "//src/google/protobuf/io",
+    ],
+)
+
+cc_test(
+    name = "delimited_message_util_test",
+    srcs = ["delimited_message_util_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":delimited_message_util",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "differencer",
+    srcs = [
+        "field_comparator.cc",
+        "message_differencer.cc",
+    ],
+    hdrs = [
+        "field_comparator.h",
+        "message_differencer.h",
+    ],
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        "//src/google/protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_test(
+    name = "field_comparator_test",
+    srcs = ["field_comparator_test.cc"],
+    deps = [
+        ":differencer",
+        ":message_differencer_unittest_cc_proto",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_test(
+    name = "message_differencer_unittest",
+    srcs = ["message_differencer_unittest.cc"],
+    copts = COPTS + select({
+        "//build_defs:config_msvc": [],
+        "//conditions:default": [
+            "-Wno-deprecated-declarations",
+        ],
+    }),
+    deps = [
+        ":differencer",
+        ":message_differencer_unittest_cc_proto",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf/testing",
+        "@com_google_absl//absl/functional:bind_front",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "field_mask_util",
+    srcs = ["field_mask_util.cc"],
+    hdrs = ["field_mask_util.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        "//src/google/protobuf",
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_test(
+    name = "field_mask_util_test",
+    srcs = ["field_mask_util_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":field_mask_util",
+        "//src/google/protobuf",
+        "//src/google/protobuf:cc_test_protos",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf/stubs",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "json_util",
+    hdrs = ["json_util.h"],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = ["//src/google/protobuf/json"],
+)
+
+cc_library(
+    name = "time_util",
+    srcs = ["time_util.cc"],
+    hdrs = ["time_util.h"],
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        "//src/google/protobuf",
+        "//src/google/protobuf/stubs",
+    ],
+)
+
+cc_test(
+    name = "time_util_test",
+    srcs = ["time_util_test.cc"],
+    deps = [
+        ":time_util",
+        "//src/google/protobuf",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+cc_library(
+    name = "type_resolver_util",
+    srcs = ["type_resolver_util.cc"],
+    hdrs = [
+        "type_resolver.h",
+        "type_resolver_util.h",
+    ],
+    copts = COPTS,
+    strip_include_prefix = "/src",
+    visibility = ["//:__subpackages__"],
+    deps = [
+        "//src/google/protobuf",
+        "//src/google/protobuf/io",
+        "//src/google/protobuf/stubs",
+        "@com_google_absl//absl/status",
+    ],
+)
+
+cc_test(
+    name = "type_resolver_util_test",
+    srcs = ["type_resolver_util_test.cc"],
+    copts = COPTS,
+    deps = [
+        ":json_format_cc_proto",
+        ":json_format_proto3_cc_proto",
+        ":json_util",
+        "//src/google/protobuf",
+        "//src/google/protobuf:test_util",
+        "//src/google/protobuf/testing",
+        "@com_google_googletest//:gtest",
+        "@com_google_googletest//:gtest_main",
+    ],
+)
+
+# Testonly protos
+
+filegroup(
+    name = "test_proto_srcs",
+    testonly = 1,
+    srcs = [
+        "json_format.proto",
+        "json_format_proto3.proto",
+        "message_differencer_unittest.proto",
+    ],
+    visibility = [
+        "//pkg:__pkg__",
+        "//python:__pkg__",
+    ],
+)
+
+proto_library(
+    name = "json_format_proto",
+    testonly = 1,
+    srcs = ["json_format.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:any_proto",
+        "//:duration_proto",
+        "//:field_mask_proto",
+        "//:struct_proto",
+        "//:test_protos",
+        "//:timestamp_proto",
+        "//:wrappers_proto",
+    ],
+)
+
+cc_proto_library(
+    name = "json_format_cc_proto",
+    testonly = 1,
+    visibility = ["//:__subpackages__"],
+    deps = [":json_format_proto"],
+)
+
+proto_library(
+    name = "json_format_proto3_proto",
+    testonly = 1,
+    srcs = ["json_format_proto3.proto"],
+    strip_import_prefix = "/src",
+    deps = [
+        "//:any_proto",
+        "//:duration_proto",
+        "//:field_mask_proto",
+        "//:struct_proto",
+        "//:test_protos",
+        "//:timestamp_proto",
+        "//:wrappers_proto",
+    ],
+)
+
+cc_proto_library(
+    name = "json_format_proto3_cc_proto",
+    testonly = 1,
+    visibility = ["//:__subpackages__"],
+    deps = [":json_format_proto3_proto"],
+)
+
+proto_library(
+    name = "message_differencer_unittest_proto",
+    testonly = 1,
+    srcs = ["message_differencer_unittest.proto"],
+    strip_import_prefix = "/src",
+    deps = ["//:any_proto"],
+)
+
+cc_proto_library(
+    name = "message_differencer_unittest_cc_proto",
+    testonly = 1,
+    deps = [":message_differencer_unittest_proto"],
+)
+
+################################################################################
+# Distribution packaging
+################################################################################
+
+pkg_files(
+    name = "dist_files",
+    srcs = glob(["**"]),
+    strip_prefix = strip_prefix.from_root(""),
+    visibility = ["//src:__pkg__"],
+)
+
+filegroup(
+    name = "test_srcs",
+    srcs = glob([
+        "*_test.cc",
+        "*unittest.cc",
+    ]),
+    visibility = ["//pkg:__pkg__"],
+)
diff --git a/src/google/protobuf/util/delimited_message_util.cc b/src/google/protobuf/util/delimited_message_util.cc
index fdc633f..1dcd943 100644
--- a/src/google/protobuf/util/delimited_message_util.cc
+++ b/src/google/protobuf/util/delimited_message_util.cc
@@ -31,8 +31,9 @@
 // Adapted from the patch of kenton@google.com (Kenton Varda)
 // See https://github.com/protocolbuffers/protobuf/pull/710 for details.
 
-#include <google/protobuf/util/delimited_message_util.h>
-#include <google/protobuf/io/coded_stream.h>
+#include "google/protobuf/util/delimited_message_util.h"
+
+#include "google/protobuf/io/coded_stream.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/delimited_message_util.h b/src/google/protobuf/util/delimited_message_util.h
index 78625cf..e52646f 100644
--- a/src/google/protobuf/util/delimited_message_util.h
+++ b/src/google/protobuf/util/delimited_message_util.h
@@ -37,18 +37,18 @@
 
 #include <ostream>
 
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
 namespace util {
 
-// Write a single size-delimited message from the given stream. Delimited
+// Write a single size-delimited message to the given stream. Delimited
 // format allows a single file or stream to contain multiple messages,
 // whereas normally writing multiple non-delimited messages to the same
 // stream would cause them to be merged. A delimited message is a varint
@@ -104,6 +104,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_DELIMITED_MESSAGE_UTIL_H__
diff --git a/src/google/protobuf/util/delimited_message_util_test.cc b/src/google/protobuf/util/delimited_message_util_test.cc
index 9483a64..9bf7fc8 100644
--- a/src/google/protobuf/util/delimited_message_util_test.cc
+++ b/src/google/protobuf/util/delimited_message_util_test.cc
@@ -31,14 +31,14 @@
 // Adapted from the patch of kenton@google.com (Kenton Varda)
 // See https://github.com/protocolbuffers/protobuf/pull/710 for details.
 
-#include <google/protobuf/util/delimited_message_util.h>
+#include "google/protobuf/util/delimited_message_util.h"
 
 #include <sstream>
 
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/field_comparator.cc b/src/google/protobuf/util/field_comparator.cc
index 5d8e865..bfab75a 100644
--- a/src/google/protobuf/util/field_comparator.cc
+++ b/src/google/protobuf/util/field_comparator.cc
@@ -30,16 +30,15 @@
 
 // Author: ksroka@google.com (Krzysztof Sroka)
 
-#include <google/protobuf/util/field_comparator.h>
+#include "google/protobuf/util/field_comparator.h"
 
 #include <limits>
 #include <string>
 
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/util/message_differencer.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/mathutil.h>
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/util/message_differencer.h"
+#include "google/protobuf/stubs/mathutil.h"
 
 namespace google {
 namespace protobuf {
@@ -130,7 +129,7 @@
 bool SimpleFieldComparator::CompareWithDifferencer(
     MessageDifferencer* differencer, const Message& message1,
     const Message& message2, const util::FieldContext* field_context) {
-  return differencer->Compare(message1, message2,
+  return differencer->Compare(message1, message2, false,
                               field_context->parent_fields());
 }
 
@@ -183,19 +182,23 @@
       return true;
     }
     // float_comparison_ == APPROXIMATE covers two use cases.
-    Tolerance* tolerance = FindOrNull(map_tolerance_, &field);
-    if (tolerance == NULL && has_default_tolerance_) {
-      tolerance = &default_tolerance_;
+    Tolerance* tolerance = nullptr;
+    if (has_default_tolerance_) tolerance = &default_tolerance_;
+
+    auto it = map_tolerance_.find(&field);
+    if (it != map_tolerance_.end()) {
+      tolerance = &it->second;
     }
-    if (tolerance == NULL) {
-      return MathUtil::AlmostEquals(value_1, value_2);
-    } else {
+
+    if (tolerance != nullptr) {
       // Use user-provided fraction and margin. Since they are stored as
       // doubles, we explicitly cast them to types of values provided. This
       // is very likely to fail if provided values are not numeric.
       return MathUtil::WithinFractionOrMargin(
           value_1, value_2, static_cast<T>(tolerance->fraction),
           static_cast<T>(tolerance->margin));
+    } else {
+      return MathUtil::AlmostEquals(value_1, value_2);
     }
   }
 }
diff --git a/src/google/protobuf/util/field_comparator.h b/src/google/protobuf/util/field_comparator.h
index 5706da3..1988b9e 100644
--- a/src/google/protobuf/util/field_comparator.h
+++ b/src/google/protobuf/util/field_comparator.h
@@ -39,10 +39,11 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/port.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -63,6 +64,8 @@
 class PROTOBUF_EXPORT FieldComparator {
  public:
   FieldComparator();
+  FieldComparator(const FieldComparator&) = delete;
+  FieldComparator& operator=(const FieldComparator&) = delete;
   virtual ~FieldComparator();
 
   enum ComparisonResult {
@@ -92,9 +95,6 @@
                                    const FieldDescriptor* field, int index_1,
                                    int index_2,
                                    const util::FieldContext* field_context) = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldComparator);
 };
 
 // Basic implementation of FieldComparator.  Supports three modes of floating
@@ -113,6 +113,8 @@
 
   // Creates new comparator with float comparison set to EXACT.
   SimpleFieldComparator();
+  SimpleFieldComparator(const SimpleFieldComparator&) = delete;
+  SimpleFieldComparator& operator=(const SimpleFieldComparator&) = delete;
 
   ~SimpleFieldComparator() override;
 
@@ -257,18 +259,11 @@
   // Field-specific float/double tolerances, which override any default for
   // those particular fields.
   ToleranceMap map_tolerance_;
-
-  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
-{
+class PROTOBUF_EXPORT DefaultFieldComparator PROTOBUF_FUTURE_FINAL
+    : public SimpleFieldComparator {
  public:
   ComparisonResult Compare(const Message& message_1, const Message& message_2,
                            const FieldDescriptor* field, int index_1,
@@ -283,6 +278,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_FIELD_COMPARATOR_H__
diff --git a/src/google/protobuf/util/field_comparator_test.cc b/src/google/protobuf/util/field_comparator_test.cc
index b680277..1eb7f62 100644
--- a/src/google/protobuf/util/field_comparator_test.cc
+++ b/src/google/protobuf/util/field_comparator_test.cc
@@ -30,14 +30,14 @@
 
 // Author: ksroka@google.com (Krzysztof Sroka)
 
-#include <google/protobuf/util/field_comparator.h>
+#include "google/protobuf/util/field_comparator.h"
 
 #include <limits>
 
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/descriptor.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/mathutil.h>
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/stubs/mathutil.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/field_mask_util.cc b/src/google/protobuf/util/field_mask_util.cc
index 700e590..ef47730 100644
--- a/src/google/protobuf/util/field_mask_util.cc
+++ b/src/google/protobuf/util/field_mask_util.cc
@@ -28,16 +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/util/field_mask_util.h>
+#include "google/protobuf/util/field_mask_util.h"
 
 #include <cstdint>
+#include <map>
+#include <string>
+#include <vector>
 
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/stubs/map_util.h>
+#include "absl/strings/str_join.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/message.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -46,19 +49,19 @@
 using google::protobuf::FieldMask;
 
 std::string FieldMaskUtil::ToString(const FieldMask& mask) {
-  return Join(mask.paths(), ",");
+  return absl::StrJoin(mask.paths(), ",");
 }
 
-void FieldMaskUtil::FromString(StringPiece str, FieldMask* out) {
+void FieldMaskUtil::FromString(absl::string_view str, FieldMask* out) {
   out->Clear();
-  std::vector<std::string> paths = Split(str, ",");
+  std::vector<std::string> paths = absl::StrSplit(str, ',');
   for (const std::string& path : paths) {
     if (path.empty()) continue;
     out->add_paths(path);
   }
 }
 
-bool FieldMaskUtil::SnakeCaseToCamelCase(StringPiece input,
+bool FieldMaskUtil::SnakeCaseToCamelCase(absl::string_view input,
                                          std::string* output) {
   output->clear();
   bool after_underscore = false;
@@ -88,7 +91,7 @@
   return true;
 }
 
-bool FieldMaskUtil::CamelCaseToSnakeCase(StringPiece input,
+bool FieldMaskUtil::CamelCaseToSnakeCase(absl::string_view input,
                                          std::string* output) {
   output->clear();
   for (const char c : input) {
@@ -122,9 +125,9 @@
   return true;
 }
 
-bool FieldMaskUtil::FromJsonString(StringPiece str, FieldMask* out) {
+bool FieldMaskUtil::FromJsonString(absl::string_view str, FieldMask* out) {
   out->Clear();
-  std::vector<std::string> paths = Split(str, ",");
+  std::vector<std::string> paths = absl::StrSplit(str, ',');
   for (const std::string& path : paths) {
     if (path.empty()) continue;
     std::string snakecase_path;
@@ -137,12 +140,12 @@
 }
 
 bool FieldMaskUtil::GetFieldDescriptors(
-    const Descriptor* descriptor, StringPiece path,
+    const Descriptor* descriptor, absl::string_view path,
     std::vector<const FieldDescriptor*>* field_descriptors) {
   if (field_descriptors != nullptr) {
     field_descriptors->clear();
   }
-  std::vector<std::string> parts = Split(path, ".");
+  std::vector<std::string> parts = absl::StrSplit(path, '.');
   for (const std::string& field_name : parts) {
     if (descriptor == nullptr) {
       return false;
@@ -185,6 +188,8 @@
 class FieldMaskTree {
  public:
   FieldMaskTree();
+  FieldMaskTree(const FieldMaskTree&) = delete;
+  FieldMaskTree& operator=(const FieldMaskTree&) = delete;
   ~FieldMaskTree();
 
   void MergeFromFieldMask(const FieldMask& mask);
@@ -246,21 +251,19 @@
  private:
   struct Node {
     Node() {}
+    Node(const Node&) = delete;
+    Node& operator=(const Node&) = delete;
 
     ~Node() { ClearChildren(); }
 
     void ClearChildren() {
-      for (std::map<std::string, Node*>::iterator it = children.begin();
-           it != children.end(); ++it) {
-        delete it->second;
+      for (auto& p : children) {
+        delete p.second;
       }
       children.clear();
     }
 
     std::map<std::string, Node*> children;
-
-   private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
   };
 
   // Merge a sub-tree to mask. This method adds the field paths represented
@@ -288,8 +291,6 @@
   bool TrimMessage(const Node* node, Message* message);
 
   Node root_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(FieldMaskTree);
 };
 
 FieldMaskTree::FieldMaskTree() {}
@@ -325,7 +326,7 @@
 }
 
 void FieldMaskTree::AddPath(const std::string& path) {
-  std::vector<std::string> parts = Split(path, ".");
+  std::vector<std::string> parts = absl::StrSplit(path, '.');
   if (parts.empty()) {
     return;
   }
@@ -358,7 +359,7 @@
     // code below.
     return;
   }
-  std::vector<std::string> parts = Split(path, ".");
+  std::vector<std::string> parts = absl::StrSplit(path, '.');
   if (parts.empty()) {
     return;
   }
@@ -389,14 +390,11 @@
         node->children[current_descriptor->field(j)->name()] = new Node();
       }
     }
-    if (ContainsKey(node->children, parts[i])) {
-      node = node->children[parts[i]];
-      if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
-        current_descriptor = field_descriptor->message_type();
-      }
-    } else {
-      // Path does not exist.
-      return;
+    auto it = node->children.find(parts[i]);
+    if (it == node->children.end()) return;
+    node = it->second;
+    if (field_descriptor->cpp_type() == FieldDescriptor::CPPTYPE_MESSAGE) {
+      current_descriptor = field_descriptor->message_type();
     }
   }
   // Remove path.
@@ -410,7 +408,7 @@
 }
 
 void FieldMaskTree::IntersectPath(const std::string& path, FieldMaskTree* out) {
-  std::vector<std::string> parts = Split(path, ".");
+  std::vector<std::string> parts = absl::StrSplit(path, '.');
   if (parts.empty()) {
     return;
   }
@@ -422,12 +420,12 @@
       }
       return;
     }
-    const Node* result = FindPtrOrNull(node->children, node_name);
-    if (result == nullptr) {
+    auto it = node->children.find(node_name);
+    if (it == node->children.end()) {
       // No intersection found.
       return;
     }
-    node = result;
+    node = it->second;
   }
   // Now we found a matching node with the given path. Add all leaf nodes
   // to out.
@@ -665,7 +663,7 @@
   tree.MergeToFieldMask(out);
 }
 
-bool FieldMaskUtil::IsPathInFieldMask(StringPiece path,
+bool FieldMaskUtil::IsPathInFieldMask(absl::string_view path,
                                       const FieldMask& mask) {
   for (int i = 0; i < mask.paths_size(); ++i) {
     const std::string& mask_path = mask.paths(i);
diff --git a/src/google/protobuf/util/field_mask_util.h b/src/google/protobuf/util/field_mask_util.h
index d51a332..03fb6a1 100644
--- a/src/google/protobuf/util/field_mask_util.h
+++ b/src/google/protobuf/util/field_mask_util.h
@@ -35,13 +35,14 @@
 
 #include <cstdint>
 #include <string>
+#include <vector>
 
-#include <google/protobuf/field_mask.pb.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/descriptor.h>
+#include "google/protobuf/field_mask.pb.h"
+#include "absl/strings/string_view.h"
+#include "google/protobuf/descriptor.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -54,7 +55,7 @@
   // Converts FieldMask to/from string, formatted by separating each path
   // with a comma (e.g., "foo_bar,baz.quz").
   static std::string ToString(const FieldMask& mask);
-  static void FromString(StringPiece str, FieldMask* out);
+  static void FromString(absl::string_view str, FieldMask* out);
 
   // Populates the FieldMask with the paths corresponding to the fields with the
   // given numbers, after checking that all field numbers are valid.
@@ -76,19 +77,19 @@
   // style conforming (i.e., not snake_case when converted to string, or not
   // camelCase when converted from string), the conversion will fail.
   static bool ToJsonString(const FieldMask& mask, std::string* out);
-  static bool FromJsonString(StringPiece str, FieldMask* out);
+  static bool FromJsonString(absl::string_view str, FieldMask* out);
 
   // Get the descriptors of the fields which the given path from the message
   // descriptor traverses, if field_descriptors is not null.
   // Return false if the path is not valid, and the content of field_descriptors
   // is unspecified.
   static bool GetFieldDescriptors(
-      const Descriptor* descriptor, StringPiece path,
+      const Descriptor* descriptor, absl::string_view path,
       std::vector<const FieldDescriptor*>* field_descriptors);
 
   // Checks whether the given path is valid for type T.
   template <typename T>
-  static bool IsValidPath(StringPiece path) {
+  static bool IsValidPath(absl::string_view path) {
     return GetFieldDescriptors(T::descriptor(), path, nullptr);
   }
 
@@ -106,7 +107,7 @@
   // Adds a path to FieldMask after checking whether the given path is valid.
   // This method check-fails if the path is not a valid path for type T.
   template <typename T>
-  static void AddPathToFieldMask(StringPiece path, FieldMask* mask) {
+  static void AddPathToFieldMask(absl::string_view path, FieldMask* mask) {
     GOOGLE_CHECK(IsValidPath<T>(path)) << path;
     mask->add_paths(std::string(path));
   }
@@ -159,7 +160,7 @@
   // "foo.bar" covers all paths like "foo.bar.baz", "foo.bar.quz.x", etc.
   // Also note that parent paths are not covered by explicit child path, i.e.
   // "foo.bar" does NOT cover "foo", even if "bar" is the only child.
-  static bool IsPathInFieldMask(StringPiece path, const FieldMask& mask);
+  static bool IsPathInFieldMask(absl::string_view path, const FieldMask& mask);
 
   class MergeOptions;
   // Merges fields specified in a FieldMask into another message.
@@ -194,7 +195,7 @@
   // Note that the input can contain characters not allowed in C identifiers.
   // For example, "foo_bar,baz_quz" will be converted to "fooBar,bazQuz"
   // successfully.
-  static bool SnakeCaseToCamelCase(StringPiece input,
+  static bool SnakeCaseToCamelCase(absl::string_view input,
                                    std::string* output);
   // Converts a field name from camelCase to snake_case:
   //   1. Every uppercase letter is converted to lowercase with an additional
@@ -208,7 +209,7 @@
   // Note that the input can contain characters not allowed in C identifiers.
   // For example, "fooBar,bazQuz" will be converted to "foo_bar,baz_quz"
   // successfully.
-  static bool CamelCaseToSnakeCase(StringPiece input,
+  static bool CamelCaseToSnakeCase(absl::string_view input,
                                    std::string* output);
 };
 
@@ -258,6 +259,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_FIELD_MASK_UTIL_H__
diff --git a/src/google/protobuf/util/field_mask_util_test.cc b/src/google/protobuf/util/field_mask_util_test.cc
index bcad739..fcfaa19 100644
--- a/src/google/protobuf/util/field_mask_util_test.cc
+++ b/src/google/protobuf/util/field_mask_util_test.cc
@@ -28,18 +28,18 @@
 // (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/util/field_mask_util.h>
+#include "google/protobuf/util/field_mask_util.h"
 
 #include <algorithm>
 #include <cstdint>
 #include <vector>
 
-#include <google/protobuf/field_mask.pb.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/unittest.pb.h>
+#include "google/protobuf/field_mask.pb.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/util/internal/constants.h b/src/google/protobuf/util/internal/constants.h
deleted file mode 100644
index 8bded86..0000000
--- a/src/google/protobuf/util/internal/constants.h
+++ /dev/null
@@ -1,101 +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_UTIL_INTERNAL_CONSTANTS_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__
-
-#include <cstdint>
-
-#include <google/protobuf/stubs/common.h>
-
-// This file contains constants used by //net/proto2/util/converter.
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-// Prefix for type URLs.
-const char kTypeServiceBaseUrl[] = "type.googleapis.com";
-
-// Format string for RFC3339 timestamp formatting.
-const char kRfc3339TimeFormat[] = "%E4Y-%m-%dT%H:%M:%S";
-
-// Same as above, but the year value is not zero-padded i.e. this accepts
-// timestamps like "1-01-0001T23:59:59Z" instead of "0001-01-0001T23:59:59Z".
-const char kRfc3339TimeFormatNoPadding[] = "%Y-%m-%dT%H:%M:%S";
-
-// 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_t kTimestampMaxSeconds = 253402300799LL;
-
-// Minimum seconds allowed in a google.protobuf.Duration value.
-const int64_t kDurationMinSeconds = -315576000000LL;
-
-// Maximum seconds allowed in a google.protobuf.Duration value.
-const int64_t kDurationMaxSeconds = 315576000000LL;
-
-// Nano seconds in a second.
-const int32_t kNanosPerSecond = 1000000000;
-
-// Type url representing NULL values in google.protobuf.Struct type.
-const char kStructNullValueTypeUrl[] =
-    "type.googleapis.com/google.protobuf.NullValue";
-
-// Type string for google.protobuf.Struct
-const char kStructType[] = "google.protobuf.Struct";
-
-// Type string for struct.proto's google.protobuf.Value value type.
-const char kStructValueType[] = "google.protobuf.Value";
-
-// Type string for struct.proto's google.protobuf.ListValue value type.
-const char kStructListValueType[] = "google.protobuf.ListValue";
-
-// Type string for google.protobuf.Timestamp
-const char kTimestampType[] = "google.protobuf.Timestamp";
-
-// Type string for google.protobuf.Duration
-const char kDurationType[] = "google.protobuf.Duration";
-
-// Type URL for struct value type google.protobuf.Value
-const char kStructValueTypeUrl[] = "type.googleapis.com/google.protobuf.Value";
-
-// Type string for google.protobuf.Any
-const char kAnyType[] = "google.protobuf.Any";
-
-// The protobuf option name of jspb.message_id;
-const char kOptionJspbMessageId[] = "jspb.message_id";
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_CONSTANTS_H__
diff --git a/src/google/protobuf/util/internal/datapiece.cc b/src/google/protobuf/util/internal/datapiece.cc
deleted file mode 100644
index 3e7aa84..0000000
--- a/src/google/protobuf/util/internal/datapiece.cc
+++ /dev/null
@@ -1,441 +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 <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/stubs/status.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/mathutil.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-using util::Status;
-
-namespace {
-
-template <typename To, typename From>
-util::StatusOr<To> ValidateNumberConversion(To after, From before) {
-  if (after == before &&
-      MathUtil::Sign<From>(before) == MathUtil::Sign<To>(after)) {
-    return after;
-  } else {
-    return util::InvalidArgumentError(
-        std::is_integral<From>::value       ? ValueAsString(before)
-        : std::is_same<From, double>::value ? DoubleAsString(before)
-                                            : FloatAsString(before));
-  }
-}
-
-// For general conversion between
-//     int32, int64, uint32, uint64, double and float
-// except conversion between double and float.
-template <typename To, typename From>
-util::StatusOr<To> NumberConvertAndCheck(From before) {
-  if (std::is_same<From, To>::value) return before;
-
-  To after = static_cast<To>(before);
-  return ValidateNumberConversion(after, before);
-}
-
-// For conversion to integer types (int32, int64, uint32, uint64) from floating
-// point types (double, float) only.
-template <typename To, typename From>
-util::StatusOr<To> FloatingPointToIntConvertAndCheck(From before) {
-  if (std::is_same<From, To>::value) return before;
-
-  To after = static_cast<To>(before);
-  return ValidateNumberConversion(after, before);
-}
-
-// For conversion between double and float only.
-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);
-}
-
-util::StatusOr<float> DoubleToFloat(double before) {
-  if (std::isnan(before)) {
-    return std::numeric_limits<float>::quiet_NaN();
-  } else if (!std::isfinite(before)) {
-    // Converting a double +inf/-inf to float should just work.
-    return static_cast<float>(before);
-  } else if (before > std::numeric_limits<float>::max() ||
-             before < -std::numeric_limits<float>::max()) {
-    // Some doubles are larger than the largest float, but after
-    // rounding they will be equal to the largest float.
-    // We can't just attempt the conversion because that has UB if
-    // the value really is out-of-range.
-    // Here we take advantage that 1/2-ing a large floating point
-    // will not lose precision.
-    double half_before = before * 0.5;
-    if (half_before < std::numeric_limits<float>::max() &&
-        half_before > -std::numeric_limits<float>::max()) {
-      const float half_fmax = std::numeric_limits<float>::max() * 0.5f;
-      // If after being cut in half, the value is less than the largest float,
-      // then it's safe to convert it to float.  Importantly, this conversion
-      // rounds in the same way that the original does.
-      float half_after = static_cast<float>(half_before);
-      if (half_after <= half_fmax && half_after >= -half_fmax) {
-        return half_after + half_after;
-      }
-    }
-    // Double value outside of the range of float.
-    return util::InvalidArgumentError(DoubleAsString(before));
-  } else {
-    return static_cast<float>(before);
-  }
-}
-
-}  // namespace
-
-util::StatusOr<int32_t> DataPiece::ToInt32() const {
-  if (type_ == TYPE_STRING)
-    return StringToNumber<int32_t>(safe_strto32);
-
-  if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<int32_t, double>(double_);
-
-  if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<int32_t, float>(float_);
-
-  return GenericConvert<int32_t>();
-}
-
-util::StatusOr<uint32_t> DataPiece::ToUint32() const {
-  if (type_ == TYPE_STRING)
-    return StringToNumber<uint32_t>(safe_strtou32);
-
-  if (type_ == TYPE_DOUBLE)
-    return FloatingPointToIntConvertAndCheck<uint32_t, double>(double_);
-
-  if (type_ == TYPE_FLOAT)
-    return FloatingPointToIntConvertAndCheck<uint32_t, float>(float_);
-
-  return GenericConvert<uint32_t>();
-}
-
-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_);
-  }
-  if (type_ == TYPE_STRING) {
-    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();
-    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 util::InvalidArgumentError(StrCat("\"", str_, "\""));
-    } else {
-      return value;
-    }
-  }
-  return GenericConvert<double>();
-}
-
-util::StatusOr<float> DataPiece::ToFloat() const {
-  if (type_ == TYPE_DOUBLE) {
-    return DoubleToFloat(double_);
-  }
-  if (type_ == TYPE_STRING) {
-    if (str_ == "Infinity") return std::numeric_limits<float>::infinity();
-    if (str_ == "-Infinity") return -std::numeric_limits<float>::infinity();
-    if (str_ == "NaN") return std::numeric_limits<float>::quiet_NaN();
-    // SafeStrToFloat() is used instead of safe_strtof() because the later
-    // does not fail on inputs like SimpleDtoa(DBL_MAX).
-    return StringToNumber<float>(SafeStrToFloat);
-  }
-  return GenericConvert<float>();
-}
-
-util::StatusOr<bool> DataPiece::ToBool() const {
-  switch (type_) {
-    case TYPE_BOOL:
-      return bool_;
-    case TYPE_STRING:
-      return StringToNumber<bool>(safe_strtob);
-    default:
-      return util::InvalidArgumentError(
-          ValueAsStringOrDefault("Wrong type. Cannot convert to Bool."));
-  }
-}
-
-util::StatusOr<std::string> DataPiece::ToString() const {
-  switch (type_) {
-    case TYPE_STRING:
-      return std::string(str_);
-    case TYPE_BYTES: {
-      std::string base64;
-      Base64Escape(str_, &base64);
-      return base64;
-    }
-    default:
-      return util::InvalidArgumentError(
-          ValueAsStringOrDefault("Cannot convert to string."));
-  }
-}
-
-std::string DataPiece::ValueAsStringOrDefault(
-    StringPiece default_string) const {
-  switch (type_) {
-    case TYPE_INT32:
-      return StrCat(i32_);
-    case TYPE_INT64:
-      return StrCat(i64_);
-    case TYPE_UINT32:
-      return StrCat(u32_);
-    case TYPE_UINT64:
-      return StrCat(u64_);
-    case TYPE_DOUBLE:
-      return DoubleAsString(double_);
-    case TYPE_FLOAT:
-      return FloatAsString(float_);
-    case TYPE_BOOL:
-      return SimpleBtoa(bool_);
-    case TYPE_STRING:
-      return StrCat("\"", str_.ToString(), "\"");
-    case TYPE_BYTES: {
-      std::string base64;
-      WebSafeBase64Escape(str_, &base64);
-      return StrCat("\"", base64, "\"");
-    }
-    case TYPE_NULL:
-      return "null";
-    default:
-      return std::string(default_string);
-  }
-}
-
-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 util::InvalidArgumentError(
-          ValueAsStringOrDefault("Invalid data in input."));
-    }
-    return decoded;
-  } else {
-    return util::InvalidArgumentError(ValueAsStringOrDefault(
-        "Wrong type. Only String or Bytes can be converted to Bytes."));
-  }
-}
-
-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) {
-    // First try the given value as a name.
-    std::string enum_name = std::string(str_);
-    const google::protobuf::EnumValue* value =
-        FindEnumValueByNameOrNull(enum_type, enum_name);
-    if (value != nullptr) return value->number();
-
-    // Check if int version of enum is sent as string.
-    util::StatusOr<int32_t> int_value = ToInt32();
-    if (int_value.ok()) {
-      if (const google::protobuf::EnumValue* enum_value =
-              FindEnumValueByNumberOrNull(enum_type, int_value.value())) {
-        return enum_value->number();
-      }
-    }
-
-    // Next try a normalized name.
-    bool should_normalize_enum =
-        case_insensitive_enum_parsing || use_lower_camel_for_enums;
-    if (should_normalize_enum) {
-      for (std::string::iterator it = enum_name.begin(); it != enum_name.end();
-           ++it) {
-        *it = *it == '-' ? '_' : ascii_toupper(*it);
-      }
-      value = FindEnumValueByNameOrNull(enum_type, enum_name);
-      if (value != nullptr) return value->number();
-    }
-
-    // If use_lower_camel_for_enums is true try with enum name without
-    // underscore. This will also accept camel case names as the enum_name has
-    // been normalized before.
-    if (use_lower_camel_for_enums) {
-      value = FindEnumValueByNameWithoutUnderscoreOrNull(enum_type, enum_name);
-      if (value != nullptr) return value->number();
-    }
-
-    // If ignore_unknown_enum_values is true an unknown enum value is ignored.
-    if (ignore_unknown_enum_values) {
-      *is_unknown_enum_value = true;
-      if (enum_type->enumvalue_size() > 0) {
-        return enum_type->enumvalue(0).number();
-      }
-    }
-  } else {
-    // We don't need to check whether the value is actually declared in the
-    // enum because we preserve unknown enum values as well.
-    return ToInt32();
-  }
-  return util::InvalidArgumentError(
-      ValueAsStringOrDefault("Cannot find enum with given value."));
-}
-
-template <typename To>
-util::StatusOr<To> DataPiece::GenericConvert() const {
-  switch (type_) {
-    case TYPE_INT32:
-      return NumberConvertAndCheck<To, int32_t>(i32_);
-    case TYPE_INT64:
-      return NumberConvertAndCheck<To, int64_t>(i64_);
-    case TYPE_UINT32:
-      return NumberConvertAndCheck<To, uint32_t>(u32_);
-    case TYPE_UINT64:
-      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 util::InvalidArgumentError(ValueAsStringOrDefault(
-          "Wrong type. Bool, Enum, String and Cord not supported in "
-          "GenericConvert."));
-  }
-}
-
-template <typename To>
-util::StatusOr<To> DataPiece::StringToNumber(bool (*func)(StringPiece,
-                                                          To*)) const {
-  if (str_.size() > 0 && (str_[0] == ' ' || str_[str_.size() - 1] == ' ')) {
-    return util::InvalidArgumentError(StrCat("\"", str_, "\""));
-  }
-  To result;
-  if (func(str_, &result)) return result;
-  return util::InvalidArgumentError(
-      StrCat("\"", std::string(str_), "\""));
-}
-
-bool DataPiece::DecodeBase64(StringPiece src, std::string* dest) const {
-  // Try web-safe decode first, if it fails, try the non-web-safe decode.
-  if (WebSafeBase64Unescape(src, dest)) {
-    if (use_strict_base64_decoding_) {
-      // In strict mode, check if the escaped version gives us the same value as
-      // unescaped.
-      std::string encoded;
-      // WebSafeBase64Escape does no padding by default.
-      WebSafeBase64Escape(*dest, &encoded);
-      // Remove trailing padding '=' characters before comparison.
-      StringPiece src_no_padding = StringPiece(src).substr(
-          0, HasSuffixString(src, "=") ? src.find_last_not_of('=') + 1
-                                      : src.length());
-      return encoded == src_no_padding;
-    }
-    return true;
-  }
-
-  if (Base64Unescape(src, dest)) {
-    if (use_strict_base64_decoding_) {
-      std::string encoded;
-      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());
-      return encoded == src_no_padding;
-    }
-    return true;
-  }
-
-  return false;
-}
-
-void DataPiece::InternalCopy(const DataPiece& other) {
-  type_ = other.type_;
-  use_strict_base64_decoding_ = other.use_strict_base64_decoding_;
-  switch (type_) {
-    case TYPE_INT32:
-    case TYPE_INT64:
-    case TYPE_UINT32:
-    case TYPE_UINT64:
-    case TYPE_DOUBLE:
-    case TYPE_FLOAT:
-    case TYPE_BOOL:
-    case TYPE_ENUM:
-    case TYPE_NULL:
-    case TYPE_BYTES:
-    case TYPE_STRING: {
-      str_ = other.str_;
-      break;
-    }
-  }
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/datapiece.h b/src/google/protobuf/util/internal/datapiece.h
deleted file mode 100644
index 6d08349..0000000
--- a/src/google/protobuf/util/internal/datapiece.h
+++ /dev/null
@@ -1,219 +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_UTIL_INTERNAL_DATAPIECE_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_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/statusor.h>
-#include <google/protobuf/stubs/strutil.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-class ProtoWriter;
-
-// Container for a single piece of data together with its data type.
-//
-// For primitive types (int32, int64, uint32, uint64, double, float, bool),
-// the data is stored by value.
-//
-// For string, a StringPiece is stored. For Cord, a pointer to Cord is stored.
-// Just like StringPiece, the DataPiece class does not own the storage for
-// the actual string or Cord, so it is the user's responsibility to guarantee
-// that the underlying storage is still valid when the DataPiece is accessed.
-class PROTOBUF_EXPORT DataPiece {
- public:
-  // Identifies data type of the value.
-  // These are the types supported by DataPiece.
-  enum Type {
-    TYPE_INT32 = 1,
-    TYPE_INT64 = 2,
-    TYPE_UINT32 = 3,
-    TYPE_UINT64 = 4,
-    TYPE_DOUBLE = 5,
-    TYPE_FLOAT = 6,
-    TYPE_BOOL = 7,
-    TYPE_ENUM = 8,
-    TYPE_STRING = 9,
-    TYPE_BYTES = 10,
-    TYPE_NULL = 11,  // explicit NULL type
-  };
-
-  // Constructors and Destructor
-  explicit DataPiece(const int32_t value)
-      : type_(TYPE_INT32), i32_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const int64_t value)
-      : type_(TYPE_INT64), i64_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const uint32_t value)
-      : type_(TYPE_UINT32), u32_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const uint64_t value)
-      : type_(TYPE_UINT64), u64_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const double value)
-      : type_(TYPE_DOUBLE),
-        double_(value),
-        use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const float value)
-      : type_(TYPE_FLOAT), float_(value), use_strict_base64_decoding_(false) {}
-  explicit DataPiece(const bool value)
-      : type_(TYPE_BOOL), bool_(value), use_strict_base64_decoding_(false) {}
-  DataPiece(StringPiece value, bool use_strict_base64_decoding)
-      : type_(TYPE_STRING),
-        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_(value),
-        use_strict_base64_decoding_(use_strict_base64_decoding) {}
-
-  DataPiece(const DataPiece& r) : type_(r.type_) { InternalCopy(r); }
-
-  DataPiece& operator=(const DataPiece& x) {
-    InternalCopy(x);
-    return *this;
-  }
-
-  static DataPiece NullData() { return DataPiece(TYPE_NULL, 0); }
-
-  virtual ~DataPiece() {
-  }
-
-  // Accessors
-  Type type() const { return type_; }
-
-  bool use_strict_base64_decoding() { return use_strict_base64_decoding_; }
-
-  StringPiece str() const {
-    GOOGLE_LOG_IF(DFATAL, type_ != TYPE_STRING) << "Not a string type.";
-    return str_;
-  }
-
-
-  // Parses, casts or converts the value stored in the DataPiece into an int32.
-  util::StatusOr<int32_t> ToInt32() const;
-
-  // Parses, casts or converts the value stored in the DataPiece into a uint32.
-  util::StatusOr<uint32_t> ToUint32() const;
-
-  // Parses, casts or converts the value stored in the DataPiece into an int64.
-  util::StatusOr<int64_t> ToInt64() const;
-
-  // Parses, casts or converts the value stored in the DataPiece into a uint64.
-  util::StatusOr<uint64_t> ToUint64() const;
-
-  // Parses, casts or converts the value stored in the DataPiece into a double.
-  util::StatusOr<double> ToDouble() const;
-
-  // Parses, casts or converts the value stored in the DataPiece into a float.
-  util::StatusOr<float> ToFloat() const;
-
-  // Parses, casts or converts the value stored in the DataPiece into a bool.
-  util::StatusOr<bool> ToBool() const;
-
-  // Parses, casts or converts the value stored in the DataPiece into a string.
-  util::StatusOr<std::string> ToString() const;
-
-  // Tries to convert the value contained in this datapiece to string. If the
-  // conversion fails, it returns the default_string.
-  std::string ValueAsStringOrDefault(StringPiece default_string) const;
-
-  util::StatusOr<std::string> ToBytes() const;
-
- private:
-  friend class ProtoWriter;
-
-  // Disallow implicit constructor.
-  DataPiece();
-
-  // Helper to create NULL or ENUM types.
-  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;
-
-  // For numeric conversion between
-  //     int32, int64, uint32, uint64, double, float and bool
-  template <typename To>
-  util::StatusOr<To> GenericConvert() const;
-
-  // 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;
-
-  // Decodes a base64 string. Returns true on success.
-  bool DecodeBase64(StringPiece src, std::string* dest) const;
-
-  // Helper function to initialize this DataPiece with 'other'.
-  void InternalCopy(const DataPiece& other);
-
-  // Data type for this piece of data.
-  Type type_;
-
-  // Stored piece of data.
-  union {
-    int32_t i32_;
-    int64_t i64_;
-    uint32_t u32_;
-    uint64_t u64_;
-    double double_;
-    float float_;
-    bool bool_;
-    StringPiece str_;
-  };
-
-  // Uses a stricter version of base64 decoding for byte fields.
-  bool use_strict_base64_decoding_;
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_DATAPIECE_H__
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.cc b/src/google/protobuf/util/internal/default_value_objectwriter.cc
deleted file mode 100644
index 7f61cda..0000000
--- a/src/google/protobuf/util/internal/default_value_objectwriter.cc
+++ /dev/null
@@ -1,642 +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 <google/protobuf/util/internal/default_value_objectwriter.h>
-
-#include <cstdint>
-#include <unordered_map>
-
-#include <google/protobuf/util/internal/constants.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/map_util.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-namespace {
-// Helper function to convert string value to given data type by calling the
-// passed converter function on the DataPiece created from "value" argument.
-// If value is empty or if conversion fails, the default_value is returned.
-template <typename T>
-T ConvertTo(StringPiece value,
-            util::StatusOr<T> (DataPiece::*converter_fn)() const,
-            T default_value) {
-  if (value.empty()) return default_value;
-  util::StatusOr<T> result = (DataPiece(value, true).*converter_fn)();
-  return result.ok() ? result.value() : default_value;
-}
-}  // namespace
-
-DefaultValueObjectWriter::DefaultValueObjectWriter(
-    TypeResolver* type_resolver, const google::protobuf::Type& type,
-    ObjectWriter* ow)
-    : typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
-      own_typeinfo_(true),
-      type_(type),
-      current_(nullptr),
-      root_(nullptr),
-      suppress_empty_list_(false),
-      preserve_proto_field_names_(false),
-      use_ints_for_enums_(false),
-      ow_(ow) {}
-
-DefaultValueObjectWriter::~DefaultValueObjectWriter() {
-  if (own_typeinfo_) {
-    delete typeinfo_;
-  }
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBool(
-    StringPiece name, bool value) {
-  if (current_ == nullptr) {
-    ow_->RenderBool(name, value);
-  } else {
-    RenderDataPiece(name, DataPiece(value));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt32(
-    StringPiece name, int32_t value) {
-  if (current_ == nullptr) {
-    ow_->RenderInt32(name, value);
-  } else {
-    RenderDataPiece(name, DataPiece(value));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint32(
-    StringPiece name, uint32_t value) {
-  if (current_ == nullptr) {
-    ow_->RenderUint32(name, value);
-  } else {
-    RenderDataPiece(name, DataPiece(value));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderInt64(
-    StringPiece name, int64_t value) {
-  if (current_ == nullptr) {
-    ow_->RenderInt64(name, value);
-  } else {
-    RenderDataPiece(name, DataPiece(value));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderUint64(
-    StringPiece name, uint64_t value) {
-  if (current_ == nullptr) {
-    ow_->RenderUint64(name, value);
-  } else {
-    RenderDataPiece(name, DataPiece(value));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderDouble(
-    StringPiece name, double value) {
-  if (current_ == nullptr) {
-    ow_->RenderDouble(name, value);
-  } else {
-    RenderDataPiece(name, DataPiece(value));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderFloat(
-    StringPiece name, float value) {
-  if (current_ == nullptr) {
-    ow_->RenderBool(name, value);
-  } else {
-    RenderDataPiece(name, DataPiece(value));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderString(
-    StringPiece name, StringPiece value) {
-  if (current_ == nullptr) {
-    ow_->RenderString(name, value);
-  } else {
-    // Since StringPiece is essentially a pointer, takes a copy of "value" to
-    // avoid ownership issues.
-    string_values_.emplace_back(new std::string(value));
-    RenderDataPiece(name, DataPiece(*string_values_.back(), true));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderBytes(
-    StringPiece name, StringPiece value) {
-  if (current_ == nullptr) {
-    ow_->RenderBytes(name, value);
-  } else {
-    // Since StringPiece is essentially a pointer, takes a copy of "value" to
-    // avoid ownership issues.
-    string_values_.emplace_back(new std::string(value));
-    RenderDataPiece(name, DataPiece(*string_values_.back(), false, true));
-  }
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::RenderNull(
-    StringPiece name) {
-  if (current_ == nullptr) {
-    ow_->RenderNull(name);
-  } else {
-    RenderDataPiece(name, DataPiece::NullData());
-  }
-  return this;
-}
-
-void DefaultValueObjectWriter::RegisterFieldScrubCallBack(
-    FieldScrubCallBack field_scrub_callback) {
-  field_scrub_callback_ = std::move(field_scrub_callback);
-}
-
-DefaultValueObjectWriter::Node* DefaultValueObjectWriter::CreateNewNode(
-    const std::string& name, const google::protobuf::Type* type, NodeKind kind,
-    const DataPiece& data, bool is_placeholder,
-    const std::vector<std::string>& path, bool suppress_empty_list,
-    bool preserve_proto_field_names, bool use_ints_for_enums,
-    FieldScrubCallBack field_scrub_callback) {
-  return new Node(name, type, kind, data, is_placeholder, path,
-                  suppress_empty_list, preserve_proto_field_names,
-                  use_ints_for_enums, std::move(field_scrub_callback));
-}
-
-DefaultValueObjectWriter::Node::Node(
-    const std::string& name, const google::protobuf::Type* type, NodeKind kind,
-    const DataPiece& data, bool is_placeholder,
-    const std::vector<std::string>& path, bool suppress_empty_list,
-    bool preserve_proto_field_names, bool use_ints_for_enums,
-    FieldScrubCallBack field_scrub_callback)
-    : name_(name),
-      type_(type),
-      kind_(kind),
-      is_any_(false),
-      data_(data),
-      is_placeholder_(is_placeholder),
-      path_(path),
-      suppress_empty_list_(suppress_empty_list),
-      preserve_proto_field_names_(preserve_proto_field_names),
-      use_ints_for_enums_(use_ints_for_enums),
-      field_scrub_callback_(std::move(field_scrub_callback)) {}
-
-DefaultValueObjectWriter::Node* DefaultValueObjectWriter::Node::FindChild(
-    StringPiece name) {
-  if (name.empty() || kind_ != OBJECT) {
-    return nullptr;
-  }
-  for (Node* child : children_) {
-    if (child->name() == name) {
-      return child;
-    }
-  }
-  return nullptr;
-}
-
-void DefaultValueObjectWriter::Node::WriteTo(ObjectWriter* ow) {
-  if (kind_ == PRIMITIVE) {
-    ObjectWriter::RenderDataPieceTo(data_, name_, ow);
-    return;
-  }
-
-  // Render maps. Empty maps are rendered as "{}".
-  if (kind_ == MAP) {
-    ow->StartObject(name_);
-    WriteChildren(ow);
-    ow->EndObject();
-    return;
-  }
-
-  // Write out lists. If we didn't have any list in response, write out empty
-  // list.
-  if (kind_ == LIST) {
-    // Suppress empty lists if requested.
-    if (suppress_empty_list_ && is_placeholder_) return;
-
-    ow->StartList(name_);
-    WriteChildren(ow);
-    ow->EndList();
-    return;
-  }
-
-  // If is_placeholder_ = true, we didn't see this node in the response, so
-  // skip output.
-  if (is_placeholder_) return;
-
-  ow->StartObject(name_);
-  WriteChildren(ow);
-  ow->EndObject();
-}
-
-void DefaultValueObjectWriter::Node::WriteChildren(ObjectWriter* ow) {
-  for (Node* child : children_) {
-    child->WriteTo(ow);
-  }
-}
-
-const google::protobuf::Type* DefaultValueObjectWriter::Node::GetMapValueType(
-    const google::protobuf::Type& found_type, const TypeInfo* typeinfo) {
-  // If this field is a map, we should use the type of its "Value" as
-  // the type of the child node.
-  for (int i = 0; i < found_type.fields_size(); ++i) {
-    const google::protobuf::Field& sub_field = found_type.fields(i);
-    if (sub_field.number() != 2) {
-      continue;
-    }
-    if (sub_field.kind() != google::protobuf::Field::TYPE_MESSAGE) {
-      // This map's value type is not a message type. We don't need to
-      // get the field_type in this case.
-      break;
-    }
-    util::StatusOr<const google::protobuf::Type*> sub_type =
-        typeinfo->ResolveTypeUrl(sub_field.type_url());
-    if (!sub_type.ok()) {
-      GOOGLE_LOG(WARNING) << "Cannot resolve type '" << sub_field.type_url() << "'.";
-    } else {
-      return sub_type.value();
-    }
-    break;
-  }
-  return nullptr;
-}
-
-void DefaultValueObjectWriter::Node::PopulateChildren(
-    const TypeInfo* typeinfo) {
-  // Ignores well known types that don't require automatically populating their
-  // primitive children. For type "Any", we only populate its children when the
-  // "@type" field is set.
-  // TODO(tsun): remove "kStructValueType" from the list. It's being checked
-  //     now because of a bug in the tool-chain that causes the "oneof_index"
-  //     of kStructValueType to not be set correctly.
-  if (type_ == nullptr || type_->name() == kAnyType ||
-      type_->name() == kStructType || type_->name() == kTimestampType ||
-      type_->name() == kDurationType || type_->name() == kStructValueType) {
-    return;
-  }
-  std::vector<Node*> new_children;
-  std::unordered_map<std::string, int> orig_children_map;
-
-  // Creates a map of child nodes to speed up lookup.
-  for (int i = 0; i < children_.size(); ++i) {
-    InsertIfNotPresent(&orig_children_map, children_[i]->name_, i);
-  }
-
-  for (int i = 0; i < type_->fields_size(); ++i) {
-    const google::protobuf::Field& field = type_->fields(i);
-
-    // This code is checking if the field to be added to the tree should be
-    // scrubbed or not by calling the field_scrub_callback_ callback function.
-    std::vector<std::string> path;
-    if (!path_.empty()) {
-      path.insert(path.begin(), path_.begin(), path_.end());
-    }
-    path.push_back(field.name());
-    if (field_scrub_callback_ && field_scrub_callback_(path, &field)) {
-      continue;
-    }
-
-    std::unordered_map<std::string, int>::iterator found =
-        orig_children_map.find(field.name());
-    // If the child field has already been set, we just add it to the new list
-    // of children.
-    if (found != orig_children_map.end()) {
-      new_children.push_back(children_[found->second]);
-      children_[found->second] = nullptr;
-      continue;
-    }
-
-    const google::protobuf::Type* field_type = nullptr;
-    bool is_map = false;
-    NodeKind kind = PRIMITIVE;
-
-    if (field.kind() == google::protobuf::Field::TYPE_MESSAGE) {
-      kind = OBJECT;
-      util::StatusOr<const google::protobuf::Type*> found_result =
-          typeinfo->ResolveTypeUrl(field.type_url());
-      if (!found_result.ok()) {
-        // "field" is of an unknown type.
-        GOOGLE_LOG(WARNING) << "Cannot resolve type '" << field.type_url() << "'.";
-      } else {
-        const google::protobuf::Type* found_type = found_result.value();
-        is_map = IsMap(field, *found_type);
-
-        if (!is_map) {
-          field_type = found_type;
-        } else {
-          // If this field is a map, we should use the type of its "Value" as
-          // the type of the child node.
-          field_type = GetMapValueType(*found_type, typeinfo);
-          kind = MAP;
-        }
-      }
-    }
-
-    if (!is_map &&
-        field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED) {
-      kind = LIST;
-    }
-
-    // If oneof_index() != 0, the child field is part of a "oneof", which means
-    // the child field is optional and we shouldn't populate its default
-    // primitive value.
-    if (field.oneof_index() != 0 && kind == PRIMITIVE) continue;
-
-    // If the child field is of primitive type, sets its data to the default
-    // value of its type.
-    std::unique_ptr<Node> child(
-        new Node(preserve_proto_field_names_ ? field.name() : field.json_name(),
-                 field_type, kind,
-                 kind == PRIMITIVE ? CreateDefaultDataPieceForField(
-                                         field, typeinfo, use_ints_for_enums_)
-                                   : DataPiece::NullData(),
-                 true, path, suppress_empty_list_, preserve_proto_field_names_,
-                 use_ints_for_enums_, field_scrub_callback_));
-    new_children.push_back(child.release());
-  }
-  // Adds all leftover nodes in children_ to the beginning of new_child.
-  for (int i = 0; i < children_.size(); ++i) {
-    if (children_[i] == nullptr) {
-      continue;
-    }
-    new_children.insert(new_children.begin(), children_[i]);
-    children_[i] = nullptr;
-  }
-  children_.swap(new_children);
-}
-
-void DefaultValueObjectWriter::MaybePopulateChildrenOfAny(Node* node) {
-  // If this is an "Any" node with "@type" already given and no other children
-  // have been added, populates its children.
-  if (node != nullptr && node->is_any() && node->type() != nullptr &&
-      node->type()->name() != kAnyType && node->number_of_children() == 1) {
-    node->PopulateChildren(typeinfo_);
-  }
-}
-
-DataPiece DefaultValueObjectWriter::FindEnumDefault(
-    const google::protobuf::Field& field, const TypeInfo* typeinfo,
-    bool use_ints_for_enums) {
-  const google::protobuf::Enum* enum_type =
-      typeinfo->GetEnumByTypeUrl(field.type_url());
-  if (!enum_type) {
-    GOOGLE_LOG(WARNING) << "Could not find enum with type '" << field.type_url()
-                 << "'";
-    return DataPiece::NullData();
-  }
-  if (!field.default_value().empty()) {
-    if (!use_ints_for_enums) {
-      return DataPiece(field.default_value(), true);
-    } else {
-      const std::string& enum_default_value_name = field.default_value();
-      for (int enum_index = 0; enum_index < enum_type->enumvalue_size();
-           ++enum_index) {
-        auto& enum_value = enum_type->enumvalue(enum_index);
-        if (enum_value.name() == enum_default_value_name)
-          return DataPiece(enum_value.number());
-      }
-      GOOGLE_LOG(WARNING) << "Could not find enum value '" << enum_default_value_name
-                   << "' with type '" << field.type_url() << "'";
-      return DataPiece::NullData();
-    }
-  }
-  // We treat the first value as the default if none is specified.
-  return enum_type->enumvalue_size() > 0
-             ? (use_ints_for_enums
-                    ? DataPiece(enum_type->enumvalue(0).number())
-                    : DataPiece(enum_type->enumvalue(0).name(), true))
-             : DataPiece::NullData();
-}
-
-DataPiece DefaultValueObjectWriter::CreateDefaultDataPieceForField(
-    const google::protobuf::Field& field, const TypeInfo* typeinfo,
-    bool use_ints_for_enums) {
-  switch (field.kind()) {
-    case google::protobuf::Field::TYPE_DOUBLE: {
-      return DataPiece(ConvertTo<double>(
-          field.default_value(), &DataPiece::ToDouble, static_cast<double>(0)));
-    }
-    case google::protobuf::Field::TYPE_FLOAT: {
-      return DataPiece(ConvertTo<float>(
-          field.default_value(), &DataPiece::ToFloat, static_cast<float>(0)));
-    }
-    case google::protobuf::Field::TYPE_INT64:
-    case google::protobuf::Field::TYPE_SINT64:
-    case google::protobuf::Field::TYPE_SFIXED64: {
-      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_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_t>(
-          field.default_value(), &DataPiece::ToInt32, static_cast<int32_t>(0)));
-    }
-    case google::protobuf::Field::TYPE_BOOL: {
-      return DataPiece(
-          ConvertTo<bool>(field.default_value(), &DataPiece::ToBool, false));
-    }
-    case google::protobuf::Field::TYPE_STRING: {
-      return DataPiece(field.default_value(), true);
-    }
-    case google::protobuf::Field::TYPE_BYTES: {
-      return DataPiece(field.default_value(), false, true);
-    }
-    case google::protobuf::Field::TYPE_UINT32:
-    case google::protobuf::Field::TYPE_FIXED32: {
-      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);
-    }
-    default: {
-      return DataPiece::NullData();
-    }
-  }
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::StartObject(
-    StringPiece name) {
-  if (current_ == nullptr) {
-    std::vector<std::string> path;
-    root_.reset(CreateNewNode(std::string(name), &type_, OBJECT,
-                              DataPiece::NullData(), false, path,
-                              suppress_empty_list_, preserve_proto_field_names_,
-                              use_ints_for_enums_, field_scrub_callback_));
-    root_->PopulateChildren(typeinfo_);
-    current_ = root_.get();
-    return this;
-  }
-  MaybePopulateChildrenOfAny(current_);
-  Node* child = current_->FindChild(name);
-  if (current_->kind() == LIST || current_->kind() == MAP || child == nullptr) {
-    // If current_ is a list or a map node, we should create a new child and use
-    // the type of current_ as the type of the new child.
-    std::unique_ptr<Node> node(
-        CreateNewNode(std::string(name),
-                      ((current_->kind() == LIST || current_->kind() == MAP)
-                           ? current_->type()
-                           : nullptr),
-                      OBJECT, DataPiece::NullData(), false,
-                      child == nullptr ? current_->path() : child->path(),
-                      suppress_empty_list_, preserve_proto_field_names_,
-                      use_ints_for_enums_, field_scrub_callback_));
-    child = node.get();
-    current_->AddChild(node.release());
-  }
-
-  child->set_is_placeholder(false);
-  if (child->kind() == OBJECT && child->number_of_children() == 0) {
-    child->PopulateChildren(typeinfo_);
-  }
-
-  stack_.push(current_);
-  current_ = child;
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::EndObject() {
-  if (stack_.empty()) {
-    // The root object ends here. Writes out the tree.
-    WriteRoot();
-    return this;
-  }
-  current_ = stack_.top();
-  stack_.pop();
-  return this;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::StartList(
-    StringPiece name) {
-  if (current_ == nullptr) {
-    std::vector<std::string> path;
-    root_.reset(CreateNewNode(std::string(name), &type_, LIST,
-                              DataPiece::NullData(), false, path,
-                              suppress_empty_list_, preserve_proto_field_names_,
-                              use_ints_for_enums_, field_scrub_callback_));
-    current_ = root_.get();
-    return this;
-  }
-  MaybePopulateChildrenOfAny(current_);
-  Node* child = current_->FindChild(name);
-  if (child == nullptr || child->kind() != LIST) {
-    std::unique_ptr<Node> node(CreateNewNode(
-        std::string(name), nullptr, LIST, DataPiece::NullData(), false,
-        child == nullptr ? current_->path() : child->path(),
-        suppress_empty_list_, preserve_proto_field_names_, use_ints_for_enums_,
-        field_scrub_callback_));
-    child = node.get();
-    current_->AddChild(node.release());
-  }
-  child->set_is_placeholder(false);
-
-  stack_.push(current_);
-  current_ = child;
-  return this;
-}
-
-void DefaultValueObjectWriter::WriteRoot() {
-  root_->WriteTo(ow_);
-  root_.reset(nullptr);
-  current_ = nullptr;
-}
-
-DefaultValueObjectWriter* DefaultValueObjectWriter::EndList() {
-  if (stack_.empty()) {
-    WriteRoot();
-    return this;
-  }
-  current_ = stack_.top();
-  stack_.pop();
-  return this;
-}
-
-void DefaultValueObjectWriter::RenderDataPiece(StringPiece name,
-                                               const DataPiece& data) {
-  MaybePopulateChildrenOfAny(current_);
-  if (current_->type() != nullptr && current_->type()->name() == kAnyType &&
-      name == "@type") {
-    util::StatusOr<std::string> data_string = data.ToString();
-    if (data_string.ok()) {
-      const std::string& string_value = data_string.value();
-      // If the type of current_ is "Any" and its "@type" field is being set
-      // here, sets the type of current_ to be the type specified by the
-      // "@type".
-      util::StatusOr<const google::protobuf::Type*> found_type =
-          typeinfo_->ResolveTypeUrl(string_value);
-      if (!found_type.ok()) {
-        GOOGLE_LOG(WARNING) << "Failed to resolve type '" << string_value << "'.";
-      } else {
-        current_->set_type(found_type.value());
-      }
-      current_->set_is_any(true);
-      // If the "@type" field is placed after other fields, we should populate
-      // other children of primitive type now. Otherwise, we should wait until
-      // the first value field is rendered before we populate the children,
-      // because the "value" field of a Any message could be omitted.
-      if (current_->number_of_children() > 1 && current_->type() != nullptr) {
-        current_->PopulateChildren(typeinfo_);
-      }
-    }
-  }
-  Node* child = current_->FindChild(name);
-  if (child == nullptr || child->kind() != PRIMITIVE) {
-    // No children are found, creates a new child.
-    std::unique_ptr<Node> node(
-        CreateNewNode(std::string(name), nullptr, PRIMITIVE, data, false,
-                      child == nullptr ? current_->path() : child->path(),
-                      suppress_empty_list_, preserve_proto_field_names_,
-                      use_ints_for_enums_, field_scrub_callback_));
-    current_->AddChild(node.release());
-  } else {
-    child->set_data(data);
-    child->set_is_placeholder(false);
-  }
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter.h b/src/google/protobuf/util/internal/default_value_objectwriter.h
deleted file mode 100644
index a9e1673..0000000
--- a/src/google/protobuf/util/internal/default_value_objectwriter.h
+++ /dev/null
@@ -1,332 +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_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__
-
-#include <cstdint>
-#include <functional>
-#include <memory>
-#include <stack>
-#include <vector>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/datapiece.h>
-#include <google/protobuf/util/internal/object_writer.h>
-#include <google/protobuf/util/internal/type_info.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/util/type_resolver.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-// An ObjectWriter that renders non-repeated primitive fields of proto messages
-// with their default values. DefaultValueObjectWriter holds objects, lists and
-// fields it receives in a tree structure and writes them out to another
-// ObjectWriter when EndObject() is called on the root object. It also writes
-// out all non-repeated primitive fields that haven't been explicitly rendered
-// with their default values (0 for numbers, "" for strings, etc).
-class PROTOBUF_EXPORT DefaultValueObjectWriter : public ObjectWriter {
- public:
-  // A Callback function to check whether a field needs to be scrubbed.
-  //
-  // Returns true if the field should not be present in the output. Returns
-  // false otherwise.
-  //
-  // The 'path' parameter is a vector of path to the field from root. For
-  // example: if a nested field "a.b.c" (b is the parent message field of c and
-  // a is the parent message field of b), then the vector should contain { "a",
-  // "b", "c" }.
-  //
-  // The Field* should point to the google::protobuf::Field of "c".
-  typedef std::function<bool(
-      const std::vector<std::string>& /*path of the field*/,
-      const google::protobuf::Field* /*field*/)>
-      FieldScrubCallBack;
-
-  DefaultValueObjectWriter(TypeResolver* type_resolver,
-                           const google::protobuf::Type& type,
-                           ObjectWriter* ow);
-
-  ~DefaultValueObjectWriter() override;
-
-  // ObjectWriter methods.
-  DefaultValueObjectWriter* StartObject(StringPiece name) override;
-
-  DefaultValueObjectWriter* EndObject() override;
-
-  DefaultValueObjectWriter* StartList(StringPiece name) override;
-
-  DefaultValueObjectWriter* EndList() override;
-
-  DefaultValueObjectWriter* RenderBool(StringPiece name,
-                                       bool value) override;
-
-  DefaultValueObjectWriter* RenderInt32(StringPiece name,
-                                        int32_t value) override;
-
-  DefaultValueObjectWriter* RenderUint32(StringPiece name,
-                                         uint32_t value) override;
-
-  DefaultValueObjectWriter* RenderInt64(StringPiece name,
-                                        int64_t value) override;
-
-  DefaultValueObjectWriter* RenderUint64(StringPiece name,
-                                         uint64_t value) override;
-
-  DefaultValueObjectWriter* RenderDouble(StringPiece name,
-                                         double value) override;
-
-  DefaultValueObjectWriter* RenderFloat(StringPiece name,
-                                        float value) override;
-
-  DefaultValueObjectWriter* RenderString(StringPiece name,
-                                         StringPiece value) override;
-  DefaultValueObjectWriter* RenderBytes(StringPiece name,
-                                        StringPiece value) override;
-
-  DefaultValueObjectWriter* RenderNull(StringPiece name) override;
-
-  // Register the callback for scrubbing of fields.
-  void RegisterFieldScrubCallBack(FieldScrubCallBack field_scrub_callback);
-
-  // If set to true, empty lists are suppressed from output when default values
-  // are written.
-  void set_suppress_empty_list(bool value) { suppress_empty_list_ = value; }
-
-  // If set to true, original proto field names are used
-  void set_preserve_proto_field_names(bool value) {
-    preserve_proto_field_names_ = value;
-  }
-
-  // If set to true, enums are rendered as ints from output when default values
-  // are written.
-  void set_print_enums_as_ints(bool value) { use_ints_for_enums_ = value; }
-
- protected:
-  enum NodeKind {
-    PRIMITIVE = 0,
-    OBJECT = 1,
-    LIST = 2,
-    MAP = 3,
-  };
-
-  // "Node" represents a node in the tree that holds the input of
-  // DefaultValueObjectWriter.
-  class PROTOBUF_EXPORT Node {
-   public:
-    Node(const std::string& name, const google::protobuf::Type* type,
-         NodeKind kind, const DataPiece& data, bool is_placeholder,
-         const std::vector<std::string>& path, bool suppress_empty_list,
-         bool preserve_proto_field_names, bool use_ints_for_enums,
-         FieldScrubCallBack field_scrub_callback);
-    virtual ~Node() {
-      for (int i = 0; i < children_.size(); ++i) {
-        delete children_[i];
-      }
-    }
-
-    // Adds a child to this node. Takes ownership of this child.
-    void AddChild(Node* child) { children_.push_back(child); }
-
-    // Finds the child given its name.
-    Node* FindChild(StringPiece name);
-
-    // Populates children of this Node based on its type. If there are already
-    // children created, they will be merged to the result. Caller should pass
-    // in TypeInfo for looking up types of the children.
-    virtual void PopulateChildren(const TypeInfo* typeinfo);
-
-    // If this node is a leaf (has data), writes the current node to the
-    // ObjectWriter; if not, then recursively writes the children to the
-    // ObjectWriter.
-    virtual void WriteTo(ObjectWriter* ow);
-
-    // Accessors
-    const std::string& name() const { return name_; }
-
-    const std::vector<std::string>& path() const { return path_; }
-
-    const google::protobuf::Type* type() const { return type_; }
-
-    void set_type(const google::protobuf::Type* type) { type_ = type; }
-
-    NodeKind kind() const { return kind_; }
-
-    int number_of_children() const { return children_.size(); }
-
-    void set_data(const DataPiece& data) { data_ = data; }
-
-    bool is_any() const { return is_any_; }
-
-    void set_is_any(bool is_any) { is_any_ = is_any; }
-
-    void set_is_placeholder(bool is_placeholder) {
-      is_placeholder_ = is_placeholder;
-    }
-
-   protected:
-    // 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& found_type, const TypeInfo* typeinfo);
-
-    // Calls WriteTo() on every child in children_.
-    void WriteChildren(ObjectWriter* ow);
-
-    // The name of this node.
-    std::string name_;
-    // google::protobuf::Type of this node. Owned by TypeInfo.
-    const google::protobuf::Type* type_;
-    // The kind of this node.
-    NodeKind kind_;
-    // Whether this is a node for "Any".
-    bool is_any_;
-    // The data of this node when it is a leaf node.
-    DataPiece data_;
-    // Children of this node.
-    std::vector<Node*> children_;
-    // Whether this node is a placeholder for an object or list automatically
-    // generated when creating the parent node. Should be set to false after
-    // the parent node's StartObject()/StartList() method is called with this
-    // node's name.
-    bool is_placeholder_;
-
-    // Path of the field of this node
-    std::vector<std::string> path_;
-
-    // Whether to suppress empty list output.
-    bool suppress_empty_list_;
-
-    // Whether to preserve original proto field names
-    bool preserve_proto_field_names_;
-
-    // Whether to always print enums as ints
-    bool use_ints_for_enums_;
-
-    // Function for determining whether a field needs to be scrubbed or not.
-    FieldScrubCallBack field_scrub_callback_;
-
-   private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Node);
-  };
-
-  // Creates a new Node and returns it. Caller owns memory of returned object.
-  virtual Node* CreateNewNode(const std::string& name,
-                              const google::protobuf::Type* type, NodeKind kind,
-                              const DataPiece& data, bool is_placeholder,
-                              const std::vector<std::string>& path,
-                              bool suppress_empty_list,
-                              bool preserve_proto_field_names,
-                              bool use_ints_for_enums,
-                              FieldScrubCallBack field_scrub_callback);
-
-  // Creates a DataPiece containing the default value of the type of the field.
-  static DataPiece CreateDefaultDataPieceForField(
-      const google::protobuf::Field& field, const TypeInfo* typeinfo) {
-    return CreateDefaultDataPieceForField(field, typeinfo, false);
-  }
-
-  // Same as the above but with a flag to use ints instead of enum names.
-  static DataPiece CreateDefaultDataPieceForField(
-      const google::protobuf::Field& field, const TypeInfo* typeinfo,
-      bool use_ints_for_enums);
-
- protected:
-  // Returns a pointer to current Node in tree.
-  Node* current() { return current_; }
-
- private:
-  // Populates children of "node" if it is an "any" Node and its real type has
-  // been given.
-  void MaybePopulateChildrenOfAny(Node* node);
-
-  // Writes the root_ node to ow_ and resets the root_ and current_ pointer to
-  // nullptr.
-  void WriteRoot();
-
-  // Adds or replaces the data_ of a primitive child node.
-  void RenderDataPiece(StringPiece name, const DataPiece& data);
-
-  // Returns the default enum value as a DataPiece, or the first enum value if
-  // there is no default. For proto3, where we cannot specify an explicit
-  // default, a zero value will always be returned.
-  static DataPiece FindEnumDefault(const google::protobuf::Field& field,
-                                   const TypeInfo* typeinfo,
-                                   bool use_ints_for_enums);
-
-  // Type information for all the types used in the descriptor. Used to find
-  // google::protobuf::Type of nested messages/enums.
-  const TypeInfo* typeinfo_;
-  // Whether the TypeInfo object is owned by this class.
-  bool own_typeinfo_;
-  // google::protobuf::Type of the root message type.
-  const google::protobuf::Type& type_;
-  // Holds copies of strings passed to RenderString.
-  std::vector<std::unique_ptr<std::string>> string_values_;
-
-  // The current Node. Owned by its parents.
-  Node* current_;
-  // The root Node.
-  std::unique_ptr<Node> root_;
-  // The stack to hold the path of Nodes from current_ to root_;
-  std::stack<Node*> stack_;
-
-  // Whether to suppress output of empty lists.
-  bool suppress_empty_list_;
-
-  // Whether to preserve original proto field names
-  bool preserve_proto_field_names_;
-
-  // Whether to always print enums as ints
-  bool use_ints_for_enums_;
-
-  // Function for determining whether a field needs to be scrubbed or not.
-  FieldScrubCallBack field_scrub_callback_;
-
-  ObjectWriter* ow_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(DefaultValueObjectWriter);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_DEFAULT_VALUE_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc b/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
deleted file mode 100644
index 96b14db..0000000
--- a/src/google/protobuf/util/internal/default_value_objectwriter_test.cc
+++ /dev/null
@@ -1,191 +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 <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/constants.h>
-#include <google/protobuf/util/internal/type_info_test_helper.h>
-#include <gtest/gtest.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-namespace testing {
-
-using proto_util_converter::testing::DefaultValueTest;
-
-// Base class for setting up required state for running default values tests on
-// different descriptors.
-class BaseDefaultValueObjectWriterTest
-    : public ::testing::TestWithParam<testing::TypeInfoSource> {
- protected:
-  explicit BaseDefaultValueObjectWriterTest(const Descriptor* descriptor)
-      : helper_(GetParam()), mock_(), expects_(&mock_) {
-    helper_.ResetTypeInfo(descriptor);
-    testing_.reset(helper_.NewDefaultValueWriter(
-        std::string(kTypeServiceBaseUrl) + "/" + descriptor->full_name(),
-        &mock_));
-  }
-
-  ~BaseDefaultValueObjectWriterTest() override {}
-
-  TypeInfoTestHelper helper_;
-  MockObjectWriter mock_;
-  ExpectingObjectWriter expects_;
-  std::unique_ptr<DefaultValueObjectWriter> testing_;
-};
-
-// Tests to cover some basic DefaultValueObjectWriter use cases. More tests are
-// in the marshalling_test.cc and translator_integration_test.cc.
-class DefaultValueObjectWriterTest : public BaseDefaultValueObjectWriterTest {
- protected:
-  DefaultValueObjectWriterTest()
-      : BaseDefaultValueObjectWriterTest(DefaultValueTest::descriptor()) {}
-  ~DefaultValueObjectWriterTest() override {}
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         DefaultValueObjectWriterTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(DefaultValueObjectWriterTest, Empty) {
-  // Set expectation
-  expects_.StartObject("")
-      ->RenderDouble("doubleValue", 0.0)
-      ->StartList("repeatedDouble")
-      ->EndList()
-      ->RenderFloat("floatValue", 0.0)
-      ->RenderInt64("int64Value", 0)
-      ->RenderUint64("uint64Value", 0)
-      ->RenderInt32("int32Value", 0)
-      ->RenderUint32("uint32Value", 0)
-      ->RenderBool("boolValue", false)
-      ->RenderString("stringValue", "")
-      ->RenderBytes("bytesValue", "")
-      ->RenderString("enumValue", "ENUM_FIRST")
-      ->EndObject();
-
-  // Actual testing
-  testing_->StartObject("")->EndObject();
-}
-
-TEST_P(DefaultValueObjectWriterTest, NonDefaultDouble) {
-  // Set expectation
-  expects_.StartObject("")
-      ->RenderDouble("doubleValue", 1.0)
-      ->StartList("repeatedDouble")
-      ->EndList()
-      ->RenderFloat("floatValue", 0.0)
-      ->RenderInt64("int64Value", 0)
-      ->RenderUint64("uint64Value", 0)
-      ->RenderInt32("int32Value", 0)
-      ->RenderUint32("uint32Value", 0)
-      ->RenderBool("boolValue", false)
-      ->RenderString("stringValue", "")
-      ->RenderString("enumValue", "ENUM_FIRST")
-      ->EndObject();
-
-  // Actual testing
-  testing_->StartObject("")->RenderDouble("doubleValue", 1.0)->EndObject();
-}
-
-TEST_P(DefaultValueObjectWriterTest, ShouldRetainUnknownField) {
-  // Set expectation
-  expects_.StartObject("")
-      ->RenderDouble("doubleValue", 1.0)
-      ->StartList("repeatedDouble")
-      ->EndList()
-      ->RenderFloat("floatValue", 0.0)
-      ->RenderInt64("int64Value", 0)
-      ->RenderUint64("uint64Value", 0)
-      ->RenderInt32("int32Value", 0)
-      ->RenderUint32("uint32Value", 0)
-      ->RenderBool("boolValue", false)
-      ->RenderString("stringValue", "")
-      ->RenderString("unknown", "abc")
-      ->StartObject("unknownObject")
-      ->RenderString("unknown", "def")
-      ->EndObject()
-      ->RenderString("enumValue", "ENUM_FIRST")
-      ->EndObject();
-
-  // Actual testing
-  testing_->StartObject("")
-      ->RenderDouble("doubleValue", 1.0)
-      ->RenderString("unknown", "abc")
-      ->StartObject("unknownObject")
-      ->RenderString("unknown", "def")
-      ->EndObject()
-      ->EndObject();
-}
-
-
-class DefaultValueObjectWriterSuppressListTest
-    : public BaseDefaultValueObjectWriterTest {
- protected:
-  DefaultValueObjectWriterSuppressListTest()
-      : BaseDefaultValueObjectWriterTest(DefaultValueTest::descriptor()) {
-    testing_->set_suppress_empty_list(true);
-  }
-  ~DefaultValueObjectWriterSuppressListTest() override {}
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         DefaultValueObjectWriterSuppressListTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(DefaultValueObjectWriterSuppressListTest, Empty) {
-  // Set expectation. Empty lists should be suppressed.
-  expects_.StartObject("")
-      ->RenderDouble("doubleValue", 0.0)
-      ->RenderFloat("floatValue", 0.0)
-      ->RenderInt64("int64Value", 0)
-      ->RenderUint64("uint64Value", 0)
-      ->RenderInt32("int32Value", 0)
-      ->RenderUint32("uint32Value", 0)
-      ->RenderBool("boolValue", false)
-      ->RenderString("stringValue", "")
-      ->RenderBytes("bytesValue", "")
-      ->RenderString("enumValue", "ENUM_FIRST")
-      ->EndObject();
-
-  // Actual testing
-  testing_->StartObject("")->EndObject();
-}
-}  // namespace testing
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/error_listener.h b/src/google/protobuf/util/internal/error_listener.h
deleted file mode 100644
index 8c9c501..0000000
--- a/src/google/protobuf/util/internal/error_listener.h
+++ /dev/null
@@ -1,109 +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_UTIL_INTERNAL_ERROR_LISTENER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_ERROR_LISTENER_H__
-
-#include <algorithm>
-#include <memory>
-#include <string>
-#include <vector>
-
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/location_tracker.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-// Interface for error listener.
-class PROTOBUF_EXPORT ErrorListener {
- public:
-  virtual ~ErrorListener() {}
-
-  // Reports an invalid name at the given location.
-  virtual void InvalidName(const LocationTrackerInterface& loc,
-                           StringPiece invalid_name,
-                           StringPiece message) = 0;
-
-  // Reports an invalid value for a field.
-  virtual void InvalidValue(const LocationTrackerInterface& loc,
-                            StringPiece type_name,
-                            StringPiece value) = 0;
-
-  // Reports a missing required field.
-  virtual void MissingField(const LocationTrackerInterface& loc,
-                            StringPiece missing_name) = 0;
-
- protected:
-  ErrorListener() {}
-
- private:
-  // Do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ErrorListener);
-};
-
-// An error listener that ignores all errors.
-class PROTOBUF_EXPORT NoopErrorListener : public ErrorListener {
- public:
-  NoopErrorListener() {}
-  ~NoopErrorListener() override {}
-
-  void InvalidName(const LocationTrackerInterface& /*loc*/,
-                   StringPiece /* invalid_name */,
-                   StringPiece /* message */) override {}
-
-  void InvalidValue(const LocationTrackerInterface& /*loc*/,
-                    StringPiece /* type_name */,
-                    StringPiece /* value */) override {}
-
-  void MissingField(const LocationTrackerInterface& /* loc */,
-                    StringPiece /* missing_name */) override {}
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(NoopErrorListener);
-};
-
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_ERROR_LISTENER_H__
diff --git a/src/google/protobuf/util/internal/expecting_objectwriter.h b/src/google/protobuf/util/internal/expecting_objectwriter.h
deleted file mode 100644
index 76fe2b6..0000000
--- a/src/google/protobuf/util/internal/expecting_objectwriter.h
+++ /dev/null
@@ -1,250 +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_UTIL_INTERNAL_EXPECTING_OBJECTWRITER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_EXPECTING_OBJECTWRITER_H__
-
-// An implementation of ObjectWriter that automatically sets the
-// gmock expectations for the response to a method. Every method
-// returns the object itself for chaining.
-//
-// Usage:
-//   // Setup
-//   MockObjectWriter mock;
-//   ExpectingObjectWriter ow(&mock);
-//
-//   // Set expectation
-//   ow.StartObject("")
-//       ->RenderString("key", "value")
-//     ->EndObject();
-//
-//   // Actual testing
-//   mock.StartObject(StringPiece())
-//         ->RenderString("key", "value")
-//       ->EndObject();
-
-#include <cstdint>
-
-#include <google/protobuf/stubs/common.h>
-#include <gmock/gmock.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/object_writer.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-using testing::Eq;
-using testing::IsEmpty;
-using testing::NanSensitiveDoubleEq;
-using testing::NanSensitiveFloatEq;
-using testing::Return;
-using testing::StrEq;
-using testing::TypedEq;
-
-class MockObjectWriter : public ObjectWriter {
- public:
-  MockObjectWriter() {}
-
-  MOCK_METHOD(ObjectWriter*, StartObject, (StringPiece), (override));
-  MOCK_METHOD(ObjectWriter*, EndObject, (), (override));
-  MOCK_METHOD(ObjectWriter*, StartList, (StringPiece), (override));
-  MOCK_METHOD(ObjectWriter*, EndList, (), (override));
-  MOCK_METHOD(ObjectWriter*, RenderBool, (StringPiece, bool), (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt32, (StringPiece, int32_t),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint32, (StringPiece, uint32_t),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderInt64, (StringPiece, int64_t),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderUint64, (StringPiece, uint64_t),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderDouble, (StringPiece, double),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderFloat, (StringPiece, float),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderString,
-              (StringPiece, StringPiece), (override));
-  MOCK_METHOD(ObjectWriter*, RenderBytes, (StringPiece, StringPiece),
-              (override));
-  MOCK_METHOD(ObjectWriter*, RenderNull, (StringPiece), (override));
-};
-
-class ExpectingObjectWriter : public ObjectWriter {
- public:
-  explicit ExpectingObjectWriter(MockObjectWriter* mock) : mock_(mock) {}
-
-  ObjectWriter* StartObject(StringPiece name) override {
-    (name.empty() ? EXPECT_CALL(*mock_, StartObject(IsEmpty()))
-                  : EXPECT_CALL(*mock_, StartObject(Eq(std::string(name)))))
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* EndObject() override {
-    EXPECT_CALL(*mock_, EndObject())
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* StartList(StringPiece name) override {
-    (name.empty() ? EXPECT_CALL(*mock_, StartList(IsEmpty()))
-                  : EXPECT_CALL(*mock_, StartList(Eq(std::string(name)))))
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* EndList() override {
-    EXPECT_CALL(*mock_, EndList())
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* RenderBool(StringPiece name, bool value) override {
-    (name.empty()
-         ? EXPECT_CALL(*mock_, RenderBool(IsEmpty(), TypedEq<bool>(value)))
-         : EXPECT_CALL(*mock_,
-                       RenderBool(Eq(std::string(name)), TypedEq<bool>(value))))
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* RenderInt32(StringPiece name, int32_t value) override {
-    (name.empty()
-         ? 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;
-  }
-
-  ObjectWriter* RenderUint32(StringPiece name, uint32_t value) override {
-    (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;
-  }
-
-  ObjectWriter* RenderInt64(StringPiece name, int64_t value) override {
-    (name.empty()
-         ? 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;
-  }
-
-  ObjectWriter* RenderUint64(StringPiece name, uint64_t value) override {
-    (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;
-  }
-
-  ObjectWriter* RenderDouble(StringPiece name, double value) override {
-    (name.empty()
-         ? EXPECT_CALL(*mock_,
-                       RenderDouble(IsEmpty(), NanSensitiveDoubleEq(value)))
-         : EXPECT_CALL(*mock_, RenderDouble(Eq(std::string(name)),
-                                            NanSensitiveDoubleEq(value))))
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* RenderFloat(StringPiece name, float value) override {
-    (name.empty()
-         ? EXPECT_CALL(*mock_,
-                       RenderFloat(IsEmpty(), NanSensitiveFloatEq(value)))
-         : EXPECT_CALL(*mock_, RenderFloat(Eq(std::string(name)),
-                                           NanSensitiveFloatEq(value))))
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* RenderString(StringPiece name,
-                             StringPiece value) override {
-    (name.empty() ? EXPECT_CALL(*mock_, RenderString(IsEmpty(),
-                                                     TypedEq<StringPiece>(
-                                                         std::string(value))))
-                  : EXPECT_CALL(*mock_, RenderString(Eq(std::string(name)),
-                                                     TypedEq<StringPiece>(
-                                                         std::string(value)))))
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-  virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) {
-    (name.empty()
-         ? EXPECT_CALL(*mock_, RenderBytes(IsEmpty(), TypedEq<StringPiece>(
-                                                          value.ToString())))
-         : EXPECT_CALL(*mock_,
-                       RenderBytes(Eq(std::string(name)),
-                                   TypedEq<StringPiece>(value.ToString()))))
-        .WillOnce(Return(mock_))
-        .RetiresOnSaturation();
-    return this;
-  }
-
-  ObjectWriter* RenderNull(StringPiece name) override {
-    (name.empty() ? EXPECT_CALL(*mock_, RenderNull(IsEmpty()))
-                  : EXPECT_CALL(*mock_, RenderNull(Eq(std::string(name))))
-                        .WillOnce(Return(mock_))
-                        .RetiresOnSaturation());
-    return this;
-  }
-
- private:
-  MockObjectWriter* mock_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ExpectingObjectWriter);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_EXPECTING_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/field_mask_utility.cc b/src/google/protobuf/util/internal/field_mask_utility.cc
deleted file mode 100644
index 521bf48..0000000
--- a/src/google/protobuf/util/internal/field_mask_utility.cc
+++ /dev/null
@@ -1,218 +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 <google/protobuf/util/internal/field_mask_utility.h>
-
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/status_macros.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-namespace {
-
-// Appends a FieldMask path segment to a prefix.
-std::string AppendPathSegmentToPrefix(StringPiece prefix,
-                                      StringPiece segment) {
-  if (prefix.empty()) {
-    return std::string(segment);
-  }
-  if (segment.empty()) {
-    return std::string(prefix);
-  }
-  // If the segment is a map key, appends it to the prefix without the ".".
-  if (HasPrefixString(segment, "[\"")) {
-    return StrCat(prefix, segment);
-  }
-  return StrCat(prefix, ".", segment);
-}
-
-}  // namespace
-
-std::string ConvertFieldMaskPath(const StringPiece path,
-                                 ConverterCallback converter) {
-  std::string result;
-  result.reserve(path.size() << 1);
-
-  bool is_quoted = false;
-  bool is_escaping = false;
-  int current_segment_start = 0;
-
-  // Loops until 1 passed the end of the input to make handling the last
-  // segment easier.
-  for (size_t i = 0; i <= path.size(); ++i) {
-    // Outputs quoted string as-is.
-    if (is_quoted) {
-      if (i == path.size()) {
-        break;
-      }
-      result.push_back(path[i]);
-      if (is_escaping) {
-        is_escaping = false;
-      } else if (path[i] == '\\') {
-        is_escaping = true;
-      } else if (path[i] == '\"') {
-        current_segment_start = i + 1;
-        is_quoted = false;
-      }
-      continue;
-    }
-    if (i == path.size() || path[i] == '.' || path[i] == '(' ||
-        path[i] == ')' || path[i] == '\"') {
-      result += converter(
-          path.substr(current_segment_start, i - current_segment_start));
-      if (i < path.size()) {
-        result.push_back(path[i]);
-      }
-      current_segment_start = i + 1;
-    }
-    if (i < path.size() && path[i] == '\"') {
-      is_quoted = true;
-    }
-  }
-  return result;
-}
-
-util::Status DecodeCompactFieldMaskPaths(StringPiece paths,
-                                         PathSinkCallback path_sink) {
-  std::stack<std::string> prefix;
-  int length = paths.length();
-  int previous_position = 0;
-  bool in_map_key = false;
-  bool is_escaping = false;
-  // Loops until 1 passed the end of the input to make the handle of the last
-  // segment easier.
-  for (int i = 0; i <= length; ++i) {
-    if (i != length) {
-      // Skips everything in a map key until we hit the end of it, which is
-      // marked by an un-escaped '"' immediately followed by a ']'.
-      if (in_map_key) {
-        if (is_escaping) {
-          is_escaping = false;
-          continue;
-        }
-        if (paths[i] == '\\') {
-          is_escaping = true;
-          continue;
-        }
-        if (paths[i] != '\"') {
-          continue;
-        }
-        // Un-escaped '"' must be followed with a ']'.
-        if (i >= length - 1 || paths[i + 1] != ']') {
-          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;
-        // Skips ']'.
-        i++;
-        // 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::InvalidArgumentError(StrCat(
-              "Invalid FieldMask '", paths,
-              "'. Map keys should be at the end of a path segment."));
-        }
-        is_escaping = false;
-        continue;
-      }
-
-      // 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::InvalidArgumentError(StrCat(
-              "Invalid FieldMask '", paths,
-              "'. Map keys should be represented as [\"some_key\"]."));
-        }
-        // "[\"" starts a map key.
-        in_map_key = true;
-        i++;  // Skips the '\"'.
-        continue;
-      }
-      // If the current character is not a special character (',', '(' or ')'),
-      // continue to the next.
-      if (paths[i] != ',' && paths[i] != ')' && paths[i] != '(') {
-        continue;
-      }
-    }
-    // Gets the current segment - sub-string between previous position (after
-    // '(', ')', ',', or the beginning of the input) and the current position.
-    StringPiece segment =
-        paths.substr(previous_position, i - previous_position);
-    std::string current_prefix = prefix.empty() ? "" : prefix.top();
-
-    if (i < length && paths[i] == '(') {
-      // Builds a prefix and save it into the stack.
-      prefix.push(AppendPathSegmentToPrefix(current_prefix, segment));
-    } else if (!segment.empty()) {
-      // When the current character is ')', ',' or the current position has
-      // passed the end of the input, builds and outputs a new paths by
-      // concatenating the last prefix with the current segment.
-      RETURN_IF_ERROR(
-          path_sink(AppendPathSegmentToPrefix(current_prefix, segment)));
-    }
-
-    // Removes the last prefix after seeing a ')'.
-    if (i < length && paths[i] == ')') {
-      if (prefix.empty()) {
-        return util::InvalidArgumentError(
-            StrCat("Invalid FieldMask '", paths,
-                         "'. Cannot find matching '(' for all ')'."));
-      }
-      prefix.pop();
-    }
-    previous_position = i + 1;
-  }
-  if (in_map_key) {
-    return util::InvalidArgumentError(
-        StrCat("Invalid FieldMask '", paths,
-                     "'. Cannot find matching ']' for all '['."));
-  }
-  if (!prefix.empty()) {
-    return util::InvalidArgumentError(
-        StrCat("Invalid FieldMask '", paths,
-                     "'. Cannot find matching ')' for all '('."));
-  }
-  return util::Status();
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/field_mask_utility.h b/src/google/protobuf/util/internal/field_mask_utility.h
deleted file mode 100644
index 1882333..0000000
--- a/src/google/protobuf/util/internal/field_mask_utility.h
+++ /dev/null
@@ -1,74 +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.
-
-// FieldMask related utility methods.
-
-#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_FIELD_MASK_UTILITY_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_FIELD_MASK_UTILITY_H__
-
-#include <functional>
-#include <stack>
-
-#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>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-typedef std::function<std::string(StringPiece)> ConverterCallback;
-typedef std::function<util::Status(StringPiece)> PathSinkCallback;
-
-// Applies a 'converter' to each segment of a FieldMask path and returns the
-// result. Quoted strings in the 'path' are copied to the output as-is without
-// converting their content. Escaping is supported within quoted strings.
-// For example, "ab\"_c" will be returned as "ab\"_c" without any changes.
-std::string ConvertFieldMaskPath(const StringPiece path,
-                                 ConverterCallback converter);
-
-// Decodes a compact list of FieldMasks. For example, "a.b,a.c.d,a.c.e" will be
-// decoded into a list of field paths - "a.b", "a.c.d", "a.c.e". And the results
-// will be sent to 'path_sink', i.e. 'path_sink' will be called once per
-// resulting path.
-// 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);
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_FIELD_MASK_UTILITY_H__
diff --git a/src/google/protobuf/util/internal/json_escaping.cc b/src/google/protobuf/util/internal/json_escaping.cc
deleted file mode 100644
index e4fa8cf..0000000
--- a/src/google/protobuf/util/internal/json_escaping.cc
+++ /dev/null
@@ -1,372 +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 <google/protobuf/util/internal/json_escaping.h>
-
-#include <cstdint>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-namespace {
-
-// Array of hex characters for conversion to hex.
-static const char kHex[] = "0123456789abcdef";
-
-// Characters 0x00 to 0x9f are very commonly used, so we provide a special
-// table lookup.
-//
-// For unicode code point ch < 0xa0:
-// kCommonEscapes[ch] is the escaped string of ch, if escaping is needed;
-//                    or an empty string, if escaping is not needed.
-static const char kCommonEscapes[160][7] = {
-    // C0 (ASCII and derivatives) control characters
-    "\\u0000", "\\u0001", "\\u0002", "\\u0003",  // 0x00
-    "\\u0004", "\\u0005", "\\u0006", "\\u0007", "\\b", "\\t", "\\n", "\\u000b",
-    "\\f", "\\r", "\\u000e", "\\u000f", "\\u0010", "\\u0011", "\\u0012",
-    "\\u0013",  // 0x10
-    "\\u0014", "\\u0015", "\\u0016", "\\u0017", "\\u0018", "\\u0019", "\\u001a",
-    "\\u001b", "\\u001c", "\\u001d", "\\u001e", "\\u001f",
-    // Escaping of " and \ are required by www.json.org string definition.
-    // Escaping of < and > are required for HTML security.
-    "", "", "\\\"", "", "", "", "", "",                              // 0x20
-    "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",  // 0x30
-    "", "", "", "", "\\u003c", "", "\\u003e", "", "", "", "", "", "", "", "",
-    "",                                                                  // 0x40
-    "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",      // 0x50
-    "", "", "", "", "\\\\", "", "", "", "", "", "", "", "", "", "", "",  // 0x60
-    "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "",      // 0x70
-    "", "", "", "", "", "", "", "\\u007f",
-    // C1 (ISO 8859 and Unicode) extended control characters
-    "\\u0080", "\\u0081", "\\u0082", "\\u0083",  // 0x80
-    "\\u0084", "\\u0085", "\\u0086", "\\u0087", "\\u0088", "\\u0089", "\\u008a",
-    "\\u008b", "\\u008c", "\\u008d", "\\u008e", "\\u008f", "\\u0090", "\\u0091",
-    "\\u0092", "\\u0093",  // 0x90
-    "\\u0094", "\\u0095", "\\u0096", "\\u0097", "\\u0098", "\\u0099", "\\u009a",
-    "\\u009b", "\\u009c", "\\u009d", "\\u009e", "\\u009f"};
-
-// Determines if the given char value is a unicode surrogate code unit (either
-// high-surrogate or low-surrogate).
-inline bool IsSurrogate(uint32_t c) {
-  // Optimized form of:
-  // return c >= kMinHighSurrogate && c <= kMaxLowSurrogate;
-  // (Reduced from 3 ALU instructions to 2 ALU instructions)
-  return (c & 0xfffff800) == JsonEscaping::kMinHighSurrogate;
-}
-
-// 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_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_t ToLowSurrogate(uint32_t cp) {
-  return (cp &
-          (JsonEscaping::kMaxLowSurrogate - JsonEscaping::kMinLowSurrogate)) +
-         JsonEscaping::kMinLowSurrogate;
-}
-
-// 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_t ToHighSurrogate(uint32_t cp) {
-  return (cp >> 10) + (JsonEscaping::kMinHighSurrogate -
-                       (JsonEscaping::kMinSupplementaryCodePoint >> 10));
-}
-
-// Input str is encoded in UTF-8. A unicode code point could be encoded in
-// UTF-8 using anywhere from 1 to 4 characters, and it could span multiple
-// reads of the ByteSource.
-//
-// This function reads the next unicode code point from the input (str) at
-// the given position (index), taking into account any left-over partial
-// code point from the previous iteration (cp), together with the number
-// of characters left to read to complete this code point (num_left).
-//
-// This function assumes that the input (str) is valid at the given position
-// (index). In order words, at least one character could be read successfully.
-//
-// The code point read (partial or complete) is stored in (cp). Upon return,
-// (num_left) stores the number of characters that has yet to be read in
-// order to complete the current unicode code point. If the read is complete,
-// then (num_left) is 0. Also, (num_read) is the number of characters read.
-//
-// 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_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_t>(str[index++]);
-    *num_read = 1;
-    // The length of the code point is determined from reading the first byte.
-    //
-    // If the first byte is between:
-    //    0..0x7f: that's the value of the code point.
-    // 0x80..0xbf: <invalid>
-    // 0xc0..0xdf: 11-bit code point encoded in 2 bytes.
-    //                                   bit 10-6, bit 5-0
-    // 0xe0..0xef: 16-bit code point encoded in 3 bytes.
-    //                        bit 15-12, bit 11-6, bit 5-0
-    // 0xf0..0xf7: 21-bit code point encoded in 4 bytes.
-    //             bit 20-18, bit 17-12, bit 11-6, bit 5-0
-    // 0xf8..0xff: <invalid>
-    //
-    // Meaning of each bit:
-    // <msb> bit 7: 0 - single byte code point: bits 6-0 are values.
-    //              1 - multibyte code point
-    //       bit 6: 0 - subsequent bytes of multibyte code point:
-    //                  bits 5-0 are values.
-    //              1 - first byte of multibyte code point
-    //       bit 5: 0 - first byte of 2-byte code point: bits 4-0 are values.
-    //              1 - first byte of code point with >= 3 bytes.
-    //       bit 4: 0 - first byte of 3-byte code point: bits 3-0 are values.
-    //              1 - first byte of code point with >= 4 bytes.
-    //       bit 3: 0 - first byte of 4-byte code point: bits 2-0 are values.
-    //              1 - reserved for future expansion.
-    if (*cp <= 0x7f) {
-      return true;
-    } else if (*cp <= 0xbf) {
-      return false;
-    } else if (*cp <= 0xdf) {
-      *cp &= 0x1f;
-      *num_left = 1;
-    } else if (*cp <= 0xef) {
-      *cp &= 0x0f;
-      *num_left = 2;
-    } else if (*cp <= 0xf7) {
-      *cp &= 0x07;
-      *num_left = 3;
-    } else {
-      return false;
-    }
-  } else {
-    // Last read was partial. Initialize num_read to 0 and continue reading
-    // the last unicode code point.
-    *num_read = 0;
-  }
-  while (*num_left > 0 && index < str.size()) {
-    uint32_t ch = static_cast<uint8_t>(str[index++]);
-    --(*num_left);
-    ++(*num_read);
-    *cp = (*cp << 6) | (ch & 0x3f);
-    if (ch < 0x80 || ch > 0xbf) return false;
-  }
-  return *num_left > 0 || (!IsSurrogate(*cp) && IsValidCodePoint(*cp));
-}
-
-// 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_t cp, char* buffer) {
-  buffer[5] = kHex[cp & 0x0f];
-  cp >>= 4;
-  buffer[4] = kHex[cp & 0x0f];
-  cp >>= 4;
-  buffer[3] = kHex[cp & 0x0f];
-  cp >>= 4;
-  buffer[2] = kHex[cp & 0x0f];
-  return StringPiece(buffer, 6);
-}
-
-// 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_t cp, char* buffer) {
-  uint16_t low = ToLowSurrogate(cp);
-  uint16_t high = ToHighSurrogate(cp);
-
-  buffer[11] = kHex[low & 0x0f];
-  low >>= 4;
-  buffer[10] = kHex[low & 0x0f];
-  low >>= 4;
-  buffer[9] = kHex[low & 0x0f];
-  low >>= 4;
-  buffer[8] = kHex[low & 0x0f];
-
-  buffer[5] = kHex[high & 0x0f];
-  high >>= 4;
-  buffer[4] = kHex[high & 0x0f];
-  high >>= 4;
-  buffer[3] = kHex[high & 0x0f];
-  high >>= 4;
-  buffer[2] = kHex[high & 0x0f];
-
-  return StringPiece(buffer, 12);
-}
-
-// If the given unicode code point needs escaping, then returns the
-// escaped form. The returned StringPiece either points to statically
-// pre-allocated char[] or to the given buffer. The input buffer needs
-// to be at least 12 bytes long.
-//
-// If the given unicode code point does not need escaping, an empty
-// StringPiece is returned.
-StringPiece EscapeCodePoint(uint32_t cp, char* buffer) {
-  if (cp < 0xa0) return kCommonEscapes[cp];
-  switch (cp) {
-    // These are not required by json spec
-    // but used to prevent security bugs in javascript.
-    case 0xfeff:  // Zero width no-break space
-    case 0xfff9:  // Interlinear annotation anchor
-    case 0xfffa:  // Interlinear annotation separator
-    case 0xfffb:  // Interlinear annotation terminator
-
-    case 0x00ad:  // Soft-hyphen
-    case 0x06dd:  // Arabic end of ayah
-    case 0x070f:  // Syriac abbreviation mark
-    case 0x17b4:  // Khmer vowel inherent Aq
-    case 0x17b5:  // Khmer vowel inherent Aa
-      return ToHex(cp, buffer);
-
-    default:
-      if ((cp >= 0x0600 && cp <= 0x0603) ||  // Arabic signs
-          (cp >= 0x200b && cp <= 0x200f) ||  // Zero width etc.
-          (cp >= 0x2028 && cp <= 0x202e) ||  // Separators etc.
-          (cp >= 0x2060 && cp <= 0x2064) ||  // Invisible etc.
-          (cp >= 0x206a && cp <= 0x206f)) {  // Shaping etc.
-        return ToHex(cp, buffer);
-      }
-
-      if (cp == 0x000e0001 ||                        // Language tag
-          (cp >= 0x0001d173 && cp <= 0x0001d17a) ||  // Music formatting
-          (cp >= 0x000e0020 && cp <= 0x000e007f)) {  // TAG symbols
-        return ToSurrogateHex(cp, buffer);
-      }
-  }
-  return StringPiece();
-}
-
-// 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_t cp, char* buffer,
-                                  bool force_output) {
-  StringPiece sp = EscapeCodePoint(cp, buffer);
-  if (force_output && sp.empty()) {
-    buffer[5] = (cp & 0x3f) | 0x80;
-    cp >>= 6;
-    if (cp <= 0x1f) {
-      buffer[4] = cp | 0xc0;
-      sp = StringPiece(buffer + 4, 2);
-      return sp;
-    }
-    buffer[4] = (cp & 0x3f) | 0x80;
-    cp >>= 6;
-    if (cp <= 0x0f) {
-      buffer[3] = cp | 0xe0;
-      sp = StringPiece(buffer + 3, 3);
-      return sp;
-    }
-    buffer[3] = (cp & 0x3f) | 0x80;
-    buffer[2] = ((cp >> 6) & 0x07) | 0xf0;
-    sp = StringPiece(buffer + 2, 4);
-  }
-  return sp;
-}
-
-}  // namespace
-
-void JsonEscaping::Escape(strings::ByteSource* input,
-                          strings::ByteSink* output) {
-  char buffer[12] = "\\udead\\ubee";
-  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();
-    StringPiece escaped;
-    int i = 0;
-    int num_read;
-    bool ok;
-    bool cp_was_split = num_left > 0;
-    // Loop until we encounter either
-    //   i) a code point that needs to be escaped; or
-    //  ii) a split code point is completely read; or
-    // iii) a character that is not a valid utf8; or
-    //  iv) end of the StringPiece str is reached.
-    do {
-      ok = ReadCodePoint(str, i, &cp, &num_left, &num_read);
-      if (num_left > 0 || !ok) break;  // case iii or iv
-      escaped = EscapeCodePoint(cp, buffer, cp_was_split);
-      if (!escaped.empty()) break;  // case i or ii
-      i += num_read;
-      num_read = 0;
-    } while (i < str.length());  // case iv
-    // First copy the un-escaped prefix, if any, to the output ByteSink.
-    if (i > 0) input->CopyTo(output, i);
-    if (num_read > 0) input->Skip(num_read);
-    if (!ok) {
-      // Case iii: Report error.
-      // TODO(wpoon): Add error reporting.
-      num_left = 0;
-    } else if (num_left == 0 && !escaped.empty()) {
-      // Case i or ii: Append the escaped code point to the output ByteSink.
-      output->Append(escaped.data(), escaped.size());
-    }
-  }
-  if (num_left > 0) {
-    // Treat as case iii: report error.
-    // TODO(wpoon): Add error reporting.
-  }
-}
-
-void JsonEscaping::Escape(StringPiece input, strings::ByteSink* output) {
-  const size_t len = input.length();
-  const char* p = input.data();
-
-  bool can_skip_escaping = true;
-  for (int i = 0; i < len; i++) {
-    char c = p[i];
-    if (c < 0x20 || c >= 0x7F || c == '"' || c == '<' || c == '>' ||
-        c == '\\') {
-      can_skip_escaping = false;
-      break;
-    }
-  }
-
-  if (can_skip_escaping) {
-    output->Append(input.data(), input.length());
-  } else {
-    strings::ArrayByteSource source(input);
-    Escape(&source, output);
-  }
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/json_escaping.h b/src/google/protobuf/util/internal/json_escaping.h
deleted file mode 100644
index 7d54f22..0000000
--- a/src/google/protobuf/util/internal/json_escaping.h
+++ /dev/null
@@ -1,98 +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_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>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-class JsonEscaping {
- public:
-  // 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 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 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 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 constexpr uint16_t kMaxLowSurrogate = 0xdfff;
-
-  // The minimum value of a unicode supplementary code point.
-  // See http://www.unicode.org/glossary/#supplementary_code_point
-  static constexpr uint32_t kMinSupplementaryCodePoint = 0x010000;
-
-  // The minimum value of a unicode code point.
-  // See http://www.unicode.org/glossary/#code_point
-  static constexpr uint32_t kMinCodePoint = 0x000000;
-
-  // The maximum value of a unicode code point.
-  // See http://www.unicode.org/glossary/#code_point
-  static constexpr uint32_t kMaxCodePoint = 0x10ffff;
-
-  JsonEscaping() {}
-  virtual ~JsonEscaping() {}
-
-  // Escape the given ByteSource to the given ByteSink.
-  static void Escape(strings::ByteSource* input, strings::ByteSink* output);
-
-  // Escape the given ByteSource to the given ByteSink.
-  // This is optimized for the case where the string is all printable 7-bit
-  // ASCII and does not contain a few other characters (such as quotes).
-  static void Escape(StringPiece input, strings::ByteSink* output);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(JsonEscaping);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_ESCAPING_H__
diff --git a/src/google/protobuf/util/internal/json_objectwriter.cc b/src/google/protobuf/util/internal/json_objectwriter.cc
deleted file mode 100644
index 1a86f00..0000000
--- a/src/google/protobuf/util/internal/json_objectwriter.cc
+++ /dev/null
@@ -1,190 +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 <google/protobuf/util/internal/json_objectwriter.h>
-
-#include <cmath>
-#include <cstdint>
-#include <limits>
-
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/json_escaping.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-
-JsonObjectWriter::~JsonObjectWriter() {
-  if (element_ && !element_->is_root()) {
-    GOOGLE_LOG(WARNING) << "JsonObjectWriter was not fully closed.";
-  }
-}
-
-JsonObjectWriter* JsonObjectWriter::StartObject(StringPiece name) {
-  WritePrefix(name);
-  WriteChar('{');
-  PushObject();
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::EndObject() {
-  Pop();
-  WriteChar('}');
-  if (element() && element()->is_root()) NewLine();
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::StartList(StringPiece name) {
-  WritePrefix(name);
-  WriteChar('[');
-  PushArray();
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::EndList() {
-  Pop();
-  WriteChar(']');
-  if (element()->is_root()) NewLine();
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderBool(StringPiece name,
-                                               bool value) {
-  return RenderSimple(name, value ? "true" : "false");
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderInt32(StringPiece name,
-                                                int32_t value) {
-  return RenderSimple(name, StrCat(value));
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderUint32(StringPiece name,
-                                                 uint32_t value) {
-  return RenderSimple(name, StrCat(value));
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderInt64(StringPiece name,
-                                                int64_t value) {
-  WritePrefix(name);
-  WriteChar('"');
-  WriteRawString(StrCat(value));
-  WriteChar('"');
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderUint64(StringPiece name,
-                                                 uint64_t value) {
-  WritePrefix(name);
-  WriteChar('"');
-  WriteRawString(StrCat(value));
-  WriteChar('"');
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderDouble(StringPiece name,
-                                                 double value) {
-  if (std::isfinite(value)) {
-    return RenderSimple(name, SimpleDtoa(value));
-  }
-
-  // Render quoted with NaN/Infinity-aware DoubleAsString.
-  return RenderString(name, DoubleAsString(value));
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderFloat(StringPiece name,
-                                                float value) {
-  if (std::isfinite(value)) {
-    return RenderSimple(name, SimpleFtoa(value));
-  }
-
-  // Render quoted with NaN/Infinity-aware FloatAsString.
-  return RenderString(name, FloatAsString(value));
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderString(StringPiece name,
-                                                 StringPiece value) {
-  WritePrefix(name);
-  WriteChar('"');
-  JsonEscaping::Escape(value, &sink_);
-  WriteChar('"');
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderBytes(StringPiece name,
-                                                StringPiece value) {
-  WritePrefix(name);
-  std::string base64;
-
-  if (use_websafe_base64_for_bytes_)
-    WebSafeBase64EscapeWithPadding(std::string(value), &base64);
-  else
-    Base64Escape(value, &base64);
-
-  WriteChar('"');
-  // TODO(wpoon): Consider a ByteSink solution that writes the base64 bytes
-  //              directly to the stream, rather than first putting them
-  //              into a string and then writing them to the stream.
-  stream_->WriteRaw(base64.data(), base64.size());
-  WriteChar('"');
-  return this;
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderNull(StringPiece name) {
-  return RenderSimple(name, "null");
-}
-
-JsonObjectWriter* JsonObjectWriter::RenderNullAsEmpty(StringPiece name) {
-  return RenderSimple(name, "");
-}
-
-void JsonObjectWriter::WritePrefix(StringPiece name) {
-  bool not_first = !element()->is_first();
-  if (not_first) WriteChar(',');
-  if (not_first || !element()->is_root()) NewLine();
-  if (!name.empty() || element()->is_json_object()) {
-    WriteChar('"');
-    if (!name.empty()) {
-      JsonEscaping::Escape(name, &sink_);
-    }
-    WriteRawString("\":");
-    if (!indent_string_.empty()) WriteChar(' ');
-  }
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/json_objectwriter.h b/src/google/protobuf/util/internal/json_objectwriter.h
deleted file mode 100644
index cb7dff6..0000000
--- a/src/google/protobuf/util/internal/json_objectwriter.h
+++ /dev/null
@@ -1,278 +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_UTIL_INTERNAL_JSON_OBJECTWRITER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_OBJECTWRITER_H__
-
-#include <cstdint>
-#include <memory>
-#include <string>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/stubs/bytestream.h>
-#include <google/protobuf/util/internal/structured_objectwriter.h>
-
-// clang-format off
-#include <google/protobuf/port_def.inc>
-// clang-format on
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-
-// An ObjectWriter implementation that outputs JSON. This ObjectWriter
-// supports writing a compact form or a pretty printed form.
-//
-// Sample usage:
-//   string output;
-//   StringOutputStream* str_stream = new StringOutputStream(&output);
-//   CodedOutputStream* out_stream = new CodedOutputStream(str_stream);
-//   JsonObjectWriter* ow = new JsonObjectWriter("  ", out_stream);
-//   ow->StartObject("")
-//       ->RenderString("name", "value")
-//       ->RenderString("emptystring", string())
-//       ->StartObject("nested")
-//         ->RenderInt64("light", 299792458);
-//         ->RenderDouble("pi", 3.141592653589793);
-//       ->EndObject()
-//       ->StartList("empty")
-//       ->EndList()
-//     ->EndObject();
-//
-// And then the output string would become:
-// {
-//   "name": "value",
-//   "emptystring": "",
-//   "nested": {
-//     "light": "299792458",
-//     "pi": 3.141592653589793
-//   },
-//   "empty": []
-// }
-//
-// JsonObjectWriter does not validate if calls actually result in valid JSON.
-// For example, passing an empty name when one would be required won't result
-// in an error, just an invalid output.
-//
-// Note that all int64 and uint64 are rendered as strings instead of numbers.
-// This is because JavaScript parses numbers as 64-bit float thus int64 and
-// uint64 would lose precision if rendered as numbers.
-//
-// JsonObjectWriter is thread-unsafe.
-class PROTOBUF_EXPORT JsonObjectWriter : public StructuredObjectWriter {
- public:
-  JsonObjectWriter(StringPiece indent_string, io::CodedOutputStream* out)
-      : element_(new Element(/*parent=*/nullptr, /*is_json_object=*/false)),
-        stream_(out),
-        sink_(out),
-        indent_string_(indent_string),
-        indent_char_('\0'),
-        indent_count_(0),
-        use_websafe_base64_for_bytes_(false) {
-    // See if we have a trivial sequence of indent characters.
-    if (!indent_string.empty()) {
-      indent_char_ = indent_string[0];
-      indent_count_ = indent_string.length();
-      for (int i = 1; i < indent_string.length(); i++) {
-        if (indent_char_ != indent_string_[i]) {
-          indent_char_ = '\0';
-          indent_count_ = 0;
-          break;
-        }
-      }
-    }
-  }
-  ~JsonObjectWriter() override;
-
-  // ObjectWriter methods.
-  JsonObjectWriter* StartObject(StringPiece name) override;
-  JsonObjectWriter* EndObject() override;
-  JsonObjectWriter* StartList(StringPiece name) override;
-  JsonObjectWriter* EndList() override;
-  JsonObjectWriter* RenderBool(StringPiece name, bool 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,
-                                 StringPiece value) override;
-  JsonObjectWriter* RenderBytes(StringPiece name, StringPiece value) override;
-  JsonObjectWriter* RenderNull(StringPiece name) override;
-  virtual JsonObjectWriter* RenderNullAsEmpty(StringPiece name);
-
-  void set_use_websafe_base64_for_bytes(bool value) {
-    use_websafe_base64_for_bytes_ = value;
-  }
-
- protected:
-  class PROTOBUF_EXPORT Element : public BaseElement {
-   public:
-    Element(Element* parent, bool is_json_object)
-        : BaseElement(parent),
-          is_first_(true),
-          is_json_object_(is_json_object) {}
-
-    // Called before each field of the Element is to be processed.
-    // Returns true if this is the first call (processing the first field).
-    bool is_first() {
-      if (is_first_) {
-        is_first_ = false;
-        return true;
-      }
-      return false;
-    }
-
-    // Whether we are currently rendering inside a JSON object (i.e., between
-    // StartObject() and EndObject()).
-    bool is_json_object() const { return is_json_object_; }
-
-   private:
-    bool is_first_;
-    bool is_json_object_;
-
-    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Element);
-  };
-
-  Element* element() override { return element_.get(); }
-
- private:
-  class PROTOBUF_EXPORT ByteSinkWrapper : public strings::ByteSink {
-   public:
-    explicit ByteSinkWrapper(io::CodedOutputStream* stream) : stream_(stream) {}
-    ~ByteSinkWrapper() override {}
-
-    // ByteSink methods.
-    void Append(const char* bytes, size_t n) override {
-      stream_->WriteRaw(bytes, n);
-    }
-
-   private:
-    io::CodedOutputStream* stream_;
-
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ByteSinkWrapper);
-  };
-
-  // Renders a simple value as a string. By default all non-string Render
-  // methods convert their argument to a string and call this method. This
-  // method can then be used to render the simple value without escaping it.
-  JsonObjectWriter* RenderSimple(StringPiece name,
-                                 StringPiece value) {
-    WritePrefix(name);
-    WriteRawString(value);
-    return this;
-  }
-
-  // Pushes a new JSON array element to the stack.
-  void PushArray() {
-    element_.reset(new Element(element_.release(), /*is_json_object=*/false));
-  }
-
-  // Pushes a new JSON object element to the stack.
-  void PushObject() {
-    element_.reset(new Element(element_.release(), /*is_json_object=*/true));
-  }
-
-  // Pops an element off of the stack and deletes the popped element.
-  void Pop() {
-    bool needs_newline = !element_->is_first();
-    element_.reset(element_->pop<Element>());
-    if (needs_newline) NewLine();
-  }
-
-  // If pretty printing is enabled, this will write a newline to the output,
-  // followed by optional indentation. Otherwise this method is a noop.
-  void NewLine() {
-    if (!indent_string_.empty()) {
-      size_t len = sizeof('\n') + (indent_string_.size() * element()->level());
-
-      // 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_t* out = nullptr;
-      if (indent_count_ > 0) {
-        out = stream_->GetDirectBufferForNBytesAndAdvance(len);
-      }
-
-      if (out != nullptr) {
-        out[0] = '\n';
-        memset(&out[1], indent_char_, len - 1);
-      } else {
-        // Slow path, no contiguous output buffer available.
-        WriteChar('\n');
-        for (int i = 0; i < element()->level(); i++) {
-          stream_->WriteRaw(indent_string_.c_str(), indent_string_.length());
-        }
-      }
-    }
-  }
-
-  // Writes a prefix. This will write out any pretty printing and
-  // commas that are required, followed by the name and a ':' if
-  // the name is not null.
-  void WritePrefix(StringPiece name);
-
-  // Writes an individual character to the output.
-  void WriteChar(const char c) { stream_->WriteRaw(&c, sizeof(c)); }
-
-  // Writes a string to the output.
-  void WriteRawString(StringPiece s) {
-    stream_->WriteRaw(s.data(), s.length());
-  }
-
-  std::unique_ptr<Element> element_;
-  io::CodedOutputStream* stream_;
-  ByteSinkWrapper sink_;
-  const std::string indent_string_;
-
-  // For the common case of indent being a single character repeated.
-  char indent_char_;
-  int indent_count_;
-
-  // Whether to use regular or websafe base64 encoding for byte fields. Defaults
-  // to regular base64 encoding.
-  bool use_websafe_base64_for_bytes_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonObjectWriter);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/json_objectwriter_test.cc b/src/google/protobuf/util/internal/json_objectwriter_test.cc
deleted file mode 100644
index 8acf2c5..0000000
--- a/src/google/protobuf/util/internal/json_objectwriter_test.cc
+++ /dev/null
@@ -1,315 +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 <google/protobuf/util/internal/json_objectwriter.h>
-
-#include <cstdint>
-
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <gtest/gtest.h>
-#include <google/protobuf/util/internal/utility.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-using io::CodedOutputStream;
-using io::StringOutputStream;
-
-class JsonObjectWriterTest : public ::testing::Test {
- protected:
-  JsonObjectWriterTest()
-      : str_stream_(new StringOutputStream(&output_)),
-        out_stream_(new CodedOutputStream(str_stream_)),
-        ow_(nullptr) {}
-
-  ~JsonObjectWriterTest() override { delete ow_; }
-
-  std::string CloseStreamAndGetString() {
-    delete out_stream_;
-    delete str_stream_;
-    return output_;
-  }
-
-  std::string output_;
-  StringOutputStream* const str_stream_;
-  CodedOutputStream* const out_stream_;
-  JsonObjectWriter* ow_;
-};
-
-TEST_F(JsonObjectWriterTest, EmptyRootObject) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")->EndObject();
-  EXPECT_EQ("{}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, EmptyObject) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")
-      ->RenderString("test", "value")
-      ->StartObject("empty")
-      ->EndObject()
-      ->EndObject();
-  EXPECT_EQ("{\"test\":\"value\",\"empty\":{}}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, EmptyRootList) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartList("")->EndList();
-  EXPECT_EQ("[]", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, EmptyList) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")
-      ->RenderString("test", "value")
-      ->StartList("empty")
-      ->EndList()
-      ->EndObject();
-  EXPECT_EQ("{\"test\":\"value\",\"empty\":[]}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, EmptyObjectKey) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")->RenderString("", "value")->EndObject();
-  EXPECT_EQ("{\"\":\"value\"}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, ObjectInObject) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")
-      ->StartObject("nested")
-      ->RenderString("field", "value")
-      ->EndObject()
-      ->EndObject();
-  EXPECT_EQ("{\"nested\":{\"field\":\"value\"}}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, ListInObject) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")
-      ->StartList("nested")
-      ->RenderString("", "value")
-      ->EndList()
-      ->EndObject();
-  EXPECT_EQ("{\"nested\":[\"value\"]}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, ObjectInList) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartList("")
-      ->StartObject("")
-      ->RenderString("field", "value")
-      ->EndObject()
-      ->EndList();
-  EXPECT_EQ("[{\"field\":\"value\"}]", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, ListInList) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartList("")
-      ->StartList("")
-      ->RenderString("", "value")
-      ->EndList()
-      ->EndList();
-  EXPECT_EQ("[[\"value\"]]", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, RenderPrimitives) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")
-      ->RenderBool("bool", true)
-      ->RenderDouble("double", std::numeric_limits<double>::max())
-      ->RenderFloat("float", std::numeric_limits<float>::max())
-      ->RenderInt32("int", std::numeric_limits<int32_t>::min())
-      ->RenderInt64("long", std::numeric_limits<int64_t>::min())
-      ->RenderBytes("bytes", "abracadabra")
-      ->RenderString("string", "string")
-      ->RenderBytes("emptybytes", "")
-      ->RenderString("emptystring", std::string())
-      ->EndObject();
-  EXPECT_EQ(
-      "{\"bool\":true,"
-      "\"double\":" +
-          ValueAsString<double>(std::numeric_limits<double>::max()) +
-          ","
-          "\"float\":" +
-          ValueAsString<float>(std::numeric_limits<float>::max()) +
-          ","
-          "\"int\":-2147483648,"
-          "\"long\":\"-9223372036854775808\","
-          "\"bytes\":\"YWJyYWNhZGFicmE=\","
-          "\"string\":\"string\","
-          "\"emptybytes\":\"\","
-          "\"emptystring\":\"\"}",
-      CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, BytesEncodesAsNonWebSafeBase64) {
-  std::string s;
-  s.push_back('\377');
-  s.push_back('\357');
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")->RenderBytes("bytes", s)->EndObject();
-  // Non-web-safe would encode this as "/+8="
-  EXPECT_EQ("{\"bytes\":\"/+8=\"}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, PrettyPrintList) {
-  ow_ = new JsonObjectWriter(" ", out_stream_);
-  ow_->StartObject("")
-      ->StartList("items")
-      ->RenderString("", "item1")
-      ->RenderString("", "item2")
-      ->RenderString("", "item3")
-      ->EndList()
-      ->StartList("empty")
-      ->EndList()
-      ->EndObject();
-  EXPECT_EQ(
-      "{\n"
-      " \"items\": [\n"
-      "  \"item1\",\n"
-      "  \"item2\",\n"
-      "  \"item3\"\n"
-      " ],\n"
-      " \"empty\": []\n"
-      "}\n",
-      CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, PrettyPrintObject) {
-  ow_ = new JsonObjectWriter(" ", out_stream_);
-  ow_->StartObject("")
-      ->StartObject("items")
-      ->RenderString("key1", "item1")
-      ->RenderString("key2", "item2")
-      ->RenderString("key3", "item3")
-      ->EndObject()
-      ->StartObject("empty")
-      ->EndObject()
-      ->EndObject();
-  EXPECT_EQ(
-      "{\n"
-      " \"items\": {\n"
-      "  \"key1\": \"item1\",\n"
-      "  \"key2\": \"item2\",\n"
-      "  \"key3\": \"item3\"\n"
-      " },\n"
-      " \"empty\": {}\n"
-      "}\n",
-      CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, PrettyPrintEmptyObjectInEmptyList) {
-  ow_ = new JsonObjectWriter(" ", out_stream_);
-  ow_->StartObject("")
-      ->StartList("list")
-      ->StartObject("")
-      ->EndObject()
-      ->EndList()
-      ->EndObject();
-  EXPECT_EQ(
-      "{\n"
-      " \"list\": [\n"
-      "  {}\n"
-      " ]\n"
-      "}\n",
-      CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, PrettyPrintDoubleIndent) {
-  ow_ = new JsonObjectWriter("  ", out_stream_);
-  ow_->StartObject("")
-      ->RenderBool("bool", true)
-      ->RenderInt32("int", 42)
-      ->EndObject();
-  EXPECT_EQ(
-      "{\n"
-      "  \"bool\": true,\n"
-      "  \"int\": 42\n"
-      "}\n",
-      CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, StringsEscapedAndEnclosedInDoubleQuotes) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")->RenderString("string", "'<>&amp;\\\"\r\n")->EndObject();
-  EXPECT_EQ("{\"string\":\"'\\u003c\\u003e&amp;\\\\\\\"\\r\\n\"}",
-            CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, Stringification) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")
-      ->RenderDouble("double_nan", std::numeric_limits<double>::quiet_NaN())
-      ->RenderFloat("float_nan", std::numeric_limits<float>::quiet_NaN())
-      ->RenderDouble("double_pos", std::numeric_limits<double>::infinity())
-      ->RenderFloat("float_pos", std::numeric_limits<float>::infinity())
-      ->RenderDouble("double_neg", -std::numeric_limits<double>::infinity())
-      ->RenderFloat("float_neg", -std::numeric_limits<float>::infinity())
-      ->EndObject();
-  EXPECT_EQ(
-      "{\"double_nan\":\"NaN\","
-      "\"float_nan\":\"NaN\","
-      "\"double_pos\":\"Infinity\","
-      "\"float_pos\":\"Infinity\","
-      "\"double_neg\":\"-Infinity\","
-      "\"float_neg\":\"-Infinity\"}",
-      CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, TestRegularByteEncoding) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->StartObject("")
-      ->RenderBytes("bytes", "\x03\xef\xc0")
-      ->EndObject();
-
-  // Test that we get regular (non websafe) base64 encoding on byte fields by
-  // default.
-  EXPECT_EQ("{\"bytes\":\"A+/A\"}", CloseStreamAndGetString());
-}
-
-TEST_F(JsonObjectWriterTest, TestWebsafeByteEncoding) {
-  ow_ = new JsonObjectWriter("", out_stream_);
-  ow_->set_use_websafe_base64_for_bytes(true);
-  ow_->StartObject("")
-      ->RenderBytes("bytes", "\x03\xef\xc0\x10")
-      ->EndObject();
-
-  // Test that we get websafe base64 encoding when explicitly asked.
-  EXPECT_EQ("{\"bytes\":\"A-_AEA==\"}", CloseStreamAndGetString());
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/json_stream_parser.cc b/src/google/protobuf/util/internal/json_stream_parser.cc
deleted file mode 100644
index 5c34dbc..0000000
--- a/src/google/protobuf/util/internal/json_stream_parser.cc
+++ /dev/null
@@ -1,995 +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 <google/protobuf/util/internal/json_stream_parser.h>
-
-#include <algorithm>
-#include <cctype>
-#include <cmath>
-#include <memory>
-#include <stack>
-#include <string>
-
-#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>
-
-
-namespace google {
-namespace protobuf {
-namespace util {
-
-namespace converter {
-
-// Number of digits in an escaped UTF-16 code unit ('\\' 'u' X X X X)
-static const int kUnicodeEscapedLength = 6;
-
-static const int kDefaultMaxRecursionDepth = 100;
-
-// These cannot be constexpr for portability with VS2015.
-static const StringPiece kKeywordTrue = "true";
-static const StringPiece kKeywordFalse = "false";
-static const StringPiece kKeywordNull = "null";
-
-inline bool IsLetter(char c) {
-  return ('a' <= c && c <= 'z') || ('A' <= c && c <= 'Z') || (c == '_') ||
-         (c == '$');
-}
-
-inline bool IsAlphanumeric(char c) {
-  return IsLetter(c) || ('0' <= c && c <= '9');
-}
-
-// 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 == ',');
-}
-
-inline void ReplaceInvalidCodePoints(StringPiece str,
-                                     const std::string& replacement,
-                                     std::string* dst) {
-  while (!str.empty()) {
-    int n_valid_bytes = internal::UTF8SpnStructurallyValid(str);
-    StringPiece valid_part = str.substr(0, n_valid_bytes);
-    StrAppend(dst, valid_part);
-
-    if (n_valid_bytes == str.size()) {
-      break;
-    }
-
-    // Append replacement value.
-    StrAppend(dst, replacement);
-
-    // Move past valid bytes + one invalid byte.
-    str.remove_prefix(n_valid_bytes + 1);
-  }
-}
-
-static bool ConsumeKey(StringPiece* input, StringPiece* key) {
-  if (input->empty() || !IsLetter((*input)[0])) return false;
-  int len = 1;
-  for (; len < input->size(); ++len) {
-    if (!IsAlphanumeric((*input)[len])) {
-      break;
-    }
-  }
-  *key = StringPiece(input->data(), len);
-  *input = StringPiece(input->data() + len, input->size() - len);
-  return true;
-}
-
-// Same as 'ConsumeKey', but allows a widened set of key characters.
-static bool ConsumeKeyPermissive(StringPiece* input,
-                                 StringPiece* key) {
-  if (input->empty() || !IsLetter((*input)[0])) return false;
-  int len = 1;
-  for (; len < input->size(); ++len) {
-    if (IsKeySeparator((*input)[len])) {
-      break;
-    }
-  }
-  *key = StringPiece(input->data(), len);
-  *input = StringPiece(input->data() + len, input->size() - len);
-  return true;
-}
-
-static bool MatchKey(StringPiece input) {
-  return !input.empty() && IsLetter(input[0]);
-}
-
-JsonStreamParser::JsonStreamParser(ObjectWriter* ow)
-    : ow_(ow),
-      stack_(),
-      leftover_(),
-      json_(),
-      p_(),
-      key_(),
-      key_storage_(),
-      finishing_(false),
-      seen_non_whitespace_(false),
-      allow_no_root_element_(false),
-      parsed_(),
-      parsed_storage_(),
-      string_open_(0),
-      chunk_storage_(),
-      coerce_to_utf8_(false),
-      utf8_replacement_character_(" "),
-      allow_empty_null_(false),
-      allow_permissive_key_naming_(false),
-      loose_float_number_conversion_(false),
-      recursion_depth_(0),
-      max_recursion_depth_(kDefaultMaxRecursionDepth) {
-  // Initialize the stack with a single value to be parsed.
-  stack_.push(VALUE);
-}
-
-JsonStreamParser::~JsonStreamParser() {}
-
-
-util::Status JsonStreamParser::Parse(StringPiece json) {
-  StringPiece chunk = json;
-  // If we have leftovers from a previous chunk, append the new chunk to it
-  // and create a new StringPiece pointing at the string's data. This could
-  // be large but we rely on the chunks to be small, assuming they are
-  // fragments of a Cord.
-  if (!leftover_.empty()) {
-    // Don't point chunk to leftover_ because leftover_ will be updated in
-    // ParseChunk(chunk).
-    chunk_storage_.swap(leftover_);
-    StrAppend(&chunk_storage_, json);
-    chunk = StringPiece(chunk_storage_);
-  }
-
-  // Find the structurally valid UTF8 prefix and parse only that.
-  int n = internal::UTF8SpnStructurallyValid(chunk);
-  if (n > 0) {
-    util::Status status = ParseChunk(chunk.substr(0, n));
-
-    // Any leftover characters are stashed in leftover_ for later parsing when
-    // there is more data available.
-    StrAppend(&leftover_, chunk.substr(n));
-    return status;
-  } else {
-    leftover_.assign(chunk.data(), chunk.size());
-    return util::Status();
-  }
-}
-
-util::Status JsonStreamParser::FinishParse() {
-  // If we do not expect anything and there is nothing left to parse we're all
-  // done.
-  if (stack_.empty() && leftover_.empty()) {
-    return util::Status();
-  }
-
-  // Lifetime needs to last until RunParser returns, so keep this variable
-  // outside of the coerce_to_utf8 block.
-  std::unique_ptr<std::string> scratch;
-
-  bool is_valid_utf8 = internal::IsStructurallyValidUTF8(leftover_);
-  if (coerce_to_utf8_ && !is_valid_utf8) {
-    scratch.reset(new std::string);
-    scratch->reserve(leftover_.size() * utf8_replacement_character_.size());
-    ReplaceInvalidCodePoints(leftover_, utf8_replacement_character_,
-                             scratch.get());
-    p_ = json_ = *scratch;
-  } else {
-    p_ = json_ = leftover_;
-    if (!is_valid_utf8) {
-      return ReportFailure("Encountered non UTF-8 code points.",
-                           ParseErrorType::NON_UTF_8);
-    }
-  }
-
-  // Parse the remainder in finishing mode, which reports errors for things like
-  // unterminated strings or unknown tokens that would normally be retried.
-  finishing_ = true;
-  util::Status result = RunParser();
-  if (result.ok()) {
-    SkipWhitespace();
-    if (!p_.empty()) {
-      result =
-          ReportFailure("Parsing terminated before end of input.",
-                        ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
-    }
-  }
-  return result;
-}
-
-util::Status JsonStreamParser::ParseChunk(StringPiece chunk) {
-  // Do not do any work if the chunk is empty.
-  if (chunk.empty()) return util::Status();
-
-  p_ = json_ = chunk;
-
-  finishing_ = false;
-  util::Status result = RunParser();
-  if (!result.ok()) return result;
-
-  SkipWhitespace();
-  if (p_.empty()) {
-    // If we parsed everything we had, clear the leftover.
-    leftover_.clear();
-  } else {
-    // 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.",
-          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.
-    leftover_ = std::string(p_);
-  }
-  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();
-    TokenType t = (string_open_ == 0) ? GetNextTokenType() : BEGIN_STRING;
-    stack_.pop();
-    util::Status result;
-    switch (type) {
-      case VALUE:
-        if (allow_no_root_element_ && IsInputAllWhiteSpaces(t)) {
-          return util::Status();
-        }
-        result = ParseValue(t);
-        break;
-
-      case OBJ_MID:
-        result = ParseObjectMid(t);
-        break;
-
-      case ENTRY:
-        result = ParseEntry(t);
-        break;
-
-      case ENTRY_MID:
-        result = ParseEntryMid(t);
-        break;
-
-      case ARRAY_VALUE:
-        result = ParseArrayValue(t);
-        break;
-
-      case ARRAY_MID:
-        result = ParseArrayMid(t);
-        break;
-
-      default:
-        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_ && 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.
-        if (!key_.empty() && key_storage_.empty()) {
-          StrAppend(&key_storage_, key_);
-          key_ = StringPiece(key_storage_);
-        }
-        result = util::Status();
-      }
-      return result;
-    }
-  }
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseValue(TokenType type) {
-  switch (type) {
-    case BEGIN_OBJECT:
-      return HandleBeginObject();
-    case BEGIN_ARRAY:
-      return HandleBeginArray();
-    case BEGIN_STRING:
-      return ParseString();
-    case BEGIN_NUMBER:
-      return ParseNumber();
-    case BEGIN_TRUE:
-      return ParseTrue();
-    case BEGIN_FALSE:
-      return ParseFalse();
-    case BEGIN_NULL:
-      return ParseNull();
-    case UNKNOWN:
-      return ReportUnknown("Expected a value.", ParseErrorType::EXPECTED_VALUE);
-    default: {
-      // Special case for having been cut off while parsing, wait for more data.
-      // This handles things like 'fals' being at the end of the string, we
-      // 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::CancelledError("");
-      }
-
-      if (allow_empty_null_ && IsEmptyNullAllowed(type)) {
-        return ParseEmptyNull();
-      }
-      return ReportFailure("Unexpected token.",
-                           ParseErrorType::UNEXPECTED_TOKEN);
-    }
-  }
-}
-
-util::Status JsonStreamParser::ParseString() {
-  util::Status result = ParseStringHelper();
-  if (result.ok()) {
-    ow_->RenderString(key_, parsed_);
-    key_ = StringPiece();
-    parsed_ = StringPiece();
-    parsed_storage_.clear();
-  }
-  return result;
-}
-
-util::Status JsonStreamParser::ParseStringHelper() {
-  // If we haven't seen the start quote, grab it and remember it for later.
-  if (string_open_ == 0) {
-    string_open_ = *p_.data();
-    GOOGLE_DCHECK(string_open_ == '\"' || string_open_ == '\'');
-    Advance();
-  }
-  // Track where we last copied data from so we can minimize copying.
-  const char* last = p_.data();
-  while (!p_.empty()) {
-    const char* data = p_.data();
-    if (*data == '\\') {
-      // We're about to handle an escape, copy all bytes from last to data.
-      if (last < data) {
-        parsed_storage_.append(last, data - last);
-      }
-      // If we ran out of string after the \, cancel or report an error
-      // depending on if we expect more data later.
-      if (p_.length() == 1) {
-        if (!finishing_) {
-          return util::CancelledError("");
-        }
-        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') {
-        util::Status result = ParseUnicodeEscape();
-        if (!result.ok()) {
-          return result;
-        }
-        // Move last pointer past the unicode escape and continue.
-        last = p_.data();
-        continue;
-      }
-      // Handle the standard set of backslash-escaped characters.
-      switch (data[1]) {
-        case 'b':
-          parsed_storage_.push_back('\b');
-          break;
-        case 'f':
-          parsed_storage_.push_back('\f');
-          break;
-        case 'n':
-          parsed_storage_.push_back('\n');
-          break;
-        case 'r':
-          parsed_storage_.push_back('\r');
-          break;
-        case 't':
-          parsed_storage_.push_back('\t');
-          break;
-        case 'v':
-          parsed_storage_.push_back('\v');
-          break;
-        default:
-          parsed_storage_.push_back(data[1]);
-      }
-      // We handled two characters, so advance past them and continue.
-      p_.remove_prefix(2);
-      last = p_.data();
-      continue;
-    }
-    // If we found the closing quote note it, advance past it, and return.
-    if (*data == string_open_) {
-      // If we didn't copy anything, reuse the input buffer.
-      if (parsed_storage_.empty()) {
-        parsed_ = StringPiece(last, data - last);
-      } else {
-        if (last < data) {
-          parsed_storage_.append(last, data - last);
-        }
-        parsed_ = StringPiece(parsed_storage_);
-      }
-      // Clear the quote char so next time we try to parse a string we'll
-      // start fresh.
-      string_open_ = 0;
-      Advance();
-      return util::Status();
-    }
-    // Normal character, just advance past it.
-    Advance();
-  }
-  // If we ran out of characters, copy over what we have so far.
-  if (last < p_.data()) {
-    parsed_storage_.append(last, p_.data() - last);
-  }
-  // If we didn't find the closing quote but we expect more data, cancel for now
-  if (!finishing_) {
-    return util::CancelledError("");
-  }
-  // End of string reached without a closing quote, report an error.
-  string_open_ = 0;
-  return ReportFailure("Closing quote expected in string.",
-                       ParseErrorType::EXPECTED_CLOSING_QUOTE);
-}
-
-// Converts a unicode escaped character to a decimal value stored in a char32
-// for use in UTF8 encoding utility.  We assume that str begins with \uhhhh and
-// convert that from the hex number to a decimal value.
-//
-// There are some security exploits with UTF-8 that we should be careful of:
-//   - http://www.unicode.org/reports/tr36/#UTF-8_Exploit
-//   - http://sites/intl-eng/design-guide/core-application
-util::Status JsonStreamParser::ParseUnicodeEscape() {
-  if (p_.length() < kUnicodeEscapedLength) {
-    if (!finishing_) {
-      return util::CancelledError("");
-    }
-    return ReportFailure("Illegal hex string.",
-                         ParseErrorType::ILLEGAL_HEX_STRING);
-  }
-  GOOGLE_DCHECK_EQ('\\', p_.data()[0]);
-  GOOGLE_DCHECK_EQ('u', p_.data()[1]);
-  uint32_t code = 0;
-  for (int i = 2; i < kUnicodeEscapedLength; ++i) {
-    if (!isxdigit(p_.data()[i])) {
-      return ReportFailure("Invalid escape sequence.",
-                           ParseErrorType::INVALID_ESCAPE_SEQUENCE);
-    }
-    code = (code << 4) + hex_digit_to_int(p_.data()[i]);
-  }
-  if (code >= JsonEscaping::kMinHighSurrogate &&
-      code <= JsonEscaping::kMaxHighSurrogate) {
-    if (p_.length() < 2 * kUnicodeEscapedLength) {
-      if (!finishing_) {
-        return util::CancelledError("");
-      }
-      if (!coerce_to_utf8_) {
-        return ReportFailure("Missing low surrogate.",
-                             ParseErrorType::MISSING_LOW_SURROGATE);
-      }
-    } else if (p_.data()[kUnicodeEscapedLength] == '\\' &&
-               p_.data()[kUnicodeEscapedLength + 1] == 'u') {
-      uint32_t low_code = 0;
-      for (int i = kUnicodeEscapedLength + 2; i < 2 * kUnicodeEscapedLength;
-           ++i) {
-        if (!isxdigit(p_.data()[i])) {
-          return ReportFailure("Invalid escape sequence.",
-                               ParseErrorType::INVALID_ESCAPE_SEQUENCE);
-        }
-        low_code = (low_code << 4) + hex_digit_to_int(p_.data()[i]);
-      }
-      if (low_code >= JsonEscaping::kMinLowSurrogate &&
-          low_code <= JsonEscaping::kMaxLowSurrogate) {
-        // Convert UTF-16 surrogate pair to 21-bit Unicode codepoint.
-        code = (((code & 0x3FF) << 10) | (low_code & 0x3FF)) +
-               JsonEscaping::kMinSupplementaryCodePoint;
-        // Advance past the first code unit escape.
-        p_.remove_prefix(kUnicodeEscapedLength);
-      } else if (!coerce_to_utf8_) {
-        return ReportFailure("Invalid low surrogate.",
-                             ParseErrorType::INVALID_LOW_SURROGATE);
-      }
-    } else if (!coerce_to_utf8_) {
-      return ReportFailure("Missing low surrogate.",
-                           ParseErrorType::MISSING_LOW_SURROGATE);
-    }
-  }
-  if (!coerce_to_utf8_ && !IsValidCodePoint(code)) {
-    return ReportFailure("Invalid unicode code point.",
-                         ParseErrorType::INVALID_UNICODE);
-  }
-  char buf[UTFmax];
-  int len = EncodeAsUTF8Char(code, buf);
-  // Advance past the [final] code unit escape.
-  p_.remove_prefix(kUnicodeEscapedLength);
-  parsed_storage_.append(buf, len);
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseNumber() {
-  NumberResult number;
-  util::Status result = ParseNumberHelper(&number);
-  if (result.ok()) {
-    switch (number.type) {
-      case NumberResult::DOUBLE:
-        ow_->RenderDouble(key_, number.double_val);
-        key_ = StringPiece();
-        break;
-
-      case NumberResult::INT:
-        ow_->RenderInt64(key_, number.int_val);
-        key_ = StringPiece();
-        break;
-
-      case NumberResult::UINT:
-        ow_->RenderUint64(key_, number.uint_val);
-        key_ = StringPiece();
-        break;
-
-      default:
-        return ReportFailure("Unable to parse number.",
-                             ParseErrorType::UNABLE_TO_PARSE_NUMBER);
-    }
-  }
-  return result;
-}
-
-util::Status JsonStreamParser::ParseDoubleHelper(const std::string& number,
-                                                 NumberResult* result) {
-  if (!safe_strtod(number, &result->double_val)) {
-    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.",
-                         ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
-  }
-  result->type = NumberResult::DOUBLE;
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseNumberHelper(NumberResult* result) {
-  const char* data = p_.data();
-  int length = p_.length();
-
-  // Look for the first non-numeric character, or the end of the string.
-  int index = 0;
-  bool floating = false;
-  bool negative = data[index] == '-';
-  // Find the first character that cannot be part of the number. Along the way
-  // detect if the number needs to be parsed as a double.
-  // Note that this restricts numbers to the JSON specification, so for example
-  // we do not support hex or octal notations.
-  for (; index < length; ++index) {
-    char c = data[index];
-    if (isdigit(c)) continue;
-    if (c == '.' || c == 'e' || c == 'E') {
-      floating = true;
-      continue;
-    }
-    if (c == '+' || c == '-' || c == 'x') continue;
-    // Not a valid number character, break out.
-    break;
-  }
-
-  // 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::CancelledError("");
-  }
-
-  // Create a string containing just the number, so we can use safe_strtoX
-  std::string number = std::string(p_.substr(0, index));
-
-  // Floating point number, parse as a double.
-  if (floating) {
-    util::Status status = ParseDoubleHelper(number, result);
-    if (status.ok()) {
-      p_.remove_prefix(index);
-    }
-    return status;
-  }
-
-  // Positive non-floating point number, parse as a uint64_t.
-  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.",
-          ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
-    }
-    if (safe_strtou64(number, &result->uint_val)) {
-      result->type = NumberResult::UINT;
-      p_.remove_prefix(index);
-      return util::Status();
-    } else {
-      // If the value is too large, parse it as double.
-      util::Status status = ParseDoubleHelper(number, result);
-      if (status.ok()) {
-        p_.remove_prefix(index);
-      }
-      return status;
-    }
-  }
-
-  // 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.",
-        ParseErrorType::OCTAL_OR_HEX_ARE_NOT_VALID_JSON_VALUES);
-  }
-  // Negative non-floating point number, parse as an int64_t.
-  if (safe_strto64(number, &result->int_val)) {
-    result->type = NumberResult::INT;
-    p_.remove_prefix(index);
-    return util::Status();
-  } else {
-    // If the value is too large, parse it as double.
-    util::Status status = ParseDoubleHelper(number, result);
-    if (status.ok()) {
-      p_.remove_prefix(index);
-    }
-    return status;
-  }
-}
-
-util::Status JsonStreamParser::HandleBeginObject() {
-  GOOGLE_DCHECK_EQ('{', *p_.data());
-  Advance();
-  ow_->StartObject(key_);
-  auto status = IncrementRecursionDepth(key_);
-  if (!status.ok()) {
-    return status;
-  }
-  key_ = StringPiece();
-  stack_.push(ENTRY);
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseObjectMid(TokenType type) {
-  if (type == UNKNOWN) {
-    return ReportUnknown("Expected , or } after key:value pair.",
-                         ParseErrorType::EXPECTED_COMMA_OR_BRACES);
-  }
-
-  // Object is complete, advance past the comma and render the EndObject.
-  if (type == END_OBJECT) {
-    Advance();
-    ow_->EndObject();
-    --recursion_depth_;
-    return util::Status();
-  }
-  // Found a comma, advance past it and get ready for an entry.
-  if (type == VALUE_SEPARATOR) {
-    Advance();
-    stack_.push(ENTRY);
-    return util::Status();
-  }
-  // Illegal token 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 }.",
-                         ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-
-  // Close the object and return. This allows for trailing commas.
-  if (type == END_OBJECT) {
-    ow_->EndObject();
-    Advance();
-    --recursion_depth_;
-    return util::Status();
-  }
-
-  util::Status result;
-  if (type == BEGIN_STRING) {
-    // Key is a string (standard JSON), parse it and store the string.
-    result = ParseStringHelper();
-    if (result.ok()) {
-      key_storage_.clear();
-      if (!parsed_storage_.empty()) {
-        parsed_storage_.swap(key_storage_);
-        key_ = StringPiece(key_storage_);
-      } else {
-        key_ = parsed_;
-      }
-      parsed_ = StringPiece();
-    }
-  } else if (type == BEGIN_KEY) {
-    // Key is a bare key (back compat), create a StringPiece pointing to it.
-    result = ParseKey();
-  } else if (type == BEGIN_NULL || type == BEGIN_TRUE || type == BEGIN_FALSE) {
-    // Key may be a bare key that begins with a reserved word.
-    result = ParseKey();
-    if (result.ok() && (key_ == kKeywordNull || key_ == kKeywordTrue ||
-                        key_ == kKeywordFalse)) {
-      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 }.",
-                           ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-  // On success we next expect an entry mid ':' then an object mid ',' or '}'
-  if (result.ok()) {
-    stack_.push(OBJ_MID);
-    stack_.push(ENTRY_MID);
-  }
-  return result;
-}
-
-util::Status JsonStreamParser::ParseEntryMid(TokenType type) {
-  if (type == UNKNOWN) {
-    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.",
-                       ParseErrorType::EXPECTED_COLON);
-}
-
-util::Status JsonStreamParser::HandleBeginArray() {
-  GOOGLE_DCHECK_EQ('[', *p_.data());
-  Advance();
-  ow_->StartList(key_);
-  key_ = StringPiece();
-  stack_.push(ARRAY_VALUE);
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseArrayValue(TokenType type) {
-  if (type == UNKNOWN) {
-    return ReportUnknown("Expected a value or ] within an array.",
-                         ParseErrorType::EXPECTED_VALUE_OR_BRACKET);
-  }
-
-  if (type == END_ARRAY) {
-    ow_->EndList();
-    Advance();
-    return util::Status();
-  }
-
-  // The ParseValue call may push something onto the stack so we need to make
-  // sure an ARRAY_MID is after it, so we push it on now. Also, the parsing of
-  // empty-null array value is relying on this ARRAY_MID token.
-  stack_.push(ARRAY_MID);
-  util::Status result = ParseValue(type);
-  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();
-  }
-  return result;
-}
-
-util::Status JsonStreamParser::ParseArrayMid(TokenType type) {
-  if (type == UNKNOWN) {
-    return ReportUnknown("Expected , or ] after array value.",
-                         ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
-  }
-
-  if (type == END_ARRAY) {
-    ow_->EndList();
-    Advance();
-    return util::Status();
-  }
-
-  // Found a comma, advance past it and expect an array value next.
-  if (type == VALUE_SEPARATOR) {
-    Advance();
-    stack_.push(ARRAY_VALUE);
-    return util::Status();
-  }
-  // Illegal token after array value.
-  return ReportFailure("Expected , or ] after array value.",
-                       ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
-}
-
-util::Status JsonStreamParser::ParseTrue() {
-  ow_->RenderBool(key_, true);
-  key_ = StringPiece();
-  p_.remove_prefix(kKeywordTrue.length());
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseFalse() {
-  ow_->RenderBool(key_, false);
-  key_ = StringPiece();
-  p_.remove_prefix(kKeywordFalse.length());
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseNull() {
-  ow_->RenderNull(key_);
-  key_ = StringPiece();
-  p_.remove_prefix(kKeywordNull.length());
-  return util::Status();
-}
-
-util::Status JsonStreamParser::ParseEmptyNull() {
-  ow_->RenderNull(key_);
-  key_ = StringPiece();
-  return util::Status();
-}
-
-bool JsonStreamParser::IsEmptyNullAllowed(TokenType type) {
-  if (stack_.empty()) return false;
-  return (stack_.top() == ARRAY_MID && type == VALUE_SEPARATOR) ||
-         stack_.top() == OBJ_MID;
-}
-
-util::Status JsonStreamParser::ReportFailure(StringPiece message,
-                                             ParseErrorType parse_code) {
-  (void)parse_code;  // Parameter is used in Google-internal code.
-  static const int kContextLength = 20;
-  const char* p_start = p_.data();
-  const char* json_start = json_.data();
-  const char* begin = std::max(p_start - kContextLength, json_start);
-  const char* end =
-      std::min(p_start + kContextLength, json_start + json_.size());
-  StringPiece segment(begin, end - begin);
-  std::string location(p_start - begin, ' ');
-  location.push_back('^');
-  auto status = util::InvalidArgumentError(
-      StrCat(message, "\n", segment, "\n", location));
-  return status;
-}
-
-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::CancelledError("");
-  }
-  if (p_.empty()) {
-    return ReportFailure(StrCat("Unexpected end of string. ", message),
-                         parse_code);
-  }
-  return ReportFailure(message, parse_code);
-}
-
-util::Status JsonStreamParser::IncrementRecursionDepth(
-    StringPiece key) const {
-  if (++recursion_depth_ > max_recursion_depth_) {
-    return util::InvalidArgumentError(StrCat(
-        "Message too deep. Max recursion depth reached for key '", key, "'"));
-  }
-  return util::Status();
-}
-
-void JsonStreamParser::SkipWhitespace() {
-  while (!p_.empty() && ascii_isspace(*p_.data())) {
-    Advance();
-  }
-  if (!p_.empty() && !ascii_isspace(*p_.data())) {
-    seen_non_whitespace_ = true;
-  }
-}
-
-void JsonStreamParser::Advance() {
-  // Advance by moving one UTF8 character while making sure we don't go beyond
-  // the length of StringPiece.
-  p_.remove_prefix(std::min<int>(
-      p_.length(), UTF8FirstLetterNumBytes(p_.data(), p_.length())));
-}
-
-util::Status JsonStreamParser::ParseKey() {
-  StringPiece original = p_;
-
-  if (allow_permissive_key_naming_) {
-    if (!ConsumeKeyPermissive(&p_, &key_)) {
-      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.",
-                           ParseErrorType::INVALID_KEY_OR_VARIABLE_NAME);
-    }
-  }
-
-  // If we consumed everything but expect more data, reset p_ and cancel since
-  // we can't know if the key was complete or not.
-  if (!finishing_ && p_.empty()) {
-    p_ = original;
-    return util::CancelledError("");
-  }
-  // Since we aren't using the key storage, clear it out.
-  key_storage_.clear();
-  return util::Status();
-}
-
-JsonStreamParser::TokenType JsonStreamParser::GetNextTokenType() {
-  SkipWhitespace();
-
-  int size = p_.size();
-  if (size == 0) {
-    // If we ran out of data, report unknown and we'll place the previous parse
-    // type onto the stack and try again when we have more data.
-    return UNKNOWN;
-  }
-  // TODO(sven): Split this method based on context since different contexts
-  // support different tokens. Would slightly speed up processing?
-  const char* data = p_.data();
-  StringPiece data_view = StringPiece(data, size);
-  if (*data == '\"' || *data == '\'') return BEGIN_STRING;
-  if (*data == '-' || ('0' <= *data && *data <= '9')) {
-    return BEGIN_NUMBER;
-  }
-  if (size >= kKeywordTrue.length() &&
-      HasPrefixString(data_view, kKeywordTrue)) {
-    return BEGIN_TRUE;
-  }
-  if (size >= kKeywordFalse.length() &&
-      HasPrefixString(data_view, kKeywordFalse)) {
-    return BEGIN_FALSE;
-  }
-  if (size >= kKeywordNull.length() &&
-      HasPrefixString(data_view, kKeywordNull)) {
-    return BEGIN_NULL;
-  }
-  if (*data == '{') return BEGIN_OBJECT;
-  if (*data == '}') return END_OBJECT;
-  if (*data == '[') return BEGIN_ARRAY;
-  if (*data == ']') return END_ARRAY;
-  if (*data == ':') return ENTRY_SEPARATOR;
-  if (*data == ',') return VALUE_SEPARATOR;
-  if (MatchKey(p_)) {
-    return BEGIN_KEY;
-  }
-
-  // We don't know that we necessarily have an invalid token here, just that we
-  // can't parse what we have so far. So we don't report an error and just
-  // return UNKNOWN so we can try again later when we have more data, or if we
-  // finish and we have leftovers.
-  return UNKNOWN;
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/json_stream_parser.h b/src/google/protobuf/util/internal/json_stream_parser.h
deleted file mode 100644
index 09f17ad..0000000
--- a/src/google/protobuf/util/internal/json_stream_parser.h
+++ /dev/null
@@ -1,350 +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_UTIL_INTERNAL_JSON_STREAM_PARSER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_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>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-
-class ObjectWriter;
-
-// A JSON parser that can parse a stream of JSON chunks rather than needing the
-// entire JSON string up front. It is a modified version of the parser in
-// //net/proto/json/json-parser.h that has been changed in the following ways:
-// - Changed from recursion to an explicit stack to allow resumption
-// - Added support for int64 and uint64 numbers
-// - Removed support for octal and decimal escapes
-// - Removed support for numeric keys
-// - Removed support for functions (javascript)
-// - Removed some lax-comma support (but kept trailing comma support)
-// - Writes directly to an ObjectWriter rather than using subclassing
-//
-// Here is an example usage:
-// JsonStreamParser parser(ow_.get());
-// util::Status result = parser.Parse(chunk1);
-// result.Update(parser.Parse(chunk2));
-// result.Update(parser.FinishParse());
-// GOOGLE_DCHECK(result.ok()) << "Failed to parse JSON";
-//
-// This parser is thread-compatible as long as only one thread is calling a
-// Parse() method at a time.
-class PROTOBUF_EXPORT JsonStreamParser {
- public:
-  // Creates a JsonStreamParser that will write to the given ObjectWriter.
-  explicit JsonStreamParser(ObjectWriter* ow);
-  virtual ~JsonStreamParser();
-
-  // 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. 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();
-
-
-  // Sets the max recursion depth of JSON message to be deserialized. JSON
-  // messages over this depth will fail to be deserialized.
-  // Default value is 100.
-  void set_max_recursion_depth(int max_depth) {
-    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.
-  int recursion_depth() { return recursion_depth_; }
-
-  enum TokenType {
-    BEGIN_STRING,     // " or '
-    BEGIN_NUMBER,     // - or digit
-    BEGIN_TRUE,       // true
-    BEGIN_FALSE,      // false
-    BEGIN_NULL,       // null
-    BEGIN_OBJECT,     // {
-    END_OBJECT,       // }
-    BEGIN_ARRAY,      // [
-    END_ARRAY,        // ]
-    ENTRY_SEPARATOR,  // :
-    VALUE_SEPARATOR,  // ,
-    BEGIN_KEY,        // letter, _, $ or digit.  Must begin with non-digit
-    UNKNOWN           // Unknown token or we ran out of the stream.
-  };
-
-  enum ParseType {
-    VALUE,        // Expects a {, [, true, false, null, string or number
-    OBJ_MID,      // Expects a ',' or }
-    ENTRY,        // Expects a key or }
-    ENTRY_MID,    // Expects a :
-    ARRAY_VALUE,  // Expects a value or ]
-    ARRAY_MID     // Expects a ',' or ]
-  };
-
-  // Holds the result of parsing a number
-  struct NumberResult {
-    enum Type { DOUBLE, INT, UINT };
-    Type type;
-    union {
-      double double_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 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
-  // the stack and return.
-  util::Status RunParser();
-
-  // Parses a value from p_ and writes it to ow_.
-  // A value may be an object, array, true, false, null, string or number.
-  util::Status ParseValue(TokenType type);
-
-  // Parses a string and writes it out to the ow_.
-  util::Status ParseString();
-
-  // Parses a string, storing the result in parsed_.
-  util::Status ParseStringHelper();
-
-  // This function parses unicode escape sequences in strings. It returns an
-  // error when there's a parsing error, either the size is not the expected
-  // size or a character is not a hex digit.  When it returns str will contain
-  // what has been successfully parsed so far.
-  util::Status ParseUnicodeEscape();
-
-  // Expects p_ to point to a JSON number, writes the number to the writer using
-  // the appropriate Render method based on the type of number.
-  util::Status ParseNumber();
-
-  // Parse a number into a NumberResult, reporting an error if no number could
-  // be parsed. This method will try to parse into a uint64, int64, or double
-  // based on whether the number was positive or negative or had a decimal
-  // component.
-  util::Status ParseNumberHelper(NumberResult* result);
-
-  // Parse a number as double into a NumberResult.
-  util::Status ParseDoubleHelper(const std::string& number,
-                                 NumberResult* result);
-
-  // Handles a { during parsing of a value.
-  util::Status HandleBeginObject();
-
-  // Parses from the ENTRY state.
-  util::Status ParseEntry(TokenType type);
-
-  // Parses from the ENTRY_MID state.
-  util::Status ParseEntryMid(TokenType type);
-
-  // Parses from the OBJ_MID state.
-  util::Status ParseObjectMid(TokenType type);
-
-  // Handles a [ during parsing of a value.
-  util::Status HandleBeginArray();
-
-  // Parses from the ARRAY_VALUE state.
-  util::Status ParseArrayValue(TokenType type);
-
-  // Parses from the ARRAY_MID state.
-  util::Status ParseArrayMid(TokenType type);
-
-  // Expects p_ to point to an unquoted literal
-  util::Status ParseTrue();
-  util::Status ParseFalse();
-  util::Status ParseNull();
-  util::Status ParseEmptyNull();
-
-  // 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,
-                             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,
-                             ParseErrorType parse_code);
-
-  // Helper function to check recursion depth and increment it. It will return
-  // OkStatus() if the current depth is allowed. Otherwise an error is returned.
-  // key is used for error reporting.
-  util::Status IncrementRecursionDepth(StringPiece key) const;
-
-  // Advance p_ past all whitespace or until the end of the string.
-  void SkipWhitespace();
-
-  // Advance p_ one UTF-8 character
-  void Advance();
-
-  // Expects p_ to point to the beginning of a key.
-  util::Status ParseKey();
-
-  // Return the type of the next token at p_.
-  TokenType GetNextTokenType();
-
-  // The object writer to write parse events to.
-  ObjectWriter* ow_;
-
-  // The stack of parsing we still need to do. When the stack runs empty we will
-  // have parsed a single value from the root (e.g. an object or list).
-  std::stack<ParseType> stack_;
-
-  // Contains any leftover text from a previous chunk that we weren't able to
-  // fully parse, for example the start of a key or number.
-  std::string leftover_;
-
-  // The current chunk of JSON being parsed. Primarily used for providing
-  // context during error reporting.
-  StringPiece json_;
-
-  // A pointer within the current JSON being parsed, used to track location.
-  StringPiece p_;
-
-  // Stores the last key read, as we separate parsing of keys and values.
-  StringPiece key_;
-
-  // Storage for key_ if we need to keep ownership, for example between chunks
-  // or if the key was unescaped from a JSON string.
-  std::string key_storage_;
-
-  // True during the FinishParse() call, so we know that any errors are fatal.
-  // For example an unterminated string will normally result in cancelling and
-  // 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_;
-
-  // Storage for the string we parsed. This may be empty if the string was able
-  // to be parsed directly from the input.
-  std::string parsed_storage_;
-
-  // The character that opened the string, either ' or ".
-  // A value of 0 indicates that string parsing is not in process.
-  char string_open_;
-
-  // Storage for the chunk that are being parsed in ParseChunk().
-  std::string chunk_storage_;
-
-  // Whether to allow non UTF-8 encoded input and replace invalid code points.
-  bool coerce_to_utf8_;
-
-  // Replacement character for invalid UTF-8 code points.
-  std::string utf8_replacement_character_;
-
-  // Whether allows empty string represented null array value or object entry
-  // value.
-  bool allow_empty_null_;
-
-  // Whether unquoted object keys can contain embedded non-alphanumeric
-  // characters when this is unambiguous for parsing.
-  bool allow_permissive_key_naming_;
-
-  // Whether allows out-of-range floating point numbers or reject them.
-  bool loose_float_number_conversion_;
-
-  // Tracks current recursion depth.
-  mutable int recursion_depth_;
-
-  // Maximum allowed recursion depth.
-  int max_recursion_depth_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(JsonStreamParser);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_JSON_STREAM_PARSER_H__
diff --git a/src/google/protobuf/util/internal/json_stream_parser_test.cc b/src/google/protobuf/util/internal/json_stream_parser_test.cc
deleted file mode 100644
index 40157a2..0000000
--- a/src/google/protobuf/util/internal/json_stream_parser_test.cc
+++ /dev/null
@@ -1,979 +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 <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>
-#include <gtest/gtest.h>
-#include <google/protobuf/stubs/time.h>
-#include <google/protobuf/util/internal/object_writer.h>
-#include <google/protobuf/stubs/status.h>
-
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-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:
-//
-// Positive tests:
-// - true, false, null
-// - empty object or array.
-// - negative and positive double and int, unsigned int
-// - single and double quoted strings
-// - string key, unquoted key, numeric key
-// - array containing array, object, value
-// - object containing array, object, value
-// - unicode handling in strings
-// - ascii escaping (\b, \f, \n, \r, \t, \v)
-// - trailing commas
-//
-// Negative tests:
-// - illegal literals
-// - mismatched quotes failure on strings
-// - unterminated string failure
-// - unexpected end of string failure
-// - mismatched object and array closing
-// - Failure to close array or object
-// - numbers too large
-// - invalid unicode escapes.
-// - invalid unicode sequences.
-// - numbers as keys
-//
-// For each test we split the input string on every possible character to ensure
-// the parser is able to handle arbitrarily split input for all cases. We also
-// do a final test of the entire test case one character at a time.
-//
-// It is verified that expected calls to the mocked objects are in sequence.
-class JsonStreamParserTest : public ::testing::Test {
- protected:
-  JsonStreamParserTest() : mock_(), ow_(&mock_) {}
-  ~JsonStreamParserTest() override {}
-
-  util::Status RunTest(StringPiece json, int split,
-                       std::function<void(JsonStreamParser*)> setup) {
-    JsonStreamParser parser(&mock_);
-    setup(&parser);
-
-    // Special case for split == length, test parsing one character at a time.
-    if (split == json.length()) {
-      GOOGLE_LOG(INFO) << "Testing split every char: " << json;
-      for (int i = 0; i < json.length(); ++i) {
-        StringPiece single = json.substr(i, 1);
-        util::Status result = parser.Parse(single);
-        if (!result.ok()) {
-          return result;
-        }
-      }
-      return parser.FinishParse();
-    }
-
-    // Normal case, split at the split point and parse two substrings.
-    StringPiece first = json.substr(0, split);
-    StringPiece rest = json.substr(split);
-    GOOGLE_LOG(INFO) << "Testing split: " << first << "><" << rest;
-    util::Status result = parser.Parse(first);
-    if (result.ok()) {
-      result = parser.Parse(rest);
-      if (result.ok()) {
-        result = parser.FinishParse();
-      }
-    }
-    if (result.ok()) {
-      EXPECT_EQ(parser.recursion_depth(), 0);
-    }
-    return result;
-  }
-
-  void DoTest(
-      StringPiece json, int split,
-      std::function<void(JsonStreamParser*)> setup = [](JsonStreamParser* p) {
-      }) {
-    util::Status result = RunTest(json, split, setup);
-    if (!result.ok()) {
-      GOOGLE_LOG(WARNING) << result;
-    }
-    EXPECT_TRUE(result.ok());
-  }
-
-  void DoErrorTest(
-      StringPiece json, int split, StringPiece error_prefix,
-      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()));
-  }
-
-  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 destructed
-  // recursively.
-  ::testing::InSequence in_sequence_;
-#endif  // !_MSC_VER
-  MockObjectWriter mock_;
-  ExpectingObjectWriter ow_;
-};
-
-
-// Positive tests
-
-// - true, false, null
-TEST_F(JsonStreamParserTest, SimpleTrue) {
-  StringPiece str = "true";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderBool("", true);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleFalse) {
-  StringPiece str = "false";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderBool("", false);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleNull) {
-  StringPiece str = "null";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderNull("");
-    DoTest(str, i);
-  }
-}
-
-// - empty object and array.
-TEST_F(JsonStreamParserTest, EmptyObject) {
-  StringPiece str = "{}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("")->EndObject();
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, EmptyList) {
-  StringPiece str = "[]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")->EndList();
-    DoTest(str, i);
-  }
-}
-
-// - negative and positive double and int, unsigned int
-TEST_F(JsonStreamParserTest, SimpleDouble) {
-  StringPiece str = "42.5";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderDouble("", 42.5);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, ScientificDouble) {
-  StringPiece str = "1.2345e-10";
-  for (int i = 0; i < str.length(); ++i) {
-    ow_.RenderDouble("", 1.2345e-10);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleNegativeDouble) {
-  StringPiece str = "-1045.235";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderDouble("", -1045.235);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleInt) {
-  StringPiece str = "123456";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderUint64("", 123456);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleNegativeInt) {
-  StringPiece str = "-79497823553162765";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderInt64("", int64_t{-79497823553162765});
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleUnsignedInt) {
-  StringPiece str = "11779497823553162765";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderUint64("", uint64_t{11779497823553162765u});
-    DoTest(str, i);
-  }
-}
-
-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.",
-                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.",
-                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.",
-                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.",
-                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.",
-                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
-  }
-}
-
-// - single and double quoted strings
-TEST_F(JsonStreamParserTest, EmptyDoubleQuotedString) {
-  StringPiece str = "\"\"";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderString("", "");
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, EmptySingleQuotedString) {
-  StringPiece str = "''";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderString("", "");
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleDoubleQuotedString) {
-  StringPiece str = "\"Some String\"";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderString("", "Some String");
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, SimpleSingleQuotedString) {
-  StringPiece str = "'Another String'";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderString("", "Another String");
-    DoTest(str, i);
-  }
-}
-
-// - string key, unquoted key, numeric key
-TEST_F(JsonStreamParserTest, ObjectKeyTypes) {
-  StringPiece str =
-      "{'s': true, \"d\": false, key: null, snake_key: [], camelKey: {}}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("")
-        ->RenderBool("s", true)
-        ->RenderBool("d", false)
-        ->RenderNull("key")
-        ->StartList("snake_key")
-        ->EndList()
-        ->StartObject("camelKey")
-        ->EndObject()
-        ->EndObject();
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, UnquotedObjectKeyWithReservedPrefxes) {
-  StringPiece str = "{ nullkey: \"a\", truekey: \"b\", falsekey: \"c\"}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("")
-        ->RenderString("nullkey", "a")
-        ->RenderString("truekey", "b")
-        ->RenderString("falsekey", "c")
-        ->EndObject();
-    DoTest(str, i);
-  }
-}
-
-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 }.",
-                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.",
-                ParseErrorType::EXPECTED_COLON);
-  }
-}
-
-
-// - array containing primitive values (true, false, null, num, string)
-TEST_F(JsonStreamParserTest, ArrayPrimitiveValues) {
-  StringPiece str = "[true, false, null, 'one', \"two\"]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")
-        ->RenderBool("", true)
-        ->RenderBool("", false)
-        ->RenderNull("")
-        ->RenderString("", "one")
-        ->RenderString("", "two")
-        ->EndList();
-    DoTest(str, i);
-  }
-}
-
-// - array containing array, object
-TEST_F(JsonStreamParserTest, ArrayComplexValues) {
-  StringPiece str =
-      "[[22, -127, 45.3, -1056.4, 11779497823553162765], {'key': true}]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")
-        ->StartList("")
-        ->RenderUint64("", 22)
-        ->RenderInt64("", -127)
-        ->RenderDouble("", 45.3)
-        ->RenderDouble("", -1056.4)
-        ->RenderUint64("", uint64_t{11779497823553162765u})
-        ->EndList()
-        ->StartObject("")
-        ->RenderBool("key", true)
-        ->EndObject()
-        ->EndList();
-    DoTest(str, i);
-  }
-}
-
-
-// - object containing array, object, value (true, false, null, num, string)
-TEST_F(JsonStreamParserTest, ObjectValues) {
-  StringPiece str =
-      "{t: true, f: false, n: null, s: 'a string', d: \"another string\", pi: "
-      "22, ni: -127, pd: 45.3, nd: -1056.4, pl: 11779497823553162765, l: [[]], "
-      "o: {'key': true}}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("")
-        ->RenderBool("t", true)
-        ->RenderBool("f", false)
-        ->RenderNull("n")
-        ->RenderString("s", "a string")
-        ->RenderString("d", "another string")
-        ->RenderUint64("pi", 22)
-        ->RenderInt64("ni", -127)
-        ->RenderDouble("pd", 45.3)
-        ->RenderDouble("nd", -1056.4)
-        ->RenderUint64("pl", uint64_t{11779497823553162765u})
-        ->StartList("l")
-        ->StartList("")
-        ->EndList()
-        ->EndList()
-        ->StartObject("o")
-        ->RenderBool("key", true)
-        ->EndObject()
-        ->EndObject();
-    DoTest(str, i);
-  }
-}
-
-
-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.",
-                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.",
-                ParseErrorType::NON_UTF_8);
-  }
-  DoErrorTest("\xFF{}", 0, "Encountered non UTF-8 code points.",
-              ParseErrorType::NON_UTF_8);
-}
-
-// - unicode handling in strings
-TEST_F(JsonStreamParserTest, UnicodeEscaping) {
-  StringPiece str = "[\"\\u0639\\u0631\\u0628\\u0649\"]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")
-        ->RenderString("", "\xD8\xB9\xD8\xB1\xD8\xA8\xD9\x89")
-        ->EndList();
-    DoTest(str, i);
-  }
-}
-
-// - unicode UTF-16 surrogate pair handling in strings
-TEST_F(JsonStreamParserTest, UnicodeSurrogatePairEscaping) {
-  StringPiece str =
-      "[\"\\u0bee\\ud800\\uddf1\\uD80C\\uDDA4\\uD83d\\udC1D\\uD83C\\uDF6F\"]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")
-        ->RenderString("",
-                       "\xE0\xAF\xAE\xF0\x90\x87\xB1\xF0\x93\x86\xA4\xF0"
-                       "\x9F\x90\x9D\xF0\x9F\x8D\xAF")
-        ->EndList();
-    DoTest(str, i);
-  }
-}
-
-
-TEST_F(JsonStreamParserTest, UnicodeEscapingInvalidCodePointWhenNotCoerced) {
-  // A low surrogate alone.
-  StringPiece str = "[\"\\ude36\"]";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid unicode code point.",
-                ParseErrorType::INVALID_UNICODE);
-  }
-}
-
-TEST_F(JsonStreamParserTest, UnicodeEscapingMissingLowSurrogateWhenNotCoerced) {
-  // A high surrogate alone.
-  StringPiece str = "[\"\\ud83d\"]";
-  for (int i = 0; i <= str.length(); ++i) {
-    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.",
-                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.",
-                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
-  }
-  // Two high surrogates.
-  str = "[\"\\ud83d\\ud83d\"]";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid low surrogate.",
-                ParseErrorType::INVALID_LOW_SURROGATE);
-  }
-}
-
-// - ascii escaping (\b, \f, \n, \r, \t, \v)
-TEST_F(JsonStreamParserTest, AsciiEscaping) {
-  StringPiece str =
-      "[\"\\b\", \"\\ning\", \"test\\f\", \"\\r\\t\", \"test\\\\\\ving\"]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")
-        ->RenderString("", "\b")
-        ->RenderString("", "\ning")
-        ->RenderString("", "test\f")
-        ->RenderString("", "\r\t")
-        ->RenderString("", "test\\\ving")
-        ->EndList();
-    DoTest(str, i);
-  }
-}
-
-// - trailing commas, we support a single trailing comma but no internal commas.
-TEST_F(JsonStreamParserTest, TrailingCommas) {
-  StringPiece str = "[['a',true,], {b: null,},]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")
-        ->StartList("")
-        ->RenderString("", "a")
-        ->RenderBool("", true)
-        ->EndList()
-        ->StartObject("")
-        ->RenderNull("b")
-        ->EndObject()
-        ->EndList();
-    DoTest(str, i);
-  }
-}
-
-// Negative tests
-
-// illegal literals
-TEST_F(JsonStreamParserTest, ExtraTextAfterTrue) {
-  StringPiece str = "truee";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderBool("", true);
-    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.",
-                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.",
-                ParseErrorType::UNABLE_TO_PARSE_NUMBER);
-  }
-}
-
-TEST_F(JsonStreamParserTest, InvalidLiteralInArray) {
-  StringPiece str = "[nule]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("");
-    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
-  }
-}
-
-TEST_F(JsonStreamParserTest, InvalidLiteralInObject) {
-  StringPiece str = "{123false}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-// mismatched quotes failure on strings
-TEST_F(JsonStreamParserTest, MismatchedSingleQuotedLiteral) {
-  StringPiece str = "'Some str\"";
-  for (int i = 0; i <= str.length(); ++i) {
-    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.",
-                ParseErrorType::EXPECTED_CLOSING_QUOTE);
-  }
-}
-
-// unterminated strings
-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.",
-                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.",
-                ParseErrorType::EXPECTED_CLOSING_QUOTE);
-  }
-}
-
-TEST_F(JsonStreamParserTest, UnterminatedStringInArray) {
-  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.",
-                ParseErrorType::EXPECTED_CLOSING_QUOTE);
-  }
-}
-
-TEST_F(JsonStreamParserTest, UnterminatedStringInObject) {
-  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.",
-                ParseErrorType::EXPECTED_CLOSING_QUOTE);
-  }
-}
-
-TEST_F(JsonStreamParserTest, UnterminatedObject) {
-  StringPiece str = "{";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected end of string.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-
-// mismatched object and array closing
-TEST_F(JsonStreamParserTest, MismatchedCloseObject) {
-  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.",
-                ParseErrorType::EXPECTED_COMMA_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, MismatchedCloseArray) {
-  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.",
-                ParseErrorType::EXPECTED_COMMA_OR_BRACKET);
-  }
-}
-
-// Invalid object keys.
-TEST_F(JsonStreamParserTest, InvalidNumericObjectKey) {
-  StringPiece str = "{42: true}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, InvalidLiteralObjectInObject) {
-  StringPiece str = "{{bob: true}}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, InvalidLiteralArrayInObject) {
-  StringPiece str = "{[null]}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, InvalidLiteralValueInObject) {
-  StringPiece str = "{false}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, MissingColonAfterStringInObject) {
-  StringPiece str = "{\"key\"}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected : between key:value pair.",
-                ParseErrorType::EXPECTED_COLON);
-  }
-}
-
-TEST_F(JsonStreamParserTest, MissingColonAfterKeyInObject) {
-  StringPiece str = "{key}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected : between key:value pair.",
-                ParseErrorType::EXPECTED_COLON);
-  }
-}
-
-TEST_F(JsonStreamParserTest, EndOfTextAfterKeyInObject) {
-  StringPiece str = "{key";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected end of string.",
-                ParseErrorType::EXPECTED_COLON);
-  }
-}
-
-TEST_F(JsonStreamParserTest, MissingValueAfterColonInObject) {
-  StringPiece str = "{key:}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
-  }
-}
-
-TEST_F(JsonStreamParserTest, MissingCommaBetweenObjectEntries) {
-  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.",
-                ParseErrorType::EXPECTED_COMMA_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, InvalidLiteralAsObjectKey) {
-  StringPiece str = "{false: 20}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected an object key or }.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, ExtraCharactersAfterObject) {
-  StringPiece str = "{}}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("")->EndObject();
-    DoErrorTest(str, i, "Parsing terminated before end of input.",
-                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
-  }
-}
-
-TEST_F(JsonStreamParserTest, PositiveNumberTooBigIsDouble) {
-  StringPiece str = "18446744073709551616";  // 2^64
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderDouble("", 18446744073709552000.0);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, NegativeNumberTooBigIsDouble) {
-  StringPiece str = "-18446744073709551616";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderDouble("", -18446744073709551616.0);
-    DoTest(str, i);
-  }
-}
-
-TEST_F(JsonStreamParserTest, DoubleTooBig) {
-  StringPiece str = "[1.89769e+308]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("");
-    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.",
-                ParseErrorType::NUMBER_EXCEEDS_RANGE_DOUBLE);
-  }
-}
-
-
-// invalid bare backslash.
-TEST_F(JsonStreamParserTest, UnfinishedEscape) {
-  StringPiece str = "\"\\";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Closing quote expected in string.",
-                ParseErrorType::EXPECTED_CLOSING_QUOTE);
-  }
-}
-
-// invalid bare backslash u.
-TEST_F(JsonStreamParserTest, UnfinishedUnicodeEscape) {
-  StringPiece str = "\"\\u";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Illegal hex string.",
-                ParseErrorType::ILLEGAL_HEX_STRING);
-  }
-}
-
-// invalid unicode sequence.
-TEST_F(JsonStreamParserTest, UnicodeEscapeCutOff) {
-  StringPiece str = "\"\\u12";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Illegal hex string.",
-                ParseErrorType::ILLEGAL_HEX_STRING);
-  }
-}
-
-// invalid unicode sequence (valid in modern EcmaScript but not in JSON).
-TEST_F(JsonStreamParserTest, BracketedUnicodeEscape) {
-  StringPiece str = "\"\\u{1f36f}\"";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.",
-                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
-  }
-}
-
-
-TEST_F(JsonStreamParserTest, UnicodeEscapeInvalidCharacters) {
-  StringPiece str = "\"\\u12$4hello";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.",
-                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
-  }
-}
-
-// invalid unicode sequence in low half surrogate: g is not a hex digit.
-TEST_F(JsonStreamParserTest, UnicodeEscapeLowHalfSurrogateInvalidCharacters) {
-  StringPiece str = "\"\\ud800\\udcfg\"";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Invalid escape sequence.",
-                ParseErrorType::INVALID_ESCAPE_SEQUENCE);
-  }
-}
-
-// Extra commas with an object or array.
-TEST_F(JsonStreamParserTest, ExtraCommaInObject) {
-  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 }.",
-                ParseErrorType::EXPECTED_OBJECT_KEY_OR_BRACES);
-  }
-}
-
-TEST_F(JsonStreamParserTest, ExtraCommaInArray) {
-  StringPiece str = "[true,,false}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("")->RenderBool("", true);
-    DoErrorTest(str, i, "Unexpected token.", ParseErrorType::UNEXPECTED_TOKEN);
-  }
-}
-
-// Extra text beyond end of value.
-TEST_F(JsonStreamParserTest, ExtraTextAfterLiteral) {
-  StringPiece str = "'hello', 'world'";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.RenderString("", "hello");
-    DoErrorTest(str, i, "Parsing terminated before end of input.",
-                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
-  }
-}
-
-TEST_F(JsonStreamParserTest, ExtraTextAfterObject) {
-  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.",
-                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
-  }
-}
-
-TEST_F(JsonStreamParserTest, ExtraTextAfterArray) {
-  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.",
-                ParseErrorType::PARSING_TERMINATED_BEFORE_END_OF_INPUT);
-  }
-}
-
-// Random unknown text in the value.
-TEST_F(JsonStreamParserTest, UnknownCharactersAsValue) {
-  StringPiece str = "*&#25";
-  for (int i = 0; i <= str.length(); ++i) {
-    DoErrorTest(str, i, "Expected a value.", ParseErrorType::EXPECTED_VALUE);
-  }
-}
-
-TEST_F(JsonStreamParserTest, UnknownCharactersInArray) {
-  StringPiece str = "[*&#25]";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartList("");
-    DoErrorTest(str, i, "Expected a value or ] within an array.",
-                ParseErrorType::EXPECTED_VALUE_OR_BRACKET);
-  }
-}
-
-TEST_F(JsonStreamParserTest, UnknownCharactersInObject) {
-  StringPiece str = "{'key': *&#25}";
-  for (int i = 0; i <= str.length(); ++i) {
-    ow_.StartObject("");
-    DoErrorTest(str, i, "Expected a value.", ParseErrorType::EXPECTED_VALUE);
-  }
-}
-
-TEST_F(JsonStreamParserTest, DeepNestJsonNotExceedLimit) {
-  int count = 99;
-  std::string str;
-  for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "{'a':");
-  }
-  StrAppend(&str, "{'nest64':'v1', 'nest64': false, 'nest64': ['v2']}");
-  for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "}");
-  }
-  ow_.StartObject("");
-  for (int i = 0; i < count; ++i) {
-    ow_.StartObject("a");
-  }
-  ow_.RenderString("nest64", "v1")
-      ->RenderBool("nest64", false)
-      ->StartList("nest64")
-      ->RenderString("", "v2")
-      ->EndList();
-  for (int i = 0; i < count; ++i) {
-    ow_.EndObject();
-  }
-  ow_.EndObject();
-  DoTest(str, 0);
-}
-
-TEST_F(JsonStreamParserTest, DeepNestJsonExceedLimit) {
-  int count = 98;
-  std::string str;
-  for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "{'a':");
-  }
-  // Supports trailing commas.
-  StrAppend(&str,
-                  "{'nest11' : [{'nest12' : null,},],"
-                  "'nest21' : {'nest22' : {'nest23' : false}}}");
-  for (int i = 0; i < count; ++i) {
-    StrAppend(&str, "}");
-  }
-  DoErrorTest(str, 0,
-              "Message too deep. Max recursion depth reached for key 'nest22'");
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/mock_error_listener.h b/src/google/protobuf/util/internal/mock_error_listener.h
deleted file mode 100644
index 3fbdd88..0000000
--- a/src/google/protobuf/util/internal/mock_error_listener.h
+++ /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.
-
-#ifndef GOOGLE_PROTOBUF_UTIL_INTERNAL_MOCK_ERROR_LISTENER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_MOCK_ERROR_LISTENER_H__
-
-#include <gmock/gmock.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/error_listener.h>
-#include <google/protobuf/util/internal/location_tracker.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-class MockErrorListener : public ErrorListener {
- public:
-  MockErrorListener() {}
-  ~MockErrorListener() override {}
-
-  MOCK_METHOD(void, InvalidName,
-              (const LocationTrackerInterface& loc,
-               StringPiece unknown_name, StringPiece message),
-              (override));
-  MOCK_METHOD(void, InvalidValue,
-              (const LocationTrackerInterface& loc, StringPiece type_name,
-               StringPiece value),
-              (override));
-  MOCK_METHOD(void, MissingField,
-              (const LocationTrackerInterface& loc,
-               StringPiece missing_name),
-              (override));
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_MOCK_ERROR_LISTENER_H__
diff --git a/src/google/protobuf/util/internal/object_location_tracker.h b/src/google/protobuf/util/internal/object_location_tracker.h
deleted file mode 100644
index 47821e6..0000000
--- a/src/google/protobuf/util/internal/object_location_tracker.h
+++ /dev/null
@@ -1,64 +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_UTIL_INTERNAL_OBJECT_LOCATION_TRACKER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_LOCATION_TRACKER_H__
-
-#include <string>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/util/internal/location_tracker.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-// An empty concrete implementation of LocationTrackerInterface.
-class ObjectLocationTracker : public LocationTrackerInterface {
- public:
-  // Creates an empty location tracker.
-  ObjectLocationTracker() {}
-
-  ~ObjectLocationTracker() override {}
-
-  // Returns empty because nothing is tracked.
-  std::string ToString() const override { return ""; }
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectLocationTracker);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_LOCATION_TRACKER_H__
diff --git a/src/google/protobuf/util/internal/object_source.h b/src/google/protobuf/util/internal/object_source.h
deleted file mode 100644
index fc7672e..0000000
--- a/src/google/protobuf/util/internal/object_source.h
+++ /dev/null
@@ -1,85 +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_UTIL_INTERNAL_OBJECT_SOURCE_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_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>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-class ObjectWriter;
-
-// An ObjectSource is anything that can write to an ObjectWriter.
-// Implementation of this interface typically provide constructors or
-// factory methods to create an instance based on some source data, for
-// example, a character stream, or protobuf.
-//
-// Derived classes could be thread-unsafe.
-class PROTOBUF_EXPORT ObjectSource {
- public:
-  virtual ~ObjectSource() {}
-
-  // Writes to the ObjectWriter
-  virtual util::Status WriteTo(ObjectWriter* ow) const {
-    return NamedWriteTo("", ow);
-  }
-
-  // Writes to the ObjectWriter with a custom name for the message.
-  // This is useful when you chain ObjectSource together by embedding one
-  // within another.
-  virtual util::Status NamedWriteTo(StringPiece name,
-                                    ObjectWriter* ow) const = 0;
-
- protected:
-  ObjectSource() {}
-
- private:
-  // Do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectSource);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_SOURCE_H__
diff --git a/src/google/protobuf/util/internal/object_writer.cc b/src/google/protobuf/util/internal/object_writer.cc
deleted file mode 100644
index 4dabd37..0000000
--- a/src/google/protobuf/util/internal/object_writer.cc
+++ /dev/null
@@ -1,93 +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 <google/protobuf/util/internal/object_writer.h>
-
-#include <google/protobuf/util/internal/datapiece.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-// static
-void ObjectWriter::RenderDataPieceTo(const DataPiece& data,
-                                     StringPiece name, ObjectWriter* ow) {
-  switch (data.type()) {
-    case DataPiece::TYPE_INT32: {
-      ow->RenderInt32(name, data.ToInt32().value());
-      break;
-    }
-    case DataPiece::TYPE_INT64: {
-      ow->RenderInt64(name, data.ToInt64().value());
-      break;
-    }
-    case DataPiece::TYPE_UINT32: {
-      ow->RenderUint32(name, data.ToUint32().value());
-      break;
-    }
-    case DataPiece::TYPE_UINT64: {
-      ow->RenderUint64(name, data.ToUint64().value());
-      break;
-    }
-    case DataPiece::TYPE_DOUBLE: {
-      ow->RenderDouble(name, data.ToDouble().value());
-      break;
-    }
-    case DataPiece::TYPE_FLOAT: {
-      ow->RenderFloat(name, data.ToFloat().value());
-      break;
-    }
-    case DataPiece::TYPE_BOOL: {
-      ow->RenderBool(name, data.ToBool().value());
-      break;
-    }
-    case DataPiece::TYPE_STRING: {
-      ow->RenderString(name, data.ToString().value());
-      break;
-    }
-    case DataPiece::TYPE_BYTES: {
-      ow->RenderBytes(name, data.ToBytes().value());
-      break;
-    }
-    case DataPiece::TYPE_NULL: {
-      ow->RenderNull(name);
-      break;
-    }
-    default:
-      break;
-  }
-}
-
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/object_writer.h b/src/google/protobuf/util/internal/object_writer.h
deleted file mode 100644
index bc4095b..0000000
--- a/src/google/protobuf/util/internal/object_writer.h
+++ /dev/null
@@ -1,151 +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_UTIL_INTERNAL_OBJECT_WRITER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_WRITER_H__
-
-#include <cstdint>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/strutil.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-
-class DataPiece;
-
-// An ObjectWriter is an interface for writing a stream of events
-// representing objects and collections. Implementation of this
-// interface can be used to write an object stream to an in-memory
-// structure, protobufs, JSON, XML, or any other output format
-// desired. The ObjectSource interface is typically used as the
-// source of an object stream.
-//
-// See JsonObjectWriter for a sample implementation of ObjectWriter
-// and its use.
-//
-// Derived classes could be thread-unsafe.
-//
-// TODO(xinb): seems like a prime candidate to apply the RAII paradigm
-// and get rid the need to call EndXXX().
-class PROTOBUF_EXPORT ObjectWriter {
- public:
-  virtual ~ObjectWriter() {}
-
-  // Starts an object. If the name is empty, the object will not be named.
-  virtual ObjectWriter* StartObject(StringPiece name) = 0;
-
-  // Ends an object.
-  virtual ObjectWriter* EndObject() = 0;
-
-  // Starts a list. If the name is empty, the list will not be named.
-  virtual ObjectWriter* StartList(StringPiece name) = 0;
-
-  // Ends a list.
-  virtual ObjectWriter* EndList() = 0;
-
-  // Renders a boolean value.
-  virtual ObjectWriter* RenderBool(StringPiece name, bool value) = 0;
-
-  // Renders an 32-bit integer value.
-  virtual ObjectWriter* RenderInt32(StringPiece name, int32_t value) = 0;
-
-  // Renders an 32-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint32(StringPiece name,
-                                     uint32_t value) = 0;
-
-  // Renders a 64-bit integer value.
-  virtual ObjectWriter* RenderInt64(StringPiece name, int64_t value) = 0;
-
-  // Renders an 64-bit unsigned integer value.
-  virtual ObjectWriter* RenderUint64(StringPiece name,
-                                     uint64_t value) = 0;
-
-
-  // Renders a double value.
-  virtual ObjectWriter* RenderDouble(StringPiece name, double value) = 0;
-  // Renders a float value.
-  virtual ObjectWriter* RenderFloat(StringPiece name, float value) = 0;
-
-  // Renders a StringPiece value. This is for rendering strings.
-  virtual ObjectWriter* RenderString(StringPiece name,
-                                     StringPiece value) = 0;
-
-  // Renders a bytes value.
-  virtual ObjectWriter* RenderBytes(StringPiece name, StringPiece value) = 0;
-
-  // Renders a Null value.
-  virtual ObjectWriter* RenderNull(StringPiece name) = 0;
-
-
-  // Renders a DataPiece object to a ObjectWriter.
-  static void RenderDataPieceTo(const DataPiece& data, StringPiece name,
-                                ObjectWriter* ow);
-
-
-  // Indicates whether this ObjectWriter has completed writing the root message,
-  // usually this means writing of one complete object. Subclasses must override
-  // this behavior appropriately.
-  virtual bool done() { return false; }
-
-  void set_use_strict_base64_decoding(bool value) {
-    use_strict_base64_decoding_ = value;
-  }
-
-  bool use_strict_base64_decoding() const {
-    return use_strict_base64_decoding_;
-  }
-
- protected:
-  ObjectWriter() : use_strict_base64_decoding_(true) {}
-
- private:
-  // If set to true, we use the stricter version of base64 decoding for byte
-  // fields by making sure decoded version encodes back to the original string.
-  bool use_strict_base64_decoding_;
-
-  // Do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ObjectWriter);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_OBJECT_WRITER_H__
diff --git a/src/google/protobuf/util/internal/proto_writer.cc b/src/google/protobuf/util/internal/proto_writer.cc
deleted file mode 100644
index afa5e2e..0000000
--- a/src/google/protobuf/util/internal/proto_writer.cc
+++ /dev/null
@@ -1,827 +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 <google/protobuf/util/internal/proto_writer.h>
-
-#include <cstdint>
-#include <functional>
-#include <stack>
-#include <unordered_set>
-
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/statusor.h>
-#include <google/protobuf/stubs/time.h>
-#include <google/protobuf/util/internal/constants.h>
-#include <google/protobuf/util/internal/field_mask_utility.h>
-#include <google/protobuf/util/internal/object_location_tracker.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/map_util.h>
-
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-using io::CodedOutputStream;
-using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
-
-ProtoWriter::ProtoWriter(TypeResolver* type_resolver,
-                         const google::protobuf::Type& type,
-                         strings::ByteSink* output, ErrorListener* listener)
-    : master_type_(type),
-      typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
-      own_typeinfo_(true),
-      done_(false),
-      ignore_unknown_fields_(false),
-      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),
-      buffer_(),
-      adapter_(&buffer_),
-      stream_(new CodedOutputStream(&adapter_)),
-      listener_(listener),
-      invalid_depth_(0),
-      tracker_(new ObjectLocationTracker()) {}
-
-ProtoWriter::ProtoWriter(const TypeInfo* typeinfo,
-                         const google::protobuf::Type& type,
-                         strings::ByteSink* output, ErrorListener* listener)
-    : master_type_(type),
-      typeinfo_(typeinfo),
-      own_typeinfo_(false),
-      done_(false),
-      ignore_unknown_fields_(false),
-      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),
-      buffer_(),
-      adapter_(&buffer_),
-      stream_(new CodedOutputStream(&adapter_)),
-      listener_(listener),
-      invalid_depth_(0),
-      tracker_(new ObjectLocationTracker()) {}
-
-ProtoWriter::~ProtoWriter() {
-  if (own_typeinfo_) {
-    delete typeinfo_;
-  }
-  if (element_ == nullptr) return;
-  // Cleanup explicitly in order to avoid destructor stack overflow when input
-  // is deeply nested.
-  // Cast to BaseElement to avoid doing additional checks (like missing fields)
-  // during pop().
-  std::unique_ptr<BaseElement> element(
-      static_cast<BaseElement*>(element_.get())->pop<BaseElement>());
-  while (element != nullptr) {
-    element.reset(element->pop<BaseElement>());
-  }
-}
-
-namespace {
-
-// Writes an INT32 field, including tag to the stream.
-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);
-  }
-  return i32.status();
-}
-
-// writes an SFIXED32 field, including tag, to the stream.
-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);
-  }
-  return i32.status();
-}
-
-// Writes an SINT32 field, including tag, to the stream.
-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);
-  }
-  return i32.status();
-}
-
-// Writes a FIXED32 field, including tag, to the stream.
-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);
-  }
-  return u32.status();
-}
-
-// Writes a UINT32 field, including tag, to the stream.
-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);
-  }
-  return u32.status();
-}
-
-// Writes an INT64 field, including tag, to the stream.
-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);
-  }
-  return i64.status();
-}
-
-// Writes an SFIXED64 field, including tag, to the stream.
-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);
-  }
-  return i64.status();
-}
-
-// Writes an SINT64 field, including tag, to the stream.
-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);
-  }
-  return i64.status();
-}
-
-// Writes a FIXED64 field, including tag, to the stream.
-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);
-  }
-  return u64.status();
-}
-
-// Writes a UINT64 field, including tag, to the stream.
-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);
-  }
-  return u64.status();
-}
-
-// Writes a DOUBLE field, including tag, to the stream.
-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);
-  }
-  return d.status();
-}
-
-// Writes a FLOAT field, including tag, to the stream.
-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);
-  }
-  return f.status();
-}
-
-// Writes a BOOL field, including tag, to the stream.
-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);
-  }
-  return b.status();
-}
-
-// Writes a BYTES field, including tag, to the stream.
-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.value(), stream);
-  }
-  return c.status();
-}
-
-// Writes a STRING field, including tag, to the stream.
-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);
-  }
-  return s.status();
-}
-
-// Given a google::protobuf::Type, returns the set of all required fields.
-std::unordered_set<const google::protobuf::Field*> GetRequiredFields(
-    const google::protobuf::Type& type) {
-  std::unordered_set<const google::protobuf::Field*> required;
-  for (int i = 0; i < type.fields_size(); i++) {
-    const google::protobuf::Field& field = type.fields(i);
-    if (field.cardinality() == google::protobuf::Field::CARDINALITY_REQUIRED) {
-      required.insert(&field);
-    }
-  }
-  return required;
-}
-
-}  // namespace
-
-ProtoWriter::ProtoElement::ProtoElement(const TypeInfo* typeinfo,
-                                        const google::protobuf::Type& type,
-                                        ProtoWriter* enclosing)
-    : BaseElement(nullptr),
-      ow_(enclosing),
-      parent_field_(nullptr),
-      typeinfo_(typeinfo),
-      proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3),
-      type_(type),
-      size_index_(-1),
-      array_index_(-1),
-      // oneof_indices_ values are 1-indexed (0 means not present).
-      oneof_indices_(type.oneofs_size() + 1) {
-  if (!proto3_) {
-    required_fields_ = GetRequiredFields(type_);
-  }
-}
-
-ProtoWriter::ProtoElement::ProtoElement(ProtoWriter::ProtoElement* parent,
-                                        const google::protobuf::Field* field,
-                                        const google::protobuf::Type& type,
-                                        bool is_list)
-    : BaseElement(parent),
-      ow_(this->parent()->ow_),
-      parent_field_(field),
-      typeinfo_(this->parent()->typeinfo_),
-      proto3_(type.syntax() == google::protobuf::SYNTAX_PROTO3),
-      type_(type),
-      size_index_(!is_list &&
-                          field->kind() == google::protobuf::Field::TYPE_MESSAGE
-                      ? ow_->size_insert_.size()
-                      : -1),
-      array_index_(is_list ? 0 : -1),
-      // oneof_indices_ values are 1-indexed (0 means not present).
-      oneof_indices_(type_.oneofs_size() + 1) {
-  if (!is_list) {
-    if (ow_->IsRepeated(*field)) {
-      // Update array_index_ if it is an explicit list.
-      if (this->parent()->array_index_ >= 0) this->parent()->array_index_++;
-    } else if (!proto3_) {
-      // For required fields tracking.
-      this->parent()->RegisterField(field);
-    }
-
-    if (field->kind() == google::protobuf::Field::TYPE_MESSAGE) {
-      if (!proto3_) {
-        required_fields_ = GetRequiredFields(type_);
-      }
-      int start_pos = ow_->stream_->ByteCount();
-      // length of serialized message is the final buffer position minus
-      // starting buffer position, plus length adjustments for size fields
-      // of any nested messages. We start with -start_pos here, so we only
-      // need to add the final buffer position to it at the end.
-      SizeInfo info = {start_pos, -start_pos};
-      ow_->size_insert_.push_back(info);
-    }
-  }
-}
-
-ProtoWriter::ProtoElement* ProtoWriter::ProtoElement::pop() {
-  if (!proto3_) {
-    // Calls the registered error listener for any required field(s) not yet
-    // seen.
-    for (std::unordered_set<const google::protobuf::Field*>::iterator it =
-             required_fields_.begin();
-         it != required_fields_.end(); ++it) {
-      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
-  // the size of all parent messages by the length of this size field.
-  // If size_index_ < 0, this is not a message, so no size field is added.
-  if (size_index_ >= 0) {
-    // Add the final buffer position to compute the total length of this
-    // serialized message. The stored value (before this addition) already
-    // contains the total length of the size fields of all nested messages
-    // minus the initial buffer position.
-    ow_->size_insert_[size_index_].size += ow_->stream_->ByteCount();
-    // Calculate the length required to serialize the size field of the
-    // message, and propagate this additional size information upward to
-    // all enclosing messages.
-    int size = ow_->size_insert_[size_index_].size;
-    int length = CodedOutputStream::VarintSize32(size);
-    for (ProtoElement* e = parent(); e != nullptr; e = e->parent()) {
-      // Only nested messages have size field, lists do not have size field.
-      if (e->size_index_ >= 0) {
-        ow_->size_insert_[e->size_index_].size += length;
-      }
-    }
-  }
-  return BaseElement::pop<ProtoElement>();
-}
-
-void ProtoWriter::ProtoElement::RegisterField(
-    const google::protobuf::Field* field) {
-  if (!required_fields_.empty() &&
-      field->cardinality() == google::protobuf::Field::CARDINALITY_REQUIRED) {
-    required_fields_.erase(field);
-  }
-}
-
-std::string ProtoWriter::ProtoElement::ToString() const {
-  std::string loc = "";
-
-  // first populate a stack with the nodes since we need to process them
-  // from root to leaf when generating the string location
-  const ProtoWriter::ProtoElement* now = this;
-  std::stack<const ProtoWriter::ProtoElement*> element_stack;
-  while (now->parent() != nullptr) {
-    element_stack.push(now);
-    now = now->parent();
-  }
-
-  // now pop each node from the stack and append to the location string
-  while (!element_stack.empty()) {
-    now = element_stack.top();
-    element_stack.pop();
-
-    if (!ow_->IsRepeated(*(now->parent_field_)) ||
-        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;
-      if (i > 0 && i == name.size()) {  // safe field name
-        if (loc.empty()) {
-          loc = name;
-        } else {
-          StrAppend(&loc, ".", name);
-        }
-      } else {
-        StrAppend(&loc, "[\"", CEscape(name), "\"]");
-      }
-    }
-
-    int array_index_now = now->array_index_;
-    if (ow_->IsRepeated(*(now->parent_field_)) && array_index_now > 0) {
-      StrAppend(&loc, "[", array_index_now - 1, "]");
-    }
-  }
-
-  return loc;
-}
-
-bool ProtoWriter::ProtoElement::IsOneofIndexTaken(int32_t index) {
-  return oneof_indices_[index];
-}
-
-void ProtoWriter::ProtoElement::TakeOneofIndex(int32_t index) {
-  oneof_indices_[index] = true;
-}
-
-void ProtoWriter::InvalidName(StringPiece unknown_name,
-                              StringPiece message) {
-  listener_->InvalidName(location(), unknown_name, message);
-}
-
-void ProtoWriter::InvalidValue(StringPiece type_name,
-                               StringPiece value) {
-  listener_->InvalidValue(location(), type_name, value);
-}
-
-void ProtoWriter::MissingField(StringPiece missing_name) {
-  listener_->MissingField(location(), missing_name);
-}
-
-ProtoWriter* ProtoWriter::StartObject(
-    StringPiece name) {
-  // Starting the root message. Create the root ProtoElement and return.
-  if (element_ == nullptr) {
-    if (!name.empty()) {
-      InvalidName(name, "Root element should not be named.");
-    }
-    element_.reset(new ProtoElement(typeinfo_, master_type_, this));
-    return this;
-  }
-
-  const google::protobuf::Field* field = BeginNamed(name, false);
-
-  if (field == nullptr) return this;
-
-  // Check to see if this field is a oneof and that no oneof in that group has
-  // already been set.
-  if (!ValidOneof(*field, name)) {
-    ++invalid_depth_;
-    return this;
-  }
-
-  const google::protobuf::Type* type = LookupType(field);
-  if (type == nullptr) {
-    ++invalid_depth_;
-    InvalidName(name, StrCat("Missing descriptor for field: ",
-                                   field->type_url()));
-    return this;
-  }
-
-  return StartObjectField(*field, *type);
-}
-
-
-ProtoWriter* ProtoWriter::EndObject() {
-  if (invalid_depth_ > 0) {
-    --invalid_depth_;
-    return this;
-  }
-
-  if (element_ != nullptr) {
-    element_.reset(element_->pop());
-  }
-
-
-  // If ending the root element,
-  // then serialize the full message with calculated sizes.
-  if (element_ == nullptr) {
-    WriteRootMessage();
-  }
-  return this;
-}
-
-ProtoWriter* ProtoWriter::StartList(
-    StringPiece name) {
-
-  const google::protobuf::Field* field = BeginNamed(name, true);
-
-  if (field == nullptr) return this;
-
-  if (!ValidOneof(*field, name)) {
-    ++invalid_depth_;
-    return this;
-  }
-
-  const google::protobuf::Type* type = LookupType(field);
-  if (type == nullptr) {
-    ++invalid_depth_;
-    InvalidName(name, StrCat("Missing descriptor for field: ",
-                                   field->type_url()));
-    return this;
-  }
-
-  return StartListField(*field, *type);
-}
-
-
-ProtoWriter* ProtoWriter::EndList() {
-  if (invalid_depth_ > 0) {
-    --invalid_depth_;
-  } else if (element_ != nullptr) {
-    element_.reset(element_->pop());
-  }
-  return this;
-}
-
-ProtoWriter* ProtoWriter::RenderDataPiece(
-    StringPiece name, const DataPiece& data) {
-  util::Status status;
-  if (invalid_depth_ > 0) return this;
-
-  const google::protobuf::Field* field = Lookup(name);
-
-  if (field == nullptr) return this;
-
-  if (!ValidOneof(*field, name)) return this;
-
-  const google::protobuf::Type* type = LookupType(field);
-  if (type == nullptr) {
-    InvalidName(name, StrCat("Missing descriptor for field: ",
-                                   field->type_url()));
-    return this;
-  }
-
-  return RenderPrimitiveField(*field, *type, data);
-}
-
-bool ProtoWriter::ValidOneof(const google::protobuf::Field& field,
-                             StringPiece unnormalized_name) {
-  if (element_ == nullptr) return true;
-
-  if (field.oneof_index() > 0) {
-    if (element_->IsOneofIndexTaken(field.oneof_index())) {
-      InvalidValue(
-          "oneof",
-          StrCat(
-              "oneof field '", element_->type().oneofs(field.oneof_index() - 1),
-              "' is already set. Cannot set '", unnormalized_name, "'"));
-      return false;
-    }
-    element_->TakeOneofIndex(field.oneof_index());
-  }
-  return true;
-}
-
-bool ProtoWriter::IsRepeated(const google::protobuf::Field& field) {
-  return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED;
-}
-
-ProtoWriter* ProtoWriter::StartObjectField(const google::protobuf::Field& field,
-                                           const google::protobuf::Type& type) {
-    WriteTag(field);
-  element_.reset(new ProtoElement(element_.release(), &field, type, false));
-  return this;
-}
-
-ProtoWriter* ProtoWriter::StartListField(const google::protobuf::Field& field,
-                                         const google::protobuf::Type& type) {
-  element_.reset(new ProtoElement(element_.release(), &field, type, true));
-  return this;
-}
-
-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;
-  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);
-  }
-  return e.status();
-}
-
-ProtoWriter* ProtoWriter::RenderPrimitiveField(
-    const google::protobuf::Field& field, const google::protobuf::Type& type,
-    const DataPiece& data) {
-  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.
-  if (!element_->proto3()) {
-    element_.reset(new ProtoElement(element_.release(), &field, type, false));
-  }
-
-  switch (field.kind()) {
-    case google::protobuf::Field::TYPE_INT32: {
-      status = WriteInt32(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_SFIXED32: {
-      status = WriteSFixed32(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_SINT32: {
-      status = WriteSInt32(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_FIXED32: {
-      status = WriteFixed32(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_UINT32: {
-      status = WriteUInt32(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_INT64: {
-      status = WriteInt64(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_SFIXED64: {
-      status = WriteSFixed64(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_SINT64: {
-      status = WriteSInt64(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_FIXED64: {
-      status = WriteFixed64(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_UINT64: {
-      status = WriteUInt64(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_DOUBLE: {
-      status = WriteDouble(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_FLOAT: {
-      status = WriteFloat(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_BOOL: {
-      status = WriteBool(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_BYTES: {
-      status = WriteBytes(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_STRING: {
-      status = WriteString(field.number(), data, stream_.get());
-      break;
-    }
-    case google::protobuf::Field::TYPE_ENUM: {
-      status = WriteEnum(
-          field.number(), data, typeinfo_->GetEnumByTypeUrl(field.type_url()),
-          stream_.get(), use_lower_camel_for_enums_,
-          case_insensitive_enum_parsing_, ignore_unknown_enum_values_);
-      break;
-    }
-    default:  // TYPE_GROUP, TYPE_MESSAGE, TYPE_UNKNOWN.
-      status = util::InvalidArgumentError(data.ValueAsStringOrDefault(""));
-  }
-
-  if (!status.ok()) {
-    // 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(),
-                 status.message());
-    element_.reset(element()->pop());
-    return this;
-  }
-
-  if (!element_->proto3()) element_.reset(element()->pop());
-
-  return this;
-}
-
-const google::protobuf::Field* ProtoWriter::BeginNamed(StringPiece name,
-                                                       bool is_list) {
-  if (invalid_depth_ > 0) {
-    ++invalid_depth_;
-    return nullptr;
-  }
-  const google::protobuf::Field* field = Lookup(name);
-  if (field == nullptr) {
-    ++invalid_depth_;
-    // InvalidName() already called in Lookup().
-    return nullptr;
-  }
-  if (is_list && !IsRepeated(*field)) {
-    ++invalid_depth_;
-    InvalidName(name, "Proto field is not repeating, cannot start list.");
-    return nullptr;
-  }
-  return field;
-}
-
-const google::protobuf::Field* ProtoWriter::Lookup(
-    StringPiece unnormalized_name) {
-  ProtoElement* e = element();
-  if (e == nullptr) {
-    InvalidName(unnormalized_name, "Root element must be a message.");
-    return nullptr;
-  }
-  if (unnormalized_name.empty()) {
-    // Objects in repeated field inherit the same field descriptor.
-    if (e->parent_field() == nullptr) {
-      InvalidName(unnormalized_name, "Proto fields must have a name.");
-    } else if (!IsRepeated(*e->parent_field())) {
-      InvalidName(unnormalized_name, "Proto fields must have a name.");
-      return nullptr;
-    }
-    return e->parent_field();
-  }
-  const google::protobuf::Field* field =
-      typeinfo_->FindField(&e->type(), unnormalized_name);
-  if (field == nullptr && !ignore_unknown_fields_) {
-    InvalidName(unnormalized_name, "Cannot find field.");
-  }
-  return field;
-}
-
-const google::protobuf::Type* ProtoWriter::LookupType(
-    const google::protobuf::Field* field) {
-  return ((field->kind() == google::protobuf::Field::TYPE_MESSAGE ||
-           field->kind() == google::protobuf::Field::TYPE_GROUP)
-              ? typeinfo_->GetTypeByTypeUrl(field->type_url())
-              : &element_->type());
-}
-
-void ProtoWriter::WriteRootMessage() {
-  GOOGLE_DCHECK(!done_);
-  int curr_pos = 0;
-  // Calls the destructor of CodedOutputStream to remove any uninitialized
-  // memory from the Cord before we read it.
-  stream_.reset(nullptr);
-  const void* data;
-  int length;
-  io::ArrayInputStream input_stream(buffer_.data(), buffer_.size());
-  while (input_stream.Next(&data, &length)) {
-    if (length == 0) continue;
-    int num_bytes = length;
-    // Write up to where we need to insert the size field.
-    // The number of bytes we may write is the smaller of:
-    //   - the current fragment size
-    //   - the distance to the next position where a size field needs to be
-    //     inserted.
-    if (!size_insert_.empty() &&
-        size_insert_.front().pos - curr_pos < num_bytes) {
-      num_bytes = size_insert_.front().pos - curr_pos;
-    }
-    output_->Append(static_cast<const char*>(data), num_bytes);
-    if (num_bytes < length) {
-      input_stream.BackUp(length - num_bytes);
-    }
-    curr_pos += num_bytes;
-    // Insert the size field.
-    //   size_insert_.front():      the next <index, size> pair to be written.
-    //   size_insert_.front().pos:  position of the size field.
-    //   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_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);
-      size_insert_.pop_front();
-    }
-  }
-  output_->Flush();
-  stream_.reset(new CodedOutputStream(&adapter_));
-  done_ = true;
-}
-
-void ProtoWriter::WriteTag(const google::protobuf::Field& field) {
-  WireFormatLite::WireType wire_type = WireFormatLite::WireTypeForFieldType(
-      static_cast<WireFormatLite::FieldType>(field.kind()));
-  stream_->WriteTag(WireFormatLite::MakeTag(field.number(), wire_type));
-}
-
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/proto_writer.h b/src/google/protobuf/util/internal/proto_writer.h
deleted file mode 100644
index a7cf6ac..0000000
--- a/src/google/protobuf/util/internal/proto_writer.h
+++ /dev/null
@@ -1,389 +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_UTIL_INTERNAL_PROTO_WRITER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTO_WRITER_H__
-
-#include <cstdint>
-#include <deque>
-#include <string>
-#include <unordered_set>
-#include <vector>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/bytestream.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/util/internal/datapiece.h>
-#include <google/protobuf/util/internal/error_listener.h>
-#include <google/protobuf/util/internal/structured_objectwriter.h>
-#include <google/protobuf/util/internal/type_info.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/stubs/status.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-
-class ObjectLocationTracker;
-
-// An ObjectWriter that can write protobuf bytes directly from writer events.
-// This class does not support special types like Struct or Map. However, since
-// this class supports raw protobuf, it can be used to provide support for
-// special types by inheriting from it or by wrapping it.
-//
-// It also supports streaming.
-class PROTOBUF_EXPORT ProtoWriter : public StructuredObjectWriter {
- public:
-// Constructor. Does not take ownership of any parameter passed in.
-  ProtoWriter(TypeResolver* type_resolver, const google::protobuf::Type& type,
-              strings::ByteSink* output, ErrorListener* listener);
-  ~ProtoWriter() override;
-
-  // ObjectWriter methods.
-  ProtoWriter* StartObject(StringPiece name) override;
-  ProtoWriter* EndObject() override;
-  ProtoWriter* StartList(StringPiece name) override;
-  ProtoWriter* EndList() override;
-  ProtoWriter* RenderBool(StringPiece name, bool value) override {
-    return RenderDataPiece(name, DataPiece(value));
-  }
-  ProtoWriter* RenderInt32(StringPiece name, int32_t value) override {
-    return RenderDataPiece(name, DataPiece(value));
-  }
-  ProtoWriter* RenderUint32(StringPiece name, uint32_t value) override {
-    return RenderDataPiece(name, DataPiece(value));
-  }
-  ProtoWriter* RenderInt64(StringPiece name, int64_t value) override {
-    return RenderDataPiece(name, DataPiece(value));
-  }
-  ProtoWriter* RenderUint64(StringPiece name, uint64_t value) override {
-    return RenderDataPiece(name, DataPiece(value));
-  }
-  ProtoWriter* RenderDouble(StringPiece name, double value) override {
-    return RenderDataPiece(name, DataPiece(value));
-  }
-  ProtoWriter* RenderFloat(StringPiece name, float value) override {
-    return RenderDataPiece(name, DataPiece(value));
-  }
-  ProtoWriter* RenderString(StringPiece name,
-                            StringPiece value) override {
-    return RenderDataPiece(name,
-                           DataPiece(value, use_strict_base64_decoding()));
-  }
-
-  ProtoWriter* RenderBytes(StringPiece name, StringPiece value) override {
-    return RenderDataPiece(
-        name, DataPiece(value, false, use_strict_base64_decoding()));
-  }
-
-  ProtoWriter* RenderNull(StringPiece name) override {
-    return RenderDataPiece(name, DataPiece::NullData());
-  }
-
-
-  // Renders a DataPiece 'value' into a field whose wire type is determined
-  // from the given field 'name'.
-  virtual ProtoWriter* RenderDataPiece(StringPiece name,
-                                       const DataPiece& data);
-
-
-  // Returns the location tracker to use for tracking locations for errors.
-  const LocationTrackerInterface& location() {
-    return element_ != nullptr ? *element_ : *tracker_;
-  }
-
-  // When true, we finished writing to output a complete message.
-  bool done() override { return done_; }
-
-  // Returns the proto stream object.
-  io::CodedOutputStream* stream() { return stream_.get(); }
-
-  // Getters and mutators of invalid_depth_.
-  void IncrementInvalidDepth() { ++invalid_depth_; }
-  void DecrementInvalidDepth() { --invalid_depth_; }
-  int invalid_depth() { return invalid_depth_; }
-
-  ErrorListener* listener() { return listener_; }
-
-  const TypeInfo* typeinfo() { return typeinfo_; }
-
-  void set_ignore_unknown_fields(bool ignore_unknown_fields) {
-    ignore_unknown_fields_ = ignore_unknown_fields;
-  }
-
-  bool ignore_unknown_fields() { return ignore_unknown_fields_; }
-
-  void set_ignore_unknown_enum_values(bool ignore_unknown_enum_values) {
-    ignore_unknown_enum_values_ = ignore_unknown_enum_values;
-  }
-
-  void set_use_lower_camel_for_enums(bool use_lower_camel_for_enums) {
-    use_lower_camel_for_enums_ = use_lower_camel_for_enums;
-  }
-
-  void set_case_insensitive_enum_parsing(bool case_insensitive_enum_parsing) {
-    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 {
-   public:
-    // Constructor for the root element. No parent nor field.
-    ProtoElement(const TypeInfo* typeinfo, const google::protobuf::Type& type,
-                 ProtoWriter* enclosing);
-
-    // Constructor for a field of an element.
-    ProtoElement(ProtoElement* parent, const google::protobuf::Field* field,
-                 const google::protobuf::Type& type, bool is_list);
-
-    ~ProtoElement() override {}
-
-    // Called just before the destructor for clean up:
-    //   - reports any missing required fields
-    //   - computes the space needed by the size field, and augment the
-    //     length of all parent messages by this additional space.
-    //   - releases and returns the parent pointer.
-    ProtoElement* pop();
-
-    // Accessors
-    // parent_field() may be nullptr if we are at root.
-    const google::protobuf::Field* parent_field() const {
-      return parent_field_;
-    }
-    const google::protobuf::Type& type() const { return type_; }
-
-    // Registers field for accounting required fields.
-    void RegisterField(const google::protobuf::Field* field);
-
-    // To report location on error messages.
-    std::string ToString() const override;
-
-    ProtoElement* parent() const override {
-      return static_cast<ProtoElement*>(BaseElement::parent());
-    }
-
-    // Returns true if the index is already taken by a preceding oneof input.
-    bool IsOneofIndexTaken(int32_t index);
-
-    // Marks the oneof 'index' as taken. Future inputs to this oneof will
-    // generate an error.
-    void TakeOneofIndex(int32_t index);
-
-    bool proto3() { return proto3_; }
-
-   private:
-    // Used for access to variables of the enclosing instance of
-    // ProtoWriter.
-    ProtoWriter* ow_;
-
-    // Describes the element as a field in the parent message.
-    // parent_field_ is nullptr if and only if this element is the root element.
-    const google::protobuf::Field* parent_field_;
-
-    // TypeInfo to lookup types.
-    const TypeInfo* typeinfo_;
-
-    // Whether the type_ is proto3 or not.
-    bool proto3_;
-
-    // Additional variables if this element is a message:
-    // (Root element is always a message).
-    // type_             : the type of this element.
-    // required_fields_  : set of required fields.
-    // size_index_       : index into ProtoWriter::size_insert_
-    //                     for later insertion of serialized message length.
-    const google::protobuf::Type& type_;
-    std::unordered_set<const google::protobuf::Field*> required_fields_;
-    const int size_index_;
-
-    // Tracks position in repeated fields, needed for LocationTrackerInterface.
-    int array_index_;
-
-    // Set of oneof indices already seen for the type_. Used to validate
-    // incoming messages so no more than one oneof is set.
-    std::vector<bool> oneof_indices_;
-
-    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoElement);
-  };
-
-  // Container for inserting 'size' information at the 'pos' position.
-  struct SizeInfo {
-    const int pos;
-    int size;
-  };
-
-  ProtoWriter(const TypeInfo* typeinfo, const google::protobuf::Type& type,
-              strings::ByteSink* output, ErrorListener* listener);
-
-  ProtoElement* element() override { return element_.get(); }
-
-  // Helper methods for calling ErrorListener. See error_listener.h.
-  void InvalidName(StringPiece unknown_name, StringPiece message);
-  void InvalidValue(StringPiece type_name, StringPiece value);
-  void MissingField(StringPiece missing_name);
-
-  // Common code for BeginObject() and BeginList() that does invalid_depth_
-  // bookkeeping associated with name lookup.
-  const google::protobuf::Field* BeginNamed(StringPiece name,
-                                            bool is_list);
-
-  // Lookup the field in the current element. Looks in the base descriptor
-  // and in any extension. This will report an error if the field cannot be
-  // found when ignore_unknown_names_ is false or if multiple matching
-  // extensions are found.
-  const google::protobuf::Field* Lookup(StringPiece name);
-
-  // Lookup the field type in the type descriptor. Returns nullptr if the type
-  // is not known.
-  const google::protobuf::Type* LookupType(
-      const google::protobuf::Field* field);
-
-  // Write serialized output to the final output ByteSink, inserting all
-  // the size information for nested messages that are missing from the
-  // intermediate Cord buffer.
-  void WriteRootMessage();
-
-  // Helper method to write proto tags based on the given field.
-  void WriteTag(const google::protobuf::Field& field);
-
-
-  // Returns true if the field for type_ can be set as a oneof. If field is not
-  // a oneof type, this function does nothing and returns true.
-  // If another field for this oneof is already set, this function returns
-  // false. It also calls the appropriate error callback.
-  // unnormalized_name is used for error string.
-  bool ValidOneof(const google::protobuf::Field& field,
-                  StringPiece unnormalized_name);
-
-  // Returns true if the field is repeated.
-  bool IsRepeated(const google::protobuf::Field& field);
-
-  // Starts an object given the field and the enclosing type.
-  ProtoWriter* StartObjectField(const google::protobuf::Field& field,
-                                const google::protobuf::Type& type);
-
-  // Starts a list given the field and the enclosing type.
-  ProtoWriter* StartListField(const google::protobuf::Field& field,
-                              const google::protobuf::Type& type);
-
-  // Renders a primitive field given the field and the enclosing type.
-  ProtoWriter* RenderPrimitiveField(const google::protobuf::Field& field,
-                                    const google::protobuf::Type& type,
-                                    const DataPiece& data);
-
- 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);
-
-  // Variables for describing the structure of the input tree:
-  // master_type_: descriptor for the whole protobuf message.
-  // typeinfo_ : the TypeInfo object to lookup types.
-  const google::protobuf::Type& master_type_;
-  const TypeInfo* typeinfo_;
-  // Whether we own the typeinfo_ object.
-  bool own_typeinfo_;
-
-  // Indicates whether we finished writing root message completely.
-  bool done_;
-
-  // If true, don't report unknown field names to the listener.
-  bool ignore_unknown_fields_;
-
-  // If true, don't report unknown enum values to the listener.
-  bool ignore_unknown_enum_values_;
-
-  // If true, check if enum name in camel case or without underscore matches the
-  // field name.
-  bool use_lower_camel_for_enums_;
-
-  // 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.
-  //               pos  - position to insert the size field.
-  //               size - size value to be inserted.
-  std::unique_ptr<ProtoElement> element_;
-  std::deque<SizeInfo> size_insert_;
-
-  // Variables for output generation:
-  // output_  : pointer to an external ByteSink for final user-visible output.
-  // buffer_  : buffer holding partial message before being ready for output_.
-  // adapter_ : internal adapter between CodedOutputStream and buffer_.
-  // stream_  : wrapper for writing tags and other encodings in wire format.
-  strings::ByteSink* output_;
-  std::string buffer_;
-  io::StringOutputStream adapter_;
-  std::unique_ptr<io::CodedOutputStream> stream_;
-
-  // Variables for error tracking and reporting:
-  // listener_     : a place to report any errors found.
-  // invalid_depth_: number of enclosing invalid nested messages.
-  // tracker_      : the root location tracker interface.
-  ErrorListener* listener_;
-  int invalid_depth_;
-  std::unique_ptr<LocationTrackerInterface> tracker_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoWriter);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTO_WRITER_H__
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.cc b/src/google/protobuf/util/internal/protostream_objectsource.cc
deleted file mode 100644
index cf6c99a..0000000
--- a/src/google/protobuf/util/internal/protostream_objectsource.cc
+++ /dev/null
@@ -1,1114 +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 <google/protobuf/util/internal/protostream_objectsource.h>
-
-#include <cstdint>
-#include <unordered_map>
-#include <utility>
-
-#include <google/protobuf/stubs/logging.h>
-#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/descriptor.h>
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/time.h>
-#include <google/protobuf/util/internal/constants.h>
-#include <google/protobuf/util/internal/field_mask_utility.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/status_macros.h>
-
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-using ::PROTOBUF_NAMESPACE_ID::internal::WireFormat;
-using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
-
-namespace {
-
-static int kDefaultMaxRecursionDepth = 64;
-
-// Finds a field with the given number. nullptr if none found.
-const google::protobuf::Field* FindFieldByNumber(
-    const google::protobuf::Type& type, int number);
-
-// Returns true if the field is packable.
-bool IsPackable(const google::protobuf::Field& field);
-
-// Finds an enum value with the given number. nullptr if none found.
-const google::protobuf::EnumValue* FindEnumValueByNumber(
-    const google::protobuf::Enum& tech_enum, int number);
-
-// Utility function to format nanos.
-const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros);
-
-util::StatusOr<std::string> MapKeyDefaultValueAsString(
-    const google::protobuf::Field& field) {
-  switch (field.kind()) {
-    case google::protobuf::Field::TYPE_BOOL:
-      return std::string("false");
-    case google::protobuf::Field::TYPE_INT32:
-    case google::protobuf::Field::TYPE_INT64:
-    case google::protobuf::Field::TYPE_UINT32:
-    case google::protobuf::Field::TYPE_UINT64:
-    case google::protobuf::Field::TYPE_SINT32:
-    case google::protobuf::Field::TYPE_SINT64:
-    case google::protobuf::Field::TYPE_SFIXED32:
-    case google::protobuf::Field::TYPE_SFIXED64:
-    case google::protobuf::Field::TYPE_FIXED32:
-    case google::protobuf::Field::TYPE_FIXED64:
-      return std::string("0");
-    case google::protobuf::Field::TYPE_STRING:
-      return std::string();
-    default:
-      return util::InternalError("Invalid map key type.");
-  }
-}
-}  // namespace
-
-
-ProtoStreamObjectSource::ProtoStreamObjectSource(
-    io::CodedInputStream* stream, TypeResolver* type_resolver,
-    const google::protobuf::Type& type, const RenderOptions& render_options)
-    : stream_(stream),
-      typeinfo_(TypeInfo::NewTypeInfo(type_resolver)),
-      own_typeinfo_(true),
-      type_(type),
-      render_options_(render_options),
-      recursion_depth_(0),
-      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 RenderOptions& render_options)
-    : stream_(stream),
-      typeinfo_(typeinfo),
-      own_typeinfo_(false),
-      type_(type),
-      render_options_(render_options),
-      recursion_depth_(0),
-      max_recursion_depth_(kDefaultMaxRecursionDepth) {
-  GOOGLE_LOG_IF(DFATAL, stream == nullptr) << "Input stream is nullptr.";
-}
-
-ProtoStreamObjectSource::~ProtoStreamObjectSource() {
-  if (own_typeinfo_) {
-    delete typeinfo_;
-  }
-}
-
-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_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.
-  // If there is any discrepancy, mark the field as not found.
-  if (field != nullptr) {
-    WireFormatLite::WireType expected_type =
-        WireFormatLite::WireTypeForFieldType(
-            static_cast<WireFormatLite::FieldType>(field->kind()));
-    WireFormatLite::WireType actual_type = WireFormatLite::GetTagWireType(tag);
-    if (actual_type != expected_type &&
-        (!IsPackable(*field) ||
-         actual_type != WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
-      field = nullptr;
-    }
-  }
-  return field;
-}
-
-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) {
-    return (*type_renderer)(this, type, name, ow);
-  }
-
-  const google::protobuf::Field* field = nullptr;
-  std::string field_name;
-  // last_tag set to dummy value that is different from tag.
-  uint32_t tag = stream_->ReadTag(), last_tag = tag + 1;
-  UnknownFieldSet unknown_fields;
-
-
-  if (include_start_and_end) {
-    ow->StartObject(name);
-  }
-  while (tag != end_tag && tag != 0) {
-    if (tag != last_tag) {  // Update field only if tag is changed.
-      last_tag = tag;
-      field = FindAndVerifyField(type, tag);
-      if (field != nullptr) {
-        if (render_options_.preserve_proto_field_names) {
-          field_name = field->name();
-        } else {
-          field_name = field->json_name();
-        }
-      }
-    }
-    if (field == nullptr) {
-      // If we didn't find a field, skip this unknown tag.
-      // TODO(wpoon): Check return boolean value.
-      WireFormat::SkipField(
-          stream_, tag,
-                                                nullptr);
-      tag = stream_->ReadTag();
-      continue;
-    }
-
-    if (field->cardinality() == google::protobuf::Field::CARDINALITY_REPEATED) {
-      if (IsMap(*field)) {
-        ow->StartObject(field_name);
-        ASSIGN_OR_RETURN(tag, RenderMap(field, field_name, tag, ow));
-        ow->EndObject();
-      } else {
-        ASSIGN_OR_RETURN(tag, RenderList(field, field_name, tag, ow));
-      }
-    } else {
-      // Render the field.
-      RETURN_IF_ERROR(RenderField(field, field_name, ow));
-      tag = stream_->ReadTag();
-    }
-  }
-
-
-  if (include_start_and_end) {
-    ow->EndObject();
-  }
-  return util::Status();
-}
-
-util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderList(
-    const google::protobuf::Field* field, StringPiece name,
-    uint32_t list_tag, ObjectWriter* ow) const {
-  uint32_t tag_to_return = 0;
-  ow->StartList(name);
-  if (IsPackable(*field) &&
-      list_tag ==
-          WireFormatLite::MakeTag(field->number(),
-                                  WireFormatLite::WIRETYPE_LENGTH_DELIMITED)) {
-    RETURN_IF_ERROR(RenderPacked(field, ow));
-    // Since packed fields have a single tag, read another tag from stream to
-    // return.
-    tag_to_return = stream_->ReadTag();
-  } else {
-    do {
-      RETURN_IF_ERROR(RenderField(field, "", ow));
-    } while ((tag_to_return = stream_->ReadTag()) == list_tag);
-  }
-  ow->EndList();
-  return tag_to_return;
-}
-
-util::StatusOr<uint32_t> ProtoStreamObjectSource::RenderMap(
-    const google::protobuf::Field* field, StringPiece /* name */,
-    uint32_t list_tag, ObjectWriter* ow) const {
-  const google::protobuf::Type* field_type =
-      typeinfo_->GetTypeByTypeUrl(field->type_url());
-  uint32_t tag_to_return = 0;
-  do {
-    // Render map entry message type.
-    uint32_t buffer32;
-    stream_->ReadVarint32(&buffer32);  // message length
-    int old_limit = stream_->PushLimit(buffer32);
-    std::string map_key;
-    for (uint32_t tag = stream_->ReadTag(); tag != 0;
-         tag = stream_->ReadTag()) {
-      const google::protobuf::Field* map_entry_field =
-          FindAndVerifyField(*field_type, tag);
-      if (map_entry_field == nullptr) {
-        WireFormat::SkipField(stream_, tag, nullptr);
-        continue;
-      }
-      // Map field numbers are key = 1 and value = 2
-      if (map_entry_field->number() == 1) {
-        map_key = ReadFieldValueAsString(*map_entry_field);
-      } else if (map_entry_field->number() == 2) {
-        if (map_key.empty()) {
-          // An absent map key is treated as the default.
-          const google::protobuf::Field* key_field =
-              FindFieldByNumber(*field_type, 1);
-          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 util::InternalError("Invalid map entry.");
-          }
-          ASSIGN_OR_RETURN(map_key, MapKeyDefaultValueAsString(*key_field));
-        }
-        RETURN_IF_ERROR(RenderField(map_entry_field, map_key, ow));
-      } else {
-        // The Type info for this map entry is incorrect. It should contain
-        // exactly two fields with field number 1 and 2.
-        return util::InternalError("Invalid map entry.");
-      }
-    }
-    stream_->PopLimit(old_limit);
-  } while ((tag_to_return = stream_->ReadTag()) == list_tag);
-  return tag_to_return;
-}
-
-util::Status ProtoStreamObjectSource::RenderPacked(
-    const google::protobuf::Field* field, ObjectWriter* ow) const {
-  uint32_t length;
-  stream_->ReadVarint32(&length);
-  int old_limit = stream_->PushLimit(length);
-  while (stream_->BytesUntilLimit() > 0) {
-    RETURN_IF_ERROR(RenderField(field, StringPiece(), ow));
-  }
-  stream_->PopLimit(old_limit);
-  return util::Status();
-}
-
-util::Status ProtoStreamObjectSource::RenderTimestamp(
-    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
-  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 util::InternalError(StrCat(
-        "Timestamp seconds exceeds limit for field: ", field_name));
-  }
-
-  if (nanos < 0 || nanos >= kNanosPerSecond) {
-    return util::InternalError(
-        StrCat("Timestamp nanos exceeds limit for field: ", field_name));
-  }
-
-  ow->RenderString(field_name,
-                   ::google::protobuf::internal::FormatTime(seconds, nanos));
-
-  return util::Status();
-}
-
-util::Status ProtoStreamObjectSource::RenderDuration(
-    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
-  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 util::InternalError(
-        StrCat("Duration seconds exceeds limit for field: ", field_name));
-  }
-
-  if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
-    return util::InternalError(
-        StrCat("Duration nanos exceeds limit for field: ", field_name));
-  }
-
-  std::string sign = "";
-  if (seconds < 0) {
-    if (nanos > 0) {
-      return util::InternalError(
-          StrCat("Duration nanos is non-negative, but seconds is "
-                       "negative for field: ",
-                       field_name));
-    }
-    sign = "-";
-    seconds = -seconds;
-    nanos = -nanos;
-  } else if (seconds == 0 && nanos < 0) {
-    sign = "-";
-    nanos = -nanos;
-  }
-  std::string formatted_duration = StringPrintf(
-      "%s%lld%ss", sign.c_str(), static_cast<long long>(seconds),  // NOLINT
-      FormatNanos(
-          nanos,
-          false
-          )
-          .c_str());
-  ow->RenderString(field_name, formatted_duration);
-  return util::Status();
-}
-
-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();
-  }
-  ow->RenderDouble(field_name, bit_cast<double>(buffer64));
-  return util::Status();
-}
-
-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();
-  }
-  ow->RenderFloat(field_name, bit_cast<float>(buffer32));
-  return util::Status();
-}
-
-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_t>(buffer64));
-  return util::Status();
-}
-
-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_t>(buffer64));
-  return util::Status();
-}
-
-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_t>(buffer32));
-  return util::Status();
-}
-
-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_t>(buffer32));
-  return util::Status();
-}
-
-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();
-  }
-  ow->RenderBool(field_name, buffer64 != 0);
-  return util::Status();
-}
-
-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.
-    os->stream_->ReadString(&str, buffer32);
-    os->stream_->ReadTag();
-  }
-  ow->RenderString(field_name, str);
-  return util::Status();
-}
-
-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);
-    os->stream_->ReadString(&str, buffer32);
-    os->stream_->ReadTag();
-  }
-  ow->RenderBytes(field_name, str);
-  return util::Status();
-}
-
-util::Status ProtoStreamObjectSource::RenderStruct(
-    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
-  const google::protobuf::Field* field = nullptr;
-  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)) {
-      ASSIGN_OR_RETURN(tag, os->RenderMap(field, field_name, tag, ow));
-    }
-  }
-  ow->EndObject();
-  return util::Status();
-}
-
-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_t tag = os->stream_->ReadTag(); tag != 0;
-       tag = os->stream_->ReadTag()) {
-    field = os->FindAndVerifyField(type, tag);
-    if (field == nullptr) {
-      WireFormat::SkipField(os->stream_, tag, nullptr);
-      continue;
-    }
-    RETURN_IF_ERROR(os->RenderField(field, field_name, ow));
-  }
-  return util::Status();
-}
-
-// TODO(skarvaje): Avoid code duplication of for loops and SkipField logic.
-util::Status ProtoStreamObjectSource::RenderStructListValue(
-    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
-  uint32_t tag = os->stream_->ReadTag();
-
-  // Render empty list when we find empty ListValue message.
-  if (tag == 0) {
-    ow->StartList(field_name);
-    ow->EndList();
-    return util::Status();
-  }
-
-  while (tag != 0) {
-    const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
-    if (field == nullptr) {
-      WireFormat::SkipField(os->stream_, tag, nullptr);
-      tag = os->stream_->ReadTag();
-      continue;
-    }
-    ASSIGN_OR_RETURN(tag, os->RenderList(field, field_name, tag, ow));
-  }
-  return util::Status();
-}
-
-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_t tag;
-  std::string type_url;
-  std::string value;
-
-  // First read out the type_url and value from the proto stream
-  for (tag = os->stream_->ReadTag(); tag != 0; tag = os->stream_->ReadTag()) {
-    const google::protobuf::Field* field = os->FindAndVerifyField(type, tag);
-    if (field == nullptr) {
-      WireFormat::SkipField(os->stream_, tag, nullptr);
-      continue;
-    }
-    // 'type_url' has field number of 1 and 'value' has field number 2
-    // //google/protobuf/any.proto
-    if (field->number() == 1) {
-      // read type_url
-      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_t value_size;
-      os->stream_->ReadVarint32(&value_size);
-      os->stream_->ReadString(&value, value_size);
-    }
-  }
-
-  // If there is no value, we don't lookup the type, we just output it (if
-  // present). If both type and value are empty we output an empty object.
-  if (value.empty()) {
-    ow->StartObject(field_name);
-    if (!type_url.empty()) {
-      ow->RenderString("@type", type_url);
-    }
-    ow->EndObject();
-    return util::Status();
-  }
-
-  // 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::InternalError("Invalid Any, the type_url is missing.");
-  }
-
-  util::StatusOr<const google::protobuf::Type*> resolved_type =
-      os->typeinfo_->ResolveTypeUrl(type_url);
-
-  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::InternalError(resolved_type.status().message());
-  }
-  // nested_type cannot be null at this time.
-  const google::protobuf::Type* nested_type = resolved_type.value();
-
-  io::ArrayInputStream zero_copy_stream(value.data(), value.size());
-  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,
-                                    os->render_options_);
-
-  // We manually call start and end object here so we can inject the @type.
-  ow->StartObject(field_name);
-  ow->RenderString("@type", type_url);
-  util::Status result =
-      nested_os.WriteMessage(nested_os.type_, "value", 0, false, ow);
-  ow->EndObject();
-  return result;
-}
-
-util::Status ProtoStreamObjectSource::RenderFieldMask(
-    const ProtoStreamObjectSource* os, const google::protobuf::Type& type,
-    StringPiece field_name, ObjectWriter* ow) {
-  std::string combined;
-  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);
-      if (field != nullptr && field->number() == 1 &&
-          field->name() == "paths") {
-        paths_field_tag = tag;
-      }
-    }
-    if (paths_field_tag != tag) {
-      return util::InternalError("Invalid FieldMask, unexpected field.");
-    }
-    std::string str;
-    os->stream_->ReadVarint32(&buffer32);  // string size.
-    os->stream_->ReadString(&str, buffer32);
-    if (!combined.empty()) {
-      combined.append(",");
-    }
-    combined.append(ConvertFieldMaskPath(str, &ToCamelCase));
-  }
-  ow->RenderString(field_name, combined);
-  return util::Status();
-}
-
-
-std::unordered_map<std::string, ProtoStreamObjectSource::TypeRenderer>*
-    ProtoStreamObjectSource::renderers_ = nullptr;
-PROTOBUF_NAMESPACE_ID::internal::once_flag source_renderers_init_;
-
-
-void ProtoStreamObjectSource::InitRendererMap() {
-  renderers_ = new std::unordered_map<std::string,
-                                      ProtoStreamObjectSource::TypeRenderer>();
-  (*renderers_)["google.protobuf.Timestamp"] =
-      &ProtoStreamObjectSource::RenderTimestamp;
-  (*renderers_)["google.protobuf.Duration"] =
-      &ProtoStreamObjectSource::RenderDuration;
-  (*renderers_)["google.protobuf.DoubleValue"] =
-      &ProtoStreamObjectSource::RenderDouble;
-  (*renderers_)["google.protobuf.FloatValue"] =
-      &ProtoStreamObjectSource::RenderFloat;
-  (*renderers_)["google.protobuf.Int64Value"] =
-      &ProtoStreamObjectSource::RenderInt64;
-  (*renderers_)["google.protobuf.UInt64Value"] =
-      &ProtoStreamObjectSource::RenderUInt64;
-  (*renderers_)["google.protobuf.Int32Value"] =
-      &ProtoStreamObjectSource::RenderInt32;
-  (*renderers_)["google.protobuf.UInt32Value"] =
-      &ProtoStreamObjectSource::RenderUInt32;
-  (*renderers_)["google.protobuf.BoolValue"] =
-      &ProtoStreamObjectSource::RenderBool;
-  (*renderers_)["google.protobuf.StringValue"] =
-      &ProtoStreamObjectSource::RenderString;
-  (*renderers_)["google.protobuf.BytesValue"] =
-      &ProtoStreamObjectSource::RenderBytes;
-  (*renderers_)["google.protobuf.Any"] = &ProtoStreamObjectSource::RenderAny;
-  (*renderers_)["google.protobuf.Struct"] =
-      &ProtoStreamObjectSource::RenderStruct;
-  (*renderers_)["google.protobuf.Value"] =
-      &ProtoStreamObjectSource::RenderStructValue;
-  (*renderers_)["google.protobuf.ListValue"] =
-      &ProtoStreamObjectSource::RenderStructListValue;
-  (*renderers_)["google.protobuf.FieldMask"] =
-      &ProtoStreamObjectSource::RenderFieldMask;
-  ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
-}
-
-void ProtoStreamObjectSource::DeleteRendererMap() {
-  delete ProtoStreamObjectSource::renderers_;
-  renderers_ = nullptr;
-}
-
-// static
-ProtoStreamObjectSource::TypeRenderer*
-ProtoStreamObjectSource::FindTypeRenderer(const std::string& type_url) {
-  PROTOBUF_NAMESPACE_ID::internal::call_once(source_renderers_init_,
-                                             InitRendererMap);
-  return FindOrNull(*renderers_, type_url);
-}
-
-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_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 util::InternalError(
-          StrCat("Invalid configuration. Could not find the type: ",
-                       field->type_url()));
-    }
-
-    // Short-circuit any special type rendering to save call-stack space.
-    const TypeRenderer* type_renderer = FindTypeRenderer(type->name());
-
-    RETURN_IF_ERROR(IncrementRecursionDepth(type->name(), field_name));
-    if (type_renderer != nullptr) {
-      RETURN_IF_ERROR((*type_renderer)(this, *type, field_name, ow));
-    } else {
-      RETURN_IF_ERROR(WriteMessage(*type, field_name, 0, true, ow));
-    }
-    --recursion_depth_;
-
-    if (!stream_->ConsumedEntireMessage()) {
-      return util::InvalidArgumentError(
-          "Nested protocol message not parsed in its entirety.");
-    }
-    stream_->PopLimit(old_limit);
-  } else {
-    // Render all other non-message types.
-    return RenderNonMessageField(field, field_name, ow);
-  }
-  return util::Status();
-}
-
-util::Status ProtoStreamObjectSource::RenderNonMessageField(
-    const google::protobuf::Field* field, StringPiece field_name,
-    ObjectWriter* ow) const {
-  // Temporary buffers of different types.
-  uint32_t buffer32 = 0;
-  uint64_t buffer64 = 0;
-  std::string strbuffer;
-  switch (field->kind()) {
-    case google::protobuf::Field::TYPE_BOOL: {
-      stream_->ReadVarint64(&buffer64);
-      ow->RenderBool(field_name, buffer64 != 0);
-      break;
-    }
-    case google::protobuf::Field::TYPE_INT32: {
-      stream_->ReadVarint32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_INT64: {
-      stream_->ReadVarint64(&buffer64);
-      ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_UINT32: {
-      stream_->ReadVarint32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_UINT64: {
-      stream_->ReadVarint64(&buffer64);
-      ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SINT32: {
-      stream_->ReadVarint32(&buffer32);
-      ow->RenderInt32(field_name, WireFormatLite::ZigZagDecode32(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SINT64: {
-      stream_->ReadVarint64(&buffer64);
-      ow->RenderInt64(field_name, WireFormatLite::ZigZagDecode64(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SFIXED32: {
-      stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderInt32(field_name, bit_cast<int32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SFIXED64: {
-      stream_->ReadLittleEndian64(&buffer64);
-      ow->RenderInt64(field_name, bit_cast<int64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_FIXED32: {
-      stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderUint32(field_name, bit_cast<uint32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_FIXED64: {
-      stream_->ReadLittleEndian64(&buffer64);
-      ow->RenderUint64(field_name, bit_cast<uint64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_FLOAT: {
-      stream_->ReadLittleEndian32(&buffer32);
-      ow->RenderFloat(field_name, bit_cast<float>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_DOUBLE: {
-      stream_->ReadLittleEndian64(&buffer64);
-      ow->RenderDouble(field_name, bit_cast<double>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_ENUM: {
-      stream_->ReadVarint32(&buffer32);
-
-      // If the field represents an explicit NULL value, render null.
-      if (field->type_url() == kStructNullValueTypeUrl) {
-        ow->RenderNull(field_name);
-        break;
-      }
-
-      // Get the nested enum type for this field.
-      // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
-      // up.
-      const google::protobuf::Enum* en =
-          typeinfo_->GetEnumByTypeUrl(field->type_url());
-      // Lookup the name of the enum, and render that. Unknown enum values
-      // are printed as integers.
-      if (en != nullptr) {
-        const google::protobuf::EnumValue* enum_value =
-            FindEnumValueByNumber(*en, buffer32);
-        if (enum_value != nullptr) {
-          if (render_options_.use_ints_for_enums) {
-            ow->RenderInt32(field_name, buffer32);
-          } 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 {
-            ow->RenderInt32(field_name, buffer32);
-        }
-      } else {
-          ow->RenderInt32(field_name, buffer32);
-      }
-      break;
-    }
-    case google::protobuf::Field::TYPE_STRING: {
-      stream_->ReadVarint32(&buffer32);  // string size.
-      stream_->ReadString(&strbuffer, buffer32);
-      ow->RenderString(field_name, strbuffer);
-      break;
-    }
-    case google::protobuf::Field::TYPE_BYTES: {
-      stream_->ReadVarint32(&buffer32);  // bytes size.
-      stream_->ReadString(&strbuffer, buffer32);
-      ow->RenderBytes(field_name, strbuffer);
-      break;
-    }
-    default:
-      break;
-  }
-  return util::Status();
-}
-
-// TODO(skarvaje): Fix this to avoid code duplication.
-const std::string ProtoStreamObjectSource::ReadFieldValueAsString(
-    const google::protobuf::Field& field) const {
-  std::string result;
-  switch (field.kind()) {
-    case google::protobuf::Field::TYPE_BOOL: {
-      uint64_t buffer64;
-      stream_->ReadVarint64(&buffer64);
-      result = buffer64 != 0 ? "true" : "false";
-      break;
-    }
-    case google::protobuf::Field::TYPE_INT32: {
-      uint32_t buffer32;
-      stream_->ReadVarint32(&buffer32);
-      result = StrCat(bit_cast<int32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_INT64: {
-      uint64_t buffer64;
-      stream_->ReadVarint64(&buffer64);
-      result = StrCat(bit_cast<int64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_UINT32: {
-      uint32_t buffer32;
-      stream_->ReadVarint32(&buffer32);
-      result = StrCat(bit_cast<uint32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_UINT64: {
-      uint64_t buffer64;
-      stream_->ReadVarint64(&buffer64);
-      result = StrCat(bit_cast<uint64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SINT32: {
-      uint32_t buffer32;
-      stream_->ReadVarint32(&buffer32);
-      result = StrCat(WireFormatLite::ZigZagDecode32(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SINT64: {
-      uint64_t buffer64;
-      stream_->ReadVarint64(&buffer64);
-      result = StrCat(WireFormatLite::ZigZagDecode64(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SFIXED32: {
-      uint32_t buffer32;
-      stream_->ReadLittleEndian32(&buffer32);
-      result = StrCat(bit_cast<int32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_SFIXED64: {
-      uint64_t buffer64;
-      stream_->ReadLittleEndian64(&buffer64);
-      result = StrCat(bit_cast<int64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_FIXED32: {
-      uint32_t buffer32;
-      stream_->ReadLittleEndian32(&buffer32);
-      result = StrCat(bit_cast<uint32_t>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_FIXED64: {
-      uint64_t buffer64;
-      stream_->ReadLittleEndian64(&buffer64);
-      result = StrCat(bit_cast<uint64_t>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_FLOAT: {
-      uint32_t buffer32;
-      stream_->ReadLittleEndian32(&buffer32);
-      result = SimpleFtoa(bit_cast<float>(buffer32));
-      break;
-    }
-    case google::protobuf::Field::TYPE_DOUBLE: {
-      uint64_t buffer64;
-      stream_->ReadLittleEndian64(&buffer64);
-      result = SimpleDtoa(bit_cast<double>(buffer64));
-      break;
-    }
-    case google::protobuf::Field::TYPE_ENUM: {
-      uint32_t buffer32;
-      stream_->ReadVarint32(&buffer32);
-      // Get the nested enum type for this field.
-      // TODO(skarvaje): Avoid string manipulation. Find ways to speed this
-      // up.
-      const google::protobuf::Enum* en =
-          typeinfo_->GetEnumByTypeUrl(field.type_url());
-      // Lookup the name of the enum, and render that. Skips unknown enums.
-      if (en != nullptr) {
-        const google::protobuf::EnumValue* enum_value =
-            FindEnumValueByNumber(*en, buffer32);
-        if (enum_value != nullptr) {
-          result = enum_value->name();
-        }
-      }
-      break;
-    }
-    case google::protobuf::Field::TYPE_STRING: {
-      uint32_t buffer32;
-      stream_->ReadVarint32(&buffer32);  // string size.
-      stream_->ReadString(&result, buffer32);
-      break;
-    }
-    case google::protobuf::Field::TYPE_BYTES: {
-      uint32_t buffer32;
-      stream_->ReadVarint32(&buffer32);  // bytes size.
-      stream_->ReadString(&result, buffer32);
-      break;
-    }
-    default:
-      break;
-  }
-  return result;
-}
-
-// Field is a map if it is a repeated message and it has an option "map_type".
-// TODO(skarvaje): Consider pre-computing the IsMap() into Field directly.
-bool ProtoStreamObjectSource::IsMap(
-    const google::protobuf::Field& field) const {
-  const google::protobuf::Type* field_type =
-      typeinfo_->GetTypeByTypeUrl(field.type_url());
-  return field.kind() == google::protobuf::Field::TYPE_MESSAGE &&
-         util::converter::IsMap(field, *field_type);
-}
-
-std::pair<int64_t, int32_t> ProtoStreamObjectSource::ReadSecondsAndNanos(
-    const google::protobuf::Type& type) const {
-  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);
-    if (field == nullptr) {
-      WireFormat::SkipField(stream_, tag, nullptr);
-      continue;
-    }
-    // 'seconds' has field number of 1 and 'nanos' has field number 2
-    // //google/protobuf/timestamp.proto & duration.proto
-    if (field->number() == 1) {
-      // read seconds
-      stream_->ReadVarint64(&seconds);
-      signed_seconds = bit_cast<int64_t>(seconds);
-    } else if (field->number() == 2) {
-      // read nanos
-      stream_->ReadVarint32(&nanos);
-      signed_nanos = bit_cast<int32_t>(nanos);
-    }
-  }
-  return std::pair<int64_t, int32_t>(signed_seconds, signed_nanos);
-}
-
-util::Status ProtoStreamObjectSource::IncrementRecursionDepth(
-    StringPiece type_name, StringPiece field_name) const {
-  if (++recursion_depth_ > max_recursion_depth_) {
-    return util::InvalidArgumentError(
-        StrCat("Message too deep. Max recursion depth reached for type '",
-                     type_name, "', field '", field_name, "'"));
-  }
-  return util::Status();
-}
-
-namespace {
-// TODO(skarvaje): Speed this up by not doing a linear scan.
-const google::protobuf::Field* FindFieldByNumber(
-    const google::protobuf::Type& type, int number) {
-  for (int i = 0; i < type.fields_size(); ++i) {
-    if (type.fields(i).number() == number) {
-      return &type.fields(i);
-    }
-  }
-  return nullptr;
-}
-
-// TODO(skarvaje): Replace FieldDescriptor by implementing IsTypePackable()
-// using tech Field.
-bool IsPackable(const google::protobuf::Field& field) {
-  return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED &&
-         FieldDescriptor::IsTypePackable(
-             static_cast<FieldDescriptor::Type>(field.kind()));
-}
-
-// TODO(skarvaje): Speed this up by not doing a linear scan.
-const google::protobuf::EnumValue* FindEnumValueByNumber(
-    const google::protobuf::Enum& tech_enum, int number) {
-  for (int i = 0; i < tech_enum.enumvalue_size(); ++i) {
-    const google::protobuf::EnumValue& ev = tech_enum.enumvalue(i);
-    if (ev.number() == number) {
-      return &ev;
-    }
-  }
-  return nullptr;
-}
-
-// TODO(skarvaje): Look into optimizing this by not doing computation on
-// double.
-const std::string FormatNanos(uint32_t nanos, bool with_trailing_zeros) {
-  if (nanos == 0) {
-    return with_trailing_zeros ? ".000" : "";
-  }
-
-  const int precision = (nanos % 1000 != 0)      ? 9
-                        : (nanos % 1000000 != 0) ? 6
-                                                 : 3;
-  std::string formatted = StringPrintf(
-      "%.*f", precision, static_cast<double>(nanos) / kNanosPerSecond);
-  // remove the leading 0 before decimal.
-  return formatted.substr(1);
-}
-}  // namespace
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/protostream_objectsource.h b/src/google/protobuf/util/internal/protostream_objectsource.h
deleted file mode 100644
index 8ed2ca9..0000000
--- a/src/google/protobuf/util/internal/protostream_objectsource.h
+++ /dev/null
@@ -1,329 +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_UTIL_INTERNAL_PROTOSTREAM_OBJECTSOURCE_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_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/stubs/statusor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/object_source.h>
-#include <google/protobuf/util/internal/object_writer.h>
-#include <google/protobuf/util/internal/type_info.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/stubs/hash.h>
-#include <google/protobuf/stubs/status.h>
-
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-class TypeInfo;
-
-// An ObjectSource that can parse a stream of bytes as a protocol buffer.
-// Its WriteTo() method can be given an ObjectWriter.
-// This implementation uses a google.protobuf.Type for tag and name lookup.
-// The field names are converted into lower camel-case when writing to the
-// ObjectWriter.
-//
-// Sample usage: (suppose input is: string proto)
-//   ArrayInputStream arr_stream(proto.data(), proto.size());
-//   CodedInputStream in_stream(&arr_stream);
-//   ProtoStreamObjectSource os(&in_stream, /*ServiceTypeInfo*/ typeinfo,
-//                              <your message google::protobuf::Type>);
-//
-//   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)
-      : 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 the max recursion depth of proto message to be deserialized. Proto
-  // messages over this depth will fail to be deserialized.
-  // Default value is 64.
-  void set_max_recursion_depth(int max_depth) {
-    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& 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_t> RenderList(
-      const google::protobuf::Field* field, StringPiece name,
-      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_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;
-
-  // Reads field value according to Field spec in 'field' and returns the read
-  // value as string. This only works for primitive datatypes (no message
-  // types).
-  const std::string ReadFieldValueAsString(
-      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 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*);
-
-  // TODO(skarvaje): Mark these methods as non-const as they modify internal
-  // state (stream_).
-  //
-  // 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_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;
-
-  // Renders a google.protobuf.Timestamp value to ObjectWriter
-  static util::Status RenderTimestamp(const ProtoStreamObjectSource* os,
-                                      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);
-
-  // 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 RenderString(const ProtoStreamObjectSource* os,
-                                   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,
-                                      const google::protobuf::Type& type,
-                                      StringPiece name, ObjectWriter* ow);
-
-  static std::unordered_map<std::string, TypeRenderer>* renderers_;
-  static void InitRendererMap();
-  static void DeleteRendererMap();
-  static TypeRenderer* FindTypeRenderer(const std::string& type_url);
-
-  // 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;
-
-
-  // Utility function to detect proto maps. The 'field' MUST be repeated.
-  bool IsMap(const google::protobuf::Field& field) const;
-
-  // 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_t, int32_t> ReadSecondsAndNanos(
-      const google::protobuf::Type& type) const;
-
-  // Helper function to check recursion depth and increment it. It will return
-  // 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;
-
-  // Input stream to read from. Ownership rests with the caller.
-  mutable io::CodedInputStream* stream_;
-
-  // Type information for all the types used in the descriptor. Used to find
-  // google::protobuf::Type of nested messages/enums.
-  const TypeInfo* typeinfo_;
-
-  // Whether this class owns the typeinfo_ object. If true the typeinfo_ object
-  // should be deleted in the destructor.
-  bool own_typeinfo_;
-
-  // google::protobuf::Type of the message source.
-  const google::protobuf::Type& type_;
-
-
-  const RenderOptions render_options_;
-
-  // Tracks current recursion depth.
-  mutable int recursion_depth_;
-
-  // Maximum allowed recursion depth.
-  int max_recursion_depth_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectSource);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTSOURCE_H__
diff --git a/src/google/protobuf/util/internal/protostream_objectsource_test.cc b/src/google/protobuf/util/internal/protostream_objectsource_test.cc
deleted file mode 100644
index e16db78..0000000
--- a/src/google/protobuf/util/internal/protostream_objectsource_test.cc
+++ /dev/null
@@ -1,1165 +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 <google/protobuf/util/internal/protostream_objectsource.h>
-
-#include <cstdint>
-#include <memory>
-#include <sstream>
-
-#include <google/protobuf/any.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/util/internal/expecting_objectwriter.h>
-#include <google/protobuf/util/internal/testdata/anys.pb.h>
-#include <google/protobuf/util/internal/testdata/books.pb.h>
-#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
-#include <google/protobuf/util/internal/testdata/maps.pb.h>
-#include <google/protobuf/util/internal/testdata/proto3.pb.h>
-#include <google/protobuf/util/internal/testdata/struct.pb.h>
-#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
-#include <gtest/gtest.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/util/internal/constants.h>
-#include <google/protobuf/util/internal/type_info_test_helper.h>
-
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-using ::google::protobuf::Any;
-using io::ArrayInputStream;
-using io::CodedInputStream;
-using proto_util_converter::testing::AnyM;
-using proto_util_converter::testing::AnyOut;
-using proto_util_converter::testing::Author;
-using proto_util_converter::testing::BadAuthor;
-using proto_util_converter::testing::BadNestedBook;
-using proto_util_converter::testing::Book;
-using proto_util_converter::testing::Book_Label;
-using proto_util_converter::testing::Cyclic;
-using proto_util_converter::testing::FieldMaskTest;
-using proto_util_converter::testing::MapOut;
-using proto_util_converter::testing::MapOutWireFormat;
-using proto_util_converter::testing::NestedBook;
-using proto_util_converter::testing::NestedFieldMask;
-using proto_util_converter::testing::PackedPrimitive;
-using proto_util_converter::testing::Primitive;
-using proto_util_converter::testing::Proto3Message;
-using proto_util_converter::testing::StructType;
-using proto_util_converter::testing::TimestampDuration;
-using ::testing::_;
-
-
-namespace {
-std::string GetTypeUrl(const Descriptor* descriptor) {
-  return std::string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
-}
-}  // namespace
-
-class ProtostreamObjectSourceTest
-    : public ::testing::TestWithParam<testing::TypeInfoSource> {
- protected:
-  ProtostreamObjectSourceTest()
-      : helper_(GetParam()),
-        mock_(),
-        ow_(&mock_),
-        use_lower_camel_for_enums_(false),
-        use_ints_for_enums_(false),
-        use_preserve_proto_field_names_(false),
-        add_trailing_zeros_(false),
-        render_unknown_enum_values_(true) {
-    helper_.ResetTypeInfo(Book::descriptor(), Proto3Message::descriptor());
-  }
-
-  ~ProtostreamObjectSourceTest() override {}
-
-  void DoTest(const Message& msg, const Descriptor* descriptor) {
-    util::Status status = ExecuteTest(msg, descriptor);
-    EXPECT_EQ(util::Status(), status);
-  }
-
-  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);
-
-    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_);
-  }
-
-  void PrepareExpectingObjectWriterForRepeatedPrimitive() {
-    ow_.StartObject("")
-        ->StartList("repFix32")
-        ->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_t>(3203))
-        ->RenderUint32("", bit_cast<uint32_t>(0))
-        ->EndList()
-        ->StartList("repI32")
-        ->RenderInt32("", 0)
-        ->RenderInt32("", 3204)
-        ->RenderInt32("", 3205)
-        ->EndList()
-        ->StartList("repSf32")
-        ->RenderInt32("", 3206)
-        ->RenderInt32("", 0)
-        ->EndList()
-        ->StartList("repS32")
-        ->RenderInt32("", 0)
-        ->RenderInt32("", 3207)
-        ->RenderInt32("", 3208)
-        ->EndList()
-        ->StartList("repFix64")
-        ->RenderUint64("", bit_cast<uint64_t>(int64_t{6401}))
-        ->RenderUint64("", bit_cast<uint64_t>(int64_t{0}))
-        ->EndList()
-        ->StartList("repU64")
-        ->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)
-        ->RenderInt64("", 0L)
-        ->EndList()
-        ->StartList("repSf64")
-        ->RenderInt64("", 0L)
-        ->RenderInt64("", 6405L)
-        ->RenderInt64("", 6406L)
-        ->EndList()
-        ->StartList("repS64")
-        ->RenderInt64("", 6407L)
-        ->RenderInt64("", 0L)
-        ->EndList()
-        ->StartList("repFloat")
-        ->RenderFloat("", 0.0f)
-        ->RenderFloat("", 32.1f)
-        ->RenderFloat("", 32.2f)
-        ->EndList()
-        ->StartList("repDouble")
-        ->RenderDouble("", 64.1L)
-        ->RenderDouble("", 0.0L)
-        ->EndList()
-        ->StartList("repBool")
-        ->RenderBool("", true)
-        ->RenderBool("", false)
-        ->EndList()
-        ->EndObject();
-  }
-
-  Primitive PrepareRepeatedPrimitive() {
-    Primitive primitive;
-    primitive.add_rep_fix32(3201);
-    primitive.add_rep_fix32(0);
-    primitive.add_rep_fix32(3202);
-    primitive.add_rep_u32(3203);
-    primitive.add_rep_u32(0);
-    primitive.add_rep_i32(0);
-    primitive.add_rep_i32(3204);
-    primitive.add_rep_i32(3205);
-    primitive.add_rep_sf32(3206);
-    primitive.add_rep_sf32(0);
-    primitive.add_rep_s32(0);
-    primitive.add_rep_s32(3207);
-    primitive.add_rep_s32(3208);
-    primitive.add_rep_fix64(6401L);
-    primitive.add_rep_fix64(0L);
-    primitive.add_rep_u64(0L);
-    primitive.add_rep_u64(6402L);
-    primitive.add_rep_u64(6403L);
-    primitive.add_rep_i64(6404L);
-    primitive.add_rep_i64(0L);
-    primitive.add_rep_sf64(0L);
-    primitive.add_rep_sf64(6405L);
-    primitive.add_rep_sf64(6406L);
-    primitive.add_rep_s64(6407L);
-    primitive.add_rep_s64(0L);
-    primitive.add_rep_float(0.0f);
-    primitive.add_rep_float(32.1f);
-    primitive.add_rep_float(32.2f);
-    primitive.add_rep_double(64.1L);
-    primitive.add_rep_double(0.0);
-    primitive.add_rep_bool(true);
-    primitive.add_rep_bool(false);
-
-    PrepareExpectingObjectWriterForRepeatedPrimitive();
-    return primitive;
-  }
-
-  PackedPrimitive PreparePackedPrimitive() {
-    PackedPrimitive primitive;
-    primitive.add_rep_fix32(3201);
-    primitive.add_rep_fix32(0);
-    primitive.add_rep_fix32(3202);
-    primitive.add_rep_u32(3203);
-    primitive.add_rep_u32(0);
-    primitive.add_rep_i32(0);
-    primitive.add_rep_i32(3204);
-    primitive.add_rep_i32(3205);
-    primitive.add_rep_sf32(3206);
-    primitive.add_rep_sf32(0);
-    primitive.add_rep_s32(0);
-    primitive.add_rep_s32(3207);
-    primitive.add_rep_s32(3208);
-    primitive.add_rep_fix64(6401L);
-    primitive.add_rep_fix64(0L);
-    primitive.add_rep_u64(0L);
-    primitive.add_rep_u64(6402L);
-    primitive.add_rep_u64(6403L);
-    primitive.add_rep_i64(6404L);
-    primitive.add_rep_i64(0L);
-    primitive.add_rep_sf64(0L);
-    primitive.add_rep_sf64(6405L);
-    primitive.add_rep_sf64(6406L);
-    primitive.add_rep_s64(6407L);
-    primitive.add_rep_s64(0L);
-    primitive.add_rep_float(0.0f);
-    primitive.add_rep_float(32.1f);
-    primitive.add_rep_float(32.2f);
-    primitive.add_rep_double(64.1L);
-    primitive.add_rep_double(0.0);
-    primitive.add_rep_bool(true);
-    primitive.add_rep_bool(false);
-
-    PrepareExpectingObjectWriterForRepeatedPrimitive();
-    return primitive;
-  }
-
-  void UseLowerCamelForEnums() { use_lower_camel_for_enums_ = true; }
-
-  void UseIntsForEnums() { use_ints_for_enums_ = true; }
-
-  void UsePreserveProtoFieldNames() { use_preserve_proto_field_names_ = true; }
-
-  void AddTrailingZeros() { add_trailing_zeros_ = true; }
-
-  void SetRenderUnknownEnumValues(bool value) {
-    render_unknown_enum_values_ = value;
-  }
-
-  testing::TypeInfoTestHelper helper_;
-
-  ::testing::NiceMock<MockObjectWriter> mock_;
-  ExpectingObjectWriter ow_;
-  bool use_lower_camel_for_enums_;
-  bool use_ints_for_enums_;
-  bool use_preserve_proto_field_names_;
-  bool add_trailing_zeros_;
-  bool render_unknown_enum_values_;
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtostreamObjectSourceTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtostreamObjectSourceTest, EmptyMessage) {
-  Book empty;
-  ow_.StartObject("")->EndObject();
-  DoTest(empty, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, Primitives) {
-  Primitive primitive;
-  primitive.set_fix32(3201);
-  primitive.set_u32(3202);
-  primitive.set_i32(3203);
-  primitive.set_sf32(3204);
-  primitive.set_s32(3205);
-  primitive.set_fix64(6401L);
-  primitive.set_u64(6402L);
-  primitive.set_i64(6403L);
-  primitive.set_sf64(6404L);
-  primitive.set_s64(6405L);
-  primitive.set_str("String Value");
-  primitive.set_bytes("Some Bytes");
-  primitive.set_float_(32.1f);
-  primitive.set_double_(64.1L);
-  primitive.set_bool_(true);
-
-  ow_.StartObject("")
-      ->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_t>(int64_t{6401}))
-      ->RenderUint64("u64", bit_cast<uint64_t>(int64_t{6402}))
-      ->RenderInt64("i64", 6403L)
-      ->RenderInt64("sf64", 6404L)
-      ->RenderInt64("s64", 6405L)
-      ->RenderString("str", "String Value")
-      ->RenderBytes("bytes", "Some Bytes")
-      ->RenderFloat("float", 32.1f)
-      ->RenderDouble("double", 64.1L)
-      ->RenderBool("bool", true)
-      ->EndObject();
-  DoTest(primitive, Primitive::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, RepeatingPrimitives) {
-  Primitive primitive = PrepareRepeatedPrimitive();
-  primitive.add_rep_str("String One");
-  primitive.add_rep_str("String Two");
-  primitive.add_rep_bytes("Some Bytes");
-
-  ow_.StartList("repStr")
-      ->RenderString("", "String One")
-      ->RenderString("", "String Two")
-      ->EndList()
-      ->StartList("repBytes")
-      ->RenderBytes("", "Some Bytes")
-      ->EndList();
-  DoTest(primitive, Primitive::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, CustomJsonName) {
-  Author author;
-  author.set_id(12345);
-
-  ow_.StartObject("")->RenderUint64("@id", 12345)->EndObject();
-  DoTest(author, Author::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, NestedMessage) {
-  Author* author = new Author();
-  author->set_name("Tolstoy");
-  Book book;
-  book.set_title("My Book");
-  book.set_allocated_author(author);
-
-  ow_.StartObject("")
-      ->RenderString("title", "My Book")
-      ->StartObject("author")
-      ->RenderString("name", "Tolstoy")
-      ->EndObject()
-      ->EndObject();
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, RepeatingField) {
-  Author author;
-  author.set_alive(false);
-  author.set_name("john");
-  author.add_pseudonym("phil");
-  author.add_pseudonym("bob");
-
-  ow_.StartObject("")
-      ->RenderBool("alive", false)
-      ->RenderString("name", "john")
-      ->StartList("pseudonym")
-      ->RenderString("", "phil")
-      ->RenderString("", "bob")
-      ->EndList()
-      ->EndObject();
-  DoTest(author, Author::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, PackedRepeatingFields) {
-  DoTest(PreparePackedPrimitive(), PackedPrimitive::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, NonPackedPackableFieldsActuallyPacked) {
-  // Protostream is packed, but parse with non-packed Primitive.
-  DoTest(PreparePackedPrimitive(), Primitive::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, PackedPackableFieldNotActuallyPacked) {
-  // Protostream is not packed, but parse with PackedPrimitive.
-  DoTest(PrepareRepeatedPrimitive(), PackedPrimitive::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, BadAuthor) {
-  Author author;
-  author.set_alive(false);
-  author.set_name("john");
-  author.set_id(1234L);
-  author.add_pseudonym("phil");
-  author.add_pseudonym("bob");
-
-  ow_.StartObject("")
-      ->StartList("alive")
-      ->RenderBool("", false)
-      ->EndList()
-      ->StartList("name")
-      ->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")
-      ->EndObject();
-  // Protostream created with Author, but parsed with BadAuthor.
-  DoTest(author, BadAuthor::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, NestedBookToBadNestedBook) {
-  Book* book = new Book();
-  book->set_length(250);
-  book->set_published(2014L);
-  NestedBook nested;
-  nested.set_allocated_book(book);
-
-  ow_.StartObject("")
-      ->StartList("book")
-      ->RenderUint32("", 24)  // tag for field length (3 << 3)
-      ->RenderUint32("", 250)
-      ->RenderUint32("", 32)  // tag for field published (4 << 3)
-      ->RenderUint32("", 2014)
-      ->EndList()
-      ->EndObject();
-  // Protostream created with NestedBook, but parsed with BadNestedBook.
-  DoTest(nested, BadNestedBook::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, BadNestedBookToNestedBook) {
-  BadNestedBook nested;
-  nested.add_book(1);
-  nested.add_book(2);
-  nested.add_book(3);
-  nested.add_book(4);
-  nested.add_book(5);
-  nested.add_book(6);
-  nested.add_book(7);
-
-  ow_.StartObject("")->StartObject("book")->EndObject()->EndObject();
-  // Protostream created with BadNestedBook, but parsed with NestedBook.
-  DoTest(nested, NestedBook::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest,
-       LongRepeatedListDoesNotBreakIntoMultipleJsonLists) {
-  Book book;
-
-  int repeat = 10000;
-  for (int i = 0; i < repeat; ++i) {
-    Book_Label* label = book.add_labels();
-    label->set_key(StrCat("i", i));
-    label->set_value(StrCat("v", i));
-  }
-
-  // Make sure StartList and EndList are called exactly once (see b/18227499 for
-  // problems when this doesn't happen)
-  EXPECT_CALL(mock_, StartList(_)).Times(1);
-  EXPECT_CALL(mock_, EndList()).Times(1);
-
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputMacroCase) {
-  Book book;
-  book.set_type(Book::ACTION_AND_ADVENTURE);
-
-  UseLowerCamelForEnums();
-
-  ow_.StartObject("")->RenderString("type", "actionAndAdventure")->EndObject();
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputSnakeCase) {
-  Book book;
-  book.set_type(Book::arts_and_photography);
-
-  UseLowerCamelForEnums();
-
-  ow_.StartObject("")->RenderString("type", "artsAndPhotography")->EndObject();
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, LowerCamelEnumOutputWithNumber) {
-  Book book;
-  book.set_type(Book::I18N_Tech);
-
-  UseLowerCamelForEnums();
-
-  ow_.StartObject("")->RenderString("type", "i18nTech")->EndObject();
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, EnumCaseIsUnchangedByDefault) {
-  Book book;
-  book.set_type(Book::ACTION_AND_ADVENTURE);
-  ow_.StartObject("")
-      ->RenderString("type", "ACTION_AND_ADVENTURE")
-      ->EndObject();
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, UseIntsForEnumsTest) {
-  Book book;
-  book.set_type(Book::ACTION_AND_ADVENTURE);
-
-  UseIntsForEnums();
-
-  ow_.StartObject("")->RenderInt32("type", 3)->EndObject();
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, UsePreserveProtoFieldNames) {
-  Book book;
-  book.set_snake_field("foo");
-
-  UsePreserveProtoFieldNames();
-
-  ow_.StartObject("")->RenderString("snake_field", "foo")->EndObject();
-  DoTest(book, Book::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest,
-       UnknownEnumAreDroppedWhenRenderUnknownEnumValuesIsUnset) {
-  Proto3Message message;
-  message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
-
-  SetRenderUnknownEnumValues(false);
-
-  // Unknown enum values are not output.
-  ow_.StartObject("")->EndObject();
-  DoTest(message, Proto3Message::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest,
-       UnknownEnumAreOutputWhenRenderUnknownEnumValuesIsSet) {
-  Proto3Message message;
-  message.set_enum_value(static_cast<Proto3Message::NestedEnum>(1234));
-
-  SetRenderUnknownEnumValues(true);
-
-  // Unknown enum values are output.
-  ow_.StartObject("")->RenderInt32("enumValue", 1234)->EndObject();
-  DoTest(message, Proto3Message::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceTest, CyclicMessageDepthTest) {
-  Cyclic cyclic;
-  cyclic.set_m_int(123);
-
-  Book* book = cyclic.mutable_m_book();
-  book->set_title("book title");
-  Cyclic* current = cyclic.mutable_m_cyclic();
-  Author* current_author = cyclic.add_m_author();
-  for (int i = 0; i < 63; ++i) {
-    Author* next = current_author->add_friend_();
-    next->set_id(i);
-    next->set_name(StrCat("author_name_", i));
-    next->set_alive(true);
-    current_author = next;
-  }
-
-  // Recursive message with depth (65) > max (max is 64).
-  for (int i = 0; i < 64; ++i) {
-    Cyclic* next = current->mutable_m_cyclic();
-    next->set_m_str(StrCat("count_", i));
-    current = next;
-  }
-
-  util::Status status = ExecuteTest(cyclic, Cyclic::descriptor());
-  EXPECT_TRUE(util::IsInvalidArgument(status));
-}
-
-class ProtostreamObjectSourceMapsTest : public ProtostreamObjectSourceTest {
- protected:
-  ProtostreamObjectSourceMapsTest() {
-    helper_.ResetTypeInfo(MapOut::descriptor());
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtostreamObjectSourceMapsTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-// Tests JSON map.
-//
-// This is the example expected output.
-// {
-//   "map1": {
-//     "key1": {
-//       "foo": "foovalue"
-//     },
-//     "key2": {
-//       "foo": "barvalue"
-//     }
-//   },
-//   "map2": {
-//     "nestedself": {
-//       "map1": {
-//         "nested_key1": {
-//           "foo": "nested_foo"
-//         }
-//       },
-//       "bar": "nested_bar_string"
-//     }
-//   },
-//   "map3": {
-//     "111": "one one one"
-//   },
-//   "bar": "top bar"
-// }
-TEST_P(ProtostreamObjectSourceMapsTest, MapsTest) {
-  MapOut out;
-  (*out.mutable_map1())["key1"].set_foo("foovalue");
-  (*out.mutable_map1())["key2"].set_foo("barvalue");
-
-  MapOut* nested_value = &(*out.mutable_map2())["nestedself"];
-  (*nested_value->mutable_map1())["nested_key1"].set_foo("nested_foo");
-  nested_value->set_bar("nested_bar_string");
-
-  (*out.mutable_map3())[111] = "one one one";
-
-  out.set_bar("top bar");
-
-  ow_.StartObject("")
-      ->StartObject("map1")
-      ->StartObject("key1")
-      ->RenderString("foo", "foovalue")
-      ->EndObject()
-      ->StartObject("key2")
-      ->RenderString("foo", "barvalue")
-      ->EndObject()
-      ->StartObject("map2")
-      ->StartObject("nestedself")
-      ->StartObject("map1")
-      ->StartObject("nested_key1")
-      ->RenderString("foo", "nested_foo")
-      ->EndObject()
-      ->EndObject()
-      ->RenderString("bar", "nested_bar_string")
-      ->EndObject()
-      ->EndObject()
-      ->StartObject("map3")
-      ->RenderString("111", "one one one")
-      ->EndObject()
-      ->EndObject()
-      ->RenderString("bar", "top bar")
-      ->EndObject();
-
-  DoTest(out, MapOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceMapsTest, MissingKeysTest) {
-  // MapOutWireFormat has the same wire representation with MapOut but uses
-  // repeated message fields to represent map fields so we can intentionally
-  // leave out the key field or the value field of a map entry.
-  MapOutWireFormat out;
-  // Create some map entries without keys. They will be rendered with the
-  // default values ("" for strings, "0" for integers, etc.).
-  // {
-  //   "map1": {
-  //     "": {
-  //       "foo": "foovalue"
-  //     }
-  //   },
-  //   "map2": {
-  //     "": {
-  //       "map1": {
-  //         "nested_key1": {
-  //           "foo": "nested_foo"
-  //         }
-  //       }
-  //     }
-  //   },
-  //   "map3": {
-  //     "0": "one one one"
-  //   },
-  //   "map4": {
-  //     "false": "bool"
-  //   }
-  // }
-  out.add_map1()->mutable_value()->set_foo("foovalue");
-  MapOut* nested = out.add_map2()->mutable_value();
-  (*nested->mutable_map1())["nested_key1"].set_foo("nested_foo");
-  out.add_map3()->set_value("one one one");
-  out.add_map4()->set_value("bool");
-
-  ow_.StartObject("")
-      ->StartObject("map1")
-      ->StartObject("")
-      ->RenderString("foo", "foovalue")
-      ->EndObject()
-      ->EndObject()
-      ->StartObject("map2")
-      ->StartObject("")
-      ->StartObject("map1")
-      ->StartObject("nested_key1")
-      ->RenderString("foo", "nested_foo")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject()
-      ->EndObject()
-      ->StartObject("map3")
-      ->RenderString("0", "one one one")
-      ->EndObject()
-      ->StartObject("map4")
-      ->RenderString("false", "bool")
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, MapOut::descriptor());
-}
-
-class ProtostreamObjectSourceAnysTest : public ProtostreamObjectSourceTest {
- protected:
-  ProtostreamObjectSourceAnysTest() {
-    helper_.ResetTypeInfo({AnyOut::descriptor(), Book::descriptor(),
-                           google::protobuf::Any::descriptor()});
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtostreamObjectSourceAnysTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-// Tests JSON any support.
-//
-// This is the example expected output.
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.testing.AnyM"
-//     "foo": "foovalue"
-//   }
-// }
-TEST_P(ProtostreamObjectSourceAnysTest, BasicAny) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  AnyM m;
-  m.set_foo("foovalue");
-  any->PackFrom(m);
-
-  ow_.StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.AnyM")
-      ->RenderString("foo", "foovalue")
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, LowerCamelEnumOutputSnakeCase) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  Book book;
-  book.set_type(Book::arts_and_photography);
-  any->PackFrom(book);
-
-  UseLowerCamelForEnums();
-
-  ow_.StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.Book")
-      ->RenderString("type", "artsAndPhotography")
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, UseIntsForEnumsTest) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  Book book;
-  book.set_type(Book::ACTION_AND_ADVENTURE);
-  any->PackFrom(book);
-
-  UseIntsForEnums();
-
-  ow_.StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.Book")
-      ->RenderInt32("type", 3)
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, UsePreserveProtoFieldNames) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  Book book;
-  book.set_snake_field("foo");
-  any->PackFrom(book);
-
-  UsePreserveProtoFieldNames();
-
-  ow_.StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.Book")
-      ->RenderString("snake_field", "foo")
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, RecursiveAny) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-  any->set_type_url("type.googleapis.com/google.protobuf.Any");
-
-  ::google::protobuf::Any nested_any;
-  nested_any.set_type_url(
-      "type.googleapis.com/proto_util_converter.testing.AnyM");
-
-  AnyM m;
-  m.set_foo("foovalue");
-  nested_any.set_value(m.SerializeAsString());
-
-  any->set_value(nested_any.SerializeAsString());
-
-  ow_.StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->StartObject("value")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.AnyM")
-      ->RenderString("foo", "foovalue")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, DoubleRecursiveAny) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-  any->set_type_url("type.googleapis.com/google.protobuf.Any");
-
-  ::google::protobuf::Any nested_any;
-  nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
-
-  ::google::protobuf::Any second_nested_any;
-  second_nested_any.set_type_url(
-      "type.googleapis.com/proto_util_converter.testing.AnyM");
-
-  AnyM m;
-  m.set_foo("foovalue");
-  second_nested_any.set_value(m.SerializeAsString());
-  nested_any.set_value(second_nested_any.SerializeAsString());
-  any->set_value(nested_any.SerializeAsString());
-
-  ow_.StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->StartObject("value")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->StartObject("value")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.AnyM")
-      ->RenderString("foo", "foovalue")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, EmptyAnyOutputsEmptyObject) {
-  AnyOut out;
-  out.mutable_any();
-
-  ow_.StartObject("")->StartObject("any")->EndObject()->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, EmptyWithTypeAndNoValueOutputsType) {
-  AnyOut out;
-  out.mutable_any()->set_type_url("foo.googleapis.com/my.Type");
-
-  ow_.StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "foo.googleapis.com/my.Type")
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, AnyOut::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, MissingTypeUrlError) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  AnyM m;
-  m.set_foo("foovalue");
-  any->set_value(m.SerializeAsString());
-
-  // We start the "AnyOut" part and then fail when we hit the Any object.
-  ow_.StartObject("");
-
-  util::Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeServiceError) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-  any->set_type_url("foo.googleapis.com/my.own.Type");
-
-  AnyM m;
-  m.set_foo("foovalue");
-  any->set_value(m.SerializeAsString());
-
-  // We start the "AnyOut" part and then fail when we hit the Any object.
-  ow_.StartObject("");
-
-  util::Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
-}
-
-TEST_P(ProtostreamObjectSourceAnysTest, UnknownTypeError) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-  any->set_type_url("type.googleapis.com/unknown.Type");
-
-  AnyM m;
-  m.set_foo("foovalue");
-  any->set_value(m.SerializeAsString());
-
-  // We start the "AnyOut" part and then fail when we hit the Any object.
-  ow_.StartObject("");
-
-  util::Status status = ExecuteTest(out, AnyOut::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
-}
-
-class ProtostreamObjectSourceStructTest : public ProtostreamObjectSourceTest {
- protected:
-  ProtostreamObjectSourceStructTest() {
-    helper_.ResetTypeInfo(StructType::descriptor(),
-                          google::protobuf::Struct::descriptor());
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtostreamObjectSourceStructTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-// Tests struct
-//
-//  "object": {
-//    "k1": 123,
-//    "k2": true
-//  }
-TEST_P(ProtostreamObjectSourceStructTest, StructRenderSuccess) {
-  StructType out;
-  google::protobuf::Struct* s = out.mutable_object();
-  s->mutable_fields()->operator[]("k1").set_number_value(123);
-  s->mutable_fields()->operator[]("k2").set_bool_value(true);
-
-  ow_.StartObject("")
-      ->StartObject("object")
-      ->RenderDouble("k1", 123)
-      ->RenderBool("k2", true)
-      ->EndObject()
-      ->EndObject();
-
-  DoTest(out, StructType::descriptor());
-}
-
-TEST_P(ProtostreamObjectSourceStructTest, MissingValueSkipsField) {
-  StructType out;
-  google::protobuf::Struct* s = out.mutable_object();
-  s->mutable_fields()->operator[]("k1");
-
-  ow_.StartObject("")->StartObject("object")->EndObject()->EndObject();
-
-  DoTest(out, StructType::descriptor());
-}
-
-class ProtostreamObjectSourceFieldMaskTest
-    : public ProtostreamObjectSourceTest {
- protected:
-  ProtostreamObjectSourceFieldMaskTest() {
-    helper_.ResetTypeInfo(FieldMaskTest::descriptor(),
-                          google::protobuf::FieldMask::descriptor());
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtostreamObjectSourceFieldMaskTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtostreamObjectSourceFieldMaskTest, FieldMaskRenderSuccess) {
-  FieldMaskTest out;
-  out.set_id("1");
-  out.mutable_single_mask()->add_paths("path1");
-  out.mutable_single_mask()->add_paths("snake_case_path2");
-  ::google::protobuf::FieldMask* mask = out.add_repeated_mask();
-  mask->add_paths("path3");
-  mask = out.add_repeated_mask();
-  mask->add_paths("snake_case_path4");
-  mask->add_paths("path5");
-  NestedFieldMask* nested = out.add_nested_mask();
-  nested->set_data("data");
-  nested->mutable_single_mask()->add_paths("nested.path1");
-  nested->mutable_single_mask()->add_paths("nested_field.snake_case_path2");
-  mask = nested->add_repeated_mask();
-  mask->add_paths("nested_field.path3");
-  mask->add_paths("nested.snake_case_path4");
-  mask = nested->add_repeated_mask();
-  mask->add_paths("nested.path5");
-  mask = nested->add_repeated_mask();
-  mask->add_paths(
-      "snake_case.map_field[\"map_key_should_be_ignored\"].nested_snake_case."
-      "map_field[\"map_key_sho\\\"uld_be_ignored\"]");
-
-  ow_.StartObject("")
-      ->RenderString("id", "1")
-      ->RenderString("singleMask", "path1,snakeCasePath2")
-      ->StartList("repeatedMask")
-      ->RenderString("", "path3")
-      ->RenderString("", "snakeCasePath4,path5")
-      ->EndList()
-      ->StartList("nestedMask")
-      ->StartObject("")
-      ->RenderString("data", "data")
-      ->RenderString("singleMask", "nested.path1,nestedField.snakeCasePath2")
-      ->StartList("repeatedMask")
-      ->RenderString("", "nestedField.path3,nested.snakeCasePath4")
-      ->RenderString("", "nested.path5")
-      ->RenderString("",
-                     "snakeCase.mapField[\"map_key_should_be_ignored\"]."
-                     "nestedSnakeCase.mapField[\"map_key_sho\\\"uld_be_"
-                     "ignored\"]")
-      ->EndList()
-      ->EndObject()
-      ->EndList()
-      ->EndObject();
-
-  DoTest(out, FieldMaskTest::descriptor());
-}
-
-class ProtostreamObjectSourceTimestampTest
-    : public ProtostreamObjectSourceTest {
- protected:
-  ProtostreamObjectSourceTimestampTest() {
-    helper_.ResetTypeInfo(TimestampDuration::descriptor());
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtostreamObjectSourceTimestampTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampBelowMinTest) {
-  TimestampDuration out;
-  google::protobuf::Timestamp* ts = out.mutable_ts();
-  // Min allowed seconds - 1
-  ts->set_seconds(kTimestampMinSeconds - 1);
-  ow_.StartObject("");
-
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
-}
-
-TEST_P(ProtostreamObjectSourceTimestampTest, InvalidTimestampAboveMaxTest) {
-  TimestampDuration out;
-  google::protobuf::Timestamp* ts = out.mutable_ts();
-  // Max allowed seconds + 1
-  ts->set_seconds(kTimestampMaxSeconds + 1);
-  ow_.StartObject("");
-
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
-}
-
-TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationBelowMinTest) {
-  TimestampDuration out;
-  google::protobuf::Duration* dur = out.mutable_dur();
-  // Min allowed seconds - 1
-  dur->set_seconds(kDurationMinSeconds - 1);
-  ow_.StartObject("");
-
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
-}
-
-TEST_P(ProtostreamObjectSourceTimestampTest, InvalidDurationAboveMaxTest) {
-  TimestampDuration out;
-  google::protobuf::Duration* dur = out.mutable_dur();
-  // Min allowed seconds + 1
-  dur->set_seconds(kDurationMaxSeconds + 1);
-  ow_.StartObject("");
-
-  util::Status status = ExecuteTest(out, TimestampDuration::descriptor());
-  EXPECT_TRUE(util::IsInternal(status));
-}
-
-TEST_P(ProtostreamObjectSourceTimestampTest, TimestampDurationDefaultValue) {
-  TimestampDuration out;
-  out.mutable_ts()->set_seconds(0);
-  out.mutable_dur()->set_seconds(0);
-
-  ow_.StartObject("")
-      ->RenderString("ts", "1970-01-01T00:00:00Z")
-      ->RenderString("dur", "0s")
-      ->EndObject();
-
-  DoTest(out, TimestampDuration::descriptor());
-}
-
-
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.cc b/src/google/protobuf/util/internal/protostream_objectwriter.cc
deleted file mode 100644
index ecb219e..0000000
--- a/src/google/protobuf/util/internal/protostream_objectwriter.cc
+++ /dev/null
@@ -1,1401 +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 <google/protobuf/util/internal/protostream_objectwriter.h>
-
-#include <cstdint>
-#include <functional>
-#include <stack>
-#include <unordered_map>
-#include <unordered_set>
-
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/wire_format_lite.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/util/internal/constants.h>
-#include <google/protobuf/util/internal/field_mask_utility.h>
-#include <google/protobuf/util/internal/object_location_tracker.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/map_util.h>
-
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-using util::Status;
-using ::PROTOBUF_NAMESPACE_ID::internal::WireFormatLite;
-using std::placeholders::_1;
-
-
-ProtoStreamObjectWriter::ProtoStreamObjectWriter(
-    TypeResolver* type_resolver, const google::protobuf::Type& type,
-    strings::ByteSink* output, ErrorListener* listener,
-    const ProtoStreamObjectWriter::Options& options)
-    : ProtoWriter(type_resolver, type, output, listener),
-      master_type_(type),
-      current_(nullptr),
-      options_(options) {
-  set_ignore_unknown_fields(options_.ignore_unknown_fields);
-  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(
-    const TypeInfo* typeinfo, const google::protobuf::Type& type,
-    strings::ByteSink* output, ErrorListener* listener,
-    const ProtoStreamObjectWriter::Options& options)
-    : ProtoWriter(typeinfo, type, output, listener),
-      master_type_(type),
-      current_(nullptr),
-      options_(options) {
-  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(
-    const TypeInfo* typeinfo, const google::protobuf::Type& type,
-    strings::ByteSink* output, ErrorListener* listener)
-    : ProtoWriter(typeinfo, type, output, listener),
-      master_type_(type),
-      current_(nullptr),
-      options_(ProtoStreamObjectWriter::Options::Defaults()) {}
-
-ProtoStreamObjectWriter::~ProtoStreamObjectWriter() {
-  if (current_ == nullptr) return;
-  // Cleanup explicitly in order to avoid destructor stack overflow when input
-  // is deeply nested.
-  // Cast to BaseElement to avoid doing additional checks (like missing fields)
-  // during pop().
-  std::unique_ptr<BaseElement> element(
-      static_cast<BaseElement*>(current_.get())->pop<BaseElement>());
-  while (element != nullptr) {
-    element.reset(element->pop<BaseElement>());
-  }
-}
-
-namespace {
-// Utility method to split a string representation of Timestamp or Duration and
-// return the parts.
-void SplitSecondsAndNanos(StringPiece input, StringPiece* seconds,
-                          StringPiece* nanos) {
-  size_t idx = input.rfind('.');
-  if (idx != std::string::npos) {
-    *seconds = input.substr(0, idx);
-    *nanos = input.substr(idx + 1);
-  } else {
-    *seconds = input;
-    *nanos = StringPiece();
-  }
-}
-
-Status GetNanosFromStringPiece(StringPiece s_nanos,
-                               const char* parse_failure_message,
-                               const char* exceeded_limit_message,
-                               int32_t* nanos) {
-  *nanos = 0;
-
-  // Count the number of leading 0s and consume them.
-  int num_leading_zeros = 0;
-  while (s_nanos.Consume("0")) {
-    num_leading_zeros++;
-  }
-  int32_t i_nanos = 0;
-  // 's_nanos' contains fractional seconds -- i.e. 'nanos' is equal to
-  // "0." + s_nanos.ToString() seconds. An int32_t 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 util::InvalidArgumentError(parse_failure_message);
-  }
-  if (i_nanos > kNanosPerSecond || i_nanos < 0) {
-    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 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_t scale = num_leading_zeros + s_nanos.size();
-    // 'conversion' converts i_nanos into nanoseconds.
-    // conversion = kNanosPerSecond / static_cast<int32_t>(std::pow(10, scale))
-    // For efficiency, we precompute the conversion factor.
-    int32_t conversion = 0;
-    switch (scale) {
-      case 1:
-        conversion = 100000000;
-        break;
-      case 2:
-        conversion = 10000000;
-        break;
-      case 3:
-        conversion = 1000000;
-        break;
-      case 4:
-        conversion = 100000;
-        break;
-      case 5:
-        conversion = 10000;
-        break;
-      case 6:
-        conversion = 1000;
-        break;
-      case 7:
-        conversion = 100;
-        break;
-      case 8:
-        conversion = 10;
-        break;
-      case 9:
-        conversion = 1;
-        break;
-      default:
-        return util::InvalidArgumentError(exceeded_limit_message);
-    }
-    *nanos = i_nanos * conversion;
-  }
-
-  return Status();
-}
-
-}  // namespace
-
-ProtoStreamObjectWriter::AnyWriter::AnyWriter(ProtoStreamObjectWriter* parent)
-    : parent_(parent),
-      ow_(),
-      invalid_(false),
-      data_(),
-      output_(&data_),
-      depth_(0),
-      is_well_known_type_(false),
-      well_known_type_render_(nullptr) {}
-
-ProtoStreamObjectWriter::AnyWriter::~AnyWriter() {}
-
-void ProtoStreamObjectWriter::AnyWriter::StartObject(StringPiece name) {
-  ++depth_;
-  // If an object writer is absent, that means we have not called StartAny()
-  // before reaching here, which happens when we have data before the "@type"
-  // field.
-  if (ow_ == nullptr) {
-    // Save data before the "@type" field for later replay.
-    uninterpreted_events_.push_back(Event(Event::START_OBJECT, name));
-  } else if (is_well_known_type_ && depth_ == 1) {
-    // For well-known types, the only other field besides "@type" should be a
-    // "value" field.
-    if (name != "value" && !invalid_) {
-      parent_->InvalidValue("Any",
-                            "Expect a \"value\" field for well-known types.");
-      invalid_ = true;
-    }
-    ow_->StartObject("");
-  } else {
-    // Forward the call to the child writer if:
-    //   1. the type is not a well-known type.
-    //   2. or, we are in a nested Any, Struct, or Value object.
-    ow_->StartObject(name);
-  }
-}
-
-bool ProtoStreamObjectWriter::AnyWriter::EndObject() {
-  --depth_;
-  if (ow_ == nullptr) {
-    if (depth_ >= 0) {
-      // Save data before the "@type" field for later replay.
-      uninterpreted_events_.push_back(Event(Event::END_OBJECT));
-    }
-  } else if (depth_ >= 0 || !is_well_known_type_) {
-    // As long as depth_ >= 0, we know we haven't reached the end of Any.
-    // Propagate these EndObject() calls to the contained ow_. For regular
-    // message types, we propagate the end of Any as well.
-    ow_->EndObject();
-  }
-  // A negative depth_ implies that we have reached the end of Any
-  // object. Now we write out its contents.
-  if (depth_ < 0) {
-    WriteAny();
-    return false;
-  }
-  return true;
-}
-
-void ProtoStreamObjectWriter::AnyWriter::StartList(StringPiece name) {
-  ++depth_;
-  if (ow_ == nullptr) {
-    // Save data before the "@type" field for later replay.
-    uninterpreted_events_.push_back(Event(Event::START_LIST, name));
-  } else if (is_well_known_type_ && depth_ == 1) {
-    if (name != "value" && !invalid_) {
-      parent_->InvalidValue("Any",
-                            "Expect a \"value\" field for well-known types.");
-      invalid_ = true;
-    }
-    ow_->StartList("");
-  } else {
-    ow_->StartList(name);
-  }
-}
-
-void ProtoStreamObjectWriter::AnyWriter::EndList() {
-  --depth_;
-  if (depth_ < 0) {
-    GOOGLE_LOG(DFATAL) << "Mismatched EndList found, should not be possible";
-    depth_ = 0;
-  }
-  if (ow_ == nullptr) {
-    // Save data before the "@type" field for later replay.
-    uninterpreted_events_.push_back(Event(Event::END_LIST));
-  } else {
-    ow_->EndList();
-  }
-}
-
-void ProtoStreamObjectWriter::AnyWriter::RenderDataPiece(
-    StringPiece name, const DataPiece& value) {
-  // Start an Any only at depth_ 0. Other RenderDataPiece calls with "@type"
-  // should go to the contained ow_ as they indicate nested Anys.
-  if (depth_ == 0 && ow_ == nullptr && name == "@type") {
-    StartAny(value);
-  } else if (ow_ == nullptr) {
-    // Save data before the "@type" field.
-    uninterpreted_events_.push_back(Event(name, value));
-  } else if (depth_ == 0 && is_well_known_type_) {
-    if (name != "value" && !invalid_) {
-      parent_->InvalidValue("Any",
-                            "Expect a \"value\" field for well-known types.");
-      invalid_ = true;
-    }
-    if (well_known_type_render_ == nullptr) {
-      // Only Any and Struct don't have a special type render but both of
-      // them expect a JSON object (i.e., a StartObject() call).
-      if (value.type() != DataPiece::TYPE_NULL && !invalid_) {
-        parent_->InvalidValue("Any", "Expect a JSON object.");
-        invalid_ = true;
-      }
-    } else {
-      ow_->ProtoWriter::StartObject("");
-      Status status = (*well_known_type_render_)(ow_.get(), value);
-      if (!status.ok()) ow_->InvalidValue("Any", status.message());
-      ow_->ProtoWriter::EndObject();
-    }
-  } else {
-    ow_->RenderDataPiece(name, value);
-  }
-}
-
-void ProtoStreamObjectWriter::AnyWriter::StartAny(const DataPiece& value) {
-  // Figure out the type url. This is a copy-paste from WriteString but we also
-  // need the value, so we can't just call through to that.
-  if (value.type() == DataPiece::TYPE_STRING) {
-    type_url_ = std::string(value.str());
-  } else {
-    util::StatusOr<std::string> s = value.ToString();
-    if (!s.ok()) {
-      parent_->InvalidValue("String", s.status().message());
-      invalid_ = true;
-      return;
-    }
-    type_url_ = s.value();
-  }
-  // Resolve the type url, and report an error if we failed to resolve it.
-  util::StatusOr<const google::protobuf::Type*> resolved_type =
-      parent_->typeinfo()->ResolveTypeUrl(type_url_);
-  if (!resolved_type.ok()) {
-    parent_->InvalidValue("Any", resolved_type.status().message());
-    invalid_ = true;
-    return;
-  }
-  // At this point, type is never null.
-  const google::protobuf::Type* type = resolved_type.value();
-
-  well_known_type_render_ = FindTypeRenderer(type_url_);
-  if (well_known_type_render_ != nullptr ||
-      // Explicitly list Any and Struct here because they don't have a
-      // custom renderer.
-      type->name() == kAnyType || type->name() == kStructType) {
-    is_well_known_type_ = true;
-  }
-
-  // Create our object writer and initialize it with the first StartObject
-  // call.
-  ow_.reset(new ProtoStreamObjectWriter(parent_->typeinfo(), *type, &output_,
-                                        parent_->listener(),
-                                        parent_->options_));
-
-  // Don't call StartObject() for well-known types yet. Depending on the
-  // type of actual data, we may not need to call StartObject(). For
-  // example:
-  // {
-  //   "@type": "type.googleapis.com/google.protobuf.Value",
-  //   "value": [1, 2, 3],
-  // }
-  // With the above JSON representation, we will only call StartList() on the
-  // contained ow_.
-  if (!is_well_known_type_) {
-    ow_->StartObject("");
-  }
-
-  // Now we know the proto type and can interpret all data fields we gathered
-  // before the "@type" field.
-  for (int i = 0; i < uninterpreted_events_.size(); ++i) {
-    uninterpreted_events_[i].Replay(this);
-  }
-}
-
-void ProtoStreamObjectWriter::AnyWriter::WriteAny() {
-  if (ow_ == nullptr) {
-    if (uninterpreted_events_.empty()) {
-      // We never got any content, so just return immediately, which is
-      // equivalent to writing an empty Any.
-      return;
-    } else {
-      // There are uninterpreted data, but we never got a "@type" field.
-      if (!invalid_) {
-        parent_->InvalidValue("Any",
-                              StrCat("Missing @type for any field in ",
-                                           parent_->master_type_.name()));
-        invalid_ = true;
-      }
-      return;
-    }
-  }
-  // Render the type_url and value fields directly to the stream.
-  // type_url has tag 1 and value has tag 2.
-  WireFormatLite::WriteString(1, type_url_, parent_->stream());
-  if (!data_.empty()) {
-    WireFormatLite::WriteBytes(2, data_, parent_->stream());
-  }
-}
-
-void ProtoStreamObjectWriter::AnyWriter::Event::Replay(
-    AnyWriter* writer) const {
-  switch (type_) {
-    case START_OBJECT:
-      writer->StartObject(name_);
-      break;
-    case END_OBJECT:
-      writer->EndObject();
-      break;
-    case START_LIST:
-      writer->StartList(name_);
-      break;
-    case END_LIST:
-      writer->EndList();
-      break;
-    case RENDER_DATA_PIECE:
-      writer->RenderDataPiece(name_, value_);
-      break;
-  }
-}
-
-void ProtoStreamObjectWriter::AnyWriter::Event::DeepCopy() {
-  // DataPiece only contains a string reference. To make sure the referenced
-  // string value stays valid, we make a copy of the string value and update
-  // DataPiece to reference our own copy.
-  if (value_.type() == DataPiece::TYPE_STRING) {
-    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().value();
-    value_ =
-        DataPiece(value_storage_, true, value_.use_strict_base64_decoding());
-  }
-}
-
-ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter* enclosing,
-                                    ItemType item_type, bool is_placeholder,
-                                    bool is_list)
-    : BaseElement(nullptr),
-      ow_(enclosing),
-      any_(),
-      item_type_(item_type),
-      is_placeholder_(is_placeholder),
-      is_list_(is_list) {
-  if (item_type_ == ANY) {
-    any_.reset(new AnyWriter(ow_));
-  }
-  if (item_type == MAP) {
-    map_keys_.reset(new std::unordered_set<std::string>);
-  }
-}
-
-ProtoStreamObjectWriter::Item::Item(ProtoStreamObjectWriter::Item* parent,
-                                    ItemType item_type, bool is_placeholder,
-                                    bool is_list)
-    : BaseElement(parent),
-      ow_(this->parent()->ow_),
-      any_(),
-      item_type_(item_type),
-      is_placeholder_(is_placeholder),
-      is_list_(is_list) {
-  if (item_type == ANY) {
-    any_.reset(new AnyWriter(ow_));
-  }
-  if (item_type == MAP) {
-    map_keys_.reset(new std::unordered_set<std::string>);
-  }
-}
-
-bool ProtoStreamObjectWriter::Item::InsertMapKeyIfNotPresent(
-    StringPiece map_key) {
-  return InsertIfNotPresent(map_keys_.get(), std::string(map_key));
-}
-
-
-ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartObject(
-    StringPiece name) {
-  if (invalid_depth() > 0) {
-    IncrementInvalidDepth();
-    return this;
-  }
-
-  // Starting the root message. Create the root Item and return.
-  // ANY message type does not need special handling, just set the ItemType
-  // to ANY.
-  if (current_ == nullptr) {
-    ProtoWriter::StartObject(name);
-    current_.reset(new Item(
-        this, master_type_.name() == kAnyType ? Item::ANY : Item::MESSAGE,
-        false, false));
-
-    // If master type is a special type that needs extra values to be written to
-    // stream, we write those values.
-    if (master_type_.name() == kStructType) {
-      // Struct has a map<string, Value> field called "fields".
-      // https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto
-      // "fields": [
-      Push("fields", Item::MAP, true, true);
-      return this;
-    }
-
-    if (master_type_.name() == kStructValueType) {
-      // We got a StartObject call with google.protobuf.Value field. The only
-      // object within that type is a struct type. So start a struct.
-      //
-      // The struct field in Value type is named "struct_value"
-      // https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto
-      // Also start the map field "fields" within the struct.
-      // "struct_value": {
-      //   "fields": [
-      Push("struct_value", Item::MESSAGE, true, false);
-      Push("fields", Item::MAP, true, true);
-      return this;
-    }
-
-    if (master_type_.name() == kStructListValueType) {
-      InvalidValue(kStructListValueType,
-                   "Cannot start root message with ListValue.");
-    }
-
-    return this;
-  }
-
-  // Send all ANY events to AnyWriter.
-  if (current_->IsAny()) {
-    current_->any()->StartObject(name);
-    return this;
-  }
-
-  // If we are within a map, we render name as keys and send StartObject to the
-  // value field.
-  if (current_->IsMap()) {
-    if (!ValidMapKey(name)) {
-      IncrementInvalidDepth();
-      return this;
-    }
-
-    // Map is a repeated field of message type with a "key" and a "value" field.
-    // https://developers.google.com/protocol-buffers/docs/proto3?hl=en#maps
-    // message MapFieldEntry {
-    //   key_type key = 1;
-    //   value_type value = 2;
-    // }
-    //
-    // repeated MapFieldEntry map_field = N;
-    //
-    // That means, we render the following element within a list (hence no
-    // name):
-    // { "key": "<name>", "value": {
-    Push("", Item::MESSAGE, false, false);
-    ProtoWriter::RenderDataPiece("key",
-                                 DataPiece(name, use_strict_base64_decoding()));
-    Push("value", IsAny(*Lookup("value")) ? Item::ANY : Item::MESSAGE, true,
-         false);
-
-    // Make sure we are valid so far after starting map fields.
-    if (invalid_depth() > 0) return this;
-
-    // If top of stack is g.p.Struct type, start the struct the map field within
-    // it.
-    if (element() != nullptr && IsStruct(*element()->parent_field())) {
-      // Render "fields": [
-      Push("fields", Item::MAP, true, true);
-      return this;
-    }
-
-    // If top of stack is g.p.Value type, start the Struct within it.
-    if (element() != nullptr && IsStructValue(*element()->parent_field())) {
-      // Render
-      // "struct_value": {
-      //   "fields": [
-      Push("struct_value", Item::MESSAGE, true, false);
-      Push("fields", Item::MAP, true, true);
-    }
-    return this;
-  }
-
-  const google::protobuf::Field* field = BeginNamed(name, false);
-
-  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
-    // "<name>": {
-    //   "fields": {
-    Push(name, Item::MESSAGE, false, false);
-    Push("fields", Item::MAP, true, true);
-    return this;
-  }
-
-  if (IsStructValue(*field)) {
-    // We got a StartObject call with google.protobuf.Value field.  The only
-    // object within that type is a struct type. So start a struct.
-    // Render
-    // "<name>": {
-    //   "struct_value": {
-    //     "fields": {
-    Push(name, Item::MESSAGE, false, false);
-    Push("struct_value", Item::MESSAGE, true, false);
-    Push("fields", Item::MAP, true, true);
-    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");
-    }
-
-    return this;
-  }
-
-  // A regular message type. Pass it directly to ProtoWriter.
-  // Render
-  // "<name>": {
-  Push(name, IsAny(*field) ? Item::ANY : Item::MESSAGE, false, false);
-  return this;
-}
-
-ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndObject() {
-  if (invalid_depth() > 0) {
-    DecrementInvalidDepth();
-    return this;
-  }
-
-  if (current_ == nullptr) return this;
-
-  if (current_->IsAny()) {
-    if (current_->any()->EndObject()) return this;
-  }
-
-  Pop();
-
-  return this;
-}
-
-
-ProtoStreamObjectWriter* ProtoStreamObjectWriter::StartList(
-    StringPiece name) {
-  if (invalid_depth() > 0) {
-    IncrementInvalidDepth();
-    return this;
-  }
-
-  // Since we cannot have a top-level repeated item in protobuf, the only way
-  // this is valid is if we start a special type google.protobuf.ListValue or
-  // google.protobuf.Value.
-  if (current_ == nullptr) {
-    if (!name.empty()) {
-      InvalidName(name, "Root element should not be named.");
-      IncrementInvalidDepth();
-      return this;
-    }
-
-    // If master type is a special type that needs extra values to be written to
-    // stream, we write those values.
-    if (master_type_.name() == kStructValueType) {
-      // We got a StartList with google.protobuf.Value master type. This means
-      // we have to start the "list_value" within google.protobuf.Value.
-      //
-      // See
-      // https://github.com/protocolbuffers/protobuf/blob/main/src/google/protobuf/struct.proto
-      //
-      // Render
-      // "<name>": {
-      //   "list_value": {
-      //     "values": [  // Start this list.
-      ProtoWriter::StartObject(name);
-      current_.reset(new Item(this, Item::MESSAGE, false, false));
-      Push("list_value", Item::MESSAGE, true, false);
-      Push("values", Item::MESSAGE, true, true);
-      return this;
-    }
-
-    if (master_type_.name() == kStructListValueType) {
-      // We got a StartList with google.protobuf.ListValue master type. This
-      // means we have to start the "values" within google.protobuf.ListValue.
-      //
-      // Render
-      // "<name>": {
-      //   "values": [  // Start this list.
-      ProtoWriter::StartObject(name);
-      current_.reset(new Item(this, Item::MESSAGE, false, false));
-      Push("values", Item::MESSAGE, true, true);
-      return this;
-    }
-
-    // Send the event to ProtoWriter so proper errors can be reported.
-    //
-    // Render a regular list:
-    // "<name>": [
-    ProtoWriter::StartList(name);
-    current_.reset(new Item(this, Item::MESSAGE, false, true));
-    return this;
-  }
-
-  if (current_->IsAny()) {
-    current_->any()->StartList(name);
-    return this;
-  }
-
-  // If the top of stack is a map, we are starting a list value within a map.
-  // Since map does not allow repeated values, this can only happen when the map
-  // value is of a special type that renders a list in JSON.  These can be one
-  // of 3 cases:
-  // i. We are rendering a list value within google.protobuf.Struct
-  // ii. We are rendering a list value within google.protobuf.Value
-  // iii. We are rendering a list value with type google.protobuf.ListValue.
-  if (current_->IsMap()) {
-    if (!ValidMapKey(name)) {
-      IncrementInvalidDepth();
-      return this;
-    }
-
-    // Start the repeated map entry object.
-    // Render
-    // { "key": "<name>", "value": {
-    Push("", Item::MESSAGE, false, false);
-    ProtoWriter::RenderDataPiece("key",
-                                 DataPiece(name, use_strict_base64_decoding()));
-    Push("value", Item::MESSAGE, true, false);
-
-    // Make sure we are valid after pushing all above items.
-    if (invalid_depth() > 0) return this;
-
-    // case i and ii above. Start "list_value" field within g.p.Value
-    if (element() != nullptr && element()->parent_field() != nullptr) {
-      // Render
-      // "list_value": {
-      //   "values": [  // Start this list
-      if (IsStructValue(*element()->parent_field())) {
-        Push("list_value", Item::MESSAGE, true, false);
-        Push("values", Item::MESSAGE, true, true);
-        return this;
-      }
-
-      // Render
-      // "values": [
-      if (IsStructListValue(*element()->parent_field())) {
-        // case iii above. Bind directly to g.p.ListValue
-        Push("values", Item::MESSAGE, true, true);
-        return this;
-      }
-    }
-
-    // Report an error.
-    InvalidValue("Map", StrCat("Cannot have repeated items ('", name,
-                                     "') within a map."));
-    return this;
-  }
-
-  // When name is empty and stack is not empty, we are rendering an item within
-  // a list.
-  if (name.empty()) {
-    if (element() != nullptr && element()->parent_field() != nullptr) {
-      if (IsStructValue(*element()->parent_field())) {
-        // Since it is g.p.Value, we bind directly to the list_value.
-        // Render
-        // {  // g.p.Value item within the list
-        //   "list_value": {
-        //     "values": [
-        Push("", Item::MESSAGE, false, false);
-        Push("list_value", Item::MESSAGE, true, false);
-        Push("values", Item::MESSAGE, true, true);
-        return this;
-      }
-
-      if (IsStructListValue(*element()->parent_field())) {
-        // Since it is g.p.ListValue, we bind to it directly.
-        // Render
-        // {  // g.p.ListValue item within the list
-        //   "values": [
-        Push("", Item::MESSAGE, false, false);
-        Push("values", Item::MESSAGE, true, true);
-        return this;
-      }
-    }
-
-    // Pass the event to underlying ProtoWriter.
-    Push(name, Item::MESSAGE, false, true);
-    return this;
-  }
-
-  // name is not empty
-  const google::protobuf::Field* field = Lookup(name);
-
-  if (field == nullptr) {
-    IncrementInvalidDepth();
-    return this;
-  }
-
-  if (IsStructValue(*field)) {
-    // If g.p.Value is repeated, start that list. Otherwise, start the
-    // "list_value" within it.
-    if (IsRepeated(*field)) {
-      // Render it just like a regular repeated field.
-      // "<name>": [
-      Push(name, Item::MESSAGE, false, true);
-      return this;
-    }
-
-    // Start the "list_value" field.
-    // Render
-    // "<name>": {
-    //   "list_value": {
-    //     "values": [
-    Push(name, Item::MESSAGE, false, false);
-    Push("list_value", Item::MESSAGE, true, false);
-    Push("values", Item::MESSAGE, true, true);
-    return this;
-  }
-
-  if (IsStructListValue(*field)) {
-    // If g.p.ListValue is repeated, start that list. Otherwise, start the
-    // "values" within it.
-    if (IsRepeated(*field)) {
-      // Render it just like a regular repeated field.
-      // "<name>": [
-      Push(name, Item::MESSAGE, false, true);
-      return this;
-    }
-
-    // Start the "values" field within g.p.ListValue.
-    // Render
-    // "<name>": {
-    //   "values": [
-    Push(name, Item::MESSAGE, false, false);
-    Push("values", Item::MESSAGE, true, true);
-    return this;
-  }
-
-  // If we are here, the field should be repeated. Report an error otherwise.
-  if (!IsRepeated(*field)) {
-    IncrementInvalidDepth();
-    InvalidName(name, "Proto field is not repeating, cannot start list.");
-    return this;
-  }
-
-  if (IsMap(*field)) {
-    if (options_.use_legacy_json_map_format) {
-      Push(name, Item::MESSAGE, false, true);
-      return this;
-    }
-    InvalidValue("Map", StrCat("Cannot bind a list to map for field '",
-                                     name, "'."));
-    IncrementInvalidDepth();
-    return this;
-  }
-
-  // Pass the event to ProtoWriter.
-  // Render
-  // "<name>": [
-  Push(name, Item::MESSAGE, false, true);
-  return this;
-}
-
-ProtoStreamObjectWriter* ProtoStreamObjectWriter::EndList() {
-  if (invalid_depth() > 0) {
-    DecrementInvalidDepth();
-    return this;
-  }
-
-  if (current_ == nullptr) return this;
-
-  if (current_->IsAny()) {
-    current_->any()->EndList();
-    return this;
-  }
-
-  Pop();
-  return this;
-}
-
-Status ProtoStreamObjectWriter::RenderStructValue(ProtoStreamObjectWriter* ow,
-                                                  const DataPiece& data) {
-  std::string struct_field_name;
-  switch (data.type()) {
-    case DataPiece::TYPE_INT32: {
-      if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<int32_t> int_value = data.ToInt32();
-        if (int_value.ok()) {
-          ow->ProtoWriter::RenderDataPiece(
-              "string_value",
-              DataPiece(SimpleDtoa(int_value.value()), true));
-          return Status();
-        }
-      }
-      struct_field_name = "number_value";
-      break;
-    }
-    case DataPiece::TYPE_UINT32: {
-      if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<uint32_t> int_value = data.ToUint32();
-        if (int_value.ok()) {
-          ow->ProtoWriter::RenderDataPiece(
-              "string_value",
-              DataPiece(SimpleDtoa(int_value.value()), true));
-          return Status();
-        }
-      }
-      struct_field_name = "number_value";
-      break;
-    }
-    case DataPiece::TYPE_INT64: {
-      // 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) {
-        util::StatusOr<int64_t> int_value = data.ToInt64();
-        if (int_value.ok()) {
-          ow->ProtoWriter::RenderDataPiece(
-              "string_value", DataPiece(StrCat(int_value.value()), true));
-          return Status();
-        }
-      }
-      struct_field_name = "number_value";
-      break;
-    }
-    case DataPiece::TYPE_UINT64: {
-      // 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) {
-        util::StatusOr<uint64_t> int_value = data.ToUint64();
-        if (int_value.ok()) {
-          ow->ProtoWriter::RenderDataPiece(
-              "string_value", DataPiece(StrCat(int_value.value()), true));
-          return Status();
-        }
-      }
-      struct_field_name = "number_value";
-      break;
-    }
-    case DataPiece::TYPE_FLOAT: {
-      if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<float> float_value = data.ToFloat();
-        if (float_value.ok()) {
-          ow->ProtoWriter::RenderDataPiece(
-              "string_value",
-              DataPiece(SimpleDtoa(float_value.value()), true));
-          return Status();
-        }
-      }
-      struct_field_name = "number_value";
-      break;
-    }
-    case DataPiece::TYPE_DOUBLE: {
-      if (ow->options_.struct_integers_as_strings) {
-        util::StatusOr<double> double_value = data.ToDouble();
-        if (double_value.ok()) {
-          ow->ProtoWriter::RenderDataPiece(
-              "string_value",
-              DataPiece(SimpleDtoa(double_value.value()), true));
-          return Status();
-        }
-      }
-      struct_field_name = "number_value";
-      break;
-    }
-    case DataPiece::TYPE_STRING: {
-      struct_field_name = "string_value";
-      break;
-    }
-    case DataPiece::TYPE_BOOL: {
-      struct_field_name = "bool_value";
-      break;
-    }
-    case DataPiece::TYPE_NULL: {
-      struct_field_name = "null_value";
-      break;
-    }
-    default: {
-      return util::InvalidArgumentError(
-          "Invalid struct data type. Only number, string, boolean or  null "
-          "values are supported.");
-    }
-  }
-  ow->ProtoWriter::RenderDataPiece(struct_field_name, data);
-  return Status();
-}
-
-Status ProtoStreamObjectWriter::RenderTimestamp(ProtoStreamObjectWriter* ow,
-                                                const DataPiece& data) {
-  if (data.type() == DataPiece::TYPE_NULL) return Status();
-  if (data.type() != DataPiece::TYPE_STRING) {
-    return util::InvalidArgumentError(
-        StrCat("Invalid data type for timestamp, value is ",
-                     data.ValueAsStringOrDefault("")));
-  }
-
-  StringPiece value(data.str());
-
-  int64_t seconds;
-  int32_t nanos;
-  if (!::google::protobuf::internal::ParseTime(value.ToString(), &seconds,
-                                               &nanos)) {
-    return util::InvalidArgumentError(StrCat("Invalid time format: ", value));
-  }
-
-
-  ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
-  ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
-  return Status();
-}
-
-static inline util::Status RenderOneFieldPath(ProtoStreamObjectWriter* ow,
-                                              StringPiece path) {
-  ow->ProtoWriter::RenderDataPiece(
-      "paths", DataPiece(ConvertFieldMaskPath(path, &ToSnakeCase), true));
-  return Status();
-}
-
-Status ProtoStreamObjectWriter::RenderFieldMask(ProtoStreamObjectWriter* ow,
-                                                const DataPiece& data) {
-  if (data.type() == DataPiece::TYPE_NULL) return Status();
-  if (data.type() != DataPiece::TYPE_STRING) {
-    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
-  // conversions as much as possible. Because ToSnakeCase sometimes returns the
-  // wrong value.
-  return DecodeCompactFieldMaskPaths(data.str(),
-                                     std::bind(&RenderOneFieldPath, ow, _1));
-}
-
-Status ProtoStreamObjectWriter::RenderDuration(ProtoStreamObjectWriter* ow,
-                                               const DataPiece& data) {
-  if (data.type() == DataPiece::TYPE_NULL) return Status();
-  if (data.type() != DataPiece::TYPE_STRING) {
-    return util::InvalidArgumentError(
-        StrCat("Invalid data type for duration, value is ",
-                     data.ValueAsStringOrDefault("")));
-  }
-
-  StringPiece value(data.str());
-
-  if (!HasSuffixString(value, "s")) {
-    return util::InvalidArgumentError(
-        "Illegal duration format; duration must end with 's'");
-  }
-  value = value.substr(0, value.size() - 1);
-  int sign = 1;
-  if (HasPrefixString(value, "-")) {
-    sign = -1;
-    value = value.substr(1);
-  }
-
-  StringPiece s_secs, s_nanos;
-  SplitSecondsAndNanos(value, &s_secs, &s_nanos);
-  uint64_t unsigned_seconds;
-  if (!safe_strtou64(s_secs, &unsigned_seconds)) {
-    return util::InvalidArgumentError(
-        "Invalid duration format, failed to parse seconds");
-  }
-
-  int32_t nanos = 0;
-  Status nanos_status = GetNanosFromStringPiece(
-      s_nanos, "Invalid duration format, failed to parse nano seconds",
-      "Duration value exceeds limits", &nanos);
-  if (!nanos_status.ok()) {
-    return nanos_status;
-  }
-  nanos = sign * nanos;
-
-  int64_t seconds = sign * unsigned_seconds;
-  if (seconds > kDurationMaxSeconds || seconds < kDurationMinSeconds ||
-      nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
-    return util::InvalidArgumentError("Duration value exceeds limits");
-  }
-
-  ow->ProtoWriter::RenderDataPiece("seconds", DataPiece(seconds));
-  ow->ProtoWriter::RenderDataPiece("nanos", DataPiece(nanos));
-  return Status();
-}
-
-Status ProtoStreamObjectWriter::RenderWrapperType(ProtoStreamObjectWriter* ow,
-                                                  const DataPiece& data) {
-  if (data.type() == DataPiece::TYPE_NULL) return Status();
-  ow->ProtoWriter::RenderDataPiece("value", data);
-  return Status();
-}
-
-ProtoStreamObjectWriter* ProtoStreamObjectWriter::RenderDataPiece(
-    StringPiece name, const DataPiece& data) {
-  Status status;
-  if (invalid_depth() > 0) return this;
-
-  if (current_ == nullptr) {
-    const TypeRenderer* type_renderer =
-        FindTypeRenderer(GetFullTypeWithUrl(master_type_.name()));
-    if (type_renderer == nullptr) {
-      InvalidName(name, "Root element must be a message.");
-      return this;
-    }
-    // Render the special type.
-    // "<name>": {
-    //   ... Render special type ...
-    // }
-    ProtoWriter::StartObject(name);
-    status = (*type_renderer)(this, data);
-    if (!status.ok()) {
-      InvalidValue(master_type_.name(),
-                   StrCat("Field '", name, "', ", status.message()));
-    }
-    ProtoWriter::EndObject();
-    return this;
-  }
-
-  if (current_->IsAny()) {
-    current_->any()->RenderDataPiece(name, data);
-    return this;
-  }
-
-  const google::protobuf::Field* field = nullptr;
-  if (current_->IsMap()) {
-    if (!ValidMapKey(name)) return this;
-
-    field = Lookup("value");
-    if (field == nullptr) {
-      GOOGLE_LOG(DFATAL) << "Map does not have a value field.";
-      return this;
-    }
-
-    if (options_.ignore_null_value_map_entry) {
-      // If we are rendering explicit null values and the backend proto field is
-      // not of the google.protobuf.NullType type, interpret null as absence.
-      if (data.type() == DataPiece::TYPE_NULL &&
-          field->type_url() != kStructNullValueTypeUrl) {
-        return this;
-      }
-    }
-
-    // Render an item in repeated map list.
-    // { "key": "<name>", "value":
-    Push("", Item::MESSAGE, false, false);
-    ProtoWriter::RenderDataPiece("key",
-                                 DataPiece(name, use_strict_base64_decoding()));
-
-    const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
-    if (type_renderer != nullptr) {
-      // Map's value type is a special type. Render it like a message:
-      // "value": {
-      //   ... Render special type ...
-      // }
-      Push("value", Item::MESSAGE, true, false);
-      status = (*type_renderer)(this, data);
-      if (!status.ok()) {
-        InvalidValue(field->type_url(),
-                     StrCat("Field '", name, "', ", status.message()));
-      }
-      Pop();
-      return this;
-    }
-
-    // If we are rendering explicit null values and the backend proto field is
-    // not of the google.protobuf.NullType type, we do nothing.
-    if (data.type() == DataPiece::TYPE_NULL &&
-        field->type_url() != kStructNullValueTypeUrl) {
-      Pop();
-      return this;
-    }
-
-    // Render the map value as a primitive type.
-    ProtoWriter::RenderDataPiece("value", data);
-    Pop();
-    return this;
-  }
-
-  field = Lookup(name);
-  if (field == nullptr) return this;
-
-  // Check if the field is of special type. Render it accordingly if so.
-  const TypeRenderer* type_renderer = FindTypeRenderer(field->type_url());
-  if (type_renderer != nullptr) {
-    // Pass through null value only for google.protobuf.Value. For other
-    // types we ignore null value just like for regular field types.
-    if (data.type() != DataPiece::TYPE_NULL ||
-        field->type_url() == kStructValueTypeUrl) {
-      Push(name, Item::MESSAGE, false, false);
-      status = (*type_renderer)(this, data);
-      if (!status.ok()) {
-        InvalidValue(field->type_url(),
-                     StrCat("Field '", name, "', ", status.message()));
-      }
-      Pop();
-    }
-    return this;
-  }
-
-  // If we are rendering explicit null values and the backend proto field is
-  // not of the google.protobuf.NullType type, we do nothing.
-  if (data.type() == DataPiece::TYPE_NULL &&
-      field->type_url() != kStructNullValueTypeUrl) {
-    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;
-}
-
-// Map of functions that are responsible for rendering well known type
-// represented by the key.
-std::unordered_map<std::string, ProtoStreamObjectWriter::TypeRenderer>*
-    ProtoStreamObjectWriter::renderers_ = nullptr;
-PROTOBUF_NAMESPACE_ID::internal::once_flag writer_renderers_init_;
-
-void ProtoStreamObjectWriter::InitRendererMap() {
-  renderers_ = new std::unordered_map<std::string,
-                                      ProtoStreamObjectWriter::TypeRenderer>();
-  (*renderers_)["type.googleapis.com/google.protobuf.Timestamp"] =
-      &ProtoStreamObjectWriter::RenderTimestamp;
-  (*renderers_)["type.googleapis.com/google.protobuf.Duration"] =
-      &ProtoStreamObjectWriter::RenderDuration;
-  (*renderers_)["type.googleapis.com/google.protobuf.FieldMask"] =
-      &ProtoStreamObjectWriter::RenderFieldMask;
-  (*renderers_)["type.googleapis.com/google.protobuf.Double"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Float"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Int64"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.UInt64"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Int32"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.UInt32"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Bool"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.String"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Bytes"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.DoubleValue"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.FloatValue"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Int64Value"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.UInt64Value"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Int32Value"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.UInt32Value"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.BoolValue"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.StringValue"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.BytesValue"] =
-      &ProtoStreamObjectWriter::RenderWrapperType;
-  (*renderers_)["type.googleapis.com/google.protobuf.Value"] =
-      &ProtoStreamObjectWriter::RenderStructValue;
-  ::google::protobuf::internal::OnShutdown(&DeleteRendererMap);
-}
-
-void ProtoStreamObjectWriter::DeleteRendererMap() {
-  delete ProtoStreamObjectWriter::renderers_;
-  renderers_ = nullptr;
-}
-
-ProtoStreamObjectWriter::TypeRenderer*
-ProtoStreamObjectWriter::FindTypeRenderer(const std::string& type_url) {
-  PROTOBUF_NAMESPACE_ID::internal::call_once(writer_renderers_init_,
-                                             InitRendererMap);
-  return FindOrNull(*renderers_, type_url);
-}
-
-bool ProtoStreamObjectWriter::ValidMapKey(StringPiece unnormalized_name) {
-  if (current_ == nullptr) return true;
-
-  if (!current_->InsertMapKeyIfNotPresent(unnormalized_name)) {
-    listener()->InvalidName(
-        location(), unnormalized_name,
-        StrCat("Repeated map key: '", unnormalized_name,
-                     "' is already set."));
-    return false;
-  }
-
-  return true;
-}
-
-void ProtoStreamObjectWriter::Push(
-    StringPiece name, Item::ItemType item_type, bool is_placeholder,
-    bool is_list) {
-  is_list ? ProtoWriter::StartList(name) : ProtoWriter::StartObject(name);
-
-  // invalid_depth == 0 means it is a successful StartObject or StartList.
-  if (invalid_depth() == 0)
-    current_.reset(
-        new Item(current_.release(), item_type, is_placeholder, is_list));
-}
-
-void ProtoStreamObjectWriter::Pop() {
-  // Pop all placeholder items sending StartObject or StartList events to
-  // ProtoWriter according to is_list value.
-  while (current_ != nullptr && current_->is_placeholder()) {
-    PopOneElement();
-  }
-  if (current_ != nullptr) {
-    PopOneElement();
-  }
-}
-
-void ProtoStreamObjectWriter::PopOneElement() {
-  current_->is_list() ? ProtoWriter::EndList() : ProtoWriter::EndObject();
-  current_.reset(current_->pop<Item>());
-}
-
-bool ProtoStreamObjectWriter::IsMap(const google::protobuf::Field& field) {
-  if (field.type_url().empty() ||
-      field.kind() != google::protobuf::Field::TYPE_MESSAGE ||
-      field.cardinality() != google::protobuf::Field::CARDINALITY_REPEATED) {
-    return false;
-  }
-  const google::protobuf::Type* field_type =
-      typeinfo()->GetTypeByTypeUrl(field.type_url());
-
-  return converter::IsMap(field, *field_type);
-}
-
-bool ProtoStreamObjectWriter::IsAny(const google::protobuf::Field& field) {
-  return GetTypeWithoutUrl(field.type_url()) == kAnyType;
-}
-
-bool ProtoStreamObjectWriter::IsStruct(const google::protobuf::Field& field) {
-  return GetTypeWithoutUrl(field.type_url()) == kStructType;
-}
-
-bool ProtoStreamObjectWriter::IsStructValue(
-    const google::protobuf::Field& field) {
-  return GetTypeWithoutUrl(field.type_url()) == kStructValueType;
-}
-
-bool ProtoStreamObjectWriter::IsStructListValue(
-    const google::protobuf::Field& field) {
-  return GetTypeWithoutUrl(field.type_url()) == kStructListValueType;
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter.h b/src/google/protobuf/util/internal/protostream_objectwriter.h
deleted file mode 100644
index ce2517f..0000000
--- a/src/google/protobuf/util/internal/protostream_objectwriter.h
+++ /dev/null
@@ -1,453 +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_UTIL_INTERNAL_PROTOSTREAM_OBJECTWRITER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTWRITER_H__
-
-#include <deque>
-#include <string>
-#include <unordered_map>
-#include <unordered_set>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/bytestream.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/util/internal/datapiece.h>
-#include <google/protobuf/util/internal/error_listener.h>
-#include <google/protobuf/util/internal/proto_writer.h>
-#include <google/protobuf/util/internal/structured_objectwriter.h>
-#include <google/protobuf/util/internal/type_info.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/stubs/hash.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-class ObjectLocationTracker;
-
-// An ObjectWriter that can write protobuf bytes directly from writer events.
-// This class supports all special types like Struct and Map. It uses
-// the ProtoWriter class to write raw proto bytes.
-//
-// It also supports streaming.
-class PROTOBUF_EXPORT ProtoStreamObjectWriter : public ProtoWriter {
- public:
-  // Options that control ProtoStreamObjectWriter class's behavior.
-  struct Options {
-    // Treats numeric inputs in google.protobuf.Struct as strings. Normally,
-    // numeric values are returned in double field "number_value" of
-    // google.protobuf.Struct. However, this can cause precision loss for
-    // int64/uint64/double inputs. This option is provided for cases that want
-    // to preserve number precision.
-    //
-    // TODO(skarvaje): Rename to struct_numbers_as_strings as it covers double
-    // as well.
-    bool struct_integers_as_strings;
-
-    // Not treat unknown fields as an error. If there is an unknown fields,
-    // just ignore it and continue to process the rest. Note that this doesn't
-    // apply to unknown enum values.
-    bool ignore_unknown_fields;
-
-    // Ignore unknown enum values.
-    bool ignore_unknown_enum_values;
-
-    // If true, check if enum name in camel case or without underscore matches
-    // the field name.
-    bool use_lower_camel_for_enums;
-
-    // If true, check if enum name in UPPER_CASE matches the field name.
-    bool case_insensitive_enum_parsing;
-
-    // If true, skips rendering the map entry if map value is null unless the
-    // value type is google.protobuf.NullType.
-    bool ignore_null_value_map_entry;
-
-    // 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),
-          ignore_unknown_enum_values(false),
-          use_lower_camel_for_enums(false),
-          case_insensitive_enum_parsing(false),
-          ignore_null_value_map_entry(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() {
-      static Options defaults;
-      return defaults;
-    }
-  };
-
-  // Constructor. Does not take ownership of any parameter passed in.
-  ProtoStreamObjectWriter(TypeResolver* type_resolver,
-                          const google::protobuf::Type& type,
-                          strings::ByteSink* output, ErrorListener* listener,
-                          const ProtoStreamObjectWriter::Options& options =
-                              ProtoStreamObjectWriter::Options::Defaults());
-  ~ProtoStreamObjectWriter() override;
-
-  // ObjectWriter methods.
-  ProtoStreamObjectWriter* StartObject(StringPiece name) override;
-  ProtoStreamObjectWriter* EndObject() override;
-  ProtoStreamObjectWriter* StartList(StringPiece name) override;
-  ProtoStreamObjectWriter* EndList() override;
-
-  // Renders a DataPiece 'value' into a field whose wire type is determined
-  // from the given field 'name'.
-  ProtoStreamObjectWriter* RenderDataPiece(StringPiece name,
-                                           const DataPiece& data) override;
-
- protected:
-  // Function that renders a well known type with modified behavior.
-  typedef util::Status (*TypeRenderer)(ProtoStreamObjectWriter*,
-                                       const DataPiece&);
-
-  // Handles writing Anys out using nested object writers and the like.
-  class PROTOBUF_EXPORT AnyWriter {
-   public:
-    explicit AnyWriter(ProtoStreamObjectWriter* parent);
-    ~AnyWriter();
-
-    // Passes a StartObject call through to the Any writer.
-    void StartObject(StringPiece name);
-
-    // Passes an EndObject call through to the Any. Returns true if the any
-    // handled the EndObject call, false if the Any is now all done and is no
-    // longer needed.
-    bool EndObject();
-
-    // Passes a StartList call through to the Any writer.
-    void StartList(StringPiece name);
-
-    // Passes an EndList call through to the Any writer.
-    void EndList();
-
-    // Renders a data piece on the any.
-    void RenderDataPiece(StringPiece name, const DataPiece& value);
-
-   private:
-    // Before the "@type" field is encountered, we store all incoming data
-    // into this Event struct and replay them after we get the "@type" field.
-    class PROTOBUF_EXPORT Event {
-     public:
-      enum Type {
-        START_OBJECT = 0,
-        END_OBJECT = 1,
-        START_LIST = 2,
-        END_LIST = 3,
-        RENDER_DATA_PIECE = 4,
-      };
-
-      // Constructor for END_OBJECT and END_LIST events.
-      explicit Event(Type type) : type_(type), value_(DataPiece::NullData()) {}
-
-      // Constructor for START_OBJECT and START_LIST events.
-      explicit Event(Type type, StringPiece name)
-          : type_(type), name_(name), value_(DataPiece::NullData()) {}
-
-      // Constructor for RENDER_DATA_PIECE events.
-      explicit Event(StringPiece name, const DataPiece& value)
-          : type_(RENDER_DATA_PIECE), name_(name), value_(value) {
-        DeepCopy();
-      }
-
-      Event(const Event& other)
-          : type_(other.type_), name_(other.name_), value_(other.value_) {
-        DeepCopy();
-      }
-
-      Event& operator=(const Event& other) {
-        type_ = other.type_;
-        name_ = other.name_;
-        value_ = other.value_;
-        DeepCopy();
-        return *this;
-      }
-
-      void Replay(AnyWriter* writer) const;
-
-     private:
-      void DeepCopy();
-
-      Type type_;
-      std::string name_;
-      DataPiece value_;
-      std::string value_storage_;
-    };
-
-    // Handles starting up the any once we have a type.
-    void StartAny(const DataPiece& value);
-
-    // Writes the Any out to the parent writer in its serialized form.
-    void WriteAny();
-
-    // The parent of this writer, needed for various bits such as type info and
-    // the listeners.
-    ProtoStreamObjectWriter* parent_;
-
-    // The nested object writer, used to write events.
-    std::unique_ptr<ProtoStreamObjectWriter> ow_;
-
-    // The type_url_ that this Any represents.
-    std::string type_url_;
-
-    // Whether this any is invalid. This allows us to only report an invalid
-    // Any message a single time rather than every time we get a nested field.
-    bool invalid_;
-
-    // The output data and wrapping ByteSink.
-    std::string data_;
-    strings::StringByteSink output_;
-
-    // The depth within the Any, so we can track when we're done.
-    int depth_;
-
-    // True if the type is a well-known type. Well-known types in Any
-    // has a special formatting:
-    // {
-    //   "@type": "type.googleapis.com/google.protobuf.XXX",
-    //   "value": <JSON representation of the type>,
-    // }
-    bool is_well_known_type_;
-    TypeRenderer* well_known_type_render_;
-
-    // Store data before the "@type" field.
-    std::vector<Event> uninterpreted_events_;
-  };
-
-  // Represents an item in a stack of items used to keep state between
-  // ObjectWrier events.
-  class PROTOBUF_EXPORT Item : public BaseElement {
-   public:
-    // Indicates the type of item.
-    enum ItemType {
-      MESSAGE,  // Simple message
-      MAP,      // Proto3 map type
-      ANY,      // Proto3 Any type
-    };
-
-    // Constructor for the root item.
-    Item(ProtoStreamObjectWriter* enclosing, ItemType item_type,
-         bool is_placeholder, bool is_list);
-
-    // Constructor for a field of a message.
-    Item(Item* parent, ItemType item_type, bool is_placeholder, bool is_list);
-
-    ~Item() override {}
-
-    // These functions return true if the element type is corresponding to the
-    // type in function name.
-    bool IsMap() { return item_type_ == MAP; }
-    bool IsAny() { return item_type_ == ANY; }
-
-    AnyWriter* any() const { return any_.get(); }
-
-    Item* parent() const override {
-      return static_cast<Item*>(BaseElement::parent());
-    }
-
-    // Inserts map key into hash set if and only if the key did NOT already
-    // exist in hash set.
-    // The hash set (map_keys_) is ONLY used to keep track of map keys.
-    // Return true if insert successfully; returns false if the map key was
-    // already present.
-    bool InsertMapKeyIfNotPresent(StringPiece map_key);
-
-    bool is_placeholder() const { return is_placeholder_; }
-    bool is_list() const { return is_list_; }
-
-   private:
-    // Used for access to variables of the enclosing instance of
-    // ProtoStreamObjectWriter.
-    ProtoStreamObjectWriter* ow_;
-
-    // A writer for Any objects, handles all Any-related nonsense.
-    std::unique_ptr<AnyWriter> any_;
-
-    // The type of this element, see enum for permissible types.
-    ItemType item_type_;
-
-    // Set of map keys already seen for the type_. Used to validate incoming
-    // messages so no map key appears more than once.
-    std::unique_ptr<std::unordered_set<std::string> > map_keys_;
-
-    // Conveys whether this Item is a placeholder or not. Placeholder items are
-    // pushed to stack to account for special types.
-    bool is_placeholder_;
-
-    // Conveys whether this Item is a list or not. This is used to send
-    // StartList or EndList calls to underlying ObjectWriter.
-    bool is_list_;
-
-    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(Item);
-  };
-
-  ProtoStreamObjectWriter(const TypeInfo* typeinfo,
-                          const google::protobuf::Type& type,
-                          strings::ByteSink* output, ErrorListener* listener);
-
-  ProtoStreamObjectWriter(const TypeInfo* typeinfo,
-                          const google::protobuf::Type& type,
-                          strings::ByteSink* output, ErrorListener* listener,
-                          const ProtoStreamObjectWriter::Options& options);
-
-  // Returns true if the field is a map.
-  inline bool IsMap(const google::protobuf::Field& field);
-
-  // Returns true if the field is an any.
-  inline bool IsAny(const google::protobuf::Field& field);
-
-  // Returns true if the field is google.protobuf.Struct.
-  inline bool IsStruct(const google::protobuf::Field& field);
-
-  // Returns true if the field is google.protobuf.Value.
-  inline bool IsStructValue(const google::protobuf::Field& field);
-
-  // Returns true if the field is google.protobuf.ListValue.
-  inline bool IsStructListValue(const google::protobuf::Field& field);
-
-  // 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);
-
-  // Renders google.protobuf.Timestamp value.
-  static util::Status RenderTimestamp(ProtoStreamObjectWriter* ow,
-                                      const DataPiece& data);
-
-  // Renders google.protobuf.FieldMask value.
-  static util::Status RenderFieldMask(ProtoStreamObjectWriter* ow,
-                                      const DataPiece& data);
-
-  // Renders google.protobuf.Duration value.
-  static util::Status RenderDuration(ProtoStreamObjectWriter* ow,
-                                     const DataPiece& data);
-
-  // Renders wrapper message types for primitive types in
-  // google/protobuf/wrappers.proto.
-  static util::Status RenderWrapperType(ProtoStreamObjectWriter* ow,
-                                        const DataPiece& data);
-
-  static void InitRendererMap();
-  static void DeleteRendererMap();
-  static TypeRenderer* FindTypeRenderer(const std::string& type_url);
-
-  // Returns true if the map key for type_ is not duplicated key.
-  // If map key is duplicated key, this function returns false.
-  // Note that caller should make sure that the current proto element (current_)
-  // is of element type MAP or STRUCT_MAP.
-  // It also calls the appropriate error callback and unnormalzied_name is used
-  // for error string.
-  bool ValidMapKey(StringPiece unnormalized_name);
-
-  // Pushes an item on to the stack. Also calls either StartObject or StartList
-  // on the underlying ObjectWriter depending on whether is_list is false or
-  // not.
-  // is_placeholder conveys whether the item is a placeholder item or not.
-  // Placeholder items are pushed when adding auxiliary types' StartObject or
-  // StartList calls.
-  void Push(StringPiece name, Item::ItemType item_type,
-            bool is_placeholder, bool is_list);
-
-
-  // Pops items from the stack. All placeholder items are popped until a
-  // non-placeholder item is found.
-  void Pop();
-
-  // Pops one element from the stack. Calls EndObject() or EndList() on the
-  // underlying ObjectWriter depending on the value of is_list_.
-  void PopOneElement();
-
- private:
-  // Helper functions to create the map and find functions responsible for
-  // rendering well known types, keyed by type URL.
-  static std::unordered_map<std::string, TypeRenderer>* renderers_;
-
-  // Variables for describing the structure of the input tree:
-  // master_type_: descriptor for the whole protobuf message.
-  const google::protobuf::Type& master_type_;
-
-  // The current element, variable for internal state processing.
-  std::unique_ptr<Item> current_;
-
-  // Reference to the options that control this class's behavior.
-  const ProtoStreamObjectWriter::Options options_;
-
-  GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(ProtoStreamObjectWriter);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_PROTOSTREAM_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc b/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
deleted file mode 100644
index 3348999..0000000
--- a/src/google/protobuf/util/internal/protostream_objectwriter_test.cc
+++ /dev/null
@@ -1,3032 +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 <google/protobuf/util/internal/protostream_objectwriter.h>
-
-#include <stddef.h>  // For size_t
-
-#include <google/protobuf/field_mask.pb.h>
-#include <google/protobuf/timestamp.pb.h>
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/wrappers.pb.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/util/internal/mock_error_listener.h>
-#include <google/protobuf/util/internal/testdata/anys.pb.h>
-#include <google/protobuf/util/internal/testdata/books.pb.h>
-#include <google/protobuf/util/internal/testdata/field_mask.pb.h>
-#include <google/protobuf/util/internal/testdata/maps.pb.h>
-#include <google/protobuf/util/internal/testdata/oneofs.pb.h>
-#include <google/protobuf/util/internal/testdata/proto3.pb.h>
-#include <google/protobuf/util/internal/testdata/struct.pb.h>
-#include <google/protobuf/util/internal/testdata/timestamp_duration.pb.h>
-#include <google/protobuf/util/internal/testdata/wrappers.pb.h>
-#include <google/protobuf/stubs/bytestream.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <gtest/gtest.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/util/internal/constants.h>
-#include <google/protobuf/util/internal/type_info_test_helper.h>
-#include <google/protobuf/util/message_differencer.h>
-#include <google/protobuf/util/type_resolver_util.h>
-
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-
-using proto_util_converter::testing::AnyM;
-using proto_util_converter::testing::AnyOut;
-using proto_util_converter::testing::Author;
-using proto_util_converter::testing::Book;
-using proto_util_converter::testing::FieldMaskTest;
-using proto_util_converter::testing::Int32Wrapper;
-using proto_util_converter::testing::MapIn;
-using proto_util_converter::testing::Primitive;
-using proto_util_converter::testing::Proto3Message;
-using proto_util_converter::testing::Publisher;
-using proto_util_converter::testing::StructType;
-using proto_util_converter::testing::TestJsonName1;
-using proto_util_converter::testing::TestJsonName2;
-using proto_util_converter::testing::TimestampDuration;
-using proto_util_converter::testing::ValueWrapper;
-using proto_util_converter::testing::oneofs::OneOfsRequest;
-using strings::GrowingArrayByteSink;
-using ::testing::_;
-using ::testing::Args;
-
-
-namespace {
-std::string GetTypeUrl(const Descriptor* descriptor) {
-  return std::string(kTypeServiceBaseUrl) + "/" + descriptor->full_name();
-}
-}  // namespace
-
-class BaseProtoStreamObjectWriterTest
-    : public ::testing::TestWithParam<testing::TypeInfoSource> {
- protected:
-  BaseProtoStreamObjectWriterTest()
-      : helper_(GetParam()),
-        listener_(),
-        output_(new GrowingArrayByteSink(1000)),
-        ow_() {}
-
-  explicit BaseProtoStreamObjectWriterTest(const Descriptor* descriptor)
-      : helper_(GetParam()),
-        listener_(),
-        output_(new GrowingArrayByteSink(1000)),
-        ow_() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(descriptor);
-    ResetTypeInfo(descriptors);
-  }
-
-  explicit BaseProtoStreamObjectWriterTest(
-      std::vector<const Descriptor*> descriptors)
-      : helper_(GetParam()),
-        listener_(),
-        output_(new GrowingArrayByteSink(1000)),
-        ow_() {
-    ResetTypeInfo(descriptors);
-  }
-
-  void ResetTypeInfo(std::vector<const Descriptor*> descriptors) {
-    GOOGLE_CHECK(!descriptors.empty()) << "Must have at least one descriptor!";
-    helper_.ResetTypeInfo(descriptors);
-    ow_.reset(helper_.NewProtoWriter(GetTypeUrl(descriptors[0]), output_.get(),
-                                     &listener_, options_));
-  }
-
-  void ResetTypeInfo(const Descriptor* descriptor) {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(descriptor);
-    ResetTypeInfo(descriptors);
-  }
-
-  ~BaseProtoStreamObjectWriterTest() override {}
-
-  void CheckOutput(const Message& expected, int expected_length) {
-    size_t nbytes;
-    std::unique_ptr<char[]> buffer(output_->GetBuffer(&nbytes));
-    if (expected_length >= 0) {
-      EXPECT_EQ(expected_length, nbytes);
-    }
-    std::string str(buffer.get(), nbytes);
-
-    std::stringbuf str_buf(str, std::ios_base::in);
-    std::istream istream(&str_buf);
-    std::unique_ptr<Message> message(expected.New());
-    message->ParsePartialFromIstream(&istream);
-
-    if (!MessageDifferencer::Equivalent(expected, *message)) {
-      EXPECT_EQ(expected.DebugString(), message->DebugString());
-    }
-  }
-
-  void CheckOutput(const Message& expected) { CheckOutput(expected, -1); }
-
-  testing::TypeInfoTestHelper helper_;
-  MockErrorListener listener_;
-  std::unique_ptr<GrowingArrayByteSink> output_;
-  std::unique_ptr<ProtoStreamObjectWriter> ow_;
-  ProtoStreamObjectWriter::Options options_;
-};
-
-MATCHER_P(HasObjectLocation, expected,
-          "Verifies the expected object location") {
-  std::string actual = std::get<0>(arg).ToString();
-  if (actual == expected) return true;
-  *result_listener << "actual location is: " << actual;
-  return false;
-}
-
-class ProtoStreamObjectWriterTest : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterTest()
-      : BaseProtoStreamObjectWriterTest(Book::descriptor()) {}
-
-  void ResetProtoWriter() { ResetTypeInfo(Book::descriptor()); }
-
-  ~ProtoStreamObjectWriterTest() override {}
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtoStreamObjectWriterTest, EmptyObject) {
-  Book empty;
-  ow_->StartObject("")->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, SimpleObject) {
-  std::string content("My content");
-
-  Book book;
-  book.set_title("My Title");
-  book.set_length(222);
-  book.set_content(content);
-
-  ow_->StartObject("")
-      ->RenderString("title", "My Title")
-      ->RenderInt32("length", 222)
-      ->RenderBytes("content", content)
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, SimpleMessage) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_length(102);
-  Publisher* publisher = book.mutable_publisher();
-  publisher->set_name("My Publisher");
-  Author* robert = book.mutable_author();
-  robert->set_alive(true);
-  robert->set_name("robert");
-  robert->add_pseudonym("bob");
-  robert->add_pseudonym("bobby");
-  robert->add_friend_()->set_name("john");
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderInt32("length", 102)
-      ->StartObject("publisher")
-      ->RenderString("name", "My Publisher")
-      ->EndObject()
-      ->StartObject("author")
-      ->RenderBool("alive", true)
-      ->RenderString("name", "robert")
-      ->StartList("pseudonym")
-      ->RenderString("", "bob")
-      ->RenderString("", "bobby")
-      ->EndList()
-      ->StartList("friend")
-      ->StartObject("")
-      ->RenderString("name", "john")
-      ->EndObject()
-      ->EndList()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, CustomJsonName) {
-  Book book;
-  Author* robert = book.mutable_author();
-  robert->set_id(12345);
-  robert->set_name("robert");
-
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderUint64("@id", 12345)
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-// Test that two messages can have different fields mapped to the same JSON
-// name. See: https://github.com/protocolbuffers/protobuf/issues/1415
-TEST_P(ProtoStreamObjectWriterTest, ConflictingJsonName) {
-  ResetTypeInfo(TestJsonName1::descriptor());
-  TestJsonName1 message1;
-  message1.set_one_value(12345);
-  ow_->StartObject("")->RenderInt32("value", 12345)->EndObject();
-  CheckOutput(message1);
-
-  ResetTypeInfo(TestJsonName2::descriptor());
-  TestJsonName2 message2;
-  message2.set_another_value(12345);
-  ow_->StartObject("")->RenderInt32("value", 12345)->EndObject();
-  CheckOutput(message2);
-}
-
-
-TEST_P(ProtoStreamObjectWriterTest, IntEnumValuesAreAccepted) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_type(proto_util_converter::testing::Book::KIDS);
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "2")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithDifferentCaseIsRejected) {
-  Book book;
-  book.set_title("Some Book");
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  options_.case_insensitive_enum_parsing = false;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "action_and_adventure")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithSameCaseIsAccepted) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  options_.case_insensitive_enum_parsing = false;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "ACTION_AND_ADVENTURE")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithDifferentCaseIsAccepted) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  options_.case_insensitive_enum_parsing = true;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "action_AND_adventure")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, EnumValuesWithoutUnderscoreAreAccepted) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  options_.use_lower_camel_for_enums = true;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "ACTIONANDADVENTURE")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, EnumValuesInCamelCaseAreAccepted) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  options_.use_lower_camel_for_enums = true;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "actionAndAdventure")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest,
-       EnumValuesInCamelCaseRemoveDashAndUnderscoreAreAccepted) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_type(proto_util_converter::testing::Book::ACTION_AND_ADVENTURE);
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  options_.use_lower_camel_for_enums = true;
-  options_.case_insensitive_enum_parsing = false;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "action-And_Adventure")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest,
-       EnumValuesInCamelCaseWithNameNotUppercaseAreAccepted) {
-  Book book;
-  book.set_title("Some Book");
-  book.set_type(proto_util_converter::testing::Book::arts_and_photography);
-  Author* robert = book.mutable_author();
-  robert->set_name("robert");
-
-  options_.use_lower_camel_for_enums = true;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->RenderString("title", "Some Book")
-      ->RenderString("type", "artsAndPhotography")
-      ->StartObject("author")
-      ->RenderString("name", "robert")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(book);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, PrimitiveFromStringConversion) {
-  Primitive full;
-  full.set_fix32(101);
-  full.set_u32(102);
-  full.set_i32(-103);
-  full.set_sf32(-104);
-  full.set_s32(-105);
-  full.set_fix64(40000000001L);
-  full.set_u64(40000000002L);
-  full.set_i64(-40000000003L);
-  full.set_sf64(-40000000004L);
-  full.set_s64(-40000000005L);
-  full.set_str("string1");
-  full.set_bytes("Some Bytes");
-  full.set_float_(3.14f);
-  full.set_double_(-4.05L);
-  full.set_bool_(true);
-  full.add_rep_fix32(201);
-  full.add_rep_u32(202);
-  full.add_rep_i32(-203);
-  full.add_rep_sf32(-204);
-  full.add_rep_s32(-205);
-  full.add_rep_fix64(80000000001L);
-  full.add_rep_u64(80000000002L);
-  full.add_rep_i64(-80000000003L);
-  full.add_rep_sf64(-80000000004L);
-  full.add_rep_s64(-80000000005L);
-  full.add_rep_str("string2");
-  full.add_rep_bytes("More Bytes");
-  full.add_rep_float(6.14f);
-  full.add_rep_double(-8.05L);
-  full.add_rep_bool(false);
-
-  ResetTypeInfo(Primitive::descriptor());
-
-  ow_->StartObject("")
-      ->RenderString("fix32", "101")
-      ->RenderString("u32", "102")
-      ->RenderString("i32", "-103")
-      ->RenderString("sf32", "-104")
-      ->RenderString("s32", "-105")
-      ->RenderString("fix64", "40000000001")
-      ->RenderString("u64", "40000000002")
-      ->RenderString("i64", "-40000000003")
-      ->RenderString("sf64", "-40000000004")
-      ->RenderString("s64", "-40000000005")
-      ->RenderString("str", "string1")
-      ->RenderString("bytes", "U29tZSBCeXRlcw==")  // "Some Bytes"
-      ->RenderString("float", "3.14")
-      ->RenderString("double", "-4.05")
-      ->RenderString("bool", "true")
-      ->StartList("rep_fix32")
-      ->RenderString("", "201")
-      ->EndList()
-      ->StartList("rep_u32")
-      ->RenderString("", "202")
-      ->EndList()
-      ->StartList("rep_i32")
-      ->RenderString("", "-203")
-      ->EndList()
-      ->StartList("rep_sf32")
-      ->RenderString("", "-204")
-      ->EndList()
-      ->StartList("rep_s32")
-      ->RenderString("", "-205")
-      ->EndList()
-      ->StartList("rep_fix64")
-      ->RenderString("", "80000000001")
-      ->EndList()
-      ->StartList("rep_u64")
-      ->RenderString("", "80000000002")
-      ->EndList()
-      ->StartList("rep_i64")
-      ->RenderString("", "-80000000003")
-      ->EndList()
-      ->StartList("rep_sf64")
-      ->RenderString("", "-80000000004")
-      ->EndList()
-      ->StartList("rep_s64")
-      ->RenderString("", "-80000000005")
-      ->EndList()
-      ->StartList("rep_str")
-      ->RenderString("", "string2")
-      ->EndList()
-      ->StartList("rep_bytes")
-      ->RenderString("", "TW9yZSBCeXRlcw==")  // "More Bytes"
-      ->EndList()
-      ->StartList("rep_float")
-      ->RenderString("", "6.14")
-      ->EndList()
-      ->StartList("rep_double")
-      ->RenderString("", "-8.05")
-      ->EndList()
-      ->StartList("rep_bool")
-      ->RenderString("", "false")
-      ->EndList()
-      ->EndObject();
-  CheckOutput(full);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, InfinityInputTest) {
-  Primitive full;
-  full.set_double_(std::numeric_limits<double>::infinity());
-  full.set_float_(std::numeric_limits<float>::infinity());
-  full.set_str("-Infinity");
-
-  ResetTypeInfo(Primitive::descriptor());
-
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
-                                      StringPiece("\"Infinity\"")))
-      .With(Args<0>(HasObjectLocation("i32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"Infinity\"")))
-      .With(Args<0>(HasObjectLocation("u32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
-                                      StringPiece("\"-Infinity\"")))
-      .With(Args<0>(HasObjectLocation("sf64")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
-                                      StringPiece("\"Infinity\"")))
-      .With(Args<0>(HasObjectLocation("bool")));
-
-  ow_->StartObject("")
-      ->RenderString("double", "Infinity")
-      ->RenderString("float", "Infinity")
-      ->RenderString("i32", "Infinity")
-      ->RenderString("u32", "Infinity")
-      ->RenderString("sf64", "-Infinity")
-      ->RenderString("str", "-Infinity")
-      ->RenderString("bool", "Infinity")
-      ->EndObject();
-  CheckOutput(full);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, NaNInputTest) {
-  Primitive full;
-  full.set_double_(std::numeric_limits<double>::quiet_NaN());
-  full.set_float_(std::numeric_limits<float>::quiet_NaN());
-  full.set_str("NaN");
-
-  ResetTypeInfo(Primitive::descriptor());
-
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT32"),
-                                      StringPiece("\"NaN\"")))
-      .With(Args<0>(HasObjectLocation("i32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"NaN\"")))
-      .With(Args<0>(HasObjectLocation("u32")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_SFIXED64"),
-                                      StringPiece("\"NaN\"")))
-      .With(Args<0>(HasObjectLocation("sf64")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_BOOL"),
-                                      StringPiece("\"NaN\"")))
-      .With(Args<0>(HasObjectLocation("bool")));
-
-  ow_->StartObject("")
-      ->RenderString("double", "NaN")
-      ->RenderString("float", "NaN")
-      ->RenderString("i32", "NaN")
-      ->RenderString("u32", "NaN")
-      ->RenderString("sf64", "NaN")
-      ->RenderString("str", "NaN")
-      ->RenderString("bool", "NaN")
-      ->EndObject();
-
-  CheckOutput(full);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, ImplicitPrimitiveList) {
-  Book expected;
-  Author* author = expected.mutable_author();
-  author->set_name("The Author");
-  author->add_pseudonym("first");
-  author->add_pseudonym("second");
-
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "The Author")
-      ->RenderString("pseudonym", "first")
-      ->RenderString("pseudonym", "second")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest,
-       LastWriteWinsOnNonRepeatedPrimitiveFieldWithDuplicates) {
-  Book expected;
-  Author* author = expected.mutable_author();
-  author->set_name("second");
-
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "first")
-      ->RenderString("name", "second")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, ExplicitPrimitiveList) {
-  Book expected;
-  Author* author = expected.mutable_author();
-  author->set_name("The Author");
-  author->add_pseudonym("first");
-  author->add_pseudonym("second");
-
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "The Author")
-      ->StartList("pseudonym")
-      ->RenderString("", "first")
-      ->RenderString("", "second")
-      ->EndList()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitPrimitiveList) {
-  Book expected;
-  expected.set_allocated_author(new Author());
-
-  EXPECT_CALL(
-      listener_,
-      InvalidName(_, StringPiece("name"),
-                  StringPiece(
-                      "Proto field is not repeating, cannot start list.")))
-      .With(Args<0>(HasObjectLocation("author")));
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->StartList("name")
-      ->RenderString("", "first")
-      ->RenderString("", "second")
-      ->EndList()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, ImplicitMessageList) {
-  Book expected;
-  Author* outer = expected.mutable_author();
-  outer->set_name("outer");
-  outer->set_alive(true);
-  Author* first = outer->add_friend_();
-  first->set_name("first");
-  Author* second = outer->add_friend_();
-  second->set_name("second");
-
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "outer")
-      ->RenderBool("alive", true)
-      ->StartObject("friend")
-      ->RenderString("name", "first")
-      ->EndObject()
-      ->StartObject("friend")
-      ->RenderString("name", "second")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  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;
-  Author* author = expected.mutable_author();
-  author->set_name("The Author");
-  Publisher* publisher = expected.mutable_publisher();
-  publisher->set_name("second");
-
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "The Author")
-      ->EndObject()
-      ->StartObject("publisher")
-      ->RenderString("name", "first")
-      ->EndObject()
-      ->StartObject("publisher")
-      ->RenderString("name", "second")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, ExplicitMessageList) {
-  Book expected;
-  Author* outer = expected.mutable_author();
-  outer->set_name("outer");
-  outer->set_alive(true);
-  Author* first = outer->add_friend_();
-  first->set_name("first");
-  Author* second = outer->add_friend_();
-  second->set_name("second");
-
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "outer")
-      ->RenderBool("alive", true)
-      ->StartList("friend")
-      ->StartObject("")
-      ->RenderString("name", "first")
-      ->EndObject()
-      ->StartObject("")
-      ->RenderString("name", "second")
-      ->EndObject()
-      ->EndList()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, NonRepeatedExplicitMessageList) {
-  Book expected;
-  Author* author = expected.mutable_author();
-  author->set_name("The Author");
-
-  EXPECT_CALL(
-      listener_,
-      InvalidName(_, StringPiece("publisher"),
-                  StringPiece(
-                      "Proto field is not repeating, cannot start list.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "The Author")
-      ->EndObject()
-      ->StartList("publisher")
-      ->StartObject("")
-      ->RenderString("name", "first")
-      ->EndObject()
-      ->StartObject("")
-      ->RenderString("name", "second")
-      ->EndObject()
-      ->EndList()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtRoot) {
-  Book empty;
-
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnknownFieldAtAuthorFriend) {
-  Book expected;
-  Author* paul = expected.mutable_author();
-  paul->set_name("Paul");
-  Author* mark = paul->add_friend_();
-  mark->set_name("Mark");
-  Author* john = paul->add_friend_();
-  john->set_name("John");
-  Author* luke = paul->add_friend_();
-  luke->set_name("Luke");
-
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("address"),
-                                     StringPiece("Cannot find field.")))
-      .With(Args<0>(HasObjectLocation("author.friend[1]")));
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "Paul")
-      ->StartList("friend")
-      ->StartObject("")
-      ->RenderString("name", "Mark")
-      ->EndObject()
-      ->StartObject("")
-      ->RenderString("name", "John")
-      ->RenderString("address", "Patmos")
-      ->EndObject()
-      ->StartObject("")
-      ->RenderString("name", "Luke")
-      ->EndObject()
-      ->EndList()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtRoot) {
-  Book empty;
-
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnknownObjectAtAuthor) {
-  Book expected;
-  Author* author = expected.mutable_author();
-  author->set_name("William");
-  author->add_pseudonym("Bill");
-
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("wife"),
-                                     StringPiece("Cannot find field.")))
-      .With(Args<0>(HasObjectLocation("author")));
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "William")
-      ->StartObject("wife")
-      ->RenderString("name", "Hilary")
-      ->EndObject()
-      ->RenderString("pseudonym", "Bill")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnknownListAtRoot) {
-  Book empty;
-
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("")->StartList("unknown")->EndList()->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnknownListAtPublisher) {
-  Book expected;
-  expected.set_title("Brainwashing");
-  Publisher* publisher = expected.mutable_publisher();
-  publisher->set_name("propaganda");
-
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("alliance"),
-                                     StringPiece("Cannot find field.")))
-      .With(Args<0>(HasObjectLocation("publisher")));
-  ow_->StartObject("")
-      ->StartObject("publisher")
-      ->RenderString("name", "propaganda")
-      ->StartList("alliance")
-      ->EndList()
-      ->EndObject()
-      ->RenderString("title", "Brainwashing")
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtRoot) {
-  Book empty;
-
-  options_.ignore_unknown_fields = true;
-  ResetProtoWriter();
-
-  EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderString("unknown", "Nope!")->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownFieldAtAuthorFriend) {
-  Book expected;
-  Author* paul = expected.mutable_author();
-  paul->set_name("Paul");
-  Author* mark = paul->add_friend_();
-  mark->set_name("Mark");
-  Author* john = paul->add_friend_();
-  john->set_name("John");
-  Author* luke = paul->add_friend_();
-  luke->set_name("Luke");
-
-  options_.ignore_unknown_fields = true;
-  ResetProtoWriter();
-
-  EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "Paul")
-      ->StartList("friend")
-      ->StartObject("")
-      ->RenderString("name", "Mark")
-      ->EndObject()
-      ->StartObject("")
-      ->RenderString("name", "John")
-      ->RenderString("address", "Patmos")
-      ->EndObject()
-      ->StartObject("")
-      ->RenderString("name", "Luke")
-      ->EndObject()
-      ->EndList()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtRoot) {
-  Book empty;
-
-  options_.ignore_unknown_fields = true;
-  ResetProtoWriter();
-
-  EXPECT_CALL(listener_, InvalidName(_, StringPiece("unknown"),
-                                     StringPiece("Cannot find field.")))
-      .Times(0);
-  ow_->StartObject("")->StartObject("unknown")->EndObject()->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownObjectAtAuthor) {
-  Book expected;
-  Author* author = expected.mutable_author();
-  author->set_name("William");
-  author->add_pseudonym("Bill");
-
-  options_.ignore_unknown_fields = true;
-  ResetProtoWriter();
-
-  EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderString("name", "William")
-      ->StartObject("wife")
-      ->RenderString("name", "Hilary")
-      ->EndObject()
-      ->RenderString("pseudonym", "Bill")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtRoot) {
-  Book empty;
-
-  options_.ignore_unknown_fields = true;
-  ResetProtoWriter();
-
-  EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
-  ow_->StartObject("")->StartList("unknown")->EndList()->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, IgnoreUnknownListAtPublisher) {
-  Book expected;
-  expected.set_title("Brainwashing");
-  Publisher* publisher = expected.mutable_publisher();
-  publisher->set_name("propaganda");
-
-  options_.ignore_unknown_fields = true;
-  ResetProtoWriter();
-
-  EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("publisher")
-      ->RenderString("name", "propaganda")
-      ->StartList("alliance")
-      ->EndList()
-      ->EndObject()
-      ->RenderString("title", "Brainwashing")
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest,
-       IgnoreUnknownFieldsDontIgnoreUnknownEnumValues) {
-  ResetTypeInfo(Proto3Message::descriptor());
-
-  Proto3Message expected;
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(_,
-                   StringPiece(
-                       "type.googleapis.com/"
-                       "proto_util_converter.testing.Proto3Message.NestedEnum"),
-                   StringPiece("\"someunknownvalueyouwillneverknow\"")))
-      .With(Args<0>(HasObjectLocation("enum_value")));
-  ow_->StartObject("")
-      ->RenderString("enumValue", "someunknownvalueyouwillneverknow")
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, AcceptUnknownEnumValue) {
-  ResetTypeInfo(Proto3Message::descriptor());
-
-  Proto3Message expected;
-  expected.set_enum_value(static_cast<Proto3Message::NestedEnum>(12345));
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderInt32("enumValue", 12345)->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, MissingRequiredField) {
-  Book expected;
-  expected.set_title("My Title");
-  expected.set_allocated_publisher(new Publisher());
-
-  EXPECT_CALL(listener_, MissingField(_, StringPiece("name")))
-      .With(Args<0>(HasObjectLocation("publisher")));
-  ow_->StartObject("")
-      ->StartObject("publisher")
-      ->EndObject()
-      ->RenderString("title", "My Title")
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, InvalidFieldValueAtRoot) {
-  Book empty;
-
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"garbage\"")))
-      .With(Args<0>(HasObjectLocation("length")));
-  ow_->StartObject("")->RenderString("length", "garbage")->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, MultipleInvalidFieldValues) {
-  Book expected;
-  expected.set_title("My Title");
-
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_UINT32"),
-                                      StringPiece("\"-400\"")))
-      .With(Args<0>(HasObjectLocation("length")));
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("TYPE_INT64"),
-                                      StringPiece("\"3.14\"")))
-      .With(Args<0>(HasObjectLocation("published")));
-  ow_->StartObject("")
-      ->RenderString("length", "-400")
-      ->RenderString("published", "3.14")
-      ->RenderString("title", "My Title")
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtRoot) {
-  Book empty;
-
-  EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("")->RenderFloat("", 3.14)->EndObject();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnnamedFieldAtAuthor) {
-  Book expected;
-  expected.set_title("noname");
-  expected.set_allocated_author(new Author());
-
-  EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
-      .With(Args<0>(HasObjectLocation("author")));
-  ow_->StartObject("")
-      ->StartObject("author")
-      ->RenderInt32("", 123)
-      ->EndObject()
-      ->RenderString("title", "noname")
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, UnnamedListAtRoot) {
-  Book expected;
-  expected.set_title("noname");
-
-  EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("")
-      ->StartList("")
-      ->EndList()
-      ->RenderString("title", "noname")
-      ->EndObject();
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, RootNamedObject) {
-  Book expected;
-  expected.set_title("Annie");
-
-  EXPECT_CALL(
-      listener_,
-      InvalidName(_, StringPiece("oops"),
-                  StringPiece("Root element should not be named.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("oops")->RenderString("title", "Annie")->EndObject();
-  CheckOutput(expected, 7);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, RootNamedList) {
-  Book empty;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidName(_, StringPiece("oops"),
-                  StringPiece("Root element should not be named.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartList("oops")->RenderString("", "item")->EndList();
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, RootUnnamedField) {
-  Book empty;
-
-  EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Root element must be a message.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->RenderBool("", true);
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, RootNamedField) {
-  Book empty;
-
-  EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece("oops"),
-                          StringPiece("Root element must be a message.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->RenderBool("oops", true);
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, NullValue) {
-  Book empty;
-
-  ow_->RenderNull("");
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, NullValueForMessageField) {
-  Book empty;
-
-  ow_->RenderNull("author");
-  CheckOutput(empty, 0);
-}
-
-TEST_P(ProtoStreamObjectWriterTest, NullValueForPrimitiveField) {
-  Book empty;
-
-  ow_->RenderNull("length");
-  CheckOutput(empty, 0);
-}
-
-class ProtoStreamObjectWriterTimestampDurationTest
-    : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterTimestampDurationTest() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(TimestampDuration::descriptor());
-    descriptors.push_back(google::protobuf::Timestamp::descriptor());
-    descriptors.push_back(google::protobuf::Duration::descriptor());
-    ResetTypeInfo(descriptors);
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterTimestampDurationTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseTimestamp) {
-  TimestampDuration timestamp;
-  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
-  ts->set_seconds(1448249855);
-  ts->set_nanos(33155000);
-
-  ow_->StartObject("")
-      ->RenderString("ts", "2015-11-23T03:37:35.033155Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       ParseTimestampYearNotZeroPadded) {
-  TimestampDuration timestamp;
-  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
-  ts->set_seconds(-61665654145);
-  ts->set_nanos(33155000);
-
-  ow_->StartObject("")
-      ->RenderString("ts", "15-11-23T03:37:35.033155Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       ParseTimestampYearZeroPadded) {
-  TimestampDuration timestamp;
-  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
-  ts->set_seconds(-61665654145);
-  ts->set_nanos(33155000);
-
-  ow_->StartObject("")
-      ->RenderString("ts", "0015-11-23T03:37:35.033155Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       ParseTimestampWithPositiveOffset) {
-  TimestampDuration timestamp;
-  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
-  ts->set_seconds(1448249855);
-  ts->set_nanos(33155000);
-
-  ow_->StartObject("")
-      ->RenderString("ts", "2015-11-23T11:47:35.033155+08:10")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       ParseTimestampWithNegativeOffset) {
-  TimestampDuration timestamp;
-  google::protobuf::Timestamp* ts = timestamp.mutable_ts();
-  ts->set_seconds(1448249855);
-  ts->set_nanos(33155000);
-
-  ow_->StartObject("")
-      ->RenderString("ts", "2015-11-22T19:47:35.033155-07:50")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       TimestampWithInvalidOffset1) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+")));
-
-  ow_->StartObject("")->RenderString("ts", "2016-03-07T15:14:23+")->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       TimestampWithInvalidOffset2) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+08-10")));
-
-  ow_->StartObject("")
-      ->RenderString("ts", "2016-03-07T15:14:23+08-10")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       TimestampWithInvalidOffset3) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+24:10")));
-
-  ow_->StartObject("")
-      ->RenderString("ts", "2016-03-07T15:14:23+24:10")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       TimestampWithInvalidOffset4) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2016-03-07T15:14:23+04:60")));
-
-  ow_->StartObject("")
-      ->RenderString("ts", "2016-03-07T15:14:23+04:60")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError1) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: ")));
-
-  ow_->StartObject("")->RenderString("ts", "")->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError2) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: Z")));
-
-  ow_->StartObject("")->RenderString("ts", "Z")->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError3) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "1970-01-01T00:00:00.ABZ")));
-
-  ow_->StartObject("")
-      ->RenderString("ts", "1970-01-01T00:00:00.ABZ")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError4) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "-8031-10-18T00:00:00.000Z")));
-
-  ow_->StartObject("")
-      ->RenderString("ts", "-8031-10-18T00:00:00.000Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError5) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2015-11-23T03:37:35.033155   Z")));
-
-  ow_->StartObject("")
-      // Whitespace in the Timestamp nanos is not allowed.
-      ->RenderString("ts", "2015-11-23T03:37:35.033155   Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError6) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2015-11-23T03:37:35.033155 1234Z")));
-
-  ow_->StartObject("")
-      // Whitespace in the Timestamp nanos is not allowed.
-      ->RenderString("ts", "2015-11-23T03:37:35.033155 1234Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError7) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "2015-11-23T03:37:35.033abc155Z")));
-
-  ow_->StartObject("")
-      // Non-numeric characters in the Timestamp nanos is not allowed.
-      ->RenderString("ts", "2015-11-23T03:37:35.033abc155Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidTimestampError8) {
-  TimestampDuration timestamp;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece("Field 'ts', Invalid time format: "
-                      "0-12-31T23:59:59.000Z")));
-
-  ow_->StartObject("")
-      ->RenderString("ts", "0-12-31T23:59:59.000Z")
-      ->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, ParseDuration) {
-  TimestampDuration duration;
-  google::protobuf::Duration* dur = duration.mutable_dur();
-  dur->set_seconds(1448216930);
-  dur->set_nanos(132262000);
-
-  ow_->StartObject("")->RenderString("dur", "1448216930.132262s")->EndObject();
-  CheckOutput(duration);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError1) {
-  TimestampDuration duration;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece(
-              "Field 'dur', Illegal duration format; duration must "
-              "end with 's'")));
-
-  ow_->StartObject("")->RenderString("dur", "")->EndObject();
-  CheckOutput(duration);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError2) {
-  TimestampDuration duration;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece(
-              "Field 'dur', Invalid duration format, failed to parse "
-              "seconds")));
-
-  ow_->StartObject("")->RenderString("dur", "s")->EndObject();
-  CheckOutput(duration);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError3) {
-  TimestampDuration duration;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece("Field 'dur', Invalid duration format, failed to "
-                            "parse nano seconds")));
-
-  ow_->StartObject("")->RenderString("dur", "123.DEFs")->EndObject();
-  CheckOutput(duration);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError4) {
-  TimestampDuration duration;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece("Field 'dur', Duration value exceeds limits")));
-
-  ow_->StartObject("")->RenderString("dur", "315576000002s")->EndObject();
-  CheckOutput(duration);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, InvalidDurationError5) {
-  TimestampDuration duration;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece("Field 'dur', Duration value exceeds limits")));
-
-  ow_->StartObject("")->RenderString("dur", "0.1000000001s")->EndObject();
-  CheckOutput(duration);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       MismatchedTimestampTypeInput) {
-  TimestampDuration timestamp;
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Timestamp"),
-          StringPiece(
-              "Field 'ts', Invalid data type for timestamp, value is 1")))
-      .With(Args<0>(HasObjectLocation("ts")));
-  ow_->StartObject("")->RenderInt32("ts", 1)->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest,
-       MismatchedDurationTypeInput) {
-  TimestampDuration duration;
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Duration"),
-          StringPiece(
-              "Field 'dur', Invalid data type for duration, value is 1")))
-      .With(Args<0>(HasObjectLocation("dur")));
-  ow_->StartObject("")->RenderInt32("dur", 1)->EndObject();
-  CheckOutput(duration);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, TimestampAcceptsNull) {
-  TimestampDuration timestamp;
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderNull("ts")->EndObject();
-  CheckOutput(timestamp);
-}
-
-TEST_P(ProtoStreamObjectWriterTimestampDurationTest, DurationAcceptsNull) {
-  TimestampDuration duration;
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderNull("dur")->EndObject();
-  CheckOutput(duration);
-}
-
-class ProtoStreamObjectWriterStructTest
-    : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterStructTest() { ResetProtoWriter(); }
-
-  // Resets ProtoWriter with current set of options and other state.
-  void ResetProtoWriter() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(StructType::descriptor());
-    descriptors.push_back(google::protobuf::Struct::descriptor());
-    ResetTypeInfo(descriptors);
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterStructTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-// TODO(skarvaje): Write tests for failure cases.
-TEST_P(ProtoStreamObjectWriterStructTest, StructRenderSuccess) {
-  StructType struct_type;
-  google::protobuf::Struct* s = struct_type.mutable_object();
-  s->mutable_fields()->operator[]("k1").set_number_value(123);
-  s->mutable_fields()->operator[]("k2").set_bool_value(true);
-
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->RenderDouble("k1", 123)
-      ->RenderBool("k2", true)
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, StructNullInputSuccess) {
-  StructType struct_type;
-  EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece(""),
-                          StringPiece("Proto fields must have a name.")))
-      .With(Args<0>(HasObjectLocation("")));
-  ow_->StartObject("")->RenderNull("")->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, StructInvalidInputFailure) {
-  StructType struct_type;
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.Struct"),
-          StringPiece("true")))
-      .With(Args<0>(HasObjectLocation("object")));
-
-  ow_->StartObject("")->RenderBool("object", true)->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, StructAcceptsNull) {
-  StructType struct_type;
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-
-  ow_->StartObject("")->RenderNull("object")->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, StructValuePreservesNull) {
-  StructType struct_type;
-  (*struct_type.mutable_object()->mutable_fields())["key"].set_null_value(
-      google::protobuf::NULL_VALUE);
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->RenderNull("key")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, SimpleRepeatedStructMapKeyTest) {
-  EXPECT_CALL(listener_,
-              InvalidName(_, StringPiece("gBike"),
-                          StringPiece(
-                              "Repeated map key: 'gBike' is already set.")));
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->RenderString("gBike", "v1")
-      ->RenderString("gBike", "v2")
-      ->EndObject()
-      ->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapListKeyTest) {
-  EXPECT_CALL(
-      listener_,
-      InvalidName(_, StringPiece("k1"),
-                  StringPiece("Repeated map key: 'k1' is already set.")));
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->RenderString("k1", "v1")
-      ->StartList("k1")
-      ->RenderString("", "v2")
-      ->EndList()
-      ->EndObject()
-      ->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, RepeatedStructMapObjectKeyTest) {
-  EXPECT_CALL(
-      listener_,
-      InvalidName(_, StringPiece("k1"),
-                  StringPiece("Repeated map key: 'k1' is already set.")));
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->StartObject("k1")
-      ->RenderString("sub_k1", "v1")
-      ->EndObject()
-      ->StartObject("k1")
-      ->RenderString("sub_k2", "v2")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, OptionStructIntAsStringsTest) {
-  StructType struct_type;
-  google::protobuf::Struct* s = struct_type.mutable_object();
-  s->mutable_fields()->operator[]("k1").set_string_value("123");
-  s->mutable_fields()->operator[]("k2").set_bool_value(true);
-  s->mutable_fields()->operator[]("k3").set_string_value("-222222222");
-  s->mutable_fields()->operator[]("k4").set_string_value("33333333");
-
-  options_.struct_integers_as_strings = true;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->RenderDouble("k1", 123)
-      ->RenderBool("k2", true)
-      ->RenderInt64("k3", -222222222)
-      ->RenderUint64("k4", 33333333)
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, Struct32BitIntsAndFloatsTest) {
-  StructType struct_type;
-  google::protobuf::Struct* s = struct_type.mutable_object();
-  s->mutable_fields()->operator[]("k1").set_number_value(1.5);
-  s->mutable_fields()->operator[]("k2").set_number_value(100);
-  s->mutable_fields()->operator[]("k3").set_number_value(100);
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->RenderFloat("k1", 1.5)
-      ->RenderInt32("k2", 100)
-      ->RenderUint32("k3", 100)
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest,
-       Struct32BitIntsAndFloatsAsStringsTest) {
-  StructType struct_type;
-  google::protobuf::Struct* s = struct_type.mutable_object();
-  s->mutable_fields()->operator[]("k1").set_string_value("1.5");
-  s->mutable_fields()->operator[]("k2").set_string_value("100");
-  s->mutable_fields()->operator[]("k3").set_string_value("100");
-
-  options_.struct_integers_as_strings = true;
-  ResetProtoWriter();
-
-  ow_->StartObject("")
-      ->StartObject("object")
-      ->RenderFloat("k1", 1.5)
-      ->RenderInt32("k2", 100)
-      ->RenderUint32("k3", 100)
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(struct_type);
-}
-
-TEST_P(ProtoStreamObjectWriterStructTest, ValuePreservesNull) {
-  ValueWrapper value;
-  value.mutable_value()->set_null_value(google::protobuf::NULL_VALUE);
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderNull("value")->EndObject();
-  CheckOutput(value);
-}
-
-class ProtoStreamObjectWriterMapTest : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterMapTest() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(MapIn::descriptor());
-    descriptors.push_back(google::protobuf::DoubleValue::descriptor());
-    ResetTypeInfo(descriptors);
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterMapTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtoStreamObjectWriterMapTest, MapShouldNotAcceptList) {
-  MapIn mm;
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(_, StringPiece("Map"),
-                   StringPiece(
-                       "Cannot bind a list to map for field 'map_input'.")));
-  ow_->StartObject("")
-      ->StartList("map_input")
-      ->RenderString("a", "b")
-      ->EndList()
-      ->EndObject();
-  CheckOutput(mm);
-}
-
-TEST_P(ProtoStreamObjectWriterMapTest, MapAcceptsNullValue) {
-  // Null should not be a valid map value.
-  // See http://go/proto3-json-spec#heading=h.r2ddatp7y4vi
-  // This test is added for backward compatibility.
-  MapIn mm;
-  (*mm.mutable_map_input())["a"] = "b";
-  (*mm.mutable_map_input())["x"] = "";
-  ow_->StartObject("")
-      ->StartObject("map_input")
-      ->RenderString("a", "b")
-      ->RenderNull("x")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(mm);
-}
-
-TEST_P(ProtoStreamObjectWriterMapTest, MapShouldIgnoreNullValueEntry) {
-  options_.ignore_null_value_map_entry = true;
-  ResetTypeInfo(MapIn::descriptor());
-  MapIn mm;
-  (*mm.mutable_map_input())["a"] = "b";
-  ow_->StartObject("")
-      ->StartObject("map_input")
-      ->RenderString("a", "b")
-      ->RenderNull("x")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(mm);
-}
-
-TEST_P(ProtoStreamObjectWriterMapTest, RepeatedMapKeyTest) {
-  EXPECT_CALL(
-      listener_,
-      InvalidName(_, StringPiece("k1"),
-                  StringPiece("Repeated map key: 'k1' is already set.")));
-  ow_->StartObject("")
-      ->RenderString("other", "test")
-      ->StartObject("map_input")
-      ->RenderString("k1", "v1")
-      ->RenderString("k1", "v2")
-      ->EndObject()
-      ->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterMapTest, AnyInMap) {
-  MapIn mm;
-  google::protobuf::DoubleValue d;
-  d.set_value(40.2);
-  (*mm.mutable_map_any())["foo"].PackFrom(d);
-  ow_->StartObject("")
-      ->StartObject("map_any")
-      ->StartObject("foo")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue")
-      ->RenderDouble("value", 40.2)
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(mm);
-}
-
-class ProtoStreamObjectWriterAnyTest : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterAnyTest() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(AnyOut::descriptor());
-    descriptors.push_back(Book::descriptor());
-    descriptors.push_back(google::protobuf::Any::descriptor());
-    descriptors.push_back(google::protobuf::DoubleValue::descriptor());
-    descriptors.push_back(google::protobuf::FieldMask::descriptor());
-    descriptors.push_back(google::protobuf::Int32Value::descriptor());
-    descriptors.push_back(google::protobuf::Struct::descriptor());
-    descriptors.push_back(google::protobuf::Timestamp::descriptor());
-    descriptors.push_back(google::protobuf::Value::descriptor());
-    ResetTypeInfo(descriptors);
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterAnyTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyRenderSuccess) {
-  AnyOut any;
-  google::protobuf::Any* any_type = any.mutable_any();
-  any_type->set_type_url("type.googleapis.com/google.protobuf.DoubleValue");
-  google::protobuf::DoubleValue d;
-  d.set_value(40.2);
-  any_type->set_value(d.SerializeAsString());
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.DoubleValue")
-      ->RenderDouble("value", 40.2)
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, RecursiveAny) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-  any->set_type_url("type.googleapis.com/google.protobuf.Any");
-
-  ::google::protobuf::Any nested_any;
-  nested_any.set_type_url(
-      "type.googleapis.com/proto_util_converter.testing.AnyM");
-
-  AnyM m;
-  m.set_foo("foovalue");
-  nested_any.set_value(m.SerializeAsString());
-
-  any->set_value(nested_any.SerializeAsString());
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->StartObject("value")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.AnyM")
-      ->RenderString("foo", "foovalue")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out, 112);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, DoubleRecursiveAny) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-  any->set_type_url("type.googleapis.com/google.protobuf.Any");
-
-  ::google::protobuf::Any nested_any;
-  nested_any.set_type_url("type.googleapis.com/google.protobuf.Any");
-
-  ::google::protobuf::Any second_nested_any;
-  second_nested_any.set_type_url(
-      "type.googleapis.com/proto_util_converter.testing.AnyM");
-
-  AnyM m;
-  m.set_foo("foovalue");
-  second_nested_any.set_value(m.SerializeAsString());
-
-  nested_any.set_value(second_nested_any.SerializeAsString());
-  any->set_value(nested_any.SerializeAsString());
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->StartObject("value")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->StartObject("value")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.AnyM")
-      ->RenderString("foo", "foovalue")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out, 156);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, TypeUrlAtEnd) {
-  Book book;
-  book.set_title("C++");
-  book.set_length(1234);
-  book.set_content("Hello World!");
-
-  ::google::protobuf::Any any;
-  any.PackFrom(book);
-
-  ::google::protobuf::Any outer_any;
-  outer_any.PackFrom(any);
-
-  AnyOut out;
-  out.mutable_any()->PackFrom(outer_any);
-
-  // Put the @type field at the end of each Any message. Parsers should
-  // be able to accept that.
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->StartObject("value")
-      ->StartObject("value")
-      ->RenderString("title", "C++")
-      ->RenderInt32("length", 1234)
-      ->RenderBytes("content", "Hello World!")
-      ->RenderString("@type",
-                     "type.googleapis.com/proto_util_converter.testing.Book")
-      ->EndObject()
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->EndObject()
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// Same as TypeUrlAtEnd, but use temporary string values to make sure we don't
-// mistakenly store StringPiece objects pointing to invalid memory.
-TEST_P(ProtoStreamObjectWriterAnyTest, TypeUrlAtEndWithTemporaryStrings) {
-  Book book;
-  book.set_title("C++");
-  book.set_length(1234);
-  book.set_content("Hello World!");
-
-  ::google::protobuf::Any any;
-  any.PackFrom(book);
-
-  ::google::protobuf::Any outer_any;
-  outer_any.PackFrom(any);
-
-  AnyOut out;
-  out.mutable_any()->PackFrom(outer_any);
-
-  std::string name, value;
-  // Put the @type field at the end of each Any message. Parsers should
-  // be able to accept that.
-  ow_->StartObject("")->StartObject("any");
-  {
-    ow_->StartObject("value");
-    {
-      ow_->StartObject("value");
-      {
-        name = "title";
-        value = "C++";
-        ow_->RenderString(name, value);
-        name = "length";
-        ow_->RenderInt32(name, 1234);
-        name = "content";
-        value = "Hello World!";
-        ow_->RenderBytes(name, value);
-        name = "@type";
-        value = "type.googleapis.com/proto_util_converter.testing.Book";
-        ow_->RenderString(name, value);
-      }
-      ow_->EndObject();
-
-      name = "@type";
-      value = "type.googleapis.com/google.protobuf.Any";
-      ow_->RenderString(name, value);
-    }
-    ow_->EndObject();
-
-    name = "@type";
-    value = "type.googleapis.com/google.protobuf.Any";
-    ow_->RenderString(name, value);
-  }
-  ow_->EndObject()->EndObject();
-  CheckOutput(out);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, EmptyAnyFromEmptyObject) {
-  AnyOut out;
-  out.mutable_any();
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-
-  ow_->StartObject("")->StartObject("any")->EndObject()->EndObject();
-
-  CheckOutput(out, 2);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails1) {
-  AnyOut any;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(_, StringPiece("Any"),
-                   StringPiece("Missing @type for any field in "
-                                     "proto_util_converter.testing.AnyOut")));
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->StartObject("another")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails2) {
-  AnyOut any;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(_, StringPiece("Any"),
-                   StringPiece("Missing @type for any field in "
-                                     "proto_util_converter.testing.AnyOut")));
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->StartList("another")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithoutTypeUrlFails3) {
-  AnyOut any;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(_, StringPiece("Any"),
-                   StringPiece("Missing @type for any field in "
-                                     "proto_util_converter.testing.AnyOut")));
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("value", "somevalue")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithInvalidTypeUrlFails) {
-  AnyOut any;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Invalid type URL, type URLs must be of the form "
-                            "'type.googleapis.com/<typename>', got: "
-                            "type.other.com/some.Type")));
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.other.com/some.Type")
-      ->RenderDouble("value", 40.2)
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithUnknownTypeFails) {
-  AnyOut any;
-
-  EXPECT_CALL(listener_,
-              InvalidValue(_, StringPiece("Any"),
-                           StringPiece(
-                               "Invalid type URL, unknown type: some.Type")));
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/some.Type")
-      ->RenderDouble("value", 40.2)
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyIncorrectInputTypeFails) {
-  AnyOut any;
-
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(_,
-                   StringPiece("type.googleapis.com/google.protobuf.Any"),
-                   StringPiece("1")));
-  ow_->StartObject("")->RenderInt32("any", 1)->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyAcceptsNull) {
-  AnyOut any;
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderNull("any")->EndObject();
-  CheckOutput(any);
-}
-
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypeErrorTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("Any"),
-                                      StringPiece("Invalid time format: ")));
-
-  AnyOut any;
-  google::protobuf::Any* any_type = any.mutable_any();
-  any_type->set_type_url("type.googleapis.com/google.protobuf.Timestamp");
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp")
-      ->RenderString("value", "")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Value",
-//     "value": "abc"
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedPrimitiveValue) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  ::google::protobuf::Value value;
-  value.set_string_value("abc");
-  any->PackFrom(value);
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
-      ->RenderString("value", "abc")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Value",
-//     "value": {
-//       "foo": "abc"
-//     }
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedObjectValue) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  ::google::protobuf::Value value;
-  (*value.mutable_struct_value()->mutable_fields())["foo"].set_string_value(
-      "abc");
-  any->PackFrom(value);
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
-      ->StartObject("value")
-      ->RenderString("foo", "abc")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Value",
-//     "value": ["hello"],
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWithNestedArrayValue) {
-  AnyOut out;
-  ::google::protobuf::Any* any = out.mutable_any();
-
-  ::google::protobuf::Value value;
-  value.mutable_list_value()->add_values()->set_string_value("hello");
-  any->PackFrom(value);
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
-      ->StartList("value")
-      ->RenderString("", "hello")
-      ->EndList()
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Value",
-//     "not_value": ""
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest,
-       AnyWellKnownTypesNoValueFieldForPrimitive) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Expect a \"value\" field for well-known types.")));
-  AnyOut any;
-  google::protobuf::Any* any_type = any.mutable_any();
-  any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
-      ->RenderString("not_value", "")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Value",
-//     "not_value": {}
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForObject) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Expect a \"value\" field for well-known types.")));
-  AnyOut any;
-  google::protobuf::Any* any_type = any.mutable_any();
-  any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
-      ->StartObject("not_value")
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Value",
-//     "not_value": [],
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesNoValueFieldForArray) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("Any"),
-          StringPiece("Expect a \"value\" field for well-known types.")));
-  AnyOut any;
-  google::protobuf::Any* any_type = any.mutable_any();
-  any_type->set_type_url("type.googleapis.com/google.protobuf.Value");
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Value")
-      ->StartList("not_value")
-      ->EndList()
-      ->EndObject()
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Struct",
-//     "value": "",
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForStruct) {
-  EXPECT_CALL(listener_,
-              InvalidValue(_, StringPiece("Any"),
-                           StringPiece("Expect a JSON object.")));
-  AnyOut any;
-  google::protobuf::Any* any_type = any.mutable_any();
-  any_type->set_type_url("type.googleapis.com/google.protobuf.Struct");
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Struct")
-      ->RenderString("value", "")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-// Test the following case:
-//
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Any",
-//     "value": "",
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyWellKnownTypesExpectObjectForAny) {
-  EXPECT_CALL(listener_,
-              InvalidValue(_, StringPiece("Any"),
-                           StringPiece("Expect a JSON object.")));
-  AnyOut any;
-  google::protobuf::Any* any_type = any.mutable_any();
-  any_type->set_type_url("type.googleapis.com/google.protobuf.Any");
-
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->RenderString("value", "")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(any);
-}
-
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Any",
-//     "value": null
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, AnyInAnyAcceptsNull) {
-  AnyOut out;
-  google::protobuf::Any empty;
-  out.mutable_any()->PackFrom(empty);
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Any")
-      ->RenderNull("value")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Timestamp",
-//     "value": null
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, TimestampInAnyAcceptsNull) {
-  AnyOut out;
-  google::protobuf::Timestamp empty;
-  out.mutable_any()->PackFrom(empty);
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Timestamp")
-      ->RenderNull("value")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Duration",
-//     "value": null
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, DurationInAnyAcceptsNull) {
-  AnyOut out;
-  google::protobuf::Duration empty;
-  out.mutable_any()->PackFrom(empty);
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Duration")
-      ->RenderNull("value")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.FieldMask",
-//     "value": null
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, FieldMaskInAnyAcceptsNull) {
-  AnyOut out;
-  google::protobuf::FieldMask empty;
-  out.mutable_any()->PackFrom(empty);
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.FieldMask")
-      ->RenderNull("value")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-// {
-//   "any": {
-//     "@type": "type.googleapis.com/google.protobuf.Int32Value",
-//     "value": null
-//   }
-// }
-TEST_P(ProtoStreamObjectWriterAnyTest, WrapperInAnyAcceptsNull) {
-  AnyOut out;
-  google::protobuf::Int32Value empty;
-  out.mutable_any()->PackFrom(empty);
-
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")
-      ->StartObject("any")
-      ->RenderString("@type", "type.googleapis.com/google.protobuf.Int32Value")
-      ->RenderNull("value")
-      ->EndObject()
-      ->EndObject();
-  CheckOutput(out);
-}
-
-class ProtoStreamObjectWriterFieldMaskTest
-    : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterFieldMaskTest() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(FieldMaskTest::descriptor());
-    descriptors.push_back(google::protobuf::FieldMask::descriptor());
-    ResetTypeInfo(descriptors);
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterFieldMaskTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, SimpleFieldMaskTest) {
-  FieldMaskTest expected;
-  expected.set_id("1");
-  expected.mutable_single_mask()->add_paths("path1");
-
-  ow_->StartObject("");
-  ow_->RenderString("id", "1");
-  ow_->RenderString("single_mask", "path1");
-  ow_->EndObject();
-
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, MultipleMasksInCompactForm) {
-  FieldMaskTest expected;
-  expected.set_id("1");
-  expected.mutable_single_mask()->add_paths("camel_case1");
-  expected.mutable_single_mask()->add_paths("camel_case2");
-  expected.mutable_single_mask()->add_paths("camel_case3");
-
-  ow_->StartObject("");
-  ow_->RenderString("id", "1");
-  ow_->RenderString("single_mask", "camelCase1,camelCase2,camelCase3");
-  ow_->EndObject();
-
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, RepeatedFieldMaskTest) {
-  FieldMaskTest expected;
-  expected.set_id("1");
-  google::protobuf::FieldMask* mask = expected.add_repeated_mask();
-  mask->add_paths("field1");
-  mask->add_paths("field2");
-  expected.add_repeated_mask()->add_paths("field3");
-
-  ow_->StartObject("");
-  ow_->RenderString("id", "1");
-  ow_->StartList("repeated_mask");
-  ow_->RenderString("", "field1,field2");
-  ow_->RenderString("", "field3");
-  ow_->EndList();
-  ow_->EndObject();
-
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, EmptyFieldMaskTest) {
-  FieldMaskTest expected;
-  expected.set_id("1");
-
-  ow_->StartObject("");
-  ow_->RenderString("id", "1");
-  ow_->RenderString("single_mask", "");
-  ow_->EndObject();
-
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, MaskUsingApiaryStyleShouldWork) {
-  FieldMaskTest expected;
-  expected.set_id("1");
-
-  ow_->StartObject("");
-  ow_->RenderString("id", "1");
-  // Case1
-  ow_->RenderString("single_mask",
-                    "outerField(camelCase1,camelCase2,camelCase3)");
-  expected.mutable_single_mask()->add_paths("outer_field.camel_case1");
-  expected.mutable_single_mask()->add_paths("outer_field.camel_case2");
-  expected.mutable_single_mask()->add_paths("outer_field.camel_case3");
-
-  ow_->StartList("repeated_mask");
-
-  ow_->RenderString("", "a(field1,field2)");
-  google::protobuf::FieldMask* mask = expected.add_repeated_mask();
-  mask->add_paths("a.field1");
-  mask->add_paths("a.field2");
-
-  ow_->RenderString("", "a(field3)");
-  mask = expected.add_repeated_mask();
-  mask->add_paths("a.field3");
-
-  ow_->RenderString("", "a()");
-  expected.add_repeated_mask();
-
-  ow_->RenderString("", "a(,)");
-  expected.add_repeated_mask();
-
-  ow_->RenderString("", "a(field1(field2(field3)))");
-  mask = expected.add_repeated_mask();
-  mask->add_paths("a.field1.field2.field3");
-
-  ow_->RenderString("", "a(field1(field2(field3,field4),field5),field6)");
-  mask = expected.add_repeated_mask();
-  mask->add_paths("a.field1.field2.field3");
-  mask->add_paths("a.field1.field2.field4");
-  mask->add_paths("a.field1.field5");
-  mask->add_paths("a.field6");
-
-  ow_->RenderString("", "a(id,field1(id,field2(field3,field4),field5),field6)");
-  mask = expected.add_repeated_mask();
-  mask->add_paths("a.id");
-  mask->add_paths("a.field1.id");
-  mask->add_paths("a.field1.field2.field3");
-  mask->add_paths("a.field1.field2.field4");
-  mask->add_paths("a.field1.field5");
-  mask->add_paths("a.field6");
-
-  ow_->RenderString("", "a(((field3,field4)))");
-  mask = expected.add_repeated_mask();
-  mask->add_paths("a.field3");
-  mask->add_paths("a.field4");
-
-  ow_->EndList();
-  ow_->EndObject();
-
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreCloseThanOpenParentheses) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece("Field 'single_mask', Invalid FieldMask 'a(b,c))'. "
-                            "Cannot find matching '(' for all ')'.")));
-
-  ow_->StartObject("");
-  ow_->RenderString("id", "1");
-  ow_->RenderString("single_mask", "a(b,c))");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, MoreOpenThanCloseParentheses) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece(
-              "Field 'single_mask', Invalid FieldMask 'a(((b,c)'. Cannot "
-              "find matching ')' for all '('.")));
-
-  ow_->StartObject("");
-  ow_->RenderString("id", "1");
-  ow_->RenderString("single_mask", "a(((b,c)");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, PathWithMapKeyShouldWork) {
-  FieldMaskTest expected;
-  expected.mutable_single_mask()->add_paths("path.to.map[\"key1\"]");
-  expected.mutable_single_mask()->add_paths(
-      "path.to.map[\"e\\\"[]][scape\\\"\"]");
-  expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
-
-  ow_->StartObject("");
-  ow_->RenderString("single_mask",
-                    "path.to.map[\"key1\"],path.to.map[\"e\\\"[]][scape\\\"\"],"
-                    "path.to.map[\"key2\"]");
-  ow_->EndObject();
-
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest,
-       MapKeyMustBeAtTheEndOfAPathSegment) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece(
-              "Field 'single_mask', Invalid FieldMask "
-              "'path.to.map[\"key1\"]a,path.to.map[\"key2\"]'. "
-              "Map keys should be at the end of a path segment.")));
-
-  ow_->StartObject("");
-  ow_->RenderString("single_mask",
-                    "path.to.map[\"key1\"]a,path.to.map[\"key2\"]");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustEnd) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece("Field 'single_mask', Invalid FieldMask "
-                            "'path.to.map[\"key1\"'. Map keys should be "
-                            "represented as [\"some_key\"].")));
-
-  ow_->StartObject("");
-  ow_->RenderString("single_mask", "path.to.map[\"key1\"");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyMustBeEscapedCorrectly) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("type.googleapis.com/google.protobuf.FieldMask"),
-          StringPiece("Field 'single_mask', Invalid FieldMask "
-                            "'path.to.map[\"ke\"y1\"]'. Map keys should be "
-                            "represented as [\"some_key\"].")));
-
-  ow_->StartObject("");
-  ow_->RenderString("single_mask", "path.to.map[\"ke\"y1\"]");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, MapKeyCanContainAnyChars) {
-  FieldMaskTest expected;
-  expected.mutable_single_mask()->add_paths(
-      // \xE5\xAD\x99 is the UTF-8 byte sequence for chinese character 孙.
-      // We cannot embed non-ASCII characters in the code directly because
-      // some windows compilers will try to interpret them using the system's
-      // current encoding and end up with invalid UTF-8 byte sequence.
-      "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"]");
-  expected.mutable_single_mask()->add_paths("path.to.map[\"key2\"]");
-
-  ow_->StartObject("");
-  ow_->RenderString(
-      "single_mask",
-      "path.to.map[\"(),[],\\\"'!@#$%^&*123_|War\xE5\xAD\x99,./?><\\\\\"],"
-      "path.to.map[\"key2\"]");
-  ow_->EndObject();
-
-  CheckOutput(expected);
-}
-
-TEST_P(ProtoStreamObjectWriterFieldMaskTest, FieldMaskAcceptsNull) {
-  FieldMaskTest expected;
-  EXPECT_CALL(listener_, InvalidValue(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderNull("single_mask")->EndObject();
-  CheckOutput(expected);
-}
-
-class ProtoStreamObjectWriterWrappersTest
-    : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterWrappersTest() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(Int32Wrapper::descriptor());
-    descriptors.push_back(google::protobuf::Int32Value::descriptor());
-    ResetTypeInfo(descriptors);
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterWrappersTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtoStreamObjectWriterWrappersTest, WrapperAcceptsNull) {
-  Int32Wrapper wrapper;
-  EXPECT_CALL(listener_, InvalidName(_, _, _)).Times(0);
-  ow_->StartObject("")->RenderNull("int32")->EndObject();
-  CheckOutput(wrapper);
-}
-
-class ProtoStreamObjectWriterOneOfsTest
-    : public BaseProtoStreamObjectWriterTest {
- protected:
-  ProtoStreamObjectWriterOneOfsTest() {
-    std::vector<const Descriptor*> descriptors;
-    descriptors.push_back(OneOfsRequest::descriptor());
-    descriptors.push_back(google::protobuf::Struct::descriptor());
-    ResetTypeInfo(descriptors);
-  }
-};
-
-INSTANTIATE_TEST_SUITE_P(DifferentTypeInfoSourceTest,
-                         ProtoStreamObjectWriterOneOfsTest,
-                         ::testing::Values(
-                             testing::USE_TYPE_RESOLVER));
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForPrimitiveTypesTest) {
-  EXPECT_CALL(
-      listener_,
-      InvalidValue(
-          _, StringPiece("oneof"),
-          StringPiece(
-              "oneof field 'data' is already set. Cannot set 'intData'")));
-
-  ow_->StartObject("");
-  ow_->RenderString("strData", "blah");
-  ow_->RenderString("intData", "123");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForMessageTypesPrimitiveFirstTest) {
-  // Test for setting primitive oneof field first and then message field.
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'messageData'")));
-
-  // JSON: { "strData": "blah", "messageData": { "dataValue": 123 } }
-  ow_->StartObject("");
-  ow_->RenderString("strData", "blah");
-  ow_->StartObject("messageData");
-  ow_->RenderInt32("dataValue", 123);
-  ow_->EndObject();
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForMessageTypesMessageFirstTest) {
-  // Test for setting message oneof field first and then primitive field.
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'strData'")));
-
-  // JSON: { "messageData": { "dataValue": 123 }, "strData": "blah" }
-  ow_->StartObject("");
-  ow_->StartObject("messageData");
-  ow_->RenderInt32("dataValue", 123);
-  ow_->EndObject();
-  ow_->RenderString("strData", "blah");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForStructTypesPrimitiveFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'structData'")));
-
-  // JSON: { "strData": "blah", "structData": { "a": "b" } }
-  ow_->StartObject("");
-  ow_->RenderString("strData", "blah");
-  ow_->StartObject("structData");
-  ow_->RenderString("a", "b");
-  ow_->EndObject();
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForStructTypesStructFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'strData'")));
-
-  // JSON: { "structData": { "a": "b" }, "strData": "blah" }
-  ow_->StartObject("");
-  ow_->StartObject("structData");
-  ow_->RenderString("a", "b");
-  ow_->EndObject();
-  ow_->RenderString("strData", "blah");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForStructValueTypesTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'valueData'")));
-
-  // JSON: { "messageData": { "dataValue": 123 }, "valueData": { "a": "b" } }
-  ow_->StartObject("");
-  ow_->StartObject("messageData");
-  ow_->RenderInt32("dataValue", 123);
-  ow_->EndObject();
-  ow_->StartObject("valueData");
-  ow_->RenderString("a", "b");
-  ow_->EndObject();
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForWellKnownTypesPrimitiveFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'tsData'")));
-
-  // JSON: { "intData": 123, "tsData": "1970-01-02T01:00:00.000Z" }
-  ow_->StartObject("");
-  ow_->RenderInt32("intData", 123);
-  ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForWellKnownTypesWktFirstTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'intData'")));
-
-  // JSON: { "tsData": "1970-01-02T01:00:00.000Z", "intData": 123 }
-  ow_->StartObject("");
-  ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
-  ow_->RenderInt32("intData", 123);
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForWellKnownTypesAndMessageTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'messageData'")));
-
-  // JSON: { "tsData": "1970-01-02T01:00:00.000Z",
-  //         "messageData": { "dataValue": 123 } }
-  ow_->StartObject("");
-  ow_->RenderString("tsData", "1970-01-02T01:00:00.000Z");
-  ow_->StartObject("messageData");
-  ow_->RenderInt32("dataValue", 123);
-  ow_->EndObject();
-  ow_->EndObject();
-}
-
-TEST_P(ProtoStreamObjectWriterOneOfsTest,
-       MultipleOneofsFailForOneofWithinAnyTest) {
-  EXPECT_CALL(listener_, InvalidValue(_, StringPiece("oneof"),
-                                      StringPiece(
-                                          "oneof field 'data' is already set. "
-                                          "Cannot set 'intData'")));
-
-  // JSON:
-  // { "anyData":
-  //    { "@type":
-  //       "type.googleapis.com/proto_util_converter.testing.oneofs.OneOfsRequest",
-  //     "strData": "blah",
-  //     "intData": 123
-  //    }
-  // }
-  ow_->StartObject("");
-  ow_->StartObject("anyData");
-  ow_->RenderString(
-      "@type",
-      "type.googleapis.com/proto_util_converter.testing.oneofs.OneOfsRequest");
-  ow_->RenderString("strData", "blah");
-  ow_->RenderInt32("intData", 123);
-  ow_->EndObject();
-  ow_->EndObject();
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/structured_objectwriter.h b/src/google/protobuf/util/internal/structured_objectwriter.h
deleted file mode 100644
index f6f7c89..0000000
--- a/src/google/protobuf/util/internal/structured_objectwriter.h
+++ /dev/null
@@ -1,121 +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_UTIL_INTERNAL_STRUCTURED_OBJECTWRITER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_STRUCTURED_OBJECTWRITER_H__
-
-#include <memory>
-
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/util/internal/object_writer.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-// An StructuredObjectWriter is an ObjectWriter for writing
-// tree-structured data in a stream of events representing objects
-// and collections. Implementation of this interface can be used to
-// write an object stream to an in-memory structure, protobufs,
-// JSON, XML, or any other output format desired. The ObjectSource
-// interface is typically used as the source of an object stream.
-//
-// See JsonObjectWriter for a sample implementation of
-// StructuredObjectWriter and its use.
-//
-// Derived classes could be thread-unsafe.
-class PROTOBUF_EXPORT StructuredObjectWriter : public ObjectWriter {
- public:
-  ~StructuredObjectWriter() override {}
-
- protected:
-  // A base element class for subclasses to extend, makes tracking state easier.
-  //
-  // StructuredObjectWriter behaves as a visitor. BaseElement represents a node
-  // in the input tree. Implementation of StructuredObjectWriter should also
-  // extend BaseElement to keep track of the location in the input tree.
-  class PROTOBUF_EXPORT BaseElement {
-   public:
-    // Takes ownership of the parent Element.
-    explicit BaseElement(BaseElement* parent)
-        : parent_(parent),
-          level_(parent == nullptr ? 0 : parent->level() + 1) {}
-    virtual ~BaseElement() {}
-
-    // Releases ownership of the parent and returns a pointer to it.
-    template <typename ElementType>
-    ElementType* pop() {
-      return down_cast<ElementType*>(parent_.release());
-    }
-
-    // Returns true if this element is the root.
-    bool is_root() const { return parent_ == nullptr; }
-
-    // Returns the number of hops from this element to the root element.
-    int level() const { return level_; }
-
-   protected:
-    // Returns pointer to parent element without releasing ownership.
-    virtual BaseElement* parent() const { return parent_.get(); }
-
-   private:
-    // Pointer to the parent Element.
-    std::unique_ptr<BaseElement> parent_;
-
-    // Number of hops to the root Element.
-    // The root Element has nullptr parent_ and a level_ of 0.
-    const int level_;
-
-    GOOGLE_DISALLOW_IMPLICIT_CONSTRUCTORS(BaseElement);
-  };
-
-  StructuredObjectWriter() {}
-
-  // Returns the current element. Used for indentation and name overrides.
-  virtual BaseElement* element() = 0;
-
- private:
-  // Do not add any data members to this class.
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StructuredObjectWriter);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_STRUCTURED_OBJECTWRITER_H__
diff --git a/src/google/protobuf/util/internal/testdata/anys.proto b/src/google/protobuf/util/internal/testdata/anys.proto
deleted file mode 100644
index b6fc3f6..0000000
--- a/src/google/protobuf/util/internal/testdata/anys.proto
+++ /dev/null
@@ -1,118 +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 = "proto3";
-
-package proto_util_converter.testing;
-
-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";
-
-// Top-level test cases proto used by MarshallingTest. See description
-// at the top of the class MarshallingTest for details on how to write
-// test cases.
-message AnyTestCases {
-  AnyWrapper empty_any = 1;
-  AnyWrapper type_only_any = 2;
-  AnyWrapper wrapper_any = 3;
-  AnyWrapper any_with_timestamp_value = 4;
-  AnyWrapper any_with_duration_value = 5;
-  AnyWrapper any_with_struct_value = 6;
-  AnyWrapper recursive_any = 7;
-  AnyWrapper any_with_message_value = 8;
-  AnyWrapper any_with_nested_message = 9;
-  AnyWrapper any_with_message_with_wrapper_type = 10;
-  AnyWrapper any_with_message_with_timestamp = 11;
-  AnyWrapper any_with_message_containing_map = 12;
-  AnyWrapper any_with_message_containing_struct = 13;
-  AnyWrapper any_with_message_containing_repeated_message = 14;
-  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;
-  google.protobuf.Any top_level_any_with_pivot_one = 52;
-  google.protobuf.Any top_level_any_with_pivot_two = 53;
-  google.protobuf.Any top_level_any_unordered = 54;
-}
-
-message AnyWrapper {
-  google.protobuf.Any any = 1;
-}
-
-// Hack to make sure the types we put into the any are included in the types.
-// Real solution is to add these types to the service config.
-message Imports {
-  google.protobuf.DoubleValue dbl = 1;
-  google.protobuf.Struct struct = 2;
-  google.protobuf.Timestamp timestamp = 3;
-  google.protobuf.Duration duration = 4;
-  google.protobuf.Int32Value i32 = 5;
-  google.protobuf.Empty empty = 6;
-  Data data = 100;
-}
-
-message Data {
-  int32 attr = 1;
-  string str = 2;
-  repeated string msgs = 3;
-  Data nested_data = 4;
-  google.protobuf.Int32Value int_wrapper = 5;
-  google.protobuf.Timestamp time = 6;
-  map<string, string> map_data = 7;
-  google.protobuf.Struct struct_data = 8;
-  repeated Data repeated_data = 9;
-  repeated google.protobuf.Any repeated_any = 10;
-}
-
-service AnyTestService {
-  rpc Call(AnyTestCases) returns (AnyTestCases);
-  rpc Call1(Imports) returns (Imports);
-}
-
-message AnyIn {
-  string something = 1;
-  google.protobuf.Any any = 2;
-}
-
-message AnyOut {
-  google.protobuf.Any any = 1;
-}
-
-message AnyM {
-  string foo = 1;
-}
diff --git a/src/google/protobuf/util/internal/testdata/books.proto b/src/google/protobuf/util/internal/testdata/books.proto
deleted file mode 100644
index 328c5ce..0000000
--- a/src/google/protobuf/util/internal/testdata/books.proto
+++ /dev/null
@@ -1,251 +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: sven@google.com (Sven Mawson)
-//
-// Sample protos for testing.
-
-// Some of the older enums don't use CAPITALS_WITH_UNDERSCORES for testing.
-// LINT: LEGACY_NAMES
-// LINT: ALLOW_GROUPS
-
-syntax = "proto2";
-
-package proto_util_converter.testing;
-
-import "google/protobuf/util/internal/testdata/anys.proto";
-
-// A book
-message Book {
-  optional string title = 1;
-  optional Author author = 2;
-  optional uint32 length = 3;
-  optional int64 published = 4;
-  optional bytes content = 5;
-
-  optional group Data = 6 {
-    optional uint32 year = 7;
-    optional string copyright = 8;
-  }
-
-  message Label {
-    optional string key = 1;
-    optional string value = 2;
-  }
-
-  optional Publisher publisher = 9;
-  repeated Label labels = 10;
-
-  enum Type {
-    FICTION = 1;
-    KIDS = 2;
-    ACTION_AND_ADVENTURE = 3;
-    arts_and_photography = 4;
-    I18N_Tech = 5;
-  }
-  optional Type type = 11;
-
-  // Useful for testing JSON snake/camel-case conversions.
-  optional string snake_field = 12;
-
-  // Used to test type not found in type info. Messages defined in other files
-  // are not added when adding Book to type info.
-  optional AnyWrapper type_not_found = 13;
-
-  // Used to test invalid value inside of primitive repeated fields.
-  repeated int32 primitive_repeated = 14;
-
-  extensions 200 to 499;
-}
-
-// A publisher of a book, tests required fields.
-message Publisher {
-  required string name = 1;
-}
-
-// An author of a book
-message Author {
-  optional uint64 id = 1 [json_name = "@id"];
-  optional string name = 2;
-  repeated string pseudonym = 3;
-  optional bool alive = 4;
-  repeated Author friend = 5;
-}
-
-// For testing resiliency of our protostream parser.
-// Field numbers of Author are reused for something else.
-message BadAuthor {
-  optional string id = 1;         // non-length-delimited to length-delimited.
-  repeated uint64 name = 2;       // string to repeated (both length-delimited).
-  optional string pseudonym = 3;  // Repeated to optional.
-  repeated bool alive = 4 [packed = true];  // Optional to repeated.
-}
-
-// All primitive types
-message Primitive {
-  // 32 bit numbers:
-  optional fixed32 fix32 = 1;
-  optional uint32 u32 = 2;
-  optional int32 i32 = 3;
-  optional sfixed32 sf32 = 4;
-  optional sint32 s32 = 5;
-
-  // 64 bit numbers:
-  optional fixed64 fix64 = 6;
-  optional uint64 u64 = 7;
-  optional int64 i64 = 8;
-  optional sfixed64 sf64 = 9;
-  optional sint64 s64 = 10;
-
-  // The other stuff.
-  optional string str = 11;
-  optional bytes bytes = 12;
-  optional float float = 13;
-  optional double double = 14;
-  optional bool bool = 15;
-
-  // repeated 32 bit numbers:
-  repeated fixed32 rep_fix32 = 16;
-  repeated uint32 rep_u32 = 17;
-  repeated int32 rep_i32 = 18;
-  repeated sfixed32 rep_sf32 = 19;
-  repeated sint32 rep_s32 = 20;
-
-  // repeated 64 bit numbers:
-  repeated fixed64 rep_fix64 = 21;
-  repeated uint64 rep_u64 = 22;
-  repeated int64 rep_i64 = 23;
-  repeated sfixed64 rep_sf64 = 24;
-  repeated sint64 rep_s64 = 25;
-
-  // repeated other stuff:
-  repeated string rep_str = 26;
-  repeated bytes rep_bytes = 27;
-  repeated float rep_float = 28;
-  repeated double rep_double = 29;
-  repeated bool rep_bool = 30;
-}
-
-// Test packed versions of all repeated primitives.
-// The field numbers should match their non-packed version in Primitive message.
-message PackedPrimitive {
-  // repeated 32 bit numbers:
-  repeated fixed32 rep_fix32 = 16 [packed = true];
-  repeated uint32 rep_u32 = 17 [packed = true];
-  repeated int32 rep_i32 = 18 [packed = true];
-  repeated sfixed32 rep_sf32 = 19 [packed = true];
-  repeated sint32 rep_s32 = 20 [packed = true];
-
-  // repeated 64 bit numbers:
-  repeated fixed64 rep_fix64 = 21 [packed = true];
-  repeated uint64 rep_u64 = 22 [packed = true];
-  repeated int64 rep_i64 = 23 [packed = true];
-  repeated sfixed64 rep_sf64 = 24 [packed = true];
-  repeated sint64 rep_s64 = 25 [packed = true];
-
-  // repeated other stuff:
-  repeated float rep_float = 28 [packed = true];
-  repeated double rep_double = 29 [packed = true];
-  repeated bool rep_bool = 30 [packed = true];
-}
-
-// Test extensions.
-extend Book {
-  repeated Author more_author = 201;
-}
-
-// Test nested extensions.
-message NestedBook {
-  extend Book {
-    optional NestedBook another_book = 301;
-  }
-  // Recurse
-  optional Book book = 1;
-}
-
-// For testing resiliency of our protostream parser.
-// Field number of NestedBook is reused for something else.
-message BadNestedBook {
-  repeated uint32 book = 1 [packed = true];  // Packed to optional message.
-}
-
-// A recursively defined message.
-message Cyclic {
-  optional int32 m_int = 1;
-  optional string m_str = 2;
-  optional Book m_book = 3;
-  repeated Author m_author = 5;
-  optional Cyclic m_cyclic = 4;
-}
-
-// Test that two messages can have different fields mapped to the same JSON
-// name. See: https://github.com/protocolbuffers/protobuf/issues/1415
-message TestJsonName1 {
-  optional int32 one_value = 1 [json_name = "value"];
-}
-message TestJsonName2 {
-  optional int32 another_value = 1 [json_name = "value"];
-}
-
-message TestPrimitiveFieldsWithSameJsonName {
-  optional string val_str1 = 1;
-  optional string val_str_1 = 2;
-
-  optional int32 val_int321 = 3;
-  optional int32 val_int32_1 = 4;
-
-  optional uint32 val_uint321 = 5;
-  optional uint32 val_uint32_1 = 6;
-
-  optional int64 val_int641 = 7;
-  optional int64 val_int64_1 = 8;
-
-  optional uint64 val_uint641 = 9;
-  optional uint64 val_uint64_1 = 10;
-
-  optional bool val_bool1 = 11;
-  optional bool val_bool_1 = 12;
-
-  optional double val_double1 = 13;
-  optional double val_double_1 = 14;
-
-  optional float val_float1 = 15;
-  optional float val_float_1 = 16;
-}
-
-message TestRepeatedFieldsWithSameJsonName {
-  repeated string rep_str1 = 1;
-  repeated string rep_str_1 = 2;
-}
-
-message TestMessageFieldsWithSameJsonName {
-  optional Primitive prim1 = 1;
-  optional Primitive prim_1 = 2;
-}
diff --git a/src/google/protobuf/util/internal/testdata/default_value.proto b/src/google/protobuf/util/internal/testdata/default_value.proto
deleted file mode 100644
index 79ce144..0000000
--- a/src/google/protobuf/util/internal/testdata/default_value.proto
+++ /dev/null
@@ -1,170 +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 = "proto3";
-
-package proto_util_converter.testing;
-
-import "google/protobuf/any.proto";
-import "google/protobuf/struct.proto";
-import "google/protobuf/wrappers.proto";
-
-message DefaultValueTestCases {
-  DoubleMessage empty_double = 1;
-  DoubleMessage double_with_default_value = 2;
-  DoubleMessage double_with_nondefault_value = 3;
-  DoubleMessage repeated_double = 4;
-  DoubleMessage nested_message = 5;
-  DoubleMessage repeated_nested_message = 6;
-  DoubleMessage double_message_with_oneof = 7;
-  StructMessage empty_struct = 201;
-  StructMessage empty_struct2 = 202;
-  StructMessage struct_with_null_value = 203;
-  StructMessage struct_with_values = 204;
-  StructMessage struct_with_nested_struct = 205;
-  StructMessage struct_with_nested_list = 206;
-  StructMessage struct_with_list_of_nulls = 207;
-  StructMessage struct_with_list_of_lists = 208;
-  StructMessage struct_with_list_of_structs = 209;
-  google.protobuf.Struct top_level_struct = 210;
-  ValueMessage value_wrapper_simple = 212;
-  ValueMessage value_wrapper_with_struct = 213;
-  ValueMessage value_wrapper_with_list = 214;
-  ListValueMessage list_value_wrapper = 215;
-  google.protobuf.Value top_level_value_simple = 216;
-  google.protobuf.Value top_level_value_with_struct = 217;
-  google.protobuf.Value top_level_value_with_list = 218;
-  google.protobuf.ListValue top_level_listvalue = 219;
-  AnyMessage empty_any = 301;
-  AnyMessage type_only_any = 302;
-  AnyMessage recursive_any = 303;
-  AnyMessage any_with_message_value = 304;
-  AnyMessage any_with_nested_message = 305;
-  AnyMessage any_with_message_containing_map = 306;
-  AnyMessage any_with_message_containing_struct = 307;
-  google.protobuf.Any top_level_any = 308;
-  StringtoIntMap empty_map = 401;
-  StringtoIntMap string_to_int = 402;
-  IntToStringMap int_to_string = 403;
-  MixedMap mixed1 = 404;
-  MixedMap2 mixed2 = 405;
-  MixedMap2 empty_mixed2 = 406;
-  MessageMap map_of_objects = 407;
-  MixedMap mixed_empty = 408;
-  MessageMap message_map_empty = 409;
-  DoubleValueMessage double_value = 501;
-  DoubleValueMessage double_value_default = 502;
-}
-
-message DoubleMessage {
-  double double_value = 1;
-  repeated double repeated_double = 2;
-  DoubleMessage nested_message = 3;
-  repeated DoubleMessage repeated_nested_message = 4;
-  google.protobuf.DoubleValue double_wrapper = 100;
-  oneof value {
-    string str_value = 112;
-    int64 num_value = 113;
-  }
-}
-
-message StructMessage {
-  google.protobuf.Struct struct = 1;
-}
-
-message ValueMessage {
-  google.protobuf.Value value = 1;
-}
-
-message ListValueMessage {
-  google.protobuf.ListValue shopping_list = 1;
-}
-message RequestMessage {
-  string content = 1;
-}
-
-// A test service.
-service DefaultValueTestService {
-  // A test method.
-  rpc Call(RequestMessage) returns (DefaultValueTestCases);
-}
-
-message AnyMessage {
-  google.protobuf.Any any = 1;
-  AnyData data = 2;
-}
-
-message AnyData {
-  int32 attr = 1;
-  string str = 2;
-  repeated string msgs = 3;
-  AnyData nested_data = 4;
-  map<string, string> map_data = 7;
-  google.protobuf.Struct struct_data = 8;
-  repeated AnyData repeated_data = 9;
-}
-
-message StringtoIntMap {
-  map<string, int32> map = 1;
-}
-
-message IntToStringMap {
-  map<int32, string> map = 1;
-}
-
-message MixedMap {
-  string msg = 1;
-  map<string, float> map = 2;
-  int32 int_value = 3;
-}
-
-message MixedMap2 {
-  enum E {
-    E0 = 0;
-    E1 = 1;
-    E2 = 2;
-    E3 = 3;
-  }
-  map<int32, bool> map = 1;
-  E ee = 2;
-  string msg = 4;
-}
-
-message MessageMap {
-  message M {
-    int32 inner_int = 1;
-    string inner_text = 2;
-  }
-  map<string, M> map = 1;
-}
-
-message DoubleValueMessage {
-  google.protobuf.DoubleValue double = 1;
-}
diff --git a/src/google/protobuf/util/internal/testdata/field_mask.proto b/src/google/protobuf/util/internal/testdata/field_mask.proto
deleted file mode 100644
index 9d2bc400..0000000
--- a/src/google/protobuf/util/internal/testdata/field_mask.proto
+++ /dev/null
@@ -1,71 +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 = "proto3";
-
-package proto_util_converter.testing;
-
-import "google/protobuf/field_mask.proto";
-
-message NestedFieldMask {
-  string data = 1;
-  google.protobuf.FieldMask single_mask = 2;
-  repeated google.protobuf.FieldMask repeated_mask = 3;
-}
-
-message FieldMaskTest {
-  string id = 1;
-  google.protobuf.FieldMask single_mask = 2;
-  repeated google.protobuf.FieldMask repeated_mask = 3;
-  repeated NestedFieldMask nested_mask = 4;
-}
-
-message FieldMaskTestCases {
-  FieldMaskWrapper single_mask = 1;
-  FieldMaskWrapper multiple_mask = 2;
-  FieldMaskWrapper snake_camel = 3;
-  FieldMaskWrapper empty_field = 4;
-  FieldMaskWrapper apiary_format1 = 5;
-  FieldMaskWrapper apiary_format2 = 6;
-  FieldMaskWrapper apiary_format3 = 7;
-  FieldMaskWrapper map_key1 = 8;
-  FieldMaskWrapper map_key2 = 9;
-  FieldMaskWrapper map_key3 = 10;
-  FieldMaskWrapper map_key4 = 11;
-  FieldMaskWrapper map_key5 = 12;
-}
-
-message FieldMaskWrapper {
-  google.protobuf.FieldMask mask = 1;
-}
-
-service FieldMaskTestService {
-  rpc Call(FieldMaskTestCases) returns (FieldMaskTestCases);
-}
diff --git a/src/google/protobuf/util/internal/testdata/maps.proto b/src/google/protobuf/util/internal/testdata/maps.proto
deleted file mode 100644
index a9fdbe6..0000000
--- a/src/google/protobuf/util/internal/testdata/maps.proto
+++ /dev/null
@@ -1,148 +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 = "proto3";
-
-package proto_util_converter.testing;
-
-import "google/protobuf/any.proto";
-
-// Top-level test cases proto used by MarshallingTest. See description
-// at the top of the class MarshallingTest for details on how to write
-// test cases.
-message MapsTestCases {
-  EmptyMap empty_map = 1;
-  StringtoInt string_to_int = 2;
-  IntToString int_to_string = 3;
-  Mixed1 mixed1 = 4;
-  Mixed2 mixed2 = 5;
-  MapOfObjects map_of_objects = 6;
-
-  // Empty key tests
-  StringtoInt empty_key_string_to_int1 = 7;
-  StringtoInt empty_key_string_to_int2 = 8;
-  StringtoInt empty_key_string_to_int3 = 9;
-  BoolToString empty_key_bool_to_string = 10;
-  IntToString empty_key_int_to_string = 11;
-  Mixed1 empty_key_mixed = 12;
-  MapOfObjects empty_key_map_objects = 13;
-}
-
-message EmptyMap {
-  map<int32, int32> map = 1;
-}
-
-message StringtoInt {
-  map<string, int32> map = 1;
-}
-
-message IntToString {
-  map<int32, string> map = 1;
-}
-
-message BoolToString {
-  map<bool, string> map = 1;
-}
-
-message Mixed1 {
-  string msg = 1;
-  map<string, float> map = 2;
-}
-
-message Mixed2 {
-  enum E {
-    E0 = 0;
-    E1 = 1;
-    E2 = 2;
-    E3 = 3;
-  }
-  map<int32, bool> map = 1;
-  E ee = 2;
-}
-
-message MapOfObjects {
-  message M {
-    string inner_text = 1;
-  }
-  map<string, M> map = 1;
-}
-
-message DummyRequest {}
-
-service MapsTestService {
-  rpc Call(DummyRequest) returns (MapsTestCases);
-}
-
-message MapIn {
-  string other = 1;
-  repeated string things = 2;
-  map<string, string> map_input = 3;
-  map<string, google.protobuf.Any> map_any = 4;
-}
-
-message MapOut {
-  map<string, MapM> map1 = 1;
-  map<string, MapOut> map2 = 2;
-  map<int32, string> map3 = 3;
-  map<bool, string> map4 = 5;
-  string bar = 4;
-}
-
-// A message with exactly the same wire representation as MapOut, but using
-// repeated message fields instead of map fields. We use this message to test
-// the wire-format compatibility of the JSON transcoder (e.g., whether it
-// handles missing keys correctly).
-message MapOutWireFormat {
-  message Map1Entry {
-    string key = 1;
-    MapM value = 2;
-  }
-  repeated Map1Entry map1 = 1;
-  message Map2Entry {
-    string key = 1;
-    MapOut value = 2;
-  }
-  repeated Map2Entry map2 = 2;
-  message Map3Entry {
-    int32 key = 1;
-    string value = 2;
-  }
-  repeated Map3Entry map3 = 3;
-  message Map4Entry {
-    bool key = 1;
-    string value = 2;
-  }
-  repeated Map4Entry map4 = 5;
-  string bar = 4;
-}
-
-message MapM {
-  string foo = 1;
-}
diff --git a/src/google/protobuf/util/internal/testdata/oneofs.proto b/src/google/protobuf/util/internal/testdata/oneofs.proto
deleted file mode 100644
index 7706af0..0000000
--- a/src/google/protobuf/util/internal/testdata/oneofs.proto
+++ /dev/null
@@ -1,77 +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.
-
-// Proto to test proto3 oneofs.
-syntax = "proto3";
-
-package proto_util_converter.testing.oneofs;
-
-import "google/protobuf/any.proto";
-import "google/protobuf/struct.proto";
-import "google/protobuf/timestamp.proto";
-
-message OneOfsRequest {
-  string value = 1;
-  oneof data {
-    string str_data = 2;
-    int32 int_data = 3;
-    // Simple message
-    Data message_data = 4;
-    MoreData more_data = 5;
-    // Well known types
-    google.protobuf.Struct struct_data = 6;
-    google.protobuf.Value value_data = 7;
-    google.protobuf.ListValue list_value_data = 8;
-    google.protobuf.Timestamp ts_data = 9;
-  }
-  google.protobuf.Any any_data = 19;
-}
-
-message RequestWithSimpleOneof {
-  string value = 1;
-  oneof data {
-    string str_data = 2;
-    int32 int_data = 3;
-    Data message_data = 4;
-    MoreData more_data = 5;
-  }
-}
-
-message Data {
-  int32 data_value = 1;
-}
-
-message MoreData {
-  string str_value = 1;
-}
-
-message Response {
-  string value = 1;
-}
diff --git a/src/google/protobuf/util/internal/testdata/struct.proto b/src/google/protobuf/util/internal/testdata/struct.proto
deleted file mode 100644
index a50ea87..0000000
--- a/src/google/protobuf/util/internal/testdata/struct.proto
+++ /dev/null
@@ -1,117 +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 = "proto3";
-
-package proto_util_converter.testing;
-
-import "google/protobuf/struct.proto";
-
-message StructTestCases {
-  StructWrapper empty_value = 1;
-  StructWrapper empty_value2 = 2;
-  StructWrapper null_value = 3;
-  StructWrapper simple_struct = 4;
-  StructWrapper longer_struct = 5;
-  StructWrapper struct_with_nested_struct = 6;
-  StructWrapper struct_with_nested_list = 7;
-  StructWrapper struct_with_list_of_nulls = 8;
-  StructWrapper struct_with_list_of_lists = 9;
-  StructWrapper struct_with_list_of_structs = 10;
-  StructWrapper struct_with_empty_list = 11;
-  StructWrapper struct_with_list_with_empty_struct = 12;
-  google.protobuf.Struct top_level_struct = 13;
-  google.protobuf.Struct top_level_struct_with_empty_list = 14;
-  google.protobuf.Struct top_level_struct_with_list_with_empty_struct = 15;
-  ValueWrapper value_wrapper_simple = 16;
-  ValueWrapper value_wrapper_with_struct = 17;
-  ValueWrapper value_wrapper_with_list = 18;
-  ValueWrapper value_wrapper_with_empty_list = 19;
-  ValueWrapper value_wrapper_with_list_with_empty_struct = 20;
-  ListValueWrapper list_value_wrapper = 21;
-  ListValueWrapper list_value_wrapper_with_empty_list = 22;
-  ListValueWrapper list_value_wrapper_with_list_with_empty_struct = 23;
-  google.protobuf.Value top_level_value_simple = 24;
-  google.protobuf.Value top_level_value_with_struct = 25;
-  google.protobuf.Value top_level_value_with_list = 26;
-  google.protobuf.Value top_level_value_with_empty_list = 27;
-  google.protobuf.Value top_level_value_with_list_with_empty_struct = 28;
-  google.protobuf.ListValue top_level_listvalue = 29;
-  google.protobuf.ListValue top_level_empty_listvalue = 30;
-  google.protobuf.ListValue top_level_listvalue_with_empty_struct = 31;
-  RepeatedValueWrapper repeated_value = 32;
-  RepeatedValueWrapper repeated_value_nested_list = 33;
-  RepeatedValueWrapper repeated_value_nested_list2 = 34;
-  RepeatedValueWrapper repeated_value_nested_list3 = 35;
-  RepeatedListValueWrapper repeated_listvalue = 36;
-  MapOfStruct map_of_struct = 37;
-  MapOfStruct map_of_struct_value = 38;
-  MapOfStruct map_of_listvalue = 39;
-}
-
-message StructWrapper {
-  google.protobuf.Struct struct = 1;
-}
-
-message ValueWrapper {
-  google.protobuf.Value value = 1;
-}
-
-message RepeatedValueWrapper {
-  repeated google.protobuf.Value values = 1;
-}
-
-message ListValueWrapper {
-  google.protobuf.ListValue shopping_list = 1;
-}
-
-message RepeatedListValueWrapper {
-  repeated google.protobuf.ListValue dimensions = 1;
-}
-
-message MapOfStruct {
-  map<string, google.protobuf.Struct> struct_map = 1;
-  map<string, google.protobuf.Value> value_map = 2;
-  map<string, google.protobuf.ListValue> listvalue_map = 3;
-}
-
-// Hack to test return types with Struct as top-level message. Struct typers
-// cannot be directly used in API requests. Hence using Dummy as request type.
-message Dummy {
-  string text = 1;
-}
-
-service StructTestService {
-  rpc Call(Dummy) returns (StructTestCases);
-}
-
-message StructType {
-  google.protobuf.Struct object = 1;
-}
diff --git a/src/google/protobuf/util/internal/testdata/timestamp_duration.proto b/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
deleted file mode 100644
index 8e87bdd..0000000
--- a/src/google/protobuf/util/internal/testdata/timestamp_duration.proto
+++ /dev/null
@@ -1,80 +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 = "proto3";
-
-package proto_util_converter.testing;
-
-import "google/protobuf/duration.proto";
-import "google/protobuf/timestamp.proto";
-
-message TimestampDurationTestCases {
-  // Timestamp tests
-  TimeStampType epoch = 1;
-  TimeStampType epoch2 = 2;
-  TimeStampType mintime = 3;
-  TimeStampType maxtime = 4;
-  TimeStampType timeval1 = 5;
-  TimeStampType timeval2 = 6;
-  TimeStampType timeval3 = 7;
-  TimeStampType timeval4 = 8;
-  TimeStampType timeval5 = 9;
-  TimeStampType timeval6 = 10;
-  TimeStampType timeval7 = 11;
-  google.protobuf.Timestamp timeval8 = 12;
-
-  // Duration tests
-  DurationType zero_duration = 101;
-  DurationType min_duration = 102;
-  DurationType max_duration = 103;
-  DurationType duration1 = 104;
-  DurationType duration2 = 105;
-  DurationType duration3 = 106;
-  DurationType duration4 = 107;
-  google.protobuf.Duration duration5 = 108;
-}
-
-message TimeStampType {
-  google.protobuf.Timestamp timestamp = 1;
-}
-
-message DurationType {
-  google.protobuf.Duration duration = 1;
-}
-
-service TimestampDurationTestService {
-  rpc Call(TimestampDurationTestCases) returns (TimestampDurationTestCases);
-}
-
-message TimestampDuration {
-  google.protobuf.Timestamp ts = 1;
-  google.protobuf.Duration dur = 2;
-  repeated google.protobuf.Timestamp rep_ts = 3;
-}
diff --git a/src/google/protobuf/util/internal/testdata/wrappers.proto b/src/google/protobuf/util/internal/testdata/wrappers.proto
deleted file mode 100644
index e7a0541..0000000
--- a/src/google/protobuf/util/internal/testdata/wrappers.proto
+++ /dev/null
@@ -1,100 +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 = "proto3";
-
-package proto_util_converter.testing;
-
-import "google/protobuf/wrappers.proto";
-
-// Top-level test cases proto used by MarshallingTest. See description
-// at the top of the class MarshallingTest for details on how to write
-// test cases.
-message WrappersTestCases {
-  DoubleWrapper double_wrapper = 1;
-  FloatWrapper float_wrapper = 2;
-  Int64Wrapper int64_wrapper = 3;
-  UInt64Wrapper uint64_wrapper = 4;
-  Int32Wrapper int32_wrapper = 5;
-  UInt32Wrapper uint32_wrapper = 6;
-  BoolWrapper bool_wrapper = 7;
-  StringWrapper string_wrapper = 8;
-  BytesWrapper bytes_wrapper = 9;
-
-  DoubleWrapper double_wrapper_default = 10;
-  FloatWrapper float_wrapper_default = 11;
-  Int64Wrapper int64_wrapper_default = 12;
-  UInt64Wrapper uint64_wrapper_default = 13;
-  Int32Wrapper int32_wrapper_default = 14;
-  UInt32Wrapper uint32_wrapper_default = 15;
-  BoolWrapper bool_wrapper_default = 16;
-  StringWrapper string_wrapper_default = 17;
-  BytesWrapper bytes_wrapper_default = 18;
-}
-
-message DoubleWrapper {
-  google.protobuf.DoubleValue double = 1;
-}
-
-message FloatWrapper {
-  google.protobuf.FloatValue float = 1;
-}
-
-message Int64Wrapper {
-  google.protobuf.Int64Value int64 = 1;
-}
-
-message UInt64Wrapper {
-  google.protobuf.UInt64Value uint64 = 1;
-}
-
-message Int32Wrapper {
-  google.protobuf.Int32Value int32 = 1;
-}
-
-message UInt32Wrapper {
-  google.protobuf.UInt32Value uint32 = 1;
-}
-
-message BoolWrapper {
-  google.protobuf.BoolValue bool = 1;
-}
-
-message StringWrapper {
-  google.protobuf.StringValue string = 1;
-}
-
-message BytesWrapper {
-  google.protobuf.BytesValue bytes = 1;
-}
-
-service WrappersTestService {
-  rpc Call(WrappersTestCases) returns (WrappersTestCases);
-}
diff --git a/src/google/protobuf/util/internal/type_info.cc b/src/google/protobuf/util/internal/type_info.cc
deleted file mode 100644
index b6cf536..0000000
--- a/src/google/protobuf/util/internal/type_info.cc
+++ /dev/null
@@ -1,182 +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 <google/protobuf/util/internal/type_info.h>
-
-#include <map>
-#include <set>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/statusor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/stubs/map_util.h>
-#include <google/protobuf/stubs/status.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-namespace {
-// A TypeInfo that looks up information provided by a TypeResolver.
-class TypeInfoForTypeResolver : public TypeInfo {
- public:
-  explicit TypeInfoForTypeResolver(TypeResolver* type_resolver)
-      : type_resolver_(type_resolver) {}
-
-  ~TypeInfoForTypeResolver() override {
-    DeleteCachedTypes(&cached_types_);
-    DeleteCachedTypes(&cached_enums_);
-  }
-
-  util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
-      StringPiece type_url) const override {
-    std::map<StringPiece, StatusOrType>::iterator it =
-        cached_types_.find(type_url);
-    if (it != cached_types_.end()) {
-      return it->second;
-    }
-    // Stores the string value so it can be referenced using StringPiece in the
-    // cached_types_ map.
-    const std::string& string_type_url =
-        *string_storage_.insert(std::string(type_url)).first;
-    std::unique_ptr<google::protobuf::Type> type(new google::protobuf::Type());
-    util::Status status =
-        type_resolver_->ResolveMessageType(string_type_url, type.get());
-    StatusOrType result =
-        status.ok() ? StatusOrType(type.release()) : StatusOrType(status);
-    cached_types_[string_type_url] = result;
-    return result;
-  }
-
-  const google::protobuf::Type* GetTypeByTypeUrl(
-      StringPiece type_url) const override {
-    StatusOrType result = ResolveTypeUrl(type_url);
-    return result.ok() ? result.value() : NULL;
-  }
-
-  const google::protobuf::Enum* GetEnumByTypeUrl(
-      StringPiece type_url) const override {
-    std::map<StringPiece, StatusOrEnum>::iterator it =
-        cached_enums_.find(type_url);
-    if (it != cached_enums_.end()) {
-      return it->second.ok() ? it->second.value() : NULL;
-    }
-    // Stores the string value so it can be referenced using StringPiece in the
-    // cached_enums_ map.
-    const std::string& string_type_url =
-        *string_storage_.insert(std::string(type_url)).first;
-    std::unique_ptr<google::protobuf::Enum> enum_type(
-        new google::protobuf::Enum());
-    util::Status status =
-        type_resolver_->ResolveEnumType(string_type_url, enum_type.get());
-    StatusOrEnum result =
-        status.ok() ? StatusOrEnum(enum_type.release()) : StatusOrEnum(status);
-    cached_enums_[string_type_url] = result;
-    return result.ok() ? result.value() : NULL;
-  }
-
-  const google::protobuf::Field* FindField(
-      const google::protobuf::Type* type,
-      StringPiece camel_case_name) const override {
-    std::map<const google::protobuf::Type*, CamelCaseNameTable>::const_iterator
-        it = indexed_types_.find(type);
-    const CamelCaseNameTable& camel_case_name_table =
-        (it == indexed_types_.end())
-            ? PopulateNameLookupTable(type, &indexed_types_[type])
-            : it->second;
-    StringPiece name = FindWithDefault(
-        camel_case_name_table, camel_case_name, StringPiece());
-    if (name.empty()) {
-      // Didn't find a mapping. Use whatever provided.
-      name = camel_case_name;
-    }
-    return FindFieldInTypeOrNull(type, name);
-  }
-
- private:
-  typedef util::StatusOr<const google::protobuf::Type*> StatusOrType;
-  typedef util::StatusOr<const google::protobuf::Enum*> StatusOrEnum;
-  typedef std::map<StringPiece, StringPiece> CamelCaseNameTable;
-
-  template <typename T>
-  static void DeleteCachedTypes(std::map<StringPiece, T>* cached_types) {
-    for (typename std::map<StringPiece, T>::iterator it =
-             cached_types->begin();
-         it != cached_types->end(); ++it) {
-      if (it->second.ok()) {
-        delete it->second.value();
-      }
-    }
-  }
-
-  const CamelCaseNameTable& PopulateNameLookupTable(
-      const google::protobuf::Type* type,
-      CamelCaseNameTable* camel_case_name_table) const {
-    for (int i = 0; i < type->fields_size(); ++i) {
-      const google::protobuf::Field& field = type->fields(i);
-      StringPiece name = field.name();
-      StringPiece camel_case_name = field.json_name();
-      const StringPiece* existing = InsertOrReturnExisting(
-          camel_case_name_table, camel_case_name, name);
-      if (existing && *existing != name) {
-        GOOGLE_LOG(WARNING) << "Field '" << name << "' and '" << *existing
-                     << "' map to the same camel case name '" << camel_case_name
-                     << "'.";
-      }
-    }
-    return *camel_case_name_table;
-  }
-
-  TypeResolver* type_resolver_;
-
-  // Stores string values that will be referenced by StringPieces in
-  // cached_types_, cached_enums_.
-  mutable std::set<std::string> string_storage_;
-
-  mutable std::map<StringPiece, StatusOrType> cached_types_;
-  mutable std::map<StringPiece, StatusOrEnum> cached_enums_;
-
-  mutable std::map<const google::protobuf::Type*, CamelCaseNameTable>
-      indexed_types_;
-};
-}  // namespace
-
-TypeInfo* TypeInfo::NewTypeInfo(TypeResolver* type_resolver) {
-  return new TypeInfoForTypeResolver(type_resolver);
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/type_info.h b/src/google/protobuf/util/internal/type_info.h
deleted file mode 100644
index 257df5b..0000000
--- a/src/google/protobuf/util/internal/type_info.h
+++ /dev/null
@@ -1,97 +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_UTIL_INTERNAL_TYPE_INFO_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_TYPE_INFO_H__
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/stubs/statusor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/stubs/status.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-// Internal helper class for type resolving. Note that this class is not
-// thread-safe and should only be accessed in one thread.
-class PROTOBUF_EXPORT TypeInfo {
- public:
-  TypeInfo() {}
-  virtual ~TypeInfo() {}
-
-  // Resolves a type url into a Type. If the type url is invalid, returns
-  // INVALID_ARGUMENT error status. If the type url is valid but the
-  // corresponding type cannot be found, returns a NOT_FOUND error status.
-  //
-  // This TypeInfo class retains the ownership of the returned pointer.
-  virtual util::StatusOr<const google::protobuf::Type*> ResolveTypeUrl(
-      StringPiece type_url) const = 0;
-
-  // Resolves a type url into a Type. Like ResolveTypeUrl() but returns
-  // NULL if the type url is invalid or the type cannot be found.
-  //
-  // This TypeInfo class retains the ownership of the returned pointer.
-  virtual const google::protobuf::Type* GetTypeByTypeUrl(
-      StringPiece type_url) const = 0;
-
-  // Resolves a type url for an enum. Returns NULL if the type url is
-  // invalid or the type cannot be found.
-  //
-  // This TypeInfo class retains the ownership of the returned pointer.
-  virtual const google::protobuf::Enum* GetEnumByTypeUrl(
-      StringPiece type_url) const = 0;
-
-  // Looks up a field in the specified type given a CamelCase name.
-  virtual const google::protobuf::Field* FindField(
-      const google::protobuf::Type* type,
-      StringPiece camel_case_name) const = 0;
-
-  // Creates a TypeInfo object that looks up type information from a
-  // TypeResolver. Caller takes ownership of the returned pointer.
-  static TypeInfo* NewTypeInfo(TypeResolver* type_resolver);
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeInfo);
-};
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_TYPE_INFO_H__
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.cc b/src/google/protobuf/util/internal/type_info_test_helper.cc
deleted file mode 100644
index 088f412..0000000
--- a/src/google/protobuf/util/internal/type_info_test_helper.cc
+++ /dev/null
@@ -1,132 +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 <google/protobuf/util/internal/type_info_test_helper.h>
-
-#include <memory>
-#include <vector>
-
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/util/internal/constants.h>
-#include <google/protobuf/util/internal/default_value_objectwriter.h>
-#include <google/protobuf/util/internal/protostream_objectsource.h>
-#include <google/protobuf/util/internal/protostream_objectwriter.h>
-#include <google/protobuf/util/internal/type_info.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/util/type_resolver_util.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-namespace testing {
-
-
-void TypeInfoTestHelper::ResetTypeInfo(
-    const std::vector<const Descriptor*>& descriptors) {
-  switch (type_) {
-    case USE_TYPE_RESOLVER: {
-      const DescriptorPool* pool = descriptors[0]->file()->pool();
-      for (int i = 1; i < descriptors.size(); ++i) {
-        GOOGLE_CHECK(pool == descriptors[i]->file()->pool())
-            << "Descriptors from different pools are not supported.";
-      }
-      type_resolver_.reset(
-          NewTypeResolverForDescriptorPool(kTypeServiceBaseUrl, pool));
-      typeinfo_.reset(TypeInfo::NewTypeInfo(type_resolver_.get()));
-      return;
-    }
-  }
-  GOOGLE_LOG(FATAL) << "Can not reach here.";
-}
-
-void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor) {
-  std::vector<const Descriptor*> descriptors;
-  descriptors.push_back(descriptor);
-  ResetTypeInfo(descriptors);
-}
-
-void TypeInfoTestHelper::ResetTypeInfo(const Descriptor* descriptor1,
-                                       const Descriptor* descriptor2) {
-  std::vector<const Descriptor*> descriptors;
-  descriptors.push_back(descriptor1);
-  descriptors.push_back(descriptor2);
-  ResetTypeInfo(descriptors);
-}
-
-TypeInfo* TypeInfoTestHelper::GetTypeInfo() { return typeinfo_.get(); }
-
-ProtoStreamObjectSource* TypeInfoTestHelper::NewProtoSource(
-    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, render_options);
-    }
-  }
-  GOOGLE_LOG(FATAL) << "Can not reach here.";
-  return nullptr;
-}
-
-ProtoStreamObjectWriter* TypeInfoTestHelper::NewProtoWriter(
-    const std::string& type_url, strings::ByteSink* output,
-    ErrorListener* listener, const ProtoStreamObjectWriter::Options& options) {
-  const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
-  switch (type_) {
-    case USE_TYPE_RESOLVER: {
-      return new ProtoStreamObjectWriter(type_resolver_.get(), *type, output,
-                                         listener, options);
-    }
-  }
-  GOOGLE_LOG(FATAL) << "Can not reach here.";
-  return nullptr;
-}
-
-DefaultValueObjectWriter* TypeInfoTestHelper::NewDefaultValueWriter(
-    const std::string& type_url, ObjectWriter* writer) {
-  const google::protobuf::Type* type = typeinfo_->GetTypeByTypeUrl(type_url);
-  switch (type_) {
-    case USE_TYPE_RESOLVER: {
-      return new DefaultValueObjectWriter(type_resolver_.get(), *type, writer);
-    }
-  }
-  GOOGLE_LOG(FATAL) << "Can not reach here.";
-  return nullptr;
-}
-
-}  // namespace testing
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/type_info_test_helper.h b/src/google/protobuf/util/internal/type_info_test_helper.h
deleted file mode 100644
index 1110a34..0000000
--- a/src/google/protobuf/util/internal/type_info_test_helper.h
+++ /dev/null
@@ -1,96 +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_UTIL_INTERNAL_TYPE_INFO_TEST_HELPER_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_TYPE_INFO_TEST_HELPER_H__
-
-#include <memory>
-#include <vector>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/util/internal/default_value_objectwriter.h>
-#include <google/protobuf/util/internal/protostream_objectsource.h>
-#include <google/protobuf/util/internal/protostream_objectwriter.h>
-#include <google/protobuf/util/internal/type_info.h>
-#include <google/protobuf/util/type_resolver.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-namespace testing {
-
-enum TypeInfoSource {
-  USE_TYPE_RESOLVER,
-};
-
-// In the unit-tests we want to test two scenarios: one with type info from
-// ServiceTypeInfo, the other with type info from TypeResolver. This class
-// wraps the detail of where the type info is from and provides the same
-// interface so the same unit-test code can test both scenarios.
-class TypeInfoTestHelper {
- public:
-  explicit TypeInfoTestHelper(TypeInfoSource type) : type_(type) {}
-
-  // Creates a TypeInfo object for the given set of descriptors.
-  void ResetTypeInfo(const std::vector<const Descriptor*>& descriptors);
-
-  // Convenient overloads.
-  void ResetTypeInfo(const Descriptor* descriptor);
-  void ResetTypeInfo(const Descriptor* descriptor1,
-                     const Descriptor* descriptor2);
-
-  // Returns the TypeInfo created after ResetTypeInfo.
-  TypeInfo* GetTypeInfo();
-
-  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,
-      ErrorListener* listener, const ProtoStreamObjectWriter::Options& options);
-
-  DefaultValueObjectWriter* NewDefaultValueWriter(const std::string& type_url,
-                                                  ObjectWriter* writer);
-
- private:
-  TypeInfoSource type_;
-  std::unique_ptr<TypeInfo> typeinfo_;
-  std::unique_ptr<TypeResolver> type_resolver_;
-};
-}  // namespace testing
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_TYPE_INFO_TEST_HELPER_H__
diff --git a/src/google/protobuf/util/internal/utility.cc b/src/google/protobuf/util/internal/utility.cc
deleted file mode 100644
index 918ee17..0000000
--- a/src/google/protobuf/util/internal/utility.cc
+++ /dev/null
@@ -1,416 +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 <google/protobuf/util/internal/utility.h>
-
-#include <algorithm>
-#include <cmath>
-#include <cstdint>
-#include <limits>
-
-#include <google/protobuf/stubs/callback.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/wrappers.pb.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/util/internal/constants.h>
-#include <google/protobuf/stubs/map_util.h>
-
-// clang-format off
-#include <google/protobuf/port_def.inc>
-// clang-format on
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-bool GetBoolOptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, bool default_value) {
-  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
-  if (opt == nullptr) {
-    return default_value;
-  }
-  return GetBoolFromAny(opt->value());
-}
-
-int64_t GetInt64OptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, int64_t default_value) {
-  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
-  if (opt == nullptr) {
-    return default_value;
-  }
-  return GetInt64FromAny(opt->value());
-}
-
-double GetDoubleOptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, double default_value) {
-  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
-  if (opt == nullptr) {
-    return default_value;
-  }
-  return GetDoubleFromAny(opt->value());
-}
-
-std::string GetStringOptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, StringPiece default_value) {
-  const google::protobuf::Option* opt = FindOptionOrNull(options, option_name);
-  if (opt == nullptr) {
-    return std::string(default_value);
-  }
-  return GetStringFromAny(opt->value());
-}
-
-template <typename T>
-void ParseFromAny(const std::string& data, T* result) {
-  result->ParseFromString(data);
-}
-
-// Returns a boolean value contained in Any type.
-// TODO(skarvaje): Add type checking & error messages here.
-bool GetBoolFromAny(const google::protobuf::Any& any) {
-  google::protobuf::BoolValue b;
-  ParseFromAny(any.value(), &b);
-  return b.value();
-}
-
-int64_t GetInt64FromAny(const google::protobuf::Any& any) {
-  google::protobuf::Int64Value i;
-  ParseFromAny(any.value(), &i);
-  return i.value();
-}
-
-double GetDoubleFromAny(const google::protobuf::Any& any) {
-  google::protobuf::DoubleValue i;
-  ParseFromAny(any.value(), &i);
-  return i.value();
-}
-
-std::string GetStringFromAny(const google::protobuf::Any& any) {
-  google::protobuf::StringValue s;
-  ParseFromAny(any.value(), &s);
-  return s.value();
-}
-
-const StringPiece GetTypeWithoutUrl(StringPiece type_url) {
-  if (type_url.size() > kTypeUrlSize && type_url[kTypeUrlSize] == '/') {
-    return type_url.substr(kTypeUrlSize + 1);
-  } else {
-    size_t idx = type_url.rfind('/');
-    if (idx != type_url.npos) {
-      type_url.remove_prefix(idx + 1);
-    }
-    return type_url;
-  }
-}
-
-const std::string GetFullTypeWithUrl(StringPiece simple_type) {
-  return StrCat(kTypeServiceBaseUrl, "/", simple_type);
-}
-
-const google::protobuf::Option* FindOptionOrNull(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name) {
-  for (int i = 0; i < options.size(); ++i) {
-    const google::protobuf::Option& opt = options.Get(i);
-    if (opt.name() == option_name) {
-      return &opt;
-    }
-  }
-  return nullptr;
-}
-
-const google::protobuf::Field* FindFieldInTypeOrNull(
-    const google::protobuf::Type* type, StringPiece field_name) {
-  if (type != nullptr) {
-    for (int i = 0; i < type->fields_size(); ++i) {
-      const google::protobuf::Field& field = type->fields(i);
-      if (field.name() == field_name) {
-        return &field;
-      }
-    }
-  }
-  return nullptr;
-}
-
-const google::protobuf::Field* FindJsonFieldInTypeOrNull(
-    const google::protobuf::Type* type, StringPiece json_name) {
-  if (type != nullptr) {
-    for (int i = 0; i < type->fields_size(); ++i) {
-      const google::protobuf::Field& field = type->fields(i);
-      if (field.json_name() == json_name) {
-        return &field;
-      }
-    }
-  }
-  return nullptr;
-}
-
-const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
-    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);
-      if (field.number() == number) {
-        return &field;
-      }
-    }
-  }
-  return nullptr;
-}
-
-const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
-    const google::protobuf::Enum* enum_type, StringPiece enum_name) {
-  if (enum_type != nullptr) {
-    for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
-      const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
-      if (enum_value.name() == enum_name) {
-        return &enum_value;
-      }
-    }
-  }
-  return nullptr;
-}
-
-const google::protobuf::EnumValue* FindEnumValueByNumberOrNull(
-    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);
-      if (enum_value.number() == value) {
-        return &enum_value;
-      }
-    }
-  }
-  return nullptr;
-}
-
-const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull(
-    const google::protobuf::Enum* enum_type, StringPiece enum_name) {
-  if (enum_type != nullptr) {
-    for (int i = 0; i < enum_type->enumvalue_size(); ++i) {
-      const google::protobuf::EnumValue& enum_value = enum_type->enumvalue(i);
-      std::string enum_name_without_underscore = enum_value.name();
-
-      // Remove underscore from the name.
-      enum_name_without_underscore.erase(
-          std::remove(enum_name_without_underscore.begin(),
-                      enum_name_without_underscore.end(), '_'),
-          enum_name_without_underscore.end());
-      // Make the name uppercase.
-      for (std::string::iterator it = enum_name_without_underscore.begin();
-           it != enum_name_without_underscore.end(); ++it) {
-        *it = ascii_toupper(*it);
-      }
-
-      if (enum_name_without_underscore == enum_name) {
-        return &enum_value;
-      }
-    }
-  }
-  return nullptr;
-}
-
-std::string EnumValueNameToLowerCamelCase(StringPiece input) {
-  std::string input_string(input);
-  std::transform(input_string.begin(), input_string.end(), input_string.begin(),
-                 ::tolower);
-  return ToCamelCase(input_string);
-}
-
-std::string ToCamelCase(StringPiece input) {
-  bool capitalize_next = false;
-  bool was_cap = true;
-  bool is_cap = false;
-  bool first_word = true;
-  std::string result;
-  result.reserve(input.size());
-
-  for (size_t i = 0; i < input.size(); ++i, was_cap = is_cap) {
-    is_cap = ascii_isupper(input[i]);
-    if (input[i] == '_') {
-      capitalize_next = true;
-      if (!result.empty()) first_word = false;
-      continue;
-    } else if (first_word) {
-      // Consider when the current character B is capitalized,
-      // first word ends when:
-      // 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])))) {
-        first_word = false;
-        result.push_back(input[i]);
-      } else {
-        result.push_back(ascii_tolower(input[i]));
-        continue;
-      }
-    } else if (capitalize_next) {
-      capitalize_next = false;
-      if (ascii_islower(input[i])) {
-        result.push_back(ascii_toupper(input[i]));
-        continue;
-      } else {
-        result.push_back(input[i]);
-        continue;
-      }
-    } else {
-      result.push_back(ascii_tolower(input[i]));
-    }
-  }
-  return result;
-}
-
-std::string ToSnakeCase(StringPiece input) {
-  bool was_not_underscore = false;  // Initialize to false for case 1 (below)
-  bool was_not_cap = false;
-  std::string result;
-  result.reserve(input.size() << 1);
-
-  for (size_t i = 0; i < input.size(); ++i) {
-    if (ascii_isupper(input[i])) {
-      // Consider when the current character B is capitalized:
-      // 1) At beginning of input:   "B..." => "b..."
-      //    (e.g. "Biscuit" => "biscuit")
-      // 2) Following a lowercase:   "...aB..." => "...a_b..."
-      //    (e.g. "gBike" => "g_bike")
-      // 3) At the end of input:     "...AB" => "...ab"
-      //    (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
-            ascii_islower(input[i + 1])))) {  // case 4 in
-        // We add an underscore for case 2 and case 4.
-        result.push_back('_');
-      }
-      result.push_back(ascii_tolower(input[i]));
-      was_not_underscore = true;
-      was_not_cap = false;
-    } else {
-      result.push_back(input[i]);
-      was_not_underscore = input[i] != '_';
-      was_not_cap = true;
-    }
-  }
-  return result;
-}
-
-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",
-    "google.protobuf.DoubleValue", "google.protobuf.FloatValue",
-    "google.protobuf.Int64Value",  "google.protobuf.UInt64Value",
-    "google.protobuf.Int32Value",  "google.protobuf.UInt32Value",
-    "google.protobuf.BoolValue",   "google.protobuf.StringValue",
-    "google.protobuf.BytesValue",  "google.protobuf.FieldMask"};
-
-void DeleteWellKnownTypes() { delete well_known_types_; }
-
-void InitWellKnownTypes() {
-  well_known_types_ = new std::set<std::string>;
-  for (int i = 0; i < GOOGLE_ARRAYSIZE(well_known_types_name_array_); ++i) {
-    well_known_types_->insert(well_known_types_name_array_[i]);
-  }
-  google::protobuf::internal::OnShutdown(&DeleteWellKnownTypes);
-}
-
-bool IsWellKnownType(const std::string& type_name) {
-  PROTOBUF_NAMESPACE_ID::internal::call_once(well_known_types_init_,
-                                             InitWellKnownTypes);
-  return ContainsKey(*well_known_types_, type_name);
-}
-
-bool IsValidBoolString(StringPiece bool_string) {
-  return bool_string == "true" || bool_string == "false" ||
-         bool_string == "1" || bool_string == "0";
-}
-
-bool IsMap(const google::protobuf::Field& field,
-           const google::protobuf::Type& type) {
-  return field.cardinality() == google::protobuf::Field::CARDINALITY_REPEATED &&
-         (GetBoolOptionOrDefault(type.options(), "map_entry", false) ||
-          GetBoolOptionOrDefault(type.options(),
-                                 "google.protobuf.MessageOptions.map_entry",
-                                 false));
-}
-
-bool IsMessageSetWireFormat(const google::protobuf::Type& type) {
-  return GetBoolOptionOrDefault(type.options(), "message_set_wire_format",
-                                false) ||
-         GetBoolOptionOrDefault(
-             type.options(),
-             "google.protobuf.MessageOptions.message_set_wire_format", false);
-}
-
-std::string DoubleAsString(double value) {
-  if (value == std::numeric_limits<double>::infinity()) return "Infinity";
-  if (value == -std::numeric_limits<double>::infinity()) return "-Infinity";
-  if (std::isnan(value)) return "NaN";
-
-  return SimpleDtoa(value);
-}
-
-std::string FloatAsString(float value) {
-  if (std::isfinite(value)) return SimpleFtoa(value);
-  return DoubleAsString(value);
-}
-
-bool SafeStrToFloat(StringPiece str, float* value) {
-  double double_value;
-  if (!safe_strtod(str, &double_value)) {
-    return false;
-  }
-
-  if (std::isinf(double_value) || std::isnan(double_value)) return false;
-
-  // Fail if the value is not representable in float.
-  if (double_value > std::numeric_limits<float>::max() ||
-      double_value < -std::numeric_limits<float>::max()) {
-    return false;
-  }
-
-  *value = static_cast<float>(double_value);
-  return true;
-}
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/internal/utility.h b/src/google/protobuf/util/internal/utility.h
deleted file mode 100644
index 79d6779..0000000
--- a/src/google/protobuf/util/internal/utility.h
+++ /dev/null
@@ -1,204 +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_UTIL_INTERNAL_UTILITY_H__
-#define GOOGLE_PROTOBUF_UTIL_INTERNAL_UTILITY_H__
-
-#include <cstdint>
-#include <memory>
-#include <string>
-#include <utility>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/any.pb.h>
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/repeated_field.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/statusor.h>
-#include <google/protobuf/stubs/status.h>
-
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace converter {
-
-// Size of "type.googleapis.com"
-static const int64_t kTypeUrlSize = 19;
-
-// Finds the tech option identified by option_name. Parses the boolean value and
-// returns it.
-// When the option with the given name is not found, default_value is returned.
-PROTOBUF_EXPORT bool GetBoolOptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, bool default_value);
-
-// Returns int64 option value. If the option isn't found, returns the
-// default_value.
-PROTOBUF_EXPORT int64_t GetInt64OptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, int64_t default_value);
-
-// Returns double option value. If the option isn't found, returns the
-// default_value.
-PROTOBUF_EXPORT double GetDoubleOptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, double default_value);
-
-// Returns string option value. If the option isn't found, returns the
-// default_value.
-PROTOBUF_EXPORT std::string GetStringOptionOrDefault(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name, StringPiece default_value);
-
-// 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/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_t GetInt64FromAny(const google::protobuf::Any& any);
-
-// Returns double value contained in Any type.
-PROTOBUF_EXPORT double GetDoubleFromAny(const google::protobuf::Any& any);
-
-// Returns string value contained in Any type.
-PROTOBUF_EXPORT std::string GetStringFromAny(const google::protobuf::Any& any);
-
-// Returns the type string without the url prefix. e.g.: If the passed type is
-// 'type.googleapis.com/tech.type.Bool', the returned value is 'tech.type.Bool'.
-PROTOBUF_EXPORT const StringPiece GetTypeWithoutUrl(
-    StringPiece type_url);
-
-// Returns the simple_type with the base type url (kTypeServiceBaseUrl)
-// prefixed.
-//
-// E.g:
-// GetFullTypeWithUrl("google.protobuf.Timestamp") returns the string
-// "type.googleapis.com/google.protobuf.Timestamp".
-PROTOBUF_EXPORT const std::string GetFullTypeWithUrl(
-    StringPiece simple_type);
-
-// Finds and returns option identified by name and option_name within the
-// provided map. Returns nullptr if none found.
-const google::protobuf::Option* FindOptionOrNull(
-    const RepeatedPtrField<google::protobuf::Option>& options,
-    StringPiece option_name);
-
-// Finds and returns the field identified by field_name in the passed tech Type
-// object. Returns nullptr if none found.
-const google::protobuf::Field* FindFieldInTypeOrNull(
-    const google::protobuf::Type* type, StringPiece field_name);
-
-// Similar to FindFieldInTypeOrNull, but this looks up fields with given
-// json_name.
-const google::protobuf::Field* FindJsonFieldInTypeOrNull(
-    const google::protobuf::Type* type, StringPiece json_name);
-
-// Similar to FindFieldInTypeOrNull, but this looks up fields by number.
-const google::protobuf::Field* FindFieldInTypeByNumberOrNull(
-    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.
-const google::protobuf::EnumValue* FindEnumValueByNameOrNull(
-    const google::protobuf::Enum* enum_type, StringPiece enum_name);
-
-// 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_t value);
-
-// Finds and returns the EnumValue identified by enum_name without underscore in
-// the passed tech Enum object. Returns nullptr if none found.
-// For Ex. if enum_name is ACTIONANDADVENTURE it can get accepted if
-// EnumValue's name is action_and_adventure or ACTION_AND_ADVENTURE.
-const google::protobuf::EnumValue* FindEnumValueByNameWithoutUnderscoreOrNull(
-    const google::protobuf::Enum* enum_type, StringPiece enum_name);
-
-// Converts input to camel-case and returns it.
-PROTOBUF_EXPORT std::string ToCamelCase(const StringPiece input);
-
-// Converts enum name string to camel-case and returns it.
-std::string EnumValueNameToLowerCamelCase(const StringPiece input);
-
-// Converts input to snake_case and returns it.
-PROTOBUF_EXPORT std::string ToSnakeCase(StringPiece input);
-
-// Returns true if type_name represents a well-known type.
-PROTOBUF_EXPORT bool IsWellKnownType(const std::string& type_name);
-
-// Returns true if 'bool_string' represents a valid boolean value. Only "true",
-// "false", "0" and "1" are allowed.
-PROTOBUF_EXPORT bool IsValidBoolString(StringPiece bool_string);
-
-// Returns true if "field" is a protobuf map field based on its type.
-PROTOBUF_EXPORT bool IsMap(const google::protobuf::Field& field,
-                           const google::protobuf::Type& type);
-
-// Returns true if the given type has special MessageSet wire format.
-bool IsMessageSetWireFormat(const google::protobuf::Type& type);
-
-// Infinity/NaN-aware conversion to string.
-PROTOBUF_EXPORT std::string DoubleAsString(double value);
-PROTOBUF_EXPORT std::string FloatAsString(float value);
-
-// Convert from int32, int64, uint32, uint64, double or float to string.
-template <typename T>
-std::string ValueAsString(T value) {
-  return StrCat(value);
-}
-
-template <>
-inline std::string ValueAsString(float value) {
-  return FloatAsString(value);
-}
-
-template <>
-inline std::string ValueAsString(double value) {
-  return DoubleAsString(value);
-}
-
-// Converts a string to float. Unlike safe_strtof, conversion will fail if the
-// value fits into double but not float (e.g., DBL_MAX).
-PROTOBUF_EXPORT bool SafeStrToFloat(StringPiece str, float* value);
-
-}  // namespace converter
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
-
-#include <google/protobuf/port_undef.inc>
-
-#endif  // GOOGLE_PROTOBUF_UTIL_INTERNAL_UTILITY_H__
diff --git a/src/google/protobuf/util/json_format.proto b/src/google/protobuf/util/json_format.proto
index 7b7100d..a2703ce 100644
--- a/src/google/protobuf/util/json_format.proto
+++ b/src/google/protobuf/util/json_format.proto
@@ -38,6 +38,9 @@
 
 package protobuf_unittest;
 
+import "google/protobuf/any.proto";
+import "google/protobuf/struct.proto";
+
 message TestFlagsAndStrings {
   required int32 A = 1;
   repeated group RepeatedGroup = 2 {
@@ -92,7 +95,6 @@
   optional uint32 f = 6;
 }
 
-
 message TestCamelCase {
   optional string normal_field = 1;
   optional int32 CAPITAL_FIELD = 2;
diff --git a/src/google/protobuf/util/json_format_proto3.proto b/src/google/protobuf/util/json_format_proto3.proto
index 0eec9da..62c2316 100644
--- a/src/google/protobuf/util/json_format_proto3.proto
+++ b/src/google/protobuf/util/json_format_proto3.proto
@@ -46,6 +46,7 @@
 enum EnumType {
   FOO = 0;
   BAR = 1;
+  TLSv1_2 = 2;
 }
 
 message MessageType {
@@ -179,10 +180,23 @@
   map<bool, int32> bool_map = 2;
 }
 
+message TestNullValue {
+  google.protobuf.NullValue null_value = 20;
+  repeated google.protobuf.NullValue repeated_null_value = 21;
+}
+
 message TestCustomJsonName {
   int32 value = 1 [json_name = "@value"];
 }
 
+message TestEvilJson {
+  int32 regular_value = 1 [json_name = "regular_name"];
+  int32 script = 2 [json_name = "</script>"];
+  int32 quotes = 3 [json_name = "unbalanced\"quotes"];
+  int32 script_and_quotes = 4
+      [json_name = "\"<script>alert('hello!);</script>"];
+}
+
 message TestExtensions {
   .protobuf_unittest.TestAllExtensions extensions = 1;
 }
@@ -192,3 +206,107 @@
   EnumType enum_value2 = 2;
   EnumType enum_value3 = 3;
 }
+
+message MapsTestCases {
+  EmptyMap empty_map = 1;
+  StringtoInt string_to_int = 2;
+  IntToString int_to_string = 3;
+  Mixed1 mixed1 = 4;
+  Mixed2 mixed2 = 5;
+  MapOfObjects map_of_objects = 6;
+
+  // Empty key tests
+  StringtoInt empty_key_string_to_int1 = 7;
+  StringtoInt empty_key_string_to_int2 = 8;
+  StringtoInt empty_key_string_to_int3 = 9;
+  BoolToString empty_key_bool_to_string = 10;
+  IntToString empty_key_int_to_string = 11;
+  Mixed1 empty_key_mixed = 12;
+  MapOfObjects empty_key_map_objects = 13;
+}
+
+message EmptyMap {
+  map<int32, int32> map = 1;
+}
+
+message StringtoInt {
+  map<string, int32> map = 1;
+}
+
+message IntToString {
+  map<int32, string> map = 1;
+}
+
+message BoolToString {
+  map<bool, string> map = 1;
+}
+
+message Mixed1 {
+  string msg = 1;
+  map<string, float> map = 2;
+}
+
+message Mixed2 {
+  enum E {
+    E0 = 0;
+    E1 = 1;
+    E2 = 2;
+    E3 = 3;
+  }
+  map<int32, bool> map = 1;
+  E ee = 2;
+}
+
+message MapOfObjects {
+  message M {
+    string inner_text = 1;
+  }
+  map<string, M> map = 1;
+}
+
+message MapIn {
+  string other = 1;
+  repeated string things = 2;
+  map<string, string> map_input = 3;
+  map<string, google.protobuf.Any> map_any = 4;
+}
+
+message MapOut {
+  map<string, MapM> map1 = 1;
+  map<string, MapOut> map2 = 2;
+  map<int32, string> map3 = 3;
+  map<bool, string> map4 = 5;
+  string bar = 4;
+}
+
+// A message with exactly the same wire representation as MapOut, but using
+// repeated message fields instead of map fields. We use this message to test
+// the wire-format compatibility of the JSON transcoder (e.g., whether it
+// handles missing keys correctly).
+message MapOutWireFormat {
+  message Map1Entry {
+    string key = 1;
+    MapM value = 2;
+  }
+  repeated Map1Entry map1 = 1;
+  message Map2Entry {
+    string key = 1;
+    MapOut value = 2;
+  }
+  repeated Map2Entry map2 = 2;
+  message Map3Entry {
+    int32 key = 1;
+    string value = 2;
+  }
+  repeated Map3Entry map3 = 3;
+  message Map4Entry {
+    bool key = 1;
+    string value = 2;
+  }
+  repeated Map4Entry map4 = 5;
+  string bar = 4;
+}
+
+message MapM {
+  string foo = 1;
+}
diff --git a/src/google/protobuf/util/json_util.cc b/src/google/protobuf/util/json_util.cc
deleted file mode 100644
index c39c10d..0000000
--- a/src/google/protobuf/util/json_util.cc
+++ /dev/null
@@ -1,284 +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 <google/protobuf/util/json_util.h>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/once.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/bytestream.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/util/internal/default_value_objectwriter.h>
-#include <google/protobuf/util/internal/error_listener.h>
-#include <google/protobuf/util/internal/json_objectwriter.h>
-#include <google/protobuf/util/internal/json_stream_parser.h>
-#include <google/protobuf/util/internal/protostream_objectsource.h>
-#include <google/protobuf/util/internal/protostream_objectwriter.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/util/type_resolver_util.h>
-#include <google/protobuf/stubs/status_macros.h>
-
-// clang-format off
-#include <google/protobuf/port_def.inc>
-// clang-format on
-
-namespace google {
-namespace protobuf {
-namespace util {
-
-namespace internal {
-ZeroCopyStreamByteSink::~ZeroCopyStreamByteSink() {
-  if (buffer_size_ > 0) {
-    stream_->BackUp(buffer_size_);
-  }
-}
-
-void ZeroCopyStreamByteSink::Append(const char* bytes, size_t len) {
-  while (true) {
-    if (len <= buffer_size_) {  // NOLINT
-      memcpy(buffer_, bytes, len);
-      buffer_ = static_cast<char*>(buffer_) + len;
-      buffer_size_ -= len;
-      return;
-    }
-    if (buffer_size_ > 0) {
-      memcpy(buffer_, bytes, buffer_size_);
-      bytes += buffer_size_;
-      len -= buffer_size_;
-    }
-    if (!stream_->Next(&buffer_, &buffer_size_)) {
-      // There isn't a way for ByteSink to report errors.
-      buffer_size_ = 0;
-      return;
-    }
-  }
-}
-}  // namespace internal
-
-util::Status BinaryToJsonStream(TypeResolver* resolver,
-                                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::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);
-  if (options.always_print_primitive_fields) {
-    converter::DefaultValueObjectWriter default_value_writer(resolver, type,
-                                                             &json_writer);
-    default_value_writer.set_preserve_proto_field_names(
-        options.preserve_proto_field_names);
-    default_value_writer.set_print_enums_as_ints(
-        options.always_print_enums_as_ints);
-    return proto_source.WriteTo(&default_value_writer);
-  } else {
-    return proto_source.WriteTo(&json_writer);
-  }
-}
-
-util::Status BinaryToJsonString(TypeResolver* resolver,
-                                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,
-                            options);
-}
-
-namespace {
-class StatusErrorListener : public converter::ErrorListener {
- public:
-  StatusErrorListener() {}
-  ~StatusErrorListener() override {}
-
-  util::Status GetStatus() { return status_; }
-
-  void InvalidName(const converter::LocationTrackerInterface& loc,
-                   StringPiece unknown_name,
-                   StringPiece message) override {
-    std::string loc_string = GetLocString(loc);
-    if (!loc_string.empty()) {
-      loc_string.append(" ");
-    }
-    status_ = util::InvalidArgumentError(
-        StrCat(loc_string, unknown_name, ": ", message));
-  }
-
-  void InvalidValue(const converter::LocationTrackerInterface& loc,
-                    StringPiece type_name,
-                    StringPiece value) override {
-    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::InvalidArgumentError(StrCat(
-        GetLocString(loc), ": missing field ", std::string(missing_name)));
-  }
-
- private:
-  util::Status status_;
-
-  std::string GetLocString(const converter::LocationTrackerInterface& loc) {
-    std::string loc_string = loc.ToString();
-    StripWhitespace(&loc_string);
-    if (!loc_string.empty()) {
-      loc_string = StrCat("(", loc_string, ")");
-    }
-    return loc_string;
-  }
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StatusErrorListener);
-};
-}  // namespace
-
-util::Status JsonToBinaryStream(TypeResolver* resolver,
-                                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);
-  StatusErrorListener listener;
-  converter::ProtoStreamObjectWriter::Options proto_writer_options;
-  proto_writer_options.ignore_unknown_fields = options.ignore_unknown_fields;
-  proto_writer_options.ignore_unknown_enum_values =
-      options.ignore_unknown_fields;
-  proto_writer_options.case_insensitive_enum_parsing =
-      options.case_insensitive_enum_parsing;
-  converter::ProtoStreamObjectWriter proto_writer(
-      resolver, type, &sink, &listener, proto_writer_options);
-
-  converter::JsonStreamParser parser(&proto_writer);
-  const void* buffer;
-  int length;
-  while (json_input->Next(&buffer, &length)) {
-    if (length == 0) continue;
-    RETURN_IF_ERROR(parser.Parse(
-        StringPiece(static_cast<const char*>(buffer), length)));
-  }
-  RETURN_IF_ERROR(parser.FinishParse());
-
-  return listener.GetStatus();
-}
-
-util::Status JsonToBinaryString(TypeResolver* resolver,
-                                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,
-                            options);
-}
-
-namespace {
-const char* kTypeUrlPrefix = "type.googleapis.com";
-TypeResolver* generated_type_resolver_ = nullptr;
-PROTOBUF_NAMESPACE_ID::internal::once_flag generated_type_resolver_init_;
-
-std::string GetTypeUrl(const Message& message) {
-  return std::string(kTypeUrlPrefix) + "/" +
-         message.GetDescriptor()->full_name();
-}
-
-void DeleteGeneratedTypeResolver() {  // NOLINT
-  delete generated_type_resolver_;
-}
-
-void InitGeneratedTypeResolver() {
-  generated_type_resolver_ = NewTypeResolverForDescriptorPool(
-      kTypeUrlPrefix, DescriptorPool::generated_pool());
-  ::google::protobuf::internal::OnShutdown(&DeleteGeneratedTypeResolver);
-}
-
-TypeResolver* GetGeneratedTypeResolver() {
-  PROTOBUF_NAMESPACE_ID::internal::call_once(generated_type_resolver_init_,
-                                             InitGeneratedTypeResolver);
-  return generated_type_resolver_;
-}
-}  // namespace
-
-util::Status MessageToJsonString(const Message& message, std::string* output,
-                                 const JsonOptions& options) {
-  const DescriptorPool* pool = message.GetDescriptor()->file()->pool();
-  TypeResolver* resolver =
-      pool == DescriptorPool::generated_pool()
-          ? GetGeneratedTypeResolver()
-          : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
-  util::Status result =
-      BinaryToJsonString(resolver, GetTypeUrl(message),
-                         message.SerializeAsString(), output, options);
-  if (pool != DescriptorPool::generated_pool()) {
-    delete resolver;
-  }
-  return result;
-}
-
-util::Status JsonStringToMessage(StringPiece input, Message* message,
-                                 const JsonParseOptions& options) {
-  const DescriptorPool* pool = message->GetDescriptor()->file()->pool();
-  TypeResolver* resolver =
-      pool == DescriptorPool::generated_pool()
-          ? GetGeneratedTypeResolver()
-          : NewTypeResolverForDescriptorPool(kTypeUrlPrefix, pool);
-  std::string binary;
-  util::Status result = JsonToBinaryString(resolver, GetTypeUrl(*message),
-                                           input, &binary, options);
-  if (result.ok() && !message->ParseFromString(binary)) {
-    result = util::InvalidArgumentError(
-        "JSON transcoder produced invalid protobuf output.");
-  }
-  if (pool != DescriptorPool::generated_pool()) {
-    delete resolver;
-  }
-  return result;
-}
-
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/json_util.h b/src/google/protobuf/util/json_util.h
index 0f1c4d8..2f4f2cb 100644
--- a/src/google/protobuf/util/json_util.h
+++ b/src/google/protobuf/util/json_util.h
@@ -33,172 +33,30 @@
 #ifndef GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
 #define GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
 
-#include <google/protobuf/stubs/bytestream.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/util/type_resolver.h>
+#include "absl/base/attributes.h"
 
-// Must be included last.
-#include <google/protobuf/port_def.inc>
+
+#include "google/protobuf/json/json.h"
 
 namespace google {
 namespace protobuf {
-namespace io {
-class ZeroCopyInputStream;
-class ZeroCopyOutputStream;
-}  // namespace io
 namespace util {
+using JsonParseOptions = ::google::protobuf::json::ParseOptions;
+using JsonPrintOptions = ::google::protobuf::json::PrintOptions;
 
-struct JsonParseOptions {
-  // Whether to ignore unknown JSON fields during parsing
-  bool ignore_unknown_fields;
+using JsonOptions ABSL_DEPRECATED("use JsonPrintOptions instead") =
+    JsonPrintOptions;
 
-  // If true, when a lowercase enum value fails to parse, try convert it to
-  // UPPER_CASE and see if it matches a valid enum.
-  // WARNING: This option exists only to preserve legacy behavior. Avoid using
-  // this option. If your enum needs to support different casing, consider using
-  // allow_alias instead.
-  bool case_insensitive_enum_parsing;
+using ::google::protobuf::json::BinaryToJsonStream;
+using ::google::protobuf::json::BinaryToJsonString;
 
-  JsonParseOptions()
-      : ignore_unknown_fields(false), case_insensitive_enum_parsing(false) {}
-};
+using ::google::protobuf::json::JsonStringToMessage;
+using ::google::protobuf::json::JsonToBinaryStream;
 
-struct JsonPrintOptions {
-  // Whether to add spaces, line breaks and indentation to make the JSON output
-  // easy to read.
-  bool add_whitespace;
-  // Whether to always print primitive fields. By default proto3 primitive
-  // fields with default values will be omitted in JSON output. For example, an
-  // int32 field set to 0 will be omitted. Set this flag to true will override
-  // the default behavior and print primitive fields regardless of their values.
-  bool always_print_primitive_fields;
-  // Whether to always print enums as ints. By default they are rendered as
-  // strings.
-  bool always_print_enums_as_ints;
-  // Whether to preserve proto field names
-  bool preserve_proto_field_names;
-
-  JsonPrintOptions()
-      : add_whitespace(false),
-        always_print_primitive_fields(false),
-        always_print_enums_as_ints(false),
-        preserve_proto_field_names(false) {}
-};
-
-// DEPRECATED. Use JsonPrintOptions instead.
-typedef JsonPrintOptions JsonOptions;
-
-// Converts from protobuf message to JSON and appends it to |output|. This is a
-// 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);
-
-inline util::Status MessageToJsonString(const Message& message,
-                                        std::string* output) {
-  return MessageToJsonString(message, output, JsonOptions());
-}
-
-// Converts from JSON to protobuf message. This is a simple wrapper of
-// JsonStringToBinary(). It will use the DescriptorPool of the passed-in
-// message to resolve Any types.
-PROTOBUF_EXPORT util::Status JsonStringToMessage(
-    StringPiece input, Message* message, const JsonParseOptions& options);
-
-inline util::Status JsonStringToMessage(StringPiece input,
-                                        Message* message) {
-  return JsonStringToMessage(input, message, JsonParseOptions());
-}
-
-// Converts protobuf binary data to JSON.
-// The conversion will fail if:
-//   1. TypeResolver fails to resolve a type.
-//   2. input is not valid protobuf wire format, or conflicts with the type
-//      information returned by TypeResolver.
-// Note that unknown fields will be discarded silently.
-PROTOBUF_EXPORT util::Status BinaryToJsonStream(
-    TypeResolver* resolver, const std::string& type_url,
-    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) {
-  return BinaryToJsonStream(resolver, type_url, binary_input, json_output,
-                            JsonPrintOptions());
-}
-
-PROTOBUF_EXPORT util::Status BinaryToJsonString(
-    TypeResolver* resolver, const std::string& type_url,
-    const std::string& binary_input, std::string* json_output,
-    const JsonPrintOptions& options);
-
-inline util::Status BinaryToJsonString(TypeResolver* resolver,
-                                       const std::string& type_url,
-                                       const std::string& binary_input,
-                                       std::string* json_output) {
-  return BinaryToJsonString(resolver, type_url, binary_input, json_output,
-                            JsonPrintOptions());
-}
-
-// Converts JSON data to protobuf binary format.
-// The conversion will fail if:
-//   1. TypeResolver fails to resolve a type.
-//   2. input is not valid JSON format, or conflicts with the type
-//      information returned by TypeResolver.
-PROTOBUF_EXPORT util::Status JsonToBinaryStream(
-    TypeResolver* resolver, const std::string& type_url,
-    io::ZeroCopyInputStream* json_input,
-    io::ZeroCopyOutputStream* binary_output, const JsonParseOptions& options);
-
-inline util::Status JsonToBinaryStream(
-    TypeResolver* resolver, const std::string& type_url,
-    io::ZeroCopyInputStream* json_input,
-    io::ZeroCopyOutputStream* binary_output) {
-  return JsonToBinaryStream(resolver, type_url, json_input, binary_output,
-                            JsonParseOptions());
-}
-
-PROTOBUF_EXPORT util::Status JsonToBinaryString(
-    TypeResolver* resolver, const std::string& type_url,
-    StringPiece json_input, std::string* binary_output,
-    const JsonParseOptions& options);
-
-inline util::Status JsonToBinaryString(TypeResolver* resolver,
-                                       const std::string& type_url,
-                                       StringPiece json_input,
-                                       std::string* binary_output) {
-  return JsonToBinaryString(resolver, type_url, json_input, binary_output,
-                            JsonParseOptions());
-}
-
-namespace internal {
-// Internal helper class. Put in the header so we can write unit-tests for it.
-class PROTOBUF_EXPORT ZeroCopyStreamByteSink : public strings::ByteSink {
- public:
-  explicit ZeroCopyStreamByteSink(io::ZeroCopyOutputStream* stream)
-      : stream_(stream), buffer_(nullptr), buffer_size_(0) {}
-  ~ZeroCopyStreamByteSink() override;
-
-  void Append(const char* bytes, size_t len) override;
-
- private:
-  io::ZeroCopyOutputStream* stream_;
-  void* buffer_;
-  int buffer_size_;
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(ZeroCopyStreamByteSink);
-};
-}  // namespace internal
-
+using ::google::protobuf::json::JsonToBinaryString;
+using ::google::protobuf::json::MessageToJsonString;
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
-
 #endif  // GOOGLE_PROTOBUF_UTIL_JSON_UTIL_H__
diff --git a/src/google/protobuf/util/json_util_test.cc b/src/google/protobuf/util/json_util_test.cc
deleted file mode 100644
index 7216199..0000000
--- a/src/google/protobuf/util/json_util_test.cc
+++ /dev/null
@@ -1,672 +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 <google/protobuf/util/json_util.h>
-
-#include <cstdint>
-#include <list>
-#include <string>
-
-#include <google/protobuf/util/internal/testdata/maps.pb.h>
-#include <google/protobuf/util/json_format.pb.h>
-#include <google/protobuf/util/json_format_proto3.pb.h>
-#include <gtest/gtest.h>
-#include <google/protobuf/descriptor_database.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/util/type_resolver_util.h>
-
-namespace google {
-namespace protobuf {
-namespace util {
-namespace {
-
-using proto3::BAR;
-using proto3::FOO;
-using proto3::TestAny;
-using proto3::TestEnumValue;
-using proto3::TestMap;
-using proto3::TestMessage;
-using proto3::TestOneof;
-using proto_util_converter::testing::MapIn;
-
-// As functions defined in json_util.h are just thin wrappers around the
-// JSON conversion code in //net/proto2/util/converter, in this test we
-// only cover some very basic cases to make sure the wrappers have forwarded
-// parameters to the underlying implementation correctly. More detailed
-// tests are contained in the //net/proto2/util/converter directory.
-class JsonUtilTest : public ::testing::Test {
- protected:
-  JsonUtilTest() {}
-
-  std::string ToJson(const Message& message, const JsonPrintOptions& options) {
-    std::string result;
-    GOOGLE_CHECK_OK(MessageToJsonString(message, &result, options));
-    return result;
-  }
-
-  bool FromJson(const std::string& json, Message* message,
-                const JsonParseOptions& options) {
-    return JsonStringToMessage(json, message, options).ok();
-  }
-
-  bool FromJson(const std::string& json, Message* message) {
-    return FromJson(json, message, JsonParseOptions());
-  }
-
-  std::unique_ptr<TypeResolver> resolver_;
-};
-
-TEST_F(JsonUtilTest, TestWhitespaces) {
-  TestMessage m;
-  m.mutable_message_value();
-
-  JsonPrintOptions options;
-  EXPECT_EQ("{\"messageValue\":{}}", ToJson(m, options));
-  options.add_whitespace = true;
-  EXPECT_EQ(
-      "{\n"
-      " \"messageValue\": {}\n"
-      "}\n",
-      ToJson(m, options));
-}
-
-TEST_F(JsonUtilTest, TestDefaultValues) {
-  TestMessage m;
-  JsonPrintOptions options;
-  EXPECT_EQ("{}", ToJson(m, options));
-  options.always_print_primitive_fields = true;
-  EXPECT_EQ(
-      "{\"boolValue\":false,"
-      "\"int32Value\":0,"
-      "\"int64Value\":\"0\","
-      "\"uint32Value\":0,"
-      "\"uint64Value\":\"0\","
-      "\"floatValue\":0,"
-      "\"doubleValue\":0,"
-      "\"stringValue\":\"\","
-      "\"bytesValue\":\"\","
-      "\"enumValue\":\"FOO\","
-      "\"repeatedBoolValue\":[],"
-      "\"repeatedInt32Value\":[],"
-      "\"repeatedInt64Value\":[],"
-      "\"repeatedUint32Value\":[],"
-      "\"repeatedUint64Value\":[],"
-      "\"repeatedFloatValue\":[],"
-      "\"repeatedDoubleValue\":[],"
-      "\"repeatedStringValue\":[],"
-      "\"repeatedBytesValue\":[],"
-      "\"repeatedEnumValue\":[],"
-      "\"repeatedMessageValue\":[]"
-      "}",
-      ToJson(m, options));
-
-  options.always_print_primitive_fields = true;
-  m.set_string_value("i am a test string value");
-  m.set_bytes_value("i am a test bytes value");
-  EXPECT_EQ(
-      "{\"boolValue\":false,"
-      "\"int32Value\":0,"
-      "\"int64Value\":\"0\","
-      "\"uint32Value\":0,"
-      "\"uint64Value\":\"0\","
-      "\"floatValue\":0,"
-      "\"doubleValue\":0,"
-      "\"stringValue\":\"i am a test string value\","
-      "\"bytesValue\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
-      "\"enumValue\":\"FOO\","
-      "\"repeatedBoolValue\":[],"
-      "\"repeatedInt32Value\":[],"
-      "\"repeatedInt64Value\":[],"
-      "\"repeatedUint32Value\":[],"
-      "\"repeatedUint64Value\":[],"
-      "\"repeatedFloatValue\":[],"
-      "\"repeatedDoubleValue\":[],"
-      "\"repeatedStringValue\":[],"
-      "\"repeatedBytesValue\":[],"
-      "\"repeatedEnumValue\":[],"
-      "\"repeatedMessageValue\":[]"
-      "}",
-      ToJson(m, options));
-
-  options.preserve_proto_field_names = true;
-  m.set_string_value("i am a test string value");
-  m.set_bytes_value("i am a test bytes value");
-  EXPECT_EQ(
-      "{\"bool_value\":false,"
-      "\"int32_value\":0,"
-      "\"int64_value\":\"0\","
-      "\"uint32_value\":0,"
-      "\"uint64_value\":\"0\","
-      "\"float_value\":0,"
-      "\"double_value\":0,"
-      "\"string_value\":\"i am a test string value\","
-      "\"bytes_value\":\"aSBhbSBhIHRlc3QgYnl0ZXMgdmFsdWU=\","
-      "\"enum_value\":\"FOO\","
-      "\"repeated_bool_value\":[],"
-      "\"repeated_int32_value\":[],"
-      "\"repeated_int64_value\":[],"
-      "\"repeated_uint32_value\":[],"
-      "\"repeated_uint64_value\":[],"
-      "\"repeated_float_value\":[],"
-      "\"repeated_double_value\":[],"
-      "\"repeated_string_value\":[],"
-      "\"repeated_bytes_value\":[],"
-      "\"repeated_enum_value\":[],"
-      "\"repeated_message_value\":[]"
-      "}",
-      ToJson(m, options));
-}
-
-TEST_F(JsonUtilTest, TestPreserveProtoFieldNames) {
-  TestMessage m;
-  m.mutable_message_value();
-
-  JsonPrintOptions options;
-  options.preserve_proto_field_names = true;
-  EXPECT_EQ("{\"message_value\":{}}", ToJson(m, options));
-}
-
-TEST_F(JsonUtilTest, TestAlwaysPrintEnumsAsInts) {
-  TestMessage orig;
-  orig.set_enum_value(proto3::BAR);
-  orig.add_repeated_enum_value(proto3::FOO);
-  orig.add_repeated_enum_value(proto3::BAR);
-
-  JsonPrintOptions print_options;
-  print_options.always_print_enums_as_ints = true;
-
-  std::string expected_json = "{\"enumValue\":1,\"repeatedEnumValue\":[0,1]}";
-  EXPECT_EQ(expected_json, ToJson(orig, print_options));
-
-  TestMessage parsed;
-  JsonParseOptions parse_options;
-  ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
-
-  EXPECT_EQ(proto3::BAR, parsed.enum_value());
-  EXPECT_EQ(2, parsed.repeated_enum_value_size());
-  EXPECT_EQ(proto3::FOO, parsed.repeated_enum_value(0));
-  EXPECT_EQ(proto3::BAR, parsed.repeated_enum_value(1));
-}
-
-TEST_F(JsonUtilTest, TestPrintEnumsAsIntsWithDefaultValue) {
-  TestEnumValue orig;
-  // orig.set_enum_value1(proto3::FOO)
-  orig.set_enum_value2(proto3::FOO);
-  orig.set_enum_value3(proto3::BAR);
-
-  JsonPrintOptions print_options;
-  print_options.always_print_enums_as_ints = true;
-  print_options.always_print_primitive_fields = true;
-
-  std::string expected_json =
-      "{\"enumValue1\":0,\"enumValue2\":0,\"enumValue3\":1}";
-  EXPECT_EQ(expected_json, ToJson(orig, print_options));
-
-  TestEnumValue parsed;
-  JsonParseOptions parse_options;
-  ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
-
-  EXPECT_EQ(proto3::FOO, parsed.enum_value1());
-  EXPECT_EQ(proto3::FOO, parsed.enum_value2());
-  EXPECT_EQ(proto3::BAR, parsed.enum_value3());
-}
-
-TEST_F(JsonUtilTest, TestPrintProto2EnumAsIntWithDefaultValue) {
-  protobuf_unittest::TestDefaultEnumValue orig;
-
-  JsonPrintOptions print_options;
-  // use enum as int
-  print_options.always_print_enums_as_ints = true;
-  print_options.always_print_primitive_fields = true;
-
-  // result should be int rather than string
-  std::string expected_json = "{\"enumValue\":2}";
-  EXPECT_EQ(expected_json, ToJson(orig, print_options));
-
-  protobuf_unittest::TestDefaultEnumValue parsed;
-  JsonParseOptions parse_options;
-  ASSERT_TRUE(FromJson(expected_json, &parsed, parse_options));
-
-  EXPECT_EQ(protobuf_unittest::DEFAULT, parsed.enum_value());
-}
-
-TEST_F(JsonUtilTest, ParseMessage) {
-  // Some random message but good enough to verify that the parsing wrapper
-  // functions are working properly.
-  std::string input =
-      "{\n"
-      "  \"int32Value\": 1234567891,\n"
-      "  \"int64Value\": 5302428716536692736,\n"
-      "  \"floatValue\": 3.4028235e+38,\n"
-      "  \"repeatedInt32Value\": [1, 2],\n"
-      "  \"messageValue\": {\n"
-      "    \"value\": 2048\n"
-      "  },\n"
-      "  \"repeatedMessageValue\": [\n"
-      "    {\"value\": 40}, {\"value\": 96}\n"
-      "  ]\n"
-      "}\n";
-  JsonParseOptions options;
-  TestMessage m;
-  ASSERT_TRUE(FromJson(input, &m, options));
-  EXPECT_EQ(1234567891, m.int32_value());
-  EXPECT_EQ(5302428716536692736, m.int64_value());
-  EXPECT_EQ(3.402823466e+38f, m.float_value());
-  ASSERT_EQ(2, m.repeated_int32_value_size());
-  EXPECT_EQ(1, m.repeated_int32_value(0));
-  EXPECT_EQ(2, m.repeated_int32_value(1));
-  EXPECT_EQ(2048, m.message_value().value());
-  ASSERT_EQ(2, m.repeated_message_value_size());
-  EXPECT_EQ(40, m.repeated_message_value(0).value());
-  EXPECT_EQ(96, m.repeated_message_value(1).value());
-}
-
-TEST_F(JsonUtilTest, ParseMap) {
-  TestMap message;
-  (*message.mutable_string_map())["hello"] = 1234;
-  JsonPrintOptions print_options;
-  JsonParseOptions parse_options;
-  EXPECT_EQ("{\"stringMap\":{\"hello\":1234}}", ToJson(message, print_options));
-  TestMap other;
-  ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
-  EXPECT_EQ(message.DebugString(), other.DebugString());
-}
-
-TEST_F(JsonUtilTest, ParsePrimitiveMapIn) {
-  MapIn message;
-  JsonPrintOptions print_options;
-  print_options.always_print_primitive_fields = true;
-  JsonParseOptions parse_options;
-  EXPECT_EQ("{\"other\":\"\",\"things\":[],\"mapInput\":{},\"mapAny\":{}}",
-            ToJson(message, print_options));
-  MapIn other;
-  ASSERT_TRUE(FromJson(ToJson(message, print_options), &other, parse_options));
-  EXPECT_EQ(message.DebugString(), other.DebugString());
-}
-
-TEST_F(JsonUtilTest, PrintPrimitiveOneof) {
-  TestOneof message;
-  JsonPrintOptions options;
-  options.always_print_primitive_fields = true;
-  message.mutable_oneof_message_value();
-  EXPECT_EQ("{\"oneofMessageValue\":{\"value\":0}}", ToJson(message, options));
-
-  message.set_oneof_int32_value(1);
-  EXPECT_EQ("{\"oneofInt32Value\":1}", ToJson(message, options));
-}
-
-TEST_F(JsonUtilTest, TestParseIgnoreUnknownFields) {
-  TestMessage m;
-  JsonParseOptions options;
-  options.ignore_unknown_fields = true;
-  EXPECT_TRUE(FromJson("{\"unknownName\":0}", &m, options));
-}
-
-TEST_F(JsonUtilTest, TestParseErrors) {
-  TestMessage m;
-  JsonParseOptions options;
-  // Parsing should fail if the field name can not be recognized.
-  EXPECT_FALSE(FromJson("{\"unknownName\":0}", &m, options));
-  // Parsing should fail if the value is invalid.
-  EXPECT_FALSE(FromJson("{\"int32Value\":2147483648}", &m, options));
-}
-
-TEST_F(JsonUtilTest, TestDynamicMessage) {
-  // Some random message but good enough to test the wrapper functions.
-  std::string input =
-      "{\n"
-      "  \"int32Value\": 1024,\n"
-      "  \"repeatedInt32Value\": [1, 2],\n"
-      "  \"messageValue\": {\n"
-      "    \"value\": 2048\n"
-      "  },\n"
-      "  \"repeatedMessageValue\": [\n"
-      "    {\"value\": 40}, {\"value\": 96}\n"
-      "  ]\n"
-      "}\n";
-
-  // Create a new DescriptorPool with the same protos as the generated one.
-  DescriptorPoolDatabase database(*DescriptorPool::generated_pool());
-  DescriptorPool pool(&database);
-  // A dynamic version of the test proto.
-  DynamicMessageFactory factory;
-  std::unique_ptr<Message> message(
-      factory.GetPrototype(pool.FindMessageTypeByName("proto3.TestMessage"))
-          ->New());
-  EXPECT_TRUE(FromJson(input, message.get()));
-
-  // Convert to generated message for easy inspection.
-  TestMessage generated;
-  EXPECT_TRUE(generated.ParseFromString(message->SerializeAsString()));
-  EXPECT_EQ(1024, generated.int32_value());
-  ASSERT_EQ(2, generated.repeated_int32_value_size());
-  EXPECT_EQ(1, generated.repeated_int32_value(0));
-  EXPECT_EQ(2, generated.repeated_int32_value(1));
-  EXPECT_EQ(2048, generated.message_value().value());
-  ASSERT_EQ(2, generated.repeated_message_value_size());
-  EXPECT_EQ(40, generated.repeated_message_value(0).value());
-  EXPECT_EQ(96, generated.repeated_message_value(1).value());
-
-  JsonOptions options;
-  EXPECT_EQ(ToJson(generated, options), ToJson(*message, options));
-}
-
-TEST_F(JsonUtilTest, TestParsingUnknownAnyFields) {
-  std::string input =
-      "{\n"
-      "  \"value\": {\n"
-      "    \"@type\": \"type.googleapis.com/proto3.TestMessage\",\n"
-      "    \"unknown_field\": \"UNKNOWN_VALUE\",\n"
-      "    \"string_value\": \"expected_value\"\n"
-      "  }\n"
-      "}";
-
-  TestAny m;
-  JsonParseOptions options;
-  EXPECT_FALSE(FromJson(input, &m, options));
-
-  options.ignore_unknown_fields = true;
-  EXPECT_TRUE(FromJson(input, &m, options));
-
-  TestMessage t;
-  EXPECT_TRUE(m.value().UnpackTo(&t));
-  EXPECT_EQ("expected_value", t.string_value());
-}
-
-TEST_F(JsonUtilTest, TestParsingUnknownEnumsProto2) {
-  std::string input =
-      "{\n"
-      "  \"a\": \"UNKNOWN_VALUE\"\n"
-      "}";
-  protobuf_unittest::TestNumbers m;
-  JsonParseOptions options;
-  EXPECT_FALSE(FromJson(input, &m, options));
-
-  options.ignore_unknown_fields = true;
-  EXPECT_TRUE(FromJson(input, &m, options));
-  EXPECT_FALSE(m.has_a());
-}
-
-TEST_F(JsonUtilTest, TestParsingUnknownEnumsProto3) {
-  TestMessage m;
-  {
-    JsonParseOptions options;
-    ASSERT_FALSE(options.ignore_unknown_fields);
-    std::string input =
-        "{\n"
-        "  \"enum_value\":\"UNKNOWN_VALUE\"\n"
-        "}";
-    m.set_enum_value(proto3::BAR);
-    EXPECT_FALSE(FromJson(input, &m, options));
-    ASSERT_EQ(proto3::BAR, m.enum_value());  // Keep previous value
-
-    options.ignore_unknown_fields = true;
-    EXPECT_TRUE(FromJson(input, &m, options));
-    EXPECT_EQ(0, m.enum_value());  // Unknown enum value must be decoded as 0
-  }
-  // Integer values are read as usual
-  {
-    JsonParseOptions options;
-    std::string input =
-        "{\n"
-        "  \"enum_value\":12345\n"
-        "}";
-    m.set_enum_value(proto3::BAR);
-    EXPECT_TRUE(FromJson(input, &m, options));
-    ASSERT_EQ(12345, m.enum_value());
-
-    options.ignore_unknown_fields = true;
-    EXPECT_TRUE(FromJson(input, &m, options));
-    EXPECT_EQ(12345, m.enum_value());
-  }
-
-  // Trying to pass an object as an enum field value is always treated as an
-  // error
-  {
-    JsonParseOptions options;
-    std::string input =
-        "{\n"
-        "  \"enum_value\":{}\n"
-        "}";
-    options.ignore_unknown_fields = true;
-    EXPECT_FALSE(FromJson(input, &m, options));
-    options.ignore_unknown_fields = false;
-    EXPECT_FALSE(FromJson(input, &m, options));
-  }
-  // Trying to pass an array as an enum field value is always treated as an
-  // error
-  {
-    JsonParseOptions options;
-    std::string input =
-        "{\n"
-        "  \"enum_value\":[]\n"
-        "}";
-    EXPECT_FALSE(FromJson(input, &m, options));
-    options.ignore_unknown_fields = true;
-    EXPECT_FALSE(FromJson(input, &m, options));
-  }
-}
-
-TEST_F(JsonUtilTest, TestParsingEnumIgnoreCase) {
-  TestMessage m;
-  {
-    JsonParseOptions options;
-    std::string input =
-        "{\n"
-        "  \"enum_value\":\"bar\"\n"
-        "}";
-    m.set_enum_value(proto3::FOO);
-    EXPECT_FALSE(FromJson(input, &m, options));
-    // Default behavior is case-sensitive, so keep previous value.
-    ASSERT_EQ(proto3::FOO, m.enum_value());
-  }
-  {
-    JsonParseOptions options;
-    options.case_insensitive_enum_parsing = false;
-    std::string input =
-        "{\n"
-        "  \"enum_value\":\"bar\"\n"
-        "}";
-    m.set_enum_value(proto3::FOO);
-    EXPECT_FALSE(FromJson(input, &m, options));
-    ASSERT_EQ(proto3::FOO, m.enum_value());  // Keep previous value
-  }
-  {
-    JsonParseOptions options;
-    options.case_insensitive_enum_parsing = true;
-    std::string input =
-        "{\n"
-        "  \"enum_value\":\"bar\"\n"
-        "}";
-    m.set_enum_value(proto3::FOO);
-    EXPECT_TRUE(FromJson(input, &m, options));
-    ASSERT_EQ(proto3::BAR, m.enum_value());
-  }
-}
-
-typedef std::pair<char*, int> Segment;
-// A ZeroCopyOutputStream that writes to multiple buffers.
-class SegmentedZeroCopyOutputStream : public io::ZeroCopyOutputStream {
- public:
-  explicit SegmentedZeroCopyOutputStream(std::list<Segment> segments)
-      : segments_(segments),
-        last_segment_(static_cast<char*>(NULL), 0),
-        byte_count_(0) {}
-
-  bool Next(void** buffer, int* length) override {
-    if (segments_.empty()) {
-      return false;
-    }
-    last_segment_ = segments_.front();
-    segments_.pop_front();
-    *buffer = last_segment_.first;
-    *length = last_segment_.second;
-    byte_count_ += *length;
-    return true;
-  }
-
-  void BackUp(int length) override {
-    GOOGLE_CHECK(length <= last_segment_.second);
-    segments_.push_front(
-        Segment(last_segment_.first + last_segment_.second - length, length));
-    last_segment_ = Segment(last_segment_.first, last_segment_.second - length);
-    byte_count_ -= length;
-  }
-
-  int64_t ByteCount() const override { return byte_count_; }
-
- private:
-  std::list<Segment> segments_;
-  Segment last_segment_;
-  int64_t byte_count_;
-};
-
-// This test splits the output buffer and also the input data into multiple
-// segments and checks that the implementation of ZeroCopyStreamByteSink
-// handles all possible cases correctly.
-TEST(ZeroCopyStreamByteSinkTest, TestAllInputOutputPatterns) {
-  static const int kOutputBufferLength = 10;
-  // An exhaustive test takes too long, skip some combinations to make the test
-  // run faster.
-  static const int kSkippedPatternCount = 7;
-
-  char buffer[kOutputBufferLength];
-  for (int split_pattern = 0; split_pattern < (1 << (kOutputBufferLength - 1));
-       split_pattern += kSkippedPatternCount) {
-    // Split the buffer into small segments according to the split_pattern.
-    std::list<Segment> segments;
-    int segment_start = 0;
-    for (int i = 0; i < kOutputBufferLength - 1; ++i) {
-      if (split_pattern & (1 << i)) {
-        segments.push_back(
-            Segment(buffer + segment_start, i - segment_start + 1));
-        segment_start = i + 1;
-      }
-    }
-    segments.push_back(
-        Segment(buffer + segment_start, kOutputBufferLength - segment_start));
-
-    // Write exactly 10 bytes through the ByteSink.
-    std::string input_data = "0123456789";
-    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
-         input_pattern += kSkippedPatternCount) {
-      memset(buffer, 0, sizeof(buffer));
-      {
-        SegmentedZeroCopyOutputStream output_stream(segments);
-        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
-        int start = 0;
-        for (int j = 0; j < input_data.length() - 1; ++j) {
-          if (input_pattern & (1 << j)) {
-            byte_sink.Append(&input_data[start], j - start + 1);
-            start = j + 1;
-          }
-        }
-        byte_sink.Append(&input_data[start], input_data.length() - start);
-      }
-      EXPECT_EQ(input_data, std::string(buffer, input_data.length()));
-    }
-
-    // Write only 9 bytes through the ByteSink.
-    input_data = "012345678";
-    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
-         input_pattern += kSkippedPatternCount) {
-      memset(buffer, 0, sizeof(buffer));
-      {
-        SegmentedZeroCopyOutputStream output_stream(segments);
-        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
-        int start = 0;
-        for (int j = 0; j < input_data.length() - 1; ++j) {
-          if (input_pattern & (1 << j)) {
-            byte_sink.Append(&input_data[start], j - start + 1);
-            start = j + 1;
-          }
-        }
-        byte_sink.Append(&input_data[start], input_data.length() - start);
-      }
-      EXPECT_EQ(input_data, std::string(buffer, input_data.length()));
-      EXPECT_EQ(0, buffer[input_data.length()]);
-    }
-
-    // Write 11 bytes through the ByteSink. The extra byte will just
-    // be ignored.
-    input_data = "0123456789A";
-    for (int input_pattern = 0; input_pattern < (1 << (input_data.size() - 1));
-         input_pattern += kSkippedPatternCount) {
-      memset(buffer, 0, sizeof(buffer));
-      {
-        SegmentedZeroCopyOutputStream output_stream(segments);
-        internal::ZeroCopyStreamByteSink byte_sink(&output_stream);
-        int start = 0;
-        for (int j = 0; j < input_data.length() - 1; ++j) {
-          if (input_pattern & (1 << j)) {
-            byte_sink.Append(&input_data[start], j - start + 1);
-            start = j + 1;
-          }
-        }
-        byte_sink.Append(&input_data[start], input_data.length() - start);
-      }
-      EXPECT_EQ(input_data.substr(0, kOutputBufferLength),
-                std::string(buffer, kOutputBufferLength));
-    }
-  }
-}
-
-TEST_F(JsonUtilTest, TestWrongJsonInput) {
-  const char json[] = "{\"unknown_field\":\"some_value\"}";
-  io::ArrayInputStream input_stream(json, strlen(json));
-  char proto_buffer[10000];
-  io::ArrayOutputStream output_stream(proto_buffer, sizeof(proto_buffer));
-  std::string message_type = "type.googleapis.com/proto3.TestMessage";
-  TypeResolver* resolver = NewTypeResolverForDescriptorPool(
-      "type.googleapis.com", DescriptorPool::generated_pool());
-
-  auto result_status = util::JsonToBinaryStream(resolver, message_type,
-                                                &input_stream, &output_stream);
-
-  delete resolver;
-
-  EXPECT_FALSE(result_status.ok());
-  EXPECT_TRUE(util::IsInvalidArgument(result_status));
-}
-
-TEST_F(JsonUtilTest, HtmlEscape) {
-  TestMessage m;
-  m.set_string_value("</script>");
-  JsonPrintOptions options;
-  EXPECT_EQ("{\"stringValue\":\"\\u003c/script\\u003e\"}", ToJson(m, options));
-}
-
-}  // namespace
-}  // namespace util
-}  // namespace protobuf
-}  // namespace google
diff --git a/src/google/protobuf/util/message_differencer.cc b/src/google/protobuf/util/message_differencer.cc
index 30560ed..6843a3e 100644
--- a/src/google/protobuf/util/message_differencer.cc
+++ b/src/google/protobuf/util/message_differencer.cc
@@ -32,7 +32,7 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/util/message_differencer.h>
+#include "google/protobuf/util/message_differencer.h"
 
 #include <algorithm>
 #include <cstddef>
@@ -42,24 +42,27 @@
 #include <memory>
 #include <utility>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/printer.h>
-#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/stubs/strutil.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/util/field_comparator.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/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 "absl/container/fixed_array.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/match.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "google/protobuf/io/printer.h"
+#include "google/protobuf/io/zero_copy_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/util/field_comparator.h"
 
 // Always include as last one, otherwise it can break compilation
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -152,10 +155,16 @@
     key_field_path.push_back(key);
     key_field_paths_.push_back(key_field_path);
   }
+  MultipleFieldsMapKeyComparator(const MultipleFieldsMapKeyComparator&) =
+      delete;
+  MultipleFieldsMapKeyComparator& operator=(
+      const MultipleFieldsMapKeyComparator&) = delete;
   bool IsMatch(const Message& message1, const Message& message2,
+               int unpacked_any,
                const std::vector<SpecificField>& parent_fields) const override {
     for (const auto& path : key_field_paths_) {
-      if (!IsMatchInternal(message1, message2, parent_fields, path, 0)) {
+      if (!IsMatchInternal(message1, message2, unpacked_any, parent_fields,
+                           path, 0)) {
         return false;
       }
     }
@@ -164,7 +173,7 @@
 
  private:
   bool IsMatchInternal(
-      const Message& message1, const Message& message2,
+      const Message& message1, const Message& message2, int unpacked_any,
       const std::vector<SpecificField>& parent_fields,
       const std::vector<const FieldDescriptor*>& key_field_path,
       int path_index) const {
@@ -172,14 +181,15 @@
     std::vector<SpecificField> current_parent_fields(parent_fields);
     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);
+        return message_differencer_->CompareMapField(
+            message1, message2, unpacked_any, field, &current_parent_fields);
       } else if (field->is_repeated()) {
         return message_differencer_->CompareRepeatedField(
-            message1, message2, field, &current_parent_fields);
+            message1, message2, unpacked_any, field, &current_parent_fields);
       } else {
         return message_differencer_->CompareFieldValueUsingParentFields(
-            message1, message2, field, -1, -1, &current_parent_fields);
+            message1, message2, unpacked_any, field, -1, -1,
+            &current_parent_fields);
       }
     } else {
       const Reflection* reflection1 = message1.GetReflection();
@@ -193,17 +203,19 @@
         return false;
       }
       SpecificField specific_field;
+      specific_field.message1 = &message1;
+      specific_field.message2 = &message2;
+      specific_field.unpacked_any = unpacked_any;
       specific_field.field = field;
       current_parent_fields.push_back(specific_field);
       return IsMatchInternal(reflection1->GetMessage(message1, field),
                              reflection2->GetMessage(message2, field),
-                             current_parent_fields, key_field_path,
-                             path_index + 1);
+                             false /*key is never Any*/, current_parent_fields,
+                             key_field_path, path_index + 1);
     }
   }
   MessageDifferencer* message_differencer_;
   std::vector<std::vector<const FieldDescriptor*> > key_field_paths_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MultipleFieldsMapKeyComparator);
 };
 
 // Preserve the order when treating repeated field as SMART_LIST. The current
@@ -254,7 +266,7 @@
     : message_differencer_(message_differencer) {}
 
 bool MessageDifferencer::MapEntryKeyComparator::IsMatch(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const std::vector<SpecificField>& parent_fields) const {
   // Map entry has its key in the field with tag 1.  See the comment for
   // map_entry in MessageOptions.
@@ -268,11 +280,11 @@
 
   std::vector<SpecificField> current_parent_fields(parent_fields);
   if (treat_as_set) {
-    return message_differencer_->Compare(message1, message2,
+    return message_differencer_->Compare(message1, message2, unpacked_any,
                                          &current_parent_fields);
   }
   return message_differencer_->CompareFieldValueUsingParentFields(
-      message1, message2, key, -1, -1, &current_parent_fields);
+      message1, message2, unpacked_any, key, -1, -1, &current_parent_fields);
 }
 
 bool MessageDifferencer::Equals(const Message& message1,
@@ -326,9 +338,6 @@
   for (MapKeyComparator* comparator : owned_key_comparators_) {
     delete comparator;
   }
-  for (IgnoreCriteria* criteria : ignore_criteria_) {
-    delete criteria;
-  }
 }
 
 void MessageDifferencer::set_field_comparator(FieldComparator* comparator) {
@@ -337,14 +346,14 @@
   field_comparator_.base = comparator;
 }
 
-#ifdef PROTOBUF_FUTURE_BREAKING_CHANGES
+#ifdef PROTOBUF_FUTURE_REMOVE_DEFAULT_FIELD_COMPARATOR
 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
+#endif  // PROTOBUF_FUTURE_REMOVE_DEFAULT_FIELD_COMPARATOR
 
 void MessageDifferencer::set_message_field_comparison(
     MessageFieldComparison comparison) {
@@ -490,8 +499,9 @@
   map_field_key_comparator_[field] = key_comparator;
 }
 
-void MessageDifferencer::AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
-  ignore_criteria_.push_back(ignore_criteria);
+void MessageDifferencer::AddIgnoreCriteria(
+    std::unique_ptr<IgnoreCriteria> ignore_criteria) {
+  ignore_criteria_.push_back(std::move(ignore_criteria));
 }
 
 void MessageDifferencer::IgnoreField(const FieldDescriptor* field) {
@@ -547,10 +557,10 @@
     StreamReporter reporter(&output_stream);
     reporter.SetMessages(message1, message2);
     reporter_ = &reporter;
-    result = Compare(message1, message2, &parent_fields);
+    result = Compare(message1, message2, false, &parent_fields);
     reporter_ = NULL;
   } else {
-    result = Compare(message1, message2, &parent_fields);
+    result = Compare(message1, message2, false, &parent_fields);
   }
   return result;
 }
@@ -590,18 +600,20 @@
     StreamReporter reporter(&output_stream);
     reporter_ = &reporter;
     result = CompareRequestedFieldsUsingSettings(
-        message1, message2, message1_fields, message2_fields, &parent_fields);
+        message1, message2, false, message1_fields, message2_fields,
+        &parent_fields);
     reporter_ = NULL;
   } else {
     result = CompareRequestedFieldsUsingSettings(
-        message1, message2, message1_fields, message2_fields, &parent_fields);
+        message1, message2, false, message1_fields, message2_fields,
+        &parent_fields);
   }
 
   return result;
 }
 
 bool MessageDifferencer::Compare(const Message& message1,
-                                 const Message& message2,
+                                 const Message& message2, int unpacked_any,
                                  std::vector<SpecificField>* parent_fields) {
   const Descriptor* descriptor1 = message1.GetDescriptor();
   const Descriptor* descriptor2 = message2.GetDescriptor();
@@ -622,7 +634,7 @@
       if (data1->GetDescriptor() != data2->GetDescriptor()) {
         return false;
       }
-      return Compare(*data1, *data2, parent_fields);
+      return Compare(*data1, *data2, unpacked_any + 1, parent_fields);
     }
   }
   const Reflection* reflection1 = message1.GetReflection();
@@ -647,7 +659,7 @@
   FieldDescriptorArray message1_fields = RetrieveFields(message1, true);
   FieldDescriptorArray message2_fields = RetrieveFields(message2, false);
 
-  return CompareRequestedFieldsUsingSettings(message1, message2,
+  return CompareRequestedFieldsUsingSettings(message1, message2, unpacked_any,
                                              message1_fields, message2_fields,
                                              parent_fields) &&
          unknown_compare_result;
@@ -685,7 +697,7 @@
 }
 
 bool MessageDifferencer::CompareRequestedFieldsUsingSettings(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptorArray& message1_fields,
     const FieldDescriptorArray& message2_fields,
     std::vector<SpecificField>* parent_fields) {
@@ -696,20 +708,23 @@
       // rather than the addition or deletion of fields).
       FieldDescriptorArray fields_union =
           CombineFields(message1_fields, FULL, message2_fields, FULL);
-      return CompareWithFieldsInternal(message1, message2, fields_union,
-                                       fields_union, parent_fields);
+      return CompareWithFieldsInternal(message1, message2, unpacked_any,
+                                       fields_union, fields_union,
+                                       parent_fields);
     } else {
       // Simple equality comparison, use the unaltered field lists.
-      return CompareWithFieldsInternal(message1, message2, message1_fields,
-                                       message2_fields, parent_fields);
+      return CompareWithFieldsInternal(message1, message2, unpacked_any,
+                                       message1_fields, message2_fields,
+                                       parent_fields);
     }
   } else {
     if (message_field_comparison_ == EQUIVALENT) {
       // We use the list of fields for message1 for both messages when
       // comparing.  This way, extra fields in message2 are ignored,
       // and missing fields in message2 use their default value.
-      return CompareWithFieldsInternal(message1, message2, message1_fields,
-                                       message1_fields, parent_fields);
+      return CompareWithFieldsInternal(message1, message2, unpacked_any,
+                                       message1_fields, message1_fields,
+                                       parent_fields);
     } else {
       // We need to consider the full list of fields for message1
       // but only the intersection for message2.  This way, any fields
@@ -717,8 +732,9 @@
       // present in message1 will be marked as a difference.
       FieldDescriptorArray fields_intersection =
           CombineFields(message1_fields, PARTIAL, message2_fields, PARTIAL);
-      return CompareWithFieldsInternal(message1, message2, message1_fields,
-                                       fields_intersection, parent_fields);
+      return CompareWithFieldsInternal(message1, message2, unpacked_any,
+                                       message1_fields, fields_intersection,
+                                       parent_fields);
     }
   }
 }
@@ -761,7 +777,7 @@
 }
 
 bool MessageDifferencer::CompareWithFieldsInternal(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptorArray& message1_fields,
     const FieldDescriptorArray& message2_fields,
     std::vector<SpecificField>* parent_fields) {
@@ -789,6 +805,9 @@
         // the next field in message1_fields.
         if (reporter_ != NULL) {
           SpecificField specific_field;
+          specific_field.message1 = &message1;
+          specific_field.message2 = &message2;
+          specific_field.unpacked_any = unpacked_any;
           specific_field.field = field1;
           parent_fields->push_back(specific_field);
           if (report_ignores_) {
@@ -808,6 +827,9 @@
 
         for (int i = 0; i < count; ++i) {
           SpecificField specific_field;
+          specific_field.message1 = &message1;
+          specific_field.message2 = &message2;
+          specific_field.unpacked_any = unpacked_any;
           specific_field.field = field1;
           if (field1->is_repeated()) {
             AddSpecificIndex(&specific_field, message1, field1, i);
@@ -834,6 +856,9 @@
         // the next field in message2_fields.
         if (reporter_ != NULL) {
           SpecificField specific_field;
+          specific_field.message1 = &message1;
+          specific_field.message2 = &message2;
+          specific_field.unpacked_any = unpacked_any;
           specific_field.field = field2;
           parent_fields->push_back(specific_field);
           if (report_ignores_) {
@@ -852,6 +877,9 @@
 
         for (int i = 0; i < count; ++i) {
           SpecificField specific_field;
+          specific_field.message1 = &message1,
+          specific_field.message2 = &message2;
+          specific_field.unpacked_any = unpacked_any;
           specific_field.field = field2;
           if (field2->is_repeated()) {
             specific_field.index = i;
@@ -881,6 +909,9 @@
       // Ignore this field. Report and move on.
       if (reporter_ != NULL) {
         SpecificField specific_field;
+        specific_field.message1 = &message1;
+        specific_field.message2 = &message2;
+        specific_field.unpacked_any = unpacked_any;
         specific_field.field = field1;
         parent_fields->push_back(specific_field);
         if (report_ignores_) {
@@ -897,17 +928,20 @@
     bool fieldDifferent = false;
     assert(field1 != NULL);
     if (field1->is_map()) {
-      fieldDifferent =
-          !CompareMapField(message1, message2, field1, parent_fields);
+      fieldDifferent = !CompareMapField(message1, message2, unpacked_any,
+                                        field1, parent_fields);
     } else if (field1->is_repeated()) {
-      fieldDifferent =
-          !CompareRepeatedField(message1, message2, field1, parent_fields);
+      fieldDifferent = !CompareRepeatedField(message1, message2, unpacked_any,
+                                             field1, parent_fields);
     } else {
       fieldDifferent = !CompareFieldValueUsingParentFields(
-          message1, message2, field1, -1, -1, parent_fields);
+          message1, message2, unpacked_any, field1, -1, -1, parent_fields);
 
       if (reporter_ != nullptr) {
         SpecificField specific_field;
+        specific_field.message1 = &message1;
+        specific_field.message2 = &message2;
+        specific_field.unpacked_any = unpacked_any;
         specific_field.field = field1;
         parent_fields->push_back(specific_field);
         if (fieldDifferent) {
@@ -934,13 +968,14 @@
 bool MessageDifferencer::IsMatch(
     const FieldDescriptor* repeated_field,
     const MapKeyComparator* key_comparator, const Message* message1,
-    const Message* message2, const std::vector<SpecificField>& parent_fields,
-    Reporter* reporter, int index1, int index2) {
+    const Message* message2, int unpacked_any,
+    const std::vector<SpecificField>& parent_fields, Reporter* reporter,
+    int index1, int index2) {
   std::vector<SpecificField> current_parent_fields(parent_fields);
   if (repeated_field->cpp_type() != FieldDescriptor::CPPTYPE_MESSAGE) {
-    return CompareFieldValueUsingParentFields(*message1, *message2,
-                                              repeated_field, index1, index2,
-                                              &current_parent_fields);
+    return CompareFieldValueUsingParentFields(
+        *message1, *message2, unpacked_any, repeated_field, index1, index2,
+        &current_parent_fields);
   }
   // Back up the Reporter and output_string_.  They will be reset in the
   // following code.
@@ -951,9 +986,9 @@
   bool match;
 
   if (key_comparator == NULL) {
-    match = CompareFieldValueUsingParentFields(*message1, *message2,
-                                               repeated_field, index1, index2,
-                                               &current_parent_fields);
+    match = CompareFieldValueUsingParentFields(
+        *message1, *message2, unpacked_any, repeated_field, index1, index2,
+        &current_parent_fields);
   } else {
     const Reflection* reflection1 = message1->GetReflection();
     const Reflection* reflection2 = message2->GetReflection();
@@ -962,6 +997,9 @@
     const Message& m2 =
         reflection2->GetRepeatedMessage(*message2, repeated_field, index2);
     SpecificField specific_field;
+    specific_field.message1 = message1;
+    specific_field.message2 = message2;
+    specific_field.unpacked_any = unpacked_any;
     specific_field.field = repeated_field;
     if (repeated_field->is_map()) {
       specific_field.map_entry1 = &m1;
@@ -970,7 +1008,7 @@
     specific_field.index = index1;
     specific_field.new_index = index2;
     current_parent_fields.push_back(specific_field);
-    match = key_comparator->IsMatch(m1, m2, current_parent_fields);
+    match = key_comparator->IsMatch(m1, m2, false, current_parent_fields);
   }
 
   reporter_ = backup_reporter;
@@ -979,7 +1017,7 @@
 }
 
 bool MessageDifferencer::CompareMapFieldByMapReflection(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptor* map_field, std::vector<SpecificField>* parent_fields,
     DefaultFieldComparator* comparator) {
   GOOGLE_DCHECK_EQ(nullptr, reporter_);
@@ -1054,10 +1092,14 @@
         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.message1 = &message1;
+        specific_value_field.message2 = &message2;
+        specific_value_field.unpacked_any = unpacked_any;
         specific_value_field.field = val_des;
         parent_fields->push_back(specific_value_field);
-        compare_result = Compare(it.GetValueRef().GetMessageValue(),
-                                 value2.GetMessageValue(), parent_fields);
+        compare_result =
+            Compare(it.GetValueRef().GetMessageValue(),
+                    value2.GetMessageValue(), false, parent_fields);
         parent_fields->pop_back();
         if (!compare_result) {
           return false;
@@ -1070,7 +1112,7 @@
 }
 
 bool MessageDifferencer::CompareMapField(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptor* repeated_field,
     std::vector<SpecificField>* parent_fields) {
   GOOGLE_DCHECK(repeated_field->is_map());
@@ -1096,29 +1138,34 @@
         repeated_field->message_type()->map_value();
     std::vector<SpecificField> current_parent_fields(*parent_fields);
     SpecificField specific_field;
+    specific_field.message1 = &message1;
+    specific_field.message2 = &message2;
+    specific_field.unpacked_any = unpacked_any;
     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 CompareMapFieldByMapReflection(
+          message1, message2, unpacked_any, repeated_field,
+          &current_parent_fields, field_comparator_.default_impl);
     }
   }
 
-  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
+  return CompareRepeatedRep(message1, message2, unpacked_any, repeated_field,
+                            parent_fields);
 }
 
 bool MessageDifferencer::CompareRepeatedField(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptor* repeated_field,
     std::vector<SpecificField>* parent_fields) {
   GOOGLE_DCHECK(!repeated_field->is_map());
-  return CompareRepeatedRep(message1, message2, repeated_field, parent_fields);
+  return CompareRepeatedRep(message1, message2, unpacked_any, repeated_field,
+                            parent_fields);
 }
 
 bool MessageDifferencer::CompareRepeatedRep(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptor* repeated_field,
     std::vector<SpecificField>* parent_fields) {
   // the input FieldDescriptor is guaranteed to be repeated field.
@@ -1157,9 +1204,9 @@
   // match_list2.
   if (!simple_list) {
     // Try to match indices of the repeated fields. Return false if match fails.
-    if (!MatchRepeatedFieldIndices(message1, message2, repeated_field,
-                                   key_comparator, *parent_fields, &match_list1,
-                                   &match_list2) &&
+    if (!MatchRepeatedFieldIndices(
+            message1, message2, unpacked_any, repeated_field, key_comparator,
+            *parent_fields, &match_list1, &match_list2) &&
         reporter_ == nullptr) {
       return false;
     }
@@ -1167,6 +1214,9 @@
 
   bool fieldDifferent = false;
   SpecificField specific_field;
+  specific_field.message1 = &message1;
+  specific_field.message2 = &message2;
+  specific_field.unpacked_any = unpacked_any;
   specific_field.field = repeated_field;
 
   // At this point, we have already matched pairs of fields (with the reporting
@@ -1213,8 +1263,8 @@
     }
 
     const bool result = CompareFieldValueUsingParentFields(
-        message1, message2, repeated_field, i, specific_field.new_index,
-        parent_fields);
+        message1, message2, unpacked_any, repeated_field, i,
+        specific_field.new_index, parent_fields);
 
     // If we have found differences, either report them or terminate if
     // no reporter is present. Note that ReportModified, ReportMoved, and
@@ -1269,14 +1319,15 @@
 
 bool MessageDifferencer::CompareFieldValue(const Message& message1,
                                            const Message& message2,
+                                           int unpacked_any,
                                            const FieldDescriptor* field,
                                            int index1, int index2) {
-  return CompareFieldValueUsingParentFields(message1, message2, field, index1,
-                                            index2, NULL);
+  return CompareFieldValueUsingParentFields(message1, message2, unpacked_any,
+                                            field, index1, index2, nullptr);
 }
 
 bool MessageDifferencer::CompareFieldValueUsingParentFields(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptor* field, int index1, int index2,
     std::vector<SpecificField>* parent_fields) {
   FieldContext field_context(parent_fields);
@@ -1302,11 +1353,14 @@
     if (parent_fields != NULL) {
       // Append currently compared field to the end of parent_fields.
       SpecificField specific_field;
+      specific_field.message1 = &message1;
+      specific_field.message2 = &message2;
+      specific_field.unpacked_any = unpacked_any;
       specific_field.field = field;
       AddSpecificIndex(&specific_field, message1, field, index1);
       AddSpecificNewIndex(&specific_field, message2, field, index2);
       parent_fields->push_back(specific_field);
-      const bool compare_result = Compare(m1, m2, parent_fields);
+      const bool compare_result = Compare(m1, m2, false, parent_fields);
       parent_fields->pop_back();
       return compare_result;
     } else {
@@ -1371,7 +1425,7 @@
   if (ignored_fields_.find(field) != ignored_fields_.end()) {
     return true;
   }
-  for (IgnoreCriteria* criteria : ignore_criteria_) {
+  for (const auto& criteria : ignore_criteria_) {
     if (criteria->IsIgnored(message1, message2, field, parent_fields)) {
       return true;
     }
@@ -1383,7 +1437,7 @@
     const Message& message1, const Message& message2,
     const SpecificField& field,
     const std::vector<SpecificField>& parent_fields) {
-  for (IgnoreCriteria* criteria : ignore_criteria_) {
+  for (const auto& criteria : ignore_criteria_) {
     if (criteria->IsUnknownFieldIgnored(message1, message2, field,
                                         parent_fields)) {
       return true;
@@ -1586,6 +1640,8 @@
 
     // Build the SpecificField.  This is slightly complicated.
     SpecificField specific_field;
+    specific_field.message1 = &message1;
+    specific_field.message2 = &message2;
     specific_field.unknown_field_number = focus_field->number();
     specific_field.unknown_field_type = focus_field->type();
 
@@ -1688,6 +1744,8 @@
   // match_list1[i] == -1 means the node is not matched. Same with match_list2.
   MaximumMatcher(int count1, int count2, NodeMatchCallback callback,
                  std::vector<int>* match_list1, std::vector<int>* match_list2);
+  MaximumMatcher(const MaximumMatcher&) = delete;
+  MaximumMatcher& operator=(const MaximumMatcher&) = delete;
   // Find a maximum match and return the number of matched node pairs.
   // If early_return is true, this method will return 0 immediately when it
   // finds that not all nodes on the left side can be matched.
@@ -1708,7 +1766,6 @@
   std::map<std::pair<int, int>, bool> cached_match_results_;
   std::vector<int>* match_list1_;
   std::vector<int>* match_list2_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MaximumMatcher);
 };
 
 MaximumMatcher::MaximumMatcher(int count1, int count2,
@@ -1788,7 +1845,7 @@
 }  // namespace
 
 bool MessageDifferencer::MatchRepeatedFieldIndices(
-    const Message& message1, const Message& message2,
+    const Message& message1, const Message& message2, int unpacked_any,
     const FieldDescriptor* repeated_field,
     const MapKeyComparator* key_comparator,
     const std::vector<SpecificField>& parent_fields,
@@ -1822,7 +1879,7 @@
     // Here we use the augmenting path algorithm.
     auto callback = [&](int i1, int i2) {
       return IsMatch(repeated_field, key_comparator, &message1, &message2,
-                     parent_fields, nullptr, i1, i2);
+                     unpacked_any, parent_fields, nullptr, i1, i2);
     };
     MaximumMatcher matcher(count1, count2, std::move(callback), match_list1,
                            match_list2);
@@ -1841,7 +1898,7 @@
       start_offset = std::min(count1, count2);
       for (int i = 0; i < count1 && i < count2; i++) {
         if (IsMatch(repeated_field, key_comparator, &message1, &message2,
-                    parent_fields, nullptr, i, i)) {
+                    unpacked_any, parent_fields, nullptr, i, i)) {
           match_list1->at(i) = i;
           match_list2->at(i) = i;
         } else {
@@ -1865,11 +1922,12 @@
 
         if (is_treated_as_smart_set) {
           num_diffs_reporter.Reset();
-          match = IsMatch(repeated_field, key_comparator, &message1, &message2,
-                          parent_fields, &num_diffs_reporter, i, j);
+          match =
+              IsMatch(repeated_field, key_comparator, &message1, &message2,
+                      unpacked_any, parent_fields, &num_diffs_reporter, i, j);
         } else {
           match = IsMatch(repeated_field, key_comparator, &message1, &message2,
-                          parent_fields, nullptr, i, j);
+                          unpacked_any, parent_fields, nullptr, i, j);
         }
 
         if (is_treated_as_smart_set) {
@@ -2000,19 +2058,18 @@
         continue;
       }
     } else {
-      printer_->PrintRaw(StrCat(specific_field.unknown_field_number));
+      printer_->PrintRaw(absl::StrCat(specific_field.unknown_field_number));
     }
     if (left_side && specific_field.index >= 0) {
-      printer_->Print("[$name$]", "name", StrCat(specific_field.index));
+      printer_->Print("[$name$]", "name", absl::StrCat(specific_field.index));
     }
     if (!left_side && specific_field.new_index >= 0) {
       printer_->Print("[$name$]", "name",
-                      StrCat(specific_field.new_index));
+                      absl::StrCat(specific_field.new_index));
     }
   }
 }
 
-
 void MessageDifferencer::StreamReporter::PrintValue(
     const Message& message, const std::vector<SpecificField>& field_path,
     bool left_side) {
@@ -2072,19 +2129,19 @@
   std::string output;
   switch (unknown_field->type()) {
     case UnknownField::TYPE_VARINT:
-      output = StrCat(unknown_field->varint());
+      output = absl::StrCat(unknown_field->varint());
       break;
     case UnknownField::TYPE_FIXED32:
-      output = StrCat(
-          "0x", strings::Hex(unknown_field->fixed32(), strings::ZERO_PAD_8));
+      output = absl::StrCat(
+          "0x", absl::Hex(unknown_field->fixed32(), absl::kZeroPad8));
       break;
     case UnknownField::TYPE_FIXED64:
-      output = StrCat(
-          "0x", strings::Hex(unknown_field->fixed64(), strings::ZERO_PAD_16));
+      output = absl::StrCat(
+          "0x", absl::Hex(unknown_field->fixed64(), absl::kZeroPad16));
       break;
     case UnknownField::TYPE_LENGTH_DELIMITED:
-      output = StringPrintf(
-          "\"%s\"", CEscape(unknown_field->length_delimited()).c_str());
+      output = absl::StrFormat(
+          "\"%s\"", absl::CEscape(unknown_field->length_delimited()).c_str());
       break;
     case UnknownField::TYPE_GROUP:
       // TODO(kenton):  Print the contents of the group like we do for
@@ -2126,7 +2183,7 @@
     if (key_string.empty()) {
       key_string = "''";
     }
-    printer_->PrintRaw(StrCat("[", key_string, "]"));
+    printer_->PrintRaw(absl::StrCat("[", key_string, "]"));
   }
 }
 
diff --git a/src/google/protobuf/util/message_differencer.h b/src/google/protobuf/util/message_differencer.h
index f63cd54..1985574 100644
--- a/src/google/protobuf/util/message_differencer.h
+++ b/src/google/protobuf/util/message_differencer.h
@@ -51,13 +51,15 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/descriptor.h>  // FieldDescriptor
-#include <google/protobuf/message.h>     // Message
-#include <google/protobuf/unknown_field_set.h>
-#include <google/protobuf/util/field_comparator.h>
+#include "google/protobuf/descriptor.h"  // FieldDescriptor
+#include "google/protobuf/message.h"     // Message
+#include "google/protobuf/unknown_field_set.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/container/fixed_array.h"
+#include "google/protobuf/util/field_comparator.h"
 
 // Always include as last one, otherwise it can break compilation
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -79,7 +81,7 @@
 // In case of internal google codebase we are using absl::FixedArray instead
 // of vector. It significantly speeds up proto comparison (by ~30%) by
 // reducing the number of malloc/free operations
-typedef std::vector<const FieldDescriptor*> FieldDescriptorArray;
+typedef absl::FixedArray<const FieldDescriptor*, 16> FieldDescriptorArray;
 
 // A basic differencer that can be used to determine
 // the differences between two specified Protocol Messages. If any differences
@@ -177,6 +179,22 @@
   // Identifies an individual field in a message instance.  Used for field_path,
   // below.
   struct SpecificField {
+    // The messages that contain this field. They are always set. They are valid
+    // only during a call to Reporter::Report* methods.
+    //
+    // If the original messages are of type google.protobuf.Any, these fields
+    // will store the unpacked payloads, and unpacked_any will become > 0.  More
+    // precisely, unpacked_any defines the nesting level of Any.  For example,
+    // if the original message packs another Any, then unpacked_any=2, assuming
+    // the differencer unpacked both of them.
+    //
+    // When an Any object packs a non-Any proto object whose field includes
+    // Any, then unpacked_any=1. Thus, in most practical applications,
+    // unpacked_any will be 0 or 1.
+    const Message* message1 = nullptr;
+    const Message* message2 = nullptr;
+    int unpacked_any = 0;
+
     // 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.
@@ -238,21 +256,22 @@
   class PROTOBUF_EXPORT Reporter {
    public:
     Reporter();
+    Reporter(const Reporter&) = delete;
+    Reporter& operator=(const Reporter&) = delete;
     virtual ~Reporter();
 
     // Reports that a field has been added into Message2.
     virtual void ReportAdded(const Message& message1, const Message& message2,
-                             const std::vector<SpecificField>& field_path) = 0;
+                             const std::vector<SpecificField>& field_path) {}
 
     // Reports that a field has been deleted from Message1.
-    virtual void ReportDeleted(
-        const Message& message1, const Message& message2,
-        const std::vector<SpecificField>& field_path) = 0;
+    virtual void ReportDeleted(const Message& message1, const Message& message2,
+                               const std::vector<SpecificField>& field_path) {}
 
     // Reports that the value of a field has been modified.
-    virtual void ReportModified(
-        const Message& message1, const Message& message2,
-        const std::vector<SpecificField>& field_path) = 0;
+    virtual void ReportModified(const Message& message1,
+                                const Message& message2,
+                                const std::vector<SpecificField>& field_path) {}
 
     // Reports that a repeated field has been moved to another location.  This
     // only applies when using TreatAsSet or TreatAsMap()  -- see below. Also
@@ -300,9 +319,6 @@
     virtual void ReportUnknownFieldIgnored(
         const Message& /* message1 */, const Message& /* message2 */,
         const std::vector<SpecificField>& /* field_path */) {}
-
-   private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(Reporter);
   };
 
   // MapKeyComparator is used to determine if two elements have the same key
@@ -310,17 +326,25 @@
   class PROTOBUF_EXPORT MapKeyComparator {
    public:
     MapKeyComparator();
+    MapKeyComparator(const MapKeyComparator&) = delete;
+    MapKeyComparator& operator=(const MapKeyComparator&) = delete;
     virtual ~MapKeyComparator();
 
-    virtual bool IsMatch(
-        const Message& /* message1 */, const Message& /* message2 */,
-        const std::vector<SpecificField>& /* parent_fields */) const {
+    // This method should be overridden by every implementation.  The arg
+    // unmapped_any is nonzero the original messages provided by the user are of
+    // type google.protobuf.Any.
+    //
+    // More precisely, unpacked_any defines the nesting level of Any.  For
+    // example, if Any packs another Any then unpacked_any=2, assuming the
+    // patcher unpacked both.  Note that when an Any object packs a non-Any
+    // proto object whose field includes Any, then unpacked_any=1. Thus, in most
+    // practical applications, unpacked_any will be 0 or 1.
+    virtual bool IsMatch(const Message& message1, const Message& message2,
+                         int /* unmapped_any */,
+                         const std::vector<SpecificField>& fields) const {
       GOOGLE_CHECK(false) << "IsMatch() is not implemented.";
       return false;
     }
-
-   private:
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MapKeyComparator);
   };
 
   // Abstract base class from which all IgnoreCriteria derive.
@@ -354,6 +378,8 @@
   // To add a Reporter, construct default here, then use ReportDifferencesTo or
   // ReportDifferencesToString.
   explicit MessageDifferencer();
+  MessageDifferencer(const MessageDifferencer&) = delete;
+  MessageDifferencer& operator=(const MessageDifferencer&) = delete;
 
   ~MessageDifferencer();
 
@@ -503,7 +529,10 @@
   // Add a custom ignore criteria that is evaluated in addition to the
   // ignored fields added with IgnoreField.
   // Takes ownership of ignore_criteria.
-  void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria);
+  void AddIgnoreCriteria(IgnoreCriteria* ignore_criteria) {
+    AddIgnoreCriteria(absl::WrapUnique(ignore_criteria));
+  }
+  void AddIgnoreCriteria(std::unique_ptr<IgnoreCriteria> ignore_criteria);
 
   // Indicates that any field with the given descriptor should be
   // ignored for the purposes of comparing two messages. This applies
@@ -524,9 +553,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
+#ifdef PROTOBUF_FUTURE_REMOVE_DEFAULT_FIELD_COMPARATOR
   void set_field_comparator(DefaultFieldComparator* comparator);
-#endif  // PROTOBUF_FUTURE_BREAKING_CHANGES
+#endif  // PROTOBUF_FUTURE_REMOVE_DEFAULT_FIELD_COMPARATOR
 
   // DEPRECATED. Pass a DefaultFieldComparator instance instead.
   // Sets the fraction and margin for the float comparison of a given field.
@@ -648,6 +677,8 @@
    public:
     explicit StreamReporter(io::ZeroCopyOutputStream* output);
     explicit StreamReporter(io::Printer* printer);  // delimiter '$'
+    StreamReporter(const StreamReporter&) = delete;
+    StreamReporter& operator=(const StreamReporter&) = delete;
     ~StreamReporter() override;
 
     // When set to true, the stream reporter will also output aggregates nodes
@@ -715,7 +746,6 @@
     const Message* message1_;
     const Message* message2_;
     MessageDifferencer::UnpackAnyField unpack_any_field_;
-    GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(StreamReporter);
   };
 
  private:
@@ -732,7 +762,7 @@
    public:
     explicit MapEntryKeyComparator(MessageDifferencer* message_differencer);
     bool IsMatch(
-        const Message& message1, const Message& message2,
+        const Message& message1, const Message& message2, int unpacked_any,
         const std::vector<SpecificField>& parent_fields) const override;
 
    private:
@@ -762,7 +792,7 @@
   // (i.e. if the current message is an embedded message, the parent_fields
   // vector will contain the field that has this embedded message).
   bool Compare(const Message& message1, const Message& message2,
-               std::vector<SpecificField>* parent_fields);
+               int unpacked_any, std::vector<SpecificField>* parent_fields);
 
   // Compares all the unknown fields in two messages.
   bool CompareUnknownFields(const Message& message1, const Message& message2,
@@ -773,46 +803,47 @@
   // lists are modified depending on comparison settings, and then passed to
   // CompareWithFieldsInternal.
   bool CompareRequestedFieldsUsingSettings(
-      const Message& message1, const Message& message2,
+      const Message& message1, const Message& message2, int unpacked_any,
       const FieldDescriptorArray& message1_fields,
       const FieldDescriptorArray& message2_fields,
       std::vector<SpecificField>* parent_fields);
 
   // Compares the specified messages with the specified field lists.
   bool CompareWithFieldsInternal(const Message& message1,
-                                 const Message& message2,
+                                 const Message& message2, int unpacked_any,
                                  const FieldDescriptorArray& message1_fields,
                                  const FieldDescriptorArray& message2_fields,
                                  std::vector<SpecificField>* parent_fields);
 
   // Compares the repeated fields, and report the error.
   bool CompareRepeatedField(const Message& message1, const Message& message2,
-                            const FieldDescriptor* field,
+                            int unpacked_any, 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,
+                       int unpacked_any, 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,
+                          int unpacked_any, 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 Message& message2, int unpacked_any,
                                       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);
+                         int unpacked_any, const FieldDescriptor* field,
+                         int index1, int index2);
 
   // Compares the specified field on the two messages, returning
   // true if they are the same, false otherwise. For repeated fields,
@@ -824,7 +855,7 @@
   // To avoid confusing users you should not set it to NULL unless you modified
   // Reporter to handle the change of parent_fields correctly.
   bool CompareFieldValueUsingParentFields(
-      const Message& message1, const Message& message2,
+      const Message& message1, const Message& message2, int unpacked_any,
       const FieldDescriptor* field, int index1, int index2,
       std::vector<SpecificField>* parent_fields);
 
@@ -840,7 +871,7 @@
   // elements are equal.
   bool IsMatch(const FieldDescriptor* repeated_field,
                const MapKeyComparator* key_comparator, const Message* message1,
-               const Message* message2,
+               const Message* message2, int unpacked_any,
                const std::vector<SpecificField>& parent_fields,
                Reporter* reporter, int index1, int index2);
 
@@ -888,7 +919,7 @@
   // that the comparison succeeds when this method returns true (you need to
   // double-check in this case).
   bool MatchRepeatedFieldIndices(
-      const Message& message1, const Message& message2,
+      const Message& message1, const Message& message2, int unpacked_any,
       const FieldDescriptor* repeated_field,
       const MapKeyComparator* key_comparator,
       const std::vector<SpecificField>& parent_fields,
@@ -929,7 +960,7 @@
   std::vector<MapKeyComparator*> owned_key_comparators_;
   FieldKeyComparatorMap map_field_key_comparator_;
   MapEntryKeyComparator map_entry_key_comparator_;
-  std::vector<IgnoreCriteria*> ignore_criteria_;
+  std::vector<std::unique_ptr<IgnoreCriteria>> ignore_criteria_;
   // Reused multiple times in RetrieveFields to avoid extra allocations
   std::vector<const FieldDescriptor*> tmp_message_fields_;
 
@@ -952,7 +983,6 @@
       match_indices_for_smart_list_callback_;
 
   MessageDifferencer::UnpackAnyField unpack_any_field_;
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MessageDifferencer);
 };
 
 // This class provides extra information to the FieldComparator::Compare
@@ -975,6 +1005,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_MESSAGE_DIFFERENCER_H__
diff --git a/src/google/protobuf/util/message_differencer_unittest.cc b/src/google/protobuf/util/message_differencer_unittest.cc
index f8e44df..5cecaee 100644
--- a/src/google/protobuf/util/message_differencer_unittest.cc
+++ b/src/google/protobuf/util/message_differencer_unittest.cc
@@ -34,30 +34,30 @@
 //
 // TODO(ksroka): Move some of these tests to field_comparator_test.cc.
 
+#include "google/protobuf/util/message_differencer.h"
+
 #include <algorithm>
 #include <random>
 #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>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl.h>
-#include <google/protobuf/text_format.h>
-#include <google/protobuf/wire_format.h>
-#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/testing/googletest.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include <gmock/gmock.h>
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "absl/functional/bind_front.h"
+#include "absl/strings/str_split.h"
+#include "google/protobuf/any_test.pb.h"
+#include "google/protobuf/map_test_util.h"
+#include "google/protobuf/map_unittest.pb.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/text_format.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/util/field_comparator.h"
+#include "google/protobuf/util/message_differencer_unittest.pb.h"
+#include "google/protobuf/wire_format.h"
+
 
 namespace google {
 namespace protobuf {
@@ -68,7 +68,7 @@
 const FieldDescriptor* GetFieldDescriptor(const Message& message,
                                           const std::string& field_name) {
   std::vector<std::string> field_path =
-      Split(field_name, ".", true);
+      absl::StrSplit(field_name, ".", absl::SkipEmpty());
   const Descriptor* descriptor = message.GetDescriptor();
   const FieldDescriptor* field = nullptr;
   for (int i = 0; i < field_path.size(); i++) {
@@ -1869,7 +1869,7 @@
       name += parent_fields[i].field->name() + ".";
     }
     name += field->name();
-    for (int i = 0; i < GOOGLE_ARRAYSIZE(kIgnoredFields); ++i) {
+    for (int i = 0; i < ABSL_ARRAYSIZE(kIgnoredFields); ++i) {
       if (name.compare(kIgnoredFields[i]) == 0) {
         return true;
       }
@@ -1885,7 +1885,7 @@
   TextFormat::MergeFromString("rm { a: 11\n b: 13 }", &msg2);
   util::MessageDifferencer differ;
   differ.TreatAsSet(GetFieldDescriptor(msg1, "rm"));
-  differ.AddIgnoreCriteria(new TestIgnorer);
+  differ.AddIgnoreCriteria(absl::WrapUnique(new TestIgnorer));
   EXPECT_TRUE(differ.Compare(msg1, msg2));
 }
 
@@ -1897,7 +1897,7 @@
   util::MessageDifferencer differ;
   differ.TreatAsMap(GetFieldDescriptor(msg1, "rm"),
                     GetFieldDescriptor(msg1, "rm.m"));
-  differ.AddIgnoreCriteria(new TestIgnorer);
+  differ.AddIgnoreCriteria(absl::WrapUnique(new TestIgnorer));
   EXPECT_TRUE(differ.Compare(msg1, msg2));
 }
 
@@ -1907,6 +1907,7 @@
  public:
   typedef util::MessageDifferencer::SpecificField SpecificField;
   bool IsMatch(const Message& message1, const Message& message2,
+               int unpacked_any,
                const std::vector<SpecificField>& parent_fields) const override {
     const Reflection* reflection1 = message1.GetReflection();
     const Reflection* reflection2 = message2.GetReflection();
@@ -1968,6 +1969,7 @@
  public:
   typedef util::MessageDifferencer::SpecificField SpecificField;
   bool IsMatch(const Message& message1, const Message& message2,
+               int unpacked_any,
                const std::vector<SpecificField>& parent_fields) const override {
     return parent_fields.back().index + 1 == parent_fields.back().new_index;
   }
@@ -3402,6 +3404,7 @@
  public:
   typedef util::MessageDifferencer::SpecificField SpecificField;
   bool IsMatch(const Message& message1, const Message& message2,
+               int unpacked_any,
                const std::vector<SpecificField>& parent_fields) const override {
     const Reflection* reflection1 = message1.GetReflection();
     const Reflection* reflection2 = message2.GetReflection();
@@ -3472,9 +3475,6 @@
     }
     return output;
   }
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(MatchingTest);
 };
 
 TEST_F(MatchingTest, StreamReporterMatching) {
diff --git a/src/google/protobuf/util/time_util.cc b/src/google/protobuf/util/time_util.cc
index 9893aa3..c278150 100644
--- a/src/google/protobuf/util/time_util.cc
+++ b/src/google/protobuf/util/time_util.cc
@@ -28,19 +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.
 
-#include <google/protobuf/util/time_util.h>
+#include "google/protobuf/util/time_util.h"
 
 #include <cstdint>
+#include <cstdlib>
 
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/duration.pb.h>
-#include <google/protobuf/timestamp.pb.h>
-#include <google/protobuf/stubs/int128.h>
-#include <google/protobuf/stubs/stringprintf.h>
-#include <google/protobuf/stubs/time.h>
+#include "google/protobuf/duration.pb.h"
+#include "google/protobuf/timestamp.pb.h"
+#include "absl/numeric/int128.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "absl/time/clock.h"
+#include "absl/time/time.h"
 
 // Must go after other includes.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -50,19 +52,24 @@
 using google::protobuf::Timestamp;
 
 namespace {
-static const int kNanosPerSecond = 1000000000;
-static const int kMicrosPerSecond = 1000000;
-static const int kMillisPerSecond = 1000;
-static const int kNanosPerMillisecond = 1000000;
-static const int kNanosPerMicrosecond = 1000;
-static const int kSecondsPerMinute = 60;  // Note that we ignore leap seconds.
-static const int kSecondsPerHour = 3600;
+static constexpr int32_t kNanosPerSecond = 1000000000;
+static constexpr int32_t kMicrosPerSecond = 1000000;
+static constexpr int32_t kMillisPerSecond = 1000;
+static constexpr int32_t kNanosPerMillisecond = 1000000;
+static constexpr int32_t kNanosPerMicrosecond = 1000;
+static constexpr int32_t kSecondsPerMinute =
+    60;  // Note that we ignore leap seconds.
+static constexpr int32_t kSecondsPerHour = 3600;
 
 template <typename T>
-T CreateNormalized(int64_t seconds, int64_t nanos);
+T CreateNormalized(int64_t seconds, int32_t nanos);
 
 template <>
-Timestamp CreateNormalized(int64_t seconds, int64_t nanos) {
+Timestamp CreateNormalized(int64_t seconds, int32_t nanos) {
+  GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
+         seconds <= TimeUtil::kTimestampMaxSeconds)
+      << "Timestamp seconds are outside of the valid range";
+
   // Make sure nanos is in the range.
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     seconds += nanos / kNanosPerSecond;
@@ -73,8 +80,12 @@
     seconds -= 1;
     nanos += kNanosPerSecond;
   }
+
   GOOGLE_DCHECK(seconds >= TimeUtil::kTimestampMinSeconds &&
-         seconds <= TimeUtil::kTimestampMaxSeconds);
+         seconds <= TimeUtil::kTimestampMaxSeconds &&
+         nanos >= TimeUtil::kTimestampMinNanoseconds &&
+         nanos <= TimeUtil::kTimestampMaxNanoseconds)
+      << "Timestamp is outside of the valid range";
   Timestamp result;
   result.set_seconds(seconds);
   result.set_nanos(static_cast<int32_t>(nanos));
@@ -82,7 +93,11 @@
 }
 
 template <>
-Duration CreateNormalized(int64_t seconds, int64_t nanos) {
+Duration CreateNormalized(int64_t seconds, int32_t nanos) {
+  GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
+         seconds <= TimeUtil::kDurationMaxSeconds)
+      << "Duration seconds are outside of the valid range";
+
   // Make sure nanos is in the range.
   if (nanos <= -kNanosPerSecond || nanos >= kNanosPerSecond) {
     seconds += nanos / kNanosPerSecond;
@@ -96,8 +111,12 @@
     seconds -= 1;
     nanos += kNanosPerSecond;
   }
+
   GOOGLE_DCHECK(seconds >= TimeUtil::kDurationMinSeconds &&
-         seconds <= TimeUtil::kDurationMaxSeconds);
+         seconds <= TimeUtil::kDurationMaxSeconds &&
+         nanos >= TimeUtil::kDurationMinNanoseconds &&
+         nanos <= TimeUtil::kDurationMaxNanoseconds)
+      << "Duration is outside of the valid range";
   Duration result;
   result.set_seconds(seconds);
   result.set_nanos(static_cast<int32_t>(nanos));
@@ -108,24 +127,49 @@
 // precision to represent the exact value.
 std::string FormatNanos(int32_t nanos) {
   if (nanos % kNanosPerMillisecond == 0) {
-    return StringPrintf("%03d", nanos / kNanosPerMillisecond);
+    return absl::StrFormat("%03d", nanos / kNanosPerMillisecond);
   } else if (nanos % kNanosPerMicrosecond == 0) {
-    return StringPrintf("%06d", nanos / kNanosPerMicrosecond);
+    return absl::StrFormat("%06d", nanos / kNanosPerMicrosecond);
   } else {
-    return StringPrintf("%09d", nanos);
+    return absl::StrFormat("%09d", nanos);
   }
 }
 
 std::string FormatTime(int64_t seconds, int32_t nanos) {
-  return ::google::protobuf::internal::FormatTime(seconds, nanos);
+  static const char kTimestampFormat[] = "%E4Y-%m-%dT%H:%M:%S";
+
+  timespec spec;
+  spec.tv_sec = seconds;
+  // We only use absl::FormatTime to format the seconds part because we need
+  // finer control over the precision of nanoseconds.
+  spec.tv_nsec = 0;
+  std::string result = absl::FormatTime(
+      kTimestampFormat, absl::TimeFromTimespec(spec), absl::UTCTimeZone());
+  // We format the nanoseconds part separately to meet the precision
+  // requirement.
+  if (nanos != 0) {
+    result += "." + FormatNanos(nanos);
+  }
+  result += "Z";
+  return result;
 }
 
 bool ParseTime(const std::string& value, int64_t* seconds, int32_t* nanos) {
-  return ::google::protobuf::internal::ParseTime(value, seconds, nanos);
+  absl::Time result;
+  if (!absl::ParseTime(absl::RFC3339_full, value, &result, nullptr)) {
+    return false;
+  }
+  timespec spec = absl::ToTimespec(result);
+  *seconds = spec.tv_sec;
+  *nanos = spec.tv_nsec;
+  return true;
 }
 
 void CurrentTime(int64_t* seconds, int32_t* nanos) {
-  return ::google::protobuf::internal::GetCurrentTime(seconds, nanos);
+  absl::Time now = absl::Now();
+  timespec spec = absl::ToTimespec(now);
+  *seconds = spec.tv_sec;
+  *nanos = spec.tv_nsec;
 }
 
 // Truncates the remainder part after division.
@@ -148,10 +192,14 @@
 // Actually define these static const integers. Required by C++ standard (but
 // some compilers don't like it).
 #ifndef _MSC_VER
-const int64_t TimeUtil::kTimestampMinSeconds;
-const int64_t TimeUtil::kTimestampMaxSeconds;
-const int64_t TimeUtil::kDurationMaxSeconds;
-const int64_t TimeUtil::kDurationMinSeconds;
+constexpr int64_t TimeUtil::kTimestampMinSeconds;
+constexpr int64_t TimeUtil::kTimestampMaxSeconds;
+constexpr int32_t TimeUtil::kTimestampMinNanoseconds;
+constexpr int32_t TimeUtil::kTimestampMaxNanoseconds;
+constexpr int64_t TimeUtil::kDurationMaxSeconds;
+constexpr int64_t TimeUtil::kDurationMinSeconds;
+constexpr int32_t TimeUtil::kDurationMaxNanoseconds;
+constexpr int32_t TimeUtil::kDurationMinNanoseconds;
 #endif  // !_MSC_VER
 
 std::string TimeUtil::ToString(const Timestamp& timestamp) {
@@ -186,7 +234,7 @@
     seconds = -seconds;
     nanos = -nanos;
   }
-  result += StrCat(seconds);
+  result += absl::StrCat(seconds);
   if (nanos != 0) {
     result += "." + FormatNanos(nanos);
   }
@@ -220,11 +268,13 @@
     nanos_part = value.substr(pos + 1, value.length() - pos - 2);
   }
   char* end;
-  int64_t seconds = strto64(seconds_part.c_str(), &end, 10);
+  static_assert(sizeof(int64_t) == sizeof(long long),
+                "sizeof int64_t is not sizeof long long");
+  int64_t seconds = std::strtoll(seconds_part.c_str(), &end, 10);
   if (end != seconds_part.c_str() + seconds_part.length()) {
     return false;
   }
-  int64_t nanos = strto64(nanos_part.c_str(), &end, 10);
+  int64_t nanos = std::strtoll(nanos_part.c_str(), &end, 10);
   if (end != nanos_part.c_str() + nanos_part.length()) {
     return false;
   }
@@ -261,37 +311,43 @@
 }
 
 Duration TimeUtil::MinutesToDuration(int64_t minutes) {
-  return CreateNormalized<Duration>(minutes * kSecondsPerMinute, 0);
+  GOOGLE_DCHECK(minutes >= TimeUtil::kDurationMinSeconds / kSecondsPerMinute &&
+         minutes <= TimeUtil::kDurationMaxSeconds / kSecondsPerMinute)
+      << "Duration minutes are outside of the valid range";
+  return SecondsToDuration(minutes * kSecondsPerMinute);
 }
 
 Duration TimeUtil::HoursToDuration(int64_t hours) {
-  return CreateNormalized<Duration>(hours * kSecondsPerHour, 0);
+  GOOGLE_DCHECK(hours >= TimeUtil::kDurationMinSeconds / kSecondsPerHour &&
+         hours <= TimeUtil::kDurationMaxSeconds / kSecondsPerHour)
+      << "Duration hours are outside of the valid range";
+  return SecondsToDuration(hours * kSecondsPerHour);
 }
 
 int64_t TimeUtil::DurationToNanoseconds(const Duration& duration) {
+  GOOGLE_DCHECK(IsDurationValid(duration)) << "Duration is outside of the valid range";
   return duration.seconds() * kNanosPerSecond + duration.nanos();
 }
 
 int64_t TimeUtil::DurationToMicroseconds(const Duration& duration) {
-  return duration.seconds() * kMicrosPerSecond +
-         RoundTowardZero(duration.nanos(), kNanosPerMicrosecond);
+  return RoundTowardZero(DurationToNanoseconds(duration), kNanosPerMicrosecond);
 }
 
 int64_t TimeUtil::DurationToMilliseconds(const Duration& duration) {
-  return duration.seconds() * kMillisPerSecond +
-         RoundTowardZero(duration.nanos(), kNanosPerMillisecond);
+  return RoundTowardZero(DurationToNanoseconds(duration), kNanosPerMillisecond);
 }
 
 int64_t TimeUtil::DurationToSeconds(const Duration& duration) {
+  GOOGLE_DCHECK(IsDurationValid(duration)) << "Duration is outside of the valid range";
   return duration.seconds();
 }
 
 int64_t TimeUtil::DurationToMinutes(const Duration& duration) {
-  return RoundTowardZero(duration.seconds(), kSecondsPerMinute);
+  return RoundTowardZero(DurationToSeconds(duration), kSecondsPerMinute);
 }
 
 int64_t TimeUtil::DurationToHours(const Duration& duration) {
-  return RoundTowardZero(duration.seconds(), kSecondsPerHour);
+  return RoundTowardZero(DurationToSeconds(duration), kSecondsPerHour);
 }
 
 Timestamp TimeUtil::NanosecondsToTimestamp(int64_t nanos) {
@@ -316,20 +372,28 @@
 }
 
 int64_t TimeUtil::TimestampToNanoseconds(const Timestamp& timestamp) {
+  GOOGLE_DCHECK(IsTimestampValid(timestamp))
+      << "Timestamp is outside of the valid range";
   return timestamp.seconds() * kNanosPerSecond + timestamp.nanos();
 }
 
 int64_t TimeUtil::TimestampToMicroseconds(const Timestamp& timestamp) {
+  GOOGLE_DCHECK(IsTimestampValid(timestamp))
+      << "Timestamp is outside of the valid range";
   return timestamp.seconds() * kMicrosPerSecond +
          RoundTowardZero(timestamp.nanos(), kNanosPerMicrosecond);
 }
 
 int64_t TimeUtil::TimestampToMilliseconds(const Timestamp& timestamp) {
+  GOOGLE_DCHECK(IsTimestampValid(timestamp))
+      << "Timestamp is outside of the valid range";
   return timestamp.seconds() * kMillisPerSecond +
          RoundTowardZero(timestamp.nanos(), kNanosPerMillisecond);
 }
 
 int64_t TimeUtil::TimestampToSeconds(const Timestamp& timestamp) {
+  GOOGLE_DCHECK(IsTimestampValid(timestamp))
+      << "Timestamp is outside of the valid range";
   return timestamp.seconds();
 }
 
@@ -381,7 +445,7 @@
 using ::PROTOBUF_NAMESPACE_ID::util::kNanosPerSecond;
 
 // Convert a Duration to uint128.
-void ToUint128(const Duration& value, uint128* result, bool* negative) {
+void ToUint128(const Duration& value, absl::uint128* result, bool* negative) {
   if (value.seconds() < 0 || value.nanos() < 0) {
     *negative = true;
     *result = static_cast<uint64_t>(-value.seconds());
@@ -393,11 +457,11 @@
   }
 }
 
-void ToDuration(const uint128& value, bool negative, Duration* duration) {
+void ToDuration(const absl::uint128& value, bool negative, Duration* duration) {
   int64_t seconds =
-      static_cast<int64_t>(Uint128Low64(value / kNanosPerSecond));
+      static_cast<int64_t>(absl::Uint128Low64(value / kNanosPerSecond));
   int32_t nanos =
-      static_cast<int32_t>(Uint128Low64(value % kNanosPerSecond));
+      static_cast<int32_t>(absl::Uint128Low64(value % kNanosPerSecond));
   if (negative) {
     seconds = -seconds;
     nanos = -nanos;
@@ -421,7 +485,7 @@
 
 Duration& operator*=(Duration& d, int64_t r) {  // NOLINT
   bool negative;
-  uint128 value;
+  absl::uint128 value;
   ToUint128(d, &value, &negative);
   if (r > 0) {
     value *= static_cast<uint64_t>(r);
@@ -450,7 +514,7 @@
 
 Duration& operator/=(Duration& d, int64_t r) {  // NOLINT
   bool negative;
-  uint128 value;
+  absl::uint128 value;
   ToUint128(d, &value, &negative);
   if (r > 0) {
     value /= static_cast<uint64_t>(r);
@@ -468,10 +532,10 @@
 
 Duration& operator%=(Duration& d1, const Duration& d2) {  // NOLINT
   bool negative1, negative2;
-  uint128 value1, value2;
+  absl::uint128 value1, value2;
   ToUint128(d1, &value1, &negative1);
   ToUint128(d2, &value2, &negative2);
-  uint128 result = value1 % value2;
+  absl::uint128 result = value1 % value2;
   // When negative values are involved in division, we round the division
   // result towards zero. With this semantics, sign of the remainder is the
   // same as the dividend. For example:
@@ -484,10 +548,10 @@
 
 int64_t operator/(const Duration& d1, const Duration& d2) {
   bool negative1, negative2;
-  uint128 value1, value2;
+  absl::uint128 value1, value2;
   ToUint128(d1, &value1, &negative1);
   ToUint128(d2, &value2, &negative2);
-  int64_t result = Uint128Low64(value1 / value2);
+  int64_t result = absl::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 709527e..c272199 100644
--- a/src/google/protobuf/util/time_util.h
+++ b/src/google/protobuf/util/time_util.h
@@ -50,11 +50,11 @@
 #include <sys/time.h>
 #endif
 
-#include <google/protobuf/duration.pb.h>
-#include <google/protobuf/timestamp.pb.h>
+#include "google/protobuf/duration.pb.h"
+#include "google/protobuf/timestamp.pb.h"
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -69,11 +69,31 @@
   // The min/max Timestamp/Duration values we support.
   //
   // For "0001-01-01T00:00:00Z".
-  static const int64_t kTimestampMinSeconds = -62135596800LL;
+  static constexpr int64_t kTimestampMinSeconds = -62135596800LL;
   // For "9999-12-31T23:59:59.999999999Z".
-  static const int64_t kTimestampMaxSeconds = 253402300799LL;
-  static const int64_t kDurationMinSeconds = -315576000000LL;
-  static const int64_t kDurationMaxSeconds = 315576000000LL;
+  static constexpr int64_t kTimestampMaxSeconds = 253402300799LL;
+  static constexpr int32_t kTimestampMinNanoseconds = 0;
+  static constexpr int32_t kTimestampMaxNanoseconds = 999999999;
+  static constexpr int64_t kDurationMinSeconds = -315576000000LL;
+  static constexpr int64_t kDurationMaxSeconds = 315576000000LL;
+  static constexpr int32_t kDurationMinNanoseconds = -999999999;
+  static constexpr int32_t kDurationMaxNanoseconds = 999999999;
+
+  static bool IsTimestampValid(const Timestamp& timestamp) {
+    return timestamp.seconds() <= kTimestampMaxSeconds &&
+           timestamp.seconds() >= kTimestampMinSeconds &&
+           timestamp.nanos() <= kTimestampMaxNanoseconds &&
+           timestamp.nanos() >= kTimestampMinNanoseconds;
+  }
+
+  static bool IsDurationValid(const Duration& duration) {
+    return duration.seconds() <= kDurationMaxSeconds &&
+           duration.seconds() >= kDurationMinSeconds &&
+           duration.nanos() <= kDurationMaxNanoseconds &&
+           duration.nanos() >= kDurationMinNanoseconds &&
+           !(duration.seconds() >= 1 && duration.nanos() < 0) &&
+           !(duration.seconds() <= -1 && duration.nanos() > 0);
+  }
 
   // Converts Timestamp to/from RFC 3339 date string format.
   // Generated output will always be Z-normalized and uses 3, 6 or 9
@@ -102,9 +122,6 @@
   static std::string ToString(const Duration& duration);
   static bool FromString(const std::string& value, Duration* timestamp);
 
-#ifdef GetCurrentTime
-#undef GetCurrentTime  // Visual Studio has macro GetCurrentTime
-#endif
   // Gets the current UTC time.
   static Timestamp GetCurrentTime();
   // Returns the Time representing "1970-01-01 00:00:00".
@@ -309,6 +326,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_TIME_UTIL_H__
diff --git a/src/google/protobuf/util/time_util_test.cc b/src/google/protobuf/util/time_util_test.cc
index 79e2427..dceb6db 100644
--- a/src/google/protobuf/util/time_util_test.cc
+++ b/src/google/protobuf/util/time_util_test.cc
@@ -28,14 +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.
 
-#include <google/protobuf/util/time_util.h>
+#include "google/protobuf/util/time_util.h"
 
 #include <cstdint>
 #include <ctime>
 
-#include <google/protobuf/duration.pb.h>
-#include <google/protobuf/timestamp.pb.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/duration.pb.h"
+#include "google/protobuf/timestamp.pb.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
 
 namespace google {
@@ -48,15 +48,18 @@
 namespace {
 
 TEST(TimeUtilTest, TimestampStringFormat) {
-  Timestamp begin, end;
-  EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
-  EXPECT_EQ(TimeUtil::kTimestampMinSeconds, begin.seconds());
-  EXPECT_EQ(0, begin.nanos());
-  EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
-  EXPECT_EQ(TimeUtil::kTimestampMaxSeconds, end.seconds());
-  EXPECT_EQ(999999999, end.nanos());
-  EXPECT_EQ("0001-01-01T00:00:00Z", TimeUtil::ToString(begin));
-  EXPECT_EQ("9999-12-31T23:59:59.999999999Z", TimeUtil::ToString(end));
+  // These these are out of bounds for 32-bit architectures.
+  if(sizeof(time_t) >= sizeof(uint64_t)) {
+    Timestamp begin, end;
+    EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
+    EXPECT_EQ(TimeUtil::kTimestampMinSeconds, begin.seconds());
+    EXPECT_EQ(0, begin.nanos());
+    EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
+    EXPECT_EQ(TimeUtil::kTimestampMaxSeconds, end.seconds());
+    EXPECT_EQ(999999999, end.nanos());
+    EXPECT_EQ("0001-01-01T00:00:00Z", TimeUtil::ToString(begin));
+    EXPECT_EQ("9999-12-31T23:59:59.999999999Z", TimeUtil::ToString(end));
+  }
 
   // Test negative timestamps.
   Timestamp time = TimeUtil::NanosecondsToTimestamp(-1);
@@ -94,9 +97,12 @@
   EXPECT_TRUE(TimeUtil::FromString("0001-01-01T00:00:00Z", &begin));
   EXPECT_TRUE(TimeUtil::FromString("9999-12-31T23:59:59.999999999Z", &end));
 
-  EXPECT_EQ("315537897599.999999999s", TimeUtil::ToString(end - begin));
+  // These these are out of bounds for 32-bit architectures.
+  if(sizeof(time_t) >= sizeof(uint64_t)) {
+    EXPECT_EQ("315537897599.999999999s", TimeUtil::ToString(end - begin));
+    EXPECT_EQ("-315537897599.999999999s", TimeUtil::ToString(begin - end));
+  }
   EXPECT_EQ(999999999, (end - begin).nanos());
-  EXPECT_EQ("-315537897599.999999999s", TimeUtil::ToString(begin - end));
   EXPECT_EQ(-999999999, (begin - end).nanos());
 
   // Generated output should contain 3, 6, or 9 fractional digits.
@@ -378,6 +384,147 @@
   EXPECT_TRUE(t2 != t1);
 }
 
+TEST(TimeUtilTest, IsDurationValid) {
+  Duration valid;
+  Duration overflow;
+  overflow.set_seconds(TimeUtil::kDurationMaxSeconds + 1);
+  Duration underflow;
+  underflow.set_seconds(TimeUtil::kDurationMinSeconds - 1);
+  Duration overflow_nanos;
+  overflow_nanos.set_nanos(TimeUtil::kDurationMaxNanoseconds + 1);
+  Duration underflow_nanos;
+  underflow_nanos.set_nanos(TimeUtil::kDurationMinNanoseconds - 1);
+  Duration positive_seconds_negative_nanos;
+  positive_seconds_negative_nanos.set_seconds(1);
+  positive_seconds_negative_nanos.set_nanos(-1);
+  Duration negative_seconds_positive_nanos;
+  negative_seconds_positive_nanos.set_seconds(-1);
+  negative_seconds_positive_nanos.set_nanos(1);
+
+  EXPECT_TRUE(TimeUtil::IsDurationValid(valid));
+  EXPECT_FALSE(TimeUtil::IsDurationValid(overflow));
+  EXPECT_FALSE(TimeUtil::IsDurationValid(underflow));
+  EXPECT_FALSE(TimeUtil::IsDurationValid(overflow_nanos));
+  EXPECT_FALSE(TimeUtil::IsDurationValid(underflow_nanos));
+  EXPECT_FALSE(TimeUtil::IsDurationValid(positive_seconds_negative_nanos));
+  EXPECT_FALSE(TimeUtil::IsDurationValid(negative_seconds_positive_nanos));
+}
+
+TEST(TimeUtilTest, IsTimestampValid) {
+  Timestamp valid;
+  Timestamp overflow;
+  overflow.set_seconds(TimeUtil::kTimestampMaxSeconds + 1);
+  Timestamp underflow;
+  underflow.set_seconds(TimeUtil::kTimestampMinSeconds - 1);
+  Timestamp overflow_nanos;
+  overflow_nanos.set_nanos(TimeUtil::kTimestampMaxNanoseconds + 1);
+  Timestamp underflow_nanos;
+  underflow_nanos.set_nanos(TimeUtil::kTimestampMinNanoseconds - 1);
+
+  EXPECT_TRUE(TimeUtil::IsTimestampValid(valid));
+  EXPECT_FALSE(TimeUtil::IsTimestampValid(overflow));
+  EXPECT_FALSE(TimeUtil::IsTimestampValid(underflow));
+  EXPECT_FALSE(TimeUtil::IsTimestampValid(overflow_nanos));
+  EXPECT_FALSE(TimeUtil::IsTimestampValid(underflow_nanos));
+}
+
+#ifdef PROTOBUF_HAS_DEATH_TEST  // death tests do not work on Windows yet.
+#ifndef NDEBUG
+
+TEST(TimeUtilTest, DurationBounds) {
+  Duration overflow;
+  overflow.set_seconds(TimeUtil::kDurationMaxSeconds + 1);
+  Duration underflow;
+  underflow.set_seconds(TimeUtil::kDurationMinSeconds - 1);
+  Duration overflow_nanos;
+  overflow_nanos.set_nanos(TimeUtil::kDurationMaxNanoseconds + 1);
+  Duration underflow_nanos;
+  underflow_nanos.set_nanos(TimeUtil::kDurationMinNanoseconds - 1);
+
+  EXPECT_DEATH({ TimeUtil::SecondsToDuration(overflow.seconds()); },
+                     "Duration seconds");
+  EXPECT_DEATH({ TimeUtil::SecondsToDuration(underflow.seconds()); },
+                     "Duration seconds");
+  EXPECT_DEATH(
+      { TimeUtil::MinutesToDuration(overflow.seconds() / 60 + 1); },
+      "Duration minutes");
+  EXPECT_DEATH(
+      { TimeUtil::MinutesToDuration(underflow.seconds() / 60 - 1); },
+      "Duration minutes");
+  EXPECT_DEATH(
+      { TimeUtil::HoursToDuration(overflow.seconds() / 60 + 1); },
+      "Duration hours");
+  EXPECT_DEATH(
+      { TimeUtil::HoursToDuration(underflow.seconds() / 60 - 1); },
+      "Duration hours");
+
+  EXPECT_DEATH({ TimeUtil::DurationToNanoseconds(overflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::DurationToNanoseconds(underflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::DurationToNanoseconds(overflow_nanos); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::DurationToNanoseconds(underflow_nanos); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::DurationToSeconds(overflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::DurationToSeconds(underflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::DurationToSeconds(overflow_nanos); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::DurationToSeconds(underflow_nanos); },
+                     "outside of the valid range");
+}
+
+TEST(TimeUtilTest, TimestampBounds) {
+  Timestamp overflow;
+  overflow.set_seconds(TimeUtil::kDurationMaxSeconds + 1);
+  Timestamp underflow;
+  underflow.set_seconds(TimeUtil::kDurationMinSeconds - 1);
+  Timestamp overflow_nanos;
+  overflow_nanos.set_nanos(TimeUtil::kDurationMaxNanoseconds + 1);
+  Timestamp underflow_nanos;
+  underflow_nanos.set_nanos(TimeUtil::kDurationMinNanoseconds - 1);
+
+  EXPECT_DEATH({ TimeUtil::TimestampToNanoseconds(overflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToNanoseconds(underflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToNanoseconds(overflow_nanos); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToNanoseconds(underflow_nanos); },
+                     "outside of the valid range");
+
+  EXPECT_DEATH({ TimeUtil::TimestampToMicroseconds(overflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToMicroseconds(underflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToMicroseconds(overflow_nanos); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToMicroseconds(underflow_nanos); },
+                     "outside of the valid range");
+
+  EXPECT_DEATH({ TimeUtil::TimestampToMilliseconds(overflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToMilliseconds(underflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToMilliseconds(overflow_nanos); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToMilliseconds(underflow_nanos); },
+                     "outside of the valid range");
+
+  EXPECT_DEATH({ TimeUtil::TimestampToSeconds(overflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToSeconds(underflow); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToSeconds(overflow_nanos); },
+                     "outside of the valid range");
+  EXPECT_DEATH({ TimeUtil::TimestampToSeconds(underflow_nanos); },
+                     "outside of the valid range");
+}
+#endif  // !NDEBUG
+#endif  // PROTOBUF_HAS_DEATH_TEST
+
 }  // namespace
 }  // namespace util
 }  // namespace protobuf
diff --git a/src/google/protobuf/util/type_resolver.h b/src/google/protobuf/util/type_resolver.h
index b2e7b43..f5c3338 100644
--- a/src/google/protobuf/util/type_resolver.h
+++ b/src/google/protobuf/util/type_resolver.h
@@ -35,13 +35,13 @@
 
 #include <string>
 
-#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/type.pb.h"
+#include "absl/status/status.h"
+#include "google/protobuf/port.h"
+
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -54,24 +54,23 @@
 class PROTOBUF_EXPORT TypeResolver {
  public:
   TypeResolver() {}
+  TypeResolver(const TypeResolver&) = delete;
+  TypeResolver& operator=(const TypeResolver&) = delete;
   virtual ~TypeResolver() {}
 
   // Resolves a type url for a message type.
-  virtual util::Status ResolveMessageType(
+  virtual absl::Status ResolveMessageType(
       const std::string& type_url, google::protobuf::Type* message_type) = 0;
 
   // Resolves a type url for an enum type.
-  virtual util::Status ResolveEnumType(const std::string& type_url,
+  virtual absl::Status ResolveEnumType(const std::string& type_url,
                                        google::protobuf::Enum* enum_type) = 0;
-
- private:
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(TypeResolver);
 };
 
 }  // namespace util
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_H__
diff --git a/src/google/protobuf/util/type_resolver_util.cc b/src/google/protobuf/util/type_resolver_util.cc
index 8be0efb..d077482 100644
--- a/src/google/protobuf/util/type_resolver_util.cc
+++ b/src/google/protobuf/util/type_resolver_util.cc
@@ -28,20 +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.
 
-#include <google/protobuf/util/type_resolver_util.h>
+#include "google/protobuf/util/type_resolver_util.h"
 
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/wrappers.pb.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/stubs/status.h>
-#include <google/protobuf/util/internal/utility.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/stubs/status.h>
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/wrappers.pb.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/descriptor.h"
+#include "absl/status/status.h"
+#include "absl/strings/escaping.h"
+#include "absl/strings/str_cat.h"
+#include "google/protobuf/io/strtod.h"
+#include "google/protobuf/util/type_resolver.h"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -70,38 +70,38 @@
                              const DescriptorPool* pool)
       : url_prefix_(url_prefix), pool_(pool) {}
 
-  util::Status ResolveMessageType(const std::string& type_url,
+  absl::Status ResolveMessageType(const std::string& type_url,
                                   Type* type) override {
     std::string type_name;
-    util::Status status = ParseTypeUrl(type_url, &type_name);
+    absl::Status status = ParseTypeUrl(type_url, &type_name);
     if (!status.ok()) {
       return status;
     }
 
     const Descriptor* descriptor = pool_->FindMessageTypeByName(type_name);
     if (descriptor == NULL) {
-      return util::NotFoundError("Invalid type URL, unknown type: " +
+      return absl::NotFoundError("Invalid type URL, unknown type: " +
                                  type_name);
     }
     ConvertDescriptor(descriptor, type);
-    return util::Status();
+    return absl::Status();
   }
 
-  util::Status ResolveEnumType(const std::string& type_url,
+  absl::Status ResolveEnumType(const std::string& type_url,
                                Enum* enum_type) override {
     std::string type_name;
-    util::Status status = ParseTypeUrl(type_url, &type_name);
+    absl::Status status = ParseTypeUrl(type_url, &type_name);
     if (!status.ok()) {
       return status;
     }
 
     const EnumDescriptor* descriptor = pool_->FindEnumTypeByName(type_name);
     if (descriptor == NULL) {
-      return util::InvalidArgumentError("Invalid type URL, unknown type: " +
+      return absl::InvalidArgumentError("Invalid type URL, unknown type: " +
                                         type_name);
     }
     ConvertEnumDescriptor(descriptor, enum_type);
-    return util::Status();
+    return absl::Status();
   }
 
  private:
@@ -303,43 +303,43 @@
     return url_prefix_ + "/" + descriptor->full_name();
   }
 
-  util::Status ParseTypeUrl(const std::string& type_url,
+  absl::Status ParseTypeUrl(const std::string& type_url,
                             std::string* type_name) {
     if (type_url.substr(0, url_prefix_.size() + 1) != url_prefix_ + "/") {
-      return util::InvalidArgumentError(
-          StrCat("Invalid type URL, type URLs must be of the form '",
+      return absl::InvalidArgumentError(
+          absl::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 util::Status();
+    return absl::Status();
   }
 
   std::string DefaultValueAsString(const FieldDescriptor* descriptor) {
     switch (descriptor->cpp_type()) {
       case FieldDescriptor::CPPTYPE_INT32:
-        return StrCat(descriptor->default_value_int32());
+        return absl::StrCat(descriptor->default_value_int32());
         break;
       case FieldDescriptor::CPPTYPE_INT64:
-        return StrCat(descriptor->default_value_int64());
+        return absl::StrCat(descriptor->default_value_int64());
         break;
       case FieldDescriptor::CPPTYPE_UINT32:
-        return StrCat(descriptor->default_value_uint32());
+        return absl::StrCat(descriptor->default_value_uint32());
         break;
       case FieldDescriptor::CPPTYPE_UINT64:
-        return StrCat(descriptor->default_value_uint64());
+        return absl::StrCat(descriptor->default_value_uint64());
         break;
       case FieldDescriptor::CPPTYPE_FLOAT:
-        return SimpleFtoa(descriptor->default_value_float());
+        return io::SimpleFtoa(descriptor->default_value_float());
         break;
       case FieldDescriptor::CPPTYPE_DOUBLE:
-        return SimpleDtoa(descriptor->default_value_double());
+        return io::SimpleDtoa(descriptor->default_value_double());
         break;
       case FieldDescriptor::CPPTYPE_BOOL:
         return descriptor->default_value_bool() ? "true" : "false";
         break;
       case FieldDescriptor::CPPTYPE_STRING:
         if (descriptor->type() == FieldDescriptor::TYPE_BYTES) {
-          return CEscape(descriptor->default_value_string());
+          return absl::CEscape(descriptor->default_value_string());
         } else {
           return descriptor->default_value_string();
         }
diff --git a/src/google/protobuf/util/type_resolver_util.h b/src/google/protobuf/util/type_resolver_util.h
index 7f6a4b9..0327e61 100644
--- a/src/google/protobuf/util/type_resolver_util.h
+++ b/src/google/protobuf/util/type_resolver_util.h
@@ -35,15 +35,15 @@
 
 #include <string>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 namespace google {
 namespace protobuf {
 class DescriptorPool;
 namespace util {
 class TypeResolver;
 
-// Must be included last.
-#include <google/protobuf/port_def.inc>
-
 // Creates a TypeResolver that serves type information in the given descriptor
 // pool. Caller takes ownership of the returned TypeResolver.
 PROTOBUF_EXPORT TypeResolver* NewTypeResolverForDescriptorPool(
@@ -53,6 +53,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_UTIL_TYPE_RESOLVER_UTIL_H__
diff --git a/src/google/protobuf/util/type_resolver_util_test.cc b/src/google/protobuf/util/type_resolver_util_test.cc
index 2780a39..8a54bca 100644
--- a/src/google/protobuf/util/type_resolver_util_test.cc
+++ b/src/google/protobuf/util/type_resolver_util_test.cc
@@ -28,7 +28,7 @@
 // (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/util/type_resolver_util.h>
+#include "google/protobuf/util/type_resolver_util.h"
 
 #include <cstdint>
 #include <limits>
@@ -36,16 +36,16 @@
 #include <string>
 #include <vector>
 
-#include <google/protobuf/type.pb.h>
-#include <google/protobuf/wrappers.pb.h>
-#include <google/protobuf/map_unittest.pb.h>
-#include <google/protobuf/test_util.h>
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_custom_options.pb.h>
-#include <google/protobuf/util/json_format_proto3.pb.h>
-#include <google/protobuf/util/type_resolver.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/type.pb.h"
+#include "google/protobuf/wrappers.pb.h"
+#include "google/protobuf/util/type_resolver.h"
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
+#include "google/protobuf/util/json_format_proto3.pb.h"
+#include "google/protobuf/map_unittest.pb.h"
+#include "google/protobuf/test_util.h"
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_custom_options.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/well_known_types_unittest.cc b/src/google/protobuf/well_known_types_unittest.cc
index c9a9aa1..4d7a0ff 100644
--- a/src/google/protobuf/well_known_types_unittest.cc
+++ b/src/google/protobuf/well_known_types_unittest.cc
@@ -27,12 +27,11 @@
 // 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/unittest_well_known_types.pb.h>
-
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/testing/googletest.h>
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/stl_util.h>
+
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/testing/googletest.h"
+#include "google/protobuf/unittest_well_known_types.pb.h"
 
 namespace google {
 namespace protobuf {
diff --git a/src/google/protobuf/wire_format.cc b/src/google/protobuf/wire_format.cc
index 6fe63c8..ff542b7 100644
--- a/src/google/protobuf/wire_format.cc
+++ b/src/google/protobuf/wire_format.cc
@@ -32,30 +32,31 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/wire_format.h"
 
 #include <stack>
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.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/descriptor.h>
-#include <google/protobuf/descriptor.pb.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/map_field.h>
-#include <google/protobuf/map_field_inl.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/unknown_field_set.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/cord.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/descriptor.pb.h"
+#include "google/protobuf/dynamic_message.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/map_field.h"
+#include "google/protobuf/map_field_inl.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/unknown_field_set.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 const size_t kMapEntryTagByteSize = 2;
 
@@ -1765,4 +1766,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/wire_format.h b/src/google/protobuf/wire_format.h
index 1acbf9e..64313c2 100644
--- a/src/google/protobuf/wire_format.h
+++ b/src/google/protobuf/wire_format.h
@@ -40,22 +40,23 @@
 #define GOOGLE_PROTOBUF_WIRE_FORMAT_H__
 
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/parse_context.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/stubs/common.h"
+#include "absl/base/casts.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/parse_context.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/wire_format_lite.h"
 
 #ifdef SWIG
 #error "You cannot SWIG proto headers"
 #endif
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -79,6 +80,8 @@
 // This class is really a namespace that contains only static methods
 class PROTOBUF_EXPORT WireFormat {
  public:
+  WireFormat() = delete;
+
   // Given a field return its WireType
   static inline WireFormatLite::WireType WireTypeForField(
       const FieldDescriptor* field);
@@ -285,6 +288,7 @@
 
  private:
   struct MessageSetParser;
+  friend class TcParser;
   // Skip a MessageSet field.
   static bool SkipMessageSetField(io::CodedInputStream* input,
                                   uint32_t field_number,
@@ -301,8 +305,6 @@
                                                  uint64_t tag,
                                                  const Reflection* reflection,
                                                  const FieldDescriptor* field);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormat);
 };
 
 // Subclass of FieldSkipper which saves skipped fields to an UnknownFieldSet.
@@ -337,7 +339,7 @@
   // Some compilers don't like enum -> enum casts, so we implicit_cast to
   // int first.
   return WireFormatLite::WireTypeForFieldType(
-      static_cast<WireFormatLite::FieldType>(implicit_cast<int>(type)));
+      static_cast<WireFormatLite::FieldType>(absl::implicit_cast<int>(type)));
 }
 
 inline uint32_t WireFormat::MakeTag(const FieldDescriptor* field) {
@@ -350,7 +352,7 @@
   // int first.
   return WireFormatLite::TagSize(
       field_number,
-      static_cast<WireFormatLite::FieldType>(implicit_cast<int>(type)));
+      static_cast<WireFormatLite::FieldType>(absl::implicit_cast<int>(type)));
 }
 
 inline void WireFormat::VerifyUTF8String(const char* data, int size,
@@ -409,6 +411,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_H__
diff --git a/src/google/protobuf/wire_format_lite.cc b/src/google/protobuf/wire_format_lite.cc
index 5ab1ca1..a8110bc 100644
--- a/src/google/protobuf/wire_format_lite.cc
+++ b/src/google/protobuf/wire_format_lite.cc
@@ -32,23 +32,23 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/wire_format_lite.h"
 
 #include <limits>
 #include <stack>
 #include <string>
 #include <vector>
 
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/io/zero_copy_stream.h>
-#include <google/protobuf/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/stubs/stringprintf.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/str_cat.h"
+#include "absl/strings/str_format.h"
+#include "utf8_validity.h"
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -593,8 +593,8 @@
   return ReadBytesToString(input, *p);
 }
 
-void PrintUTF8ErrorLog(StringPiece message_name,
-                       StringPiece field_name, const char* operation_str,
+void PrintUTF8ErrorLog(absl::string_view message_name,
+                       absl::string_view field_name, const char* operation_str,
                        bool emit_stacktrace) {
   std::string stacktrace;
   (void)emit_stacktrace;  // Parameter is used by Google-internal code.
@@ -602,13 +602,13 @@
   if (!field_name.empty()) {
     if (!message_name.empty()) {
       quoted_field_name =
-          StrCat(" '", message_name, ".", field_name, "'");
+          absl::StrCat(" '", message_name, ".", field_name, "'");
     } else {
-      quoted_field_name = StrCat(" '", field_name, "'");
+      quoted_field_name = absl::StrCat(" '", field_name, "'");
     }
   }
   std::string error_message =
-      StrCat("String field", quoted_field_name,
+      absl::StrCat("String field", quoted_field_name,
                    " contains invalid UTF-8 data "
                    "when ",
                    operation_str,
@@ -620,7 +620,7 @@
 
 bool WireFormatLite::VerifyUtf8String(const char* data, int size, Operation op,
                                       const char* field_name) {
-  if (!IsStructurallyValidUTF8(data, size)) {
+  if (!utf8_range::IsStructurallyValid({data, static_cast<size_t>(size)})) {
     const char* operation_str = nullptr;
     switch (op) {
       case PARSE:
@@ -815,4 +815,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#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 80d3961..59fb09d 100644
--- a/src/google/protobuf/wire_format_lite.h
+++ b/src/google/protobuf/wire_format_lite.h
@@ -44,16 +44,16 @@
 #include <limits>
 #include <string>
 
-#include <google/protobuf/stubs/common.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/port.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/message_lite.h>
-#include <google/protobuf/repeated_field.h>
+#include "google/protobuf/stubs/common.h"
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/port.h"
+#include "absl/base/casts.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/message_lite.h"
+#include "google/protobuf/port.h"
+#include "google/protobuf/repeated_field.h"
 
-// Do UTF-8 validation on string type in Debug build only
 #ifndef NDEBUG
 #define GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
 #endif
@@ -70,7 +70,7 @@
 
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -87,6 +87,7 @@
 // This class is really a namespace that contains only static methods.
 class PROTOBUF_EXPORT WireFormatLite {
  public:
+  WireFormatLite() = delete;
   // -----------------------------------------------------------------
   // Helper constants and functions related to the format.  These are
   // mostly meant for internal and generated code to use.
@@ -102,7 +103,11 @@
   // identifies the encoding of this data, it is possible to skip
   // unrecognized fields for forwards compatibility.
 
-  enum WireType {
+  enum WireType
+#ifndef SWIG
+      : int
+#endif  // !SWIG
+  {
     WIRETYPE_VARINT = 0,
     WIRETYPE_FIXED64 = 1,
     WIRETYPE_LENGTH_DELIMITED = 2,
@@ -742,8 +747,6 @@
   static const WireFormatLite::WireType kWireTypeForFieldType[];
   static void WriteSubMessageMaybeToArray(int size, const MessageLite& value,
                                           io::CodedOutputStream* output);
-
-  GOOGLE_DISALLOW_EVIL_CONSTRUCTORS(WireFormatLite);
 };
 
 // A class which deals with unknown values.  The default implementation just
@@ -818,19 +821,19 @@
 }
 
 inline uint32_t WireFormatLite::EncodeFloat(float value) {
-  return bit_cast<uint32_t>(value);
+  return absl::bit_cast<uint32_t>(value);
 }
 
 inline float WireFormatLite::DecodeFloat(uint32_t value) {
-  return bit_cast<float>(value);
+  return absl::bit_cast<float>(value);
 }
 
 inline uint64_t WireFormatLite::EncodeDouble(double value) {
-  return bit_cast<uint64_t>(value);
+  return absl::bit_cast<uint64_t>(value);
 }
 
 inline double WireFormatLite::DecodeDouble(uint64_t value) {
-  return bit_cast<double>(value);
+  return absl::bit_cast<double>(value);
 }
 
 // ZigZag Transform:  Encodes signed integers so that they can be
@@ -1903,6 +1906,6 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
 
 #endif  // GOOGLE_PROTOBUF_WIRE_FORMAT_LITE_H__
diff --git a/src/google/protobuf/wire_format_unittest.cc b/src/google/protobuf/wire_format_unittest.cc
index f1ed951..f51cf53 100644
--- a/src/google/protobuf/wire_format_unittest.cc
+++ b/src/google/protobuf/wire_format_unittest.cc
@@ -32,12 +32,12 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/wire_format.h"
 
-#include <google/protobuf/unittest.pb.h>
-#include <google/protobuf/unittest_mset.pb.h>
-#include <google/protobuf/unittest_mset_wire_format.pb.h>
-#include <google/protobuf/unittest_proto3_arena.pb.h>
+#include "google/protobuf/unittest.pb.h"
+#include "google/protobuf/unittest_mset.pb.h"
+#include "google/protobuf/unittest_mset_wire_format.pb.h"
+#include "google/protobuf/unittest_proto3_arena.pb.h"
 #include <gmock/gmock.h>
 #include <gtest/gtest.h>
 
@@ -49,12 +49,12 @@
 
 // Must include after defining UNITTEST, etc.
 // clang-format off
-#include <google/protobuf/test_util.inc>
-#include <google/protobuf/wire_format_unittest.inc>
+#include "google/protobuf/test_util.inc"
+#include "google/protobuf/wire_format_unittest.inc"
 // clang-format on
 
 // Must be included last.
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 
 namespace google {
 namespace protobuf {
@@ -67,4 +67,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/wire_format_unittest.inc b/src/google/protobuf/wire_format_unittest.inc
index 0e3869c..9e0973b 100644
--- a/src/google/protobuf/wire_format_unittest.inc
+++ b/src/google/protobuf/wire_format_unittest.inc
@@ -32,26 +32,26 @@
 //  Based on original Protocol Buffers design by
 //  Sanjay Ghemawat, Jeff Dean, and others.
 
-#include <google/protobuf/stubs/logging.h>
-#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/io/zero_copy_stream_impl_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/wire_format.h>
-#include <google/protobuf/wire_format_lite.h>
+#include "google/protobuf/stubs/logging.h"
+#include "google/protobuf/stubs/common.h"
 #include <gmock/gmock.h>
-#include <google/protobuf/testing/googletest.h>
+#include "google/protobuf/testing/googletest.h"
 #include <gtest/gtest.h>
-#include <google/protobuf/stubs/casts.h>
-#include <google/protobuf/stubs/logging.h>
-#include <google/protobuf/stubs/strutil.h>
-#include <google/protobuf/dynamic_message.h>
-#include <google/protobuf/test_util2.h>
-#include <google/protobuf/stubs/stl_util.h>
+#include "absl/base/casts.h"
+#include "google/protobuf/stubs/logging.h"
+#include "absl/strings/cord.h"
+#include "absl/strings/match.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/dynamic_message.h"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/io/zero_copy_stream_impl.h"
+#include "google/protobuf/io/zero_copy_stream_impl_lite.h"
+#include "google/protobuf/test_util2.h"
+#include "google/protobuf/wire_format.h"
+#include "google/protobuf/wire_format_lite.h"
 
 // clang-format off
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 // clang-format on
 
 namespace google {
@@ -63,15 +63,15 @@
   // Verify that WireFormatLite::FieldType and WireFormatLite::CppType match
   // FieldDescriptor::Type and FieldDescriptor::CppType.
 
-  EXPECT_EQ(implicit_cast<int>(FieldDescriptor::MAX_TYPE),
-            implicit_cast<int>(WireFormatLite::MAX_FIELD_TYPE));
-  EXPECT_EQ(implicit_cast<int>(FieldDescriptor::MAX_CPPTYPE),
-            implicit_cast<int>(WireFormatLite::MAX_CPPTYPE));
+  EXPECT_EQ(absl::implicit_cast<int>(FieldDescriptor::MAX_TYPE),
+            absl::implicit_cast<int>(WireFormatLite::MAX_FIELD_TYPE));
+  EXPECT_EQ(absl::implicit_cast<int>(FieldDescriptor::MAX_CPPTYPE),
+            absl::implicit_cast<int>(WireFormatLite::MAX_CPPTYPE));
 
   for (int i = 1; i <= WireFormatLite::MAX_FIELD_TYPE; i++) {
-    EXPECT_EQ(implicit_cast<int>(FieldDescriptor::TypeToCppType(
+    EXPECT_EQ(absl::implicit_cast<int>(FieldDescriptor::TypeToCppType(
                   static_cast<FieldDescriptor::Type>(i))),
-              implicit_cast<int>(WireFormatLite::FieldTypeToCppType(
+              absl::implicit_cast<int>(WireFormatLite::FieldTypeToCppType(
                   static_cast<WireFormatLite::FieldType>(i))));
   }
 }
@@ -493,16 +493,14 @@
 
   // Serialize to flat array
   {
-    uint8_t* target =
-        reinterpret_cast<uint8_t*>(::google::protobuf::string_as_array(&flat_data));
+    uint8_t* target = reinterpret_cast<uint8_t*>(&flat_data[0]);
     uint8_t* end = message_set.SerializeWithCachedSizesToArray(target);
     EXPECT_EQ(size, end - target);
   }
 
   // Serialize to buffer
   {
-    io::ArrayOutputStream array_stream(::google::protobuf::string_as_array(&stream_data), size,
-                                       1);
+    io::ArrayOutputStream array_stream(&stream_data[0], size, 1);
     io::CodedOutputStream output_stream(&array_stream);
     message_set.SerializeWithCachedSizes(&output_stream);
     ASSERT_FALSE(output_stream.HadError());
@@ -1560,7 +1558,7 @@
 #ifdef GOOGLE_PROTOBUF_UTF8_VALIDATION_ENABLED
   ASSERT_EQ(1, errors.size());
   EXPECT_TRUE(
-      HasPrefixString(errors[0],
+      absl::StartsWith(errors[0],
                        "String field contains invalid UTF-8 data when "
                        "serializing a protocol buffer. Use the "
                        "'bytes' type if you intend to send raw bytes."));
@@ -1706,4 +1704,4 @@
 }  // namespace protobuf
 }  // namespace google
 
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/wrappers.pb.cc b/src/google/protobuf/wrappers.pb.cc
index 40ba60a..a09a6a2 100644
--- a/src/google/protobuf/wrappers.pb.cc
+++ b/src/google/protobuf/wrappers.pb.cc
@@ -1,268 +1,316 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/wrappers.proto
 
-#include <google/protobuf/wrappers.pb.h>
+#include "google/protobuf/wrappers.pb.h"
 
 #include <algorithm>
-
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/extension_set.h>
-#include <google/protobuf/wire_format_lite.h>
-#include <google/protobuf/descriptor.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/reflection_ops.h>
-#include <google/protobuf/wire_format.h>
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/extension_set.h"
+#include "google/protobuf/wire_format_lite.h"
+#include "google/protobuf/descriptor.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/reflection_ops.h"
+#include "google/protobuf/wire_format.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
 
+// Must be included last.
+#include "google/protobuf/port_def.inc"
 PROTOBUF_PRAGMA_INIT_SEG
-
 namespace _pb = ::PROTOBUF_NAMESPACE_ID;
-namespace _pbi = _pb::internal;
-
+namespace _pbi = ::PROTOBUF_NAMESPACE_ID::internal;
 PROTOBUF_NAMESPACE_OPEN
 PROTOBUF_CONSTEXPR DoubleValue::DoubleValue(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.value_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct DoubleValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR DoubleValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR DoubleValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~DoubleValueDefaultTypeInternal() {}
   union {
     DoubleValue _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DoubleValueDefaultTypeInternal _DoubleValue_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 DoubleValueDefaultTypeInternal _DoubleValue_default_instance_;
 PROTOBUF_CONSTEXPR FloatValue::FloatValue(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.value_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct FloatValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR FloatValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR FloatValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~FloatValueDefaultTypeInternal() {}
   union {
     FloatValue _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FloatValueDefaultTypeInternal _FloatValue_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 FloatValueDefaultTypeInternal _FloatValue_default_instance_;
 PROTOBUF_CONSTEXPR Int64Value::Int64Value(
     ::_pbi::ConstantInitialized): _impl_{
-    /*decltype(_impl_.value_)*/int64_t{0}
+    /*decltype(_impl_.value_)*/::int64_t{0}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct Int64ValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR Int64ValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR Int64ValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~Int64ValueDefaultTypeInternal() {}
   union {
     Int64Value _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Int64ValueDefaultTypeInternal _Int64Value_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Int64ValueDefaultTypeInternal _Int64Value_default_instance_;
 PROTOBUF_CONSTEXPR UInt64Value::UInt64Value(
     ::_pbi::ConstantInitialized): _impl_{
-    /*decltype(_impl_.value_)*/uint64_t{0u}
+    /*decltype(_impl_.value_)*/::uint64_t{0u}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct UInt64ValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR UInt64ValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR UInt64ValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~UInt64ValueDefaultTypeInternal() {}
   union {
     UInt64Value _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_;
 PROTOBUF_CONSTEXPR Int32Value::Int32Value(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.value_)*/0
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct Int32ValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR Int32ValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR Int32ValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~Int32ValueDefaultTypeInternal() {}
   union {
     Int32Value _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Int32ValueDefaultTypeInternal _Int32Value_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 Int32ValueDefaultTypeInternal _Int32Value_default_instance_;
 PROTOBUF_CONSTEXPR UInt32Value::UInt32Value(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.value_)*/0u
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct UInt32ValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR UInt32ValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR UInt32ValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~UInt32ValueDefaultTypeInternal() {}
   union {
     UInt32Value _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 UInt32ValueDefaultTypeInternal _UInt32Value_default_instance_;
 PROTOBUF_CONSTEXPR BoolValue::BoolValue(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.value_)*/false
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct BoolValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR BoolValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR BoolValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~BoolValueDefaultTypeInternal() {}
   union {
     BoolValue _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BoolValueDefaultTypeInternal _BoolValue_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BoolValueDefaultTypeInternal _BoolValue_default_instance_;
 PROTOBUF_CONSTEXPR StringValue::StringValue(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct StringValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR StringValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR StringValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~StringValueDefaultTypeInternal() {}
   union {
     StringValue _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 StringValueDefaultTypeInternal _StringValue_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 StringValueDefaultTypeInternal _StringValue_default_instance_;
 PROTOBUF_CONSTEXPR BytesValue::BytesValue(
     ::_pbi::ConstantInitialized): _impl_{
     /*decltype(_impl_.value_)*/{&::_pbi::fixed_address_empty_string, ::_pbi::ConstantInitialized{}}
   , /*decltype(_impl_._cached_size_)*/{}} {}
 struct BytesValueDefaultTypeInternal {
-  PROTOBUF_CONSTEXPR BytesValueDefaultTypeInternal()
-      : _instance(::_pbi::ConstantInitialized{}) {}
+  PROTOBUF_CONSTEXPR BytesValueDefaultTypeInternal() : _instance(::_pbi::ConstantInitialized{}) {}
   ~BytesValueDefaultTypeInternal() {}
   union {
     BytesValue _instance;
   };
 };
-PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BytesValueDefaultTypeInternal _BytesValue_default_instance_;
+
+PROTOBUF_ATTRIBUTE_NO_DESTROY PROTOBUF_CONSTINIT
+    PROTOBUF_ATTRIBUTE_INIT_PRIORITY1 BytesValueDefaultTypeInternal _BytesValue_default_instance_;
 PROTOBUF_NAMESPACE_CLOSE
 static ::_pb::Metadata file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[9];
-static constexpr ::_pb::EnumDescriptor const** file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
-static constexpr ::_pb::ServiceDescriptor const** file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
-
-const uint32_t TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DoubleValue, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DoubleValue, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FloatValue, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FloatValue, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int64Value, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int64Value, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt64Value, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt64Value, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int32Value, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int32Value, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt32Value, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt32Value, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BoolValue, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BoolValue, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::StringValue, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::StringValue, _impl_.value_),
-  ~0u,  // no _has_bits_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BytesValue, _internal_metadata_),
-  ~0u,  // no _extensions_
-  ~0u,  // no _oneof_case_
-  ~0u,  // no _weak_field_map_
-  ~0u,  // no _inlined_string_donated_
-  PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BytesValue, _impl_.value_),
+static constexpr const ::_pb::EnumDescriptor**
+    file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
+static constexpr const ::_pb::ServiceDescriptor**
+    file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto = nullptr;
+const ::uint32_t TableStruct_google_2fprotobuf_2fwrappers_2eproto::offsets[] PROTOBUF_SECTION_VARIABLE(
+    protodesc_cold) = {
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DoubleValue, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::DoubleValue, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FloatValue, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::FloatValue, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int64Value, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int64Value, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt64Value, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt64Value, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int32Value, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::Int32Value, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt32Value, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::UInt32Value, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BoolValue, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BoolValue, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::StringValue, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::StringValue, _impl_.value_),
+    ~0u,  // no _has_bits_
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BytesValue, _internal_metadata_),
+    ~0u,  // no _extensions_
+    ~0u,  // no _oneof_case_
+    ~0u,  // no _weak_field_map_
+    ~0u,  // no _inlined_string_donated_
+    ~0u,  // no _split_
+    ~0u,  // no sizeof(Split)
+    PROTOBUF_FIELD_OFFSET(::PROTOBUF_NAMESPACE_ID::BytesValue, _impl_.value_),
 };
-static const ::_pbi::MigrationSchema schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
-  { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DoubleValue)},
-  { 7, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FloatValue)},
-  { 14, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Int64Value)},
-  { 21, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UInt64Value)},
-  { 28, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Int32Value)},
-  { 35, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UInt32Value)},
-  { 42, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::BoolValue)},
-  { 49, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::StringValue)},
-  { 56, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::BytesValue)},
+
+static const ::_pbi::MigrationSchema
+    schemas[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+        { 0, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::DoubleValue)},
+        { 9, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::FloatValue)},
+        { 18, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Int64Value)},
+        { 27, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UInt64Value)},
+        { 36, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::Int32Value)},
+        { 45, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::UInt32Value)},
+        { 54, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::BoolValue)},
+        { 63, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::StringValue)},
+        { 72, -1, -1, sizeof(::PROTOBUF_NAMESPACE_ID::BytesValue)},
 };
 
 static const ::_pb::Message* const file_default_instances[] = {
-  &::PROTOBUF_NAMESPACE_ID::_DoubleValue_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_FloatValue_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Int64Value_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_UInt64Value_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_Int32Value_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_UInt32Value_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_BoolValue_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_StringValue_default_instance_._instance,
-  &::PROTOBUF_NAMESPACE_ID::_BytesValue_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_DoubleValue_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_FloatValue_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Int64Value_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_UInt64Value_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_Int32Value_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_UInt32Value_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_BoolValue_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_StringValue_default_instance_._instance,
+    &::PROTOBUF_NAMESPACE_ID::_BytesValue_default_instance_._instance,
 };
-
-const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) =
-  "\n\036google/protobuf/wrappers.proto\022\017google"
-  ".protobuf\"\034\n\013DoubleValue\022\r\n\005value\030\001 \001(\001\""
-  "\033\n\nFloatValue\022\r\n\005value\030\001 \001(\002\"\033\n\nInt64Val"
-  "ue\022\r\n\005value\030\001 \001(\003\"\034\n\013UInt64Value\022\r\n\005valu"
-  "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\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 ::_pbi::once_flag descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once;
+const char descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto[] PROTOBUF_SECTION_VARIABLE(protodesc_cold) = {
+    "\n\036google/protobuf/wrappers.proto\022\017google"
+    ".protobuf\"\034\n\013DoubleValue\022\r\n\005value\030\001 \001(\001\""
+    "\033\n\nFloatValue\022\r\n\005value\030\001 \001(\002\"\033\n\nInt64Val"
+    "ue\022\r\n\005value\030\001 \001(\003\"\034\n\013UInt64Value\022\r\n\005valu"
+    "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\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 ::absl::once_flag descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once;
 const ::_pbi::DescriptorTable descriptor_table_google_2fprotobuf_2fwrappers_2eproto = {
-    false, false, 455, descriptor_table_protodef_google_2fprotobuf_2fwrappers_2eproto,
+    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, file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto,
+    &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,
+    file_level_enum_descriptors_google_2fprotobuf_2fwrappers_2eproto,
     file_level_service_descriptors_google_2fprotobuf_2fwrappers_2eproto,
 };
+
+// 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 ::_pbi::DescriptorTable* descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter() {
   return &descriptor_table_google_2fprotobuf_2fwrappers_2eproto;
 }
-
 // Force running AddDescriptors() at dynamic initialization time.
-PROTOBUF_ATTRIBUTE_INIT_PRIORITY2 static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fwrappers_2eproto(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
+PROTOBUF_ATTRIBUTE_INIT_PRIORITY2
+static ::_pbi::AddDescriptorsRunner dynamic_init_dummy_google_2fprotobuf_2fwrappers_2eproto(&descriptor_table_google_2fprotobuf_2fwrappers_2eproto);
 PROTOBUF_NAMESPACE_OPEN
-
 // ===================================================================
 
 class DoubleValue::_Internal {
@@ -276,14 +324,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.DoubleValue)
 }
 DoubleValue::DoubleValue(const DoubleValue& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  DoubleValue* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.value_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  _this->_impl_.value_ = from._impl_.value_;
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.DoubleValue)
 }
 
@@ -316,7 +359,7 @@
 
 void DoubleValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.DoubleValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -325,18 +368,20 @@
 }
 
 const char* DoubleValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // double value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 9)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 9)) {
           _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<double>(ptr);
           ptr += sizeof(double);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -361,16 +406,17 @@
 #undef CHK_
 }
 
-uint8_t* DoubleValue::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* DoubleValue::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.DoubleValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // double value = 1;
-  static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size.");
+  static_assert(sizeof(::uint64_t) == sizeof(double), "Code assumes ::uint64_t and double are the same size.");
   double tmp_value = this->_internal_value();
-  uint64_t raw_value;
+  ::uint64_t raw_value;
   memcpy(&raw_value, &tmp_value, sizeof(tmp_value));
   if (raw_value != 0) {
     target = stream->EnsureSpace(target);
@@ -385,18 +431,19 @@
   return target;
 }
 
-size_t DoubleValue::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DoubleValue)
-  size_t total_size = 0;
+::size_t DoubleValue::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.DoubleValue)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   // double value = 1;
-  static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size.");
+  static_assert(sizeof(::uint64_t) == sizeof(double), "Code assumes ::uint64_t and double are the same size.");
   double tmp_value = this->_internal_value();
-  uint64_t raw_value;
+  ::uint64_t raw_value;
   memcpy(&raw_value, &tmp_value, sizeof(tmp_value));
   if (raw_value != 0) {
     total_size += 1 + 8;
@@ -415,14 +462,15 @@
 void DoubleValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<DoubleValue*>(&to_msg);
   auto& from = static_cast<const DoubleValue&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.DoubleValue)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
-  static_assert(sizeof(uint64_t) == sizeof(double), "Code assumes uint64_t and double are the same size.");
+  static_assert(sizeof(::uint64_t) == sizeof(double), "Code assumes ::uint64_t and double are the same size.");
   double tmp_value = from._internal_value();
-  uint64_t raw_value;
+  ::uint64_t raw_value;
   memcpy(&raw_value, &tmp_value, sizeof(tmp_value));
   if (raw_value != 0) {
     _this->_internal_set_value(from._internal_value());
@@ -448,11 +496,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata DoubleValue::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[0]);
 }
-
 // ===================================================================
 
 class FloatValue::_Internal {
@@ -466,14 +514,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.FloatValue)
 }
 FloatValue::FloatValue(const FloatValue& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  FloatValue* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.value_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  _this->_impl_.value_ = from._impl_.value_;
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.FloatValue)
 }
 
@@ -506,7 +549,7 @@
 
 void FloatValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.FloatValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -515,18 +558,20 @@
 }
 
 const char* FloatValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // float value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 13)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 13)) {
           _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::UnalignedLoad<float>(ptr);
           ptr += sizeof(float);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -551,16 +596,17 @@
 #undef CHK_
 }
 
-uint8_t* FloatValue::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* FloatValue::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.FloatValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // float value = 1;
-  static_assert(sizeof(uint32_t) == sizeof(float), "Code assumes uint32_t and float are the same size.");
+  static_assert(sizeof(::uint32_t) == sizeof(float), "Code assumes ::uint32_t and float are the same size.");
   float tmp_value = this->_internal_value();
-  uint32_t raw_value;
+  ::uint32_t raw_value;
   memcpy(&raw_value, &tmp_value, sizeof(tmp_value));
   if (raw_value != 0) {
     target = stream->EnsureSpace(target);
@@ -575,18 +621,19 @@
   return target;
 }
 
-size_t FloatValue::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FloatValue)
-  size_t total_size = 0;
+::size_t FloatValue::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.FloatValue)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
   // float value = 1;
-  static_assert(sizeof(uint32_t) == sizeof(float), "Code assumes uint32_t and float are the same size.");
+  static_assert(sizeof(::uint32_t) == sizeof(float), "Code assumes ::uint32_t and float are the same size.");
   float tmp_value = this->_internal_value();
-  uint32_t raw_value;
+  ::uint32_t raw_value;
   memcpy(&raw_value, &tmp_value, sizeof(tmp_value));
   if (raw_value != 0) {
     total_size += 1 + 4;
@@ -605,14 +652,15 @@
 void FloatValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<FloatValue*>(&to_msg);
   auto& from = static_cast<const FloatValue&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.FloatValue)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
-  static_assert(sizeof(uint32_t) == sizeof(float), "Code assumes uint32_t and float are the same size.");
+  static_assert(sizeof(::uint32_t) == sizeof(float), "Code assumes ::uint32_t and float are the same size.");
   float tmp_value = from._internal_value();
-  uint32_t raw_value;
+  ::uint32_t raw_value;
   memcpy(&raw_value, &tmp_value, sizeof(tmp_value));
   if (raw_value != 0) {
     _this->_internal_set_value(from._internal_value());
@@ -638,11 +686,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata FloatValue::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[1]);
 }
-
 // ===================================================================
 
 class Int64Value::_Internal {
@@ -656,14 +704,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Int64Value)
 }
 Int64Value::Int64Value(const Int64Value& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  Int64Value* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.value_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  _this->_impl_.value_ = from._impl_.value_;
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Int64Value)
 }
 
@@ -672,7 +715,7 @@
   (void)arena;
   (void)is_message_owned;
   new (&_impl_) Impl_{
-      decltype(_impl_.value_){int64_t{0}}
+      decltype(_impl_.value_){::int64_t{0}}
     , /*decltype(_impl_._cached_size_)*/{}
   };
 }
@@ -696,27 +739,29 @@
 
 void Int64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int64Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  _impl_.value_ = int64_t{0};
+  _impl_.value_ = ::int64_t{0};
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* Int64Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // int64 value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -741,10 +786,11 @@
 #undef CHK_
 }
 
-uint8_t* Int64Value::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Int64Value::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int64Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // int64 value = 1;
@@ -761,11 +807,12 @@
   return target;
 }
 
-size_t Int64Value::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int64Value)
-  size_t total_size = 0;
+::size_t Int64Value::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int64Value)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -787,9 +834,10 @@
 void Int64Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Int64Value*>(&to_msg);
   auto& from = static_cast<const Int64Value&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int64Value)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (from._internal_value() != 0) {
@@ -816,11 +864,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Int64Value::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[2]);
 }
-
 // ===================================================================
 
 class UInt64Value::_Internal {
@@ -834,14 +882,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt64Value)
 }
 UInt64Value::UInt64Value(const UInt64Value& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  UInt64Value* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.value_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  _this->_impl_.value_ = from._impl_.value_;
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt64Value)
 }
 
@@ -850,7 +893,7 @@
   (void)arena;
   (void)is_message_owned;
   new (&_impl_) Impl_{
-      decltype(_impl_.value_){uint64_t{0u}}
+      decltype(_impl_.value_){::uint64_t{0u}}
     , /*decltype(_impl_._cached_size_)*/{}
   };
 }
@@ -874,27 +917,29 @@
 
 void UInt64Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt64Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
-  _impl_.value_ = uint64_t{0u};
+  _impl_.value_ = ::uint64_t{0u};
   _internal_metadata_.Clear<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>();
 }
 
 const char* UInt64Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // uint64 value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -919,10 +964,11 @@
 #undef CHK_
 }
 
-uint8_t* UInt64Value::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* UInt64Value::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt64Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // uint64 value = 1;
@@ -939,11 +985,12 @@
   return target;
 }
 
-size_t UInt64Value::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt64Value)
-  size_t total_size = 0;
+::size_t UInt64Value::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt64Value)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -965,9 +1012,10 @@
 void UInt64Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<UInt64Value*>(&to_msg);
   auto& from = static_cast<const UInt64Value&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt64Value)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (from._internal_value() != 0) {
@@ -994,11 +1042,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UInt64Value::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[3]);
 }
-
 // ===================================================================
 
 class Int32Value::_Internal {
@@ -1012,14 +1060,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.Int32Value)
 }
 Int32Value::Int32Value(const Int32Value& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  Int32Value* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.value_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  _this->_impl_.value_ = from._impl_.value_;
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.Int32Value)
 }
 
@@ -1052,7 +1095,7 @@
 
 void Int32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.Int32Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1061,18 +1104,20 @@
 }
 
 const char* Int32Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // int32 value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1097,10 +1142,11 @@
 #undef CHK_
 }
 
-uint8_t* Int32Value::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* Int32Value::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.Int32Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // int32 value = 1;
@@ -1117,11 +1163,12 @@
   return target;
 }
 
-size_t Int32Value::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int32Value)
-  size_t total_size = 0;
+::size_t Int32Value::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.Int32Value)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1143,9 +1190,10 @@
 void Int32Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<Int32Value*>(&to_msg);
   auto& from = static_cast<const Int32Value&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.Int32Value)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (from._internal_value() != 0) {
@@ -1172,11 +1220,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata Int32Value::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[4]);
 }
-
 // ===================================================================
 
 class UInt32Value::_Internal {
@@ -1190,14 +1238,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.UInt32Value)
 }
 UInt32Value::UInt32Value(const UInt32Value& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  UInt32Value* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.value_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  _this->_impl_.value_ = from._impl_.value_;
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.UInt32Value)
 }
 
@@ -1230,7 +1273,7 @@
 
 void UInt32Value::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.UInt32Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1239,18 +1282,20 @@
 }
 
 const char* UInt32Value::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // uint32 value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint32(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1275,10 +1320,11 @@
 #undef CHK_
 }
 
-uint8_t* UInt32Value::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* UInt32Value::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.UInt32Value)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // uint32 value = 1;
@@ -1295,11 +1341,12 @@
   return target;
 }
 
-size_t UInt32Value::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt32Value)
-  size_t total_size = 0;
+::size_t UInt32Value::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.UInt32Value)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1321,9 +1368,10 @@
 void UInt32Value::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<UInt32Value*>(&to_msg);
   auto& from = static_cast<const UInt32Value&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.UInt32Value)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (from._internal_value() != 0) {
@@ -1350,11 +1398,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata UInt32Value::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[5]);
 }
-
 // ===================================================================
 
 class BoolValue::_Internal {
@@ -1368,14 +1416,9 @@
   // @@protoc_insertion_point(arena_constructor:google.protobuf.BoolValue)
 }
 BoolValue::BoolValue(const BoolValue& from)
-  : ::PROTOBUF_NAMESPACE_ID::Message() {
-  BoolValue* const _this = this; (void)_this;
-  new (&_impl_) Impl_{
-      decltype(_impl_.value_){}
-    , /*decltype(_impl_._cached_size_)*/{}};
-
-  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(from._internal_metadata_);
-  _this->_impl_.value_ = from._impl_.value_;
+  : ::PROTOBUF_NAMESPACE_ID::Message(), _impl_(from._impl_) {
+  _internal_metadata_.MergeFrom<::PROTOBUF_NAMESPACE_ID::UnknownFieldSet>(
+      from._internal_metadata_);
   // @@protoc_insertion_point(copy_constructor:google.protobuf.BoolValue)
 }
 
@@ -1408,7 +1451,7 @@
 
 void BoolValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BoolValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1417,18 +1460,20 @@
 }
 
 const char* BoolValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // bool value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 8)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 8)) {
           _impl_.value_ = ::PROTOBUF_NAMESPACE_ID::internal::ReadVarint64(&ptr);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1453,10 +1498,11 @@
 #undef CHK_
 }
 
-uint8_t* BoolValue::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* BoolValue::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BoolValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // bool value = 1;
@@ -1473,11 +1519,12 @@
   return target;
 }
 
-size_t BoolValue::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BoolValue)
-  size_t total_size = 0;
+::size_t BoolValue::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BoolValue)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1499,9 +1546,10 @@
 void BoolValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<BoolValue*>(&to_msg);
   auto& from = static_cast<const BoolValue&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BoolValue)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (from._internal_value() != 0) {
@@ -1528,11 +1576,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata BoolValue::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[6]);
 }
-
 // ===================================================================
 
 class StringValue::_Internal {
@@ -1598,7 +1646,7 @@
 
 void StringValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.StringValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1607,20 +1655,22 @@
 }
 
 const char* StringValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // string value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
           CHK_(::_pbi::VerifyUTF8(str, "google.protobuf.StringValue.value"));
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1645,10 +1695,11 @@
 #undef CHK_
 }
 
-uint8_t* StringValue::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* StringValue::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.StringValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // string value = 1;
@@ -1669,11 +1720,12 @@
   return target;
 }
 
-size_t StringValue::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.StringValue)
-  size_t total_size = 0;
+::size_t StringValue::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.StringValue)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1697,9 +1749,10 @@
 void StringValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<StringValue*>(&to_msg);
   auto& from = static_cast<const StringValue&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.StringValue)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (!from._internal_value().empty()) {
@@ -1731,11 +1784,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata StringValue::GetMetadata() const {
+
   return ::_pbi::AssignDescriptors(
       &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_getter, &descriptor_table_google_2fprotobuf_2fwrappers_2eproto_once,
       file_level_metadata_google_2fprotobuf_2fwrappers_2eproto[7]);
 }
-
 // ===================================================================
 
 class BytesValue::_Internal {
@@ -1801,7 +1854,7 @@
 
 void BytesValue::Clear() {
 // @@protoc_insertion_point(message_clear_start:google.protobuf.BytesValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1810,19 +1863,21 @@
 }
 
 const char* BytesValue::_InternalParse(const char* ptr, ::_pbi::ParseContext* ctx) {
+
 #define CHK_(x) if (PROTOBUF_PREDICT_FALSE(!(x))) goto failure
   while (!ctx->Done(&ptr)) {
-    uint32_t tag;
+    ::uint32_t tag;
     ptr = ::_pbi::ReadTag(ptr, &tag);
     switch (tag >> 3) {
       // bytes value = 1;
       case 1:
-        if (PROTOBUF_PREDICT_TRUE(static_cast<uint8_t>(tag) == 10)) {
+        if (PROTOBUF_PREDICT_TRUE(static_cast<::uint8_t>(tag) == 10)) {
           auto str = _internal_mutable_value();
           ptr = ::_pbi::InlineGreedyStringParser(str, ptr, ctx);
           CHK_(ptr);
-        } else
+        } else {
           goto handle_unusual;
+        }
         continue;
       default:
         goto handle_unusual;
@@ -1847,10 +1902,11 @@
 #undef CHK_
 }
 
-uint8_t* BytesValue::_InternalSerialize(
-    uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+::uint8_t* BytesValue::_InternalSerialize(
+    ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const {
+
   // @@protoc_insertion_point(serialize_to_array_start:google.protobuf.BytesValue)
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   // bytes value = 1;
@@ -1867,11 +1923,12 @@
   return target;
 }
 
-size_t BytesValue::ByteSizeLong() const {
-// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BytesValue)
-  size_t total_size = 0;
+::size_t BytesValue::ByteSizeLong() const {
 
-  uint32_t cached_has_bits = 0;
+// @@protoc_insertion_point(message_byte_size_start:google.protobuf.BytesValue)
+  ::size_t total_size = 0;
+
+  ::uint32_t cached_has_bits = 0;
   // Prevent compiler warnings about cached_has_bits being unused
   (void) cached_has_bits;
 
@@ -1895,9 +1952,10 @@
 void BytesValue::MergeImpl(::PROTOBUF_NAMESPACE_ID::Message& to_msg, const ::PROTOBUF_NAMESPACE_ID::Message& from_msg) {
   auto* const _this = static_cast<BytesValue*>(&to_msg);
   auto& from = static_cast<const BytesValue&>(from_msg);
+
   // @@protoc_insertion_point(class_specific_merge_from_start:google.protobuf.BytesValue)
   GOOGLE_DCHECK_NE(&from, _this);
-  uint32_t cached_has_bits = 0;
+  ::uint32_t cached_has_bits = 0;
   (void) cached_has_bits;
 
   if (!from._internal_value().empty()) {
@@ -1929,11 +1987,11 @@
 }
 
 ::PROTOBUF_NAMESPACE_ID::Metadata BytesValue::GetMetadata() const {
+
   return ::_pbi::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
@@ -1974,6 +2032,5 @@
   return Arena::CreateMessageInternal< ::PROTOBUF_NAMESPACE_ID::BytesValue >(arena);
 }
 PROTOBUF_NAMESPACE_CLOSE
-
 // @@protoc_insertion_point(global_scope)
-#include <google/protobuf/port_undef.inc>
+#include "google/protobuf/port_undef.inc"
diff --git a/src/google/protobuf/wrappers.pb.h b/src/google/protobuf/wrappers.pb.h
index f8b51c0..4be9b0b 100644
--- a/src/google/protobuf/wrappers.pb.h
+++ b/src/google/protobuf/wrappers.pb.h
@@ -1,38 +1,43 @@
 // Generated by the protocol buffer compiler.  DO NOT EDIT!
 // source: google/protobuf/wrappers.proto
 
-#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto
-#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto
+#ifndef GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto_2epb_2eh
+#define GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto_2epb_2eh
 
 #include <limits>
 #include <string>
+#include <type_traits>
 
-#include <google/protobuf/port_def.inc>
+#include "google/protobuf/port_def.inc"
 #if PROTOBUF_VERSION < 3021000
-#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 3021010 < 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.
-#endif
+#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  // PROTOBUF_VERSION
 
-#include <google/protobuf/port_undef.inc>
-#include <google/protobuf/io/coded_stream.h>
-#include <google/protobuf/arena.h>
-#include <google/protobuf/arenastring.h>
-#include <google/protobuf/generated_message_util.h>
-#include <google/protobuf/metadata_lite.h>
-#include <google/protobuf/generated_message_reflection.h>
-#include <google/protobuf/message.h>
-#include <google/protobuf/repeated_field.h>  // IWYU pragma: export
-#include <google/protobuf/extension_set.h>  // IWYU pragma: export
-#include <google/protobuf/unknown_field_set.h>
+#if 3021010 < 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."
+#endif  // PROTOBUF_MIN_PROTOC_VERSION
+#include "google/protobuf/port_undef.inc"
+#include "google/protobuf/io/coded_stream.h"
+#include "google/protobuf/arena.h"
+#include "google/protobuf/arenastring.h"
+#include "google/protobuf/generated_message_util.h"
+#include "google/protobuf/metadata_lite.h"
+#include "google/protobuf/generated_message_reflection.h"
+#include "google/protobuf/message.h"
+#include "google/protobuf/repeated_field.h"  // IWYU pragma: export
+#include "google/protobuf/extension_set.h"  // IWYU pragma: export
+#include "google/protobuf/unknown_field_set.h"
 // @@protoc_insertion_point(includes)
-#include <google/protobuf/port_def.inc>
+
+// Must be included last.
+#include "google/protobuf/port_def.inc"
+
 #define PROTOBUF_INTERNAL_EXPORT_google_2fprotobuf_2fwrappers_2eproto PROTOBUF_EXPORT
+
 PROTOBUF_NAMESPACE_OPEN
 namespace internal {
 class AnyMetadata;
@@ -41,9 +46,10 @@
 
 // Internal implementation detail -- do not use these members.
 struct PROTOBUF_EXPORT TableStruct_google_2fprotobuf_2fwrappers_2eproto {
-  static const uint32_t offsets[];
+  static const ::uint32_t offsets[];
 };
-PROTOBUF_EXPORT extern 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;
 struct BoolValueDefaultTypeInternal;
@@ -72,22 +78,33 @@
 class UInt64Value;
 struct UInt64ValueDefaultTypeInternal;
 PROTOBUF_EXPORT extern UInt64ValueDefaultTypeInternal _UInt64Value_default_instance_;
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::BoolValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::BoolValue>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::BytesValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::BytesValue>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DoubleValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DoubleValue>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FloatValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FloatValue>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Int32Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Int32Value>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Int64Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Int64Value>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::StringValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::StringValue>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UInt32Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UInt32Value>(Arena*);
+template <>
+PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UInt64Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UInt64Value>(Arena*);
 PROTOBUF_NAMESPACE_CLOSE
-PROTOBUF_NAMESPACE_OPEN
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::BoolValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::BoolValue>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::BytesValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::BytesValue>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::DoubleValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::DoubleValue>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::FloatValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::FloatValue>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Int32Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Int32Value>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::Int64Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::Int64Value>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::StringValue* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::StringValue>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UInt32Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UInt32Value>(Arena*);
-template<> PROTOBUF_EXPORT ::PROTOBUF_NAMESPACE_ID::UInt64Value* Arena::CreateMaybeMessage<::PROTOBUF_NAMESPACE_ID::UInt64Value>(Arena*);
-PROTOBUF_NAMESPACE_CLOSE
+
 PROTOBUF_NAMESPACE_OPEN
 
 // ===================================================================
 
+
+// -------------------------------------------------------------------
+
 class PROTOBUF_EXPORT DoubleValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.DoubleValue) */ {
  public:
@@ -177,10 +194,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -191,7 +208,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.DoubleValue";
   }
   protected:
@@ -233,8 +250,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT FloatValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.FloatValue) */ {
@@ -325,10 +341,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -339,7 +355,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.FloatValue";
   }
   protected:
@@ -381,8 +397,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Int64Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int64Value) */ {
@@ -473,10 +488,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -487,7 +502,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Int64Value";
   }
   protected:
@@ -509,11 +524,11 @@
   };
   // int64 value = 1;
   void clear_value();
-  int64_t value() const;
-  void set_value(int64_t value);
+  ::int64_t value() const;
+  void set_value(::int64_t value);
   private:
-  int64_t _internal_value() const;
-  void _internal_set_value(int64_t value);
+  ::int64_t _internal_value() const;
+  void _internal_set_value(::int64_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.Int64Value)
@@ -524,13 +539,12 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   struct Impl_ {
-    int64_t value_;
+    ::int64_t value_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT UInt64Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt64Value) */ {
@@ -621,10 +635,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -635,7 +649,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.UInt64Value";
   }
   protected:
@@ -657,11 +671,11 @@
   };
   // uint64 value = 1;
   void clear_value();
-  uint64_t value() const;
-  void set_value(uint64_t value);
+  ::uint64_t value() const;
+  void set_value(::uint64_t value);
   private:
-  uint64_t _internal_value() const;
-  void _internal_set_value(uint64_t value);
+  ::uint64_t _internal_value() const;
+  void _internal_set_value(::uint64_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.UInt64Value)
@@ -672,13 +686,12 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   struct Impl_ {
-    uint64_t value_;
+    ::uint64_t value_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT Int32Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.Int32Value) */ {
@@ -769,10 +782,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -783,7 +796,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.Int32Value";
   }
   protected:
@@ -805,11 +818,11 @@
   };
   // int32 value = 1;
   void clear_value();
-  int32_t value() const;
-  void set_value(int32_t value);
+  ::int32_t value() const;
+  void set_value(::int32_t value);
   private:
-  int32_t _internal_value() const;
-  void _internal_set_value(int32_t value);
+  ::int32_t _internal_value() const;
+  void _internal_set_value(::int32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.Int32Value)
@@ -820,13 +833,12 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   struct Impl_ {
-    int32_t value_;
+    ::int32_t value_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT UInt32Value final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.UInt32Value) */ {
@@ -917,10 +929,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -931,7 +943,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.UInt32Value";
   }
   protected:
@@ -953,11 +965,11 @@
   };
   // uint32 value = 1;
   void clear_value();
-  uint32_t value() const;
-  void set_value(uint32_t value);
+  ::uint32_t value() const;
+  void set_value(::uint32_t value);
   private:
-  uint32_t _internal_value() const;
-  void _internal_set_value(uint32_t value);
+  ::uint32_t _internal_value() const;
+  void _internal_set_value(::uint32_t value);
   public:
 
   // @@protoc_insertion_point(class_scope:google.protobuf.UInt32Value)
@@ -968,13 +980,12 @@
   typedef void InternalArenaConstructable_;
   typedef void DestructorSkippable_;
   struct Impl_ {
-    uint32_t value_;
+    ::uint32_t value_;
     mutable ::PROTOBUF_NAMESPACE_ID::internal::CachedSize _cached_size_;
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT BoolValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BoolValue) */ {
@@ -1065,10 +1076,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1079,7 +1090,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.BoolValue";
   }
   protected:
@@ -1121,8 +1132,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT StringValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.StringValue) */ {
@@ -1213,10 +1223,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1227,7 +1237,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.StringValue";
   }
   protected:
@@ -1274,8 +1284,7 @@
   };
   union { Impl_ _impl_; };
   friend struct ::TableStruct_google_2fprotobuf_2fwrappers_2eproto;
-};
-// -------------------------------------------------------------------
+};// -------------------------------------------------------------------
 
 class PROTOBUF_EXPORT BytesValue final :
     public ::PROTOBUF_NAMESPACE_ID::Message /* @@protoc_insertion_point(class_definition:google.protobuf.BytesValue) */ {
@@ -1366,10 +1375,10 @@
   PROTOBUF_ATTRIBUTE_REINITIALIZES void Clear() final;
   bool IsInitialized() const final;
 
-  size_t ByteSizeLong() const final;
+  ::size_t ByteSizeLong() const final;
   const char* _InternalParse(const char* ptr, ::PROTOBUF_NAMESPACE_ID::internal::ParseContext* ctx) final;
-  uint8_t* _InternalSerialize(
-      uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
+  ::uint8_t* _InternalSerialize(
+      ::uint8_t* target, ::PROTOBUF_NAMESPACE_ID::io::EpsCopyOutputStream* stream) const final;
   int GetCachedSize() const final { return _impl_._cached_size_.Get(); }
 
   private:
@@ -1380,7 +1389,7 @@
 
   private:
   friend class ::PROTOBUF_NAMESPACE_ID::internal::AnyMetadata;
-  static ::PROTOBUF_NAMESPACE_ID::StringPiece FullMessageName() {
+  static ::absl::string_view FullMessageName() {
     return "google.protobuf.BytesValue";
   }
   protected:
@@ -1431,12 +1440,17 @@
 // ===================================================================
 
 
+
+
 // ===================================================================
 
+
 #ifdef __GNUC__
-  #pragma GCC diagnostic push
-  #pragma GCC diagnostic ignored "-Wstrict-aliasing"
+#pragma GCC diagnostic push
+#pragma GCC diagnostic ignored "-Wstrict-aliasing"
 #endif  // __GNUC__
+// -------------------------------------------------------------------
+
 // DoubleValue
 
 // double value = 1;
@@ -1451,7 +1465,7 @@
   return _internal_value();
 }
 inline void DoubleValue::_internal_set_value(double value) {
-  
+
   _impl_.value_ = value;
 }
 inline void DoubleValue::set_value(double value) {
@@ -1475,7 +1489,7 @@
   return _internal_value();
 }
 inline void FloatValue::_internal_set_value(float value) {
-  
+
   _impl_.value_ = value;
 }
 inline void FloatValue::set_value(float value) {
@@ -1489,20 +1503,20 @@
 
 // int64 value = 1;
 inline void Int64Value::clear_value() {
-  _impl_.value_ = int64_t{0};
+  _impl_.value_ = ::int64_t{0};
 }
-inline int64_t Int64Value::_internal_value() const {
+inline ::int64_t Int64Value::_internal_value() const {
   return _impl_.value_;
 }
-inline int64_t Int64Value::value() const {
+inline ::int64_t Int64Value::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Int64Value.value)
   return _internal_value();
 }
-inline void Int64Value::_internal_set_value(int64_t value) {
-  
+inline void Int64Value::_internal_set_value(::int64_t value) {
+
   _impl_.value_ = value;
 }
-inline void Int64Value::set_value(int64_t value) {
+inline void Int64Value::set_value(::int64_t value) {
   _internal_set_value(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Int64Value.value)
 }
@@ -1513,20 +1527,20 @@
 
 // uint64 value = 1;
 inline void UInt64Value::clear_value() {
-  _impl_.value_ = uint64_t{0u};
+  _impl_.value_ = ::uint64_t{0u};
 }
-inline uint64_t UInt64Value::_internal_value() const {
+inline ::uint64_t UInt64Value::_internal_value() const {
   return _impl_.value_;
 }
-inline uint64_t UInt64Value::value() const {
+inline ::uint64_t UInt64Value::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UInt64Value.value)
   return _internal_value();
 }
-inline void UInt64Value::_internal_set_value(uint64_t value) {
-  
+inline void UInt64Value::_internal_set_value(::uint64_t value) {
+
   _impl_.value_ = value;
 }
-inline void UInt64Value::set_value(uint64_t value) {
+inline void UInt64Value::set_value(::uint64_t value) {
   _internal_set_value(value);
   // @@protoc_insertion_point(field_set:google.protobuf.UInt64Value.value)
 }
@@ -1539,18 +1553,18 @@
 inline void Int32Value::clear_value() {
   _impl_.value_ = 0;
 }
-inline int32_t Int32Value::_internal_value() const {
+inline ::int32_t Int32Value::_internal_value() const {
   return _impl_.value_;
 }
-inline int32_t Int32Value::value() const {
+inline ::int32_t Int32Value::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.Int32Value.value)
   return _internal_value();
 }
-inline void Int32Value::_internal_set_value(int32_t value) {
-  
+inline void Int32Value::_internal_set_value(::int32_t value) {
+
   _impl_.value_ = value;
 }
-inline void Int32Value::set_value(int32_t value) {
+inline void Int32Value::set_value(::int32_t value) {
   _internal_set_value(value);
   // @@protoc_insertion_point(field_set:google.protobuf.Int32Value.value)
 }
@@ -1563,18 +1577,18 @@
 inline void UInt32Value::clear_value() {
   _impl_.value_ = 0u;
 }
-inline uint32_t UInt32Value::_internal_value() const {
+inline ::uint32_t UInt32Value::_internal_value() const {
   return _impl_.value_;
 }
-inline uint32_t UInt32Value::value() const {
+inline ::uint32_t UInt32Value::value() const {
   // @@protoc_insertion_point(field_get:google.protobuf.UInt32Value.value)
   return _internal_value();
 }
-inline void UInt32Value::_internal_set_value(uint32_t value) {
-  
+inline void UInt32Value::_internal_set_value(::uint32_t value) {
+
   _impl_.value_ = value;
 }
-inline void UInt32Value::set_value(uint32_t value) {
+inline void UInt32Value::set_value(::uint32_t value) {
   _internal_set_value(value);
   // @@protoc_insertion_point(field_set:google.protobuf.UInt32Value.value)
 }
@@ -1595,7 +1609,7 @@
   return _internal_value();
 }
 inline void BoolValue::_internal_set_value(bool value) {
-  
+
   _impl_.value_ = value;
 }
 inline void BoolValue::set_value(bool value) {
@@ -1631,11 +1645,11 @@
   return _impl_.value_.Get();
 }
 inline void StringValue::_internal_set_value(const std::string& value) {
-  
+
   _impl_.value_.Set(value, GetArenaForAllocation());
 }
 inline std::string* StringValue::_internal_mutable_value() {
-  
+
   return _impl_.value_.Mutable(GetArenaForAllocation());
 }
 inline std::string* StringValue::release_value() {
@@ -1643,11 +1657,6 @@
   return _impl_.value_.Release();
 }
 inline void StringValue::set_allocated_value(std::string* value) {
-  if (value != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.value_.SetAllocated(value, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.value_.IsDefault()) {
@@ -1685,11 +1694,11 @@
   return _impl_.value_.Get();
 }
 inline void BytesValue::_internal_set_value(const std::string& value) {
-  
+
   _impl_.value_.Set(value, GetArenaForAllocation());
 }
 inline std::string* BytesValue::_internal_mutable_value() {
-  
+
   return _impl_.value_.Mutable(GetArenaForAllocation());
 }
 inline std::string* BytesValue::release_value() {
@@ -1697,11 +1706,6 @@
   return _impl_.value_.Release();
 }
 inline void BytesValue::set_allocated_value(std::string* value) {
-  if (value != nullptr) {
-    
-  } else {
-    
-  }
   _impl_.value_.SetAllocated(value, GetArenaForAllocation());
 #ifdef PROTOBUF_FORCE_COPY_DEFAULT_STRING
   if (_impl_.value_.IsDefault()) {
@@ -1712,30 +1716,15 @@
 }
 
 #ifdef __GNUC__
-  #pragma GCC diagnostic pop
+#pragma GCC diagnostic pop
 #endif  // __GNUC__
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
-// -------------------------------------------------------------------
-
 
 // @@protoc_insertion_point(namespace_scope)
-
 PROTOBUF_NAMESPACE_CLOSE
 
+
 // @@protoc_insertion_point(global_scope)
 
-#include <google/protobuf/port_undef.inc>
-#endif  // GOOGLE_PROTOBUF_INCLUDED_GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto
+#include "google/protobuf/port_undef.inc"
+
+#endif  // GOOGLE_PROTOBUF_INCLUDED_google_2fprotobuf_2fwrappers_2eproto_2epb_2eh
diff --git a/src/google/protobuf/wrappers.proto b/src/google/protobuf/wrappers.proto
index d49dd53..1959fa5 100644
--- a/src/google/protobuf/wrappers.proto
+++ b/src/google/protobuf/wrappers.proto
@@ -27,7 +27,7 @@
 // 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.
-
+//
 // Wrappers for primitive (non-message) types. These types are useful
 // for embedding primitives in the `google.protobuf.Any` type and for places
 // where we need to distinguish between the absence of a primitive
@@ -42,13 +42,13 @@
 
 package google.protobuf;
 
-option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 option cc_enable_arenas = true;
 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;
 option objc_class_prefix = "GPB";
+option csharp_namespace = "Google.Protobuf.WellKnownTypes";
 
 // Wrapper message for `double`.
 //
diff --git a/tests.sh b/tests.sh
deleted file mode 100755
index 180b870..0000000
--- a/tests.sh
+++ /dev/null
@@ -1,611 +0,0 @@
-#!/bin/bash
-#
-# Build and run tests for the protobuf project. We use this script to run
-# tests on kokoro (Ubuntu and MacOS). It can run locally as well but you
-# need to make sure the required compilers/tools are available.
-
-internal_build_cpp() {
-  if [ -f src/protoc ]; then
-    # Already built.
-    return
-  fi
-
-  # Initialize any submodules.
-  git submodule update --init --recursive
-
-  ./autogen.sh
-  ./configure CXXFLAGS="-fPIC -std=c++11"  # -fPIC is needed for python cpp test.
-                                           # See python/setup.py for more details
-  make -j$(nproc)
-}
-
-build_cpp() {
-  internal_build_cpp
-  make check -j$(nproc) || (cat src/test-suite.log; false)
-  cd conformance && make test_cpp && cd ..
-}
-
-build_cpp_tcmalloc() {
-  internal_build_cpp
-  ./configure LIBS=-ltcmalloc && make clean && make \
-      PTHREAD_CFLAGS='-pthread -DGOOGLE_PROTOBUF_HEAP_CHECK_DRACONIAN' \
-      check
-  cd src
-  PPROF_PATH=/usr/bin/google-pprof HEAPCHECK=strict ./protobuf-test
-}
-
-build_cpp_distcheck() {
-  grep -q -- "-Og" src/Makefile.am &&
-    echo "The -Og flag is incompatible with Clang versions older than 4.0." &&
-    exit 1
-
-  # Initialize any submodules.
-  git submodule update --init --recursive
-  ./autogen.sh
-  ./configure
-  make dist
-
-  # List all files that should be included in the distribution package.
-  git ls-files | grep "^\(java\|python\|objectivec\|csharp\|ruby\|php\|cmake\|examples\|src/google/protobuf/.*\.proto\)" |\
-    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 "python/protobuf_distutils" | grep -v "csharp/compatibility_tests" > dist.lst
-  # Unzip the dist tar file.
-  DIST=`ls *.tar.gz`
-  tar -xf $DIST
-  cd ${DIST//.tar.gz}
-  # Check if every file exists in the dist tar file.
-  FILES_MISSING=""
-  for FILE in $(<../dist.lst); do
-    [ -f "$FILE" ] || {
-      echo "$FILE is not found!"
-      FILES_MISSING="$FILE $FILES_MISSING"
-    }
-  done
-  cd ..
-  if [ ! -z "$FILES_MISSING" ]; then
-    echo "Missing files in EXTRA_DIST: $FILES_MISSING"
-    exit 1
-  fi
-
-  # Do the regular dist-check for C++.
-  make distcheck -j$(nproc)
-}
-
-build_dist_install() {
-  # Create a symlink pointing to python2 and put it at the beginning of $PATH.
-  # This is necessary because the googletest build system involves a Python
-  # script that is not compatible with Python 3. More recent googletest
-  # versions have fixed this, but they have also removed the autotools build
-  # system support that we rely on. This is a temporary workaround to keep the
-  # googletest build working when the default python binary is Python 3.
-  mkdir tmp || true
-  pushd tmp
-  ln -s /usr/bin/python2 ./python
-  popd
-  PATH=$PWD/tmp:$PATH
-
-  # Initialize any submodules.
-  git submodule update --init --recursive
-  ./autogen.sh
-  ./configure
-  make dist
-
-  # Unzip the dist tar file and install it.
-  DIST=`ls *.tar.gz`
-  tar -xf $DIST
-  pushd ${DIST//.tar.gz}
-  ./configure && make check -j4 && make install
-
-  export LD_LIBRARY_PATH=/usr/local/lib
-
-  # Try to install Java
-  pushd java
-  use_java jdk11
-  $MVN install
-  popd
-
-  # Try to install Python
-  python3 -m venv venv
-  source venv/bin/activate
-  pushd python
-  python3 setup.py clean build sdist
-  pip3 install dist/protobuf-*.tar.gz
-  popd
-  deactivate
-  rm -rf python/venv
-}
-
-build_csharp() {
-  # Required for conformance tests and to regenerate protos.
-  internal_build_cpp
-  NUGET=/usr/local/bin/nuget.exe
-
-  # Disable some unwanted dotnet options
-  export DOTNET_SKIP_FIRST_TIME_EXPERIENCE=true
-  export DOTNET_CLI_TELEMETRY_OPTOUT=true
-
-  # TODO(jtattermusch): is this still needed with "first time experience"
-  # disabled?
-  # Perform "dotnet new" once to get the setup preprocessing out of the
-  # way. That spews a lot of output (including backspaces) into logs
-  # otherwise, and can cause problems. It doesn't matter if this step
-  # is performed multiple times; it's cheap after the first time anyway.
-  # (It also doesn't matter if it's unnecessary, which it will be on some
-  # systems. It's necessary on Jenkins in order to avoid unprintable
-  # characters appearing in the JUnit output.)
-  mkdir dotnettmp
-  (cd dotnettmp; dotnet new > /dev/null)
-  rm -rf dotnettmp
-
-  # Check that the protos haven't broken C# codegen.
-  # TODO(jonskeet): Fail if regenerating creates any changes.
-  csharp/generate_protos.sh
-
-  csharp/buildall.sh
-  cd conformance && make test_csharp && cd ..
-
-  # Run csharp compatibility test between 3.0.0 and the current version.
-  csharp/compatibility_tests/v3.0.0/test.sh 3.0.0
-  
-  # Regression test for https://github.com/protocolbuffers/protobuf/issues/9526
-  # - all line endings in .proto and .cs (and .csproj) files should be LF.
-  if git ls-files --eol csharp | grep -E '\.cs|\.proto' | grep -v w/lf
-  then
-    echo "The files listed above have mixed or CRLF line endings; please change to LF."
-    exit 1
-  fi
-}
-
-build_golang() {
-  # Go build needs `protoc`.
-  internal_build_cpp
-  # Add protoc to the path so that the examples build finds it.
-  export PATH="`pwd`/src:$PATH"
-
-  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"
-  (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 ..
-}
-
-use_java() {
-  version=$1
-  case "$version" in
-    jdk17)
-      export PATH=/usr/lib/jvm/java-17-openjdk-amd64/bin:$PATH
-      export JAVA_HOME=/usr/lib/jvm/java-17-openjdk-amd64
-      ;;
-    jdk11)
-      export PATH=/usr/lib/jvm/java-11-openjdk-amd64/bin:$PATH
-      export JAVA_HOME=/usr/lib/jvm/java-11-openjdk-amd64
-      ;;
-    jdk8)
-      export PATH=/usr/lib/jvm/java-8-openjdk-amd64/bin:$PATH
-      export JAVA_HOME=/usr/lib/jvm/java-8-openjdk-amd64
-      ;;
-    jdk7)
-      export PATH=/usr/lib/jvm/java-7-openjdk-amd64/bin:$PATH
-      export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
-      ;;
-    oracle7)
-      export PATH=/usr/lib/jvm/java-7-oracle/bin:$PATH
-      export JAVA_HOME=/usr/lib/jvm/java-7-openjdk-amd64
-      ;;
-  esac
-
-  MAVEN_LOCAL_REPOSITORY=/var/maven_local_repository
-  MVN="$MVN -e --quiet -Dhttps.protocols=TLSv1.2 -Dmaven.repo.local=$MAVEN_LOCAL_REPOSITORY"
-
-  which java
-  java -version
-  $MVN -version
-}
-
-# --batch-mode suppresses download progress output that spams the logs.
-MVN="mvn --batch-mode"
-
-internal_build_java() {
-  version=$1
-  dir=java_$version
-  # Java build needs `protoc`.
-  internal_build_cpp
-  cp -r java $dir
-  cd $dir && $MVN clean
-  # Skip tests here - callers will decide what tests they want to run
-  $MVN install -Dmaven.test.skip=true
-}
-
-build_java() {
-  version=$1
-  internal_build_java $version
-  # Skip the Kotlin tests on Oracle 7
-  if [ "$version" == "oracle7" ]; then
-    $MVN test -pl bom,lite,core,util
-  else
-    $MVN test
-  fi
-  cd ../..
-}
-
-# The conformance tests are hard-coded to work with the $ROOT/java directory.
-# So this can't run in parallel with two different sets of tests.
-build_java_with_conformance_tests() {
-  # Java build needs `protoc`.
-  internal_build_cpp
-  # This local installation avoids the problem caused by a new version not yet in Maven Central
-  cd java/bom && $MVN install
-  cd ../..
-  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 ..
-}
-
-build_java_jdk7() {
-  use_java jdk7
-  build_java_with_conformance_tests
-}
-
-build_java_oracle7() {
-  use_java oracle7
-  build_java oracle7
-}
-
-build_java_jdk8() {
-  use_java jdk8
-  build_java_with_conformance_tests
-}
-
-build_java_jdk11() {
-  use_java jdk11
-  build_java
-}
-
-build_java_jdk17() {
-  use_java jdk17
-  build_java
-}
-
-build_java_linkage_monitor() {
-  # Linkage Monitor checks compatibility with other Google libraries
-  # https://github.com/GoogleCloudPlatform/cloud-opensource-java/tree/master/linkage-monitor
-
-  use_java jdk11
-  internal_build_cpp
-
-  # Linkage Monitor uses $HOME/.m2 local repository
-  MVN="mvn -e -B -Dhttps.protocols=TLSv1.2"
-  cd java
-  # Installs the snapshot version locally
-  $MVN install -Dmaven.test.skip=true
-
-  # Linkage Monitor uses the snapshot versions installed in $HOME/.m2 to verify compatibility
-  JAR=linkage-monitor-latest-all-deps.jar
-  curl -v -O "https://storage.googleapis.com/cloud-opensource-java-linkage-monitor/${JAR}"
-  # Fails if there's new linkage errors compared with baseline
-  java -jar $JAR com.google.cloud:libraries-bom
-}
-
-build_objectivec_ios() {
-  # Reused the build script that takes care of configuring and ensuring things
-  # are up to date.  The OS X test runs the objc conformance test, so skip it
-  # here.
-  objectivec/DevTools/full_mac_build.sh \
-      --core-only --skip-xcode-osx --skip-xcode-tvos --skip-objc-conformance "$@"
-}
-
-build_objectivec_ios_debug() {
-  build_objectivec_ios --skip-xcode-release
-}
-
-build_objectivec_ios_release() {
-  build_objectivec_ios --skip-xcode-debug
-}
-
-build_objectivec_osx() {
-  # Reused the build script that takes care of configuring and ensuring things
-  # are up to date.
-  objectivec/DevTools/full_mac_build.sh \
-      --core-only --skip-xcode-ios --skip-xcode-tvos
-}
-
-build_objectivec_tvos() {
-  # Reused the build script that takes care of configuring and ensuring things
-  # are up to date.  The OS X test runs the objc conformance test, so skip it
-  # here.
-  objectivec/DevTools/full_mac_build.sh \
-      --core-only --skip-xcode-ios --skip-xcode-osx --skip-objc-conformance "$@"
-}
-
-build_objectivec_tvos_debug() {
-  build_objectivec_tvos --skip-xcode-release
-}
-
-build_objectivec_tvos_release() {
-  build_objectivec_tvos --skip-xcode-debug
-}
-
-build_python() {
-  internal_build_cpp
-  cd python
-  tox --skip-missing-interpreters
-  cd ..
-}
-
-build_python_version() {
-  internal_build_cpp
-  cd python
-  envlist=$1
-  tox -e $envlist
-  cd ..
-}
-
-build_python37() {
-  build_python_version py37-python
-}
-
-build_python38() {
-  build_python_version py38-python
-}
-
-build_python39() {
-  build_python_version py39-python
-}
-
-build_python310() {
-  build_python_version py310-python
-}
-
-build_python_cpp() {
-  internal_build_cpp
-  export LD_LIBRARY_PATH=../src/.libs # for Linux
-  export DYLD_LIBRARY_PATH=../src/.libs # for OS X
-  cd python
-  tox --skip-missing-interpreters
-  cd ..
-}
-
-build_python_cpp_version() {
-  internal_build_cpp
-  export LD_LIBRARY_PATH=../src/.libs # for Linux
-  export DYLD_LIBRARY_PATH=../src/.libs # for OS X
-  cd python
-  envlist=$1
-  tox -e $envlist
-  cd ..
-}
-
-build_python37_cpp() {
-  build_python_cpp_version py37-cpp
-}
-
-build_python38_cpp() {
-  build_python_cpp_version py38-cpp
-}
-
-build_python39_cpp() {
-  build_python_cpp_version py39-cpp
-}
-
-build_python310_cpp() {
-  build_python_cpp_version py310-cpp
-}
-
-build_ruby23() {
-  internal_build_cpp  # For conformance tests.
-  cd ruby && bash travis-test.sh ruby-2.3.8 && cd ..
-}
-build_ruby24() {
-  internal_build_cpp  # For conformance tests.
-  cd ruby && bash travis-test.sh ruby-2.4 && cd ..
-}
-build_ruby25() {
-  internal_build_cpp  # For conformance tests.
-  cd ruby && bash travis-test.sh ruby-2.5.1 && cd ..
-}
-build_ruby26() {
-  internal_build_cpp  # For conformance tests.
-  cd ruby && bash travis-test.sh ruby-2.6.0 && cd ..
-}
-build_ruby27() {
-  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.2 && cd ..
-}
-build_ruby31() {
-  internal_build_cpp  # For conformance tests.
-  cd ruby && bash travis-test.sh ruby-3.1.0 && cd ..
-}
-
-build_jruby92() {
-  internal_build_cpp                # For conformance tests.
-  internal_build_java jdk8 && cd .. # For Maven protobuf jar with local changes
-  cd ruby && bash travis-test.sh jruby-9.2.20.1 && cd ..
-}
-
-build_jruby93() {
-  internal_build_cpp                # For conformance tests.
-  internal_build_java jdk8 && cd .. # For Maven protobuf jar with local changes
-  cd ruby && bash travis-test.sh jruby-9.3.4.0 && cd ..
-}
-
-use_php() {
-  VERSION=$1
-  export PATH=/usr/local/php-${VERSION}/bin:$PATH
-  internal_build_cpp
-}
-
-build_php() {
-  use_php $1
-  pushd php
-  rm -rf vendor
-  php -v
-  php -m
-  composer update
-  composer test
-  popd
-  (cd conformance && make test_php)
-}
-
-test_php_c() {
-  pushd php
-  rm -rf vendor
-  php -v
-  php -m
-  composer update
-  composer test_c
-  popd
-  (cd conformance && make test_php_c)
-}
-
-build_php_c() {
-  use_php $1
-  test_php_c
-}
-
-build_php7.0_mac() {
-  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 "php5-7.0*"`  # The folder name may change upon time
-  test ! -z "$PHP_FOLDER"
-  export PATH="$PHP_FOLDER/bin:$PATH"
-
-  # 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
-  chmod ug+x valgrind
-  sudo mv valgrind /usr/local/bin/valgrind
-
-  # Test
-  test_php_c
-}
-
-build_php7.3_mac() {
-  internal_build_cpp
-  # Install PHP
-  # 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 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
-  chmod ug+x valgrind
-  sudo mv valgrind /usr/local/bin/valgrind
-
-  # Test
-  test_php_c
-}
-
-build_php_compatibility() {
-  internal_build_cpp
-}
-
-build_php_multirequest() {
-  use_php 7.4
-  php/tests/multirequest.sh
-}
-
-build_php8.0_all() {
-  build_php 8.0
-  build_php 8.1
-  build_php_c 8.0
-  build_php_c 8.1
-}
-
-build_php_all_32() {
-  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
-  build_php_multirequest
-  build_php_compatibility
-}
-
-build_benchmark() {
-  use_php 7.2
-  cd kokoro/linux/benchmark && ./run.sh
-}
-
-# -------- main --------
-
-if [ "$#" -ne 1 ]; then
-  echo "
-Usage: $0 { cpp |
-            cpp_distcheck |
-            csharp |
-            java_jdk7 |
-            java_oracle7 |
-            java_jdk8 |
-            java_jdk11 |
-            java_jdk17 |
-            java_linkage_monitor |
-            objectivec_ios |
-            objectivec_ios_debug |
-            objectivec_ios_release |
-            objectivec_osx |
-            objectivec_tvos |
-            objectivec_tvos_debug |
-            objectivec_tvos_release |
-            python |
-            python_cpp |
-            python_compatibility |
-            ruby23 |
-            ruby24 |
-            ruby25 |
-            ruby26 |
-            ruby27 |
-            ruby30 |
-            ruby31 |
-            jruby92 |
-            jruby93 |
-            ruby_all |
-            php_all |
-            php_all_32 |
-            php7.0_mac |
-            php7.3_mac |
-            dist_install |
-            benchmark }
-"
-  exit 1
-fi
-
-set -e  # exit immediately on error
-set -x  # display all commands
-cd $(dirname $0)
-eval "build_$1"
diff --git a/third_party/abseil-cpp b/third_party/abseil-cpp
new file mode 160000
index 0000000..273292d
--- /dev/null
+++ b/third_party/abseil-cpp
@@ -0,0 +1 @@
+Subproject commit 273292d1cfc0a94a65082ee350509af1d113344d
diff --git a/third_party/benchmark b/third_party/benchmark
deleted file mode 160000
index 5b7683f..0000000
--- a/third_party/benchmark
+++ /dev/null
@@ -1 +0,0 @@
-Subproject commit 5b7683f49e1e9223cf9927b24f6fd3d6bd82e3f8
diff --git a/third_party/googletest b/third_party/googletest
index 5ec7f0c..4c9a3bb 160000
--- a/third_party/googletest
+++ b/third_party/googletest
@@ -1 +1 @@
-Subproject commit 5ec7f0c4a113e2f18ac2c6cc7df51ad6afc24081
+Subproject commit 4c9a3bb62bf3ba1f1010bf96f9c8ed767b363774
diff --git a/third_party/jsoncpp b/third_party/jsoncpp
new file mode 160000
index 0000000..9059f5c
--- /dev/null
+++ b/third_party/jsoncpp
@@ -0,0 +1 @@
+Subproject commit 9059f5cad030ba11d37818847443a53918c327b1
diff --git a/third_party/jsoncpp.BUILD b/third_party/jsoncpp.BUILD
new file mode 100644
index 0000000..b013e4f
--- /dev/null
+++ b/third_party/jsoncpp.BUILD
@@ -0,0 +1,37 @@
+licenses(["unencumbered"])  # Public Domain or MIT
+
+exports_files(["LICENSE"])
+
+cc_library(
+    name = "jsoncpp",
+    srcs = [
+        "src/lib_json/json_reader.cpp",
+        "src/lib_json/json_tool.h",
+        "src/lib_json/json_value.cpp",
+        "src/lib_json/json_writer.cpp",
+    ],
+    hdrs = [
+        "include/json/allocator.h",
+        "include/json/assertions.h",
+        "include/json/config.h",
+        "include/json/forwards.h",
+        "include/json/json.h",
+        "include/json/json_features.h",
+        "include/json/reader.h",
+        "include/json/value.h",
+        "include/json/version.h",
+        "include/json/writer.h",
+    ],
+    copts = [
+        "-DJSON_USE_EXCEPTION=0",
+        "-DJSON_HAS_INT64",
+    ],
+    includes = ["include"],
+    visibility = ["//visibility:public"],
+    deps = [":private"],
+)
+
+cc_library(
+    name = "private",
+    textual_hdrs = ["src/lib_json/json_valueiterator.inl"],
+)
diff --git a/third_party/utf8_range b/third_party/utf8_range
new file mode 160000
index 0000000..de0b4a8
--- /dev/null
+++ b/third_party/utf8_range
@@ -0,0 +1 @@
+Subproject commit de0b4a8ff9b5d4c98108bdfe723291a33c52c54f
diff --git a/third_party/utf8_range/BUILD.bazel b/third_party/utf8_range/BUILD.bazel
deleted file mode 100644
index 899a93a..0000000
--- a/third_party/utf8_range/BUILD.bazel
+++ /dev/null
@@ -1,35 +0,0 @@
-
-# Pulled from: https://github.com/cyb70289/utf8
-
-exports_files(["LICENSE"])
-
-filegroup(
-    name = "utf8_range_srcs",
-    srcs = [
-        "naive.c",
-        "range2-neon.c",
-        "range2-sse.c",
-        "utf8_range.h",
-    ],
-    visibility = [
-        "@com_google_protobuf//:__subpackages__",
-        "@upb//:__subpackages__",
-    ],
-)
-
-cc_library(
-    name = "utf8_range",
-    hdrs = ["utf8_range.h"],
-    srcs = [
-        "naive.c",
-        "range2-neon.c",
-        "range2-sse.c",
-    ],
-    visibility = ["//:__pkg__"],
-)
-
-filegroup(
-    name = "cmake_files",
-    srcs = glob(["*"]),
-    visibility = ["//cmake:__pkg__"],
-)
diff --git a/third_party/utf8_range/LICENSE b/third_party/utf8_range/LICENSE
deleted file mode 100644
index c1f087e..0000000
--- a/third_party/utf8_range/LICENSE
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2019 Yibo Cai
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-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 OR COPYRIGHT HOLDERS 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.
diff --git a/third_party/utf8_range/naive.c b/third_party/utf8_range/naive.c
deleted file mode 100644
index 9b7e5bb..0000000
--- a/third_party/utf8_range/naive.c
+++ /dev/null
@@ -1,92 +0,0 @@
-#include <stdio.h>
-
-/*
- * http://www.unicode.org/versions/Unicode6.0.0/ch03.pdf - page 94
- *
- * Table 3-7. Well-Formed UTF-8 Byte Sequences
- *
- * +--------------------+------------+-------------+------------+-------------+
- * | Code Points        | First Byte | Second Byte | Third Byte | Fourth Byte |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+0000..U+007F     | 00..7F     |             |            |             |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+0080..U+07FF     | C2..DF     | 80..BF      |            |             |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+0800..U+0FFF     | E0         | A0..BF      | 80..BF     |             |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+1000..U+CFFF     | E1..EC     | 80..BF      | 80..BF     |             |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+D000..U+D7FF     | ED         | 80..9F      | 80..BF     |             |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+E000..U+FFFF     | EE..EF     | 80..BF      | 80..BF     |             |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+10000..U+3FFFF   | F0         | 90..BF      | 80..BF     | 80..BF      |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+40000..U+FFFFF   | F1..F3     | 80..BF      | 80..BF     | 80..BF      |
- * +--------------------+------------+-------------+------------+-------------+
- * | U+100000..U+10FFFF | F4         | 80..8F      | 80..BF     | 80..BF      |
- * +--------------------+------------+-------------+------------+-------------+
- */
-
-/* Return 0 - success,  >0 - index(1 based) of first error char */
-int utf8_naive(const unsigned char *data, int len)
-{
-    int err_pos = 1;
-
-    while (len) {
-        int bytes;
-        const unsigned char byte1 = data[0];
-
-        /* 00..7F */
-        if (byte1 <= 0x7F) {
-            bytes = 1;
-        /* C2..DF, 80..BF */
-        } else if (len >= 2 && byte1 >= 0xC2 && byte1 <= 0xDF &&
-                (signed char)data[1] <= (signed char)0xBF) {
-            bytes = 2;
-        } else if (len >= 3) {
-            const unsigned char byte2 = data[1];
-
-            /* Is byte2, byte3 between 0x80 ~ 0xBF */
-            const int byte2_ok = (signed char)byte2 <= (signed char)0xBF;
-            const int byte3_ok = (signed char)data[2] <= (signed char)0xBF;
-
-            if (byte2_ok && byte3_ok &&
-                     /* E0, A0..BF, 80..BF */
-                    ((byte1 == 0xE0 && byte2 >= 0xA0) ||
-                     /* E1..EC, 80..BF, 80..BF */
-                     (byte1 >= 0xE1 && byte1 <= 0xEC) ||
-                     /* ED, 80..9F, 80..BF */
-                     (byte1 == 0xED && byte2 <= 0x9F) ||
-                     /* EE..EF, 80..BF, 80..BF */
-                     (byte1 >= 0xEE && byte1 <= 0xEF))) {
-                bytes = 3;
-            } else if (len >= 4) {
-                /* Is byte4 between 0x80 ~ 0xBF */
-                const int byte4_ok = (signed char)data[3] <= (signed char)0xBF;
-
-                if (byte2_ok && byte3_ok && byte4_ok &&
-                         /* F0, 90..BF, 80..BF, 80..BF */
-                        ((byte1 == 0xF0 && byte2 >= 0x90) ||
-                         /* F1..F3, 80..BF, 80..BF, 80..BF */
-                         (byte1 >= 0xF1 && byte1 <= 0xF3) ||
-                         /* F4, 80..8F, 80..BF, 80..BF */
-                         (byte1 == 0xF4 && byte2 <= 0x8F))) {
-                    bytes = 4;
-                } else {
-                    return err_pos;
-                }
-            } else {
-                return err_pos;
-            }
-        } else {
-            return err_pos;
-        }
-
-        len -= bytes;
-        err_pos += bytes;
-        data += bytes;
-    }
-
-    return 0;
-}
diff --git a/third_party/utf8_range/range2-neon.c b/third_party/utf8_range/range2-neon.c
deleted file mode 100644
index 6833965..0000000
--- a/third_party/utf8_range/range2-neon.c
+++ /dev/null
@@ -1,157 +0,0 @@
-/*
- * Process 2x16 bytes in each iteration.
- * Comments removed for brevity. See range-neon.c for details.
- */
-#if defined(__aarch64__) && defined(__ARM_NEON)
-
-#include <stdio.h>
-#include <stdint.h>
-#include <arm_neon.h>
-
-int utf8_naive(const unsigned char *data, int len);
-
-static const uint8_t _first_len_tbl[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
-};
-
-static const uint8_t _first_range_tbl[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
-};
-
-static const uint8_t _range_min_tbl[] = {
-    0x00, 0x80, 0x80, 0x80, 0xA0, 0x80, 0x90, 0x80,
-    0xC2, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF, 0xFF,
-};
-static const uint8_t _range_max_tbl[] = {
-    0x7F, 0xBF, 0xBF, 0xBF, 0xBF, 0x9F, 0xBF, 0x8F,
-    0xF4, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
-};
-
-static const uint8_t _range_adjust_tbl[] = {
-    2, 3, 0, 0, 0, 0, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0,
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0, 0, 0, 0, 0,
-};
-
-/* Return 0 on success, -1 on error */
-int utf8_range2(const unsigned char *data, int len)
-{
-    if (len >= 32) {
-        uint8x16_t prev_input = vdupq_n_u8(0);
-        uint8x16_t prev_first_len = vdupq_n_u8(0);
-
-        const uint8x16_t first_len_tbl = vld1q_u8(_first_len_tbl);
-        const uint8x16_t first_range_tbl = vld1q_u8(_first_range_tbl);
-        const uint8x16_t range_min_tbl = vld1q_u8(_range_min_tbl);
-        const uint8x16_t range_max_tbl = vld1q_u8(_range_max_tbl);
-        const uint8x16x2_t range_adjust_tbl = vld2q_u8(_range_adjust_tbl);
-
-        const uint8x16_t const_1 = vdupq_n_u8(1);
-        const uint8x16_t const_2 = vdupq_n_u8(2);
-        const uint8x16_t const_e0 = vdupq_n_u8(0xE0);
-
-        uint8x16_t error1 = vdupq_n_u8(0);
-        uint8x16_t error2 = vdupq_n_u8(0);
-        uint8x16_t error3 = vdupq_n_u8(0);
-        uint8x16_t error4 = vdupq_n_u8(0);
-
-        while (len >= 32) {
-            /******************* two blocks interleaved **********************/
-
-#if defined(__GNUC__) && !defined(__clang__) && (__GNUC__ < 8)
-            /* gcc doesn't support vldq1_u8_x2 until version 8 */
-            const uint8x16_t input_a = vld1q_u8(data);
-            const uint8x16_t input_b = vld1q_u8(data + 16);
-#else
-            /* Forces a double load on Clang */
-            const uint8x16x2_t input_pair = vld1q_u8_x2(data);
-            const uint8x16_t input_a = input_pair.val[0];
-            const uint8x16_t input_b = input_pair.val[1];
-#endif
-
-            const uint8x16_t high_nibbles_a = vshrq_n_u8(input_a, 4);
-            const uint8x16_t high_nibbles_b = vshrq_n_u8(input_b, 4);
-
-            const uint8x16_t first_len_a =
-                vqtbl1q_u8(first_len_tbl, high_nibbles_a);
-            const uint8x16_t first_len_b =
-                vqtbl1q_u8(first_len_tbl, high_nibbles_b);
-
-            uint8x16_t range_a = vqtbl1q_u8(first_range_tbl, high_nibbles_a);
-            uint8x16_t range_b = vqtbl1q_u8(first_range_tbl, high_nibbles_b);
-
-            range_a =
-                vorrq_u8(range_a, vextq_u8(prev_first_len, first_len_a, 15));
-            range_b =
-                vorrq_u8(range_b, vextq_u8(first_len_a, first_len_b, 15));
-
-            uint8x16_t tmp1_a, tmp2_a, tmp1_b, tmp2_b;
-            tmp1_a = vextq_u8(prev_first_len, first_len_a, 14);
-            tmp1_a = vqsubq_u8(tmp1_a, const_1);
-            range_a = vorrq_u8(range_a, tmp1_a);
-
-            tmp1_b = vextq_u8(first_len_a, first_len_b, 14);
-            tmp1_b = vqsubq_u8(tmp1_b, const_1);
-            range_b = vorrq_u8(range_b, tmp1_b);
-
-            tmp2_a = vextq_u8(prev_first_len, first_len_a, 13);
-            tmp2_a = vqsubq_u8(tmp2_a, const_2);
-            range_a = vorrq_u8(range_a, tmp2_a);
-
-            tmp2_b = vextq_u8(first_len_a, first_len_b, 13);
-            tmp2_b = vqsubq_u8(tmp2_b, const_2);
-            range_b = vorrq_u8(range_b, tmp2_b);
-
-            uint8x16_t shift1_a = vextq_u8(prev_input, input_a, 15);
-            uint8x16_t pos_a = vsubq_u8(shift1_a, const_e0);
-            range_a = vaddq_u8(range_a, vqtbl2q_u8(range_adjust_tbl, pos_a));
-
-            uint8x16_t shift1_b = vextq_u8(input_a, input_b, 15);
-            uint8x16_t pos_b = vsubq_u8(shift1_b, const_e0);
-            range_b = vaddq_u8(range_b, vqtbl2q_u8(range_adjust_tbl, pos_b));
-
-            uint8x16_t minv_a = vqtbl1q_u8(range_min_tbl, range_a);
-            uint8x16_t maxv_a = vqtbl1q_u8(range_max_tbl, range_a);
-
-            uint8x16_t minv_b = vqtbl1q_u8(range_min_tbl, range_b);
-            uint8x16_t maxv_b = vqtbl1q_u8(range_max_tbl, range_b);
-
-            error1 = vorrq_u8(error1, vcltq_u8(input_a, minv_a));
-            error2 = vorrq_u8(error2, vcgtq_u8(input_a, maxv_a));
-
-            error3 = vorrq_u8(error3, vcltq_u8(input_b, minv_b));
-            error4 = vorrq_u8(error4, vcgtq_u8(input_b, maxv_b));
-
-            /************************ next iteration *************************/
-            prev_input = input_b;
-            prev_first_len = first_len_b;
-
-            data += 32;
-            len -= 32;
-        }
-        error1 = vorrq_u8(error1, error2);
-        error1 = vorrq_u8(error1, error3);
-        error1 = vorrq_u8(error1, error4);
-
-        if (vmaxvq_u8(error1))
-            return -1;
-
-        uint32_t token4;
-        vst1q_lane_u32(&token4, vreinterpretq_u32_u8(prev_input), 3);
-
-        const int8_t *token = (const int8_t *)&token4;
-        int lookahead = 0;
-        if (token[3] > (int8_t)0xBF)
-            lookahead = 1;
-        else if (token[2] > (int8_t)0xBF)
-            lookahead = 2;
-        else if (token[1] > (int8_t)0xBF)
-            lookahead = 3;
-
-        data -= lookahead;
-        len += lookahead;
-    }
-
-    return utf8_naive(data, len);
-}
-
-#endif
diff --git a/third_party/utf8_range/range2-sse.c b/third_party/utf8_range/range2-sse.c
deleted file mode 100644
index f3deb86..0000000
--- a/third_party/utf8_range/range2-sse.c
+++ /dev/null
@@ -1,170 +0,0 @@
-/*
- * Process 2x16 bytes in each iteration.
- * Comments removed for brevity. See range-sse.c for details.
- */
-#ifdef __SSE4_1__
-
-#include <stdio.h>
-#include <stdint.h>
-#include <x86intrin.h>
-
-int utf8_naive(const unsigned char *data, int len);
-
-static const int8_t _first_len_tbl[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 2, 3,
-};
-
-static const int8_t _first_range_tbl[] = {
-    0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 8, 8, 8, 8,
-};
-
-static const int8_t _range_min_tbl[] = {
-    0x00, 0x80, 0x80, 0x80, 0xA0, 0x80, 0x90, 0x80,
-    0xC2, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F, 0x7F,
-};
-static const int8_t _range_max_tbl[] = {
-    0x7F, 0xBF, 0xBF, 0xBF, 0xBF, 0x9F, 0xBF, 0x8F,
-    0xF4, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80, 0x80,
-};
-
-static const int8_t _df_ee_tbl[] = {
-    0, 2, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 3, 0,
-};
-static const int8_t _ef_fe_tbl[] = {
-    0, 3, 0, 0, 0, 4, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
-};
-
-/* Return 0 on success, -1 on error */
-int utf8_range2(const unsigned char *data, int len)
-{
-    if (len >= 32) {
-        __m128i prev_input = _mm_set1_epi8(0);
-        __m128i prev_first_len = _mm_set1_epi8(0);
-
-        const __m128i first_len_tbl =
-            _mm_loadu_si128((const __m128i *)_first_len_tbl);
-        const __m128i first_range_tbl =
-            _mm_loadu_si128((const __m128i *)_first_range_tbl);
-        const __m128i range_min_tbl =
-            _mm_loadu_si128((const __m128i *)_range_min_tbl);
-        const __m128i range_max_tbl =
-            _mm_loadu_si128((const __m128i *)_range_max_tbl);
-        const __m128i df_ee_tbl =
-            _mm_loadu_si128((const __m128i *)_df_ee_tbl);
-        const __m128i ef_fe_tbl =
-            _mm_loadu_si128((const __m128i *)_ef_fe_tbl);
-
-        __m128i error = _mm_set1_epi8(0);
-
-        while (len >= 32) {
-            /***************************** block 1 ****************************/
-            const __m128i input_a = _mm_loadu_si128((const __m128i *)data);
-
-            __m128i high_nibbles =
-                _mm_and_si128(_mm_srli_epi16(input_a, 4), _mm_set1_epi8(0x0F));
-
-            __m128i first_len_a = _mm_shuffle_epi8(first_len_tbl, high_nibbles);
-
-            __m128i range_a = _mm_shuffle_epi8(first_range_tbl, high_nibbles);
-
-            range_a = _mm_or_si128(
-                    range_a, _mm_alignr_epi8(first_len_a, prev_first_len, 15));
-
-            __m128i tmp;
-            tmp = _mm_alignr_epi8(first_len_a, prev_first_len, 14);
-            tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(1));
-            range_a = _mm_or_si128(range_a, tmp);
-
-            tmp = _mm_alignr_epi8(first_len_a, prev_first_len, 13);
-            tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(2));
-            range_a = _mm_or_si128(range_a, tmp);
-
-            __m128i shift1, pos, range2;
-            shift1 = _mm_alignr_epi8(input_a, prev_input, 15);
-            pos = _mm_sub_epi8(shift1, _mm_set1_epi8(0xEF));
-            tmp = _mm_subs_epu8(pos, _mm_set1_epi8(0xF0));
-            range2 = _mm_shuffle_epi8(df_ee_tbl, tmp);
-            tmp = _mm_adds_epu8(pos, _mm_set1_epi8(0x70));
-            range2 = _mm_add_epi8(range2, _mm_shuffle_epi8(ef_fe_tbl, tmp));
-
-            range_a = _mm_add_epi8(range_a, range2);
-
-            __m128i minv = _mm_shuffle_epi8(range_min_tbl, range_a);
-            __m128i maxv = _mm_shuffle_epi8(range_max_tbl, range_a);
-
-            tmp = _mm_or_si128(
-                      _mm_cmplt_epi8(input_a, minv),
-                      _mm_cmpgt_epi8(input_a, maxv)
-                  );
-            error = _mm_or_si128(error, tmp);
-
-            /***************************** block 2 ****************************/
-            const __m128i input_b = _mm_loadu_si128((const __m128i *)(data+16));
-
-            high_nibbles =
-                _mm_and_si128(_mm_srli_epi16(input_b, 4), _mm_set1_epi8(0x0F));
-
-            __m128i first_len_b = _mm_shuffle_epi8(first_len_tbl, high_nibbles);
-
-            __m128i range_b = _mm_shuffle_epi8(first_range_tbl, high_nibbles);
-
-            range_b = _mm_or_si128(
-                    range_b, _mm_alignr_epi8(first_len_b, first_len_a, 15));
-
-
-            tmp = _mm_alignr_epi8(first_len_b, first_len_a, 14);
-            tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(1));
-            range_b = _mm_or_si128(range_b, tmp);
-
-            tmp = _mm_alignr_epi8(first_len_b, first_len_a, 13);
-            tmp = _mm_subs_epu8(tmp, _mm_set1_epi8(2));
-            range_b = _mm_or_si128(range_b, tmp);
-
-            shift1 = _mm_alignr_epi8(input_b, input_a, 15);
-            pos = _mm_sub_epi8(shift1, _mm_set1_epi8(0xEF));
-            tmp = _mm_subs_epu8(pos, _mm_set1_epi8(0xF0));
-            range2 = _mm_shuffle_epi8(df_ee_tbl, tmp);
-            tmp = _mm_adds_epu8(pos, _mm_set1_epi8(0x70));
-            range2 = _mm_add_epi8(range2, _mm_shuffle_epi8(ef_fe_tbl, tmp));
-
-            range_b = _mm_add_epi8(range_b, range2);
-
-            minv = _mm_shuffle_epi8(range_min_tbl, range_b);
-            maxv = _mm_shuffle_epi8(range_max_tbl, range_b);
-
-
-            tmp = _mm_or_si128(
-                      _mm_cmplt_epi8(input_b, minv),
-                      _mm_cmpgt_epi8(input_b, maxv)
-                  );
-            error = _mm_or_si128(error, tmp);
-
-            /************************ next iteration **************************/
-            prev_input = input_b;
-            prev_first_len = first_len_b;
-
-            data += 32;
-            len -= 32;
-        }
-
-        if (!_mm_testz_si128(error, error))
-            return -1;
-
-        int32_t token4 = _mm_extract_epi32(prev_input, 3);
-        const int8_t *token = (const int8_t *)&token4;
-        int lookahead = 0;
-        if (token[3] > (int8_t)0xBF)
-            lookahead = 1;
-        else if (token[2] > (int8_t)0xBF)
-            lookahead = 2;
-        else if (token[1] > (int8_t)0xBF)
-            lookahead = 3;
-
-        data -= lookahead;
-        len += lookahead;
-    }
-
-    return utf8_naive(data, len);
-}
-
-#endif
diff --git a/third_party/utf8_range/utf8_range.h b/third_party/utf8_range/utf8_range.h
deleted file mode 100644
index 23b32a1..0000000
--- a/third_party/utf8_range/utf8_range.h
+++ /dev/null
@@ -1,9 +0,0 @@
-
-#if ((defined(__ARM_NEON) && defined(__aarch64__)) || defined(__SSE4_1__)) && !defined(TRUFFLERUBY)
-int utf8_range2(const unsigned char* data, int len);
-#else
-int utf8_naive(const unsigned char* data, int len);
-static inline int utf8_range2(const unsigned char* data, int len) {
-  return utf8_naive(data, len);
-}
-#endif
diff --git a/toolchain/cc_toolchain_config.bzl b/toolchain/cc_toolchain_config.bzl
index 2599477..b610a8e 100644
--- a/toolchain/cc_toolchain_config.bzl
+++ b/toolchain/cc_toolchain_config.bzl
@@ -29,193 +29,193 @@
 ]
 
 def _impl(ctx):
-  if "mingw" in ctx.attr.target_full_name:
-      artifact_name_patterns = [
-          artifact_name_pattern(
-              category_name = "executable",
-              prefix = "",
-              extension = ".exe",
-          ),
-      ]
-  else:
-      artifact_name_patterns = []
+    if "mingw" in ctx.attr.target_full_name:
+        artifact_name_patterns = [
+            artifact_name_pattern(
+                category_name = "executable",
+                prefix = "",
+                extension = ".exe",
+            ),
+        ]
+    else:
+        artifact_name_patterns = []
 
-  tool_paths = [
-      tool_path(
-          name = "gcc",
-          path = "/usr/local/bin/clang",
-      ),
-      tool_path(
-          name = "ld",
-          path = ctx.attr.linker_path,
-      ),
-      tool_path(
-          name = "ar",
-          path = "/usr/local/bin/llvm-ar",
-      ),
-      tool_path(
-          name = "compat-ld",
-          path = ctx.attr.linker_path,
-      ),
-      tool_path(
-          name = "cpp",
-          path = "/bin/false",
-      ),
-      tool_path(
-          name = "dwp",
-          path = "/bin/false",
-      ),
-      tool_path(
-          name = "gcov",
-          path = "/bin/false",
-      ),
-      tool_path(
-          name = "nm",
-          path = "/bin/false",
-      ),
-      tool_path(
-          name = "objcopy",
-          path = "/bin/false",
-      ),
-      tool_path(
-          name = "objdump",
-          path = "/bin/false",
-      ),
-      tool_path(
-          name = "strip",
-          path = "/bin/false",
-      ),
-  ]
+    tool_paths = [
+        tool_path(
+            name = "gcc",
+            path = "/usr/local/bin/clang",
+        ),
+        tool_path(
+            name = "ld",
+            path = ctx.attr.linker_path,
+        ),
+        tool_path(
+            name = "ar",
+            path = "/usr/local/bin/llvm-ar",
+        ),
+        tool_path(
+            name = "compat-ld",
+            path = ctx.attr.linker_path,
+        ),
+        tool_path(
+            name = "cpp",
+            path = "/bin/false",
+        ),
+        tool_path(
+            name = "dwp",
+            path = "/bin/false",
+        ),
+        tool_path(
+            name = "gcov",
+            path = "/bin/false",
+        ),
+        tool_path(
+            name = "nm",
+            path = "/bin/false",
+        ),
+        tool_path(
+            name = "objcopy",
+            path = "/bin/false",
+        ),
+        tool_path(
+            name = "objdump",
+            path = "/bin/false",
+        ),
+        tool_path(
+            name = "strip",
+            path = "/bin/false",
+        ),
+    ]
 
-  linker_flags = feature(
-      name = "default_linker_flags",
-      enabled = True,
-      flag_sets = [
-          flag_set(
-              actions = all_link_actions,
-              flag_groups = [
-                  flag_group(
-                      flags = [
-                          "-B" + ctx.attr.linker_path,
-                          "-lstdc++",
-                          "--target=" + ctx.attr.target_full_name,
-                      ] + ctx.attr.extra_linker_flags,
-                  ),
-              ],
-          ),
-      ],
-  )
+    linker_flags = feature(
+        name = "default_linker_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_link_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "-B" + ctx.attr.linker_path,
+                            "-lstdc++",
+                            "--target=" + ctx.attr.target_full_name,
+                        ] + ctx.attr.extra_linker_flags,
+                    ),
+                ],
+            ),
+        ],
+    )
 
-  if "osx" in ctx.attr.target_full_name:
-    sysroot_action_set = all_link_actions
-  else:
-    sysroot_action_set = all_link_actions + all_compile_actions
+    if "osx" in ctx.attr.target_full_name:
+        sysroot_action_set = all_link_actions
+    else:
+        sysroot_action_set = all_link_actions + all_compile_actions
 
-  sysroot_flags = feature(
-      name = "sysroot_flags",
-      #Only enable this if a sysroot was specified
-      enabled = (ctx.attr.sysroot != ""),
-      flag_sets = [
-          flag_set(
-              actions = sysroot_action_set,
-              flag_groups = [
-                  flag_group(
-                      flags = [
-                          "--sysroot",
-                          ctx.attr.sysroot,
-                      ],
-                  ),
-              ],
-          ),
-      ],
-  )
+    sysroot_flags = feature(
+        name = "sysroot_flags",
+        #Only enable this if a sysroot was specified
+        enabled = (ctx.attr.sysroot != ""),
+        flag_sets = [
+            flag_set(
+                actions = sysroot_action_set,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            "--sysroot",
+                            ctx.attr.sysroot,
+                        ],
+                    ),
+                ],
+            ),
+        ],
+    )
 
-  if ctx.attr.target_cpu == "x86_32":
-    bit_flag = "-m32"
-  else:
-    bit_flag = "-m64"
-  compiler_flags = feature(
-      name = "default_compile_flags",
-      enabled = True,
-      flag_sets = [
-          flag_set(
-              actions = all_compile_actions,
-              flag_groups = [
-                  flag_group(
-                      flags = [
-                          bit_flag,
-                          "-Wall",
-                          "-no-canonical-prefixes",
-                          "--target=" + ctx.attr.target_full_name,
-                          "-fvisibility=hidden",
-                      ] + ctx.attr.extra_compiler_flags + [
-                          "-isystem",
-                          ctx.attr.sysroot,
-                      ],
-                  ),
-              ],
-          ),
-          flag_set(
-              actions = all_compile_actions,
-              flag_groups = [flag_group(flags = ["-DNDEBUG", "-O3"])],
-              with_features = [with_feature_set(features = ["opt"])],
-          ),
-          flag_set(
-              actions = all_compile_actions,
-              flag_groups = [flag_group(flags = ["-g"])],
-              with_features = [with_feature_set(features = ["dbg"])],
-          ),
-          flag_set(
-              actions = all_compile_actions,
-              flag_groups = [flag_group(flags = ["-O1"])],
-              with_features = [with_feature_set(features = ["fastbuild"])],
-          ),
-      ],
-  )
+    if ctx.attr.target_cpu == "x86_32":
+        bit_flag = "-m32"
+    else:
+        bit_flag = "-m64"
+    compiler_flags = feature(
+        name = "default_compile_flags",
+        enabled = True,
+        flag_sets = [
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [
+                    flag_group(
+                        flags = [
+                            bit_flag,
+                            "-Wall",
+                            "-no-canonical-prefixes",
+                            "--target=" + ctx.attr.target_full_name,
+                            "-fvisibility=hidden",
+                        ] + ctx.attr.extra_compiler_flags + [
+                            "-isystem",
+                            ctx.attr.sysroot,
+                        ],
+                    ),
+                ],
+            ),
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [flag_group(flags = ["-DNDEBUG", "-O3"])],
+                with_features = [with_feature_set(features = ["opt"])],
+            ),
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [flag_group(flags = ["-g"])],
+                with_features = [with_feature_set(features = ["dbg"])],
+            ),
+            flag_set(
+                actions = all_compile_actions,
+                flag_groups = [flag_group(flags = ["-O1"])],
+                with_features = [with_feature_set(features = ["fastbuild"])],
+            ),
+        ],
+    )
 
-  features = [
-      linker_flags,
-      compiler_flags,
-      sysroot_flags,
-      feature(name = "dbg"),
-      feature(name = "opt"),
-  ]
+    features = [
+        linker_flags,
+        compiler_flags,
+        sysroot_flags,
+        feature(name = "dbg"),
+        feature(name = "opt"),
+    ]
 
-  if "mingw" in ctx.attr.target_full_name:
-      features.append(
-          feature(
-              name = "targets_windows",
-              enabled = True,
-          )
-      )
-  else:
-      features.append(
-          feature(
-              name = "supports_pic",
-              enabled = True
-          )
-      )
+    if "mingw" in ctx.attr.target_full_name:
+        features.append(
+            feature(
+                name = "targets_windows",
+                enabled = True,
+            ),
+        )
+    else:
+        features.append(
+            feature(
+                name = "supports_pic",
+                enabled = True,
+            ),
+        )
 
-  return cc_common.create_cc_toolchain_config_info(
-      abi_libc_version = ctx.attr.abi_version,
-      abi_version = ctx.attr.abi_version,
-      artifact_name_patterns = artifact_name_patterns,
-      ctx = ctx,
-      compiler = "clang",
-      cxx_builtin_include_directories = [
-          ctx.attr.sysroot,
-          ctx.attr.extra_include,
-          "/usr/local/include",
-          "/usr/local/lib/clang",
-      ],
-      features = features,
-      host_system_name = "local",
-      target_cpu = ctx.attr.target_cpu,
-      target_libc = ctx.attr.target_cpu,
-      target_system_name = ctx.attr.target_full_name,
-      toolchain_identifier = ctx.attr.target_full_name,
-      tool_paths = tool_paths,
-  )
+    return cc_common.create_cc_toolchain_config_info(
+        abi_libc_version = ctx.attr.abi_version,
+        abi_version = ctx.attr.abi_version,
+        artifact_name_patterns = artifact_name_patterns,
+        ctx = ctx,
+        compiler = "clang",
+        cxx_builtin_include_directories = [
+            ctx.attr.sysroot,
+            ctx.attr.extra_include,
+            "/usr/local/include",
+            "/usr/local/lib/clang",
+        ],
+        features = features,
+        host_system_name = "local",
+        target_cpu = ctx.attr.target_cpu,
+        target_libc = ctx.attr.target_cpu,
+        target_system_name = ctx.attr.target_full_name,
+        toolchain_identifier = ctx.attr.target_full_name,
+        tool_paths = tool_paths,
+    )
 
 cc_toolchain_config = rule(
     implementation = _impl,
diff --git a/toolchain/toolchains.bazelrc b/toolchain/toolchains.bazelrc
index fbd655b..908a26e 100644
--- a/toolchain/toolchains.bazelrc
+++ b/toolchain/toolchains.bazelrc
@@ -2,9 +2,12 @@
 build:cross_config --host_crosstool_top=@bazel_tools//tools/cpp:toolchain
 
 build:linux-aarch_64 --config=cross_config --cpu=linux-aarch_64
+build:linux-aarch64 --config=cross_config --cpu=linux-aarch_64
 build:linux-ppcle_64 --config=cross_config --cpu=linux-ppcle_64
+build:linux-ppc64le --config=cross_config --cpu=linux-ppcle_64
 build:linux-s390_64 --config=cross_config --cpu=linux-s390_64
 build:linux-x86_32 --config=cross_config --cpu=linux-x86_32
+build:linux-i386 --config=cross_config --cpu=linux-x86_32
 build:linux-x86_64 --config=cross_config --cpu=linux-x86_64
 build:osx-aarch_64 --config=cross_config --action_env=MACOSX_DEPLOYMENT_TARGET=10.9 --cpu=osx-aarch_64
 build:osx-x86_64 --config=cross_config --action_env=MACOSX_DEPLOYMENT_TARGET=10.9 --cpu=osx-x86_64
diff --git a/update_compatibility_version.py b/update_compatibility_version.py
deleted file mode 100755
index f93479b..0000000
--- a/update_compatibility_version.py
+++ /dev/null
@@ -1,56 +0,0 @@
-#!/usr/bin/env python
-"""Compatibility tests between last released and the current version.
-
-Usage: ./update_compatibility_version.py <MAJOR>.<MINOR>.<MICRO> [<RC version>]
-Example: ./update_compatibility_version.py 3.7.1
-"""
-
-from __future__ import print_function
-import re
-import sys
-
-if len(sys.argv) < 2 or len(sys.argv) > 3:
-  print("""
-[ERROR] Please specify a version.
-
-./update_compatibility_version.py.py <MAJOR>.<MINOR>.<MICRO> [<RC version>]
-
-Example:
-./update_compatibility_version.py.py 3.7.1 2
-""")
-  exit(1)
-
-NEW_VERSION = sys.argv[1]
-NEW_VERSION_INFO = NEW_VERSION.split('.')
-if len(NEW_VERSION_INFO) != 3:
-  print("""
-[ERROR] Version must be in the format <MAJOR>.<MINOR>.<MICRO>
-
-Example:
-./update_compatibility_version.py.py 3.7.3
-""")
-  exit(1)
-
-if len(sys.argv) > 2:
-  RC_VERSION = int(sys.argv[2])
-  # Do not update compatibility versions for rc release
-  if RC_VERSION != 0:
-    exit(0)
-
-
-def RewriteTextFile(filename, line_rewriter):
-  lines = open(filename, 'r').readlines()
-  updated_lines = []
-  for line in lines:
-    updated_lines.append(line_rewriter(line))
-  if lines == updated_lines:
-    print('%s was not updated. Please double check.' % filename)
-  f = open(filename, 'w')
-  f.write(''.join(updated_lines))
-  f.close()
-
-
-def ReplaceVersion(line):
-  return re.sub(r'LAST_RELEASED=.*$', 'LAST_RELEASED=%s' % NEW_VERSION, line)
-
-RewriteTextFile('tests.sh', ReplaceVersion)
diff --git a/update_file_lists.sh b/update_file_lists.sh
deleted file mode 100755
index 3ef366d..0000000
--- a/update_file_lists.sh
+++ /dev/null
@@ -1,195 +0,0 @@
-#!/bin/bash -u
-
-# This script copies source file lists from src/Makefile.am to cmake files.
-
-get_variable_value() {
-  local FILENAME=$1
-  local VARNAME=$2
-  awk "
-    BEGIN { start = 0; }
-    /^$VARNAME =/ { start = 1; }
-    { if (start) { print \$0; } }
-    /\\\\\$/ { next; }
-    { start = 0; }
-  " $FILENAME \
-    | sed "s/^$VARNAME =//" \
-    | sed "s/[ \\]//g" \
-    | grep -v "^\\$" \
-    | grep -v "^$" \
-    | LC_ALL=C sort | uniq
-}
-
-get_header_files() {
-  get_variable_value $@ | grep '\.h$'
-}
-
-get_source_files() {
-  get_variable_value $@ | grep "cc$\|inc$"
-}
-
-get_proto_files() {
-  get_variable_value $@ | grep "pb.cc$" | sed "s/pb.cc/proto/"
-}
-
-sort_files() {
-  for FILE in $@; do
-    echo $FILE
-  done | LC_ALL=C sort | uniq
-}
-
-MAKEFILE=src/Makefile.am
-
-[ -f "$MAKEFILE" ] || {
-  echo "Cannot find: $MAKEFILE"
-  exit 1
-}
-
-# Extract file lists from src/Makefile.am
-GZHEADERS=$(get_variable_value $MAKEFILE GZHEADERS)
-LIBPROTOBUF_HEADERS=$(get_variable_value $MAKEFILE nobase_include_HEADERS | grep -v /compiler/)
-LIBPROTOBUF_HEADERS=$(sort_files $GZHEADERS $LIBPROTOBUF_HEADERS)
-LIBPROTOBUF_LITE_SOURCES=$(get_source_files $MAKEFILE libprotobuf_lite_la_SOURCES)
-LIBPROTOBUF_SOURCES=$(get_source_files $MAKEFILE libprotobuf_la_SOURCES)
-LIBPROTOC_SOURCES=$(get_source_files $MAKEFILE libprotoc_la_SOURCES)
-LIBPROTOC_HEADERS=$(get_variable_value $MAKEFILE nobase_include_HEADERS | grep /compiler/)
-LITE_PROTOS=$(get_proto_files $MAKEFILE protoc_lite_outputs)
-PROTOS=$(get_proto_files $MAKEFILE protoc_outputs)
-WKT_PROTOS=$(get_variable_value $MAKEFILE nobase_dist_proto_DATA)
-COMMON_TEST_SOURCES=$(get_source_files $MAKEFILE COMMON_TEST_SOURCES)
-COMMON_LITE_TEST_SOURCES=$(get_source_files $MAKEFILE COMMON_LITE_TEST_SOURCES)
-TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_test_SOURCES)
-NON_MSVC_TEST_SOURCES=$(get_source_files $MAKEFILE NON_MSVC_TEST_SOURCES)
-LITE_TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_lite_test_SOURCES)
-LITE_ARENA_TEST_SOURCES=$(get_source_files $MAKEFILE protobuf_lite_arena_test_SOURCES)
-TEST_PLUGIN_SOURCES=$(get_source_files $MAKEFILE test_plugin_SOURCES)
-
-################################################################################
-# Update cmake files.
-################################################################################
-
-CMAKE_DIR=cmake
-EXTRACT_INCLUDES_BAT=cmake/extract_includes.bat.in
-[ -d "$CMAKE_DIR" ] || {
-  echo "Cannot find: $CMAKE_DIR"
-  exit 1
-}
-
-[ -f "$EXTRACT_INCLUDES_BAT" ] || {
-  echo "Cannot find: $EXTRACT_INCLUDES_BAT"
-  exit 1
-}
-
-set_cmake_value() {
-  local FILENAME=$1
-  local VARNAME=$2
-  local PREFIX=$3
-  shift
-  shift
-  shift
-  awk -v values="$*" -v prefix="$PREFIX" "
-    BEGIN { start = 0; }
-    /^set\\($VARNAME/ {
-      start = 1;
-      print \$0;
-      len = split(values, vlist, \" \");
-      for (i = 1; i <= len; ++i) {
-        printf(\"  \");
-        if (vlist[i] !~ /^\\\$/) {
-          printf(\"%s\", prefix);
-        }
-        printf(\"%s\\n\", vlist[i]);
-      }
-      next;
-    }
-    start && /^\\)/ {
-      start = 0;
-    }
-    !start {
-      print \$0;
-    }
-  " $FILENAME > /tmp/$$
-  cp /tmp/$$ $FILENAME
-}
-
-
-# Replace file lists in cmake files.
-CMAKE_PREFIX="\${protobuf_SOURCE_DIR}/src/"
-set_cmake_value $CMAKE_DIR/libprotobuf-lite.cmake libprotobuf_lite_files $CMAKE_PREFIX $LIBPROTOBUF_LITE_SOURCES
-set_cmake_value $CMAKE_DIR/libprotobuf.cmake libprotobuf_files $CMAKE_PREFIX $LIBPROTOBUF_SOURCES
-set_cmake_value $CMAKE_DIR/libprotoc.cmake libprotoc_files $CMAKE_PREFIX $LIBPROTOC_SOURCES
-set_cmake_value $CMAKE_DIR/libprotoc.cmake libprotoc_headers $CMAKE_PREFIX $LIBPROTOC_HEADERS
-set_cmake_value $CMAKE_DIR/tests.cmake lite_test_protos "" $LITE_PROTOS
-set_cmake_value $CMAKE_DIR/tests.cmake tests_protos "" $PROTOS
-set_cmake_value $CMAKE_DIR/tests.cmake common_test_files $CMAKE_PREFIX '${common_lite_test_files}' $COMMON_TEST_SOURCES
-set_cmake_value $CMAKE_DIR/tests.cmake common_lite_test_files $CMAKE_PREFIX $COMMON_LITE_TEST_SOURCES
-set_cmake_value $CMAKE_DIR/tests.cmake tests_files $CMAKE_PREFIX $TEST_SOURCES
-set_cmake_value $CMAKE_DIR/tests.cmake non_msvc_tests_files $CMAKE_PREFIX $NON_MSVC_TEST_SOURCES
-set_cmake_value $CMAKE_DIR/tests.cmake lite_test_files $CMAKE_PREFIX $LITE_TEST_SOURCES
-set_cmake_value $CMAKE_DIR/tests.cmake lite_arena_test_files $CMAKE_PREFIX $LITE_ARENA_TEST_SOURCES
-
-# Generate extract_includes.bat
-echo "mkdir include" > $EXTRACT_INCLUDES_BAT
-for INCLUDE in $LIBPROTOBUF_HEADERS $LIBPROTOC_HEADERS $WKT_PROTOS; do
-  INCLUDE_DIR=$(dirname "$INCLUDE")
-  while [ ! "$INCLUDE_DIR" = "." ]; do
-    echo "mkdir include\\${INCLUDE_DIR//\//\\}"
-    INCLUDE_DIR=$(dirname "$INCLUDE_DIR")
-  done
-done | sort | uniq >> $EXTRACT_INCLUDES_BAT
-for INCLUDE in $(sort_files $LIBPROTOBUF_HEADERS $LIBPROTOC_HEADERS) $WKT_PROTOS; do
-  WINPATH=${INCLUDE//\//\\}
-  echo "copy \"\${PROTOBUF_SOURCE_WIN32_PATH}\\..\\src\\$WINPATH\" include\\$WINPATH" >> $EXTRACT_INCLUDES_BAT
-done
-
-################################################################################
-# Update bazel BUILD files.
-################################################################################
-
-set_bazel_value() {
-  local FILENAME=$1
-  local VARNAME=$2
-  local PREFIX=$3
-  shift
-  shift
-  shift
-  awk -v values="$*" -v prefix="$PREFIX" "
-    BEGIN { start = 0; }
-    /# AUTOGEN\\($VARNAME\\)/ {
-      start = 1;
-      print \$0;
-      # replace \$0 with indent.
-      sub(/#.*/, \"\", \$0)
-      len = split(values, vlist, \" \");
-      for (i = 1; i <= len; ++i) {
-        printf(\"%s\\\"%s%s\\\",\n\", \$0, prefix, vlist[i]);
-      }
-      next;
-    }
-    start && /\]/ {
-      start = 0
-    }
-    !start {
-      print \$0;
-    }
-  " $FILENAME > /tmp/$$
-  cp /tmp/$$ $FILENAME
-}
-
-
-BAZEL_BUILD=./BUILD
-BAZEL_PREFIX="src/"
-if [ -f "$BAZEL_BUILD" ]; then
-  set_bazel_value $BAZEL_BUILD protobuf_lite_srcs $BAZEL_PREFIX $LIBPROTOBUF_LITE_SOURCES
-  set_bazel_value $BAZEL_BUILD protobuf_srcs $BAZEL_PREFIX $LIBPROTOBUF_SOURCES
-  set_bazel_value $BAZEL_BUILD protoc_lib_srcs $BAZEL_PREFIX $LIBPROTOC_SOURCES
-  set_bazel_value $BAZEL_BUILD lite_test_protos "" $LITE_PROTOS
-  set_bazel_value $BAZEL_BUILD well_known_protos "" $WKT_PROTOS
-  set_bazel_value $BAZEL_BUILD test_protos "" $PROTOS
-  set_bazel_value $BAZEL_BUILD common_test_srcs $BAZEL_PREFIX $COMMON_LITE_TEST_SOURCES $COMMON_TEST_SOURCES
-  set_bazel_value $BAZEL_BUILD test_srcs $BAZEL_PREFIX $TEST_SOURCES
-  set_bazel_value $BAZEL_BUILD non_msvc_test_srcs $BAZEL_PREFIX $NON_MSVC_TEST_SOURCES
-  set_bazel_value $BAZEL_BUILD test_plugin_srcs $BAZEL_PREFIX $TEST_PLUGIN_SOURCES
-else
-  echo "Skipped BUILD file update."
-fi
-
diff --git a/update_version.py b/update_version.py
deleted file mode 100755
index cb9f4db..0000000
--- a/update_version.py
+++ /dev/null
@@ -1,405 +0,0 @@
-#!/usr/bin/env python3
-# Usage: ./update_version.py <MAJOR>.<MINOR>.<MICRO> [<RC version>]
-#
-# Example:
-# ./update_version.py 3.7.1 2
-#   => Version will become 3.7.1-rc-2 (beta)
-# ./update_version.py 3.7.1
-#   => Version will become 3.7.1 (stable)
-
-import datetime
-import re
-import sys
-from xml.dom import minidom
-
-if len(sys.argv) < 2 or len(sys.argv) > 3:
-  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("""
-[ERROR] Version must be in the format <MAJOR>.<MINOR>.<MICRO>
-
-Example:
-./update_version.py 3.7.3
-""")
-  exit(1)
-
-RC_VERSION = -1
-if len(sys.argv) > 2:
-  RC_VERSION = int(sys.argv[2])
-
-
-def Find(elem, tagname):
-  for child in elem.childNodes:
-    if child.nodeName == tagname:
-      return child
-  return None
-
-
-def FindAndClone(elem, tagname):
-  return Find(elem, tagname).cloneNode(True)
-
-
-def ReplaceText(elem, text):
-  elem.firstChild.replaceWholeText(text)
-
-
-def GetFullVersion(rc_suffix = '-rc-'):
-  if RC_VERSION < 0:
-    return NEW_VERSION
-  else:
-    return '%s%s%s' % (NEW_VERSION, rc_suffix, RC_VERSION)
-
-
-def GetSharedObjectVersion():
-  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
-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)
-  return [NEW_VERSION_INFO[1] + protobuf_version_offset, NEW_VERSION_INFO[2], 0]
-
-
-def RewriteXml(filename, rewriter, add_xml_prefix=True):
-  document = minidom.parse(filename)
-  rewriter(document)
-  # document.toxml() always prepend the XML version without inserting new line.
-  # We wants to preserve as much of the original formatting as possible, so we
-  # will remove the default XML version and replace it with our custom one when
-  # wherever necessary.
-  content = document.toxml().replace('<?xml version="1.0" ?>', '')
-  file_handle = open(filename, 'wb')
-  if add_xml_prefix:
-    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()
-
-
-def RewriteTextFile(filename, line_rewriter):
-  lines = open(filename, 'r').readlines()
-  updated_lines = []
-  for line in lines:
-    updated_lines.append(line_rewriter(line))
-  if lines == updated_lines:
-    print('%s was not updated. Please double check.' % filename)
-  f = open(filename, 'w')
-  f.write(''.join(updated_lines))
-  f.close()
-
-
-def UpdateCMake():
-  cmake_files = (
-    'cmake/libprotobuf.cmake',
-    'cmake/libprotobuf-lite.cmake',
-    'cmake/libprotoc.cmake'
-  )
-  for cmake_file in cmake_files:
-    RewriteTextFile(cmake_file,
-      lambda line : re.sub(
-        r'SOVERSION ([0-9]+)$',
-        'SOVERSION %s' % GetSharedObjectVersion()[0],
-        line))
-
-
-def UpdateConfigure():
-  RewriteTextFile('configure.ac',
-    lambda line : re.sub(
-      r'^AC_INIT\(\[Protocol Buffers\],\[.*\],\[protobuf@googlegroups.com\],\[protobuf\]\)$',
-      ('AC_INIT([Protocol Buffers],[%s],[protobuf@googlegroups.com],[protobuf])'
-        % GetFullVersion()),
-      line))
-
-
-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 .*$',
-      '#define GOOGLE_PROTOBUF_VERSION %s' % cpp_version,
-      line)
-    line = re.sub(
-      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 .*$',
-        '#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC %s' % cpp_version,
-        line)
-      line = re.sub(
-        r'^#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION .*$',
-        '#define GOOGLE_PROTOBUF_MIN_PROTOC_VERSION %s' % cpp_version,
-        line)
-      line = re.sub(
-        r'^static const int kMinHeaderVersionForLibrary = .*$',
-        'static const int kMinHeaderVersionForLibrary = %s;' % cpp_version,
-        line)
-      line = re.sub(
-        r'^static const int kMinHeaderVersionForProtoc = .*$',
-        '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 .*$',
-        '#define PROTOBUF_MIN_HEADER_VERSION_FOR_PROTOC %s' % cpp_version,
-        line)
-      line = re.sub(
-        r'^#define PROTOBUF_MIN_PROTOC_VERSION .*$',
-        '#define PROTOBUF_MIN_PROTOC_VERSION %s' % cpp_version,
-        line)
-      line = re.sub(
-        r'^#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION .*$',
-        '#define GOOGLE_PROTOBUF_MIN_LIBRARY_VERSION %s' % cpp_version,
-        line)
-    return line
-
-  def RewritePbH(line):
-    line = re.sub(
-        r'^#if PROTOBUF_VERSION < .*$',
-        '#if PROTOBUF_VERSION < %s' % cpp_version,
-        line)
-    line = re.sub(
-        r'^#if .* < PROTOBUF_MIN_PROTOC_VERSION$',
-        '#if %s < PROTOBUF_MIN_PROTOC_VERSION' % cpp_version,
-        line)
-    return line
-
-  RewriteTextFile('src/google/protobuf/stubs/common.h', RewriteCommon)
-  RewriteTextFile('src/google/protobuf/port_def.inc', RewritePortDef)
-  RewriteTextFile('src/google/protobuf/any.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/api.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/descriptor.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/duration.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/empty.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/field_mask.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/source_context.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/struct.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/timestamp.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/type.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/wrappers.pb.h', RewritePbH)
-  RewriteTextFile('src/google/protobuf/compiler/plugin.pb.h', RewritePbH)
-
-
-def UpdateCsharp():
-  RewriteXml('csharp/src/Google.Protobuf/Google.Protobuf.csproj',
-    lambda document : ReplaceText(
-      Find(Find(document.documentElement, 'PropertyGroup'), 'VersionPrefix'),
-      GetFullVersion(rc_suffix = '-rc')),
-    add_xml_prefix=False)
-
-  RewriteXml('csharp/Google.Protobuf.Tools.nuspec',
-    lambda document : ReplaceText(
-      Find(Find(document.documentElement, 'metadata'), 'version'),
-      GetFullVersion(rc_suffix = '-rc')))
-
-
-def UpdateJava():
-  RewriteXml('java/pom.xml',
-    lambda document : ReplaceText(
-      Find(document.documentElement, 'version'), GetFullVersion()))
-
-  RewriteXml('java/bom/pom.xml',
-    lambda document : ReplaceText(
-      Find(document.documentElement, 'version'), GetFullVersion()))
-
-  RewriteXml('java/core/pom.xml',
-    lambda document : ReplaceText(
-      Find(Find(document.documentElement, 'parent'), 'version'),
-      GetFullVersion()))
-
-  RewriteXml('java/lite/pom.xml',
-    lambda document : ReplaceText(
-      Find(Find(document.documentElement, 'parent'), 'version'),
-      GetFullVersion()))
-
-  RewriteXml('java/util/pom.xml',
-    lambda document : ReplaceText(
-      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()))
-
-  RewriteTextFile('java/README.md',
-    lambda line : re.sub(
-      r'<version>.*</version>',
-      '<version>%s</version>' % GetFullVersion(),
-      line))
-
-  RewriteTextFile('java/README.md',
-    lambda line : re.sub(
-      r'implementation \'com.google.protobuf:protobuf-java:.*\'',
-      'implementation \'com.google.protobuf:protobuf-java:%s\'' % GetFullVersion(),
-      line))
-
-  RewriteTextFile('java/lite.md',
-    lambda line : re.sub(
-      r'<version>.*</version>',
-      '<version>%s</version>' % GetFullVersion(),
-      line))
-
-
-def UpdateMakefile():
-  RewriteTextFile('src/Makefile.am',
-    lambda line : re.sub(
-      r'^PROTOBUF_VERSION = .*$',
-      'PROTOBUF_VERSION = %s' % ":".join(map(str,GetSharedObjectVersion())),
-      line))
-
-
-def UpdateObjectiveC():
-  RewriteTextFile('Protobuf.podspec',
-    lambda line : re.sub(
-      r"^  s.version  = '.*'$",
-      "  s.version  = '%s'" % GetFullVersion(rc_suffix = '-rc'),
-      line))
-  RewriteTextFile('Protobuf-C++.podspec',
-    lambda line : re.sub(
-      r"^  s.version  = '.*'$",
-      "  s.version  = '%s'" % GetFullVersion(rc_suffix = '-rc'),
-      line))
-
-
-def UpdatePhp():
-  def Callback(document):
-    def CreateNode(tagname, indent, children):
-      elem = document.createElement(tagname)
-      indent += 1
-      for child in children:
-        elem.appendChild(document.createTextNode('\n' + (' ' * indent)))
-        elem.appendChild(child)
-      indent -= 1
-      elem.appendChild(document.createTextNode('\n' + (' ' * indent)))
-      return elem
-
-    root = document.documentElement
-    now = datetime.datetime.now()
-    ReplaceText(Find(root, 'date'), now.strftime('%Y-%m-%d'))
-    ReplaceText(Find(root, 'time'), now.strftime('%H:%M:%S'))
-    version = Find(root, 'version')
-    ReplaceText(Find(version, 'release'), GetFullVersion(rc_suffix = 'RC'))
-    ReplaceText(Find(version, 'api'), NEW_VERSION)
-    stability = Find(root, 'stability')
-    ReplaceText(Find(stability, 'release'),
-        'stable' if RC_VERSION < 0 else 'beta')
-    ReplaceText(Find(stability, 'api'), 'stable' if RC_VERSION < 0 else 'beta')
-    changelog = Find(root, 'changelog')
-    for old_version in changelog.getElementsByTagName('version'):
-      if Find(old_version, 'release').firstChild.nodeValue == NEW_VERSION:
-        print ('[WARNING] Version %s already exists in the change log.'
-          % NEW_VERSION)
-        return
-    if RC_VERSION != 0:
-      changelog.appendChild(document.createTextNode(' '))
-      release = CreateNode('release', 2, [
-          CreateNode('version', 3, [
-            FindAndClone(version, 'release'),
-            FindAndClone(version, 'api')
-          ]),
-          CreateNode('stability', 3, [
-            FindAndClone(stability, 'release'),
-            FindAndClone(stability, 'api')
-          ]),
-          FindAndClone(root, 'date'),
-          FindAndClone(root, 'time'),
-          FindAndClone(root, 'license'),
-          CreateNode('notes', 3, []),
-        ])
-      changelog.appendChild(release)
-      changelog.appendChild(document.createTextNode('\n '))
-  RewriteXml('php/ext/google/protobuf/package.xml', Callback)
-  RewriteTextFile('php/ext/google/protobuf/protobuf.h',
-    lambda line : re.sub(
-      r"^#define PHP_PROTOBUF_VERSION .*$",
-      "#define PHP_PROTOBUF_VERSION \"%s\"" % GetFullVersion(rc_suffix = 'RC'),
-      line))
-
-def UpdatePython():
-  RewriteTextFile('python/google/protobuf/__init__.py',
-    lambda line : re.sub(
-      r"^__version__ = '.*'$",
-      "__version__ = '%s'" % GetFullVersion(rc_suffix = 'rc'),
-      line))
-
-def UpdateRuby():
-  RewriteXml('ruby/pom.xml',
-             lambda document : ReplaceText(
-                 Find(document.documentElement, 'version'), GetFullVersion()))
-  RewriteXml('ruby/pom.xml',
-             lambda document : ReplaceText(
-                 Find(Find(Find(document.documentElement, 'dependencies'), 'dependency'), 'version'),
-                 GetFullVersion()))
-  RewriteTextFile('ruby/google-protobuf.gemspec',
-    lambda line : re.sub(
-      r'^  s.version     = ".*"$',
-      '  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))
-
-
-UpdateCMake()
-UpdateConfigure()
-UpdateCsharp()
-UpdateCpp()
-UpdateJava()
-UpdateMakefile()
-UpdateObjectiveC()
-UpdatePhp()
-UpdatePython()
-UpdateRuby()
-UpdateBazel()
diff --git a/util/python/BUILD.bazel b/util/python/BUILD.bazel
deleted file mode 100644
index 071efd2..0000000
--- a/util/python/BUILD.bazel
+++ /dev/null
@@ -1,22 +0,0 @@
-load("@rules_cc//cc:defs.bzl", "cc_library")
-
-exports_files(["BUILD.bazel"])
-
-# This is a placeholder for python headers. Projects needing to use
-# fast cpp protos in protobuf's python interface should build with
-# --define=use_fast_cpp_protos=true, and in addition, provide
-# //external:python_headers dependency that in turn provides Python.h.
-#
-# Projects that include protobuf using a Bazel external repository will need to
-# add a workspace rule to their WORKSPACE files to add an external workspace
-# that includes the Python headers. For example, the protobuf WORKSPACE file
-# includes the following local_repository rule that points to this directory:
-#
-# new_local_repository(
-#   name = "python_headers",
-#   path = __workspace_dir__ + "/util/python",
-# )
-cc_library(
-    name = "python_headers",
-    visibility = ["//visibility:public"],
-)
diff --git a/version.json b/version.json
index 0b70324..4244127 100644
--- a/version.json
+++ b/version.json
@@ -1,17 +1,17 @@
 {
-    "21.x": {
-        "protoc_version": "21.11-dev",
+    "main": {
+        "protoc_version": "22-dev",
         "lts": false,
-        "date": "2022-11-30",
+        "date": "2022-07-21",
         "languages": {
-            "cpp": "3.21.11-dev",
-            "csharp": "3.21.11-dev",
-            "java": "3.21.11-dev",
-            "javascript": "3.21.11-dev",
-            "objectivec": "3.21.11-dev",
-            "php": "3.21.11-dev",
-            "python": "4.21.11-dev",
-            "ruby": "3.21.11-dev"
+            "cpp": "3.22-dev",
+            "csharp": "3.22-dev",
+            "java": "3.22-dev",
+            "javascript": "3.22-dev",
+            "objectivec": "3.22-dev",
+            "php": "3.22-dev",
+            "python": "4.22-dev",
+            "ruby": "3.22-dev"
         }
     }
-}
\ No newline at end of file
+}